diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,1191 +1,3571 @@
 * Hackage: <http://hackage.haskell.org/package/sbv>
-* GitHub:  <http://leventerkok.github.com/sbv/>
-
-* Latest Hackage released version: 5.15, 2017-01-30
-
-### Version 5.15, 2017-01-30
-
-  * Bump up dependency on CrackNum >= 1.9, to get access to hexadecimal floats.
-  * Improve time/tracking-print code. Thanks to Iavor Diatchki for the patch.
-
-### Version 5.14, 2017-01-12
-  
-  * Bump up QuickCheck dependency to >= 2.9.2 to avoid the following quick-check
-    bug <http://github.com/nick8325/quickcheck/issues/113>, which transitively impacted
-    the quick-check as implemented by SBV.
-
-  * Generalize casts between integral-floats, using the rounding mode round-nearest-ties-to-even.
-    Previously calls to sFromIntegral did not support conversion to floats since it needed
-    a rounding mode. But it does make sense to support them with the default mode. If a different
-    mode is needed, use the function 'toSFloat' as before, which takes an explicit rounding mode.
-
-### Version 5.13, 2016-10-29
-
-  * Fix broken links, thanks to Stephan Renatus for the patch.
-
-  * Code generation: Create directory path if it does not exist. Thanks to Robert Dockins
-    for the patch.
-
-  * Generalize the type of sFromIntegral, dropping the Bits requirement. In turn, this
-    allowed us to remove sIntegerToSReal, since sFromIntegral can be used instead.
-
-  * Add support for sRealToSInteger. (Essentially the floor function for SReal.)
-
-  * Several space-leaks fixed for better performance. Patch contributed by Robert Dockins.
-
-  * Improved Random instance for Rational. Thanks to Joe Leslie-Hurd for the idea.
-
-### Version 5.12, 2016-06-06
-
-  * Fix GHC8.0 compliation issues, and warning clean-up. Thanks to Adam Foltzer for the bulk
-    of the work and Tom Sydney Kerckhove for the initial patch for 8.0 compatibility.
-
-  * Minor fix to printing models with floats when the base is 2/16, making sure the alignment
-    is done properly accommodating for the crackNum output.
-
-  * Wait for external process to die on exception, to avoid spawning zombies. Thanks to
-    Daniel Wagner for the patch.
-
-  * Fix hash-consed arrays: Previously we were caching based only on elements, which is not
-    sufficient as you can have conflicts differing only on the address type, but same contents.
-    Thanks to Brian Huffman for reporting and the corresponding patch.
-
-### Version 5.11, 2016-01-15
-
-  * Fix documentation issue; no functional changes
-
-### Version 5.10, 2016-01-14
-
-  * Documentation: Fix a bunch of dead http links. Thanks to Andres Sicard-Ramirez
-    for reporting.
-
-  * Additions to the Dynamic API:
-
-       * svSetBit                  : set a given bit
-       * svBlastLE, svBlastBE      : Bit-blast to big/little endian
-       * svWordFromLE, svWordFromBE: Unblast from big/little endian
-       * svAddConstant		   : Add a constant to an SVal
-       * svIncrement, svDecrement  : Add/subtract 1 from an SVal
-
-### Version 5.9, 2016-01-05
-
-  * Default definition for 'symbolicMerge', which allows types that are
-    instances of 'Generic' to have an automatically derivable merge (i.e.,
-    ite) instance. Thanks to Christian Conkle for the patch.
-
-  * Add support for "non-model-vars," where we can now tell SBV not
-    to take into account certain variables from a model-building
-    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
-    motivation.
-
-  * Yices interface: If Reals are used, then pick the logic QF_UFLRA, instead
-    of QF_AUFLIA. Unfortunately, logic selection remains tricky since the SMTLib
-    story for logic selection is rather messy. Other solvers are not impacted
-    by this change.
-
-### Version 5.8, 2016-01-01
-
-  * Fix some typos
-  * Add 'svEnumFromThenTo' to the Dynamic interface, allowing dynamic construction
-    of [x, y .. z] and [x .. y] when the involved values are concrete.
-  * Add 'svExp' to the Dynamic interface, implementing exponentation
-
-### Version 5.7, 2015-12-21
-
-  * Export HasKind(..) from the Dynamic interface. Thanks to Adam Foltzer for the patch.
-  * More careful handling of SMT-Lib reserved names.
-  * Update tested version of MathSAT to 5.3.9
-  * Generalize sShiftLeft/sShiftRight/sRotateLeft/sRotateRight to work with signed
-    shift/rotate amounts, where negative values revert the direction. Similar
-    generalizations are also done for the dynamic variants.
-
-### Version 5.6, 2015-12-06
-  
-  * Minor changes to how we print models:
-  * Align by the type
-  * Always print the type (previously we were skipping for Bool)
-
-  * Rework how SBV properties are quick-checked; much more usable and robust
-
-  * Provide a function sbvQuickCheck, which is essentially the same as
-    quickCheck, except it also returns a boolean. Useful for the
-    programmable API. (The dynamic version is called svQuickCheck)
-
-  * Several changes/additions in support of the sbvPlugin development:
-  * Data.SBV.Dynamic: Define/export svFloat/svDouble/sReal/sNumerator/sDenominator
-  * Data.SBV.Internals: Export constructors of Result, SMTModel,
-    and the function showModel
-  * Simplify how Uninterpreted-types are internally represented.
-
-### Version 5.5, 2015-11-10
-
-  * This is essentially the same release as 5.4 below, except to allow SBV compile
-    with GHC 7.8 series. Thanks to Adam Foltzer for the patch.
-
-### Version 5.4, 2015-11-09
-
-  * Add 'sAssert', which allows users to pepper their code with boolean conditions, much like
-    the usual ASSERT calls. Note that the semantics of an 'sAssert' is that it is a NOOP, i.e.,
-    it simply returns its final argument. Use in coordination with 'safe' and 'safeWith', see below.
-
-  * Implement 'safe' and 'safeWith', which statically determine all calls to 'sAssert'
-    being safe to execute. Any vilations will be flagged. 
-
-  * SBV->C: Translate 'sAssert' calls to dynamic checks in the generated C code. If this is
-    not desired, use the 'cgIgnoreSAssert' function to turn it off.
-
-  * Add 'isSafe': Which converts a 'SafeResult' to a 'Bool', when we are only interested
-    in a boolean result.
-
-  * Add Data/SBV/Examples/Misc/NoDiv0 to demonstrate the use of the 'safe' function.
-
-### Version 5.3, 2015-10-20
-
-  * Main point of this release to make SBV compile with GHC 7.8 again, to accommodate mainly
-    for Cryptol. As Cryptol moves to GHC >= 7.10, we intend to remove the "compatibility" changes
-    again. Thanks to Adam Foltzer for the patch.
-
-  * Minor mods to how bitvector equality/inequality are translated to SMTLib. No user visible
-    impact.
-
-### Version 5.2, 2015-10-12
-
-  * Regression on 5.1: Fix a minor bug in base 2/16 printing where uninterpreted constants were
-    not handled correctly.
-
-### Version 5.1, 2015-10-10
-
-  * fpMin, fpMax: If these functions receive +0/-0 as their two arguments, i.e., both
-    zeros but alternating signs in any order, then SMTLib requires the output to be
-    nondeterministicly chosen. Previously, we fixed this result as +0 following the
-    interpretation in Z3, but Z3 recently changed and now incorporates the nondeterministic
-    output. SBV similarly changed to allow for non-determinism here.
-
-  * Change the types of the following Floating-point operations:
-  
-        * sFloatAsSWord32, sFloatAsSWord32, blastSFloat, blastSDouble
-
-    These were previously coded as relations, since NaN values were not representable
-    in the target domain uniquely. While it was OK, it was hard to use them. We now
-    simply implement these as functions, and they are underspecified if the inputs
-    are NaNs: In those cases, we simply get a symbolic output. The new types are:
-
-       * sFloatAsSWord32  :: SFloat  -> SWord32
-       * sDoubleAsSWord64 :: SDouble -> SWord64
-       * blastSFloat      :: SFloat  -> (SBool, [SBool], [SBool])
-       * blastSDouble     :: SDouble -> (SBool, [SBool], [SBool])
-
-  * MathSAT backend: Use the SMTLib interpretation of fp.min/fp.max by passing the
-    "-theory.fp.minmax_zero_mode=4" argument explicitly.
-
-  * Fix a bug in hash-consing of floating-point constants, where we were confusing +0 and
-    -0 since we were using them as keys into the map though they compare equal. We now
-    explicitly keep track of the negative-zero status to make sure this confusion does
-    not arise. Note that this bug only exhibited itself in rare occurrences of both
-    constants being present in a benchmark; a true corner case. Note that @NaN@ values
-    are also interesting in this context: Since NaN /= NaN, we never hash-cons floating
-    point constants that have the value NaN. But that is actually OK; it is a bit wasteful
-    in case you have a lot of NaN constants around, but there is no soundness issue: We
-    just waste a little bit of space.
-
-  * Remove the functions `allSatWithAny` and `allSatWithAll`. These two variants do *not*
-    make sense when run with multiple solvers, as they internally sequentialize the solutions
-    due to the nature of `allSat`. Not really needed anyhow; so removed. The variants
-    `satWithAny/All` and `proveWithAny/All` are still available.
-
-  * Export SMTLibVersion from the library, forgotten export needed by Cryptol. Thanks to Adam
-    Foltzer for the patch.
-
-  * Slightly modify model-outputs so the variables are aligned vertically. (Only matters
-    if we have model-variable names that are of differing length.)
-
-  * Move to Travis-CI "docker" based infrastructure for builds
-
-  * Enable local builds to use the Herbie plugin. Currently SBV does not have any
-    expressions that can benefit from Herbie, but it is nice to have this support in general.
-
-### Version 5.0, 2015-09-22
-
-  * Note: This is a backwards-compatibility breaking release, see below for details.
-
-  * SBV now requires GHC 7.10.1 or newer to be compiled, taking advantage of newer features/bug-fixes
-    in GHC. If you really need SBV to compile with older GHCs, please get in touch.
-
-  * SBV no longer supports SMTLib1. We now exclusively use SMTLib2 for communicating with backend
-    solvers. Strictly speaking, this means some loss in functionality: Uninterpreted-function models
-    that we supported via Yices-1 are no longer available. In practice this facility was not really
-    used, and required a very old version of Yices that was no longer supported by SRI and has
-    lacked in other features. So, in reality this change should hardly matter for end-users.
-
-  * Added function "label", which is useful in emitting comments around expressions. It is essentially
-    a no-op, but does generate a comment with the given text in the SMT-Lib and C output, for diagnostic
-    purposes.
-
-  * Added "sFromIntegral": Conversions from all integral types (SInteger, SWord/SInts) between
-    each other. Similar to the "fromIntegral" function of Haskell. These generate simple casts when
-    used in code-generation to C, and thus are very efficient.
-
-  * SBV no longer supports the functions sBranch/sAssert, as we realized these functions can cause
-    soundness issues under certain conditions. While the triggering scenarios are not common use-cases
-    for these functions, we are opting for safety, and thus removing support. See
-    http://github.com/LeventErkok/sbv/issues/180 for details; and see below for the new function
-    'isSatisfiableInCurrentPath'.
-
-  * A new function 'isSatisfiableInCurrentPath' is added, which checks for satisfiability during a
-    symbolic simulation run. This function can be used as the basis of sBranch/sAssert like functionality
-    if needed. The difference is that this is a much lower level call, and also exposes the fact that
-    the result is in the 'Symbolic' monad (which avoids the soundness issue). Of course, the new type
-    makes it less useful as it will not be a drop-in replacement for if-then-else like structure. Intended
-    to be used by tools built on top of SBV, as opposed to end-users.
-
-  * SBV no longer implements the 'SignCast' class, as its functionality is replaced by the 'sFromIntegral'
-    function. Programs using the functions 'signCast' and 'unsignCast' should simply replace both
-    with calls to 'sFromIntegral'. (Note that extra type-annotations might be necessary, similar to
-    the uses of the 'fromIntegral' function in Haskell.)
-
-  * Backend solver related changes:
-
-       * Yices: Upgraded to work with Yices release 2.4.1. Note that earlier versions of Yices
-         are *not* supported.
-
-       * Boolector: Upgraded to work with new Boolector release 2.0.7. Note that earlier versions
-         of Boolector are *not* supported.
-     
-       * MathSAT: Upgraded to work with latest release 5.3.7. Note that earlier versions of MathSAT
-         are *not* supported (due to a buffering issue in MathSAT itself.)
-     
-       * MathSAT: Enabled floating-point support in MathSAT.
-     
-  * New examples:
-
-       * Add Data.SBV.Examples.Puzzles.Birthday, which solves the Cheryl-Birthday problem that
-         went viral in April 2015. Turns out really easy to solve for SMT, but the formalization
-         of the problem is still interesting as an exercise in formal reasoning.
-
-       * Add Data.SBV.Examples.Puzzles.SendMoreMoney, which solves the classic send + more = money
-         problem. Really a trivial example, but included since it is pretty much the hello-world for
-         basic constraint solving.
-
-       * Add Data.SBV.Examples.Puzzles.Fish, which solves a typical logic puzzle; finding the unique
-         solution to a set of assertions made about a bunch of people, their pets, beverage choices,
-         etc. Not particularly interesting, but could be fun to play around with for modeling purposes.
-
-       * Add Data.SBV.Examples.BitPrecise.MultMask, which demonstrates the use of the bitvector
-         solver to an interesting bit-shuffling problem.
-
-  * Rework floating-point arithmetic, and add missing floating-point operations:
-
-      * fpRem            : remainder
-      * fpRoundToIntegral: truncating round 
-      * fpMin            : min
-      * fpMax            : max
-      * fpIsEqualObject  : FP equality as object (i.e., NaN equals NaN, +0 does not equal -0, etc.)
-
-    This brings SBV up-to par with everything supported by the SMT-Lib FP theory.
-
-  * Add the IEEEFloatConvertable class, which provides conversions to/from Floats and other types. (i.e.,
-    value conversions from all other types to Floats and Doubles; and back.)
-
-  * Add SWord32/SWord64 to/from SFloat/SDouble conversions, as bit-pattern reinterpretation; using the
-    IEEE754 interchange format. The functions are: sWord32AsSFloat, sWord64AsSDouble, sFloatAsSWord32,
-    sDoubleAsSWord64. Note that the sWord32AsSFloat and sWord64ToSDouble are regular functions, but
-    sFloatToSWord32 and sDoubleToSWord64 are "relations", since NaN values are not uniquely convertable.
-
-  * Add 'sExtractBits', which takes a list of indices to extract bits from, essentially
-    equivalent to 'map sTestBit'.
-
-  * Rename a set of symbolic functions for consistency. Here are the old/new names:
-   
-     * sbvTestBit               --> sTestBit
-     * sbvPopCount              --> sPopCount
-     * sbvShiftLeft             --> sShiftLeft
-     * sbvShiftRight            --> sShiftRight
-     * sbvRotateLeft            --> sRotateLeft
-     * sbvRotateRight           --> sRotateRight
-     * sbvSignedShiftArithRight --> sSignedShiftArithRight
-
-  * Rename all FP recognizers to be in sync with FP operations. Here are the old/new names:
-
-     * isNormalFP       --> fpIsNormal       
-     * isSubnormalFP    --> fpIsSubnormal    
-     * isZeroFP         --> fpIsZero         
-     * isInfiniteFP     --> fpIsInfinite     
-     * isNaNFP          --> fpIsNaN          
-     * isNegativeFP     --> fpIsNegative     
-     * isPositiveFP     --> fpIsPositive     
-     * isNegativeZeroFP --> fpIsNegativeZero 
-     * isPositiveZeroFP --> fpIsPositiveZero 
-     * isPointFP        --> fpIsPoint        
-
-  * Lots of other work around floating-point, test cases, reorg, etc.
-
-  * Introduce shorter variants for rounding modes: sRNE, sRNA, sRTP, sRTN, sRTZ;
-    aliases for sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive,
-    sRoundTowardNegative, and sRoundTowardZero; respectively.
-
-### Version 4.4, 2015-04-13
-
-  * Hook-up crackNum package; so counter-examples involving floats and
-    doubles can be printed in detail when the printBase is chosen to be
-    2 or 16. (With base 10, we still get the simple output.) 
-
-      ```
-      Prelude Data.SBV> satWith z3{printBase=2} $ \x -> x .== (2::SFloat)
-      Satisfiable. Model:
-        s0 = 2.0 :: Float
-                        3  2          1         0
-                        1 09876543 21098765432109876543210
-                        S ---E8--- ----------F23----------
-                Binary: 0 10000000 00000000000000000000000
-                   Hex: 4000 0000
-             Precision: SP
-                  Sign: Positive
-              Exponent: 1 (Stored: 128, Bias: 127)
-                 Value: +2.0 (NORMAL)
-      ```
-
-  * Change how we print type info; for models insted of SType just print Type (i.e.,
-    for SWord8, instead print Word8) which makes more sense and is more consistent.
-    This change should be mostly relevant as how we see the counter-example output.
-
-  * Fix long standing bug #75, where we now support arrays with Boolean source/targets.
-    This is not a very commonly used case, but by letting the solver pick the logic,
-    we now allow arrays to be uniformly supported.
-
-### Version 4.3, 2015-04-10
-
-  * Introduce Data.SBV.Dynamic, by Brian Huffman. This is mostly an internal
-    reorg of the SBV codebase, and end-users should not be impacted by the
-    changes. The introduction of the Dynamic SBV variant (i.e., one that does
-    not mandate a phantom type as in "SBV Word8" etc. allows library writers
-    more flexibility as they deal with arbitrary bit-vector sizes. The main
-    customor of these changes are the Cryptol language and the associated
-    toolset, but other developers building on top of SBV can find it useful
-    as well. NB: The "strongly-typed" aspect of SBV is still the main way
-    end-users should interact with SBV, and nothing changed in that respect!
-
-  * Add symbolic variants of floating-point rounding-modes for convenience
-
-  * Rename toSReal to sIntegerToSReal, which captures the intent more clearly
-
-  * Code clean-up: remove mbMinBound/mbMaxBound thus allowing less calls to
-    unliteral. Contributed by Brian Huffman.
-
-  * Introduce FP conversion functions:
-  
-       * Between SReal and SFloat/SDouble
-           * fpToSReal
-           * sRealToSFloat
-           * sRealToSDouble
-       * Between SWord32 and SFloat
-           * sWord32ToSFloat
-           * sFloatToSWord32
-       * Between SWord64 and SDouble. (Relational, due to non-unique NaNs)
-           * sWord64ToSDouble
-       * sDoubleToSWord64
-       * From float to sign/exponent/mantissa fields: (Relational, due to non-unique NaNs)
-           * blastSFloat
-           * blastSDouble
-
-  * Rework floating point classifiers. Remove isSNaN and isFPPoint (both renamed),
-    and add the following new recognizers:
-
-       * isNormalFP
-       * isSubnormalFP
-       * isZeroFP
-       * isInfiniteFP
-       * isNaNFP
-       * isNegativeFP
-       * isPositiveFP
-       * isNegativeZeroFP
-       * isPositiveZeroFP
-       * isPointFP (corresponds to a real number, i.e., neither NaN nor infinity)
-
-  * Reimplement sbvTestBit, by Brian Huffman. This version is much faster at large
-    word sizes, as it avoids the costly mask generation.
-
-  * Code changes to suppress warnings with GHC7.10. General clean-up.
-
-### Version 4.2, 2015-03-17
-
-  * Add exponentiation (.^). Thanks to Daniel Wagner for contributing the code!
-
-  * Better handling of SBV_$SOLVER_OPTIONS, in particular keeping track of
-    proper quoting in environment variables. Thanks to Adam Foltzer for
-    the patch!
-
-  * Silence some hlint/ghci warnings. Thanks to Trevor Elliott for the patch!
-
-  * Haddock documentation fixes, improvements, etc.
-  
-  * Change ABC default option string to %blast; "&sweep -C 5000; &syn4; &cec -s -m -C 2000"
-    which seems to give good results. Use SBV_ABC_OPTIONS environment variable (or
-    via abc.rc file and a combination of SBV_ABC_OPTIONS) to experiment.
-
-### Version 4.1, 2015-03-06
-
-  * Add support for the ABC solver from Berkeley. Thanks to Adam Foltzer
-    for the required infrastructure! See: http://www.eecs.berkeley.edu/~alanmi/abc/
-    And Alan Mishchenko for adding infrastructure to ABC to work with SBV.
-
-  * Upgrade the Boolector connection to use a SMT-Lib2 based interaction. NB. You
-    need at least Boolector 2.0.6 installed!
-
-  * Tracking changes in the SMT-Lib floating-point theory. If you are
-    using symbolic floating-point types (i.e., SFloat and SDouble), then
-    you should upgrade to this version and also get a very latest (unstable)
-    Z3 release. See http://smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml
-    for details.
-
-  * Introduce a new class, 'RoundingFloat', which supports floating-point
-    operations with arbitrary rounding-modes. Note that Haskell only allows
-    RoundNearestTiesToAway, but with SBV, we get all 5 IEEE754 rounding-modes
-    and all the basic operations ('fpAdd', 'fpMul', 'fpDiv', etc.) with these
-    modes.
-    
-  * Allow Floating-Point RoundingMode to be symbolic as well
-
-  * Improve the example "Data/SBV/Examples/Misc/Floating.hs" to include
-    rounding-mode based addition example.
-    
-  * Changes required to make SBV compile with GHC 7.10; mostly around instance
-    NFData declarations. Thanks to Iavor Diatchki for the patch.
-
-  * Export a few extra symbols from the Internals module (mainly for
-    Cryptol usage.)
-
-### Version 4.0, 2015-01-22
-
-This release mainly contains contributions from Brian Huffman, allowing
-end-users to define new symbolic types, such as Word4, that SBV does not
-natively support. When GHC gets type-level literals, we shall most likely
-incorporate arbitrary bit-sized vectors and ints using this mechanism,
-but in the interim, this release provides a means for the users to introduce
-individual instances.
-
-  * Modifications to support arbitrary bit-sized vectors; 
-    These changes have been contributed by Brian Huffman
-    of Galois.. Thanks Brian.
-  * A new example "Data/SBV/Examples/Misc/Word4.hs" showing
-    how users can add new symbolic types.
-  * Support for rotate-left/rotate-right with variable
-    rotation amounts. (From Brian Huffman.)
-
-### Version 3.5, 2015-01-15
-
-This release is mainly adding support for enumerated types in Haskell being
-translated to their symbolic counterparts; instead of going completely
-uninterpreted.
-
-  * Keep track of data-type details for uninterpreted sorts.
-  * Rework the U2Bridge example to use enumerated types.
-  * The "Uninterpreted" name no longer makes sense with this change, so
-    rework the relevant names to ensure proper internal naming.
-  * Add Data/SBV/Examples/Misc/Enumerate.hs as an example for demonstrating
-    how enumerations are translated.
-  * Fix a long-standing bug in the implementation of select when
-    translated as SMT-Lib tables. (Github issue #103.) Thanks to
-    Brian Huffman for reporting.
-
-### Version 3.4, 2014-12-21
-
-  * This release is mainly addressing floating-point changes in SMT-Lib.
-
-      * Track changes in the QF_FPA logic standard; new constants and alike. If you are
-        using the floating-point logic, then you need a relatively new version of Z3
-        installed (4.3.3 or newer).
-
-      * Add unary-negation as an explicit operator. Previously, we merely used the "0-x"
-        semantics; but with floating point, this does not hold as 0-0 is 0, and is not -0!
-        (Note that negative-zero is a valid floating point value, that is different than
-        positive-zero; yet it compares equal to it. Sigh..)
-
-      * Similarly, add abs as a native method; to make sure we map it to fp.abs for
-        floating point values.
-
-      * Test suite improvements
-
-### Version 3.3, 2014-12-05
-
-  * Implement 'safe' and 'safeWith', which statically determine all calls to 'sAssert'
-    being safe to execute. This way, users can pepper their programs with liberal
-    calls to 'sAssert' and check they are all safe in one go without further worry.
-
-  * Robustify the interface to external solvers, by making sure we catch cases where
-    the external solver might exist but not be runnable (library dependency missing,
-    for example). It is impossible to be absolutely foolproof, but we now catch a
-    few more cases and fail gracefully.
-
-### Version 3.2, 2014-11-18
-
-  * Implement 'sAssert'. This adds conditional symbolic simulation, by ensuring arbitrary
-    boolean conditions hold during simulation; similar to ASSERT calls in other languages.
-    Note that failures will be detected at symbolic-simulation time, i.e., each assert will
-    generate a call to the external solver to ensure that the condition is never violated.
-    If violation is possible the user will get an error, indicating the failure conditions.
-
-  * Also implement 'sAssertCont' which allows for a programmatic way to extract/display results
-    for consumers of 'sAssert'. While the latter simply calls 'error' in case of an assertion
-    violation, the 'sAssertCont' variant takes a continuation which can be used to program
-    how the results should be interpreted/displayed. (This is useful for libraries built on top of
-    SBV.) Note that the type of the continuation is such that execution should still stop, i.e.,
-    once an assertion violation is detected, symbolic simulation will never continue.
-
-  * Rework/simplify the 'Mergeable' class to make sure 'sBranch' is sufficiently lazy
-    in case of structural merges. The original implementation was only
-    lazy at the Word instance, but not at lists/tuples etc. Thanks to Brian Huffman
-    for reporting this bug.
-
-  * Add a few constant-folding optimizations for 'sDiv'and 'sRem'
-
-  * Boolector: Modify output parser to conform to the new Boolector output format. This
-    means that you need at least v2.0.0 of Boolector installed if you want to use that
-    particular solver.
-
-  * Fix long-standing translation bug regarding boolean Ord class comparisons. (i.e., 
-    'False > True' etc.) While Haskell allows for this, SMT-Lib does not; and hence
-    we have to be careful in translating. Thanks to Brian Huffman for reporting.
-
-  * C code generation: Correctly translate square-root and fusedMA functions to C.
-
-### 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>
-     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!
-
- New features/bug-fixes in v3.1:
-
- * Using multiple-SMT solvers in parallel:
-      * Added functions that let the user run multiple solvers, using asynchronous
-        threads. All results can be obtained (proveWithAll, proveWithAny, satWithAll),
-        or SBV can return the fastest result (satWithAny, allSatWithAll, allSatWithAny).
-        These functions are good for playing with multiple-solvers, especially on
-        machines with multiple-cores.
-      * Add function: sbvAvailableSolvers; which returns the list of solvers currently
-        available, as installed on the machine we are running. (Not the list that SBV
-        supports, but those that are actually available at run-time.) This function
-        is useful with the multi-solve API.
- * Implement sBranch:
-      * sBranch is a variant of 'ite' that consults the external
-        SMT solver to see if a given branch condition is satisfiable
-        before evaluating it. This can make certain otherwise recursive
-        and thus not-symbolically-terminating inputs amenable to symbolic
-        simulation, if termination can be established this way. Needless
-        to say, this problem is always decidable as far as SBV programs
-        are concerned, but it does not mean the decision procedure is cheap!
-        Use with care. 
-      * sBranchTimeOut config parameter can be used to curtail long runs when
-        sBranch is used. Of course, if time-out happens, SBV will
-        assume the branch is feasible, in which case symbolic-termination
-        may come back to bite you.)
- * New API:
-      * Add predicate 'isSNaN' which allows testing 'SFloat'/'SDouble' values
-        for nan-ness. This is similar to the Prelude function 'isNaN', except
-        the Prelude version requires a RealFrac instance, which unfortunately is
-        not currently implementable for cases. (Requires trigonometric functions etc.)
-        Thus, we provide 'isSNaN' separately (along with the already existing
-        'isFPPoint') to simplify reasoning with floating-point.
- * Examples:
-     * Add Data/SBV/Examples/Misc/SBranch.hs, to illustrate the use of sBranch.
- * Bug fixes:
-     * Fix pipe-blocking issue, which exhibited itself in the presence of
-       large numbers of variables (> 10K or so). See github issue #86. Thanks
-       to Philipp Meyer for the fine report.
- * Misc:
-     * Add missing SFloat/SDouble instances for SatModel class
-     * Explicitly support KBool as a kind, separating it from "KUnbounded False 1".
-       Thanks to Brian Huffman for contributing the changes. This should have no
-       user-visible impact, but comes in handy for internal reasons.
-
-### Version 3.0, 2014-02-16
-   
- * Support for floating-point numbers:
-      * Preliminary support for IEEE-floating point arithmetic, introducing
-        the types `SFloat` and `SDouble`. The support is still quite new,
-        and Z3 is the only solver that currently features a solver for
-        this logic. Likely to have bugs, both at the SBV level, and at the
-        Z3 level; so any bug reports are welcome!
- * New backend solvers:
-      * SBV now supports MathSAT from Fondazione Bruno Kessler and
-        DISI-University of Trento. See: http://mathsat.fbk.eu/
- * Support all-sat calls in the presence of uninterpreted sorts:
-      * Implement better support for `allSat` in the presence of uninterpreted
-        sorts. Previously, SBV simply rejected running `allSat` queries
-        in the presence of uninterpreted sorts, since it was not possible
-        to generate a refuting model. The model returned by the SMT solver
-        is simply not usable, since it names constants that is not visible
-        in a subsequent run. Eric Seidel came up with the idea that we can
-        actually compute equivalence classes based on a produced model, and
-        assert the constraint that the new model should disallow the previously
-        found equivalence classes instead. The idea seems to work well
-        in practice, and there is also an example program demonstrating
-        the functionality: Examples/Uninterpreted/UISortAllSat.hs
- * Programmable model extraction improvements:
-      * Add functions `getModelDictionary` and `getModelDictionaries`, which
-        provide low-level access to models returned from SMT solvers. Former
-        for `sat` and `prove` calls, latter for `allSat` calls. Together with
-        the exported utils from the `Data.SBV.Internals` module, this should
-        allow for expert users to dissect the models returned and do fancier
-        programming on top of SBV.
-      * Add `getModelValue`, `getModelValues`, `getModelUninterpretedValue`, and
-        `getModelUninterpretedValues`; which further aid in model value
-        extraction.
- * Other:
-      * Allow users to specify the SMT-Lib logic to use, if necessary. SBV will
-        still pick the logic automatically, but users can now override that choice.
-        Comes in handy when playing with custom logics.
- * Bug fixes:
-      * Address allsat-laziness issue (#78 in github issue tracker). Essentially,
-        simplify how all-sat is called so we can avoid calling the solver for
-        solutions that are not needed. Thanks to Eric Seidel for reporting.
- * Examples:
-      * Add Data/SBV/Examples/Misc/ModelExtract.hs as a simple example for
-        programmable model extraction and usage.
-      * Add Data/SBV/Examples/Misc/Floating.hs for some FP examples.
-      * Use the AUFLIA logic in Examples.Existentials.Diophantine which helps
-        z3 complete the proof quickly. (The BV logics take too long for this problem.)
-
-### Version 2.10, 2013-03-22
- 
- * Add support for the Boolector SMT solver
-    * See: http://fmv.jku.at/boolector/
-    * Use `import Data.SBV.Bridge.Boolector` to use Boolector from SBV
-    * Boolector supports QF_BV (with an without arrays). In the last
-      SMT-Lib competition it won both bit-vector categories. It is definitely
-      worth trying it out for bitvector problems.
- * Changes to the library:
-    * Generalize types of `allDifferent` and `allEqual` to take
-      arbitrary EqSymbolic values. (Previously was just over SBV values.)
-    * Add `inRange` predicate, which checks if a value is bounded within
-      two others.
-    * Add `sElem` predicate, which checks for symbolic membership
-    * Add `fullAdder`: Returns the carry-over as a separate boolean bit.
-    * Add `fullMultiplier`: Returns both the lower and higher bits resulting
-      from  multiplication.
-    * Use the SMT-Lib Bool sort to represent SBool, instead of bit-vectors of length 1.
-      While this is an under-the-hood mechanism that should be user-transparent, it
-      turns out that one can no longer write axioms that return booleans in a direct
-      way due to this translation. This change makes it easier to write axioms that
-      utilize booleans as there is now a 1-to-1 match. (Suggested by Thomas DuBuisson.)
- * Solvers changes:
-    * Z3: Update to the new parameter naming schema of Z3. This implies that
-      you need to have a really recent version of Z3 installed, something
-      in the Z3-4.3 series.
- * Examples:
-    * Add Examples/Uninterpreted/Shannon.hs: Demonstrating Shannon expansion,
-      boolean derivatives, etc.
- * Bug-fixes:
-    * Gracefully handle the case if the backend-SMT solver does not put anything
-      in stdout. (Reported by Thomas DuBuisson.)
-    * Handle uninterpreted sort values, if they happen to be only created via
-      function calls, as opposed to being inputs. (Reported by Thomas DuBuisson.)
-
-### Version 2.9, 2013-01-02
-
-  * Add support for the CVC4 SMT solver from New York University and
-    the University of Iowa. <http://cvc4.cs.nyu.edu/>.
-    NB. Z3 remains the default solver for SBV. To use CVC4, use the
-    *With variants of the interface (i.e., proveWith, satWith, ..)
-    by passing cvc4 as the solver argument. (Similarly, use 'yices'
-    as the argument for the *With functions for invoking yices.)
-  * Latest release of Yices calls the SMT-Lib based solver executable
-    yices-smt. Updated the default value of the executable to have this
-    name for ease of use.
-  * Add an extra boolean flag to compileToSMTLib and generateSMTBenchmarks
-    functions to control if the translation should keep the query as is
-    (for SAT cases), or negate it (for PROVE cases). Previously, this value
-    was hard-coded to do the PROVE case only.
-  * Add bridge modules, to simplify use of different solvers. You can now say:
-
-          import Data.SBV.Bridge.CVC4
-          import Data.SBV.Bridge.Yices
-          import Data.SBV.Bridge.Z3
-   
-    to pick the appropriate default solver. if you simply 'import Data.SBV', then
-    you will get the default SMT solver, which is currently Z3. The value
-    'defaultSMTSolver' refers to z3 (currently), and 'sbvCurrentSolver' refers
-    to the chosen solver as determined by the imported module. (The latter is
-    useful for modifying options to the SMT solver in an solver-agnostic way.)
-  * Various improvements to Z3 model parsing routines.
-  * New web page for SBV: http://leventerkok.github.com/sbv/ is now online.
-
-### Version 2.8, 2012-11-29
-
-  * Rename the SNum class to SIntegral, and make it index over regular
-    types. This makes it much more useful, simplifying coding of
-    polymorphic symbolic functions over integral types, which is
-    the common case.
-  * Add the functions:
-  * sbvShiftLeft
-  * sbvShiftRight
-    which can accommodate unsigned symbolic shift amounts. Note that
-    one cannot use the Haskell shiftL/shiftR functions from the Bits class since
-    they are hard-wired to take 'Int' values as the shift amounts only.
-  * Add a new function 'sbvArithShiftRight', which is the same as
-    a shift-right, except it uses the MSB of the input as the bit to fill
-    in (instead of always filling in with 0 bits). Note that this is
-    the same as shiftRight for signed values, but differs from a shiftRight
-    when the input is unsigned. (There is no Haskell analogue of this
-    function, as Haskell shiftR is always arithmetic for signed
-    types and logical for unsigned ones.) This variant is designed for
-    use cases when one uses the underlying unsigned SMT-Lib representation
-    to implement custom signed operations, for instance.
-  * Several typo fixes.
-
-### Version 2.7, 2012-10-21
-
-  * Add missing QuickCheck instance for SReal
-  * When dealing with concrete SReals, make sure to operate
-    only on exact algebraic reals on the Haskell side, leaving
-    true algebraic reals (i.e., those that are roots of polynomials
-    that cannot be expressed as a rational) symbolic. This avoids
-    issues with functions that we cannot implement directly on
-    the Haskell side, like exact square-roots.
-  * Documentation tweaks, typo fixes etc.
-  * Rename BVDivisible class to SDivisible; since SInteger
-    is also an instance of this class, and SDivisible is a
-    more appropriate name to start with. Also add sQuot and sRem
-    methods; along with sDivMod, sDiv, and sMod, with usual
-    semantics. 
-  * Improve test suite, adding many constant-folding tests
-    and start using cabal based tests (--enable-tests option.)
-
-### Versions 2.4, 2.5, and 2.6: Around mid October 2012
-
-  * Workaround issues related hackage compilation, in particular to the
-    problem with the new containers package release, which does provide
-    an NFData instance for sequences.
-  * Add explicit Num requirements when necessary, as the Bits class
-    no longer does this.
-  * Remove dependency on the hackage package strict-concurrency, as
-    hackage can no longer compile it due to some dependency mismatch.
-  * Add forgotten Real class instance for the type 'AlgReal'
-  * Stop putting bounds on hackage dependencies, as they cause
-    more trouble then they actually help. (See the discussion
-    here: <http://www.haskell.org/pipermail/haskell-cafe/2012-July/102352.html>.)
-
-### Version 2.3, 2012-07-20
-
-  * Maintanence release, no new features.
-  * Tweak cabal dependencies to avoid using packages that are newer
-    than those that come with ghc-7.4.2. Apparently this is a no-no
-    that breaks many things, see the discussion in this thread:
-      http://www.haskell.org/pipermail/haskell-cafe/2012-July/102352.html
-    In particular, the use of containers >= 0.5 is *not* OK until we have
-    a version of GHC that comes with that version.
-
-### Version 2.2, 2012-07-17
-
-  * Maintanence release, no new features.
-  * Update cabal dependencies, in particular fix the
-    regression with respect to latest version of the
-    containers package.
-
-### Version 2.1, 2012-05-24
-
- * Library:
-    * Add support for uninterpreted sorts, together with user defined
-      domain axioms. See Data.SBV.Examples.Uninterpreted.Sort
-      and Data.SBV.Examples.Uninterpreted.Deduce for basic examples of
-      this feature.
-    * Add support for C code-generation with SReals. The user picks
-      one of 3 possible C types for the SReal type: CgFloat, CgDouble
-      or CgLongDouble, using the function cgSRealType. Naturally, the
-      resulting C program will suffer a loss of precision, as it will
-      be subject to IEE-754 rounding as implied by the underlying type.
-    * Add toSReal :: SInteger -> SReal, which can be used to promote
-      symbolic integers to reals. Comes handy in mixed integer/real
-      computations.
- * Examples:
-    * Recast the dog-cat-mouse example to use the solver over reals.
-    * Add Data.SBV.Examples.Uninterpreted.Sort, and
-           Data.SBV.Examples.Uninterpreted.Deduce
-      for illustrating uninterpreted sorts and axioms.
-
-### Version 2.0, 2012-05-10
-  
-  This is a major release of SBV, adding support for symbolic algebraic reals: SReal.
-  See http://en.wikipedia.org/wiki/Algebraic_number for details. In brief, algebraic
-  reals are solutions to univariate polynomials with rational coefficients. The arithmetic
-  on algebraic reals is precise, with no approximation errors. Note that algebraic reals
-  are a proper subset of all reals, in particular transcendental numbers are not
-  representable in this way. (For instance, "sqrt 2" is algebraic, but pi, e are not.)
-  However, algebraic reals is a superset of rationals, so SBV now also supports symbolic
-  rationals as well.
-    
-  You *should* use Z3 v4.0 when working with real numbers. While the interface will
-  work with older versions of Z3 (or other SMT solvers in general), it uses Z3
-  root-obj construct to retrieve and query algebraic reals.
-
-  While SReal values have infinite precision, printing such values is not trivial since
-  we might need an infinite number of digits if the result happens to be irrational. The
-  user controls printing precision, by specifying how many digits after the decimal point
-  should be printed. The default number of decimal digits to print is 10. (See the
-  'printRealPrec' field of SMT-solver configuration.)
-
-  The acronym SBV used to stand for Symbolic Bit Vectors. However, SBV has grown beyond
-  bit-vectors, especially with the addition of support for SInteger and SReal types and
-  other code-generation utilities. Therefore, "SMT Based Verification" is now a better fit
-  for the expansion of the acronym SBV.
-
-  Other notable changes in the library:
-
-  * Add functions s[TYPE] and s[TYPE]s for each symbolic type we support (i.e.,
-    sBool, sBools, sWord8, sWord8s, etc.), to create symbolic variables of the
-    right kind.  Strictly speaking these are just synonyms for 'free'
-    and 'mapM free' (plural versions), so they are not adding any additional
-    power. Except, they are specialized at their respective types, and might be
-    easier to remember.
-  * Add function solve, which is merely a synonym for (return . bAnd), but
-    it simplifies expressing problems.
-  * Add class SNum, which simplifies writing polymorphic code over symbolic values
-  * Increase haddock coverage metrics
-  * Major code refactoring around symbolic kinds
-  * SMTLib2: Emit ":produce-models" call before setting the logic, as required
-    by the SMT-Lib2 standard. [Patch provided by arrowdodger on github, thanks!]
-
-  Bugs fixed:
-
-   * [Performance] Use a much simpler default definition for "select": While the
-     older version (based on binary search on the bits of the indexer) was correct,
-     it created unnecessarily big expressions. Since SBV does not have a notion
-     of concrete subwords, the binary-search trick was not bringing any advantage
-     in any case. Instead, we now simply use a linear walk over the elements.
-
-  Examples:
-
-   * Change dog-cat-mouse example to use SInteger for the counts
-   * Add merge-sort example: Data.SBV.Examples.BitPrecise.MergeSort
-   * Add diophantine solver example: Data.SBV.Examples.Existentials.Diophantine
-
-### Version 1.4, 2012-05-10
-
-   * Interim release for test purposes
-
-### Version 1.3, 2012-02-25
-
-  * Workaround cabal/hackage issue, functionally the same as release
-    1.2 below
-
-### Version 1.2, 2012-02-25
-
- Library:
-
-  * Add a hook so users can add custom script segments for SMT solvers. The new
-    "solverTweaks" field in the SMTConfig data-type can be used for this purpose.
-    The need for this came about due to the need to workaround a Z3 v3.2 issue
-    detalied below:
-      http://stackoverflow.com/questions/9426420/soundness-issue-with-integer-bv-mixed-benchmarks
-    As a consequence, mixed Integer/BV problems can cause soundness issues in Z3
-    and does in SBV. Unfortunately, it is too severe for SBV to add the woraround
-    option, as it slows down the solver as a side effect as well. Thus, we are
-    making this optionally available if/when needed. (Note that the work-around
-    should not be necessary with Z3 v3.3; which is not released yet.)
-  * Other minor clean-up
-
-### Version 1.1, 2012-02-14
-
- Library:
-
-  * Rename bitValue to sbvTestBit
-  * Add sbvPopCount
-  * Add a custom implementation of 'popCount' for the Bits class
-    instance of SBV (GHC >= 7.4.1 only)
-  * Add 'sbvCheckSolverInstallation', which can be used to check
-    that the given solver is installed and good to go.
-  * Add 'generateSMTBenchmarks', simplifying the generation of
-    SMTLib benchmarks for offline sharing.
-
-### Version 1.0, 2012-02-13
-
- Library:
-
-  * Z3 is now the "default" SMT solver. Yices is still available, but
-    has to be specifically selected. (Use satWith, allSatWith, proveWith, etc.)
-  * Better handling of the pConstrain probability threshold for test
-    case generation and quickCheck purposes.
-  * Add 'renderTest', which accompanies 'genTest' to render test
-    vectors as Haskell/C/Forte program segments.
-  * Add 'expectedValue' which can compute the expected value of
-    a symbolic value under the given constraints. Useful for statistical
-    analysis and probability computations.
-  * When saturating provable values, use forAll_ for proofs and forSome_
-    for sat/allSat. (Previously we were allways using forAll_, which is
-    not incorrect but less intuitive.)
-  * add function:
-      extractModels :: SatModel a => AllSatResult -> [a]
-    which simplifies accessing allSat results greatly.
-
- Code-generation:
-
-  * add "cgGenerateMakefile" which allows the user to choose if SBV
-    should generate a Makefile. (default: True)
-
- Other
-
-  * Changes to make it compile with GHC 7.4.1.
-
-### Version 0.9.24, 2011-12-28
-
-  Library:
-
-   * Add "forSome," analogous to "forAll." (The name "exists" would've
-     been better, but it's already taken.) This is not as useful as
-     one might think as forAll and forSome do not nest, as an inner
-     application of one pushes its argument to a Predicate, making
-     the outer one useless, but it is nonetheless useful by itself.
-   * Add a "Modelable" class, which simplifies model extraction.
-   * Add support for quick-check at the "Symbolic SBool" level. Previously
-     SBV only allowed functions returning SBool to be quick-checked, which
-     forced a certain style of coding. In particular with the addition
-     of quantifiers, the new coding style mostly puts the top-level
-     expressions in the Symbolic monad, which were not quick-checkable
-     before. With new support, the quickCheck, prove, sat, and allSat
-     commands are all interchangeable with obvious meanings.
-   * Add support for concrete test case generation, see the genTest function.
-   * Improve optimize routines and add support for iterative optimization.
-   * Add "constrain", simplifying conjunctive constraints, especially
-     useful for adding constraints at variable generation time via
-     forall/exists. Note that the interpretation of such constraints
-     is different for genTest and quickCheck functions, where constraints
-     will be used for appropriately filtering acceptable test values
-     in those two cases.
-   * Add "pConstrain", which probabilistically adds constraints. This
-     is useful for quickCheck and genTest functions for filtering acceptable
-     test values. (Calls to pConstrain will be rejected for sat/prove calls.)
-   * Add "isVacuous" which can be used to check that the constraints added
-     via constrain are satisfable. This is useful to prevent vacuous passes,
-     i.e., when a proof is not just passing because the constraints imposed
-     are inconsistent. (Also added accompanying isVacuousWith.)
-   * Add "free" and "free_", analogous to "forall/forall_" and "exists/exists_"
-     The difference is that free behaves universally in a proof context, while
-     it behaves existentially in a sat context. This allows us to express
-     properties more succinctly, since the intended semantics is usually this
-     way depending on the context. (i.e., in a proof, we want our variables
-     universal, in a sat call existential.) Of course, exists/forall are still
-     available when mixed quantifiers are needed, or when the user wants to
-     be explicit about the quantifiers.
-
-  Examples
-
-   * Add Data/SBV/Examples/Puzzles/Coins.hs. (Shows the usage of "constrain".)
-
-  Dependencies
-
-   * Bump up random package dependency to 1.0.1.1 (from 1.0.0.2)
-
-  Internal
-
-   * Major reorganization of files to and build infrastructure to
-     decrease build times and better layout
-   * Get rid of custom Setup.hs, just use simple build. The extra work
-     was not worth the complexity.
-
-### Version 0.9.23, 2011-12-05
-  
-  Library:
-
-   * Add support for SInteger, the type of signed unbounded integer
-     values. SBV can now prove theorems about unbounded numbers,
-     following the semantics of Haskell Integer type. (Requires z3 to
-     be used as the backend solver.)
-   * Add functions 'optimize', 'maximize', and 'minimize' that can
-     be used to find optimal solutions to given constraints with
-     respect to a given cost function.
-   * Add 'cgUninterpret', which simplifies code generation when we want
-     to use an alternate definition in the target language (i.e., C). This
-     is important for efficient code generation, when we want to
-     take advantage of native libraries available in the target platform.
-
-  Other:
-
-   * Change getModel to return a tuple in the success case, where
-     the first component is a boolean indicating whether the model
-     is "potential." This is used to indicate that the solver
-     actually returned "unknown" for the problem and the model
-     might therefore be bogus. Note that we did not need this before
-     since we only supported bounded bit-vectors, which has a decidable
-     theory. With the addition of unbounded Integers and quantifiers, the
-     solvers can now return unknown. This should still be rare in practice,
-     but can happen with the use of non-linear constructs. (i.e.,
-     multiplication of two variables.)
-
-### Version 0.9.22, 2011-11-13
-   
-  The major change in this release is the support for quantifiers. The
-  SBV library *no* longer assumes all variables are universals in a proof,
-  (and correspondingly existential in a sat) call. Instead, the user
-  marks free-variables appropriately using forall/exists functions, and the
-  solver translates them accordingly. Note that this is a non-backwards
-  compatible change in sat calls, as the semantics of formulas is essentially
-  changing. While this is unfortunate, it is more uniform and simpler to understand
-  in general.
-
-  This release also adds support for the Z3 solver, which is the main
-  SMT-solver used for solving formulas involving quantifiers. More formally,
-  we use the new AUFBV/ABV/UFBV logics when quantifiers are involved. Also, 
-  the communication with Z3 is now done via SMT-Lib2 format. Eventually
-  the SMTLib1 connection will be severed.
-
-  The other main change is the support for C code generation with
-  uninterpreted functions enabling users to interface with external
-  C functions defined elsewhere. See below for details.
-
-  Other changes:
-
-  Code:
-
-   * Change getModel, so it returns an Either value to indicate
-     something went wrong; instead of throwing an error
-   * Add support for computing CRCs directly (without needing
-     polynomial division).
-
-  Code generation:
-
-   * Add "cgGenerateDriver" function, which can be used to turn
-     on/off driver program generation. Default is to generate
-     a driver. (Issue "cgGenerateDriver False" to skip the driver.)
-     For a library, a driver will be generated if any of the
-     constituent parts has a driver. Otherwise it will be skipped.
-   * Fix a bug in C code generation where "Not" over booleans were
-     incorrectly getting translated due to need for masking.
-   * Add support for compilation with uninterpreted functions. Users
-     can now specify the corresponding C code and SBV will simply
-     call the "native" functions instead of generating it. This
-     enables interfacing with other C programs. See the functions:
-     cgAddPrototype, cgAddDecl, cgAddLDFlags
-
-  Examples:
-
-   * Add CRC polynomial generation example via existentials
-   * Add USB CRC code generation example, both via polynomials and using the internal CRC functionality
-
-### Version 0.9.21, 2011-08-05
-   
- Code generation:
-
-  * Allow for inclusion of user makefiles
-  * Allow for CCFLAGS to be set by the user
-  * Other minor clean-up
-
-### Version 0.9.20, 2011-06-05
-   
-  Regression on 0.9.19; add missing file to cabal
-
-### Version 0.9.19, 2011-06-05
-
-
-  * Add SignCast class for conversion between signed/unsigned
-    quantities for same-sized bit-vectors
-  * Add full-binary trees that can be indexed symbolically (STree). The
-    advantage of this type is that the reads and writes take
-    logarithmic time. Suitable for implementing faster symbolic look-up.
-  * Expose HasSignAndSize class through Data.SBV.Internals
-  * Many minor improvements, file re-orgs
-
-Examples:
-
-  * Add sentence-counting example
-  * Add an implementation of RC4
-
-### Version 0.9.18, 2011-04-07
-
-Code:
-
-  * Re-engineer code-generation, and compilation to C.
-    In particular, allow arrays of inputs to be specified,
-    both as function arguments and output reference values.
-  * Add support for generation of generation of C-libraries,
-    allowing code generation for a set of functions that
-    work together.
-
-Examples:
-
-  * Update code-generation examples to use the new API.
-  * Include a library-generation example for doing 128-bit
-    AES encryption
-
-### Version 0.9.17, 2011-03-29
-   
-Code:
-
-  * Simplify and reorganize the test suite
-
-Examples:
-
-  * Improve AES decryption example, by using
-    table-lookups in InvMixColumns.
-  
-### Version 0.9.16, 2011-03-28
-
-Code:
-
-  * Further optimizations on Bits instance of SBV
-
-Examples:
-
-  * Add AES algorithm as an example, showing how
-    encryption algorithms are particularly suitable
-    for use with the code-generator
-
-### Version 0.9.15, 2011-03-24
-   
-Bug fixes:
-
-  * Fix rotateL/rotateR instances on concrete
-    words. Previous versions was bogus since
-    it relied on the Integer instance, which
-    does the wrong thing after normalization.
-  * Fix conversion of signed numbers from bits,
-    previous version did not handle twos
-    complement layout correctly
-
-Testing:
-
-  * Add a sleuth of concrete test cases on
-    arithmetic to catch bugs. (There are many
-    of them, ~30K, but they run quickly.)
-
-### Version 0.9.14, 2011-03-19
-    
-  * Reimplement sharing using Stable names, inspired
-    by the Data.Reify techniques. This avoids tricks
-    with unsafe memory stashing, and hence is safe.
-    Thus, issues with respect to CAFs are now resolved.
-
-### Version 0.9.13, 2011-03-16
-    
-Bug fixes:
-
-  * Make sure SBool short-cut evaluations are done
-    as early as possible, as these help with coding
-    recursion-depth based algorithms, when dealing
-    with symbolic termination issues.
-
-Examples:
-
-  * Add fibonacci code-generation example, original
-    code by Lee Pike.
-  * Add a GCD code-generation/verification example
-
-### Version 0.9.12, 2011-03-10
-  
-New features:
-
-  * Add support for compilation to C
-  * Add a mechanism for offline saving of SMT-Lib files
-
-Bug fixes:
-
-  * Output naming bug, reported by Josef Svenningsson
-  * Specification bug in Legatos multipler example
-
-### Version 0.9.11, 2011-02-16
-  
+* GitHub:  <http://github.com/LeventErkok/sbv>
+
+### Version 14.4, 2026-07-03
+
+  * Add `curry` and `uncurry` (for symbolic 2-tuples) and `curry3` and `uncurry3` (for
+    symbolic 3-tuples) to `Data.SBV.Tuple`, mirroring `Prelude.curry`/`Prelude.uncurry`.
+
+  * New example `Documentation.SBV.Examples.BitPrecise.Adders`, building ripple-carry and
+    carry-lookahead adders out of logic gates and proving them correct (equal to bit-vector
+    addition, equal to each other, and the carry-out equal to the overflow flag) fully
+    automatically by bit-blasting.
+
+  * New example `Documentation.SBV.Examples.TP.Adder`, the inductive companion to the above:
+    it models the operands as arbitrary-length symbolic bit lists and proves, for all widths
+    at once, that a ripple-carry adder computes the integer value of the bits, and that a
+    parallel-prefix (carry-lookahead) tree computes the same carry as the ripple---resting on
+    the associativity of the generate/propagate carry operator.
+
+  * Use str.to_re (instead of str.to.re) in regular-expression construction, which is the standard
+    naming in SMTLib2. Thanks to May Torrence for reporting the discrepancy.
+
+### Version 14.3, 2026-06-19
+
+  * Improve fpRoundToIntegralH to remove redundant internal check. Thanks to Ryan Scott for the report.
+
+  * Add support for arctan/arcsin/arccos in CVC5. Thanks to Ryan Scott for pointing out support for it.
+
+  * Improved backend-solver communication so that if a solver returns an error message SBV now makes
+    sure it gets captured and displayed properly before the solver-process itself terminates.
+
+  * Drop support for pi as an SReal: The whole premise of SReal is it represents algebraic-reals
+    (i.e., those that are roots of polynomials) exactly. But pi is not representable as such, since
+    it's transcendental. Older versions of SBV used an approximation, but that's confusing to say
+    the least, and downright wrong. Note that you can still use pi at floating-point types, where
+    precision loss is built into the semantics.
+
+  * Fix the enumeration quasi-quoter for a zero step: `[sEnum| 1, 1 .. 5 |]` is now the
+    (semantically infinite) list of 1's, instead of the empty list.
+
+  * Soundness fix for termination measures: a real-valued measure is now rejected at compile
+    time. The reals are not well-ordered (an infinite descending chain like 1, 1/2, 1/4, ...
+    never reaches a minimum), so a non-negative, strictly-decreasing real measure does not
+    imply termination. Use an integer-valued measure instead.
+
+  * Termination measures may now be given over the bounded bit-vector types (`Word8`..`Word64`,
+    `Int8`..`Int64`, `WordN n`, `IntN n`), in addition to the integer/float types supported before.
+
+### Version 14.2, 2026-06-05
+
+  * Fix float to integer conversions, which were ignoring the rounding mode previously. Thanks to
+    Ryan Scott for the report.
+
+  * Fix the implementation of properFraction for arbitrary-sized floats. Thanks to Ryan Scott
+    for the report and the fix.
+
+  * Fix a bug in pCase, where SBV was over-approximating the bound variables, causing the
+    unused-variable warning checker to flag branches unnecessarily in generated code.
+
+  * New TP example: Run-length encoding roundtrip (`Documentation.SBV.Examples.TP.RunLength`).
+    Proves that `decode (encode xs) == xs` for a run-length encode/decode pair.
+
+  * New TP example: Two-stack queue (`Documentation.SBV.Examples.TP.Queue`).
+    Proves that a queue implemented with two lists (front/back) correctly implements
+    FIFO semantics via an abstraction function.
+
+  * New cabal flag `compile_examples` (default: True) controls whether the
+    `Documentation.SBV.Examples.*` modules are built as part of the library.
+    Disable with `-f-compile_examples` when using SBV as a dependency to skip
+    compiling the example modules. Thanks to Robin Webbers for the contribution.
+
+  * Add more floating-point operations to `Data.SBV.Dynamic`. Thanks to Ryan Scott for the patch.
+
+### Version 14.1, 2026-05-04
+
+  * [BACKWARDS COMPATIBILITY] Removed `tpRibbon`. The ribbon length for TP proof
+    output is now auto-computed from the proof structure via a lightweight dry-run
+    pass. Users no longer need to manually set it.
+
+  * New TP combinators `whenDryRun` and `unlessDryRun` allow user code to guard
+    actions (e.g., proof tree printing) that should only run during the real pass of a TP
+    based proof.
+
+  * TP `pCase` now supports nested `case` expressions as proof case-splits,
+    mirroring how `sCase` treats nested `case` as symbolic cases.
+
+  * Consolidated internal solver IPC timeouts into named constants.
+    Set the environment variable `SBV_COMM_TIMEOUT_FACTOR` to scale them (e.g., `2` to double).
+
+  * Better handling of logic-strings, accommodating solver differences. Thanks to Ryan Scott for the report.
+
+  * Fixed a bug in fpRemH, which calculates the floating point reminder for concrete values. The result
+    was rounded twice, which is against the specification. Thanks to Ryan Scott for the report and the fix.
+
+  * Simplify how floating-point literals are printed. The older method worked for Z3/CVC5, but not for Bitwuzla.
+    Thanks to Ryan Scott for the report and the fix.
+
+  * Fix the definition of sRealToSIntegerTruncate to do proper truncation. Thanks to Ryan Scott for the
+    report and the fix.
+
+### Version 14.0, 2026-04-01
+
+  * [BACKWARDS COMPATIBILITY] The most important change in this release is how SBV treats
+    function definitions via `smtFunction` and its variants. In prior versions, these definitions were
+    directly translated to SMT-lib, without checking that they actually terminate. Starting with
+    this release, SBV now requires all functions to terminate (with an escape hatch where the user
+    explicitly opts out), and it proves it for all functions involved in a proof. SBV guesses
+    and verifies a termination measure, and in case it can't do so will tell the user to supply
+    their own version. This major departure from the old style of ignoring termination is a step
+    towards incorporating a better architecture for much improved (semi-)automated theorem proving
+    in SBV. See below for more details.
+
+  * [BACKWARDS COMPATIBILITY] Major improvements to the `sCase` and `pCase` quasi-quoters:
+    - Type prefix is no longer required; the type is inferred automatically
+      from the patterns. Old syntax: `[sCase|Expr e of ...]`. New syntax: `[sCase| e of ...]`.
+
+    - Wildcard-only patterns are now supported. An unguarded wildcard generates the rhs directly,
+      while guarded wildcards produce an `ite`-chain (for `sCase`) or proof obligations (for `pCase`).
+
+    - Built-in types are now supported: `Maybe`, `Either`, `List`, and `Tuple2` through `Tuple8`.
+      Nested patterns across built-in types are also supported (e.g., `Just (x:_)`, `Left (a, b)`).
+      For single-constructor types, the generated code omits the redundant constructor tester guard.
+
+    - Primitive types are now supported: `Bool`, `Integer`, `Char`, and `String`. Patterns can use
+      `True`/`False`, integer literals, character literals, string literals, variable bindings,
+      and wildcards.
+
+       ```haskell
+       [sCase| m of         [sCase| x of      [sCase| xs of                [sCase| c of
+          Nothing -> 0         0 -> sTrue        []      -> 0                 'a' -> 1
+          Just x  -> x + 1     _ -> sFalse       x : xs' -> x + f xs'         'b' -> 2
+       |]                   |]                |]                               _   -> 0
+                                                                           |]
+
+       [sCase| x of                            [sCase| x of
+          _ | x .> 0 -> x                         0         -> y
+            | sTrue  -> -x                        _ | x .> y -> x
+       |]                                           | sTrue  -> y
+                                               |]
+       ```
+
+    - As-patterns (`x@pat`) are now supported in both top-level and nested positions.
+      The as-name is bound to the scrutinee (top-level) or accessor (nested) via a
+      let-binding, which is elided when the name is unused. This works with all pattern
+      types: constructors, tuples, lists, wildcards, and in combination with nested `case`
+      expressions.
+
+       ```haskell
+       [sCase| xs of
+          a : tl@(_ : _) -> a + case tl of
+                                   b : _ -> b
+                                   []    -> 0
+          _ : _           -> 0
+          []              -> 0
+       |]
+       ```
+
+    - Plain `case` expressions inside `[sCase|...|]` and `[pCase|...|]` are now automatically
+      treated as symbolic case-splits. This works around GHC's quasi-quoter nesting limitation
+      (`[sCase|` cannot contain `|]`), and makes nested symbolic case expressions natural:
+
+       ```haskell
+       [sCase| e of
+          Zero      -> case m of
+                         Nothing -> 0
+                         Just v  -> v
+          Num k     -> k
+          Add a b   -> t a m + t b m
+       |]
+       ```
+
+      All `case` expressions inside `sCase` and `pCase` become symbolic; use a `let` or helper
+      function for regular Haskell case expressions.
+
+  * Improved documentation for `lambdaArray`, explaining the model-theoretic distinction
+    between the pure array theory (`select`/`store`/`const`) and the richer setting where
+    arrays are identified with function spaces.
+
+  * [BACKWARDS COMPATIBILITY] `recall` and `recallWith` no longer take a `String` argument.
+    A recalled proof is now automatically cached and reused if the same proposition is
+    encountered again. `tpNoCache` has been removed.
+
+  * SBV now detects conflicting `smtFunction` definitions: if two calls use the same SMT
+    name but have different bodies, an error is raised. Identical re-registrations (which
+    happen naturally with recursive functions) remain allowed.
+
+  * SBV now automatically checks termination of recursive functions defined via `smtFunction`.
+    A measure (a non-negative expression that strictly decreases at each recursive call) is
+    guessed automatically from argument types when possible. For functions that need an explicit
+    measure, use `smtFunctionWithMeasure`:
+
+    ```haskell
+    ld = smtFunctionWithMeasure "ld" (\k n -> (n - k) `smax` 0, [])
+       $ \k n -> ite (n `sMod` k .== 0) k (ld (k+1) n)
+    ```
+
+    When the measure requires inductive properties to verify, supply TP proof actions as helpers
+    via `measureLemma`/`measureLemmaWith`:
+
+    ```haskell
+    normalize = smtFunctionWithMeasure "normalize"
+                  ( \f -> tuple (ifComplexity f, ifDepth f)
+                  , [measureLemma ifDepthNonNeg, measureLemma ifComplexityPos]
+                  )
+              $ \f -> ...
+    ```
+
+  * For nested recursive functions (like McCarthy's 91 function) where the termination argument
+    depends on the function's return value at smaller inputs, use `smtFunctionWithContract`. This
+    takes a measure and a contract (post-condition) that are verified simultaneously via well-founded
+    induction:
+
+    ```haskell
+    mcCarthy91 = smtFunctionWithContract "mcCarthy91"
+                   ( \n -> 0 `smax` (101 - n)
+                   , \n r -> n .<= 100 .=> r .== 91
+                   , []
+                   )
+               $ \n -> ite (n .> 100) (n - 10) (mcCarthy91 (mcCarthy91 (n + 11)))
+    ```
+
+  * Productive (corecursive) functions can now be defined via `smtProductiveFunction`. Unlike
+    terminating functions, productive functions need not have a base case — they may produce
+    infinite output, so long as every recursive call is guarded by a data constructor.
+
+  * New function `smtFunctionNoTermination` for defining recursive SMT functions without any
+    termination check. The function is emitted as `define-fun-rec` and the user takes
+    responsibility for well-definedness. Use this for functions where termination is believed
+    but cannot be proven. Any TP proof that depends on such a function will be marked as
+    `[Modulo: <name> termination]` instead of `[Proven]` in its root of trust.
+
+  * New example `Documentation.SBV.Examples.TP.Countdown`, proving properties of a
+    list-building countdown function using induction.
+
+  * New example `Documentation.SBV.Examples.TP.NatStream`, demonstrating `smtProductiveFunction`
+    with the infinite stream `nats n = [n, n+1, n+2, ...]` and proofs about its head, length, and
+    element access.
+
+  * New example `Documentation.SBV.Examples.TP.MutualCorecursion`, demonstrating mutually
+    corecursive productive functions. Two functions `ping` and `pong` take turns producing
+    elements of a stream, and we prove elementwise equality and that the k-th element of
+    `ping n` is `n + k`.
+
+  * New example `Documentation.SBV.Examples.TP.Collatz`, using `smtFunctionNoTermination` to
+    define the Collatz function (whose termination is a famous open problem) and proving that
+    all powers of two reach 1.
+
+### Version 13.6, 2026-03-02
+
+  * The `sCase` quasi-quoter now supports nested constructor patterns. Sub-patterns
+    in a constructor match can themselves be constructors, including nullary ones. For example:
+
+    ```haskell
+    normalize f = smtFunction "normalize" $ \f ->
+      [sCase|Formula f of
+        If (If p q r) left right -> normalize (sIf p (sIf q left right) (sIf r left right))
+        If c          left right -> sIf c (normalize left) (normalize right)
+        _                        -> f
+      |]
+    ```
+
+    Nested patterns generate appropriate `isCstr`/`getCstr_i` guards and let-bindings
+    automatically. Pattern guards (`, e1, e2`) may also be used alongside nested patterns.
+    Additionally, `| True` is now accepted as a synonym for `| sTrue` in guards.
+
+  * The `sCase` quasi-quoter now supports integer and string literal patterns in nested
+    positions (and at the top level inside a constructor). For example:
+
+    ```haskell
+    p e = [sCase|Formula e of
+             Val 0         -> 100          -- fires when the Val field equals 0
+             Val 1         -> 200          -- fires when the Val field equals 1
+             Add (Val 0) r -> eval r       -- nested literal: fires when left child is Val 0
+             _             -> eval e
+          |]
+    ```
+
+    A literal sub-pattern desugars to a symbolic equality guard (`getC_i e .== lit`),
+    so the exhaustiveness checker correctly requires a fallback for any constructor
+    that only appears with literal sub-patterns.
+
+  * Add the `pCase` quasi-quoter for proof case-splits. Same syntax as `sCase`, but
+    generates `cases [cond ==> proof, ...]` instead of `ite` chains. Wildcards are
+    allowed as the last arm (with or without guards), generating a negated disjunction
+    of all prior guards to do fall-thru proofs.
+
+  * Add minimum and maximum to Data.SBV.List. If they receive empty list as argument,
+    then the result is underspecified, i.e., can be any value of the element type.
+
+  * Add mapConcat to Documentation.SBV.Examples.TP.Lists, which proves the theorem
+    `map f . concat = concat . map (map f)`.
+
+  * Add Documentation.SBV.Examples.TP.Kadane, proving the correctness of Kadane's algorithm
+    for computing the maximum segment sum. The proof uses a generalized invariant lemma to relate
+    the accumulator-based implementation to the specification. (This proof was completed with
+    assistance from Claude, in particular the part where we had to come up with the invariant
+    about the helper function.)
+
+  * Add Documentation.SBV.Examples.TP.Coins, proving the classic coin change theorem: for any
+    amount n >= 8, you can make exact change using only 3-cent and 5-cent coins. Inspired by
+    an Imandra example at <https://github.com/imandra-ai/imandrax-examples/blob/main/src/coins.iml>.
+
+  * Add Documentation.SBV.Examples.TP.Ackermann, proving the relationship between Ackermann's
+    original function and R. Peter's version (1935). Inspired by an Imandra example at
+    <https://github.com/imandra-ai/imandrax-examples/blob/main/src/ackermann.iml>. This proof
+    was developed by Claude with minimal user prompting and guidance.
+
+  * Add Documentation.SBV.Examples.TP.PigeonHole, proving the pigeonhole principle: If a list
+    of numbers sum up to more than the length of the list, then some cell must have a value
+    greater than one.
+
+  * Add Documentation.SBV.Examples.TP.TautologyChecker, a verified tautology checker for
+    propositional formulas using an unordered BDD-style SAT solver approach. The proof establishes
+    both soundness (if the checker says a formula is a tautology, it evaluates to true under all
+    bindings) and completeness (if the checker says a formula is not a tautology, falsify returns
+    a counterexample binding). Inspired by an Imandra example at
+    <https://github.com/imandra-ai/imandrax-examples/blob/main/src/tautology.iml>, originally
+    based on Boyer-Moore '79. This proof was developed with Claude's assistance.
+
+  * Add Documentation.SBV.Examples.TP.ConstFold, proving the correctness of a constant-folding
+    optimizer for a simple expression language with variables, constants, arithmetic, and let-bindings.
+    The optimizer performs bottom-up simplification including arithmetic identities (e.g., addition/
+    multiplication by 0 or 1, constant propagation) and let-folding (inlining `Let x (Con v) b` via
+    capture-avoiding substitution).
+
+### Version 13.5, 2026-01-26
+
+  * Replace internal SMT-lib program representation from plain String to Text. This
+    should improve performance and memory behavior in certain cases. Since solver time
+    dominates for most cases, this is not going to be noticeable by end-users, except
+    for very large programs. In any case, it should at least improve memory usage.
+    NB. Historical note: Most of these transformations were done by Claude code; the
+    era of AI coding had its first contributions to SBV. I' duly impressed by Claude's
+    ability to understand and manipulate Haskell. (I also tried Gemini, which was less
+    successful, compared to Claude.) I, for one, welcome our new computer overlords.
+
+  * Added Documentation.SBV.Examples.TP.UpDown.hs, demonstrating proof of a a couple of
+    list-processing functions together with naturals using TP. The problem itself is inspired
+    by a midterm exam question for an ACL2-class taught by J Moore at UT Austin back in 2011;
+    a minor tribute to J's amazing legacy.
+
+### Version 13.4, 2026-01-09
+
+  * Remove Eq constraint on readArray, generalizing it to arbitrary types for array-reads.
+
+  * Added 'freeArray', which creates an array with no constraints at all. (Compare to 'constArray'.)
+    Note that this is useful for expression contexts. If you're in a symbolic context (i.e., in
+    the Symbolic monad), you can just use 'free' or 'sArray' as usual.)
+
+  * Add missing instance of SatModel for Arrays. Thanks to Robin Webbers for the patch.
+
+  * Export ArrayModel, so it can be programmatically processed after a call.
+
+  * Moved Data/SBV/TP/List.hs to Documentation/SBV/Examples/TP/Lists.hs, which aligns better with the
+    haddock documentation.
+
+  * Fixed closure-version implementations of list functions filter, partition, takeWhile, and dropWhile.
+    Thanks to amigalemming on github for the bug report.
+
+  * Query mode now works with optimization directives. In this case, we perform lexicographic
+    optimization. (Let me know if you need other methods.) The advantage of this is that calls
+    to getValue works in this mode, so it is easier to access optimized model values. In case
+    the optimal value is in an extension field (i.e., involves epsilon or infinity values),
+    then calls to  getValue  will throw an error and alert the user. In this latter case, you
+    should resort back to using the regular optimize calls.
+
+  * Added new puzzle example: Documentation.SBV.Examples.Puzzles.SquareBirthday
+
+  * Add recallWith to Data.SBV.TP, which allows you to change the solver in a recalled proof.
+
+### Version 13.3, 2025-12-05
+
+  * Added 'constArray', which allows creation of constant valued symbolic arrays. The definition
+    is semantically equivalent to 'lambdaArray . const', but we generate simpler SMTLib code
+    for it. For the general case of initializing an array with arbitrary functions, continue
+    using 'lambdaArray'. Thanks to Robin Webbers for the patch.
+
+  * Improved the infinite-number-of-primes theorem statement slightly.
+
+### Version 13.2, 2025-12-02
+
+  * Improve support for SMTDefinable class, allowing support for on-the-fly generated functions.
+    Thanks to Eddy Westbrook for the patch. This should have no impact on existing code or usage,
+    just allowing new use cases. Let us know if it breaks anything.
+
+  * SBV now supports uninterpreted functions of arbitrary arities. (Previously, we had support for upto
+    12 args; Eddy's work above generalized this to arbitrary arity.)
+
+  * Added Documentation.SBV.Examples.TP.Primes, which formalizes prime numbers and proves that there are
+    an infinite number of primes.
+
+### Version 13.1, 2025-10-31
+
+  * Tweaks to make sure SBV compiles with GHC 9.8.4. No other changes on top of 13.0 below.
+
+### Version 13.0, 2025-10-31
+
+  * SBV now supports algebraic data-types. A new function 'mkSymbolic' is introduced, which take a list of types
+    and turns them into types that you can symbolically process. Clearly, Haskell ADTs are extremely rich:
+    Parameterized, self-referential, and mutually-recursive datatypes are supported. GADTs and more complicated
+    forms of data-types (with higher-order fields, for instance) are not supported. What SBV covers should handle
+    most use cases, please get in touch if you have a use case that is currently not supported.
+
+  * Introduced a new quasiquoter, named sCase, which allows writing case-expressions over symbolic ADTs. It supports
+    wildcards and guards. It does not support pattern guards, nor complex patterns. (Each pattern is either a
+    variable or an underscore.) Symbolic-boolean guards allow for concise expressions. This construct makes
+    symbolic programming with ADTs easier.
+
+  * Added examples under Documentation.SBV.Examples.ADT, demonstrating the use of basic ADTs and a case study
+    of modeling type-checking constraints.
+
+  * Added Documentation.SBV.Examples.TP.Peano, modeling peano numbers using an ADT and demonstrating many proofs.
+
+  * Added Documentation.SBV.Examples.TP.VM demonstrating the correctness of a simple interpreter over an expression
+    language with respect to a version that compiles the expression and runs the instructions over a virtual machine.
+
+  * [BACKWARDS COMPATIBILITY] The old functions 'mkSymbolicEnumeration' and 'mkUninterpretedSort' are now removed,
+    since their functionality is subsumed by 'mkSymbolic'.
+
+  * [BACKWARDS COMPATIBILITY] Strong-induction now takes extra proof objects that can be used to establish that
+    the measure provided is non-negative. This is usually not needed, so simply pass []. However, in case of strong
+    induction over ADTs in particular, it can come in handy to aid the solver in establishing the given measure
+    is valid.
+
+### Version 12.2, 2025-08-15
+
+  * Fix floating-point constant-folding code, which inadvertently constant-folded for symbolic rounding modes.
+
+  * Euclidian modulus/division does not restrict division by 0. Following SMTLib, we allow sEDiv and sEMod
+    to underconstrain the value if the divisor is 0. The main motivation for this is to allow for direct translation
+    to SMTLib for these operations where solvers perform much better. Fixed the code to avoid unintended constant
+    folding for the euclidian case.
+
+  * Add missing Num instance for SRational and beef up test suite. Thanks to Jan Grant for reporting.
+
+  * [BACKWARDS COMPATIBILITY] Reworked OrdSymbolic and Numeric instances, making them more robust. While this should
+    be mostly invisible to end-users, you might have to add an extra 'FlexibleInstances' pragma that wasn't needed
+    before. Please get in touch if you see inadvertent effects due to uses of symbolic ordering.
+
+  * TP: Add tpAsms, which explicitly prints the assumption-proving step for each proof transition. Default is False,
+    as assumptions are typically simple to prove. But if you use complicated booleans, this step can come in handy
+    in seeing where a proof gets stuck.
+
+  * TP: Add 'recall': Which turns of printing for a TP computation. This allows for non-verbose output in proof-scripts
+    when we reuse an old proof. Note that this is safe: We still run the proof mentioned so any failures in it will
+    be caught; it's just that we do it quietly to reduce verbosity in the re-calling proof.
+
+  * TP: Add '|->': This is similar to '|-', except it applies to a boolean-chain of reasoning where each step is
+    equivalent to the conjunction of the previous and the next. This allows for concise expression of boolean
+    reasoning steps. See gcdAdd in Documentation.SBV.Examples.TP.GCD for an example.
+
+  * Added Documentation.SBV.Examples.TP.GCD, which proves correctness and several other properties of Euclidian
+    GCD algorithm. We also prove subtraction based and the so-called binary-GCD algorithms correct.
+
+### Version 12.1, 2025-07-11
+
+  * Add missing instances for strong-equality, extending it to lists/Maybe etc. (Only impacts floats and structures
+    that contain floats.)
+
+  * Be more careful about applications of equality when floats are involved. Previously, we were using regular SMTLib
+    equality for structures. (i.e., lists of values or any other container that have a float element stored somewhere.)
+    Unfortunately the IEEE-754 semantics for equality does not correspond to SMTLib's notion of equality in these
+    cases, causing semantic differences. Now we are more careful, and we also warn the user about performance
+    implications and ask them to use custom-functions instead.
+
+### Version 12.0, 2025-07-04
+
+  * [BACKWARDS COMPATIBILITY] Renamed KnuckleDragger to TP, for theorem-proving. The original name was confusing, and
+    the design has diverged from Phil's tool in significant ways and goals.
+
+  * TP:
+      - Keep track of proofs with a unique id.
+      - Removed theorem variants; lemmas are almost exclusively used and the only difference was in printing.
+      - Add method rootOfTrust which can be used to retrieve uses of sorry in a proof. The idea is that
+        to get a proof clean, you need to resolve all the proofs returned by this call.
+      - Renamed kdShowDepsHTML to showProofTreeHTML. (Along with showProofTree which renders in ASCII.)
+      - Renamed the unicode symbol for hints from ⁇ to ∵, which is more mathematical.
+      - TP utils:
+          - Add tpQuiet : quiets TP proofs
+          - Add tpRibbon: simplifies setting the ribbon size in a proof.
+          - Add tpStats : makes TP proofs print detailed statistics
+          - Add tpCache : makes TP proofs use caching. This option can save time in re-running proofs. It comes
+                with the proof-obligation on the user that all the name/type pairs used in lemmas are unique. See
+                Documentation.SBV.Examples.TP.Basics for an example demonstration.
+        Note that all these utils will be in effect with the closest call to runTP/runTPWith. If you change the
+        solver for a specific lemma, we'll only change the solver, not TP-options.
+      - Generalize various TP list/sort proofs.
+      - Added qc/qcWith helpers, which allow you to run quick-check on specific proof steps
+      - Added disp as TP helper: It allows you to print the value of arbitrary expressions if a proof-step fails. Good for debugging.
+
+   * New TP examples:
+      - Documentation.SBV.Examples.TP.Fibonacci:  Proving tail-recursive fibonacci is equivalent to textbook definition
+      - Documentation.SBV.Examples.TP.Majority:   Proof of Boyer-Moore's majority selection algorithm correct.
+      - Documentation.SBV.Examples.TP.McCarthy91: Proof of correctness for McCarthy's 91 function.
+      - Documentation.SBV.Examples.TP.PowerMod:   Proving arithmetic properties relating power operation and modular arithmetic.
+      - Documentation.SBV.Examples.TP.ReverseAcc: Proving the accumulating reverse definition is correct.
+      - Documentation.SBV.Examples.TP.Reverse:    Proving a definition of reverse that uses no auxiliary definitions is correct.
+      - Documentation.SBV.Examples.TP.SumReverse: Proving summing a list and its reverse are equivalent.
+
+  * [BACKWARDS COMPATIBILITY] Reworked enum instances for symbolic values. Removed old Enum class instances for symbolic values,
+    as that API is not compatible with symbolic values, and only worked when the arguments used were literal constants. There is
+    now a new class 'EnumSymbolic' which has the exact same methods as 'Enum', except their types are more symbolic friendly. (For
+    instance, enumerations produce symbolic ists.) These definitions are now much more symbolic/proof friendly as well. In particular,
+    there is now an sEnum quasiquoter that allows you to construct symbolic enumerations of the form [|sEnum|a, b .. c|] etc., akin to
+    regular Haskell enumerations but working on symbolic values and constructing symbolic lists. If you had old code that relied
+    on Enum instances over constant symbolic values, you might have to use the underlying type for the enum, and then lift to
+    the symbolic level. Please get in touch if this causes issues.
+
+  * [BACKWARDS COMPATIBILITY] Remove Data.SBV.Tools.NaturalInduction. The functionality provided by this tool is much better
+    addressed by TP'sinduction methods. If you were using this functionality and have problems
+    porting to TP, please get in touch!
+
+  * Added functions 'takeWhile', 'dropWhile', 'sum', 'product', 'last', 'replicate', '\\', upFromTo, upFrom,
+    downFromTo, and downFrom to Data.SBV.List; corresponding to the symbolic equivalents of usual list processing functions.
+
+  * [BACKWARDS COMPATIBILITY] Removed Data.SBV.String, and unified list and string functions just as in Haskell. This was a
+    long-time wart in SBV, where we distinguished strings and list of characters since SMTLib does not equate them. SBV now
+    treats these uniformly, obviating the need for Data.SBV.String.
+
+  * Improved smt-function definitions: You can now define polymorphic, recursive, and higher-order functions in SBV
+    that will be translated to SMTLib functions, without expanding them. Polymorphic functions get monomorphised. Recursive
+    functions are supported, including mutual recursion.
+
+    NB. For higher-order functions, if the function passed (whether named or lambda defined) as the higher-order argument have
+    free variables, you must create a closure. See the 'Closure' type. If they are already closed, then you can use them as is.
+
+    See 'smtFunction' and 'smtHOFunction' for details.
+
+### Version 11.7, 2025-05-16
+
+  * KnuckleDragger: Add a proof of correctness for the quick-sort algorithm.
+
+  * KnuckleDragger: Add methods 'getProofTree' and 'kdShowDepsHTML' to collect and render
+    the proof as a dependency tree, unicode or as HTML. Useful for programming
+    methods/tactics on top of knuckle-dragger provided facilities.
+
+### Version 11.6, 2025-05-10
+
+  * Make SBV compile cleanly with GHC 9.8.4. This is really as far back a GHC you should be using,
+    unless you can't use anything newer.
+
+  * KnuckleDragger:
+      - Simplify and generalize inductive proofs. You can now do proofs with user-specified measure functions.
+      - Tweak proof-traces to print user given hints (aids in debugging).
+      - Add a proof of correctness for the binary-search algorithm.
+
+### Version 11.5, 2025-04-25
+
+  * Documentation updates
+
+  * KnuckleDragger: Add support for case-splitting, trivial proofs, and other improvements.
+
+  * KnuckleDragger: Add support for strong-induction principle over integers and lists.
+
+### Version 11.4, 2025-03-12
+
+  * Generalize the strong-induction principle to use lexicographic order for simultaneous
+    induction over two lists.
+
+  * Added a proof of correctness for the merge-sort algorithm using KnuckleDragger
+
+  * More exports from Data.SBV.Internals to enable compilation of SBVPlugin.
+
+### Version 11.3, 2025-03-10
+
+  * Fix various haddock documentation links
+
+  * KD: Clean-up proofs using the cases tactic
+
+### Version 11.2, 2025-03-08
+
+  * Renamed the all-sat partitioning function from 'partition' to 'allSatPartiton'
+
+  * Added support for 'partition' and 'splitAt' to Data.SBV.List
+
+  * KnuckleDragger:
+      - Renamed ? to ?? (which aligns better), and added unicode equivalent of it, named ⁇
+      - Added strong-induction as a proof-method, with examples for both numeric and list examples
+      - Added a double-induction principle, allowing inductive proofs over two lists simultaneously
+      - Added a case-splitting tactic for calculational style proofs
+      - Added many other example KD proofs, for lists in particular
+      - Added a proof of the (functional) insertion sort algorithm
+
+### Version 11.1, 2025-02-21
+
+  * Completely reworked KnuckleDragger interfaces and proof styles, adding calculational and induction
+    based proof strategies. SBV can now prove many inductive theorems in this mode, where the user guides
+    the SMT solver to find tricky proofs. See Documentation/SBV/Examples/KnuckleDragger directory for many
+    examples demonstrating the new features.
+
+  * Generalize support for polymorphic and higher-order functions. These are still experimental, as SMTLib's
+    higher-order function support is nascent. (Version 3 of SMTLib will have proper support for such functions, which
+    is not released yet.) Currently, SBV can handle polymorphic and higher-order usage of: 'reverse', 'any', 'all',
+    'filter', 'map', 'foldl', 'foldr', 'zip', and 'zipWith'; all exported from the 'Data.SBV.List' module.
+    These functions are supported polymorphically, and (except reverse and zip) all take a function as
+    an argument. SBV firstifies these functions, and the resulting code is compatible with Z3 and CVC5.
+    (Firstification might change in the future, as SMTLib gains support for more higher-order
+    features itself.) Proof-support in backend solvers for higher-order functions is still quite weak,
+    though KnuckleDragger makes things easier.
+
+  * Generalize the signatures of the default project-embed implementations of the Queriable class.
+
+  * [BACKWARDS COMPATIBILITY] Removed rarely used functions mapi, foldli, foldri from Data.SBV.List. These
+    can now be defined by the user as we have proper support for fold and map using lambdas.
+
+  * [BACKWARDS COMPATIBILITY] Removed "Data/SBV/Tools/BoundedFix.hs", and "Data/SBV/Tools/BoundedList.hs", which
+    were relatively unused and are more or less obsolete with SBV's new support for sequences and recursive
+    functions. If you were using these functions you could easily recreate them. Please get in touch if you
+    need this old functionality.
+
+  * [BACKWARDS COMPATIBILITY] Data.SBV no longer exports the class SatModel, which is more directed
+    towards internal SBV purposes. If you need it, you can now import it from Data.SBV.Internals.
+
+  * [BACKWARDS COMPATIBILITY] Added 'registerFunction' which comes in handy for telling SBV about functions
+    that are used in query mode. This is typically not necessary as SBV will register them automatically, but
+    there are certain scenarios where explicit control is needed. This function also generalizes the old
+    'registerUISMTFunction', which was a special case of this function and is now removed.
+
+  * [BACKWARDS COMPATIBILITY] The function 'registerSMTType' is renamed to 'registerType'.
+
+  * Fix the time-out limit setting for CVC4/5. Thanks to Daniel Matichuk for reporting.
+
+  * Fix a performance issue with nested-lambda/quantifiers. Thanks to Blake C. Rawlings for reporting and
+    Jeff Young for analysis.
+
+### Version 11.0, 2024-11-06
+
+  * [BACKWARDS COMPATIBILITY] SBV now handles arrays in a much more uniform way, unifying
+    their use with all the other symbolic types. This required some back-wards compatibility
+    changes, mostly around replacing calls to newArray with sArray. I expect there to be
+    no semantic changes, only syntactic ones. Please do get in touch if you have trouble
+    porting your old code using arrays to the new API.
+
+  * Turn on support for floats and uninterpreted sorts/functions in Bitwuzla.
+
+  * Add Data.SBV.Tools.KnuckleDragger, inspired by and modeled after Philip Zucker's tool
+    (https://github.com/philzook58/knuckledragger) by the same name.
+
+  * Added several KnuckleDragger proof examples, see Documentation.SBV.Examples.KnuckleDragger modules.
+    Amongst the proofs are the irrationality of square-root of 2, several list lemmas, and a few
+    inductive proofs over naturals, amongst others.
+
+  * Add sDivides, which takes a concrete integer and a (possibly symbolic), and returns sTrue
+    if the first argument divides the second. It is essentially equivalent to @a `sMod` n .== 0`,
+    but it translates to the built-in divisibility predicate in SMTLib, which (might) perform better.
+    Note that the @n@ argument is concrete, and must be > 0.
+
+  * Clarified SSet, SList, and SArray: keys/contents: In SMTLib, the semantics of these containers
+    use object-equality. In Haskell, they use instances of the Eq class. Usually this is just fine,
+    except when it isn't: Floats! Since NaN /= NaN, and +0 is distinguished from -0, what holds
+    in Haskell doesn't in the SMTLib logic. So, we define the semantics of equality to follow
+    the SMTLib semantics. If you are not using floats, then this doesn't matter. If you do, bear
+    in mind that the values will be treated with object equality; which (honestly) is easier to understand.
+
+  * SBV now prints the elements of uninterpreted sorts more simply for z3. Previously, we simply used the
+    name z3 produced, which looked like @T!val!i@ for the uninterpreted type @T@, we know convert it to @T_i@.
+
+  * Added Documentation/SBV/Examples/Puzzles/DieHard.hs, which solves the die-hard jug-water problem using
+    a BMC style search.
+
+  * [BACKWARDS COMPATIBILITY] Changed the signature of the functions bmc (and bmcWith), induct (and inductWith)
+    functions, so they take the transition as a relation, instead of a function returning multiple values. This
+    generalizes the use cases, and it is easy to translate from existing applications. Simply change your old
+    'State -> [State]' function to 'State -> State -> SBool', which can be achieved by
+    'newTrans s1 s2 = s2 `sElem` oldTrans s1', though you probably want to code this in a more readable way
+    depending on the actual transition relation you want to model. Furthermore, the function bmc is now
+    split into two bmcRefute and bmcCover, to indicate use cases more clearly.
+
+  * [BACKWARDS COMPATIBILITY] Removed the Fresh class, which was used as a proxy for the Queriable class as
+    an easier to instantiate version. The extra functionality unfortunately made writing custom Queriable
+    instances harder, and it is usually not harder to write Queriable in the first place.
+    If you were using the Fresh class, instead define Queriable, the definition should be fairly
+    simple. Please contact if you have difficulty using the Queriable interface.
+
+### Version 10.12, 2024-08-11
+
+  * Fix a few custom-floating-point format conversion bugs. Thanks to Sirui Lu for the patch.
+
+  * Add a few OVERLAPPABLE pragmas to generic Queriable instances to make them easily overridable by
+    user programs. Thanks to Marco Zocca for reporting.
+
+  * Add signedMulOverflow, which checks whether multiplication of two signed-bitvectors can overflow.
+    SBV already had a method (bvMulO) that served this purpose, translating to the corresponding predicate
+    in SMTLib. Unfortunately not all solvers support this predicate efficiently. In particular, as of Aug 2024,
+    bitwuzla has a performant checker for this overflow, but z3 does not. In case you cannot use bitwuzla for
+    some reason, you might want to use the new signedMulOverflow function for better performance.
+
+### Version 10.11, 2024-07-26
+
+  * Add Documentation.SBV.Examples.Puzzles.Tower module, solving the visible towers puzzle.
+
+  * Fix several representation bugs related to arbitrary-precision floats. Thanks to Sirui
+    Lu for the reports and patches.
+
+  * Removed the generic Num a => Num (SBV a) instance. When used at a non-standard type, this
+    created type-checking but invalid SBV programs. See https://github.com/LeventErkok/sbv/issues/706
+    for details.
+
+  * Add functions optLexicographic, optLexicographicWith, optPareto, optParetoWith, optIndependent, optIndependentWith
+    which makes using optimization functions easier. These are simple wrappers over the existing optimization routines,
+    simplifying their interface.
+
+  * Change how optimization results are presented when the underlying metric space is different from the type
+    being optimized. As noted in https://github.com/LeventErkok/sbv/issues/716, the format SBV used was confusing.
+    We now be more explicit, and print the original value in its own right, along with the metric-space value.
+    Thanks to Andrew Anderson for reporting.
+
+### Version 10.10, 2024-05-11
+
+  * Add EqSymbolic, OrdSymbolic and Mergeable instances for NonEmpty type
+
+  * Better handling of spawned processes, avoiding zombies. Thanks to Sirui Lu for the patch.
+
+### Version 10.9, 2024-04-05
+
+  * Fix printing of floats to be more consistent, using lowercase letters
+
+### Version 10.8, 2024-04-05
+
+  * Increase the number of digits used in printing floats in decimal base, which leads to
+    better output in most cases.
+
+### Version 10.7, 2024-03-23
+
+  * Fix SMTDefinable instances for functions of arity 8-12. Thanks to Nick Lewchenko for the patch.
+
+### Version 10.6, 2024-03-16
+
+  * Added Data.SBV.Tools.BVOptimize module, which implements a custom optimizer for unsigned bit-vector
+    values. See 'minBV' and 'maxBV' methods. These algorithms use the incremental solver instead of
+    the optimizer engines, and they can be more performant in certain cases. (For instance, z3's
+    optimization engine isn't incremental, which makes it perform poorly on certain BV-optimization
+    problems.) These algorithms scan the bits from most to least significant bit, and individually
+    set/unset them in an incremental fashion to optimize quickly.
+
+  * SBV web-page is no longer maintained. The info is put into the README.md instead.
+
+### Version 10.5, 2024-02-20
+
+  * Export svFloatingPointAsSWord through Data.SBV.Internals
+
+  * crackNum: if verbose, alert the user if surface value of a NaN doesn't match its calculated value
+    due to the redundancy in NaN representations.
+
+### Version 10.4, 2024-02-15
+
+  * Before issuing a get-value, make sure there are no outstanding assert calls.
+    See: https://github.com/LeventErkok/sbv/issues/682 for details.
+
+  * crackNum mode now displays the surface form of NaNs more faithfully, if provided
+    with the input string. This functionality is used by the crackNum executable.
+
+### Version 10.3, 2024-01-05
+
+  * Clean-up GHC extensions required in the cabal file, and changes required to compile cleanly with GHC 9.8 series.
+
+  * Added 'partition', which allows for partitioning all-sat search spaces when models are generated.
+
+  * Added 'sSetBitTo', variant of 'setBitTo', but allows symbolic indexes.
+
+  * Added 'uninterpretWithArgs', which allows for user given argument names for uninterpreted functions. These
+    names come in handy when displaying models of uninterpreted functions.
+
+  * Added `Documentation.SBV.Examples.Misc.ProgramPaths`, showing an example use of all-sat partitioning.
+
+  * Added `Documentation.SBV.Examples.BitPrecise.PEXT_PDEP`, modeling x86 instructions PDEP and PEXT.
+
+  * Added `Documentation.SBV.Examples.Puzzles.Newspaper`, another puzzle example.
+
+  * Added `Documentation.SBV.Examples.ProofTools.AddHorn`, demonstrating the use of the horn-clause solver for
+    invariant generation.
+
+  * Add 'sbv2smt', which renders the given sbv definition as an SMTLib definition. Mainly useful for debugging purposes.
+    It can render both ground definitions and functions, and the latter can be handy in producing SMTLib functions to
+    be used in other settings.
+
+  * Add support for OpenSMT from Università della Svizzera italiana https://verify.inf.usi.ch/opensmt
+
+  * Fix a bug in bit-vector rotation that manifested itself in small-bv sizes. Thanks to Sirui Lu for reporting.
+
+  * [BACKWARDS COMPATIBILITY] Change the overflow detection API to match the new SMTLib predicates. These predicates
+    do not distinguish between over/underflow, so strictly speaking the new API is less powerful than the old one. However,
+    we choose to follow SMTLib here for portability purposes. If you need separate overflow/underflow checking you can
+    use the encodings from earlier implementations, please get in touch if this proves problematic.
+
+  * [BACKWARDS COMPATIBILITY] Dropped hasSize, which checked cardinality of sets. This call hasn't been supported by
+    z3 for some time, and its uses were thus limited, and behavior was problematic even when supported due to finiteness
+    issues.
+
+  * Removed a few examples, which were causing regression failures with changes in z3. These are trickier examples, and
+    new releases of z3 had varying performance issues, making them not suitable regression and documentation purposes. In
+    particular, 'Documentation.SBV.Examples.Existentials.CRCPolynomial', 'Documentation.SBV.Examples.Lists.Nested', and
+    'Documentation.SBV.Examples.BitPrecise.MultMask' were removed.
+
+  * SBV now keeps track of contexts, thus avoiding rare (but unsound) cases of incorrect API usage where contexts
+    are mixed. We now issue a run-time error. See https://github.com/LeventErkok/sbv/issues/71 for details.
+
+  * Improve the getFunction signature, to return more detailed info on the produced SMT functions, including the parse-tree.
+
+  * SBV now tracks whether a declared uninterpreted function is curried or not. This helps in more precise printing of
+    satisfying models with uninterpreted functions. (Previously all UI functions were displayed as if they were curried.)
+
+### Version 10.2, 2023-06-09
+
+  * Improve HLint pragmas. Thanks to George Thomas for the patch.
+
+  * Added an implementation of the Prince encryption algorithm. See Documentation/SBV/Examples/Crypto/Prince.hs.
+
+  * Added on-the-fly decryption mode for AES. See Documentation/SBV/Examples/Crypto/AES.hs for details.
+
+  * Added functions `sEDivMod`, `sEDiv`, and `sEMod` which perform euclidian division over symbolic integers.
+
+  * Added 'Data.SBV.Tools.NaturalInduction' which provides a proof method to perform induction over natural numbers. See the functions 'inductNat' and 'inductNatWith'.
+
+### Version 10.1, 2023-04-14
+
+  * [BACKWARDS COMPATIBILITY] SBV now handles quantifiers in a much more disciplined way. All of the previous
+    ways of creating quantified variables (i.e., the functions sbvForall, sbvExists, universal, existential) are
+    removed. Instead, we can now express quantifiers in a much straightforward way, by passing them to
+    'constrain' directly. A simple example is:
+
+        constrain $ \(Forall x) (Exists y) -> y .> (x :: SInteger)
+
+    You can nest quantifiers as you wish, and the quantified parameters can be of arbitrary symbolic type.
+    Additionally, you can convert such a quantified formula to a regular boolean, via a call to 'quantifiedBool'
+    function, essentially performing quantifier elimination:
+
+        other_condition .&& quantifiedBool (\(Forall x) (Exists y) -> y .> (x :: SInteger))
+
+    Or you can prove/sat quantified formulas directly:
+
+        prove $ \(Forall x) (Exists y) -> y .> (x :: SInteger)
+
+    This facility makes quantifiers part of the regular SBV language, allowing them to be mixed/matched with all
+    your other symbolic computations.
+
+    SBV also supports the constructors ExistsUnique to create unique existentials, in addition to
+    ForallN and ExistsN for creating multiple variables at the same time.
+
+    The new function skolemize can be used to skolemize quantified formulas: The skolemized version of a
+    formula has no existential (replaced by uninterpreted functions), and is equisatisfiable to the original.
+
+    See the following files demonstrating reasoning with quantifiers:
+
+       * Documentation/SBV/Examples/Puzzles/Birthday.hs
+       * Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
+       * Documentation/SBV/Examples/Puzzles/Rabbits.hs
+       * Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
+
+  * You can now define new functions in the generated SMTLib output, via an smtFunction call. Typically, we simply
+    unroll all definitions, but there are certain cases where we would like the functions
+    remain intact in the output. This is especially true of recursive functions, where the termination would
+    depend on a symbolic variable, which cannot be symbolically-simulated. By translating these to SMTLib
+    functions, we can now handle such definitions. Note that such definitions will no longer be constant-folded
+    on the Haskell side, and each call will induce a call in the solver instead. The new method smtFunction
+    can handle both recursive and non-recursive functions. See "Documentation/SBV/Examples/Misc/Definitions.hs"
+    for examples.
+
+  * Added new SList functions: map, mapi, foldl, foldr, foldli, foldri, zip, zipWith, filter, all, any.
+    Note that these work on arbitrary--but finite--length lists, with all terminating elements, per
+    usual SBV interpretation. These functions map to the underlying solver's fold and map functions,
+    via lambda-abstractions. Note that the SMT engines remain incomplete with respect to sequence
+    theories. (That is, any property that requires induction for its proof will cause unknown
+    answers, or will not terminate.) However, basic properties, especially when the solver can determine the
+    shape of the sequence arguments (i.e., number of elements), should go through.
+
+  * New function 'lambdaAsArray' allows creation of array values out of lambda-expressions. See
+    "Documentation/SBV/Examples/Misc/LambdaArray.hs" for an example use. This adds expressive power,
+    as we can now specify arrays with index dependent contents much more easily.
+
+  * Added support for abduct-generation, as supported by CVC5. See "Documentation/SBV/Examples/Queries/Abducts.hs"
+    for a basic example.
+
+  * Added support for special-relations. You can now check if a relation is partial, linear, tree,
+    or piecewise-linear orders in SBV. (Or you can constrain relations to satisfy the corresponding laws, thus
+    creating relations with these properties.) Additionally, you can create transitive-closures of relations.
+    See Documentation/SBV/Examples/Misc/FirstOrderLogic.hs for several examples.
+
+  * [BACKWARDS COMPATIBILITY] The signature of Data.SBV.List's concat has changed. In previous releases
+    this was a synonym for appending two lists, now it takes a list-of-lists and flattens it, matching the
+    Haskell list function with the same name.
+
+  * [BACKWARDS COMPATIBILITY] The function addAxiom is removed. Instead use quantified-constraints, as described
+    above.
+
+  * [BACKWARDS COMPATIBILITY] Renamed the Uninterpreted class to SMTDefinable, since its task has changed, handling
+    both kinds of definitions. Unless you were referring to the name Uninterpreted in your code, this should not
+    impact you. Otherwise, simply rename it to SMTDefinable.
+
+  * [BACKWARDS COMPATIBILITY] The configuration variable 'allowQuantifiedQueries' is removed. It is no
+    longer relevant with our new quantification strategy described above.
+
+  * [BACKWARDS COMPATIBILITY] The function 'isVacuous' is renamed to 'isVacuousProof' (and 'isVacuousWith'
+    became 'isVacuousProofWith') to better reflect this function applies to checking vacuity in a proof context.
+
+  * [BACKWARDS COMPATIBILITY] Satisfiability and proof checks are now put in different classes, instead of sharing
+    the same class. This should not have any impact on user-level code, unless you were building libraries
+    on top of SBV. See the 'ProvableM' and 'SatisfiableM' classes.
+
+  * [BACKWARDS COMPATIBILITY] Renamed 'Goal' to 'ConstraintSet' which is more indicative of its purpose. A set
+    of constraints can be satisfied, but proving them does not make sense. The name goal, however, suggested
+    something we can prove.
+
+  * [BACKWARDS COMPATIBILITY] SBV is now more lenient in returning function-interpretations, returning the SMTLib
+    string in complicated cases in case of bailing out. Note that we still don't support complicated function
+    values in allSat calls, as there's no way to reject existing interpretations. Consequently, the
+    parameter 'satTrackUFs' is renamed to 'allSatTrackUFs' to better capture its new role.
+
+  * Addressed an issue on Windows where solver synchronization fails due to unmapped diagnostic-challenge.
+    (See issue #644 for details.) Thanks to Ryan Scott for reporting and helping with debugging.
+
+  * Add missing Arbitrary instances for WordN and IntN types, enabling quickcheck on these types.
+
+  * Rewrote some of the older examples to use more modern SBV idioms.
+
+  * Changes needed to compile with upcoming GHC 9.6. Thanks to Lars Kuhtz and Ryan Scott for several patches.
+
+### Version 9.2, 2023-1-16
+
+  * Handle uninterpreted sorts better, avoiding kind-registration issue.
+    See #634 for details. Thanks to Nick Lewchenko for the report.
+
+### Version 9.1, 2023-01-09
+
+  * CVC5: Add support for algebraic reals in CVC5 models
+
+  * Export more solvers from Trans/Dynamic interfaces. Thanks to Ryan Scott for the patch.
+
+### Version 9.0, 2022-04-27
+
+  * Changes required to compile cleanly with GHC 9.2 series.
+
+  * In future versions, GHC will make `forall` a reserved word, which will create a conflict with SBV's use of the same.
+    To accommodate for these changes and to be consistent, following identifiers were renamed:
+
+       - `forall`   --> `sbvForall`
+       - `forall_`  --> `sbvForall_`
+       - `exists`   --> `sbvExists`
+       - `exists_`  --> `sbvExists_`
+       - `forAll`   --> `universal`
+       - `forAll_`  --> `universal_`
+       - `forSome`  --> `existential`
+       - `forSome_` --> `existential_`
+
+   * Add support for `reverse` on symbolic lists and strings. Note that this definition uses a recursive function
+     declaration in SMTLib, so any proof involving inductive reasoning will likely not-terminate. However, it
+     should be usable at ground-level and for simpler non-inductive properties. Of course, as SMT-solvers mature
+     this can change in the future.
+
+   * Changed the String/List versions of `.++/.!!` to directly use the names `++/!!`. Since these modules
+     are intended to be used qualified only, there's no reason to add the dots.
+
+   * Added function `addSMTDefinition`, which allows users to give direct definitions of SMTLib functions. This
+     is useful for defining recursive functions that are not symbolically terminating.
+
+   * Added `Documentation.SBV.Examples.Lists.CountOutAndTransfer` example, proving that the so-called
+     coating card trick works correctly.
+
+   * Added `Documentation.SBV.Examples.Puzzles.Jugs` example, solving the water-jug transfer puzzle.
+
+   * Added `Documentation.SBV.Examples.Puzzles.AOC_2021_24` example, showing how to model an EDSL in SBV,
+     solving the advent-of-code, 2021, day 24 problem.
+
+   * Added `Documentation.SBV.Examples.Puzzles.Drinker` example, proving the famous Drinker paradox of
+     Raymond Smullyan.
+
+   * Added concrete type instances of Mergeable class.
+
+   * Fixed a bug in the implementation of the concrete-path for sPopCount
+
+   * Added complement, power, and difference operators for regular expressions. Also added `everything`, `nothing`,
+     `anyChar` as new recognizers.
+
+   * Fixed the semantics of `All` regular expressions to recognize all-strings, and added `AllChar` as a
+     new regular-expression constructor to match any single regular expression. Thanks to Matt Torrence for
+     the patch.
+
+   * Fixed a bug in the concrete implementation of bit-vector join, which didn't handle signed quantities
+     correctly. Thanks to Sirui Lu for the report and test cases.
+
+### Version 8.17, 2021-10-25
+
+  * SBV now supports cvc5; the latest incarnation of CVC. See https://github.com/cvc5/cvc5
+    for details.
+
+  * SBV now supports bitwuzla; the latest incarnation of Boolector. See https://bitwuzla.github.io
+    for details.
+
+  * Fixed handling of CRational values in constant folding, which was missing a case.
+    Thanks to Jaro Reinders for reporting.
+
+  * Fixed calls to distinct for floating-point values, causing SBV to throw an exception.
+
+  * Add missing instances of SatModel for Char and String. Thanks to eax- on github
+    for the contribution.
+
+  * Add support for symbolic comparison of regular expressions.
+
+  * Export svToSV from Data.SBV.Dynamic. Thanks to Matt Parker for the PR.
+
+### Version 8.16, 2021-08-18
+
+  * Put extra annotations on data-type constructors, which makes
+    SBV generate problems that z3 can parse more easily. Thanks to
+    Greg Sullivan for reporting the issue in the first place.
+
+### Version 8.15, 2021-05-30
+
+  * Remove support for SFunArray abstraction. Turns out that the caching
+    mechanisms SBV used for SFunArray weren't entirely safe, and the code
+    has become unmaintainable over-time. Instead you should simply use
+    SArray, which has the exact same API. Thanks to frenchFrog42 on
+    github for reporting some of the problems.
+
+  * Fix the cmd line params for invocations of Boolector. You need
+    Boolector 3.2.2 to work with this version of SBV.
+
+  * NB. Recent releases of z3 no longer support optimization of real-valued
+    goals in the presence of strict inequalities, i.e., .>, .<, and ./= operators.
+    So, you might get a bogus result if you are using optimization with
+    SReal parameters that have strict inequalities. See https://github.com/Z3Prover/z3/issues/5314
+    for details. There is not much SBV can do to prevent these, unfortunately,
+    as z3 optimization engine goals seem to have changed. Note that use of
+    non-strict inequalities (i.e., .>=, .<=) should be fine. Also, this
+    only impacts the optimize calls: regular sat/prove invocations are not
+    impacted.
+
+### Version 8.14, 2021-03-29
+
+  * Improve the fast all-sat algorithm to also support uninterpreted values.
+
+  * Generalize svTestBit to work on floats, returning the respecting bit in the
+    representation of the float.
+
+  * Fixes to crack-num facility of how we display floats in detail.
+
+### Version 8.13, 2021-03-21
+
+  * Generalized floating point: Add support for brain-floats, with
+    type `SFPBFloat`, which has 8-bits of exponent and 8-bits of
+    significand. This format is affectionately called "brain-float"
+    because it's often used in modeling neural networks machine-learning
+    applications, offering a wider-range than IEEE's half-float, at the
+    expense of reduced precision. It has 8-exponent bits and 8-significand
+    bits, including the hidden bit.
+
+  * Add support for SRational type, rational values built out of the ratio
+    of two integers. Use the module "Data.SBV.Rational", which exports the
+    constructor .% to build rationals. Note that you cannot take numerator
+    and denominator of rationals apart, since SMTLib has no way of storing
+    the rational in a canonical way. Otherwise, symbolic rationals follow
+    the same rules as Haskell's Rational type.
+
+  * SBV now implements a faster allSat algorithm, which applies in most common
+    use cases. (Essentially, when there are no uninterpreted values or sorts present.)
+    The new algorithm has been measured to be at least an order of magnitude
+    faster or more in common cases as it splits the search space into disjoint
+    models, reducing the burden of accumulated lemmas over multiple calls. (See
+    http://theory.stanford.edu/%7Enikolaj/programmingz3.html#sec-blocking-evaluations
+    for details.)
+
+### Version 8.12, 2021-03-09
+
+  * Fix a bug in crackNum for unsigned-integer values, which incorrectly
+    showed a negation sign for values with msb set to 1.
+
+### Version 8.11, 2021-03-09
+
+  * SBV now supports floating-point numbers with arbitrary exponent and
+    significand sizes. The type is `SFloatingPoint eb sb`, where `eb`
+    and `sb` are type-level naturals. In particular, SBV can now reason about
+    half-floats, which are used much more frequently in ML applications. Through
+    the LibBF binding, you can also use these concretely, so if you have a use
+    case for computing with floats, you can use SBV as a vehicle for doing so.
+    The exponent/significand sizes are limited to those supported by the LibBF
+    bindings, though the allowed range is rather large and should not be a limitation
+    in practice. (In particular, you'll most likely run out of memory before you
+    hit precision limits!)
+
+  * We now support a separate `crackNum` parameter in model display. If set to True
+    (default is False), SBV will display numeric values of bounded integers, words,
+    and all floats (SDouble, SFloat, and the new SFloatingPoint) in models in detail,
+    showing how they are laid out in memory. Numbers follow the usual 2's-complement
+    notation if they are signed, bit-vectors if they are not signed, and the floats
+    follow the usual IEEE754 binary layout rules. Similarly, there's now a function
+    crack :: SBV a -> String that does the same for non-model printing contexts.
+
+  * Changed the isNonModelVar config param to take a String (instead of Text).
+    Simplifies programming.
+
+  * Changes to make SBV compile with GHC9.0. Thanks to Ryan Scott for the patch.
+
+### Version 8.10, 2021-02-13
+
+  * Add "Documentation/SBV/Examples/Misc/NestedArray.hs" to demonstrate how
+    to model multi-dimensional arrays in SBV.
+
+  * Add "Documentation/SBV/Examples/Puzzles/Murder.hs" as another puzzle example.
+
+  * Performance updates: Thanks to Jeff Young, SBV now uses better underlying
+    data structures, performing better for heavy use-case scenarios.
+
+  * SBV now tracks constants more closely in query mode, providing more support
+    for constant arrays in a seamless way. (See #574 for details.)
+
+  * Pop-calls are now supported for Yices and Boolector. (#577)
+
+  * Changes required to make SBV work with latest version of z3 regarding
+    String and Characters, which now allow for unicode characters. This required
+    renaming of certain recognizers in 'Data.SBV.Char' to restrict them to the
+    Latin1 subset. Otherwise, the changes should be transparent to the end user.
+    Please report any issues you might run into when you use SChar and SString types.
+
+### Version 8.9, 2020-10-28
+
+  * Rename 'sbvAvailableSolvers' to 'getAvailableSolvers'.
+
+  * Use SMTLib's int2bv if supported by the backend solver. If not, we still
+    do a manual translation. (CVC4 and z3 support it natively, Yices and
+    MathSAT does not, for which we do the manual translation. ABC and dReal
+    doesn't support the conversion at all, since former doesn't support integers
+    and the latter doesn't support bit-vectors.) Thanks to Martin Lundfall
+    for the initial pull request.
+
+  * Add `sym` as a synonym for `uninterpret`. This allows us to write expressions
+    of the form `sat $ sym "a" - sym "b" .== (0::SInteger)`, without resorting to lambda
+    expressions or having to explicitly be in the Symbolic monad.
+
+  * Added missing instances for overflow-checking arithmetic of arbitrary
+    sized signed and unsigned bitvectors.
+
+  * In a sat (or allSat) call, also return the values of the uninterpreted values, along with
+    all the explicitly named inputs. Strictly speaking, this is backwards-incompatible,
+    but it the new behavior is consistent with how we handle uninterpreted values in general.
+
+  * Improve SMTLib logic-detection code to use generics.
+
+### Version 8.8, 2020-09-04
+
+  * Reworked uninterpreted sorts. Added new function `mkUninterpretedSort` to make
+    declaration of completely uninterpreted sorts easier. In particular, we now
+    automatically introduce the symbolic variant of the type (by prefixing the
+    underlying type with `S`) so it becomes automatically available, both for uninterpreted
+    sorts and enumerations. In the latter case, we also automatically introduce the value `sX`
+    for each enumeration constant `X`, defined to be precisely `literal X`.
+
+  * Handle incremental mode table-declarations that depend on freshly declared variables. Thanks
+    to Gergő Érdi for reporting.
+
+  * Fix a soundness bug in SFunArray caching. Thanks to Gergő Érdi for reporting. See
+    https://github.com/LeventErkok/sbv/issues/541 for details.
+
+  * Add support for the dReal solver, and introduce the notion of delta-satisfiability,
+    where you can now check properties to be satisfiable against delta-perturbations.
+    See "Documentation.SBV.Examples.DeltaSat.DeltaSat" for a basic example.
+
+  * Add "extraArgs" parameter to SMTConfig to simplify passing extra command line
+    arguments to the solver.
+
+  * Add a method
+
+        sListArray :: (HasKind a, SymVal b) => b -> [(SBV a, SBV b)] -> array a b
+
+    to the `SymArray` class, which allows for creation of arrays from lists of constant or
+    symbolic lists of pairs. The first argument is the value to use for uninitialized entries.
+    Note that the initializer must be a known constant, i.e., it cannot be symbolic. Latter
+    elements of the list will overwrite the earlier ones, if there are repeated keys.
+
+  * Thanks to Jan Hrcek, a whole bunch of typos were fixed in the documentation and
+    the source code. Much appreciated!
+
+### Version 8.7, 2020-06-30
+
+  * Add support for concurrent versions of solvers for query problems. Similar to
+    `satWithAny`, `proveWithAny` etc., except when we have queries. Thanks to Jeffrey Young
+    for the idea and the implementation.
+
+  * Add "Documentation.SBV.Examples.Misc.Newtypes", demonstrating how to use newtypes
+    over existing symbolic types as symbolic quantities themselves. Thanks to Curran McConnell
+    for the example.
+
+  * Added new predicate `sNotElem`, negating `sElem`.
+
+  * Added new predicate `distinctExcept`. This is same as `distinct`
+    except you can also provide an ignore list. The elements in
+    the first list will be checked to be distinct from each other,
+    or belong to the second list. This is good for writing constraints
+    that either require a default value or if picked be different
+    from each other for a set of variables. This sort of constraint
+    can be coded in user space, but SBV generates efficient code
+    instead of the obvious quadratic number of constraints.
+
+  * Add function 'algRealToRational' that can convert an algebraic-real
+    to a Haskell rational. We get an either value: If the algebraic real
+    is exact, then it returns a 'Left' value that represents the value
+    precisely. Otherwise, it returns a 'Right' value, which is only
+    an approximation. Note: Setting 'printRealPrec' in SMTConfig
+    to a higher value will increase the precision at the cost of more
+    computation by the SMT solver.
+
+  * Removed the 'SMTValue' class. It's functionality was not really
+    needed. If you ever used this class, removing it from your
+    type signatures should fix the issue. (You might have to
+    add SymVal constraint if you did not already have it.) Please
+    get in touch if you used this class in some cunning way and you
+    need its functionality back.
+
+  * Reworked SBVBenchSuite api, Phase 1 of BenchSuite completed.
+
+  * Add support for addAxiom command to work in the interactive mode.
+    Thanks to Martin Lundfall for the feedback.
+
+  * Fixed `proveWithAny` and `satWithAny` functions so they properly
+    kill the solvers that did not terminate first. Previously, they
+    became zombies if they didn't end up quickly. Thanks to
+    Robert Dockins for the investigation and the fix.
+
+  * Fixed a bug where resetAssertions call was forgetting to restore the
+    array and table contexts. Thanks to Martin Lundfall for reporting.
+
+### Version 8.6, 2020-02-08
+
+  * Fix typo in error message. Thanks to Oliver Charles
+    for the patch.
+
+  * Fix parsing of sequence counter-examples to accommodate
+    recent changes in z3.
+
+  * Add missing exports related to N-bit words. Thanks to
+    Markus Barenhoff for the patch.
+
+  * Generalized code-generation functions to accept a function
+    with an arbitrary return type, which was previously just unit.
+    This allows for complicated code-generation scenarios where
+    one code-gen run can produce input to the next.
+
+  * Scalability improvements for internal data structures. Thanks
+    to Brian Huffman for the patch.
+
+  * Add interpolation support for Z3, following changes to that
+    solver. Note that SBV now supports two different APIs for
+    interpolation extraction, one for Z3 and the other for
+    MathSAT. This is unfortunate, but necessary since interpolant
+    extraction isn't quite standardized amongst solvers and
+    MathSAT and Z3 use sufficiently different calling mechanisms
+    to warrant their own calls. See 'Documentation.SBV.Examples.Queries.Interpolants'
+    for examples that illustrate both cases.
+
+  * Add a new argument to `displayModels` function to allow rearranging
+    of the results in an 'allSat` call. Strictly speaking this is
+    a backwards breaking change, but substituting `id` for the
+    new argument gives you old functionality, so easy to work-around.
+
+
+### Version 8.5, 2019-10-16
+
+  * Changes to compile with GHC 8.8. Thanks to Oliver Charles
+    for the patch.
+
+  * Minor fix to how kinds are shown for non-standard sizes.
+
+  * Thanks to Jeffrey Young, SBV now has a performance benchmark
+    test-suite. The framework still new, but should help
+    in the long run to make sure SBV performance doesn't regress
+    on its test-suite, and by extension in general usage.
+
+### Version 8.4, 2019-08-31
+
+  * SBV now supports arbitrary-size bit-vectors, i.e.,
+    SWord 17, SInt 9, SWord 128 etc. These work like any
+    other bit-vector, using the `DataKinds` feature of
+    GHC. Thanks to Ben Blaxill for the idea and the initial
+    implementation. Note that SBV still supports the traditional
+    fixed-size bit-vectors, SInt8, SWord16 etc. Support for
+    these will not be removed; so existing programs will
+    continue to work.
+
+  * To convert between arbitrary sized bit-vectors and
+    the old style equivalents, use `fromSized` and `toSized`
+    functions. The behavior is controlled with a closed
+    type-family so you will get a (hopefully not too
+    horrendous) type error message if you try to convert,
+    say, a SInt16 to SInt 22; or vice versa.
+
+  * Added arbitrary-sized bit vector operations: extraction,
+    extension, and joining; these use proxy arguments to
+    determine precise size info, and are much better suited
+    for type safety. Consequently, removed the Splittable
+    class which provided similar operations but only on
+    predefined types. There is a new class called ByteConverter
+    to convert to-and-from bytes for suitable bit-vector
+    sizes up to 512.
+
+  * Tuple construction functions are given new types to strengthen
+    type checking. Previously the tuple argument was ignored,
+    causing things to be marked as tuples when they actually
+    cannot be. (NB. The system was always type-safe, it just
+    didn't produce helpful type-error messages before.)
+
+  * Model validator: In the presence of universally quantified
+    variables, SBV used to refuse to validate given models. This
+    is the right thing to do since we would have to validate
+    the model for all possible values of all the universally
+    quantified variables. Obviously this is not useful. Instead,
+    SBV now simply assumes any universally quantified variable
+    is zero during model validation. This severely limits the
+    validation result, but it is better than nothing. (In the
+    verbose mode, a message to this effect will be printed.)
+
+  * Model validator: SBV can now validate models returned from
+    the backend solver for regular-expression match problems.
+    We also constant fold matches against constant strings without
+    calling the solver at all, less useful perhaps but more inline
+    with the general SBV methodology.
+
+  * Add implementation of SHA-2 family of functions as an example
+    algorithm.  These are good for code-generation purposes as
+    opposed to actual verification tasks as it is hard to state
+    any properties of these algorithms. But the SBV generated
+    code can be quite useful in other development and verification
+    environments. See 'Documentation.SBV.Examples.Crypto.SHA' for
+    details.
+
+  * Add 'cgShowU8UsingHex function, which controls if we print unsigned-8 bit
+    values in code generation driver code in hex or not. Previously we were
+    using decimal, but in crypto code hex is always better. Default is 'False'
+    to keep backwards compatibility.
+
+  * Add `sObserve` from: `SymWord a => String -> SBV a -> Symbolic ()` which
+    comes in handy in symbolic contexts, especially with quick-check uses.
+
+  * Ramped up travis-appveyor build infrastructure. However, we no
+    longer test on the CI, since build-times are prohibitively long
+    and myriad issues cause instability. If you can help out regarding
+    testing on CI, please reach out!
+
+### Version 8.3, 2019-06-08
+
+  * Increment base dependency to 4.11.
+
+  * Add support for `Data.Set.hasSize`.
+
+  * Add `supportsFP` to CVC4 capabilities list. (#469)
+
+  * Fix a glitch in allSat computations that incorrectly
+    used values of internal variables in model construction.
+
+  * SBV now directly uses the new `seq.nth` function from z3
+    for sequence element access, instead of implementing it
+    internally.
+
+### Version 8.2, 2019-04-07
+
+  * Fixed minor issue with getting observables in quantified contexts.
+
+  * Simplify data-type constructor usage and accessor formats. See
+    http://github.com/Z3Prover/z3/issues/2135 for a discussion.
+
+  * Add support for model validation in optimization problems. Use the
+    config parameter: `optimizeValidateConstraints`. Default: False. This
+    feature nicely complements the `validateModel` option, which works
+    for `sat` and `prove` calls. Note that when we validate the model
+    for an optimization problem, we only make sure that the given result
+    satisfies the constraints not that it is minimum (or maximum) such
+    model. (And hence the new configuration variable.) Validating optimality
+    is beyond the scope of SBV.
+
+### 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 equivalent 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 'allowQuantifiedQueries', 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
+    'allowQuantifiedQueries' 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
+    changes. Lots of reworking of the internals to modernize the SBV code base.
+    A few external API changes happened as well, mainly in terms of renamed
+    types/operators to reflect the current state of things. I expect most end user
+    programs to carry over unchanged, perhaps needing a bunch of renames. See below
+    for details.
+
+  * Transformer stack and `SymbolicT`: This major internal revamping was contributed
+    by Brian Schroeder. Brian reworked the internals of SBV to allow for custom monad
+    stacks. In particular, there is now a `SymbolicT` monad transformer, which
+    generalizes the `Symbolic` monad over an arbitrary base type, allowing users to
+    build SBV based symbolic execution engines on top of their own monad infrastructure.
+
+    Brian took the pains to ensure existing users (or those who do not have their
+    own monad stack), the transformer capabilities remain transparent. That is,
+    your existing code should recompile as is, or perhaps with minor aesthetic
+    changes. Please report if you find otherwise, or need help.
+
+    See `Documentation.SBV.Examples.Transformers.SymbolicEval` for an example of
+    how to use the transformer based code.
+
+    Thanks to Brian Schroeder for this massive effort to modernize the SBV code-base!
+
+  * Support for tuples: Thanks to Joel Burget, SBV now supports tuple types (up-to
+    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. 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
+    the generality was hardly ever used and caused typing ambiguities. The new
+    implementation simplifies boolean operators to simply operate on the `SBool`
+    type. Also changed the operator names to fit with all the others by starting
+    them with dots. A simple conversion guide:
+
+        * Literal True : true    became   sTrue
+        * Literal False: false   became   sFalse
+        * Negation     : bNot    became   sNot
+        * Conjunction  : &&&     became   .&&
+        * Disjunction  : |||     became   .||
+        * XOr          : <+>     became   .<+>
+        * Nand         : ~&      became   .~&
+        * Nor          : ~|      became   .~|
+        * Implication  : ==>     became   .=>
+        * Iff          : <=>     became   .<=>
+        * Aggregate and: bAnd    became   sAnd
+        * Aggregate or : bOr     became   sOr
+        * Existential  : bAny    became   sAny
+        * Universal    : bAll    became   sAll
+
+  * [BACKWARDS COMPATIBILITY, INTERNAL] Historically, SBV focused on bit-vectors and machine
+    words, which meant lots of internal types were named suggestive of this heritage.
+    With the addition of `SInteger`, `SReal`, `SFloat`, `SDouble` we have expanded
+    this, but still remained focused on atomic types. But, thanks largely to
+    Joel Burget, SBV now supports symbolic characters, strings, lists, and now
+    tuples, and nested tuples/lists, which makes this word-oriented naming confusing.
+    To reflect, we made the following internal renamings:
+
+        * SymWord     became      SymVal
+        * SW          became      SV
+        * CW          became      CV
+        * CWVal       became      CVal
+
+    Along with these, many of the internal constructor/variable names also changed in
+    a similar fashion.
+
+    For most casual users, these changes should not require any changes. But if you were
+    developing libraries on top of SBV, then you will have to adapt to the new schema.
+    Please report if there are any gotchas we have forgotten about.
+
+  * [BACKWARDS COMPATIBILITY] When user queries are present, SBV now picks the logic
+    "ALL" (as opposed to a suitable variant of bit-vectors as in the past versions).
+    This can be overridden by the 'setLogic' command as usual of course. While the new
+    choice breaks backwards compatibility, I expect the impact will be minimal, and
+    the new behavior matches better with user expectations on how external queries are
+    usually employed.
+
+  * [BACKWARDS COMPATIBILITY] Renamed the module `Data.SBV.List.Bounded` to
+    `Data.SBV.Tools.BoundedList`.
+
+  * Introduced a `Queriable` class, which simplifies symbolic programming with composite
+    user types. See `Documentation.SBV.Examples.ProofTools` directory for several
+    use cases and examples.
+
+  * Added function `observeIf`, companion to `observe`. Allows observing of values
+    if they satisfy a given predicate.
+
+  * Added function `ensureSat`, which makes sure the solver context is satisfiable
+    when called in the query mode. If not, an error will be thrown. Simplifies
+    programming when we expect a satisfiable result and want to bail out if otherwise.
+
+  * Added `nil` to `Data.SBV.List`. Added `nil` and `uncons` to `Data.SBV.String`.
+    These were inadvertently left out previously.
+
+  * Add `Data.SBV.Tools.BMC` module, which provides a BMC (bounded-model
+    checking engine) for traditional state transition systems. See
+    `Documentation.SBV.Examples.ProofTools.BMC` for example uses.
+
+  * Add `Data.SBV.Tools.Induction` module, which provides an induction engine
+    for traditional state transition systems. Also added several example use
+    cases in the directory `Documentation.SBV.Examples.ProofTools`.
+
+### Version 7.13, 2018-12-16
+
+  * Generalize the types of `bminimum` and `bmaximum` by removing the `Num`
+    constraint.
+
+  * Change the type of `observe` from: `SymWord a => String -> SBV a -> Symbolic ()`
+    to `SymWord a => String -> SBV a -> SBV a`. This allows for more concise observables,
+    like this:
+
+        prove $ \x -> observe "lhs" (x+x) .== observe "rhs" (2*x+1)
+        Falsifiable. Counter-example:
+          s0  = 0 :: Integer
+          lhs = 0 :: Integer
+          rhs = 1 :: Integer
+
+  * Add `Data.SBV.Tools.Range` module which defines `ranges` and `rangesWith` functions: They
+    compute the satisfying contiguous ranges for predicates with a single variable. See
+    `Data.SBV.Tools.Range` for examples.
+
+  * Add `Data.SBV.Tools.BoundedFix` module, which defines the operator `bfix` that can be used
+    as a bounded fixed-point operator for use in bounded-model-checking like algorithms. See
+    `Data.SBV.Tools.BoundedFix` for some example use cases.
+
+  * Fix list-element extraction code, which asserted too strong a constraint. See issue #421
+    for details. Thanks to Joel Burget for reporting.
+
+  * New bounded list functions: `breverse`, `bsort`, `bfoldrM`, `bfoldlM`, and `bmapM`.
+    Contributed by Joel Burget.
+
+  * Add two new puzzle examples:
+       * `Documentation.SBV.Examples.Puzzles.LadyAndTigers`
+       * `Documentation.SBV.Examples.Puzzles.Garden`
+
+### Version 7.12, 2018-09-23
+
+  * Modifications to make SBV compile with GHC 8.6.1. (SBV should
+    now compile fine with all versions of GHC since 8.0.1; and
+    possibly earlier. Please report if you are using a version
+    in this range and have issues.)
+
+  * Improve the BoundedMutex example to show a non-fair trace.
+    See `Documentation/SBV/Examples/Lists/BoundedMutex.hs`.
+
+  * Improve Haddock documentation links throughout.
+
+### Version 7.11, 2018-09-20
+
+  * Add support for symbolic lists. (That is, arbitrary but fixed length symbolic
+    lists of integers, floats, reals, etc. Nested lists are allowed as well.)
+    This is building on top of Joel Burget's initial work for supporting symbolic
+    strings and sequences, as supported by Z3. Note that the list theory solvers
+    are incomplete, so some queries might receive an unknown answer. See
+    `Documentation/SBV/Examples/Lists/Fibonacci.hs` for an example, and the
+    module `Data.SBV.List` for details.
+
+  * A new module `Data.SBV.List.Bounded` provides extra functions to manipulate
+    lists with given concrete bounds. Note that SMT solvers cannot deal with
+    recursive functions/inductive proofs in general, so the utilities in this
+    file can come in handy when expressing bounded-model-checking style
+    algorithms. See `Documentation/SBV/Examples/Lists/BoundedMutex.hs` for a
+    simple mutex algorithm proof.
+
+  * Remove dependency on data-binary-ieee754 package; which is no longer
+    supported.
+
+### Version 7.10, 2018-07-20
+  * [BACKWARDS COMPATIBILITY] '==' and '/=' now always throw an error instead of
+    only throwing an error for non-concrete values.
+    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
+    value, which itself can be symbolic. If provided, the array will return
+    the given value for all reads from uninitialized locations. If not given,
+    then reads from unwritten locations produce uninterpreted constants. The
+    behavior of 'SFunArray' and 'SArray' is exactly the same in this regard.
+    Note that this is a backwards-compatibility breaking change, as you need
+    to pass a 'Nothing' argument to 'newArray' to get the old behavior.
+    (Solver note: If you use 'SFunArray', then defaults are fully supported
+    by SBV since these are internally handled, concrete or symbolic. If you
+    use 'SArray', which gets translated to SMTLib, then MathSAT and Z3 supports
+    default values with both concrete and symbolic cases, CVC4 only supports
+    if they are constants. Boolector and Yices don't support default values
+    at this point in time, and ABC doesn't support arrays at all.)
+
+  * [BACKWARDS COMPATIBILITY] SMTException type has been renamed to
+    SBVException. SBV now throws this exception in more cases to aid in
+    building tools on top of SBV that might want to deal with exceptions
+    in different ways. (Previously, we used to call 'error' instead.)
+
+  * [BACKWARDS COMPATIBILITY] Rename 'assertSoft' to 'assertWithPenalty', which
+    better reflects the nature of this function. Also add extra checks to warn
+    the user if optimization constraints are present in a regular sat/prove call.
+
+  * Implement `softConstrain`: Similar to 'constrain', except the solver is
+    free to leave it unsatisfied (i.e., leave it false) if necessary to
+    find a satisfying solution. Useful in modeling conditions that are
+    "nice-to-have" but not "required." Note that this is similar to
+    'assertWithPenalty', except it works in non-optimization contexts.
+    See `Documentation.SBV.Examples.Misc.SoftConstrain` for a simple example.
+
+  * Add 'CheckedArithmetic' class, which provides bit-vector arithmetic
+    operations that do automatic underflow/overflow checking. The operations
+    follow their regular counter-parts, with an exclamation mark added at
+    the end: +!, -!, *!, /!. There is also negateChecked, for the same
+    function on unary negation. If you program using these functions,
+    then you can call 'safe' on the resulting programs to make sure
+    these operations never cause underflow and overflow conditions.
+
+  * Similar to above, add 'sFromIntegralChecked', providing overflow/underflow
+    checks for cast operations.
+
+  * Add `Documentation.SBV.Examples.BitPrecise.BrokenSearch` module to show the
+    use of overflow checking utilities, using the classic broken binary search
+    example from http://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html
+
+  * Fix an issue where SBV was not sending array declarations to the SMT-solver
+    if there were no explicit constraints. Thanks to Oliver Charles for reporting.
+
+  * Rework 'SFunArray' implementation, addressing performance issues. We now
+    carefully memoize elements as we do the look-ups. This addresses several
+    performance issues that came up; hopefully providing some relief. The
+    function 'mkSFunArray' is also removed, which used to lift Haskell
+    functions to such arrays, often used to implement initial values. Now,
+    if a read is done on an unwritten element of 'SFunArray' we get an
+    uninterpreted constant. This is inline with how 'SArray' works, and
+    is consistent. The old 'SFunArray' implementation based on functions
+    is no longer available, though it is easy to implement it in user-space
+    if needed. Please get in contact if this proves to be an issue.
+
+  * Add 'freshArray' to allow for creation of existential fresh arrays in the query mode.
+    This is similar to 'newArray' which works in the Symbolic mode, and is analogous to
+    'freshVar'. Most users shouldn't need this as 'newArray' calls should suffice. Only
+    use if you need a brand new array after switching to query mode.
+
+  * SBV now rejects queries if universally quantified inputs are present. Previously
+    these were allowed to go through, but in general skolemization makes the corresponding
+    variables unusable in the query context. See http://github.com/LeventErkok/sbv/issues/407
+    for details. If you have an actual use case for such a feature, please get in
+    touch. Thanks to Brian Schroeder for reporting this anomaly.
+
+  * Export 'addSValOptGoal' from 'Data.SBV.Internals', to help with 'Metric' class
+    instantiations. Requested by Dan Rosen.
+
+  * Export 'registerKind' from 'Data.SBV.Internals', to help with custom array declarations.
+    Thanks to Brian Schroeder for the patch.
+
+  * If an asynchronous exception is caught, SBV now throws it back without further processing.
+    (For instance, if the backend solver gets killed. Previously we were turning these into
+    synchronous errors.) Thanks to Oliver Charles for pointing out this corner case.
+
+### Version 7.9, 2018-06-15
+
+  * Add support for bit-vector arithmetic underflow/overflow detection. The new
+    'ArithmeticOverflow' class captures conditions under which addition, subtraction,
+    multiplication, division, and negation can underflow/overflow for
+    both signed and unsigned bit-vector values. The implementation is based on
+    http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/z3prefix.pdf,
+    and can be used to detect overflow caused bugs in machine arithmetic.
+    See `Data.SBV.Tools.Overflow` for details.
+
+  * Add 'sFromIntegralO', which is the overflow/underflow detecting variant
+    of 'sFromIntegral'. This function returns (along with the converted
+    result), a pair of booleans showing whether the conversion underflowed
+    or overflowed.
+
+  * Change the function 'getUnknownReason' to return a proper data-type
+    ('SMTReasonUnknown') as opposed to a mere string. This is at the
+    query level. Similarly, change `Unknown` result to return the same
+    data-type at the sat/prove level.
+
+  * Interpolants: With Z3 4.8.0 release, Z3 folks have dropped support
+    for producing interpolants. If you need interpolants, you will have
+    to use the MathSAT backend now. Also, the MathSAT API is slightly
+    different from how Z3 supported interpolants as well, which means
+    your old code will need some modifications. See the example in
+    Documentation.SBV.Examples.Queries.Interpolants for the new usage.
+
+  * Add 'constrainWithAttribute' call, which can be used to attach
+    arbitrary attribute to a constraint. Main use case is in interpolant
+    generation with MathSAT.
+
+  * C code generation: SBV now spits out linker flag -lm if needed.
+    Thanks to Matt Peddie for reporting.
+
+  * Code reorg: Simplify constant mapping table, by properly accounting
+    for negative-zero floats.
+
+  * Export 'sexprToVal' for the class SMTValue, which allows for custom
+    definitions of value extractions. Thanks to Brian Schroeder for the
+    patch.
+
+  * Export 'Logic' directly from Data.SBV. (Previously was from Control.)
+
+  * Fix a long standing issue (ever since we introduced queries) where
+    'sAssert' calls were run in the context of the final output boolean,
+    which is simply the wrong thing to do.
+
+### Version 7.8, 2018-05-18
+
+  * Fix printing of min-bounds for signed 32/64 bit numbers in C
+    code generation: These are tricky since C does not allow
+    -min_value as a valid literal!  Instead we use the macros provided in
+    stdint.h. Thanks to Matt Peddie for reporting this corner case.
+
+  * Fix translation of the `abs` function in C code generation, making
+    sure we use the correct variant. Thanks to Matt Peddie for reporting.
+
+  * Fix handling of tables and arrays in pushed-contexts. Previously,
+    we used initializers to get table/array values stored properly.
+    However, this trick does not work if we are in a pushed-context;
+    since a pop can forget the corresponding assignments. SBV now
+    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 http://github.com/LeventErkok/sbv/issues/374
+    for details.)
+
+  * Fix corner case in ite branch equality with float/double arguments,
+    where we were previously confusing +/-0 as equal to each other.
+    Thanks to Matt Peddie for reporting.
+
+  * Add a call 'cgOverwriteFiles', which suppresses code-generation
+    prompts for overwriting files and quiets the prompts during
+    code generation. Thanks to Matt Peddie for the suggestion.
+
+  * Add support for uninterpreted function introductions in the query
+    mode. Previously, this was only allowed before the query started,
+    now we fully support uninterpreted functions in all modes.
+
+  * New example: Documentation/SBV/Examples/Puzzles/HexPuzzle.hs,
+    showing how to code cover properties using SBV, using a form
+    of bounded model checking.
+
+### Version 7.7, 2018-04-29
+
+  * Add support for Symbolic characters ('SChar') and strings ('SString'.)
+    Thanks to Joel Burget for the initial implementation.
+
+    The 'SChar' type currently corresponds to the Latin-1 character
+    set, and is thus a subset of the Haskell 'Char' type. This is
+    due to the current limitations in SMT-solvers. However, there
+    is a pending SMTLib proposal to support unicode, and SBV will track
+    these changes to have full unicode support: For further details
+    see: https://smt-lib.org/theories-UnicodeStrings.shtml
+
+    The 'SString' type is the type of symbolic strings, consisting
+    of characters from the Latin-1 character set currently, just
+    like the planned 'SChar' improvements. Note that an 'SString'
+    is *not* simply a list of 'SChar' values: It is a symbolic
+    type of its own and is processed as a single item. Conversions
+    from list of characters is possible (via the 'implode' function).
+    In the other direction, one cannot generally 'explode' a string,
+    since it may be of arbitrary length and thus we would not know
+    what concrete list to map it to. This is a bit unlike Haskell,
+    but the differences dissipate quickly in general, and the power
+    of being able to deal with a string as a symbolic entity on its
+    own opens up many verification possibilities.
+
+    Note that currently only Z3 and CVC4 has support for this logic,
+    and they do differ in some details. Various character/string
+    operations are supported, including length, concatenation,
+    regular-expression matching, substring operations, recognizers, etc.
+    If you use this logic, you are likely to find bugs in solvers themselves
+    as support is rather new: Please report.
+
+  * If unsat-core extraction is enabled, SBV now returns the unsat-core
+    directly with in a solver result. Thanks to Ara Adkins for the
+    suggestion.
+
+  * Add 'observe'. This function allows internal expressions to be
+    given values, which will be part of the satisfying model or
+    the counter-example upon model construction. Useful for tracking
+    expected/returned values. Also works with quickCheck.
+
+  * Revamp Haddock documentation, hopefully easier to follow now.
+
+  * Slightly modify the generated-C headers by removing whitespace.
+    This allows for certain "lint" rules to pass when SBV generated
+    code is used in conjunction with a larger code base. Thanks
+    to Greg Horn for the pull request.
+
+  * Improve implementation of 'svExp' to match that of '.^', making
+    it more defined when the exponent is constant. Thanks to Brian
+    Huffman for the patch.
+
+  * Export the underlying polynomial representation for algorithmic
+    reals from the Internals module for further user processing.
+    Thanks  to Jan Path for the patch.
+
+### Version 7.6, 2018-03-18
+
+  * GHC 8.4.1 compatibility: Work around compilation issues. SBV
+    now compiles cleanly with GHC 8.4.1.
+
+  * Define and export sWordN, sWordN_, sIntN_, from the Dynamic
+    interface, which simplifies creation of variables of arbitrary
+    bit sizes. These are similar to sWord8, sInt8, etc.; except
+    they create dynamic counterparts that can be of arbitrary bit size.
+
+### Version 7.5, 2018-01-13
+
+  * Remove obsolete references to tactics in a few haddock comments. Thanks
+    to Matthew Pickering for reporting.
+
+  * Added logic Logic_NONE, to be used in cases where SBV should not
+    try to set the logic. This is useful when there is no viable value to
+    set, and the back-end solver doesn't understand the SMT-Lib convention
+    of using "ALL" as the logic name. (One example of this is the Yices
+    solver.)
+
+  * SBV now returns SMTException (instead of just calling error) in case
+    the backend solver responds with error message. The type SMTException
+    can be caught by the user programs, and it includes many fields as an
+    indication of what went wrong. (The command sent, what was expected,
+    what was seen, etc.) Note that if this exception is ever caught, the
+    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 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
+    base-type it's used at is Integral. This was already true for all instances,
+    so we are just making it more explicit.
+
+  * Improve the implementation of .^ (exponentiation) to cover more cases,
+    in particular signed exponents are now OK so long as they are concrete
+    and positive, following Haskell convention.
+
+  * Removed the 'FromBits' class. Its functionality is now merged with the
+    new 'SFiniteBits' class, see below.
+
+  * Introduce 'SFiniteBits' class, which only incorporates finite-words in it,
+    i.e., SWord/SInt for 8-16-32-64. In particular it leaves out SInteger,
+    SFloat, SDouble, and SReal. Important in recognizing bit-vectors of
+    finite size, essentially. Here are the methods:
+
+        class (SymWord a, Num a, Bits a) => SFiniteBits a where
+            sFiniteBitSize      :: SBV a -> Int                     -- ^ Bit size
+            lsb                 :: SBV a -> SBool                   -- ^ Least significant bit of a word, always stored at index 0.
+            msb                 :: SBV a -> SBool                   -- ^ Most significant bit of a word, always stored at the last position.
+            blastBE             :: SBV a -> [SBool]                 -- ^ Big-endian blasting of a word into its bits. Also see the 'FromBits' class.
+            blastLE             :: SBV a -> [SBool]                 -- ^ Little-endian blasting of a word into its bits. Also see the 'FromBits' class.
+            fromBitsBE          :: [SBool] -> SBV a                 -- ^ Reconstruct from given bits, given in little-endian
+            fromBitsLE          :: [SBool] -> SBV a                 -- ^ Reconstruct from given bits, given in little-endian
+            sTestBit            :: SBV a -> Int -> SBool            -- ^ Replacement for 'testBit', returning 'SBool' instead of 'Bool'
+            sExtractBits        :: SBV a -> [Int] -> [SBool]        -- ^ Variant of 'sTestBit', where we want to extract multiple bit positions.
+            sPopCount           :: SBV a -> SWord8                  -- ^ Variant of 'popCount', returning a symbolic value.
+            setBitTo            :: SBV a -> Int -> SBool -> SBV a   -- ^ A combo of 'setBit' and 'clearBit', when the bit to be set is symbolic.
+            fullAdder           :: SBV a -> SBV a -> (SBool, SBV a) -- ^ Full adder, returns carry-out from the addition. Only for unsigned quantities.
+            fullMultiplier      :: SBV a -> SBV a -> (SBV a, SBV a) -- ^ Full multiplier, returns both high and low-order bits. Only for unsigned quantities.
+            sCountLeadingZeros  :: SBV a -> SWord8                  -- ^ Count leading zeros in a word, big-endian interpretation
+            sCountTrailingZeros :: SBV a -> SWord8                  -- ^ Count trailing zeros in a word, big-endian interpretation
+
+    Note that the functions 'sFiniteBitSize', 'sCountLeadingZeros', and 'sCountTrailingZeros' are
+    new. Others have existed in SBV before, we are just grouping them together now in this new class.
+
+  * Tightened certain signatures where SBV was too liberal, using the SFiniteBits class. New signatures are:
+
+         sSignedShiftArithRight :: (SFiniteBits a, SIntegral b) => SBV a -> SBV b -> SBV a
+         crc                    :: (SFiniteBits a, SFiniteBits b) => Int -> SBV a -> SBV b -> SBV b
+         readSTree              :: (SFiniteBits i, SymWord e) => STree i e -> SBV i -> SBV e
+         writeSTree             :: (SFiniteBits i, SymWord e) => STree i e -> SBV i -> SBV e -> STree i e
+
+    Thanks to Thomas DuBuisson for reporting.
+
+### Version 7.4, 2017-11-03
+
+  * Export queryDebug from the Control module, allowing custom queries to print
+    debugging messages with the verbose flag is set.
+
+  * Relax value-parsing to allow for non-standard output from solvers. For
+    instance, MathSAT/Yices prints reals as integers when they do not have a
+    fraction. We now support such cases, relaxing the standard slightly. Thanks
+    to Geoffrey Ramseyer for reporting.
+
+  * 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 http://github.com/LeventErkok/sbv/issues/333
+    for details.
+
+### Version 7.3, 2017-09-06
+
+  * Query mode: Add support for arrays in query mode. Thanks to Brad Hardy for
+    providing the use-case and debugging help.
+
+  * Query mode: Add support for tables. (As used by 'select' calls.)
+
+### Version 7.2, 2017-08-29
+
+  * Reworked implementation of shifts and rotates: When a signed quantity was
+    being shifted right by more than its size, SBV used to return 0. Robert Dockins pointed
+    out that the correct answer is actually -1 in such cases. The new implementation
+    merges the dynamic and typed interfaces, and drops support for non-constant shifts
+    of unbounded integers, which is not supported by SMTLib. Thanks to Robert for
+    reporting the issue and identifying the root cause.
+
+  * Rework how quantifiers are handled: We now generate separate asserts for
+    prefix-existentials. This allows for better (smaller) quantified code, while
+    preserving semantics.
+
+  * Rework the interaction between quantifiers and optimization routines.
+    Optimization routines now properly handle quantified formulas, so long as the
+    quantified metric does not involve any universal quantification itself. Thanks
+    to Matthew Danish for reporting the issue.
+
+  * Development/Infrastructure: Lots of work around the continuous integration
+    for SBV. We now build/test on Linux/Mac/Windows on every commit. Thanks to
+    Travis/Appveyor for providing free remote infrastructure. There are still
+    gotchas and some reductions in tests due to host capacity issues. If you
+    would like to be involved and improve the test suite, please get in touch!
+
+### Version 7.1, 2017-07-29
+
+  * Add support for 'getInterpolant' in Query mode.
+
+  * Support for SMT-results that can contain multi-line strings, which
+    is rare but it does happen. Previously SBV incorrectly interpreted such
+    responses to be erroneous.
+
+  * Many improvements to build infrastructure and code clean-up.
+
+  * Fix a bug in the implementation of `svSetBit`. Thanks to Robert Dockins
+    for the report.
+
+### Version 7.0, 2017-07-19
+
+  * NB. SBV now requires GHC >= 8.0.1 to compile. If you are stuck with an older
+    version of GHC, please get in contact.
+
+  * This is a major rewrite of the internals of SBV, and is a backwards compatibility
+    breaking release. While we kept the top-level and most commonly used APIs the
+    same (both types and semantics), much of the internals and advanced features
+    have been rewritten to move SBV to a new model of execution: SBV no longer
+    runs your program symbolically and calls the SMT solver afterwards. Instead,
+    the interaction with the solver happens interleaved with the actual program execution.
+    The motivation is to allow the end-users to send/receive arbitrary SMTLib
+    commands to the solver, instead of the cooked-up recipes. SBV still provides
+    all the recipes for its existing functionality, but users can now interact
+    with the solver directly. See the module `Data.SBV.Control` for the main
+    API, together with the new functions 'runSMT' and 'runSMTWith'.
+
+  * The 'Tactic' based solver control (introduced in v6.0) is completely removed, and
+    is replaced by the above described mechanism which gives the user a lot of
+    flexibility instead. Use queries for anything that required a tactic before.
+
+  * The call 'allSat' has been reworked so it performs only one call to the underlying
+    solver and repeatedly issues check-sat to get new assignments. This differs from the
+    previous implementation where we spun off a new call to the executable for each
+    successive model. While this is more efficient and much more preferable, it also
+    means that the results are no longer lazily computed: If there is an infinite number
+    of solutions (or a very large number), you can no longer merely do a 'take' on the result.
+    While this is inconvenient, it fits better with our new methodology of query based
+    interaction. Note that the old behavior can be modeled, if required, by the user; by explicitly
+    interleaving the calls to 'sat.' Furthermore, we now provide a new configuration
+    parameter named 'allSatMaxModelCount' which can be used to limit the number models we
+    seek. The default is to get all models, however long that might take.
+
+  * The Bridge modules (`Data.SBV.Bridge.Yices`, `Data.SBV.Bridge.Z3`) etc. are
+    all removed. The bridge functionality was hardly used, where different solvers
+    were much easier to access using the `with` functions. (Such as `proveWith`,
+    `satWith` etc.) This should result in no loss of functionality, except for
+    occasional explicit mention of solvers in your code, if you were using
+    bridge modules to start with.
+
+  * Optimization routines have been changed to take a priority as an argument, (i.e.,
+    Lexicographic, Independent, etc.). The old method of supplying the priority
+    via tactics is no longer supported.
+
+  * Pareto-front extraction has been reworked, reflecting the changes in Z3 for
+    this functionality. Since pareto-fronts can be infinite in number, the user
+    is now allowed to specify a "limit" to stop the solver from querying ad
+    infinitum. If the limit is not specified, then sbv will query till it
+    exhausts all the pareto-fronts, or till it runs out of memory in case there
+    is an infinite number of them.
+
+  * Extraction of unsat-cores has changed. To use this feature, we now use
+    custom queries. See `Data.SBV.Examples.Misc.UnsatCore` for an example.
+    Old style of unsat-core extraction is no longer supported.
+
+  * The 'timing' option of SMTConfig has been reworked. Since we now start the
+    solver immediately, it is no longer sensible to distinguish between "SBV" time,
+    "translation" time etc. Instead, we print one simple "Elapsed" time if requested.
+    If you need a detailed timing analysis, use the new 'transcript' option to
+    SMTConfig: It will produce a file with precise timing intervals for each
+    command issued to help you figure out how long each step took.
+
+  * The following functions have been reworked, so they now also return
+    the time-elapsed for each solver:
+
+        satWithAll   :: Provable a => [SMTConfig] -> a -> IO [(Solver, NominalDiffTime, SatResult)]
+        satWithAny   :: Provable a => [SMTConfig] -> a -> IO  (Solver, NominalDiffTime, SatResult)
+        proveWithAll :: Provable a => [SMTConfig] -> a -> IO [(Solver, NominalDiffTime, ThmResult)]
+        proveWithAny :: Provable a => [SMTConfig] -> a -> IO  (Solver, NominalDiffTime, ThmResult)
+
+  * Changed the way `satWithAny` and `proveWithAny` works. Previously, these
+    two functions ran multiple solvers, and took the result of the first
+    one to finish, killing all the others. In addition, they *waited* for
+    the still-running solvers to finish cleaning-up, as sending a 'ThreadKilled'
+    is usually not instantaneous. Furthermore, a solver might simply take
+    its time! We now send the interrupt but do not wait for the process to
+    actually terminate. In rare occasions this could create zombie processes
+    if you use a solver that is not cooperating, but we have seen not insignificant
+    speed-ups for regular usage due to ThreadKilled wait times being rather long.
+
+  * Configuration option `useLogic` is removed. If required, this should
+    be done by a call to the new 'setLogic' function:
+
+        setLogic QF_NRA
+
+  * Configuration option `timeOut` is removed. This was rarely used, and the solver
+    support was rather sketchy. We now have a better mechanism in the query mode
+    for timeouts, where it really matters. Please get in touch if you relied on
+    this old mechanism. Correspondingly, the functions `isTheorem`, `isSatisfiable`,
+    `isTheoremWith` and `isSatisfiableWith` had their time-out arguments removed
+    and return types simplified.
+
+  * The function 'isSatisfiableInCurrentPath' is removed. Proper queries should be used
+    for what this function tentatively attempted to provide. Please get in touch
+    if you relied on this function and want to restructure your code to use proper queries.
+
+  * Configuration option 'smtFile' is removed. Instead use 'transcript' now, which
+    provides a much more detailed output that is directly loadable to a solver
+    and has an accurate account of precisely what SBV sent.
+
+  * Enumerations are now much easier to use symbolically, with the addition
+    of the template-haskell splice mkSymbolicEnumeration. See `Data/SBV/Examples/Misc/Enumerate.hs`
+    for an example.
+
+  * Thanks to Kanishka Azimi, our external test suite is now run by
+    Tasty! Kanishka modernized the test suite, and reworked the
+    infrastructure that was showing its age. Thanks!
+
+  * The function pConstrain and the Data.SBV.Tools.ExpectedValue are
+    removed. Probabilistic constraints were rarely used, and if
+    necessary can be implemented outside of SBV. If you were using
+    this feature, please get in contact.
+
+  * SArray and SFunArray has been reworked, and they no longer take
+    and initial value. Similarly resetArray has been removed, as it
+    did not really do what it advertised. If an initial value is needed,
+    it is best to code this explicitly in your model.
+
+### Version 6.1, 2017-05-26
+
+  * Add support for unsat-core extraction. To use this feature, use
+    the `namedConstraint` function:
+
+        namedConstraint :: String -> SBool -> Symbolic ()
+
+    to associate a label to a constrain or a boolean term that
+    can later be labeled by the backend solver as belonging to the
+    unsat-core.
+
+    Unsat-cores are not enabled by default since they can be
+    expensive; to use:
+
+        satWith z3{getUnsatCore=True} $ do ...
+
+    In the programmatic API, the function:
+
+        extractUnsatCore :: Modelable a => a -> Maybe [String]
+
+    can be used to programmatically extract the unsat-core. Note that
+    backend solvers will only include the named expressions in the unsat-core,
+    i.e., any unnamed yet part-of-the-core-unsat expressions will be missing;
+    as speculated in the SMT-Lib document itself.
+
+    Currently, Z3, MathSAT, and CVC4 backends support unsat-cores.
+
+    (Thanks to Rohit Ramesh for the suggestion leading to this feature.)
+
+  * Added function `distinct`, which returns true if all the elements of the
+    given list are different. This function replaces the old `allDifferent`
+    function, which is now removed. The difference is that `distinct` will produce
+    much better code for SMT-Lib. If you used `allDifferent` before, simply
+    replacing it with `distinct` should work.
+
+  * Add support for pseudo-boolean operations:
+
+          pbAtMost           :: [SBool]        -> Int -> SBool
+          pbAtLeast          :: [SBool]        -> Int -> SBool
+          pbExactly          :: [SBool]        -> Int -> SBool
+          pbLe               :: [(Int, SBool)] -> Int -> SBool
+          pbGe               :: [(Int, SBool)] -> Int -> SBool
+          pbEq               :: [(Int, SBool)] -> Int -> SBool
+          pbMutexed          :: [SBool]               -> SBool
+          pbStronglyMutexed  :: [SBool]               -> SBool
+
+    These functions, while can be directly coded in SBV, produce better
+    translations to SMTLib for more efficient solving of cardinality constraints.
+    Currently, only Z3 supports pseudo-booleans directly. For all other solvers,
+    SBV will translate these to equivalent terms that do not require special
+    functions.
+
+  * The function getModel has been renamed to getAssignment. (The former name is
+    now available as a query command.)
+
+  * Export `SolverCapabilities` from `Data.SBV.Internals`, in case users want access.
+
+  * Move code-generation facilities to `Data.SBV.Tools.CodeGen`, no longer exporting
+    the relevant functions directly from `Data.SBV`. This could break existing code,
+    but the fix should be as simple as `import Data.SBV.Tools.CodeGen`.
+
+  * Move the following two functions to `Data.SBV.Internals`:
+
+         compileToSMTLib
+         generateSMTBenchmarks
+
+    If you use them, please `import Data.SBV.Internals`.
+
+  * Reorganized `EqSymbolic` and `EqOrd` classes to collect some of the
+    similarly named function together. Users should see no impact due to this change.
+
+
+### Version 6.0, 2017-05-07
+
+  * This is a backwards compatibility breaking release, hence the major version
+    bump from 5.15 to 6.0:
+
+       - Most of existing code should work with no changes.
+       - Old code relying on some features might require extra imports,
+         since we no longer export some functionality directly from `Data.SBV`.
+         This was done in order to reduce the number of exported items to
+         avoid extra clutter.
+       - Old optimization features are removed, as the new and much improved
+         capabilities should be used instead.
+
+  * The next two bullets cover new features in SBV regarding optimization, based
+    on the capabilities of the z3 SMT solver. With this release SBV gains the
+    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.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
+    supports optimization routines.
+
+    Optimization can be done over bit-vector, real, and integer goals. The relevant
+    functions are:
+
+        - `minimize`: Minimize a given arithmetic goal
+        - `maximize`: Minimize a given arithmetic goal
+
+    For instance, a call of the form
+
+         minimize "name-of-goal" $ x + 2*y
+
+    Minimizes the arithmetic goal x+2*y, where x and y can be bit-vectors, reals,
+    or integers. Such goals will be lexicographically optimized, i.e., in the order
+    given. If there are multiple goals, then user can also ask for independent
+    optimization results, or pareto-fronts.
+
+    Once the objectives are given, a top level call to `optimize` (similar to `prove`
+    and `sat`) performs the optimization.
+
+  * SBV now implements soft-asserts. A soft assertion is a hint to the SMT solver that
+    we would like a particular condition to hold if *possible*. That is, if there is
+    a solution satisfying it, then we would like it to hold. However, if the set of
+    constraints is unsatisfiable, then a soft-assertion can be violated by incurring
+    a user-given numeric penalty to satisfy the remaining constraints. The solver then
+    tries to minimize the penalty, i.e., satisfy as many of the soft-asserts as possible
+    such that the total penalty for those that are not satisfied is minimized.
+
+    Note that `assertSoft` works well with optimization goals (minimize/maximize etc.),
+    and are most useful when we are optimizing a metric and thus some of the constraints
+    can be relaxed with a penalty to obtain a good solution.
+
+  * SBV no longer provides the old optimization routines, based on iterative and quantifier
+    based methods. Those methods were rarely used, and are now superseded by the above
+    mechanism. If the old code is needed, please contact for help: They can be resurrected
+    in your own code if absolutely necessary.
+
+  * (NB. This feature is deprecated in 7.0, see above for its replacement.)
+    SBV now implements tactics, which allow the user to navigate the proof process.
+    This is an advanced feature that most users will have no need of, but can become
+    handy when dealing with complicated problems. Users can, for instance, implement
+    case-splitting in a proof to guide the underlying solver through. Here is the list
+    of tactics implemented:
+
+        - `CaseSplit`         : Case-split, with implicit coverage. Bool says whether we should be verbose.
+        - `CheckCaseVacuity`  : Should the case-splits be checked for vacuity? (Default: True.)
+        - `ParallelCase`      : Run case-splits in parallel. (Default: Sequential.)
+        - `CheckConstrVacuity`: Should constraints be checked for vacuity? (Default: False.)
+        - `StopAfter`         : Time-out given to solver, in seconds.
+        - `CheckUsing`        : Invoke with check-sat-using command, instead of check-sat
+        - `UseLogic`          : Use this logic, a custom one can be specified too
+        - `UseSolver`         : Use this solver (z3, yices, etc.)
+        - `OptimizePriority`  : Specify priority for optimization: Lexicographic (default), Independent, or Pareto.
+
+  * Name-space clean-up. The following modules are no longer automatically exported
+    from Data.SBV:
+
+        - `Data.SBV.Tools.ExpectedValue` (computing with expected values)
+        - `Data.SBV.Tools.GenTest` (test case generation)
+        - `Data.SBV.Tools.Polynomial` (polynomial arithmetic, CRCs etc.)
+        - `Data.SBV.Tools.STree` (full symbolic binary trees)
+
+    To use the functionality of these modules, users must now explicitly import the corresponding
+    module. Not other changes should be needed other than the explicit import.
+
+  * Changed the signatures of:
+
+          isSatisfiableInCurrentPath :: SBool -> Symbolic Bool
+        svIsSatisfiableInCurrentPath :: SVal  -> Symbolic Bool
+
+    to:
+
+          isSatisfiableInCurrentPath :: SBool -> Symbolic (Maybe SatResult)
+        svIsSatisfiableInCurrentPath :: SVal  -> Symbolic (Maybe SatResult)
+
+    which returns the result in case of SAT. This is more useful than before. This is
+    backwards-compatibility breaking, but is more useful. (Requested by Jared Ziegler.)
+
+  * Add instance `Provable (Symbolic ())`, which simply stands for returning true
+    for proof/sat purposes. This allows for simpler coding, as constrain/minimize/maximize
+    calls (which return unit) can now be directly sat/prove processed, without needing
+    a final call to return at the end.
+
+  * Add type synonym `Goal` (for `Symbolic ()`), in order to simplify type signatures
+
+  * SBV now properly adds check-sat commands and other directives in debugging output.
+
+  * New examples:
+      - Data.SBV.Examples.Optimization.LinearOpt: Simple linear-optimization example.
+      - Data.SBV.Examples.Optimization.Production: Scheduling machines in a shop
+      - Data.SBV.Examples.Optimization.VM: Scheduling virtual-machines in a data-center
+
+### Version 5.15, 2017-01-30
+
+  * Bump up dependency on CrackNum >= 1.9, to get access to hexadecimal floats.
+  * Improve time/tracking-print code. Thanks to Iavor Diatchki for the patch.
+
+### Version 5.14, 2017-01-12
+
+  * Bump up QuickCheck dependency to >= 2.9.2 to avoid the following quick-check
+    bug <http://github.com/nick8325/quickcheck/issues/113>, which transitively impacted
+    the quick-check as implemented by SBV.
+
+  * Generalize casts between integral-floats, using the rounding mode round-nearest-ties-to-even.
+    Previously calls to sFromIntegral did not support conversion to floats since it needed
+    a rounding mode. But it does make sense to support them with the default mode. If a different
+    mode is needed, use the function 'toSFloat' as before, which takes an explicit rounding mode.
+
+### Version 5.13, 2016-10-29
+
+  * Fix broken links, thanks to Stephan Renatus for the patch.
+
+  * Code generation: Create directory path if it does not exist. Thanks to Robert Dockins
+    for the patch.
+
+  * Generalize the type of sFromIntegral, dropping the Bits requirement. In turn, this
+    allowed us to remove sIntegerToSReal, since sFromIntegral can be used instead.
+
+  * Add support for sRealToSInteger. (Essentially the floor function for SReal.)
+
+  * Several space-leaks fixed for better performance. Patch contributed by Robert Dockins.
+
+  * Improved Random instance for Rational. Thanks to Joe Leslie-Hurd for the idea.
+
+### Version 5.12, 2016-06-06
+
+  * Fix GHC8.0 compilation issues, and warning clean-up. Thanks to Adam Foltzer for the bulk
+    of the work and Tom Sydney Kerckhove for the initial patch for 8.0 compatibility.
+
+  * Minor fix to printing models with floats when the base is 2/16, making sure the alignment
+    is done properly accommodating for the crackNum output.
+
+  * Wait for external process to die on exception, to avoid spawning zombies. Thanks to
+    Daniel Wagner for the patch.
+
+  * Fix hash-consed arrays: Previously we were caching based only on elements, which is not
+    sufficient as you can have conflicts differing only on the address type, but same contents.
+    Thanks to Brian Huffman for reporting and the corresponding patch.
+
+### Version 5.11, 2016-01-15
+
+  * Fix documentation issue; no functional changes
+
+### Version 5.10, 2016-01-14
+
+  * Documentation: Fix a bunch of dead http links. Thanks to Andres Sicard-Ramirez
+    for reporting.
+
+  * Additions to the Dynamic API:
+
+       * svSetBit                  : set a given bit
+       * svBlastLE, svBlastBE      : Bit-blast to big/little endian
+       * svWordFromLE, svWordFromBE: Unblast from big/little endian
+       * svAddConstant             : Add a constant to an SVal
+       * svIncrement, svDecrement  : Add/subtract 1 from an SVal
+
+### Version 5.9, 2016-01-05
+
+  * Default definition for 'symbolicMerge', which allows types that are
+    instances of 'Generic' to have an automatically derivable merge (i.e.,
+    ite) instance. Thanks to Christian Conkle for the patch.
+
+  * Add support for "non-model-vars," where we can now tell SBV not
+    to take into account certain variables from a model-building
+    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 http://github.com/LeventErkok/sbv/issues/208 for
+    motivation.
+
+  * Yices interface: If Reals are used, then pick the logic QF_UFLRA, instead
+    of QF_AUFLIA. Unfortunately, logic selection remains tricky since the SMTLib
+    story for logic selection is rather messy. Other solvers are not impacted
+    by this change.
+
+### Version 5.8, 2016-01-01
+
+  * Fix some typos
+  * Add 'svEnumFromThenTo' to the Dynamic interface, allowing dynamic construction
+    of [x, y .. z] and [x .. y] when the involved values are concrete.
+  * Add 'svExp' to the Dynamic interface, implementing exponentiation
+
+### Version 5.7, 2015-12-21
+
+  * Export `HasKind(..)` from the Dynamic interface. Thanks to Adam Foltzer for the patch.
+  * More careful handling of SMT-Lib reserved names.
+  * Update tested version of MathSAT to 5.3.9
+  * Generalize `sShiftLeft`/`sShiftRight`/`sRotateLeft`/`sRotateRight` to work with signed
+    shift/rotate amounts, where negative values revert the direction. Similar
+    generalizations are also done for the dynamic variants.
+
+### Version 5.6, 2015-12-06
+
+  * Minor changes to how we print models:
+  * Align by the type
+  * Always print the type (previously we were skipping for Bool)
+
+  * Rework how SBV properties are quick-checked; much more usable and robust
+
+  * Provide a function `sbvQuickCheck`, which is essentially the same as
+    quickCheck, except it also returns a boolean. Useful for the
+    programmable API. (The dynamic version is called `svQuickCheck`.)
+
+  * Several changes/additions in support of the sbvPlugin development:
+  * Data.SBV.Dynamic: Define/export `svFloat`/`svDouble`/`sReal`/`sNumerator`/`sDenominator`
+  * Data.SBV.Internals: Export constructors of `Result`, `SMTModel`,
+    and the function `showModel`
+  * Simplify how Uninterpreted-types are internally represented.
+
+### Version 5.5, 2015-11-10
+
+  * This is essentially the same release as 5.4 below, except to allow SBV compile
+    with GHC 7.8 series. Thanks to Adam Foltzer for the patch.
+
+### Version 5.4, 2015-11-09
+
+  * Add 'sAssert', which allows users to pepper their code with boolean conditions, much like
+    the usual ASSERT calls. Note that the semantics of an 'sAssert' is that it is a NOOP, i.e.,
+    it simply returns its final argument. Use in coordination with 'safe' and 'safeWith', see below.
+
+  * Implement 'safe' and 'safeWith', which statically determine all calls to 'sAssert'
+    being safe to execute. Any violations will be flagged.
+
+  * SBV->C: Translate 'sAssert' calls to dynamic checks in the generated C code. If this is
+    not desired, use the 'cgIgnoreSAssert' function to turn it off.
+
+  * Add 'isSafe': Which converts a 'SafeResult' to a 'Bool', when we are only interested
+    in a boolean result.
+
+  * Add Data/SBV/Examples/Misc/NoDiv0 to demonstrate the use of the 'safe' function.
+
+### Version 5.3, 2015-10-20
+
+  * Main point of this release to make SBV compile with GHC 7.8 again, to accommodate mainly
+    for Cryptol. As Cryptol moves to GHC >= 7.10, we intend to remove the "compatibility" changes
+    again. Thanks to Adam Foltzer for the patch.
+
+  * Minor mods to how bitvector equality/inequality are translated to SMTLib. No user visible
+    impact.
+
+### Version 5.2, 2015-10-12
+
+  * Regression on 5.1: Fix a minor bug in base 2/16 printing where uninterpreted constants were
+    not handled correctly.
+
+### Version 5.1, 2015-10-10
+
+  * fpMin, fpMax: If these functions receive +0/-0 as their two arguments, i.e., both
+    zeros but alternating signs in any order, then SMTLib requires the output to be
+    nondeterministically chosen. Previously, we fixed this result as +0 following the
+    interpretation in Z3, but Z3 recently changed and now incorporates the nondeterministic
+    output. SBV similarly changed to allow for non-determinism here.
+
+  * Change the types of the following Floating-point operations:
+
+        * sFloatAsSWord32, sFloatAsSWord32, blastSFloat, blastSDouble
+
+    These were previously coded as relations, since NaN values were not representable
+    in the target domain uniquely. While it was OK, it was hard to use them. We now
+    simply implement these as functions, and they are underspecified if the inputs
+    are NaNs: In those cases, we simply get a symbolic output. The new types are:
+
+       * sFloatAsSWord32  :: SFloat  -> SWord32
+       * sDoubleAsSWord64 :: SDouble -> SWord64
+       * blastSFloat      :: SFloat  -> (SBool, [SBool], [SBool])
+       * blastSDouble     :: SDouble -> (SBool, [SBool], [SBool])
+
+  * MathSAT backend: Use the SMTLib interpretation of fp.min/fp.max by passing the
+    "-theory.fp.minmax_zero_mode=4" argument explicitly.
+
+  * Fix a bug in hash-consing of floating-point constants, where we were confusing +0 and
+    -0 since we were using them as keys into the map though they compare equal. We now
+    explicitly keep track of the negative-zero status to make sure this confusion does
+    not arise. Note that this bug only exhibited itself in rare occurrences of both
+    constants being present in a benchmark; a true corner case. Note that @NaN@ values
+    are also interesting in this context: Since NaN /= NaN, we never hash-cons floating
+    point constants that have the value NaN. But that is actually OK; it is a bit wasteful
+    in case you have a lot of NaN constants around, but there is no soundness issue: We
+    just waste a little bit of space.
+
+  * Remove the functions `allSatWithAny` and `allSatWithAll`. These two variants do *not*
+    make sense when run with multiple solvers, as they internally sequentialize the solutions
+    due to the nature of `allSat`. Not really needed anyhow; so removed. The variants
+    `satWithAny/All` and `proveWithAny/All` are still available.
+
+  * Export SMTLibVersion from the library, forgotten export needed by Cryptol. Thanks to Adam
+    Foltzer for the patch.
+
+  * Slightly modify model-outputs so the variables are aligned vertically. (Only matters
+    if we have model-variable names that are of differing length.)
+
+  * Move to Travis-CI "docker" based infrastructure for builds
+
+  * Enable local builds to use the Herbie plugin. Currently SBV does not have any
+    expressions that can benefit from Herbie, but it is nice to have this support in general.
+
+### Version 5.0, 2015-09-22
+
+  * Note: This is a backwards-compatibility breaking release, see below for details.
+
+  * SBV now requires GHC 7.10.1 or newer to be compiled, taking advantage of newer features/bug-fixes
+    in GHC. If you really need SBV to compile with older GHCs, please get in touch.
+
+  * SBV no longer supports SMTLib1. We now exclusively use SMTLib2 for communicating with backend
+    solvers. Strictly speaking, this means some loss in functionality: Uninterpreted-function models
+    that we supported via Yices-1 are no longer available. In practice this facility was not really
+    used, and required a very old version of Yices that was no longer supported by SRI and has
+    lacked in other features. So, in reality this change should hardly matter for end-users.
+
+  * Added function `label`, which is useful in emitting comments around expressions. It is essentially
+    a no-op, but does generate a comment with the given text in the SMT-Lib and C output, for diagnostic
+    purposes.
+
+  * Added `sFromIntegral`: Conversions from all integral types (SInteger, SWord/SInts) between
+    each other. Similar to the `fromIntegral` function of Haskell. These generate simple casts when
+    used in code-generation to C, and thus are very efficient.
+
+  * SBV no longer supports the functions sBranch/sAssert, as we realized these functions can cause
+    soundness issues under certain conditions. While the triggering scenarios are not common use-cases
+    for these functions, we are opting for safety, and thus removing support. See
+    http://github.com/LeventErkok/sbv/issues/180 for details; and see below for the new function
+    'isSatisfiableInCurrentPath'.
+
+  * A new function 'isSatisfiableInCurrentPath' is added, which checks for satisfiability during a
+    symbolic simulation run. This function can be used as the basis of sBranch/sAssert like functionality
+    if needed. The difference is that this is a much lower level call, and also exposes the fact that
+    the result is in the 'Symbolic' monad (which avoids the soundness issue). Of course, the new type
+    makes it less useful as it will not be a drop-in replacement for if-then-else like structure. Intended
+    to be used by tools built on top of SBV, as opposed to end-users.
+
+  * SBV no longer implements the 'SignCast' class, as its functionality is replaced by the 'sFromIntegral'
+    function. Programs using the functions 'signCast' and 'unsignCast' should simply replace both
+    with calls to 'sFromIntegral'. (Note that extra type-annotations might be necessary, similar to
+    the uses of the 'fromIntegral' function in Haskell.)
+
+  * Backend solver related changes:
+
+       * Yices: Upgraded to work with Yices release 2.4.1. Note that earlier versions of Yices
+         are *not* supported.
+
+       * Boolector: Upgraded to work with new Boolector release 2.0.7. Note that earlier versions
+         of Boolector are *not* supported.
+
+       * MathSAT: Upgraded to work with latest release 5.3.7. Note that earlier versions of MathSAT
+         are *not* supported (due to a buffering issue in MathSAT itself.)
+
+       * MathSAT: Enabled floating-point support in MathSAT.
+
+  * New examples:
+
+       * Add Data.SBV.Examples.Puzzles.Birthday, which solves the Cheryl-Birthday problem that
+         went viral in April 2015. Turns out really easy to solve for SMT, but the formalization
+         of the problem is still interesting as an exercise in formal reasoning.
+
+       * Add Data.SBV.Examples.Puzzles.SendMoreMoney, which solves the classic send + more = money
+         problem. Really a trivial example, but included since it is pretty much the hello-world for
+         basic constraint solving.
+
+       * Add Data.SBV.Examples.Puzzles.Fish, which solves a typical logic puzzle; finding the unique
+         solution to a set of assertions made about a bunch of people, their pets, beverage choices,
+         etc. Not particularly interesting, but could be fun to play around with for modeling purposes.
+
+       * Add Data.SBV.Examples.BitPrecise.MultMask, which demonstrates the use of the bitvector
+         solver to an interesting bit-shuffling problem.
+
+  * Rework floating-point arithmetic, and add missing floating-point operations:
+
+      * fpRem            : remainder
+      * fpRoundToIntegral: truncating round
+      * fpMin            : min
+      * fpMax            : max
+      * fpIsEqualObject  : FP equality as object (i.e., NaN equals NaN, +0 does not equal -0, etc.)
+
+    This brings SBV up-to par with everything supported by the SMT-Lib FP theory.
+
+  * Add the IEEEFloatConvertable class, which provides conversions to/from Floats and other types. (i.e.,
+    value conversions from all other types to Floats and Doubles; and back.)
+
+  * Add SWord32/SWord64 to/from SFloat/SDouble conversions, as bit-pattern reinterpretation; using the
+    IEEE754 interchange format. The functions are: sWord32AsSFloat, sWord64AsSDouble, sFloatAsSWord32,
+    sDoubleAsSWord64. Note that the sWord32AsSFloat and sWord64ToSDouble are regular functions, but
+    sFloatToSWord32 and sDoubleToSWord64 are "relations", since NaN values are not uniquely convertible.
+
+  * Add 'sExtractBits', which takes a list of indices to extract bits from, essentially
+    equivalent to 'map sTestBit'.
+
+  * Rename a set of symbolic functions for consistency. Here are the old/new names:
+
+     * sbvTestBit               --> sTestBit
+     * sbvPopCount              --> sPopCount
+     * sbvShiftLeft             --> sShiftLeft
+     * sbvShiftRight            --> sShiftRight
+     * sbvRotateLeft            --> sRotateLeft
+     * sbvRotateRight           --> sRotateRight
+     * sbvSignedShiftArithRight --> sSignedShiftArithRight
+
+  * Rename all FP recognizers to be in sync with FP operations. Here are the old/new names:
+
+     * isNormalFP       --> fpIsNormal
+     * isSubnormalFP    --> fpIsSubnormal
+     * isZeroFP         --> fpIsZero
+     * isInfiniteFP     --> fpIsInfinite
+     * isNaNFP          --> fpIsNaN
+     * isNegativeFP     --> fpIsNegative
+     * isPositiveFP     --> fpIsPositive
+     * isNegativeZeroFP --> fpIsNegativeZero
+     * isPositiveZeroFP --> fpIsPositiveZero
+     * isPointFP        --> fpIsPoint
+
+  * Lots of other work around floating-point, test cases, reorg, etc.
+
+  * Introduce shorter variants for rounding modes: sRNE, sRNA, sRTP, sRTN, sRTZ;
+    aliases for sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive,
+    sRoundTowardNegative, and sRoundTowardZero; respectively.
+
+### Version 4.4, 2015-04-13
+
+  * Hook-up crackNum package; so counter-examples involving floats and
+    doubles can be printed in detail when the printBase is chosen to be
+    2 or 16. (With base 10, we still get the simple output.)
+
+      ```
+      Prelude Data.SBV> satWith z3{printBase=2} $ \x -> x .== (2::SFloat)
+      Satisfiable. Model:
+        s0 = 2.0 :: Float
+                        3  2          1         0
+                        1 09876543 21098765432109876543210
+                        S ---E8--- ----------F23----------
+                Binary: 0 10000000 00000000000000000000000
+                   Hex: 4000 0000
+             Precision: SP
+                  Sign: Positive
+              Exponent: 1 (Stored: 128, Bias: 127)
+                 Value: +2.0 (NORMAL)
+      ```
+
+  * Change how we print type info; for models instead of SType just print Type (i.e.,
+    for SWord8, instead print Word8) which makes more sense and is more consistent.
+    This change should be mostly relevant as how we see the counter-example output.
+
+  * Fix long standing bug #75, where we now support arrays with Boolean source/targets.
+    This is not a very commonly used case, but by letting the solver pick the logic,
+    we now allow arrays to be uniformly supported.
+
+### Version 4.3, 2015-04-10
+
+  * Introduce Data.SBV.Dynamic, by Brian Huffman. This is mostly an internal
+    reorg of the SBV codebase, and end-users should not be impacted by the
+    changes. The introduction of the Dynamic SBV variant (i.e., one that does
+    not mandate a phantom type as in `SBV Word8` etc. allows library writers
+    more flexibility as they deal with arbitrary bit-vector sizes. The main
+    customer of these changes are the Cryptol language and the associated
+    toolset, but other developers building on top of SBV can find it useful
+    as well. NB: The "strongly-typed" aspect of SBV is still the main way
+    end-users should interact with SBV, and nothing changed in that respect!
+
+  * Add symbolic variants of floating-point rounding-modes for convenience
+
+  * Rename toSReal to sIntegerToSReal, which captures the intent more clearly
+
+  * Code clean-up: remove mbMinBound/mbMaxBound thus allowing less calls to
+    unliteral. Contributed by Brian Huffman.
+
+  * Introduce FP conversion functions:
+
+       * Between SReal and SFloat/SDouble
+           * fpToSReal
+           * sRealToSFloat
+           * sRealToSDouble
+       * Between SWord32 and SFloat
+           * sWord32ToSFloat
+           * sFloatToSWord32
+       * Between SWord64 and SDouble. (Relational, due to non-unique NaNs)
+           * sWord64ToSDouble
+       * sDoubleToSWord64
+       * From float to sign/exponent/mantissa fields: (Relational, due to non-unique NaNs)
+           * blastSFloat
+           * blastSDouble
+
+  * Rework floating point classifiers. Remove isSNaN and isFPPoint (both renamed),
+    and add the following new recognizers:
+
+       * isNormalFP
+       * isSubnormalFP
+       * isZeroFP
+       * isInfiniteFP
+       * isNaNFP
+       * isNegativeFP
+       * isPositiveFP
+       * isNegativeZeroFP
+       * isPositiveZeroFP
+       * isPointFP (corresponds to a real number, i.e., neither NaN nor infinity)
+
+  * Re-implement sbvTestBit, by Brian Huffman. This version is much faster at large
+    word sizes, as it avoids the costly mask generation.
+
+  * Code changes to suppress warnings with GHC7.10. General clean-up.
+
+### Version 4.2, 2015-03-17
+
+  * Add exponentiation (.^). Thanks to Daniel Wagner for contributing the code!
+
+  * Better handling of SBV_$SOLVER_OPTIONS, in particular keeping track of
+    proper quoting in environment variables. Thanks to Adam Foltzer for
+    the patch!
+
+  * Silence some hlint/ghci warnings. Thanks to Trevor Elliott for the patch!
+
+  * Haddock documentation fixes, improvements, etc.
+
+  * Change ABC default option string to %blast; "&sweep -C 5000; &syn4; &cec -s -m -C 2000"
+    which seems to give good results. Use SBV_ABC_OPTIONS environment variable (or
+    via abc.rc file and a combination of SBV_ABC_OPTIONS) to experiment.
+
+### Version 4.1, 2015-03-06
+
+  * Add support for the ABC solver from Berkeley. Thanks to Adam Foltzer
+    for the required infrastructure! See: https://github.com/berkeley-abc/abc
+    And Alan Mishchenko for adding infrastructure to ABC to work with SBV.
+
+  * Upgrade the Boolector connection to use a SMT-Lib2 based interaction. NB. You
+    need at least Boolector 2.0.6 installed!
+
+  * Tracking changes in the SMT-Lib floating-point theory. If you are
+    using symbolic floating-point types (i.e., SFloat and SDouble), then
+    you should upgrade to this version and also get a very latest (unstable)
+    Z3 release. See https://smt-lib.org/theories-FloatingPoint.shtml
+    for details.
+
+  * Introduce a new class, 'RoundingFloat', which supports floating-point
+    operations with arbitrary rounding-modes. Note that Haskell only allows
+    RoundNearestTiesToAway, but with SBV, we get all 5 IEEE754 rounding-modes
+    and all the basic operations ('fpAdd', 'fpMul', 'fpDiv', etc.) with these
+    modes.
+
+  * Allow Floating-Point RoundingMode to be symbolic as well
+
+  * Improve the example `Data/SBV/Examples/Misc/Floating.hs` to include
+    rounding-mode based addition example.
+
+  * Changes required to make SBV compile with GHC 7.10; mostly around instance
+    NFData declarations. Thanks to Iavor Diatchki for the patch.
+
+  * Export a few extra symbols from the Internals module (mainly for
+    Cryptol usage.)
+
+### Version 4.0, 2015-01-22
+
+This release mainly contains contributions from Brian Huffman, allowing
+end-users to define new symbolic types, such as Word4, that SBV does not
+natively support. When GHC gets type-level literals, we shall most likely
+incorporate arbitrary bit-sized vectors and ints using this mechanism,
+but in the interim, this release provides a means for the users to introduce
+individual instances.
+
+  * Modifications to support arbitrary bit-sized vectors;
+    These changes have been contributed by Brian Huffman
+    of Galois. Thanks Brian.
+  * A new example `Data/SBV/Examples/Misc/Word4.hs` showing
+    how users can add new symbolic types.
+  * Support for rotate-left/rotate-right with variable
+    rotation amounts. (From Brian Huffman.)
+
+### Version 3.5, 2015-01-15
+
+This release is mainly adding support for enumerated types in Haskell being
+translated to their symbolic counterparts; instead of going completely
+uninterpreted.
+
+  * Keep track of data-type details for uninterpreted sorts.
+  * Rework the U2Bridge example to use enumerated types.
+  * The "Uninterpreted" name no longer makes sense with this change, so
+    rework the relevant names to ensure proper internal naming.
+  * Add Data/SBV/Examples/Misc/Enumerate.hs as an example for demonstrating
+    how enumerations are translated.
+  * Fix a long-standing bug in the implementation of select when
+    translated as SMT-Lib tables. (Github issue #103.) Thanks to
+    Brian Huffman for reporting.
+
+### Version 3.4, 2014-12-21
+
+  * This release is mainly addressing floating-point changes in SMT-Lib.
+
+      * Track changes in the QF_FPA logic standard; new constants and alike. If you are
+        using the floating-point logic, then you need a relatively new version of Z3
+        installed (4.3.3 or newer).
+
+      * Add unary-negation as an explicit operator. Previously, we merely used the "0-x"
+        semantics; but with floating point, this does not hold as 0-0 is 0, and is not -0!
+        (Note that negative-zero is a valid floating point value, that is different than
+        positive-zero; yet it compares equal to it. Sigh..)
+
+      * Similarly, add abs as a native method; to make sure we map it to fp.abs for
+        floating point values.
+
+      * Test suite improvements
+
+### Version 3.3, 2014-12-05
+
+  * Implement 'safe' and 'safeWith', which statically determine all calls to 'sAssert'
+    being safe to execute. This way, users can pepper their programs with liberal
+    calls to 'sAssert' and check they are all safe in one go without further worry.
+
+  * Robustify the interface to external solvers, by making sure we catch cases where
+    the external solver might exist but not be runnable (library dependency missing,
+    for example). It is impossible to be absolutely foolproof, but we now catch a
+    few more cases and fail gracefully.
+
+### Version 3.2, 2014-11-18
+
+  * Implement 'sAssert'. This adds conditional symbolic simulation, by ensuring arbitrary
+    boolean conditions hold during simulation; similar to ASSERT calls in other languages.
+    Note that failures will be detected at symbolic-simulation time, i.e., each assert will
+    generate a call to the external solver to ensure that the condition is never violated.
+    If violation is possible the user will get an error, indicating the failure conditions.
+
+  * Also implement 'sAssertCont' which allows for a programmatic way to extract/display results
+    for consumers of 'sAssert'. While the latter simply calls 'error' in case of an assertion
+    violation, the 'sAssertCont' variant takes a continuation which can be used to program
+    how the results should be interpreted/displayed. (This is useful for libraries built on top of
+    SBV.) Note that the type of the continuation is such that execution should still stop, i.e.,
+    once an assertion violation is detected, symbolic simulation will never continue.
+
+  * Rework/simplify the 'Mergeable' class to make sure 'sBranch' is sufficiently lazy
+    in case of structural merges. The original implementation was only
+    lazy at the Word instance, but not at lists/tuples etc. Thanks to Brian Huffman
+    for reporting this bug.
+
+  * Add a few constant-folding optimizations for 'sDiv' and 'sRem'
+
+  * Boolector: Modify output parser to conform to the new Boolector output format. This
+    means that you need at least v2.0.0 of Boolector installed if you want to use that
+    particular solver.
+
+  * Fix long-standing translation bug regarding boolean Ord class comparisons. (i.e.,
+    'False > True' etc.) While Haskell allows for this, SMT-Lib does not; and hence
+    we have to be careful in translating. Thanks to Brian Huffman for reporting.
+
+  * C code generation: Correctly translate square-root and fusedMA functions to C.
+
+### Version 3.1, 2014-07-12
+
+ New features/bug-fixes in v3.1:
+
+ * Using multiple-SMT solvers in parallel:
+      * Added functions that let the user run multiple solvers, using asynchronous
+        threads. All results can be obtained (proveWithAll, proveWithAny, satWithAll),
+        or SBV can return the fastest result (satWithAny, allSatWithAll, allSatWithAny).
+        These functions are good for playing with multiple-solvers, especially on
+        machines with multiple-cores.
+      * Add function: sbvAvailableSolvers; which returns the list of solvers currently
+        available, as installed on the machine we are running. (Not the list that SBV
+        supports, but those that are actually available at run-time.) This function
+        is useful with the multi-solve API.
+ * Implement sBranch:
+      * sBranch is a variant of 'ite' that consults the external
+        SMT solver to see if a given branch condition is satisfiable
+        before evaluating it. This can make certain otherwise recursive
+        and thus not-symbolically-terminating inputs amenable to symbolic
+        simulation, if termination can be established this way. Needless
+        to say, this problem is always decidable as far as SBV programs
+        are concerned, but it does not mean the decision procedure is cheap!
+        Use with care.
+      * sBranchTimeOut config parameter can be used to curtail long runs when
+        sBranch is used. Of course, if time-out happens, SBV will
+        assume the branch is feasible, in which case symbolic-termination
+        may come back to bite you.)
+ * New API:
+      * Add predicate 'isSNaN' which allows testing 'SFloat'/'SDouble' values
+        for nan-ness. This is similar to the Prelude function 'isNaN', except
+        the Prelude version requires a RealFrac instance, which unfortunately is
+        not currently implementable for cases. (Requires trigonometric functions etc.)
+        Thus, we provide 'isSNaN' separately (along with the already existing
+        'isFPPoint') to simplify reasoning with floating-point.
+ * Examples:
+     * Add Data/SBV/Examples/Misc/SBranch.hs, to illustrate the use of sBranch.
+ * Bug fixes:
+     * Fix pipe-blocking issue, which exhibited itself in the presence of
+       large numbers of variables (> 10K or so). See github issue #86. Thanks
+       to Philipp Meyer for the fine report.
+ * Misc:
+     * Add missing SFloat/SDouble instances for SatModel class
+     * Explicitly support KBool as a kind, separating it from `KUnbounded False 1`.
+       Thanks to Brian Huffman for contributing the changes. This should have no
+       user-visible impact, but comes in handy for internal reasons.
+
+### Version 3.0, 2014-02-16
+
+ * Support for floating-point numbers:
+      * Preliminary support for IEEE-floating point arithmetic, introducing
+        the types `SFloat` and `SDouble`. The support is still quite new,
+        and Z3 is the only solver that currently features a solver for
+        this logic. Likely to have bugs, both at the SBV level, and at the
+        Z3 level; so any bug reports are welcome!
+ * New backend solvers:
+      * SBV now supports MathSAT from Fondazione Bruno Kessler and
+        DISI-University of Trento. See: http://mathsat.fbk.eu/
+ * Support all-sat calls in the presence of uninterpreted sorts:
+      * Implement better support for `allSat` in the presence of uninterpreted
+        sorts. Previously, SBV simply rejected running `allSat` queries
+        in the presence of uninterpreted sorts, since it was not possible
+        to generate a refuting model. The model returned by the SMT solver
+        is simply not usable, since it names constants that is not visible
+        in a subsequent run. Eric Seidel came up with the idea that we can
+        actually compute equivalence classes based on a produced model, and
+        assert the constraint that the new model should disallow the previously
+        found equivalence classes instead. The idea seems to work well
+        in practice, and there is also an example program demonstrating
+        the functionality: Examples/Uninterpreted/UISortAllSat.hs
+ * Programmable model extraction improvements:
+      * Add functions `getModelDictionary` and `getModelDictionaries`, which
+        provide low-level access to models returned from SMT solvers. Former
+        for `sat` and `prove` calls, latter for `allSat` calls. Together with
+        the exported utils from the `Data.SBV.Internals` module, this should
+        allow for expert users to dissect the models returned and do fancier
+        programming on top of SBV.
+      * Add `getModelValue`, `getModelValues`, `getModelUninterpretedValue`, and
+        `getModelUninterpretedValues`; which further aid in model value
+        extraction.
+ * Other:
+      * Allow users to specify the SMT-Lib logic to use, if necessary. SBV will
+        still pick the logic automatically, but users can now override that choice.
+        Comes in handy when playing with custom logics.
+ * Bug fixes:
+      * Address allsat-laziness issue (#78 in github issue tracker). Essentially,
+        simplify how all-sat is called so we can avoid calling the solver for
+        solutions that are not needed. Thanks to Eric Seidel for reporting.
+ * Examples:
+      * Add Data/SBV/Examples/Misc/ModelExtract.hs as a simple example for
+        programmable model extraction and usage.
+      * Add Data/SBV/Examples/Misc/Floating.hs for some FP examples.
+      * Use the AUFLIA logic in Examples.Existentials.Diophantine which helps
+        z3 complete the proof quickly. (The BV logics take too long for this problem.)
+
+### Version 2.10, 2013-03-22
+
+ * Add support for the Boolector SMT solver
+    * See: https://boolector.github.io
+    * Use `import Data.SBV.Bridge.Boolector` to use Boolector from SBV
+    * Boolector supports QF_BV (with an without arrays). In the last
+      SMT-Lib competition it won both bit-vector categories. It is definitely
+      worth trying it out for bitvector problems.
+ * Changes to the library:
+    * Generalize types of `allDifferent` and `allEqual` to take
+      arbitrary EqSymbolic values. (Previously was just over SBV values.)
+    * Add `inRange` predicate, which checks if a value is bounded within
+      two others.
+    * Add `sElem` predicate, which checks for symbolic membership
+    * Add `fullAdder`: Returns the carry-over as a separate boolean bit.
+    * Add `fullMultiplier`: Returns both the lower and higher bits resulting
+      from  multiplication.
+    * Use the SMT-Lib Bool sort to represent SBool, instead of bit-vectors of length 1.
+      While this is an under-the-hood mechanism that should be user-transparent, it
+      turns out that one can no longer write axioms that return booleans in a direct
+      way due to this translation. This change makes it easier to write axioms that
+      utilize booleans as there is now a 1-to-1 match. (Suggested by Thomas DuBuisson.)
+ * Solvers changes:
+    * Z3: Update to the new parameter naming schema of Z3. This implies that
+      you need to have a really recent version of Z3 installed, something
+      in the Z3-4.3 series.
+ * Examples:
+    * Add Examples/Uninterpreted/Shannon.hs: Demonstrating Shannon expansion,
+      boolean derivatives, etc.
+ * Bug-fixes:
+    * Gracefully handle the case if the backend-SMT solver does not put anything
+      in stdout. (Reported by Thomas DuBuisson.)
+    * Handle uninterpreted sort values, if they happen to be only created via
+      function calls, as opposed to being inputs. (Reported by Thomas DuBuisson.)
+
+### Version 2.9, 2013-01-02
+
+  * Add support for the CVC4 SMT solver from Stanford: <https://cvc4.github.io/>
+    NB. Z3 remains the default solver for SBV. To use CVC4, use the
+    *With variants of the interface (i.e., proveWith, satWith, ..)
+    by passing cvc4 as the solver argument. (Similarly, use 'yices'
+    as the argument for the *With functions for invoking yices.)
+  * Latest release of Yices calls the SMT-Lib based solver executable
+    yices-smt. Updated the default value of the executable to have this
+    name for ease of use.
+  * Add an extra boolean flag to compileToSMTLib and generateSMTBenchmarks
+    functions to control if the translation should keep the query as is
+    (for SAT cases), or negate it (for PROVE cases). Previously, this value
+    was hard-coded to do the PROVE case only.
+  * Add bridge modules, to simplify use of different solvers. You can now say:
+
+          import Data.SBV.Bridge.CVC4
+          import Data.SBV.Bridge.Yices
+          import Data.SBV.Bridge.Z3
+
+    to pick the appropriate default solver. if you simply 'import Data.SBV', then
+    you will get the default SMT solver, which is currently Z3. The value
+    'defaultSMTSolver' refers to z3 (currently), and 'sbvCurrentSolver' refers
+    to the chosen solver as determined by the imported module. (The latter is
+    useful for modifying options to the SMT solver in an solver-agnostic way.)
+  * Various improvements to Z3 model parsing routines.
+
+### Version 2.8, 2012-11-29
+
+  * Rename the SNum class to SIntegral, and make it index over regular
+    types. This makes it much more useful, simplifying coding of
+    polymorphic symbolic functions over integral types, which is
+    the common case.
+  * Add the functions:
+  * sbvShiftLeft
+  * sbvShiftRight
+    which can accommodate unsigned symbolic shift amounts. Note that
+    one cannot use the Haskell shiftL/shiftR functions from the Bits class since
+    they are hard-wired to take 'Int' values as the shift amounts only.
+  * Add a new function 'sbvArithShiftRight', which is the same as
+    a shift-right, except it uses the MSB of the input as the bit to fill
+    in (instead of always filling in with 0 bits). Note that this is
+    the same as shiftRight for signed values, but differs from a shiftRight
+    when the input is unsigned. (There is no Haskell analogue of this
+    function, as Haskell shiftR is always arithmetic for signed
+    types and logical for unsigned ones.) This variant is designed for
+    use cases when one uses the underlying unsigned SMT-Lib representation
+    to implement custom signed operations, for instance.
+  * Several typo fixes.
+
+### Version 2.7, 2012-10-21
+
+  * Add missing QuickCheck instance for SReal
+  * When dealing with concrete SReals, make sure to operate
+    only on exact algebraic reals on the Haskell side, leaving
+    true algebraic reals (i.e., those that are roots of polynomials
+    that cannot be expressed as a rational) symbolic. This avoids
+    issues with functions that we cannot implement directly on
+    the Haskell side, like exact square-roots.
+  * Documentation tweaks, typo fixes etc.
+  * Rename BVDivisible class to SDivisible; since SInteger
+    is also an instance of this class, and SDivisible is a
+    more appropriate name to start with. Also add sQuot and sRem
+    methods; along with sDivMod, sDiv, and sMod, with usual
+    semantics.
+  * Improve test suite, adding many constant-folding tests
+    and start using cabal based tests (--enable-tests option.)
+
+### Versions 2.4, 2.5, and 2.6: Around mid October 2012
+
+  * Workaround issues related hackage compilation, in particular to the
+    problem with the new containers package release, which does provide
+    an NFData instance for sequences.
+  * Add explicit Num requirements when necessary, as the Bits class
+    no longer does this.
+  * Remove dependency on the hackage package strict-concurrency, as
+    hackage can no longer compile it due to some dependency mismatch.
+  * Add forgotten Real class instance for the type 'AlgReal'
+  * Stop putting bounds on hackage dependencies, as they cause
+    more trouble then they actually help. (See the discussion
+    here: <http://www.haskell.org/pipermail/haskell-cafe/2012-July/102352.html>.)
+
+### Version 2.3, 2012-07-20
+
+  * Maintenance release, no new features.
+  * Tweak cabal dependencies to avoid using packages that are newer
+    than those that come with ghc-7.4.2. Apparently this is a no-no
+    that breaks many things, see the discussion in this thread:
+      http://www.haskell.org/pipermail/haskell-cafe/2012-July/102352.html
+    In particular, the use of containers >= 0.5 is *not* OK until we have
+    a version of GHC that comes with that version.
+
+### Version 2.2, 2012-07-17
+
+  * Maintenance release, no new features.
+  * Update cabal dependencies, in particular fix the
+    regression with respect to latest version of the
+    containers package.
+
+### Version 2.1, 2012-05-24
+
+ * Library:
+    * Add support for uninterpreted sorts, together with user defined
+      domain axioms. See Data.SBV.Examples.Uninterpreted.Sort
+      and Data.SBV.Examples.Uninterpreted.Deduce for basic examples of
+      this feature.
+    * Add support for C code-generation with SReals. The user picks
+      one of 3 possible C types for the SReal type: CgFloat, CgDouble
+      or CgLongDouble, using the function cgSRealType. Naturally, the
+      resulting C program will suffer a loss of precision, as it will
+      be subject to IEE-754 rounding as implied by the underlying type.
+    * Add toSReal :: SInteger -> SReal, which can be used to promote
+      symbolic integers to reals. Comes handy in mixed integer/real
+      computations.
+ * Examples:
+    * Recast the dog-cat-mouse example to use the solver over reals.
+    * Add Data.SBV.Examples.Uninterpreted.Sort, and
+           Data.SBV.Examples.Uninterpreted.Deduce
+      for illustrating uninterpreted sorts and axioms.
+
+### Version 2.0, 2012-05-10
+
+  This is a major release of SBV, adding support for symbolic algebraic reals: SReal.
+  See http://en.wikipedia.org/wiki/Algebraic_number for details. In brief, algebraic
+  reals are solutions to univariate polynomials with rational coefficients. The arithmetic
+  on algebraic reals is precise, with no approximation errors. Note that algebraic reals
+  are a proper subset of all reals, in particular transcendental numbers are not
+  representable in this way. (For instance, "sqrt 2" is algebraic, but pi, e are not.)
+  However, algebraic reals is a superset of rationals, so SBV now also supports symbolic
+  rationals as well.
+
+  You *should* use Z3 v4.0 when working with real numbers. While the interface will
+  work with older versions of Z3 (or other SMT solvers in general), it uses Z3
+  root-obj construct to retrieve and query algebraic reals.
+
+  While SReal values have infinite precision, printing such values is not trivial since
+  we might need an infinite number of digits if the result happens to be irrational. The
+  user controls printing precision, by specifying how many digits after the decimal point
+  should be printed. The default number of decimal digits to print is 10. (See the
+  'printRealPrec' field of SMT-solver configuration.)
+
+  The acronym SBV used to stand for Symbolic Bit Vectors. However, SBV has grown beyond
+  bit-vectors, especially with the addition of support for SInteger and SReal types and
+  other code-generation utilities. Therefore, "SMT Based Verification" is now a better fit
+  for the expansion of the acronym SBV.
+
+  Other notable changes in the library:
+
+  * Add functions s[TYPE] and s[TYPE]s for each symbolic type we support (i.e.,
+    sBool, sBools, sWord8, sWord8s, etc.), to create symbolic variables of the
+    right kind.  Strictly speaking these are just synonyms for 'free'
+    and 'mapM free' (plural versions), so they are not adding any additional
+    power. Except, they are specialized at their respective types, and might be
+    easier to remember.
+  * Add function solve, which is merely a synonym for (return . bAnd), but
+    it simplifies expressing problems.
+  * Add class SNum, which simplifies writing polymorphic code over symbolic values
+  * Increase haddock coverage metrics
+  * Major code refactoring around symbolic kinds
+  * SMTLib2: Emit ":produce-models" call before setting the logic, as required
+    by the SMT-Lib2 standard. [Patch provided by arrowdodger on github, thanks!]
+
+  Bugs fixed:
+
+   * [Performance] Use a much simpler default definition for "select": While the
+     older version (based on binary search on the bits of the indexer) was correct,
+     it created unnecessarily big expressions. Since SBV does not have a notion
+     of concrete subwords, the binary-search trick was not bringing any advantage
+     in any case. Instead, we now simply use a linear walk over the elements.
+
+  Examples:
+
+   * Change dog-cat-mouse example to use SInteger for the counts
+   * Add merge-sort example: Data.SBV.Examples.BitPrecise.MergeSort
+   * Add diophantine solver example: Data.SBV.Examples.Existentials.Diophantine
+
+### Version 1.4, 2012-05-10
+
+   * Interim release for test purposes
+
+### Version 1.3, 2012-02-25
+
+  * Workaround cabal/hackage issue, functionally the same as release
+    1.2 below
+
+### Version 1.2, 2012-02-25
+
+ Library:
+
+  * Add a hook so users can add custom script segments for SMT solvers. The new
+    "solverTweaks" field in the SMTConfig data-type can be used for this purpose.
+    As a consequence, mixed Integer/BV problems can cause soundness issues in Z3
+    and does in SBV. Unfortunately, it is too severe for SBV to add the workaround
+    option, as it slows down the solver as a side effect as well. Thus, we are
+    making this optionally available if/when needed. (Note that the work-around
+    should not be necessary with Z3 v3.3; which is not released yet.)
+  * Other minor clean-up
+
+### Version 1.1, 2012-02-14
+
+ Library:
+
+  * Rename bitValue to sbvTestBit
+  * Add sbvPopCount
+  * Add a custom implementation of 'popCount' for the Bits class
+    instance of SBV (GHC >= 7.4.1 only)
+  * Add 'sbvCheckSolverInstallation', which can be used to check
+    that the given solver is installed and good to go.
+  * Add 'generateSMTBenchmarks', simplifying the generation of
+    SMTLib benchmarks for offline sharing.
+
+### Version 1.0, 2012-02-13
+
+ Library:
+
+  * Z3 is now the "default" SMT solver. Yices is still available, but
+    has to be specifically selected. (Use satWith, allSatWith, proveWith, etc.)
+  * Better handling of the pConstrain probability threshold for test
+    case generation and quickCheck purposes.
+  * Add 'renderTest', which accompanies 'genTest' to render test
+    vectors as Haskell/C/Forte program segments.
+  * Add 'expectedValue' which can compute the expected value of
+    a symbolic value under the given constraints. Useful for statistical
+    analysis and probability computations.
+  * When saturating provable values, use forAll_ for proofs and forSome_
+    for sat/allSat. (Previously we were always using forAll_, which is
+    not incorrect but less intuitive.)
+  * add function:
+      extractModels :: SatModel a => AllSatResult -> [a]
+    which simplifies accessing allSat results greatly.
+
+ Code-generation:
+
+  * add "cgGenerateMakefile" which allows the user to choose if SBV
+    should generate a Makefile. (default: True)
+
+ Other
+
+  * Changes to make it compile with GHC 7.4.1.
+
+### Version 0.9.24, 2011-12-28
+
+  Library:
+
+   * Add "forSome," analogous to "forAll." (The name "exists" would've
+     been better, but it's already taken.) This is not as useful as
+     one might think as forAll and forSome do not nest, as an inner
+     application of one pushes its argument to a Predicate, making
+     the outer one useless, but it is nonetheless useful by itself.
+   * Add a "Modelable" class, which simplifies model extraction.
+   * Add support for quick-check at the "Symbolic SBool" level. Previously
+     SBV only allowed functions returning SBool to be quick-checked, which
+     forced a certain style of coding. In particular with the addition
+     of quantifiers, the new coding style mostly puts the top-level
+     expressions in the Symbolic monad, which were not quick-checkable
+     before. With new support, the quickCheck, prove, sat, and allSat
+     commands are all interchangeable with obvious meanings.
+   * Add support for concrete test case generation, see the genTest function.
+   * Improve optimize routines and add support for iterative optimization.
+   * Add "constrain", simplifying conjunctive constraints, especially
+     useful for adding constraints at variable generation time via
+     forall/exists. Note that the interpretation of such constraints
+     is different for genTest and quickCheck functions, where constraints
+     will be used for appropriately filtering acceptable test values
+     in those two cases.
+   * Add "pConstrain", which probabilistically adds constraints. This
+     is useful for quickCheck and genTest functions for filtering acceptable
+     test values. (Calls to pConstrain will be rejected for sat/prove calls.)
+   * Add "isVacuous" which can be used to check that the constraints added
+     via constrain are satisfiable. This is useful to prevent vacuous passes,
+     i.e., when a proof is not just passing because the constraints imposed
+     are inconsistent. (Also added accompanying isVacuousWith.)
+   * Add "free" and "free_", analogous to "forall/forall_" and "exists/exists_"
+     The difference is that free behaves universally in a proof context, while
+     it behaves existentially in a sat context. This allows us to express
+     properties more succinctly, since the intended semantics is usually this
+     way depending on the context. (i.e., in a proof, we want our variables
+     universal, in a sat call existential.) Of course, exists/forall are still
+     available when mixed quantifiers are needed, or when the user wants to
+     be explicit about the quantifiers.
+
+  Examples
+
+   * Add Data/SBV/Examples/Puzzles/Coins.hs. (Shows the usage of "constrain".)
+
+  Dependencies
+
+   * Bump up random package dependency to 1.0.1.1 (from 1.0.0.2)
+
+  Internal
+
+   * Major reorganization of files to and build infrastructure to
+     decrease build times and better layout
+   * Get rid of custom Setup.hs, just use simple build. The extra work
+     was not worth the complexity.
+
+### Version 0.9.23, 2011-12-05
+
+  Library:
+
+   * Add support for SInteger, the type of signed unbounded integer
+     values. SBV can now prove theorems about unbounded numbers,
+     following the semantics of Haskell Integer type. (Requires z3 to
+     be used as the backend solver.)
+   * Add functions 'optimize', 'maximize', and 'minimize' that can
+     be used to find optimal solutions to given constraints with
+     respect to a given cost function.
+   * Add 'cgUninterpret', which simplifies code generation when we want
+     to use an alternate definition in the target language (i.e., C). This
+     is important for efficient code generation, when we want to
+     take advantage of native libraries available in the target platform.
+
+  Other:
+
+   * Change getModel to return a tuple in the success case, where
+     the first component is a boolean indicating whether the model
+     is "potential." This is used to indicate that the solver
+     actually returned "unknown" for the problem and the model
+     might therefore be bogus. Note that we did not need this before
+     since we only supported bounded bit-vectors, which has a decidable
+     theory. With the addition of unbounded Integers and quantifiers, the
+     solvers can now return unknown. This should still be rare in practice,
+     but can happen with the use of non-linear constructs. (i.e.,
+     multiplication of two variables.)
+
+### Version 0.9.22, 2011-11-13
+
+  The major change in this release is the support for quantifiers. The
+  SBV library *no* longer assumes all variables are universals in a proof,
+  (and correspondingly existential in a sat) call. Instead, the user
+  marks free-variables appropriately using forall/exists functions, and the
+  solver translates them accordingly. Note that this is a non-backwards
+  compatible change in sat calls, as the semantics of formulas is essentially
+  changing. While this is unfortunate, it is more uniform and simpler to understand
+  in general.
+
+  This release also adds support for the Z3 solver, which is the main
+  SMT-solver used for solving formulas involving quantifiers. More formally,
+  we use the new AUFBV/ABV/UFBV logics when quantifiers are involved. Also,
+  the communication with Z3 is now done via SMT-Lib2 format. Eventually
+  the SMTLib1 connection will be severed.
+
+  The other main change is the support for C code generation with
+  uninterpreted functions enabling users to interface with external
+  C functions defined elsewhere. See below for details.
+
+  Other changes:
+
+  Code:
+
+   * Change getModel, so it returns an Either value to indicate
+     something went wrong; instead of throwing an error
+   * Add support for computing CRCs directly (without needing
+     polynomial division).
+
+  Code generation:
+
+   * Add "cgGenerateDriver" function, which can be used to turn
+     on/off driver program generation. Default is to generate
+     a driver. (Issue "cgGenerateDriver False" to skip the driver.)
+     For a library, a driver will be generated if any of the
+     constituent parts has a driver. Otherwise it will be skipped.
+   * Fix a bug in C code generation where "Not" over booleans were
+     incorrectly getting translated due to need for masking.
+   * Add support for compilation with uninterpreted functions. Users
+     can now specify the corresponding C code and SBV will simply
+     call the "native" functions instead of generating it. This
+     enables interfacing with other C programs. See the functions:
+     cgAddPrototype, cgAddDecl, cgAddLDFlags
+
+  Examples:
+
+   * Add CRC polynomial generation example via existentials
+   * Add USB CRC code generation example, both via polynomials and using the internal CRC functionality
+
+### Version 0.9.21, 2011-08-05
+
+ Code generation:
+
+  * Allow for inclusion of user makefiles
+  * Allow for CCFLAGS to be set by the user
+  * Other minor clean-up
+
+### Version 0.9.20, 2011-06-05
+
+  Regression on 0.9.19; add missing file to cabal
+
+### Version 0.9.19, 2011-06-05
+
+
+  * Add SignCast class for conversion between signed/unsigned
+    quantities for same-sized bit-vectors
+  * Add full-binary trees that can be indexed symbolically (STree). The
+    advantage of this type is that the reads and writes take
+    logarithmic time. Suitable for implementing faster symbolic look-up.
+  * Expose HasSignAndSize class through Data.SBV.Internals
+  * Many minor improvements, file re-orgs
+
+Examples:
+
+  * Add sentence-counting example
+  * Add an implementation of RC4
+
+### Version 0.9.18, 2011-04-07
+
+Code:
+
+  * Re-engineer code-generation, and compilation to C.
+    In particular, allow arrays of inputs to be specified,
+    both as function arguments and output reference values.
+  * Add support for generation of generation of C-libraries,
+    allowing code generation for a set of functions that
+    work together.
+
+Examples:
+
+  * Update code-generation examples to use the new API.
+  * Include a library-generation example for doing 128-bit
+    AES encryption
+
+### Version 0.9.17, 2011-03-29
+
+Code:
+
+  * Simplify and reorganize the test suite
+
+Examples:
+
+  * Improve AES decryption example, by using
+    table-lookups in InvMixColumns.
+
+### Version 0.9.16, 2011-03-28
+
+Code:
+
+  * Further optimizations on Bits instance of SBV
+
+Examples:
+
+  * Add AES algorithm as an example, showing how
+    encryption algorithms are particularly suitable
+    for use with the code-generator
+
+### Version 0.9.15, 2011-03-24
+
+Bug fixes:
+
+  * Fix rotateL/rotateR instances on concrete
+    words. Previous versions was bogus since
+    it relied on the Integer instance, which
+    does the wrong thing after normalization.
+  * Fix conversion of signed numbers from bits,
+    previous version did not handle twos
+    complement layout correctly
+
+Testing:
+
+  * Add a sleuth of concrete test cases on
+    arithmetic to catch bugs. (There are many
+    of them, ~30K, but they run quickly.)
+
+### Version 0.9.14, 2011-03-19
+
+  * Re-implement sharing using Stable names, inspired
+    by the Data.Reify techniques. This avoids tricks
+    with unsafe memory stashing, and hence is safe.
+    Thus, issues with respect to CAFs are now resolved.
+
+### Version 0.9.13, 2011-03-16
+
+Bug fixes:
+
+  * Make sure SBool short-cut evaluations are done
+    as early as possible, as these help with coding
+    recursion-depth based algorithms, when dealing
+    with symbolic termination issues.
+
+Examples:
+
+  * Add fibonacci code-generation example, original
+    code by Lee Pike.
+  * Add a GCD code-generation/verification example
+
+### Version 0.9.12, 2011-03-10
+
+New features:
+
+  * Add support for compilation to C
+  * Add a mechanism for offline saving of SMT-Lib files
+
+Bug fixes:
+
+  * Output naming bug, reported by Josef Svenningsson
+  * Specification bug in Legatos multiplier example
+
+### Version 0.9.11, 2011-02-16
+
   * Make ghc-7.0 happy, minor re-org on the cabal file/Setup.hs
 
 ### Version 0.9.10, 2011-02-15
diff --git a/COPYRIGHT b/COPYRIGHT
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,4 +1,4 @@
-Copyright (c) 2010-2017, Levent Erkok (erkokl@gmail.com)
+Copyright (c) 2010-2026, Levent Erkok (erkokl@gmail.com)
 All rights reserved.
 
 The sbv library is distributed with the BSD3 license. See the LICENSE file
diff --git a/Data/SBV.hs b/Data/SBV.hs
--- a/Data/SBV.hs
+++ b/Data/SBV.hs
@@ -1,813 +1,1858 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- (The sbv library is hosted at <http://github.com/LeventErkok/sbv>.
--- Comments, bug reports, and patches are always welcome.)
---
--- SBV: SMT Based Verification
---
--- Express properties about Haskell programs and automatically prove
--- them using SMT solvers.
---
--- >>> prove $ \x -> x `shiftL` 2 .== 4 * (x :: SWord8)
--- Q.E.D.
---
--- >>> prove $ \x -> x `shiftL` 2 .== 2 * (x :: SWord8)
--- Falsifiable. Counter-example:
---   s0 = 32 :: Word8
---
--- The function 'prove' has the following type:
---
--- @
---     'prove' :: 'Provable' a => a -> 'IO' 'ThmResult'
--- @
---
--- The class 'Provable' comes with instances for n-ary predicates, for arbitrary n.
--- The predicates are just regular Haskell functions over symbolic types listed below.
--- Functions for checking satisfiability ('sat' and 'allSat') are also
--- provided.
---
--- The sbv library introduces the following symbolic types:
---
---   * 'SBool': Symbolic Booleans (bits).
---
---   * 'SWord8', 'SWord16', 'SWord32', 'SWord64': Symbolic Words (unsigned).
---
---   * 'SInt8',  'SInt16',  'SInt32',  'SInt64': Symbolic Ints (signed).
---
---   * 'SInteger': Unbounded signed integers.
---
---   * 'SReal': Algebraic-real numbers
---
---   * 'SFloat': IEEE-754 single-precision floating point values
---
---   * 'SDouble': IEEE-754 double-precision floating point values
---
---   * 'SArray', 'SFunArray': Flat arrays of symbolic values.
---
---   * Symbolic polynomials over GF(2^n), polynomial arithmetic, and CRCs.
---
---   * Uninterpreted constants and functions over symbolic values, with user
---     defined SMT-Lib axioms.
---
---   * Uninterpreted sorts, and proofs over such sorts, potentially with axioms.
---
--- 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') 
--- and 'Ord' ('OrdSymbolic'), along with several other custom classes for simplifying
--- programming with symbolic values. The framework takes full advantage of Haskell's type
--- inference to avoid many common mistakes.
---
--- Furthermore, predicates (i.e., functions that return 'SBool') built out of
--- these types can also be:
---
---   * proven correct via an external SMT solver (the 'prove' function)
---
---   * checked for satisfiability (the 'sat', 'allSat' functions)
---
---   * used in synthesis (the `sat` function with existentials)
---
---   * quick-checked
---
--- If a predicate is not valid, 'prove' will return a counterexample: An
--- assignment to inputs such that the predicate fails. The 'sat' function will
--- return a satisfying assignment, if there is one. The 'allSat' function returns
--- all satisfying assignments, lazily.
---
--- The sbv library uses third-party SMT solvers via the standard SMT-Lib interface:
--- <http://smtlib.cs.uiowa.edu/>
---
--- The SBV library is designed to work with any SMT-Lib compliant SMT-solver.
--- Currently, we support the following SMT-Solvers out-of-the box:
---
---   * ABC from University of Berkeley: <http://www.eecs.berkeley.edu/~alanmi/abc/>
---
---   * CVC4 from New York University and University of Iowa: <http://cvc4.cs.nyu.edu/>
---
---   * Boolector from Johannes Kepler University: <http://fmv.jku.at/boolector/>
---
---   * MathSAT from Fondazione Bruno Kessler and DISI-University of Trento: <http://mathsat.fbk.eu/>
---
---   * Yices from SRI: <http://yices.csl.sri.com/>
---
---   * Z3 from Microsoft: <http://github.com/Z3Prover/z3/wiki>
---
--- SBV also allows calling these solvers in parallel, either getting results from multiple solvers
--- or returning the fastest one. (See 'proveWithAll', 'proveWithAny', etc.)
---
--- Support for other compliant solvers can be added relatively easily, please
--- get in touch if there is a solver you'd like to see included.
----------------------------------------------------------------------------------
-
-{-# LANGUAGE FlexibleInstances #-}
-
-module Data.SBV (
-  -- * Programming with symbolic values
-  -- $progIntro
-
-  -- ** Symbolic types
-
-  -- *** Symbolic bit
-    SBool
-  -- *** Unsigned symbolic bit-vectors
-  , SWord8, SWord16, SWord32, SWord64
-  -- *** Signed symbolic bit-vectors
-  , SInt8, SInt16, SInt32, SInt64
-  -- *** Signed unbounded integers
-  -- $unboundedLimitations
-  , SInteger
-  -- *** IEEE-floating point numbers
-  -- $floatingPoints
-  , SFloat, SDouble, IEEEFloating(..), IEEEFloatConvertable(..), RoundingMode(..), SRoundingMode, nan, infinity, sNaN, sInfinity
-  -- **** Rounding modes
-  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero, sRNE, sRNA, sRTP, sRTN, sRTZ
-  -- **** Bit-pattern conversions
-  , sFloatAsSWord32, sWord32AsSFloat, sDoubleAsSWord64, sWord64AsSDouble, blastSFloat, blastSDouble
-  -- *** Signed algebraic reals
-  -- $algReals
-  , SReal, AlgReal, sRealToSInteger
-  -- ** Creating a symbolic variable
-  -- $createSym
-  , sBool, sWord8, sWord16, sWord32, sWord64, sInt8, sInt16, sInt32, sInt64, sInteger, sReal, sFloat, sDouble
-  -- ** Creating a list of symbolic variables
-  -- $createSyms
-  , sBools, sWord8s, sWord16s, sWord32s, sWord64s, sInt8s, sInt16s, sInt32s, sInt64s, sIntegers, sReals, sFloats, sDoubles
-  -- *** Abstract SBV type
-  , SBV
-  -- *** Arrays of symbolic values
-  , SymArray(..), SArray, SFunArray, mkSFunArray
-  -- *** Full binary trees
-  , STree, readSTree, writeSTree, mkSTree
-  -- ** Operations on symbolic values
-  -- *** Word level
-  , sTestBit, sExtractBits, sPopCount, sShiftLeft, sShiftRight, sRotateLeft, sRotateRight, sSignedShiftArithRight, sFromIntegral, setBitTo, oneIf
-  , lsb, msb, label
-  -- *** Predicates
-  , allEqual, allDifferent, inRange, sElem
-  -- *** Addition and Multiplication with high-bits
-  , fullAdder, fullMultiplier
-  -- *** Exponentiation
-  , (.^)
-  -- *** Blasting/Unblasting
-  , blastBE, blastLE, FromBits(..)
-  -- *** Splitting, joining, and extending
-  , Splittable(..)
-  -- ** Polynomial arithmetic and CRCs
-  , Polynomial(..), crcBV, crc
-  -- ** Conditionals: Mergeable values
-  , Mergeable(..), ite, iteLazy
-  -- ** Symbolic equality
-  , EqSymbolic(..)
-  -- ** Symbolic ordering
-  , OrdSymbolic(..)
-  -- ** Symbolic integral numbers
-  , SIntegral
-  -- ** Division
-  , SDivisible(..)
-  -- ** The Boolean class
-  , Boolean(..)
-  -- *** Generalizations of boolean operations
-  , bAnd, bOr, bAny, bAll
-  -- ** Pretty-printing and reading numbers in Hex & Binary
-  , PrettyNum(..), readBin
-  -- * Checking satisfiability in path conditions
-  , isSatisfiableInCurrentPath
-
-  -- * Uninterpreted sorts, constants, and functions
-  -- $uninterpreted
-  , Uninterpreted(..), addAxiom
-
-  -- * Enumerations
-  -- $enumerations
-
-  -- * Properties, proofs, satisfiability, and safety
-  -- $proveIntro
-
-  -- ** Predicates
-  , Predicate, Provable(..), Equality(..)
-  -- ** Proving properties
-  , prove, proveWith, isTheorem, isTheoremWith
-  -- ** Checking satisfiability
-  , sat, satWith, isSatisfiable, isSatisfiableWith
-  -- ** Checking safety
-  -- $safeIntro
-  , sAssert, safe, safeWith, isSafe, SExecutable(..)
-  -- ** Finding all satisfying assignments
-  , allSat, allSatWith
-  -- ** Satisfying a sequence of boolean conditions
-  , solve
-  -- ** Adding constraints
-  -- $constrainIntro
-  , constrain, pConstrain
-  -- ** Checking constraint vacuity
-  , isVacuous, isVacuousWith
-  -- ** Quick-checking
-  , sbvQuickCheck
-
-  -- * Proving properties using multiple solvers
-  -- $multiIntro
-  , proveWithAll, proveWithAny, satWithAll, satWithAny
-
-  -- * Optimization
-  -- $optimizeIntro
-  , minimize, maximize, optimize
-  , minimizeWith, maximizeWith, optimizeWith
-
-  -- * Computing expected values
-  , expectedValue, expectedValueWith
-
-  -- * Model extraction
-  -- $modelExtraction
-
-  -- ** Inspecting proof results
-  -- $resultTypes
-  , ThmResult(..), SatResult(..), SafeResult(..), AllSatResult(..), SMTResult(..)
-
-  -- ** Programmable model extraction
-  -- $programmableExtraction
-  , SatModel(..), Modelable(..), displayModels, extractModels
-  , getModelDictionaries, getModelValues, getModelUninterpretedValues
-
-  -- * SMT Interface: Configurations and solvers
-  , SMTConfig(..), SMTLibVersion(..), SMTLibLogic(..), Logic(..), OptimizeOpts(..), Solver(..), SMTSolver(..), boolector, cvc4, yices, z3, mathSAT, abc, defaultSolverConfig, sbvCurrentSolver, defaultSMTCfg, sbvCheckSolverInstallation, sbvAvailableSolvers
-  , Timing(..), TimedStep(..), TimingInfo, showTDiff
-
-  -- * Symbolic computations
-  , Symbolic, output, SymWord(..)
-
-  -- * Getting SMT-Lib output (for offline analysis)
-  , compileToSMTLib, generateSMTBenchmarks
-
-  -- * Test case generation
-  , genTest, getTestValues, TestVectors, TestStyle(..), renderTest, CW(..), HasKind(..), Kind(..), cwToBool
-
-  -- * Code generation from symbolic programs
-  -- $cCodeGeneration
-  , SBVCodeGen
-
-  -- ** Setting code-generation options
-  , cgPerformRTCs, cgSetDriverValues, cgGenerateDriver, cgGenerateMakefile
-
-  -- ** Designating inputs
-  , cgInput, cgInputArr
-
-  -- ** Designating outputs
-  , cgOutput, cgOutputArr
-
-  -- ** Designating return values
-  , cgReturn, cgReturnArr
-
-  -- ** Code generation with uninterpreted functions
-  , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert
-
-  -- ** Code generation with 'SInteger' and 'SReal' types
-  -- $unboundedCGen
-  , cgIntegerSize, cgSRealType, CgSRealType(..)
-
-  -- ** Compilation to C
-  , compileToC, compileToCLib
-
-  -- * Module exports
-  -- $moduleExportIntro
-
-  , module Data.Bits
-  , module Data.Word
-  , module Data.Int
-  , module Data.Ratio
-  ) where
-
-import Control.Monad            (filterM)
-import Control.Concurrent.Async (async, waitAny, waitAnyCancel)
-import System.IO.Unsafe         (unsafeInterleaveIO)             -- only used safely!
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model
-import Data.SBV.BitVectors.Floating
-import Data.SBV.BitVectors.PrettyNum
-import Data.SBV.BitVectors.Splittable
-import Data.SBV.BitVectors.STree
-import Data.SBV.Compilers.C
-import Data.SBV.Compilers.CodeGen
-import Data.SBV.Provers.Prover
-import Data.SBV.Tools.GenTest
-import Data.SBV.Tools.ExpectedValue
-import Data.SBV.Tools.Optimize
-import Data.SBV.Tools.Polynomial
-import Data.SBV.Utils.Boolean
-import Data.SBV.Utils.TDiff
-import Data.Bits
-import Data.Int
-import Data.Ratio
-import Data.Word
-
--- | The currently active solver, obtained by importing "Data.SBV".
--- To have other solvers /current/, import one of the bridge
--- modules "Data.SBV.Bridge.ABC", "Data.SBV.Bridge.Boolector", "Data.SBV.Bridge.CVC4",
--- "Data.SBV.Bridge.Yices", or "Data.SBV.Bridge.Z3" directly.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = z3
-
--- | Form the symbolic conjunction of a given list of boolean conditions. Useful in expressing
--- problems with constraints, like the following:
---
--- @
---   do [x, y, z] <- sIntegers [\"x\", \"y\", \"z\"]
---      solve [x .> 5, y + z .< x]
--- @
-solve :: [SBool] -> Symbolic SBool
-solve = return . bAnd
-
--- | Check whether the given solver is installed and is ready to go. This call does a
--- simple call to the solver to ensure all is well.
-sbvCheckSolverInstallation :: SMTConfig -> IO Bool
-sbvCheckSolverInstallation cfg = do ThmResult r <- proveWith cfg $ \x -> (x+x) .== ((x*2) :: SWord8)
-                                    case r of
-                                      Unsatisfiable _ -> return True
-                                      _               -> return False
-
--- | The default configs corresponding to supported SMT solvers
-defaultSolverConfig :: Solver -> SMTConfig
-defaultSolverConfig Z3        = z3
-defaultSolverConfig Yices     = yices
-defaultSolverConfig Boolector = boolector
-defaultSolverConfig CVC4      = cvc4
-defaultSolverConfig MathSAT   = mathSAT
-defaultSolverConfig ABC       = abc
-
--- | Return the known available solver configs, installed on your machine.
-sbvAvailableSolvers :: IO [SMTConfig]
-sbvAvailableSolvers = filterM sbvCheckSolverInstallation (map defaultSolverConfig [minBound .. maxBound])
-
-sbvWithAny :: [SMTConfig] -> (SMTConfig -> a -> IO b) -> a -> IO (Solver, b)
-sbvWithAny []      _    _ = error "SBV.withAny: No solvers given!"
-sbvWithAny solvers what a = snd `fmap` (mapM try solvers >>= waitAnyCancel)
-   where try s = async $ what s a >>= \r -> return (name (solver s), r)
-
-sbvWithAll :: [SMTConfig] -> (SMTConfig -> a -> IO b) -> a -> IO [(Solver, b)]
-sbvWithAll solvers what a = mapM try solvers >>= (unsafeInterleaveIO . go)
-   where try s = async $ what s a >>= \r -> return (name (solver s), r)
-         go []  = return []
-         go as  = do (d, r) <- waitAny as
-                     -- The following filter works because the Eq instance on Async
-                     -- checks the thread-id; so we know that we're removing the
-                     -- correct solver from the list. This also allows for
-                     -- running the same-solver (with different options), since
-                     -- they will get different thread-ids.
-                     rs <- unsafeInterleaveIO $ go (filter (/= d) as)
-                     return (r : rs)
-
--- | Prove a property with multiple solvers, running them in separate threads. The
--- results will be returned in the order produced.
-proveWithAll :: Provable a => [SMTConfig] -> a -> IO [(Solver, ThmResult)]
-proveWithAll  = (`sbvWithAll` proveWith)
-
--- | Prove a property with multiple solvers, running them in separate threads. Only
--- the result of the first one to finish will be returned, remaining threads will be killed.
-proveWithAny :: Provable a => [SMTConfig] -> a -> IO (Solver, ThmResult)
-proveWithAny  = (`sbvWithAny` proveWith)
-
--- | Find a satisfying assignment to a property with multiple solvers, running them in separate threads. The
--- results will be returned in the order produced.
-satWithAll :: Provable a => [SMTConfig] -> a -> IO [(Solver, SatResult)]
-satWithAll = (`sbvWithAll` satWith)
-
--- | Find a satisfying assignment to a property with multiple solvers, running them in separate threads. Only
--- the result of the first one to finish will be returned, remaining threads will be killed.
-satWithAny :: Provable a => [SMTConfig] -> a -> IO (Solver, SatResult)
-satWithAny    = (`sbvWithAny` satWith)
-
--- | Equality as a proof method. Allows for
--- very concise construction of equivalence proofs, which is very typical in
--- bit-precise proofs.
-infix 4 ===
-class Equality a where
-  (===) :: a -> a -> IO ThmResult
-
-instance {-# OVERLAPPABLE #-} (SymWord a, EqSymbolic z) => Equality (SBV a -> z) where
-  k === l = prove $ \a -> k a .== l a
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, EqSymbolic z) => Equality (SBV a -> SBV b -> z) where
-  k === l = prove $ \a b -> k a b .== l a b
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, EqSymbolic z) => Equality ((SBV a, SBV b) -> z) where
-  k === l = prove $ \a b -> k (a, b) .== l (a, b)
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> z) where
-  k === l = prove $ \a b c -> k a b c .== l a b c
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c) -> z) where
-  k === l = prove $ \a b c -> k (a, b, c) .== l (a, b, c)
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> z) where
-  k === l = prove $ \a b c d -> k a b c d .== l a b c d
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d) -> z) where
-  k === l = prove $ \a b c d -> k (a, b, c, d) .== l (a, b, c, d)
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> z) where
-  k === l = prove $ \a b c d e -> k a b c d e .== l a b c d e
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e) -> z) where
-  k === l = prove $ \a b c d e -> k (a, b, c, d, e) .== l (a, b, c, d, e)
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> z) where
-  k === l = prove $ \a b c d e f -> k a b c d e f .== l a b c d e f
-
-instance {-# OVERLAPPABLE #-}
- (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> z) where
-  k === l = prove $ \a b c d e f -> k (a, b, c, d, e, f) .== l (a, b, c, d, e, f)
-
-instance {-# OVERLAPPABLE #-}
- (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SymWord g, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> z) where
-  k === l = prove $ \a b c d e f g -> k a b c d e f g .== l a b c d e f g
-
-instance {-# OVERLAPPABLE #-} (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SymWord g, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> z) where
-  k === l = prove $ \a b c d e f g -> k (a, b, c, d, e, f, g) .== l (a, b, c, d, e, f, g)
-
--- Haddock section documentation
-{- $progIntro
-The SBV library is really two things:
-
-  * A framework for writing symbolic programs in Haskell, i.e., programs operating on
-    symbolic values along with the usual concrete counterparts.
-
-  * A framework for proving properties of such programs using SMT solvers.
-
-The programming goal of SBV is to provide a /seamless/ experience, i.e., let people program
-in the usual Haskell style without distractions of symbolic coding. While Haskell helps
-in some aspects (the 'Num' and 'Bits' classes simplify coding), it makes life harder
-in others. For instance, @if-then-else@ only takes 'Bool' as a test in Haskell, and
-comparisons ('>' etc.) only return 'Bool's. Clearly we would like these values to be
-symbolic (i.e., 'SBool'), thus stopping us from using some native Haskell constructs.
-When symbolic versions of operators are needed, they are typically obtained by prepending a dot,
-for instance '==' becomes '.=='. Care has been taken to make the transition painless. In
-particular, any Haskell program you build out of symbolic components is fully concretely
-executable within Haskell, without the need for any custom interpreters. (They are truly
-Haskell programs, not AST's built out of pieces of syntax.) This provides for an integrated
-feel of the system, one of the original design goals for SBV.
--}
-
-{- $proveIntro
-The SBV library provides a "push-button" verification system via automated SMT solving. The
-design goal is to let SMT solvers be used without any knowledge of how SMT solvers work
-or how different logics operate. The details are hidden behind the SBV framework, providing
-Haskell programmers with a clean API that is unencumbered by the details of individual solvers.
-To that end, we use the SMT-Lib standard (<http://smtlib.cs.uiowa.edu/>)
-to communicate with arbitrary SMT solvers.
--}
-
-{- $multiIntro
-On a multi-core machine, it might be desirable to try a given property using multiple SMT solvers,
-using parallel threads. Even with machines with single-cores, threading can be helpful if you
-want to try out multiple-solvers but do not know which one would work the best
-for the problem at hand ahead of time.
-
-The functions in this section allow proving/satisfiability-checking with multiple
-backends at the same time. Each function comes in two variants, one that
-returns the results from all solvers, the other that returns the fastest one.
-
-The @All@ variants, (i.e., 'proveWithAll', 'satWithAll') run all solvers and
-return all the results. SBV internally makes sure that the result is lazily generated; so,
-the order of solvers given does not matter. In other words, the order of results will follow
-the order of the solvers as they finish, not as given by the user. These variants are useful when you
-want to make sure multiple-solvers agree (or disagree!) on a given problem.
-
-The @Any@ variants, (i.e., 'proveWithAny', 'satWithAny') will run all the solvers
-in parallel, and return the results of the first one finishing. The other threads will then be killed. These variants
-are useful when you do not care if the solvers produce the same result, but rather want to get the
-solution as quickly as possible, taking advantage of modern many-core machines.
-
-Note that the function 'sbvAvailableSolvers' will return all the installed solvers, which can be
-used as the first argument to all these functions, if you simply want to try all available solvers on a machine.
--}
-
-{- $safeIntro
-
-The 'sAssert' function allows users to introduce invariants to make sure
-certain properties hold at all times. This is another mechanism to provide further documentation/contract info
-into SBV code. The functions 'safe' and 'safeWith' can be used to statically discharge these proof assumptions.
-If a violation is found, SBV will print a model showing which inputs lead to the invariant being violated.
-
-Here's a simple example. Let's assume we have a function that does subtraction, and requires its
-first argument to be larger than the second:
-
->>> let sub x y = sAssert Nothing "sub: x >= y must hold!" (x .>= y) (x - y)
-
-Clearly, this function is not safe, as there's nothing that stops us from passing it a larger second argument.
-We can use 'safe' to statically see if such a violation is possible before we use this function elsewhere.
-
->>> safe (sub :: SInt8 -> SInt8 -> SInt8)
-[sub: x >= y must hold!: Violated. Model:
-  s0 = -128 :: Int8
-  s1 = -127 :: Int8]
-
-What happens if we make sure to arrange for this invariant? Consider this version:
-
->>> let safeSub x y = ite (x .>= y) (sub x y) 0
-
-Clearly, 'safeSub' must be safe. And indeed, SBV can prove that:
-
->>> safe (safeSub :: SInt8 -> SInt8 -> SInt8)
-[sub: x >= y must hold!: No violations detected]
-
-Note how we used 'sub' and 'safeSub' polymorphically. We only need to monomorphise our types when a proof
-attempt is done, as we did in the 'safe' calls.
-
-If required, the user can pass a 'CallStack' through the first argument to 'sAssert', which will be used
-by SBV to print a diagnostic info to pinpoint the failure.
-
-Also see "Data.SBV.Examples.Misc.NoDiv0" for the classic div-by-zero example.
--}
-
-
-{- $optimizeIntro
-Symbolic optimization. A call of the form:
-
-    @minimize Quantified cost n valid@
-
-returns @Just xs@, such that:
-
-   * @xs@ has precisely @n@ elements
-
-   * @valid xs@ holds
-
-   * @cost xs@ is minimal. That is, for all sequences @ys@ that satisfy the first two criteria above, @cost xs .<= cost ys@ holds.
-
-If there is no such sequence, then 'minimize' will return 'Nothing'.
-
-The function 'maximize' is similar, except the comparator is '.>='. So the value returned has the largest cost (or value, in that case).
-
-The function 'optimize' allows the user to give a custom comparison function.
-
-The 'OptimizeOpts' argument controls how the optimization is done. If 'Quantified' is used, then the SBV optimization engine satisfies the following predicate:
-
-   @exists xs. forall ys. valid xs && (valid ys \`implies\` (cost xs \`cmp\` cost ys))@
-
-Note that this may cause efficiency problems as it involves alternating quantifiers.
-If 'OptimizeOpts' is set to 'Iterative' 'True', then SBV will programmatically
-search for an optimal solution, by repeatedly calling the solver appropriately. (The boolean argument controls whether progress reports are given. Use
-'False' for quiet operation.)
-
-=== Quantified vs Iterative
-
-Note that the quantified and iterative versions are two different optimization approaches and may not necessarily yield the same
-results. In particular, the quantified version can tell us no such solution exists if there is no global optimum value, while the iterative
-version might simply loop forever for such a problem. To wit, consider the example:
-
-   @ maximize Quantified head 1 (const true :: [SInteger] -> SBool) @
-
-which asks for the largest `SInteger` value. The SMT solver will happily answer back saying there is no such value with the 'Quantified' call, but the 'Iterative' variant
-will simply loop forever as it would search through an infinite chain of ascending 'SInteger' values.
-
-In practice, however, the iterative version is usually the more effective choice since alternating quantifiers are hard to deal with for many SMT-solvers and thus will
-likely result in an @unknown@ result. While the 'Iterative' variant can loop for a long time, one can simply use the boolean flag 'True' and see how the search is progressing.
--}
-
-{- $modelExtraction
-The default 'Show' instances for prover calls provide all the counter-example information in a
-human-readable form and should be sufficient for most casual uses of sbv. However, tools built
-on top of sbv will inevitably need to look into the constructed models more deeply, programmatically
-extracting their results and performing actions based on them. The API provided in this section
-aims at simplifying this task.
--}
-
-{- $resultTypes
-'ThmResult', 'SatResult', and 'AllSatResult' are simple newtype wrappers over 'SMTResult'. Their
-main purpose is so that we can provide custom 'Show' instances to print results accordingly.
--}
-
-{- $programmableExtraction
-While default 'Show' instances are sufficient for most use cases, it is sometimes desirable (especially
-for library construction) that the SMT-models are reinterpreted in terms of domain types. Programmable
-extraction allows getting arbitrarily typed models out of SMT models.
--}
-
-{- $cCodeGeneration
-The SBV library can generate straight-line executable code in C. (While other target languages are
-certainly possible, currently only C is supported.) The generated code will perform no run-time memory-allocations,
-(no calls to @malloc@), so its memory usage can be predicted ahead of time. Also, the functions will execute precisely the
-same instructions in all calls, so they have predictable timing properties as well. The generated code
-has no loops or jumps, and is typically quite fast. While the generated code can be large due to complete unrolling,
-these characteristics make them suitable for use in hard real-time systems, as well as in traditional computing.
--}
-
-{- $unboundedCGen
-The types 'SInteger' and 'SReal' are unbounded quantities that have no direct counterparts in the C language. Therefore,
-it is not possible to generate standard C code for SBV programs using these types, unless custom libraries are available. To
-overcome this, SBV allows the user to explicitly set what the corresponding types should be for these two cases, using
-the functions below. Note that while these mappings will produce valid C code, the resulting code will be subject to
-overflow/underflows for 'SInteger', and rounding for 'SReal', so there is an implicit loss of precision.
-
-If the user does /not/ specify these mappings, then SBV will
-refuse to compile programs that involve these types.
--}
-
-{- $moduleExportIntro
-The SBV library exports the following modules wholesale, as user programs will have to import these
-modules to make any sensible use of the SBV functionality.
--}
-
-{- $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.
--}
-
-{- $createSyms
-These functions simplify declaring a sequence symbolic variables of various types. Strictly speaking, they are just synonyms
-for 'mapM' 'free' (specialized at the given type), but they might be easier to use.
--}
-
-{- $unboundedLimitations
-The SBV library supports unbounded signed integers with the type 'SInteger', which are not subject to
-overflow/underflow as it is the case with the bounded types, such as 'SWord8', 'SInt16', etc. However,
-some bit-vector based operations are /not/ supported for the 'SInteger' type while in the verification mode. That
-is, you can use these operations on 'SInteger' values during normal programming/simulation.
-but the SMT translation will not support these operations since there corresponding operations are not supported in SMT-Lib.
-Note that this should rarely be a problem in practice, as these operations are mostly meaningful on fixed-size
-bit-vectors. The operations that are restricted to bounded word/int sizes are:
-
-   * Rotations and shifts: 'rotateL', 'rotateR', 'shiftL', 'shiftR'
-
-   * Bitwise logical ops: '.&.', '.|.', 'xor', 'complement'
-
-   * Extraction and concatenation: 'split', '#', and 'extend' (see the 'Splittable' class)
-
-Usual arithmetic ('+', '-', '*', 'sQuotRem', 'sQuot', 'sRem', 'sDivMod', 'sDiv', 'sMod') and logical operations ('.<', '.<=', '.>', '.>=', '.==', './=') operations are
-supported for 'SInteger' fully, both in programming and verification modes.
--}
-
-{- $algReals
-Algebraic reals are roots of single-variable polynomials with rational coefficients. (See
-<http://en.wikipedia.org/wiki/Algebraic_number>.) Note that algebraic reals are infinite
-precision numbers, but they do not cover all /real/ numbers. (In particular, they cannot
-represent transcendentals.) Some irrational numbers are algebraic (such as @sqrt 2@), while
-others are not (such as pi and e).
-
-SBV can deal with real numbers just fine, since the theory of reals is decidable. (See
-<http://smtlib.cs.uiowa.edu/theories-Reals.shtml>.) In addition, by leveraging backend
-solver capabilities, SBV can also represent and solve non-linear equations involving real-variables.
-(For instance, the Z3 SMT solver, supports polynomial constraints on reals starting with v4.0.)
--}
-
-{- $floatingPoints
-Floating point numbers are defined by the IEEE-754 standard; and correspond to Haskell's
-'Float' and 'Double' types. For SMT support with floating-point numbers, see the paper
-by Rummer and Wahl: <http://www.philipp.ruemmer.org/publications/smt-fpa.pdf>.
--}
-
-{- $constrainIntro
-A constraint is a means for restricting the input domain of a formula. Here's a simple
-example:
-
-@
-   do x <- 'exists' \"x\"
-      y <- 'exists' \"y\"
-      'constrain' $ x .> y
-      'constrain' $ x + y .>= 12
-      'constrain' $ y .>= 3
-      ...
-@
-
-The first constraint requires @x@ to be larger than @y@. The scond one says that
-sum of @x@ and @y@ must be at least @12@, and the final one says that @y@ to be at least @3@.
-Constraints provide an easy way to assert additional properties on the input domain, right at the point of
-the introduction of variables.
-
-Note that the proper reading of a constraint
-depends on the context:
-
-    * In a 'sat' (or 'allSat') call: The constraint added is asserted
-    conjunctively. That is, the resulting satisfying model (if any) will
-    always satisfy all the constraints given.
-
-  * In a 'prove' call: In this case, the constraint acts as an implication.
-    The property is proved under the assumption that the constraint
-    holds. In other words, the constraint says that we only care about
-    the input space that satisfies the constraint.
-
-  * In a 'quickCheck' call: The constraint acts as a filter for 'quickCheck';
-    if the constraint does not hold, then the input value is considered to be irrelevant
-    and is skipped. Note that this is similar to 'prove', but is stronger: We do not
-    accept a test case to be valid just because the constraints fail on them, although
-    semantically the implication does hold. We simply skip that test case as a /bad/
-    test vector.
-
-  * In a 'genTest' call: Similar to 'quickCheck' and 'prove': If a constraint
-    does not hold, the input value is ignored and is not included in the test
-    set.
-
-A good use case (in fact the motivating use case) for 'constrain' is attaching a
-constraint to a 'forall' or 'exists' variable at the time of its creation.
-Also, the conjunctive semantics for 'sat' and the implicative
-semantics for 'prove' simplify programming by choosing the correct interpretation
-automatically. However, one should be aware of the semantic difference. For instance, in
-the presence of constraints, formulas that are /provable/ are not necessarily
-/satisfiable/. To wit, consider:
-
- @
-    do x <- 'exists' \"x\"
-       'constrain' $ x .< x
-       return $ x .< (x :: 'SWord8')
- @
-
-This predicate is unsatisfiable since no element of 'SWord8' is less than itself. But
-it's (vacuously) true, since it excludes the entire domain of values, thus making the proof
-trivial. Hence, this predicate is provable, but is not satisfiable. To make sure the given
-constraints are not vacuous, the functions 'isVacuous' (and 'isVacuousWith') can be used.
-
-Also note that this semantics imply that test case generation ('genTest') and quick-check
-can take arbitrarily long in the presence of constraints, if the random input values generated
-rarely satisfy the constraints. (As an extreme case, consider @'constrain' 'false'@.)
-
-A probabilistic constraint (see 'pConstrain') attaches a probability threshold for the
-constraint to be considered. For instance:
-
-  @
-     'pConstrain' 0.8 c
-  @
-
-will make sure that the condition @c@ is satisfied 80% of the time (and correspondingly, falsified 20%
-of the time), in expectation. This variant is useful for 'genTest' and 'quickCheck' functions, where we
-want to filter the test cases according to some probability distribution, to make sure that the test-vectors
-are drawn from interesting subsets of the input space. For instance, if we were to generate 100 test cases
-with the above constraint, we'd expect about 80 of them to satisfy the condition @c@, while about 20 of them
-will fail it.
-
-The following properties hold:
-
-  @
-    'constrain'      = 'pConstrain' 1
-    'pConstrain' t c = 'pConstrain' (1-t) (not c)
-  @
-
-Note that while 'constrain' can be used freely, 'pConstrain' is only allowed in the contexts of
-'genTest' or 'quickCheck'. Calls to 'pConstrain' in a prove/sat call will be rejected as SBV does not
-deal with probabilistic constraints when it comes to satisfiability and proofs.
-Also, both 'constrain' and 'pConstrain' calls during code-generation will also be rejected, for similar reasons.
--}
-
-{- $uninterpreted
-Users can introduce new uninterpreted sorts simply by defining a data-type in Haskell and registering it as such. The
-following example demonstrates:
-
-  @
-     data B = B () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
-  @
-
-(Note that you'll also need to use the language pragmas @DeriveDataTypeable@, @DeriveAnyClass@, and import @Data.Generics@ for the above to work.) 
-
-This is all it takes to introduce 'B' as an uninterpreted sort in SBV, which makes the type @SBV B@ automagically become available as the type
-of symbolic values that ranges over 'B' values. Note that the @()@ argument is important to distinguish it from enumerations.
-
-Uninterpreted functions over both uninterpreted and regular sorts can be declared using the facilities introduced by
-the 'Uninterpreted' class.
--}
-
-{- $enumerations
-If the uninterpreted sort definition takes the form of an enumeration (i.e., a simple data type with all nullary constructors), then SBV will actually
-translate that as just such a data-type to SMT-Lib, and will use the constructors as the inhabitants of the said sort. A simple example is:
-
-  @
-    data X = A | B | C deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
-  @
-
-Now, the user can define
-
-  @
-    type SX = SBV X
-  @
-
-and treat @SX@ as a regular symbolic type ranging over the values @A@, @B@, and @C@. Such values can be compared for equality, and with the usual
-other comparison operators, such as @.==@, @./=@, @.>@, @.>=@, @<@, and @<=@.
-
-Note that in this latter case the type is no longer uninterpreted, but is properly represented as a simple enumeration of the said elements. A simple
-query would look like:
-
-   @
-     allSat $ \x -> x .== (x :: SX)
-   @
-
-which would list all three elements of this domain as satisfying solutions.
-
-   @
-     Solution #1:
-       s0 = A :: X
-     Solution #2:
-       s0 = B :: X
-     Solution #3:
-       s0 = C :: X
-     Found 3 different solutions.
-   @
-
-Note that the result is properly typed as @X@ elements; these are not mere strings. So, in a 'getModel' scenario, the user can recover actual
-elements of the domain and program further with those values as usual.
--}
-
-{-# ANN module ("HLint: ignore Use import/export shortcut" :: String) #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- (The sbv library is hosted at <http://github.com/LeventErkok/sbv>.
+-- Comments, bug reports, and patches are always welcome.)
+--
+-- SBV: SMT Based Verification
+--
+-- Express properties about Haskell programs and automatically prove
+-- them using SMT solvers.
+--
+-- >>> prove $ \x -> x `shiftL` 2 .== 4 * (x :: SWord8)
+-- Q.E.D.
+--
+-- >>> prove $ \x -> x `shiftL` 2 .== 2 * (x :: SWord8)
+-- Falsifiable. Counter-example:
+--   s0 = 64 :: Word8
+--
+-- And similarly, 'sat' finds a satisfying instance. The types involved are:
+--
+-- @
+--     'prove' :: 'Provable' a => a -> 'IO' t'ThmResult'
+--     'sat'   :: 'Data.SBV.Provers.Satisfiable' a => a -> 'IO' t'SatResult'
+-- @
+--
+-- The classes 'Provable' and 'Data.SBV.Provers.Satisfiable' come with instances for n-ary predicates, for arbitrary n.
+-- The predicates are just regular Haskell functions over symbolic types listed below.
+-- Functions for checking satisfiability ('sat' and 'allSat') are also
+-- provided.
+--
+-- __Symbolic Types__
+--
+-- The sbv library introduces the following symbolic types:
+--
+--   * 'SBool': Symbolic Booleans (bits).
+--
+--   * 'SWord8', 'SWord16', 'SWord32', 'SWord64': Symbolic Words (unsigned).
+--
+--   * 'SInt8',  'SInt16',  'SInt32',  'SInt64': Symbolic Ints (signed).
+--
+--   * 'SWord' @n@: Generalized symbolic words of arbitrary bit-size.
+--
+--   * 'SInt' @n@: Generalized symbolic ints of arbitrary bit-size.
+--
+--   * 'SInteger': Unbounded signed integers.
+--
+--   * 'SReal': Algebraic-real numbers.
+--
+--   * 'SFloat': IEEE-754 single-precision floating point values.
+--
+--   * 'SDouble': IEEE-754 double-precision floating point values.
+--
+--   * 'SRational': Rationals. (Ratio of two symbolic integers.)
+--
+--   * 'SFloatingPoint': Generalized IEEE-754 floating point values, with user specified exponent and
+--   mantissa widths.
+--
+--   * 'SChar', 'SString', 'RegExp': Characters, strings and regular expressions.
+--
+--   * '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': Arrays of symbolic values.
+--
+--   * Symbolic polynomials over GF(2^n), polynomial arithmetic, and CRCs.
+--
+--   * Uninterpreted constants and functions over symbolic values, with user
+--     defined SMT-Lib axioms.
+--
+--   * Uninterpreted sorts, and proofs over such sorts, potentially with axioms.
+--
+--   *  Algebraic data types, including recursive fields..
+--
+--   * Ability to define SMTLib functions, generated directly from Haskell versions,
+--     including support for recursive and mutually recursive functions.
+--
+--   * Express quantified formulas (both universals and existentials, including
+--     alternating quantifiers), covering first-order logic.
+--
+--   * 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')
+-- and 'Ord' ('OrdSymbolic'), along with several other custom classes for simplifying
+-- programming with symbolic values. The framework takes full advantage of Haskell's type
+-- inference to avoid many common mistakes.
+--
+-- Furthermore, predicates (i.e., functions that return 'SBool') built out of
+-- these types can also be:
+--
+--   * proven correct via an external SMT solver (the 'prove' function)
+--
+--   * checked for satisfiability (the 'sat', 'allSat' functions)
+--
+--   * used in synthesis (the `sat` function with existentials)
+--
+--   * quick-checked
+--
+-- If a predicate is not valid, 'prove' will return a counterexample: An
+-- assignment to inputs such that the predicate fails. The 'sat' function will
+-- return a satisfying assignment, if there is one. The 'allSat' function returns
+-- all satisfying assignments.
+--
+--
+-- __Solvers__
+--
+-- The sbv library uses third-party SMT solvers via the standard SMT-Lib interface:
+-- <https://smt-lib.org>
+--
+-- The SBV library is designed to work with any SMT-Lib compliant SMT-solver.
+-- Currently, we support the following SMT-Solvers out-of-the box:
+--
+--   * ABC from University of Berkeley: <http://www.eecs.berkeley.edu/~alanmi/abc/>
+--
+--   * CVC4, and CVC5 from Stanford University and the University of Iowa. <https://cvc4.github.io/> and <https://cvc5.github.io>
+--
+--   * Boolector from Johannes Kepler University: <https://boolector.github.io> and its successor Bitwuzla from Stanford
+--     university: <https://bitwuzla.github.io>
+--
+--   * MathSAT from Fondazione Bruno Kessler and DISI-University of Trento: <http://mathsat.fbk.eu/>
+--
+--   * Yices from SRI: <http://github.com/SRI-CSL/yices2>
+--
+--   * DReal from CMU: <http://dreal.github.io/>
+--
+--   * OpenSMT from Università della Svizzera italiana <https://verify.inf.usi.ch/opensmt>
+--
+--   * Z3 from Microsoft: <http://github.com/Z3Prover/z3/wiki>
+--
+-- SBV requires recent versions of these solvers; please see the file
+-- @SMTSolverVersions.md@ in the source distribution for specifics.
+--
+-- SBV also allows calling these solvers in parallel, either getting results from multiple solvers
+-- or returning the fastest one. (See 'proveWithAll', 'proveWithAny', etc.)
+--
+-- Support for other compliant solvers can be added relatively easily, please
+-- get in touch if there is a solver you'd like to see included.
+--
+--
+-- __TP: Semi-automated theorem proving__
+--
+-- While SMT solvers are quite powerful, there is a certain class of problems that they are just not well suited for. In particular, SMT
+-- solvers are not good at proofs that require induction, or those that require complex chains of reasoning. Induction is necessary to reason about
+-- any recursive algorithm, and most such proofs require carefully constructed equational steps.
+--
+-- SBV allows for a style of semi-automated theorem proving, called TP, which can be used to construct such proofs.
+-- The documentation includes example proofs for many list functions, and even inductive proofs for
+-- the familiar insertion, merge, quick-sort algorithms, along with a proof that the square-root of 2 is irrational.
+-- While a proper theorem prover (such as Lean, Isabelle etc.) is a more appropriate choice for such proofs, with some
+-- guidance (and acceptance of a much larger trusted code base!), SBV can be used to establish correctness of various mathematical
+-- claims and algorithms that are usually beyond the scope of SMT solvers alone.
+-- See "Data.SBV.TP" for the API, and
+--
+--    - "Documentation.SBV.Examples.TP.BinarySearch"
+--    - "Documentation.SBV.Examples.TP.GCD"
+--    - "Documentation.SBV.Examples.TP.InsertionSort"
+--    - "Documentation.SBV.Examples.TP.MergeSort"
+--    - "Documentation.SBV.Examples.TP.QuickSort"
+--    - "Documentation.SBV.Examples.TP.Sqrt2IsIrrational"
+--    - "Documentation.SBV.Examples.TP.ShefferStroke"
+--    - "Documentation.SBV.Examples.TP.Lists"
+--
+-- for various proofs performed in this style.
+--
+-- Note that SBV's TP proofs are upto termination, i.e., if you axiomatize
+-- non-terminating behavior, then you can prove arbitrary results. SBV neither
+-- checks nor ensures termination, which is beyond its scope and capabilities.
+-- So, any TP proof should be considered true so long as all functions
+-- used in the property are terminating.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE DefaultSignatures     #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeApplications      #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV (
+  -- $progIntro
+
+  -- * Symbolic types
+
+  -- ** Booleans
+    SBool
+  -- *** Boolean values and functions
+  , sTrue, sFalse, sNot, (.&&), (.||), (.<+>), (.~&), (.~|), (.=>), (.<=>), fromBool, oneIf
+  -- *** Logical aggregations
+  , sAnd, sOr, sAny, sAll
+  -- ** Bit-vectors
+  -- *** Unsigned bit-vectors
+  , SWord8, SWord16, SWord32, SWord64, SWord, WordN
+  -- *** Signed bit-vectors
+  , SInt8, SInt16, SInt32, SInt64, SInt, IntN
+  -- *** Converting between fixed-size and arbitrary bit-vectors
+  , BVIsNonZero, FromSized, ToSized, fromSized, toSized
+  -- ** Unbounded integers
+  -- $unboundedLimitations
+  , SInteger
+  -- ** Floating point numbers
+  -- $floatingPoints
+  , ValidFloat, SFloat, SDouble
+  , SFloatingPoint, FloatingPoint
+  , SFPHalf, FPHalf
+  , SFPBFloat, FPBFloat
+  , SFPSingle, FPSingle
+  , SFPDouble, FPDouble
+  , SFPQuad, FPQuad
+  , fpFromInteger
+  -- ** Rationals
+  , SRational, (.%)
+  -- ** Algebraic reals
+  -- $algReals
+  , SReal, AlgReal(..), sRealToSInteger, algRealToRational, RealPoint(..), realPoint, RationalCV(..)
+  -- ** Characters, Strings and Regular Expressions
+  -- $strings
+  , SChar, SString
+  -- ** Symbolic lists
+  -- $lists
+  , SList, (.:)
+  -- ** Symbolic enumerators
+  , EnumSymbolic(..), sEnum
+  -- ** Symbolic case-expressions
+  , sCase, pCase
+  -- ** Tuples
+  -- $tuples
+  , SymTuple, STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+  -- ** Sets
+  , RCSet(..), SSet
+  -- * Arrays of symbolic values
+  , SArray, sArray, sArray_, sArrays, readArray, writeArray, lambdaArray, constArray, freeArray, listArray, ArrayModel(..)
+
+  -- * Creating symbolic values
+  -- ** Single value
+  -- $createSym
+  , sBool, sBool_
+  , sWord8, sWord8_, sWord16, sWord16_, sWord32, sWord32_, sWord64, sWord64_, sWord, sWord_
+  , sInt8,  sInt8_,  sInt16,  sInt16_,  sInt32,  sInt32_,  sInt64,  sInt64_, sInt, sInt_
+  , sInteger, sInteger_
+  , sReal, sReal_
+  , sRational, sRational_
+  , sFloat, sFloat_
+  , sDouble, sDouble_
+  , sFloatingPoint, sFloatingPoint_
+  , sFPHalf, sFPHalf_
+  , sFPBFloat, sFPBFloat_
+  , sFPSingle, sFPSingle_
+  , sFPDouble, sFPDouble_
+  , sFPQuad, sFPQuad_
+  , sChar, sChar_
+  , sString, sString_
+  , sList, sList_
+  , sTuple, sTuple_
+  , sSet, sSet_
+
+  -- * Symbolic 'Maybe'
+  , SMaybe, sMaybe, sMaybe_, sMaybes
+
+  -- * Symbolic 'Either'
+  , SEither, sEither, sEither_, sEithers
+
+  -- ** List of values
+  -- $createSyms
+  , sBools
+  , sWord8s, sWord16s, sWord32s, sWord64s, sWords
+  , sInt8s,  sInt16s,  sInt32s,  sInt64s, sInts
+  , sIntegers
+  , sReals
+  , sRationals
+  , sFloats
+  , sDoubles
+  , sFloatingPoints
+  , sFPHalfs
+  , sFPBFloats
+  , sFPSingles
+  , sFPDoubles
+  , sFPQuads
+  , sChars
+  , sStrings
+  , sLists
+  , sTuples
+  , sSets
+
+  -- * Symbolic Equality and Comparisons
+  -- $distinctNote
+  , EqSymbolic(..), OrdSymbolic(..), Zero(..), MeasureOf, Equality(..)
+  -- * Conditionals: Mergeable values
+  , Mergeable(..), ite, iteLazy
+
+  -- * Symbolic integral numbers
+  , SIntegral
+  -- * Division and Modulus
+  , SDivisible(..)
+  -- $euclidianNote
+  , sEDivMod, sEDiv, sEMod, sDivides
+  -- * Bit-vector operations
+  -- ** Conversions
+  , sFromIntegral
+  -- ** Shifts and rotates
+  -- $shiftRotate
+  , sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight
+  -- ** Finite bit-vector operations
+  , SFiniteBits(..)
+  -- ** Splitting, joining, and extending bit-vectors
+  , bvExtract, (#), zeroExtend, signExtend, bvDrop, bvTake, ByteConverter(..)
+  -- ** Exponentiation
+  , (.^)
+  -- * IEEE-floating point numbers
+  , IEEEFloating(..), RoundingMode(..), SRoundingMode, nan, infinity, sNaN, sInfinity
+  -- ** Rounding modes
+  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero, sRNE, sRNA, sRTP, sRTN, sRTZ
+  -- ** Conversion to/from floats
+  -- $conversionNote
+  , IEEEFloatConvertible(..)
+
+  -- ** Bit-pattern conversions
+  , sFloatAsSWord32,       sWord32AsSFloat
+  , sDoubleAsSWord64,      sWord64AsSDouble
+  , sFloatingPointAsSWord, sWordAsSFloatingPoint
+
+  -- ** Extracting bit patterns from floats
+  , blastSFloat
+  , blastSDouble
+  , blastSFloatingPoint
+
+  -- ** Showing values in detail
+  , crack
+
+  -- * Symbolic data types
+  -- $symbolicADT
+  , mkSymbolic
+
+  -- * Stopping unrolling: Defined functions
+  , SMTDefinable(..)
+  , smtFunction
+  , smtFunctionWithMeasure
+  , smtFunctionWithContract
+  , smtProductiveFunction
+  , smtFunctionNoTermination
+  , ContractOf, MeasureHelper(..)
+  , smtHOFunction, smtHOFunctionWithMeasure, Closure(..), registerType
+
+  -- * Special relations
+  -- $specialRels
+  , Relation, isPartialOrder, isLinearOrder, isTreeOrder, isPiecewiseLinearOrder, mkTransitiveClosure
+
+  -- * Properties, proofs, and satisfiability
+  -- $proveIntro
+  -- $multiIntro
+  , Predicate, ConstraintSet, Provable, Satisfiable
+  , prove, proveWith
+  , dprove, dproveWith
+  , sat, satWith
+  , dsat, dsatWith
+  , allSat, allSatWith
+  , isVacuousProof, isVacuousProofWith
+  , isTheorem, isTheoremWith, isSatisfiable, isSatisfiableWith
+  , proveWithAny, proveWithAll, proveConcurrentWithAny, proveConcurrentWithAll
+  , satWithAny,   satWithAll,   satConcurrentWithAny,   satConcurrentWithAll
+  , generateSMTBenchmarkSat, generateSMTBenchmarkProof
+  , solve
+  -- ** Partitioning result space
+  -- $partitionIntro
+  , allSatPartition
+
+  -- * Constraints and Quantifiers
+  -- $constrainIntro
+  -- ** General constraints
+  -- $generalConstraints
+  , constrain, softConstrain
+
+  -- ** Quantified constraints, quantifier elimination, and skolemization
+  -- $quantifiers
+  , QuantifiedBool, quantifiedBool, Forall(..), Exists(..), ExistsUnique(..), ForallN(..), ExistsN(..), QNot(..), Skolemize(..)
+
+  -- ** Constraint Vacuity
+  -- $constraintVacuity
+
+  -- ** Named constraints and attributes
+  -- $namedConstraints
+  , namedConstraint, constrainWithAttribute
+
+  -- ** Unsat cores
+  -- $unsatCores
+
+  -- ** Cardinality constraints
+  -- $cardIntro
+  , pbAtMost, pbAtLeast, pbExactly, pbLe, pbGe, pbEq, pbMutexed, pbStronglyMutexed
+
+  -- * Checking safety
+  -- $safeIntro
+  , sAssert, isSafe, SExecutable, sName, safe, safeWith
+
+  -- * Quick-checking
+  , sbvQuickCheck
+
+  -- * Optimization
+  -- $optiIntro
+  , optimize, optimizeWith
+  , optLexicographic, optLexicographicWith
+  , optPareto, optParetoWith
+  , optIndependent, optIndependentWith
+
+  -- ** Multiple optimization goals
+  -- $multiOpt
+  , OptimizeStyle(..)
+  -- ** Objectives and Metrics
+  , Objective(..)
+  , Metric(..), minimize, maximize
+  -- ** Soft assertions
+  -- $softAssertions
+  , assertWithPenalty , Penalty(..)
+  -- ** Field extensions
+  -- | If an optimization results in an infinity/epsilon value, the returned t'CV' value will be in the corresponding extension field.
+  , ExtCV(..), GeneralizedCV(..)
+
+  -- * Model extraction
+  -- $modelExtraction
+
+  -- ** Inspecting proof results
+  -- $resultTypes
+  , ThmResult(..), SatResult(..), AllSatResult(..), SafeResult(..), OptimizeResult(..), SMTResult(..), SMTReasonUnknown(..)
+
+  -- ** Observing expressions
+  -- $observeInternal
+  , observe, observeIf, sObserve
+
+  -- ** Programmable model extraction
+  -- $programmableExtraction
+  , Modelable(..), displayModels, extractModels
+  , getModelDictionaries, getModelValues
+
+  -- * SMT Interface
+  , SMTConfig(..), TPOptions(..), Timing(..), SMTLibVersion(..), Solver(..), SMTSolver(..)
+  -- ** Controlling verbosity
+  -- $verbosity
+
+  -- ** Solvers
+  , boolector, bitwuzla, cvc4, cvc5, yices, dReal, z3, mathSAT, abc, openSMT
+  -- ** Configurations
+  , defaultSolverConfig, defaultSMTCfg, defaultDeltaSMTCfg, sbvCheckSolverInstallation, getAvailableSolvers
+  , setLogic, Logic(..), setOption, setInfo, setTimeOut
+  -- ** SBV exceptions
+  , SBVException(..)
+
+  -- * Abstract SBV type
+  , SBV, HasKind(..), Kind(..)
+  , SymVal, free, free_, mkFreeVars, symbolic, symbolics, literal, unliteral, fromCV
+  , isConcrete, isSymbolic, isConcretely, mkSymVal
+  , MonadSymbolic(..), Symbolic, SymbolicT, label, output, runSMT, runSMTWith
+  , some
+
+  -- * Queriable values
+  , Queriable(..), freshVar, freshVar_
+
+  -- * Module exports
+  -- $moduleExportIntro
+
+  , module Data.Bits
+  , module Data.Word
+  , module Data.Int
+  , module Data.Ratio
+  ) where
+
+import Control.Monad       (unless)
+import Control.Monad.Trans (MonadIO)
+
+import qualified Data.Text as T
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Data       hiding (free, free_, mkFreeVars,
+                                        output, symbolic, symbolics, mkSymVal,
+                                        bvExtract, bvDrop, bvTake, (#))
+import Data.SBV.Core.Model      hiding (assertWithPenalty, minimize, maximize,
+                                        solve, sBool, sBool_, sBools, sChar, sChar_, sChars,
+                                        sDouble, sDouble_, sDoubles, sFloat, sFloat_, sFloats,
+                                        sFloatingPoint, sFloatingPoint_, sFloatingPoints,
+                                        sFPHalf, sFPHalf_, sFPHalfs, sFPBFloat, sFPBFloat_, sFPBFloats, sFPSingle, sFPSingle_, sFPSingles,
+                                        sFPDouble, sFPDouble_, sFPDoubles, sFPQuad, sFPQuad_, sFPQuads,
+                                        sInt8, sInt8_, sInt8s, sInt16, sInt16_, sInt16s, sInt32, sInt32_, sInt32s,
+                                        sInt64, sInt64_, sInt64s, sInteger, sInteger_, sIntegers,
+                                        sWord, sWords, sWord_, sInt, sInts, sInt_,
+                                        sList, sList_, sLists, sTuple, sTuple_, sTuples,
+                                        sReal, sReal_, sReals, sString, sString_, sStrings,
+                                        sRational, sRational_, sRationals,
+                                        sWord8, sWord8_, sWord8s, sWord16, sWord16_, sWord16s,
+                                        sWord32, sWord32_, sWord32s, sWord64, sWord64_, sWord64s,
+                                        sSet, sSet_, sSets,
+                                        sArray, sArray_, sArrays,
+                                        sBarrelRotateLeft, sBarrelRotateRight, zeroExtend, signExtend, sObserve)
+
+import qualified Data.SBV.Core.Model as M  (sBarrelRotateLeft, sBarrelRotateRight, zeroExtend, signExtend)
+import qualified Data.SBV.Core.Data  as CD (bvExtract, (#), bvDrop, bvTake)
+
+import Data.SBV.Core.Kind
+
+import Data.SBV.Core.SizedFloats
+
+import Data.SBV.Maybe hiding (map)
+import Data.SBV.Either
+
+import Data.SBV.Core.Floating
+import Data.SBV.Core.Symbolic   ( MonadSymbolic(..), SymbolicT, registerKind
+                                , ProgInfo(..), rProgInfo, SpecialRelOp(..), UICodeKind(UINone)
+                                , getRootState, UIName(UIGiven)
+                                )
+
+import Data.SBV.Provers.Prover hiding (prove, proveWith, sat, satWith, allSat,
+                                       dsat, dsatWith, dprove, dproveWith,
+                                       allSatWith, optimize, optimizeWith,
+                                       isVacuousProof, isVacuousProofWith,
+                                       isTheorem, isTheoremWith, isSatisfiable,
+                                       isSatisfiableWith, runSMT, runSMTWith,
+                                       sName, safe, safeWith)
+
+import Data.IORef (modifyIORef', readIORef)
+
+import Data.SBV.Client
+import Data.SBV.Client.BaseIO
+
+import Data.SBV.Utils.TDiff (Timing(..))
+
+import Data.Bits
+import Data.Int
+import Data.Ratio
+import Data.Word
+
+import Data.SBV.SMT.Utils (SBVException(..))
+
+import Data.SBV.Control.Types (SMTReasonUnknown(..), Logic(..))
+import Data.SBV.Control.Utils (getValue, freshVar, freshVar_)
+
+import qualified Data.SBV.Utils.CrackNum as CN
+
+import Data.Proxy (Proxy(..))
+import Data.Kind  (Type)
+import GHC.TypeLits (KnownNat, type (<=), type (+), type (-))
+
+import Data.Char (isSpace, isPunctuation)
+import Data.SBV.List (EnumSymbolic(..))
+import Data.SBV.SEnum (sEnum)
+import Data.SBV.SCase (sCase, pCase)
+
+import Data.SBV.Rational
+
+#ifdef DOCTEST
+--- $setup
+--- >>> :set -XDataKinds -XFlexibleContexts -XTypeApplications -XRankNTypes
+--- >>> import Data.Proxy
+#endif
+
+-- | Show a value in detailed (cracked) form, if possible.
+-- This makes most sense with numbers, and especially floating-point types.
+crack :: Bool -> SBV a -> String
+crack verb (SBV (SVal _ (Left cv))) | Just s <- CN.crackNum cv verb Nothing = s
+crack _    (SBV sv)                                                         = show sv
+
+-- Haddock section documentation
+{- $progIntro
+The SBV library is really two things:
+
+  * A framework for writing symbolic programs in Haskell, i.e., programs operating on
+    symbolic values along with the usual concrete counterparts.
+
+  * A framework for proving properties of such programs using SMT solvers.
+
+The programming goal of SBV is to provide a /seamless/ experience, i.e., let people program
+in the usual Haskell style without distractions of symbolic coding. While Haskell helps
+in some aspects (the 'Num' and 'Bits' classes simplify coding), it makes life harder
+in others. For instance, @if-then-else@ only takes 'Bool' as a test in Haskell, and
+comparisons ('>' etc.) only return 'Bool's. Clearly we would like these values to be
+symbolic (i.e., 'SBool'), thus stopping us from using some native Haskell constructs.
+When symbolic versions of operators are needed, they are typically obtained by prepending a dot,
+for instance '==' becomes '.=='. Care has been taken to make the transition painless. In
+particular, any Haskell program you build out of symbolic components is fully concretely
+executable within Haskell, without the need for any custom interpreters. (They are truly
+Haskell programs, not AST's built out of pieces of syntax.) This provides for an integrated
+feel of the system, one of the original design goals for SBV.
+
+Incremental query mode: SBV provides a wide variety of ways to utilize SMT-solvers, without requiring the user to
+deal with the solvers themselves. While this mode is convenient, advanced users might need
+access to the underlying solver at a lower level. For such use cases, SBV allows
+users to have an interactive session: The user can issue commands to the solver, inspect
+the values/results, and formulate new constraints. This advanced feature is available through
+the "Data.SBV.Control" module, where most SMTLib features are made available via a typed-API.
+-}
+
+{- $proveIntro
+The SBV library provides a "push-button" verification system via automated SMT solving. The
+design goal is to let SMT solvers be used without any knowledge of how SMT solvers work
+or how different logics operate. The details are hidden behind the SBV framework, providing
+Haskell programmers with a clean API that is unencumbered by the details of individual solvers.
+To that end, we use the SMT-Lib standard (<https://smt-lib.org>)
+to communicate with arbitrary SMT solvers.
+-}
+
+{- $multiIntro
+=== Using multiple solvers
+On a multi-core machine, it might be desirable to try a given property using multiple SMT solvers,
+using parallel threads. Even with machines with single-cores, threading can be helpful if you
+want to try out multiple-solvers but do not know which one would work the best
+for the problem at hand ahead of time.
+
+SBV allows proving/satisfiability-checking with multiple
+backends at the same time. Each function comes in two variants, one that
+returns the results from all solvers, the other that returns the fastest one.
+
+The @All@ variants, (i.e., 'proveWithAll', 'satWithAll') run all solvers and
+return all the results. SBV internally makes sure that the result is lazily generated; so,
+the order of solvers given does not matter. In other words, the order of results will follow
+the order of the solvers as they finish, not as given by the user. These variants are useful when you
+want to make sure multiple-solvers agree (or disagree!) on a given problem.
+
+The @Any@ variants, (i.e., 'proveWithAny', 'satWithAny') will run all the solvers
+in parallel, and return the results of the first one finishing. The other threads will then be killed. These variants
+are useful when you do not care if the solvers produce the same result, but rather want to get the
+solution as quickly as possible, taking advantage of modern many-core machines.
+
+Note that the function 'getAvailableSolvers' will return all the installed solvers, which can be
+used as the first argument to all these functions, if you simply want to try all available solvers on a machine.
+-}
+
+{- $safeIntro
+
+The 'sAssert' function allows users to introduce invariants to make sure
+certain properties hold at all times. This is another mechanism to provide further documentation/contract info
+into SBV code. The functions 'safe' and 'safeWith' can be used to statically discharge these proof assumptions.
+If a violation is found, SBV will print a model showing which inputs lead to the invariant being violated.
+
+Here's a simple example. Let's assume we have a function that does subtraction, and requires its
+first argument to be larger than the second:
+
+>>> let sub x y = sAssert Nothing "sub: x >= y must hold!" (x .>= y) (x - y)
+
+Clearly, this function is not safe, as there's nothing that stops us from passing it a larger second argument.
+We can use 'safe' to statically see if such a violation is possible before we use this function elsewhere.
+
+>>> safe (sub :: SInt8 -> SInt8 -> SInt8)
+[sub: x >= y must hold!: Violated. Model:
+  s0 = 0 :: Int8
+  s1 = 1 :: Int8]
+
+What happens if we make sure to arrange for this invariant? Consider this version:
+
+>>> let safeSub x y = ite (x .>= y) (sub x y) 0
+
+Clearly, @safeSub@ must be safe. And indeed, SBV can prove that:
+
+>>> safe (safeSub :: SInt8 -> SInt8 -> SInt8)
+[sub: x >= y must hold!: No violations detected]
+
+Note how we used @sub@ and @safeSub@ polymorphically. We only need to monomorphise our types when a proof
+attempt is done, as we did in the 'safe' calls.
+
+If required, the user can pass a @CallStack@ through the first argument to 'sAssert', which will be used
+by SBV to print a diagnostic info to pinpoint the failure.
+
+Also see "Documentation.SBV.Examples.Misc.NoDiv0" for the classic div-by-zero example.
+-}
+
+
+{- $optiIntro
+  SBV can optimize metric functions, i.e., those that generate both bounded @SIntN@, @SWordN@, and unbounded 'SInteger'
+  types, along with those produce 'SReal's. That is, it can find models satisfying all the constraints while minimizing
+  or maximizing user given metrics. Currently, optimization requires the use of the z3 SMT solver as the backend,
+  and a good review of these features is given
+  in this paper: <http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-scss2014.pdf>.
+
+  Goals can be lexicographically (default), independently, or pareto-front optimized. The relevant functions are:
+
+      * 'minimize': Minimize a given arithmetic goal
+      * 'maximize': Maximize a given arithmetic goal
+
+  Goals can be optimized at a regular or an extended value: An extended value is either positive or negative infinity
+  (for unbounded integers and reals) or positive or negative epsilon differential from a real value (for reals).
+
+  For instance, a call of the form
+
+       @ 'minimize' "name-of-goal" $ x + 2*y @
+
+  minimizes the arithmetic goal @x+2*y@, where @x@ and @y@ can be signed\/unsigned bit-vectors, reals,
+  or integers.
+
+== A simple example
+
+  Here's an optimization example in action:
+
+  >>> optimize Lexicographic $ \x y -> minimize "goal" (x+2*(y::SInteger))
+  Optimal in an extension field:
+    goal = -oo :: Integer
+
+  We will describe the role of the constructor 'Lexicographic' shortly.
+
+  Of course, this becomes more useful when the result is not in an extension field:
+
+>>> :{
+    optimize Lexicographic $ do
+                  x <- sInteger "x"
+                  y <- sInteger "y"
+                  constrain $ x .> 0
+                  constrain $ x .< 6
+                  constrain $ y .> 2
+                  constrain $ y .< 12
+                  minimize "goal" $ x + 2 * y
+    :}
+Optimal model:
+  x    = 1 :: Integer
+  y    = 3 :: Integer
+  goal = 7 :: Integer
+
+  As usual, the programmatic API can be used to extract the values of objectives and model-values ('getModelObjectives',
+  'getModelAssignment', etc.) to access these values and program with them further.
+
+  The following examples illustrate the use of basic optimization routines:
+
+     * "Documentation.SBV.Examples.Optimization.LinearOpt": Simple linear-optimization example.
+     * "Documentation.SBV.Examples.Optimization.Production": Scheduling machines in a shop
+     * "Documentation.SBV.Examples.Optimization.VM": Scheduling virtual-machines in a data-center
+-}
+
+{- $multiOpt
+
+  Multiple goals can be specified, using the same syntax. In this case, the user gets to pick what style of
+  optimization to perform, by passing the relevant 'OptimizeStyle' as the first argument to 'optimize'.
+
+    * ['Lexicographic']. The solver will optimize the goals in the given order, optimizing
+      the latter ones under the model that optimizes the previous ones.
+
+    * ['Independent']. The solver will optimize the goals independently of each other. In this case the user will
+      be presented a model for each goal given.
+
+    * ['Pareto']. Finally, the user can query for pareto-fronts. A pareto front is an model such that no goal can be made
+      "better" without making some other goal "worse."
+
+      Pareto fronts only make sense when the objectives are bounded. If there are unbounded objective values, then the
+      backend solver can loop infinitely. (This is what z3 does currently.) If you are not sure the objectives are
+      bounded, you should first use 'Independent' mode to ensure the objectives are bounded, and then switch to
+      pareto-mode to extract them further.
+
+      The optional number argument to 'Pareto' specifies the maximum number of pareto-fronts the user is asking
+      to get. If 'Nothing', SBV will query for all pareto-fronts. Note that pareto-fronts can be really large,
+      so if 'Nothing' is used, there is a potential for waiting indefinitely for the SBV-solver interaction to finish. (If
+      you suspect this might be the case, run in 'verbose' mode to see the interaction and put a limiting factor
+      appropriately.)
+-}
+
+{- $softAssertions
+
+  Related to optimization, SBV implements soft-asserts via 'assertWithPenalty' calls. A soft assertion
+  is a hint to the SMT solver that we would like a particular condition to hold if **possible*.
+  That is, if there is a solution satisfying it, then we would like it to hold, but it can be violated
+  if there is no way to satisfy it. Each soft-assertion can be associated with a numeric penalty for
+  not satisfying it, hence turning it into an optimization problem.
+
+  Note that 'assertWithPenalty' works well with optimization goals ('minimize'/'maximize' etc.),
+  and are most useful when we are optimizing a metric and thus some of the constraints
+  can be relaxed with a penalty to obtain a good solution. Again
+  see <http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-scss2014.pdf>
+  for a good overview of the features in Z3 that SBV is providing the bridge for.
+
+  A soft assertion can be specified in one of the following three main ways:
+
+       @
+         'assertWithPenalty' "bounded_x" (x .< 5) 'DefaultPenalty'
+         'assertWithPenalty' "bounded_x" (x .< 5) $ v'Penalty' 2.3 Nothing
+         'assertWithPenalty' "bounded_x" (x .< 5) $ v'Penalty' 4.7 (Just "group-1") @
+
+  In the first form, we are saying that the constraint @x .< 5@ must be satisfied, if possible,
+  but if this constraint can not be satisfied to find a model, it can be violated with the default penalty of 1.
+
+  In the second case, we are associating a penalty value of @2.3@.
+
+  Finally in the third case, we are also associating this constraint with a group. The group
+  name is only needed if we have classes of soft-constraints that should be considered together.
+
+-}
+
+{- $modelExtraction
+The default 'Show' instances for prover calls provide all the counter-example information in a
+human-readable form and should be sufficient for most casual uses of sbv. However, tools built
+on top of sbv will inevitably need to look into the constructed models more deeply, programmatically
+extracting their results and performing actions based on them. The API provided in this section
+aims at simplifying this task.
+-}
+
+{- $resultTypes
+t'ThmResult', t'SatResult', and t'AllSatResult' are simple newtype wrappers over t'SMTResult'. Their
+main purpose is so that we can provide custom 'Show' instances to print results accordingly.
+-}
+
+{- $programmableExtraction
+While default 'Show' instances are sufficient for most use cases, it is sometimes desirable (especially
+for library construction) that the SMT-models are reinterpreted in terms of domain types. Programmable
+extraction allows getting arbitrarily typed models out of SMT models.
+-}
+
+{- $moduleExportIntro
+The SBV library exports the following modules wholesale, as user programs will have to import these
+modules to make any sensible use of the SBV functionality.
+-}
+
+{- $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. We provide both the named and anonymous
+versions, latter with the underscore suffix.
+-}
+
+{- $createSyms
+These functions simplify declaring a sequence symbolic variables of various types. Strictly speaking, they are just synonyms
+for 'mapM' 'free' (specialized at the given type), but they might be easier to use.
+-}
+
+{- $unboundedLimitations
+The SBV library supports unbounded signed integers with the type 'SInteger', which are not subject to
+overflow/underflow as it is the case with the bounded types, such as 'SWord8', 'SInt16', etc. However,
+some bit-vector based operations are /not/ supported for the 'SInteger' type while in the verification mode. That
+is, you can use these operations on 'SInteger' values during normal programming/simulation.
+but the SMT translation will not support these operations since their corresponding operations are not supported in SMT-Lib.
+Note that this should rarely be a problem in practice, as these operations are mostly meaningful on fixed-size
+bit-vectors. The operations that are restricted to bounded word/int sizes are:
+
+   * Rotations and shifts: 'rotateL', 'rotateR', 'shiftL', 'shiftR'
+
+   * Bitwise logical ops: '.&.', '.|.', 'xor', 'complement'
+
+   * Extraction and concatenation: 'bvExtract', '#', 'zeroExtend', 'signExtend', 'bvDrop', and 'bvTake'
+
+Usual arithmetic ('Prelude.+', 'Prelude.-', '*', 'sQuotRem', 'sQuot', 'sRem', 'sDivMod', 'sDiv', 'sMod') and logical operations ('.<', '.<=', '.>', '.>=', '.==', './=') operations are
+supported for 'SInteger' fully, both in programming and verification modes.
+-}
+
+{- $algReals
+Algebraic reals are roots of single-variable polynomials with rational coefficients. (See
+<http://en.wikipedia.org/wiki/Algebraic_number>.) Note that algebraic reals are infinite
+precision numbers, but they do not cover all /real/ numbers. (In particular, they cannot
+represent transcendentals.) Some irrational numbers are algebraic (such as @sqrt 2@), while
+others are not (such as pi and e).
+
+SBV can deal with real numbers just fine, since the theory of reals is decidable. (See
+<https://smt-lib.org/theories-Reals.shtml>.) In addition, by leveraging backend
+solver capabilities, SBV can also represent and solve non-linear equations involving real-variables.
+(For instance, the Z3 SMT solver, supports polynomial constraints on reals starting with v4.0.)
+-}
+
+{- $floatingPoints
+Floating point numbers are defined by the IEEE-754 standard; and correspond to Haskell's
+'Float' and 'Double' types. For SMT support with floating-point numbers, see the paper
+by Rummer and Wahl: <http://www.philipp.ruemmer.org/publications/smt-fpa.pdf>.
+-}
+
+{- $strings
+Support for characters, strings, and regular expressions (initial version contributed by Joel Burget)
+adds support for QF_S logic, described here: <https://smt-lib.org/theories-UnicodeStrings.shtml>
+
+See "Data.SBV.Char", "Data.SBV.List", "Data.SBV.RegExp" for related functions.
+-}
+
+{- $lists
+Support for symbolic lists (initial version contributed by Joel Burget) adds support for sequence support.
+
+See "Data.SBV.List" for related functions.
+-}
+
+{- $tuples
+Tuples can be used as symbolic values. This is useful in combination with lists, for example @SBV [(Integer, String)]@ is a valid type. These types can be arbitrarily nested, eg @SBV [(Integer, [(Char, (Integer, String))])]@. Instances of upto 8-tuples are provided.
+-}
+
+{- $shiftRotate
+Symbolic words (both signed and unsigned) are an instance of Haskell's 'Bits' class, so regular
+bitwise operations are automatically available for them. Shifts and rotates, however, require
+specialized type-signatures since Haskell insists on an 'Int' second argument for them.
+-}
+
+{- $partitionIntro
+The function 'allSatPartition' allows one to restrict the results returned by calls to 'Data.SBV.allSat'.
+In certain cases, we might consider certain models to be "equivalent," i.e., we might want to
+create equivalence classes over the search space when it comes to what we consider all satisfying
+solutions. In these cases, we can use 'allSatPartition' to tell SBV what classes of solutions to consider
+as unique. Consider:
+
+>>> :{
+allSat $ do
+   x <- sInteger "x"
+   y <- sInteger "y"
+   allSatPartition "p1" $ x .>= 0
+   allSatPartition "p2" $ y .>= 0
+:}
+Solution #1:
+  x  =    -1 :: Integer
+  y  =     0 :: Integer
+  p1 = False :: Bool
+  p2 =  True :: Bool
+Solution #2:
+  x  =    0 :: Integer
+  y  =    0 :: Integer
+  p1 = True :: Bool
+  p2 = True :: Bool
+Solution #3:
+  x  =     0 :: Integer
+  y  =    -1 :: Integer
+  p1 =  True :: Bool
+  p2 = False :: Bool
+Solution #4:
+  x  =    -1 :: Integer
+  y  =    -1 :: Integer
+  p1 = False :: Bool
+  p2 = False :: Bool
+Found 4 different solutions.
+
+Without the call to 'allSatPartition' the above example, 'allSat' would return all possible combinations of @x@ and @y@ subject to the constraints. (Since we have none here,
+the call would try to enumerate the infinite set of all integer tuples!) But 'allSatPartition' allows us to restrict our attention to the examples that satisfy the partitioning
+constraints. The first argument to 'allSatPartition' is simply a name, for diagnostic purposes. Note that the conditions given by 'allSatPartition' are /not/ imposed on the search
+space at all: They're only used when we construct the search space. In the above example, we pick one example from each quadrant. Furthermore, while it is typical to pass
+a boolean as a partitioning argument, it is not required: Any expression is OK, whose value creates the equivalence class:
+
+>>> :{
+allSat $ do
+   x <- sInteger "x"
+   allSatPartition "p" $ x `sMod` 3
+:}
+Solution #1:
+  x = 2 :: Integer
+  p = 2 :: Integer
+Solution #2:
+  x = 1 :: Integer
+  p = 1 :: Integer
+Solution #3:
+  x = 0 :: Integer
+  p = 0 :: Integer
+Found 3 different solutions.
+
+In the above, we get three examples, as the expression @x mod 3@ can take only three different values.
+-}
+
+{- $constrainIntro
+A constraint is a means for restricting the input domain of a formula. Here's a simple
+example:
+
+@
+   do x <- 'free' \"x\"
+      y <- 'free' \"y\"
+      'constrain' $ x .> y
+      'constrain' $ x + y .>= 12
+      'constrain' $ y .>= 3
+      ...
+@
+
+The first constraint requires @x@ to be larger than @y@. The second one says that
+sum of @x@ and @y@ must be at least @12@, and the final one says that @y@ to be at least @3@.
+Constraints provide an easy way to assert additional properties on the input domain, right at the point of
+the introduction of variables.
+
+Note that the proper reading of a constraint
+depends on the context:
+
+  * In a 'sat' (or 'allSat') call: The constraint added is asserted
+    conjunctively. That is, the resulting satisfying model (if any) will
+    always satisfy all the constraints given.
+
+  * In a 'prove' call: In this case, the constraint acts as an implication.
+    The property is proved under the assumption that the constraint
+    holds. In other words, the constraint says that we only care about
+    the input space that satisfies the constraint.
+
+  * In a @quickCheck@ call: The constraint acts as a filter for @quickCheck@;
+    if the constraint does not hold, then the input value is considered to be irrelevant
+    and is skipped. Note that this is similar to 'prove', but is stronger: We do not
+    accept a test case to be valid just because the constraints fail on them, although
+    semantically the implication does hold. We simply skip that test case as a /bad/
+    test vector.
+
+  * In a 'Data.SBV.Tools.GenTest.genTest' call: Similar to @quickCheck@ and 'prove': If a constraint
+    does not hold, the input value is ignored and is not included in the test
+    set.
+-}
+
+{- $generalConstraints
+A good use case (in fact the motivating use case) for 'constrain' is attaching a
+constraint to a variable at the time of its creation.
+Also, the conjunctive semantics for 'sat' and the implicative
+semantics for 'prove' simplify programming by choosing the correct interpretation
+automatically. However, one should be aware of the semantic difference. For instance, in
+the presence of constraints, formulas that are /provable/ are not necessarily
+/satisfiable/. To wit, consider:
+
+ @
+    do x <- 'free' \"x\"
+       'constrain' $ x .< x
+       return $ x .< (x :: 'SWord8')
+ @
+
+This predicate is unsatisfiable since no element of 'SWord8' is less than itself. But
+it's (vacuously) true, since it excludes the entire domain of values, thus making the proof
+trivial. Hence, this predicate is provable, but is not satisfiable. To make sure the given
+constraints are not vacuous, the functions 'isVacuousProof' (and 'isVacuousProofWith') can be used.
+
+Also note that this semantics imply that test case generation ('Data.SBV.Tools.GenTest.genTest') and
+quick-check can take arbitrarily long in the presence of constraints, if the random input values generated
+rarely satisfy the constraints. (As an extreme case, consider @'constrain' 'sFalse'@.)
+-}
+
+{- $quantifiers
+You can write quantified formulas, and reason with them as in first-order logic. Here is a simple example:
+
+@
+    constrain $ \\(Forall x) (Exists y) -> y .> (x :: SInteger)
+@
+
+You can nest quantifiers as you wish, and the quantified parameters can be of arbitrary symbolic type.
+Additionally, you can convert such a quantified formula to a regular boolean, via a call to 'quantifiedBool'
+function, essentially performing quantifier elimination:
+
+@
+    other_condition .&& quantifiedBool (\\(Forall x) (Exists y) -> y .> (x :: SInteger))
+@
+
+Or you can prove/sat quantified formulas directly:
+
+@
+    prove $ \\(Forall x) (Exists y) -> y .> (x :: SInteger)
+@
+
+This facility makes quantifiers part of the regular SBV language, allowing them to be mixed/matched with all
+your other symbolic computations.  See the following files demonstrating reasoning with quantifiers:
+
+   * "Documentation.SBV.Examples.Puzzles.Birthday"
+   * "Documentation.SBV.Examples.Puzzles.KnightsAndKnaves"
+   * "Documentation.SBV.Examples.Puzzles.Rabbits"
+   * "Documentation.SBV.Examples.Misc.FirstOrderLogic"
+
+SBV also supports the constructors t'ExistsUnique' to create unique existentials, in addition
+to t'ForallN' and t'ExistsN' for creating multiple variables at the same time.
+
+In general, SBV will not display the values of quantified variables for a satisfying instance.
+For a satisfiability problem, you can apply skolemization manually to have these values
+computed by the backend solver. Note that skolemization will produce functions for
+existentials under universals, and SBV generally cannot translate function values back
+to Haskell, except in certain simple cases. However, for prefix existentials, the manual
+transformation can pay off. As an example, compare:
+
+>>> sat $ \(Exists x) (Forall y) -> x .<= (y :: SWord8)
+Satisfiable
+
+to:
+
+>>> sat $ do { x <- free "x"; pure (quantifiedBool (\(Forall y) -> x .<= (y :: SWord8))) }
+Satisfiable. Model:
+  x = 0 :: Word8
+
+where we have skolemized the top-level existential out, and received a witness value for it.
+-}
+
+{- $constraintVacuity
+
+When adding constraints, one has to be careful about
+making sure they are not inconsistent. The function 'isVacuousProof' can be used for this purpose.
+Here is an example. Consider the following predicate:
+
+    >>> let pred = do { x <- free "x"; constrain $ x .< x; return $ x .>= (5 :: SWord8) }
+
+This predicate asserts that all 8-bit values are larger than 5, subject to the constraint that the
+values considered satisfy @x .< x@, i.e., they are less than themselves. Since there are no values that
+satisfy this constraint, the proof will pass vacuously:
+
+    >>> prove pred
+    Q.E.D.
+
+We can use 'isVacuousProof' to make sure to see that the pass was vacuous:
+
+    >>> isVacuousProof pred
+    True
+
+While the above example is trivial, things can get complicated if there are multiple constraints with
+non-straightforward relations; so if constraints are used one should make sure to check the predicate
+is not vacuously true. Here's an example that is not vacuous:
+
+     >>> let pred' = do { x <- free "x"; constrain $ x .> 6; return $ x .>= (5 :: SWord8) }
+
+This time the proof passes as expected:
+
+     >>> prove pred'
+     Q.E.D.
+
+And the proof is not vacuous:
+
+     >>> isVacuousProof pred'
+     False
+-}
+
+{- $namedConstraints
+
+Constraints can be given names:
+
+  @ 'namedConstraint' "a is at least 5" $ a .>= 5@
+
+Similarly, arbitrary term attributes can also be associated:
+
+  @ 'constrainWithAttribute' [(":solver-specific-attribute", "value")] $ a .>= 5@
+
+Note that a 'namedConstraint' is equivalent to a 'constrainWithAttribute' call, setting the `":named"' attribute.
+-}
+
+{- $unsatCores
+Named constraints are useful when used in conjunction with 'Data.SBV.Control.getUnsatCore' function
+where the backend solver can be queried to obtain an unsat core in case the constraints are unsatisfiable.
+See 'Data.SBV.Control.getUnsatCore' for details and "Documentation.SBV.Examples.Queries.UnsatCore" for an example use case.
+-}
+
+{- $symbolicADT
+Users can introduce new uninterpreted sorts simply by defining an empty data-type in Haskell and registering it as such. The
+following example demonstrates:
+
+  @
+     data B
+     mkSymbolic [''B]
+  @
+
+This is all it takes to introduce @B@ as an uninterpreted sort in SBV, which makes the type @SBV B@ automagically become available as the type
+of symbolic values that ranges over @B@ values. Note that this will also introduce the type @SB@ into your environment, which is a synonym
+for @SBV B@.
+
+If the uninterpreted sort definition takes the form of an enumeration (i.e., a simple data type with all nullary constructors), then
+it will turn into an enumeration in SMTLib.  A simple example is:
+
+@
+    data X = A | B | C
+    mkSymbolic [''X]
+@
+
+Note the magic incantation @mkSymbolic [''X]@, requires the following extensions:
+@TemplateHaskell@, @TypeApplications@, and @FlexibleInstances@.
+Parametric data-types also require @ScopedTypeVariables@.
+
+SBV also supports good old ADT's as well, with fields. The support for this is similar, where SBV will create the
+corresponding datatype in a symbolic manner:
+
+@
+-- | A basic arithmetic expression type.
+data Expr = Num Integer
+          | Var String
+          | Add Expr Expr
+          | Mul Expr Expr
+          | Let String Expr Expr
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
+@
+
+These types can also be parameterized, per usual Haskell usage.
+
+We also support a symbolic case-expression quasi-quoter, allowing us to write:
+
+@
+eval :: SExpr -> SInteger
+eval = go []
+ where go :: SList (String, Integer) -> SExpr -> SInteger
+       go = smtFunction "eval"
+          $ \env expr -> [sCase| expr of
+                            Num i     -> i
+                            Var s     -> get env s
+                            Add l r   -> go env l + go env r
+                            Mul l r   -> go env l * go env r
+                            Let s e r -> go (tuple (s, go env e) SL..: env) r
+                         |]
+
+       get :: SList (String, Integer) -> SString -> SInteger
+       get = smtFunction "get"
+           $ \env s -> ite (SL.null env) 0
+                     $ let (k, v) = untuple (SL.head env)
+                       in ite (s .== k) v (get (SL.tail env) s)
+@
+
+which defines an interpreter for this data-type. Such definitions also come with an induction principle
+to perform TP based proofs on. These can be accessed using the 'Data.SBV.TP.inductiveLemma' function.
+
+The argument to @mkSymbolic@ is typically a list of types. The requirement is that if the types you pass on
+are mutually recursively defined, you should give them as a list. Otherwise, you can give them all together,
+or one at a time.
+-}
+
+{- $cardIntro
+A pseudo-boolean function (<http://en.wikipedia.org/wiki/Pseudo-Boolean_function>) is a
+function from booleans to reals, basically treating 'True' as @1@ and 'False' as @0@. They
+are typically expressed in polynomial form. Such functions can be used to express cardinality
+constraints, where we want to /count/ how many things satisfy a certain condition.
+
+One can code such constraints using regular SBV programming: Simply
+walk over the booleans and the corresponding coefficients, and assert the required relation.
+For instance:
+
+   > [b0, b1, b2, b3] `pbAtMost` 2
+
+is precisely equivalent to:
+
+   > sum (map (\b -> ite b 1 0) [b0, b1, b2, b3]) .<= 2
+
+and they both express that at most /two/ of @b0@, @b1@, @b2@, and @b3@ can be 'sTrue'.
+However, the equivalent forms give rise to long formulas and the cardinality constraint
+can get lost in the translation. The idea here is that if you use these functions instead, SBV will
+produce better translations to SMTLib for more efficient solving of cardinality constraints, assuming
+the backend solver supports them. Currently, only Z3 supports pseudo-booleans directly. For all other solvers,
+SBV will translate these to equivalent terms that do not require special functions.
+-}
+
+{- $verbosity
+
+SBV provides various levels of verbosity to aid in debugging, by using the t'SMTConfig' fields:
+
+  * ['verbose'] Print on stdout a shortened account of what is sent/received. This is specifically trimmed to reduce noise
+    and is good for quick debugging. The output is not supposed to be machine-readable.
+  * ['redirectVerbose'] Send the verbose output to a file. Note that you still have to set `verbose=True` for redirection to
+    take effect. Otherwise, the output is the same as what you would see in `verbose`.
+  * ['transcript'] Produce a file that is valid SMTLib2 format, containing everything sent and received. In particular, one can
+    directly feed this file to the SMT-solver outside of the SBV since it is machine-readable. This is good for offline analysis
+    situations, where you want to have a full account of what happened. For instance, it will print time-stamps at every interaction
+    point, so you can see how long each command took.
+-}
+
+{- $observeInternal
+
+The 'observe' command can be used to trace values of arbitrary expressions during a 'sat', 'prove', or perhaps more
+importantly, in a @quickCheck@ call with the 'sObserve' variant.. This is useful for, for instance, recording expected vs. obtained expressions
+as a symbolic program is executing.
+
+>>> :{
+prove $ do a1 <- free "i1"
+           a2 <- free "i2"
+           let spec, res :: SWord8
+               spec = a1 + a2
+               res  = ite (a1 .== 12 .&& a2 .== 22)   -- insert a malicious bug!
+                          1
+                          (a1 + a2)
+           return $ observe "Expected" spec .== observe "Result" res
+:}
+Falsifiable. Counter-example:
+  i1       = 12 :: Word8
+  i2       = 22 :: Word8
+  Expected = 34 :: Word8
+  Result   =  1 :: Word8
+
+The 'observeIf' variant allows the user to specify a boolean condition when the value is interesting to observe. Useful when
+you have lots of "debugging" points, but not all are of interest. Use the 'sObserve' variant when you are at the 'Symbolic'
+monad, which also supports quick-check applications.
+-}
+
+{- $distinctNote
+Symbolic equality provides the notion of what it means to be equal, similar to Haskell's 'Eq' class, except allowing comparison of
+symbolic values. The methods are '.==' and './=', returning 'SBool' results. We also provide a notion of strong equality ('.===' and './=='),
+which is useful for floating-point value comparisons as it deals more uniformly with @NaN@ and positive/negative zeros. Additionally, we
+provide 'distinct' that can be used to assert all elements of a list are different from each other, and 'distinctExcept' which is similar
+to 'distinct' but allows for certain values to be considered different. These latter two functions are useful in modeling a variety of
+puzzles and cardinality constraints:
+
+>>> prove $ \a -> distinctExcept [a, a] [0::SInteger] .<=> a .== 0
+Q.E.D.
+>>> prove $ \a b -> distinctExcept [a, b] [0::SWord8] .<=> (a .== b .=> a .== 0)
+Q.E.D.
+>>> prove $ \a b c d -> distinctExcept [a, b, c, d] [] .== distinct [a, b, c, (d::SInteger)]
+Q.E.D.
+-}
+
+{- $euclidianNote
+=== Euclidian division and modulus
+
+Euclidian division and modulus for integers differ from regular division modulus when
+the divisor is negative. It satisfies the following desirable property: For any @m@, @n@, we have:
+
+@
+  Given @m@, @n@, s.t., n /= 0
+  Let (q, r) = m `sEDivMod` n
+  Then: m = n * q + r
+   and 0 <= r <= |n| - 1
+@
+
+That is, the modulus is always positive.
+There's no standard Haskell function that performs this operation. The main reason to prefer this
+function is that SMT solvers can deal with them better.
+Compare:
+
+>>> sDivMod @SInteger 3 (-2)
+(-2 :: SInteger,-1 :: SInteger)
+>>> sEDivMod 3 (-2)
+(-1 :: SInteger,1 :: SInteger)
+>>> prove $ \x y -> y .> 0 .=> x `sDivMod` y .== x `sEDivMod` y
+Q.E.D.
+-}
+
+{- $conversionNote
+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. Similarly, 'toSFloatingPoint' converts to a generalized
+floating-point number with specified exponent and significand bit widths.
+
+Conversions from float: 'fromSFloat', 'fromSDouble', 'fromSFloatingPoint' 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 'Data.SBV.Core.Floating.fpIsNaN', 'Data.SBV.Core.Floating.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.
+
+Some examples to illustrate the behavior follows:
+
+>>> :{
+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 = RoundNearestTiesToAway :: RoundingMode
+  s1 =               22049281 :: Int32
+
+Note how we get a failure on `Int32`. The counter-example value is not representable exactly as a single precision float:
+
+>>> toRational (22049281 :: Float)
+22049280 % 1
+
+Note how the numerator is different, it is off by 1. This is hardly surprising, since floats become sparser as
+the magnitude increases to be able to cover all the integer values representable.
+
+>>> :{
+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 =    2305843026393563113 :: 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 (fromIntegral (2305843026393563113 :: Int64) :: Double)
+2305843026393563136 % 1
+
+In this case the numerator is off by 23.
+-}
+
+-- | An implementation of rotate-left, using a barrel shifter like design. Only works when both
+-- arguments are finite bit-vectors, 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 = M.sBarrelRotateLeft
+
+-- | 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 = M.sBarrelRotateRight
+
+-- | Extract a portion of bits to form a smaller bit-vector.
+--
+-- >>> prove $ \x -> bvExtract (Proxy @7) (Proxy @3) (x :: SWord 12) .== bvDrop (Proxy @4) (bvTake (Proxy @9) x)
+-- Q.E.D.
+bvExtract :: forall i j n bv proxy. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                                    , KnownNat i
+                                    , KnownNat j
+                                    , i + 1 <= n
+                                    , j <= i
+                                    , BVIsNonZero (i - j + 1)
+                                    ) => proxy i                -- ^ @i@: Start position, numbered from @n-1@ to @0@
+                                      -> proxy j                -- ^ @j@: End position, numbered from @n-1@ to @0@, @j <= i@ must hold
+                                      -> SBV (bv n)             -- ^ Input bit vector of size @n@
+                                      -> SBV (bv (i - j + 1))   -- ^ Output is of size @i - j + 1@
+bvExtract = CD.bvExtract
+
+-- | Join two bit-vectors.
+--
+-- >>> prove $ \x y -> x .== bvExtract (Proxy @79) (Proxy @71) ((x :: SWord 9) # (y :: SWord 71))
+-- Q.E.D.
+(#) :: ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+       , KnownNat m, BVIsNonZero m, SymVal (bv m)
+       ) => SBV (bv n)                     -- ^ First input, of size @n@, becomes the left side
+         -> SBV (bv m)                     -- ^ Second input, of size @m@, becomes the right side
+         -> SBV (bv (n + m))               -- ^ Concatenation, of size @n+m@
+(#) = (CD.#)
+infixr 5 #
+
+-- | Zero extend a bit-vector.
+--
+-- >>> prove $ \x -> bvExtract (Proxy @20) (Proxy @12) (zeroExtend (x :: SInt 12) :: SInt 21) .== 0
+-- Q.E.D.
+zeroExtend :: forall n m bv. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                             , KnownNat m, BVIsNonZero m, SymVal (bv m)
+                             , n + 1 <= m
+                             , SIntegral (bv (m - n))
+                             , BVIsNonZero (m - n)
+                             ) => SBV (bv n)    -- ^ Input, of size @n@
+                               -> SBV (bv m)    -- ^ Output, of size @m@. @n < m@ must hold
+zeroExtend = M.zeroExtend
+
+-- | Sign extend a bit-vector.
+--
+-- >>> prove $ \x -> sNot (msb x) .=> bvExtract (Proxy @20) (Proxy @12) (signExtend (x :: SInt 12) :: SInt 21) .== 0
+-- Q.E.D.
+-- >>> prove $ \x ->       msb x  .=> bvExtract (Proxy @20) (Proxy @12) (signExtend (x :: SInt 12) :: SInt 21) .== complement 0
+-- Q.E.D.
+signExtend :: forall n m bv. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                             , KnownNat m, BVIsNonZero m, SymVal (bv m)
+                             , n + 1 <= m
+                             , SFiniteBits (bv n)
+                             , SIntegral   (bv (m - n))
+                             , BVIsNonZero (m - n)
+                             ) => SBV (bv n)  -- ^ Input, of size @n@
+                               -> SBV (bv m)  -- ^ Output, of size @m@. @n < m@ must hold
+signExtend = M.signExtend
+
+-- | Drop bits from the top of a bit-vector.
+--
+-- >>> prove $ \x -> bvDrop (Proxy @0) (x :: SWord 43) .== x
+-- Q.E.D.
+-- >>> prove $ \x -> bvDrop (Proxy @20) (x :: SWord 21) .== ite (lsb x) 1 (0 :: SWord 1)
+-- Q.E.D.
+bvDrop :: forall i n m bv proxy. ( KnownNat n, BVIsNonZero n
+                                 , KnownNat i
+                                 , i + 1 <= n
+                                 , i + m - n <= 0
+                                 , BVIsNonZero (n - i)
+                                 ) => proxy i                    -- ^ @i@: Number of bits to drop. @i < n@ must hold.
+                                   -> SBV (bv n)                 -- ^ Input, of size @n@
+                                   -> SBV (bv m)                 -- ^ Output, of size @m@. @m = n - i@ holds.
+bvDrop = CD.bvDrop
+
+-- | Take bits from the top of a bit-vector.
+--
+-- >>> prove $ \x -> bvTake (Proxy @13) (x :: SWord 13) .== x
+-- Q.E.D.
+-- >>> prove $ \x -> bvTake (Proxy @1) (x :: SWord 13) .== ite (msb x) 1 0
+-- Q.E.D.
+-- >>> prove $ \x -> bvTake (Proxy @4) x # bvDrop (Proxy @4) x .== (x :: SWord 23)
+-- Q.E.D.
+bvTake :: forall i n bv proxy. ( KnownNat n, BVIsNonZero n
+                               , KnownNat i, BVIsNonZero i
+                               , i <= n
+                               ) => proxy i                  -- ^ @i@: Number of bits to take. @0 < i <= n@ must hold.
+                                 -> SBV (bv n)               -- ^ Input, of size @n@
+                                 -> SBV (bv i)               -- ^ Output, of size @i@
+bvTake = CD.bvTake
+
+-- | A helper class to convert sized bit-vectors to/from bytes.
+class ByteConverter a where
+   -- | Convert to a sequence of bytes
+   --
+   -- >>> prove $ \a b c d -> toBytes ((fromBytes [a, b, c, d]) :: SWord 32) .== [a, b, c, d]
+   -- Q.E.D.
+   toBytes   :: a -> [SWord 8]
+
+   -- | Convert from a sequence of bytes
+   --
+   -- >>> prove $ \r -> fromBytes (toBytes r) .== (r :: SWord 64)
+   -- Q.E.D.
+   fromBytes :: [SWord 8] -> a
+
+-- NB. The following instances are automatically generated by buildUtils/genByteConverter.hs
+-- It is possible to write these more compactly indeed, but this explicit form generates
+-- better C code, and hence we allow the verbosity here.
+
+-- | 'SWord' 8 instance for 'ByteConverter'
+instance ByteConverter (SWord 8) where
+   toBytes a = [a]
+
+   fromBytes [x] = x
+   fromBytes as  = error $ "fromBytes:SWord 8: Incorrect number of bytes: " ++ show (length as)
+
+-- | 'SWord' 16 instance for 'ByteConverter'
+instance ByteConverter (SWord 16) where
+   toBytes a = [ bvExtract (Proxy @15) (Proxy  @8) a
+               , bvExtract (Proxy  @7) (Proxy  @0) a
+               ]
+
+   fromBytes as
+     | l == 2
+     = (fromBytes :: [SWord 8] -> SWord 8) (take 1 as) # fromBytes (drop 1 as)
+     | True
+     = error $ "fromBytes:SWord 16: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 32 instance for 'ByteConverter'
+instance ByteConverter (SWord 32) where
+   toBytes a = [ bvExtract (Proxy @31) (Proxy @24) a, bvExtract (Proxy @23) (Proxy @16) a, bvExtract (Proxy @15) (Proxy  @8) a, bvExtract (Proxy  @7) (Proxy  @0) a
+               ]
+
+   fromBytes as
+     | l == 4
+     = (fromBytes :: [SWord 8] -> SWord 16) (take 2 as) # fromBytes (drop 2 as)
+     | True
+     = error $ "fromBytes:SWord 32: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 64 instance for 'ByteConverter'
+instance ByteConverter (SWord 64) where
+   toBytes a = [ bvExtract (Proxy @63) (Proxy @56) a, bvExtract (Proxy @55) (Proxy @48) a, bvExtract (Proxy @47) (Proxy @40) a, bvExtract (Proxy @39) (Proxy @32) a
+               , bvExtract (Proxy @31) (Proxy @24) a, bvExtract (Proxy @23) (Proxy @16) a, bvExtract (Proxy @15) (Proxy  @8) a, bvExtract (Proxy  @7) (Proxy  @0) a
+               ]
+
+   fromBytes as
+     | l == 8
+     = (fromBytes :: [SWord 8] -> SWord 32) (take 4 as) # fromBytes (drop 4 as)
+     | True
+     = error $ "fromBytes:SWord 64: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 128 instance for 'ByteConverter'
+instance ByteConverter (SWord 128) where
+   toBytes a = [ bvExtract (Proxy @127) (Proxy @120) a, bvExtract (Proxy @119) (Proxy @112) a, bvExtract (Proxy @111) (Proxy @104) a, bvExtract (Proxy @103) (Proxy  @96) a
+               , bvExtract (Proxy  @95) (Proxy  @88) a, bvExtract (Proxy  @87) (Proxy  @80) a, bvExtract (Proxy  @79) (Proxy  @72) a, bvExtract (Proxy  @71) (Proxy  @64) a
+               , bvExtract (Proxy  @63) (Proxy  @56) a, bvExtract (Proxy  @55) (Proxy  @48) a, bvExtract (Proxy  @47) (Proxy  @40) a, bvExtract (Proxy  @39) (Proxy  @32) a
+               , bvExtract (Proxy  @31) (Proxy  @24) a, bvExtract (Proxy  @23) (Proxy  @16) a, bvExtract (Proxy  @15) (Proxy   @8) a, bvExtract (Proxy   @7) (Proxy   @0) a
+               ]
+
+   fromBytes as
+     | l == 16
+     = (fromBytes :: [SWord 8] -> SWord 64) (take 8 as) # fromBytes (drop 8 as)
+     | True
+     = error $ "fromBytes:SWord 128: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 256 instance for 'ByteConverter'
+instance ByteConverter (SWord 256) where
+   toBytes a = [ bvExtract (Proxy @255) (Proxy @248) a, bvExtract (Proxy @247) (Proxy @240) a, bvExtract (Proxy @239) (Proxy @232) a, bvExtract (Proxy @231) (Proxy @224) a
+               , bvExtract (Proxy @223) (Proxy @216) a, bvExtract (Proxy @215) (Proxy @208) a, bvExtract (Proxy @207) (Proxy @200) a, bvExtract (Proxy @199) (Proxy @192) a
+               , bvExtract (Proxy @191) (Proxy @184) a, bvExtract (Proxy @183) (Proxy @176) a, bvExtract (Proxy @175) (Proxy @168) a, bvExtract (Proxy @167) (Proxy @160) a
+               , bvExtract (Proxy @159) (Proxy @152) a, bvExtract (Proxy @151) (Proxy @144) a, bvExtract (Proxy @143) (Proxy @136) a, bvExtract (Proxy @135) (Proxy @128) a
+               , bvExtract (Proxy @127) (Proxy @120) a, bvExtract (Proxy @119) (Proxy @112) a, bvExtract (Proxy @111) (Proxy @104) a, bvExtract (Proxy @103) (Proxy  @96) a
+               , bvExtract (Proxy  @95) (Proxy  @88) a, bvExtract (Proxy  @87) (Proxy  @80) a, bvExtract (Proxy  @79) (Proxy  @72) a, bvExtract (Proxy  @71) (Proxy  @64) a
+               , bvExtract (Proxy  @63) (Proxy  @56) a, bvExtract (Proxy  @55) (Proxy  @48) a, bvExtract (Proxy  @47) (Proxy  @40) a, bvExtract (Proxy  @39) (Proxy  @32) a
+               , bvExtract (Proxy  @31) (Proxy  @24) a, bvExtract (Proxy  @23) (Proxy  @16) a, bvExtract (Proxy  @15) (Proxy   @8) a, bvExtract (Proxy   @7) (Proxy   @0) a
+               ]
+
+   fromBytes as
+     | l == 32
+     = (fromBytes :: [SWord 8] -> SWord 128) (take 16 as) # fromBytes (drop 16 as)
+     | True
+     = error $ "fromBytes:SWord 256: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 512 instance for 'ByteConverter'
+instance ByteConverter (SWord 512) where
+   toBytes a = [ bvExtract (Proxy @511) (Proxy @504) a, bvExtract (Proxy @503) (Proxy @496) a, bvExtract (Proxy @495) (Proxy @488) a, bvExtract (Proxy @487) (Proxy @480) a
+               , bvExtract (Proxy @479) (Proxy @472) a, bvExtract (Proxy @471) (Proxy @464) a, bvExtract (Proxy @463) (Proxy @456) a, bvExtract (Proxy @455) (Proxy @448) a
+               , bvExtract (Proxy @447) (Proxy @440) a, bvExtract (Proxy @439) (Proxy @432) a, bvExtract (Proxy @431) (Proxy @424) a, bvExtract (Proxy @423) (Proxy @416) a
+               , bvExtract (Proxy @415) (Proxy @408) a, bvExtract (Proxy @407) (Proxy @400) a, bvExtract (Proxy @399) (Proxy @392) a, bvExtract (Proxy @391) (Proxy @384) a
+               , bvExtract (Proxy @383) (Proxy @376) a, bvExtract (Proxy @375) (Proxy @368) a, bvExtract (Proxy @367) (Proxy @360) a, bvExtract (Proxy @359) (Proxy @352) a
+               , bvExtract (Proxy @351) (Proxy @344) a, bvExtract (Proxy @343) (Proxy @336) a, bvExtract (Proxy @335) (Proxy @328) a, bvExtract (Proxy @327) (Proxy @320) a
+               , bvExtract (Proxy @319) (Proxy @312) a, bvExtract (Proxy @311) (Proxy @304) a, bvExtract (Proxy @303) (Proxy @296) a, bvExtract (Proxy @295) (Proxy @288) a
+               , bvExtract (Proxy @287) (Proxy @280) a, bvExtract (Proxy @279) (Proxy @272) a, bvExtract (Proxy @271) (Proxy @264) a, bvExtract (Proxy @263) (Proxy @256) a
+               , bvExtract (Proxy @255) (Proxy @248) a, bvExtract (Proxy @247) (Proxy @240) a, bvExtract (Proxy @239) (Proxy @232) a, bvExtract (Proxy @231) (Proxy @224) a
+               , bvExtract (Proxy @223) (Proxy @216) a, bvExtract (Proxy @215) (Proxy @208) a, bvExtract (Proxy @207) (Proxy @200) a, bvExtract (Proxy @199) (Proxy @192) a
+               , bvExtract (Proxy @191) (Proxy @184) a, bvExtract (Proxy @183) (Proxy @176) a, bvExtract (Proxy @175) (Proxy @168) a, bvExtract (Proxy @167) (Proxy @160) a
+               , bvExtract (Proxy @159) (Proxy @152) a, bvExtract (Proxy @151) (Proxy @144) a, bvExtract (Proxy @143) (Proxy @136) a, bvExtract (Proxy @135) (Proxy @128) a
+               , bvExtract (Proxy @127) (Proxy @120) a, bvExtract (Proxy @119) (Proxy @112) a, bvExtract (Proxy @111) (Proxy @104) a, bvExtract (Proxy @103) (Proxy  @96) a
+               , bvExtract (Proxy  @95) (Proxy  @88) a, bvExtract (Proxy  @87) (Proxy  @80) a, bvExtract (Proxy  @79) (Proxy  @72) a, bvExtract (Proxy  @71) (Proxy  @64) a
+               , bvExtract (Proxy  @63) (Proxy  @56) a, bvExtract (Proxy  @55) (Proxy  @48) a, bvExtract (Proxy  @47) (Proxy  @40) a, bvExtract (Proxy  @39) (Proxy  @32) a
+               , bvExtract (Proxy  @31) (Proxy  @24) a, bvExtract (Proxy  @23) (Proxy  @16) a, bvExtract (Proxy  @15) (Proxy   @8) a, bvExtract (Proxy   @7) (Proxy   @0) a
+               ]
+
+   fromBytes as
+     | l == 64
+     = (fromBytes :: [SWord 8] -> SWord 256) (take 32 as) # fromBytes (drop 32 as)
+     | True
+     = error $ "fromBytes:SWord 512: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+-- | 'SWord' 1024 instance for 'ByteConverter'
+instance ByteConverter (SWord 1024) where
+   toBytes a = [ bvExtract (Proxy @1023) (Proxy @1016) a, bvExtract (Proxy @1015) (Proxy @1008) a, bvExtract (Proxy @1007) (Proxy @1000) a, bvExtract (Proxy  @999) (Proxy  @992) a
+               , bvExtract (Proxy  @991) (Proxy  @984) a, bvExtract (Proxy  @983) (Proxy  @976) a, bvExtract (Proxy  @975) (Proxy  @968) a, bvExtract (Proxy  @967) (Proxy  @960) a
+               , bvExtract (Proxy  @959) (Proxy  @952) a, bvExtract (Proxy  @951) (Proxy  @944) a, bvExtract (Proxy  @943) (Proxy  @936) a, bvExtract (Proxy  @935) (Proxy  @928) a
+               , bvExtract (Proxy  @927) (Proxy  @920) a, bvExtract (Proxy  @919) (Proxy  @912) a, bvExtract (Proxy  @911) (Proxy  @904) a, bvExtract (Proxy  @903) (Proxy  @896) a
+               , bvExtract (Proxy  @895) (Proxy  @888) a, bvExtract (Proxy  @887) (Proxy  @880) a, bvExtract (Proxy  @879) (Proxy  @872) a, bvExtract (Proxy  @871) (Proxy  @864) a
+               , bvExtract (Proxy  @863) (Proxy  @856) a, bvExtract (Proxy  @855) (Proxy  @848) a, bvExtract (Proxy  @847) (Proxy  @840) a, bvExtract (Proxy  @839) (Proxy  @832) a
+               , bvExtract (Proxy  @831) (Proxy  @824) a, bvExtract (Proxy  @823) (Proxy  @816) a, bvExtract (Proxy  @815) (Proxy  @808) a, bvExtract (Proxy  @807) (Proxy  @800) a
+               , bvExtract (Proxy  @799) (Proxy  @792) a, bvExtract (Proxy  @791) (Proxy  @784) a, bvExtract (Proxy  @783) (Proxy  @776) a, bvExtract (Proxy  @775) (Proxy  @768) a
+               , bvExtract (Proxy  @767) (Proxy  @760) a, bvExtract (Proxy  @759) (Proxy  @752) a, bvExtract (Proxy  @751) (Proxy  @744) a, bvExtract (Proxy  @743) (Proxy  @736) a
+               , bvExtract (Proxy  @735) (Proxy  @728) a, bvExtract (Proxy  @727) (Proxy  @720) a, bvExtract (Proxy  @719) (Proxy  @712) a, bvExtract (Proxy  @711) (Proxy  @704) a
+               , bvExtract (Proxy  @703) (Proxy  @696) a, bvExtract (Proxy  @695) (Proxy  @688) a, bvExtract (Proxy  @687) (Proxy  @680) a, bvExtract (Proxy  @679) (Proxy  @672) a
+               , bvExtract (Proxy  @671) (Proxy  @664) a, bvExtract (Proxy  @663) (Proxy  @656) a, bvExtract (Proxy  @655) (Proxy  @648) a, bvExtract (Proxy  @647) (Proxy  @640) a
+               , bvExtract (Proxy  @639) (Proxy  @632) a, bvExtract (Proxy  @631) (Proxy  @624) a, bvExtract (Proxy  @623) (Proxy  @616) a, bvExtract (Proxy  @615) (Proxy  @608) a
+               , bvExtract (Proxy  @607) (Proxy  @600) a, bvExtract (Proxy  @599) (Proxy  @592) a, bvExtract (Proxy  @591) (Proxy  @584) a, bvExtract (Proxy  @583) (Proxy  @576) a
+               , bvExtract (Proxy  @575) (Proxy  @568) a, bvExtract (Proxy  @567) (Proxy  @560) a, bvExtract (Proxy  @559) (Proxy  @552) a, bvExtract (Proxy  @551) (Proxy  @544) a
+               , bvExtract (Proxy  @543) (Proxy  @536) a, bvExtract (Proxy  @535) (Proxy  @528) a, bvExtract (Proxy  @527) (Proxy  @520) a, bvExtract (Proxy  @519) (Proxy  @512) a
+               , bvExtract (Proxy  @511) (Proxy  @504) a, bvExtract (Proxy  @503) (Proxy  @496) a, bvExtract (Proxy  @495) (Proxy  @488) a, bvExtract (Proxy  @487) (Proxy  @480) a
+               , bvExtract (Proxy  @479) (Proxy  @472) a, bvExtract (Proxy  @471) (Proxy  @464) a, bvExtract (Proxy  @463) (Proxy  @456) a, bvExtract (Proxy  @455) (Proxy  @448) a
+               , bvExtract (Proxy  @447) (Proxy  @440) a, bvExtract (Proxy  @439) (Proxy  @432) a, bvExtract (Proxy  @431) (Proxy  @424) a, bvExtract (Proxy  @423) (Proxy  @416) a
+               , bvExtract (Proxy  @415) (Proxy  @408) a, bvExtract (Proxy  @407) (Proxy  @400) a, bvExtract (Proxy  @399) (Proxy  @392) a, bvExtract (Proxy  @391) (Proxy  @384) a
+               , bvExtract (Proxy  @383) (Proxy  @376) a, bvExtract (Proxy  @375) (Proxy  @368) a, bvExtract (Proxy  @367) (Proxy  @360) a, bvExtract (Proxy  @359) (Proxy  @352) a
+               , bvExtract (Proxy  @351) (Proxy  @344) a, bvExtract (Proxy  @343) (Proxy  @336) a, bvExtract (Proxy  @335) (Proxy  @328) a, bvExtract (Proxy  @327) (Proxy  @320) a
+               , bvExtract (Proxy  @319) (Proxy  @312) a, bvExtract (Proxy  @311) (Proxy  @304) a, bvExtract (Proxy  @303) (Proxy  @296) a, bvExtract (Proxy  @295) (Proxy  @288) a
+               , bvExtract (Proxy  @287) (Proxy  @280) a, bvExtract (Proxy  @279) (Proxy  @272) a, bvExtract (Proxy  @271) (Proxy  @264) a, bvExtract (Proxy  @263) (Proxy  @256) a
+               , bvExtract (Proxy  @255) (Proxy  @248) a, bvExtract (Proxy  @247) (Proxy  @240) a, bvExtract (Proxy  @239) (Proxy  @232) a, bvExtract (Proxy  @231) (Proxy  @224) a
+               , bvExtract (Proxy  @223) (Proxy  @216) a, bvExtract (Proxy  @215) (Proxy  @208) a, bvExtract (Proxy  @207) (Proxy  @200) a, bvExtract (Proxy  @199) (Proxy  @192) a
+               , bvExtract (Proxy  @191) (Proxy  @184) a, bvExtract (Proxy  @183) (Proxy  @176) a, bvExtract (Proxy  @175) (Proxy  @168) a, bvExtract (Proxy  @167) (Proxy  @160) a
+               , bvExtract (Proxy  @159) (Proxy  @152) a, bvExtract (Proxy  @151) (Proxy  @144) a, bvExtract (Proxy  @143) (Proxy  @136) a, bvExtract (Proxy  @135) (Proxy  @128) a
+               , bvExtract (Proxy  @127) (Proxy  @120) a, bvExtract (Proxy  @119) (Proxy  @112) a, bvExtract (Proxy  @111) (Proxy  @104) a, bvExtract (Proxy  @103) (Proxy   @96) a
+               , bvExtract (Proxy   @95) (Proxy   @88) a, bvExtract (Proxy   @87) (Proxy   @80) a, bvExtract (Proxy   @79) (Proxy   @72) a, bvExtract (Proxy   @71) (Proxy   @64) a
+               , bvExtract (Proxy   @63) (Proxy   @56) a, bvExtract (Proxy   @55) (Proxy   @48) a, bvExtract (Proxy   @47) (Proxy   @40) a, bvExtract (Proxy   @39) (Proxy   @32) a
+               , bvExtract (Proxy   @31) (Proxy   @24) a, bvExtract (Proxy   @23) (Proxy   @16) a, bvExtract (Proxy   @15) (Proxy    @8) a, bvExtract (Proxy    @7) (Proxy    @0) a
+               ]
+
+   fromBytes as
+     | l == 128
+     = (fromBytes :: [SWord 8] -> SWord 512) (take 64 as) # fromBytes (drop 64 as)
+     | True
+     = error $ "fromBytes:SWord 1024: Incorrect number of bytes: " ++ show l
+     where l = length as
+
+{- $specialRels
+A special relation is a binary relation that has additional properties. SBV allows for the checking of various kinds
+of special relations respecting various axioms, and allows for creating transitive closures.
+See "Documentation.SBV.Examples.Misc.FirstOrderLogic" for several examples.
+-}
+
+-- | A type synonym for binary relations.
+type Relation a = (SBV a, SBV a) -> SBool
+
+-- | Check if a relation is a partial order. The string argument must uniquely identify this order.
+isPartialOrder :: SymVal a => String -> Relation a -> SBool
+isPartialOrder = checkSpecialRelation . IsPartialOrder
+
+-- | Check if a relation is a linear order. The string argument must uniquely identify this order.
+isLinearOrder :: SymVal a => String -> Relation a -> SBool
+isLinearOrder = checkSpecialRelation . IsLinearOrder
+
+-- | Check if a relation is a tree order. The string argument must uniquely identify this order.
+isTreeOrder :: SymVal a => String -> Relation a -> SBool
+isTreeOrder = checkSpecialRelation . IsTreeOrder
+
+-- | Check if a relation is a piece-wise linear order. The string argument must uniquely identify this order.
+isPiecewiseLinearOrder :: SymVal a => String -> Relation a -> SBool
+isPiecewiseLinearOrder = checkSpecialRelation . IsPiecewiseLinearOrder
+
+-- | Make sure it's internally acceptable
+sanitizeRelName :: String -> String
+sanitizeRelName s = "__internal_sbv_" ++ map sanitize s
+  where sanitize c | isSpace c || isPunctuation c = '_'
+                               | True             = c
+
+-- | Create the transitive closure of a given relation. The string argument must uniquely identify the newly created relation.
+mkTransitiveClosure :: forall a. SymVal a => String -> Relation a -> Relation a
+mkTransitiveClosure nm rel = res
+  where ka = kindOf (Proxy @a)
+
+        -- The internal name of this relation
+        inm = sanitizeRelName $ "_TransitiveClosure_" ++ nm ++ "_"
+        key = (inm, nm)
+
+        res (a, b) = SBV $ SVal KBool $ Right $ cache result
+          where result st = do -- Is this new? If so create it, otherwise reuse
+                               ProgInfo{progTransClosures = curProgTransClosures} <- readIORef (rProgInfo st)
+
+                               unless (key `elem` curProgTransClosures) $ do
+
+                                  registerKind st ka
+
+                                  -- Add to the end so if we get incremental ones the order doesn't change for old ones!
+                                  modifyIORef' (rProgInfo st) (\u -> u{progTransClosures = curProgTransClosures ++ [key]})
+
+                                  -- Equate it to the relation we are given. We want to do this in the root state
+                                  let SBV eq = quantifiedBool $ \(Forall x) (Forall y) -> rel (x, y) .== uninterpret inm x y
+                                  internalConstraint (getRootState st) False [] eq
+
+                               sa <- sbvToSV st a
+                               sb <- sbvToSV st b
+
+                               newExpr st KBool $ SBVApp (Uninterpreted (T.pack nm)) [sa, sb]
+
+-- | Check if the given relation satisfies the required axioms
+checkSpecialRelation :: forall a. SymVal a => SpecialRelOp -> Relation a -> SBool
+checkSpecialRelation op rel = SBV $ SVal KBool $ Right $ cache result
+  where ka = kindOf (Proxy @a)
+
+        internalize nm = case op of
+                           IsPartialOrder         _ -> IsPartialOrder         nm
+                           IsLinearOrder          _ -> IsLinearOrder          nm
+                           IsTreeOrder            _ -> IsTreeOrder            nm
+                           IsPiecewiseLinearOrder _ -> IsPiecewiseLinearOrder nm
+
+        result st = do -- The internal name of this relation
+                       let nm  = sanitizeRelName (show op)
+                           iop = internalize nm
+
+                       -- Is this new? If so create it, otherwise reuse
+                       ProgInfo{progSpecialRels = curSpecialRels} <- readIORef (rProgInfo st)
+
+                       unless (op `elem` curSpecialRels) $ do
+
+                          registerKind st ka
+                          uop <- newUninterpreted st (UIGiven nm) Nothing (SBVType [ka, ka, KBool]) (UINone True)
+
+                          let nm' = case uop of
+                                      Uninterpreted s -> T.unpack s
+                                      _               -> error $ "Data.SBV: Impossible happened: checkSpecialRelation received: " ++ show op
+
+                          -- Add to the end so if we get incremental ones the order doesn't change for old ones!
+                          modifyIORef' (rProgInfo st) (\u -> u{progSpecialRels = curSpecialRels ++ [iop]})
+
+                          -- Equate it to the relation we are given. We want to do this in the parent state
+                          let SBV eq = quantifiedBool $ \(Forall x) (Forall y) -> rel (x, y) .== uninterpret nm' x y
+                          internalConstraint (getRootState st) False [] eq
+
+                       newExpr st KBool $ SBVApp (SpecialRelOp ka iop) []
+
+-- | Optimize lexicographically, with the default solver.
+optLexicographic :: Satisfiable a => a -> IO SMTResult
+optLexicographic = optLexicographicWith defaultSMTCfg
+
+-- | Optimize lexicographically, using the given solver.
+optLexicographicWith :: Satisfiable a => SMTConfig -> a -> IO SMTResult
+optLexicographicWith config p = do
+   res <- optimizeWith config Lexicographic p
+   case res of
+     LexicographicResult r -> pure r
+     _                     -> error $ "A lexicographic optimization call resulted in a bad result:"
+                                    ++ "\n" ++ show res
+
+-- | Pareto front optimization, with the default solver.
+optPareto :: Satisfiable a => Maybe Int -> a -> IO (Bool, [SMTResult])
+optPareto = optParetoWith defaultSMTCfg
+
+-- | Pareto front optimization, with the given solver. The optional integer argument is the number of fronts to return. If 'Nothing', then
+-- we will return all pareto fronts. If the first component of the result is 'True' then we reached the pareto-query limit specified by
+-- the user, so there might be more unqueried results remaining. If 'False', it means that all the pareto fronts are returned.
+optParetoWith :: Satisfiable a => SMTConfig -> Maybe Int -> a -> IO (Bool, [SMTResult])
+optParetoWith config mbLim p = do
+   res <- optimizeWith config (Pareto mbLim) p
+   case res of
+     ParetoResult r -> pure r
+     _              -> error $ "A pareto optimization call resulted in a bad result:"
+                             ++ "\n" ++ show res
+
+-- | Independent optimization, with the default solver. In each result, string is the name of the objective optimized given by the user.
+optIndependent :: Satisfiable a => a -> IO [(String, SMTResult)]
+optIndependent = optIndependentWith defaultSMTCfg
+
+-- | Independent optimization, with the given solver. In each result, string is the name of the objective optimized given by the user.
+optIndependentWith :: Satisfiable a => SMTConfig -> a -> IO [(String, SMTResult)]
+optIndependentWith config p = do
+   res <- optimizeWith config Independent p
+   case res of
+     IndependentResult r -> pure r
+     _                   -> error $ "An independent optimization call resulted in a bad result:"
+                                  ++ "\n" ++ show res
+
+-- | An queriable value: Mapping between concrete/symbolic values. If your type is traversable and simply embeds
+-- symbolic equivalents for one type, then you can simply define 'create'. (Which is the most common case.)
+class Queriable m a where
+  type QueryResult a :: Type
+
+  -- | ^ Create a new symbolic value of type @a@
+  create  :: QueryT m a
+
+  -- | ^ Extract the current value in a SAT context
+  project :: a -> QueryT m (QueryResult a)
+
+  -- | ^ Create a literal value. Morally, 'embed' and 'project' are inverses of each other
+  -- via the t'QueryT' monad transformer.
+  embed   :: QueryResult a -> QueryT m a
+
+  default project :: (a ~ t e, QueryResult (t e) ~ t (QueryResult e), Traversable t, Monad m, Queriable m e) =>  a -> QueryT m (QueryResult a)
+  project = mapM project
+
+  default embed   :: (a ~ t e, QueryResult (t e) ~ t (QueryResult e), Traversable t, Monad m, Queriable m e) => QueryResult a -> QueryT m a
+  embed = mapM embed
+  {-# MINIMAL create #-}
+
+-- | Generic 'Queriable' instance for 'SymVal' values. This provides the base case for the generic definitions for project and embed
+-- when we automatically derive them. We make this instance overlappable should the user have a different mapping in mind, for instance
+-- mapping a symbolic boolean to a concrete integer for whatever reason.
+instance {-# OVERLAPPABLE #-} (MonadIO m, SymVal a) => Queriable m (SBV a) where
+  type QueryResult (SBV a) = a
+
+  create  = freshVar_
+  project = getValue
+  embed   = pure . literal
+
+{- HLint ignore module "Use import/export shortcut" -}
diff --git a/Data/SBV/BitVectors/AlgReals.hs b/Data/SBV/BitVectors/AlgReals.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/AlgReals.hs
+++ /dev/null
@@ -1,234 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.AlgReals
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Algrebraic reals in Haskell.
------------------------------------------------------------------------------
-
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-module Data.SBV.BitVectors.AlgReals (AlgReal(..), mkPolyReal, algRealToSMTLib2, algRealToHaskell, mergeAlgReals, isExactRational, algRealStructuralEqual, algRealStructuralCompare) where
-
-import Data.List       (sortBy, isPrefixOf, partition)
-import Data.Ratio      ((%), numerator, denominator)
-import Data.Function   (on)
-import System.Random
-import Test.QuickCheck (Arbitrary(..))
-
--- | Algebraic reals. Note that the representation is left abstract. We represent
--- rational results explicitly, while the roots-of-polynomials are represented
--- implicitly by their defining equation
-data AlgReal = AlgRational Bool Rational          -- bool says it's exact (i.e., SMT-solver did not return it with ? at the end.)
-             | AlgPolyRoot (Integer,  Polynomial) -- which root
-                           (Maybe String)         -- approximate decimal representation with given precision, if available
-
--- | Check wheter a given argument is an exact rational
-isExactRational :: AlgReal -> Bool
-isExactRational (AlgRational True _) = True
-isExactRational _                    = False
-
--- | A univariate polynomial, represented simply as a
--- coefficient list. For instance, "5x^3 + 2x - 5" is
--- represented as [(5, 3), (2, 1), (-5, 0)]
-newtype Polynomial = Polynomial [(Integer, Integer)]
-                   deriving (Eq, Ord)
-
--- | Construct a poly-root real with a given approximate value (either as a decimal, or polynomial-root)
-mkPolyReal :: Either (Bool, String) (Integer, [(Integer, Integer)]) -> AlgReal
-mkPolyReal (Left (exact, str))
- = case (str, break (== '.') str) of
-      ("", (_, _))    -> AlgRational exact 0
-      (_, (x, '.':y)) -> AlgRational exact (read (x++y) % (10 ^ length y))
-      (_, (x, _))     -> AlgRational exact (read x % 1)
-mkPolyReal (Right (k, coeffs))
- = AlgPolyRoot (k, Polynomial (normalize coeffs)) Nothing
- where normalize :: [(Integer, Integer)] -> [(Integer, Integer)]
-       normalize = merge . sortBy (flip compare `on` snd)
-       merge []                     = []
-       merge [x]                    = [x]
-       merge ((a, b):r@((c, d):xs))
-         | b == d                   = merge ((a+c, b):xs)
-         | True                     = (a, b) : merge r
-
-instance Show Polynomial where
-  show (Polynomial xs) = chkEmpty (join (concat [term p | p@(_, x) <- xs, x /= 0])) ++ " = " ++ show c
-     where c  = -1 * head ([k | (k, 0) <- xs] ++ [0])
-           term ( 0, _) = []
-           term ( 1, 1) = [ "x"]
-           term ( 1, p) = [ "x^" ++ show p]
-           term (-1, 1) = ["-x"]
-           term (-1, p) = ["-x^" ++ show p]
-           term (k,  1) = [show k ++ "x"]
-           term (k,  p) = [show k ++ "x^" ++ show p]
-           join []      = ""
-           join (k:ks) = k ++ s ++ join ks
-             where s = case ks of
-                        []    -> ""
-                        (y:_) | "-" `isPrefixOf` y -> ""
-                              | "+" `isPrefixOf` y -> ""
-                              | True               -> "+"
-           chkEmpty s = if null s then "0" else s
-
-instance Show AlgReal where
-  show (AlgRational exact a)         = showRat exact a
-  show (AlgPolyRoot (i, p) mbApprox) = "root(" ++ show i ++ ", " ++ show p ++ ")" ++ maybe "" app mbApprox
-     where app v | last v == '?' = " = " ++ init v ++ "..."
-                 | True          = " = " ++ v
-
--- lift unary op through an exact rational, otherwise bail
-lift1 :: String -> (Rational -> Rational) -> AlgReal -> AlgReal
-lift1 _  o (AlgRational e a) = AlgRational e (o a)
-lift1 nm _ a                 = error $ "AlgReal." ++ nm ++ ": unsupported argument: " ++ show a
-
--- lift binary op through exact rationals, otherwise bail
-lift2 :: String -> (Rational -> Rational -> Rational) -> AlgReal -> AlgReal -> AlgReal
-lift2 _  o (AlgRational True a) (AlgRational True b) = AlgRational True (a `o` b)
-lift2 nm _ a                    b                    = error $ "AlgReal." ++ nm ++ ": unsupported arguments: " ++ show (a, b)
-
--- The idea in the instances below is that we will fully support operations
--- on "AlgRational" AlgReals, but leave everything else undefined. When we are
--- on the Haskell side, the AlgReal's are *not* reachable. They only represent
--- return values from SMT solvers, which we should *not* need to manipulate.
-instance Eq AlgReal where
-  AlgRational True a == AlgRational True b = a == b
-  a                  == b                  = error $ "AlgReal.==: unsupported arguments: " ++ show (a, b)
-
-instance Ord AlgReal where
-  AlgRational True a `compare` AlgRational True b = a `compare` b
-  a                  `compare` b                  = error $ "AlgReal.compare: unsupported arguments: " ++ show (a, b)
-
--- | Structural equality for AlgReal; used when constants are Map keys
-algRealStructuralEqual   :: AlgReal -> AlgReal -> Bool
-AlgRational a b `algRealStructuralEqual` AlgRational c d = (a, b) == (c, d)
-AlgPolyRoot a b `algRealStructuralEqual` AlgPolyRoot c d = (a, b) == (c, d)
-_               `algRealStructuralEqual` _               = False
-
--- | Structural comparisons for AlgReal; used when constants are Map keys
-algRealStructuralCompare :: AlgReal -> AlgReal -> Ordering
-AlgRational a b `algRealStructuralCompare` AlgRational c d = (a, b) `compare` (c, d)
-AlgRational _ _ `algRealStructuralCompare` AlgPolyRoot _ _ = LT
-AlgPolyRoot _ _ `algRealStructuralCompare` AlgRational _ _ = GT
-AlgPolyRoot a b `algRealStructuralCompare` AlgPolyRoot c d = (a, b) `compare` (c, d)
-
-instance Num AlgReal where
-  (+)         = lift2 "+"      (+)
-  (*)         = lift2 "*"      (*)
-  (-)         = lift2 "-"      (-)
-  negate      = lift1 "negate" negate
-  abs         = lift1 "abs"    abs
-  signum      = lift1 "signum" signum
-  fromInteger = AlgRational True . fromInteger
-
--- |  NB: Following the other types we have, we require `a/0` to be `0` for all a.
-instance Fractional AlgReal where
-  (AlgRational True _) / (AlgRational True b) | b == 0 = 0
-  a                    / b                             = lift2 "/" (/) a b
-  fromRational = AlgRational True
-
-instance Real AlgReal where
-  toRational (AlgRational True v) = v
-  toRational x                    = error $ "AlgReal.toRational: Argument cannot be represented as a rational value: " ++ algRealToHaskell x
-
-instance Random Rational where
-  random g = (a % b', g'')
-     where (a, g')  = random g
-           (b, g'') = random g'
-           b'       = if 0 < b then b else 1 - b -- ensures 0 < b
-
-  randomR (l, h) g = (r * d + l, g'')
-     where (b, g')  = random g
-           b'       = if 0 < b then b else 1 - b -- ensures 0 < b
-           (a, g'') = randomR (0, b') g'
-
-           r = a % b'
-           d = h - l
-
-instance Random AlgReal where
-  random g = let (a, g') = random g in (AlgRational True a, g')
-  randomR (AlgRational True l, AlgRational True h) g = let (a, g') = randomR (l, h) g in (AlgRational True a, g')
-  randomR lh                                       _ = error $ "AlgReal.randomR: unsupported bounds: " ++ show lh
-
--- | Render an 'AlgReal' as an SMTLib2 value. Only supports rationals for the time being.
-algRealToSMTLib2 :: AlgReal -> String
-algRealToSMTLib2 (AlgRational True r)
-   | m == 0 = "0.0"
-   | m < 0  = "(- (/ "  ++ show (abs m) ++ ".0 " ++ show n ++ ".0))"
-   | True   =    "(/ "  ++ show m       ++ ".0 " ++ show n ++ ".0)"
-  where (m, n) = (numerator r, denominator r)
-algRealToSMTLib2 r@(AlgRational False _)
-   = error $ "SBV: Unexpected inexact rational to be converted to SMTLib2: " ++ show r
-algRealToSMTLib2 (AlgPolyRoot (i, Polynomial xs) _) = "(root-obj (+ " ++ unwords (concatMap term xs) ++ ") " ++ show i ++ ")"
-  where term (0, _) = []
-        term (k, 0) = [coeff k]
-        term (1, 1) = ["x"]
-        term (1, p) = ["(^ x " ++ show p ++ ")"]
-        term (k, 1) = ["(* " ++ coeff k ++ " x)"]
-        term (k, p) = ["(* " ++ coeff k ++ " (^ x " ++ show p ++ "))"]
-        coeff n | n < 0 = "(- " ++ show (abs n) ++ ")"
-                | True  = show n
-
--- | Render an 'AlgReal' as a Haskell value. Only supports rationals, since there is no corresponding
--- standard Haskell type that can represent root-of-polynomial variety.
-algRealToHaskell :: AlgReal -> String
-algRealToHaskell (AlgRational True r) = "((" ++ show r ++ ") :: Rational)"
-algRealToHaskell r                    = error $ "SBV.algRealToHaskell: Unsupported argument: " ++ show r
-
--- Try to show a rational precisely if we can, with finite number of
--- digits. Otherwise, show it as a rational value.
-showRat :: Bool -> Rational -> String
-showRat exact r = p $ case f25 (denominator r) [] of
-                       Nothing               -> show r   -- bail out, not precisely representable with finite digits
-                       Just (noOfZeros, num) -> let present = length num
-                                                in neg $ case noOfZeros `compare` present of
-                                                           LT -> let (b, a) = splitAt (present - noOfZeros) num in b ++ "." ++ if null a then "0" else a
-                                                           EQ -> "0." ++ num
-                                                           GT -> "0." ++ replicate (noOfZeros - present) '0' ++ num
-  where p   = if exact then id else (++ "...")
-        neg = if r < 0 then ('-':) else id
-        -- factor a number in 2's and 5's if possible
-        -- If so, it'll return the number of digits after the zero
-        -- to reach the next power of 10, and the numerator value scaled
-        -- appropriately and shown as a string
-        f25 :: Integer -> [Integer] -> Maybe (Int, String)
-        f25 1 sofar = let (ts, fs)   = partition (== 2) sofar
-                          [lts, lfs] = map length [ts, fs]
-                          noOfZeros  = lts `max` lfs
-                      in Just (noOfZeros, show (abs (numerator r)  * factor ts fs))
-        f25 v sofar = let (q2, r2) = v `quotRem` 2
-                          (q5, r5) = v `quotRem` 5
-                      in case (r2, r5) of
-                           (0, _) -> f25 q2 (2 : sofar)
-                           (_, 0) -> f25 q5 (5 : sofar)
-                           _      -> Nothing
-        -- compute the next power of 10 we need to get to
-        factor []     fs     = product [2 | _ <- fs]
-        factor ts     []     = product [5 | _ <- ts]
-        factor (_:ts) (_:fs) = factor ts fs
-
--- | Merge the representation of two algebraic reals, one assumed to be
--- in polynomial form, the other in decimal. Arguments can be the same
--- kind, so long as they are both rationals and equivalent; if not there
--- must be one that is precise. It's an error to pass anything
--- else to this function! (Used in reconstructing SMT counter-example values with reals).
-mergeAlgReals :: String -> AlgReal -> AlgReal -> AlgReal
-mergeAlgReals _ f@(AlgRational exact r) (AlgPolyRoot kp Nothing)
-  | exact = f
-  | True  = AlgPolyRoot kp (Just (showRat False r))
-mergeAlgReals _ (AlgPolyRoot kp Nothing) f@(AlgRational exact r)
-  | exact = f
-  | True  = AlgPolyRoot kp (Just (showRat False r))
-mergeAlgReals _ f@(AlgRational e1 r1) s@(AlgRational e2 r2)
-  | (e1, r1) == (e2, r2) = f
-  | e1                   = f
-  | e2                   = s
-mergeAlgReals m _ _ = error m
-
--- Quickcheck instance
-instance Arbitrary AlgReal where
-  arbitrary = AlgRational True `fmap` arbitrary
diff --git a/Data/SBV/BitVectors/Concrete.hs b/Data/SBV/BitVectors/Concrete.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Concrete.hs
+++ /dev/null
@@ -1,194 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Concrete
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Operations on concrete values
------------------------------------------------------------------------------
-
-module Data.SBV.BitVectors.Concrete
-  ( module Data.SBV.BitVectors.Concrete
-  ) where
-
-import Data.Bits
-import System.Random (randomIO, randomRIO)
-
-import Data.SBV.BitVectors.Kind
-import Data.SBV.BitVectors.AlgReals
-
--- | A constant value
-data CWVal = CWAlgReal  !AlgReal              -- ^ algebraic real
-           | CWInteger  !Integer              -- ^ bit-vector/unbounded integer
-           | CWFloat    !Float                -- ^ float
-           | CWDouble   !Double               -- ^ double
-           | CWUserSort !(Maybe Int, String)  -- ^ value of an uninterpreted/user kind. The Maybe Int shows index position for enumerations
-
--- | Eq instance for CWVal. Note that we cannot simply derive Eq/Ord, since CWAlgReal doesn't have proper
--- instances for these when values are infinitely precise reals. However, we do
--- need a structural eq/ord for Map indexes; so define custom ones here:
-instance Eq CWVal where
-  CWAlgReal a  == CWAlgReal b       = a `algRealStructuralEqual` b
-  CWInteger a  == CWInteger b       = a == b
-  CWUserSort a == CWUserSort b = a == b
-  CWFloat a    == CWFloat b         = a == b
-  CWDouble a   == CWDouble b        = a == b
-  _            == _                 = False
-
--- | Ord instance for CWVal. Same comments as the 'Eq' instance why this cannot be derived.
-instance Ord CWVal where
-  CWAlgReal a `compare` CWAlgReal b   = a `algRealStructuralCompare` b
-  CWAlgReal _ `compare` CWInteger _   = LT
-  CWAlgReal _ `compare` CWFloat _     = LT
-  CWAlgReal _ `compare` CWDouble _    = LT
-  CWAlgReal _ `compare` CWUserSort _  = LT
-
-  CWInteger _ `compare` CWAlgReal _   = GT
-  CWInteger a `compare` CWInteger b   = a `compare` b
-  CWInteger _ `compare` CWFloat _     = LT
-  CWInteger _ `compare` CWDouble _    = LT
-  CWInteger _ `compare` CWUserSort _  = LT
-
-  CWFloat _   `compare` CWAlgReal _   = GT
-  CWFloat _   `compare` CWInteger _   = GT
-  CWFloat a   `compare` CWFloat b     = a `compare` b
-  CWFloat _   `compare` CWDouble _    = LT
-  CWFloat _   `compare` CWUserSort _  = LT
-
-  CWDouble _  `compare` CWAlgReal _   = GT
-  CWDouble _  `compare` CWInteger _   = GT
-  CWDouble _  `compare` CWFloat _     = GT
-  CWDouble a  `compare` CWDouble b    = a `compare` b
-  CWDouble _  `compare` CWUserSort _  = LT
-
-  CWUserSort _ `compare` CWAlgReal _  = GT
-  CWUserSort _ `compare` CWInteger _  = GT
-  CWUserSort _ `compare` CWFloat _    = GT
-  CWUserSort _ `compare` CWDouble _   = GT
-  CWUserSort a `compare` CWUserSort b = a `compare` b
-
--- | 'CW' represents a concrete word of a fixed size:
--- Endianness is mostly irrelevant (see the 'FromBits' class).
--- For signed words, the most significant digit is considered to be the sign.
-data CW = CW { _cwKind  :: !Kind
-             , cwVal    :: !CWVal
-             }
-        deriving (Eq, Ord)
-
--- | 'Kind' instance for CW
-instance HasKind CW where
-  kindOf (CW k _) = k
-
--- | Are two CW's of the same type?
-cwSameType :: CW -> CW -> Bool
-cwSameType x y = kindOf x == kindOf y
-
--- | Convert a CW to a Haskell boolean (NB. Assumes input is well-kinded)
-cwToBool :: CW -> Bool
-cwToBool x = cwVal x /= CWInteger 0
-
--- | Normalize a CW. Essentially performs modular arithmetic to make sure the
--- value can fit in the given bit-size. Note that this is rather tricky for
--- negative values, due to asymmetry. (i.e., an 8-bit negative number represents
--- values in the range -128 to 127; thus we have to be careful on the negative side.)
-normCW :: CW -> CW
-normCW c@(CW (KBounded signed sz) (CWInteger v)) = c { cwVal = CWInteger norm }
- where norm | sz == 0 = 0
-            | signed  = let rg = 2 ^ (sz - 1)
-                        in case divMod v rg of
-                                  (a, b) | even a -> b
-                                  (_, b)          -> b - rg
-            | True    = v `mod` (2 ^ sz)
-normCW c@(CW KBool (CWInteger v)) = c { cwVal = CWInteger (v .&. 1) }
-normCW c = c
-
--- | Constant False as a CW. We represent it using the integer value 0.
-falseCW :: CW
-falseCW = CW KBool (CWInteger 0)
-
--- | Constant True as a CW. We represent it using the integer value 1.
-trueCW :: CW
-trueCW  = CW KBool (CWInteger 1)
-
--- | Lift a unary function through a CW
-liftCW :: (AlgReal -> b) -> (Integer -> b) -> (Float -> b) -> (Double -> b) -> ((Maybe Int, String) -> b) -> CW -> b
-liftCW f _ _ _ _ (CW _ (CWAlgReal v))  = f v
-liftCW _ f _ _ _ (CW _ (CWInteger v))  = f v
-liftCW _ _ f _ _ (CW _ (CWFloat v))    = f v
-liftCW _ _ _ f _ (CW _ (CWDouble v))   = f v
-liftCW _ _ _ _ f (CW _ (CWUserSort v)) = f v
-
--- | Lift a binary function through a CW
-liftCW2 :: (AlgReal -> AlgReal -> b) -> (Integer -> Integer -> b) -> (Float -> Float -> b) -> (Double -> Double -> b) -> ((Maybe Int, String) -> (Maybe Int, String) -> b) -> CW -> CW -> b
-liftCW2 r i f d u x y = case (cwVal x, cwVal y) of
-                         (CWAlgReal a,  CWAlgReal b)  -> r a b
-                         (CWInteger a,  CWInteger b)  -> i a b
-                         (CWFloat a,    CWFloat b)    -> f a b
-                         (CWDouble a,   CWDouble b)   -> d a b
-                         (CWUserSort a, CWUserSort b) -> u a b
-                         _                            -> error $ "SBV.liftCW2: impossible, incompatible args received: " ++ show (x, y)
-
--- | Map a unary function through a CW.
-mapCW :: (AlgReal -> AlgReal) -> (Integer -> Integer) -> (Float -> Float) -> (Double -> Double) -> ((Maybe Int, String) -> (Maybe Int, String)) -> CW -> CW
-mapCW r i f d u x  = normCW $ CW (kindOf x) $ case cwVal x of
-                                               CWAlgReal a  -> CWAlgReal  (r a)
-                                               CWInteger a  -> CWInteger  (i a)
-                                               CWFloat a    -> CWFloat    (f a)
-                                               CWDouble a   -> CWDouble   (d a)
-                                               CWUserSort a -> CWUserSort (u a)
-
--- | Map a binary function through a CW.
-mapCW2 :: (AlgReal -> AlgReal -> AlgReal) -> (Integer -> Integer -> Integer) -> (Float -> Float -> Float) -> (Double -> Double -> Double) -> ((Maybe Int, String) -> (Maybe Int, String) -> (Maybe Int, String)) -> CW -> CW -> CW
-mapCW2 r i f d u x y = case (cwSameType x y, cwVal x, cwVal y) of
-                        (True, CWAlgReal a,  CWAlgReal b)  -> normCW $ CW (kindOf x) (CWAlgReal  (r a b))
-                        (True, CWInteger a,  CWInteger b)  -> normCW $ CW (kindOf x) (CWInteger  (i a b))
-                        (True, CWFloat a,    CWFloat b)    -> normCW $ CW (kindOf x) (CWFloat    (f a b))
-                        (True, CWDouble a,   CWDouble b)   -> normCW $ CW (kindOf x) (CWDouble   (d a b))
-                        (True, CWUserSort a, CWUserSort b) -> normCW $ CW (kindOf x) (CWUserSort (u a b))
-                        _                                  -> error $ "SBV.mapCW2: impossible, incompatible args received: " ++ show (x, y)
-
--- | Show instance for 'CW'.
-instance Show CW where
-  show = showCW True
-
--- | Show a CW, with kind info if bool is True
-showCW :: Bool -> CW -> String
-showCW shk w | isBoolean w = show (cwToBool w) ++ (if shk then " :: Bool" else "")
-showCW shk w               = liftCW show show show show snd w ++ kInfo
-      where kInfo | shk  = " :: " ++ shKind (kindOf w)
-                  | True = ""
-            shKind k@KUserSort {}         = show k
-            shKind k | ('S':sk) <- show k = sk
-            shKind k                      = show k
-
--- | Create a constant word from an integral.
-mkConstCW :: Integral a => Kind -> a -> CW
-mkConstCW KBool           a = normCW $ CW KBool      (CWInteger (toInteger a))
-mkConstCW k@KBounded{}    a = normCW $ CW k          (CWInteger (toInteger a))
-mkConstCW KUnbounded      a = normCW $ CW KUnbounded (CWInteger (toInteger a))
-mkConstCW KReal           a = normCW $ CW KReal      (CWAlgReal (fromInteger (toInteger a)))
-mkConstCW KFloat          a = normCW $ CW KFloat     (CWFloat   (fromInteger (toInteger a)))
-mkConstCW KDouble         a = normCW $ CW KDouble    (CWDouble  (fromInteger (toInteger a)))
-mkConstCW (KUserSort s _) a = error $ "Unexpected call to mkConstCW with uninterpreted kind: " ++ s ++ " with value: " ++ show (toInteger a)
-
--- | Generate a random constant value ('CWVal') of the correct kind.
-randomCWVal :: Kind -> IO CWVal
-randomCWVal k =
-  case k of
-    KBool         -> fmap CWInteger (randomRIO (0,1))
-    KBounded s w  -> fmap CWInteger (randomRIO (bounds s w))
-    KUnbounded    -> fmap CWInteger randomIO
-    KReal         -> fmap CWAlgReal randomIO
-    KFloat        -> fmap CWFloat randomIO
-    KDouble       -> fmap CWDouble randomIO
-    KUserSort s _ -> error $ "Unexpected call to randomCWVal with uninterpreted kind: " ++ s
-  where
-    bounds :: Bool -> Int -> (Integer, Integer)
-    bounds False w = (0, 2^w - 1)
-    bounds True w = (-x, x-1) where x = 2^(w-1)
-
--- | Generate a random constant value ('CW') of the correct kind.
-randomCW :: Kind -> IO CW
-randomCW k = fmap (CW k) (randomCWVal k)
diff --git a/Data/SBV/BitVectors/Data.hs b/Data/SBV/BitVectors/Data.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Data.hs
+++ /dev/null
@@ -1,542 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Data
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Internal data-structures for the sbv library
------------------------------------------------------------------------------
-
-{-# LANGUAGE TypeSynonymInstances  #-}
-{-# LANGUAGE TypeOperators         #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE PatternGuards         #-}
-{-# LANGUAGE DefaultSignatures     #-}
-{-# LANGUAGE NamedFieldPuns        #-}
-
-module Data.SBV.BitVectors.Data
- ( SBool, SWord8, SWord16, SWord32, SWord64
- , SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble
- , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
- , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
- , sRNE, sRNA, sRTP, sRTN, sRTZ
- , SymWord(..)
- , CW(..), CWVal(..), AlgReal(..), cwSameType, cwToBool
- , mkConstCW ,liftCW2, mapCW, mapCW2
- , SW(..), trueSW, falseSW, trueCW, falseCW, normCW
- , SVal(..)
- , SBV(..), NodeId(..), mkSymSBV
- , ArrayContext(..), ArrayInfo, SymArray(..), SFunArray(..), mkSFunArray, SArray(..)
- , sbvToSW, sbvToSymSW, forceSWArg
- , SBVExpr(..), newExpr
- , cache, Cached, uncache, uncacheAI, HasKind(..)
- , Op(..), FPOp(..), NamedSymVar, getTableIndex
- , SBVPgm(..), Symbolic, SExecutable(..), runSymbolic, runSymbolic', State, getPathCondition, extendPathCondition
- , inProofMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
- , Logic(..), SMTLibLogic(..)
- , addConstraint, internalVariable, internalConstraint, isCodeGenMode
- , SBVType(..), newUninterpreted, addAxiom
- , Quantifier(..), needsExistentials
- , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension, smtLibReservedNames
- , SolverCapabilities(..)
- , extractSymbolicSimulationState
- , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), getSBranchRunConfig
- , declNewSArray, declNewSFunArray
- ) where
-
-import Control.DeepSeq      (NFData(..))
-import Control.Monad.Reader (ask)
-import Control.Monad.Trans  (liftIO)
-import Data.Int             (Int8, Int16, Int32, Int64)
-import Data.Word            (Word8, Word16, Word32, Word64)
-import Data.List            (elemIndex, intercalate)
-import Data.Maybe           (fromMaybe)
-
-import qualified Data.Generics as G    (Data(..))
-
-import System.Random
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.Utils.Lib
-
-import Data.SBV.BitVectors.Kind
-import Data.SBV.BitVectors.Concrete
-import Data.SBV.BitVectors.Symbolic
-import Data.SBV.SMT.SMTLibNames
-
-import Prelude ()
-import Prelude.Compat
-
--- | Get the current path condition
-getPathCondition :: State -> SBool
-getPathCondition st = SBV (getSValPathCondition st)
-
--- | Extend the path condition with the given test value.
-extendPathCondition :: State -> (SBool -> SBool) -> State
-extendPathCondition st f = extendSValPathCondition st (unSBV . f . SBV)
-
--- | The "Symbolic" value. The parameter 'a' is phantom, but is
--- extremely important in keeping the user interface strongly typed.
-newtype SBV a = SBV { unSBV :: SVal }
-
--- | A symbolic boolean/bit
-type SBool   = SBV Bool
-
--- | 8-bit unsigned symbolic value
-type SWord8  = SBV Word8
-
--- | 16-bit unsigned symbolic value
-type SWord16 = SBV Word16
-
--- | 32-bit unsigned symbolic value
-type SWord32 = SBV Word32
-
--- | 64-bit unsigned symbolic value
-type SWord64 = SBV Word64
-
--- | 8-bit signed symbolic value, 2's complement representation
-type SInt8   = SBV Int8
-
--- | 16-bit signed symbolic value, 2's complement representation
-type SInt16  = SBV Int16
-
--- | 32-bit signed symbolic value, 2's complement representation
-type SInt32  = SBV Int32
-
--- | 64-bit signed symbolic value, 2's complement representation
-type SInt64  = SBV Int64
-
--- | Infinite precision signed symbolic value
-type SInteger = SBV Integer
-
--- | Infinite precision symbolic algebraic real value
-type SReal = SBV AlgReal
-
--- | IEEE-754 single-precision floating point numbers
-type SFloat = SBV Float
-
--- | IEEE-754 double-precision floating point numbers
-type SDouble = SBV Double
-
--- | Not-A-Number for 'Double' and 'Float'. Surprisingly, Haskell
--- Prelude doesn't have this value defined, so we provide it here.
-nan :: Floating a => a
-nan = 0/0
-
--- | Infinity for 'Double' and 'Float'. Surprisingly, Haskell
--- Prelude doesn't have this value defined, so we provide it here.
-infinity :: Floating a => a
-infinity = 1/0
-
--- | Symbolic variant of Not-A-Number. This value will inhabit both
--- 'SDouble' and 'SFloat'.
-sNaN :: (Floating a, SymWord a) => SBV a
-sNaN = literal nan
-
--- | Symbolic variant of infinity. This value will inhabit both
--- 'SDouble' and 'SFloat'.
-sInfinity :: (Floating a, SymWord a) => SBV a
-sInfinity = literal infinity
-
--- | 'RoundingMode' can be used symbolically
-instance SymWord RoundingMode
-
--- | The symbolic variant of 'RoundingMode'
-type SRoundingMode = SBV RoundingMode
-
--- | Symbolic variant of 'RoundNearestTiesToEven'
-sRoundNearestTiesToEven :: SRoundingMode
-sRoundNearestTiesToEven = literal RoundNearestTiesToEven
-
--- | Symbolic variant of 'RoundNearestTiesToAway'
-sRoundNearestTiesToAway :: SRoundingMode
-sRoundNearestTiesToAway = literal RoundNearestTiesToAway
-
--- | Symbolic variant of 'RoundNearestPositive'
-sRoundTowardPositive :: SRoundingMode
-sRoundTowardPositive = literal RoundTowardPositive
-
--- | Symbolic variant of 'RoundTowardNegative'
-sRoundTowardNegative :: SRoundingMode
-sRoundTowardNegative = literal RoundTowardNegative
-
--- | Symbolic variant of 'RoundTowardZero'
-sRoundTowardZero :: SRoundingMode
-sRoundTowardZero = literal RoundTowardZero
-
--- | Alias for 'sRoundNearestTiesToEven'
-sRNE :: SRoundingMode
-sRNE = sRoundNearestTiesToEven
-
--- | Alias for 'sRoundNearestTiesToAway'
-sRNA :: SRoundingMode
-sRNA = sRoundNearestTiesToAway
-
--- | Alias for 'sRoundTowardPositive'
-sRTP :: SRoundingMode
-sRTP = sRoundTowardPositive
-
--- | Alias for 'sRoundTowardNegative'
-sRTN :: SRoundingMode
-sRTN = sRoundTowardNegative
-
--- | Alias for 'sRoundTowardZero'
-sRTZ :: SRoundingMode
-sRTZ = sRoundTowardZero
-
--- Not particularly "desirable", but will do if needed
-instance Show (SBV a) where
-  show (SBV sv) = show sv
-
--- Equality constraint on SBV values. Not desirable since we can't really compare two
--- symbolic values, but will do.
-instance Eq (SBV a) where
-  SBV a == SBV b = a == b
-  SBV a /= SBV b = a /= b
-
-instance HasKind (SBV a) where
-  kindOf (SBV (SVal k _)) = k
-
--- | Convert a symbolic value to a symbolic-word
-sbvToSW :: State -> SBV a -> IO SW
-sbvToSW st (SBV s) = svToSW st s
-
--------------------------------------------------------------------------
--- * Symbolic Computations
--------------------------------------------------------------------------
-
--- | Create a symbolic variable.
-mkSymSBV :: forall a. Maybe Quantifier -> Kind -> Maybe String -> Symbolic (SBV a)
-mkSymSBV mbQ k mbNm = fmap SBV (svMkSymVar mbQ k mbNm)
-
--- | Convert a symbolic value to an SW, inside the Symbolic monad
-sbvToSymSW :: SBV a -> Symbolic SW
-sbvToSymSW sbv = do
-        st <- ask
-        liftIO $ sbvToSW st sbv
-
--- | A class representing what can be returned from a symbolic computation.
-class Outputtable a where
-  -- | Mark an interim result as an output. Useful when constructing Symbolic programs
-  -- that return multiple values, or when the result is programmatically computed.
-  output :: a -> Symbolic a
-
-instance Outputtable (SBV a) where
-  output i = do
-          outputSVal (unSBV i)
-          return i
-
-instance Outputtable a => Outputtable [a] where
-  output = mapM output
-
-instance Outputtable () where
-  output = return
-
-instance (Outputtable a, Outputtable b) => Outputtable (a, b) where
-  output = mlift2 (,) output output
-
-instance (Outputtable a, Outputtable b, Outputtable c) => Outputtable (a, b, c) where
-  output = mlift3 (,,) output output output
-
-instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d) => Outputtable (a, b, c, d) where
-  output = mlift4 (,,,) output output output output
-
-instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e) => Outputtable (a, b, c, d, e) where
-  output = mlift5 (,,,,) output output output output output
-
-instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f) => Outputtable (a, b, c, d, e, f) where
-  output = mlift6 (,,,,,) output output output output output output
-
-instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g) => Outputtable (a, b, c, d, e, f, g) where
-  output = mlift7 (,,,,,,) output output output output output output output
-
-instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g, Outputtable h) => Outputtable (a, b, c, d, e, f, g, h) where
-  output = mlift8 (,,,,,,,) output output output output output output output output
-
--------------------------------------------------------------------------------
--- * Symbolic Words
--------------------------------------------------------------------------------
--- | A 'SymWord' is a potential symbolic bitvector that can be created instances of
--- to be fed to a symbolic program. Note that these methods are typically not needed
--- in casual uses with 'prove', 'sat', 'allSat' etc, as default instances automatically
--- provide the necessary bits.
-class (HasKind a, Ord a) => SymWord a where
-  -- | Create a user named input (universal)
-  forall :: String -> Symbolic (SBV a)
-  -- | Create an automatically named input
-  forall_ :: Symbolic (SBV a)
-  -- | Get a bunch of new words
-  mkForallVars :: Int -> Symbolic [SBV a]
-  -- | Create an existential variable
-  exists  :: String -> Symbolic (SBV a)
-  -- | Create an automatically named existential variable
-  exists_ :: Symbolic (SBV a)
-  -- | Create a bunch of existentials
-  mkExistVars :: Int -> Symbolic [SBV a]
-  -- | Create a free variable, universal in a proof, existential in sat
-  free :: String -> Symbolic (SBV a)
-  -- | Create an unnamed free variable, universal in proof, existential in sat
-  free_ :: Symbolic (SBV a)
-  -- | Create a bunch of free vars
-  mkFreeVars :: Int -> Symbolic [SBV a]
-  -- | Similar to free; Just a more convenient name
-  symbolic  :: String -> Symbolic (SBV a)
-  -- | Similar to mkFreeVars; but automatically gives names based on the strings
-  symbolics :: [String] -> Symbolic [SBV a]
-  -- | Turn a literal constant to symbolic
-  literal :: a -> SBV a
-  -- | Extract a literal, if the value is concrete
-  unliteral :: SBV a -> Maybe a
-  -- | Extract a literal, from a CW representation
-  fromCW :: CW -> a
-  -- | Is the symbolic word concrete?
-  isConcrete :: SBV a -> Bool
-  -- | Is the symbolic word really symbolic?
-  isSymbolic :: SBV a -> Bool
-  -- | Does it concretely satisfy the given predicate?
-  isConcretely :: SBV a -> (a -> Bool) -> Bool
-  -- | One stop allocator
-  mkSymWord :: Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
-
-  -- minimal complete definition:: Nothing.
-  -- Giving no instances is ok when defining an uninterpreted/enumerated sort, but otherwise you really
-  -- want to define: literal, fromCW, mkSymWord
-  forall   = mkSymWord (Just ALL) . Just
-  forall_  = mkSymWord (Just ALL)   Nothing
-  exists   = mkSymWord (Just EX)  . Just
-  exists_  = mkSymWord (Just EX)    Nothing
-  free     = mkSymWord Nothing    . Just
-  free_    = mkSymWord Nothing      Nothing
-  mkForallVars n = mapM (const forall_) [1 .. n]
-  mkExistVars n  = mapM (const exists_) [1 .. n]
-  mkFreeVars n   = mapM (const free_)   [1 .. n]
-  symbolic       = free
-  symbolics      = mapM symbolic
-  unliteral (SBV (SVal _ (Left c)))  = Just $ fromCW c
-  unliteral _                        = Nothing
-  isConcrete (SBV (SVal _ (Left _))) = True
-  isConcrete _                       = False
-  isSymbolic = not . isConcrete
-  isConcretely s p
-    | Just i <- unliteral s = p i
-    | True                  = False
-
-  default literal :: Show a => a -> SBV a
-  literal x = let k@(KUserSort  _ conts) = kindOf x
-                  sx                     = show x
-                  mbIdx = case conts of
-                            Right xs -> sx `elemIndex` xs
-                            _        -> Nothing
-              in SBV $ SVal k (Left (CW k (CWUserSort (mbIdx, sx))))
-
-  default fromCW :: Read a => CW -> a
-  fromCW (CW _ (CWUserSort (_, s))) = read s
-  fromCW cw                         = error $ "Cannot convert CW " ++ show cw ++ " to kind " ++ show (kindOf (undefined :: a))
-
-  default mkSymWord :: (Read a, G.Data a) => Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
-  mkSymWord mbQ mbNm = SBV <$> mkSValUserSort k mbQ mbNm
-    where k = constructUKind (undefined :: a)
-
-instance (Random a, SymWord a) => Random (SBV a) where
-  randomR (l, h) g = case (unliteral l, unliteral h) of
-                       (Just lb, Just hb) -> let (v, g') = randomR (lb, hb) g in (literal (v :: a), g')
-                       _                  -> error "SBV.Random: Cannot generate random values with symbolic bounds"
-  random         g = let (v, g') = random g in (literal (v :: a) , g')
----------------------------------------------------------------------------------
--- * Symbolic Arrays
----------------------------------------------------------------------------------
-
--- | Flat arrays of symbolic values
--- An @array a b@ is an array indexed by the type @'SBV' a@, with elements of type @'SBV' b@
--- If an initial value is not provided in 'newArray_' and 'newArray' methods, then the elements
--- are left unspecified, i.e., the solver is free to choose any value. This is the right thing
--- to do if arrays are used as inputs to functions to be verified, typically. 
---
--- While it's certainly possible for user to create instances of 'SymArray', the
--- 'SArray' and 'SFunArray' instances already provided should cover most use cases
--- in practice. (There are some differences between these models, however, see the corresponding
--- declaration.)
---
---
--- Minimal complete definition: All methods are required, no defaults.
-class SymArray array where
-  -- | Create a new array, with an optional initial value
-  newArray_      :: (HasKind a, HasKind b) => Maybe (SBV b) -> Symbolic (array a b)
-  -- | Create a named new array, with an optional initial value
-  newArray       :: (HasKind a, HasKind b) => String -> Maybe (SBV b) -> Symbolic (array a b)
-  -- | Read the array element at @a@
-  readArray      :: array a b -> SBV a -> SBV b
-  -- | Reset all the elements of the array to the value @b@
-  resetArray     :: SymWord b => array a b -> SBV b -> array a b
-  -- | Update the element at @a@ to be @b@
-  writeArray     :: SymWord b => array a b -> SBV a -> SBV b -> array a b
-  -- | Merge two given arrays on the symbolic condition
-  -- Intuitively: @mergeArrays cond a b = if cond then a else b@.
-  -- Merging pushes the if-then-else choice down on to elements
-  mergeArrays    :: SymWord b => SBV Bool -> array a b -> array a b -> array a b
-
--- | Arrays implemented in terms of SMT-arrays: <http://smtlib.cs.uiowa.edu/theories-ArraysEx.shtml>
---
---   * Maps directly to SMT-lib arrays
---
---   * Reading from an unintialized value is OK and yields an unspecified result
---
---   * Can check for equality of these arrays
---
---   * Cannot quick-check theorems using @SArray@ values
---
---   * Typically slower as it heavily relies on SMT-solving for the array theory
---
-newtype SArray a b = SArray { unSArray :: SArr }
-
-instance (HasKind a, HasKind b) => Show (SArray a b) where
-  show SArray{} = "SArray<" ++ showType (undefined :: a) ++ ":" ++ showType (undefined :: b) ++ ">"
-
-instance SymArray SArray where
-  newArray_                                      = declNewSArray (\t -> "array_" ++ show t)
-  newArray n                                     = declNewSArray (const n)
-  readArray   (SArray arr) (SBV a)               = SBV (readSArr arr a)
-  resetArray  (SArray arr) (SBV b)               = SArray (resetSArr arr b)
-  writeArray  (SArray arr) (SBV a)    (SBV b)    = SArray (writeSArr arr a b)
-  mergeArrays (SBV t)      (SArray a) (SArray b) = SArray (mergeSArr t a b)
-
--- | Declare a new symbolic array, with a potential initial value
-declNewSArray :: forall a b. (HasKind a, HasKind b) => (Int -> String) -> Maybe (SBV b) -> Symbolic (SArray a b)
-declNewSArray mkNm mbInit = do
-   let aknd = kindOf (undefined :: a)
-       bknd = kindOf (undefined :: b)
-   arr <- newSArr (aknd, bknd) mkNm (fmap unSBV mbInit)
-   return (SArray arr)
-
--- | Declare a new functional symbolic array, with a potential initial value. Note that a read from an uninitialized cell will result in an error.
-declNewSFunArray :: forall a b. (HasKind a, HasKind b) => Maybe (SBV b) -> Symbolic (SFunArray a b)
-declNewSFunArray mbiVal = return $ SFunArray $ const $ fromMaybe (error "Reading from an uninitialized array entry") mbiVal
-
--- | Arrays implemented internally as functions
---
---    * Internally handled by the library and not mapped to SMT-Lib
---
---    * Reading an uninitialized value is considered an error (will throw exception)
---
---    * Cannot check for equality (internally represented as functions)
---
---    * Can quick-check
---
---    * Typically faster as it gets compiled away during translation
---
-newtype SFunArray a b = SFunArray (SBV a -> SBV b)
-
-instance (HasKind a, HasKind b) => Show (SFunArray a b) where
-  show (SFunArray _) = "SFunArray<" ++ showType (undefined :: a) ++ ":" ++ showType (undefined :: b) ++ ">"
-
--- | Lift a function to an array. Useful for creating arrays in a pure context. (Otherwise use `newArray`.)
-mkSFunArray :: (SBV a -> SBV b) -> SFunArray a b
-mkSFunArray = SFunArray
-
--- | Add a constraint with a given probability
-addConstraint :: Maybe Double -> SBool -> SBool -> Symbolic ()
-addConstraint mt (SBV c) (SBV c') = addSValConstraint mt c c'
-
-instance NFData (SBV a) where
-  rnf (SBV x) = rnf x `seq` ()
-
--- | Symbolically executable program fragments. This class is mainly used for 'safe' calls, and is sufficently populated internally to cover most use
--- cases. Users can extend it as they wish to allow 'safe' checks for SBV programs that return/take types that are user-defined.
-class SExecutable a where
-   sName_ :: a -> Symbolic ()
-   sName  :: [String] -> a -> Symbolic ()
-
-instance NFData a => SExecutable (Symbolic a) where
-   sName_   a = a >>= \r -> rnf r `seq` return ()
-   sName []   = sName_
-   sName xs   = error $ "SBV.SExecutable.sName: Extra unmapped name(s): " ++ intercalate ", " xs
-
-instance SExecutable (SBV a) where
-   sName_   v = sName_ (output v)
-   sName xs v = sName xs (output v)
-
--- Unit output
-instance SExecutable () where
-   sName_   () = sName_   (output ())
-   sName xs () = sName xs (output ())
-
--- List output
-instance SExecutable [SBV a] where
-   sName_   vs = sName_   (output vs)
-   sName xs vs = sName xs (output vs)
-
--- 2 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b) => SExecutable (SBV a, SBV b) where
-  sName_ (a, b) = sName_ (output a >> output b)
-  sName _       = sName_
-
--- 3 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c) => SExecutable (SBV a, SBV b, SBV c) where
-  sName_ (a, b, c) = sName_ (output a >> output b >> output c)
-  sName _          = sName_
-
--- 4 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d) => SExecutable (SBV a, SBV b, SBV c, SBV d) where
-  sName_ (a, b, c, d) = sName_ (output a >> output b >> output c >> output c >> output d)
-  sName _             = sName_
-
--- 5 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e) where
-  sName_ (a, b, c, d, e) = sName_ (output a >> output b >> output c >> output d >> output e)
-  sName _                = sName_
-
--- 6 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e, NFData f, SymWord f) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) where
-  sName_ (a, b, c, d, e, f) = sName_ (output a >> output b >> output c >> output d >> output e >> output f)
-  sName _                   = sName_
-
--- 7 Tuple output
-instance (NFData a, SymWord a, NFData b, SymWord b, NFData c, SymWord c, NFData d, SymWord d, NFData e, SymWord e, NFData f, SymWord f, NFData g, SymWord g) => SExecutable (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) where
-  sName_ (a, b, c, d, e, f, g) = sName_ (output a >> output b >> output c >> output d >> output e >> output f >> output g)
-  sName _                      = sName_
-
--- Functions
-instance (SymWord a, SExecutable p) => SExecutable (SBV a -> p) where
-   sName_        k = forall_   >>= \a -> sName_   $ k a
-   sName (s:ss)  k = forall s  >>= \a -> sName ss $ k a
-   sName []      k = sName_ k
-
--- 2 Tuple input
-instance (SymWord a, SymWord b, SExecutable p) => SExecutable ((SBV a, SBV b) -> p) where
-  sName_        k = forall_  >>= \a -> sName_   $ \b -> k (a, b)
-  sName (s:ss)  k = forall s >>= \a -> sName ss $ \b -> k (a, b)
-  sName []      k = sName_ k
-
--- 3 Tuple input
-instance (SymWord a, SymWord b, SymWord c, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c) -> p) where
-  sName_       k  = forall_  >>= \a -> sName_   $ \b c -> k (a, b, c)
-  sName (s:ss) k  = forall s >>= \a -> sName ss $ \b c -> k (a, b, c)
-  sName []     k  = sName_ k
-
--- 4 Tuple input
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d) -> p) where
-  sName_        k = forall_  >>= \a -> sName_   $ \b c d -> k (a, b, c, d)
-  sName (s:ss)  k = forall s >>= \a -> sName ss $ \b c d -> k (a, b, c, d)
-  sName []      k = sName_ k
-
--- 5 Tuple input
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
-  sName_        k = forall_  >>= \a -> sName_   $ \b c d e -> k (a, b, c, d, e)
-  sName (s:ss)  k = forall s >>= \a -> sName ss $ \b c d e -> k (a, b, c, d, e)
-  sName []      k = sName_ k
-
--- 6 Tuple input
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
-  sName_        k = forall_  >>= \a -> sName_   $ \b c d e f -> k (a, b, c, d, e, f)
-  sName (s:ss)  k = forall s >>= \a -> sName ss $ \b c d e f -> k (a, b, c, d, e, f)
-  sName []      k = sName_ k
-
--- 7 Tuple input
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SymWord g, SExecutable p) => SExecutable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
-  sName_        k = forall_  >>= \a -> sName_   $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  sName (s:ss)  k = forall s >>= \a -> sName ss $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  sName []      k = sName_ k
diff --git a/Data/SBV/BitVectors/Floating.hs b/Data/SBV/BitVectors/Floating.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Floating.hs
+++ /dev/null
@@ -1,446 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Floating
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Implementation of floating-point operations mapping to SMT-Lib2 floats
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.BitVectors.Floating (
-         IEEEFloating(..), IEEEFloatConvertable(..)
-       , sFloatAsSWord32, sDoubleAsSWord64, sWord32AsSFloat, sWord64AsSDouble
-       , blastSFloat, blastSDouble
-       ) where
-
-import Control.Monad (join)
-
-import qualified Data.Binary.IEEE754 as DB (wordToFloat, wordToDouble, floatToWord, doubleToWord)
-
-import Data.Int            (Int8,  Int16,  Int32,  Int64)
-import Data.Word           (Word8, Word16, Word32, Word64)
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model
-import Data.SBV.BitVectors.AlgReals (isExactRational)
-import Data.SBV.Utils.Boolean
-import Data.SBV.Utils.Numeric
-
--- | 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
--- not concretely evaluate these, but rather pass down to the SMT solver.
-class (SymWord a, RealFloat a) => IEEEFloating a where
-  -- | Compute the floating point absolute value.
-  fpAbs             ::                  SBV a -> SBV a
-
-  -- | Compute the unary negation. Note that @0 - x@ is not equivalent to @-x@ for floating-point, since @-0@ and @0@ are different.
-  fpNeg             ::                  SBV a -> SBV a
-
-  -- | Add two floating point values, using the given rounding mode
-  fpAdd             :: SRoundingMode -> SBV a -> SBV a -> SBV a
-
-  -- | Subtract two floating point values, using the given rounding mode
-  fpSub             :: SRoundingMode -> SBV a -> SBV a -> SBV a
-
-  -- | Multiply two floating point values, using the given rounding mode
-  fpMul             :: SRoundingMode -> SBV a -> SBV a -> SBV a
-
-  -- | Divide two floating point values, using the given rounding mode
-  fpDiv             :: SRoundingMode -> SBV a -> SBV a -> SBV a
-
-  -- | Fused-multiply-add three floating point values, using the given rounding mode. @fpFMA x y z = x*y+z@ but with only
-  -- one rounding done for the whole operation; not two. Note that we will never concretely evaluate this function since
-  -- Haskell lacks an FMA implementation.
-  fpFMA             :: SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
-
-  -- | Compute the square-root of a float, using the given rounding mode
-  fpSqrt            :: SRoundingMode -> SBV a -> SBV a
-
-  -- | Compute the remainder: @x - y * n@, where @n@ is the truncated integer nearest to x/y. The rounding mode
-  -- is implicitly assumed to be @RoundNearestTiesToEven@.
-  fpRem             ::                  SBV a -> SBV a -> SBV a
-
-  -- | Round to the nearest integral value, using the given rounding mode.
-  fpRoundToIntegral :: SRoundingMode -> SBV a -> SBV a
-
-  -- | Compute the minimum of two floats, respects @infinity@ and @NaN@ values
-  fpMin             ::                  SBV a -> SBV a -> SBV a
-
-  -- | Compute the maximum of two floats, respects @infinity@ and @NaN@ values
-  fpMax             ::                  SBV a -> SBV a -> SBV a
-
-  -- | Are the two given floats exactly the same. That is, @NaN@ will compare equal to itself, @+0@ will /not/ compare
-  -- equal to @-0@ etc. This is the object level equality, as opposed to the semantic equality. (For the latter, just use '.=='.)
-  fpIsEqualObject   ::                  SBV a -> SBV a -> SBool
-
-  -- | Is the floating-point number a normal value. (i.e., not denormalized.)
-  fpIsNormal :: SBV a -> SBool
-
-  -- | Is the floating-point number a subnormal value. (Also known as denormal.)
-  fpIsSubnormal :: SBV a -> SBool
-
-  -- | Is the floating-point number 0? (Note that both +0 and -0 will satisfy this predicate.)
-  fpIsZero :: SBV a -> SBool
-
-  -- | Is the floating-point number infinity? (Note that both +oo and -oo will satisfy this predicate.)
-  fpIsInfinite :: SBV a -> SBool
-
-  -- | Is the floating-point number a NaN value?
-  fpIsNaN ::  SBV a -> SBool
-
-  -- | Is the floating-point number negative? Note that -0 satisfies this predicate but +0 does not.
-  fpIsNegative :: SBV a -> SBool
-
-  -- | Is the floating-point number positive? Note that +0 satisfies this predicate but -0 does not.
-  fpIsPositive :: SBV a -> SBool
-
-  -- | Is the floating point number -0?
-  fpIsNegativeZero :: SBV a -> SBool
-
-  -- | Is the floating point number +0?
-  fpIsPositiveZero :: SBV a -> SBool
-
-  -- | Is the floating-point number a regular floating point, i.e., not NaN, nor +oo, nor -oo. Normals or denormals are allowed.
-  fpIsPoint :: SBV a -> SBool
-
-  -- Default definitions. Minimal complete definition: None! All should be taken care by defaults
-  -- Note that we never evaluate FMA concretely, as there's no fma operator in Haskell
-  fpAbs              = lift1  FP_Abs             (Just abs)                Nothing
-  fpNeg              = lift1  FP_Neg             (Just negate)             Nothing
-  fpAdd              = lift2  FP_Add             (Just (+))                . Just
-  fpSub              = lift2  FP_Sub             (Just (-))                . Just
-  fpMul              = lift2  FP_Mul             (Just (*))                . Just
-  fpDiv              = lift2  FP_Div             (Just (/))                . Just
-  fpFMA              = lift3  FP_FMA             Nothing                   . Just
-  fpSqrt             = lift1  FP_Sqrt            (Just sqrt)               . Just
-  fpRem              = lift2  FP_Rem             (Just fpRemH)             Nothing
-  fpRoundToIntegral  = lift1  FP_RoundToIntegral (Just fpRoundToIntegralH) . Just
-  fpMin              = liftMM FP_Min             (Just fpMinH)             Nothing
-  fpMax              = liftMM FP_Max             (Just fpMaxH)             Nothing
-  fpIsEqualObject    = lift2B FP_ObjEqual        (Just fpIsEqualObjectH)   Nothing
-  fpIsNormal         = lift1B FP_IsNormal        fpIsNormalizedH
-  fpIsSubnormal      = lift1B FP_IsSubnormal     isDenormalized
-  fpIsZero           = lift1B FP_IsZero          (== 0)
-  fpIsInfinite       = lift1B FP_IsInfinite      isInfinite
-  fpIsNaN            = lift1B FP_IsNaN           isNaN
-  fpIsNegative       = lift1B FP_IsNegative      (\x -> x < 0 ||       isNegativeZero x)
-  fpIsPositive       = lift1B FP_IsPositive      (\x -> x >= 0 && not (isNegativeZero x))
-  fpIsNegativeZero x = fpIsZero x &&& fpIsNegative x
-  fpIsPositiveZero x = fpIsZero x &&& fpIsPositive x
-  fpIsPoint        x = bnot (fpIsNaN x ||| fpIsInfinite x)
-
--- | SFloat instance
-instance IEEEFloating Float
-
--- | 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. (SymWord a, HasKind r, SymWord 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 (undefined :: r)
-        y st    = do msw <- sbvToSW st rm
-                     xsw <- sbvToSW st f
-                     newExpr st kTo (SBVApp (IEEEFP (FP_Cast kFrom kTo msw)) [xsw])
-
--- | Check that a given float is a point
-ptCheck :: IEEEFloating a => Maybe (SBV a -> SBool)
-ptCheck = Just fpIsPoint
-
-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)
-
-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)
-
-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)
-
-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)
-
-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)
-
-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)
-
-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 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)
-
-instance IEEEFloatConvertable Float where
-  fromSFloat _ f = f
-  toSFloat   _ f = f
-  fromSDouble    = genericFPConverter Nothing Nothing fp2fp
-  toSDouble      = genericFPConverter Nothing Nothing fp2fp
-
-instance IEEEFloatConvertable Double where
-  fromSFloat      = genericFPConverter Nothing Nothing fp2fp
-  toSFloat        = genericFPConverter Nothing Nothing fp2fp
-  fromSDouble _ d = d
-  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)
-
--- 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)
-
--- | Concretely evaluate one arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
-concEval1 :: SymWord a => Maybe (a -> a) -> Maybe SRoundingMode -> SBV a -> Maybe (SBV a)
-concEval1 mbOp mbRm a = do op <- mbOp
-                           v  <- unliteral a
-                           case join (unliteral `fmap` mbRm) of
-                             Nothing                     -> (Just . literal) (op v)
-                             Just RoundNearestTiesToEven -> (Just . literal) (op v)
-                             _                           -> Nothing
-
--- | Concretely evaluate two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
-concEval2 :: SymWord a => Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> Maybe (SBV a)
-concEval2 mbOp mbRm a b  = do op <- mbOp
-                              v1 <- unliteral a
-                              v2 <- unliteral b
-                              case join (unliteral `fmap` mbRm) of
-                                Nothing                     -> (Just . literal) (v1 `op` v2)
-                                Just RoundNearestTiesToEven -> (Just . literal) (v1 `op` v2)
-                                _                           -> Nothing
-
--- | Concretely evaluate a bool producing two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
-concEval2B :: SymWord a => Maybe (a -> a -> Bool) -> Maybe SRoundingMode -> SBV a -> SBV a -> Maybe SBool
-concEval2B mbOp mbRm a b  = do op <- mbOp
-                               v1 <- unliteral a
-                               v2 <- unliteral b
-                               case join (unliteral `fmap` mbRm) of
-                                 Nothing                     -> (Just . literal) (v1 `op` v2)
-                                 Just RoundNearestTiesToEven -> (Just . literal) (v1 `op` v2)
-                                 _                           -> Nothing
-
--- | Concretely evaluate two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
-concEval3 :: SymWord a => Maybe (a -> a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a -> Maybe (SBV a)
-concEval3 mbOp mbRm a b c = do op <- mbOp
-                               v1 <- unliteral a
-                               v2 <- unliteral b
-                               v3 <- unliteral c
-                               case join (unliteral `fmap` mbRm) of
-                                 Nothing                     -> (Just . literal) (op v1 v2 v3)
-                                 Just RoundNearestTiesToEven -> (Just . literal) (op v1 v2 v3)
-                                 _                           -> Nothing
-
--- | Add the converted rounding mode if given as an argument
-addRM :: State -> Maybe SRoundingMode -> [SW] -> IO [SW]
-addRM _  Nothing   as = return as
-addRM st (Just rm) as = do swm <- sbvToSW st rm
-                           return (swm : as)
-
--- | Lift a 1 arg FP-op
-lift1 :: SymWord a => FPOp -> Maybe (a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a
-lift1 w mbOp mbRm a
-  | Just cv <- concEval1 mbOp mbRm a
-  = cv
-  | True
-  = SBV $ SVal k $ Right $ cache r
-  where k    = kindOf a
-        r st = do swa  <- sbvToSW st a
-                  args <- addRM st mbRm [swa]
-                  newExpr st k (SBVApp (IEEEFP w) args)
-
--- | Lift an FP predicate
-lift1B :: SymWord a => FPOp -> (a -> Bool) -> SBV a -> SBool
-lift1B w f a
-   | Just v <- unliteral a = literal $ f v
-   | True                  = SBV $ SVal KBool $ Right $ cache r
-   where r st = do swa <- sbvToSW st a
-                   newExpr st KBool (SBVApp (IEEEFP w) [swa])
-
-
--- | Lift a 2 arg FP-op
-lift2 :: SymWord a => FPOp -> Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a
-lift2 w mbOp mbRm a b
-  | Just cv <- concEval2 mbOp mbRm a b
-  = cv
-  | True
-  = SBV $ SVal k $ Right $ cache r
-  where k    = kindOf a
-        r st = do swa  <- sbvToSW st a
-                  swb  <- sbvToSW st b
-                  args <- addRM st mbRm [swa, swb]
-                  newExpr st k (SBVApp (IEEEFP w) args)
-
--- | Lift min/max: Note that we protect against constant folding if args are alternating sign 0's, since
--- SMTLib is deliberately nondeterministic in this case
-liftMM :: (SymWord a, RealFloat a) => FPOp -> Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a
-liftMM w mbOp mbRm a b
-  | Just v1 <- unliteral a
-  , Just v2 <- unliteral b
-  , not ((isN0 v1 && isP0 v2) || (isP0 v1 && isN0 v2))          -- If not +0/-0 or -0/+0
-  , Just cv <- concEval2 mbOp mbRm a b
-  = cv
-  | True
-  = SBV $ SVal k $ Right $ cache r
-  where isN0   = isNegativeZero
-        isP0 x = x == 0 && not (isN0 x)
-        k    = kindOf a
-        r st = do swa  <- sbvToSW st a
-                  swb  <- sbvToSW st b
-                  args <- addRM st mbRm [swa, swb]
-                  newExpr st k (SBVApp (IEEEFP w) args)
-
--- | Lift a 2 arg FP-op, producing bool
-lift2B :: SymWord a => FPOp -> Maybe (a -> a -> Bool) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBool
-lift2B w mbOp mbRm a b
-  | Just cv <- concEval2B mbOp mbRm a b
-  = cv
-  | True
-  = SBV $ SVal KBool $ Right $ cache r
-  where r st = do swa  <- sbvToSW st a
-                  swb  <- sbvToSW st b
-                  args <- addRM st mbRm [swa, swb]
-                  newExpr st KBool (SBVApp (IEEEFP w) args)
-
--- | Lift a 3 arg FP-op
-lift3 :: SymWord a => FPOp -> Maybe (a -> a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
-lift3 w mbOp mbRm a b c
-  | Just cv <- concEval3 mbOp mbRm a b c
-  = cv
-  | True
-  = SBV $ SVal k $ Right $ cache r
-  where k    = kindOf a
-        r st = do swa  <- sbvToSW st a
-                  swb  <- sbvToSW st b
-                  swc  <- sbvToSW st c
-                  args <- addRM st mbRm [swa, swb, swc]
-                  newExpr st k (SBVApp (IEEEFP w) args)
-
--- | Convert an 'SFloat' to an 'SWord32', preserving the bit-correspondence. Note that since the
--- representation for @NaN@s are not unique, this function will return a symbolic value when given a
--- concrete @NaN@.
---
--- Implementation note: Since there's no corresponding function in SMTLib for conversion to
--- bit-representation due to partiality, we use a translation trick by allocating a new word variable,
--- converting it to float, and requiring it to be equivalent to the input. In code-generation mode, we simply map
--- it to a simple conversion.
-sFloatAsSWord32 :: SFloat -> SWord32
-sFloatAsSWord32 fVal
-  | Just f <- unliteral fVal, not (isNaN f)
-  = literal (DB.floatToWord f)
-  | True
-  = SBV (SVal w32 (Right (cache y)))
-  where w32  = KBounded False 32
-        y st | isCodeGenMode st
-             = do f <- sbvToSW st fVal
-                  newExpr st w32 (SBVApp (IEEEFP (FP_Reinterpret KFloat w32)) [f])
-             | True
-             = do n   <- internalVariable st w32
-                  ysw <- newExpr st KFloat (SBVApp (IEEEFP (FP_Reinterpret w32 KFloat)) [n])
-                  internalConstraint st $ unSBV $ fVal `fpIsEqualObject` SBV (SVal KFloat (Right (cache (\_ -> return ysw))))
-                  return n
-
--- | Convert an 'SDouble' to an 'SWord64', preserving the bit-correspondence. Note that since the
--- representation for @NaN@s are not unique, this function will return a symbolic value when given a
--- concrete @NaN@.
---
--- See the implementation note for 'sFloatAsSWord32', as it applies here as well.
-sDoubleAsSWord64 :: SDouble -> SWord64
-sDoubleAsSWord64 fVal
-  | Just f <- unliteral fVal, not (isNaN f)
-  = literal (DB.doubleToWord f)
-  | True
-  = SBV (SVal w64 (Right (cache y)))
-  where w64  = KBounded False 64
-        y st | isCodeGenMode st
-             = do f <- sbvToSW st fVal
-                  newExpr st w64 (SBVApp (IEEEFP (FP_Reinterpret KDouble w64)) [f])
-             | True
-             = do n   <- internalVariable st w64
-                  ysw <- newExpr st KDouble (SBVApp (IEEEFP (FP_Reinterpret w64 KDouble)) [n])
-                  internalConstraint st $ unSBV $ fVal `fpIsEqualObject` SBV (SVal KDouble (Right (cache (\_ -> return ysw))))
-                  return n
-
--- | Extract the sign\/exponent\/mantissa of a single-precision float. The output will have
--- 8 bits in the second argument for exponent, and 23 in the third for the mantissa.
-blastSFloat :: SFloat -> (SBool, [SBool], [SBool])
-blastSFloat = extract . sFloatAsSWord32
- where extract x = (sTestBit x 31, sExtractBits x [30, 29 .. 23], sExtractBits x [22, 21 .. 0])
-
--- | Extract the sign\/exponent\/mantissa of a single-precision float. The output will have
--- 11 bits in the second argument for exponent, and 52 in the third for the mantissa.
-blastSDouble :: SDouble -> (SBool, [SBool], [SBool])
-blastSDouble = extract . sDoubleAsSWord64
- where extract x = (sTestBit x 63, sExtractBits x [62, 61 .. 52], sExtractBits x [51, 50 .. 0])
-
--- | Reinterpret the bits in a 32-bit word as a single-precision floating point number
-sWord32AsSFloat :: SWord32 -> SFloat
-sWord32AsSFloat fVal
-  | Just f <- unliteral fVal = literal $ DB.wordToFloat f
-  | True                     = SBV (SVal KFloat (Right (cache y)))
-  where y st = do xsw <- sbvToSW st fVal
-                  newExpr st KFloat (SBVApp (IEEEFP (FP_Reinterpret (kindOf fVal) KFloat)) [xsw])
-
--- | Reinterpret the bits in a 32-bit word as a single-precision floating point number
-sWord64AsSDouble :: SWord64 -> SDouble
-sWord64AsSDouble dVal
-  | Just d <- unliteral dVal = literal $ DB.wordToDouble d
-  | True                     = SBV (SVal KDouble (Right (cache y)))
-  where y st = do xsw <- sbvToSW st dVal
-                  newExpr st KDouble (SBVApp (IEEEFP (FP_Reinterpret (kindOf dVal) KDouble)) [xsw])
-
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/BitVectors/Kind.hs b/Data/SBV/BitVectors/Kind.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Kind.hs
+++ /dev/null
@@ -1,160 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Kind
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Internal data-structures for the sbv library
------------------------------------------------------------------------------
-
-{-# LANGUAGE    DefaultSignatures   #-}
-{-# LANGUAGE    ScopedTypeVariables #-}
-{-# OPTIONS_GHC -fno-warn-orphans   #-}
-
-module Data.SBV.BitVectors.Kind (Kind(..), HasKind(..), constructUKind) where
-
-import qualified Data.Generics as G (Data(..), DataType, dataTypeName, dataTypeOf, tyconUQname, dataTypeConstrs, constrFields)
-
-import Data.Int
-import Data.Word
-import Data.SBV.BitVectors.AlgReals
-
--- | Kind of symbolic value
-data Kind = KBool
-          | KBounded !Bool !Int
-          | KUnbounded
-          | KReal
-          | KUserSort String (Either String [String])
-          | KFloat
-          | KDouble
-
--- | Helper for Eq/Ord instances below
-kindRank :: Kind -> Either Int (Either (Bool, Int) String)
-kindRank KBool           = Left 0
-kindRank (KBounded  b i) = Right (Left (b, i))
-kindRank KUnbounded      = Left 1
-kindRank KReal           = Left 2
-kindRank (KUserSort s _) = Right (Right s)
-kindRank KFloat          = Left 3
-kindRank KDouble         = Left 4
-{-# INLINE kindRank #-}
-
--- | We want to equate user-sorts only by name
-instance Eq Kind where
-  k1 == k2 = kindRank k1 == kindRank k2
-
--- | We want to order user-sorts only by name
-instance Ord Kind where
-  k1 `compare` k2 = kindRank k1 `compare` kindRank k2
-
-instance Show Kind where
-  show KBool              = "SBool"
-  show (KBounded False n) = "SWord" ++ show n
-  show (KBounded True n)  = "SInt"  ++ show n
-  show KUnbounded         = "SInteger"
-  show KReal              = "SReal"
-  show (KUserSort s _)    = s
-  show KFloat             = "SFloat"
-  show KDouble            = "SDouble"
-
-instance Eq  G.DataType where
-   a == b = G.tyconUQname (G.dataTypeName a) == G.tyconUQname (G.dataTypeName b)
-
-instance Ord G.DataType where
-   a `compare` b = G.tyconUQname (G.dataTypeName a) `compare` G.tyconUQname (G.dataTypeName b)
-
--- | Does this kind represent a signed quantity?
-kindHasSign :: Kind -> Bool
-kindHasSign k =
-  case k of
-    KBool        -> False
-    KBounded b _ -> b
-    KUnbounded   -> True
-    KReal        -> True
-    KFloat       -> True
-    KDouble      -> True
-    KUserSort{}  -> 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
-constructUKind :: forall a. (Read a, G.Data a) => a -> Kind
-constructUKind a = KUserSort sortName mbEnumFields
-  where dataType      = G.dataTypeOf a
-        sortName      = G.tyconUQname . G.dataTypeName $ dataType
-        constrs       = G.dataTypeConstrs dataType
-        isEnumeration = not (null constrs) && all (null . G.constrFields) constrs
-        mbEnumFields
-         | isEnumeration = check constrs []
-         | True          = Left $ sortName ++ "is not a finite non-empty enumeration"
-        check []     sofar = Right $ reverse sofar
-        check (c:cs) sofar = case checkConstr c of
-                                Nothing -> check cs (show c : sofar)
-                                Just s  -> Left $ sortName ++ "." ++ show c ++ ": " ++ s
-        checkConstr c = case (reads (show c) :: [(a, String)]) of
-                          ((_, "") : _)  -> Nothing
-                          _              -> Just "not a nullary constructor"
-
--- | A class for capturing values that have a sign and a size (finite or infinite)
--- minimal complete definition: kindOf. This class can be automatically derived
--- for data-types that have a 'Data' instance; this is useful for creating uninterpreted
--- sorts.
-class HasKind a where
-  kindOf          :: a -> Kind
-  hasSign         :: a -> Bool
-  intSizeOf       :: a -> Int
-  isBoolean       :: a -> Bool
-  isBounded       :: a -> Bool   -- NB. This really means word/int; i.e., Real/Float will test False
-  isReal          :: a -> Bool
-  isFloat         :: a -> Bool
-  isDouble        :: a -> Bool
-  isInteger       :: a -> Bool
-  isUninterpreted :: a -> Bool
-  showType        :: a -> String
-  -- defaults
-  hasSign x = kindHasSign (kindOf x)
-  intSizeOf x = case kindOf x of
-                  KBool         -> error "SBV.HasKind.intSizeOf((S)Bool)"
-                  KBounded _ s  -> s
-                  KUnbounded    -> error "SBV.HasKind.intSizeOf((S)Integer)"
-                  KReal         -> error "SBV.HasKind.intSizeOf((S)Real)"
-                  KFloat        -> error "SBV.HasKind.intSizeOf((S)Float)"
-                  KDouble       -> error "SBV.HasKind.intSizeOf((S)Double)"
-                  KUserSort s _ -> error $ "SBV.HasKind.intSizeOf: Uninterpreted sort: " ++ s
-  isBoolean       x | KBool{}      <- kindOf x = True
-                    | True                     = False
-  isBounded       x | KBounded{}   <- kindOf x = True
-                    | True                     = False
-  isReal          x | KReal{}      <- kindOf x = True
-                    | True                     = False
-  isFloat         x | KFloat{}     <- kindOf x = True
-                    | True                     = False
-  isDouble        x | KDouble{}    <- kindOf x = True
-                    | True                     = False
-  isInteger       x | KUnbounded{} <- kindOf x = True
-                    | True                     = False
-  isUninterpreted x | KUserSort{}  <- kindOf x = True
-                    | True                     = False
-  showType = show . kindOf
-
-  -- default signature for uninterpreted/enumerated kinds
-  default kindOf :: (Read a, G.Data a) => a -> Kind
-  kindOf = constructUKind
-
-instance HasKind Bool    where kindOf _ = KBool
-instance HasKind Int8    where kindOf _ = KBounded True  8
-instance HasKind Word8   where kindOf _ = KBounded False 8
-instance HasKind Int16   where kindOf _ = KBounded True  16
-instance HasKind Word16  where kindOf _ = KBounded False 16
-instance HasKind Int32   where kindOf _ = KBounded True  32
-instance HasKind Word32  where kindOf _ = KBounded False 32
-instance HasKind Int64   where kindOf _ = KBounded True  64
-instance HasKind Word64  where kindOf _ = KBounded False 64
-instance HasKind Integer where kindOf _ = KUnbounded
-instance HasKind AlgReal where kindOf _ = KReal
-instance HasKind Float   where kindOf _ = KFloat
-instance HasKind Double  where kindOf _ = KDouble
-
-instance HasKind Kind where
-  kindOf = id
diff --git a/Data/SBV/BitVectors/Model.hs b/Data/SBV/BitVectors/Model.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Model.hs
+++ /dev/null
@@ -1,1698 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Model
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Instance declarations for our symbolic world
------------------------------------------------------------------------------
-
-{-# OPTIONS_GHC -fno-warn-orphans   #-}
-{-# LANGUAGE TypeSynonymInstances   #-}
-{-# LANGUAGE BangPatterns           #-}
-{-# LANGUAGE PatternGuards          #-}
-{-# LANGUAGE FlexibleContexts       #-}
-{-# LANGUAGE FlexibleInstances      #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE ScopedTypeVariables    #-}
-{-# LANGUAGE Rank2Types             #-}
-{-# LANGUAGE TypeOperators          #-}
-{-# LANGUAGE DefaultSignatures      #-}
-
-module Data.SBV.BitVectors.Model (
-    Mergeable(..), EqSymbolic(..), OrdSymbolic(..), SDivisible(..), Uninterpreted(..), SIntegral
-  , ite, iteLazy, sTestBit, sExtractBits, sPopCount, setBitTo, sFromIntegral
-  , sShiftLeft, sShiftRight, sRotateLeft, sRotateRight, sSignedShiftArithRight, (.^)
-  , allEqual, allDifferent, inRange, sElem, oneIf, blastBE, blastLE, fullAdder, fullMultiplier
-  , lsb, msb, genVar, genVar_, forall, forall_, exists, exists_
-  , constrain, pConstrain, 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, slet
-  , sRealToSInteger, label
-  , sAssert
-  , liftQRem, liftDMod, symbolicMergeWithKind
-  , genLiteral, genFromCW, genMkSymVar
-  , isSatisfiableInCurrentPath
-  , sbvQuickCheck
-  )
-  where
-
-import Control.Monad        (when, unless)
-import Control.Monad.Reader (ask)
-import Control.Monad.Trans  (liftIO)
-
-import GHC.Generics (U1(..), M1(..), (:*:)(..), K1(..))
-import qualified GHC.Generics as G
-import GHC.Stack.Compat
-
-import Data.Array      (Array, Ix, listArray, elems, bounds, rangeSize)
-import Data.Bits       (Bits(..))
-import Data.Int        (Int8, Int16, Int32, Int64)
-import Data.List       (genericLength, genericIndex, genericTake, unzip4, unzip5, unzip6, unzip7, intercalate)
-import Data.Maybe      (fromMaybe)
-import Data.Word       (Word8, Word16, Word32, Word64)
-
-import Test.QuickCheck                         (Testable(..), Arbitrary(..))
-import qualified Test.QuickCheck.Test    as QC (isSuccess)
-import qualified Test.QuickCheck         as QC (quickCheckResult, counterexample)
-import qualified Test.QuickCheck.Monadic as QC (monadicIO, run, assert, pre, monitor)
-import System.Random
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data
-import Data.SBV.Utils.Boolean
-
-import Data.SBV.Provers.Prover (isVacuous, prove, defaultSMTCfg, internalSATCheck)
-import Data.SBV.SMT.SMT        (ThmResult, SatResult(..), showModel)
-
-import Data.SBV.BitVectors.Symbolic
-import Data.SBV.BitVectors.Operations
-
--- | Newer versions of GHC (Starting with 7.8 I think), distinguishes between FiniteBits and Bits classes.
--- We should really use FiniteBitSize for SBV which would make things better. In the interim, just work
--- around pesky warnings..
-ghcBitSize :: Bits a => a -> Int
-ghcBitSize x = fromMaybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") (bitSizeMaybe x)
-
-mkSymOpSC :: (SW -> SW -> Maybe SW) -> Op -> State -> Kind -> SW -> SW -> IO SW
-mkSymOpSC shortCut op st k a b = maybe (newExpr st k (SBVApp op [a, b])) return (shortCut a b)
-
-mkSymOp :: Op -> State -> Kind -> SW -> SW -> IO SW
-mkSymOp = mkSymOpSC (const (const Nothing))
-
--- Symbolic-Word class instances
-
--- | Generate a finite symbolic bitvector, named
-genVar :: Maybe Quantifier -> Kind -> String -> Symbolic (SBV a)
-genVar q k = mkSymSBV q k . Just
-
--- | Generate a finite symbolic bitvector, unnamed
-genVar_ :: Maybe Quantifier -> Kind -> Symbolic (SBV a)
-genVar_ q k = mkSymSBV q k Nothing
-
--- | Generate a finite constant bitvector
-genLiteral :: Integral a => Kind -> a -> SBV b
-genLiteral k = SBV . SVal k . Left . mkConstCW k
-
--- | Convert a constant to an integral value
-genFromCW :: Integral a => CW -> a
-genFromCW (CW _ (CWInteger x)) = fromInteger x
-genFromCW c                    = error $ "genFromCW: Unsupported non-integral value: " ++ show c
-
--- | Generically make a symbolic var
-genMkSymVar :: Kind -> Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
-genMkSymVar k mbq Nothing  = genVar_ mbq k
-genMkSymVar k mbq (Just s) = genVar  mbq k s
-
--- | Base type of () allows simple construction for uninterpreted types.
-instance SymWord ()
-instance HasKind ()
-
-instance SymWord Bool where
-  mkSymWord  = genMkSymVar KBool
-  literal x  = SBV (svBool x)
-  fromCW     = cwToBool
-
-instance SymWord Word8 where
-  mkSymWord  = genMkSymVar (KBounded False 8)
-  literal    = genLiteral  (KBounded False 8)
-  fromCW     = genFromCW
-
-instance SymWord Int8 where
-  mkSymWord  = genMkSymVar (KBounded True 8)
-  literal    = genLiteral  (KBounded True 8)
-  fromCW     = genFromCW
-
-instance SymWord Word16 where
-  mkSymWord  = genMkSymVar (KBounded False 16)
-  literal    = genLiteral  (KBounded False 16)
-  fromCW     = genFromCW
-
-instance SymWord Int16 where
-  mkSymWord  = genMkSymVar (KBounded True 16)
-  literal    = genLiteral  (KBounded True 16)
-  fromCW     = genFromCW
-
-instance SymWord Word32 where
-  mkSymWord  = genMkSymVar (KBounded False 32)
-  literal    = genLiteral  (KBounded False 32)
-  fromCW     = genFromCW
-
-instance SymWord Int32 where
-  mkSymWord  = genMkSymVar (KBounded True 32)
-  literal    = genLiteral  (KBounded True 32)
-  fromCW     = genFromCW
-
-instance SymWord Word64 where
-  mkSymWord  = genMkSymVar (KBounded False 64)
-  literal    = genLiteral  (KBounded False 64)
-  fromCW     = genFromCW
-
-instance SymWord Int64 where
-  mkSymWord  = genMkSymVar (KBounded True 64)
-  literal    = genLiteral  (KBounded True 64)
-  fromCW     = genFromCW
-
-instance SymWord Integer where
-  mkSymWord  = genMkSymVar KUnbounded
-  literal    = SBV . SVal KUnbounded . Left . mkConstCW KUnbounded
-  fromCW     = genFromCW
-
-instance SymWord AlgReal where
-  mkSymWord  = genMkSymVar KReal
-  literal    = SBV . SVal KReal . Left . CW KReal . CWAlgReal
-  fromCW (CW _ (CWAlgReal a)) = a
-  fromCW c                    = error $ "SymWord.AlgReal: Unexpected non-real value: " ++ show c
-  -- AlgReal needs its own definition of isConcretely
-  -- to make sure we avoid using unimplementable Haskell functions
-  isConcretely (SBV (SVal KReal (Left (CW KReal (CWAlgReal v))))) p
-     | isExactRational v = p v
-  isConcretely _ _       = False
-
-instance SymWord Float where
-  mkSymWord  = genMkSymVar KFloat
-  literal    = SBV . SVal KFloat . Left . CW KFloat . CWFloat
-  fromCW (CW _ (CWFloat a)) = a
-  fromCW c                  = error $ "SymWord.Float: Unexpected non-float value: " ++ show c
-  -- For Float, we conservatively return 'False' for isConcretely. The reason is that
-  -- this function is used for optimizations when only one of the argument is concrete,
-  -- and in the presence of NaN's it would be incorrect to do any optimization
-  isConcretely _ _ = False
-
-instance SymWord Double where
-  mkSymWord  = genMkSymVar KDouble
-  literal    = SBV . SVal KDouble . Left . CW KDouble . CWDouble
-  fromCW (CW _ (CWDouble a)) = a
-  fromCW c                   = error $ "SymWord.Double: Unexpected non-double value: " ++ show c
-  -- For Double, we conservatively return 'False' for isConcretely. The reason is that
-  -- this function is used for optimizations when only one of the argument is concrete,
-  -- and in the presence of NaN's it would be incorrect to do any optimization
-  isConcretely _ _ = False
-
-------------------------------------------------------------------------------------
--- * Smart constructors for creating symbolic values. These are not strictly
--- necessary, as they are mere aliases for 'symbolic' and 'symbolics', but 
--- they nonetheless make programming easier.
-------------------------------------------------------------------------------------
--- | Declare an 'SBool'
-sBool :: String -> Symbolic SBool
-sBool = symbolic
-
--- | Declare a list of 'SBool's
-sBools :: [String] -> Symbolic [SBool]
-sBools = symbolics
-
--- | Declare an 'SWord8'
-sWord8 :: String -> Symbolic SWord8
-sWord8 = symbolic
-
--- | Declare a list of 'SWord8's
-sWord8s :: [String] -> Symbolic [SWord8]
-sWord8s = symbolics
-
--- | Declare an 'SWord16'
-sWord16 :: String -> Symbolic SWord16
-sWord16 = symbolic
-
--- | Declare a list of 'SWord16's
-sWord16s :: [String] -> Symbolic [SWord16]
-sWord16s = symbolics
-
--- | Declare an 'SWord32'
-sWord32 :: String -> Symbolic SWord32
-sWord32 = symbolic
-
--- | Declare a list of 'SWord32's
-sWord32s :: [String] -> Symbolic [SWord32]
-sWord32s = symbolics
-
--- | Declare an 'SWord64'
-sWord64 :: String -> Symbolic SWord64
-sWord64 = symbolic
-
--- | Declare a list of 'SWord64's
-sWord64s :: [String] -> Symbolic [SWord64]
-sWord64s = symbolics
-
--- | Declare an 'SInt8'
-sInt8 :: String -> Symbolic SInt8
-sInt8 = symbolic
-
--- | Declare a list of 'SInt8's
-sInt8s :: [String] -> Symbolic [SInt8]
-sInt8s = symbolics
-
--- | Declare an 'SInt16'
-sInt16 :: String -> Symbolic SInt16
-sInt16 = symbolic
-
--- | Declare a list of 'SInt16's
-sInt16s :: [String] -> Symbolic [SInt16]
-sInt16s = symbolics
-
--- | Declare an 'SInt32'
-sInt32 :: String -> Symbolic SInt32
-sInt32 = symbolic
-
--- | Declare a list of 'SInt32's
-sInt32s :: [String] -> Symbolic [SInt32]
-sInt32s = symbolics
-
--- | Declare an 'SInt64'
-sInt64 :: String -> Symbolic SInt64
-sInt64 = symbolic
-
--- | Declare a list of 'SInt64's
-sInt64s :: [String] -> Symbolic [SInt64]
-sInt64s = symbolics
-
--- | Declare an 'SInteger'
-sInteger:: String -> Symbolic SInteger
-sInteger = symbolic
-
--- | Declare a list of 'SInteger's
-sIntegers :: [String] -> Symbolic [SInteger]
-sIntegers = symbolics
-
--- | Declare an 'SReal'
-sReal:: String -> Symbolic SReal
-sReal = symbolic
-
--- | Declare a list of 'SReal's
-sReals :: [String] -> Symbolic [SReal]
-sReals = symbolics
-
--- | Declare an 'SFloat'
-sFloat :: String -> Symbolic SFloat
-sFloat = symbolic
-
--- | Declare a list of 'SFloat's
-sFloats :: [String] -> Symbolic [SFloat]
-sFloats = symbolics
-
--- | Declare an 'SDouble'
-sDouble :: String -> Symbolic SDouble
-sDouble = symbolic
-
--- | Declare a list of 'SDouble's
-sDoubles :: [String] -> Symbolic [SDouble]
-sDoubles = symbolics
-
--- | Convert an SReal to an SInteger. That is, it computes the
--- largest integer @n@ that satisfies @sIntegerToSReal n <= r@
--- essentially giving us the @floor@.
---
--- For instance, @1.3@ will be @1@, but @-1.3@ will be @-2@.
-sRealToSInteger :: SReal -> SInteger
-sRealToSInteger x
-  | Just i <- unliteral x, isExactRational i
-  = literal $ floor (toRational i)
-  | True
-  = SBV (SVal KUnbounded (Right (cache y)))
-  where y st = do xsw <- sbvToSW st x
-                  newExpr st KUnbounded (SBVApp (KindCast KReal KUnbounded) [xsw])
-
--- | label: Label the result of an expression. This is essentially a no-op, but useful as it generates a comment in the generated C/SMT-Lib code.
--- Note that if the argument is a constant, then the label is dropped completely, per the usual constant folding strategy.
-label :: SymWord a => String -> SBV a -> SBV a
-label m x
-   | Just _ <- unliteral x = x
-   | True                  = SBV $ SVal k $ Right $ cache r
-  where k    = kindOf x
-        r st = do xsw <- sbvToSW st x
-                  newExpr st k (SBVApp (Label m) [xsw])
-
--- | 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.
---
--- Minimal complete definition: '.=='
-infix 4 .==, ./=
-class EqSymbolic a where
-  (.==), (./=) :: a -> a -> SBool
-  -- minimal complete definition: .==
-  x ./= y = bnot (x .== y)
-
--- | Symbolic Comparisons. Similar to 'Eq', we cannot implement Haskell's 'Ord' class
--- since there is no way to return an 'Ordering' value from a symbolic comparison.
--- Furthermore, 'OrdSymbolic' requires 'Mergeable' to implement if-then-else, for the
--- benefit of implementing symbolic versions of 'max' and 'min' functions.
---
--- Minimal complete definition: '.<'
-infix 4 .<, .<=, .>, .>=
-class (Mergeable a, EqSymbolic a) => OrdSymbolic a where
-  (.<), (.<=), (.>), (.>=) :: a -> a -> SBool
-  smin, smax :: a -> a -> a
-  -- minimal complete definition: .<
-  a .<= b    = a .< b ||| a .== b
-  a .>  b    = b .<  a
-  a .>= b    = b .<= a
-  a `smin` b = ite (a .<= b) a b
-  a `smax` b = ite (a .<= b) b a
-
-{- We can't have a generic instance of the form:
-
-instance Eq a => EqSymbolic a where
-  x .== y = if x == y then true else false
-
-even if we're willing to allow Flexible/undecidable instances..
-This is because if we allow this it would imply EqSymbolic (SBV a);
-since (SBV a) has to be Eq as it must be a Num. But this wouldn't be
-the right choice obviously; as the Eq instance is bogus for SBV
-for natural reasons..
--}
-
-instance EqSymbolic (SBV a) where
-  SBV x .== SBV y = SBV (svEqual x y)
-  SBV x ./= SBV y = SBV (svNotEqual x y)
-
-instance SymWord 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)
-  SBV x .>= SBV y = SBV (svGreaterEq x y)
-
--- Bool
-instance EqSymbolic Bool where
-  x .== y = if x == y then true else false
-
--- Lists
-instance EqSymbolic a => EqSymbolic [a] where
-  []     .== []     = true
-  (x:xs) .== (y:ys) = x .== y &&& xs .== ys
-  _      .== _      = false
-
-instance OrdSymbolic a => OrdSymbolic [a] where
-  []     .< []     = false
-  []     .< _      = true
-  _      .< []     = false
-  (x:xs) .< (y:ys) = x .< y ||| (x .== y &&& xs .< ys)
-
--- Maybe
-instance EqSymbolic a => EqSymbolic (Maybe a) where
-  Nothing .== Nothing = true
-  Just a  .== Just b  = a .== b
-  _       .== _       = false
-
-instance (OrdSymbolic a) => OrdSymbolic (Maybe a) where
-  Nothing .<  Nothing = false
-  Nothing .<  _       = true
-  Just _  .<  Nothing = false
-  Just a  .<  Just b  = a .< b
-
--- Either
-instance (EqSymbolic a, EqSymbolic b) => EqSymbolic (Either a b) where
-  Left a  .== Left b  = a .== b
-  Right a .== Right b = a .== b
-  _       .== _       = false
-
-instance (OrdSymbolic a, OrdSymbolic b) => OrdSymbolic (Either a b) where
-  Left a  .< Left b  = a .< b
-  Left _  .< Right _ = true
-  Right _ .< Left _  = false
-  Right a .< Right b = a .< b
-
--- 2-Tuple
-instance (EqSymbolic a, EqSymbolic b) => EqSymbolic (a, b) where
-  (a0, b0) .== (a1, b1) = a0 .== a1 &&& b0 .== b1
-
-instance (OrdSymbolic a, OrdSymbolic b) => OrdSymbolic (a, b) where
-  (a0, b0) .< (a1, b1) = a0 .< a1 ||| (a0 .== a1 &&& b0 .< b1)
-
--- 3-Tuple
-instance (EqSymbolic a, EqSymbolic b, EqSymbolic c) => EqSymbolic (a, b, c) where
-  (a0, b0, c0) .== (a1, b1, c1) = (a0, b0) .== (a1, b1) &&& c0 .== c1
-
-instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c) => OrdSymbolic (a, b, c) where
-  (a0, b0, c0) .< (a1, b1, c1) = (a0, b0) .< (a1, b1) ||| ((a0, b0) .== (a1, b1) &&& c0 .< c1)
-
--- 4-Tuple
-instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d) => EqSymbolic (a, b, c, d) where
-  (a0, b0, c0, d0) .== (a1, b1, c1, d1) = (a0, b0, c0) .== (a1, b1, c1) &&& d0 .== d1
-
-instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d) => OrdSymbolic (a, b, c, d) where
-  (a0, b0, c0, d0) .< (a1, b1, c1, d1) = (a0, b0, c0) .< (a1, b1, c1) ||| ((a0, b0, c0) .== (a1, b1, c1) &&& d0 .< d1)
-
--- 5-Tuple
-instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e) => EqSymbolic (a, b, c, d, e) where
-  (a0, b0, c0, d0, e0) .== (a1, b1, c1, d1, e1) = (a0, b0, c0, d0) .== (a1, b1, c1, d1) &&& e0 .== e1
-
-instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e) => OrdSymbolic (a, b, c, d, e) where
-  (a0, b0, c0, d0, e0) .< (a1, b1, c1, d1, e1) = (a0, b0, c0, d0) .< (a1, b1, c1, d1) ||| ((a0, b0, c0, d0) .== (a1, b1, c1, d1) &&& e0 .< e1)
-
--- 6-Tuple
-instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e, EqSymbolic f) => EqSymbolic (a, b, c, d, e, f) where
-  (a0, b0, c0, d0, e0, f0) .== (a1, b1, c1, d1, e1, f1) = (a0, b0, c0, d0, e0) .== (a1, b1, c1, d1, e1) &&& f0 .== f1
-
-instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e, OrdSymbolic f) => OrdSymbolic (a, b, c, d, e, f) where
-  (a0, b0, c0, d0, e0, f0) .< (a1, b1, c1, d1, e1, f1) =    (a0, b0, c0, d0, e0) .<  (a1, b1, c1, d1, e1)
-                                                       ||| ((a0, b0, c0, d0, e0) .== (a1, b1, c1, d1, e1) &&& f0 .< f1)
-
--- 7-Tuple
-instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e, EqSymbolic f, EqSymbolic g) => EqSymbolic (a, b, c, d, e, f, g) where
-  (a0, b0, c0, d0, e0, f0, g0) .== (a1, b1, c1, d1, e1, f1, g1) = (a0, b0, c0, d0, e0, f0) .== (a1, b1, c1, d1, e1, f1) &&& g0 .== g1
-
-instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e, OrdSymbolic f, OrdSymbolic g) => OrdSymbolic (a, b, c, d, e, f, g) where
-  (a0, b0, c0, d0, e0, f0, g0) .< (a1, b1, c1, d1, e1, f1, g1) =    (a0, b0, c0, d0, e0, f0) .<  (a1, b1, c1, d1, e1, f1)
-                                                               ||| ((a0, b0, c0, d0, e0, f0) .== (a1, b1, c1, d1, e1, f1) &&& g0 .< g1)
-
--- | Symbolic Numbers. This is a simple class that simply incorporates all number like
--- base types together, simplifying writing polymorphic type-signatures that work for all
--- symbolic numbers, such as 'SWord8', 'SInt8' etc. For instance, we can write a generic
--- list-minimum function as follows:
---
--- @
---    mm :: SIntegral a => [SBV a] -> SBV a
---    mm = foldr1 (\a b -> ite (a .<= b) a b)
--- @
---
--- It is similar to the standard 'Integral' class, except ranging over symbolic instances.
-class (SymWord a, Num a, Bits a) => SIntegral a
-
--- 'SIntegral' Instances, including all possible variants except 'Bool', since booleans
--- are not numbers.
-instance SIntegral Word8
-instance SIntegral Word16
-instance SIntegral Word32
-instance SIntegral Word64
-instance SIntegral Int8
-instance SIntegral Int16
-instance SIntegral Int32
-instance SIntegral Int64
-instance SIntegral Integer
-
--- Boolean combinators
-instance Boolean SBool where
-  true  = literal True
-  false = literal False
-  bnot (SBV b) = SBV (svNot b)
-  SBV a &&& SBV b = SBV (svAnd a b)
-  SBV a ||| SBV b = SBV (svOr a b)
-  SBV a <+> SBV b = SBV (svXOr a b)
-
--- | Returns (symbolic) true if all the elements of the given list are different.
-allDifferent :: EqSymbolic a => [a] -> SBool
-allDifferent []     = true
-allDifferent (x:xs) = bAll (x ./=) xs &&& allDifferent xs
-
--- | Returns (symbolic) true if all the elements of the given list are the same.
-allEqual :: EqSymbolic a => [a] -> SBool
-allEqual []     = true
-allEqual (x:xs) = bAll (x .==) xs
-
--- | Returns (symbolic) true if the argument is in range
-inRange :: OrdSymbolic a => a -> (a, a) -> SBool
-inRange x (y, z) = x .>= y &&& x .<= z
-
--- | Symbolic membership test
-sElem :: EqSymbolic a => a -> [a] -> SBool
-sElem x xs = bAny (.== x) xs
-
--- | Returns 1 if the boolean is true, otherwise 0.
-oneIf :: (Num a, SymWord a) => SBool -> SBV a
-oneIf t = ite t 1 0
-
--- | Predicate for optimizing word operations like (+) and (*).
-isConcreteZero :: SBV a -> Bool
-isConcreteZero (SBV (SVal _     (Left (CW _     (CWInteger n))))) = n == 0
-isConcreteZero (SBV (SVal KReal (Left (CW KReal (CWAlgReal v))))) = isExactRational v && v == 0
-isConcreteZero _                                                  = False
-
--- | Predicate for optimizing word operations like (+) and (*).
-isConcreteOne :: SBV a -> Bool
-isConcreteOne (SBV (SVal _     (Left (CW _     (CWInteger 1))))) = True
-isConcreteOne (SBV (SVal KReal (Left (CW KReal (CWAlgReal v))))) = isExactRational v && v == 1
-isConcreteOne _                                                  = False
-
--- Num instance for symbolic words.
-instance (Ord a, Num a, SymWord a) => Num (SBV a) where
-  fromInteger = literal . fromIntegral
-  SBV x + SBV y = SBV (svPlus x y)
-  SBV x * SBV y = SBV (svTimes x y)
-  SBV x - SBV y = SBV (svMinus x y)
-  -- Abs is problematic for floating point, due to -0; case, so we carefully shuttle it down
-  -- to the solver to avoid the can of worms. (Alternative would be to do an if-then-else here.)
-  abs (SBV x) = SBV (svAbs x)
-  signum a
-    -- NB. The following "carefully" tests the number for == 0, as Float/Double's NaN and +/-0
-    -- cases would cause trouble with explicit equality tests.
-    | hasSign a = ite (a .> z) i
-                $ ite (a .< z) (negate i) a
-    | True      = ite (a .> z) i a
-    where z = genLiteral (kindOf a) (0::Integer)
-          i = genLiteral (kindOf a) (1::Integer)
-  -- negate is tricky because on double/float -0 is different than 0; so we cannot
-  -- just rely on the default definition; which would be 0-0, which is not -0!
-  negate (SBV x) = SBV (svUNeg x)
-
--- | Symbolic exponentiation using bit blasting and repeated squaring.
---
--- N.B. The exponent must be unsigned. Signed exponents will be rejected.
-(.^) :: (Mergeable b, Num b, SIntegral e) => b -> SBV e -> b
-b .^ e | isSigned e = error "(.^): exponentiation only works with unsigned exponents"
-       | True       = product $ zipWith (\use n -> ite use n 1)
-                                        (blastLE e)
-                                        (iterate (\x -> x*x) b)
-
-instance (SymWord a, Fractional a) => Fractional (SBV a) where
-  fromRational  = literal . fromRational
-  SBV x / sy@(SBV y) | div0 = ite (sy .== 0) 0 res
-                     | True = res
-       where res  = SBV (svDivide x y)
-             -- Identify those kinds where we have a div-0 equals 0 exception
-             div0 = case kindOf sy of
-                      KFloat        -> False
-                      KDouble       -> False
-                      KReal         -> True
-                      -- Following two cases should not happen since these types should *not* be instances of Fractional
-                      k@KBounded{}  -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KUnbounded  -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KBool       -> error $ "Unexpected Fractional case for: " ++ show k
-                      k@KUserSort{} -> 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 (SymWord a, Fractional a, Floating a) => Floating (SBV a) where
-    pi      = literal pi
-    exp     = lift1FNS "exp"     exp
-    log     = lift1FNS "log"     log
-    sqrt    = lift1F   FP_Sqrt   sqrt
-    sin     = lift1FNS "sin"     sin
-    cos     = lift1FNS "cos"     cos
-    tan     = lift1FNS "tan"     tan
-    asin    = lift1FNS "asin"    asin
-    acos    = lift1FNS "acos"    acos
-    atan    = lift1FNS "atan"    atan
-    sinh    = lift1FNS "sinh"    sinh
-    cosh    = lift1FNS "cosh"    cosh
-    tanh    = lift1FNS "tanh"    tanh
-    asinh   = lift1FNS "asinh"   asinh
-    acosh   = lift1FNS "acosh"   acosh
-    atanh   = lift1FNS "atanh"   atanh
-    (**)    = lift2FNS "**"      (**)
-    logBase = lift2FNS "logBase" logBase
-
--- | Lift a 1 arg FP-op, using sRNE default
-lift1F :: SymWord a => FPOp -> (a -> a) -> SBV a -> SBV a
-lift1F w op a
-  | Just v <- unliteral a
-  = literal $ op v
-  | True
-  = SBV $ SVal k $ Right $ cache r
-  where k    = kindOf a
-        r st = do swa  <- sbvToSW st a
-                  swm  <- sbvToSW st sRNE
-                  newExpr st k (SBVApp (IEEEFP w) [swm, swa])
-
--- | Lift a float/double unary function, only over constants
-lift1FNS :: (SymWord a, Floating a) => String -> (a -> a) -> SBV a -> SBV a
-lift1FNS nm f sv
-  | Just v <- unliteral sv = literal $ f v
-  | True                   = error $ "SBV." ++ nm ++ ": not supported for symbolic values of type " ++ show (kindOf sv)
-
--- | Lift a float/double binary function, only over constants
-lift2FNS :: (SymWord a, Floating a) => String -> (a -> a -> a) -> SBV a -> SBV a -> SBV a
-lift2FNS nm f sv1 sv2
-  | Just v1 <- unliteral sv1
-  , Just v2 <- unliteral sv2 = literal $ f v1 v2
-  | True                     = error $ "SBV." ++ nm ++ ": not supported for symbolic values of type " ++ show (kindOf sv1)
-
--- NB. In the optimizations below, use of -1 is valid as
--- -1 has all bits set to True for both signed and unsigned values
-instance (Num a, Bits a, SymWord 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)
-  complement (SBV x) = SBV (svNot x)
-  bitSize  x         = intSizeOf x
-  bitSizeMaybe x     = Just $ intSizeOf x
-  isSigned x         = hasSign x
-  bit i              = 1 `shiftL` i
-  setBit        x i  = x .|. genLiteral (kindOf x) (bit i :: Integer)
-  clearBit      x i  = x .&. genLiteral (kindOf x) (complement (bit i) :: Integer)
-  complementBit x i  = x `xor` genLiteral (kindOf x) (bit i :: Integer)
-  shiftL  (SBV x) i  = SBV (svShl x i)
-  shiftR  (SBV x) i  = SBV (svShr x i)
-  rotateL (SBV x) i  = SBV (svRol x i)
-  rotateR (SBV x) i  = SBV (svRor x i)
-  -- NB. testBit is *not* implementable on non-concrete symbolic words
-  x `testBit` i
-    | SBV (SVal _ (Left (CW _ (CWInteger n)))) <- x
-    = testBit n i
-    | True
-    = error $ "SBV.testBit: Called on symbolic value: " ++ show x ++ ". Use sTestBit instead."
-  -- NB. popCount is *not* implementable on non-concrete symbolic words
-  popCount x
-    | SBV (SVal _ (Left (CW (KBounded _ w) (CWInteger n)))) <- x
-    = popCount (n .&. (bit w - 1))
-    | True
-    = error $ "SBV.popCount: Called on symbolic value: " ++ show x ++ ". Use sPopCount instead."
-
--- | Replacement for 'testBit'. Since 'testBit' requires a 'Bool' to be returned,
--- we cannot implement it for symbolic words. Index 0 is the least-significant bit.
-sTestBit :: SBV a -> Int -> SBool
-sTestBit (SBV x) i = SBV (svTestBit x i)
-
--- | Variant of 'sTestBit', where we want to extract multiple bit positions.
-sExtractBits :: SBV a -> [Int] -> [SBool]
-sExtractBits x = map (sTestBit x)
-
--- | Replacement for 'popCount'. Since 'popCount' returns an 'Int', we cannot implement
--- it for symbolic words. Here, we return an 'SWord8', which can overflow when used on
--- quantities that have more than 255 bits. Currently, that's only the 'SInteger' type
--- that SBV supports, all other types are safe. Even with 'SInteger', this will only
--- overflow if there are at least 256-bits set in the number, and the smallest such
--- number is 2^256-1, which is a pretty darn big number to worry about for practical
--- purposes. In any case, we do not support 'sPopCount' for unbounded symbolic integers,
--- as the only possible implementation wouldn't symbolically terminate. So the only overflow
--- issue is with really-really large concrete 'SInteger' values.
-sPopCount :: (Num a, Bits a, SymWord a) => SBV a -> SWord8
-sPopCount x
-  | isReal x          = error "SBV.sPopCount: Called on a real value" -- can't really happen due to types, but being overcautious
-  | isConcrete x      = go 0 x
-  | not (isBounded x) = error "SBV.sPopCount: Called on an infinite precision symbolic value"
-  | True              = sum [ite b 1 0 | b <- blastLE x]
-  where -- concrete case
-        go !c 0 = c
-        go !c w = go (c+1) (w .&. (w-1))
-
--- | Generalization of 'setBit' based on a symbolic boolean. Note that 'setBit' and
--- 'clearBit' are still available on Symbolic words, this operation comes handy when
--- the condition to set/clear happens to be symbolic.
-setBitTo :: (Num a, Bits a, SymWord a) => SBV a -> Int -> SBool -> SBV a
-setBitTo x i b = ite b (setBit x i) (clearBit x i)
-
--- | Conversion between integral-symbolic values, akin to Haskell's fromIntegral
-sFromIntegral :: forall a b. (Integral a, HasKind a, Num a, SymWord a, HasKind b, Num b, SymWord b) => SBV a -> SBV b
-sFromIntegral x
-  | isReal x
-  = error "SBV.sFromIntegral: Called on a real value" -- can't really happen due to types, but being overcautious
-  | Just v <- unliteral x
-  = literal (fromIntegral v)
-  | True
-  = result
-  where result = SBV (SVal kTo (Right (cache y)))
-        kFrom  = kindOf x
-        kTo    = kindOf (undefined :: b)
-        y st   = do xsw <- sbvToSW st x
-                    newExpr st kTo (SBVApp (KindCast kFrom kTo) [xsw])
-
--- | Generalization of 'shiftL', when the shift-amount is symbolic. Since Haskell's
--- 'shiftL' 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.
-sShiftLeft :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sShiftLeft x i
-  | not (isBounded x)
-  = error "SBV.sShiftRight: Shifted amount should be a bounded quantity!"
-  | True
-  = ite (i .< 0)
-        (select [x `shiftR` k | k <- [0 .. ghcBitSize x - 1]] z (-i))
-        (select [x `shiftL` k | k <- [0 .. ghcBitSize x - 1]] z   i )
-  where z = genLiteral (kindOf x) (0::Integer)
-
--- | Generalization of 'shiftR', when the shift-amount is symbolic. Since Haskell's
--- 'shiftR' 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.
---
--- NB. If the shiftee is signed, then this is an arithmetic shift; otherwise it's logical,
--- following the usual Haskell convention. See 'sSignedShiftArithRight' for a variant
--- that explicitly uses the msb as the sign bit, even for unsigned underlying types.
-sShiftRight :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sShiftRight x i
-  | not (isBounded x)
-  = error "SBV.sShiftRight: Shifted amount should be a bounded quantity!"
-  | True
-  = ite (i .< 0)
-        (select [x `shiftL` k | k <- [0 .. ghcBitSize x - 1]] z (-i))
-        (select [x `shiftR` k | k <- [0 .. ghcBitSize x - 1]] z   i )
-  where z = genLiteral (kindOf x) (0::Integer)
-
--- | Arithmetic shift-right with a symbolic unsigned shift amount. This is equivalent
--- to 'sShiftRight' when the argument is signed. However, if the argument is unsigned,
--- then it explicitly treats its msb as a sign-bit, and uses it as the bit that
--- gets shifted in. Useful when using the underlying unsigned bit representation to implement
--- custom signed operations. Note that there is no direct Haskell analogue of this function.
-sSignedShiftArithRight:: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sSignedShiftArithRight x i
-  | isSigned i = error "sSignedShiftArithRight: shift amount should be unsigned"
-  | isSigned x = sShiftRight x i
-  | True       = ite (msb x)
-                     (complement (sShiftRight (complement x) i))
-                     (sShiftRight x i)
-
--- | 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 x i
-  | not (isBounded x)
-  = sShiftLeft x i
-  | isBounded i && bit si <= toInteger sx    -- wrap-around not possible
-  = ite (i .< 0)
-        (select [x `rotateR` k | k <- [0 .. bit si - 1]] z (-i))
-        (select [x `rotateL` k | k <- [0 .. bit si - 1]] z   i )
-  | True
-  = ite (i .< 0)
-        (select [x `rotateR` k | k <- [0 .. sx     - 1]] z ((-i) `sRem` n))
-        (select [x `rotateL` k | k <- [0 .. sx     - 1]] z (  i  `sRem` n))
-    where sx = ghcBitSize x
-          si = ghcBitSize i
-          z  = genLiteral (kindOf x) (0::Integer)
-          n  = genLiteral (kindOf i) (toInteger sx)
-
--- | 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 x i
-  | not (isBounded x)
-  = sShiftRight x i
-  | isBounded i && bit si <= toInteger sx   -- wrap-around not possible
-  = ite (i .< 0)
-        (select [x `rotateL` k | k <- [0 .. bit si - 1]] z (-i))
-        (select [x `rotateR` k | k <- [0 .. bit si - 1]] z   i)
-  | True
-  = ite (i .< 0)
-        (select [x `rotateL` k | k <- [0 .. sx     - 1]] z ((-i) `sRem` n))
-        (select [x `rotateR` k | k <- [0 .. sx     - 1]] z (  i  `sRem` n))
-    where sx = ghcBitSize x
-          si = ghcBitSize i
-          z  = genLiteral (kindOf x) (0::Integer)
-          n  = genLiteral (kindOf i) (toInteger sx)
-
--- | Full adder. Returns the carry-out from the addition.
---
--- N.B. Only works for unsigned types. Signed arguments will be rejected.
-fullAdder :: SIntegral a => SBV a -> SBV a -> (SBool, SBV a)
-fullAdder a b
-  | isSigned a = error "fullAdder: only works on unsigned numbers"
-  | True       = (a .> s ||| b .> s, s)
-  where s = a + b
-
--- | Full multiplier: Returns both the high-order and the low-order bits in a tuple,
--- thus fully accounting for the overflow.
---
--- N.B. Only works for unsigned types. Signed arguments will be rejected.
---
--- N.B. The higher-order bits are determined using a simple shift-add multiplier,
--- thus involving bit-blasting. It'd be naive to expect SMT solvers to deal efficiently
--- with properties involving this function, at least with the current state of the art.
-fullMultiplier :: SIntegral a => SBV a -> SBV a -> (SBV a, SBV a)
-fullMultiplier a b
-  | isSigned a = error "fullMultiplier: only works on unsigned numbers"
-  | True       = (go (ghcBitSize a) 0 a, a*b)
-  where go 0 p _ = p
-        go n p x = let (c, p')  = ite (lsb x) (fullAdder p b) (false, p)
-                       (o, p'') = shiftIn c p'
-                       (_, x')  = shiftIn o x
-                   in go (n-1) p'' x'
-        shiftIn k v = (lsb v, mask .|. (v `shiftR` 1))
-           where mask = ite k (bit (ghcBitSize v - 1)) 0
-
--- | Little-endian blasting of a word into its bits. Also see the 'FromBits' class.
-blastLE :: (Num a, Bits a, SymWord a) => SBV a -> [SBool]
-blastLE x
- | isReal x          = error "SBV.blastLE: Called on a real value"
- | not (isBounded x) = error "SBV.blastLE: Called on an infinite precision value"
- | True              = map (sTestBit x) [0 .. intSizeOf x - 1]
-
--- | Big-endian blasting of a word into its bits. Also see the 'FromBits' class.
-blastBE :: (Num a, Bits a, SymWord a) => SBV a -> [SBool]
-blastBE = reverse . blastLE
-
--- | Least significant bit of a word, always stored at index 0.
-lsb :: SBV a -> SBool
-lsb x = sTestBit x 0
-
--- | Most significant bit of a word, always stored at the last position.
-msb :: (Num a, Bits a, SymWord a) => SBV a -> SBool
-msb x
- | isReal x          = error "SBV.msb: Called on a real value"
- | not (isBounded x) = error "SBV.msb: Called on an infinite precision value"
- | True              = sTestBit x (intSizeOf x - 1)
-
--- 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
--- limited. While symbolic variants can be defined for many of these, they will just diverge
--- as final sizes cannot be determined statically.
-instance (Show a, Bounded a, Integral a, Num a, SymWord a) => Enum (SBV a) where
-  succ x
-    | v == (maxBound :: a) = error $ "Enum.succ{" ++ showType x ++ "}: tried to take `succ' of maxBound"
-    | True                 = fromIntegral $ v + 1
-    where v = enumCvt "succ" x
-  pred x
-    | v == (minBound :: a) = error $ "Enum.pred{" ++ showType x ++ "}: tried to take `pred' of minBound"
-    | True                 = fromIntegral $ v - 1
-    where v = enumCvt "pred" x
-  toEnum x
-    | xi < fromIntegral (minBound :: a) || xi > fromIntegral (maxBound :: a)
-    = error $ "Enum.toEnum{" ++ showType r ++ "}: " ++ show x ++ " is out-of-bounds " ++ show (minBound :: a, maxBound :: a)
-    | True
-    = r
-    where xi :: Integer
-          xi = fromIntegral x
-          r  :: SBV a
-          r  = fromIntegral x
-  fromEnum x
-     | r < fromIntegral (minBound :: Int) || r > fromIntegral (maxBound :: Int)
-     = error $ "Enum.fromEnum{" ++ showType x ++ "}:  value " ++ show r ++ " is outside of Int's bounds " ++ show (minBound :: Int, maxBound :: Int)
-     | True
-     = fromIntegral r
-    where r :: Integer
-          r = enumCvt "fromEnum" x
-  enumFrom x = map fromIntegral [xi .. fromIntegral (maxBound :: a)]
-     where xi :: Integer
-           xi = enumCvt "enumFrom" x
-  enumFromThen x y
-     | yi >= xi  = map fromIntegral [xi, yi .. fromIntegral (maxBound :: a)]
-     | True      = map fromIntegral [xi, yi .. fromIntegral (minBound :: a)]
-       where xi, yi :: Integer
-             xi = enumCvt "enumFromThen.x" x
-             yi = enumCvt "enumFromThen.y" y
-  enumFromThenTo x y z = map fromIntegral [xi, yi .. zi]
-       where xi, yi, zi :: Integer
-             xi = enumCvt "enumFromThenTo.x" x
-             yi = enumCvt "enumFromThenTo.y" y
-             zi = enumCvt "enumFromThenTo.z" z
-
--- | Helper function for use in enum operations
-enumCvt :: (SymWord a, Integral a, Num b) => String -> SBV a -> b
-enumCvt w x = case unliteral x of
-                Nothing -> error $ "Enum." ++ w ++ "{" ++ showType x ++ "}: Called on symbolic value " ++ show x
-                Just v  -> fromIntegral v
-
--- | The 'SDivisible' class captures the essence of division.
--- Unfortunately we cannot use Haskell's 'Integral' class since the 'Real'
--- and 'Enum' superclasses are not implementable for symbolic bit-vectors.
--- However, 'quotRem' and 'divMod' makes perfect sense, and the 'SDivisible' class captures
--- this operation. One issue is how division by 0 behaves. The verification
--- technology requires total functions, and there are several design choices
--- here. We follow Isabelle/HOL approach of assigning the value 0 for division
--- by 0. Therefore, we impose the following pair of laws:
---
--- @
---      x `sQuotRem` 0 = (0, x)
---      x `sDivMod`  0 = (0, x)
--- @
---
--- Note that our instances implement this law even when @x@ is @0@ itself.
---
--- NB. 'quot' truncates toward zero, while 'div' truncates toward negative infinity.
---
--- Minimal complete definition: 'sQuotRem', 'sDivMod'
-class SDivisible a where
-  sQuotRem :: a -> a -> (a, a)
-  sDivMod  :: a -> a -> (a, a)
-  sQuot    :: a -> a -> a
-  sRem     :: a -> a -> a
-  sDiv     :: a -> a -> a
-  sMod     :: a -> a -> a
-
-  x `sQuot` y = fst $ x `sQuotRem` y
-  x `sRem`  y = snd $ x `sQuotRem` y
-  x `sDiv`  y = fst $ x `sDivMod`  y
-  x `sMod`  y = snd $ x `sDivMod`  y
-
-instance SDivisible Word64 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Int64 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Word32 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Int32 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Word16 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Int16 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Word8 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Int8 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible Integer where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
-instance SDivisible CW where
-  sQuotRem a b
-    | CWInteger x <- cwVal a, CWInteger y <- cwVal b
-    = let (r1, r2) = sQuotRem x y in (normCW a{ cwVal = CWInteger r1 }, normCW b{ cwVal = CWInteger r2 })
-  sQuotRem a b = error $ "SBV.sQuotRem: impossible, unexpected args received: " ++ show (a, b)
-  sDivMod a b
-    | CWInteger x <- cwVal a, CWInteger y <- cwVal b
-    = let (r1, r2) = sDivMod x y in (normCW a { cwVal = CWInteger r1 }, normCW b { cwVal = CWInteger r2 })
-  sDivMod a b = error $ "SBV.sDivMod: impossible, unexpected args received: " ++ show (a, b)
-
-instance SDivisible SWord64 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SInt64 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SWord32 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SInt32 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SWord16 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SInt16 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SWord8 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
-instance SDivisible SInt8 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
--- | Lift 'QRem' to symbolic words. Division by 0 is defined s.t. @x/0 = 0@; which
--- holds even when @x@ is @0@ itself.
-liftQRem :: SymWord a => SBV a -> SBV a -> (SBV a, SBV a)
-liftQRem x y
-  | isConcreteZero x
-  = (x, x)
-  | isConcreteOne y
-  = (x, z)
-{-------------------------------
- - N.B. The seemingly innocuous variant when y == -1 only holds if the type is signed;
- - and also is problematic around the minBound.. So, we refrain from that optimization
-  | isConcreteOnes y
-  = (-x, z)
---------------------------------}
-  | True
-  = ite (y .== z) (z, x) (qr x y)
-  where qr (SBV (SVal sgnsz (Left a))) (SBV (SVal _ (Left b))) = let (q, r) = sQuotRem a b in (SBV (SVal sgnsz (Left q)), SBV (SVal sgnsz (Left r)))
-        qr a@(SBV (SVal sgnsz _))      b                       = (SBV (SVal sgnsz (Right (cache (mk Quot)))), SBV (SVal sgnsz (Right (cache (mk Rem)))))
-                where mk o st = do sw1 <- sbvToSW st a
-                                   sw2 <- sbvToSW st b
-                                   mkSymOp o st sgnsz sw1 sw2
-        z = genLiteral (kindOf x) (0::Integer)
-
--- | Lift 'DMod' 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 :: (SymWord a, Num a, SDivisible (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
-liftDMod x y
-  | isConcreteZero x
-  = (x, x)
-  | isConcreteOne y
-  = (x, z)
-{-------------------------------
- - N.B. The seemingly innocuous variant when y == -1 only holds if the type is signed;
- - and also is problematic around the minBound.. So, we refrain from that optimization
-  | isConcreteOnes y
-  = (-x, z)
---------------------------------}
-  | True
-  = ite (y .== z) (z, x) $ ite (signum r .== negate (signum y)) (q-i, r+y) qr
- where qr@(q, r) = x `sQuotRem` y
-       z = genLiteral (kindOf x) (0::Integer)
-       i = genLiteral (kindOf x) (1::Integer)
-
--- SInteger instance for quotRem/divMod are tricky!
--- SMT-Lib only has Euclidean operations, but Haskell
--- uses "truncate to 0" for quotRem, and "truncate to negative infinity" for divMod.
--- So, we cannot just use the above liftings directly.
-instance SDivisible SInteger where
-  sDivMod = liftDMod
-  sQuotRem x y
-    | not (isSymbolic x || isSymbolic y)
-    = liftQRem x y
-    | True
-    = ite (y .== 0) (0, x) (qE+i, rE-i*y)
-    where (qE, rE) = liftQRem x y   -- for integers, this is euclidean due to SMTLib semantics
-          i = ite (x .>= 0 ||| rE .== 0) 0
-            $ ite (y .>  0)              1 (-1)
-
--- Quickcheck interface
-
--- The Arbitrary instance for SFunArray returns an array initialized
--- to an arbitrary element
-instance (SymWord b, Arbitrary b) => Arbitrary (SFunArray a b) where
-  arbitrary = arbitrary >>= \r -> return $ SFunArray (const r)
-
-instance (SymWord a, Arbitrary a) => Arbitrary (SBV a) where
-  arbitrary = literal `fmap` arbitrary
-
--- |  Symbolic conditionals are modeled by the 'Mergeable' class, describing
--- how to merge the results of an if-then-else call with a symbolic test. SBV
--- provides all basic types as instances of this class, so users only need
--- to declare instances for custom data-types of their programs as needed.
---
--- A 'Mergeable' instance may be automatically derived for a custom data-type
--- with a single constructor where the type of each field is an instance of
--- 'Mergeable', such as a record of symbolic values. Users only need to add
--- 'G.Generic' and 'Mergeable' to the @deriving@ clause for the data-type. See
--- 'Data.SBV.Examples.Puzzles.U2Bridge.Status' for an example and an
--- illustration of what the instance would look like if written by hand.
---
--- The function 'select' is a total-indexing function out of a list of choices
--- with a default value, simulating array/list indexing. It's an n-way generalization
--- of the 'ite' function.
---
--- Minimal complete definition: None, if the type is instance of 'Generic'. Otherwise
--- 'symbolicMerge'. Note that most types subject to merging are likely to be
--- trivial instances of 'Generic'.
-class Mergeable a where
-   -- | Merge two values based on the condition. The first argument states
-   -- whether we force the then-and-else branches before the merging, at the
-   -- word level. This is an efficiency concern; one that we'd rather not
-   -- make but unfortunately necessary for getting symbolic simulation
-   -- working efficiently.
-   symbolicMerge :: Bool -> SBool -> a -> a -> a
-   -- | Total indexing operation. @select xs default index@ is intuitively
-   -- the same as @xs !! index@, except it evaluates to @default@ if @index@
-   -- underflows/overflows.
-   select :: (SymWord 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
-   -- "concrete" subwords: If an index is symbolic, then all its bits are
-   -- symbolic as well. So, the binary search only pays off only if the indexed
-   -- list is really humongous, which is not very common in general. (Also,
-   -- for the case when the list is bit-vectors, we use SMT tables anyhow.)
-   select xs err ind
-    | isReal   ind = bad "real"
-    | isFloat  ind = bad "float"
-    | isDouble ind = bad "double"
-    | hasSign  ind = ite (ind .< 0) err (walk xs ind err)
-    | True         =                     walk xs ind err
-    where bad w = error $ "SBV.select: unsupported " ++ w ++ " valued select/index expression"
-          walk []     _ acc = acc
-          walk (e:es) i acc = walk es (i-1) (ite (i .== 0) e acc)
-
-   -- Default implementation for 'symbolicMerge' if the type is 'Generic'
-   default symbolicMerge :: (G.Generic a, GMergeable (G.Rep a)) => Bool -> SBool -> a -> a -> a
-   symbolicMerge = symbolicMergeDefault
-
-
--- | If-then-else. This is by definition 'symbolicMerge' with both
--- branches forced. This is typically the desired behavior, but also
--- see 'iteLazy' should you need more laziness.
-ite :: Mergeable a => SBool -> a -> a -> a
-ite t a b
-  | Just r <- unliteral t = if r then a else b
-  | True                  = symbolicMerge True t a b
-
--- | A Lazy version of ite, which does not force its arguments. This might
--- cause issues for symbolic simulation with large thunks around, so use with
--- care.
-iteLazy :: Mergeable a => SBool -> a -> a -> a
-iteLazy t a b
-  | Just r <- unliteral t = if r then a else b
-  | True                  = symbolicMerge False t a b
-
--- | Symbolic assert. Check that the given boolean condition is always true in the given path. The
--- optional first argument can be used to provide call-stack info via GHC's location facilities.
-sAssert :: Maybe CallStack -> String -> SBool -> SBV a -> SBV a
-sAssert cs msg cond x = SBV $ SVal k $ Right $ cache r
-  where k     = kindOf x
-        r st  = do xsw <- sbvToSW st x
-                   let pc = getPathCondition st
-                       -- We're checking if there are any cases where the path-condition holds, but not the condition
-                       -- Any violations of this, should be signaled, i.e., whenever the following formula is satisfiable
-                       mustNeverHappen = pc &&& bnot cond
-                   cnd <- sbvToSW st mustNeverHappen
-                   addAssertion st cs msg cnd
-                   return xsw
-
--- | Merge two symbolic values, at kind @k@, possibly @force@'ing the branches to make
--- sure they do not evaluate to the same result. This should only be used for internal purposes;
--- as default definitions provided should suffice in many cases. (i.e., End users should
--- only need to define 'symbolicMerge' when needed; which should be rare to start with.)
-symbolicMergeWithKind :: Kind -> Bool -> SBool -> SBV a -> SBV a -> SBV a
-symbolicMergeWithKind k force (SBV t) (SBV a) (SBV b) = SBV (svSymbolicMerge k force t a b)
-
-instance SymWord a => Mergeable (SBV a) where
-    symbolicMerge force t x y
-    -- Carefully use the kindOf instance to avoid strictness issues.
-       | force = symbolicMergeWithKind (kindOf x)                True  t x y
-       | True  = symbolicMergeWithKind (kindOf (undefined :: a)) False t x y
-    -- Custom version of select that translates to SMT-Lib tables at the base type of words
-    select xs err ind
-      | SBV (SVal _ (Left c)) <- ind = case cwVal c of
-                                         CWInteger i -> if i < 0 || i >= genericLength xs
-                                                        then err
-                                                        else xs `genericIndex` i
-                                         _           -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
-    select xsOrig err ind = xs `seq` SBV (SVal kElt (Right (cache r)))
-      where kInd = kindOf ind
-            kElt = kindOf err
-            -- Based on the index size, we need to limit the elements. For instance if the index is 8 bits, but there
-            -- are 257 elements, that last element will never be used and we can chop it of..
-            xs   = case kindOf ind of
-                     KBounded False i -> genericTake ((2::Integer) ^ (fromIntegral i     :: Integer)) xsOrig
-                     KBounded True  i -> genericTake ((2::Integer) ^ (fromIntegral (i-1) :: Integer)) xsOrig
-                     KUnbounded       -> xsOrig
-                     _                -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
-            r st  = do sws <- mapM (sbvToSW st) xs
-                       swe <- sbvToSW st err
-                       if all (== swe) sws  -- off-chance that all elts are the same. Note that this also correctly covers the case when list is empty.
-                          then return swe
-                          else do idx <- getTableIndex st kInd kElt sws
-                                  swi <- sbvToSW st ind
-                                  let len = length xs
-                                  -- NB. No need to worry here that the index might be < 0; as the SMTLib translation takes care of that automatically
-                                  newExpr st kElt (SBVApp (LkUp (idx, kInd, kElt, len) swi swe) [])
-
--- Unit
-instance Mergeable () where
-   symbolicMerge _ _ _ _ = ()
-   select _ _ _ = ()
-
--- 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..
-
--- Lists
-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)
-    where (lxs, lys) = (length xs, length ys)
-
--- Maybe
-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)
-      where k Nothing = "Nothing"
-            k _       = "Just"
-
--- Either
-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)
-     where k (Left _)  = "Left"
-           k (Right _) = "Right"
-
--- Arrays
-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)
-    where [ba, bb] = map bounds [a, b]
-          k = rangeSize
-
--- Functions
-instance Mergeable b => Mergeable (a -> b) where
-  symbolicMerge f t g h x = symbolicMerge f t (g x) (h x)
-  {- Following definition, while correct, is utterly inefficient. Since the
-     application is delayed, this hangs on to the inner list and all the
-     impending merges, even when ind is concrete. Thus, it's much better to
-     simply use the default definition for the function case.
-  -}
-  -- select xs err ind = \x -> select (map ($ x) xs) (err x) ind
-
--- 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)
-    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)
-    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)
-    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)
-    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)
-    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)
-    where (as, bs, cs, ds, es, fs, gs) = unzip7 xs
-
--- Arbitrary product types, using GHC.Generics
---
--- NB: Because of the way GHC.Generics works, the implementation of
--- symbolicMerge' is recursive. The derived instance for @data T a = T a a a a@
--- resembles that for (a, (a, (a, a))), not the flat 4-tuple (a, a, a, a). This
--- difference should have no effect in practice. Note also that, unlike the
--- hand-rolled tuple instances, the generic instance does not provide a custom
--- 'select' implementation, and so does not benefit from the SMT-table
--- implementation in the 'SBV a' instance.
-
--- | Not exported. Symbolic merge using the generic representation provided by
--- 'G.Generics'.
-symbolicMergeDefault :: (G.Generic a, GMergeable (G.Rep a)) => Bool -> SBool -> a -> a -> a
-symbolicMergeDefault force t x y = G.to $ symbolicMerge' force t (G.from x) (G.from y)
-
--- | Not exported. Used only in 'symbolicMergeDefault'. Instances are provided for
--- the generic representations of product types where each element is Mergeable.
-class GMergeable f where
-  symbolicMerge' :: Bool -> SBool -> f a -> f a -> f a
-
-instance GMergeable U1 where
-  symbolicMerge' _ _ _ _ = U1
-
-instance (Mergeable c) => GMergeable (K1 i c) where
-  symbolicMerge' force t (K1 x) (K1 y) = K1 $ symbolicMerge force t x y
-
-instance (GMergeable f) => GMergeable (M1 i c f) where
-  symbolicMerge' force t (M1 x) (M1 y) = M1 $ symbolicMerge' force t x y
-
-instance (GMergeable f, GMergeable g) => GMergeable (f :*: g) where
-  symbolicMerge' force t (x1 :*: y1) (x2 :*: y2) = symbolicMerge' force t x1 x2 :*: symbolicMerge' force t y1 y2
-
--- Bounded instances
-instance (SymWord a, Bounded a) => Bounded (SBV a) where
-  minBound = literal minBound
-  maxBound = literal maxBound
-
--- Arrays
-
--- SArrays are both "EqSymbolic" and "Mergeable"
-instance EqSymbolic (SArray a b) where
-  (SArray a) .== (SArray b) = SBV (eqSArr a b)
-
--- When merging arrays; we'll ignore the force argument. This is arguably
--- the right thing to do as we've too many things and likely we want to keep it efficient.
-instance SymWord b => Mergeable (SArray a b) where
-  symbolicMerge _ = mergeArrays
-
--- SFunArrays are only "Mergeable". Although a brute
--- force equality can be defined, any non-toy instance
--- will suffer from efficiency issues; so we don't define it
-instance SymArray SFunArray where
-  newArray _                                  = newArray_ -- the name is irrelevant in this case
-  newArray_     mbiVal                        = declNewSFunArray mbiVal
-  readArray     (SFunArray f)                 = f
-  resetArray    (SFunArray _) a               = SFunArray $ const a
-  writeArray    (SFunArray f) a b             = SFunArray (\a' -> ite (a .== a') b (f a'))
-  mergeArrays t (SFunArray g)   (SFunArray h) = SFunArray (\x -> ite t (g x) (h x))
-
--- When merging arrays; we'll ignore the force argument. This is arguably
--- the right thing to do as we've too many things and likely we want to keep it efficient.
-instance SymWord b => Mergeable (SFunArray a b) where
-  symbolicMerge _ = mergeArrays
-
--- | Uninterpreted constants and functions. An uninterpreted constant is
--- a value that is indexed by its name. The only property the prover assumes
--- about these values are that they are equivalent to themselves; i.e., (for
--- functions) they return the same results when applied to same arguments.
--- We support uninterpreted-functions as a general means of black-box'ing
--- operations that are /irrelevant/ for the purposes of the proof; i.e., when
--- the proofs can be performed without any knowledge about the function itself.
---
--- Minimal complete definition: 'sbvUninterpret'. However, most instances in
--- practice are already provided by SBV, so end-users should not need to define their
--- own instances.
-class Uninterpreted a where
-  -- | Uninterpret a value, receiving an object that can be used instead. Use this version
-  -- when you do not need to add an axiom about this value.
-  uninterpret :: String -> a
-  -- | Uninterpret a value, only for the purposes of code-generation. For execution
-  -- and verification the value is used as is. For code-generation, the alternate
-  -- definition is used. This is useful when we want to take advantage of native
-  -- libraries on the target languages.
-  cgUninterpret :: String -> [String] -> a -> a
-  -- | Most generalized form of uninterpretation, this function should not be needed
-  -- by end-user-code, but is rather useful for the library development.
-  sbvUninterpret :: Maybe ([String], a) -> String -> a
-
-  -- minimal complete definition: 'sbvUninterpret'
-  uninterpret             = sbvUninterpret Nothing
-  cgUninterpret nm code v = sbvUninterpret (Just (code, v)) nm
-
--- Plain constants
-instance HasKind a => Uninterpreted (SBV a) where
-  sbvUninterpret mbCgData nm
-     | Just (_, v) <- mbCgData = v
-     | True                    = SBV $ SVal ka $ Right $ cache result
-    where ka = kindOf (undefined :: a)
-          result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st v
-                    | True = do newUninterpreted st nm (SBVType [ka]) (fst `fmap` mbCgData)
-                                newExpr st ka $ SBVApp (Uninterpreted nm) []
-
--- Functions of one argument
-instance (SymWord b, HasKind a) => Uninterpreted (SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0
-           | Just (_, v) <- mbCgData, isConcrete arg0
-           = v arg0
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0)
-                           | True = do newUninterpreted st nm (SBVType [kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       mapM_ forceSWArg [sw0]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0]
-
--- Functions of two arguments
-instance (SymWord c, SymWord b, HasKind a) => Uninterpreted (SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1
-           = v arg0 arg1
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1)
-                           | True = do newUninterpreted st nm (SBVType [kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       mapM_ forceSWArg [sw0, sw1]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1]
-
--- Functions of three arguments
-instance (SymWord d, SymWord c, SymWord b, HasKind a) => Uninterpreted (SBV d -> SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1 arg2
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1, isConcrete arg2
-           = v arg0 arg1 arg2
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 kd = kindOf (undefined :: d)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1 arg2)
-                           | True = do newUninterpreted st nm (SBVType [kd, kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       sw2 <- sbvToSW st arg2
-                                       mapM_ forceSWArg [sw0, sw1, sw2]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1, sw2]
-
--- Functions of four arguments
-instance (SymWord e, SymWord d, SymWord c, SymWord b, HasKind a) => Uninterpreted (SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1 arg2 arg3
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1, isConcrete arg2, isConcrete arg3
-           = v arg0 arg1 arg2 arg3
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 kd = kindOf (undefined :: d)
-                 ke = kindOf (undefined :: e)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1 arg2 arg3)
-                           | True = do newUninterpreted st nm (SBVType [ke, kd, kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       sw2 <- sbvToSW st arg2
-                                       sw3 <- sbvToSW st arg3
-                                       mapM_ forceSWArg [sw0, sw1, sw2, sw3]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1, sw2, sw3]
-
--- Functions of five arguments
-instance (SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a) => Uninterpreted (SBV f -> SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1 arg2 arg3 arg4
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1, isConcrete arg2, isConcrete arg3, isConcrete arg4
-           = v arg0 arg1 arg2 arg3 arg4
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 kd = kindOf (undefined :: d)
-                 ke = kindOf (undefined :: e)
-                 kf = kindOf (undefined :: f)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1 arg2 arg3 arg4)
-                           | True = do newUninterpreted st nm (SBVType [kf, ke, kd, kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       sw2 <- sbvToSW st arg2
-                                       sw3 <- sbvToSW st arg3
-                                       sw4 <- sbvToSW st arg4
-                                       mapM_ forceSWArg [sw0, sw1, sw2, sw3, sw4]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1, sw2, sw3, sw4]
-
--- Functions of six arguments
-instance (SymWord g, SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a) => Uninterpreted (SBV g -> SBV f -> SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1 arg2 arg3 arg4 arg5
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1, isConcrete arg2, isConcrete arg3, isConcrete arg4, isConcrete arg5
-           = v arg0 arg1 arg2 arg3 arg4 arg5
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 kd = kindOf (undefined :: d)
-                 ke = kindOf (undefined :: e)
-                 kf = kindOf (undefined :: f)
-                 kg = kindOf (undefined :: g)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1 arg2 arg3 arg4 arg5)
-                           | True = do newUninterpreted st nm (SBVType [kg, kf, ke, kd, kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       sw2 <- sbvToSW st arg2
-                                       sw3 <- sbvToSW st arg3
-                                       sw4 <- sbvToSW st arg4
-                                       sw5 <- sbvToSW st arg5
-                                       mapM_ forceSWArg [sw0, sw1, sw2, sw3, sw4, sw5]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1, sw2, sw3, sw4, sw5]
-
--- Functions of seven arguments
-instance (SymWord h, SymWord g, SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a)
-            => Uninterpreted (SBV h -> SBV g -> SBV f -> SBV e -> SBV d -> SBV c -> SBV b -> SBV a) where
-  sbvUninterpret mbCgData nm = f
-    where f arg0 arg1 arg2 arg3 arg4 arg5 arg6
-           | Just (_, v) <- mbCgData, isConcrete arg0, isConcrete arg1, isConcrete arg2, isConcrete arg3, isConcrete arg4, isConcrete arg5, isConcrete arg6
-           = v arg0 arg1 arg2 arg3 arg4 arg5 arg6
-           | True
-           = SBV $ SVal ka $ Right $ cache result
-           where ka = kindOf (undefined :: a)
-                 kb = kindOf (undefined :: b)
-                 kc = kindOf (undefined :: c)
-                 kd = kindOf (undefined :: d)
-                 ke = kindOf (undefined :: e)
-                 kf = kindOf (undefined :: f)
-                 kg = kindOf (undefined :: g)
-                 kh = kindOf (undefined :: h)
-                 result st | Just (_, v) <- mbCgData, inProofMode st = sbvToSW st (v arg0 arg1 arg2 arg3 arg4 arg5 arg6)
-                           | True = do newUninterpreted st nm (SBVType [kh, kg, kf, ke, kd, kc, kb, ka]) (fst `fmap` mbCgData)
-                                       sw0 <- sbvToSW st arg0
-                                       sw1 <- sbvToSW st arg1
-                                       sw2 <- sbvToSW st arg2
-                                       sw3 <- sbvToSW st arg3
-                                       sw4 <- sbvToSW st arg4
-                                       sw5 <- sbvToSW st arg5
-                                       sw6 <- sbvToSW st arg6
-                                       mapM_ forceSWArg [sw0, sw1, sw2, sw3, sw4, sw5, sw6]
-                                       newExpr st ka $ SBVApp (Uninterpreted nm) [sw0, sw1, sw2, sw3, sw4, sw5, sw6]
-
--- Uncurried functions of two arguments
-instance (SymWord c, SymWord b, HasKind a) => Uninterpreted ((SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc2 `fmap` mbCgData) nm in uncurry f
-    where uc2 (cs, fn) = (cs, curry fn)
-
--- Uncurried functions of three arguments
-instance (SymWord d, SymWord c, SymWord b, HasKind a) => Uninterpreted ((SBV d, SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc3 `fmap` mbCgData) nm in \(arg0, arg1, arg2) -> f arg0 arg1 arg2
-    where uc3 (cs, fn) = (cs, \a b c -> fn (a, b, c))
-
--- Uncurried functions of four arguments
-instance (SymWord e, SymWord d, SymWord c, SymWord b, HasKind a)
-            => Uninterpreted ((SBV e, SBV d, SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc4 `fmap` mbCgData) nm in \(arg0, arg1, arg2, arg3) -> f arg0 arg1 arg2 arg3
-    where uc4 (cs, fn) = (cs, \a b c d -> fn (a, b, c, d))
-
--- Uncurried functions of five arguments
-instance (SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a)
-            => Uninterpreted ((SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc5 `fmap` mbCgData) nm in \(arg0, arg1, arg2, arg3, arg4) -> f arg0 arg1 arg2 arg3 arg4
-    where uc5 (cs, fn) = (cs, \a b c d e -> fn (a, b, c, d, e))
-
--- Uncurried functions of six arguments
-instance (SymWord g, SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a)
-            => Uninterpreted ((SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc6 `fmap` mbCgData) nm in \(arg0, arg1, arg2, arg3, arg4, arg5) -> f arg0 arg1 arg2 arg3 arg4 arg5
-    where uc6 (cs, fn) = (cs, \a b c d e f -> fn (a, b, c, d, e, f))
-
--- Uncurried functions of seven arguments
-instance (SymWord h, SymWord g, SymWord f, SymWord e, SymWord d, SymWord c, SymWord b, HasKind a)
-            => Uninterpreted ((SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
-  sbvUninterpret mbCgData nm = let f = sbvUninterpret (uc7 `fmap` mbCgData) nm in \(arg0, arg1, arg2, arg3, arg4, arg5, arg6) -> f arg0 arg1 arg2 arg3 arg4 arg5 arg6
-    where uc7 (cs, fn) = (cs, \a b c d e f g -> fn (a, b, c, d, e, f, g))
-
--- | Adding arbitrary constraints. When adding constraints, one has to be careful about
--- making sure they are not inconsistent. The function 'isVacuous' can be use for this purpose.
--- Here is an example. Consider the following predicate:
---
--- >>> let pred = do { x <- forall "x"; constrain $ x .< x; return $ x .>= (5 :: SWord8) }
---
--- This predicate asserts that all 8-bit values are larger than 5, subject to the constraint that the
--- values considered satisfy @x .< x@, i.e., they are less than themselves. Since there are no values that
--- satisfy this constraint, the proof will pass vacuously:
---
--- >>> prove pred
--- Q.E.D.
---
--- We can use 'isVacuous' to make sure to see that the pass was vacuous:
---
--- >>> isVacuous pred
--- True
---
--- While the above example is trivial, things can get complicated if there are multiple constraints with
--- non-straightforward relations; so if constraints are used one should make sure to check the predicate
--- is not vacuously true. Here's an example that is not vacuous:
---
---  >>> let pred' = do { x <- forall "x"; constrain $ x .> 6; return $ x .>= (5 :: SWord8) }
---
--- This time the proof passes as expected:
---
---  >>> prove pred'
---  Q.E.D.
---
--- And the proof is not vacuous:
---
---  >>> isVacuous pred'
---  False
-constrain :: SBool -> Symbolic ()
-constrain c = addConstraint Nothing c (bnot c)
-
--- | Adding a probabilistic constraint. The 'Double' argument is the probability
--- threshold. Probabilistic constraints are useful for 'genTest' and 'quickCheck'
--- calls where we restrict our attention to /interesting/ parts of the input domain.
-pConstrain :: Double -> SBool -> Symbolic ()
-pConstrain t c = addConstraint (Just t) c (bnot c)
-
--- Quickcheck interface on symbolic-booleans..
-instance Testable SBool where
-  property (SBV (SVal _ (Left b))) = property (cwToBool b)
-  property s                       = error $ "Cannot quick-check in the presence of uninterpreted constants! (" ++ show s ++ ")"
-
-instance Testable (Symbolic SBool) where
-   property prop = QC.monadicIO $ do (cond, r, tvals) <- QC.run (newStdGen >>= test)
-                                     QC.pre cond
-                                     unless (r || null tvals) $ QC.monitor (QC.counterexample (complain tvals))
-                                     QC.assert r
-     where test g = do (r, Result{resTraces=tvals, resConsts=cs, resConstraints=cstrs, resUIConsts=unints}) <- runSymbolic' (Concrete g) prop
-                       let cval = fromMaybe (error "Cannot quick-check in the presence of uninterpeted constants!") . (`lookup` cs)
-                           cond = all (cwToBool . cval) cstrs
-                       case map fst unints of
-                         [] -> case unliteral r of
-                                 Nothing -> noQC [show r]
-                                 Just b  -> return (cond, b, tvals)
-                         us -> noQC us
-           complain qcInfo = showModel defaultSMTCfg (SMTModel qcInfo)
-           noQC us         = error $ "Cannot quick-check in the presence of uninterpreted constants: " ++ intercalate ", " us
-
--- | Quick check an SBV property. Note that a regular 'quickCheck' call will work just as
--- well. Use this variant if you want to receive the boolean result.
-sbvQuickCheck :: Symbolic SBool -> IO Bool
-sbvQuickCheck prop = QC.isSuccess `fmap` QC.quickCheckResult prop
-
--- Quickcheck interface on dynamically-typed values. A run-time check
--- ensures that the value has boolean type.
-instance Testable (Symbolic SVal) where
-  property m = property $ do s <- m
-                             when (kindOf s /= KBool) $ error "Cannot quickcheck non-boolean value"
-                             return (SBV s :: SBool)
-
--- | Explicit sharing combinator. The SBV library has internal caching/hash-consing mechanisms
--- built in, based on Andy Gill's type-safe obervable sharing technique (see: <http://ittc.ku.edu/~andygill/paper.php?label=DSLExtract09>).
--- However, there might be times where being explicit on the sharing can help, especially in experimental code. The 'slet' combinator
--- ensures that its first argument is computed once and passed on to its continuation, explicitly indicating the intent of sharing. Most
--- use cases of the SBV library should simply use Haskell's @let@ construct for this purpose.
-slet :: forall a b. (HasKind a, HasKind b) => SBV a -> (SBV a -> SBV b) -> SBV b
-slet x f = SBV $ SVal k $ Right $ cache r
-    where k    = kindOf (undefined :: b)
-          r st = do xsw <- sbvToSW st x
-                    let xsbv = SBV $ SVal (kindOf x) (Right (cache (const (return xsw))))
-                        res  = f xsbv
-                    sbvToSW st res
-
--- | Check if a boolean condition is satisfiable in the current state. This function can be useful in contexts where an
--- interpreter implemented on top of SBV needs to decide if a particular stae (represented by the boolean) is reachable
--- in the current if-then-else paths implied by the 'ite' calls.
-isSatisfiableInCurrentPath :: SBool -> Symbolic Bool
-isSatisfiableInCurrentPath cond = do
-       st <- ask
-       let cfg  = fromMaybe defaultSMTCfg (getSBranchRunConfig st)
-           msg  = when (verbose cfg) . putStrLn . ("** " ++)
-           pc   = getPathCondition st
-       check <- liftIO $ internalSATCheck cfg (pc &&& cond) st "isSatisfiableInCurrentPath: Checking satisfiability"
-       let res = case check of
-                   SatResult Satisfiable{}     -> True
-                   SatResult (Unsatisfiable _) -> False
-                   _                           -> error $ "isSatisfiableInCurrentPath: Unexpected external result: " ++ show check
-       res `seq` liftIO $ msg $ "isSatisfiableInCurrentPath: Conclusion: " ++ if res then "Satisfiable" else "Unsatisfiable"
-       return res
-
--- We use 'isVacuous' and 'prove' only for the "test" section in this file, and GHC complains about that. So, this shuts it up.
-__unused :: a
-__unused = error "__unused" (isVacuous :: SBool -> IO Bool) (prove :: SBool -> IO ThmResult)
-
-{-# ANN module   ("HLint: ignore Reduce duplication" :: String)#-}
-{-# ANN module   ("HLint: ignore Eta reduce" :: String)        #-}
diff --git a/Data/SBV/BitVectors/Operations.hs b/Data/SBV/BitVectors/Operations.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Operations.hs
+++ /dev/null
@@ -1,807 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Operations
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Constructors and basic operations on symbolic values
------------------------------------------------------------------------------
-
-{-# LANGUAGE BangPatterns #-}
-
-module Data.SBV.BitVectors.Operations
-  (
-  -- ** Basic constructors
-    svTrue, svFalse, svBool
-  , svInteger, svFloat, svDouble, svReal, svEnumFromThenTo
-  -- ** Basic destructors
-  , svAsBool, svAsInteger, svNumerator, svDenominator
-  -- ** Basic operations
-  , svPlus, svTimes, svMinus, svUNeg, svAbs
-  , svDivide, svQuot, svRem
-  , svEqual, svNotEqual
-  , svLessThan, svGreaterThan, svLessEq, svGreaterEq
-  , svAnd, svOr, svXOr, svNot
-  , svShl, svShr, svRol, svRor
-  , svExtract, svJoin
-  , svUninterpreted
-  , svIte, svLazyIte, svSymbolicMerge
-  , svSelect
-  , svSign, svUnsign, svSetBit, svWordFromBE, svWordFromLE
-  , svExp, svFromIntegral
-  -- ** Derived operations
-  , svToWord1, svFromWord1, svTestBit
-  , svShiftLeft, svShiftRight
-  , svRotateLeft, svRotateRight
-  , svBlastLE, svBlastBE
-  , svAddConstant, svIncrement, svDecrement
-  )
-  where
-
-import Data.Bits (Bits(..))
-import Data.List (genericIndex, genericLength, genericTake)
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Kind
-import Data.SBV.BitVectors.Concrete
-import Data.SBV.BitVectors.Symbolic
-
-import Data.Ratio
-
---------------------------------------------------------------------------------
--- Basic constructors
-
--- | Boolean True.
-svTrue :: SVal
-svTrue = SVal KBool (Left trueCW)
-
--- | Boolean False.
-svFalse :: SVal
-svFalse = SVal KBool (Left falseCW)
-
--- | Convert from a Boolean.
-svBool :: Bool -> SVal
-svBool b = if b then svTrue else svFalse
-
--- | Convert from an Integer.
-svInteger :: Kind -> Integer -> SVal
-svInteger k n = SVal k (Left $! mkConstCW k n)
-
--- | Convert from a Float
-svFloat :: Float -> SVal
-svFloat f = SVal KFloat (Left $! CW KFloat (CWFloat f))
-
--- | Convert from a Float
-svDouble :: Double -> SVal
-svDouble d = SVal KDouble (Left $! CW KDouble (CWDouble d))
-
--- | Convert from a Rational
-svReal :: Rational -> SVal
-svReal d = SVal KReal (Left $! CW KReal (CWAlgReal (fromRational d)))
-
---------------------------------------------------------------------------------
--- Basic destructors
-
--- | Extract a bool, by properly interpreting the integer stored.
-svAsBool :: SVal -> Maybe Bool
-svAsBool (SVal _ (Left cw)) = Just (cwToBool cw)
-svAsBool _                  = Nothing
-
--- | Extract an integer from a concrete value.
-svAsInteger :: SVal -> Maybe Integer
-svAsInteger (SVal _ (Left (CW _ (CWInteger n)))) = Just n
-svAsInteger _                                    = Nothing
-
--- | Grab the numerator of an SReal, if available
-svNumerator :: SVal -> Maybe Integer
-svNumerator (SVal KReal (Left (CW KReal (CWAlgReal (AlgRational True r))))) = Just $ numerator r
-svNumerator _                                                               = Nothing
-
--- | Grab the denominator of an SReal, if available
-svDenominator :: SVal -> Maybe Integer
-svDenominator (SVal KReal (Left (CW KReal (CWAlgReal (AlgRational True r))))) = Just $ denominator r
-svDenominator _                                                               = Nothing
-
--------------------------------------------------------------------------------------
--- | Constructing [x, y, .. z] and [x .. y]. Only works when all arguments are concrete and integral and the result is guaranteed finite
--- Note that the it isn't "obviously" clear why the following works; after all we're doing the construction over Integer's and mapping
--- it back to other types such as SIntN/SWordN. The reason is that the values we receive are guaranteed to be in their domains; and thus
--- the lifting to Integers preserves the bounds; and then going back is just fine. So, things like @[1, 5 .. 200] :: [SInt8]@ work just
--- fine (end evaluate to empty list), since we see @[1, 5 .. -56]@ in the @Integer@ domain. Also note the explicit check for @s /= f@
--- below to make sure we don't stutter and produce an infinite list.
-svEnumFromThenTo :: SVal -> Maybe SVal -> SVal -> Maybe [SVal]
-svEnumFromThenTo bf mbs bt
-  | Just bs <- mbs, Just f <- svAsInteger bf, Just s <- svAsInteger bs, Just t <- svAsInteger bt, s /= f = Just $ map (svInteger (kindOf bf)) [f, s .. t]
-  | Nothing <- mbs, Just f <- svAsInteger bf,                           Just t <- svAsInteger bt         = Just $ map (svInteger (kindOf bf)) [f    .. t]
-  | True                                                                                                 = Nothing
-
--------------------------------------------------------------------------------------
--- Basic operations
-
--- | Addition.
-svPlus :: SVal -> SVal -> SVal
-svPlus x y
-  | isConcreteZero x = y
-  | isConcreteZero y = x
-  | True             = liftSym2 (mkSymOp Plus) rationalCheck (+) (+) (+) (+) x y
-
--- | Multiplication.
-svTimes :: SVal -> SVal -> SVal
-svTimes x y
-  | isConcreteZero x = x
-  | isConcreteZero y = y
-  | isConcreteOne x  = y
-  | isConcreteOne y  = x
-  | True             = liftSym2 (mkSymOp Times) rationalCheck (*) (*) (*) (*) x y
-
--- | Subtraction.
-svMinus :: SVal -> SVal -> SVal
-svMinus x y
-  | isConcreteZero y = x
-  | True             = liftSym2 (mkSymOp Minus) rationalCheck (-) (-) (-) (-) x y
-
--- | Unary minus.
-svUNeg :: SVal -> SVal
-svUNeg = liftSym1 (mkSymOp1 UNeg) negate negate negate negate
-
--- | Absolute value.
-svAbs :: SVal -> SVal
-svAbs = liftSym1 (mkSymOp1 Abs) abs abs abs abs
-
--- | Division.
-svDivide :: SVal -> SVal -> SVal
-svDivide = liftSym2 (mkSymOp Quot) rationalCheck (/) die (/) (/)
-   where -- should never happen
-         die = error "impossible: integer valued data found in Fractional instance"
-
--- | Exponentiation.
-svExp :: SVal -> SVal -> SVal
-svExp b e | hasSign (kindOf e) = error "svExp: exponentiation only works with unsigned exponents"
-          | True               = prod $ zipWith (\use n -> svIte use n one)
-                                                (svBlastLE e)
-                                                (iterate (\x -> svTimes x x) b)
-         where prod = foldr svTimes one
-               one  = svInteger (kindOf b) 1
-
--- | Bit-blast: Little-endian. Assumes the input is a bit-vector.
-svBlastLE :: SVal -> [SVal]
-svBlastLE x = map (svTestBit x) [0 .. intSizeOf x - 1]
-
--- | Set a given bit at index
-svSetBit :: SVal -> Int -> SVal
-svSetBit x i = x `svXOr` svInteger (kindOf x) (bit i :: Integer)
-
--- | Bit-blast: Big-endian. Assumes the input is a bit-vector.
-svBlastBE :: SVal -> [SVal]
-svBlastBE = reverse . svBlastLE
-
--- | Un-bit-blast from big-endian representation to a word of the right size.
--- The input is assumed to be unsigned.
-svWordFromLE :: [SVal] -> SVal
-svWordFromLE bs = go zero 0 bs
-  where zero = svInteger (KBounded False (length bs)) 0
-        go !acc _  []     = acc
-        go !acc !i (x:xs) = go (svIte x (svSetBit acc i) acc) (i+1) xs
-
--- | Un-bit-blast from little-endian representation to a word of the right size.
--- The input is assumed to be unsigned.
-svWordFromBE :: [SVal] -> SVal
-svWordFromBE = svWordFromLE . reverse
-
--- | Add a constant value:
-svAddConstant :: Integral a => SVal -> a -> SVal
-svAddConstant x i = x `svPlus` svInteger (kindOf x) (fromIntegral i)
-
--- | Increment:
-svIncrement :: SVal -> SVal
-svIncrement x = svAddConstant x (1::Integer)
-
--- | Decrement:
-svDecrement :: SVal -> SVal
-svDecrement x = svAddConstant x (-1 :: Integer)
-
--- | Quotient: Overloaded operation whose meaning depends on the kind at which
--- it is used: For unbounded integers, it corresponds to the SMT-Lib
--- "div" operator ("Euclidean" division, which always has a
--- non-negative remainder). For unsigned bitvectors, it is "bvudiv";
--- and for signed bitvectors it is "bvsdiv", which rounds toward zero.
--- All operations have unspecified semantics in case @y = 0@.
-svQuot :: SVal -> SVal -> SVal
-svQuot x y
-  | isConcreteZero x = x
-  | isConcreteOne y  = x
-  | True             = liftSym2 (mkSymOp Quot) nonzeroCheck
-                                (noReal "quot") quot' (noFloat "quot") (noDouble "quot") x y
-  where
-    quot' a b | kindOf x == KUnbounded = div a (abs b) * signum b
-              | otherwise              = quot a b
-
--- | Remainder: Overloaded operation whose meaning depends on the kind at which
--- it is used: For unbounded integers, it corresponds to the SMT-Lib
--- "mod" operator (always non-negative). For unsigned bitvectors, it
--- is "bvurem"; and for signed bitvectors it is "bvsrem", which rounds
--- toward zero (sign of remainder matches that of @x@). All operations
--- have unspecified semantics in case @y = 0@.
-svRem :: SVal -> SVal -> SVal
-svRem x y
-  | isConcreteZero x = x
-  | isConcreteOne y  = svInteger (kindOf x) 0
-  | True             = liftSym2 (mkSymOp Rem) nonzeroCheck
-                                (noReal "rem") rem' (noFloat "rem") (noDouble "rem") x y
-  where
-    rem' a b | kindOf x == KUnbounded = mod a (abs b)
-             | otherwise              = rem a b
-
--- | Optimize away x == true and x /= false to x; otherwise just do eqOpt
-eqOptBool :: Op -> SW -> SW -> SW -> Maybe SW
-eqOptBool op w x y
-  | k == KBool && op == Equal    && x == trueSW  = Just y         -- true  .== y     --> y
-  | k == KBool && op == Equal    && y == trueSW  = Just x         -- x     .== true  --> x
-  | k == KBool && op == NotEqual && x == falseSW = Just y         -- false ./= y     --> y
-  | k == KBool && op == NotEqual && y == falseSW = Just x         -- x     ./= false --> x
-  | True                                         = eqOpt w x y    -- fallback
-  where k = swKind x
-
--- | Equality.
-svEqual :: SVal -> SVal -> SVal
-svEqual = liftSym2B (mkSymOpSC (eqOptBool Equal trueSW) Equal) rationalCheck (==) (==) (==) (==) (==)
-
--- | Inequality.
-svNotEqual :: SVal -> SVal -> SVal
-svNotEqual = liftSym2B (mkSymOpSC (eqOptBool NotEqual falseSW) NotEqual) rationalCheck (/=) (/=) (/=) (/=) (/=)
-
--- | Less than.
-svLessThan :: SVal -> SVal -> SVal
-svLessThan x y
-  | isConcreteMax x = svFalse
-  | isConcreteMin y = svFalse
-  | True            = liftSym2B (mkSymOpSC (eqOpt falseSW) LessThan) rationalCheck (<) (<) (<) (<) (uiLift "<" (<)) x y
-
--- | Greater than.
-svGreaterThan :: SVal -> SVal -> SVal
-svGreaterThan x y
-  | isConcreteMin x = svFalse
-  | isConcreteMax y = svFalse
-  | True            = liftSym2B (mkSymOpSC (eqOpt falseSW) 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 trueSW) 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 trueSW) GreaterEq) rationalCheck (>=) (>=) (>=) (>=) (uiLift ">=" (>=)) x y
-
--- | Bitwise and.
-svAnd :: SVal -> SVal -> SVal
-svAnd x y
-  | isConcreteZero x = x
-  | isConcreteOnes x = y
-  | isConcreteZero y = y
-  | isConcreteOnes y = x
-  | True             = liftSym2 (mkSymOpSC opt And) (const (const True)) (noReal ".&.") (.&.) (noFloat ".&.") (noDouble ".&.") x y
-  where opt a b
-          | a == falseSW || b == falseSW = Just falseSW
-          | a == trueSW                  = Just b
-          | b == trueSW                  = Just a
-          | True                         = Nothing
-
--- | Bitwise or.
-svOr :: SVal -> SVal -> SVal
-svOr x y
-  | isConcreteZero x = y
-  | isConcreteOnes x = x
-  | isConcreteZero y = x
-  | isConcreteOnes y = y
-  | True             = liftSym2 (mkSymOpSC opt Or) (const (const True))
-                       (noReal ".|.") (.|.) (noFloat ".|.") (noDouble ".|.") x y
-  where opt a b
-          | a == trueSW || b == trueSW = Just trueSW
-          | a == falseSW               = Just b
-          | b == falseSW               = Just a
-          | True                       = Nothing
-
--- | Bitwise xor.
-svXOr :: SVal -> SVal -> SVal
-svXOr x y
-  | isConcreteZero x = y
-  | isConcreteOnes x = svNot y
-  | isConcreteZero y = x
-  | isConcreteOnes y = svNot x
-  | True             = liftSym2 (mkSymOpSC opt XOr) (const (const True))
-                       (noReal "xor") xor (noFloat "xor") (noDouble "xor") x y
-  where opt a b
-          | a == b && swKind a == KBool = Just falseSW
-          | a == falseSW                = Just b
-          | b == falseSW                = Just a
-          | True                        = Nothing
-
--- | Bitwise complement.
-svNot :: SVal -> SVal
-svNot = liftSym1 (mkSymOp1SC opt Not)
-                 (noRealUnary "complement") complement
-                 (noFloatUnary "complement") (noDoubleUnary "complement")
-  where opt a
-          | a == falseSW = Just trueSW
-          | a == trueSW  = Just falseSW
-          | True         = Nothing
-
--- | Shift left by a constant amount. Translates to the "bvshl"
--- operation in SMT-Lib.
-svShl :: SVal -> Int -> SVal
-svShl x i
-  | i < 0   = svShr x (-i)
-  | i == 0  = x
-  | True    = liftSym1 (mkSymOp1 (Shl i))
-                       (noRealUnary "shiftL") (`shiftL` i)
-                       (noFloatUnary "shiftL") (noDoubleUnary "shiftL") x
-
--- | 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.
-svShr :: SVal -> Int -> SVal
-svShr x i
-  | i < 0   = svShl x (-i)
-  | i == 0  = x
-  | True    = liftSym1 (mkSymOp1 (Shr i))
-                       (noRealUnary "shiftR") (`shiftR` i)
-                       (noFloatUnary "shiftR") (noDoubleUnary "shiftR") x
-
--- | Rotate-left, by a constant
-svRol :: SVal -> Int -> SVal
-svRol x i
-  | i < 0   = svRor x (-i)
-  | i == 0  = x
-  | True    = case kindOf x of
-                KBounded _ sz -> liftSym1 (mkSymOp1 (Rol (i `mod` sz)))
-                                          (noRealUnary "rotateL") (rot True sz i)
-                                          (noFloatUnary "rotateL") (noDoubleUnary "rotateL") x
-                _ -> svShl x i   -- for unbounded Integers, rotateL is the same as shiftL in Haskell
-
--- | Rotate-right, by a constant
-svRor :: SVal -> Int -> SVal
-svRor x i
-  | i < 0   = svRol x (-i)
-  | i == 0  = x
-  | True    = case kindOf x of
-                KBounded _ sz -> liftSym1 (mkSymOp1 (Ror (i `mod` sz)))
-                                          (noRealUnary "rotateR") (rot False sz i)
-                                          (noFloatUnary "rotateR") (noDoubleUnary "rotateR") x
-                _ -> svShr x i   -- for unbounded integers, rotateR is the same as shiftR in Haskell
-
--- | Generic rotation. Since the underlying representation is just Integers, rotations has to be
--- careful on the bit-size.
-rot :: Bool -> Int -> Int -> Integer -> Integer
-rot toLeft sz amt x
-  | sz < 2 = x
-  | True   = norm x y' `shiftL` y  .|. norm (x `shiftR` y') y
-  where (y, y') | toLeft = (amt `mod` sz, sz - y)
-                | True   = (sz - y', amt `mod` sz)
-        norm v s = v .&. ((1 `shiftL` s) - 1)
-
--- | Extract bit-sequences.
-svExtract :: Int -> Int -> SVal -> SVal
-svExtract i j x@(SVal (KBounded s _) _)
-  | i < j
-  = SVal k (Left $! CW k (CWInteger 0))
-  | SVal _ (Left (CW _ (CWInteger v))) <- x
-  = SVal k (Left $! normCW (CW k (CWInteger (v `shiftR` j))))
-  | True
-  = SVal k (Right (cache y))
-  where k = KBounded s (i - j + 1)
-        y st = do sw <- svToSW st x
-                  newExpr st k (SBVApp (Extract i j) [sw])
-svExtract _ _ _ = error "extract: non-bitvector type"
-
--- | Join two words, by concataneting
-svJoin :: SVal -> SVal -> SVal
-svJoin x@(SVal (KBounded s i) a) y@(SVal (KBounded _ j) b)
-  | i == 0 = y
-  | j == 0 = x
-  | Left (CW _ (CWInteger m)) <- a, Left (CW _ (CWInteger n)) <- b
-  = SVal k (Left $! CW k (CWInteger (m `shiftL` j .|. n)))
-  | True
-  = SVal k (Right (cache z))
-  where
-    k = KBounded s (i + j)
-    z st = do xsw <- svToSW st x
-              ysw <- svToSW st y
-              newExpr st k (SBVApp Join [xsw, ysw])
-svJoin _ _ = error "svJoin: non-bitvector type"
-
--- | Uninterpreted constants and functions. An uninterpreted constant is
--- a value that is indexed by its name. The only property the prover assumes
--- about these values are that they are equivalent to themselves; i.e., (for
--- functions) they return the same results when applied to same arguments.
--- We support uninterpreted-functions as a general means of black-box'ing
--- operations that are /irrelevant/ for the purposes of the proof; i.e., when
--- the proofs can be performed without any knowledge about the function itself.
-svUninterpreted :: Kind -> String -> Maybe [String] -> [SVal] -> SVal
-svUninterpreted k nm code args = SVal k $ Right $ cache result
-  where result st = do let ty = SBVType (map kindOf args ++ [k])
-                       newUninterpreted st nm ty code
-                       sws <- mapM (svToSW st) args
-                       mapM_ forceSWArg sws
-                       newExpr st k $ SBVApp (Uninterpreted nm) sws
-
--- | If-then-else. This one will force branches.
-svIte :: SVal -> SVal -> SVal -> SVal
-svIte t a b = svSymbolicMerge (kindOf a) True t a b
-
--- | Lazy If-then-else. This one will delay forcing the branches unless it's really necessary.
-svLazyIte :: Kind -> SVal -> SVal -> SVal -> SVal
-svLazyIte k t a b = svSymbolicMerge k False t a b
-
--- | Merge two symbolic values, at kind @k@, possibly @force@'ing the branches to make
--- sure they do not evaluate to the same result.
-svSymbolicMerge :: Kind -> Bool -> SVal -> SVal -> SVal -> SVal
-svSymbolicMerge k force t a b
-  | Just r <- svAsBool t
-  = if r then a else b
-  | force, rationalSBVCheck a b, areConcretelyEqual a b
-  = a
-  | True
-  = SVal k $ Right $ cache c
-  where c st = do swt <- svToSW st t
-                  case () of
-                    () | swt == trueSW  -> svToSW st a       -- these two cases should never be needed as we expect symbolicMerge to be
-                    () | swt == falseSW -> svToSW st b       -- called with symbolic tests, but just in case..
-                    () -> do {- It is tempting to record the choice of the test expression here as we branch down to the 'then' and 'else' branches. That is,
-                                when we evaluate 'a', we can make use of the fact that the test expression is True, and similarly we can use the fact that it
-                                is False when b is evaluated. In certain cases this can cut down on symbolic simulation significantly, for instance if
-                                repetitive decisions are made in a recursive loop. Unfortunately, the implementation of this idea is quite tricky, due to
-                                our sharing based implementation. As the 'then' branch is evaluated, we will create many expressions that are likely going
-                                to be "reused" when the 'else' branch is executed. But, it would be *dead wrong* to share those values, as they were "cached"
-                                under the incorrect assumptions. To wit, consider the following:
-
-                                   foo x y = ite (y .== 0) k (k+1)
-                                     where k = ite (y .== 0) x (x+1)
-
-                                When we reduce the 'then' branch of the first ite, we'd record the assumption that y is 0. But while reducing the 'then' branch, we'd
-                                like to share 'k', which would evaluate (correctly) to 'x' under the given assumption. When we backtrack and evaluate the 'else'
-                                branch of the first ite, we'd see 'k' is needed again, and we'd look it up from our sharing map to find (incorrectly) that its value
-                                is 'x', which was stored there under the assumption that y was 0, which no longer holds. Clearly, this is unsound.
-
-                                A sound implementation would have to precisely track which assumptions were active at the time expressions get shared. That is,
-                                in the above example, we should record that the value of 'k' was cached under the assumption that 'y' is 0. While sound, this
-                                approach unfortunately leads to significant loss of valid sharing when the value itself had nothing to do with the assumption itself.
-                                To wit, consider:
-
-                                   foo x y = ite (y .== 0) k (k+1)
-                                     where k = x+5
-
-                                If we tracked the assumptions, we would recompute 'k' twice, since the branch assumptions would differ. Clearly, there is no need to
-                                re-compute 'k' in this case since its value is independent of y. Note that the whole SBV performance story is based on agressive sharing,
-                                and losing that would have other significant ramifications.
-
-                                The "proper" solution would be to track, with each shared computation, precisely which assumptions it actually *depends* on, rather
-                                than blindly recording all the assumptions present at that time. SBV's symbolic simulation engine clearly has all the info needed to do this
-                                properly, but the implementation is not straightforward at all. For each subexpression, we would need to chase down its dependencies
-                                transitively, which can require a lot of scanning of the generated program causing major slow-down; thus potentially defeating the
-                                whole purpose of sharing in the first place.
-
-                                Design choice: Keep it simple, and simply do not track the assumption at all. This will maximize sharing, at the cost of evaluating
-                                unreachable branches. I think the simplicity is more important at this point than efficiency.
-
-                                Also note that the user can avoid most such issues by properly combining if-then-else's with common conditions together. That is, the
-                                first program above should be written like this:
-
-                                  foo x y = ite (y .== 0) x (x+2)
-
-                                In general, the following transformations should be done whenever possible:
-
-                                  ite e1 (ite e1 e2 e3) e4  --> ite e1 e2 e4
-                                  ite e1 e2 (ite e1 e3 e4)  --> ite e1 e2 e4
-
-                                This is in accordance with the general rule-of-thumb stating conditionals should be avoided as much as possible. However, we might prefer
-                                the following:
-
-                                  ite e1 (f e2 e4) (f e3 e5) --> f (ite e1 e2 e3) (ite e1 e4 e5)
-
-                                especially if this expression happens to be inside 'f's body itself (i.e., when f is recursive), since it reduces the number of
-                                recursive calls. Clearly, programming with symbolic simulation in mind is another kind of beast alltogether.
-                             -}
-                             let sta = st `extendSValPathCondition` svAnd t
-                             let stb = st `extendSValPathCondition` svAnd (svNot t)
-                             swa <- svToSW sta a -- evaluate 'then' branch
-                             swb <- svToSW stb b -- evaluate 'else' branch
-                             case () of               -- merge:
-                               () | swa == swb                      -> return swa
-                               () | swa == trueSW && swb == falseSW -> return swt
-                               () | swa == falseSW && swb == trueSW -> newExpr st k (SBVApp Not [swt])
-                               ()                                   -> newExpr st k (SBVApp Ite [swt, swa, swb])
-
--- | Total indexing operation. @svSelect xs default index@ is
--- intuitively the same as @xs !! index@, except it evaluates to
--- @default@ if @index@ overflows. Translates to SMT-Lib tables.
-svSelect :: [SVal] -> SVal -> SVal -> SVal
-svSelect xs err ind
-  | SVal _ (Left c) <- ind =
-    case cwVal c of
-      CWInteger i -> if i < 0 || i >= genericLength xs
-                     then err
-                     else xs `genericIndex` i
-      _           -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
-svSelect xsOrig err ind = xs `seq` SVal kElt (Right (cache r))
-  where
-    kInd = kindOf ind
-    kElt = kindOf err
-    -- Based on the index size, we need to limit the elements. For
-    -- instance if the index is 8 bits, but there are 257 elements,
-    -- that last element will never be used and we can chop it off.
-    xs = case kInd of
-           KBounded False i -> genericTake ((2::Integer) ^ i) xsOrig
-           KBounded True  i -> genericTake ((2::Integer) ^ (i-1)) xsOrig
-           KUnbounded       -> xsOrig
-           _                -> error $ "SBV.select: unsupported " ++ show kInd ++ " valued select/index expression"
-    r st = do sws <- mapM (svToSW st) xs
-              swe <- svToSW st err
-              if all (== swe) sws  -- off-chance that all elts are the same
-                 then return swe
-                 else do idx <- getTableIndex st kInd kElt sws
-                         swi <- svToSW st ind
-                         let len = length xs
-                         -- NB. No need to worry here that the index
-                         -- might be < 0; as the SMTLib translation
-                         -- takes care of that automatically
-                         newExpr st kElt (SBVApp (LkUp (idx, kInd, kElt, len) swi swe) [])
-
-svChangeSign :: Bool -> SVal -> SVal
-svChangeSign s x
-  | Just n <- svAsInteger x = svInteger k n
-  | True                    = SVal k (Right (cache y))
-  where
-    k = KBounded s (intSizeOf x)
-    y st = do xsw <- svToSW st x
-              newExpr st k (SBVApp (Extract (intSizeOf x - 1) 0) [xsw])
-
--- | Convert a symbolic bitvector from unsigned to signed.
-svSign :: SVal -> SVal
-svSign = svChangeSign True
-
--- | Convert a symbolic bitvector from signed to unsigned.
-svUnsign :: SVal -> SVal
-svUnsign = svChangeSign False
-
--- | Convert a symbolic bitvector from one integral kind to another.
-svFromIntegral :: Kind -> SVal -> SVal
-svFromIntegral kTo x
-  | Just v <- svAsInteger x
-  = svInteger kTo v
-  | True
-  = result
-  where result = SVal kTo (Right (cache y))
-        kFrom  = kindOf x
-        y st   = do xsw <- svToSW st x
-                    newExpr st kTo (SBVApp (KindCast kFrom kTo) [xsw])
-
---------------------------------------------------------------------------------
--- Derived operations
-
--- | Convert an SVal from kind Bool to an unsigned bitvector of size 1.
-svToWord1 :: SVal -> SVal
-svToWord1 b = svSymbolicMerge k True b (svInteger k 1) (svInteger k 0)
-  where k = KBounded False 1
-
--- | Convert an SVal from a bitvector of size 1 (signed or unsigned) to kind Bool.
-svFromWord1 :: SVal -> SVal
-svFromWord1 x = svNotEqual x (svInteger k 0)
-  where k = kindOf x
-
--- | Test the value of a bit. Note that we do an extract here
--- as opposed to masking and checking against zero, as we found
--- extraction to be much faster with large bit-vectors.
-svTestBit :: SVal -> Int -> SVal
-svTestBit x i
-  | i < intSizeOf x = svFromWord1 (svExtract i i x)
-  | True            = svFalse
-
--- | Generalization of 'svShl', where the shift-amount is symbolic.
--- The first argument should be a bounded quantity.
-svShiftLeft :: SVal -> SVal -> SVal
-svShiftLeft x i
-  | not (isBounded x)
-  = error "SBV.svShiftLeft: Shifted amount should be a bounded quantity!"
-  | True
-  = svIte (svLessThan i zi)
-          (svSelect [svShr x k | k <- [0 .. intSizeOf x - 1]] z (svUNeg i))
-          (svSelect [svShl x k | k <- [0 .. intSizeOf x - 1]] z         i)
-  where z  = svInteger (kindOf x) 0
-        zi = svInteger (kindOf i) 0
-
--- | Generalization of 'svShr', where the shift-amount is symbolic.
--- The first argument should be a bounded quantity.
---
--- NB. If the shiftee is signed, then this is an arithmetic shift;
--- otherwise it's logical.
-svShiftRight :: SVal -> SVal -> SVal
-svShiftRight x i
-  | not (isBounded x)
-  = error "SBV.svShiftLeft: Shifted amount should be a bounded quantity!"
-  | True
-  = svIte (svLessThan i zi)
-          (svSelect [svShl x k | k <- [0 .. intSizeOf x - 1]] z (svUNeg i))
-          (svSelect [svShr x k | k <- [0 .. intSizeOf x - 1]] z         i)
-  where z  = svInteger (kindOf x) 0
-        zi = svInteger (kindOf i) 0
-
--- | Generalization of 'svRol', where the rotation amount is symbolic.
--- The first argument should be a bounded quantity.
-svRotateLeft :: SVal -> SVal -> SVal
-svRotateLeft x i
-  | not (isBounded x)
-  = svShiftLeft x i
-  | isBounded i && bit si <= toInteger sx            -- wrap-around not possible
-  = svIte (svLessThan i zi)
-          (svSelect [x `svRor` k | k <- [0 .. bit si - 1]] z (svUNeg i))
-          (svSelect [x `svRol` k | k <- [0 .. bit si - 1]] z         i)
-  | True
-  = svIte (svLessThan i zi)
-          (svSelect [x `svRor` k | k <- [0 .. sx     - 1]] z (svUNeg i `svRem` n))
-          (svSelect [x `svRol` k | k <- [0 .. sx     - 1]] z (       i  `svRem` n))
-    where sx = intSizeOf x
-          si = intSizeOf i
-          z  = svInteger (kindOf x) 0
-          zi = svInteger (kindOf i) 0
-          n  = svInteger (kindOf i) (toInteger sx)
-
--- | Generalization of 'svRor', where the rotation amount is symbolic.
--- The first argument should be a bounded quantity.
-svRotateRight :: SVal -> SVal -> SVal
-svRotateRight x i
-  | not (isBounded x)
-  = svShiftRight x i
-  | isBounded i && bit si <= toInteger sx                   -- wrap-around not possible
-  = svIte (svLessThan i zi)
-          (svSelect [x `svRol` k | k <- [0 .. bit si - 1]] z (svUNeg i))
-          (svSelect [x `svRor` k | k <- [0 .. bit si - 1]] z         i)
-  | True
-  = svIte (svLessThan i zi)
-          (svSelect [x `svRol` k | k <- [0 .. sx     - 1]] z (svUNeg i `svRem` n))
-          (svSelect [x `svRor` k | k <- [0 .. sx     - 1]] z (       i  `svRem` n))
-    where sx = intSizeOf x
-          si = intSizeOf i
-          z  = svInteger (kindOf x) 0
-          zi = svInteger (kindOf i) 0
-          n  = svInteger (kindOf i) (toInteger sx)
-
---------------------------------------------------------------------------------
--- Utility functions
-
-noUnint  :: (Maybe Int, String) -> a
-noUnint x = error $ "Unexpected operation called on uninterpreted/enumerated value: " ++ show x
-
-noUnint2 :: (Maybe Int, String) -> (Maybe Int, String) -> a
-noUnint2 x y = error $ "Unexpected binary operation called on uninterpreted/enumerated values: " ++ show (x, y)
-
-liftSym1 :: (State -> Kind -> SW -> IO SW) -> (AlgReal -> AlgReal) -> (Integer -> Integer) -> (Float -> Float) -> (Double -> Double) -> SVal -> SVal
-liftSym1 _   opCR opCI opCF opCD   (SVal k (Left a)) = SVal k . Left  $! mapCW opCR opCI opCF opCD noUnint a
-liftSym1 opS _    _    _    _    a@(SVal k _)        = SVal k $ Right $ cache c
-   where c st = do swa <- svToSW st a
-                   opS st k swa
-
-liftSW2 :: (State -> Kind -> SW -> SW -> IO SW) -> Kind -> SVal -> SVal -> Cached SW
-liftSW2 opS k a b = cache c
-  where c st = do sw1 <- svToSW st a
-                  sw2 <- svToSW st b
-                  opS st k sw1 sw2
-
-liftSym2 :: (State -> Kind -> SW -> SW -> IO SW) -> (CW -> CW -> Bool) -> (AlgReal -> AlgReal -> AlgReal) -> (Integer -> Integer -> Integer) -> (Float -> Float -> Float) -> (Double -> Double -> Double) -> SVal -> SVal -> SVal
-liftSym2 _   okCW opCR opCI opCF opCD   (SVal k (Left a)) (SVal _ (Left b)) | okCW a b = SVal k . Left  $! mapCW2 opCR opCI opCF opCD noUnint2 a b
-liftSym2 opS _    _    _    _    _    a@(SVal k _)        b                            = SVal k $ Right $  liftSW2 opS k a b
-
-liftSym2B :: (State -> Kind -> SW -> SW -> IO SW) -> (CW -> CW -> Bool) -> (AlgReal -> AlgReal -> Bool) -> (Integer -> Integer -> Bool) -> (Float -> Float -> Bool) -> (Double -> Double -> Bool) -> ((Maybe Int, String) -> (Maybe Int, String) -> Bool) -> SVal -> SVal -> SVal
-liftSym2B _   okCW opCR opCI opCF opCD opUI (SVal _ (Left a)) (SVal _ (Left b)) | okCW a b = svBool (liftCW2 opCR opCI opCF opCD opUI a b)
-liftSym2B opS _    _    _    _    _    _    a                 b                            = SVal KBool $ Right $ liftSW2 opS KBool a b
-
-mkSymOpSC :: (SW -> SW -> Maybe SW) -> Op -> State -> Kind -> SW -> SW -> IO SW
-mkSymOpSC shortCut op st k a b = maybe (newExpr st k (SBVApp op [a, b])) return (shortCut a b)
-
-mkSymOp :: Op -> State -> Kind -> SW -> SW -> IO SW
-mkSymOp = mkSymOpSC (const (const Nothing))
-
-mkSymOp1SC :: (SW -> Maybe SW) -> Op -> State -> Kind -> SW -> IO SW
-mkSymOp1SC shortCut op st k a = maybe (newExpr st k (SBVApp op [a])) return (shortCut a)
-
-mkSymOp1 :: Op -> State -> Kind -> SW -> IO SW
-mkSymOp1 = mkSymOp1SC (const Nothing)
-
--- | eqOpt says the references are to the same SW, thus we can optimize. Note that
--- we explicitly disallow KFloat/KDouble here. Why? Because it's *NOT* true that
--- NaN == NaN, NaN >= NaN, and so-forth. So, we have to make sure we don't optimize
--- floats and doubles, in case the argument turns out to be NaN.
-eqOpt :: SW -> SW -> SW -> Maybe SW
-eqOpt w x y = case swKind x of
-                KFloat  -> Nothing
-                KDouble -> Nothing
-                _       -> if x == y then Just w else Nothing
-
--- For uninterpreted/enumerated values, we carefully lift through the constructor index for comparisons:
-uiLift :: String -> (Int -> Int -> Bool) -> (Maybe Int, String) -> (Maybe Int, String) -> Bool
-uiLift _ cmp (Just i, _) (Just j, _) = i `cmp` j
-uiLift w _   a           b           = error $ "Data.SBV.BitVectors.Model: Impossible happened while trying to lift " ++ w ++ " over " ++ show (a, b)
-
--- | Predicate for optimizing word operations like (+) and (*).
-isConcreteZero :: SVal -> Bool
-isConcreteZero (SVal _     (Left (CW _     (CWInteger n)))) = n == 0
-isConcreteZero (SVal KReal (Left (CW KReal (CWAlgReal v)))) = isExactRational v && v == 0
-isConcreteZero _                                            = False
-
--- | Predicate for optimizing word operations like (+) and (*).
-isConcreteOne :: SVal -> Bool
-isConcreteOne (SVal _     (Left (CW _     (CWInteger 1)))) = True
-isConcreteOne (SVal KReal (Left (CW KReal (CWAlgReal v)))) = isExactRational v && v == 1
-isConcreteOne _                                            = False
-
--- | Predicate for optimizing bitwise operations.
-isConcreteOnes :: SVal -> Bool
-isConcreteOnes (SVal _ (Left (CW (KBounded b w) (CWInteger n)))) = n == if b then -1 else bit w - 1
-isConcreteOnes (SVal _ (Left (CW KUnbounded     (CWInteger n)))) = n == -1
-isConcreteOnes (SVal _ (Left (CW KBool          (CWInteger n)))) = n == 1
-isConcreteOnes _                                                 = False
-
--- | Predicate for optimizing comparisons.
-isConcreteMax :: SVal -> Bool
-isConcreteMax (SVal _ (Left (CW (KBounded False w) (CWInteger n)))) = n == bit w - 1
-isConcreteMax (SVal _ (Left (CW (KBounded True  w) (CWInteger n)))) = n == bit (w - 1) - 1
-isConcreteMax (SVal _ (Left (CW KBool              (CWInteger n)))) = n == 1
-isConcreteMax _                                                     = False
-
--- | Predicate for optimizing comparisons.
-isConcreteMin :: SVal -> Bool
-isConcreteMin (SVal _ (Left (CW (KBounded False _) (CWInteger n)))) = n == 0
-isConcreteMin (SVal _ (Left (CW (KBounded True  w) (CWInteger n)))) = n == - bit (w - 1)
-isConcreteMin (SVal _ (Left (CW KBool              (CWInteger n)))) = n == 0
-isConcreteMin _                                                     = False
-
--- | Predicate for optimizing conditionals.
-areConcretelyEqual :: SVal -> SVal -> Bool
-areConcretelyEqual (SVal _ (Left a)) (SVal _ (Left b)) = a == b
-areConcretelyEqual _                       _           = False
-
--- | Most operations on concrete rationals require a compatibility check to avoid faulting
--- on algebraic reals.
-rationalCheck :: CW -> CW -> Bool
-rationalCheck a b = case (cwVal a, cwVal b) of
-                     (CWAlgReal x, CWAlgReal y) -> isExactRational x && isExactRational y
-                     _                          -> True
-
--- | Quot/Rem operations require a nonzero check on the divisor.
---
-nonzeroCheck :: CW -> CW -> Bool
-nonzeroCheck _ b = cwVal b /= CWInteger 0
-
--- | Same as rationalCheck, except for SBV's
-rationalSBVCheck :: SVal -> SVal -> Bool
-rationalSBVCheck (SVal KReal (Left a)) (SVal KReal (Left b)) = rationalCheck a b
-rationalSBVCheck _                     _                     = True
-
-noReal :: String -> AlgReal -> AlgReal -> AlgReal
-noReal o a b = error $ "SBV.AlgReal." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
-
-noFloat :: String -> Float -> Float -> Float
-noFloat o a b = error $ "SBV.Float." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
-
-noDouble :: String -> Double -> Double -> Double
-noDouble o a b = error $ "SBV.Double." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
-
-noRealUnary :: String -> AlgReal -> AlgReal
-noRealUnary o a = error $ "SBV.AlgReal." ++ o ++ ": Unexpected argument: " ++ show a
-
-noFloatUnary :: String -> Float -> Float
-noFloatUnary o a = error $ "SBV.Float." ++ o ++ ": Unexpected argument: " ++ show a
-
-noDoubleUnary :: String -> Double -> Double
-noDoubleUnary o a = error $ "SBV.Double." ++ o ++ ": Unexpected argument: " ++ show a
-
-{-# ANN svIte     ("HLint: ignore Eta reduce" :: String)         #-}
-{-# ANN svLazyIte ("HLint: ignore Eta reduce" :: String)         #-}
-{-# ANN module    ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/BitVectors/PrettyNum.hs b/Data/SBV/BitVectors/PrettyNum.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/PrettyNum.hs
+++ /dev/null
@@ -1,296 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.PrettyNum
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Number representations in hex/bin
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Data.SBV.BitVectors.PrettyNum (
-        PrettyNum(..), readBin, shex, shexI, sbin, sbinI
-      , showCFloat, showCDouble, showHFloat, showHDouble
-      , showSMTFloat, showSMTDouble, smtRoundingMode, cwToSMTLib, mkSkolemZero
-      ) where
-
-import Data.Char  (ord, intToDigit)
-import Data.Int   (Int8, Int16, Int32, Int64)
-import Data.List  (isPrefixOf)
-import Data.Maybe (fromJust, fromMaybe, listToMaybe)
-import Data.Ratio (numerator, denominator)
-import Data.Word  (Word8, Word16, Word32, Word64)
-import Numeric    (showIntAtBase, showHex, readInt)
-
-import Data.Numbers.CrackNum (floatToFP, doubleToFP)
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.AlgReals (algRealToSMTLib2)
-
--- | PrettyNum class captures printing of numbers in hex and binary formats; also supporting negative numbers.
---
--- Minimal complete definition: 'hexS' and 'binS'
-class PrettyNum a where
-  -- | Show a number in hexadecimal (starting with @0x@ and type.)
-  hexS :: a -> String
-  -- | Show a number in binary (starting with @0b@ and type.)
-  binS :: a -> String
-  -- | Show a number in hex, without prefix, or types.
-  hex :: a -> String
-  -- | Show a number in bin, without prefix, or types.
-  bin :: a -> String
-
--- 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}
-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) ;}
-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)  ;}
-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) ;}
-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) ;}
-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) ;}
-instance PrettyNum Integer where
-  {hexS = shexI True True; binS = sbinI True True; hex = shexI False False; bin = sbinI False False;}
-
-instance PrettyNum CW where
-  hexS cw | isUninterpreted cw = show cw ++ " :: " ++ show (kindOf cw)
-          | isBoolean cw       = hexS (cwToBool cw) ++ " :: Bool"
-          | isFloat cw         = let CWFloat  f  = cwVal cw in show f ++ " :: Float\n"  ++ show (floatToFP f)
-          | isDouble cw        = let CWDouble d  = cwVal cw in show d ++ " :: Double\n" ++ show (doubleToFP d)
-          | isReal cw          = let CWAlgReal w = cwVal cw in show w ++ " :: Real"
-          | not (isBounded cw) = let CWInteger w = cwVal cw in shexI True True w
-          | True               = let CWInteger w = cwVal cw in shex  True True (hasSign cw, intSizeOf cw) w
-
-  binS cw | isUninterpreted cw = show cw  ++ " :: " ++ show (kindOf cw)
-          | isBoolean cw       = binS (cwToBool cw)  ++ " :: Bool"
-          | isFloat cw         = let CWFloat  f  = cwVal cw in show f ++ " :: Float\n"  ++ show (floatToFP f)
-          | isDouble cw        = let CWDouble d  = cwVal cw in show d ++ " :: Double\n" ++ show (doubleToFP d)
-          | isReal cw          = let CWAlgReal w = cwVal cw in show w ++ " :: Real"
-          | not (isBounded cw) = let CWInteger w = cwVal cw in sbinI True True w
-          | True               = let CWInteger w = cwVal cw in sbin  True True (hasSign cw, intSizeOf cw) w
-
-  hex cw | isUninterpreted cw = show cw
-         | isBoolean cw       = hexS (cwToBool cw) ++ " :: Bool"
-         | isFloat cw         = let CWFloat  f  = cwVal cw in show f
-         | isDouble cw        = let CWDouble d  = cwVal cw in show d
-         | isReal cw          = let CWAlgReal w = cwVal cw in show w
-         | not (isBounded cw) = let CWInteger w = cwVal cw in shexI False False w
-         | True               = let CWInteger w = cwVal cw in shex  False False (hasSign cw, intSizeOf cw) w
-
-  bin cw | isUninterpreted cw = show cw
-         | isBoolean cw       = binS (cwToBool cw) ++ " :: Bool"
-         | isFloat cw         = let CWFloat  f  = cwVal cw in show f
-         | isDouble cw        = let CWDouble d  = cwVal cw in show d
-         | isReal cw          = let CWAlgReal w = cwVal cw in show w
-         | not (isBounded cw) = let CWInteger w = cwVal cw in sbinI False False w
-         | True               = let CWInteger w = cwVal cw in sbin  False False (hasSign cw, intSizeOf cw) w
-
-instance (SymWord 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
-  hex  s = maybe (show s) (hex  :: a -> String) $ unliteral s
-  bin  s = maybe (show s) (bin  :: a -> String) $ unliteral s
-
--- | Show as a hexadecimal value. First bool controls whether type info is printed
--- while the second boolean controls wether 0x prefix is printed. The tuple is
--- the signedness and the bit-length of the input. The length of the string
--- will /not/ depend on the value, but rather the bit-length.
-shex :: (Show a, Integral a) => Bool -> Bool -> (Bool, Int) -> a -> String
-shex shType shPre (signed, size) a
- | a < 0
- = "-" ++ pre ++ pad l (s16 (abs (fromIntegral a :: Integer)))  ++ t
- | True
- = pre ++ pad l (s16 a) ++ t
- where t | shType = " :: " ++ (if signed then "Int" else "Word") ++ show size
-         | True   = ""
-       pre | shPre = "0x"
-           | True  = ""
-       l = (size + 3) `div` 4
-
--- | Show as a hexadecimal value, integer version. Almost the same as shex above
--- except we don't have a bit-length so the length of the string will depend
--- on the actual value.
-shexI :: Bool -> Bool -> Integer -> String
-shexI shType shPre a
- | a < 0
- = "-" ++ pre ++ s16 (abs a)  ++ t
- | True
- = pre ++ s16 a ++ t
- where t | shType = " :: Integer"
-         | True   = ""
-       pre | shPre = "0x"
-           | True  = ""
-
--- | Similar to 'shex'; except in binary.
-sbin :: (Show a, Integral a) => Bool -> Bool -> (Bool, Int) -> a -> String
-sbin shType shPre (signed,size) a
- | a < 0
- = "-" ++ pre ++ pad size (s2 (abs (fromIntegral a :: Integer)))  ++ t
- | True
- = pre ++ pad size (s2 a) ++ t
- where t | shType = " :: " ++ (if signed then "Int" else "Word") ++ show size
-         | True   = ""
-       pre | shPre = "0b"
-           | True  = ""
-
--- | Similar to 'shexI'; except in binary.
-sbinI :: Bool -> Bool -> Integer -> String
-sbinI shType shPre a
- | a < 0
- = "-" ++ pre ++ s2 (abs a) ++ t
- | True
- =  pre ++ s2 a ++ t
- where t | shType = " :: Integer"
-         | True   = ""
-       pre | shPre = "0b"
-           | True  = ""
-
--- | Pad a string to a given length. If the string is longer, then we don't drop anything.
-pad :: Int -> String -> String
-pad l s = replicate (l - length s) '0' ++ s
-
--- | Binary printer
-s2 :: (Show a, Integral a) => a -> String
-s2  v = showIntAtBase 2 dig v "" where dig = fromJust . flip lookup [(0, '0'), (1, '1')]
-
--- | Hex printer
-s16 :: (Show a, Integral a) => a -> String
-s16 v = showHex v ""
-
--- | A more convenient interface for reading binary numbers, also supports negative numbers
-readBin :: Num a => String -> a
-readBin ('-':s) = -(readBin s)
-readBin s = case readInt 2 isDigit cvt s' of
-              [(a, "")] -> a
-              _         -> error $ "SBV.readBin: Cannot read a binary number from: " ++ show s
-  where cvt c = ord c - ord '0'
-        isDigit = (`elem` "01")
-        s' | "0b" `isPrefixOf` s = drop 2 s
-           | True                = s
-
--- | A version of show for floats that generates correct C literals for nan/infinite. NB. Requires "math.h" to be included.
-showCFloat :: Float -> String
-showCFloat f
-   | isNaN f             = "((float) NAN)"
-   | isInfinite f, f < 0 = "((float) (-INFINITY))"
-   | isInfinite f        = "((float) INFINITY)"
-   | True                = 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
-
--- | A version of show for floats that generates correct Haskell literals for nan/infinite
-showHFloat :: Float -> String
-showHFloat f
-   | isNaN f             = "((0/0) :: Float)"
-   | isInfinite f, f < 0 = "((-1/0) :: Float)"
-   | isInfinite f        = "((1/0) :: Float)"
-   | True                = show f
-
--- | A version of show for doubles that generates correct Haskell literals for nan/infinite
-showHDouble :: Double -> String
-showHDouble d
-   | isNaN d             = "((0/0) :: Double)"
-   | isInfinite d, d < 0 = "((-1/0) :: Double)"
-   | isInfinite d        = "((1/0) :: Double)"
-   | True                = show d
-
--- | A version of show for floats that generates correct SMTLib literals using the rounding mode
-showSMTFloat :: RoundingMode -> Float -> String
-showSMTFloat rm f
-   | isNaN f             = as "NaN"
-   | isInfinite f, f < 0 = as "-oo"
-   | isInfinite f        = as "+oo"
-   | isNegativeZero f    = as "-zero"
-   | f == 0              = as "+zero"
-   | True                = "((_ to_fp 8 24) " ++ smtRoundingMode rm ++ " " ++ toSMTLibRational (toRational f) ++ ")"
-   where as s = "(_ " ++ s ++ " 8 24)"
-
--- | A version of show for doubles that generates correct SMTLib literals using the rounding mode
-showSMTDouble :: RoundingMode -> Double -> String
-showSMTDouble rm d
-   | isNaN d             = as "NaN"
-   | isInfinite d, d < 0 = as "-oo"
-   | isInfinite d        = as "+oo"
-   | isNegativeZero d    = as "-zero"
-   | d == 0              = as "+zero"
-   | True                = "((_ to_fp 11 53) " ++ smtRoundingMode rm ++ " " ++ toSMTLibRational (toRational d) ++ ")"
-   where as s = "(_ " ++ s ++ " 11 53)"
-
--- | Show a rational in SMTLib format
-toSMTLibRational :: Rational -> String
-toSMTLibRational r
-   | n < 0
-   = "(- (/ "  ++ show (abs n) ++ " " ++ show d ++ "))"
-   | True
-   = "(/ " ++ show n ++ " " ++ show d ++ ")"
-  where n = numerator r
-        d = denominator r
-
--- | Convert a rounding mode to the format SMT-Lib2 understands.
-smtRoundingMode :: RoundingMode -> String
-smtRoundingMode RoundNearestTiesToEven = "roundNearestTiesToEven"
-smtRoundingMode RoundNearestTiesToAway = "roundNearestTiesToAway"
-smtRoundingMode RoundTowardPositive    = "roundTowardPositive"
-smtRoundingMode RoundTowardNegative    = "roundTowardNegative"
-smtRoundingMode RoundTowardZero        = "roundTowardZero"
-
--- | Convert a CW to an SMTLib2 compliant value
-cwToSMTLib :: RoundingMode -> CW -> String
-cwToSMTLib rm x
-  | isBoolean       x, CWInteger  w      <- cwVal x = if w == 0 then "false" else "true"
-  | isUninterpreted x, CWUserSort (_, s) <- cwVal x = roundModeConvert s
-  | isReal          x, CWAlgReal  r      <- cwVal x = algRealToSMTLib2 r
-  | isFloat         x, CWFloat    f      <- cwVal x = showSMTFloat  rm f
-  | isDouble        x, CWDouble   d      <- cwVal x = showSMTDouble rm d
-  | not (isBounded x), CWInteger  w      <- cwVal x = if w >= 0 then show w else "(- " ++ show (abs w) ++ ")"
-  | not (hasSign x)  , CWInteger  w      <- cwVal x = smtLibHex (intSizeOf x) w
-  -- signed numbers (with 2's complement representation) is problematic
-  -- since there's no way to put a bvneg over a positive number to get minBound..
-  -- Hence, we punt and use binary notation in that particular case
-  | hasSign x        , CWInteger  w      <- cwVal x = if w == negate (2 ^ intSizeOf x)
-                                                      then mkMinBound (intSizeOf x)
-                                                      else negIf (w < 0) $ smtLibHex (intSizeOf x) (abs w)
-  | True = error $ "SBV.cvtCW: 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])
-        -- Carefully code hex numbers, SMTLib is picky about lengths of hex constants. For the time
-        -- being, SBV only supports sizes that are multiples of 4, but the below code is more robust
-        -- in case of future extensions to support arbitrary sizes.
-        smtLibHex :: Int -> Integer -> String
-        smtLibHex 1  v = "#b" ++ show v
-        smtLibHex sz v
-          | sz `mod` 4 == 0 = "#x" ++ pad (sz `div` 4) (showHex v "")
-          | True            = "#b" ++ pad sz (showBin v "")
-           where showBin = showIntAtBase 2 intToDigit
-        negIf :: Bool -> String -> String
-        negIf True  a = "(bvneg " ++ a ++ ")"
-        negIf False a = a
-        -- anamoly 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)
-        mkMinBound :: Int -> String
-        mkMinBound i = "#b1" ++ replicate (i-1) '0'
-
--- | Create a skolem 0 for the kind
-mkSkolemZero :: RoundingMode -> Kind -> String
-mkSkolemZero _ (KUserSort _ (Right (f:_))) = f
-mkSkolemZero _ (KUserSort s _)             = error $ "SBV.mkSkolemZero: Unexpected uninterpreted sort: " ++ s
-mkSkolemZero rm k                          = cwToSMTLib rm (mkConstCW k (0::Integer))
diff --git a/Data/SBV/BitVectors/STree.hs b/Data/SBV/BitVectors/STree.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/STree.hs
+++ /dev/null
@@ -1,75 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.STree
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Implementation of full-binary symbolic trees, providing logarithmic
--- time access to elements. Both reads and writes are supported.
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-
-module Data.SBV.BitVectors.STree (STree, readSTree, writeSTree, mkSTree) where
-
-import Data.Bits (Bits(..))
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model
-
--- | A symbolic tree containing values of type e, indexed by
--- elements of type i. Note that these are full-trees, and their
--- their shapes remain constant. There is no API provided that
--- can change the shape of the tree. These structures are useful
--- when dealing with data-structures that are indexed with symbolic
--- values where access time is important. 'STree' structures provide
--- logarithmic time reads and writes.
-type STree i e = STreeInternal (SBV i) (SBV e)
-
--- Internal representation, not exposed to the user
-data STreeInternal i e = SLeaf e                        -- NB. parameter 'i' is phantom
-                       | SBin  (STreeInternal i e) (STreeInternal i e)
-                       deriving Show
-
-instance (SymWord e, Mergeable (SBV e)) => Mergeable (STree i e) where
-  symbolicMerge f b (SLeaf i)  (SLeaf j)    = SLeaf (symbolicMerge f b i j)
-  symbolicMerge f b (SBin l r) (SBin l' r') = SBin  (symbolicMerge f b l l') (symbolicMerge f b r r')
-  symbolicMerge _ _ _          _            = error "SBV.STree.symbolicMerge: Impossible happened while merging states"
-
--- | Reading a value. We bit-blast the index and descend down the full tree
--- according to bit-values.
-readSTree :: (Num i, Bits i, SymWord i, SymWord e) => STree i e -> SBV i -> SBV e
-readSTree s i = walk (blastBE i) s
-  where walk []     (SLeaf v)  = v
-        walk (b:bs) (SBin l r) = ite b (walk bs r) (walk bs l)
-        walk _      _          = error $ "SBV.STree.readSTree: Impossible happened while reading: " ++ show i
-
--- | Writing a value, similar to how reads are done. The important thing is that the tree
--- representation keeps updates to a minimum.
-writeSTree :: (Mergeable (SBV e), Num i, Bits i, SymWord i, SymWord e) => STree i e -> SBV i -> SBV e -> STree i e
-writeSTree s i j = walk (blastBE i) s
-  where walk []     _          = SLeaf j
-        walk (b:bs) (SBin l r) = SBin (ite b l (walk bs l)) (ite b (walk bs r) r)
-        walk _      _          = error $ "SBV.STree.writeSTree: Impossible happened while reading: " ++ show i
-
--- | Construct the fully balanced initial tree using the given values.
-mkSTree :: forall i e. HasKind i => [SBV e] -> STree i e
-mkSTree ivals
-  | isReal (undefined :: i)
-  = error "SBV.STree.mkSTree: Cannot build a real-valued sized tree"
-  | not (isBounded (undefined :: i))
-  = error "SBV.STree.mkSTree: Cannot build an infinitely large tree"
-  | reqd /= given
-  = error $ "SBV.STree.mkSTree: Required " ++ show reqd ++ " elements, received: " ++ show given
-  | True
-  = go ivals
-  where reqd = 2 ^ intSizeOf (undefined :: i)
-        given = length ivals
-        go []  = error "SBV.STree.mkSTree: Impossible happened, ran out of elements"
-        go [l] = SLeaf l
-        go ns  = let (l, r) = splitAt (length ns `div` 2) ns in SBin (go l) (go r)
diff --git a/Data/SBV/BitVectors/Splittable.hs b/Data/SBV/BitVectors/Splittable.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Splittable.hs
+++ /dev/null
@@ -1,119 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Splittable
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Implementation of bit-vector concatanetation and splits
------------------------------------------------------------------------------
-
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE TypeSynonymInstances   #-}
-{-# LANGUAGE FlexibleInstances      #-}
-{-# LANGUAGE BangPatterns           #-}
-
-module Data.SBV.BitVectors.Splittable (Splittable(..), FromBits(..), checkAndConvert) where
-
-import Data.Bits (Bits(..))
-import Data.Word (Word8, Word16, Word32, Word64)
-
-import Data.SBV.BitVectors.Operations
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model
-
-infixr 5 #
--- | Splitting an @a@ into two @b@'s and joining back.
--- Intuitively, @a@ is a larger bit-size word than @b@, typically double.
--- The 'extend' operation captures embedding of a @b@ value into an @a@
--- without changing its semantic value.
---
--- Minimal complete definition: All, no defaults.
-class Splittable a b | b -> a where
-  split  :: a -> (b, b)
-  (#)    :: b -> b -> a
-  extend :: b -> a
-
-genSplit :: (Integral a, Num b) => Int -> a -> (b, b)
-genSplit ss x = (fromIntegral ((ix `shiftR` ss) .&. mask), fromIntegral (ix .&. mask))
-  where ix = toInteger x
-        mask = 2 ^ ss - 1
-
-genJoin :: (Integral b, Num a) => Int -> b -> b -> a
-genJoin ss x y = fromIntegral ((ix `shiftL` ss) .|. iy)
-  where ix = toInteger x
-        iy = toInteger y
-
--- concrete instances
-instance Splittable Word64 Word32 where
-  split = genSplit 32
-  (#)   = genJoin  32
-  extend b = 0 # b
-
-instance Splittable Word32 Word16 where
-  split = genSplit 16
-  (#)   = genJoin  16
-  extend b = 0 # b
-
-instance Splittable Word16 Word8 where
-  split = genSplit 8
-  (#)   = genJoin  8
-  extend b = 0 # b
-
--- symbolic instances
-instance Splittable SWord64 SWord32 where
-  split (SBV x) = (SBV (svExtract 63 32 x), SBV (svExtract 31 0 x))
-  SBV a # SBV b = SBV (svJoin a b)
-  extend b = 0 # b
-
-instance Splittable SWord32 SWord16 where
-  split (SBV x) = (SBV (svExtract 31 16 x), SBV (svExtract 15 0 x))
-  SBV a # SBV b = SBV (svJoin a b)
-  extend b = 0 # b
-
-instance Splittable SWord16 SWord8 where
-  split (SBV x) = (SBV (svExtract 15 8 x), SBV (svExtract 7 0 x))
-  SBV a # SBV b = SBV (svJoin a b)
-  extend b = 0 # b
-
--- | Unblasting a value from symbolic-bits. The bits can be given little-endian
--- or big-endian. For a signed number in little-endian, we assume the very last bit
--- is the sign digit. This is a bit awkward, but it is more consistent with the "reverse" view of
--- little-big-endian representations
---
--- Minimal complete definition: 'fromBitsLE'
-class FromBits a where
- fromBitsLE, fromBitsBE :: [SBool] -> a
- fromBitsBE = fromBitsLE . reverse
-
--- | Construct a symbolic word from its bits given in little-endian
-fromBinLE :: (Num a, Bits a, SymWord a) => [SBool] -> SBV a
-fromBinLE = go 0 0
-  where go !acc _  []     = acc
-        go !acc !i (x:xs) = go (ite x (setBit acc i) acc) (i+1) xs
-
--- | Perform a sanity check that we should receive precisely the same
--- number of bits as required by the resulting type. The input is little-endian
-checkAndConvert :: (Num a, Bits a, SymWord a) => Int -> [SBool] -> SBV a
-checkAndConvert sz xs
-  | sz /= l
-  = error $ "SBV.fromBits.SWord" ++ ssz ++ ": Expected " ++ ssz ++ " elements, got: " ++ show l
-  | True
-  = fromBinLE xs
-  where l   = length xs
-        ssz = show sz
-
-instance FromBits SBool where
- fromBitsLE [x] = x
- fromBitsLE xs  = error $ "SBV.fromBits.SBool: Expected 1 element, got: " ++ show (length xs)
-
-instance FromBits SWord8  where fromBitsLE = checkAndConvert  8
-instance FromBits SInt8   where fromBitsLE = checkAndConvert  8
-instance FromBits SWord16 where fromBitsLE = checkAndConvert 16
-instance FromBits SInt16  where fromBitsLE = checkAndConvert 16
-instance FromBits SWord32 where fromBitsLE = checkAndConvert 32
-instance FromBits SInt32  where fromBitsLE = checkAndConvert 32
-instance FromBits SWord64 where fromBitsLE = checkAndConvert 64
-instance FromBits SInt64  where fromBitsLE = checkAndConvert 64
diff --git a/Data/SBV/BitVectors/Symbolic.hs b/Data/SBV/BitVectors/Symbolic.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Symbolic.hs
+++ /dev/null
@@ -1,1122 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Symbolic
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Symbolic values
------------------------------------------------------------------------------
-
-{-# LANGUAGE    GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE    TypeSynonymInstances       #-}
-{-# LANGUAGE    TypeOperators              #-}
-{-# LANGUAGE    MultiParamTypeClasses      #-}
-{-# LANGUAGE    ScopedTypeVariables        #-}
-{-# LANGUAGE    FlexibleInstances          #-}
-{-# LANGUAGE    PatternGuards              #-}
-{-# LANGUAGE    NamedFieldPuns             #-}
-{-# LANGUAGE    DeriveDataTypeable         #-}
-{-# LANGUAGE    CPP                        #-}
-{-# OPTIONS_GHC -fno-warn-orphans          #-}
-
-module Data.SBV.BitVectors.Symbolic
-  ( NodeId(..)
-  , SW(..), swKind, trueSW, falseSW
-  , Op(..), FPOp(..)
-  , Quantifier(..), needsExistentials
-  , RoundingMode(..)
-  , SBVType(..), newUninterpreted, addAxiom
-  , SVal(..)
-  , svMkSymVar
-  , ArrayContext(..), ArrayInfo
-  , svToSW, svToSymSW, forceSWArg
-  , SBVExpr(..), newExpr, isCodeGenMode
-  , Cached, cache, uncache
-  , ArrayIndex, uncacheAI
-  , NamedSymVar
-  , getSValPathCondition, extendSValPathCondition
-  , getTableIndex
-  , SBVPgm(..), Symbolic, runSymbolic, runSymbolic', State
-  , inProofMode, SBVRunMode(..), Result(..)
-  , Logic(..), SMTLibLogic(..)
-  , addAssertion, addSValConstraint, internalConstraint, internalVariable
-  , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension
-  , SolverCapabilities(..)
-  , extractSymbolicSimulationState
-  , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), SMTEngine, getSBranchRunConfig
-  , outputSVal
-  , mkSValUserSort
-  , SArr(..), readSArr, resetSArr, writeSArr, mergeSArr, newSArr, eqSArr
-  ) where
-
-import Control.DeepSeq      (NFData(..))
-import Control.Monad        (when, unless)
-import Control.Monad.Reader (MonadReader, ReaderT, ask, runReaderT)
-import Control.Monad.Trans  (MonadIO, liftIO)
-import Data.Char            (isAlpha, isAlphaNum, toLower)
-import Data.IORef           (IORef, newIORef, modifyIORef, readIORef, writeIORef)
-import Data.List            (intercalate, sortBy)
-import Data.Maybe           (isJust, fromJust, fromMaybe)
-
-import GHC.Stack.Compat
-
-import qualified Data.Generics as G    (Data(..))
-import qualified Data.IntMap   as IMap (IntMap, empty, size, toAscList, lookup, insert, insertWith)
-import qualified Data.Map      as Map  (Map, empty, toList, size, insert, lookup)
-import qualified Data.Set      as Set  (Set, empty, toList, insert)
-import qualified Data.Foldable as F    (toList)
-import qualified Data.Sequence as S    (Seq, empty, (|>))
-
-import System.Mem.StableName
-import System.Random
-
-import Data.SBV.BitVectors.Kind
-import Data.SBV.BitVectors.Concrete
-import Data.SBV.SMT.SMTLibNames
-import Data.SBV.Utils.TDiff(Timing)
-
-import Prelude ()
-import Prelude.Compat
-
--- | A symbolic node id
-newtype NodeId = NodeId Int deriving (Eq, Ord)
-
--- | A symbolic word, tracking it's signedness and size.
-data SW = SW !Kind !NodeId deriving (Eq, Ord)
-
-instance HasKind SW where
-  kindOf (SW k _) = k
-
-instance Show SW where
-  show (SW _ (NodeId n))
-    | n < 0 = "s_" ++ show (abs n)
-    | True  = 's' : show n
-
--- | Kind of a symbolic word.
-swKind :: SW -> Kind
-swKind (SW k _) = k
-
--- | Forcing an argument; this is a necessary evil to make sure all the arguments
--- to an uninterpreted function and sBranch test conditions are evaluated before called;
--- the semantics of uinterpreted functions is necessarily strict; deviating from Haskell's
-forceSWArg :: SW -> IO ()
-forceSWArg (SW k n) = k `seq` n `seq` return ()
-
--- | Constant False as an SW. Note that this value always occupies slot -2.
-falseSW :: SW
-falseSW = SW KBool $ NodeId (-2)
-
--- | Constant True as an SW. Note that this value always occupies slot -1.
-trueSW :: SW
-trueSW  = SW KBool $ NodeId (-1)
-
--- | Symbolic operations
-data Op = Plus
-        | Times
-        | Minus
-        | UNeg
-        | Abs
-        | Quot
-        | Rem
-        | Equal
-        | NotEqual
-        | LessThan
-        | GreaterThan
-        | LessEq
-        | GreaterEq
-        | Ite
-        | And
-        | Or
-        | XOr
-        | Not
-        | Shl Int
-        | Shr Int
-        | Rol Int
-        | Ror Int
-        | Extract Int Int                       -- Extract i j: extract bits i to j. Least significant bit is 0 (big-endian)
-        | Join                                  -- Concat two words to form a bigger one, in the order given
-        | LkUp (Int, Kind, Kind, Int) !SW !SW   -- (table-index, arg-type, res-type, length of the table) index out-of-bounds-value
-        | ArrEq   Int Int                       -- Array equality
-        | ArrRead Int
-        | KindCast Kind Kind
-        | Uninterpreted String
-        | Label String                          -- Essentially no-op; useful for code generation to emit comments.
-        | IEEEFP FPOp                           -- Floating-point ops, categorized separately
-        deriving (Eq, Ord)
-
--- | Floating point operations
-data FPOp = FP_Cast        Kind Kind SW   -- From-Kind, To-Kind, RoundingMode. This is "value" conversion
-          | FP_Reinterpret Kind Kind      -- From-Kind, To-Kind. This is bit-reinterpretation using IEEE-754 interchange format
-          | FP_Abs
-          | FP_Neg
-          | FP_Add
-          | FP_Sub
-          | FP_Mul
-          | FP_Div
-          | FP_FMA
-          | FP_Sqrt
-          | FP_Rem
-          | FP_RoundToIntegral
-          | FP_Min
-          | FP_Max
-          | FP_ObjEqual
-          | FP_IsNormal
-          | FP_IsSubnormal
-          | FP_IsZero
-          | FP_IsInfinite
-          | FP_IsNaN
-          | FP_IsNegative
-          | FP_IsPositive
-          deriving (Eq, Ord)
-
--- | Note that the show instance maps to the SMTLib names. We need to make sure
--- this mapping stays correct through SMTLib changes. The only exception
--- is FP_Cast; where we handle different source/origins explicitly later on.
-instance Show FPOp where
-   show (FP_Cast f t r)      = "(FP_Cast: " ++ show f ++ " -> " ++ show t ++ ", using RM [" ++ show r ++ "])"
-   show (FP_Reinterpret f t) = case (f, t) of
-                                  (KBounded False 32, KFloat)  -> "(_ to_fp 8 24)"
-                                  (KBounded False 64, KDouble) -> "(_ to_fp 11 53)"
-                                  _                            -> error $ "SBV.FP_Reinterpret: Unexpected conversion: " ++ show f ++ " to " ++ show t
-   show FP_Abs               = "fp.abs"
-   show FP_Neg               = "fp.neg"
-   show FP_Add               = "fp.add"
-   show FP_Sub               = "fp.sub"
-   show FP_Mul               = "fp.mul"
-   show FP_Div               = "fp.div"
-   show FP_FMA               = "fp.fma"
-   show FP_Sqrt              = "fp.sqrt"
-   show FP_Rem               = "fp.rem"
-   show FP_RoundToIntegral   = "fp.roundToIntegral"
-   show FP_Min               = "fp.min"
-   show FP_Max               = "fp.max"
-   show FP_ObjEqual          = "="
-   show FP_IsNormal          = "fp.isNormal"
-   show FP_IsSubnormal       = "fp.isSubnormal"
-   show FP_IsZero            = "fp.isZero"
-   show FP_IsInfinite        = "fp.isInfinite"
-   show FP_IsNaN             = "fp.isNaN"
-   show FP_IsNegative        = "fp.isNegative"
-   show FP_IsPositive        = "fp.isPositive"
-
--- | Show instance for 'Op'. Note that this is largely for debugging purposes, not used
--- for being read by any tool.
-instance Show Op where
-  show (Shl i) = "<<"  ++ show i
-  show (Shr i) = ">>"  ++ show i
-  show (Rol i) = "<<<" ++ show i
-  show (Ror i) = ">>>" ++ show i
-  show (Extract i j) = "choose [" ++ show i ++ ":" ++ show j ++ "]"
-  show (LkUp (ti, at, rt, l) i e)
-        = "lookup(" ++ tinfo ++ ", " ++ show i ++ ", " ++ show e ++ ")"
-        where tinfo = "table" ++ show ti ++ "(" ++ show at ++ " -> " ++ show rt ++ ", " ++ show l ++ ")"
-  show (ArrEq i j)       = "array_" ++ show i ++ " == array_" ++ show j
-  show (ArrRead i)       = "select array_" ++ show i
-  show (KindCast fr to)  = "cast_" ++ show fr ++ "_" ++ show to
-  show (Uninterpreted i) = "[uninterpreted] " ++ i
-  show (Label s)         = "[label] " ++ s
-  show (IEEEFP w)        = show w
-  show op
-    | Just s <- op `lookup` syms = s
-    | True                       = error "impossible happened; can't find op!"
-    where syms = [ (Plus, "+"), (Times, "*"), (Minus, "-"), (UNeg, "-"), (Abs, "abs")
-                 , (Quot, "quot")
-                 , (Rem,  "rem")
-                 , (Equal, "=="), (NotEqual, "/=")
-                 , (LessThan, "<"), (GreaterThan, ">"), (LessEq, "<="), (GreaterEq, ">=")
-                 , (Ite, "if_then_else")
-                 , (And, "&"), (Or, "|"), (XOr, "^"), (Not, "~")
-                 , (Join, "#")
-                 ]
-
--- | Quantifiers: forall or exists. Note that we allow
--- arbitrary nestings.
-data Quantifier = ALL | EX deriving Eq
-
--- | Are there any existential quantifiers?
-needsExistentials :: [Quantifier] -> Bool
-needsExistentials = (EX `elem`)
-
--- | A simple type for SBV computations, used mainly for uninterpreted constants.
--- We keep track of the signedness/size of the arguments. A non-function will
--- have just one entry in the list.
-newtype SBVType = SBVType [Kind]
-             deriving (Eq, Ord)
-
-instance Show SBVType where
-  show (SBVType []) = error "SBV: internal error, empty SBVType"
-  show (SBVType xs) = intercalate " -> " $ map show xs
-
--- | A symbolic expression
-data SBVExpr = SBVApp !Op ![SW]
-             deriving (Eq, Ord)
-
--- | To improve hash-consing, take advantage of commutative operators by
--- reordering their arguments.
-reorder :: SBVExpr -> SBVExpr
-reorder s = case s of
-              SBVApp op [a, b] | isCommutative op && a > b -> SBVApp op [b, a]
-              _ -> s
-  where isCommutative :: Op -> Bool
-        isCommutative o = o `elem` [Plus, Times, Equal, NotEqual, And, Or, XOr]
-
--- | Show instance for 'SBVExpr'. Again, only for debugging purposes.
-instance Show SBVExpr where
-  show (SBVApp Ite [t, a, b]) = unwords ["if", show t, "then", show a, "else", show b]
-  show (SBVApp (Shl i) [a])   = unwords [show a, "<<", show i]
-  show (SBVApp (Shr i) [a])   = unwords [show a, ">>", show i]
-  show (SBVApp (Rol i) [a])   = unwords [show a, "<<<", show i]
-  show (SBVApp (Ror i) [a])   = unwords [show a, ">>>", show i]
-  show (SBVApp op  [a, b])    = unwords [show a, show op, show b]
-  show (SBVApp op  args)      = unwords (show op : map show args)
-
--- | A program is a sequence of assignments
-newtype SBVPgm = SBVPgm {pgmAssignments :: S.Seq (SW, SBVExpr)}
-
--- | 'NamedSymVar' pairs symbolic words and user given/automatically generated names
-type NamedSymVar = (SW, String)
-
--- | Result of running a symbolic computation
-data Result = Result { reskinds       :: Set.Set Kind                     -- ^ kinds used in the program
-                     , resTraces      :: [(String, CW)]                   -- ^ quick-check counter-example information (if any)
-                     , resUISegs      :: [(String, [String])]             -- ^ uninterpeted code segments
-                     , resInputs      :: [(Quantifier, NamedSymVar)]      -- ^ inputs (possibly existential)
-                     , resConsts      :: [(SW, CW)]                       -- ^ constants
-                     , resTables      :: [((Int, Kind, Kind), [SW])]      -- ^ tables (automatically constructed) (tableno, index-type, result-type) elts
-                     , resArrays      :: [(Int, ArrayInfo)]               -- ^ arrays (user specified)
-                     , resUIConsts    :: [(String, SBVType)]              -- ^ uninterpreted constants
-                     , resAxioms      :: [(String, [String])]             -- ^ axioms
-                     , resAsgns       :: SBVPgm                           -- ^ assignments
-                     , resConstraints :: [SW]                             -- ^ additional constraints (boolean)
-                     , resAssertions  :: [(String, Maybe CallStack, SW)]  -- ^ assertions
-                     , resOutputs     :: [SW]                             -- ^ outputs
-                     }
-
--- | Show instance for 'Result'. Only for debugging purposes.
-instance Show Result where
-  show (Result _ _ _ _ cs _ _ [] [] _ [] _ [r])
-    | Just c <- r `lookup` cs
-    = show c
-  show (Result kinds _ cgs is cs ts as uis axs xs cstrs asserts os)  = intercalate "\n" $
-                   (if null usorts then [] else "SORTS" : map ("  " ++) usorts)
-                ++ ["INPUTS"]
-                ++ map shn is
-                ++ ["CONSTANTS"]
-                ++ map shc cs
-                ++ ["TABLES"]
-                ++ map sht ts
-                ++ ["ARRAYS"]
-                ++ map sha as
-                ++ ["UNINTERPRETED CONSTANTS"]
-                ++ map shui uis
-                ++ ["USER GIVEN CODE SEGMENTS"]
-                ++ concatMap shcg cgs
-                ++ ["AXIOMS"]
-                ++ map shax axs
-                ++ ["DEFINE"]
-                ++ map (\(s, e) -> "  " ++ shs s ++ " = " ++ show e) (F.toList (pgmAssignments xs))
-                ++ ["CONSTRAINTS"]
-                ++ map (("  " ++) . show) cstrs
-                ++ ["ASSERTIONS"]
-                ++ map (("  "++) . shAssert) asserts
-                ++ ["OUTPUTS"]
-                ++ map (("  " ++) . show) os
-    where usorts = [sh s t | KUserSort s t <- Set.toList kinds]
-                   where sh s (Left   _) = s
-                         sh s (Right es) = s ++ " (" ++ intercalate ", " es ++ ")"
-          shs sw = show sw ++ " :: " ++ show (swKind sw)
-          sht ((i, at, rt), es)  = "  Table " ++ show i ++ " : " ++ show at ++ "->" ++ show rt ++ " = " ++ show es
-          shc (sw, cw) = "  " ++ show sw ++ " = " ++ show cw
-          shcg (s, ss) = ("Variable: " ++ s) : map ("  " ++) ss
-          shn (q, (sw, nm)) = "  " ++ ni ++ " :: " ++ show (swKind sw) ++ ex ++ alias
-            where ni = show sw
-                  ex | q == ALL = ""
-                     | True     = ", existential"
-                  alias | ni == nm = ""
-                        | True     = ", aliasing " ++ show nm
-          sha (i, (nm, (ai, bi), ctx)) = "  " ++ ni ++ " :: " ++ show ai ++ " -> " ++ show bi ++ alias
-                                       ++ "\n     Context: "     ++ show ctx
-            where ni = "array_" ++ show i
-                  alias | ni == nm = ""
-                        | True     = ", aliasing " ++ show nm
-          shui (nm, t) = "  [uninterpreted] " ++ nm ++ " :: " ++ show t
-          shax (nm, ss) = "  -- user defined axiom: " ++ nm ++ "\n  " ++ intercalate "\n  " ss
-          shAssert (nm, stk, p) = "  -- assertion: " ++ nm ++ " " ++ maybe "[No location]"
-#if MIN_VERSION_base(4,9,0)
-                prettyCallStack
-#else
-                showCallStack
-#endif
-                stk ++ ": " ++ show p
-
--- | The context of a symbolic array as created
-data ArrayContext = ArrayFree (Maybe SW)     -- ^ A new array, with potential initializer for each cell
-                  | ArrayReset Int SW        -- ^ An array created from another array by fixing each element to another value
-                  | ArrayMutate Int SW SW    -- ^ An array created by mutating another array at a given cell
-                  | ArrayMerge  SW Int Int   -- ^ An array created by symbolically merging two other arrays
-
-instance Show ArrayContext where
-  show (ArrayFree Nothing)  = " initialized with random elements"
-  show (ArrayFree (Just s)) = " initialized with " ++ show s ++ " :: " ++ show (swKind s)
-  show (ArrayReset i s)     = " reset array_" ++ show i ++ " with " ++ show s ++ " :: " ++ show (swKind s)
-  show (ArrayMutate i a b)  = " cloned from array_" ++ show i ++ " with " ++ show a ++ " :: " ++ show (swKind a) ++ " |-> " ++ show b ++ " :: " ++ show (swKind b)
-  show (ArrayMerge s i j)   = " merged arrays " ++ show i ++ " and " ++ show j ++ " on condition " ++ show s
-
--- | Expression map, used for hash-consing
-type ExprMap   = Map.Map SBVExpr SW
-
--- | Constants are stored in a map, for hash-consing. The bool is needed to tell -0 from +0, sigh
-type CnstMap   = Map.Map (Bool, CW) SW
-
--- | Kinds used in the program; used for determining the final SMT-Lib logic to pick
-type KindSet = Set.Set Kind
-
--- | Tables generated during a symbolic run
-type TableMap  = Map.Map (Kind, Kind, [SW]) Int
-
--- | Representation for symbolic arrays
-type ArrayInfo = (String, (Kind, Kind), ArrayContext)
-
--- | Arrays generated during a symbolic run
-type ArrayMap  = IMap.IntMap ArrayInfo
-
--- | Uninterpreted-constants generated during a symbolic run
-type UIMap     = Map.Map String SBVType
-
--- | Code-segments for Uninterpreted-constants, as given by the user
-type CgMap     = Map.Map String [String]
-
--- | Cached values, implementing sharing
-type Cache a   = IMap.IntMap [(StableName (State -> IO a), a)]
-
--- | Different means of running a symbolic piece of code
-data SBVRunMode = Proof (Bool, SMTConfig) -- ^ Fully Symbolic, proof mode.
-                | CodeGen                 -- ^ Code generation mode.
-                | Concrete StdGen         -- ^ Concrete simulation mode. The StdGen is for the pConstrain acceptance in cross runs.
-
--- | Is this a concrete run? (i.e., quick-check or test-generation like)
-isConcreteMode :: State -> Bool
-isConcreteMode State{runMode} = case runMode of
-                                  Concrete{} -> True
-                                  Proof{}    -> False
-                                  CodeGen    -> False
-
--- | Is this a CodeGen run? (i.e., generating code)
-isCodeGenMode :: State -> Bool
-isCodeGenMode State{runMode} = case runMode of
-                                 Concrete{} -> False
-                                 Proof{}    -> False
-                                 CodeGen    -> True
-
--- | The state of the symbolic interpreter
-data State  = State { runMode      :: SBVRunMode
-                    , pathCond     :: SVal                             -- ^ kind KBool
-                    , rStdGen      :: IORef StdGen
-                    , rCInfo       :: IORef [(String, CW)]
-                    , rctr         :: IORef Int
-                    , rUsedKinds   :: IORef KindSet
-                    , rinps        :: IORef [(Quantifier, NamedSymVar)]
-                    , rConstraints :: IORef [SW]
-                    , routs        :: IORef [SW]
-                    , rtblMap      :: IORef TableMap
-                    , spgm         :: IORef SBVPgm
-                    , rconstMap    :: IORef CnstMap
-                    , rexprMap     :: IORef ExprMap
-                    , rArrayMap    :: IORef ArrayMap
-                    , rUIMap       :: IORef UIMap
-                    , rCgMap       :: IORef CgMap
-                    , raxioms      :: IORef [(String, [String])]
-                    , rAsserts     :: IORef [(String, Maybe CallStack, SW)]
-                    , rSWCache     :: IORef (Cache SW)
-                    , rAICache     :: IORef (Cache Int)
-                    }
-
--- | Get the current path condition
-getSValPathCondition :: State -> SVal
-getSValPathCondition = pathCond
-
--- | Extend the path condition with the given test value.
-extendSValPathCondition :: State -> (SVal -> SVal) -> State
-extendSValPathCondition st f = st{pathCond = f (pathCond st)}
-
--- | Are we running in proof mode?
-inProofMode :: State -> Bool
-inProofMode s = case runMode s of
-                  Proof{}    -> True
-                  CodeGen    -> False
-                  Concrete{} -> False
-
--- | If in proof mode, get the underlying configuration (used for 'sBranch')
-getSBranchRunConfig :: State -> Maybe SMTConfig
-getSBranchRunConfig st = case runMode st of
-                           Proof (_, s)  -> Just s
-                           _             -> Nothing
-
--- | The "Symbolic" value. Either a constant (@Left@) or a symbolic
--- value (@Right Cached@). Note that caching is essential for making
--- sure sharing is preserved.
-data SVal = SVal !Kind !(Either CW (Cached SW))
-
-instance HasKind SVal where
-  kindOf (SVal k _) = k
-
--- | Show instance for 'SVal'. Not particularly "desirable", but will do if needed
--- NB. We do not show the type info on constant KBool values, since there's no
--- implicit "fromBoolean" applied to Booleans in Haskell; and thus a statement
--- of the form "True :: SBool" is just meaningless. (There should be a fromBoolean!)
-instance Show SVal where
-  show (SVal KBool (Left c))  = showCW False c
-  show (SVal k     (Left c))  = showCW False c ++ " :: " ++ show k
-  show (SVal k     (Right _)) =         "<symbolic> :: " ++ show k
-
--- | Equality constraint on SBV values. Not desirable since we can't really compare two
--- symbolic values, but will do.
-instance Eq SVal where
-  SVal _ (Left a) == SVal _ (Left b) = a == b
-  a == b = error $ "Comparing symbolic bit-vectors; Use (.==) instead. Received: " ++ show (a, b)
-  SVal _ (Left a) /= SVal _ (Left b) = a /= b
-  a /= b = error $ "Comparing symbolic bit-vectors; Use (./=) instead. Received: " ++ show (a, b)
-
--- | Increment the variable counter
-incCtr :: State -> IO Int
-incCtr s = do ctr <- readIORef (rctr s)
-              let i = ctr + 1
-              i `seq` writeIORef (rctr s) i
-              return ctr
-
--- | Generate a random value, for quick-check and test-gen purposes
-throwDice :: State -> IO Double
-throwDice st = do g <- readIORef (rStdGen st)
-                  let (r, g') = randomR (0, 1) g
-                  writeIORef (rStdGen st) g'
-                  return r
-
--- | Create a new uninterpreted symbol, possibly with user given code
-newUninterpreted :: State -> String -> SBVType -> Maybe [String] -> IO ()
-newUninterpreted st nm t mbCode
-  | null nm || not enclosed && (not (isAlpha (head nm)) || not (all validChar (tail nm)))
-  = error $ "Bad uninterpreted constant name: " ++ show nm ++ ". Must be a valid identifier."
-  | True = do
-        uiMap <- readIORef (rUIMap st)
-        case nm `Map.lookup` uiMap of
-          Just t' -> when (t /= t') $ error $  "Uninterpreted constant " ++ show nm ++ " used at incompatible types\n"
-                                            ++ "      Current type      : " ++ show t ++ "\n"
-                                            ++ "      Previously used at: " ++ show t'
-          Nothing -> do modifyIORef (rUIMap st) (Map.insert nm t)
-                        when (isJust mbCode) $ modifyIORef (rCgMap st) (Map.insert nm (fromJust mbCode))
-  where validChar x = isAlphaNum x || x `elem` "_"
-        enclosed    = head nm == '|' && last nm == '|' && length nm > 2 && not (any (`elem` "|\\") (tail (init nm)))
-
--- | Add a new sAssert based constraint
-addAssertion :: State -> Maybe CallStack -> String -> SW -> IO ()
-addAssertion st cs msg cond = modifyIORef (rAsserts st) ((msg, cs, cond):)
-
--- | Create an internal variable, which acts as an input but isn't visible to the user.
--- Such variables are existentially quantified in a SAT context, and universally quantified
--- in a proof context.
-internalVariable :: State -> Kind -> IO SW
-internalVariable st k = do (sw, nm) <- newSW st k
-                           let q = case runMode st of
-                                     Proof (True,  _) -> EX
-                                     _                -> ALL
-                           modifyIORef (rinps st) ((q, (sw, "__internal_sbv_" ++ nm)):)
-                           return sw
-{-# INLINE internalVariable #-}
-
--- | Create a new SW
-newSW :: State -> Kind -> IO (SW, String)
-newSW st k = do ctr <- incCtr st
-                let sw = SW k (NodeId ctr)
-                registerKind st k
-                return (sw, 's' : show ctr)
-{-# INLINE newSW #-}
-
--- | Register a new kind with the system, used for uninterpreted sorts
-registerKind :: State -> Kind -> IO ()
-registerKind st k
-  | KUserSort sortName _ <- k, map toLower sortName `elem` smtLibReservedNames
-  = error $ "SBV: " ++ show sortName ++ " is a reserved sort; please use a different name."
-  | True
-  = modifyIORef (rUsedKinds st) (Set.insert k)
-
--- | Create a new constant; hash-cons as necessary
--- NB. For each constant, we also store weather it's negative-0 or not,
--- as otherwise +0 == -0 and thus we'd confuse those entries. That's a
--- bummer as we incur an extra boolean for this rare case, but it's simple
--- and hopefully we don't generate a ton of constants in general.
-newConst :: State -> CW -> IO SW
-newConst st c = do
-  constMap <- readIORef (rconstMap st)
-  let key = (isNeg0 (cwVal c), c)
-  case key `Map.lookup` constMap of
-    Just sw -> return sw
-    Nothing -> do let k = kindOf c
-                  (sw, _) <- newSW st k
-                  modifyIORef (rconstMap st) (Map.insert key sw)
-                  return sw
-  where isNeg0 (CWFloat  f) = isNegativeZero f
-        isNeg0 (CWDouble d) = isNegativeZero d
-        isNeg0 _            = False
-{-# INLINE newConst #-}
-
--- | Create a new table; hash-cons as necessary
-getTableIndex :: State -> Kind -> Kind -> [SW] -> IO Int
-getTableIndex st at rt elts = do
-  let key = (at, rt, elts)
-  tblMap <- readIORef (rtblMap st)
-  case key `Map.lookup` tblMap of
-    Just i -> return i
-    _      -> do let i = Map.size tblMap
-                 modifyIORef (rtblMap st) (Map.insert key i)
-                 return i
-
--- | Create a new expression; hash-cons as necessary
-newExpr :: State -> Kind -> SBVExpr -> IO SW
-newExpr st k app = do
-   let e = reorder app
-   exprMap <- readIORef (rexprMap st)
-   case e `Map.lookup` exprMap of
-     Just sw -> return sw
-     Nothing -> do (sw, _) <- newSW st k
-                   modifyIORef (spgm st)     (\(SBVPgm xs) -> SBVPgm (xs S.|> (sw, e)))
-                   modifyIORef (rexprMap st) (Map.insert e sw)
-                   return sw
-{-# INLINE newExpr #-}
-
--- | Convert a symbolic value to a symbolic-word
-svToSW :: State -> SVal -> IO SW
-svToSW st (SVal _ (Left c))  = newConst st c
-svToSW st (SVal _ (Right f)) = uncache f st
-
--- | Convert a symbolic value to an SW, inside the Symbolic monad
-svToSymSW :: SVal -> Symbolic SW
-svToSymSW sbv = do st <- ask
-                   liftIO $ svToSW st sbv
-
--------------------------------------------------------------------------
--- * Symbolic Computations
--------------------------------------------------------------------------
--- | A Symbolic computation. Represented by a reader monad carrying the
--- state of the computation, layered on top of IO for creating unique
--- references to hold onto intermediate results.
-newtype Symbolic a = Symbolic (ReaderT State IO a)
-                   deriving (Applicative, Functor, Monad, MonadIO, MonadReader State)
-
--- | Create a symbolic value, based on the quantifier we have. If an
--- explicit quantifier is given, we just use that. If not, then we
--- pick existential for SAT calls and universal for everything else.
--- @randomCW@ is used for generating random values for this variable
--- when used for 'quickCheck' purposes.
-svMkSymVar :: Maybe Quantifier -> Kind -> Maybe String -> Symbolic SVal
-svMkSymVar mbQ k mbNm = do
-        st <- ask
-        let q = case (mbQ, runMode st) of
-                  (Just x,  _)                -> x   -- user given, just take it
-                  (Nothing, Concrete{})       -> ALL -- concrete simulation, pick universal
-                  (Nothing, Proof (True,  _)) -> EX  -- sat mode, pick existential
-                  (Nothing, Proof (False, _)) -> ALL -- proof mode, pick universal
-                  (Nothing, CodeGen)          -> ALL -- code generation, pick universal
-        case runMode st of
-          Concrete _ | q == EX -> case mbNm of
-                                    Nothing -> error $ "Cannot quick-check in the presence of existential variables, type: " ++ show k
-                                    Just nm -> error $ "Cannot quick-check in the presence of existential variable " ++ nm ++ " :: " ++ show k
-          Concrete _           -> do cw <- liftIO (randomCW k)
-                                     liftIO $ modifyIORef (rCInfo st) ((fromMaybe "_" mbNm, cw):)
-                                     return (SVal k (Left cw))
-          _          -> do (sw, internalName) <- liftIO $ newSW st k
-                           let nm = fromMaybe internalName mbNm
-                           liftIO $ modifyIORef (rinps st) ((q, (sw, nm)):)
-                           return $ SVal k $ Right $ cache (const (return sw))
-
--- | Create a properly quantified variable of a user defined sort. Only valid
--- in proof contexts.
-mkSValUserSort :: Kind -> Maybe Quantifier -> Maybe String -> Symbolic SVal
-mkSValUserSort k mbQ mbNm = do
-        st <- ask
-        let (KUserSort sortName _) = k
-        liftIO $ registerKind st k
-        let q = case (mbQ, runMode st) of
-                  (Just x,  _)                -> x
-                  (Nothing, Proof (True,  _)) -> EX
-                  (Nothing, Proof (False, _)) -> ALL
-                  (Nothing, CodeGen)          -> error $ "SBV: Uninterpreted sort " ++ sortName ++ " can not be used in code-generation mode."
-                  (Nothing, Concrete{})       -> error $ "SBV: Uninterpreted sort " ++ sortName ++ " can not be used in concrete simulation mode."
-        ctr <- liftIO $ incCtr st
-        let sw = SW k (NodeId ctr)
-            nm = fromMaybe ('s':show ctr) mbNm
-        liftIO $ modifyIORef (rinps st) ((q, (sw, nm)):)
-        return $ SVal k $ Right $ cache (const (return sw))
-
--- | Add a user specified axiom to the generated SMT-Lib file. The first argument is a mere
--- string, use for commenting purposes. The second argument is intended to hold the multiple-lines
--- of the axiom text as expressed in SMT-Lib notation. Note that we perform no checks on the axiom
--- itself, to see whether it's actually well-formed or is sensical by any means.
--- A separate formalization of SMT-Lib would be very useful here.
-addAxiom :: String -> [String] -> Symbolic ()
-addAxiom nm ax = do
-        st <- ask
-        liftIO $ modifyIORef (raxioms st) ((nm, ax) :)
-
--- | Run a symbolic computation in Proof mode and return a 'Result'. The boolean
--- argument indicates if this is a sat instance or not.
-runSymbolic :: (Bool, SMTConfig) -> Symbolic a -> IO Result
-runSymbolic m c = snd `fmap` runSymbolic' (Proof m) c
-
--- | Run a symbolic computation, and return a extra value paired up with the 'Result'
-runSymbolic' :: SBVRunMode -> Symbolic a -> IO (a, Result)
-runSymbolic' currentRunMode (Symbolic c) = do
-   ctr       <- newIORef (-2) -- start from -2; False and True will always occupy the first two elements
-   cInfo     <- newIORef []
-   pgm       <- newIORef (SBVPgm S.empty)
-   emap      <- newIORef Map.empty
-   cmap      <- newIORef Map.empty
-   inps      <- newIORef []
-   outs      <- newIORef []
-   tables    <- newIORef Map.empty
-   arrays    <- newIORef IMap.empty
-   uis       <- newIORef Map.empty
-   cgs       <- newIORef Map.empty
-   axioms    <- newIORef []
-   swCache   <- newIORef IMap.empty
-   aiCache   <- newIORef IMap.empty
-   usedKinds <- newIORef Set.empty
-   cstrs     <- newIORef []
-   asserts   <- newIORef []
-   rGen      <- case currentRunMode of
-                  Concrete g -> newIORef g
-                  _          -> newStdGen >>= newIORef
-   let st = State { runMode      = currentRunMode
-                  , pathCond     = SVal KBool (Left trueCW)
-                  , rStdGen      = rGen
-                  , rCInfo       = cInfo
-                  , rctr         = ctr
-                  , rUsedKinds   = usedKinds
-                  , rinps        = inps
-                  , routs        = outs
-                  , rtblMap      = tables
-                  , spgm         = pgm
-                  , rconstMap    = cmap
-                  , rArrayMap    = arrays
-                  , rexprMap     = emap
-                  , rUIMap       = uis
-                  , rCgMap       = cgs
-                  , raxioms      = axioms
-                  , rSWCache     = swCache
-                  , rAICache     = aiCache
-                  , rConstraints = cstrs
-                  , rAsserts     = asserts
-                  }
-   _ <- newConst st falseCW -- s(-2) == falseSW
-   _ <- newConst st trueCW  -- s(-1) == trueSW
-   r <- runReaderT c st
-   res <- extractSymbolicSimulationState st
-   return (r, res)
-
--- | Grab the program from a running symbolic simulation state. This is useful for internal purposes, for
--- instance when implementing 'sBranch'.
-extractSymbolicSimulationState :: State -> IO Result
-extractSymbolicSimulationState st@State{ spgm=pgm, rinps=inps, routs=outs, rtblMap=tables, rArrayMap=arrays, rUIMap=uis, raxioms=axioms
-                                       , rAsserts=asserts, rUsedKinds=usedKinds, rCgMap=cgs, rCInfo=cInfo, rConstraints=cstrs} = do
-   SBVPgm rpgm  <- readIORef pgm
-   inpsO <- reverse `fmap` readIORef inps
-   outsO <- reverse `fmap` readIORef outs
-   let swap  (a, b)              = (b, a)
-       swapc ((_, a), b)         = (b, a)
-       cmp   (a, _) (b, _)       = a `compare` b
-       arrange (i, (at, rt, es)) = ((i, at, rt), es)
-   cnsts <- (sortBy cmp . map swapc . Map.toList) `fmap` readIORef (rconstMap st)
-   tbls  <- (map arrange . sortBy cmp . map swap . Map.toList) `fmap` readIORef tables
-   arrs  <- IMap.toAscList `fmap` readIORef arrays
-   unint <- Map.toList `fmap` readIORef uis
-   axs   <- reverse `fmap` readIORef axioms
-   knds  <- readIORef usedKinds
-   cgMap <- Map.toList `fmap` readIORef cgs
-   traceVals <- reverse `fmap` readIORef cInfo
-   extraCstrs <- reverse `fmap` readIORef cstrs
-   assertions <- reverse `fmap` readIORef asserts
-   return $ Result knds traceVals cgMap inpsO cnsts tbls arrs unint axs (SBVPgm rpgm) extraCstrs assertions outsO
-
--- | Handling constraints
-imposeConstraint :: SVal -> Symbolic ()
-imposeConstraint c = do st <- ask
-                        case runMode st of
-                          CodeGen -> error "SBV: constraints are not allowed in code-generation"
-                          _       -> liftIO $ internalConstraint st c
-
--- | Require a boolean condition to be true in the state. Only used for internal purposes.
-internalConstraint :: State -> SVal -> IO ()
-internalConstraint st b = do v <- svToSW st b
-                             modifyIORef (rConstraints st) (v:)
-
--- | Add a constraint with a given probability
-addSValConstraint :: Maybe Double -> SVal -> SVal -> Symbolic ()
-addSValConstraint Nothing  c _  = imposeConstraint c
-addSValConstraint (Just t) c c'
-  | t < 0 || t > 1
-  = error $ "SBV: pConstrain: Invalid probability threshold: " ++ show t ++ ", must be in [0, 1]."
-  | True
-  = do st <- ask
-       unless (isConcreteMode st) $ error "SBV: pConstrain only allowed in 'genTest' or 'quickCheck' contexts."
-       case () of
-         () | t > 0 && t < 1 -> liftIO (throwDice st) >>= \d -> imposeConstraint (if d <= t then c else c')
-            | t > 0          -> imposeConstraint c
-            | True           -> imposeConstraint c'
-
--- | Mark an interim result as an output. Useful when constructing Symbolic programs
--- that return multiple values, or when the result is programmatically computed.
-outputSVal :: SVal -> Symbolic ()
-outputSVal (SVal _ (Left c)) = do
-  st <- ask
-  sw <- liftIO $ newConst st c
-  liftIO $ modifyIORef (routs st) (sw:)
-outputSVal (SVal _ (Right f)) = do
-  st <- ask
-  sw <- liftIO $ uncache f st
-  liftIO $ modifyIORef (routs st) (sw:)
-
----------------------------------------------------------------------------------
--- * Symbolic Arrays
----------------------------------------------------------------------------------
-
--- | Arrays implemented in terms of SMT-arrays: <http://smtlib.cs.uiowa.edu/theories-ArraysEx.shtml>
---
---   * Maps directly to SMT-lib arrays
---
---   * Reading from an unintialized value is OK and yields an unspecified result
---
---   * Can check for equality of these arrays
---
---   * Cannot quick-check theorems using @SArr@ values
---
---   * Typically slower as it heavily relies on SMT-solving for the array theory
---
-
-data SArr = SArr (Kind, Kind) (Cached ArrayIndex)
-
--- | Read the array element at @a@
-readSArr :: SArr -> SVal -> SVal
-readSArr (SArr (_, bk) f) a = SVal bk $ Right $ cache r
-  where r st = do arr <- uncacheAI f st
-                  i   <- svToSW st a
-                  newExpr st bk (SBVApp (ArrRead arr) [i])
-
--- | Reset all the elements of the array to the value @b@
-resetSArr :: SArr -> SVal -> SArr
-resetSArr (SArr ainfo f) b = SArr ainfo $ cache g
-  where g st = do amap <- readIORef (rArrayMap st)
-                  val <- svToSW st b
-                  i <- uncacheAI f st
-                  let j = IMap.size amap
-                  j `seq` modifyIORef (rArrayMap st) (IMap.insert j ("array_" ++ show j, ainfo, ArrayReset i val))
-                  return j
-
--- | Update the element at @a@ to be @b@
-writeSArr :: SArr -> SVal -> SVal -> SArr
-writeSArr (SArr ainfo f) a b = SArr ainfo $ cache g
-  where g st = do arr  <- uncacheAI f st
-                  addr <- svToSW st a
-                  val  <- svToSW st b
-                  amap <- readIORef (rArrayMap st)
-                  let j = IMap.size amap
-                  j `seq` modifyIORef (rArrayMap st) (IMap.insert j ("array_" ++ show j, ainfo, ArrayMutate arr addr val))
-                  return j
-
--- | Merge two given arrays on the symbolic condition
--- Intuitively: @mergeArrays cond a b = if cond then a else b@.
--- Merging pushes the if-then-else choice down on to elements
-mergeSArr :: SVal -> SArr -> SArr -> SArr
-mergeSArr t (SArr ainfo a) (SArr _ b) = SArr ainfo $ cache h
-  where h st = do ai <- uncacheAI a st
-                  bi <- uncacheAI b st
-                  ts <- svToSW st t
-                  amap <- readIORef (rArrayMap st)
-                  let k = IMap.size amap
-                  k `seq` modifyIORef (rArrayMap st) (IMap.insert k ("array_" ++ show k, ainfo, ArrayMerge ts ai bi))
-                  return k
-
--- | Create a named new array, with an optional initial value
-newSArr :: (Kind, Kind) -> (Int -> String) -> Maybe SVal -> Symbolic SArr
-newSArr ainfo mkNm mbInit = do
-    st <- ask
-    amap <- liftIO $ readIORef $ rArrayMap st
-    let i = IMap.size amap
-        nm = mkNm i
-    actx <- liftIO $ case mbInit of
-                       Nothing   -> return $ ArrayFree Nothing
-                       Just ival -> svToSW st ival >>= \sw -> return $ ArrayFree (Just sw)
-    liftIO $ modifyIORef (rArrayMap st) (IMap.insert i (nm, ainfo, actx))
-    return $ SArr ainfo $ cache $ const $ return i
-
--- | Compare two arrays for equality
-eqSArr :: SArr -> SArr -> SVal
-eqSArr (SArr _ a) (SArr _ b) = SVal KBool $ Right $ cache c
-  where c st = do ai <- uncacheAI a st
-                  bi <- uncacheAI b st
-                  newExpr st KBool (SBVApp (ArrEq ai bi) [])
-
----------------------------------------------------------------------------------
--- * Cached values
----------------------------------------------------------------------------------
-
--- | We implement a peculiar caching mechanism, applicable to the use case in
--- implementation of SBV's.  Whenever we do a state based computation, we do
--- not want to keep on evaluating it in the then-current state. That will
--- produce essentially a semantically equivalent value. Thus, we want to run
--- it only once, and reuse that result, capturing the sharing at the Haskell
--- level. This is similar to the "type-safe observable sharing" work, but also
--- takes into the account of how symbolic simulation executes.
---
--- See Andy Gill's type-safe obervable sharing trick for the inspiration behind
--- this technique: <http://ittc.ku.edu/~andygill/paper.php?label=DSLExtract09>
---
--- Note that this is *not* a general memo utility!
-newtype Cached a = Cached (State -> IO a)
-
--- | Cache a state-based computation
-cache :: (State -> IO a) -> Cached a
-cache = Cached
-
--- | Uncache a previously cached computation
-uncache :: Cached SW -> State -> IO SW
-uncache = uncacheGen rSWCache
-
--- | An array index is simple an int value
-type ArrayIndex = Int
-
--- | Uncache, retrieving array indexes
-uncacheAI :: Cached ArrayIndex -> State -> IO ArrayIndex
-uncacheAI = uncacheGen rAICache
-
--- | Generic uncaching. Note that this is entirely safe, since we do it in the IO monad.
-uncacheGen :: (State -> IORef (Cache a)) -> Cached a -> State -> IO a
-uncacheGen getCache (Cached f) st = do
-        let rCache = getCache st
-        stored <- readIORef rCache
-        sn <- f `seq` makeStableName f
-        let h = hashStableName sn
-        case maybe Nothing (sn `lookup`) (h `IMap.lookup` stored) of
-          Just r  -> return r
-          Nothing -> do r <- f st
-                        r `seq` modifyIORef rCache (IMap.insertWith (++) h [(sn, r)])
-                        return r
-
--- | Representation of SMTLib Program versions. As of June 2015, we're dropping support
--- for SMTLib1, and supporting SMTLib2 only. We keep this data-type around in case
--- SMTLib3 comes along and we want to support 2 and 3 simultaneously.
-data SMTLibVersion = SMTLib2
-                   deriving (Bounded, Enum, Eq, Show)
-
--- | The extension associated with the version
-smtLibVersionExtension :: SMTLibVersion -> String
-smtLibVersionExtension SMTLib2 = "smt2"
-
--- | Representation of an SMT-Lib program. In between pre and post goes the refuted models
-data SMTLibPgm = SMTLibPgm SMTLibVersion  ( [(String, SW)]  -- alias table
-                                          , [String]        -- pre: declarations.
-                                          , [String])       -- post: formula
-instance NFData SMTLibVersion where rnf a                       = a `seq` ()
-instance NFData SMTLibPgm     where rnf (SMTLibPgm v (t, d, p)) = rnf v `seq` rnf t `seq` rnf d `seq` rnf p `seq` ()
-
-instance Show SMTLibPgm where
-  show (SMTLibPgm _ (_, pre, post)) = intercalate "\n" $ pre ++ post
-
--- Other Technicalities..
-instance NFData CW where
-  rnf (CW x y) = x `seq` y `seq` ()
-
-#if MIN_VERSION_base(4,9,0)
-#else
--- Can't really force this, but not a big deal
-instance NFData CallStack where
-  rnf _ = ()
-#endif
-  
-
-
-instance NFData Result where
-  rnf (Result kindInfo qcInfo cgs inps consts tbls arrs uis axs pgm cstr asserts outs)
-        = rnf kindInfo `seq` rnf qcInfo `seq` rnf cgs     `seq` rnf inps
-                       `seq` rnf consts `seq` rnf tbls    `seq` rnf arrs
-                       `seq` rnf uis    `seq` rnf axs     `seq` rnf pgm
-                       `seq` rnf cstr   `seq` rnf asserts `seq` rnf outs
-instance NFData Kind         where rnf a          = seq a ()
-instance NFData ArrayContext where rnf a          = seq a ()
-instance NFData SW           where rnf a          = seq a ()
-instance NFData SBVExpr      where rnf a          = seq a ()
-instance NFData Quantifier   where rnf a          = seq a ()
-instance NFData SBVType      where rnf a          = seq a ()
-instance NFData SBVPgm       where rnf a          = seq a ()
-instance NFData (Cached a)   where rnf (Cached f) = f `seq` ()
-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 (Unknown _ xs)      = rnf xs `seq` ()
-  rnf (ProofError _ xs)   = rnf xs `seq` ()
-  rnf (TimeOut _)         = ()
-
-instance NFData SMTModel where
-  rnf (SMTModel assocs) = rnf assocs `seq` ()
-
-instance NFData SMTScript where
-  rnf (SMTScript b m) = rnf b `seq` rnf m `seq` ()
-
--- | SMT-Lib logics. If left unspecified SBV will pick the logic based on what it determines is needed. However, the
--- user can override this choice using the 'useLogic' parameter to the configuration. This is especially handy if
--- one is experimenting with custom logics that might be supported on new solvers. See <http://smtlib.cs.uiowa.edu/logics.shtml>
--- for the official list.
-data SMTLibLogic
-  = AUFLIA    -- ^ Formulas over the theory of linear integer arithmetic and arrays extended with free sort and function symbols but restricted to arrays with integer indices and values
-  | AUFLIRA   -- ^ Linear formulas with free sort and function symbols over one- and two-dimentional arrays of integer index and real value
-  | AUFNIRA   -- ^ Formulas with free function and predicate symbols over a theory of arrays of arrays of integer index and real value
-  | LRA       -- ^ Linear formulas in linear real arithmetic
-  | QF_ABV    -- ^ Quantifier-free formulas over the theory of bitvectors and bitvector arrays
-  | QF_AUFBV  -- ^ Quantifier-free formulas over the theory of bitvectors and bitvector arrays extended with free sort and function symbols
-  | QF_AUFLIA -- ^ Quantifier-free linear formulas over the theory of integer arrays extended with free sort and function symbols
-  | QF_AX     -- ^ Quantifier-free formulas over the theory of arrays with extensionality
-  | QF_BV     -- ^ Quantifier-free formulas over the theory of fixed-size bitvectors
-  | QF_IDL    -- ^ Difference Logic over the integers. Boolean combinations of inequations of the form x - y < b where x and y are integer variables and b is an integer constant
-  | QF_LIA    -- ^ Unquantified linear integer arithmetic. In essence, Boolean combinations of inequations between linear polynomials over integer variables
-  | QF_LRA    -- ^ Unquantified linear real arithmetic. In essence, Boolean combinations of inequations between linear polynomials over real variables.
-  | QF_NIA    -- ^ Quantifier-free integer arithmetic.
-  | QF_NRA    -- ^ Quantifier-free real arithmetic.
-  | QF_RDL    -- ^ Difference Logic over the reals. In essence, Boolean combinations of inequations of the form x - y < b where x and y are real variables and b is a rational constant.
-  | QF_UF     -- ^ Unquantified formulas built over a signature of uninterpreted (i.e., free) sort and function symbols.
-  | QF_UFBV   -- ^ Unquantified formulas over bitvectors with uninterpreted sort function and symbols.
-  | QF_UFIDL  -- ^ Difference Logic over the integers (in essence) but with uninterpreted sort and function symbols.
-  | QF_UFLIA  -- ^ Unquantified linear integer arithmetic with uninterpreted sort and function symbols.
-  | QF_UFLRA  -- ^ Unquantified linear real arithmetic with uninterpreted sort and function symbols.
-  | QF_UFNRA  -- ^ Unquantified non-linear real arithmetic with uninterpreted sort and function symbols.
-  | UFLRA     -- ^ Linear real arithmetic with uninterpreted sort and function symbols.
-  | UFNIA     -- ^ Non-linear integer arithmetic with uninterpreted sort and function symbols.
-  | QF_FPBV   -- ^ Quantifier-free formulas over the theory of floating point numbers, arrays, and bit-vectors
-  | QF_FP     -- ^ Quantifier-free formulas over the theory of floating point numbers
-  deriving Show
-
--- | Chosen logic for the solver
-data Logic = PredefinedLogic SMTLibLogic  -- ^ Use one of the logics as defined by the standard
-           | CustomLogic     String       -- ^ Use this name for the logic
-
-instance Show Logic where
-  show (PredefinedLogic l) = show l
-  show (CustomLogic     s) = s
-
--- | Translation tricks needed for specific capabilities afforded by each solver
-data SolverCapabilities = SolverCapabilities {
-         capSolverName              :: String               -- ^ Name of the solver
-       , mbDefaultLogic             :: Bool -> Maybe String -- ^ set-logic string to use in case not automatically determined (if any). If Bool is True, then reals are present.
-       , supportsMacros             :: Bool                 -- ^ Does the solver understand SMT-Lib2 macros?
-       , supportsProduceModels      :: Bool                 -- ^ Does the solver understand produce-models option setting
-       , supportsQuantifiers        :: Bool                 -- ^ Does the solver understand SMT-Lib2 style quantifiers?
-       , supportsUninterpretedSorts :: Bool                 -- ^ Does the solver understand SMT-Lib2 style uninterpreted-sorts
-       , supportsUnboundedInts      :: Bool                 -- ^ Does the solver support unbounded integers?
-       , supportsReals              :: Bool                 -- ^ Does the solver support reals?
-       , supportsFloats             :: Bool                 -- ^ Does the solver support single-precision floating point numbers?
-       , supportsDoubles            :: Bool                 -- ^ Does the solver support double-precision floating point numbers?
-       }
-
--- | Rounding mode to be used for the IEEE floating-point operations.
--- Note that Haskell's default is 'RoundNearestTiesToEven'. If you use
--- a different rounding mode, then the counter-examples you get may not
--- match what you observe in Haskell.
-data RoundingMode = RoundNearestTiesToEven  -- ^ Round to nearest representable floating point value.
-                                            -- If precisely at half-way, pick the even number.
-                                            -- (In this context, /even/ means the lowest-order bit is zero.)
-                  | RoundNearestTiesToAway  -- ^ Round to nearest representable floating point value.
-                                            -- If precisely at half-way, pick the number further away from 0.
-                                            -- (That is, for positive values, pick the greater; for negative values, pick the smaller.)
-                  | RoundTowardPositive     -- ^ Round towards positive infinity. (Also known as rounding-up or ceiling.)
-                  | RoundTowardNegative     -- ^ Round towards negative infinity. (Also known as rounding-down or floor.)
-                  | RoundTowardZero         -- ^ Round towards zero. (Also known as truncation.)
-                  deriving (Eq, Ord, Show, Read, G.Data, Bounded, Enum)
-
--- | 'RoundingMode' kind
-instance HasKind RoundingMode
-
--- | Solver configuration. See also 'z3', 'yices', 'cvc4', 'boolector', 'mathSAT', etc. which are instantiations of this type for those solvers, with
--- reasonable defaults. In particular, custom configuration can be created by varying those values. (Such as @z3{verbose=True}@.)
---
--- Most fields are self explanatory. The notion of precision for printing algebraic reals stems from the fact that such values does
--- not necessarily have finite decimal representations, and hence we have to stop printing at some depth. It is important to
--- emphasize that such values always have infinite precision internally. The issue is merely with how we print such an infinite
--- precision value on the screen. The field 'printRealPrec' controls the printing precision, by specifying the number of digits after
--- the decimal point. The default value is 16, but it can be set to any positive integer.
---
--- When printing, SBV will add the suffix @...@ at the and of a real-value, if the given bound is not sufficient to represent the real-value
--- exactly. Otherwise, the number will be written out in standard decimal notation. Note that SBV will always print the whole value if it
--- is precise (i.e., if it fits in a finite number of digits), regardless of the precision limit. The limit only applies if the representation
--- of the real value is not finite, i.e., if it is not rational.
---
--- 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.)
-       , sBranchTimeOut :: Maybe Int      -- ^ How much time to give to the solver for each call of 'sBranch' check. (In seconds. Default: No limit.)
-       , timeOut        :: Maybe Int      -- ^ How much time to give to the solver. (In seconds. Default: No limit.)
-       , 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)
-       , solverTweaks   :: [String]       -- ^ Additional lines of script to give to the solver (user specified)
-       , satCmd         :: String         -- ^ Usually "(check-sat)". However, users might tweak it based on solver characteristics.
-       , isNonModelVar  :: String -> Bool -- ^ When constructing a model, ignore variables whose name satisfy this predicate. (Default: (const False), i.e., don't ignore anything)
-       , smtFile        :: Maybe FilePath -- ^ If Just, the generated SMT script will be put in this 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
-       , useLogic       :: Maybe Logic    -- ^ If Nothing, pick automatically. Otherwise, either use the given one, or use the custom string.
-       }
-
-instance Show SMTConfig where
-  show = show . solver
-
--- | A model, as returned by a solver
-newtype SMTModel = SMTModel {
-        modelAssocs    :: [(String, CW)]        -- ^ Mapping of symbolic values to constants.
-     }
-     deriving Show
-
--- | The result of an SMT solver call. Each constructor is tagged with
--- the 'SMTConfig' that created it so that further tools can inspect it
--- 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            -- ^ Unsatisfiable
-               | Satisfiable   SMTConfig SMTModel   -- ^ Satisfiable with model
-               | Unknown       SMTConfig SMTModel   -- ^ Prover returned unknown, with a potential (possibly bogus) model
-               | ProofError    SMTConfig [String]   -- ^ Prover errored out
-               | TimeOut       SMTConfig            -- ^ Computation timed out (see the 'timeout' combinator)
-
--- | A script, to be passed to the solver.
-data SMTScript = SMTScript {
-          scriptBody  :: String        -- ^ Initial feed
-        , scriptModel :: Maybe String  -- ^ Optional continuation script, if the result is sat
-        }
-
--- | An SMT engine
-type SMTEngine = SMTConfig -> Bool -> [(Quantifier, NamedSymVar)] -> [Either SW (SW, [SW])] -> String -> IO SMTResult
-
--- | Solvers that SBV is aware of
-data Solver = Z3
-            | Yices
-            | Boolector
-            | CVC4
-            | MathSAT
-            | ABC
-            deriving (Show, Enum, Bounded)
-
--- | An SMT solver
-data SMTSolver = SMTSolver {
-         name           :: Solver             -- ^ The solver in use
-       , executable     :: String             -- ^ The path to its executable
-       , options        :: [String]           -- ^ Options to provide to the solver
-       , engine         :: SMTEngine          -- ^ The solver engine, responsible for interpreting solver output
-       , capabilities   :: SolverCapabilities -- ^ Various capabilities of the solver
-       }
-
-instance Show SMTSolver where
-   show = show . name
-
-{-# ANN type FPOp   ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/Data/SBV/Bridge/ABC.hs b/Data/SBV/Bridge/ABC.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/ABC.hs
+++ /dev/null
@@ -1,114 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.ABC
--- Copyright   :  (c) Adam Foltzer
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the ABC verification and synthesis tool. Import this
--- module if you want to use ABC as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.Boolector"
--- 
---       - "Data.SBV.Bridge.CVC4"
--- 
---       - "Data.SBV.Bridge.MathSAT"
--- 
---       - "Data.SBV.Bridge.Yices"
--- 
---       - "Data.SBV.Bridge.Z3"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.ABC (
-  -- * ABC specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to abc.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = abc
-
--- | Prove theorems, using ABC
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using ABC
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using ABC
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using ABC
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using ABC
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using ABC
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using ABC
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using ABC
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using ABC
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using ABC
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Bridge/Boolector.hs b/Data/SBV/Bridge/Boolector.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/Boolector.hs
+++ /dev/null
@@ -1,116 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.Boolector
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the Boolector SMT solver. Import this module if you want to use the
--- Boolector SMT prover as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.ABC"
--- 
---       - "Data.SBV.Bridge.CVC4"
--- 
---       - "Data.SBV.Bridge.MathSAT"
--- 
---       - "Data.SBV.Bridge.Yices"
--- 
---       - "Data.SBV.Bridge.Z3"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.Boolector (
-  -- * Boolector specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  -- * Non-Boolector specific SBV interface
-  -- $moduleExportIntro
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to Boolector.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = boolector
-
--- | Prove theorems, using the Boolector SMT solver
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using the Boolector SMT solver
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using the Boolector SMT solver
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using the Boolector SMT solver
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using the Boolector SMT solver
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using the Boolector SMT solver
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using the Boolector SMT solver
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using the Boolector SMT solver
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using the Boolector SMT solver
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using the Boolector SMT solver
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Bridge/CVC4.hs b/Data/SBV/Bridge/CVC4.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/CVC4.hs
+++ /dev/null
@@ -1,116 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.CVC4
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the CVC4 SMT solver. Import this module if you want to use the
--- CVC4 SMT prover as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.ABC"
--- 
---       - "Data.SBV.Bridge.Boolector"
--- 
---       - "Data.SBV.Bridge.MathSAT"
--- 
---       - "Data.SBV.Bridge.Yices"
--- 
---       - "Data.SBV.Bridge.Z3"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.CVC4 (
-  -- * CVC4 specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  -- * Non-CVC4 specific SBV interface
-  -- $moduleExportIntro
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to cvc4.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = cvc4
-
--- | Prove theorems, using the CVC4 SMT solver
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using the CVC4 SMT solver
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using the CVC4 SMT solver
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using the CVC4 SMT solver
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using the CVC4 SMT solver
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using the CVC4 SMT solver
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using the CVC4 SMT solver
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using the CVC4 SMT solver
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using the CVC4 SMT solver
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using the CVC4 SMT solver
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Bridge/MathSAT.hs b/Data/SBV/Bridge/MathSAT.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/MathSAT.hs
+++ /dev/null
@@ -1,116 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.MathSAT
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the MathSAT SMT solver. Import this module if you want to use the
--- MathSAT SMT prover as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.ABC"
--- 
---       - "Data.SBV.Bridge.Boolector"
--- 
---       - "Data.SBV.Bridge.CVC4"
--- 
---       - "Data.SBV.Bridge.Yices"
--- 
---       - "Data.SBV.Bridge.Z3"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.MathSAT (
-  -- * MathSAT specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  -- * Non-MathSAT specific SBV interface
-  -- $moduleExportIntro
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to MathSAT.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = mathSAT
-
--- | Prove theorems, using the MathSAT SMT solver
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using the MathSAT SMT solver
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using the MathSAT SMT solver
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using the MathSAT SMT solver
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using the MathSAT SMT solver
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using the MathSAT SMT solver
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using the MathSAT SMT solver
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using the MathSAT SMT solver
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using the MathSAT SMT solver
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using the MathSAT SMT solver
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Bridge/Yices.hs b/Data/SBV/Bridge/Yices.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/Yices.hs
+++ /dev/null
@@ -1,116 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.Yices
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the Yices SMT solver. Import this module if you want to use the
--- Yices SMT prover as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.ABC"
--- 
---       - "Data.SBV.Bridge.Boolector"
--- 
---       - "Data.SBV.Bridge.CVC4"
--- 
---       - "Data.SBV.Bridge.MathSAT"
--- 
---       - "Data.SBV.Bridge.Z3"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.Yices (
-  -- * Yices specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  -- * Non-Yices specific SBV interface
-  -- $moduleExportIntro
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to yices.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = yices
-
--- | Prove theorems, using the Yices SMT solver
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using the Yices SMT solver
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using the Yices SMT solver
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using the Yices SMT solver
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using the Yices SMT solver
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using the Yices SMT solver
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using the Yices SMT solver
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using the Yices SMT solver
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using the Yices SMT solver
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using the Yices SMT solver
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Bridge/Z3.hs b/Data/SBV/Bridge/Z3.hs
deleted file mode 100644
--- a/Data/SBV/Bridge/Z3.hs
+++ /dev/null
@@ -1,116 +0,0 @@
----------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Bridge.Z3
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Interface to the Z3 SMT solver. Import this module if you want to use the
--- Z3 SMT prover as your backend solver. Also see:
---
---       - "Data.SBV.Bridge.ABC"
--- 
---       - "Data.SBV.Bridge.Boolector"
--- 
---       - "Data.SBV.Bridge.CVC4"
--- 
---       - "Data.SBV.Bridge.MathSAT"
--- 
---       - "Data.SBV.Bridge.Yices"
---
----------------------------------------------------------------------------------
-
-module Data.SBV.Bridge.Z3 (
-  -- * Z3 specific interface
-  sbvCurrentSolver
-  -- ** Proving, checking satisfiability
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
-  -- ** Optimization routines
-  , optimize, minimize, maximize
-  -- * Non-Z3 specific SBV interface
-  -- $moduleExportIntro
-  , module Data.SBV
-  ) where
-
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
-
--- | Current solver instance, pointing to z3.
-sbvCurrentSolver :: SMTConfig
-sbvCurrentSolver = z3
-
--- | Prove theorems, using the Z3 SMT solver
-prove :: Provable a
-      => a              -- ^ Property to check
-      -> IO ThmResult   -- ^ Response from the SMT solver, containing the counter-example if found
-prove = proveWith sbvCurrentSolver
-
--- | Find satisfying solutions, using the Z3 SMT solver
-sat :: Provable a
-    => a                -- ^ Property to check
-    -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
-sat = satWith sbvCurrentSolver
-
--- | Check all 'sAssert' calls are safe, using the Z3 SMT solver
-safe :: SExecutable a
-    => a                -- ^ Program containing sAssert calls
-    -> IO [SafeResult]
-safe = safeWith sbvCurrentSolver
-
--- | Find all satisfying solutions, using the Z3 SMT solver
-allSat :: Provable a
-       => a                -- ^ Property to check
-       -> IO AllSatResult  -- ^ List of all satisfying models
-allSat = allSatWith sbvCurrentSolver
-
--- | Check vacuity of the explicit constraints introduced by calls to the 'constrain' function, using the Z3 SMT solver
-isVacuous :: Provable a
-          => a             -- ^ Property to check
-          -> IO Bool       -- ^ True if the constraints are unsatisifiable
-isVacuous = isVacuousWith sbvCurrentSolver
-
--- | Check if the statement is a theorem, with an optional time-out in seconds, using the Z3 SMT solver
-isTheorem :: Provable a
-          => Maybe Int          -- ^ Optional time-out, specify in seconds
-          -> a                  -- ^ Property to check
-          -> IO (Maybe Bool)    -- ^ Returns Nothing if time-out expires
-isTheorem = isTheoremWith sbvCurrentSolver
-
--- | Check if the statement is satisfiable, with an optional time-out in seconds, using the Z3 SMT solver
-isSatisfiable :: Provable a
-              => Maybe Int       -- ^ Optional time-out, specify in seconds
-              -> a               -- ^ Property to check
-              -> IO (Maybe Bool) -- ^ Returns Nothing if time-out expiers
-isSatisfiable = isSatisfiableWith sbvCurrentSolver
-
--- | Optimize cost functions, using the Z3 SMT solver
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> (SBV c -> SBV c -> SBool)   -- ^ Betterness check: This is the comparison predicate for optimization
-         -> ([SBV a] -> SBV c)          -- ^ Cost function
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-optimize = optimizeWith sbvCurrentSolver
-
--- | Minimize cost functions, using the Z3 SMT solver
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to minimize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-minimize = minimizeWith sbvCurrentSolver
-
--- | Maximize cost functions, using the Z3 SMT solver
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-         => OptimizeOpts                -- ^ Parameters to optimization (Iterative, Quantified, etc.)
-         -> ([SBV a] -> SBV c)          -- ^ Cost function to maximize
-         -> Int                         -- ^ Number of inputs
-         -> ([SBV a] -> SBool)          -- ^ Validity function
-         -> IO (Maybe [a])              -- ^ Returns Nothing if there is no valid solution, otherwise an optimal solution
-maximize = maximizeWith sbvCurrentSolver
-
-{- $moduleExportIntro
-The remainder of the SBV library that is common to all back-end SMT solvers, directly coming from the "Data.SBV" module.
--}
diff --git a/Data/SBV/Char.hs b/Data/SBV/Char.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Char.hs
@@ -0,0 +1,315 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Char
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A collection of character utilities, follows the namings
+-- in "Data.Char" and is intended to be imported qualified.
+-- Also, it is recommended you use the @OverloadedStrings@
+-- extension to allow literal strings to be used as
+-- symbolic-strings when working with symbolic characters
+-- and strings.
+--
+-- 'SChar' type only covers all unicode characters, following the specification
+-- in <https://smt-lib.org/theories-UnicodeStrings.shtml>.
+-- However, some of the recognizers only support the Latin1 subset, suffixed
+-- by @L1@. The reason for this is that there is no performant way of performing
+-- these functions for the entire unicode set. As SMTLib's capabilities increase,
+-- we will provide full unicode versions as well.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE OverloadedLists   #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Char (
+        -- * Occurrence in a string
+        elem, notElem
+        -- * Conversion to\/from 'SInteger'
+        , ord, chr
+        -- * Conversion to upper\/lower case
+        , toLowerL1, toUpperL1
+        -- * Converting digits to ints and back
+        , digitToInt, intToDigit
+        -- * Character classification
+        , isControlL1, isSpaceL1, isLowerL1, isUpperL1, isAlphaL1, isAlphaNumL1, isPrintL1, isDigit, isOctDigit, isHexDigit
+        , isLetterL1, isMarkL1, isNumberL1, isPunctuationL1, isSymbolL1, isSeparatorL1
+        -- * Subranges
+        , isAscii, isLatin1, isAsciiUpper, isAsciiLower
+        ) where
+
+import Prelude hiding (elem, notElem, Enum(..))
+import qualified Prelude as P
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model
+
+import qualified Data.Char as C
+
+import Data.SBV.List (EnumSymbolic(..))
+import qualified Data.SBV.List as SL
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.List (isInfixOf)
+-- >>> import Prelude hiding(elem, notElem)
+-- >>> :set -XOverloadedLists
+-- >>> :set -XOverloadedStrings
+#endif
+
+-- | Is the character in the string?
+--
+-- >>> :set -XOverloadedStrings
+-- >>> prove $ \c -> c `elem` [c]
+-- Q.E.D.
+-- >>> prove $ \c -> sNot (c `elem` "")
+-- Q.E.D.
+elem :: SChar -> SString -> SBool
+c `elem` s
+ | Just cs <- unliteral s, Just cc <- unliteral c
+ = literal (cc `P.elem` cs)
+ | Just cs <- unliteral s                            -- If only the second string is concrete, element-wise checking is still much better!
+ = sAny (c .==) $ map literal cs
+ | True
+ = [c] `SL.isInfixOf` s
+
+-- | Is the character not in the string?
+--
+-- >>> prove $ \c s -> c `elem` s .<=> sNot (c `notElem` s)
+-- Q.E.D.
+notElem :: SChar -> SString -> SBool
+c `notElem` s = sNot (c `elem` s)
+
+-- | The 'ord' of a character.
+ord :: SChar -> SInteger
+ord c
+ | Just cc <- unliteral c
+ = literal (fromIntegral (C.ord cc))
+ | True
+ = SBV $ SVal KUnbounded $ Right $ cache r
+ where r st = do csv <- sbvToSV st c
+                 newExpr st KUnbounded (SBVApp (StrOp StrToCode) [csv])
+
+-- | Conversion from an integer to a character.
+--
+-- >>> prove $ \x -> 0 .<= x .&& x .< 256 .=> ord (chr x) .== x
+-- Q.E.D.
+-- >>> prove $ \x -> chr (ord x) .== x
+-- Q.E.D.
+chr :: SInteger -> SChar
+chr w
+ | Just cw <- unliteral w
+ = literal (C.chr (fromIntegral cw))
+ | True
+ = SBV $ SVal KChar $ Right $ cache r
+ where r st = do wsv <- sbvToSV st w
+                 newExpr st KChar (SBVApp (StrOp StrFromCode) [wsv])
+
+-- | Lift a char function to a symbolic version. If the given char is
+-- not in the class recognized by predicate, the output is the same as the input.
+-- Only works for the Latin1 set, i.e., the first 256 characters. If the given
+-- character is outside this range, it's returned unchanged.
+liftFunL1 :: (Char -> Char) -> SChar -> SChar
+liftFunL1 f c = walk kernel
+  where kernel = [g | g <- map C.chr [0 .. 255], g /= f g]
+        walk []     = c
+        walk (d:ds) = ite (literal d .== c) (literal (f d)) (walk ds)
+
+-- | Lift a char predicate to a symbolic version. Only works for the Latin1 set, i.e., the
+-- first 256 characters.
+liftPredL1 :: (Char -> Bool) -> SChar -> SBool
+liftPredL1 predicate c = c `sElem` [literal g | g <- map C.chr [0 .. 255], predicate g]
+
+-- | Convert to lower-case. Only works for the Latin1 subset, otherwise returns its argument unchanged.
+--
+-- >>> prove $ \c -> toLowerL1 (toLowerL1 c) .== toLowerL1 c
+-- Q.E.D.
+-- >>> prove $ \c -> isLowerL1 c .&& c `notElem` "\181\255" .=> toLowerL1 (toUpperL1 c) .== c
+-- Q.E.D.
+toLowerL1 :: SChar -> SChar
+toLowerL1 = liftFunL1 C.toLower
+
+-- | Convert to upper-case. Only works for the Latin1 subset, otherwise returns its argument unchanged.
+--
+-- >>> prove $ \c -> toUpperL1 (toUpperL1 c) .== toUpperL1 c
+-- Q.E.D.
+-- >>> prove $ \c -> isUpperL1 c .=> toUpperL1 (toLowerL1 c) .== c
+-- Q.E.D.
+toUpperL1 :: SChar -> SChar
+toUpperL1 = liftFunL1 C.toUpper
+
+-- | Convert a digit to an integer. Works for hexadecimal digits too. If the input isn't a digit,
+-- then return -1.
+--
+-- >>> prove $ \c -> isDigit c .|| isHexDigit c .=> digitToInt c .>= 0 .&& digitToInt c .<= 15
+-- Q.E.D.
+-- >>> prove $ \c -> sNot (isDigit c .|| isHexDigit c) .=> digitToInt c .== -1
+-- Q.E.D.
+digitToInt :: SChar -> SInteger
+digitToInt c = ite (uc `elem` "0123456789") (sFromIntegral (o - ord (literal '0')))
+             $ ite (uc `elem` "ABCDEF")     (sFromIntegral (o - ord (literal 'A') + 10))
+             $ -1
+  where uc = toUpperL1 c
+        o  = ord uc
+
+-- | Convert an integer to a digit, inverse of 'digitToInt'. If the integer is out of
+-- bounds, we return the arbitrarily chosen space character. Note that for hexadecimal
+-- letters, we return the corresponding lowercase letter.
+--
+-- >>> prove $ \i -> i .>= 0 .&& i .<= 15 .=> digitToInt (intToDigit i) .== i
+-- Q.E.D.
+-- >>> prove $ \i -> i .<  0 .|| i .>  15 .=> digitToInt (intToDigit i) .== -1
+-- Q.E.D.
+-- >>> prove $ \c -> digitToInt c .== -1 .<=> intToDigit (digitToInt c) .== literal ' '
+-- Q.E.D.
+intToDigit :: SInteger -> SChar
+intToDigit i = ite (i .>=  0 .&& i .<=  9) (chr (sFromIntegral i + ord (literal '0')))
+             $ ite (i .>= 10 .&& i .<= 15) (chr (sFromIntegral i + ord (literal 'a') - 10))
+             $ literal ' '
+
+-- | Is this a control character? Control characters are essentially the non-printing characters. Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isControlL1 :: SChar -> SBool
+isControlL1 = liftPredL1 C.isControl
+
+-- | Is this white-space? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isSpaceL1 :: SChar -> SBool
+isSpaceL1 = liftPredL1 C.isSpace
+
+-- | Is this a lower-case character? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- >>> prove $ \c -> isUpperL1 c .=> isLowerL1 (toLowerL1 c)
+-- Q.E.D.
+isLowerL1 :: SChar -> SBool
+isLowerL1 = liftPredL1 C.isLower
+
+-- | Is this an upper-case character? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- >>> prove $ \c -> sNot (isLowerL1 c .&& isUpperL1 c)
+-- Q.E.D.
+isUpperL1 :: SChar -> SBool
+isUpperL1 = liftPredL1 C.isUpper
+
+-- | Is this an alphabet character? That is lower-case, upper-case and title-case letters, plus letters of caseless scripts and modifiers letters.
+-- Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isAlphaL1 :: SChar -> SBool
+isAlphaL1 = liftPredL1 C.isAlpha
+
+-- | Is this an alphabetical character or a digit? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- >>> prove $ \c -> isAlphaNumL1 c .<=> isAlphaL1 c .|| isNumberL1 c
+-- Q.E.D.
+isAlphaNumL1 :: SChar -> SBool
+isAlphaNumL1 = liftPredL1 C.isAlphaNum
+
+-- | Is this a printable character? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isPrintL1 :: SChar -> SBool
+isPrintL1 = liftPredL1 C.isPrint
+
+-- | Is this an ASCII digit, i.e., one of @0@..@9@. Note that this is a subset of 'isNumberL1'.
+--
+-- >>> prove $ \c -> isDigit c .=> isNumberL1 c
+-- Q.E.D.
+isDigit :: SChar -> SBool
+isDigit = liftPredL1 C.isDigit
+
+-- | Is this an Octal digit, i.e., one of @0@..@7@.
+isOctDigit :: SChar -> SBool
+isOctDigit = liftPredL1 C.isOctDigit
+
+-- | Is this a Hex digit, i.e, one of @0@..@9@, @a@..@f@, @A@..@F@.
+--
+-- >>> prove $ \c -> isHexDigit c .=> isAlphaNumL1 c
+-- Q.E.D.
+isHexDigit :: SChar -> SBool
+isHexDigit = liftPredL1 C.isHexDigit
+
+-- | Is this an alphabet character. Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- >>> prove $ \c -> isLetterL1 c .<=> isAlphaL1 c
+-- Q.E.D.
+isLetterL1 :: SChar -> SBool
+isLetterL1 = liftPredL1 C.isLetter
+
+-- | Is this a mark? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- Note that there are no marks in the Latin1 set, so this function always returns false!
+--
+-- >>> prove $ sNot . isMarkL1
+-- Q.E.D.
+isMarkL1 :: SChar -> SBool
+isMarkL1 = liftPredL1 C.isMark
+
+-- | Is this a number character? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isNumberL1 :: SChar -> SBool
+isNumberL1 = liftPredL1 C.isNumber
+
+-- | Is this a punctuation mark? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isPunctuationL1 :: SChar -> SBool
+isPunctuationL1 = liftPredL1 C.isPunctuation
+
+-- | Is this a symbol? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+isSymbolL1 :: SChar -> SBool
+isSymbolL1 = liftPredL1 C.isSymbol
+
+-- | Is this a separator? Only works for the Latin1 subset, otherwise returns 'sFalse'.
+--
+-- >>> prove $ \c -> isSeparatorL1 c .=> isSpaceL1 c
+-- Q.E.D.
+isSeparatorL1 :: SChar -> SBool
+isSeparatorL1 = liftPredL1 C.isSeparator
+
+-- | Is this an ASCII character, i.e., the first 128 characters.
+isAscii :: SChar -> SBool
+isAscii c = ord c .< 128
+
+-- | Is this a Latin1 character?
+isLatin1 :: SChar -> SBool
+isLatin1 c = ord c .< 256
+
+-- | Is this an ASCII Upper-case letter? i.e., @A@ thru @Z@
+--
+-- >>> prove $ \c -> isAsciiUpper c .<=> ord c .>= ord (literal 'A') .&& ord c .<= ord (literal 'Z')
+-- Q.E.D.
+-- >>> prove $ \c -> isAsciiUpper c .<=> isAscii c .&& isUpperL1 c
+-- Q.E.D.
+isAsciiUpper :: SChar -> SBool
+isAsciiUpper = liftPredL1 C.isAsciiUpper
+
+-- | Is this an ASCII Lower-case letter? i.e., @a@ thru @z@
+--
+-- >>> prove $ \c -> isAsciiLower c .<=> ord c .>= ord (literal 'a') .&& ord c .<= ord (literal 'z')
+-- Q.E.D.
+-- >>> prove $ \c -> isAsciiLower c .<=> isAscii c .&& isLowerL1 c
+-- Q.E.D.
+isAsciiLower :: SChar -> SBool
+isAsciiLower = liftPredL1 C.isAsciiLower
+
+-- | Symbolic enum instance for symbolic characters
+instance EnumSymbolic Char where
+   succ     = smtFunction "EnumSymbolic.Char.succ"   (\x -> ite (x .== maxBound) (some "EnumSymbolic.Char.succ_maxBound" (const sTrue)) (chr (ord x + 1)))
+   pred     = smtFunction "EnumSymbolic.Char.pred"   (\x -> ite (x .== minBound) (some "EnumSymbolic.Char.pred_minBound" (const sTrue)) (chr (ord x - 1)))
+   toEnum   = smtFunction "EnumSymbolic.Char.toEnum" (\x ->
+                            ite (x .< ord (minBound :: SChar)) (some "EnumSymbolic.Char.toEnum.<minBound" (const sTrue))
+                          $ ite (x .> ord (maxBound :: SChar)) (some "EnumSymbolic.Char.toEnum.>maxBound" (const sTrue))
+                          $ chr x)
+
+   fromEnum = ord
+
+   enumFrom n   = SL.map chr (enumFromTo @Integer (ord n) (ord (maxBound @SChar)))
+   enumFromThen = smtFunction "EnumSymbolic.Char.enumFromThen" $ \n1 n2 ->
+                              let i_n1, i_n2 :: SInteger
+                                  i_n1 = ord n1
+                                  i_n2 = ord n2
+                              in SL.map chr (ite (i_n2 .>= i_n1)
+                                                 (enumFromThenTo i_n1 i_n2 (ord (maxBound @SChar)))
+                                                 (enumFromThenTo i_n1 i_n2 (ord (minBound @SChar))))
+
+   enumFromTo     n m   = SL.map chr (enumFromTo     @Integer (ord n) (ord m))
+   enumFromThenTo n m t = SL.map chr (enumFromThenTo @Integer (ord n) (ord m) (ord t))
diff --git a/Data/SBV/Client.hs b/Data/SBV/Client.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Client.hs
@@ -0,0 +1,777 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Client
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Cross-cutting toplevel client functions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DeriveLift          #-}
+{-# LANGUAGE LambdaCase          #-}
+{-# LANGUAGE PackageImports      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving  #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TupleSections       #-}
+
+#if MIN_VERSION_template_haskell(2,22,1)
+-- No need for newer versions of TH
+#else
+{-# LANGUAGE FlexibleInstances   #-}
+#endif
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Client
+  ( sbvCheckSolverInstallation
+  , defaultSolverConfig
+  , getAvailableSolvers
+  , mkSymbolic
+  , getConstructors
+  ) where
+
+import Data.SBV.Core.TH (getConstructors, bad, report)
+
+import Data.Generics
+
+import Control.Monad (filterM, mapAndUnzipM, zipWithM)
+import Data.Function (fix)
+import Test.QuickCheck (Arbitrary(..), elements)
+
+import qualified Control.Exception as C
+
+import Data.Char
+import Data.Word
+import Data.Int
+import Data.Ratio
+
+import qualified "template-haskell" Language.Haskell.TH        as TH
+import qualified "template-haskell" Language.Haskell.TH.Syntax as TH
+
+import Language.Haskell.TH.ExpandSyns as TH
+
+import Data.SBV.Core.Concrete (cvRank)
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Symbolic (registerKind)
+
+import Data.SBV.Provers.Prover
+import qualified Data.SBV.List as SL
+
+import Data.List (genericLength)
+
+import Data.SBV.TP.Kernel
+
+-- | Check whether the given solver is installed and is ready to go. This call does a
+-- simple call to the solver to ensure all is well.
+sbvCheckSolverInstallation :: SMTConfig -> IO Bool
+sbvCheckSolverInstallation cfg = check `C.catch` (\(_ :: C.SomeException) -> pure False)
+  where check = do ThmResult r <- proveWith cfg $ \x -> sNot (sNot x) .== (x :: SBool)
+                   case r of
+                     Unsatisfiable{} -> pure True
+                     _               -> pure False
+
+-- | The default configs corresponding to supported SMT solvers
+defaultSolverConfig :: Solver -> SMTConfig
+defaultSolverConfig ABC       = abc
+defaultSolverConfig Boolector = boolector
+defaultSolverConfig Bitwuzla  = bitwuzla
+defaultSolverConfig CVC4      = cvc4
+defaultSolverConfig CVC5      = cvc5
+defaultSolverConfig DReal     = dReal
+defaultSolverConfig MathSAT   = mathSAT
+defaultSolverConfig OpenSMT   = openSMT
+defaultSolverConfig Yices     = yices
+defaultSolverConfig Z3        = z3
+
+-- | Return the known available solver configs, installed on your machine.
+getAvailableSolvers :: IO [SMTConfig]
+getAvailableSolvers = filterM sbvCheckSolverInstallation (map defaultSolverConfig [minBound .. maxBound])
+
+#if MIN_VERSION_template_haskell(2,22,1)
+-- Starting template haskell 2.22.1 the following instances are automatically provided
+#else
+deriving instance TH.Lift TH.OccName
+deriving instance TH.Lift TH.NameSpace
+deriving instance TH.Lift TH.PkgName
+deriving instance TH.Lift TH.ModName
+deriving instance TH.Lift TH.NameFlavour
+deriving instance TH.Lift TH.Name
+deriving instance TH.Lift TH.Type
+deriving instance TH.Lift TH.Specificity
+deriving instance TH.Lift (TH.TyVarBndr TH.Specificity)
+deriving instance TH.Lift (TH.TyVarBndr ())
+deriving instance TH.Lift TH.TyLit
+#endif
+
+-- A few other things we need to TH lift
+deriving instance TH.Lift Kind
+
+data ADTKind = ADTUninterpreted -- Completely uninterpreted
+             | ADTEnum          -- Enumeration
+             | ADTFull          -- A full datatype
+
+-- | Create a mutually recursive group of ADTs.
+mkSymbolic :: [TH.Name] -> TH.Q [TH.Dec]
+mkSymbolic ts = concat <$> mapM mkSymbolicADT ts
+
+-- | Create a symbolic ADT.
+mkSymbolicADT :: TH.Name -> TH.Q [TH.Dec]
+mkSymbolicADT typeName = do
+
+     (tKind, params, cstrs) <- dissect typeName
+     ds <- mkADT tKind typeName params cstrs
+
+     -- declare an "undefiner" so we don't have stray names
+     nm <- TH.newName $ "_undefiner_" ++ TH.nameBase typeName
+     addDoc "Autogenerated definition to avoid unused-variable warnings from GHC." nm
+
+     -- undefiner must be careful in putting ascriptions
+     aVar <- TH.newName "a"
+     let undefine n
+           | base == "sCase" ++ tbase = wrap 1   -- Needs an extra param
+           | True                     = wrap 0
+           where tbase  = TH.nameBase typeName
+                 base   = TH.nameBase n
+                 wrap c = foldl TH.AppTypeE (TH.VarE n) (replicate (c + length params) (TH.ConT ''Integer))
+
+         names     = [undefine n | TH.FunD n _ <- ds]
+         body      = foldl TH.AppE (TH.VarE 'undefined)
+                                   (names ++ [TH.SigE (TH.VarE 'undefined)
+                                                      (foldl TH.AppT (TH.ConT (TH.mkName ('S' : TH.nameBase typeName)))
+                                                                     (map (const (TH.ConT ''Integer)) params))])
+
+         undefSig  = TH.SigD nm (TH.ForallT [] [] (TH.VarT aVar))
+         undefBody = TH.FunD nm [TH.Clause [] (TH.NormalB body) []]
+
+     pure $ ds ++ [undefSig, undefBody]
+
+-- | Add document to a generated declaration for the declaration
+addDeclDocs :: (TH.Name, String) -> [(TH.Name, String)] -> TH.Q ()
+addDeclDocs (tnm, ts) cnms = do add True (tnm, ts)
+                                mapM_  (add False) cnms
+   where add True  (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the type t'"        ++ cs ++ "'."
+         add False (cnm, cs) = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc cnm) $ "Symbolic version of the constructor v'" ++ cs ++ "'."
+
+-- | Add document to a generated function
+addDoc :: String -> TH.Name -> TH.Q ()
+addDoc what tnm = TH.addModFinalizer $ TH.putDoc (TH.DeclDoc tnm) what
+
+-- | Symbolic version of a type
+mkSBV :: TH.Type -> TH.Type
+mkSBV a = TH.ConT ''SBV `TH.AppT` a
+
+-- | Saturate the type with its parameters
+saturate :: TH.Type -> [TH.Name] -> TH.Type
+saturate t ps = foldr (\p b -> TH.AppT b (TH.VarT p)) t (reverse ps)
+
+-- | Create a symbolic ADT
+mkADT ::  ADTKind                                       -- What kind of ADT are we generating?
+       -> TH.Name                                       -- type name
+       -> [TH.Name]                                     -- parameters
+       -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -- constructors
+       -> TH.Q [TH.Dec]                                 -- declarations
+mkADT adtKind typeName params cstrs = do
+
+    let typeCon = saturate (TH.ConT typeName) params
+        sType   = mkSBV typeCon
+
+        inSymValContext = TH.ForallT [] [TH.AppT (TH.ConT ''SymVal) (TH.VarT n) | n <- params]
+
+        isEnum = case adtKind of
+                  ADTUninterpreted -> False
+                  ADTEnum          -> True
+                  ADTFull          -> False
+
+        -- Given Cstr f1 f2 f3, generate the clause:
+        --     inp@(Cstr [f1, f2, f3]) = case sequenceA [unlitCV (literal f1), unlitCV (literal f2), unlitCV (literal f3)] of
+        --                                 Just c  -> let k = kindOf inp
+        --                                            in SBV $ SVal k (Left (CV k (CADT (Cstr, c))))
+        --                                 Nothing -> sCstr (literal f1)
+        --
+        mkLitClause (n, fs) = do
+           as  <- mapM (const (TH.newName "a")) fs
+           inp <- TH.newName "inp"
+           c   <- TH.newName "c"
+
+           let app a b = [| $a (literal $b) |]
+
+           TH.clause [TH.asP inp (TH.conP n (map TH.varP as))]
+                     (TH.normalB
+                           (TH.caseE [| sequenceA $(TH.listE [ [| unlitCV (literal $(TH.varE a)) |] | a <- as ]) |]
+                                     [ TH.match [p|Just $(TH.varP c)|]
+                                                (TH.normalB [| let k = kindOf $(TH.varE inp)
+                                                               in SBV $ SVal k (Left (CV k (CADT (TH.nameBase n, $(TH.varE c)))))
+                                                            |])
+                                                []
+                                     , TH.match [p|Nothing|]
+                                                (TH.normalB (foldl app (TH.varE (TH.mkName ('s' : TH.nameBase n))) (map TH.varE as)))
+                                                []
+                                     ]))
+                     []
+
+    litFun <- case adtKind of
+                ADTUninterpreted -> do noLit <- [| error $ unlines [ "Data.SBV: unexpected call to derived literal implementation"
+                                                                   , "***"
+                                                                   , "*** Type: " ++ show typeName
+                                                                   , ""
+                                                                   , "***Please report this as a bug!"
+                                                                   ]
+                                                |]
+                                       pure $ TH.FunD 'literal [TH.Clause [TH.WildP] (TH.NormalB noLit) []]
+
+                ADTEnum          -> TH.FunD 'literal <$> mapM mkLitClause cstrs
+                ADTFull          -> TH.FunD 'literal <$> mapM mkLitClause cstrs
+
+    fromCVFunName <- TH.newName ("cv2" ++ TH.nameBase typeName)
+    addDoc ("Conversion from SMT values to " ++ TH.nameBase typeName ++ " values.") fromCVFunName
+
+    let fromCVSig = TH.SigD fromCVFunName
+                            (inSymValContext (foldr (TH.AppT . TH.AppT TH.ArrowT) typeCon
+                                                    [TH.ConT ''String, TH.AppT TH.ListT (TH.ConT ''CV)]))
+
+        fromCVCls :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q TH.Clause
+        fromCVCls (nm, args) = do
+            ns <- mapM (\(i, _) -> TH.newName ("a" ++ show i)) (zip [(1::Int)..] args)
+            let pat = foldr ((\p acc -> TH.ConP '(:) [] [p, acc]) . TH.VarP) (TH.ConP '[] [] []) ns
+            pure $ TH.Clause [TH.LitP (TH.StringL (TH.nameBase nm)), pat]
+                             (TH.NormalB (foldl TH.AppE (TH.ConE nm)
+                                                        [TH.AppE (TH.VarE 'fromCV) (TH.VarE n) | n <- ns]))
+                             []
+
+    catchAll <- do s <- TH.newName "s"
+                   l <- TH.newName "l"
+                   let errStr   = TH.LitE (TH.StringL ("fromCV " ++ TH.nameBase typeName ++ ": Unexpected constructor/arity: "))
+                       tup      = TH.TupE [Just (TH.VarE s), Just (TH.AppE (TH.VarE 'length) (TH.VarE l))]
+                       showCall = TH.AppE (TH.VarE 'show) tup
+                       errMsg   = TH.InfixE (Just errStr) (TH.VarE '(++)) (Just showCall)
+                   pure $ TH.Clause [TH.VarP s, TH.VarP l] (TH.NormalB (TH.AppE (TH.VarE 'error) errMsg)) []
+
+    fromCVFun <- do clss <- mapM fromCVCls cstrs
+                    pure $ TH.FunD fromCVFunName (clss ++ [catchAll])
+
+    getFromCV <- [| let unexpected w = error $ "fromCV: " ++ show typeName ++ ": " ++ w
+                        kindName (KADT n _ _) = n
+                        kindName (KApp n _)   = n
+                        kindName k            = unexpected $ "An ADT kind was expected, but got: " ++ show k
+                    in \case CV k (CADT (c, kvs)) | kindName k == unmod typeName
+                                                 -> $(TH.varE fromCVFunName) c (map (uncurry CV) kvs)
+                             CV k e -> unexpected $ "Was expecting a CADT value, but got kind: " ++ show k ++ " (rank: " ++ show (cvRank e) ++ ")"
+                 |]
+
+    symCtx  <- TH.cxt [TH.appT (TH.conT ''SymVal) (TH.varT n) | n <- params]
+
+    mmBound <- if isEnum
+                  then let universe     = [TH.conE con | (con, _) <- cstrs]
+                           (minb, maxb) = case (universe, reverse universe) of
+                                             (x:_, y:_) -> (x, y)
+                                             _          -> error $ "Impossible: Ran out of elements in determining bounds: " ++ show cstrs
+                       in [| Just ($minb, $maxb) |]
+                  else [| Nothing |]
+
+    -- make the initializer to get the subtypes registered
+    st <- TH.newName "_st"  -- Get an underscored name here, since st might go unused if there're no subtypes
+    register <- do let concretize b@TH.ConT{}     = b
+                       concretize TH.VarT{}       = TH.ConT ''Integer
+                       concretize (TH.AppT l arg) = TH.AppT (concretize l) (concretize arg)
+                       concretize r               = r
+
+                   end <- TH.noBindS [| pure () |]
+                   pure $ TH.DoE Nothing $ [TH.NoBindS (TH.AppE (TH.AppE (TH.VarE 'registerKind) (TH.VarE st))
+                                                                (TH.AppE (TH.VarE 'kindOf)
+                                                                         (TH.AppTypeE (TH.ConE 'Proxy) (concretize t))))
+                                           | (_, fts) <- cstrs, (_, t, KApp n _) <- fts, n /= TH.nameBase typeName
+                                           ] ++ [end]
+
+    let regFun = TH.FunD 'mkSymValInit [TH.Clause [TH.VarP st, TH.WildP] (TH.NormalB register) []]
+
+    let symVal = TH.InstanceD
+                      Nothing
+                      symCtx
+                      (TH.AppT (TH.ConT ''SymVal) typeCon)
+                      [ litFun
+                      , regFun
+                      , TH.FunD 'minMaxBound [TH.Clause [] (TH.NormalB mmBound)   []]
+                      , TH.FunD 'fromCV      [TH.Clause [] (TH.NormalB getFromCV) []]
+                       ]
+
+    defCstrs <- [| [(unmod n, map (\(_, _, t) -> t) ntks) | (n, ntks) <- cstrs] |]
+
+    kindCtx <- TH.cxt [TH.appT (TH.conT ''HasKind) (TH.varT p) | p <- params]
+
+    let mkPair a b = TH.TupE [Just a, Just b]
+        kindDef = foldl1 TH.AppE [ TH.ConE 'KADT
+                                 , TH.LitE (TH.StringL (unmod typeName))
+                                 , TH.ListE [ mkPair (TH.LitE (TH.StringL (TH.nameBase p)))
+                                                     (TH.AppE (TH.VarE 'kindOf) (TH.AppTypeE (TH.ConE 'Proxy) (TH.VarT p)))
+                                            | p <- params
+                                            ]
+                                 , defCstrs
+                                 ]
+
+        kindDecl = TH.InstanceD
+                        Nothing
+                        kindCtx
+                        (TH.AppT (TH.ConT ''HasKind) typeCon)
+                        [TH.FunD 'kindOf [TH.Clause [TH.WildP] (TH.NormalB kindDef) []]]
+
+    hasArbitrary <- TH.isInstance ''Arbitrary [typeCon]
+    arbDecl <- case () of
+                () | hasArbitrary -> pure []
+                   | isEnum       -> let universe  = TH.listE [TH.conE con | (con, _) <- cstrs]
+                                     in [d|instance Arbitrary $(pure typeCon) where
+                                             arbitrary = elements $universe
+                                        |]
+                   | True         -> [d|instance {-# OVERLAPPABLE #-} Arbitrary $(pure typeCon) where
+                                          arbitrary = error $ unlines [ ""
+                                                                      , "*** Data.SBV: Cannot quickcheck the given property."
+                                                                      , "***"
+                                                                      , "*** Default arbitrary instance for " ++ TH.nameBase typeName ++ " is too limited."
+                                                                      , "***"
+                                                                      , "*** You can overcome this by giving your own Arbitrary instance."
+                                                                      , "*** Please get in touch if this workaround is not suitable for your case."
+                                                                      ]
+                                    |]
+
+    -- Declare constructors
+    let declConstructor :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q ((TH.Name, String), [TH.Dec])
+        declConstructor (n, ntks) = do
+            let ats = map (mkSBV . (\(_, t, _) -> t)) ntks
+                ty  = inSymValContext $ foldr (TH.AppT . TH.AppT TH.ArrowT) sType ats
+                bnm = TH.nameBase n
+                nm  = TH.mkName $ 's' : bnm
+
+            as    <- mapM (const (TH.newName "a")) ntks
+            c     <- TH.newName "c"
+
+            cls <- TH.clause (map TH.varP as)
+                             (TH.normalB
+                                   (TH.caseE [| sequenceA $(TH.listE [ [| unlitCV $(TH.varE a) |] | a <- as ]) |]
+                                             [ TH.match [p|Just $(TH.varP c)|]
+                                                        -- We need the kind of the result type to build the value, but the
+                                                        -- result type can only be recovered from the (signature-pinned) result
+                                                        -- itself: a parametric type may carry the parameter in a phantom
+                                                        -- position (e.g. the @a@ in @Right :: b -> Either a b@) that no argument
+                                                        -- mentions. We tie the kind to the result via 'fix'. Crucially, 'fix'
+                                                        -- binds @res@ as a /lambda-bound/ variable, which is always monomorphic;
+                                                        -- a plain @let@ group would be generalized when the monomorphism
+                                                        -- restriction is off (as it is at the GHCi prompt), yielding a spurious
+                                                        -- ambiguous @HasKind@. ('kindOf' ignores its argument, so 'fix' is safe.)
+                                                        (TH.normalB [| fix (\res -> let k = kindOf res
+                                                                                    in SBV $ SVal k (Left (CV k (CADT (bnm, $(TH.varE c)))))) |])
+                                                        []
+                                             , TH.match [p|Nothing|]
+                                                        (TH.normalB (foldl (\a b -> [| $a $b |]) [| mkADTConstructor bnm |] (map TH.varE as)))
+                                                        []
+                                             ]))
+                             []
+
+            pure ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]])
+
+    (constrNames, cdecls) <- mapAndUnzipM declConstructor cstrs
+
+    let btname = TH.nameBase typeName
+        tname  = TH.mkName ('S' : btname)
+        tdecl  = TH.TySynD tname [TH.PlainTV p TH.BndrReq | p <- params] sType
+
+    addDeclDocs (tname, btname) constrNames
+
+    -- Declare accessors
+    let -- NB. field count starts at 1!
+        declAccessor :: TH.Name -> (Maybe TH.Name, TH.Type, Kind) -> Int -> TH.Q [((TH.Name, String), [TH.Dec])]
+        declAccessor c (mbUN, ft, _) i = do
+                let bnm  = TH.nameBase c
+                    anm  = "get" ++ bnm ++ "_" ++ show i
+                    nm   = TH.mkName anm
+                    ty    = inSymValContext $ TH.AppT (TH.AppT TH.ArrowT sType) (mkSBV ft)
+
+                cls <- do inp <- TH.newName "inp"
+                          TH.clause [TH.varP inp]
+                                    (TH.normalB
+                                          (TH.caseE [| unlitCV $(TH.varE inp) |]
+                                                    [ TH.match [p|Just (_, CADT (got, kv))|]
+                                                               (TH.guardedB [do g <- TH.normalG [| got == bnm |]
+                                                                                e <- [| let (k, v) = (kv !! (i-1))
+                                                                                        in SBV $ SVal k (Left (CV k v))
+                                                                                     |]
+                                                                                pure (g, e)
+                                                                            ])
+                                                               []
+                                                    , TH.match [p|_|]
+                                                               (TH.normalB [| mkADTAccessor anm $(TH.varE inp) |])
+                                                               []
+                                                    ]))
+                                    []
+
+                -- If there's a custom accessor given, declare that here too
+                extras <- case mbUN of
+                            Nothing -> pure []
+                            Just un -> do let sun = TH.mkName $ 's' : TH.nameBase un
+                                          pure [((sun, bnm), [TH.SigD sun ty, TH.FunD sun [cls]])]
+
+                pure $ ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]]) : extras
+
+    allDefs <- sequence [zipWithM (declAccessor c) fs [(1::Int) ..] | (c, fs) <- cstrs]
+    let (accessorNames, accessorDecls) = unzip $ concat (concat allDefs)
+
+    mapM_ (addDoc "Field accessor function." . fst) accessorNames
+
+    testerDecls <- mkTesters sType inSymValContext cstrs
+
+    -- Get the case analyzer
+    caseSigFuns <- mkCaseAnalyzer adtKind typeName params cstrs
+
+    -- Get the induction schema, upto 5 extra args. Only for enums and adts
+    indDecs <- do let schemas = mapM (mkInductionSchema typeName params cstrs) [0 .. 5]
+                  case adtKind of
+                    ADTUninterpreted -> pure []
+                    ADTEnum          -> schemas
+                    ADTFull          -> schemas
+
+    -- If this is an enumeration get EnumSymbolic and OrSymbolic instances
+    symEnum <- case adtKind of
+                ADTUninterpreted -> pure []
+                ADTFull          -> pure []
+                ADTEnum          ->
+                  let universe  = TH.listE [TH.conE                          con   | (con, _) <- cstrs]
+                      universeS = TH.listE [TH.litE (TH.stringL (TH.nameBase con)) | (con, _) <- cstrs]
+                  in [d| instance SatModel $(TH.conT typeName) where
+                           parseCVs (CV _ (CADT (s, [])) : r)
+                             | Just v <- s `lookup` zip $universeS $universe
+                             = Just (v, r)
+                           parseCVs _ = Nothing
+
+                         instance SL.EnumSymbolic $(TH.conT typeName) where
+                           succ x = go (zip $universe (drop 1 $universe))
+                             where go []              = some ("succ_" ++ show typeName ++ "_maximal") (const sTrue)
+                                   go ((c, s) : rest) = ite (x .== literal c) (literal s) (go rest)
+
+                           pred x = go (zip (drop 1 $universe) $universe)
+                             where go []              = some ("pred_" ++ show typeName ++ "_minimal") (const sTrue)
+                                   go ((c, s) : rest) = ite (x .== literal c) (literal s) (go rest)
+
+                           toEnum x = go (zip $universe [0..])
+                             where go []              = some ("toEnum_" ++ show typeName ++ "_out_of_range") (const sTrue)
+                                   go ((c, i) : rest) = ite (x .== literal i) (literal c) (go rest)
+
+                           fromEnum x = go 0 $universe
+                             where go _ []     = error "fromEnum: Impossible happened, ran out of elements."
+                                   go i [_]    = i
+                                   go i (c:cs) = ite (x .== literal c) i (go (i+1) cs)
+
+                           enumFrom n = SL.map SL.toEnum (SL.enumFromTo (SL.fromEnum n) (genericLength $universe - 1))
+
+                           enumFromThen = smtFunction ("EnumSymbolic." ++ TH.nameBase typeName ++ ".enumFromThen") $ \n1 n2 ->
+                                                      let i_n1, i_n2 :: SInteger
+                                                          i_n1 = SL.fromEnum n1
+                                                          i_n2 = SL.fromEnum n2
+                                                      in SL.map SL.toEnum (ite (i_n2 .>= i_n1)
+                                                                               (SL.enumFromThenTo i_n1 i_n2 (genericLength $universe - 1))
+                                                                               (SL.enumFromThenTo i_n1 i_n2 0))
+
+                           enumFromTo     n m   = SL.map SL.toEnum (SL.enumFromTo     (SL.fromEnum n) (SL.fromEnum m))
+
+                           enumFromThenTo n m t = SL.map SL.toEnum (SL.enumFromThenTo (SL.fromEnum n) (SL.fromEnum m) (SL.fromEnum t))
+
+                         instance OrdSymbolic (SBV $(TH.conT typeName)) where
+                           a .<  b = SL.fromEnum a .<  SL.fromEnum b
+                           a .<= b = SL.fromEnum a .<= SL.fromEnum b
+                           a .>  b = SL.fromEnum a .>  SL.fromEnum b
+                           a .>= b = SL.fromEnum a .>= SL.fromEnum b
+                     |]
+
+    pure $  [tdecl, symVal, kindDecl]
+         ++ arbDecl
+         ++ concat cdecls
+         ++ testerDecls
+         ++ concat accessorDecls
+         ++ symEnum
+         ++ [fromCVSig, fromCVFun]
+         ++ caseSigFuns
+         ++ concat indDecs
+
+-- | Make a case analyzer for the type. Works for ADTs and enums. Returns sig and defn
+mkCaseAnalyzer :: ADTKind -> TH.Name -> [TH.Name] -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> TH.Q [TH.Dec]
+mkCaseAnalyzer kind typeName params cstrs = case kind of
+                                              ADTUninterpreted -> pure [] -- no case analyzer for fully uninterpreted types
+                                              ADTEnum          -> mk
+                                              ADTFull          -> mk
+  where mk = do let typeCon = saturate (TH.ConT typeName) params
+                    sType   = mkSBV typeCon
+
+                    bnm = TH.nameBase typeName
+                    cnm = TH.mkName $ "sCase" ++ bnm
+
+                se   <- TH.newName ('s' : bnm)
+                fs   <- mapM (\(nm, _) -> TH.newName ('f' : TH.nameBase nm)) cstrs
+                res  <- TH.newName "result"
+
+                let def = TH.FunD cnm [TH.Clause (map TH.VarP (fs ++ [se])) (TH.NormalB (iteChain (zipWith (mkCase se) fs cstrs))) []]
+
+                    iteChain :: [(TH.Exp, TH.Exp)] -> TH.Exp
+                    iteChain []       = error $ unlines [ "Data.SBV.mkADT: Impossible happened!"
+                                                        , ""
+                                                        , "   Received an empty list for: " ++ show typeName
+                                                        , ""
+                                                        , "While building the case-analyzer."
+                                                        , "Please report this as a bug."
+                                                        ]
+                    iteChain [(_, l)]        = l
+                    iteChain ((t, e) : rest) = foldl TH.AppE (TH.VarE 'ite) [TH.AppE t (TH.VarE se), e, iteChain rest]
+
+                    mkCase :: TH.Name -> TH.Name -> (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> (TH.Exp, TH.Exp)
+                    mkCase cexpr func (c, fields) = (TH.VarE (TH.mkName ("is" ++ TH.nameBase c)), foldl TH.AppE (TH.VarE func) args)
+                       where getters = [TH.mkName ("get" ++ TH.nameBase c ++ "_" ++ show i) | (i, _) <- zip [(1 :: Int) ..] fields]
+                             args    = map (\g -> TH.AppE (TH.VarE g) (TH.VarE cexpr)) getters
+
+                    rvar   = TH.VarT res
+                    mkFun  = foldr (TH.AppT . TH.AppT TH.ArrowT) rvar
+                    fTypes = [mkFun (map (mkSBV . (\(_, t, _) -> t)) ftks) | (_, ftks) <- cstrs]
+                    sig    = TH.SigD cnm (TH.ForallT []
+                                                     (TH.AppT (TH.ConT ''Mergeable) (TH.VarT res)
+                                                     : [TH.AppT (TH.ConT ''SymVal) (TH.VarT p) | p <- params]
+                                                     )
+                                                     (mkFun (fTypes ++ [sType])))
+
+                addDoc ("Case analyzer for the type " ++ bnm ++ ".") cnm
+                pure [sig, def]
+
+-- | Declare testers
+mkTesters :: TH.Type -> (TH.Type -> TH.Type) -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> TH.Q [TH.Dec]
+mkTesters sType inSymValContext cstrs = do
+    let declTester :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q ((TH.Name, String), [TH.Dec])
+        declTester (c, _) = do
+             let ty  = inSymValContext $ TH.AppT (TH.AppT TH.ArrowT sType) (TH.ConT ''SBool)
+                 bnm = TH.nameBase c
+                 nm  = TH.mkName $ "is" ++ bnm
+
+             inp <- TH.newName "inp"
+             cls <- TH.clause [TH.varP inp]
+                              (TH.normalB
+                                    (TH.caseE [| unlitCV $(TH.varE inp) |]
+                                              [ TH.match [p|Just (_, CADT (got, _))|]
+                                                         (TH.normalB [| literal (got == bnm) |])
+                                                         []
+                                              , TH.match [p|Nothing|]
+                                                         (TH.normalB [| mkADTTester ("is-" ++ bnm) $(TH.varE inp) |])
+                                                         []
+                                              ]))
+                              []
+             pure ((nm, bnm), [TH.SigD nm ty, TH.FunD nm [cls]])
+
+    (testerNames, testerDecls) <- mapAndUnzipM declTester cstrs
+
+    mapM_ (addDoc "Field recognizer predicate." . fst) testerNames
+
+    pure $ concat testerDecls
+
+-- We'll just drop the modules to keep this simple
+-- If you use multiple expressions named the same (coming from different modules), oh well.
+unmod :: TH.Name -> String
+unmod = reverse . takeWhile (/= '.') . reverse . show
+
+-- | Given a type name, determine what kind of a data-type it is.
+dissect :: TH.Name -> TH.Q (ADTKind, [TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])])
+dissect typeName = do
+        (args, tcs) <- getConstructors typeName
+
+        let mk n (mbfn, t) = do k <- expandSyns t >>= toSBV typeName n
+                                pure (mbfn, t, k)
+
+        cs <- mapM (\(n, ts) -> (n,) <$> mapM (mk n) ts) tcs
+
+        let k | null cs             = ADTUninterpreted
+              | all (null . snd) cs = ADTEnum
+              | True                = ADTFull
+
+        pure (k, args, cs)
+
+-- | Find the SBV kind for this type
+toSBV :: TH.Name -> TH.Name -> TH.Type -> TH.Q Kind
+toSBV typeName constructorName = go
+  where hasArrows (TH.AppT TH.ArrowT _)   = True
+        hasArrows (TH.AppT lhs       rhs) = hasArrows lhs || hasArrows rhs
+        hasArrows _                       = False
+
+        -- Handle type variables (parameters)
+        go (TH.VarT v) = pure $ KVar (TH.nameBase v)
+
+        -- tuples
+        go t | Just ps <- getTuple t = KTuple <$> mapM go ps
+
+        -- recognize strings, since we don't (yet) support chars
+        go (TH.AppT TH.ListT (TH.ConT t)) | t == ''Char = pure KString
+
+        -- lists
+        go (TH.AppT TH.ListT t) = KList <$> go t
+
+        -- arbitrary words/ints
+        go (TH.AppT (TH.ConT nm) (TH.LitT (TH.NumTyLit n)))
+            | nm == ''WordN = pure $ KBounded False (fromIntegral n)
+            | nm == ''IntN  = pure $ KBounded True  (fromIntegral n)
+
+        -- arbitrary floats
+        go (TH.AppT (TH.AppT (TH.ConT nm) (TH.LitT (TH.NumTyLit eb))) (TH.LitT (TH.NumTyLit sb)))
+            | nm == ''FloatingPoint = pure $ KFP (fromIntegral eb) (fromIntegral sb)
+
+        -- Rational
+        go (TH.AppT (TH.ConT nm) (TH.ConT i))
+            | nm == ''Ratio && i == ''Integer
+            = pure KRational
+
+        -- deal with base types
+        go t@(TH.ConT constr)
+            | Just base <- getBase constr
+            = case base of
+                Left (w, r) -> bad w $ [ "Datatype   : " ++ show typeName
+                                       , "Constructor: " ++ show constructorName
+                                       , "Kind       : " ++ TH.pprint t
+                                       , ""
+                                       ] ++ r
+                Right k     -> pure k
+
+        -- deal with constructors
+        go t
+           | Just (c, ps) <- getConApp t
+           = KApp (TH.nameBase c) <$> mapM go ps
+
+        -- giving up
+        go t = bad "Unsupported constructor kind" [ "Datatype   : " ++ TH.nameBase typeName
+                                                  , "Constructor: " ++ TH.nameBase constructorName
+                                                  , "Kind       : " ++ TH.pprint t
+                                                  , ""
+                                                  , if hasArrows t
+                                                    then "Higher order fields (i.e., function values) are not supported."
+                                                    else report
+                                                  ]
+
+        -- Extract application of a constructor to some type-variables
+        getConApp t = locate t []
+          where locate (TH.ConT c)     sofar = Just (c, sofar)
+                locate (TH.AppT l arg) sofar = locate l (arg : sofar)
+                locate _               _     = Nothing
+
+        -- Extract an N-tuple
+        getTuple = tup []
+          where tup sofar (TH.TupleT _) = Just sofar
+                tup sofar (TH.AppT t p) = tup (p : sofar) t
+                tup _     _             = Nothing
+
+        -- Given the name of a base type, what's the equivalent in the SBV domain (if we have it)
+        getBase :: TH.Name -> Maybe (Either (String, [String]) Kind)
+        getBase t
+          | t == ''Bool     = Just $ Right KBool
+          | t == ''Integer  = Just $ Right KUnbounded
+          | t == ''Float    = Just $ Right KFloat
+          | t == ''Double   = Just $ Right KDouble
+          | t == ''Char     = Just $ Right KChar
+          | t == ''String   = Just $ Right KString
+          | t == ''AlgReal  = Just $ Right KReal
+          | t == ''Rational = Just $ Right KRational
+          | t == ''Word8    = Just $ Right $ KBounded False  8
+          | t == ''Word16   = Just $ Right $ KBounded False 16
+          | t == ''Word32   = Just $ Right $ KBounded False 32
+          | t == ''Word64   = Just $ Right $ KBounded False 64
+          | t == ''Int8     = Just $ Right $ KBounded True   8
+          | t == ''Int16    = Just $ Right $ KBounded True  16
+          | t == ''Int32    = Just $ Right $ KBounded True  32
+          | t == ''Int64    = Just $ Right $ KBounded True  64
+
+          -- Platform specific, flag:
+          |    t == ''Int
+            || t == ''Word  = Just $ Left ( "Platform specific type: " ++ show t
+                                          , [ "Please pick a more specific type, such as"
+                                            , "Integer, Word8, WordN 32, IntN 16 etc."
+                                            ])
+
+          -- Otherwise, can't translate
+          | True            = Nothing
+
+-- | Make an induction schema for the type, with n extra arguments.
+mkInductionSchema :: TH.Name -> [TH.Name] -> [(TH.Name, [(Maybe TH.Name, TH.Type, Kind)])] -> Int -> TH.Q [TH.Dec]
+mkInductionSchema typeName params cstrs extraArgCnt = do
+   let btype = TH.nameBase typeName
+       nm    = "induct" ++ btype ++ if extraArgCnt == 0 then "" else show extraArgCnt
+
+   pf <- TH.newName "pf"
+
+   extraNames <- mapM (const (TH.newName "extraN")) [0 .. extraArgCnt-1]
+   extraSyms  <- mapM (const (TH.newName "extraS")) [0 .. extraArgCnt-1]
+   extraTypes <- mapM (const (TH.newName "extraT")) [0 .. extraArgCnt-1]
+
+   let mkLam = TH.lamE . map (\a -> TH.conP 'Forall [TH.varP a])
+
+   let mkIndCase :: (TH.Name, [(Maybe TH.Name, TH.Type, Kind)]) -> TH.Q TH.Exp
+       mkIndCase (cstr, flds)
+         | null flds && null extraNames
+         = [| $(TH.varE pf) $(scstr) |]
+         | True
+         = do as <- mapM (const (TH.newName "a")) flds
+              let -- When can we have the inductive hypothesis?
+                  --  (1) same type
+                  --  (2) applied at exactly the same types
+                  isRecursive (_, _, k) = case k of
+                                            KApp t ps -> t == btype && ps == map (KVar . TH.nameBase) params
+                                            _         -> False
+                  recFields = [a | (a, f) <- zip as flds, isRecursive f]
+
+              TH.appE (TH.varE 'quantifiedBool)
+                      (mkLam (as ++ extraNames)
+                             (mkImp recFields (foldl TH.appE
+                                                     (TH.appE (TH.varE pf) (foldl TH.appE scstr (map TH.varE as)))
+                                                     (map TH.varE extraNames))))
+         where cnm   = TH.nameBase cstr
+               lcnm  = map toLower cnm
+               scstr = TH.varE (TH.mkName ('s' : cnm))
+
+               mkImp []  e = e
+               mkImp [i] e = foldl1 TH.appE [TH.varE '(.=>), assume i, e]
+               mkImp is  e = foldl1 TH.appE [TH.varE '(.=>), foldl1 TH.appE [TH.varE 'sAnd, TH.listE (map assume is)], e]
+
+               assume :: TH.Name -> TH.Q TH.Exp
+               assume n = do en <- mapM (const (TH.newName (lcnm ++ "_extraN"))) [0 .. extraArgCnt-1]
+                             TH.appE (TH.varE 'quantifiedBool)
+                                     (mkLam en (foldl TH.appE (TH.varE pf) (map TH.varE (n : en))))
+
+   cases <- mapM mkIndCase cstrs
+   post  <- do a <- TH.newName "recVal"
+               TH.appE (TH.varE 'quantifiedBool)
+                       (mkLam (a : extraNames) $ foldl TH.appE (TH.varE pf) (map TH.varE (a : extraNames)))
+
+   propName <- TH.newName "prop"
+   argName  <- TH.newName "a"
+   taName   <- TH.newName "ta"
+
+   let pre    = foldl1 TH.AppE [TH.VarE 'sAnd,  TH.ListE cases]
+       schema = foldl1 TH.AppE [TH.VarE '(.=>), pre, post]
+       ihB    = TH.AppE (TH.VarE 'proofOf) (foldl1 TH.AppE [TH.VarE 'internalAxiom, TH.LitE (TH.StringL nm), schema])
+
+       instHead = TH.AppT (TH.ConT ''HasInductionSchema)
+                          (foldr (TH.AppT . TH.AppT TH.ArrowT)
+                                 (TH.ConT ''SBool)
+                                 [  TH.AppT (TH.ConT ''Forall) (TH.VarT es) `TH.AppT` et
+                                  | (es, et) <- zip (taName : extraSyms)
+                                                    (saturate (TH.ConT typeName) params : map TH.VarT extraTypes)
+                                 ])
+
+       pfFun = TH.FunD pf [TH.Clause (map TH.VarP (argName : extraNames))
+                                     (TH.NormalB (foldl TH.AppE
+                                                        (TH.VarE propName)
+                                                        [TH.AppE (TH.ConE 'Forall) (TH.VarE a) | a <- argName : extraNames]))
+                                     []
+                          ]
+
+       method = TH.FunD 'inductionSchema
+                        [TH.Clause [TH.VarP propName]
+                                   (TH.NormalB (TH.LetE [pfFun] ihB))
+                                   []
+                        ]
+
+   context <- TH.cxt [TH.appT (TH.conT ''SymVal) (TH.varT n) | n <- params ++ extraTypes]
+
+   pure [TH.InstanceD Nothing context instHead [method]]
diff --git a/Data/SBV/Client/BaseIO.hs b/Data/SBV/Client/BaseIO.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Client/BaseIO.hs
@@ -0,0 +1,855 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Client.BaseIO
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Monomorphized versions of functions for simplified client use via
+-- @Data.SBV@, where we restrict the underlying monad to be IO.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NamedFieldPuns   #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Client.BaseIO where
+
+import Data.SBV.Core.Data      (Kind, Outputtable, Penalty,
+                                SymVal, SBool, SBV, SChar, SDouble, SFloat, SWord, SInt,
+                                SFPHalf, SFPBFloat, SFPSingle, SFPDouble, SFPQuad, SFloatingPoint,
+                                SInt8, SInt16, SInt32, SInt64, SInteger, SList,
+                                SReal, SString, SV, SWord8, SWord16, SWord32,
+                                SWord64, SRational, SSet, SArray, constrain, (.==))
+import Data.SBV.Core.Kind      (BVIsNonZero, ValidFloat)
+import Data.SBV.Core.Model     (Metric(..), SymTuple)
+import Data.SBV.Core.Symbolic  (Objective, OptimizeStyle, Result, VarContext, Symbolic, SBVRunMode, SMTConfig,
+                                SVal, symbolicEnv, rPartitionVars, State(..))
+import Data.SBV.Control.Types  (SMTOption)
+import Data.SBV.Provers.Prover (Provable, Satisfiable, SExecutable, ThmResult)
+import Data.SBV.SMT.SMT        (AllSatResult, SafeResult, SatResult, OptimizeResult)
+
+import GHC.TypeLits (KnownNat)
+
+import Data.IORef(readIORef, modifyIORef')
+
+import qualified Data.SBV.Core.Data      as Trans
+import qualified Data.SBV.Core.Model     as Trans
+import qualified Data.SBV.Core.Symbolic  as Trans
+import qualified Data.SBV.Provers.Prover as Trans
+
+import Control.Monad.Trans (liftIO)
+
+-- | Prove a predicate, using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.prove'
+prove :: Provable a => a -> IO ThmResult
+prove = Trans.prove
+
+-- | Prove the predicate using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.proveWith'
+proveWith :: Provable a => SMTConfig -> a -> IO ThmResult
+proveWith = Trans.proveWith
+
+-- | Prove a predicate with delta-satisfiability, using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.prove'
+dprove :: Provable a => a -> IO ThmResult
+dprove = Trans.dprove
+
+-- | Prove the predicate with delta-satisfiability using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.proveWith'
+dproveWith :: Provable a => SMTConfig -> a -> IO ThmResult
+dproveWith = Trans.dproveWith
+
+-- | Find a satisfying assignment for a predicate, using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sat'
+sat :: Satisfiable a => a -> IO SatResult
+sat = Trans.sat
+
+-- | Find a satisfying assignment using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.satWith'
+satWith :: Satisfiable a => SMTConfig -> a -> IO SatResult
+satWith = Trans.satWith
+
+-- | Find a delta-satisfying assignment for a predicate, using the default solver for delta-satisfiability.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.dsat'
+dsat :: Satisfiable a => a -> IO SatResult
+dsat = Trans.dsat
+
+-- | Find a satisfying assignment using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.satWith'
+dsatWith :: Satisfiable a => SMTConfig -> a -> IO SatResult
+dsatWith = Trans.dsatWith
+
+-- | Find all satisfying assignments, using the default solver.
+-- Equivalent to @'allSatWith' 'Data.SBV.defaultSMTCfg'@. See 'allSatWith' for details.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.allSat'
+allSat :: Satisfiable a => a -> IO AllSatResult
+allSat = Trans.allSat
+
+-- | Return all satisfying assignments for a predicate.
+-- Note that this call will block until all satisfying assignments are found. If you have a problem
+-- with infinitely many satisfying models (consider 'SInteger') or a very large number of them, you
+-- might have to wait for a long time. To avoid such cases, use the 'Data.SBV.Core.Symbolic.allSatMaxModelCount'
+-- parameter in the configuration.
+--
+-- NB. Uninterpreted constant/function values and counter-examples for array values are ignored for
+-- the purposes of 'allSat'. That is, only the satisfying assignments modulo uninterpreted functions and
+-- array inputs will be returned. This is due to the limitation of not having a robust means of getting a
+-- function counter-example back from the SMT solver.
+--  Find all satisfying assignments using the given SMT-solver
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.allSatWith'
+allSatWith :: Satisfiable a => SMTConfig -> a -> IO AllSatResult
+allSatWith = Trans.allSatWith
+
+-- | Optimize a given collection of `Objective`s.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.optimize'
+optimize :: Satisfiable a => OptimizeStyle -> a -> IO OptimizeResult
+optimize = Trans.optimize
+
+-- | Optimizes the objectives using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.optimizeWith'
+optimizeWith :: Satisfiable a => SMTConfig -> OptimizeStyle -> a -> IO OptimizeResult
+optimizeWith = Trans.optimizeWith
+
+-- | Check if the constraints given are consistent in a prove call using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isVacuousProof'
+isVacuousProof :: Provable a => a -> IO Bool
+isVacuousProof = Trans.isVacuousProof
+
+-- | Determine if the constraints are vacuous in a SAT call using the given SMT-solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isVacuousProofWith'
+isVacuousProofWith :: Provable a => SMTConfig -> a -> IO Bool
+isVacuousProofWith = Trans.isVacuousProofWith
+
+-- | Checks theoremhood using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isTheorem'
+isTheorem :: Provable a => a -> IO Bool
+isTheorem = Trans.isTheorem
+
+-- | Check whether a given property is a theorem.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isTheoremWith'
+isTheoremWith :: Provable a => SMTConfig -> a -> IO Bool
+isTheoremWith = Trans.isTheoremWith
+
+-- | Checks satisfiability using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isSatisfiable'
+isSatisfiable :: Satisfiable a => a -> IO Bool
+isSatisfiable = Trans.isSatisfiable
+
+-- | Check whether a given property is satisfiable.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.isSatisfiableWith'
+isSatisfiableWith :: Satisfiable a => SMTConfig -> a -> IO Bool
+isSatisfiableWith = Trans.isSatisfiableWith
+
+-- | Run an arbitrary symbolic computation, equivalent to @'runSMTWith' 'Data.SBV.defaultSMTCfg'@
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.runSMT'
+runSMT :: Symbolic a -> IO a
+runSMT = Trans.runSMT
+
+-- | Runs an arbitrary symbolic computation, exposed to the user in SAT mode
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.runSMTWith'
+runSMTWith :: SMTConfig -> Symbolic a -> IO a
+runSMTWith = Trans.runSMTWith
+
+-- | Create an argument for a name used in a safety-checking call.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sName_'
+sName :: SExecutable IO a => a -> Symbolic ()
+sName = Trans.sName
+
+-- | Check safety using the default solver.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.safe'
+safe :: SExecutable IO a => a -> IO [SafeResult]
+safe = Trans.safe
+
+-- | Check if any of the 'Data.SBV.sAssert' calls can be violated.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.safeWith'
+safeWith :: SExecutable IO a => SMTConfig -> a -> IO [SafeResult]
+safeWith = Trans.safeWith
+
+-- Data.SBV.Core.Data:
+
+-- | Create a symbolic variable.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.mkSymSBV'
+mkSymSBV :: VarContext -> Kind -> Maybe String -> Symbolic (SBV a)
+mkSymSBV = Trans.mkSymSBV
+
+-- | Convert a symbolic value to an SV, inside the Symbolic monad
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sbvToSymSV'
+sbvToSymSV :: SBV a -> Symbolic SV
+sbvToSymSV = Trans.sbvToSymSV
+
+-- | Mark an interim result as an output. Useful when constructing Symbolic programs
+-- that return multiple values, or when the result is programmatically computed.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.output'
+output :: Outputtable a => a -> Symbolic a
+output = Trans.output
+
+-- | Create a partitioning constraint, for all-sat calls.
+allSatPartition :: SymVal a => String -> SBV a -> Symbolic ()
+allSatPartition nm term = do
+   State{rPartitionVars} <- symbolicEnv
+
+   -- Generate a unique variable with the prefix nm if necessary and
+   -- add it to partitions
+   fresh <- liftIO $ do olds <- readIORef rPartitionVars
+                        let new = case filter (`notElem` olds) (nm : [nm ++ "_" ++ show i | i <- [(1 :: Int) ..]]) of
+                                    h:_ -> h
+                                    []  -> error $ "Impossible: Can't get a fresh variable from infinite list in partition." ++ show (nm, term)
+                        modifyIORef' rPartitionVars (++ [new])
+                        pure new
+
+   -- declare and constrain
+   v <- free fresh
+   constrain $ v .== term
+
+-- | Create a free variable, universal in a proof, existential in sat
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.free'
+free :: SymVal a => String -> Symbolic (SBV a)
+free = Trans.free
+
+-- | Create an unnamed free variable, universal in proof, existential in sat
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.free_'
+free_ :: SymVal a => Symbolic (SBV a)
+free_ = Trans.free_
+
+-- | Create a bunch of free vars
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.mkFreeVars'
+mkFreeVars :: SymVal a => Int -> Symbolic [SBV a]
+mkFreeVars = Trans.mkFreeVars
+
+-- | Similar to free; Just a more convenient name
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.symbolic'
+symbolic :: SymVal a => String -> Symbolic (SBV a)
+symbolic = Trans.symbolic
+
+-- | Similar to mkFreeVars; but automatically gives names based on the strings
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.symbolics'
+symbolics :: SymVal a => [String] -> Symbolic [SBV a]
+symbolics = Trans.symbolics
+
+-- | One stop allocator
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.mkSymVal'
+mkSymVal :: SymVal a => VarContext -> Maybe String -> Symbolic (SBV a)
+mkSymVal = Trans.mkSymVal
+
+-- Data.SBV.Core.Model:
+
+-- | Generically make a symbolic var
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.genMkSymVar'
+genMkSymVar :: Kind -> VarContext -> Maybe String -> Symbolic (SBV a)
+genMkSymVar = Trans.genMkSymVar
+
+-- | 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 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 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 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 unnamed '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 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 a named 'SWord'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord'
+sWord :: (KnownNat n, BVIsNonZero n) => String -> Symbolic (SWord n)
+sWord = Trans.sWord
+
+-- | Declare an unnamed 'SWord'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord_'
+sWord_ :: (KnownNat n, BVIsNonZero n) => Symbolic (SWord n)
+sWord_ = Trans.sWord_
+
+-- | Declare a list of 'SWord8's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWords'
+sWords :: (KnownNat n, BVIsNonZero n) => [String] -> Symbolic [SWord n]
+sWords = Trans.sWords
+
+-- | 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 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 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 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 a named 'SInt'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt'
+sInt :: (KnownNat n, BVIsNonZero n) => String -> Symbolic (SInt n)
+sInt = Trans.sInt
+
+-- | Declare an unnamed 'SInt'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt_'
+sInt_ :: (KnownNat n, BVIsNonZero n) => Symbolic (SInt n)
+sInt_ = Trans.sInt_
+
+-- | Declare a list of 'SInt's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInts'
+sInts :: (KnownNat n, BVIsNonZero n) => [String] -> Symbolic [SInt n]
+sInts = Trans.sInts
+
+-- | 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 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 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 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 a named 'SFloatingPoint eb sb'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloatingPoint'
+sFloatingPoint :: ValidFloat eb sb => String -> Symbolic (SFloatingPoint eb sb)
+sFloatingPoint = Trans.sFloatingPoint
+
+-- | Declare an unnamed 'SFloatingPoint' @eb@ @sb@
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloatingPoint_'
+sFloatingPoint_ :: ValidFloat eb sb => Symbolic (SFloatingPoint eb sb)
+sFloatingPoint_ = Trans.sFloatingPoint_
+
+-- | Declare a list of 'SFloatingPoint' @eb@ @sb@'s
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloatingPoints'
+sFloatingPoints :: ValidFloat eb sb => [String] -> Symbolic [SFloatingPoint eb sb]
+sFloatingPoints = Trans.sFloatingPoints
+
+-- | Declare a named 'SFPHalf'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPHalf'
+sFPHalf :: String -> Symbolic SFPHalf
+sFPHalf = Trans.sFPHalf
+
+-- | Declare an unnamed 'SFPHalf'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPHalf_'
+sFPHalf_ :: Symbolic SFPHalf
+sFPHalf_ = Trans.sFPHalf_
+
+-- | Declare a list of 'SFPHalf's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPHalfs'
+sFPHalfs :: [String] -> Symbolic [SFPHalf]
+sFPHalfs = Trans.sFPHalfs
+
+-- | Declare a named 'SFPBFloat'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.SFPBFloat'
+sFPBFloat :: String -> Symbolic SFPBFloat
+sFPBFloat = Trans.sFPBFloat
+
+-- | Declare an unnamed 'SFPBFloat'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.SFPBFloat'
+sFPBFloat_ :: Symbolic SFPBFloat
+sFPBFloat_ = Trans.sFPBFloat_
+
+-- | Declare a list of 'SFPQuad's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPBFloats'
+sFPBFloats :: [String] -> Symbolic [SFPBFloat]
+sFPBFloats = Trans.sFPBFloats
+
+-- | Declare a named 'SFPSingle'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPSingle'
+sFPSingle :: String -> Symbolic SFPSingle
+sFPSingle = Trans.sFPSingle
+
+-- | Declare an unnamed 'SFPSingle'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPSingle_'
+sFPSingle_ :: Symbolic SFPSingle
+sFPSingle_ = Trans.sFPSingle_
+
+-- | Declare a list of 'SFPSingle's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPSingles'
+sFPSingles :: [String] -> Symbolic [SFPSingle]
+sFPSingles = Trans.sFPSingles
+
+-- | Declare a named 'SFPDouble'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPDouble'
+sFPDouble :: String -> Symbolic SFPDouble
+sFPDouble = Trans.sFPDouble
+
+-- | Declare an unnamed 'SFPDouble'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPDouble_'
+sFPDouble_ :: Symbolic SFPDouble
+sFPDouble_ = Trans.sFPDouble_
+
+-- | Declare a list of 'SFPDouble's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPDoubles'
+sFPDoubles :: [String] -> Symbolic [SFPDouble]
+sFPDoubles = Trans.sFPDoubles
+
+-- | Declare a named 'SFPQuad'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPQuad'
+sFPQuad :: String -> Symbolic SFPQuad
+sFPQuad = Trans.sFPQuad
+
+-- | Declare an unnamed 'SFPQuad'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPQuad_'
+sFPQuad_ :: Symbolic SFPQuad
+sFPQuad_ = Trans.sFPQuad_
+
+-- | Declare a list of 'SFPQuad's
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFPQuads'
+sFPQuads :: [String] -> Symbolic [SFPQuad]
+sFPQuads = Trans.sFPQuads
+
+-- | 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 unnamed 'SChar'
+--
+-- 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
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sChars'
+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 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 named tuple.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sTuple'
+sTuple :: (SymTuple tup, 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_ :: (SymTuple tup, 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 :: (SymTuple tup, SymVal tup) => [String] -> Symbolic [SBV tup]
+sTuples = Trans.sTuples
+
+-- | Declare a named 'Data.SBV.SRational'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sRational'
+sRational :: String -> Symbolic SRational
+sRational = Trans.sRational
+
+-- | Declare an unnamed 'Data.SBV.SRational'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sRational_'
+sRational_ :: Symbolic SRational
+sRational_ = Trans.sRational_
+
+-- | Declare a list of 'Data.SBV.SRational' values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sRationals'
+sRationals :: [String] -> Symbolic [SRational]
+sRationals = Trans.sRationals
+
+-- | 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
+
+-- | Declare a named 'SArray'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sArray'
+sArray :: (SymVal a, SymVal b) => String -> Symbolic (SArray a b)
+sArray = Trans.sArray
+
+-- | Declare an unnamed 'SArray'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sArray_'
+sArray_ :: (SymVal a, SymVal b) => Symbolic (SArray a b)
+sArray_ = Trans.sArray_
+
+-- | Declare a list of 'SArray' values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sArrays'
+sArrays :: (SymVal a, SymVal b) => [String] -> Symbolic [SArray a b]
+sArrays = Trans.sArrays
+
+-- | Form the symbolic conjunction of a given list of boolean conditions. Useful in expressing
+-- problems with constraints, like the following:
+--
+-- @
+--   sat $ do [x, y, z] <- sIntegers [\"x\", \"y\", \"z\"]
+--            solve [x .> 5, y + z .< x]
+-- @
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.solve'
+solve :: [SBool] -> Symbolic SBool
+solve = Trans.solve
+
+-- | Introduce a soft assertion, with an optional penalty
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.assertWithPenalty'
+assertWithPenalty :: String -> SBool -> Penalty -> Symbolic ()
+assertWithPenalty = Trans.assertWithPenalty
+
+-- | Minimize a named metric
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.minimize'
+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 -> SBV a -> Symbolic ()
+maximize = Trans.maximize
+
+-- Data.SBV.Core.Symbolic:
+
+-- | Convert a symbolic value to an SV, inside the Symbolic monad
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.svToSymSV'
+svToSymSV :: SVal -> Symbolic SV
+svToSymSV = Trans.svToSymSV
+
+-- | Run a symbolic computation, and return a extra value paired up with the 'Result'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.runSymbolic'
+runSymbolic :: SMTConfig -> SBVRunMode -> Symbolic a -> IO (a, Result)
+runSymbolic = Trans.runSymbolic
+
+-- | Add a new option
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.addNewSMTOption'
+addNewSMTOption :: SMTOption -> Symbolic ()
+addNewSMTOption = Trans.addNewSMTOption
+
+-- | Handling constraints
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.imposeConstraint'
+imposeConstraint :: Bool -> [(String, String)] -> SVal -> Symbolic ()
+imposeConstraint = Trans.imposeConstraint
+
+-- | Add an optimization goal
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.addSValOptGoal'
+addSValOptGoal :: Objective SVal -> Symbolic ()
+addSValOptGoal = Trans.addSValOptGoal
+
+-- | Mark an interim result as an output. Useful when constructing Symbolic programs
+-- that return multiple values, or when the result is programmatically computed.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.outputSVal'
+outputSVal :: SVal -> Symbolic ()
+outputSVal = Trans.outputSVal
+
+-- | A variant of observe that you can use at the top-level. This is useful with quick-check, for instance.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sObserve'
+sObserve :: SymVal a => String -> SBV a -> Symbolic ()
+sObserve m x = Trans.sObserve m (Trans.unSBV x)
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,38 +1,44 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Compilers.C
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Compilers.C
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Compilation of symbolic programs to C
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP           #-}
-{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE TupleSections #-}
 
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
+
 module Data.SBV.Compilers.C(compileToC, compileToCLib, compileToC', compileToCLib') where
 
 import Control.DeepSeq                (rnf)
 import Data.Char                      (isSpace)
-import Data.List                      (nub, intercalate)
+import Data.List                      (nub, intercalate, intersperse)
 import Data.Maybe                     (isJust, isNothing, fromJust)
 import qualified Data.Foldable as F   (toList)
 import qualified Data.Set      as Set (member, union, unions, empty, toList, singleton, fromList)
+import qualified Data.Text     as T
 import System.FilePath                (takeBaseName, replaceExtension)
 import System.Random
+
+import Data.SBV.Core.Symbolic (ResultInp(..), ProgInfo(..))
+
+-- Work around the fact that GHC 8.4.1 started exporting <>.. Hmm..
 import Text.PrettyPrint.HughesPJ
+import qualified Text.PrettyPrint.HughesPJ as P ((<>))
 
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (shex, showCFloat, showCDouble)
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind (kRoundingMode)
 import Data.SBV.Compilers.CodeGen
 
-import GHC.Stack.Compat
-#if !MIN_VERSION_base(4,9,0)
-import GHC.SrcLoc.Compat
-#endif
+import Data.SBV.Utils.PrettyNum   (chex, showCFloat, showCDouble)
 
+import GHC.Stack
+
 ---------------------------------------------------------------------------
 -- * API
 ---------------------------------------------------------------------------
@@ -47,13 +53,18 @@
 --
 --   * The final argument is the function to be compiled.
 --
--- Compilation will also generate a @Makefile@,  a header file, and a driver (test) program, etc.
-compileToC :: Maybe FilePath -> String -> SBVCodeGen () -> IO ()
-compileToC mbDirName nm f = compileToC' nm f >>= renderCgPgmBundle mbDirName
+-- Compilation will also generate a @Makefile@,  a header file, and a driver (test) program, etc. As a
+-- result, we return whatever the code-gen function returns. Most uses should simply have @()@ as
+-- the return type here, but the value can be useful if you want to chain the result of
+-- one compilation act to the next.
+compileToC :: Maybe FilePath -> String -> SBVCodeGen a -> IO a
+compileToC mbDirName nm f = do (retVal, cfg, bundle) <- compileToC' nm f
+                               renderCgPgmBundle mbDirName (cfg, bundle)
+                               pure retVal
 
--- | Lower level version of 'compileToC', producing a 'CgPgmBundle'
-compileToC' :: String -> SBVCodeGen () -> IO CgPgmBundle
-compileToC' nm f = do rands <- randoms `fmap` newStdGen
+-- | Lower level version of 'compileToC', producing a t'CgPgmBundle'
+compileToC' :: String -> SBVCodeGen a -> IO (a, CgConfig, CgPgmBundle)
+compileToC' nm f = do rands <- randoms <$> newStdGen
                       codeGen SBVToC (defaultCgConfig { cgDriverVals = rands }) nm f
 
 -- | Create code to generate a library archive (.a) from given symbolic functions. Useful when generating code
@@ -66,12 +77,16 @@
 --
 --   * The third argument is the list of functions to include, in the form of function-name/code pairs, similar
 --     to the second and third arguments of 'compileToC', except in a list.
-compileToCLib :: Maybe FilePath -> String -> [(String, SBVCodeGen ())] -> IO ()
-compileToCLib mbDirName libName comps = compileToCLib' libName comps >>= renderCgPgmBundle mbDirName
+compileToCLib :: Maybe FilePath -> String -> [(String, SBVCodeGen a)] -> IO [a]
+compileToCLib mbDirName libName comps = do (retVal, cfg, pgm) <- compileToCLib' libName comps
+                                           renderCgPgmBundle mbDirName (cfg, pgm)
+                                           pure retVal
 
--- | Lower level version of 'compileToCLib', producing a 'CgPgmBundle'
-compileToCLib' :: String -> [(String, SBVCodeGen ())] -> IO CgPgmBundle
-compileToCLib' libName comps = mergeToLib libName `fmap` mapM (uncurry compileToC') comps
+-- | Lower level version of 'compileToCLib', producing a t'CgPgmBundle'
+compileToCLib' :: String -> [(String, SBVCodeGen a)] -> IO ([a], CgConfig, CgPgmBundle)
+compileToCLib' libName comps = do resCfgBundles <- mapM (uncurry compileToC') comps
+                                  let (finalCfg, finalPgm) = mergeToLib libName [(c, b) | (_, c, b) <- resCfgBundles]
+                                  pure ([r | (r, _, _) <- resCfgBundles], finalCfg, finalPgm)
 
 ---------------------------------------------------------------------------
 -- * Implementation
@@ -82,7 +97,7 @@
 
 instance CgTarget SBVToC where
   targetName _ = "C"
-  translate _  = cgen
+  translate  _ = cgen
 
 -- Unexpected input, or things we will probably never support
 die :: String -> a
@@ -103,13 +118,18 @@
                                , (nmd ++ ".c", (CgDriver,         genDriver cfg randVals nm ins outs mbRet))
                                , (nm  ++ ".c", (CgSource,         body))
                                ]
-        body = genCProg cfg nm sig sbvProg ins outs mbRet extDecls
+
+        (body, flagsNeeded) = genCProg cfg nm sig sbvProg ins outs mbRet extDecls
+
         bundleKind = (cgInteger cfg, cgReal cfg)
+
         randVals = cgDriverVals cfg
+
         filt xs  = [c | c@(_, (k, _)) <- xs, need k]
           where need k | isCgDriver   k = cgGenDriver cfg
                        | isCgMakefile k = cgGenMakefile cfg
                        | True           = True
+
         nmd      = nm ++ "_driver"
         sig      = pprCFunHeader nm ins outs mbRet
         ins      = cgInputs st
@@ -125,67 +145,83 @@
         extDecls  = case cgDecls st of
                      [] -> empty
                      xs -> vcat $ text "/* User given declarations: */" : map text xs
-        flags    = cgLDFlags st
+        flags    = flagsNeeded ++ cgLDFlags st
 
 -- | Pretty print a functions type. If there is only one output, we compile it
 -- as a function that returns that value. Otherwise, we compile it as a void function
 -- that takes return values as pointers to be updated.
-pprCFunHeader :: String -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SW -> Doc
-pprCFunHeader fn ins outs mbRet = retType <+> text fn <> parens (fsep (punctuate comma (map mkParam ins ++ map mkPParam outs)))
+pprCFunHeader :: String -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SV -> Doc
+pprCFunHeader fn ins outs mbRet = retType <+> text fn P.<> parens (fsep (punctuate comma (map mkParam ins ++ map mkPParam outs)))
   where retType = case mbRet of
                    Nothing -> text "void"
-                   Just sw -> pprCWord False sw
+                   Just sv -> pprCWord False sv
 
 mkParam, mkPParam :: (String, CgVal) -> Doc
-mkParam  (n, CgAtomic sw)     = pprCWord True  sw <+> text n
+mkParam  (n, CgAtomic sv)     = pprCWord True  sv <+> text n
 mkParam  (_, CgArray  [])     = die "mkParam: CgArray with no elements!"
-mkParam  (n, CgArray  (sw:_)) = pprCWord True  sw <+> text "*" <> text n
-mkPParam (n, CgAtomic sw)     = pprCWord False sw <+> text "*" <> text n
+mkParam  (n, CgArray  (sv:_)) = pprCWord True  sv <+> text "*" P.<> text n
+mkPParam (n, CgAtomic sv)     = pprCWord False sv <+> text "*" P.<> text n
 mkPParam (_, CgArray  [])     = die "mPkParam: CgArray with no elements!"
-mkPParam (n, CgArray  (sw:_)) = pprCWord False sw <+> text "*" <> text n
+mkPParam (n, CgArray  (sv:_)) = pprCWord False sv <+> text "*" P.<> text n
 
 -- | Renders as "const SWord8 s0", etc. the first parameter is the width of the typefield
-declSW :: Int -> SW -> Doc
-declSW w sw = text "const" <+> pad (showCType sw) <+> text (show sw)
+declSV :: Int -> SV -> Doc
+declSV w sv = text "const" <+> pad (showCType sv) <+> text (show sv)
   where pad s = text $ s ++ replicate (w - length s) ' '
 
 -- | Return the proper declaration and the result as a pair. No consts
-declSWNoConst :: Int -> SW -> (Doc, Doc)
-declSWNoConst w sw = (text "     " <+> pad (showCType sw), text (show sw))
+declSVNoConst :: Int -> SV -> (Doc, Doc)
+declSVNoConst w sv = (text "     " <+> pad (showCType sv), text (show sv))
   where pad s = text $ s ++ replicate (w - length s) ' '
 
 -- | Renders as "s0", etc, or the corresponding constant
-showSW :: CgConfig -> [(SW, CW)] -> SW -> Doc
-showSW cfg consts sw
-  | sw == falseSW                 = text "false"
-  | sw == trueSW                  = text "true"
-  | Just cw <- sw `lookup` consts = mkConst cfg cw
-  | True                          = text $ show sw
+showSV :: CgConfig -> [(SV, CV)] -> SV -> Doc
+showSV cfg consts sv
+  | sv == falseSV                 = text "false"
+  | sv == trueSV                  = text "true"
+  | Just cv <- sv `lookup` consts = mkConst cfg cv
+  | True                          = text $ show sv
 
 -- | Words as it would map to a C word
 pprCWord :: HasKind a => Bool -> a -> Doc
 pprCWord cnst v = (if cnst then text "const" else empty) <+> text (showCType v)
 
 -- | Almost a "show", but map "SWord1" to "SBool"
--- which is used for extracting one-bit words.
+-- which is used for extracting one-bit words. This is OK since C's bool type
+-- handles arithmetic fine, and maps nicely to our `SWord 1`. (Same isn't true for `SInt 1`, which
+-- doesn't have an easy counter-part on the C side.
 showCType :: HasKind a => a -> String
 showCType i = case kindOf i of
                 KBounded False 1 -> "SBool"
                 k                -> show k
 
 -- | The printf specifier for the type
-specifier :: CgConfig -> SW -> Doc
-specifier cfg sw = case kindOf sw of
+specifier :: CgConfig -> SV -> Doc
+specifier cfg sv = case kindOf sv of
+                     KVar{}        -> die $ "variable sort: " ++ show (kindOf sv)
                      KBool         -> spec (False, 1)
                      KBounded b i  -> spec (b, i)
                      KUnbounded    -> spec (True, fromJust (cgInteger cfg))
                      KReal         -> specF (fromJust (cgReal cfg))
                      KFloat        -> specF CgFloat
                      KDouble       -> specF CgDouble
-                     KUserSort s _ -> die $ "uninterpreted sort: " ++ s
-  where spec :: (Bool, Int) -> Doc
+                     KString       -> text "%s"
+                     KChar         -> text "%c"
+                     KRational     -> die   "rational sort"
+                     KFP{}         -> die   "arbitrary float sort"
+                     KList k       -> die $ "list sort: "   ++ show k
+                     KSet  k       -> die $ "set sort: "    ++ show k
+                     KApp s _      -> die $ "ADT app: "     ++ s
+                     KADT s _ _    -> die $ "ADT: "         ++ s
+                     KTuple k      -> die $ "tuple sort: "  ++ show k
+                     KArray  k1 k2 -> die $ "array sort: "  ++ show (k1, k2)
+  where u8InHex = cgShowU8InHex cfg
+
+        spec :: (Bool, Int) -> Doc
         spec (False,  1) = text "%d"
-        spec (False,  8) = text "%\"PRIu8\""
+        spec (False,  8)
+          | u8InHex      = text "0x%02\"PRIx8\""
+          | True         = text "%\"PRIu8\""
         spec (True,   8) = text "%\"PRId8\""
         spec (False, 16) = text "0x%04\"PRIx16\"U"
         spec (True,  16) = text "%\"PRId16\""
@@ -194,38 +230,42 @@
         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.
 --   There are many options here, using binary, decimal, etc. We simply use decimal for values 8-bits or less,
 --   and hex otherwise.
-mkConst :: CgConfig -> CW -> Doc
-mkConst cfg  (CW KReal (CWAlgReal (AlgRational _ r))) = double (fromRational r :: Double) <> sRealSuffix (fromJust (cgReal cfg))
+mkConst :: CgConfig -> CV -> Doc
+mkConst cfg  (CV KReal (CAlgReal (AlgRational _ r))) = double (fromRational r :: Double) P.<> sRealSuffix (fromJust (cgReal cfg))
   where sRealSuffix CgFloat      = text "F"
         sRealSuffix CgDouble     = empty
         sRealSuffix CgLongDouble = text "L"
-mkConst cfg (CW KUnbounded       (CWInteger i)) = showSizedConst i (True, fromJust (cgInteger cfg))
-mkConst _   (CW (KBounded sg sz) (CWInteger i)) = showSizedConst i (sg,   sz)
-mkConst _   (CW KBool            (CWInteger i)) = showSizedConst i (False, 1)
-mkConst _   (CW KFloat           (CWFloat f))   = text $ showCFloat f
-mkConst _   (CW KDouble          (CWDouble d))  = text $ showCDouble d
-mkConst _   cw                                  = die $ "mkConst: " ++ show cw
+mkConst cfg (CV KUnbounded       (CInteger i)) = showSizedConst (cgShowU8InHex cfg) i (True, fromJust (cgInteger cfg))
+mkConst cfg (CV (KBounded sg sz) (CInteger i)) = showSizedConst (cgShowU8InHex cfg) i (sg,   sz)
+mkConst cfg (CV KBool            (CInteger i)) = showSizedConst (cgShowU8InHex cfg) i (False, 1)
+mkConst _   (CV KFloat           (CFloat f))   = text $ showCFloat f
+mkConst _   (CV KDouble          (CDouble d))  = text $ showCDouble d
+mkConst _   (CV KString          (CString s))  = text $ show s
+mkConst _   (CV KChar            (CChar c))    = text $ show c
+mkConst _   cv                                 = die $ "mkConst: " ++ show cv
 
-showSizedConst :: Integer -> (Bool, Int) -> Doc
-showSizedConst i   (False,  1) = text (if i == 0 then "false" else "true")
-showSizedConst i   (False,  8) = integer i
-showSizedConst i   (True,   8) = integer i
-showSizedConst i t@(False, 16) = text (shex False True t i) <> text "U"
-showSizedConst i t@(True,  16) = text (shex False True t i)
-showSizedConst i t@(False, 32) = text (shex False True t i) <> text "UL"
-showSizedConst i t@(True,  32) = text (shex False True t i) <> text "L"
-showSizedConst i t@(False, 64) = text (shex False True t i) <> text "ULL"
-showSizedConst i t@(True,  64) = text (shex False True t i) <> text "LL"
-showSizedConst i   (True,  1)  = die $ "Signed 1-bit value " ++ show i
-showSizedConst i   (s, sz)     = die $ "Constant " ++ show i ++ " at type " ++ (if s then "SInt" else "SWord") ++ show sz
+showSizedConst :: Bool -> Integer -> (Bool, Int) -> Doc
+showSizedConst _   i   (False,  1) = text (if i == 0 then "false" else "true")
+showSizedConst u8h i t@(False,  8)
+  | u8h                            = text $ T.unpack (chex False True t i)
+  | True                           = integer i
+showSizedConst _   i   (True,   8) = integer i
+showSizedConst _   i t@(False, 16) = text $ T.unpack $ chex False True t i
+showSizedConst _   i t@(True,  16) = text $ T.unpack $ chex False True t i
+showSizedConst _   i t@(False, 32) = text $ T.unpack $ chex False True t i
+showSizedConst _   i t@(True,  32) = text $ T.unpack $ chex False True t i
+showSizedConst _   i t@(False, 64) = text $ T.unpack $ chex False True t i
+showSizedConst _   i t@(True,  64) = text $ T.unpack $ chex False True t i
+showSizedConst _   i   (s, sz)     = die $ "Constant " ++ show i ++ " at type " ++ (if s then "SInt" else "SWord") ++ show sz
 
 -- | Generate a makefile. The first argument is True if we have a driver.
 genMake :: Bool -> String -> String -> [String] -> Doc
@@ -233,24 +273,24 @@
  where ifld = not (null ldFlags)
        ld | ifld = text "${LDFLAGS}"
           | True = empty
-       lns = [ (True, text "# Makefile for" <+> nm <> text ". Automatically generated by SBV. Do not edit!")
+       lns = [ (True, text "# Makefile for" <+> nm P.<> text ". Automatically generated by SBV. Do not edit!")
              , (True, text "")
              , (True, text "# include any user-defined .mk file in the current directory.")
              , (True, text "-include *.mk")
              , (True, text "")
              , (True, text "CC?=gcc")
              , (True, text "CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer")
-             , (ifld, text "LDFLAGS?=" <> text (unwords ldFlags))
+             , (ifld, text "LDFLAGS?=" P.<> text (unwords ldFlags))
              , (True, text "")
              , (ifdr, text "all:" <+> nmd)
              , (ifdr, text "")
-             , (True, nmo <> text (": " ++ ppSameLine (hsep [nmc, nmh])))
+             , (True, nmo P.<> text (": " ++ ppSameLine (hsep [nmc, nmh])))
              , (True, text "\t${CC} ${CCFLAGS}" <+> text "-c $< -o $@")
              , (True, text "")
-             , (ifdr, nmdo <> text ":" <+> nmdc)
+             , (ifdr, nmdo P.<> text ":" <+> nmdc)
              , (ifdr, text "\t${CC} ${CCFLAGS}" <+> text "-c $< -o $@")
              , (ifdr, text "")
-             , (ifdr, nmd <> text (": " ++ ppSameLine (hsep [nmo, nmdo])))
+             , (ifdr, nmd P.<> text (": " ++ ppSameLine (hsep [nmo, nmdo])))
              , (ifdr, text "\t${CC} ${CCFLAGS}" <+> text "$^ -o $@" <+> ld)
              , (ifdr, text "")
              , (True, text "clean:")
@@ -262,16 +302,16 @@
              ]
        nm   = text fn
        nmd  = text dn
-       nmh  = nm <> text ".h"
-       nmc  = nm <> text ".c"
-       nmo  = nm <> text ".o"
-       nmdc = nmd <> text ".c"
-       nmdo = nmd <> text ".o"
+       nmh  = nm P.<> text ".h"
+       nmc  = nm P.<> text ".c"
+       nmo  = nm P.<> text ".o"
+       nmdc = nmd P.<> text ".c"
+       nmdo = nmd P.<> text ".o"
 
 -- | Generate the header
 genHeader :: (Maybe Int, Maybe CgSRealType) -> String -> [Doc] -> Doc -> Doc
 genHeader (ik, rk) fn sigs protos =
-     text "/* Header file for" <+> nm <> text ". Automatically generated by SBV. Do not edit! */"
+     text "/* Header file for" <+> nm P.<> text ". Automatically generated by SBV. Do not edit! */"
   $$ text ""
   $$ text "#ifndef" <+> tag
   $$ text "#define" <+> tag
@@ -294,13 +334,13 @@
   $$ text "typedef double SDouble;"
   $$ text ""
   $$ text "/* Unsigned bit-vectors */"
-  $$ text "typedef uint8_t  SWord8 ;"
+  $$ text "typedef uint8_t  SWord8;"
   $$ text "typedef uint16_t SWord16;"
   $$ text "typedef uint32_t SWord32;"
   $$ text "typedef uint64_t SWord64;"
   $$ text ""
   $$ text "/* Signed bit-vectors */"
-  $$ text "typedef int8_t  SInt8 ;"
+  $$ text "typedef int8_t  SInt8;"
   $$ text "typedef int16_t SInt16;"
   $$ text "typedef int32_t SInt32;"
   $$ text "typedef int64_t SInt64;"
@@ -308,13 +348,13 @@
   $$ imapping
   $$ rmapping
   $$ text ("/* Entry point prototype" ++ plu ++ ": */")
-  $$ vcat (map (<> semi) sigs)
+  $$ vcat (map (P.<> semi) sigs)
   $$ text ""
   $$ protos
   $$ text "#endif /*" <+> tag <+> text "*/"
   $$ text ""
  where nm  = text fn
-       tag = text "__" <> nm <> text "__HEADER_INCLUDED__"
+       tag = text "__" P.<> nm P.<> text "__HEADER_INCLUDED__"
        plu = if length sigs /= 1 then "s" else ""
        imapping = case ik of
                     Nothing -> empty
@@ -333,13 +373,13 @@
 sepIf b = if b then text "" else empty
 
 -- | Generate an example driver program
-genDriver :: CgConfig -> [Integer] -> String -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SW -> [Doc]
+genDriver :: CgConfig -> [Integer] -> String -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SV -> [Doc]
 genDriver cfg randVals fn inps outs mbRet = [pre, header, body, post]
- where pre    =  text "/* Example driver program for" <+> nm <> text ". */"
+ where pre    =  text "/* Example driver program for" <+> nm P.<> text ". */"
               $$ text "/* Automatically generated by SBV. Edit as you see fit! */"
               $$ text ""
               $$ text "#include <stdio.h>"
-       header =  text "#include" <+> doubleQuotes (nm <> text ".h")
+       header =  text "#include" <+> doubleQuotes (nm P.<> text ".h")
               $$ text ""
               $$ text "int main(void)"
               $$ text "{"
@@ -350,86 +390,112 @@
                       $$ call
                       $$ text ""
                       $$ (case mbRet of
-                              Just sw -> text "printf" <> parens (printQuotes (fcall <+> text "=" <+> specifier cfg sw <> text "\\n")
-                                                                              <> comma <+> resultVar) <> semi
-                              Nothing -> text "printf" <> parens (printQuotes (fcall <+> text "->\\n")) <> semi)
+                              Just sv -> text "printf" P.<> parens (printQuotes (fcall <+> text "=" <+> specifier cfg sv P.<> text "\\n")
+                                                                              P.<> comma <+> resultVar) P.<> semi
+                              Nothing -> text "printf" P.<> parens (printQuotes (fcall <+> text "->\\n")) P.<> semi)
                       $$ vcat (map display outs)
                       )
        post   =   text ""
-              $+$ nest 2 (text "return 0" <> semi)
+              $+$ nest 2 (text "return 0" P.<> semi)
               $$  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 sw)            : cs) = ([mkRVal sw r], n, CgAtomic sw) : matchRands rs cs
+       matchRands (r:rs) ((n, CgAtomic sv)            : cs) = ([mkRVal sv r], n, CgAtomic sv) : matchRands rs cs
        matchRands _      ((n, CgArray [])             : _ ) = die $ "Unsupported empty array input " ++ show n
-       matchRands rs     ((n, a@(CgArray sws@(sw:_))) : cs)
+       matchRands rs     ((n, a@(CgArray sws@(sv:_))) : cs)
           | length frs /= l                                 = die "Run out of driver values!"
-          | True                                            = (map (mkRVal sw) frs, n, a) : matchRands srs cs
+          | True                                            = (map (mkRVal sv) frs, n, a) : matchRands srs cs
           where l          = length sws
                 (frs, srs) = splitAt l rs
-       mkRVal sw r = mkConst cfg $ mkConstCW (kindOf sw) r
+       mkRVal sv r = mkConst cfg $ mkConstCV (kindOf sv) r
        mkInp (_,  _, CgAtomic{})         = empty  -- constant, no need to declare
        mkInp (_,  n, CgArray [])         = die $ "Unsupported empty array value for " ++ show n
-       mkInp (vs, n, CgArray sws@(sw:_)) =  pprCWord True sw <+> text n <> brackets (int (length sws)) <+> text "= {"
+       mkInp (vs, n, CgArray sws@(sv:_)) =  pprCWord True sv <+> text n P.<> brackets (int (length sws)) <+> text "= {"
                                                       $$ nest 4 (fsep (punctuate comma (align vs)))
                                                       $$ text "};"
                                          $$ text ""
-                                         $$ text "printf" <> parens (printQuotes (text "Contents of input array" <+> text n <> text ":\\n")) <> semi
+                                         $$ text "printf" P.<> parens (printQuotes (text "Contents of input array" <+> text n P.<> text ":\\n")) P.<> semi
                                          $$ display (n, CgArray sws)
                                          $$ text ""
-       mkOut (v, CgAtomic sw)            = pprCWord False sw <+> text v <> semi
+       mkOut (v, CgAtomic sv)            = pprCWord False sv <+> text v P.<> semi
        mkOut (v, CgArray [])             = die $ "Unsupported empty array value for " ++ show v
-       mkOut (v, CgArray sws@(sw:_))     = pprCWord False sw <+> text v <> brackets (int (length sws)) <> semi
+       mkOut (v, CgArray sws@(sv:_))     = pprCWord False sv <+> text v P.<> brackets (int (length sws)) P.<> semi
        resultVar = text "__result"
        call = case mbRet of
-                Nothing -> fcall <> semi
-                Just sw -> pprCWord True sw <+> resultVar <+> text "=" <+> fcall <> semi
-       fcall = nm <> parens (fsep (punctuate comma (map mkCVal pairedInputs ++ map mkOVal outs)))
+                Nothing -> fcall P.<> semi
+                Just sv -> pprCWord True sv <+> resultVar <+> text "=" <+> fcall P.<> semi
+       fcall = nm P.<> parens (fsep (punctuate comma (map mkCVal pairedInputs ++ map mkOVal outs)))
        mkCVal ([v], _, CgAtomic{}) = v
        mkCVal (vs,  n, CgAtomic{}) = die $ "Unexpected driver value computed for " ++ show n ++ render (hcat vs)
        mkCVal (_,   n, CgArray{})  = text n
-       mkOVal (n, CgAtomic{})      = text "&" <> text n
+       mkOVal (n, CgAtomic{})      = text "&" P.<> text n
        mkOVal (n, CgArray{})       = text n
-       display (n, CgAtomic sw)         = text "printf" <> parens (printQuotes (text " " <+> text n <+> text "=" <+> specifier cfg sw
-                                                                                <> text "\\n") <> comma <+> text n) <> semi
+       display (n, CgAtomic sv)         = text "printf" P.<> parens (printQuotes (text " " <+> text n <+> text "=" <+> specifier cfg sv
+                                                                                P.<> text "\\n") P.<> comma <+> text n) P.<> semi
        display (n, CgArray [])         =  die $ "Unsupported empty array value for " ++ show n
-       display (n, CgArray sws@(sw:_)) =   text "int" <+> nctr <> semi
-                                        $$ text "for(" <> nctr <+> text "= 0;" <+> nctr <+> text "<" <+> int (length sws) <+> text "; ++" <> nctr <> text ")"
-                                        $$ nest 2 (text "printf" <> parens (printQuotes (text " " <+> entrySpec <+> text "=" <+> spec <> text "\\n")
-                                                                 <> comma <+> nctr <+> comma <> entry) <> semi)
-                  where nctr      = text n <> text "_ctr"
-                        entry     = text n <> text "[" <> nctr <> text "]"
-                        entrySpec = text n <> text "[%d]"
-                        spec      = specifier cfg sw
+       display (n, CgArray sws@(sv:_)) =   text "int" <+> nctr P.<> semi
+                                        $$ text "for(" P.<> nctr <+> text "= 0;" <+> nctr <+> text "<" <+> int len <+> text "; ++" P.<> nctr P.<> text ")"
+                                        $$ nest 2 (text "printf" P.<> parens (printQuotes (text " " <+> entrySpec <+> text "=" <+> spec P.<> text "\\n")
+                                                                 P.<> comma <+> nctr <+> comma P.<> entry) P.<> semi)
+                  where nctr      = text n P.<> text "_ctr"
+                        entry     = text n P.<> text "[" P.<> nctr P.<> text "]"
+                        entrySpec = text n P.<> text "[%" P.<> int tab P.<> text "d]"
+                        spec      = specifier cfg sv
+                        len       = length sws
+                        tab       = length $ show (len - 1)
 
 -- | Generate the C program
-genCProg :: CgConfig -> String -> Doc -> Result -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SW -> Doc -> [Doc]
-genCProg cfg fn proto (Result kindInfo _tvals cgs ins preConsts tbls arrs _ _ (SBVPgm asgns) cstrs origAsserts _) inVars outVars mbRet extDecls
+genCProg :: CgConfig -> String -> Doc -> Result -> [(String, CgVal)] -> [(String, CgVal)] -> Maybe SV -> Doc -> ([Doc], [String])
+genCProg cfg fn proto (Result pinfo kindInfo _tvals _ovals cgs topInps (_, preConsts) tbls _uis axioms (SBVPgm asgns) cstrs origAsserts _) inVars outVars mbRet extDecls
   | isNothing (cgInteger cfg) && KUnbounded `Set.member` kindInfo
   = error $ "SBV->C: Unbounded integers are not supported by the C compiler."
           ++ "\nUse 'cgIntegerSize' to specify a fixed size for SInteger representation."
+  | KString `Set.member` kindInfo
+  = notyet "Strings"
+  | KChar `Set.member` kindInfo
+  = notyet "Characters"
+  | any isSet kindInfo
+  = notyet "Sets (SSet)"
+  | any isList kindInfo
+  = notyet "Lists (SList)"
+  | any isTuple kindInfo
+  = notyet "Tuples (STupleN)"
   | 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."
+  | not (null unsupportedBVs)
+  = error $ "SBV->C: Unsupported bit-vector type(s): " ++ intercalate ", " (map show unsupportedBVs)
   | not (null usorts)
   = error $ "SBV->C: Cannot compile functions with uninterpreted sorts: " ++ intercalate ", " usorts
+  | hasQuants pinfo
+  = error "SBV->C: Cannot compile in the presence of quantified variables."
+  | not $ null (progSpecialRels pinfo)
+  = error "SBV->C: Cannot compile in the presence of special relations."
+  | not (null axioms)
+  = error "SBV->C: Cannot compile in the presence of 'smtFunction' definitions, use 'compileToCLib' instead."
   | not (null cstrs)
   = tbd "Explicit constraints"
-  | not (null arrs)
-  = tbd "User specified arrays"
-  | needsExistentials (map fst ins)
-  = error "SBV->C: Cannot compile functions with existentially quantified variables."
   | True
-  = [pre, header, post]
- where asserts | cgIgnoreAsserts cfg = []
+  = ([pre, header, post], flagsNeeded)
+ where notyet m = error $ "SBV->C: " ++ m ++ " are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+
+       asserts | cgIgnoreAsserts cfg = []
                | True                = origAsserts
-       usorts = [s | KUserSort s _ <- Set.toList kindInfo, s /= "RoundingMode"] -- No support for any sorts other than RoundingMode!
-       pre    =  text "/* File:" <+> doubleQuotes (nm <> text ".c") <> text ". Automatically generated by SBV. Do not edit! */"
+
+       usorts = [s | k@(KADT s _ _) <- Set.toList kindInfo, isADT k && not (isRoundingMode k)] -- No support for any sorts other than RoundingMode!
+
+       pre    =  text "/* File:" <+> doubleQuotes (nm P.<> text ".c") P.<> text ". Automatically generated by SBV. Do not edit! */"
               $$ text ""
-       header = text "#include" <+> doubleQuotes (nm <> text ".h")
+
+       header = text "#include" <+> doubleQuotes (nm P.<> text ".h")
+
+       unsupportedBVs = [k | k@(KBounded sg sz) <- Set.toList kindInfo, (not . supported) (sg, sz)]
+         where supported (False, sz) = sz `elem` [1, 8, 16, 32, 64]
+               supported (True,  sz) = sz `elem` [   8, 16, 32, 64]
+
        post   = text ""
              $$ vcat (map codeSeg cgs)
              $$ extDecls
@@ -439,63 +505,98 @@
              $$ nest 2 (   vcat (concatMap (genIO True . (\v -> (isAlive v, v))) inVars)
                         $$ vcat (merge (map genTbl tbls) (map genAsgn assignments) (map genAssert asserts))
                         $$ sepIf (not (null assignments) || not (null tbls))
-                        $$ vcat (concatMap (genIO False) (zip (repeat True) outVars))
+                        $$ vcat (concatMap (genIO False . (True,)) outVars)
                         $$ maybe empty mkRet mbRet
                        )
              $$ text "}"
              $$ text ""
+
        nm = text fn
+
        assignments = F.toList asgns
+
+       -- Do we need any linker flags for C?
+       flagsNeeded = nub $ concatMap (getLDFlag . opRes) assignments
+          where opRes (sv, SBVApp o _) = (o, kindOf sv)
+
        codeSeg (fnm, ls) =  text "/* User specified custom code for" <+> doubleQuotes (text fnm) <+> text "*/"
                          $$ vcat (map text ls)
                          $$ text ""
-       typeWidth = getMax 0 $ [len (kindOf s) | (s, _) <- assignments] ++ [len (kindOf s) | (_, (s, _)) <- ins]
-                where len KReal{}             = 5
-                      len KFloat{}            = 6 -- SFloat
-                      len KDouble{}           = 7 -- SDouble
-                      len KUnbounded{}        = 8
-                      len KBool               = 5 -- SBool
-                      len (KBounded False n)  = 5 + length (show n) -- SWordN
-                      len (KBounded True  n)  = 4 + length (show n) -- SIntN
-                      len (KUserSort s _)     = die $ "Uninterpreted sort: " ++ s
+
+       ins = case topInps of
+               ResultTopInps (is, []) -> is
+               ResultTopInps is       -> die $ "Unexpected trackers: " ++ show is
+               ResultLamInps is       -> die $ "Unexpected inputs  : " ++ show is
+
+       typeWidth = getMax 0 $ [len (kindOf s) | (s, _) <- assignments] ++ [len (kindOf s) | NamedSymVar s _ <- ins]
+                where len (KVar s)           = die $ "Variable: " ++ s
+                      len KReal{}            = 5
+                      len KFloat{}           = 6 -- SFloat
+                      len KDouble{}          = 7 -- SDouble
+                      len KString{}          = 7 -- SString
+                      len KChar{}            = 5 -- SChar
+                      len KUnbounded{}       = 8
+                      len KBool              = 5 -- SBool
+                      len (KBounded False n) = 5 + length (show n) -- SWordN
+                      len (KBounded True  n) = 4 + length (show n) -- SIntN
+                      len KRational{}        = die   "Rational."
+                      len KFP{}              = die   "Arbitrary float."
+                      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 (KArray  k1 k2)    = die $ "Array sort:  " ++ show (k1, k2)
+                      len (KApp s _)         = die $ "Uninterpreted ADT app: " ++ s
+                      len (KADT s _ _)       = die $ "Uninterpreted ADT: "     ++ s
+
                       getMax 8 _      = 8  -- 8 is the max we can get with SInteger, so don't bother looking any further
                       getMax m []     = m
                       getMax m (x:xs) = getMax (m `max` x) xs
-       consts = (falseSW, falseCW) : (trueSW, trueCW) : preConsts
+
+       consts = (falseSV, falseCV) : (trueSV, trueCV) : preConsts
+
        isConst s = isJust (lookup s consts)
+
        -- TODO: The following is brittle. We should really have a function elsewhere
        -- that walks the SBVExprs and collects the SWs together.
        usedVariables = Set.unions (retSWs : map usedCgVal outVars ++ map usedAsgn assignments)
          where retSWs = maybe Set.empty Set.singleton mbRet
+
                usedCgVal (_, CgAtomic s)  = Set.singleton s
                usedCgVal (_, CgArray ss)  = Set.fromList ss
                usedAsgn  (_, SBVApp o ss) = Set.union (opSWs o) (Set.fromList ss)
+
                opSWs (LkUp _ a b)             = Set.fromList [a, b]
                opSWs (IEEEFP (FP_Cast _ _ s)) = Set.singleton s
                opSWs _                        = Set.empty
+
        isAlive :: (String, CgVal) -> Bool
-       isAlive (_, CgAtomic sw) = sw `Set.member` usedVariables
+       isAlive (_, CgAtomic sv) = sv `Set.member` usedVariables
        isAlive (_, _)           = True
+
        genIO :: Bool -> (Bool, (String, CgVal)) -> [Doc]
-       genIO True  (alive, (cNm, CgAtomic sw)) = [declSW typeWidth sw  <+> text "=" <+> text cNm <> semi             | alive]
-       genIO False (alive, (cNm, CgAtomic sw)) = [text "*" <> text cNm <+> text "=" <+> showSW cfg consts sw <> semi | alive]
+       genIO True  (alive, (cNm, CgAtomic sv)) = [declSV typeWidth sv  <+> text "=" <+> text cNm P.<> semi               | alive]
+       genIO False (alive, (cNm, CgAtomic sv)) = [text "*" P.<> text cNm <+> text "=" <+> showSV cfg consts sv P.<> semi | alive]
        genIO isInp (_,     (cNm, CgArray sws)) = zipWith genElt sws [(0::Int)..]
-         where genElt sw i
-                 | isInp = declSW typeWidth sw <+> text "=" <+> text entry       <> semi
-                 | True  = text entry          <+> text "=" <+> showSW cfg consts sw <> semi
+         where genElt sv i
+                 | isInp = declSV typeWidth sv <+> text "=" <+> text entry       P.<> semi
+                 | True  = text entry          <+> text "=" <+> showSV cfg consts sv P.<> semi
                  where entry = cNm ++ "[" ++ show i ++ "]"
-       mkRet sw = text "return" <+> showSW cfg consts sw <> semi
-       genTbl :: ((Int, Kind, Kind), [SW]) -> (Int, Doc)
-       genTbl ((i, _, k), elts) =  (location, static <+> text "const" <+> text (show k) <+> text ("table" ++ show i) <> text "[] = {"
-                                              $$ nest 4 (fsep (punctuate comma (align (map (showSW cfg consts) elts))))
+
+       mkRet sv = text "return" <+> showSV cfg consts sv P.<> semi
+
+       genTbl :: ((Int, Kind, Kind), [SV]) -> (Int, Doc)
+       genTbl ((i, _, k), elts) =  (location, static <+> text "const" <+> text (show k) <+> text ("table" ++ show i) P.<> text "[] = {"
+                                              $$ nest 4 (fsep (punctuate comma (align (map (showSV cfg consts) elts))))
                                               $$ text "};")
          where static   = if location == -1 then text "static" else empty
                location = maximum (-1 : map getNodeId elts)
-       getNodeId s@(SW _ (NodeId n)) | isConst s = -1
-                                     | True      = n
-       genAsgn :: (SW, SBVExpr) -> (Int, Doc)
-       genAsgn (sw, n) = (getNodeId sw, ppExpr cfg consts n (declSW typeWidth sw) (declSWNoConst typeWidth sw) <> semi)
 
+       getNodeId s@(SV _ (NodeId (_, _, n))) | isConst s = -1
+                                             | True      = n
+
+       genAsgn :: (SV, SBVExpr) -> (Int, Doc)
+       genAsgn (sv, n) = (getNodeId sv, ppExpr cfg consts n (declSV typeWidth sv) (declSVNoConst typeWidth sv) P.<> semi)
+
        -- merge tables intermixed with assignments and assertions, paying attention to putting tables as
        -- early as possible and tables right after.. Note that the assignment list (second argument) is sorted on its order
        merge :: [(Int, Doc)] -> [(Int, Doc)] -> [(Int, Doc)] -> [Doc]
@@ -505,11 +606,12 @@
                merge2 ts@((i, t):trest) as@((i', a):arest)
                  | i < i'                                 = (i,  t)  : merge2 trest as
                  | True                                   = (i', a) : merge2 ts arest
-       genAssert (msg, cs, sw) = (getNodeId sw, doc)
+
+       genAssert (msg, cs, sv) = (getNodeId sv, doc)
          where doc =     text "/* ASSERTION:" <+> text msg
-                     $$  maybe empty (vcat . map text) (locInfo (getCallStack `fmap` cs))
+                     $$  maybe empty (vcat . map text) (locInfo (getCallStack <$> cs))
                      $$  text " */"
-                     $$  text "if" <> parens (showSW cfg consts sw)
+                     $$  text "if" P.<> parens (showSV cfg consts sv)
                      $$  text "{"
                      $+$ nest 2 (vcat [errOut, text "exit(-1);"])
                      $$  text "}"
@@ -521,77 +623,89 @@
                                          (f:rs) -> Just $ (" * SOURCE   : " ++ f) : map (" *            " ++)  rs
                locInfo _         = Nothing
 
-handleIEEE :: FPOp -> [(SW, CW)] -> [(SW, Doc)] -> Doc -> Doc
+handlePB :: PBOp -> [Doc] -> Doc
+handlePB o args = case o of
+                    PB_AtMost  k -> addIf (repeat 1) <+> text "<=" <+> int k
+                    PB_AtLeast k -> addIf (repeat 1) <+> text ">=" <+> int k
+                    PB_Exactly k -> addIf (repeat 1) <+> text "==" <+> int k
+                    PB_Le cs   k -> addIf cs         <+> text "<=" <+> int k
+                    PB_Ge cs   k -> addIf cs         <+> text ">=" <+> int k
+                    PB_Eq cs   k -> addIf cs         <+> text "==" <+> int k
+
+  where addIf :: [Int] -> Doc
+        addIf cs = parens $ fsep $ intersperse (text "+") [parens (a <+> text "?" <+> int c <+> text ":" <+> int 0) | (a, c) <- zip args cs]
+
+handleIEEE :: FPOp -> [(SV, CV)] -> [(SV, Doc)] -> Doc -> Doc
 handleIEEE w consts as var = cvt w
   where same f                   = (f, f)
         named fnm dnm f          = (f fnm, f dnm)
 
-        castToUnsigned f to = parens (text "!isnan" <> parens a <+> text "&&" <+> text "signbit" <> parens a) <+> text "?" <+> cvt1 <+> text ":" <+> cvt2
-          where [a]  = map snd fpArgs
-                absA = text (if f == KFloat then "fabsf" else "fabs") <> 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)"
                                      (KFloat,  KBounded False 32) -> cast $ cpy "sizeof(SWord32)"
                                      (KDouble, KBounded False 64) -> cast $ cpy "sizeof(SWord64)"
                                      _                            -> die $ "Reinterpretation from : " ++ show f ++ " to " ++ show t
-                                    where cpy sz = \[a] -> let alhs = text "&" <> var
-                                                               arhs = text "&" <> a
-                                                           in text "memcpy" <> parens (fsep (punctuate comma [alhs, arhs, text sz]))
-        cvt FP_Abs               = dispatch $ named "fabsf" "fabs" $ \nm _ [a] -> text nm <> parens a
-        cvt FP_Neg               = dispatch $ same $ \_ [a] -> text "-" <> a
+                                    where cpy sz = \[a] -> let alhs = text "&" P.<> var
+                                                               arhs = text "&" P.<> a
+                                                           in text "memcpy" P.<> parens (fsep (punctuate comma [alhs, arhs, text sz]))
+        cvt FP_Abs               = dispatch $ named "fabsf" "fabs" $ \nm _ [a] -> text nm P.<> parens a
+        cvt FP_Neg               = dispatch $ same $ \_ [a] -> text "-" P.<> a
         cvt FP_Add               = dispatch $ same $ \_ [a, b] -> a <+> text "+" <+> b
         cvt FP_Sub               = dispatch $ same $ \_ [a, b] -> a <+> text "-" <+> b
         cvt FP_Mul               = dispatch $ same $ \_ [a, b] -> a <+> text "*" <+> b
         cvt FP_Div               = dispatch $ same $ \_ [a, b] -> a <+> text "/" <+> b
-        cvt FP_FMA               = dispatch $ named "fmaf"  "fma"  $ \nm _ [a, b, c] -> text nm <> parens (fsep (punctuate comma [a, b, c]))
-        cvt FP_Sqrt              = dispatch $ named "sqrtf" "sqrt" $ \nm _ [a]       -> text nm <> parens a
-        cvt FP_Rem               = dispatch $ named "fmodf" "fmod" $ \nm _ [a, b]    -> text nm <> parens (fsep (punctuate comma [a, b]))
-        cvt FP_RoundToIntegral   = dispatch $ named "rintf" "rint" $ \nm _ [a]       -> text nm <> parens a
-        cvt FP_Min               = dispatch $ named "fminf" "fmin" $ \nm k [a, b]    -> wrapMinMax k a b (text nm <> parens (fsep (punctuate comma [a, b])))
-        cvt FP_Max               = dispatch $ named "fmaxf" "fmax" $ \nm k [a, b]    -> wrapMinMax k a b (text nm <> parens (fsep (punctuate comma [a, b])))
+        cvt FP_FMA               = dispatch $ named "fmaf"  "fma"  $ \nm _ [a, b, c] -> text nm P.<> parens (fsep (punctuate comma [a, b, c]))
+        cvt FP_Sqrt              = dispatch $ named "sqrtf" "sqrt" $ \nm _ [a]       -> text nm P.<> parens a
+        cvt FP_Rem               = dispatch $ named "fmodf" "fmod" $ \nm _ [a, b]    -> text nm P.<> parens (fsep (punctuate comma [a, b]))
+        cvt FP_RoundToIntegral   = dispatch $ named "rintf" "rint" $ \nm _ [a]       -> text nm P.<> parens a
+        cvt FP_Min               = dispatch $ named "fminf" "fmin" $ \nm k [a, b]    -> wrapMinMax k a b (text nm P.<> parens (fsep (punctuate comma [a, b])))
+        cvt FP_Max               = dispatch $ named "fmaxf" "fmax" $ \nm k [a, b]    -> wrapMinMax k a b (text nm P.<> parens (fsep (punctuate comma [a, b])))
         cvt FP_ObjEqual          = let mkIte   x y z = x <+> text "?" <+> y <+> text ":" <+> z
-                                       chkNaN  x     = text "isnan"   <> parens x
-                                       signbit x     = text "signbit" <> parens x
+                                       chkNaN  x     = text "isnan"   P.<> parens x
+                                       signbit x     = text "signbit" P.<> parens x
                                        eq      x y   = parens (x <+> text "==" <+> y)
                                        eqZero  x     = eq x (text "0")
                                        negZero x     = parens (signbit x <+> text "&&" <+> eqZero x)
                                    in dispatch $ same $ \_ [a, b] -> mkIte (chkNaN a) (chkNaN b) (mkIte (negZero a) (negZero b) (mkIte (negZero b) (negZero a) (eq a b)))
-        cvt FP_IsNormal          = dispatch $ same $ \_ [a] -> text "isnormal" <> parens a
-        cvt FP_IsSubnormal       = dispatch $ same $ \_ [a] -> text "FP_SUBNORMAL == fpclassify" <> parens a
-        cvt FP_IsZero            = dispatch $ same $ \_ [a] -> text "FP_ZERO == fpclassify" <> parens a
-        cvt FP_IsInfinite        = dispatch $ same $ \_ [a] -> text "isinf" <> parens a
-        cvt FP_IsNaN             = dispatch $ same $ \_ [a] -> text "isnan" <> parens a
-        cvt FP_IsNegative        = dispatch $ same $ \_ [a] -> text "!isnan" <> parens a <+> text "&&" <+> text "signbit"  <> parens a
-        cvt FP_IsPositive        = dispatch $ same $ \_ [a] -> text "!isnan" <> parens a <+> text "&&" <+> text "!signbit" <> parens a
+        cvt FP_IsNormal          = dispatch $ same $ \_ [a] -> text "isnormal" P.<> parens a
+        cvt FP_IsSubnormal       = dispatch $ same $ \_ [a] -> text "FP_SUBNORMAL == fpclassify" P.<> parens a
+        cvt FP_IsZero            = dispatch $ same $ \_ [a] -> text "FP_ZERO == fpclassify" P.<> parens a
+        cvt FP_IsInfinite        = dispatch $ same $ \_ [a] -> text "isinf" P.<> parens a
+        cvt FP_IsNaN             = dispatch $ same $ \_ [a] -> text "isnan" P.<> parens a
+        cvt FP_IsNegative        = dispatch $ same $ \_ [a] -> text "!isnan" P.<> parens a <+> text "&&" <+> text "signbit"  P.<> parens a
+        cvt FP_IsPositive        = dispatch $ same $ \_ [a] -> text "!isnan" P.<> parens a <+> text "&&" <+> text "!signbit" P.<> parens a
 
         -- grab the rounding-mode, if present, and make sure it's RoundNearestTiesToEven. Otherwise skip.
         fpArgs = case as of
                    []            -> []
-                   ((m, _):args) -> case kindOf m of
-                                      KUserSort "RoundingMode" _ -> case checkRM (m `lookup` consts) of
-                                                                      Nothing          -> args
-                                                                      Just (Left  msg) -> die msg
-                                                                      Just (Right msg) -> tbd msg
-                                      _                          -> as
+                   ((m, _):args)
+                     | isRoundingMode m -> case checkRM (m `lookup` consts) of
+                                             Nothing          -> args
+                                             Just (Left  msg) -> die msg
+                                             Just (Right msg) -> tbd msg
+                     | True              -> as
 
         -- Check that the RM is RoundNearestTiesToEven.
         -- If we start supporting other rounding-modes, this would be the point where we'd insert the rounding-mode set/reset code
         -- instead of merely returning OK or not
-        checkRM (Just cv@(CW (KUserSort "RoundingMode" _) v)) =
-              case v of
-                CWUserSort (_, "RoundNearestTiesToEven") -> Nothing
-                CWUserSort (_, s)                        -> Just (Right $ "handleIEEE: Unsupported rounding-mode: " ++ show s ++ " for: " ++ show w)
-                _                                        -> Just (Left  $ "handleIEEE: Unexpected value for rounding-mode: " ++ show cv ++ " for: " ++ show w)
+        checkRM (Just cv@(CV k v))
+          | k == kRoundingMode = case v of
+                                   CADT ("RoundNearestTiesToEven", []) -> Nothing
+                                   CADT (s,                        []) -> Just (Right $ "handleIEEE: Unsupported rounding-mode: " ++ show s ++ " for: " ++ show w)
+                                   _                                   -> Just (Left  $ "handleIEEE: Unexpected value for rounding-mode: " ++ show cv ++ " for: " ++ show w)
         checkRM (Just cv) = Just (Left  $ "handleIEEE: Expected rounding-mode, but got: " ++ show cv ++ " for: " ++ show w)
         checkRM Nothing   = Just (Right $ "handleIEEE: Non-constant rounding-mode for: " ++ show w)
 
@@ -608,44 +722,60 @@
         -- In C, the second argument is returned. (I think, might depend on the architecture, optimizations etc.).
         -- We'll translate it so that we deterministically return +0.
         -- There's really no good choice here.
-        wrapMinMax k a b s = parens cond <+> text "?" <+> zero <+> text ":" <+> s
-          where zero = text $ if k == KFloat then showCFloat 0 else showCDouble 0
-                cond =                   parens (text "FP_ZERO == fpclassify" <> parens a)                                      -- a is zero
-                       <+> text "&&" <+> parens (text "FP_ZERO == fpclassify" <> parens b)                                      -- b is zero
-                       <+> text "&&" <+> parens (text "signbit" <> parens a <+> text "!=" <+> text "signbit" <> parens b)       -- a and b differ in sign
+        wrapMinMax k a b s = parens cond <+> text "?" <+> fzero <+> text ":" <+> s
+          where fzero = text $ if k == KFloat then showCFloat 0 else showCDouble 0
+                cond  =                   parens (text "FP_ZERO == fpclassify" P.<> parens a)                                  -- a is zero
+                        <+> text "&&" <+> parens (text "FP_ZERO == fpclassify" P.<> parens b)                                  -- b is zero
+                        <+> text "&&" <+> parens (text "signbit" P.<> parens a <+> text "!=" <+> text "signbit" P.<> parens b) -- a and b differ in sign
 
-ppExpr :: CgConfig -> [(SW, CW)] -> SBVExpr -> Doc -> (Doc, Doc) -> Doc
+ppExpr :: CgConfig -> [(SV, CV)] -> SBVExpr -> Doc -> (Doc, Doc) -> Doc
 ppExpr cfg consts (SBVApp op opArgs) lhs (typ, var)
   | doNotAssign op
-  = typ <+> var <> semi <+> rhs
+  = typ <+> var P.<> semi <+> rhs
   | True
   = lhs <+> text "=" <+> rhs
   where doNotAssign (IEEEFP FP_Reinterpret{}) = True   -- generates a memcpy instead; no simple assignment
         doNotAssign _                         = False  -- generates simple assignment
-        rhs = p op (map (showSW cfg consts) opArgs)
+
+        rhs = p op (map (showSV cfg consts) opArgs)
+
         rtc = cgRTC cfg
+
         cBinOps = [ (Plus, "+"),  (Times, "*"), (Minus, "-")
-                  , (Equal, "=="), (NotEqual, "!="), (LessThan, "<"), (GreaterThan, ">"), (LessEq, "<="), (GreaterEq, ">=")
+                  , (Equal False, "==")  -- no strong equality!
+                  , (NotEqual, "!="), (LessThan, "<"), (GreaterThan, ">"), (LessEq, "<="), (GreaterEq, ">=")
                   , (And, "&"), (Or, "|"), (XOr, "^")
                   ]
+
+        -- see if we can find a constant shift; makes the output way more readable
+        getShiftAmnt def [_, sv] = case sv `lookup` consts of
+                                    Just (CV _  (CInteger i)) -> integer i
+                                    _                         -> def
+        getShiftAmnt def _       = def
+
+        hd _ (h:_) = h
+        hd w []    = error $ "Data.SBV.C.ppExpr: Impossible happened: " ++ w ++ ", received empty list!"
+
         p :: Op -> [Doc] -> Doc
-        p (ArrRead _)       _  = tbd "User specified arrays (ArrRead)"
-        p (ArrEq _ _)       _  = tbd "User specified arrays (ArrEq)"
+        p ReadArray{}       _  = tbd "User specified arrays (ReadArray)"
+        p WriteArray{}      _  = tbd "User specified arrays (WriteArray)"
         p (Label s)        [a] = a <+> text "/*" <+> text s <+> text "*/"
-        p (IEEEFP w)        as = handleIEEE w consts (zip opArgs as) var
+        p (IEEEFP w)         as = handleIEEE w  consts (zip opArgs as) var
+        p (PseudoBoolean pb) as = handlePB pb as
+        p (OverflowOp o) _      = tbd $ "Overflow operations" ++ show o
         p (KindCast _ to)   [a] = parens (text (show to)) <+> a
-        p (Uninterpreted s) [] = text "/* Uninterpreted constant */" <+> text s
-        p (Uninterpreted s) as = text "/* Uninterpreted function */" <+> text s <> parens (fsep (punctuate comma as))
-        p (Extract i j) [a]    = extract i j (head opArgs) a
+        p (Uninterpreted s) [] = text "/* Uninterpreted constant */" <+> text (T.unpack s)
+        p (Uninterpreted s) as = text "/* Uninterpreted function */" <+> text (T.unpack s) P.<> parens (fsep (punctuate comma as))
+        p (Extract i j) [a]    = extract i j (hd "Extract" opArgs) a
         p Join [a, b]          = join (let (s1 : s2 : _) = opArgs in (s1, s2, a, b))
-        p (Rol i) [a]          = rotate True  i a (head opArgs)
-        p (Ror i) [a]          = rotate False i a (head opArgs)
-        p (Shl i) [a]          = shift  True  i a (head opArgs)
-        p (Shr i) [a]          = shift  False i a (head opArgs)
-        p Not [a]              = case kindOf (head opArgs) of
+        p (Rol i) [a]          = rotate True  i a (hd "Rol" opArgs)
+        p (Ror i) [a]          = rotate False i a (hd "Ror" opArgs)
+        p Shl     [a, i]       = shift  True  (getShiftAmnt i opArgs) a -- The order of i/a being reversed here is
+        p Shr     [a, i]       = shift  False (getShiftAmnt i opArgs) a -- intentional and historical (from the days when Shl/Shr had a constant parameter.)
+        p Not [a]              = case kindOf (hd "Not" opArgs) of
                                    -- be careful about booleans, bitwise complement is not correct for them!
-                                   KBool -> text "!" <> a
-                                   _     -> text "~" <> a
+                                   KBool -> text "!" P.<> a
+                                   _     -> text "~" P.<> a
         p Ite [a, b, c] = a <+> text "?" <+> b <+> text ":" <+> c
         p (LkUp (t, k, _, len) ind def) []
           | not rtc                    = lkUp -- ignore run-time-checks per user request
@@ -653,44 +783,87 @@
           | needsCheckL                = cndLkUp checkLeft
           | needsCheckR                = cndLkUp checkRight
           | True                       = lkUp
-          where [index, defVal] = map (showSW cfg consts) [ind, def]
-                lkUp = text "table" <> int t <> brackets (showSW cfg consts ind)
+          where [index, defVal] = map (showSV cfg consts) [ind, def]
+
+                lkUp = text "table" P.<> int t P.<> brackets (showSV cfg consts ind)
                 cndLkUp cnd = cnd <+> text "?" <+> defVal <+> text ":" <+> lkUp
+
                 checkLeft  = index <+> text "< 0"
                 checkRight = index <+> text ">=" <+> int len
                 checkBoth  = parens (checkLeft <+> text "||" <+> checkRight)
+
                 canOverflow True  sz = (2::Integer)^(sz-1)-1 >= fromIntegral len
                 canOverflow False sz = (2::Integer)^sz    -1 >= fromIntegral len
+
                 (needsCheckL, needsCheckR) = case k of
+                                               KVar{}          -> die $ "array index with variable: " ++ show k
                                                KBool           -> (False, canOverflow False (1::Int))
                                                KBounded sg sz  -> (sg, canOverflow sg sz)
                                                KReal           -> die "array index with real value"
                                                KFloat          -> die "array index with float value"
                                                KDouble         -> die "array index with double value"
+                                               KFP{}           -> die "array index with arbitrary float value"
+                                               KRational       -> die "array index with rational value"
+                                               KString         -> die "array index with string value"
+                                               KChar           -> die "array index with character value"
                                                KUnbounded      -> case cgInteger cfg of
                                                                     Nothing -> (True, True) -- won't matter, it'll be rejected later
                                                                     Just i  -> (True, canOverflow True i)
-                                               KUserSort s _   -> die $ "Uninterpreted sort: " ++ s
+                                               KList     s     -> die $ "List sort "   ++ show s
+                                               KSet      s     -> die $ "Set sort "    ++ show s
+                                               KTuple    s     -> die $ "Tuple sort "  ++ show s
+                                               KArray    k1 k2 -> die $ "Array  sort " ++ show (k1, k2)
+                                               KApp      s _   -> die $ "ADT app: " ++ s
+                                               KADT      s _ _ -> die $ "ADT: "     ++ s
+
         -- Div/Rem should be careful on 0, in the SBV world x `div` 0 is 0, x `rem` 0 is x
         -- NB: Quot is supposed to truncate toward 0; Not clear to me if C guarantees this behavior.
         -- Brief googling suggests C99 does indeed truncate toward 0, but other C compilers might differ.
-        p Quot [a, b] = let k = kindOf (head opArgs)
-                            z = mkConst cfg $ mkConstCW k (0::Integer)
+        p Quot [a, b] = let k = kindOf (hd "Quot" opArgs)
+                            z = mkConst cfg $ mkConstCV k (0::Integer)
                         in protectDiv0 k "/" z a b
-        p Rem  [a, b] = protectDiv0 (kindOf (head opArgs)) "%" a a b
+        p Rem  [a, b] = protectDiv0 (kindOf (hd "Rem" opArgs)) "%" a a b
         p UNeg [a]    = parens (text "-" <+> a)
-        p Abs  [a]    = let f = case kindOf (head opArgs) of
-                                  KFloat  -> text "fabsf"
-                                  KDouble -> text "fabs"
-                                  _       -> text "abs"
-                        in f <> parens a
+        p Abs  [a]    = let f KFloat             = text "fabsf" P.<> parens a
+                            f KDouble            = text "fabs"  P.<> parens a
+                            f (KBounded False _) = text "/* unsigned, skipping call to abs */" <+> a
+                            f (KBounded True 32) = text "labs"  P.<> parens a
+                            f (KBounded True 64) = text "llabs" P.<> parens a
+                            f KUnbounded         = case cgInteger cfg of
+                                                     Nothing -> f $ KBounded True 32 -- won't matter, it'll be rejected later
+                                                     Just i  -> f $ KBounded True i
+                            f KReal              = case cgReal cfg of
+                                                     Nothing           -> f KDouble -- won't matter, it'll be rejected later
+                                                     Just CgFloat      -> f KFloat
+                                                     Just CgDouble     -> f KDouble
+                                                     Just CgLongDouble -> text "fabsl" P.<> parens a
+                            f _                  = text "abs" P.<> parens a
+                        in f (kindOf (hd "Abs" opArgs))
         -- for And/Or, translate to boolean versions if on boolean kind
-        p And [a, b] | kindOf (head opArgs) == KBool = a <+> text "&&" <+> b
-        p Or  [a, b] | kindOf (head opArgs) == KBool = a <+> text "||" <+> b
+        p And [a, b] | kindOf (hd "And" opArgs) == KBool = a <+> text "&&" <+> b
+        p Or  [a, b] | kindOf (hd "Or"  opArgs) == KBool = a <+> text "||" <+> b
         p o [a, b]
           | Just co <- lookup o cBinOps
           = a <+> text co <+> b
+
+        p Implies [a, b] | kindOf (hd "Implies" opArgs) == KBool = parens (text "!" P.<> a <+> text "||" <+> b)
+
+        p NotEqual xs = mkDistinct xs
         p o args = die $ "Received operator " ++ show o ++ " applied to " ++ show args
+
+        -- generate a pairwise inequality check
+        mkDistinct args = fsep $ andAll $ walk args
+          where walk []     = []
+                walk (e:es) = map (pair e) es ++ walk es
+
+                pair e1 e2  = parens (e1 <+> text "!=" <+> e2)
+
+                -- like punctuate, but more spacing
+                andAll []     = []
+                andAll (d:ds) = go d ds
+                     where go d' [] = [d']
+                           go d' (e:es) = (d' <+> text "&&") : go e es
+
         -- Div0 needs to protect, but only when the arguments are not float/double. (Div by 0 for those are well defined to be Inf/NaN etc.)
         protectDiv0 k divOp def a b = case k of
                                         KFloat  -> res
@@ -698,15 +871,11 @@
                                         _       -> wrap
            where res  = a <+> text divOp <+> b
                  wrap = parens (b <+> text "== 0") <+> text "?" <+> def <+> text ":" <+> parens res
-        shift toLeft i a s
-          | i < 0   = shift (not toLeft) (-i) a s
-          | i == 0  = a
-          | True    = case kindOf s of
-                        KBounded _ sz | i >= sz -> mkConst cfg $ mkConstCW (kindOf s) (0::Integer)
-                        KReal                   -> tbd $ "Shift for real quantity: " ++ show (toLeft, i, s)
-                        _                       -> a <+> text cop <+> int i
+
+        shift toLeft i a = a <+> text cop <+> i
           where cop | toLeft = "<<"
                     | True   = ">>"
+
         rotate toLeft i a s
           | i < 0   = rotate (not toLeft) (-i) a s
           | i == 0  = a
@@ -716,31 +885,43 @@
                         KBounded False sz           ->     parens (a <+> text cop  <+> int i)
                                                       <+> text "|"
                                                       <+> parens (a <+> text cop' <+> int (sz - i))
-                        KUnbounded                  -> shift toLeft i a s -- For SInteger, rotate is the same as shift in Haskell
+                        KUnbounded                  -> shift toLeft (int i) a -- For SInteger, rotate is the same as shift in Haskell
                         _                           -> tbd $ "Rotation for unbounded quantity: " ++ show (toLeft, i, s)
           where (cop, cop') | toLeft = ("<<", ">>")
                             | True   = (">>", "<<")
+
         -- TBD: below we only support the values for extract that are "easy" to implement. These should cover
         -- almost all instances actually generated by SBV, however.
         extract hi lo i a  -- Isolate the bit-extraction case
           | hi == lo, KBounded _ sz <- kindOf i, hi < sz, hi >= 0
-          = text "(SBool)" <+> parens (parens (a <+> text ">>" <+> int hi) <+> text "& 1")
-        extract hi lo i a = case (hi, lo, kindOf i) of
-                              (63, 32, KBounded False 64) -> text "(SWord32)" <+> parens (a <+> text ">> 32")
-                              (31,  0, KBounded False 64) -> text "(SWord32)" <+> a
-                              (31, 16, KBounded False 32) -> text "(SWord16)" <+> parens (a <+> text ">> 16")
-                              (15,  0, KBounded False 32) -> text "(SWord16)" <+> a
-                              (15,  8, KBounded False 16) -> text "(SWord8)"  <+> parens (a <+> text ">> 8")
-                              ( 7,  0, KBounded False 16) -> text "(SWord8)"  <+> a
-                              (63,  0, KBounded False 64) -> text "(SInt64)"  <+> a
-                              (63,  0, KBounded True  64) -> text "(SWord64)" <+> a
-                              (31,  0, KBounded False 32) -> text "(SInt32)"  <+> a
-                              (31,  0, KBounded True  32) -> text "(SWord32)" <+> a
-                              (15,  0, KBounded False 16) -> text "(SInt16)"  <+> a
-                              (15,  0, KBounded True  16) -> text "(SWord16)" <+> a
-                              ( 7,  0, KBounded False  8) -> text "(SInt8)"   <+> a
-                              ( 7,  0, KBounded True   8) -> text "(SWord8)"  <+> a
-                              ( _,  _, k                ) -> tbd $ "extract with " ++ show (hi, lo, k, i)
+          = if hi == 0
+            then text "(SBool)" <+> parens (a <+> text "& 1")
+            else text "(SBool)" <+> parens (parens (a <+> text ">>" <+> int hi) <+> text "& 1")
+        extract hi lo i a
+          | srcSize `notElem` [64, 32, 16]
+          = bad "Unsupported source size"
+          | (hi + 1) `mod` 8 /= 0 || lo `mod` 8 /= 0
+          = bad "Unsupported non-byte-aligned extraction"
+          | tgtSize < 8 || tgtSize `mod` 8 /= 0
+          = bad "Unsupported target size"
+          | True
+          = text cast <+> shifted
+          where bad why    = tbd $ "extract with " ++ show (hi, lo, k, i) ++ " (Reason: " ++ why ++ ".)"
+
+                k          = kindOf i
+                srcSize    = intSizeOf k
+                tgtSize    = hi - lo + 1
+                signChange = srcSize == tgtSize
+
+                cast
+                  | signChange && hasSign k = "(SWord" ++ show srcSize ++ ")"
+                  | signChange              = "(SInt"  ++ show srcSize ++ ")"
+                  | True                    = "(SWord" ++ show tgtSize ++ ")"
+
+                shifted
+                  | lo == 0 = a
+                  | True    = parens (a <+> text ">>" <+> int lo)
+
         -- TBD: ditto here for join, just like extract above
         join (i, j, a, b) = case (kindOf i, kindOf j) of
                               (KBounded False  8, KBounded False  8) -> parens (parens (text "(SWord16)" <+> a) <+> text "<< 8")  <+> text "|" <+> parens (text "(SWord16)" <+> b)
@@ -768,17 +949,21 @@
         l     = maximum (0 : map length ss)
         pad s = replicate (l - length s) ' ' ++ s
 
--- | Merge a bunch of bundles to generate code for a library
-mergeToLib :: String -> [CgPgmBundle] -> CgPgmBundle
-mergeToLib libName bundles
+-- | Merge a bunch of bundles to generate code for a library. For the final
+-- config, we simply return the first config we receive, or the default if none.
+mergeToLib :: String -> [(CgConfig, CgPgmBundle)] -> (CgConfig, CgPgmBundle)
+mergeToLib libName cfgBundles
   | length nubKinds /= 1
   = error $  "Cannot merge programs with differing SInteger/SReal mappings. Received the following kinds:\n"
           ++ unlines (map show nubKinds)
   | True
-  = CgPgmBundle bundleKind $ sources ++ libHeader : [libDriver | anyDriver] ++ [libMake | anyMake]
-  where kinds       = [k | CgPgmBundle k _ <- bundles]
+  = (finalCfg, CgPgmBundle bundleKind $ sources ++ libHeader : [libDriver | anyDriver] ++ [libMake | anyMake])
+  where bundles     = map snd cfgBundles
+        kinds       = [k | CgPgmBundle k _ <- bundles]
         nubKinds    = nub kinds
-        bundleKind  = head nubKinds
+        bundleKind  = case nubKinds of
+                        bk:_ -> bk
+                        []   -> error "Data.SBV.C: Impossible happened: mergeLibs: kinds ended up being empty!"
         files       = concat [fs | CgPgmBundle _ fs <- bundles]
         sigs        = concat [ss | (_, (CgHeader ss, _)) <- files]
         anyMake     = not (null [() | (_, (CgMakefile{}, _)) <- files])
@@ -791,6 +976,9 @@
         libHInclude = text "#include" <+> text (show (libName ++ ".h"))
         libMake     = ("Makefile", (CgMakefile mkFlags, [genLibMake anyDriver libName sourceNms mkFlags]))
         libDriver   = (libName ++ "_driver.c", (CgDriver, mergeDrivers libName libHInclude (zip (map takeBaseName sourceNms) drivers)))
+        finalCfg    = case cfgBundles of
+                        []         -> defaultCgConfig
+                        ((c, _):_) -> c
 
 -- | Create a Makefile for the library
 genLibMake :: Bool -> String -> [String] -> [String] -> Doc
@@ -798,24 +986,24 @@
  where ifld = not (null ldFlags)
        ld | ifld = text "${LDFLAGS}"
           | True = empty
-       lns = [ (True, text "# Makefile for" <+> nm <> text ". Automatically generated by SBV. Do not edit!")
+       lns = [ (True, text "# Makefile for" <+> nm P.<> text ". Automatically generated by SBV. Do not edit!")
              , (True,  text "")
              , (True,  text "# include any user-defined .mk file in the current directory.")
              , (True,  text "-include *.mk")
              , (True,  text "")
              , (True,  text "CC?=gcc")
              , (True,  text "CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer")
-             , (ifld,  text "LDFLAGS?=" <> text (unwords ldFlags))
+             , (ifld,  text "LDFLAGS?=" P.<> text (unwords ldFlags))
              , (True,  text "AR?=ar")
              , (True,  text "ARFLAGS?=cr")
              , (True,  text "")
              , (not ifdr,  text ("all: " ++ liba))
              , (ifdr,      text ("all: " ++ unwords [liba, libd]))
              , (True,  text "")
-             , (True,  text liba <> text (": " ++ unwords os))
+             , (True,  text liba P.<> text (": " ++ unwords os))
              , (True,  text "\t${AR} ${ARFLAGS} $@ $^")
              , (True,  text "")
-             , (ifdr,  text libd <> text (": " ++ unwords [libd ++ ".c", libh]))
+             , (ifdr,  text libd P.<> text (": " ++ unwords [libd ++ ".c", libh]))
              , (ifdr,  text ("\t${CC} ${CCFLAGS} $< -o $@ " ++ liba) <+> ld)
              , (ifdr,  text "")
              , (True,  vcat (zipWith mkObj os fs))
@@ -832,14 +1020,14 @@
        libh = libName ++ ".h"
        libd = libName ++ "_driver"
        os   = map (`replaceExtension` ".o") fs
-       mkObj o f =  text o <> text (": " ++ unwords [f, libh])
+       mkObj o f =  text o P.<> text (": " ++ unwords [f, libh])
                  $$ text "\t${CC} ${CCFLAGS} -c $< -o $@"
                  $$ text ""
 
 -- | Create a driver for a library
 mergeDrivers :: String -> Doc -> [(FilePath, [Doc])] -> [Doc]
 mergeDrivers libName inc ds = pre : concatMap mkDFun ds ++ [callDrivers (map fst ds)]
-  where pre =  text "/* Example driver program for" <+> text libName <> text ". */"
+  where pre =  text "/* Example driver program for" <+> text libName P.<> text ". */"
             $$ text "/* Automatically generated by SBV. Edit as you see fit! */"
             $$ text ""
             $$ text "#include <stdio.h>"
@@ -866,4 +1054,31 @@
                  lsep = replicate (length tag) '='
                  psep = "printf(\"" ++ lsep ++ "\\n\");"
 
-{-# ANN module ("HLint: ignore Redundant lambda" :: String) #-}
+-- Does this operation with this result kind require an LD flag?
+getLDFlag :: (Op, Kind) -> [String]
+getLDFlag (o, k) = flag o
+  where math = ["-lm"]
+
+        flag (IEEEFP FP_Cast{})                                     = math
+        flag (IEEEFP fop)       | fop `elem` requiresMath           = math
+        flag Abs                | k `elem` [KFloat, KDouble, KReal] = math
+        flag _                                                      = []
+
+        requiresMath = [ FP_Abs
+                       , FP_FMA
+                       , FP_Sqrt
+                       , FP_Rem
+                       , FP_Min
+                       , FP_Max
+                       , FP_RoundToIntegral
+                       , FP_ObjEqual
+                       , FP_IsSubnormal
+                       , FP_IsInfinite
+                       , FP_IsNaN
+                       , FP_IsNegative
+                       , FP_IsPositive
+                       , FP_IsNormal
+                       , FP_IsZero
+                       ]
+
+{- HLint ignore module "Redundant lambda" -}
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,22 +1,48 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Compilers.CodeGen
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Compilers.CodeGen
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Code generation utilities
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 
-module Data.SBV.Compilers.CodeGen where
+{-# OPTIONS_GHC -Wall -Werror #-}
 
+module Data.SBV.Compilers.CodeGen (
+        -- * The codegen monad
+          SBVCodeGen(..), cgSym
+
+        -- * Specifying inputs, SBV variants
+        , cgInput,  cgInputArr
+        , cgOutput, cgOutputArr
+        , cgReturn, cgReturnArr
+
+        -- * Specifying inputs, SVal variants
+        , svCgInput,  svCgInputArr
+        , svCgOutput, svCgOutputArr
+        , svCgReturn, svCgReturnArr
+
+        -- * Settings
+        , cgPerformRTCs, cgSetDriverValues
+        , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert, cgOverwriteFiles, cgShowU8UsingHex
+        , cgIntegerSize, cgSRealType, CgSRealType(..)
+
+        -- * Infrastructure
+        , CgTarget(..), CgConfig(..), CgState(..), CgPgmBundle(..), CgPgmKind(..), CgVal(..)
+        , defaultCgConfig, initCgState, isCgDriver, isCgMakefile
+
+        -- * Generating collateral
+        , cgGenerateDriver, cgGenerateMakefile, codeGen, renderCgPgmBundle
+        ) where
+
 import Control.Monad             (filterM, replicateM, unless)
-import Control.Monad.Trans
-import Control.Monad.State.Lazy  (MonadState, StateT(..), modify)
+import Control.Monad.Trans       (MonadIO(liftIO), lift)
+import Control.Monad.State.Lazy  (MonadState, StateT(..), modify')
 import Data.Char                 (toLower, isSpace)
 import Data.List                 (nub, isPrefixOf, intercalate, (\\))
 import System.Directory          (createDirectoryIfMissing, doesDirectoryExist, doesFileExist)
@@ -26,11 +52,10 @@
 import           Text.PrettyPrint.HughesPJ      (Doc, vcat)
 import qualified Text.PrettyPrint.HughesPJ as P (render)
 
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Symbolic (svToSymSW, svMkSymVar, outputSVal)
+import Data.SBV.Core.Data
+import Data.SBV.Core.Symbolic (MonadSymbolic(..), svToSymSV, svMkSymVar, outputSVal, VarContext(..))
 
-import Prelude ()
-import Prelude.Compat
+import Data.SBV.Provers.Prover(defaultSMTCfg)
 
 -- | Abstract over code generation for different languages
 class CgTarget a where
@@ -39,70 +64,73 @@
 
 -- | Options for code-generation.
 data CgConfig = CgConfig {
-          cgRTC           :: Bool               -- ^ If 'True', perform run-time-checks for index-out-of-bounds or shifting-by-large values etc.
-        , cgInteger       :: Maybe Int          -- ^ Bit-size to use for representing SInteger (if any)
-        , cgReal          :: Maybe CgSRealType  -- ^ Type to use for representing SReal (if any)
-        , cgDriverVals    :: [Integer]          -- ^ Values to use for the driver program generated, useful for generating non-random drivers.
-        , cgGenDriver     :: Bool               -- ^ If 'True', will generate a driver program
-        , cgGenMakefile   :: Bool               -- ^ If 'True', will generate a makefile
-        , cgIgnoreAsserts :: Bool               -- ^ If 'True', will ignore 'sAssert' calls
+          cgRTC                :: Bool               -- ^ If 'True', perform run-time-checks for index-out-of-bounds or shifting-by-large values etc.
+        , cgInteger            :: Maybe Int          -- ^ Bit-size to use for representing SInteger (if any)
+        , cgReal               :: Maybe CgSRealType  -- ^ Type to use for representing SReal (if any)
+        , cgDriverVals         :: [Integer]          -- ^ Values to use for the driver program generated, useful for generating non-random drivers.
+        , cgGenDriver          :: Bool               -- ^ If 'True', will generate a driver program
+        , cgGenMakefile        :: Bool               -- ^ If 'True', will generate a makefile
+        , cgIgnoreAsserts      :: Bool               -- ^ If 'True', will ignore 'Data.SBV.sAssert' calls
+        , cgOverwriteGenerated :: Bool               -- ^ If 'True', will overwrite the generated files without prompting.
+        , cgShowU8InHex        :: Bool               -- ^ If 'True', then 8-bit unsigned values will be shown in hex as well, otherwise decimal. (Other types always shown in hex.)
         }
 
 -- | Default options for code generation. The run-time checks are turned-off, and the driver values are completely random.
 defaultCgConfig :: CgConfig
-defaultCgConfig = CgConfig { cgRTC           = False
-                           , cgInteger       = Nothing
-                           , cgReal          = Nothing
-                           , cgDriverVals    = []
-                           , cgGenDriver     = True
-                           , cgGenMakefile   = True
-                           , cgIgnoreAsserts = False
+defaultCgConfig = CgConfig { cgRTC                = False
+                           , cgInteger            = Nothing
+                           , cgReal               = Nothing
+                           , cgDriverVals         = []
+                           , cgGenDriver          = True
+                           , cgGenMakefile        = True
+                           , cgIgnoreAsserts      = False
+                           , cgOverwriteGenerated = False
+                           , cgShowU8InHex        = False
                            }
 
 -- | Abstraction of target language values
-data CgVal = CgAtomic SW
-           | CgArray  [SW]
+data CgVal = CgAtomic SV
+           | CgArray  [SV]
 
 -- | Code-generation state
 data CgState = CgState {
-          cgInputs       :: [(String, CgVal)]
-        , cgOutputs      :: [(String, CgVal)]
-        , cgReturns      :: [CgVal]
-        , cgPrototypes   :: [String]    -- extra stuff that goes into the header
-        , cgDecls        :: [String]    -- extra stuff that goes into the top of the file
-        , cgLDFlags      :: [String]    -- extra options that go to the linker
-        , cgFinalConfig  :: CgConfig
+          cgInputs         :: [(String, CgVal)]
+        , cgOutputs        :: [(String, CgVal)]
+        , cgReturns        :: [CgVal]
+        , cgPrototypes     :: [String]    -- extra stuff that goes into the header
+        , cgDecls          :: [String]    -- extra stuff that goes into the top of the file
+        , cgLDFlags        :: [String]    -- extra options that go to the linker
+        , cgFinalConfig    :: CgConfig
         }
 
 -- | Initial configuration for code-generation
 initCgState :: CgState
 initCgState = CgState {
-          cgInputs        = []
-        , cgOutputs       = []
-        , cgReturns       = []
-        , cgPrototypes    = []
-        , cgDecls         = []
-        , cgLDFlags       = []
-        , cgFinalConfig   = defaultCgConfig
+          cgInputs         = []
+        , cgOutputs        = []
+        , cgReturns        = []
+        , cgPrototypes     = []
+        , cgDecls          = []
+        , cgLDFlags        = []
+        , cgFinalConfig    = defaultCgConfig
         }
 
 -- | The code-generation monad. Allows for precise layout of input values
 -- reference parameters (for returning composite values in languages such as C),
 -- and return values.
 newtype SBVCodeGen a = SBVCodeGen (StateT CgState Symbolic a)
-                   deriving (Applicative, Functor, Monad, MonadIO, MonadState CgState)
+                   deriving ( Applicative, Functor, Monad, MonadIO, MonadState CgState
+                            , MonadSymbolic
+                            , MonadFail
+                            )
 
 -- | Reach into symbolic monad from code-generation
-liftSymbolic :: Symbolic a -> SBVCodeGen a
-liftSymbolic = SBVCodeGen . lift
-
--- | Reach into symbolic monad and output a value. Returns the corresponding SW
-cgSBVToSW :: SBV a -> SBVCodeGen SW
-cgSBVToSW = liftSymbolic . sbvToSymSW
+cgSym :: Symbolic a -> SBVCodeGen a
+cgSym = SBVCodeGen . lift
 
 -- | Sets RTC (run-time-checks) for index-out-of-bounds, shift-with-large value etc. on/off. Default: 'False'.
 cgPerformRTCs :: Bool -> SBVCodeGen ()
-cgPerformRTCs b = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgRTC = b } })
+cgPerformRTCs b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgRTC = b } })
 
 -- | Sets number of bits to be used for representing the 'SInteger' type in the generated C code.
 -- The argument must be one of @8@, @16@, @32@, or @64@. Note that this is essentially unsafe as
@@ -113,7 +141,7 @@
   | i `notElem` [8, 16, 32, 64]
   = error $ "SBV.cgIntegerSize: Argument must be one of 8, 16, 32, or 64. Received: " ++ show i
   | True
-  = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgInteger = Just i }})
+  = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgInteger = Just i }})
 
 -- | Possible mappings for the 'SReal' type when translated to C. Used in conjunction
 -- with the function 'cgSRealType'. Note that the particular characteristics of the
@@ -124,7 +152,7 @@
                  | CgLongDouble -- ^ @long double@
                  deriving Eq
 
--- | 'Show' instance for 'cgSRealType' displays values as they would be used in a C program
+-- 'Show' instance for 'cgSRealType' displays values as they would be used in a C program
 instance Show CgSRealType where
   show CgFloat      = "float"
   show CgDouble     = "double"
@@ -136,136 +164,147 @@
 -- infinite precision SReal values becomes reduced to the corresponding floating point type in
 -- C, and hence it is subject to rounding errors.
 cgSRealType :: CgSRealType -> SBVCodeGen ()
-cgSRealType rt = modify (\s -> s {cgFinalConfig = (cgFinalConfig s) { cgReal = Just rt }})
+cgSRealType rt = modify' (\s -> s {cgFinalConfig = (cgFinalConfig s) { cgReal = Just rt }})
 
 -- | Should we generate a driver program? Default: 'True'. When a library is generated, it will have
--- a driver if any of the contituent functions has a driver. (See 'compileToCLib'.)
+-- a driver if any of the constituent functions has a driver. (See 'Data.SBV.Tools.CodeGen.compileToCLib'.)
 cgGenerateDriver :: Bool -> SBVCodeGen ()
-cgGenerateDriver b = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgGenDriver = b } })
+cgGenerateDriver b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgGenDriver = b } })
 
 -- | Should we generate a Makefile? Default: 'True'.
 cgGenerateMakefile :: Bool -> SBVCodeGen ()
-cgGenerateMakefile b = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgGenMakefile = b } })
+cgGenerateMakefile b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgGenMakefile = b } })
 
 -- | Sets driver program run time values, useful for generating programs with fixed drivers for testing. Default: None, i.e., use random values.
 cgSetDriverValues :: [Integer] -> SBVCodeGen ()
-cgSetDriverValues vs = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgDriverVals = vs } })
+cgSetDriverValues vs = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgDriverVals = vs } })
 
--- | Ignore assertions (those generated by 'sAssert' calls) in the generated C code
+-- | Ignore assertions (those generated by 'Data.SBV.sAssert' calls) in the generated C code
 cgIgnoreSAssert :: Bool -> SBVCodeGen ()
-cgIgnoreSAssert b = modify (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgIgnoreAsserts = b } })
+cgIgnoreSAssert b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgIgnoreAsserts = b } })
 
 -- | Adds the given lines to the header file generated, useful for generating programs with uninterpreted functions.
 cgAddPrototype :: [String] -> SBVCodeGen ()
-cgAddPrototype ss = modify (\s -> let old = cgPrototypes s
-                                      new = if null old then ss else old ++ [""] ++ ss
-                                  in s { cgPrototypes = new })
+cgAddPrototype ss = modify' (\s -> let old = cgPrototypes s
+                                       new = if null old then ss else old ++ [""] ++ ss
+                                   in s { cgPrototypes = new })
 
+-- | If passed 'True', then we will not ask the user if we're overwriting files as we generate
+-- the C code. Otherwise, we'll prompt.
+cgOverwriteFiles :: Bool -> SBVCodeGen ()
+cgOverwriteFiles b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgOverwriteGenerated = b } })
+
+-- | If passed 'True', then we will show 'SWord 8' type in hex. Otherwise we'll show it in decimal. All signed
+-- types are shown decimal, and all unsigned larger types are shown hexadecimal otherwise.
+cgShowU8UsingHex :: Bool -> SBVCodeGen ()
+cgShowU8UsingHex b = modify' (\s -> s { cgFinalConfig = (cgFinalConfig s) { cgShowU8InHex = b } })
+
+
 -- | Adds the given lines to the program file generated, useful for generating programs with uninterpreted functions.
 cgAddDecl :: [String] -> SBVCodeGen ()
-cgAddDecl ss = modify (\s -> s { cgDecls = cgDecls s ++ ss })
+cgAddDecl ss = modify' (\s -> s { cgDecls = cgDecls s ++ ss })
 
 -- | Adds the given words to the compiler options in the generated Makefile, useful for linking extra stuff in.
 cgAddLDFlags :: [String] -> SBVCodeGen ()
-cgAddLDFlags ss = modify (\s -> s { cgLDFlags = cgLDFlags s ++ ss })
+cgAddLDFlags ss = modify' (\s -> s { cgLDFlags = cgLDFlags s ++ ss })
 
 -- | Creates an atomic input in the generated code.
 svCgInput :: Kind -> String -> SBVCodeGen SVal
-svCgInput k nm = do r <- liftSymbolic (svMkSymVar (Just ALL) k Nothing)
-                    sw <- liftSymbolic (svToSymSW r)
-                    modify (\s -> s { cgInputs = (nm, CgAtomic sw) : cgInputs s })
-                    return r
+svCgInput k nm = do r  <- symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar (Just ALL)) k Nothing
+                    sv <- svToSymSV r
+                    modify' (\s -> s { cgInputs = (nm, CgAtomic sv) : cgInputs s })
+                    pure r
 
 -- | Creates an array input in the generated code.
 svCgInputArr :: Kind -> Int -> String -> SBVCodeGen [SVal]
 svCgInputArr k sz nm
   | sz < 1 = error $ "SBV.cgInputArr: Array inputs must have at least one element, given " ++ show sz ++ " for " ++ show nm
-  | True   = do rs <- liftSymbolic $ replicateM sz (svMkSymVar (Just ALL) k Nothing)
-                sws <- liftSymbolic $ mapM svToSymSW rs
-                modify (\s -> s { cgInputs = (nm, CgArray sws) : cgInputs s })
-                return rs
+  | True   = do rs  <- symbolicEnv >>= liftIO . replicateM sz . svMkSymVar (NonQueryVar (Just ALL)) k Nothing
+                sws <- mapM svToSymSV rs
+                modify' (\s -> s { cgInputs = (nm, CgArray sws) : cgInputs s })
+                pure rs
 
 -- | Creates an atomic output in the generated code.
 svCgOutput :: String -> SVal -> SBVCodeGen ()
-svCgOutput nm v = do _ <- liftSymbolic (outputSVal v)
-                     sw <- liftSymbolic (svToSymSW v)
-                     modify (\s -> s { cgOutputs = (nm, CgAtomic sw) : cgOutputs s })
+svCgOutput nm v = do _ <- outputSVal v
+                     sv <- svToSymSV v
+                     modify' (\s -> s { cgOutputs = (nm, CgAtomic sv) : cgOutputs s })
 
 -- | Creates an array output in the generated code.
 svCgOutputArr :: String -> [SVal] -> SBVCodeGen ()
 svCgOutputArr nm vs
   | sz < 1 = error $ "SBV.cgOutputArr: Array outputs must have at least one element, received " ++ show sz ++ " for " ++ show nm
-  | True   = do _ <- liftSymbolic (mapM outputSVal vs)
-                sws <- liftSymbolic (mapM svToSymSW vs)
-                modify (\s -> s { cgOutputs = (nm, CgArray sws) : cgOutputs s })
+  | True   = do mapM_ outputSVal vs
+                sws <- mapM svToSymSV vs
+                modify' (\s -> s { cgOutputs = (nm, CgArray sws) : cgOutputs s })
   where sz = length vs
 
 -- | Creates a returned (unnamed) value in the generated code.
 svCgReturn :: SVal -> SBVCodeGen ()
-svCgReturn v = do _ <- liftSymbolic (outputSVal v)
-                  sw <- liftSymbolic (svToSymSW v)
-                  modify (\s -> s { cgReturns = CgAtomic sw : cgReturns s })
+svCgReturn v = do _ <- outputSVal v
+                  sv <- svToSymSV v
+                  modify' (\s -> s { cgReturns = CgAtomic sv : cgReturns s })
 
 -- | Creates a returned (unnamed) array value in the generated code.
 svCgReturnArr :: [SVal] -> SBVCodeGen ()
 svCgReturnArr vs
   | sz < 1 = error $ "SBV.cgReturnArr: Array returns must have at least one element, received " ++ show sz
-  | True   = do _ <- liftSymbolic (mapM outputSVal vs)
-                sws <- liftSymbolic (mapM svToSymSW vs)
-                modify (\s -> s { cgReturns = CgArray sws : cgReturns s })
+  | True   = do mapM_ outputSVal vs
+                sws <- mapM svToSymSV vs
+                modify' (\s -> s { cgReturns = CgArray sws : cgReturns s })
   where sz = length vs
 
 -- | Creates an atomic input in the generated code.
-cgInput :: SymWord a => String -> SBVCodeGen (SBV a)
-cgInput nm = do r <- liftSymbolic forall_
-                sw <- cgSBVToSW r
-                modify (\s -> s { cgInputs = (nm, CgAtomic sw) : cgInputs s })
-                return r
+cgInput :: SymVal a => String -> SBVCodeGen (SBV a)
+cgInput nm = do r  <- free_
+                sv <- sbvToSymSV r
+                modify' (\s -> s { cgInputs = (nm, CgAtomic sv) : cgInputs s })
+                pure r
 
 -- | Creates an array input in the generated code.
-cgInputArr :: SymWord a => Int -> String -> SBVCodeGen [SBV a]
+cgInputArr :: SymVal a => Int -> String -> SBVCodeGen [SBV a]
 cgInputArr sz nm
   | sz < 1 = error $ "SBV.cgInputArr: Array inputs must have at least one element, given " ++ show sz ++ " for " ++ show nm
-  | True   = do rs <- liftSymbolic $ mapM (const forall_) [1..sz]
-                sws <- mapM cgSBVToSW rs
-                modify (\s -> s { cgInputs = (nm, CgArray sws) : cgInputs s })
-                return rs
+  | True   = do rs <- mapM (const free_) [1..sz]
+                sws <- mapM sbvToSymSV rs
+                modify' (\s -> s { cgInputs = (nm, CgArray sws) : cgInputs s })
+                pure rs
 
 -- | Creates an atomic output in the generated code.
 cgOutput :: String -> SBV a -> SBVCodeGen ()
-cgOutput nm v = do _ <- liftSymbolic (output v)
-                   sw <- cgSBVToSW v
-                   modify (\s -> s { cgOutputs = (nm, CgAtomic sw) : cgOutputs s })
+cgOutput nm v = do _ <- output v
+                   sv <- sbvToSymSV v
+                   modify' (\s -> s { cgOutputs = (nm, CgAtomic sv) : cgOutputs s })
 
 -- | Creates an array output in the generated code.
-cgOutputArr :: SymWord a => String -> [SBV a] -> SBVCodeGen ()
+cgOutputArr :: SymVal a => String -> [SBV a] -> SBVCodeGen ()
 cgOutputArr nm vs
   | sz < 1 = error $ "SBV.cgOutputArr: Array outputs must have at least one element, received " ++ show sz ++ " for " ++ show nm
-  | True   = do _ <- liftSymbolic (mapM output vs)
-                sws <- mapM cgSBVToSW vs
-                modify (\s -> s { cgOutputs = (nm, CgArray sws) : cgOutputs s })
+  | True   = do mapM_ output vs
+                sws <- mapM sbvToSymSV vs
+                modify' (\s -> s { cgOutputs = (nm, CgArray sws) : cgOutputs s })
   where sz = length vs
 
 -- | Creates a returned (unnamed) value in the generated code.
 cgReturn :: SBV a -> SBVCodeGen ()
-cgReturn v = do _ <- liftSymbolic (output v)
-                sw <- cgSBVToSW v
-                modify (\s -> s { cgReturns = CgAtomic sw : cgReturns s })
+cgReturn v = do _ <- output v
+                sv <- sbvToSymSV v
+                modify' (\s -> s { cgReturns = CgAtomic sv : cgReturns s })
 
 -- | Creates a returned (unnamed) array value in the generated code.
-cgReturnArr :: SymWord a => [SBV a] -> SBVCodeGen ()
+cgReturnArr :: SymVal a => [SBV a] -> SBVCodeGen ()
 cgReturnArr vs
   | sz < 1 = error $ "SBV.cgReturnArr: Array returns must have at least one element, received " ++ show sz
-  | True   = do _ <- liftSymbolic (mapM output vs)
-                sws <- mapM cgSBVToSW vs
-                modify (\s -> s { cgReturns = CgArray sws : cgReturns s })
+  | True   = do mapM_ output vs
+                sws <- mapM sbvToSymSV vs
+                modify' (\s -> s { cgReturns = CgArray sws : cgReturns s })
   where sz = length vs
 
 -- | Representation of a collection of generated programs.
 data CgPgmBundle = CgPgmBundle (Maybe Int, Maybe CgSRealType) [(FilePath, (CgPgmKind, [Doc]))]
 
 -- | Different kinds of "files" we can produce. Currently this is quite "C" specific.
-data CgPgmKind = CgMakefile [String]
+data CgPgmKind = CgMakefile [String]  -- list of flags to pass to linker
                | CgHeader [Doc]
                | CgSource
                | CgDriver
@@ -280,7 +319,7 @@
 isCgMakefile CgMakefile{} = True
 isCgMakefile _            = False
 
--- | A simple way to print bundles, mostly for debugging purposes.
+-- A simple way to print bundles, mostly for debugging purposes.
 instance Show CgPgmBundle where
    show (CgPgmBundle _ fs) = intercalate "\n" $ map showFile fs
     where showFile :: (FilePath, (CgPgmKind, [Doc])) -> String
@@ -290,42 +329,51 @@
 
 -- | Generate code for a symbolic program, returning a Code-gen bundle, i.e., collection
 -- of makefiles, source code, headers, etc.
-codeGen :: CgTarget l => l -> CgConfig -> String -> SBVCodeGen () -> IO CgPgmBundle
+codeGen :: CgTarget l => l -> CgConfig -> String -> SBVCodeGen a -> IO (a, CgConfig, CgPgmBundle)
 codeGen l cgConfig nm (SBVCodeGen comp) = do
-   (((), st'), res) <- runSymbolic' CodeGen $ runStateT comp initCgState { cgFinalConfig = cgConfig }
-   let st = st' { cgInputs       = reverse (cgInputs st')
-                , cgOutputs      = reverse (cgOutputs st')
+   ((retVal, st'), res) <- runSymbolic defaultSMTCfg CodeGen $ runStateT comp initCgState { cgFinalConfig = cgConfig }
+   let st = st' { cgInputs  = reverse (cgInputs st')
+                , cgOutputs = reverse (cgOutputs st')
                 }
        allNamedVars = map fst (cgInputs st ++ cgOutputs st)
        dupNames = allNamedVars \\ nub allNamedVars
    unless (null dupNames) $
         error $ "SBV.codeGen: " ++ show nm ++ " has following argument names duplicated: " ++ unwords dupNames
-   return $ translate l (cgFinalConfig st) nm st res
 
+   pure (retVal, cgFinalConfig st, translate l (cgFinalConfig st) nm st res)
+
 -- | Render a code-gen bundle to a directory or to stdout
-renderCgPgmBundle :: Maybe FilePath -> CgPgmBundle -> IO ()
-renderCgPgmBundle Nothing        bundle                = print bundle
-renderCgPgmBundle (Just dirName) (CgPgmBundle _ files) = do
+renderCgPgmBundle :: Maybe FilePath -> (CgConfig, CgPgmBundle) -> IO ()
+renderCgPgmBundle Nothing        (_  , bundle)              = print bundle
+renderCgPgmBundle (Just dirName) (cfg, CgPgmBundle _ files) = do
+
         b <- doesDirectoryExist dirName
-        unless b $ do putStrLn $ "Creating directory " ++ show dirName ++ ".."
+        unless b $ do unless overWrite $ putStrLn $ "Creating directory " ++ show dirName ++ ".."
                       createDirectoryIfMissing True dirName
+
         dups <- filterM (\fn -> doesFileExist (dirName </> fn)) (map fst files)
-        goOn <- case dups of
-                  [] -> return True
-                  _  -> do putStrLn $ "Code generation would override the following " ++ (if length dups == 1 then "file:" else "files:")
-                           mapM_ (\fn -> putStrLn ('\t' : fn)) dups
-                           putStr "Continue? [yn] "
-                           hFlush stdout
-                           resp <- getLine
-                           return $ map toLower resp `isPrefixOf` "yes"
+
+        goOn <- case (overWrite, dups) of
+                  (True, _) -> pure True
+                  (_,   []) -> pure True
+                  _         -> do putStrLn $ "Code generation would overwrite the following " ++ (if length dups == 1 then "file:" else "files:")
+                                  mapM_ (\fn -> putStrLn ('\t' : fn)) dups
+                                  putStr "Continue? [yn] "
+                                  hFlush stdout
+                                  resp <- getLine
+                                  pure $ map toLower resp `isPrefixOf` "yes"
+
         if goOn then do mapM_ renderFile files
-                        putStrLn "Done."
+                        unless overWrite $ putStrLn "Done."
                 else putStrLn "Aborting."
-  where renderFile (f, (_, ds)) = do let fn = dirName </> f
-                                     putStrLn $ "Generating: " ++ show fn ++ ".."
+
+  where overWrite = cgOverwriteGenerated cfg
+
+        renderFile (f, (_, ds)) = do let fn = dirName </> f
+                                     unless overWrite $ putStrLn $ "Generating: " ++ show fn ++ ".."
                                      writeFile fn (render' (vcat ds))
 
--- | An alternative to Pretty's 'render', which might have "leading" white-space in empty lines. This version
+-- | An alternative to Pretty's @render@, which might have "leading" white-space in empty lines. This version
 -- eliminates such whitespace.
 render' :: Doc -> String
 render' = unlines . map clean . lines . P.render
diff --git a/Data/SBV/Control.hs b/Data/SBV/Control.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Control.hs
@@ -0,0 +1,169 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Control
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Control sublanguage for interacting with SMT solvers.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Control (
+     -- $queryIntro
+
+     -- * User queries
+       ExtractIO(..), MonadQuery(..), Query, query
+
+     -- * Checking satisfiability
+     , CheckSatResult(..), checkSat, ensureSat, checkSatUsing, checkSatAssuming, checkSatAssumingWithUnsatisfiableSet
+
+     -- * Querying the solver
+     -- ** Extracting values
+     , getFunction, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+
+     -- ** Extracting the unsat core
+     , getUnsatCore
+
+     -- ** Getting the model value for a symbolic variable
+     , getValue
+
+     -- ** Extracting a proof
+     , getProof
+
+     -- ** Extracting interpolants
+     , getInterpolantMathSAT, getInterpolantZ3
+
+     -- ** Getting abducts
+     , getAbduct, getAbductNext
+
+     -- ** Extracting assertions
+     , getAssertions
+
+     -- * Getting solver information
+     , SMTInfoFlag(..), SMTErrorBehavior(..), SMTInfoResponse(..)
+     , getInfo, getOption
+
+     -- * Entering and exiting assertion stack
+     , getAssertionStackDepth, push, pop, inNewAssertionStack
+
+     -- * Higher level tactics
+     , caseSplit
+
+     -- * Resetting the solver state
+     , resetAssertions
+
+     -- * Constructing assignments
+     , (|->)
+
+     -- * Terminating the query
+     , mkSMTResult
+     , exit
+
+     -- * Controlling the solver behavior
+     , ignoreExitCode, timeout
+
+     -- * Miscellaneous
+     , queryDebug
+     , echo
+     , io
+
+     -- * Solver options
+     , SMTOption(..)
+     ) where
+
+import Data.SBV.Core.Symbolic (Symbolic, QueryContext(..), Query, MonadQuery(..), SMTConfig(..))
+
+import Data.SBV.Control.BaseIO
+import Data.SBV.Control.Types
+import Data.SBV.Control.Query ((|->))
+
+import Data.SBV.Utils.ExtractIO (ExtractIO(..))
+
+import qualified Data.SBV.Control.Utils as Trans
+
+-- | Run a custom query
+query :: Query a -> Symbolic a
+query = Trans.executeQuery QueryExternal
+
+{- $queryIntro
+In certain cases, the user might want to take over the communication with the solver, programmatically
+querying the engine and issuing commands accordingly. Queries can be extremely powerful as
+they allow direct control of the solver. Here's a simple example:
+
+@
+    module Test where
+
+    import Data.SBV
+    import Data.SBV.Control  -- queries require this module to be imported!
+
+    test :: Symbolic (Maybe (Integer, Integer))
+    test = do x <- sInteger "x"   -- a free variable named "x"
+              y <- sInteger "y"   -- a free variable named "y"
+
+              -- require the sum to be 10
+              constrain $ x + y .== 10
+
+              -- Go into the Query mode
+              query $ do
+                    -- Query the solver: Are the constraints satisfiable?
+                    cs <- checkSat
+                    case cs of
+                      Unk    -> error "Solver said unknown!"
+                      DSat{} -> error "Solver said DSat!"
+                      Unsat  -> return Nothing -- no solution!
+                      Sat    -> -- Query the values:
+                                do xv <- getValue x
+                                   yv <- getValue y
+
+                                   io $ putStrLn $ "Solver returned: " ++ show (xv, yv)
+
+                                   -- We can now add new constraints,
+                                   -- Or perform arbitrary computations and tell
+                                   -- the solver anything we want!
+                                   constrain $ x .> literal xv + literal yv
+
+                                   -- call checkSat again
+                                   csNew <- checkSat
+                                   case csNew of
+                                     Unk    -> error "Solver said unknown!"
+                                     DSat{} -> error "Solver said DSat!"
+                                     Unsat  -> return Nothing
+                                     Sat    -> do xv2 <- getValue x
+                                                  yv2 <- getValue y
+
+                                                  return $ Just (xv2, yv2)
+@
+
+Note the type of @test@: it returns an optional pair of integers in the 'Symbolic' monad. We turn
+it into an IO value with the 'Data.SBV.Control.runSMT' function: (There's also 'Data.SBV.Control.runSMTWith' that uses a user specified
+solver instead of the default. Note that 'Data.SBV.Provers.z3' is best supported (and tested), if you use another solver your results may vary!)
+
+@
+    pair :: IO (Maybe (Integer, Integer))
+    pair = runSMT test
+@
+
+When run, this can return:
+
+@
+*Test> pair
+Solver returned: (10,0)
+Just (11,-1)
+@
+
+demonstrating that the user has full contact with the solver and can guide it as the program executes. SBV
+provides access to many SMTLib features in the query mode, as exported from this very module.
+
+For other examples see:
+
+  - "Documentation.SBV.Examples.Queries.AllSat": Simulating SBV's 'Data.SBV.allSat' using queries.
+  - "Documentation.SBV.Examples.Queries.CaseSplit": Performing a case-split during a query.
+  - "Documentation.SBV.Examples.Queries.Enums": Using enumerations in queries.
+  - "Documentation.SBV.Examples.Queries.FourFours": Solution to a fun arithmetic puzzle, coded using queries.
+  - "Documentation.SBV.Examples.Queries.GuessNumber": The famous number guessing game.
+  - "Documentation.SBV.Examples.Queries.UnsatCore": Extracting unsat-cores using queries.
+  - "Documentation.SBV.Examples.Queries.Interpolants": Extracting interpolants using queries.
+-}
diff --git a/Data/SBV/Control/BaseIO.hs b/Data/SBV/Control/BaseIO.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Control/BaseIO.hs
@@ -0,0 +1,518 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Control.BaseIO
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Monomorphized versions of functions for simplified client use via
+-- @Data.SBV.Control@, where we restrict the underlying monad to be IO.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Control.BaseIO where
+
+import Data.SBV.Control.Query (Assignment)
+import Data.SBV.Control.Types (CheckSatResult, SMTInfoFlag, SMTInfoResponse, SMTOption, SMTReasonUnknown)
+import Data.SBV.Core.Concrete (CV)
+import Data.SBV.Core.Data     (Symbolic, SymVal, SBool, SBV, SBVType)
+import Data.SBV.Core.Symbolic (Query, QueryContext, QueryState, State, SMTModel, SMTResult, SV, Name)
+
+import Data.Text (Text)
+
+import qualified Data.SBV.Control.Query as Trans
+import qualified Data.SBV.Control.Utils as Trans
+
+import Data.SBV.Utils.SExpr (SExpr)
+
+-- | Ask solver for info.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getInfo'
+getInfo :: SMTInfoFlag -> Query SMTInfoResponse
+getInfo = Trans.getInfo
+
+-- | Retrieve the value of an 'SMTOption.' The curious function argument is on purpose here,
+-- simply pass the constructor name. Example: the call @'getOption' 'Data.SBV.Control.ProduceUnsatCores'@ will return
+-- either @Nothing@ or @Just (ProduceUnsatCores True)@ or @Just (ProduceUnsatCores False)@.
+--
+-- Result will be 'Nothing' if the solver does not support this option.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getOption'
+getOption :: (a -> SMTOption) -> Query (Maybe SMTOption)
+getOption = Trans.getOption
+
+-- | Get the reason unknown. Only internally used.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUnknownReason'
+getUnknownReason :: Query SMTReasonUnknown
+getUnknownReason = Trans.getUnknownReason
+
+-- | Get the observables recorded during a query run.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getObservables'
+getObservables :: Query [(Name, CV)]
+getObservables = Trans.getObservables
+
+-- | Get the uninterpreted 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, (Bool, Maybe [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'
+getSMTResult :: Query SMTResult
+getSMTResult = Trans.getSMTResult
+
+-- | Issue check-sat and get results of a lexicographic optimization.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getLexicographicOptResults'
+getLexicographicOptResults :: Query SMTResult
+getLexicographicOptResults = Trans.getLexicographicOptResults
+
+-- | Issue check-sat and get results of an independent (boxed) optimization.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getIndependentOptResults'
+getIndependentOptResults :: [String] -> Query [(String, SMTResult)]
+getIndependentOptResults = Trans.getIndependentOptResults
+
+-- | Construct a pareto-front optimization result
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getParetoOptResults'
+getParetoOptResults :: Maybe Int -> Query (Bool, [SMTResult])
+getParetoOptResults = Trans.getParetoOptResults
+
+-- | Collect model values. It is implicitly assumed that we are in a check-sat
+-- context. See 'getSMTResult' for a variant that issues a check-sat first and
+-- returns an 'SMTResult'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getModel'
+getModel :: Query SMTModel
+getModel = Trans.getModel
+
+-- | Check for satisfiability, under the given conditions. Similar to 'Data.SBV.Control.checkSat' except it allows making
+-- further assumptions as captured by the first argument of booleans. (Also see 'checkSatAssumingWithUnsatisfiableSet'
+-- for a variant that returns the subset of the given assumptions that led to the 'Data.SBV.Control.Unsat' conclusion.)
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.checkSatAssuming'
+checkSatAssuming :: [SBool] -> Query CheckSatResult
+checkSatAssuming = Trans.checkSatAssuming
+
+-- | Check for satisfiability, under the given conditions. Returns the unsatisfiable
+-- set of assumptions. Similar to 'Data.SBV.Control.checkSat' except it allows making further assumptions
+-- as captured by the first argument of booleans. If the result is 'Data.SBV.Control.Unsat', the user will
+-- also receive a subset of the given assumptions that led to the 'Data.SBV.Control.Unsat' conclusion. Note
+-- that while this set will be a subset of the inputs, it is not necessarily guaranteed to be minimal.
+--
+-- You must have arranged for the production of unsat assumptions
+-- first via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceUnsatAssumptions' 'True'
+-- @
+--
+-- for this call to not error out!
+--
+-- Usage note: 'getUnsatCore' is usually easier to use than 'checkSatAssumingWithUnsatisfiableSet', as it
+-- allows the use of named assertions, as obtained by 'Data.SBV.namedConstraint'. If 'getUnsatCore'
+-- fills your needs, you should definitely prefer it over 'checkSatAssumingWithUnsatisfiableSet'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.checkSatAssumingWithUnsatisfiableSet'
+checkSatAssumingWithUnsatisfiableSet :: [SBool] -> Query (CheckSatResult, Maybe [SBool])
+checkSatAssumingWithUnsatisfiableSet = Trans.checkSatAssumingWithUnsatisfiableSet
+
+-- | The current assertion stack depth, i.e., #push - #pops after start. Always non-negative.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getAssertionStackDepth'
+getAssertionStackDepth :: Query Int
+getAssertionStackDepth = Trans.getAssertionStackDepth
+
+-- | Run the query in a new assertion stack. That is, we push the context, run the query
+-- commands, and pop it back.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.inNewAssertionStack'
+inNewAssertionStack :: Query a -> Query a
+inNewAssertionStack = Trans.inNewAssertionStack
+
+-- | Push the context, entering a new one. Pushes multiple levels if /n/ > 1.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.push'
+push :: Int -> Query ()
+push = Trans.push
+
+-- | Pop the context, exiting a new one. Pops multiple levels if /n/ > 1. It's an error to pop levels that don't exist.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.pop'
+pop :: Int -> Query ()
+pop = Trans.pop
+
+-- | Search for a result via a sequence of case-splits, guided by the user. If one of
+-- the conditions lead to a satisfiable result, returns @Just@ that result. If none of them
+-- do, returns @Nothing@. Note that we automatically generate a coverage case and search
+-- for it automatically as well. In that latter case, the string returned will be "Coverage".
+-- The first argument controls printing progress messages  See "Documentation.SBV.Examples.Queries.CaseSplit"
+-- for an example use case.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.caseSplit'
+caseSplit :: Bool -> [(String, SBool)] -> Query (Maybe (String, SMTResult))
+caseSplit = Trans.caseSplit
+
+-- | Reset the solver, by forgetting all the assertions. However, bindings are kept as is,
+-- as opposed to a full reset of the solver. Use this variant to clean-up the solver
+-- state while leaving the bindings intact. Pops all assertion levels. Declarations and
+-- definitions resulting from the 'Data.SBV.setLogic' command are unaffected. Note that SBV
+-- implicitly uses global-declarations, so bindings will remain intact.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.resetAssertions'
+resetAssertions :: Query ()
+resetAssertions = Trans.resetAssertions
+
+-- | Echo a string. Note that the echoing is done by the solver, not by SBV.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.echo'
+echo :: String -> Query ()
+echo = Trans.echo
+
+-- | Exit the solver. This action will cause the solver to terminate. Needless to say,
+-- trying to communicate with the solver after issuing "exit" will simply fail.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.exit'
+exit :: Query ()
+exit = Trans.exit
+
+-- | Retrieve the unsat-core. Note you must have arranged for
+-- unsat cores to be produced first via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceUnsatCores' 'True'
+-- @
+--
+-- for this call to not error out! Furthermore, unsat-cores require for the user to name the
+-- constraints to be considered as part of the set, which is done via 'Data.SBV.namedConstraint'.
+--
+-- NB. There is no notion of a minimal unsat-core, in case unsatisfiability can be derived
+-- in multiple ways. Furthermore, Z3 does not guarantee that the generated unsat
+-- core does not have any redundant assertions either, as doing so can incur a performance penalty.
+-- (There might be assertions in the set that is not needed.) To ensure all the assertions
+-- in the core are relevant, use:
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.OptionKeyword' ":smt.core.minimize" ["true"]
+-- @
+--
+-- Note that this only works with Z3.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUnsatCore'
+getUnsatCore :: Query [String]
+getUnsatCore = Trans.getUnsatCore
+
+-- | Retrieve the proof. Note you must have arranged for
+-- proofs to be produced first via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceProofs' 'True'
+-- @
+--
+-- for this call to not error out!
+--
+-- A proof is simply a 'String', as returned by the solver. In the future, SBV might
+-- provide a better datatype, depending on the use cases. Please get in touch if you
+-- use this function and can suggest a better API.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getProof'
+getProof :: Query String
+getProof = Trans.getProof
+
+-- | Interpolant extraction for MathSAT. Compare with 'getInterpolantZ3', which performs
+-- similar function (but with a different use model) in Z3.
+--
+-- Retrieve an interpolant after an 'Data.SBV.Control.Unsat' result is obtained. Note you must have arranged for
+-- interpolants to be produced first via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceInterpolants' 'True'
+-- @
+--
+-- for this call to not error out!
+--
+-- To get an interpolant for a pair of formulas @A@ and @B@, use a 'Data.SBV.constrainWithAttribute' call to attach
+-- interpolation groups to @A@ and @B@. Then call 'getInterpolantMathSAT' @[\"A\"]@, assuming those are the names
+-- you gave to the formulas in the @A@ group.
+--
+-- An interpolant for @A@ and @B@ is a formula @I@ such that:
+--
+-- @
+--        A .=> I
+--    and B .=> sNot I
+-- @
+--
+-- That is, it's evidence that @A@ and @B@ cannot be true together
+-- since @A@ implies @I@ but @B@ implies @not I@; establishing that @A@ and @B@ cannot
+-- be satisfied at the same time. Furthermore, @I@ will have only the symbols that are common
+-- to @A@ and @B@.
+--
+-- NB. Interpolant extraction isn't standardized well in SMTLib. Currently both MathSAT and Z3
+-- support them, but with slightly differing APIs. So, we support two APIs with slightly
+-- differing types to accommodate both. See "Documentation.SBV.Examples.Queries.Interpolants" for example
+-- usages in these solvers.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getInterpolantMathSAT'
+getInterpolantMathSAT :: [String] -> Query String
+getInterpolantMathSAT = Trans.getInterpolantMathSAT
+
+-- | Interpolant extraction for z3. Compare with 'getInterpolantMathSAT', which performs
+-- similar function (but with a different use model) in MathSAT.
+--
+-- Unlike the MathSAT variant, you should simply call 'getInterpolantZ3' on symbolic booleans
+-- to retrieve the interpolant. Do not call `checkSat` or create named constraints. This makes it
+-- harder to identify formulas, but the current state of affairs in interpolant API requires this kludge.
+--
+-- An interpolant for @A@ and @B@ is a formula @I@ such that:
+--
+-- @
+--        A ==> I
+--    and B ==> not I
+-- @
+--
+-- That is, it's evidence that @A@ and @B@ cannot be true together
+-- since @A@ implies @I@ but @B@ implies @not I@; establishing that @A@ and @B@ cannot
+-- be satisfied at the same time. Furthermore, @I@ will have only the symbols that are common
+-- to @A@ and @B@.
+--
+-- In Z3, interpolants generalize to sequences: If you pass more than two formulas, then you will get
+-- a sequence of interpolants. In general, for @N@ formulas that are not satisfiable together, you will be
+-- returned @N-1@ interpolants. If formulas are @A1 .. An@, then interpolants will be @I1 .. I(N-1)@, such
+-- that @A1 ==> I1@, @A2 /\\ I1 ==> I2@, @A3 /\\ I2 ==> I3@, ..., and finally @AN ===> not I(N-1)@.
+--
+-- Currently, SBV only returns simple and sequence interpolants, and does not support tree-interpolants.
+-- If you need these, please get in touch. Furthermore, the result will be a list of mere strings representing the
+-- interpolating formulas, as opposed to a more structured type. Please get in touch if you use this function and can
+-- suggest a better API.
+--
+-- NB. Interpolant extraction isn't standardized well in SMTLib. Currently both MathSAT and Z3
+-- support them, but with slightly differing APIs. So, we support two APIs with slightly
+-- differing types to accommodate both. See "Documentation.SBV.Examples.Queries.Interpolants" for example
+-- usages in these solvers.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getInterpolantZ3'
+getInterpolantZ3 :: [SBool] -> Query String
+getInterpolantZ3 = Trans.getInterpolantZ3
+
+-- | Get an abduct. The first argument is a conjecture. The return value will be an assertion
+-- such that in addition with the existing assertions you have, will imply this conjecture.
+-- The second argument is the grammar which guides the synthesis of this abduct, if given.
+-- Note that SBV doesn't do any checking on the grammar. See the relevant documentation on CVC5
+-- for details.
+--
+-- NB. Before you use this function, make sure to call
+--
+-- @
+--      setOption $ ProduceAbducts True
+-- @
+--
+-- to enable abduct generation.
+getAbduct :: Maybe String -> String -> SBool -> Query String
+getAbduct = Trans.getAbduct
+
+-- | Get the next abduct. Only call this after the first call to 'getAbduct' goes through. You can call
+-- it repeatedly to get a different abduct.
+getAbductNext :: Query String
+getAbductNext = Trans.getAbductNext
+
+-- | Retrieve assertions. Note you must have arranged for
+-- assertions to be available first via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceAssertions' 'True'
+-- @
+--
+-- for this call to not error out!
+--
+-- Note that the set of assertions returned is merely a list of strings, just like the
+-- case for 'getProof'. In the future, SBV might provide a better datatype, depending
+-- on the use cases. Please get in touch if you use this function and can suggest
+-- a better API.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getAssertions'
+getAssertions :: Query [String]
+getAssertions = Trans.getAssertions
+
+-- | Retrieve the assignment. This is a lightweight version of 'getValue', where the
+-- solver returns the truth value for all named subterms of type 'Bool'.
+--
+-- You must have first arranged for assignments to be produced via
+--
+-- @
+--     'Data.SBV.setOption' $ 'Data.SBV.Control.ProduceAssignments' 'True'
+-- @
+--
+-- for this call to not error out!
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getAssignment'
+getAssignment :: Query [(String, Bool)]
+getAssignment = Trans.getAssignment
+
+-- | Produce the query result from an assignment.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.mkSMTResult'
+mkSMTResult :: [Assignment] -> Query SMTResult
+mkSMTResult = Trans.mkSMTResult
+
+-- Data.SBV.Control.Utils
+
+-- | Perform an arbitrary IO action.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.io'
+io :: IO a -> Query a
+io = Trans.io
+
+-- | Modify the query state
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.modifyQueryState'
+modifyQueryState :: (QueryState -> QueryState) -> Query ()
+modifyQueryState = Trans.modifyQueryState
+
+-- | Execute in a new incremental context
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.inNewContext'
+inNewContext :: (State -> IO a) -> Query a
+inNewContext = Trans.inNewContext
+
+-- | Similar to 'freshVar', except creates unnamed variable.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.freshVar_'
+freshVar_ :: SymVal a => Query (SBV a)
+freshVar_ = Trans.freshVar_
+
+-- | Create a fresh variable in query mode. You should prefer
+-- creating input variables using 'Data.SBV.sBool', 'Data.SBV.sInt32', etc., which act
+-- as primary inputs to the model. Use 'freshVar' only in query mode for anonymous temporary variables.
+-- Note that 'freshVar' should hardly be needed: Your input variables and symbolic expressions
+-- should suffice for -- most major use cases.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.freshVar'
+freshVar :: SymVal a => String -> Query (SBV a)
+freshVar = Trans.freshVar
+
+-- | If 'Data.SBV.verbose' is 'True', print the message, useful for debugging messages
+-- in custom queries. Note that 'Data.SBV.redirectVerbose' will be respected: If a
+-- file redirection is given, the output will go to the file.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.queryDebug'
+queryDebug :: [Text] -> Query ()
+queryDebug = Trans.queryDebug
+
+-- | Send a string to the solver, and return the response
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.ask'
+ask :: Text -> Query String
+ask = Trans.ask
+
+-- | Send a string to the solver. If the first argument is 'True', we will require
+-- a "success" response as well. Otherwise, we'll fire and forget.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.send'
+send :: Bool -> Text -> Query ()
+send = Trans.send
+
+-- | Retrieve a responses from the solver until it produces a synchronization tag. We make the tag
+-- unique by attaching a time stamp, so no need to worry about getting the wrong tag unless it happens
+-- in the very same picosecond! We return multiple valid s-expressions till the solver responds with the tag.
+-- Should only be used for internal tasks or when we want to synchronize communications, and not on a
+-- regular basis! Use 'send'/'ask' for that purpose. This comes in handy, however, when solvers respond
+-- multiple times as in optimization for instance, where we both get a check-sat answer and some objective values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.retrieveResponse'
+retrieveResponse :: String -> Maybe Int -> Query [String]
+retrieveResponse = Trans.retrieveResponse
+
+-- | Get the value of a term.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getValue'
+getValue :: SymVal a => SBV a -> Query a
+getValue = Trans.getValue
+
+-- | 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. If the result is not a value-association, then we get a string
+-- representation and the triple of whether it's curried, the argument list given by the user, and the s-expression as parsed
+-- by SBV from the SMT solver.
+getFunction :: (SymVal a, SymVal r, Trans.SMTFunction fun a r) => fun -> Query (Either (String, (Bool, Maybe [String], SExpr)) ([(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 value
+getUICVal :: Maybe Int -> (String, (Bool, Maybe [String], SBVType)) -> Query CV
+getUICVal = Trans.getUICVal
+
+-- | 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, (Bool, Maybe [String], SBVType)) -> Query (Either String ([([CV], CV)], CV))
+getUIFunCVAssoc = Trans.getUIFunCVAssoc
+
+-- | Check for satisfiability.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.checkSat'
+checkSat :: Query CheckSatResult
+checkSat = Trans.checkSat
+
+-- | Ensure that the current context is satisfiable. If not, this function will throw an error.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.ensureSat'
+ensureSat :: Query ()
+ensureSat = Trans.ensureSat
+
+-- | Check for satisfiability with a custom check-sat-using command.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.checkSatUsing'
+checkSatUsing :: String -> Query CheckSatResult
+checkSatUsing = Trans.checkSatUsing
+
+-- | Retrieve the set of unsatisfiable assumptions, following a call to 'Data.SBV.Control.checkSatAssumingWithUnsatisfiableSet'. Note that
+-- this function isn't exported to the user, but rather used internally. The user simple calls 'Data.SBV.Control.checkSatAssumingWithUnsatisfiableSet'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUnsatAssumptions'
+getUnsatAssumptions :: [String] -> [(String, a)] -> Query [a]
+getUnsatAssumptions = Trans.getUnsatAssumptions
+
+-- | Timeout a query action, typically a command call to the underlying SMT solver.
+-- The duration is in microseconds (@1\/10^6@ seconds). If the duration
+-- is negative, then no timeout is imposed. When specifying long timeouts, be careful not to exceed
+-- @maxBound :: Int@. (On a 64 bit machine, this bound is practically infinite. But on a 32 bit
+-- machine, it corresponds to about 36 minutes!)
+--
+-- Semantics: The call @timeout n q@ causes the timeout value to be applied to all interactive calls that take place
+-- as we execute the query @q@. That is, each call that happens during the execution of @q@ gets a separate
+-- time-out value, as opposed to one timeout value that limits the whole query. This is typically the intended behavior.
+-- It is advisable to apply this combinator to calls that involve a single call to the solver for
+-- finer control, as opposed to an entire set of interactions. However, different use cases might call for different scenarios.
+--
+-- If the solver responds within the time-out specified, then we continue as usual. However, if the backend solver times-out
+-- using this mechanism, there is no telling what the state of the solver will be. Thus, we raise an error in this case.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.timeout'
+timeout :: Int -> Query a -> Query a
+timeout = Trans.timeout
+
+-- | Bail out if we don't get what we expected
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.unexpected'
+unexpected :: String -> Text -> String -> Maybe [String] -> String -> Maybe [String] -> Query a
+unexpected = Trans.unexpected
+
+-- | Execute a query.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.executeQuery'
+executeQuery :: QueryContext -> Query a -> Symbolic a
+executeQuery = Trans.executeQuery
diff --git a/Data/SBV/Control/Query.hs b/Data/SBV/Control/Query.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Control/Query.hs
@@ -0,0 +1,701 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Control.Query
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Querying a solver interactively.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE LambdaCase          #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Control.Query (
+       send, ask, retrieveResponse
+     , CheckSatResult(..), checkSat, checkSatUsing, checkSatAssuming, checkSatAssumingWithUnsatisfiableSet
+     , getUnsatCore, getProof, getInterpolantMathSAT, getInterpolantZ3, getAbduct, getAbductNext, getAssignment, getOption
+     , push, pop, getAssertionStackDepth
+     , inNewAssertionStack, echo, caseSplit, resetAssertions, exit, getAssertions, getModel, getSMTResult
+     , getLexicographicOptResults, getIndependentOptResults, getParetoOptResults, getAllSatResult, getUnknownReason, getObservables, ensureSat
+     , SMTOption(..), SMTInfoFlag(..), SMTErrorBehavior(..), SMTReasonUnknown(..), SMTInfoResponse(..), getInfo
+     , Logic(..), Assignment(..)
+     , ignoreExitCode, timeout
+     , (|->)
+     , mkSMTResult
+     , io
+     ) where
+
+import Control.Monad          (unless, when, zipWithM)
+import Control.Monad.IO.Class (MonadIO)
+
+import Data.IORef (readIORef)
+
+import qualified Data.Map.Strict as M
+import qualified Data.Text       as T
+import qualified Data.Foldable   as F
+
+
+import Data.Char      (toLower)
+import Data.List      (intercalate, nubBy)
+import Data.Maybe     (fromMaybe)
+import Data.Function  (on)
+
+import Data.SBV.Core.Data
+
+import Data.SBV.Core.Symbolic (MonadQuery(..), State(..), incrementInternalCounter, getSV)
+
+import Data.SBV.Utils.SExpr
+
+import Data.SBV.Control.Types
+import Data.SBV.Control.Utils
+
+import Data.SBV.Utils.Lib       (showText, unBar)
+import Data.SBV.Utils.PrettyNum (showNegativeNumber)
+
+-- | An Assignment of a model binding
+data Assignment = Assign SVal CV
+
+-- Is this a string? If so, return it, otherwise fail in the Maybe monad.
+fromECon :: SExpr -> Maybe String
+fromECon (ECon s) = Just s
+fromECon _        = Nothing
+
+-- Collect strings appearing, used in 'getOption' only
+stringsOf :: SExpr -> [String]
+stringsOf (ECon s)           = [s]
+stringsOf (ENum (i, _, _))   = [show i]
+stringsOf (EReal   r)        = [show r]
+stringsOf (EFloat  f)        = [show f]
+stringsOf (EFloatingPoint f) = [show f]
+stringsOf (EDouble d)        = [show d]
+stringsOf (EApp ss)          = concatMap stringsOf ss
+
+-- Sort of a light-hearted show for SExprs, for better consumption at the user level.
+serialize :: Bool -> SExpr -> String
+serialize removeQuotes = go
+  where go (ECon s)           = if removeQuotes then unQuote s else s
+        go (ENum (i, _, _))   = T.unpack (showNegativeNumber i)
+        go (EReal   r)        = T.unpack (showNegativeNumber r)
+        go (EFloat  f)        = T.unpack (showNegativeNumber f)
+        go (EDouble d)        = T.unpack (showNegativeNumber d)
+        go (EFloatingPoint f) = show f
+        go (EApp [x])         = go x
+        go (EApp ss)          = "(" ++ unwords (map go ss) ++ ")"
+
+-- | Generalization of 'Data.SBV.Control.getInfo'
+getInfo :: (MonadIO m, MonadQuery m) => SMTInfoFlag -> m SMTInfoResponse
+getInfo flag = do
+    let cmd = "(get-info " <> showText flag <> ")"
+        bad = unexpected "getInfo" cmd "a valid get-info response" Nothing
+
+        isAllStatistics AllStatistics = True
+        isAllStatistics _             = False
+
+        isAllStat = isAllStatistics flag
+
+        grabAllStat k v = (render k, render v)
+
+        -- we're trying to do our best to get key-value pairs here, but this
+        -- is necessarily a half-hearted attempt.
+        grabAllStats (EApp xs) = walk xs
+           where walk []             = []
+                 walk [t]            = [grabAllStat t (ECon "")]
+                 walk (t : v : rest) =  grabAllStat t v          : walk rest
+        grabAllStats o = [grabAllStat o (ECon "")]
+
+    r <- ask cmd
+
+    parse r bad $ \pe ->
+       if isAllStat
+          then pure $ Resp_AllStatistics $ grabAllStats pe
+          else case pe of
+                 ECon "unsupported"                                        -> pure Resp_Unsupported
+                 EApp [ECon ":assertion-stack-levels", ENum (i, _, _)]     -> pure $ Resp_AssertionStackLevels i
+                 EApp (ECon ":authors" : ns)                               -> pure $ Resp_Authors (map render ns)
+                 EApp [ECon ":error-behavior", ECon "immediate-exit"]      -> pure $ Resp_Error ErrorImmediateExit
+                 EApp [ECon ":error-behavior", ECon "continued-execution"] -> pure $ Resp_Error ErrorContinuedExecution
+                 EApp (ECon ":name" : o)                                   -> pure $ Resp_Name (render (EApp o))
+                 EApp (ECon ":reason-unknown" : o)                         -> pure $ Resp_ReasonUnknown (unk o)
+                 EApp (ECon ":version" : o)                                -> pure $ Resp_Version (render (EApp o))
+                 EApp (ECon s : o)                                         -> pure $ Resp_InfoKeyword s (map render o)
+                 _                                                         -> bad r Nothing
+
+  where render = serialize True
+
+        unk [ECon s] | Just d <- getUR s = d
+        unk o                            = UnknownOther (render (EApp o))
+
+        getUR s = map toLower (unQuote s) `lookup` [(map toLower k, d) | (k, d) <- unknownReasons]
+
+        -- As specified in Section 4.1 of the SMTLib document. Note that we're adding the
+        -- extra timeout as it is useful in this context.
+        unknownReasons = [ ("memout",     UnknownMemOut)
+                         , ("incomplete", UnknownIncomplete)
+                         , ("timeout",    UnknownTimeOut)
+                         ]
+
+-- | Generalization of 'Data.SBV.Control.getOption'
+getOption :: (MonadIO m, MonadQuery m) => (a -> SMTOption) -> m (Maybe SMTOption)
+getOption f = case f undefined of
+                 DiagnosticOutputChannel{}   -> askFor "DiagnosticOutputChannel"   ":diagnostic-output-channel"   $ string     DiagnosticOutputChannel
+                 ProduceAssertions{}         -> askFor "ProduceAssertions"         ":produce-assertions"          $ bool       ProduceAssertions
+                 ProduceAssignments{}        -> askFor "ProduceAssignments"        ":produce-assignments"         $ bool       ProduceAssignments
+                 ProduceProofs{}             -> askFor "ProduceProofs"             ":produce-proofs"              $ bool       ProduceProofs
+                 ProduceInterpolants{}       -> askFor "ProduceInterpolants"       ":produce-interpolants"        $ bool       ProduceInterpolants
+                 ProduceUnsatAssumptions{}   -> askFor "ProduceUnsatAssumptions"   ":produce-unsat-assumptions"   $ bool       ProduceUnsatAssumptions
+                 ProduceUnsatCores{}         -> askFor "ProduceUnsatCores"         ":produce-unsat-cores"         $ bool       ProduceUnsatCores
+                 ProduceAbducts{}            -> askFor "ProduceAbducts"            ":produce-abducts"             $ bool       ProduceAbducts
+                 RandomSeed{}                -> askFor "RandomSeed"                ":random-seed"                 $ integer    RandomSeed
+                 ReproducibleResourceLimit{} -> askFor "ReproducibleResourceLimit" ":reproducible-resource-limit" $ integer    ReproducibleResourceLimit
+                 SMTVerbosity{}              -> askFor "SMTVerbosity"              ":verbosity"                   $ integer    SMTVerbosity
+                 OptionKeyword nm _          -> askFor ("OptionKeyword" ++ nm)     nm                             $ stringList (OptionKeyword nm)
+                 SetLogic{}                  -> error "Data.SBV.Query: SMTLib does not allow querying the value of logic!"
+                 SetTimeOut{}                -> error "Data.SBV.Query: SMTLib does not allow querying the timeout value!"
+                 -- Not to be confused by getInfo, which is totally irrelevant!
+                 SetInfo{}                   -> error "Data.SBV.Query: SMTLib does not allow querying value of meta-info!"
+
+  where askFor sbvName smtLibName continue = do
+                let cmd = "(get-option " <> T.pack smtLibName <> ")"
+                    bad = unexpected ("getOption " ++ sbvName) cmd "a valid option value" Nothing
+
+                r <- ask cmd
+
+                parse r bad $ \case ECon "unsupported" -> pure Nothing
+                                    e                  -> continue e (bad r)
+
+        string c (ECon s) _ = pure $ Just $ c s
+        string _ e        k = k $ Just ["Expected string, but got: " ++ show (serialize False e)]
+
+        bool c (ENum (0, _, True)) _ = pure $ Just $ c False
+        bool c (ENum (1, _, True)) _ = pure $ Just $ c True
+        bool _ e                   k = k $ Just ["Expected boolean, but got: " ++ show (serialize False e)]
+
+        integer c (ENum (i, _, _)) _ = pure $ Just $ c i
+        integer _ e                k = k $ Just ["Expected integer, but got: " ++ show (serialize False e)]
+
+        -- free format, really
+        stringList c e _ = pure $ Just $ c $ stringsOf e
+
+-- | Generalization of 'Data.SBV.Control.getUnknownReason'
+getUnknownReason :: (MonadIO m, MonadQuery m) => m SMTReasonUnknown
+getUnknownReason = do ru <- getInfo ReasonUnknown
+                      case ru of
+                        Resp_Unsupported     -> pure $ UnknownOther "Solver responded: Unsupported."
+                        Resp_ReasonUnknown r -> pure r
+                        -- Shouldn't happen, but just in case:
+                        _                    -> error $ "Unexpected reason value received: " ++ show ru
+
+-- | Generalization of 'Data.SBV.Control.ensureSat'
+ensureSat :: (MonadIO m, MonadQuery m) => m ()
+ensureSat = do cfg <- getConfig
+               cs <- checkSatUsing $ satCmd cfg
+               case cs of
+                 Sat    -> pure ()
+                 DSat{} -> pure ()
+                 Unk    -> do s <- getUnknownReason
+                              error $ unlines [ ""
+                                              , "*** Data.SBV.ensureSat: Solver reported Unknown!"
+                                              , "*** Reason: " ++ show s
+                                              ]
+                 Unsat  -> error "Data.SBV.ensureSat: Solver reported Unsat!"
+
+-- | Generalization of 'Data.SBV.Control.getSMTResult'
+getSMTResult :: (MonadIO m, MonadQuery m) => m SMTResult
+getSMTResult = do cfg <- getConfig
+                  cs  <- checkSat
+                  case cs of
+                    Unsat  -> Unsatisfiable cfg   <$> getUnsatCoreIfRequested
+                    Sat    -> Satisfiable   cfg   <$> getModel
+                    DSat p -> DeltaSat      cfg p <$> getModel
+                    Unk    -> Unknown       cfg   <$> getUnknownReason
+
+-- | Classify a model based on whether it has unbound objectives or not.
+classifyModel :: SMTConfig -> SMTModel -> SMTResult
+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
+getLexicographicOptResults = do cfg <- getConfig
+                                cs  <- checkSat
+                                case cs of
+                                  Unsat  -> Unsatisfiable cfg <$> getUnsatCoreIfRequested
+                                  Sat    -> classifyModel cfg <$> getModelWithObjectives
+                                  DSat{} -> classifyModel cfg <$> getModelWithObjectives
+                                  Unk    -> Unknown       cfg <$> getUnknownReason
+   where getModelWithObjectives = do objectiveValues <- getObjectiveValues
+                                     m               <- getModel
+                                     pure m {modelObjectives = objectiveValues}
+
+-- | Generalization of 'Data.SBV.Control.getIndependentOptResults'
+getIndependentOptResults :: forall m. (MonadIO m, MonadQuery m) => [String] -> m [(String, SMTResult)]
+getIndependentOptResults objNames = do cfg <- getConfig
+                                       cs  <- checkSat
+
+                                       case cs of
+                                         Unsat  -> getUnsatCoreIfRequested >>= \mbUC -> pure [(nm, Unsatisfiable cfg mbUC) | nm <- objNames]
+                                         Sat    -> continue (classifyModel cfg)
+                                         DSat{} -> continue (classifyModel cfg)
+                                         Unk    -> do ur <- Unknown cfg <$> getUnknownReason
+                                                      pure [(nm, ur) | nm <- objNames]
+
+  where continue classify = do objectiveValues <- getObjectiveValues
+                               nms <- zipWithM getIndependentResult [0..] objNames
+                               pure [(n, classify (m {modelObjectives = objectiveValues})) | (n, m) <- nms]
+
+        getIndependentResult :: Int -> String -> m (String, SMTModel)
+        getIndependentResult i s = do m <- getModelAtIndex (Just i)
+                                      pure (s, m)
+
+-- | Generalization of 'Data.SBV.Control.getParetoOptResults'
+getParetoOptResults :: (MonadIO m, MonadQuery m) => Maybe Int -> m (Bool, [SMTResult])
+getParetoOptResults (Just i)
+        | i <= 0             = pure (True, [])
+getParetoOptResults mbN      = do cfg <- getConfig
+                                  cs  <- checkSat
+
+                                  case cs of
+                                    Unsat  -> pure (False, [])
+                                    Sat    -> continue (classifyModel cfg)
+                                    DSat{} -> continue (classifyModel cfg)
+                                    Unk    -> do ur <- getUnknownReason
+                                                 pure (False, [ProofError cfg [show ur] Nothing])
+
+  where continue classify = do m <- getModel
+                               (limReached, fronts) <- getParetoFronts (subtract 1 <$> mbN) [m]
+                               pure (limReached, reverse (map classify fronts))
+
+        getParetoFronts :: (MonadIO m, MonadQuery m) => Maybe Int -> [SMTModel] -> m (Bool, [SMTModel])
+        getParetoFronts (Just i) sofar | i <= 0 = pure (True, sofar)
+        getParetoFronts mbi      sofar          = do cs <- checkSat
+                                                     let more = getModel >>= \m -> getParetoFronts (subtract 1 <$> mbi) (m : sofar)
+                                                     case cs of
+                                                       Unsat  -> pure (False, sofar)
+                                                       Sat    -> more
+                                                       DSat{} -> more
+                                                       Unk    -> more
+
+-- | Generalization of 'Data.SBV.Control.checkSatAssuming'
+checkSatAssuming :: (MonadIO m, MonadQuery m) => [SBool] -> m CheckSatResult
+checkSatAssuming sBools = fst <$> checkSatAssumingHelper False sBools
+
+-- | Generalization of 'Data.SBV.Control.checkSatAssumingWithUnsatisfiableSet'
+checkSatAssumingWithUnsatisfiableSet :: (MonadIO m, MonadQuery m) => [SBool] -> m (CheckSatResult, Maybe [SBool])
+checkSatAssumingWithUnsatisfiableSet = checkSatAssumingHelper True
+
+-- | Helper for the two variants of checkSatAssuming we have. Internal only.
+checkSatAssumingHelper :: (MonadIO m, MonadQuery m) => Bool -> [SBool] -> m (CheckSatResult, Maybe [SBool])
+checkSatAssumingHelper getAssumptions sBools = do
+        -- sigh.. SMT-Lib requires the values to be literals only. So, create proxies.
+        let mkAssumption st = do swsOriginal <- mapM (\sb -> do sv <- sbvToSV st sb
+                                                                pure (sv, sb)) sBools
+
+                                 -- drop duplicates and trues
+                                 let swbs = [p | p@(sv, _) <- nubBy ((==) `on` fst) swsOriginal, sv /= trueSV]
+
+                                 -- get a unique proxy name for each
+                                 uniqueSWBs <- mapM (\(sv, sb) -> do unique <- incrementInternalCounter st
+                                                                     pure (sv, (unique, sb))) swbs
+
+                                 let translate (sv, (unique, sb)) = (nm, decls, (proxy, sb))
+                                        where nm    = show sv
+                                              proxy = "__assumption_proxy_" ++ nm ++ "_" ++ show unique
+                                              decls = [ "(declare-const " ++ proxy ++ " Bool)"
+                                                      , "(assert (= " ++ proxy ++ " " ++ nm ++ "))"
+                                                      ]
+
+                                 pure $ map translate uniqueSWBs
+
+        assumptions <- inNewContext mkAssumption
+
+        let (origNames, declss, proxyMap) = unzip3 assumptions
+
+        let cmd = "(check-sat-assuming (" <> T.pack (unwords (map fst proxyMap)) <> "))"
+            bad = unexpected "checkSatAssuming" cmd "one of sat/unsat/unknown"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceUnsatAssumptions True"
+                                  , ""
+                                  , "to tell the solver to produce unsat assumptions."
+                                  ]
+
+        mapM_ (send True . T.pack) $ concat declss
+        r <- ask cmd
+
+        let grabUnsat
+             | getAssumptions = do as <- getUnsatAssumptions origNames proxyMap
+                                   pure (Unsat, Just as)
+             | True           = pure (Unsat, Nothing)
+
+        parse r bad $ \case ECon "sat"     -> pure (Sat, Nothing)
+                            ECon "unsat"   -> grabUnsat
+                            ECon "unknown" -> pure (Unk, Nothing)
+                            _              -> bad r Nothing
+
+-- | Generalization of 'Data.SBV.Control.getAssertionStackDepth'
+getAssertionStackDepth :: (MonadIO m, MonadQuery m) => m Int
+getAssertionStackDepth = queryAssertionStackDepth <$> getQueryState
+
+-- | Upon a pop, we need to restore all arrays and tables. See: http://github.com/LeventErkok/sbv/issues/374
+restoreTablesAndArrays :: (MonadIO m, MonadQuery m) => m ()
+restoreTablesAndArrays = do st <- queryState
+
+                            tCount <- M.size  <$> (io . readIORef) (rtblMap   st)
+
+                            let inits = [ "table"  ++ show i ++ "_initializer" | i <- [0 .. tCount - 1]]
+
+                            case inits of
+                              []  -> pure ()   -- Nothing to do
+                              [x] -> send True $ "(assert " <> T.pack x <> ")"
+                              xs  -> send True $ "(assert (and " <> T.pack (unwords xs) <> "))"
+
+-- | Generalization of 'Data.SBV.Control.inNewAssertionStack'
+inNewAssertionStack :: (MonadIO m, MonadQuery m) => m a -> m a
+inNewAssertionStack q = do push 1
+                           r <- q
+                           pop 1
+                           pure r
+
+-- | Generalization of 'Data.SBV.Control.push'
+push :: (MonadIO m, MonadQuery m) => Int -> m ()
+push i
+ | i <= 0 = error $ "Data.SBV: push requires a strictly positive level argument, received: " ++ show i
+ | True   = do depth <- getAssertionStackDepth
+               send True $ "(push " <> showText i <> ")"
+               modifyQueryState $ \s -> s{queryAssertionStackDepth = depth + i}
+
+-- | Generalization of 'Data.SBV.Control.pop'
+pop :: (MonadIO m, MonadQuery m) => Int -> m ()
+pop i
+ | i <= 0 = error $ "Data.SBV: pop requires a strictly positive level argument, received: " ++ show i
+ | True   = do depth <- getAssertionStackDepth
+               if i > depth
+                  then error $ "Data.SBV: Illegally trying to pop " ++ shl i ++ ", at current level: " ++ show depth
+                  else do QueryState{queryConfig} <- getQueryState
+                          if not (supportsGlobalDecls (capabilities (solver queryConfig)))
+                             then error $ unlines [ ""
+                                                  , "*** Data.SBV: Backend solver does not support global-declarations."
+                                                  , "***           Hence, calls to 'pop' are not supported."
+                                                  , "***"
+                                                  , "*** Request this as a feature for the underlying solver!"
+                                                  ]
+                             else do send True $ "(pop " <> showText i <> ")"
+                                     restoreTablesAndArrays
+                                     modifyQueryState $ \s -> s{queryAssertionStackDepth = depth - i}
+   where shl 1 = "one level"
+         shl n = show n ++ " levels"
+
+-- | Generalization of 'Data.SBV.Control.caseSplit'
+caseSplit :: (MonadIO m, MonadQuery m) => Bool -> [(String, SBool)] -> m (Maybe (String, SMTResult))
+caseSplit printCases cases = do cfg <- getConfig
+                                go cfg (cases ++ [("Coverage", sNot (sOr (map snd cases)))])
+  where msg = when printCases . io . putStrLn
+
+        go _ []            = pure Nothing
+        go cfg ((n,c):ncs) = do let notify s = msg $ "Case " ++ n ++ ": " ++ s
+
+                                notify "Starting"
+                                r <- checkSatAssuming [c]
+
+                                case r of
+                                  Unsat    -> do notify "Unsatisfiable"
+                                                 go cfg ncs
+
+                                  Sat      -> do notify "Satisfiable"
+                                                 res <- Satisfiable cfg <$> getModel
+                                                 pure $ Just (n, res)
+
+                                  DSat mbP -> do notify $ "Delta satisfiable" ++ maybe "" (" (precision: " ++) mbP
+                                                 res <- DeltaSat cfg mbP <$> getModel
+                                                 pure $ Just (n, res)
+
+                                  Unk      -> do notify "Unknown"
+                                                 res <- Unknown cfg <$> getUnknownReason
+                                                 pure $ Just (n, res)
+
+-- | Generalization of 'Data.SBV.Control.resetAssertions'
+resetAssertions :: (MonadIO m, MonadQuery m) => m ()
+resetAssertions = do send True "(reset-assertions)"
+                     modifyQueryState $ \s -> s{ queryAssertionStackDepth = 0 }
+
+                     -- Make sure we restore tables and arrays after resetAssertions: See: https://github.com/LeventErkok/sbv/issues/535
+                     restoreTablesAndArrays
+
+-- | Generalization of 'Data.SBV.Control.echo'
+echo :: (MonadIO m, MonadQuery m) => String -> m ()
+echo s = do let cmd = "(echo \"" <> T.pack (concatMap sanitize s) <> "\")"
+
+            -- we send the command, but otherwise ignore the response
+            -- note that 'send True/False' would be incorrect here. 'send True' would
+            -- require a success response. 'send False' would fail to consume the
+            -- output. But 'ask' does the right thing! It gets "some" response,
+            -- and forgets about it immediately.
+            _ <- ask cmd
+
+            pure ()
+  where sanitize '"'  = "\"\""  -- quotes need to be duplicated
+        sanitize c    = [c]
+
+-- | Generalization of 'Data.SBV.Control.exit'
+exit :: (MonadIO m, MonadQuery m) => m ()
+exit = do send True "(exit)"
+          modifyQueryState $ \s -> s{queryAssertionStackDepth = 0}
+
+-- | Generalization of 'Data.SBV.Control.getUnsatCore'
+getUnsatCore :: (MonadIO m, MonadQuery m) => m [String]
+getUnsatCore = do
+        let cmd = "(get-unsat-core)" :: T.Text
+            bad = unexpected "getUnsatCore" cmd "an unsat-core response"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceUnsatCores True"
+                                  , ""
+                                  , "so the solver will be ready to compute unsat cores,"
+                                  , "and that there is a model by first issuing a 'checkSat' call."
+                                  , ""
+                                  , "If using z3, you might also optionally want to set:"
+                                  , ""
+                                  , "       setOption $ OptionKeyword \":smt.core.minimize\" [\"true\"]"
+                                  , ""
+                                  , "to make sure the unsat core doesn't have irrelevant entries,"
+                                  , "though this might incur a performance penalty."
+
+
+                                  ]
+
+        r <- ask cmd
+
+        parse r bad $ \case
+           EApp es | Just xs <- mapM fromECon es -> pure $ map unBar xs
+           _                                     -> bad r Nothing
+
+-- | Retrieve the unsat core if it was asked for in the configuration
+getUnsatCoreIfRequested :: (MonadIO m, MonadQuery m) => m (Maybe [String])
+getUnsatCoreIfRequested = do
+        cfg <- getConfig
+        if or [b | ProduceUnsatCores b <- solverSetOptions cfg]
+           then Just <$> getUnsatCore
+           else pure Nothing
+
+-- | Generalization of 'Data.SBV.Control.getProof'
+getProof :: (MonadIO m, MonadQuery m) => m String
+getProof = do
+        let cmd = "(get-proof)" :: T.Text
+            bad = unexpected "getProof" cmd "a get-proof response"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceProofs True"
+                                  , ""
+                                  , "to make sure the solver is ready for producing proofs,"
+                                  , "and that there is a proof by first issuing a 'checkSat' call."
+                                  ]
+
+
+        r <- ask cmd
+
+        -- we only care about the fact that we can parse the output, so the
+        -- result of parsing is ignored.
+        parse r bad $ \_ -> pure r
+
+-- | Generalization of 'Data.SBV.Control.getInterpolantMathSAT'. Use this version with MathSAT.
+getInterpolantMathSAT :: (MonadIO m, MonadQuery m) => [String] -> m String
+getInterpolantMathSAT fs
+  | null fs
+  = error "SBV.getInterpolantMathSAT requires at least one marked constraint, received none!"
+  | True
+  = do let bar s = '|' : s ++ "|"
+           cmd = "(get-interpolant (" <> T.pack (unwords (map bar fs)) <> "))"
+           bad = unexpected "getInterpolant" cmd "a get-interpolant response"
+                          $ Just [ "Make sure you use:"
+                                 , ""
+                                 , "       setOption $ ProduceInterpolants True"
+                                 , ""
+                                 , "to make sure the solver is ready for producing interpolants,"
+                                 , "and that you have used the proper attributes using the"
+                                 , "constrainWithAttribute function."
+                                 ]
+
+       r <- ask cmd
+
+       parse r bad $ \e -> pure $ serialize False e
+
+
+-- | Generalization of 'Data.SBV.Control.getAbduct'.
+getAbduct :: (SolverContext m, MonadIO m, MonadQuery m) => Maybe String -> String -> SBool -> m String
+getAbduct mbGrammar defName b = do
+   s <- inNewContext (`sbvToSV` b)
+   let cmd = "(get-abduct " <> T.pack defName <> " " <> showText s <> T.pack (fromMaybe "" mbGrammar) <> ")"
+       bad = unexpected "getAbduct" cmd "a get-abduct response" Nothing
+
+   r <- ask cmd
+
+   parse r bad $ \e -> pure $ serialize False e
+
+-- | Generalization of 'Data.SBV.Control.getAbductNext'.
+getAbductNext :: (MonadIO m, MonadQuery m) => m String
+getAbductNext = do
+   let cmd = "(get-abduct-next)" :: T.Text
+       bad = unexpected "getAbductNext" cmd "a get-abduct-next response" Nothing
+
+   r <- ask cmd
+
+   parse r bad $ \e -> pure $ serialize False e
+
+-- | Generalization of 'Data.SBV.Control.getInterpolantZ3'. Use this version with Z3.
+getInterpolantZ3 :: (MonadIO m, MonadQuery m) => [SBool] -> m String
+getInterpolantZ3 fs
+  | length fs < 2
+  = error $ "SBV.getInterpolantZ3 requires at least two booleans, received: " ++ show fs
+  | True
+  = do ss <- let fAll []     sofar = pure $ reverse sofar
+                 fAll (b:bs) sofar = do sv <- inNewContext (`sbvToSV` b)
+                                        fAll bs (sv : sofar)
+             in fAll fs []
+
+       let cmd = "(get-interpolant " <> T.pack (unwords (map show ss)) <> ")"
+           bad = unexpected "getInterpolant" cmd "a get-interpolant response" Nothing
+
+       r <- ask cmd
+
+       parse r bad $ \e -> pure $ serialize False e
+
+-- | Generalization of 'Data.SBV.Control.getAssertions'
+getAssertions :: (MonadIO m, MonadQuery m) => m [String]
+getAssertions = do
+        let cmd = "(get-assertions)" :: T.Text
+            bad = unexpected "getAssertions" cmd "a get-assertions response"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceAssertions True"
+                                  , ""
+                                  , "to make sure the solver is ready for producing assertions."
+                                  ]
+
+            render = serialize False
+
+        r <- ask cmd
+
+        parse r bad $ \pe -> case pe of
+                                EApp xs -> pure $ map render xs
+                                _       -> pure [render pe]
+
+-- | Generalization of 'Data.SBV.Control.getAssignment'
+getAssignment :: (MonadIO m, MonadQuery m) => m [(String, Bool)]
+getAssignment = do
+        let cmd = "(get-assignment)" :: T.Text
+            bad = unexpected "getAssignment" cmd "a get-assignment response"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceAssignments True"
+                                  , ""
+                                  , "to make sure the solver is ready for producing assignments,"
+                                  , "and that there is a model by first issuing a 'checkSat' call."
+                                  ]
+
+            -- we're expecting boolean assignment to labels, essentially
+            grab (EApp [ECon s, ENum (0, _, _)]) = Just (unQuote s, False)
+            grab (EApp [ECon s, ENum (1, _, _)]) = Just (unQuote s, True)
+            grab _                               = Nothing
+
+        r <- ask cmd
+
+        parse r bad $ \case EApp ps | Just vs <- mapM grab ps -> pure vs
+                            _                                 -> bad r Nothing
+
+-- | Make an assignment. The type 'Assignment' is abstract, the result is typically passed
+-- to 'mkSMTResult':
+--
+-- @ mkSMTResult [ a |-> 332
+--             , b |-> 2.3
+--             , c |-> True
+--             ]
+-- @
+--
+-- End users should use 'getModel' for automatically constructing models from the current solver state.
+-- However, an explicit 'Assignment' might be handy in complex scenarios where a model needs to be
+-- created manually.
+infix 1 |->
+(|->) :: SymVal a => SBV a -> a -> Assignment
+SBV a |-> v = case literal v of
+                SBV (SVal _ (Left cv)) -> Assign a cv
+                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' or 'optimizeValidateConstraints' features, SBV will
+-- fail on models returned via this function.
+mkSMTResult :: (MonadIO m, MonadQuery m) => [Assignment] -> m SMTResult
+mkSMTResult asgns = do
+             QueryState{queryConfig} <- getQueryState
+             inps <- F.toList <$> getTopLevelInputs
+
+             let grabValues st = do let extract (Assign s n) = sbvToSV st (SBV s) >>= \sv -> pure (sv, n)
+
+                                    modelAssignment <- mapM extract asgns
+
+                                    -- sanity checks
+                                    --     - All existentials should be given a value
+                                    --     - No duplicates
+                                    --     - No bindings to vars that are not inputs
+                                    let userSS = map fst modelAssignment
+
+                                        missing, extra, dup :: [String]
+                                        missing = [T.unpack n | NamedSymVar s n <- inps, s `notElem` userSS]
+                                        extra   = [show s | s <- userSS, s `notElem` map getSV inps]
+                                        dup     = let walk []     = []
+                                                      walk (n:ns)
+                                                        | n `elem` ns = show n : walk (filter (/= n) ns)
+                                                        | True        = walk ns
+                                                  in walk userSS
+
+                                    unless (null (missing ++ extra ++ dup)) $ do
+
+                                          let misTag = "***   Missing inputs"
+                                              dupTag = "***   Duplicate bindings"
+                                              extTag = "***   Extra bindings"
+
+                                              maxLen = maximum $  0
+                                                                : [length misTag | not (null missing)]
+                                                               ++ [length extTag | not (null extra)]
+                                                               ++ [length dupTag | not (null dup)]
+
+                                              align s = s ++ replicate (maxLen - length s) ' ' ++ ": "
+
+                                          error $ unlines $ [""
+                                                            , "*** Data.SBV: Query model construction has a faulty assignment."
+                                                            , "***"
+                                                            ]
+                                                         ++ [ align misTag ++ intercalate ", "  missing | not (null missing)]
+                                                         ++ [ align extTag ++ intercalate ", "  extra   | not (null extra)  ]
+                                                         ++ [ align dupTag ++ intercalate ", "  dup     | not (null dup)    ]
+                                                         ++ [ "***"
+                                                            , "*** Data.SBV: Check your query result construction!"
+                                                            ]
+
+                                    let findName s = case [T.unpack nm | NamedSymVar i nm <- inps, s == i] of
+                                                        [nm] -> nm
+                                                        []   -> error "*** Data.SBV: Impossible happened: Cannot find " ++ show s ++ " in the input list"
+                                                        nms  -> error $ unlines [ ""
+                                                                                , "*** Data.SBV: Impossible happened: Multiple matches for: " ++ show s
+                                                                                , "***   Candidates: " ++ unwords nms
+                                                                                ]
+
+                                    pure [(findName s, n) | (s, n) <- modelAssignment]
+
+             assocs <- inNewContext grabValues
+
+             let m = SMTModel { modelObjectives = []
+                              , modelBindings   = Nothing
+                              , modelAssocs     = assocs
+                              , modelUIFuns     = []
+                              }
+
+             pure $ Satisfiable queryConfig m
diff --git a/Data/SBV/Control/Types.hs b/Data/SBV/Control/Types.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Control/Types.hs
@@ -0,0 +1,233 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Control.Types
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Types related to interactive queries
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Control.Types (
+       CheckSatResult(..)
+     , Logic(..)
+     , SMTOption(..), isStartModeOption, isOnlyOnceOption
+     , SMTInfoFlag(..)
+     , SMTErrorBehavior(..)
+     , SMTReasonUnknown(..)
+     , SMTInfoResponse(..)
+     ) where
+
+import Control.DeepSeq (NFData(..))
+import GHC.Generics (Generic)
+
+-- | Result of a 'Data.SBV.Control.checkSat' or 'Data.SBV.Control.checkSatAssuming' call.
+data CheckSatResult = Sat                   -- ^ Satisfiable: A model is available, which can be queried with 'Data.SBV.Control.getValue'.
+                    | DSat (Maybe String)   -- ^ Delta-satisfiable: A delta-sat model is available. String is the precision info, if available.
+                    | Unsat                 -- ^ Unsatisfiable: No model is available. Unsat cores might be obtained via 'Data.SBV.Control.getUnsatCore'.
+                    | Unk                   -- ^ Unknown: Use 'Data.SBV.Control.getUnknownReason' to obtain an explanation why this might be the case.
+                    deriving (Eq, Show, NFData, Generic)
+
+-- | Collectable information from the solver.
+data SMTInfoFlag = AllStatistics
+                 | AssertionStackLevels
+                 | Authors
+                 | ErrorBehavior
+                 | Name
+                 | ReasonUnknown
+                 | Version
+                 | InfoKeyword String
+
+-- | Behavior of the solver for errors.
+data SMTErrorBehavior = ErrorImmediateExit
+                      | ErrorContinuedExecution
+                      deriving Show
+
+-- | Reason for reporting unknown.
+data SMTReasonUnknown = UnknownMemOut
+                      | UnknownIncomplete
+                      | UnknownTimeOut
+                      | UnknownOther      String
+
+-- | Trivial rnf instance
+instance NFData SMTReasonUnknown where rnf a = seq a ()
+
+-- | Show instance for unknown
+instance Show SMTReasonUnknown where
+  show UnknownMemOut     = "memout"
+  show UnknownIncomplete = "incomplete"
+  show UnknownTimeOut    = "timeout"
+  show (UnknownOther s)  = s
+
+-- | Collectable information from the solver.
+data SMTInfoResponse = Resp_Unsupported
+                     | Resp_AllStatistics        [(String, String)]
+                     | Resp_AssertionStackLevels Integer
+                     | Resp_Authors              [String]
+                     | Resp_Error                SMTErrorBehavior
+                     | Resp_Name                 String
+                     | Resp_ReasonUnknown        SMTReasonUnknown
+                     | Resp_Version              String
+                     | Resp_InfoKeyword          String [String]
+                     deriving Show
+
+-- Show instance for SMTInfoFlag maintains smt-lib format per the SMTLib2 standard document.
+instance Show SMTInfoFlag where
+  show AllStatistics        = ":all-statistics"
+  show AssertionStackLevels = ":assertion-stack-levels"
+  show Authors              = ":authors"
+  show ErrorBehavior        = ":error-behavior"
+  show Name                 = ":name"
+  show ReasonUnknown        = ":reason-unknown"
+  show Version              = ":version"
+  show (InfoKeyword s)      = s
+
+-- | Option values that can be set in the solver, following the SMTLib specification <https://smt-lib.org/language.shtml>.
+--
+-- Note that not all solvers may support all of these!
+--
+-- Furthermore, SBV doesn't support the following options allowed by SMTLib.
+--
+--    * @:interactive-mode@                (Deprecated in SMTLib, use 'ProduceAssertions' instead.)
+--    * @:print-success@                   (SBV critically needs this to be True in query mode.)
+--    * @:produce-models@                  (SBV always sets this option so it can extract models.)
+--    * @:regular-output-channel@          (SBV always requires regular output to come on stdout for query purposes.)
+--    * @:global-declarations@             (SBV always uses global declarations since definitions are accumulative.)
+--
+-- Note that 'SetLogic' and 'SetInfo' are, strictly speaking, not SMTLib options. However, we treat it as such here
+-- uniformly, as it fits better with how options work.
+data SMTOption = DiagnosticOutputChannel   FilePath
+               | ProduceAssertions         Bool
+               | ProduceAssignments        Bool
+               | ProduceProofs             Bool
+               | ProduceInterpolants       Bool
+               | ProduceUnsatAssumptions   Bool
+               | ProduceUnsatCores         Bool
+               | ProduceAbducts            Bool
+               | RandomSeed                Integer
+               | ReproducibleResourceLimit Integer
+               | SMTVerbosity              Integer
+               | OptionKeyword             String  [String]
+               | SetLogic                  Logic
+               | SetInfo                   String  [String]
+               | SetTimeOut                Integer
+               deriving Show
+
+-- | Can this command only be run at the very beginning? If 'True' then
+-- we will reject setting these options in the query mode. Note that this
+-- classification follows the SMTLib document.
+isStartModeOption :: SMTOption -> Bool
+isStartModeOption DiagnosticOutputChannel{}   = False
+isStartModeOption ProduceAssertions{}         = True
+isStartModeOption ProduceAssignments{}        = True
+isStartModeOption ProduceProofs{}             = True
+isStartModeOption ProduceInterpolants{}       = True
+isStartModeOption ProduceUnsatAssumptions{}   = True
+isStartModeOption ProduceUnsatCores{}         = True
+isStartModeOption ProduceAbducts{}            = True
+isStartModeOption RandomSeed{}                = True
+isStartModeOption ReproducibleResourceLimit{} = False
+isStartModeOption SMTVerbosity{}              = False
+isStartModeOption OptionKeyword{}             = True  -- Conservative.
+isStartModeOption SetLogic{}                  = True
+isStartModeOption SetInfo{}                   = False
+isStartModeOption SetTimeOut{}                = True
+
+-- | Can this option be set multiple times? I'm only making a guess here.
+-- If this returns True, then we'll only send the last instance we see.
+-- We might need to update as necessary.
+isOnlyOnceOption :: SMTOption -> Bool
+isOnlyOnceOption DiagnosticOutputChannel{}   = True
+isOnlyOnceOption ProduceAssertions{}         = True
+isOnlyOnceOption ProduceAssignments{}        = True
+isOnlyOnceOption ProduceProofs{}             = True
+isOnlyOnceOption ProduceInterpolants{}       = True
+isOnlyOnceOption ProduceUnsatAssumptions{}   = True
+isOnlyOnceOption ProduceAbducts{}            = False
+isOnlyOnceOption ProduceUnsatCores{}         = True
+isOnlyOnceOption RandomSeed{}                = False
+isOnlyOnceOption ReproducibleResourceLimit{} = False
+isOnlyOnceOption SMTVerbosity{}              = False
+isOnlyOnceOption OptionKeyword{}             = False -- This is really hard to determine. Just being permissive
+isOnlyOnceOption SetLogic{}                  = True
+isOnlyOnceOption SetInfo{}                   = False
+isOnlyOnceOption SetTimeOut{}                = False
+
+-- | SMT-Lib logics. If left unspecified SBV will pick the logic based on what it determines is needed. However, the
+-- user can override this choice using a call to 'Data.SBV.setLogic' This is especially handy if one is experimenting with custom
+-- logics that might be supported on new solvers. See <https://smt-lib.org/logics.shtml> for the official list.
+data Logic
+  = AUFLIA             -- ^ Formulas over the theory of linear integer arithmetic and arrays extended with free sort and function symbols but restricted to arrays with integer indices and values.
+  | AUFLIRA            -- ^ Linear formulas with free sort and function symbols over one- and two-dimensional arrays of integer index and real value.
+  | AUFNIRA            -- ^ Formulas with free function and predicate symbols over a theory of arrays of arrays of integer index and real value.
+  | LRA                -- ^ Linear formulas in linear real arithmetic.
+  | QF_ABV             -- ^ Quantifier-free formulas over the theory of bit-vectors and bit-vector arrays.
+  | QF_AUFBV           -- ^ Quantifier-free formulas over the theory of bit-vectors and bit-vector arrays extended with free sort and function symbols.
+  | QF_AUFLIA          -- ^ Quantifier-free linear formulas over the theory of integer arrays extended with free sort and function symbols.
+  | QF_AX              -- ^ Quantifier-free formulas over the theory of arrays with extensionality.
+  | QF_BV              -- ^ Quantifier-free formulas over the theory of fixed-size bit-vectors.
+  | QF_IDL             -- ^ Difference Logic over the integers. Boolean combinations of inequations of the form x - y < b where x and y are integer variables and b is an integer constant.
+  | QF_LIA             -- ^ Unquantified linear integer arithmetic. In essence, Boolean combinations of inequations between linear polynomials over integer variables.
+  | QF_LRA             -- ^ Unquantified linear real arithmetic. In essence, Boolean combinations of inequations between linear polynomials over real variables.
+  | QF_NIA             -- ^ Quantifier-free integer arithmetic.
+  | QF_NRA             -- ^ Quantifier-free real arithmetic.
+  | QF_RDL             -- ^ Difference Logic over the reals. In essence, Boolean combinations of inequations of the form x - y < b where x and y are real variables and b is a rational constant.
+  | QF_UF              -- ^ Unquantified formulas built over a signature of uninterpreted (i.e., free) sort and function symbols.
+  | QF_UFBV            -- ^ Unquantified formulas over bit-vectors with uninterpreted sort function and symbols.
+  | QF_UFIDL           -- ^ Difference Logic over the integers (in essence) but with uninterpreted sort and function symbols.
+  | QF_UFLIA           -- ^ Unquantified linear integer arithmetic with uninterpreted sort and function symbols.
+  | QF_UFLRA           -- ^ Unquantified linear real arithmetic with uninterpreted sort and function symbols.
+  | QF_UFNRA           -- ^ Unquantified non-linear real arithmetic with uninterpreted sort and function symbols.
+  | QF_UFNIRA          -- ^ Unquantified non-linear real integer arithmetic with uninterpreted sort and function symbols.
+  | UFLRA              -- ^ Linear real arithmetic with uninterpreted sort and function symbols.
+  | UFNIA              -- ^ Non-linear integer arithmetic with uninterpreted sort and function symbols.
+  | QF_FPBV            -- ^ Quantifier-free formulas over the theory of floating point numbers, arrays, and bit-vectors.
+  | QF_FP              -- ^ Quantifier-free formulas over the theory of floating point numbers.
+  | QF_FD              -- ^ Quantifier-free finite domains.
+  | QF_S               -- ^ Quantifier-free formulas over the theory of strings.
+  | Logic_ALL          -- ^ The catch-all value.
+  | Logic_NONE         -- ^ Use this value when you want SBV to simply not set the logic.
+  | CustomLogic String -- ^ In case you need a really custom string!
+
+-- The show instance is "almost" the derived one, but not quite!
+instance Show Logic where
+  show AUFLIA          = "AUFLIA"
+  show AUFLIRA         = "AUFLIRA"
+  show AUFNIRA         = "AUFNIRA"
+  show LRA             = "LRA"
+  show QF_ABV          = "QF_ABV"
+  show QF_AUFBV        = "QF_AUFBV"
+  show QF_AUFLIA       = "QF_AUFLIA"
+  show QF_AX           = "QF_AX"
+  show QF_BV           = "QF_BV"
+  show QF_IDL          = "QF_IDL"
+  show QF_LIA          = "QF_LIA"
+  show QF_LRA          = "QF_LRA"
+  show QF_NIA          = "QF_NIA"
+  show QF_NRA          = "QF_NRA"
+  show QF_RDL          = "QF_RDL"
+  show QF_UF           = "QF_UF"
+  show QF_UFBV         = "QF_UFBV"
+  show QF_UFIDL        = "QF_UFIDL"
+  show QF_UFLIA        = "QF_UFLIA"
+  show QF_UFLRA        = "QF_UFLRA"
+  show QF_UFNRA        = "QF_UFNRA"
+  show QF_UFNIRA       = "QF_UFNIRA"
+  show UFLRA           = "UFLRA"
+  show UFNIA           = "UFNIA"
+  show QF_FPBV         = "QF_FPBV"
+  show QF_FP           = "QF_FP"
+  show QF_FD           = "QF_FD"
+  show QF_S            = "QF_S"
+  show Logic_ALL       = "ALL"
+  show Logic_NONE      = "Logic_NONE"
+  show (CustomLogic l) = l
+
+{- HLint ignore type SMTInfoResponse "Use camelCase" -}
+{- HLint ignore type Logic           "Use camelCase" -}
diff --git a/Data/SBV/Control/Utils.hs b/Data/SBV/Control/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Control/Utils.hs
@@ -0,0 +1,2185 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Control.Utils
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Query related utils.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns           #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE InstanceSigs           #-}
+{-# LANGUAGE LambdaCase             #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE OverloadedStrings      #-}
+{-# LANGUAGE RankNTypes             #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TupleSections          #-}
+{-# LANGUAGE TypeApplications       #-}
+{-# LANGUAGE ViewPatterns           #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Control.Utils (
+       io
+     , ask, send, getValue, getFunction
+     , getValueCV, getUICVal, getUIFunCVAssoc, getUnsatAssumptions
+     , SMTFunction(..), getQueryState, modifyQueryState, getConfig, getObjectives, getUIs
+     , getSBVAssertions, getObservables
+     , checkSat, checkSatUsing, getAllSatResult
+     , inNewContext, freshVar, freshVar_
+     , getTopLevelInputs, parse, unexpected
+     , timeout, queryDebug, retrieveResponse, runProofOn, executeQuery
+     , startOptimizer, getObjectiveValues, getModel, getModelAtIndex
+     ) where
+
+import Data.List  (sortOn, partition, groupBy, tails, intercalate, isPrefixOf, isSuffixOf)
+
+import Data.Char      (isPunctuation, isSpace, isDigit)
+import Data.Function  (on)
+import Data.Bifunctor (first)
+
+import Data.Proxy
+
+import qualified Data.Foldable      as F (toList, for_)
+import qualified Data.Map.Strict    as Map
+import qualified Data.Set           as Set  (empty, fromList, toAscList)
+import qualified Data.Sequence      as S
+import qualified Data.Text          as T
+
+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)
+
+import Data.Maybe (isNothing, isJust, catMaybes, listToMaybe)
+
+import Data.IORef (readIORef, writeIORef, IORef, newIORef, modifyIORef')
+
+import Data.Time (getZonedTime)
+import Data.Ratio
+
+import Data.SBV.Core.Data     ( SV(..), trueSV, falseSV, CV(..), trueCV, falseCV, SBV, sbvToSV, kindOf, Kind(..)
+                              , HasKind(..), mkConstCV, CVal(..), SMTResult(..)
+                              , NamedSymVar, SMTConfig(..), SMTModel(..)
+                              , QueryState(..), SVal(..), cache
+                              , newExpr, SBVExpr(..), Op(..), FPOp(..), SBV(..)
+                              , SolverContext(..), SBool, Objective(..), SolverCapabilities(..), capabilities
+                              , Result(..), SMTProblem(..), trueSV, SymVal(..), SBVPgm(..), SMTSolver(..), SBVRunMode(..)
+                              , SBVType(..), forceSVArg, (.=>)
+                              , RCSet(..), QuantifiedBool(..), ArrayModel(..), SInfo(..), getSInfo
+                              , OptimizeStyle(..), GeneralizedCV(..), ExtCV(..)
+                              )
+
+import Data.SBV.Core.Symbolic ( IncState(..), withNewIncState, State(..), svToSV, symbolicEnv, SymbolicT
+                              , MonadQuery(..), QueryContext(..), VarContext(..)
+                              , registerLabel, svMkSymVar, validationRequested
+                              , isSafetyCheckingIStage, isSetupIStage, isRunIStage, IStage(..), QueryT(..)
+                              , extractSymbolicSimulationState, MonadSymbolic(..)
+                              , UserInputs, getSV, NamedSymVar(..), lookupInput, getUserName, getUserName'
+                              , Name, CnstMap, Inputs(..), ProgInfo(..)
+                              , mustIgnoreVar, newInternalVariable, Penalty(..), smtLibPgmText
+                              )
+
+import Data.SBV.Core.AlgReals    (mergeAlgReals, AlgReal(..), RealPoint(..))
+import Data.SBV.Core.SizedFloats (fpZero, fpFromInteger, fpFromFloat, fpFromDouble)
+import Data.SBV.Core.Kind        (smtType, hasUninterpretedSorts, expandKinds, isSomeKindOfFloat, substituteADTVars)
+import Data.SBV.Core.Operations  (svNot, svNotEqual, svOr, svEqual)
+
+import Data.SBV.SMT.SMT     (showModel, parseCVs, SatModel, AllSatResult(..), OptimizeResult(..))
+import Data.SBV.SMT.SMTLib  (toIncSMTLib, toSMTLib)
+import Data.SBV.SMT.SMTLib2 (setSMTOption)
+import Data.SBV.SMT.Utils   ( showTimeoutValue, addAnnotations, alignPlain, debug
+                            , mergeSExpr, SBVException(..), recordTranscript, TranscriptMsg(..)
+                            )
+
+import Data.SBV.Utils.ExtractIO
+import Data.SBV.Utils.Lib       (qfsToString, unBar, mapToSortedList, showText)
+import Data.SBV.Utils.SExpr
+import Data.SBV.Utils.PrettyNum (cvToSMTLib)
+
+import Data.SBV.Control.Types
+
+import qualified Control.Exception as C
+
+import GHC.Stack
+
+-- | 'Data.SBV.Trans.Control.QueryT' as a 'SolverContext'.
+instance MonadIO m => SolverContext (QueryT m) where
+   constrain                   = addQueryConstraint False []                . quantifiedBool
+   softConstrain               = addQueryConstraint True  []                . quantifiedBool
+   namedConstraint nm          = addQueryConstraint False [(":named", nm)]  . quantifiedBool
+   constrainWithAttribute attr = addQueryConstraint False attr              . quantifiedBool
+
+   contextState = queryState
+
+   internalVariable :: forall a. Kind -> QueryT m (SBV a)
+   internalVariable k = contextState >>= \st -> liftIO $ do
+       sv  <- newInternalVariable st k
+       pure $ SBV $ SVal k (Right (cache (const (pure sv))))
+
+   setOption o
+     | isStartModeOption o = error $ unlines [ ""
+                                             , "*** Data.SBV: '" ++ show o ++ "' can only be set at start-up time."
+                                             , "*** Hint: Move the call to 'setOption' before the query."
+                                             ]
+     | True                = do State{stCfg} <- contextState
+                                send True $ setSMTOption stCfg o
+
+-- | Adding a constraint, possibly with attributes and possibly soft. Only used internally.
+-- Use 'constrain' and 'namedConstraint' from user programs.
+addQueryConstraint :: (MonadIO m, MonadQuery m) => Bool -> [(String, String)] -> SBool -> m ()
+addQueryConstraint isSoft atts b = do sv <- inNewContext (\st -> liftIO $ do mapM_ (registerLabel "Constraint" st) [nm | (":named", nm) <- atts]
+                                                                             sbvToSV st b)
+
+                                      unless (null atts && sv == trueSV) $
+                                             send True $ "(" <> T.pack asrt <> " " <> addAnnotations atts (showText sv) <> ")"
+   where asrt | isSoft = "assert-soft"
+              | True   = "assert"
+
+-- | Get the current configuration
+getConfig :: (MonadIO m, MonadQuery m) => m SMTConfig
+getConfig = queryConfig <$> getQueryState
+
+-- | Get the objectives
+getObjectives :: (MonadIO m, MonadQuery m) => m [Objective (SV, SV)]
+getObjectives = do State{rOptGoals} <- queryState
+                   io $ reverse <$> readIORef rOptGoals
+
+-- | Get the assertions put in via 'Data.SBV.sAssert'
+getSBVAssertions :: (MonadIO m, MonadQuery m) => m [(String, Maybe CallStack, SV)]
+getSBVAssertions = do State{rAsserts} <- queryState
+                      io $ reverse <$> readIORef rAsserts
+
+-- | Generalization of 'Data.SBV.Control.io'
+io :: MonadIO m => IO a -> m a
+io = liftIO
+
+-- | Sync-up the external solver with new context we have generated
+syncUpSolver :: (MonadIO m, MonadQuery m) => ProgInfo -> IORef CnstMap -> IncState -> m ()
+syncUpSolver progInfo rGlobalConsts is = do
+        cfg <- getConfig
+
+        -- update global consts to have the new ones
+        (newConsts, allConsts) <- liftIO $ do nc <- readIORef (rNewConsts is)
+                                              oc <- readIORef rGlobalConsts
+                                              let !allConsts = Map.union nc oc
+                                              writeIORef rGlobalConsts allConsts
+                                              pure (nc, allConsts)
+
+        ls  <- io $ do let arrange (i, (at, rt, es)) = ((i, at, rt), es)
+                       inps        <- reverse <$> readIORef (rNewInps is)
+                       ks          <- readIORef (rNewKinds is)
+                       tbls        <- map arrange . mapToSortedList <$> readIORef (rNewTbls is)
+                       uis         <- Map.toAscList <$> readIORef (rNewUIs is)
+                       as          <- readIORef (rNewAsgns is)
+                       constraints <- readIORef (rNewConstraints is)
+
+                       let cnsts = mapToSortedList newConsts
+
+                       pure $ toIncSMTLib cfg progInfo inps ks (allConsts, cnsts) tbls uis as constraints cfg
+
+        mapM_ (send True) $ mergeSExpr ls
+
+-- | Retrieve the query context
+getQueryState :: (MonadIO m, MonadQuery m) => m QueryState
+getQueryState = do state <- queryState
+                   mbQS  <- io $ readIORef (rQueryState state)
+                   case mbQS of
+                     Nothing -> error $ unlines [ ""
+                                                , "*** Data.SBV: Impossible happened: Query context required in a non-query mode."
+                                                , "Please report this as a bug!"
+                                                ]
+                     Just qs -> pure qs
+
+-- | Generalization of 'Data.SBV.Control.modifyQueryState'
+modifyQueryState :: (MonadIO m, MonadQuery m) => (QueryState -> QueryState) -> m ()
+modifyQueryState f = do state <- queryState
+                        mbQS  <- io $ readIORef (rQueryState state)
+                        case mbQS of
+                          Nothing -> error $ unlines [ ""
+                                                     , "*** Data.SBV: Impossible happened: Query context required in a non-query mode."
+                                                     , "Please report this as a bug!"
+                                                     ]
+                          Just qs -> let fqs = f qs
+                                     in fqs `seq` io $ writeIORef (rQueryState state) $ Just fqs
+
+-- | Generalization of 'Data.SBV.Control.inNewContext'
+inNewContext :: (MonadIO m, MonadQuery m) => (State -> IO a) -> m a
+inNewContext act = do st@State{rconstMap, rProgInfo} <- queryState
+                      (is, r)  <- io $ withNewIncState st act
+                      progInfo <- io $ readIORef rProgInfo
+                      syncUpSolver progInfo rconstMap is
+                      pure r
+
+-- | Generalization of 'Data.SBV.Control.freshVar_'
+freshVar_ :: forall a m. (MonadIO m, MonadQuery m, SymVal a) => m (SBV a)
+freshVar_ = inNewContext $ fmap SBV . svMkSymVar QueryVar k Nothing
+  where k = kindOf (Proxy @a)
+
+-- | Generalization of 'Data.SBV.Control.freshVar'
+freshVar :: forall a m. (MonadIO m, MonadQuery m, SymVal a) => String -> m (SBV a)
+freshVar nm = inNewContext $ fmap SBV . svMkSymVar QueryVar k (Just nm)
+  where k = kindOf (Proxy @a)
+
+-- | Generalization of 'Data.SBV.Control.queryDebug'
+queryDebug :: (MonadIO m, MonadQuery m) => [T.Text] -> m ()
+queryDebug msgs = do QueryState{queryConfig} <- getQueryState
+                     io $ do debug queryConfig msgs
+                             recordTranscript (transcript queryConfig) (DebugMsg (T.unlines msgs))
+
+-- | We need to track sent asserts/check-sat calls so we can issue an extra check-sat call if needed
+trackAsserts :: (MonadIO m, MonadQuery m) => T.Text -> m ()
+trackAsserts s
+   | isCheckSat || isAssert
+   = do State{rOutstandingAsserts} <- queryState
+        liftIO $ writeIORef rOutstandingAsserts isAssert
+   | True
+   = pure ()
+  where trimmedS   = T.dropWhile isSpace s
+        isCheckSat = "(check-sat" `T.isPrefixOf` trimmedS
+        isAssert   = "(assert"    `T.isPrefixOf` trimmedS
+
+-- | Generalization of 'Data.SBV.Control.ask'
+ask :: (MonadIO m, MonadQuery m) => T.Text -> m String
+ask s = askIgnoring s []
+
+-- | Send a string to the solver, and return the response. Except, if the response
+-- is one of the "ignore" ones, keep querying.
+askIgnoring :: (MonadIO m, MonadQuery m) => T.Text -> [String] -> m String
+askIgnoring s ignoreList = do
+
+           trackAsserts s
+
+           QueryState{queryAsk, queryRetrieveResponse, queryTimeOutValue} <- getQueryState
+
+           case queryTimeOutValue of
+             Nothing -> queryDebug ["[SEND] " `alignPlain` s]
+             Just i  -> queryDebug ["[SEND, TimeOut: " <> showTimeoutValue i <> "] " `alignPlain` s]
+           r <- io $ queryAsk queryTimeOutValue s
+           queryDebug ["[RECV] " `alignPlain` T.pack r]
+
+           let loop currentResponse
+                 | currentResponse `notElem` ignoreList
+                 = pure currentResponse
+                 | True
+                 = do queryDebug ["[WARN] Previous response is explicitly ignored, beware!"]
+                      newResponse <- io $ queryRetrieveResponse queryTimeOutValue
+                      queryDebug ["[RECV] " `alignPlain` T.pack newResponse]
+                      loop newResponse
+
+           loop r
+
+-- | Generalization of 'Data.SBV.Control.send'
+send :: (MonadIO m, MonadQuery m) => Bool -> T.Text -> m ()
+send requireSuccess s = do
+
+            trackAsserts s
+
+            QueryState{queryAsk, querySend, queryConfig, queryTimeOutValue} <- getQueryState
+
+            if requireSuccess && supportsCustomQueries (capabilities (solver queryConfig))
+               then do r <- io $ queryAsk queryTimeOutValue s
+
+                       case words r of
+                         ["success"] -> queryDebug ["[GOOD] " `alignPlain` s]
+                         _           -> do case queryTimeOutValue of
+                                             Nothing -> queryDebug ["[FAIL] " `alignPlain` s]
+                                             Just i  -> queryDebug ["[FAIL, TimeOut: " <> showTimeoutValue i <> "]  " `alignPlain` s]
+
+
+                                           let cmd = case T.words (T.dropWhile (\c -> isSpace c || isPunctuation c) s) of
+                                                       (c:_) -> T.unpack c
+                                                       _     -> "Command"
+
+                                           unexpected cmd s "success" Nothing r Nothing
+
+               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]
+retrieveResponse userTag mbTo = do
+             ts  <- io (show <$> getZonedTime)
+
+             let synchTag = show $ userTag ++ " (at: " ++ ts ++ ")"
+                 cmd = "(echo " ++ synchTag ++ ")"
+
+             queryDebug ["[SYNC] Attempting to synchronize with tag: " <> T.pack synchTag]
+
+             send False (T.pack cmd)
+
+             QueryState{queryRetrieveResponse} <- getQueryState
+
+             let loop sofar = do
+                  s <- io $ queryRetrieveResponse mbTo
+
+                  -- strictly speaking SMTLib requires solvers to print quotes around
+                  -- echo'ed strings, but they don't always do. Accommodate for that
+                  -- here, though I wish we didn't have to.
+                  if s == synchTag || show s == synchTag
+                     then do queryDebug ["[SYNC] Synchronization achieved using tag: " <> T.pack synchTag]
+                             pure $ reverse sofar
+                     else do queryDebug ["[RECV] " `alignPlain` T.pack s]
+                             loop (s : sofar)
+
+             loop []
+
+-- | Generalization of 'Data.SBV.Control.getValue'
+getValue :: (MonadIO m, MonadQuery m, SymVal a) => SBV a -> m a
+getValue s = do
+
+      sv <- inNewContext (`sbvToSV` s)
+
+      -- If we're issuing get-value, we gotta make sure there are no outstanding asserts
+      -- This can happen if we sent some ourselves. See https://github.com/LeventErkok/sbv/issues/682
+      outstandingAsserts <- do State{rOutstandingAsserts} <- queryState
+                               liftIO $ readIORef rOutstandingAsserts
+
+      when outstandingAsserts $ do
+        queryDebug ["[NOTE] getValue: There are outstanding asserts. Ensuring we're still sat."]
+        r <- checkSat
+        let bad = unexpected "checkSat" "check-sat" "one of sat/unsat/unknown" Nothing (show r) Nothing
+        case r of
+          Sat    -> pure ()
+          DSat{} -> pure ()
+          Unk    -> bad
+          Unsat  -> bad
+
+      -- Are we in an optimization context? If so, we must ensure that the model is not in an extended field
+      objs <- getObjectives
+      unless (null objs) $ do
+         ovs <- getObjectiveValues
+         case [() | (_, ExtendedCV _) <- ovs] of
+           [] -> pure ()    -- We're good, all objectives are within the domain
+           _  -> do cfg <- getConfig
+                    m   <- getModel
+                    ov  <- getObjectiveValues
+
+                    let mdl = LexicographicResult (SatExtField cfg m{modelObjectives = ov})
+
+                        align "" = "***"
+                        align l  = "*** " ++ l
+
+                    error $ unlines $ "" : map align ([
+                                "Data.SBV.getValue: The current solver state is satisfiable in an extension field."
+                              , "That is, the optimized values assume epsilon/infinity values."
+                              , ""
+                              , "Calls to getValue is not supported in this context. Instead, use the 'optimize' method"
+                              , "directly and inspect the objective values explicitly."
+                              , ""
+                              , "The current model is:"
+                              , ""
+                              ] ++ map ("    " ++) (lines (show mdl)))
+
+      cv <- getValueCV Nothing sv
+      pure $ fromCV cv
+
+-- | A class which allows for sexpr-conversion to functions
+class (HasKind r, SatModel r) => SMTFunction fun a r | fun -> a r where
+  sexprToArg     :: (MonadIO m, SolverContext m) => fun -> [SExpr] -> m (Maybe a)
+  smtFunName     :: (MonadIO m, SolverContext m) => fun -> m ((String, Maybe [String]), Bool)
+  smtFunSaturate :: fun -> SBV r
+  smtFunType     :: fun -> SBVType
+  smtFunDefault  :: fun -> Maybe r
+  sexprToFun     :: (MonadIO m, SolverContext m, MonadQuery m, MonadSymbolic m, SymVal r) => fun -> (String, SExpr) -> m (Either String ([(a, r)], r))
+
+  {-# MINIMAL sexprToArg, smtFunSaturate, smtFunType  #-}
+
+  -- Given the function, figure out a default "return value"
+  smtFunDefault _
+    | let 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
+                    nm    <- findName st uiMap
+
+                    -- Read the uiMap again here. Why? Because the act of finding the name might've
+                    -- introduced it as an uninterpreted name!
+                    newUIMap <- liftIO $ readIORef rUIMap
+                    case nm `Map.lookup` newUIMap of
+                      Nothing                     -> cantFind newUIMap
+                      Just (isCurried, mbArgs, _) -> pure ((nm, mbArgs), isCurried)
+    where cantFind uiMap = 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
+                                        ]
+
+          findName st@State{spgm} uiMap = do
+             r <- liftIO $ sbvToSV st (smtFunSaturate f)
+             liftIO $ forceSVArg r
+             SBVPgm asgns <- liftIO $ readIORef spgm
+
+
+             case S.findIndexR ((== r) . fst) asgns of
+               Nothing -> cantFind uiMap
+               Just i  -> case asgns `S.index` i of
+                            (sv, SBVApp (Uninterpreted nm) _) | r == sv -> pure (T.unpack nm)
+                            _                                           -> cantFind uiMap
+
+  sexprToFun f (s, e) = do nm    <- fst . fst <$> smtFunName f
+                           si    <- contextState >>= getSInfo
+                           mbRes <- case parseSExprFunction e of
+                                      Just (Left nm') -> case (nm == nm', smtFunDefault f) of
+                                                           (True, Just v)  -> pure $ Just ([], v)
+                                                           _               -> bailOut nm
+                                      Just (Right v)  -> convert si v
+                                      Nothing         -> do mbPVS <- pointWiseExtract nm (smtFunType f)
+                                                            case mbPVS of
+                                                              Nothing  -> pure Nothing
+                                                              Just pts -> convert si pts
+                           pure $ maybe (Left s) Right mbRes
+    where convert st (vs, d) = do ps <- mapM (sexprPoint st) vs
+                                  pure $ (,) <$> sequenceA ps <*> sexprToVal st d
+
+          sexprPoint st (as, v) = do mbA <- sexprToArg f as
+                                     pure $ (,) <$> mbA <*> sexprToVal st 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!"
+                                       ]
+
+-- | 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 = tryPointWise
+  where trueSExpr  = ENum (1, Nothing, True)
+        falseSExpr = ENum (0, Nothing, True)
+
+        isTrueSExpr (ENum (1, Nothing, True)) = True
+        isTrueSExpr (ENum (0, Nothing, True)) = 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 ((" <> T.pack nm <> " " <> T.pack 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]] -> pure (args, e)
+                                              _                  -> bad r Nothing
+
+        getBVals :: m [([SExpr], SExpr)]
+        getBVals = mapM getBVal $ replicateM nArgs [falseSExpr, trueSExpr]
+
+        tryPointWise
+          | not isBoolFunc
+          = pure 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
+               pure $ 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.
+mkSaturatingArg :: forall a. Kind -> SBV a
+mkSaturatingArg k = SBV $ SVal k (Left (defaultKindedValue k))
+
+-- | Functions of arity 1
+instance ( SymVal a, HasKind a
+         , SatModel r, HasKind r
+         ) => SMTFunction (SBV a -> SBV r) a r
+         where
+  sexprToArg _ [a0] = contextState >>= getSInfo >>= \si -> pure $ sexprToVal si a0
+  sexprToArg _ _    = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f $ mkSaturatingArg (kindOf (Proxy @a))
+
+-- | Functions of arity 2
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SatModel r, HasKind r
+         ) => SMTFunction (SBV a -> SBV b -> SBV r) (a, b) r
+         where
+  sexprToArg _ [a0, a1] = contextState >>= getSInfo >>= \si -> pure $ (,) <$> sexprToVal si a0 <*> sexprToVal si a1
+  sexprToArg _ _        = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+
+-- | Functions of arity 3
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SatModel r, HasKind r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV r) (a, b, c) r
+         where
+  sexprToArg _ [a0, a1, a2] = contextState >>= getSInfo >>= \si -> pure $ (,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2
+  sexprToArg _ _            = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+
+-- | Functions of arity 4
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SymVal d,   HasKind d
+         , SatModel r, HasKind r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV r) (a, b, c, d) r
+         where
+  sexprToArg _ [a0, a1, a2, a3] = contextState >>= getSInfo >>= \si -> pure $ (,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3
+  sexprToArg _ _                = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+                       (mkSaturatingArg (kindOf (Proxy @d)))
+
+-- | Functions of arity 5
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SymVal d,   HasKind d
+         , SymVal e,   HasKind e
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4
+  sexprToArg _ _                    = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+                       (mkSaturatingArg (kindOf (Proxy @d)))
+                       (mkSaturatingArg (kindOf (Proxy @e)))
+
+-- | Functions of arity 6
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SymVal d,   HasKind d
+         , SymVal e,   HasKind e
+         , SymVal f,   HasKind f
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5
+  sexprToArg _ _                        = pure 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 (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+                       (mkSaturatingArg (kindOf (Proxy @d)))
+                       (mkSaturatingArg (kindOf (Proxy @e)))
+                       (mkSaturatingArg (kindOf (Proxy @f)))
+
+-- | Functions of arity 7
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SymVal d,   HasKind d
+         , SymVal e,   HasKind e
+         , SymVal f,   HasKind f
+         , SymVal g,   HasKind g
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6
+  sexprToArg _ _                            = pure 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 (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+                       (mkSaturatingArg (kindOf (Proxy @d)))
+                       (mkSaturatingArg (kindOf (Proxy @e)))
+                       (mkSaturatingArg (kindOf (Proxy @f)))
+                       (mkSaturatingArg (kindOf (Proxy @g)))
+
+-- | Functions of arity 8
+instance ( SymVal a,   HasKind a
+         , SymVal b,   HasKind b
+         , SymVal c,   HasKind c
+         , SymVal d,   HasKind d
+         , SymVal e,   HasKind e
+         , SymVal f,   HasKind f
+         , SymVal g,   HasKind g
+         , SymVal h,   HasKind h
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6 <*> sexprToVal si a7
+  sexprToArg _ _                                = pure 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 (mkSaturatingArg (kindOf (Proxy @a)))
+                       (mkSaturatingArg (kindOf (Proxy @b)))
+                       (mkSaturatingArg (kindOf (Proxy @c)))
+                       (mkSaturatingArg (kindOf (Proxy @d)))
+                       (mkSaturatingArg (kindOf (Proxy @e)))
+                       (mkSaturatingArg (kindOf (Proxy @f)))
+                       (mkSaturatingArg (kindOf (Proxy @g)))
+                       (mkSaturatingArg (kindOf (Proxy @h)))
+
+-- | Curried functions of arity 2
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SatModel r, HasKind r
+         ) => SMTFunction ((SBV a, SBV b) -> SBV r) (a, b) r
+         where
+  sexprToArg _ [a0, a1] = contextState >>= getSInfo >>= \si -> pure $ (,) <$> sexprToVal si a0 <*> sexprToVal si a1
+  sexprToArg _ _        = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       )
+
+-- | Curried functions of arity 3
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SatModel r, HasKind r
+         ) => SMTFunction ((SBV a, SBV b, SBV c) -> SBV r) (a, b, c) r
+         where
+  sexprToArg _ [a0, a1, a2] = contextState >>= getSInfo >>= \si -> pure $ (,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2
+  sexprToArg _ _            = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       )
+
+-- | Curried functions of arity 4
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SymVal d,  HasKind d
+         , SatModel r, HasKind r
+         ) => SMTFunction ((SBV a, SBV b, SBV c, SBV d) -> SBV r) (a, b, c, d) r
+         where
+  sexprToArg _ [a0, a1, a2, a3] = contextState >>= getSInfo >>= \si -> pure $ (,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3
+  sexprToArg _ _                = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       , mkSaturatingArg (kindOf (Proxy @d))
+                       )
+
+-- | Curried functions of arity 5
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SymVal d,  HasKind d
+         , SymVal e,  HasKind e
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4
+  sexprToArg _ _                    = pure Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       , mkSaturatingArg (kindOf (Proxy @d))
+                       , mkSaturatingArg (kindOf (Proxy @e))
+                       )
+
+-- | Curried functions of arity 6
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SymVal d,  HasKind d
+         , SymVal e,  HasKind e
+         , SymVal f,  HasKind f
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5
+  sexprToArg _ _                        = pure 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 ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       , mkSaturatingArg (kindOf (Proxy @d))
+                       , mkSaturatingArg (kindOf (Proxy @e))
+                       , mkSaturatingArg (kindOf (Proxy @f))
+                       )
+
+-- | Curried functions of arity 7
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SymVal d,  HasKind d
+         , SymVal e,  HasKind e
+         , SymVal f,  HasKind f
+         , SymVal g,  HasKind g
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6
+  sexprToArg _ _                            = pure 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 ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       , mkSaturatingArg (kindOf (Proxy @d))
+                       , mkSaturatingArg (kindOf (Proxy @e))
+                       , mkSaturatingArg (kindOf (Proxy @f))
+                       , mkSaturatingArg (kindOf (Proxy @g))
+                       )
+
+-- | Curried functions of arity 8
+instance ( SymVal a,  HasKind a
+         , SymVal b,  HasKind b
+         , SymVal c,  HasKind c
+         , SymVal d,  HasKind d
+         , SymVal e,  HasKind e
+         , SymVal f,  HasKind f
+         , SymVal g,  HasKind g
+         , SymVal h,  HasKind h
+         , SatModel r, HasKind 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] = contextState >>= getSInfo >>= \si -> pure $ (,,,,,,,) <$> sexprToVal si a0 <*> sexprToVal si a1 <*> sexprToVal si a2 <*> sexprToVal si a3 <*> sexprToVal si a4 <*> sexprToVal si a5 <*> sexprToVal si a6 <*> sexprToVal si a7
+  sexprToArg _ _                                = pure 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 ( mkSaturatingArg (kindOf (Proxy @a))
+                       , mkSaturatingArg (kindOf (Proxy @b))
+                       , mkSaturatingArg (kindOf (Proxy @c))
+                       , mkSaturatingArg (kindOf (Proxy @d))
+                       , mkSaturatingArg (kindOf (Proxy @e))
+                       , mkSaturatingArg (kindOf (Proxy @f))
+                       , mkSaturatingArg (kindOf (Proxy @g))
+                       , mkSaturatingArg (kindOf (Proxy @h))
+                       )
+
+-- Turn "((F (lambda ((x!1 Int)) (+ 3 (* 2 x!1)))))"
+-- into something more palatable.
+-- If we can't do that, we simply return the input unchanged
+trimFunctionResponse :: String -> String -> Bool -> Maybe [String] -> String
+trimFunctionResponse resp nm isCurried mbArgs
+  | Just parsed <- makeHaskellFunction resp nm isCurried mbArgs
+  = parsed
+  | True
+  = def $ case trim resp of
+            '(':'(':rest | nm `isPrefixOf` rest -> butLast2 $ trim (drop (length nm) rest)
+            _                                   -> resp
+  where trim     = dropWhile isSpace
+        butLast2 = reverse . drop 2 . reverse
+        def x = nm ++ " = fromSMTLib " ++ x
+
+-- | Generalization of 'Data.SBV.Control.getFunction'
+getFunction :: (MonadIO m, MonadQuery m, SolverContext m, MonadSymbolic m, SymVal a, SymVal r, SMTFunction fun a r)
+            => fun -> m (Either (String, (Bool, Maybe [String], SExpr))  ([(a, r)], r))
+getFunction f = do ((nm, args), isCurried) <- smtFunName f
+
+                   let cmd = "(get-value (" <> T.pack nm <> "))"
+                       bad = unexpected "getFunction" cmd "a function value" Nothing
+
+                   r <- ask cmd
+
+                   si <- contextState >>= getSInfo
+
+                   parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> do
+                                          mbAssocs <- sexprToFun f (trimFunctionResponse r nm isCurried args, e)
+                                          case mbAssocs of
+                                            Right assocs -> pure $ Right assocs
+                                            Left  raw    -> do
+                                               let rawRes = Left (raw, (isCurried, args, e))
+                                               mbPVS <- pointWiseExtract nm (smtFunType f)
+                                               case mbPVS of
+                                                 Just ps -> do rs <- convert si ps
+                                                               case rs of
+                                                                  Just x  -> pure $ Right x
+                                                                  Nothing -> pure rawRes
+                                                 Nothing -> pure rawRes
+                                       _ -> bad r Nothing
+    where convert si (vs, d) = do ps <- mapM (sexprPoint si) vs
+                                  pure $ (,) <$> sequenceA ps <*> sexprToVal si d
+
+          sexprPoint si (as, v) = do mbA <- sexprToArg f as
+                                     pure $ (,) <$> mbA <*> sexprToVal si v
+
+-- | Get the value of a term, but in CV form. Used internally. The model-index, in particular is extremely Z3 specific!
+getValueCVHelper :: (MonadIO m, MonadQuery m) => Maybe Int -> SV -> m CV
+getValueCVHelper mbi s
+  | s == trueSV
+  = pure trueCV
+  | s == falseSV
+  = pure falseCV
+  | True
+  = extractValue mbi (show s) (kindOf s)
+
+-- | "Make up" a CV for this type. Like zero, but smarter.
+defaultKindedValue :: Kind -> CV
+defaultKindedValue k = CV k $ cvt k
+  where cvt :: Kind -> CVal
+        cvt (KVar s)         = error ("defaultKindedValue: Unexpected kind: " ++ s)
+        cvt KBool            = CInteger 0
+        cvt KBounded{}       = CInteger 0
+        cvt KUnbounded       = CInteger 0
+        cvt KReal            = CAlgReal 0
+        cvt KFloat           = CFloat 0
+        cvt KDouble          = CDouble 0
+        cvt KRational        = CRational 0
+        cvt (KFP eb sb)      = CFP (fpZero False eb sb)
+        cvt KChar            = CChar '\NUL'                -- why not?
+        cvt KString          = CString ""
+        cvt (KList  _)       = CList []
+        cvt (KSet  _)        = CSet $ RegularSet Set.empty -- why not? Arguably, could be the universal set
+        cvt (KTuple ks)      = CTuple $ map cvt ks
+        cvt (KArray  _  k2)  = CArray $ ArrayModel [] (cvt k2)
+
+        cvt (KApp s _)       = error ("defaultKindedValue not supported for ADT app: " ++ s) -- tough luck
+
+        -- For ADTs, just return the first element if there's any
+        cvt (KADT s _ cstrs) = case cstrs of
+                                 []            -> error ("defaultKindedValue not supported for ADT: "     ++ s) -- tough luck
+                                 ((c, ks) : _) -> CADT (c, [(k, cvt fk) | fk <- ks])
+
+-- | Go from an SExpr directly to a value
+sexprToVal :: forall a. SymVal a => SInfo -> SExpr -> Maybe a
+sexprToVal si e = fromCV <$> recoverKindedValue si (kindOf (Proxy @a)) e
+
+-- | Recover a given solver-printed value with a possible interpretation
+recoverKindedValue :: SInfo -> Kind -> SExpr -> Maybe CV
+recoverKindedValue si k e =
+    case k of
+      KVar{}      -> error $ "Data.SBV.recoverKindedValue: Unexpected var kind: " ++ show k
+
+      KApp n ks   -> case [(s, ps, cstrs) | KADT s ps cstrs <- sInfoKinds si, s == n] of
+                       [(s, ps, cstr)]
+                         | length ks == length ps -> recoverKindedValue si (KADT s (zip (map fst ps) ks) cstr) e
+                       xs -> error $ unlines [ "Data.SBV.recoverKindedValue: Can't uniquely locate reference to ADT: "
+                                             , "***"
+                                             , "*** ADT    : " ++ show n
+                                             , "*** Params : " ++ show ks
+                                             , "*** Matched: " ++ show xs
+                                             , "*** Expr   : " ++ show e
+                                             , "***"
+                                             , "*** Please report this as a bug."
+                                             ]
+
+      KBool       | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
+
+      KBounded{}  | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
+
+      KUnbounded  | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | True                  -> Nothing
+
+      KReal       | ENum (i, _, _) <- e   -> Just $ mkConstCV k i
+                  | EReal i        <- e   -> Just $ CV KReal (CAlgReal i)
+                  | True                  -> interpretInterval e
+
+      KADT nm dict def                    -> let k' = KADT nm dict [(c, map (substituteADTVars nm dict) ks) | (c, ks) <- def]
+                                             in Just $ CV k' $ CADT $ interpretADT k' e
+
+      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
+
+      KFP eb sb   | ENum (i, _, _)   <- e -> Just $ CV k $ CFP $ fpFromInteger eb sb i
+                  | EFloat f         <- e -> Just $ CV k $ CFP $ fpFromFloat   eb sb f
+                  | EDouble d        <- e -> Just $ CV k $ CFP $ fpFromDouble  eb sb d
+                  | EFloatingPoint c <- e -> Just $ CV k $ CFP c
+                  | True                  -> Nothing
+
+      KChar       | ECon s      <- e      -> Just $ CV KChar $ CChar $ interpretChar s
+                  | True                  -> Nothing
+
+      KString     | ECon s      <- e      -> Just $ CV KString $ CString $ interpretString s
+                  | True                  -> Nothing
+
+      KRational                           -> Just $ CV k $ CRational $ interpretRational       e
+      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
+      KArray k1 k2                        -> Just $ CV k $ CArray    $ interpretArray    k1 k2 e
+
+  where stringLike xs = length xs >= 2 && "\"" `isPrefixOf` xs && "\"" `isSuffixOf` xs
+
+        -- Make sure strings are really strings
+        interpretString xs
+          | not (stringLike xs)
+          = error $ "Expected a string constant with quotes, received: <" ++ xs ++ ">"
+          | True
+          = qfsToString $ drop 1 (init xs)
+
+        interpretChar xs = case interpretString xs of
+                             [c] -> c
+                             _   -> error $ "Expected a singleton char constant, received: <" ++ xs ++ ">"
+
+        interpretRational (EApp [ECon "SBV.Rational", v1, v2])
+           | Just (CV _ (CInteger n)) <- recoverKindedValue si KUnbounded v1
+           , Just (CV _ (CInteger d)) <- recoverKindedValue si KUnbounded v2
+           = n % d
+        interpretRational xs = error $ "Expected a rational constant, received: <" ++ show xs ++ ">"
+
+        interpretList ek topExpr = walk topExpr
+          where walk (EApp [ECon "as", v, _])      = walk v
+                walk (ECon "seq.empty")            = []
+                walk (EApp [ECon "seq.unit", v])   = case recoverKindedValue si ek v of
+                                                       Just w -> [cvVal w]
+                                                       Nothing -> error $ "Cannot parse a sequence item of kind " ++ show ek ++ " from: " ++ show v ++ extra v
+                walk (EApp (ECon "seq.++" : rest)) = concatMap walk rest
+                walk cur                           = error $ "Expected a sequence constant, but received: " ++ show cur ++ extra cur
+
+                extra cur | show cur == t = ""
+                          | True          = "\nWhile parsing: " ++ t
+                          where t = show topExpr
+
+        -- 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 :: String -> a
+                 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)) = True
+                 isTrue (ENum (0, Nothing, True)) = 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) <- concatMap (contents True)  args]  -- deletions from universal
+                                  | True     = RegularSet    $ Set.fromList [x | (x, True)  <- concatMap (contents False) args]  -- additions to empty
+
+                 contents cvt ([v], r) = let t = isTrue r in map (, t) (element cvt v)
+                 contents _   bad      = tbd $ "Multi-valued set member seen: " ++ show bad
+
+                 element cvt x = case (cvt, ke) of
+                                   (True, KChar) -> case recoverKindedValue si KString x of
+                                                      Just v  -> case cvVal v of
+                                                                  CString [c] -> [CChar c]
+                                                                  CString _   -> []
+                                                                  _           -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
+                                                      Nothing -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
+                                   _             -> case recoverKindedValue si ke x of
+                                                      Just v  -> [cvVal v]
+                                                      Nothing -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
+
+        interpretTuple te = walk (1 :: Int) (zipWith (recoverKindedValue si) ks args) []
+                where (ks, n) = case k of
+                                  KTuple eks -> (eks, length eks)
+                                  _          -> error $ unlines [ "Impossible: Expected a tuple kind, but got: " ++ show k
+                                                                , "While trying to parse: " ++ show te
+                                                                ]
+
+                      -- | Convert a sexpr of n-tuple to constituent sexprs. Z3 and CVC4 differ here on how they
+                      -- present tuples, so we accommodate both:
+                      args = try te
+                        where -- Z3 way
+                              try (EApp (ECon f : as)) = case splitAt (T.length "mkSBVTuple") f of
+                                                             ("mkSBVTuple", c) | all isDigit c && read c == n && length as == n -> as
+                                                             _  -> bad
+                              -- CVC4 way
+                              try  (EApp (EApp [ECon "as", ECon f, _] : as)) = try (EApp (ECon f : as))
+                              try  _ = bad
+                              bad = error $ "Data.SBV.sexprToTuple: Impossible: Expected a constructor for " ++ show n ++ " tuple, but got: " ++ show te
+
+                      walk _ []           sofar = reverse sofar
+                      walk i (Just el:es) sofar = walk (i+1) es (cvVal el : sofar)
+                      walk i (Nothing:_)  _     = error $ unlines [ "Couldn't parse a tuple element at position " ++ show i
+                                                                  , "Kind: " ++ show k
+                                                                  , "Expr: " ++ show te
+                                                                  ]
+
+        -- Intervals, for dReal
+        interpretInterval expr = case expr of
+                                   EApp [ECon "interval", lo, hi] -> do vlo <- getBorder lo
+                                                                        vhi <- getBorder hi
+                                                                        pure $ CV KReal (CAlgReal (AlgInterval vlo vhi))
+                                   _                              -> Nothing
+          where getBorder (EApp [ECon "open",   v]) = recoverKindedValue si KReal v >>= border OpenPoint
+                getBorder (EApp [ECon "closed", v]) = recoverKindedValue si KReal v >>= border ClosedPoint
+                getBorder _                         = Nothing
+
+                border b (CV KReal (CAlgReal (AlgRational True v))) = pure $ b v
+                border _ other                                      = error $ "Data.SBV.interpretInterval.border: Expected a real-valued sexp, but received: " ++ show other
+
+        -- Essentially treat sets as functions, since we do allow for store associations
+        interpretArray k1 k2 expr = case parseSExprFunction expr of
+                                      Just (Right ascs) -> decode ascs
+                                      _                 -> tbd "Expected a set value, but couldn't decipher the solver output."
+
+           where tbd :: String -> a
+                 tbd w = error $ unlines [ ""
+                                         , "*** Data.SBV.interpretArray: Unable to process solver output."
+                                         , "***"
+                                         , "*** Kind    : " ++ show k
+                                         , "*** Received: " ++ show e
+                                         , "*** Reason  : " ++ w
+                                         , "***"
+                                         , "*** This is either a bug or something SBV currently does not support."
+                                         , "*** Please report this as a feature request!"
+                                         ]
+
+                 decode (args, d) = ArrayModel [(cvt k1 l, cvt k2 [r]) | (l, r) <- args] (cvt k2 [d])
+                   where cvt ek [v] = case recoverKindedValue si ek v of
+                                         Just (CV _ x) -> x
+                                         _             -> tbd $ "Cannot convert value: " ++ show v
+                         cvt _ vs   = tbd $ "Unexpected function-like-value as array index" ++ show vs
+
+        interpretADT :: Kind -> SExpr -> (String, [(Kind, CVal)])
+        interpretADT adtK@(KADT _ _ cks) expr
+           | isUninterpreted adtK
+           = case expr of
+               ECon s -> (simplifyECon s, [])
+               _      -> bad ["Unexpected expression value for uninterpreted kind."]
+           | Just ks <- cstr `lookup` cks
+           = if length fs == length ks
+             then (cstr, zipWith convert (zip [1..] ks) fs)
+             else bad ["Mismatching field count: " ++ show (fs, ks)]
+           | True
+           = bad ["Cannot find constructor in the kind: " ++ show (cstr, adtK)]
+          where (cstr, fs) = case removeAS expr of
+                               ECon c             -> (c, [])
+                               EApp (ECon c : cs) -> (c, cs)
+                               _                  -> bad ["Unexpected expression value; does not start with a constructor."]
+
+                removeAS :: SExpr -> SExpr
+                removeAS (EApp [ECon "as", i, _]) = removeAS i
+                removeAS (EApp xs)                = EApp $ map removeAS xs
+                removeAS ae                       = ae
+
+                bad :: [String] -> a
+                bad extras = error $ unlines $ [ "Data.SBV.interpretADT: Cannot recover ADT value from solver output."
+                                               , "   Kind: " ++ show adtK
+                                               , "   Expr: " ++ show expr
+                                               ] ++ extras
+
+                convert :: (Int, Kind) -> SExpr -> (Kind, CVal)
+                convert (i, fk) f = case recoverKindedValue si fk f of
+                                      Just (CV kv v) -> (kv, v)
+                                      Nothing        -> bad ["Couldn't convert field " ++ show i ++ ": " ++ show (fk, f)]
+
+        interpretADT someK expr = error $ unlines [ "Data.SBV.interpretADT: Expected an ADT kind, but got something else."
+                                                  , "   Expr: " ++ show expr
+                                                  , "   Kind: " ++ show someK
+                                                  ]
+
+-- | Generalization of 'Data.SBV.Control.getValueCV'
+getValueCV :: (MonadIO m, MonadQuery m) => Maybe Int -> SV -> m CV
+getValueCV mbi s
+  | kindOf s /= KReal
+  = getValueCVHelper mbi s
+  | True
+  = do cfg <- getConfig
+       if not (supportsApproxReals (capabilities (solver cfg)))
+          then getValueCVHelper mbi s
+          else do send True "(set-option :pp.decimal false)"
+                  rep1 <- getValueCVHelper mbi s
+                  send True   "(set-option :pp.decimal true)"
+                  send True $ "(set-option :pp.decimal_precision " <> showText (printRealPrec cfg) <> ")"
+                  rep2 <- getValueCVHelper mbi s
+
+                  let bad = unexpected "getValueCV" "get-value" ("a real-valued binding for " ++ show s) Nothing (show (rep1, rep2)) Nothing
+
+                  case (rep1, rep2) of
+                    (CV KReal (CAlgReal a), CV KReal (CAlgReal b)) -> pure $ CV KReal (CAlgReal (mergeAlgReals ("Cannot merge real-values for " ++ show s) a b))
+                    _                                              -> bad
+
+-- | Retrieve value from the solver
+extractValue :: forall m. (MonadIO m, MonadQuery m) => Maybe Int -> String -> Kind -> m CV
+extractValue mbi nm k = do
+       let modelIndex = case mbi of
+                          Nothing -> ""
+                          Just i  -> " :model_index " ++ show i
+
+           cmd        = "(get-value (" <> T.pack nm <> ")" <> T.pack modelIndex <> ")"
+
+           bad = unexpected "get-value" cmd ("a value binding for kind: " ++ show k) Nothing
+
+       r <- ask cmd
+
+       si <- queryState >>= getSInfo
+
+       let recover val = case recoverKindedValue si k val of
+                           Just cv -> pure cv
+                           Nothing -> bad r Nothing
+
+       parse r bad $ \case EApp [EApp [ECon v, val]] | v == nm -> recover val
+                           _                                   -> bad r Nothing
+
+-- | Generalization of 'Data.SBV.Control.getUICVal'
+getUICVal :: forall m. (MonadIO m, MonadQuery m) => Maybe Int -> (String, (Bool, Maybe [String], SBVType)) -> m CV
+getUICVal mbi (nm, (_, _, t)) = case t of
+                                 SBVType [k] -> extractValue mbi nm k
+                                 _           -> error $ "SBV.getUICVal: Expected to be called on an uninterpreted value of a base type, received something else: " ++ show (nm, t)
+
+-- | Generalization of 'Data.SBV.Control.getUIFunCVAssoc'
+getUIFunCVAssoc :: forall m. (MonadIO m, MonadQuery m) => Maybe Int -> (String, (Bool, Maybe [String], SBVType)) -> m (Either String ([([CV], CV)], CV))
+getUIFunCVAssoc mbi (nm, (isCurried, mbArgs, typ)) = do
+  let modelIndex = case mbi of
+                     Nothing -> ""
+                     Just i  -> " :model_index " ++ show i
+
+      cmd        = "(get-value (" <> T.pack nm <> ")" <> T.pack modelIndex <> ")"
+
+      bad        = unexpected "get-value" cmd "a function value" Nothing
+
+  r <- ask cmd
+
+  si <- queryState >>= getSInfo
+
+  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 si) ats as <*> toRes v
+         | True                    = error $ "Data.SBV.getUIFunCVAssoc: Mismatching type/value arity, got: " ++ show (as, ats)
+
+      toRes :: SExpr -> Maybe CV
+      toRes = recoverKindedValue si rt
+
+      -- if we fail to parse, we'll return this answer as the string
+      fallBack = trimFunctionResponse r nm isCurried mbArgs
+
+      -- In case we end up in the pointwise scenario, boolify the result
+      -- as that's the only type we support here.
+      tryPointWise = do mbSExprs <- pointWiseExtract nm typ
+                        case mbSExprs of
+                          Nothing     -> pure $ Left fallBack
+                          Just sExprs -> pure $ maybe (Left fallBack) Right (convert sExprs)
+
+  parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> case parseSExprFunction e of
+                                                             Just (Right assocs) | Just res <- convert assocs                 -> pure (Right res)
+                                                                                 | True                                       -> tryPointWise
+
+                                                             Just (Left nm')     | nm == nm', let res = defaultKindedValue rt -> pure (Right ([], res))
+                                                                                 | True                                       -> bad r Nothing
+
+                                                             Nothing                                                          -> tryPointWise
+
+                      _                                 -> bad r Nothing
+
+-- | Generalization of 'Data.SBV.Control.checkSat'
+checkSat :: (MonadIO m, MonadQuery m) => m CheckSatResult
+checkSat = do cfg <- getConfig
+              checkSatUsing $ satCmd cfg
+
+-- | Generalization of 'Data.SBV.Control.checkSatUsing'
+checkSatUsing :: (MonadIO m, MonadQuery m) => String -> m CheckSatResult
+checkSatUsing cmd = do let bad = unexpected "checkSat" (T.pack cmd) "one of sat/unsat/unknown" Nothing
+
+                           -- Sigh.. Ignore some of the pesky warnings. We only do it as an exception here.
+                           ignoreList = ["WARNING: optimization with quantified constraints is not supported"]
+
+                       r <- askIgnoring (T.pack cmd) ignoreList
+
+                       -- query for the precision if supported
+                       let getPrecision = do cfg <- getConfig
+                                             case supportsDeltaSat (capabilities (solver cfg)) of
+                                               Nothing -> pure Nothing
+                                               Just o  -> Just <$> ask (T.pack o)
+
+                       parse r bad $ \case ECon "sat"       -> pure Sat
+                                           ECon "unsat"     -> pure Unsat
+                                           ECon "unknown"   -> pure Unk
+                                           ECon "delta-sat" -> DSat <$> getPrecision
+                                           _                -> bad r Nothing
+
+-- | What are the top level inputs? Trackers are returned as top level existentials
+getTopLevelInputs :: (MonadIO m, MonadQuery m) => m UserInputs
+getTopLevelInputs = do State{rinps}                     <- queryState
+                       Inputs{userInputs, internInputs} <- liftIO $ readIORef rinps
+
+                       pure $ userInputs <> internInputs
+
+-- | Get observables, i.e., those explicitly labeled by the user with a call to 'Data.SBV.observe'.
+getObservables :: (MonadIO m, MonadQuery m) => m [(Name, CV)]
+getObservables = do State{rObservables} <- queryState
+
+                    rObs <- liftIO $ readIORef rObservables
+
+                    -- This intentionally reverses the result; since 'rObs' stores in reversed order
+                    let walk []             !sofar = pure sofar
+                        walk ((n, f, s):os) !sofar = do cv <- getValueCV Nothing s
+                                                        if f cv
+                                                          then walk os ((n, cv) : sofar)
+                                                          else walk os            sofar
+
+                    walk (F.toList 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, (Bool, Maybe [String], SBVType))]
+getUIs = do State{rUIMap, rDefns, rIncState} <- queryState
+            -- NB. no need to worry about new-defines, because we don't allow definitions once query mode starts
+            defineSet <- Map.keysSet <$> io (readIORef rDefns)
+
+            prior <- io $ readIORef rUIMap
+            new   <- io $ readIORef rIncState >>= readIORef . rNewUIs
+            pure $ Map.toList $ Map.withoutKeys (Map.union prior new) defineSet
+
+-- | Return all satisfying models.
+getAllSatResult :: forall m. (MonadIO m, MonadQuery m, SolverContext m) => m AllSatResult
+getAllSatResult = do queryDebug ["*** Checking Satisfiability, all solutions.."]
+
+                     cfg <- getConfig
+                     unless (supportsCustomQueries (capabilities (solver cfg))) $
+                        error $ unlines [ ""
+                                        , "*** Data.SBV: Backend solver " ++ show (name (solver cfg)) ++ " does not support custom queries."
+                                        , "***"
+                                        , "*** Custom query support is needed for allSat functionality."
+                                        , "*** Please use a solver that supports this feature."
+                                        ]
+
+                     topState@State{rUsedKinds, rPartitionVars, rProgInfo} <- queryState
+
+                     progInfo <- liftIO $ readIORef rProgInfo
+                     ki       <- liftIO $ readIORef rUsedKinds
+
+                     allModelInputs    <- getTopLevelInputs
+                     allUninterpreteds <- getUIs
+                     partitionVars     <- liftIO $ readIORef rPartitionVars
+
+                      -- Functions have at least two kinds in their type and all components must be "interpreted"
+                     let allUiFuns = [u | allSatTrackUFs cfg                                              -- config says consider UIFs
+                                        , u@(nm, (_, _, SBVType as)) <- allUninterpreteds, length as > 1  -- get the function ones
+                                        , not (mustIgnoreVar cfg (T.pack nm))                              -- make sure they aren't explicitly ignored
+                                     ]
+
+                         allUiRegs = [u | u@(nm, (_, _, SBVType as)) <- allUninterpreteds, length as == 1 -- non-function ones
+                                        , not (mustIgnoreVar cfg (T.pack 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 = pure sofar
+                         collectAcceptable ((nm, (_, _, t@(SBVType ats))):rest) sofar
+                           | not (any hasUninterpretedSorts ats)
+                           = collectAcceptable rest (nm : sofar)
+                           | True
+                           = do queryDebug [ "*** SBV.allSat: Uninterpreted function: " <> T.pack nm <> " :: " <> showText t
+                                           , "*** Will *not* be used in allSat considerations since its type"
+                                           , "*** has uninterpreted sorts present."
+                                           ]
+                                collectAcceptable rest sofar
+
+                     uiFuns <- reverse <$> collectAcceptable allUiFuns []
+                     _      <- collectAcceptable allUiRegs [] -- only done to get the queryDebug output. Actual result not needed/used
+
+                     -- 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 F.for_ (supportsFlattenedModels solverCaps) (mapM_ (send True . T.pack))
+
+                     let usorts = [s | us@(KADT s _ _) <- Set.toAscList ki, isUninterpreted us]
+
+                     unless (null usorts) $ queryDebug [ "*** SBV.allSat: Uninterpreted sorts present: " <> T.pack (unwords usorts)
+                                                       , "***             SBV will use equivalence classes to generate all-satisfying instances."
+                                                       ]
+
+                     -- Drop the things that are not model vars or internal
+                     let mkSVal nm@(getSV -> sv) = (SVal (kindOf sv) (Right (cache (const (pure sv)))), nm)
+                     let extractVars :: S.Seq (SVal, NamedSymVar)
+                         extractVars = mkSVal <$> S.filter (not . mustIgnoreVar cfg . getUserName) allModelInputs
+
+                         vars :: S.Seq (SVal, NamedSymVar)
+                         vars = case partitionVars of
+                                  [] -> extractVars
+                                  pv -> mkSVal <$> S.filter (\k -> getUserName' k `elem` pv) allModelInputs
+
+                     -- We can go fast using the disjoint model trick if things are simple enough:
+                     --     - No uninterpreted functions (uninterpreted values are OK)
+                     --     - No uninterpreted sorts
+                     --     - No quantifiers
+                     --
+                     -- Why can't we support the above?
+                     --     - Uninterpreted functions: There is no (standard) way to define a function as a literal in SMTLib.
+                     --     Some solvers support lambda, but this isn't common/reliable yet.
+                     --     - Uninterpreted sort: There's no way to access the value the solver assigns to an uninterpreted sort.
+                     --     - Quantifiers: Too complicated!
+                     --
+                     -- So, if these two things are present, we go the "slow" route, by repeatedly rejecting the
+                     -- previous model and asking for a new one. If they don't exist (which is the common case anyhow)
+                     -- we use an idea due to z3 folks <http://theory.stanford.edu/%7Enikolaj/programmingz3.html#sec-blocking-evaluations>
+                     -- which splits the search space into disjoint models and can produce results much more quickly.
+                     let isSimple = null allUiFuns && null usorts && not (hasQuants progInfo)
+
+                         start = AllSatResult { allSatMaxModelCountReached  = False
+                                              , allSatSolverReturnedUnknown = False
+                                              , allSatSolverReturnedDSat    = False
+                                              , allSatResults               = []
+                                              }
+
+                     -- partition-variables are only supported if simple
+                     case partitionVars of
+                       [] -> pure ()
+                       xs -> unless isSimple $ error $ unlines [ ""
+                                                               , "Data.SBV: Unsupported complex allSat call in the presence of partition-variables"
+                                                               , ""
+                                                               , "Partition variables are only supported when there are no uninterpreted"
+                                                               , "functions or uninterpreted sorts."
+                                                               , ""
+                                                               , "Saw parition vars: " ++ unwords xs
+                                                               ]
+
+                     if isSimple
+                        then do let mkVar :: (String, (Bool, Maybe [String], SBVType)) -> IO (SVal, NamedSymVar)
+                                    mkVar (nm, (_, _, SBVType [k])) = do sv <- newExpr topState k (SBVApp (Uninterpreted (T.pack nm)) [])
+                                                                         let sval = SVal k $ Right $ cache $ \_ -> pure sv
+                                                                             nsv  = NamedSymVar sv (T.pack nm)
+                                                                         pure (sval, nsv)
+                                    mkVar nmt = error $ "Data.SBV: Impossible happened; allSat.mkVar. Unexpected: " ++ show nmt
+                                uiVars <- io $ S.fromList <$> mapM mkVar allUiRegs
+                                fastAllSat                                        allModelInputs (uiVars S.>< extractVars) (uiVars S.>< vars) cfg start
+                        else    loop       topState (allUiFuns, uiFuns) allUiRegs allModelInputs                                        vars  cfg start
+
+   where finalize cnt cfg sofar extra
+                = when (allSatPrintAlong cfg && not (null (allSatResults 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)
+                           case extra of
+                             Nothing -> pure ()
+                             Just m  -> io $ putStrLn m
+
+         fastAllSat :: S.Seq NamedSymVar -> S.Seq (SVal, NamedSymVar) -> S.Seq (SVal, NamedSymVar) -> SMTConfig -> AllSatResult -> m AllSatResult
+         fastAllSat allInputs extractVars vars cfg start = do
+                result <- io $ newIORef (0, start, False, Nothing)
+                go result vars
+                (found, sofar, _, extra) <- io $ readIORef result
+                finalize (found+1) cfg sofar extra
+                pure sofar
+
+           where haveEnough have = case allSatMaxModelCount cfg of
+                                     Just maxModels -> have >= maxModels
+                                     _              -> False
+
+                 go :: IORef (Int, AllSatResult, Bool, Maybe String) -> S.Seq (SVal, NamedSymVar) -> m ()
+                 go finalResult = walk True
+                   where shouldContinue = do (have, _, exitLoop, _) <- io $ readIORef finalResult
+                                             pure $ not (exitLoop || haveEnough have)
+
+                         walk :: Bool -> S.Seq (SVal, NamedSymVar) -> m ()
+                         walk firstRun terms
+                           | not firstRun && S.null terms
+                           = pure ()
+                           | True
+                           = do mbCont <- do (have, sofar, exitLoop, _) <- io $ readIORef finalResult
+                                             if exitLoop
+                                                then pure Nothing
+                                                else case allSatMaxModelCount cfg of
+                                                       Just maxModels
+                                                         | have >= maxModels -> do unless (allSatMaxModelCountReached sofar) $ do
+                                                                                      queryDebug ["*** Maximum model count request of " <> showText maxModels <> " reached, stopping the search."]
+                                                                                      when (allSatPrintAlong cfg) $ io $ putStrLn "Search stopped since model count request was reached."
+                                                                                      io $ modifyIORef' finalResult $ \(h, s, _, m) -> (h, s{ allSatMaxModelCountReached = True }, True, m)
+                                                                                   pure Nothing
+                                                       _                     -> pure $ Just $ have+1
+
+                                case mbCont of
+                                  Nothing  -> pure ()
+                                  Just cnt -> do
+                                    queryDebug ["Fast allSat, Looking for solution " <> showText cnt]
+
+                                    cs <- checkSat
+
+                                    case cs of
+                                      Unsat  -> pure ()
+
+                                      Unk    -> do queryDebug ["*** Solver returned unknown, terminating query."]
+                                                   io $ modifyIORef' finalResult $ \(h, s, _, _) -> (h, s{allSatSolverReturnedUnknown = True}, True, Just "[Solver returned unknown, terminating query.]")
+
+                                      DSat _ -> do queryDebug ["*** Solver returned delta-sat, terminating query."]
+                                                   io $ modifyIORef' finalResult $ \(h, s, _, _) -> (h, s{allSatSolverReturnedDSat = True}, True, Just "[Solver returned delta-sat, terminating query.]")
+
+                                      Sat    -> do assocs <- mapM (\(sval, NamedSymVar sv n) -> do !cv <- getValueCV Nothing sv
+                                                                                                   pure (sv, (n, (sval, cv)))) extractVars
+
+                                                   bindings <- let grab i@(getSV -> sv) = case lookupInput fst sv assocs of
+                                                                                            Just (_, (_, (_, cv))) -> pure (i, cv)
+                                                                                            Nothing                -> do !cv <- getValueCV Nothing sv
+                                                                                                                         pure (i, cv)
+                                                               in if validationRequested cfg
+                                                                  then Just <$> mapM grab allInputs
+                                                                  else pure Nothing
+
+                                                   obsvs <- getObservables
+
+                                                   let lassocs = F.toList assocs
+                                                       model   = SMTModel { modelObjectives = []
+                                                                          , modelBindings   = F.toList <$> bindings
+                                                                          , modelAssocs     =    (first T.unpack <$> sortOn fst obsvs)
+                                                                                              <> [(T.unpack n, cv) | (_, (n, (_, cv))) <- lassocs]
+                                                                          , modelUIFuns     = []
+                                                                          }
+                                                       currentResult = Satisfiable cfg model
+
+                                                   io $ modifyIORef' finalResult $ \(h, s, e, m) -> let h' = h+1 in h' `seq` (h', s{allSatResults = currentResult : allSatResults s}, e, m)
+
+                                                   when (allSatPrintAlong cfg) $ do
+                                                        io $ putStrLn $ "Solution #" ++ show cnt ++ ":"
+                                                        io $ putStrLn $ showModel cfg model
+
+                                                   let findVal :: (SVal, NamedSymVar) -> (SVal, CV)
+                                                       findVal (_, NamedSymVar sv nm) = case F.toList (S.filter (\(sv', _) -> sv == sv') assocs) of
+                                                                                           [(_, (_, scv))] -> scv
+                                                                                           _               -> error $ "Data.SBV: Cannot uniquely determine " ++ show nm ++ " in " ++ show assocs
+
+                                                       cstr :: Bool -> (SVal, CV) -> m ()
+                                                       cstr shouldReject (sv, cv) = constrain (SBV $ mkEq (kindOf sv) sv (SVal (kindOf sv) (Left cv)) :: SBool)
+                                                         where mkEq :: Kind -> SVal -> SVal -> SVal
+                                                               mkEq k a b
+                                                                | any isSomeKindOfFloat (expandKinds k)
+                                                                = if shouldReject
+                                                                     then svNot  (a `fpEq` b)
+                                                                     else         a `fpEq` b
+                                                                | True
+                                                                = if shouldReject
+                                                                     then a `svNotEqual` b
+                                                                     else a `svEqual`    b
+
+                                                               fpEq a b = SVal KBool $ Right $ cache r
+                                                                   where r st = do sva <- svToSV st a
+                                                                                   svb <- svToSV st b
+                                                                                   newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [sva, svb])
+
+                                                       reject, accept :: (SVal, NamedSymVar) -> m ()
+                                                       reject = cstr True  . findVal
+                                                       accept = cstr False . findVal
+
+                                                       scope :: (SVal, NamedSymVar) -> S.Seq (SVal, NamedSymVar) -> m () -> m ()
+                                                       scope cur pres c = do
+                                                                send True "(push 1)"
+                                                                reject cur
+                                                                mapM_ accept pres
+                                                                r <- c
+                                                                send True "(pop 1)"
+                                                                pure r
+
+                                                   F.for_ [0 .. length terms - 1] $ \i -> do
+                                                        sc <- shouldContinue
+                                                        when sc $ do case S.splitAt i terms of
+                                                                       (pre, rest@(cur S.:<| _)) -> scope cur pre $ walk False rest
+                                                                       _                         -> error "Data.SBV.allSat: Impossible happened, ran out of terms!"
+
+         -- All sat loop. This is slower, as it implements the reject-the-previous model and loop around logic. But
+         -- it can handle uninterpreted sorts; so we keep it here as a fall-back.
+         loop topState (allUiFuns, uiFunsToReject) allUiRegs allInputs vars cfg = go (1::Int)
+           where go :: Int -> AllSatResult -> m AllSatResult
+                 go !cnt !sofar
+                   | Just maxModels <- allSatMaxModelCount cfg, cnt > maxModels
+                   = do queryDebug ["*** Maximum model count request of " <> showText maxModels <> " reached, stopping the search."]
+                        when (allSatPrintAlong cfg) $ io $ putStrLn "Search stopped since model count request was reached."
+                        pure $! sofar { allSatMaxModelCountReached = True }
+                   | True
+                   = do queryDebug ["Looking for solution " <> showText cnt]
+
+                        cs <- checkSat
+
+                        let endMsg = finalize cnt cfg sofar
+
+                        case cs of
+                          Unsat  -> do endMsg Nothing
+                                       pure sofar
+
+                          Unk    -> do queryDebug ["*** Solver returned unknown, terminating query."]
+                                       endMsg $ Just "[Solver returned unknown, terminating query.]"
+                                       pure sofar{ allSatSolverReturnedUnknown = True }
+
+                          DSat _ -> do queryDebug ["*** Solver returned delta-sat, terminating query."]
+                                       endMsg $ Just "[Solver returned delta-sat, terminating query.]"
+                                       pure sofar{ allSatSolverReturnedDSat = True }
+
+                          Sat    -> do assocs <- mapM (\(sval, NamedSymVar sv n) -> do !cv <- getValueCV Nothing sv
+                                                                                       pure (sv, (n, (sval, cv)))) vars
+
+                                       let getUIFun ui@(nm, (isCurried, _, t)) = do cvs <- getUIFunCVAssoc Nothing ui
+                                                                                    pure (nm, (isCurried, t, cvs))
+                                       uiFunVals <- mapM getUIFun allUiFuns
+
+                                       uiRegVals <- mapM (\ui@(nm, _) -> (nm,) <$> getUICVal Nothing ui) allUiRegs
+
+                                       obsvs <- getObservables
+
+                                       bindings <- let grab i@(getSV -> sv) = case lookupInput fst sv assocs of
+                                                                                Just (_, (_, (_, cv))) -> pure (i, cv)
+                                                                                Nothing                -> do !cv <- getValueCV Nothing sv
+                                                                                                             pure (i, cv)
+                                                   in if validationRequested cfg
+                                                         then Just <$> mapM grab allInputs
+                                                         else pure Nothing
+
+                                       let model = SMTModel { modelObjectives = []
+                                                            , modelBindings   = F.toList <$> bindings
+                                                            , modelAssocs     =    uiRegVals
+                                                                                <> (first T.unpack <$> sortOn fst obsvs)
+                                                                                <> [(T.unpack n, cv) | (_, (n, (_, cv))) <- F.toList assocs]
+                                                            , modelUIFuns     = uiFunVals
+                                                            }
+                                           m = Satisfiable cfg model
+
+                                           (interpreteds, uninterpreteds) = S.partition (not . isUninterpreted . kindOf . fst) (snd . snd <$> assocs)
+
+                                           interpretedRegUis = filter (not . isUninterpreted . kindOf . snd) uiRegVals
+
+                                           interpretedRegUiSVs = [(cvt n (kindOf cv), cv) | (n, cv) <- interpretedRegUis]
+                                             where cvt :: String -> Kind -> SVal
+                                                   cvt nm k = SVal k $ Right $ cache r
+                                                     where r st = newExpr st k (SBVApp (Uninterpreted (T.pack nm)) [])
+
+                                           -- 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]
+                                           interpretedEqs = [mkNotEq (kindOf sv) sv (SVal (kindOf sv) (Left cv)) | (sv, cv) <- interpretedRegUiSVs <> F.toList interpreteds]
+                                              where mkNotEq k a b
+                                                     | isDouble k || isFloat k || isFP k
+                                                     = svNot (a `fpEq` b)
+                                                     | True
+                                                     = a `svNotEqual` b
+
+                                                    fpEq a b = SVal KBool $ Right $ cache r
+                                                        where r st = do sva <- svToSV st a
+                                                                        svb <- svToSV st b
+                                                                        newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [sva, svb])
+
+                                           -- 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
+                                                            . map (map fst)                -- throw away values, we only need svals
+                                                            . groupBy ((==) `on` snd)      -- make sure they belong to the same sort and have the same value
+                                                            . sortOn snd                   -- sort them according to their CV (i.e., sort/value)
+                                                            $ F.toList uninterpreteds
+                                             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 [T.Text]
+                                           uninterpretedFuns   :: [T.Text]
+                                           (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 if we have a good interpretation for it
+                                                     mkNotEq (nm, (_, typ, Left def)) =
+                                                        error $ unlines [
+                                                            ""
+                                                          , "*** allSat: Unsupported: Building a rejecting instance for:"
+                                                          , "***"
+                                                          , "***     " ++ nm ++ " :: " ++ show typ
+                                                          , "***     " ++ def
+                                                          , "***"
+                                                          , "*** At this time, SBV cannot compute allSat when the model has a non-table definition."
+                                                          , "***"
+                                                          , "*** You can ignore specific functions via the 'isNonModelVar' filter:"
+                                                          , "***"
+                                                          , "***    allSatWith z3{isNonModelVar = (`elem` [" ++ show nm ++ "])} ..."
+                                                          , "***"
+                                                          , "*** Or you can ignore all uninterpreted functions for all-sat purposes using the 'allSatTrackUFs' parameter:"
+                                                          , "***"
+                                                          , "***    allSatWith z3{allSatTrackUFs = False} ..."
+                                                          , "***"
+                                                          , "*** You can see the response from the solver by running with the '{verbose = True}' option."
+                                                          , "***"
+                                                          , "*** NB. If this is a use case you'd like SBV to support, please get in touch!"
+                                                          ]
+                                                     mkNotEq (nm, (_, SBVType ts, Right vs)) = (reject, def ++ dif)
+                                                       where nm' = T.pack nm <> "_model" <> showText cnt
+
+                                                             reject = nm' <> "_reject"
+
+                                                             -- convert a constant
+                                                             scv = cvToSMTLib
+
+                                                             (ats, rt) = (init ts, last ts)
+
+                                                             args = T.unwords ["(x!" <> showText i <> " " <> smtType t <> ")" | (t, i) <- zip ats [(0::Int)..]]
+                                                             res  = smtType rt
+
+                                                             params = ["x!" <> showText i | (_, i) <- zip ats [(0::Int)..]]
+
+                                                             uparams = T.unwords params
+
+                                                             chain (vals, fallThru) = walk vals
+                                                               where walk []               = ["   " <> scv fallThru <> T.replicate (length vals) ")"]
+                                                                     walk ((as, r) : rest) = ("   (ite " <> cond as <> " " <> scv r) :  walk rest
+
+                                                                     cond as = "(and " <> T.unwords (zipWith eq params as) <> ")"
+                                                                     eq p a  = "(= " <> p <> " " <> scv a <> ")"
+
+                                                             def =    ("(define-fun " <> nm' <> " (" <> args <> ") " <> res)
+                                                                   :  chain vs
+                                                                   ++ [")"]
+
+                                                             pad = T.replicate (1 + T.length nm' - length nm) " "
+
+                                                             dif = [ "(define-fun " <>  reject <> " () Bool"
+                                                                   , "   (exists (" <> args <> ")"
+                                                                   , "           (distinct (" <> T.pack 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 = sofar { allSatResults = m : allSatResults sofar }
+
+                                           -- 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
+
+                                       -- 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 []     = pure ()
+                                                      defineRejector [x]    = send True $ "(" <> T.pack header <> x <> ")"
+                                                      defineRejector (x:xs) = mapM_ (send True) $ mergeSExpr
+                                                                                                                  $  T.pack ("(" ++ header)
+                                                                                                                  :  ("        (or " <> x)
+                                                                                                                  :  ["            " <> e | e <- xs]
+                                                                                                                  ++ ["        ))"]
+                                                  rejectFuncs <- case uninterpretedReject of
+                                                                   Nothing -> pure Nothing
+                                                                   Just fs -> do mapM_ (send True) $ mergeSExpr uninterpretedFuns
+                                                                                 defineRejector fs
+                                                                                 pure $ Just uiFunRejector
+
+                                                  -- send the disallow clause and the uninterpreted rejector:
+                                                  case (disallow, rejectFuncs) of
+                                                     (Nothing, Nothing) -> pure resultsSoFar
+                                                     (Just d,  Nothing) -> do constrain d
+                                                                              go (cnt+1) resultsSoFar
+                                                     (Nothing, Just f)  -> do send True $ "(assert " <> T.pack 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 " <> T.pack f <> " " <> showText 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
+        let cmd = "(get-unsat-assumptions)" :: T.Text
+
+            bad = unexpected "getUnsatAssumptions" cmd "a list of unsatisfiable assumptions"
+                           $ Just [ "Make sure you use:"
+                                  , ""
+                                  , "       setOption $ ProduceUnsatAssumptions True"
+                                  , ""
+                                  , "to make sure the solver is ready for producing unsat assumptions,"
+                                  , "and that there is a model by first issuing a 'checkSat' call."
+                                  ]
+
+            fromECon (ECon s) = Just s
+            fromECon _        = Nothing
+
+        r <- ask cmd
+
+        -- If unsat-cores are enabled, z3 might end-up printing an assumption that wasn't
+        -- in the original list of assumptions for `check-sat-assuming`. So, we walk over
+        -- and ignore those that weren't in the original list, and put a warning for those
+        -- we couldn't find.
+        let walk []     sofar = pure $ reverse sofar
+            walk (a:as) sofar = case a `lookup` proxyMap of
+                                  Just v  -> walk as (v:sofar)
+                                  Nothing -> do queryDebug [ "*** In call to 'getUnsatAssumptions'"
+                                                           , "***"
+                                                           , "***    Unexpected assumption named: " <> showText a
+                                                           , "***    Was expecting one of       : " <> showText originals
+                                                           , "***"
+                                                           , "*** This can happen if unsat-cores are also enabled. Ignoring."
+                                                           ]
+                                                walk as sofar
+
+        parse r bad $ \case
+           EApp es | Just xs <- mapM fromECon es -> walk xs []
+           _                                     -> bad r Nothing
+
+-- | Timeout a query action, typically a command call to the underlying SMT solver.
+-- The duration is in microseconds (@1\/10^6@ seconds). If the duration
+-- is negative, then no timeout is imposed. When specifying long timeouts, be careful not to exceed
+-- @maxBound :: Int@. (On a 64 bit machine, this bound is practically infinite. But on a 32 bit
+-- machine, it corresponds to about 36 minutes!)
+--
+-- Semantics: The call @timeout n q@ causes the timeout value to be applied to all interactive calls that take place
+-- as we execute the query @q@. That is, each call that happens during the execution of @q@ gets a separate
+-- time-out value, as opposed to one timeout value that limits the whole query. This is typically the intended behavior.
+-- It is advisable to apply this combinator to calls that involve a single call to the solver for
+-- finer control, as opposed to an entire set of interactions. However, different use cases might call for different scenarios.
+--
+-- If the solver responds within the time-out specified, then we continue as usual. However, if the backend solver times-out
+-- using this mechanism, there is no telling what the state of the solver will be. Thus, we raise an error in this case.
+timeout :: (MonadIO m, MonadQuery m) => Int -> m a -> m a
+timeout n q = do modifyQueryState (\qs -> qs {queryTimeOutValue = Just n})
+                 r <- q
+                 modifyQueryState (\qs -> qs {queryTimeOutValue = Nothing})
+                 pure r
+
+-- | Bail out if a parse goes bad
+parse :: String -> (String -> Maybe [String] -> a) -> (SExpr -> a) -> a
+parse r fCont sCont = case parseSExpr r of
+                        Left  e   -> fCont r (Just [e])
+                        Right res -> sCont res
+
+-- | Generalization of 'Data.SBV.Control.unexpected'
+unexpected :: (MonadIO m, MonadQuery m) => String -> T.Text -> String -> Maybe [String] -> String -> Maybe [String] -> m a
+unexpected ctx sent expected mbHint received mbReason = do
+        -- empty the response channel first
+        extras <- retrieveResponse "terminating upon unexpected response" (Just 5000000)
+
+        cfg <- getConfig
+
+        let exc = SBVException { sbvExceptionDescription = "Unexpected response from the solver, context: " ++ ctx
+                               , sbvExceptionSent        = Just (T.unpack sent)
+                               , sbvExceptionExpected    = Just expected
+                               , sbvExceptionReceived    = Just received
+                               , sbvExceptionStdOut      = Just $ unlines extras
+                               , sbvExceptionStdErr      = Nothing
+                               , sbvExceptionExitCode    = Nothing
+                               , sbvExceptionConfig      = cfg
+                               , sbvExceptionReason      = mbReason
+                               , sbvExceptionHint        = mbHint
+                               }
+
+        io $ C.throwIO exc
+
+-- | Convert a query result to an SMT Problem
+runProofOn :: SBVRunMode -> QueryContext -> [String] -> Result -> SMTProblem
+runProofOn rm context comments res@(Result progInfo ki _qcInfo _observables _codeSegs is consts tbls uis defns 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
+
+         o | isSafe = trueSV
+           | True   = case outputs of
+                        []  | isSetup -> trueSV
+                        [so]          -> case so of
+                                           SV KBool _ -> so
+                                           _          -> error $ unlines [ "Impossible happened, non-boolean output: " ++ show so
+                                                                         , "Detected while generating the trace:\n" ++ show res
+                                                                         ]
+                        os  -> error $ unlines [ "User error: Multiple output values detected: " ++ show os
+                                               , "Detected while generating the trace:\n" ++ show res
+                                               , "*** Check calls to \"output\", they are typically not needed!"
+                                               ]
+
+     in SMTProblem { smtLibPgm = toSMTLib config context progInfo ki isSat comments is consts tbls uis defns pgm cstrs o }
+
+-- | Generalization of 'Data.SBV.Control.executeQuery'
+executeQuery :: forall m a. ExtractIO m => QueryContext -> QueryT m a -> SymbolicT m a
+executeQuery queryContext originalQuery = do
+     st <- symbolicEnv
+     rm <- liftIO $ readIORef (runMode st)
+
+     -- Make sure the phases match:
+     () <- liftIO $ case (queryContext, rm) of
+                      (QueryInternal, _)                                -> pure ()  -- no worries, internal
+                      (QueryExternal, SMTMode QueryExternal ISetup _ _) -> pure () -- legitimate runSMT call
+                      _                                                 -> invalidQuery rm
+
+     case rm of
+        -- Transitioning from setup
+        SMTMode qc stage isSAT cfg | not (isRunIStage stage) -> do
+
+                  let slvr    = solver cfg
+                      backend = engine slvr
+
+                  -- make sure if we have dsat precision, then solver supports it
+                  let dsatOK =  isNothing (dsatPrecision cfg)
+                             || isJust    (supportsDeltaSat (capabilities slvr))
+
+                  unless dsatOK $ error $ unlines
+                                     [ ""
+                                     , "*** Data.SBV: Delta-sat precision is specified."
+                                     , "***           But the chosen solver (" ++ show (name slvr) ++ ") does not support"
+                                     , "***           delta-satisfiability."
+                                     ]
+
+                  res     <- liftIO $ extractSymbolicSimulationState st
+                  setOpts <- liftIO $ reverse <$> readIORef (rSMTOptions st)
+
+                  -- Run any registered measure checks (termination/productivity verification)
+                  liftIO $ do skip <- readIORef (rSkipMeasureChecks st)
+                              unless skip $ do
+                                checks <- readIORef (rMeasureChecks st)
+                                unless (null checks) $ do
+                                  let nms = map (\(n, _, _) -> n) checks
+                                  debug cfg ["[MEASURE] Verifying termination measures for: " <> T.pack (intercalate ", " nms)]
+                                  mapM_ (\(nm, isProductive, check) -> do
+                                            debug cfg ["[MEASURE] Checking: " <> T.pack nm]
+                                            check cfg
+                                            let tag = if isProductive then "productive" else "terminating"
+                                            debug cfg ["[MEASURE] Passed (" <> tag <> "): " <> T.pack nm]
+                                        ) checks
+
+                  let SMTProblem{smtLibPgm} = runProofOn rm queryContext [] res
+                      cfg' = cfg { solverSetOptions = solverSetOptions cfg ++ setOpts }
+                      pgm  = smtLibPgm cfg'
+
+                  liftIO $ writeIORef (runMode st) $ SMTMode qc IRun isSAT cfg
+
+                  let terminateSolver maybeForwardedException = do
+                         qs <- readIORef $ rQueryState st
+                         case qs of
+                           Nothing                         -> pure ()
+                           Just QueryState{queryTerminate} -> queryTerminate maybeForwardedException
+
+                  -- If this is an external query and there are objectives, let's add those to the list before we run
+                  -- Here we only allow Lexicographic; we might want to make that configurable later.
+                  let userQuery = case queryContext of
+                                    QueryInternal -> originalQuery
+                                    QueryExternal -> do mbDirs <- startOptimizer cfg Lexicographic
+                                                        case mbDirs of
+                                                          Nothing        -> pure ()
+                                                          Just (_, cmds) -> mapM_ (send True . T.pack) cmds
+                                                        originalQuery
+
+                  lift $ join $ liftIO $ C.mask $ \restore -> do
+                    r <- restore (extractIO $ join $ liftIO $ backend cfg' st (smtLibPgmText pgm) $ extractIO . runReaderT (runQueryT userQuery))
+                          `C.catch` \e -> terminateSolver (Just e) >> C.throwIO (e :: C.SomeException)
+                    terminateSolver Nothing
+                    pure r
+
+        -- 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
+        -- expressions like this:
+        --
+        -- In the following t0's output doesn't get recorded, as the output call is too late when we get
+        -- here. (The output field isn't "incremental.") So, t0/t1 behave differently!
+        --
+        --   t0 = satWith z3{verbose=True, transcript=Just "t.smt2"} $ query (return (false::SBool))
+        --   t1 = satWith z3{verbose=True, transcript=Just "t.smt2"} $ ((return (false::SBool)) :: Predicate)
+        --
+        -- Also, not at all clear what it means to go in an out of query mode:
+        --
+        -- r = runSMTWith z3{verbose=True} $ do
+        --         a' <- sInteger "a"
+        --
+        --        (a, av) <- query $ do _ <- checkSat
+        --                              av <- getValue a'
+        --                              return (a', av)
+        --
+        --        liftIO $ putStrLn $ "Got: " ++ show av
+        --        -- constrain $ a .> literal av + 1      -- Can't do this since we're "out" of query. Sigh.
+        --
+        --        bv <- query $ do constrain $ a .> literal av + 1
+        --                         _ <- checkSat
+        --                         getValue a
+        --
+        --        return $ a' .== a' + 1
+        --
+        -- This would be one possible implementation, alas it has the problems above:
+        --
+        --    SMTMode IRun _ _ -> liftIO $ evalStateT userQuery st
+        --
+        -- 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."
+                                              ]
+
+        -- Otherwise choke!
+        _ -> invalidQuery rm
+
+  where invalidQuery rm = error $ unlines [ ""
+                                          , "*** Data.SBV: Invalid query call."
+                                          , "***"
+                                          , "***   Current mode: " ++ show rm
+                                          , "***"
+                                          , "*** Query calls are only valid within runSMT/runSMTWith calls,"
+                                          , "*** and each call to runSMT should have only one query call inside."
+                                          ]
+
+-- | Preparing for optimization. If we have objectives, returns the directives for the solver. If not, it returns nothing.
+startOptimizer :: (MonadIO m, MonadQuery m) => SMTConfig -> OptimizeStyle -> m (Maybe ([Objective (SV, SV)], [String]))
+startOptimizer config style = do
+  objectives <- getObjectives
+
+  if null objectives
+     then pure Nothing
+     else do unless (supportsOptimization (capabilities (solver config))) $
+                    error $ unlines [ ""
+                                    , "*** Data.SBV: The backend solver " ++ show (name (solver config)) ++ "does not support optimization goals."
+                                    , "*** Please use a solver that has support, such as z3"
+                                    ]
+
+             when (validateModel config && not (optimizeValidateConstraints config)) $
+                    error $ unlines [ ""
+                                    , "*** Data.SBV: Model validation is not supported in optimization calls."
+                                    , "***"
+                                    , "*** Instead, use `cfg{optimizeValidateConstraints = True}`"
+                                    , "***"
+                                    , "*** which checks that the results satisfy the constraints but does"
+                                    , "*** NOT ensure that they are optimal."
+                                    ]
+
+
+             let optimizerDirectives = concatMap minmax objectives ++ priority style
+                   where mkEq (x, y) = "(assert (= " ++ show x ++ " " ++ show y ++ "))"
+
+                         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
+                                                               , "All soft goals must have > 0 penalties associated."
+                                                               ]
+                                    | True   = " :weight " ++ shw ++ maybe "" group mbGrp
+                                    where shw = show (fromRational w :: Double)
+
+                                 group g = " :id " ++ g
+
+                         priority Lexicographic = [] -- default, no option needed
+                         priority Independent   = ["(set-option :opt.priority box)"]
+                         priority (Pareto _)    = ["(set-option :opt.priority pareto)"]
+
+             pure $ Just (objectives, optimizerDirectives)
+
+-- | 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)]
+getObjectiveValues = do let cmd = "(get-objectives)" :: T.Text
+
+                            bad = unexpected "getObjectiveValues" cmd "a list of objective values" Nothing
+
+                        r <- ask cmd
+
+                        si <- queryState >>= getSInfo
+
+                        inputs <- F.toList <$> getTopLevelInputs
+
+                        parse r bad $ \case EApp (ECon "objectives" : es) -> catMaybes <$> mapM (getObjValue si (bad r) inputs) es
+                                            _                             -> bad r Nothing
+
+  where -- | Parse an objective value out.
+        getObjValue :: SInfo -> (forall a. Maybe [String] -> m a) -> [NamedSymVar] -> SExpr -> m (Maybe (String, GeneralizedCV))
+        getObjValue si bailOut inputs expr =
+                case expr of
+                  EApp [_]          -> pure 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 = case listToMaybe [p | p@(NamedSymVar sv _) <- inputs, show sv == nm] of
+                                Nothing                          -> pure Nothing -- Happens when the soft assertion has a group-id that's not one of the input names
+                                Just (NamedSymVar sv actualName) -> grab sv v >>= \val -> pure $ Just (T.unpack actualName, val)
+
+                dontUnderstand s = bailOut $ Just [ "Unable to understand solver output."
+                                                  , "While trying to process: " ++ s
+                                                  ]
+
+                grab :: SV -> SExpr -> m GeneralizedCV
+                grab s topExpr
+                  | Just v <- recoverKindedValue si k topExpr = pure $ RegularCV v
+                  | True                                      = ExtendedCV <$> cvt (simplify topExpr)
+                  where k = kindOf s
+
+                        -- Convert to an extended expression. Hopefully complete!
+                        cvt :: SExpr -> m ExtCV
+                        cvt (ECon "oo")                    = pure $ Infinite  k
+                        cvt (ECon "epsilon")               = pure $ Epsilon   k
+                        cvt (EApp [ECon "interval", x, y]) =          Interval  <$> cvt x <*> cvt y
+                        cvt (ENum    (i, _, _))            = pure $ BoundedCV $ mkConstCV k i
+                        cvt (EReal   r)                    = pure $ BoundedCV $ CV k $ CAlgReal r
+                        cvt (EFloat  f)                    = pure $ BoundedCV $ CV k $ CFloat   f
+                        cvt (EDouble d)                    = pure $ BoundedCV $ CV k $ CDouble  d
+                        cvt (EApp [ECon "+", x, y])        =          AddExtCV <$> cvt x <*> cvt y
+                        cvt (EApp [ECon "*", x, y])        =          MulExtCV <$> cvt x <*> cvt y
+                        -- Nothing else should show up, hopefully!
+                        cvt e = dontUnderstand (show e)
+
+                        -- drop the pesky to_real's that Z3 produces.. Cool but useless.
+                        simplify :: SExpr -> SExpr
+                        simplify (EApp [ECon "to_real", n]) = n
+                        simplify (EApp xs)                  = EApp (map simplify xs)
+                        simplify e                          = e
+
+-- | Generalization of 'Data.SBV.Control.getModel'
+getModel :: (MonadIO m, MonadQuery m) => m SMTModel
+getModel = getModelAtIndex Nothing
+
+-- | 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
+    rm <- io $ readIORef runMode
+    case rm of
+      m@CodeGen     -> error $ "SBV.getModel: Model is not available in mode: " ++ show m
+      m@LambdaGen{} -> 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{}     -> do
+          cfg <- getConfig
+          uis <- getUIs
+
+          allModelInputs <- getTopLevelInputs
+          obsvs          <- getObservables
+
+          inputAssocs <- let grab (NamedSymVar sv nm) = let wrap !c = (sv, (nm, c)) in wrap <$> getValueCV mbi sv
+                         in mapM grab allModelInputs
+
+          let name     = fst . snd
+              removeSV = snd
+              prepare  = S.unstableSort . S.filter (not . mustIgnoreVar cfg . name)
+              assocs   = (removeSV <$> prepare inputAssocs) <> S.fromList (sortOn fst obsvs)
+
+          -- collect UIs, and UI functions if requested
+          let uiFuns = [ui | ui@(nm, (_, _, SBVType as)) <- uis, length as >  1, allSatTrackUFs cfg, not (mustIgnoreVar cfg (T.pack nm))] -- functions have at least two things in their type!
+              uiRegs = [ui | ui@(nm, (_, _, SBVType as)) <- uis, length as == 1,                     not (mustIgnoreVar cfg (T.pack nm))]
+
+          -- 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 F.for_ (supportsFlattenedModels solverCaps) (mapM_ (send True . T.pack))
+
+          bindings <- let get i@(getSV -> sv) = case lookupInput fst sv inputAssocs of
+                                                  Just (_, (_, cv)) -> pure (i, cv)
+                                                  Nothing           -> do cv <- getValueCV mbi sv
+                                                                          pure (i, cv)
+
+                      in if validationRequested cfg
+                         then Just <$> mapM get allModelInputs
+                         else pure Nothing
+
+          uiFunVals <- mapM (\ui@(nm, (c, _, t)) -> (\a -> (nm, (c, t, a))) <$> getUIFunCVAssoc mbi ui) uiFuns
+
+          uiVals    <- mapM (\ui@(nm, (_, _, _)) -> (nm,) <$> getUICVal mbi ui) uiRegs
+
+          pure $ unBarModel $ SMTModel { modelObjectives = []
+                                       , modelBindings   = F.toList <$> bindings
+                                       , modelAssocs     = uiVals ++ F.toList (first T.unpack <$> assocs)
+                                       , modelUIFuns     = uiFunVals
+                                       }
+
+-- | Remove the bars from model names; these are (mostly!) automatically inserted
+unBarModel :: SMTModel -> SMTModel
+unBarModel SMTModel {modelObjectives, modelBindings, modelAssocs, modelUIFuns}
+   = SMTModel { modelObjectives = ubf       <$> modelObjectives
+              , modelBindings   = (ubn <$>) <$> modelBindings
+              , modelAssocs     = ubf       <$> modelAssocs
+              , modelUIFuns     = ubf       <$> modelUIFuns
+              }
+   where ubf (n, a) = (unBar n, a)
+         ubn (NamedSymVar sv nm, a) = (NamedSymVar sv (unBarT nm), a)
+
+         unBarT t = case T.uncons t of
+                      Just ('|', rest) | not (T.null rest) && T.last rest == '|' -> T.init rest
+                      _                                                          -> t
+
+{- HLint ignore module          "Reduce duplication" -}
+{- HLint ignore getAllSatResult "Use forM_"          -}
+{- HLint ignore getModelAtIndex "Use forM_"          -}
diff --git a/Data/SBV/Core/AlgReals.hs b/Data/SBV/Core/AlgReals.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/AlgReals.hs
@@ -0,0 +1,352 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.AlgReals
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Algebraic reals in Haskell.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns       #-}
+{-# LANGUAGE DeriveAnyClass     #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE FlexibleInstances  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.AlgReals (
+             AlgReal(..)
+           , AlgRealPoly(..)
+           , RationalCV(..)
+           , RealPoint(..), realPoint
+           , mkPolyReal
+           , algRealToSMTLib2
+           , algRealToHaskell
+           , algRealToRational
+           , mergeAlgReals
+           , isExactRational
+           , algRealStructuralEqual
+           , algRealStructuralCompare
+           )
+   where
+
+import Control.DeepSeq (NFData)
+import Data.Char       (isDigit)
+
+import Data.List       (sortBy, isPrefixOf, partition)
+import Data.Function   (on)
+import System.Random
+import Test.QuickCheck (Arbitrary(..))
+
+import Numeric (readSigned, readFloat)
+
+import Text.Read(readMaybe)
+
+import qualified Data.Generics as G
+import GHC.Generics
+import GHC.Real
+
+-- | Is the endpoint included in the interval?
+data RealPoint a = OpenPoint   a -- ^ open: i.e., doesn't include the point
+                 | ClosedPoint a -- ^ closed: i.e., includes the point
+                 deriving (Show, Eq, Ord, G.Data, NFData, Generic)
+
+-- | Extract the point associated with the open-closed point
+realPoint :: RealPoint a -> a
+realPoint (OpenPoint   a) = a
+realPoint (ClosedPoint a) = a
+
+-- | Algebraic reals. Note that the representation is left abstract. We represent
+-- rational results explicitly, while the roots-of-polynomials are represented
+-- implicitly by their defining equation
+data AlgReal = AlgRational Bool Rational                             -- ^ bool says it's exact (i.e., SMT-solver did not return it with ? at the end.)
+             | AlgPolyRoot (Integer,  AlgRealPoly) (Maybe String)    -- ^ which root of this polynomial and an approximate decimal representation with given precision, if available
+             | AlgInterval (RealPoint Rational) (RealPoint Rational) -- ^ interval, with low and high bounds
+             deriving (G.Data, Generic, NFData)
+
+-- | Check whether a given argument is an exact rational
+isExactRational :: AlgReal -> Bool
+isExactRational (AlgRational True _) = True
+isExactRational _                    = False
+
+-- | A univariate polynomial, represented simply as a
+-- coefficient list. For instance, "5x^3 + 2x - 5" is
+-- represented as [(5, 3), (2, 1), (-5, 0)]
+newtype AlgRealPoly = AlgRealPoly [(Integer, Integer)]
+                   deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Construct a poly-root real with a given approximate value (either as a decimal, or polynomial-root)
+mkPolyReal :: Either (Bool, String) (Integer, [(Integer, Integer)]) -> AlgReal
+mkPolyReal (Left (exact, str))
+ = case (str, break (== '.') str) of
+      ("", _)                                -> AlgRational exact 0
+      (_, (x, '.':y)) | all isDigit (x ++ y) -> AlgRational exact (read (x++y) % (10 ^ length y))
+      (_, (x, ""))    | all isDigit x        -> AlgRational exact (read x % 1)
+      _                                      ->
+        -- CVC5 prints in division-rational form:
+        case readMaybe (filter (/= ',') (map (\c -> if c == '/' then '%' else c) str)) :: Maybe Rational of
+          Just r  -> AlgRational exact r
+          Nothing -> error $ unlines [ "*** Data.SBV.mkPolyReal: Unable to read a number from:"
+                                     , "***"
+                                     , "*** " ++ str
+                                     , "***"
+                                     , "*** Please report this as a bug."
+                                     ]
+mkPolyReal (Right (k, coeffs))
+ = AlgPolyRoot (k, AlgRealPoly (normalize coeffs)) Nothing
+ where normalize :: [(Integer, Integer)] -> [(Integer, Integer)]
+       normalize = merge . sortBy (flip compare `on` snd)
+       merge []                     = []
+       merge [x]                    = [x]
+       merge ((a, b):r@((c, d):xs))
+         | b == d                   = let !s = a+c in merge ((s, b):xs)
+         | True                     = (a, b) : merge r
+
+instance Show AlgRealPoly where
+  show (AlgRealPoly xs) = chkEmpty (join (concat [term p | p@(_, x) <- xs, x /= 0])) ++ " = " ++ show c
+     where c  = case [k | (k, 0) <- xs] of
+                  h:_ -> -h
+                  _   -> 0
+
+           term ( 0, _) = []
+           term ( 1, 1) = [ "x"]
+           term ( 1, p) = [ "x^" ++ show p]
+           term (-1, 1) = ["-x"]
+           term (-1, p) = ["-x^" ++ show p]
+           term (k,  1) = [show k ++ "x"]
+           term (k,  p) = [show k ++ "x^" ++ show p]
+           join []      = ""
+           join (k:ks) = k ++ s ++ join ks
+             where s = case ks of
+                        []    -> ""
+                        (y:_) | "-" `isPrefixOf` y -> ""
+                              | "+" `isPrefixOf` y -> ""
+                              | True               -> "+"
+           chkEmpty s = if null s then "0" else s
+
+instance Show AlgReal where
+  show (AlgRational exact a)         = showRat exact a
+  show (AlgPolyRoot (i, p) mbApprox) = "root(" ++ show i ++ ", " ++ show p ++ ")" ++ maybe "" app mbApprox
+     where app v | not (null v) && last v == '?' = " = " ++ init v ++ "..."
+                 | True                          = " = " ++ v
+  show (AlgInterval a b)         = case (a, b) of
+                                     (OpenPoint   l, OpenPoint   h) -> "(" ++ show l ++ ", " ++ show h ++ ")"
+                                     (OpenPoint   l, ClosedPoint h) -> "(" ++ show l ++ ", " ++ show h ++ "]"
+                                     (ClosedPoint l, OpenPoint   h) -> "[" ++ show l ++ ", " ++ show h ++ ")"
+                                     (ClosedPoint l, ClosedPoint h) -> "[" ++ show l ++ ", " ++ show h ++ "]"
+
+-- lift unary op through an exact rational, otherwise bail
+lift1 :: String -> (Rational -> Rational) -> AlgReal -> AlgReal
+lift1 _  o (AlgRational e a) = AlgRational e (o a)
+lift1 nm _ a                 = error $ "AlgReal." ++ nm ++ ": unsupported argument: " ++ show a
+
+-- lift binary op through exact rationals, otherwise bail
+lift2 :: String -> (Rational -> Rational -> Rational) -> AlgReal -> AlgReal -> AlgReal
+lift2 _  o (AlgRational True a) (AlgRational True b) = AlgRational True (a `o` b)
+lift2 nm _ a                    b                    = error $ "AlgReal." ++ nm ++ ": unsupported arguments: " ++ show (a, b)
+
+-- The idea in the instances below is that we will fully support operations
+-- on "AlgRational" AlgReals, but leave everything else undefined. When we are
+-- on the Haskell side, the AlgReal's are *not* reachable. They only represent
+-- return values from SMT solvers, which we should *not* need to manipulate.
+instance Eq AlgReal where
+  AlgRational True a == AlgRational True b = a == b
+  a                  == b                  = error $ "AlgReal.==: unsupported arguments: " ++ show (a, b)
+
+instance Ord AlgReal where
+  AlgRational True a `compare` AlgRational True b = a `compare` b
+  a                  `compare` b                  = error $ "AlgReal.compare: unsupported arguments: " ++ show (a, b)
+
+-- | Structural equality for AlgReal; used when constants are Map keys
+algRealStructuralEqual   :: AlgReal -> AlgReal -> Bool
+AlgRational a b `algRealStructuralEqual` AlgRational c d = (a, b) == (c, d)
+AlgPolyRoot a b `algRealStructuralEqual` AlgPolyRoot c d = (a, b) == (c, d)
+_               `algRealStructuralEqual` _               = False
+
+-- | Structural comparisons for AlgReal; used when constants are Map keys
+algRealStructuralCompare :: AlgReal -> AlgReal -> Ordering
+AlgRational a b `algRealStructuralCompare` AlgRational c d = (a, b) `compare` (c, d)
+AlgRational _ _ `algRealStructuralCompare` AlgPolyRoot _ _ = LT
+AlgRational _ _ `algRealStructuralCompare` AlgInterval _ _ = LT
+AlgPolyRoot _ _ `algRealStructuralCompare` AlgRational _ _ = GT
+AlgPolyRoot a b `algRealStructuralCompare` AlgPolyRoot c d = (a, b) `compare` (c, d)
+AlgPolyRoot _ _ `algRealStructuralCompare` AlgInterval _ _ = LT
+AlgInterval _ _ `algRealStructuralCompare` AlgRational _ _ = GT
+AlgInterval _ _ `algRealStructuralCompare` AlgPolyRoot _ _ = GT
+AlgInterval a b `algRealStructuralCompare` AlgInterval c d = (a, b) `compare` (c, d)
+
+instance Num AlgReal where
+  (+)         = lift2 "+"      (+)
+  (*)         = lift2 "*"      (*)
+  (-)         = lift2 "-"      (-)
+  negate      = lift1 "negate" negate
+  abs         = lift1 "abs"    abs
+  signum      = lift1 "signum" signum
+  fromInteger = AlgRational True . fromInteger
+
+-- |  NB: Following the other types we have, we require `a/0` to be `0` for all a.
+instance Fractional AlgReal where
+  (AlgRational True _) / (AlgRational True b) | b == 0 = 0
+  a                    / b                             = lift2 "/" (/) a b
+  fromRational = AlgRational True
+
+instance Real AlgReal where
+  toRational (AlgRational True v) = v
+  toRational x                    = error $ "AlgReal.toRational: Argument cannot be represented as a rational value: " ++ algRealToHaskell x
+
+-- | Random instance for rational needs to be careful to split the generator twice for numerator and denominator
+instance Random Rational where
+  random g = (a % b', g'')
+     where (a, g')  = random g
+           (b, g'') = random g'
+           b'       = if 0 < b then b else 1 - b -- ensures 0 < b
+
+  randomR (l, h) g = (r * d + l, g'')
+     where (b, g')  = random g
+           b'       = if 0 < b then b else 1 - b -- ensures 0 < b
+           (a, g'') = randomR (0, b') g'
+
+           r = a % b'
+           d = h - l
+
+-- | Random generates a rational, so perhaps not as random as one wants
+instance Random AlgReal where
+  random g = let (a, g') = random g in (AlgRational True a, g')
+  randomR (AlgRational True l, AlgRational True h) g = let (a, g') = randomR (l, h) g in (AlgRational True a, g')
+  randomR lh                                       _ = error $ "AlgReal.randomR: unsupported bounds: " ++ show lh
+
+instance Enum AlgReal where
+  succ x =  x + 1
+  pred x =  x - 1
+
+  toEnum n =  AlgRational True (fromIntegral n)
+
+  fromEnum (AlgRational True  r) = fromEnum r
+  fromEnum (AlgRational False r) = error $ "AlgReal.Enum: unsupported inexact rational: " ++ show r
+  fromEnum r@AlgPolyRoot{}       = error $ "AlgReal.Enum: unsupported inexact rational: " ++ show r
+  fromEnum r@AlgInterval{}       = error $ "AlgReal.Enum: unsupported inexact rational: " ++ show r
+
+  enumFrom       = numericEnumFrom
+  enumFromTo     = numericEnumFromTo
+  enumFromThen   = numericEnumFromThen
+  enumFromThenTo = numericEnumFromThenTo
+
+-- | Render an 'AlgReal' as an SMTLib2 value. Only supports rationals for the time being.
+algRealToSMTLib2 :: AlgReal -> String
+algRealToSMTLib2 (AlgRational True r)
+   | m == 0 = "0.0"
+   | m < 0  = "(- (/ "  ++ show (abs m) ++ ".0 " ++ show n ++ ".0))"
+   | True   =    "(/ "  ++ show m       ++ ".0 " ++ show n ++ ".0)"
+  where (m, n) = (numerator r, denominator r)
+algRealToSMTLib2 r@(AlgRational False _)
+   = error $ "SBV: Unexpected inexact rational to be converted to SMTLib2: " ++ show r
+algRealToSMTLib2 (AlgPolyRoot (i, AlgRealPoly xs) _) = "(root-obj (+ " ++ unwords (concatMap term xs) ++ ") " ++ show i ++ ")"
+  where term (0, _) = []
+        term (k, 0) = [coeff k]
+        term (1, 1) = ["x"]
+        term (1, p) = ["(^ x " ++ show p ++ ")"]
+        term (k, 1) = ["(* " ++ coeff k ++ " x)"]
+        term (k, p) = ["(* " ++ coeff k ++ " (^ x " ++ show p ++ "))"]
+        coeff n | n < 0 = "(- " ++ show (abs n) ++ ")"
+                | True  = show n
+algRealToSMTLib2 r@AlgInterval{}
+   = error $ "SBV: Unexpected inexact rational to be converted to SMTLib2: " ++ show r
+
+-- | Render an 'AlgReal' as a Haskell value. Only supports rationals, since there is no corresponding
+-- standard Haskell type that can represent root-of-polynomial variety.
+algRealToHaskell :: AlgReal -> String
+algRealToHaskell (AlgRational True r) = "((" ++ show r ++ ") :: Rational)"
+algRealToHaskell r                    = error $ unlines [ ""
+                                                        , "SBV.algRealToHaskell: Unsupported argument:"
+                                                        , ""
+                                                        , "   " ++ show r
+                                                        , ""
+                                                        , "represents an irrational number, and cannot be converted to a Haskell value."
+                                                        ]
+
+-- | Conversion from internal rationals to Haskell values
+data RationalCV = RatIrreducible AlgReal                                   -- ^ Root of a polynomial, cannot be reduced
+                | RatExact       Rational                                  -- ^ An exact rational
+                | RatApprox      Rational                                  -- ^ An approximated value
+                | RatInterval    (RealPoint Rational) (RealPoint Rational) -- ^ Interval. Can be open/closed on both ends.
+                deriving Show
+
+-- | Convert an 'AlgReal' to a 'Rational'. If the 'AlgReal' is exact, then you get a 'Left' value. Otherwise,
+-- you get a 'Right' value which is simply an approximation.
+algRealToRational :: AlgReal -> RationalCV
+algRealToRational a = case a of
+                        AlgRational True  r        -> RatExact r
+                        AlgRational False r        -> RatExact r
+                        AlgPolyRoot _     Nothing  -> RatIrreducible a
+                        AlgPolyRoot _     (Just s) -> let trimmed = case reverse s of
+                                                                     '.':'.':'.':rest -> reverse rest
+                                                                     _                -> s
+                                                      in case readSigned readFloat trimmed of
+                                                           [(v, "")] -> RatApprox v
+                                                           _         -> bad "represents a value that cannot be converted to a rational"
+                        AlgInterval lo hi          -> RatInterval lo hi
+   where bad w = error $ unlines [ ""
+                                 , "SBV.algRealToRational: Unsupported argument:"
+                                 , ""
+                                 , "   " ++ show a
+                                 , ""
+                                 , w
+                                 ]
+
+-- Try to show a rational precisely if we can, with finite number of
+-- digits. Otherwise, show it as a rational value.
+showRat :: Bool -> Rational -> String
+showRat exact r = p $ case f25 (denominator r) [] of
+                       Nothing               -> show r   -- bail out, not precisely representable with finite digits
+                       Just (noOfZeros, num) -> let present = length num
+                                                in neg $ case noOfZeros `compare` present of
+                                                           LT -> let (b, a) = splitAt (present - noOfZeros) num in b ++ "." ++ if null a then "0" else a
+                                                           EQ -> "0." ++ num
+                                                           GT -> "0." ++ replicate (noOfZeros - present) '0' ++ num
+  where p   = if exact then id else (++ "...")
+        neg = if r < 0 then ('-':) else id
+        -- factor a number in 2's and 5's if possible
+        -- If so, it'll return the number of digits after the zero
+        -- to reach the next power of 10, and the numerator value scaled
+        -- appropriately and shown as a string
+        f25 :: Integer -> [Integer] -> Maybe (Int, String)
+        f25 1 sofar = let (ts, fs)   = partition (== 2) sofar
+                          lts        = length ts
+                          lfs        = length fs
+                          noOfZeros  = lts `max` lfs
+                      in Just (noOfZeros, show (abs (numerator r)  * factor ts fs))
+        f25 v sofar = let (q2, r2) = v `quotRem` 2
+                          (q5, r5) = v `quotRem` 5
+                      in case (r2, r5) of
+                           (0, _) -> f25 q2 (2 : sofar)
+                           (_, 0) -> f25 q5 (5 : sofar)
+                           _      -> Nothing
+        -- compute the next power of 10 we need to get to
+        factor []     fs     = product [2 | _ <- fs]
+        factor ts     []     = product [5 | _ <- ts]
+        factor (_:ts) (_:fs) = factor ts fs
+
+-- | Merge the representation of two algebraic reals, one assumed to be
+-- in polynomial form, the other in decimal. Arguments can be the same
+-- kind, so long as they are both rationals and equivalent; if not there
+-- must be one that is precise. It's an error to pass anything
+-- else to this function! (Used in reconstructing SMT counter-example values with reals).
+mergeAlgReals :: String -> AlgReal -> AlgReal -> AlgReal
+mergeAlgReals _ f@(AlgRational exact r) (AlgPolyRoot kp Nothing)
+  | exact = f
+  | True  = AlgPolyRoot kp (Just (showRat False r))
+mergeAlgReals _ (AlgPolyRoot kp Nothing) f@(AlgRational exact r)
+  | exact = f
+  | True  = AlgPolyRoot kp (Just (showRat False r))
+mergeAlgReals _ f@(AlgRational e1 r1) s@(AlgRational e2 r2)
+  | (e1, r1) == (e2, r2) = f
+  | e1                   = f
+  | e2                   = s
+mergeAlgReals m _ _ = error m
+
+-- Quickcheck instance
+instance Arbitrary AlgReal where
+  arbitrary = AlgRational True <$> arbitrary
diff --git a/Data/SBV/Core/Concrete.hs b/Data/SBV/Core/Concrete.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Concrete.hs
@@ -0,0 +1,539 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Concrete
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Operations on concrete values
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass      #-}
+{-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Core.Concrete where
+
+import Control.Monad (replicateM)
+
+import Control.DeepSeq (NFData)
+
+import Data.Bits
+import System.Random (randomIO, randomRIO)
+
+import Data.Char (chr, isSpace)
+import Data.List (intercalate)
+import qualified Data.Text as T
+
+import Data.SBV.Core.Kind
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.SizedFloats
+
+import Data.Proxy
+
+import Data.SBV.Utils.Numeric (fpIsEqualObjectH, fpCompareObjectH)
+
+import Data.Set (Set)
+import qualified Data.Set as Set
+
+import qualified Data.Generics as G
+
+import GHC.Generics
+
+import Test.QuickCheck (Arbitrary(..))
+
+-- | 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)
+             deriving (NFData, G.Data, Generic)
+
+instance (Ord a, Arbitrary a) => Arbitrary (RCSet a) where
+  arbitrary = do c :: Bool <- arbitrary
+                 if c then RegularSet    <$> arbitrary
+                      else ComplementSet <$> arbitrary
+
+-- | 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))
+
+-- | Underlying type for SMTLib arrays, as a list of key-value pairs, with a default for unmapped
+-- elements. Note that this type matches the typical models returned by SMT-solvers.
+-- When we store the array, we do not bother removing earlier writes, so there might be duplicates.
+-- That is, we store the history of the writes. The earlier a pair is in the list, the "later" it
+-- is done, i.e., it takes precedence over the latter entries.
+data ArrayModel a b = ArrayModel [(a, b)] b
+                     deriving (G.Data, Generic, NFData, Show)
+
+-- | The kind of an ArrayModel
+instance (HasKind a, HasKind b) => HasKind (ArrayModel a b) where
+   kindOf _ = KArray (kindOf (Proxy @a)) (kindOf (Proxy @b))
+
+-- | A constant value.
+-- Note: If you add a new constructor here, make sure you add the
+-- corresponding equality in the instance "Eq CVal" and "Ord CVal"!
+data CVal = CAlgReal  !AlgReal                  -- ^ Algebraic real
+          | CInteger  !Integer                  -- ^ Bit-vector/unbounded integer
+          | CFloat    !Float                    -- ^ Float
+          | CDouble   !Double                   -- ^ Double
+          | CFP       !FP                       -- ^ Arbitrary float
+          | CRational !Rational                 -- ^ Rational
+          | CChar     !Char                     -- ^ Character
+          | CString   !String                   -- ^ String
+          | CList     ![CVal]                   -- ^ List
+          | CSet      !(RCSet CVal)             -- ^ Set. Can be regular or complemented.
+          | CADT      !(String, [(Kind, CVal)]) -- ^ ADT: Constructor, and fields
+          | CTuple    ![CVal]                   -- ^ Tuple
+          | CArray    !(ArrayModel CVal CVal)   -- ^ Arrays are backed by look-up tables concretely
+          deriving (G.Data, Generic, NFData)
+
+-- | Assign 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 CFP       {} =  4
+cvRank CRational {} =  5
+cvRank CChar     {} =  6
+cvRank CString   {} =  7
+cvRank CList     {} =  8
+cvRank CSet      {} =  9
+cvRank CADT      {} = 10
+cvRank CTuple    {} = 11
+cvRank CArray    {} = 12
+
+-- | Eq instance for CVal. 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
+-- need a structural eq/ord for Map indexes; so define custom ones here:
+instance Eq CVal where
+  CAlgReal  a == CAlgReal  b = a `algRealStructuralEqual` b
+  CInteger  a == CInteger  b = a == b
+  CFloat    a == CFloat    b = a `fpIsEqualObjectH` b   -- We don't want +0/-0 to be confused; and also we want NaN = NaN here!
+  CDouble   a == CDouble   b = a `fpIsEqualObjectH` b   -- ditto
+  CRational a == CRational b = a == b
+  CFP       a == CFP       b = a `arbFPIsEqualObjectH` b
+  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
+  CTuple    a == CTuple    b = a == b
+  CADT      a == CADT      b = a == b
+
+  -- This is legit since we don't use this equality for actual semantic" equality, but rather as an index into maps
+  CArray    (ArrayModel a1 d1) == CArray (ArrayModel a2 d2) = (a1, d1) == (a2, d2)
+
+  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 CVal. Same comments as the 'Eq' instance why this cannot be derived.
+instance Ord CVal where
+  CAlgReal  a `compare` CAlgReal  b = a `algRealStructuralCompare` b
+  CInteger  a `compare` CInteger  b = a `compare`                  b
+  CFloat    a `compare` CFloat    b = a `fpCompareObjectH`         b
+  CDouble   a `compare` CDouble   b = a `fpCompareObjectH`         b
+  CRational a `compare` CRational b = a `compare`                  b
+  CFP       a `compare` CFP       b = a `arbFPCompareObjectH`      b
+  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
+  CTuple    a `compare` CTuple    b = a `compare`                  b
+  CADT      a `compare` CADT      b = a `compare`                  b
+
+  -- This is legit since we don't use this equality for actual semantic order, but rather as an index into maps
+  CArray    (ArrayModel a1 d1) `compare` CArray (ArrayModel a2 d2) = (a1, d1) `compare` (a2, d2)
+
+  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
+
+-- | A t'CV' represents a concrete word of a fixed size:
+-- For signed words, the most significant digit is considered to be the sign.
+data CV = CV { cvKind  :: !Kind
+             , cvVal   :: !CVal
+             }
+             deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | A generalized CV allows for expressions involving infinite and epsilon values/intervals Used in optimization problems.
+data GeneralizedCV = ExtendedCV ExtCV
+                   | RegularCV  CV
+
+-- | A simple expression type over extended values, covering infinity, epsilon and intervals.
+data ExtCV = Infinite  Kind         -- infinity
+           | Epsilon   Kind         -- epsilon
+           | Interval  ExtCV ExtCV  -- closed interval
+           | BoundedCV CV           -- a bounded value (i.e., neither infinity, nor epsilon). Note that this cannot appear at top, but can appear as a sub-expr.
+           | AddExtCV  ExtCV ExtCV  -- addition
+           | MulExtCV  ExtCV ExtCV  -- multiplication
+
+-- | Kind instance for Extended CV
+instance HasKind ExtCV where
+  kindOf (Infinite  k)   = k
+  kindOf (Epsilon   k)   = k
+  kindOf (Interval  l _) = kindOf l
+  kindOf (BoundedCV  c)  = kindOf c
+  kindOf (AddExtCV  l _) = kindOf l
+  kindOf (MulExtCV  l _) = kindOf l
+
+-- | Show instance, shows with the kind
+instance Show ExtCV where
+  show = showExtCV True
+
+-- | Show an extended CV, with kind if required
+showExtCV :: Bool -> ExtCV -> String
+showExtCV = go False
+  where go parens shk extCV = case extCV of
+                                Infinite{}    -> withKind False "oo"
+                                Epsilon{}     -> withKind False "epsilon"
+                                Interval  l u -> withKind True  $ '['  : showExtCV False l ++ " .. " ++ showExtCV False u ++ "]"
+                                BoundedCV c   -> showCV shk c
+                                AddExtCV l r  -> par $ withKind False $ add (go True False l) (go True False r)
+
+                                -- a few niceties here to grok -oo and -epsilon
+                                MulExtCV (BoundedCV (CV KUnbounded (CInteger (-1)))) Infinite{} -> withKind False "-oo"
+                                MulExtCV (BoundedCV (CV KReal      (CAlgReal (-1)))) Infinite{} -> withKind False "-oo"
+                                MulExtCV (BoundedCV (CV KUnbounded (CInteger (-1)))) Epsilon{}  -> withKind False "-epsilon"
+                                MulExtCV (BoundedCV (CV KReal      (CAlgReal (-1)))) Epsilon{}  -> withKind False "-epsilon"
+
+                                MulExtCV l r  -> par $ withKind False $ mul (go True False l) (go True False r)
+           where par v | parens = '(' : v ++ ")"
+                       | True   = v
+                 withKind isInterval v | not shk    = v
+                                       | isInterval = v ++ " :: [" ++ T.unpack (showBaseKind (kindOf extCV)) ++ "]"
+                                       | True       = v ++ " :: "  ++ T.unpack (showBaseKind (kindOf extCV))
+
+                 add :: String -> String -> String
+                 add n ('-':v) = n ++ " - " ++ v
+                 add n v       = n ++ " + " ++ v
+
+                 mul :: String -> String -> String
+                 mul n v = n ++ " * " ++ v
+
+-- | Is this a regular CV?
+isRegularCV :: GeneralizedCV -> Bool
+isRegularCV RegularCV{}  = True
+isRegularCV ExtendedCV{} = False
+
+-- | 'Kind' instance for CV
+instance HasKind CV where
+  kindOf (CV k _) = k
+
+-- | 'Kind' instance for generalized CV
+instance HasKind GeneralizedCV where
+  kindOf (ExtendedCV e) = kindOf e
+  kindOf (RegularCV  c) = kindOf c
+
+-- | Are two CV's of the same type?
+cvSameType :: CV -> CV -> Bool
+cvSameType x y = kindOf x == kindOf y
+
+-- | Convert a CV to a Haskell boolean (NB. Assumes input is well-kinded)
+cvToBool :: CV -> Bool
+cvToBool x = cvVal x /= CInteger 0
+
+-- | Normalize a CV. Essentially performs modular arithmetic to make sure the
+-- value can fit in the given bit-size. Note that this is rather tricky for
+-- negative values, due to asymmetry. (i.e., an 8-bit negative number represents
+-- values in the range -128 to 127; thus we have to be careful on the negative side.)
+normCV :: CV -> CV
+normCV c@(CV (KBounded signed sz) (CInteger v)) = c { cvVal = CInteger norm }
+ where norm | sz == 0 = 0
+
+            | signed  = let rg = 2 ^ (sz - 1)
+                        in case divMod v rg of
+                                  (a, b) | even a -> b
+                                  (_, b)          -> b - rg
+
+            | True    = {- We really want to do:
+
+                                v `mod` (2 ^ sz)
+
+                           Below is equivalent, and hopefully faster!
+                        -}
+                        v .&. (((1 :: Integer) `shiftL` sz) - 1)
+normCV c@(CV KBool (CInteger v)) = c { cvVal = CInteger (v .&. 1) }
+normCV c                         = c
+{-# INLINE normCV #-}
+
+-- | Constant False as a t'CV'. We represent it using the integer value 0.
+falseCV :: CV
+falseCV = CV KBool (CInteger 0)
+
+-- | Constant True as a t'CV'. We represent it using the integer value 1.
+trueCV :: CV
+trueCV  = CV KBool (CInteger 1)
+
+-- | Map a unary function through a t'CV'.
+mapCV :: (AlgReal             -> AlgReal)
+      -> (Integer             -> Integer)
+      -> (Float               -> Float)
+      -> (Double              -> Double)
+      -> (FP                  -> FP)
+      -> (Rational            -> Rational)
+      -> CV                   -> CV
+mapCV r i f d af ra x  = normCV $ CV (kindOf x) $ case cvVal x of
+                                                    CAlgReal  a -> CAlgReal  (r  a)
+                                                    CInteger  a -> CInteger  (i  a)
+                                                    CFloat    a -> CFloat    (f  a)
+                                                    CDouble   a -> CDouble   (d  a)
+                                                    CFP       a -> CFP       (af a)
+                                                    CRational a -> CRational (ra a)
+                                                    CChar{}     -> error "Data.SBV.mapCV: Unexpected call through mapCV with chars!"
+                                                    CString{}   -> error "Data.SBV.mapCV: Unexpected call through mapCV with strings!"
+                                                    CADT{}      -> error "Data.SBV.mapCV: Unexpected call through mapCV with ADTs!"
+                                                    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!"
+                                                    CArray{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with arrays!"
+
+-- | Map a binary function through a t'CV'.
+mapCV2 :: (AlgReal             -> AlgReal             -> AlgReal)
+       -> (Integer             -> Integer             -> Integer)
+       -> (Float               -> Float               -> Float)
+       -> (Double              -> Double              -> Double)
+       -> (FP                  -> FP                  -> FP)
+       -> (Rational            -> Rational            -> Rational)
+       -> CV                   -> CV                  -> CV
+mapCV2 r i f d af ra 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))
+                            (True, CFloat    a, CFloat    b) -> normCV $ CV (kindOf x) (CFloat    (f  a b))
+                            (True, CDouble   a, CDouble   b) -> normCV $ CV (kindOf x) (CDouble   (d  a b))
+                            (True, CFP       a, CFP       b) -> normCV $ CV (kindOf x) (CFP       (af a b))
+                            (True, CRational a, CRational b) -> normCV $ CV (kindOf x) (CRational (ra a b))
+                            (True, CChar{},     CChar{})     -> unexpected "chars!"
+                            (True, CString{},   CString{})   -> unexpected "strings!"
+                            (True, CList{},     CList{})     -> unexpected "lists!"
+                            (True, CTuple{},    CTuple{})    -> unexpected "tuples!"
+                            _                                -> unexpected $ "incompatible args: " ++ show (x, y)
+   where unexpected w = error $ unlines [ ""
+                                        , "*** Data.SBV.mapCV2: Unexpected call through mapCV2 with " ++ w
+                                        , "*** Please report this as a bug!"
+                                        ]
+
+-- | Show instance for t'CV'.
+instance Show CV where
+  show = showCV True
+
+-- | Show instance for Generalized t'CV'
+instance Show GeneralizedCV where
+  show (ExtendedCV k) = showExtCV True k
+  show (RegularCV  c) = showCV    True c
+
+-- | 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 = sh (cvVal w) ++ kInfo
+  where kInfo | shk  = " :: " ++ T.unpack (showBaseKind wk)
+              | True = ""
+
+        wk = kindOf w
+
+        sh (CAlgReal  v) = show  v
+        sh (CInteger  v) = show  v
+        sh (CFloat    v) = show  v
+        sh (CDouble   v) = show  v
+        sh (CFP       v) = show  v
+        sh (CRational v) = show  v
+        sh (CChar     v) = show  v
+        sh (CString   v) = show  v
+        sh (CADT      c) = shADT c
+        sh (CList     v) = shL   v
+        sh (CSet      v) = shS   v
+        sh (CTuple    v) = shT   v
+        sh (CArray    v) = shA   v
+
+        shL xs = "[" ++ intercalate "," (map (showCV False . CV ke) xs) ++ "]"
+          where ke = case wk of
+                       KList k -> k
+                       _       -> error $ "Data.SBV.showCV: Impossible happened, expected list, got: " ++ show wk
+
+        -- 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              -> set e
+                    ComplementSet e | Set.null e -> "U"
+                                    | True       -> "U - " ++ set e
+          where set xs = "{" ++ intercalate "," (map (showCV False . CV ke) (Set.toList xs)) ++ "}"
+                ke = case wk of
+                       KSet k -> k
+                       _      -> error $ "Data.SBV.showCV: Impossible happened, expected set, got: " ++ show wk
+
+        shT :: [CVal] -> String
+        shT xs = "(" ++ intercalate "," xs' ++ ")"
+          where xs' = case wk of
+                        KTuple ks | length ks == length xs -> zipWith (\k x -> showCV False (CV k x)) ks xs
+                        _   -> error $ "Data.SBV.showCV: Impossible happened, expected tuple (of length " ++ show (length xs) ++ "), got: " ++ show wk
+
+        shA :: ArrayModel CVal CVal -> String
+        shA (ArrayModel assocs def)
+          | KArray k1 k2 <- wk = "([" ++ intercalate "," [showCV False (CV (KTuple [k1, k2]) (CTuple [a, b])) | (a, b) <- assocs] ++ "], " ++ showCV False (CV k2 def) ++ ")"
+          | True               = error $ "Data.SBV.showCV: Impossible happened, expected array, got: " ++ show wk
+
+        shADT (c, kvs)
+          | null @[] flds = c
+          | True          = unwords (c : map wrap flds)
+          where wrap v
+                 | take 1 v `elem` ["(", "[", "{"]  = v
+                 | any isSpace v || take 1 v == "-" = '(' : v ++ ")"
+                 | True                             = v
+
+                flds = map (\(k, v) -> showCV False (CV k v)) kvs
+
+-- | Create a constant word from an integral.
+mkConstCV :: Integral a => Kind -> a -> CV
+mkConstCV k@KVar{}        _ = error $ "mkConstCV: Unexpected kind: " ++ show k
+mkConstCV KBool           a = normCV $ CV KBool      (CInteger  (toInteger a))
+mkConstCV k@KBounded{}    a = normCV $ CV k          (CInteger  (toInteger a))
+mkConstCV KUnbounded      a = normCV $ CV KUnbounded (CInteger  (toInteger a))
+mkConstCV KReal           a = normCV $ CV KReal      (CAlgReal  (fromInteger (toInteger a)))
+mkConstCV KFloat          a = normCV $ CV KFloat     (CFloat    (fromInteger (toInteger a)))
+mkConstCV KDouble         a = normCV $ CV KDouble    (CDouble   (fromInteger (toInteger a)))
+mkConstCV k@(KFP eb sb)   a = normCV $ CV k          (CFP       (fpFromInteger eb sb (toInteger a)))
+mkConstCV KRational       a = normCV $ CV KRational  (CRational (fromInteger (toInteger a)))
+mkConstCV KChar           a = error $ "Unexpected call to mkConstCV (Char) with value: "   ++ show (toInteger a)
+mkConstCV KString         a = error $ "Unexpected call to mkConstCV (String) with value: " ++ show (toInteger a)
+mkConstCV (KApp s _)      a = error $ "Unexpected call to mkConstCV with kind: " ++ s ++ " with value: " ++ show (toInteger a)
+mkConstCV (KADT s _ _)    a = error $ "Unexpected call to mkConstCV with ADT: "  ++ 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@KArray{}      a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
+
+-- | Create a constant value from a floating-point value.
+fpConstCV ::
+  -- | Must be 'KFloat', 'KDouble', or 'KFP'.
+  Kind ->
+  -- | The constant to use when the kind is 'KFloat'.
+  Float ->
+  -- | The constant to use when the kind is 'KDouble'.
+  Double ->
+  -- | The constant to make when the kind is 'KFP', where the 'Int's represent
+  -- the exponent and significand sizes.
+  (Int -> Int -> FP) ->
+  CV
+fpConstCV k cf cd cfp =
+  case k of
+    KFloat    -> CV k $ CFloat cf
+    KDouble   -> CV k $ CDouble cd
+    KFP eb sb -> CV k $ CFP $ cfp eb sb
+
+    KVar{} -> unexpected
+    KBool{} -> unexpected
+    KBounded{} -> unexpected
+    KUnbounded{} -> unexpected
+    KReal{} -> unexpected
+    KRational{} -> unexpected
+    KChar{} -> unexpected
+    KString{} -> unexpected
+    KApp{} -> unexpected
+    KADT{} -> unexpected
+    KList{} -> unexpected
+    KSet{} -> unexpected
+    KTuple{} -> unexpected
+    KArray{} -> unexpected
+  where unexpected = error $ "Data.SBV.fpConstCV: Unexpected kind: " ++ show k
+
+-- | Generate a random constant value ('CVal') of the correct kind. We error out for a completely uninterpreted type.
+randomCVal :: Kind -> IO CVal
+randomCVal k =
+  case k of
+    KVar{}             -> error $ "randomCVal: Unexpected kind: " ++ show k
+    KBool              -> CInteger  <$> randomRIO (0, 1)
+    KBounded s w       -> CInteger  <$> randomRIO (bounds s w)
+    KUnbounded         -> CInteger  <$> randomIO
+    KReal              -> CAlgReal  <$> randomIO
+    KFloat             -> CFloat    <$> randomIO
+    KDouble            -> CDouble   <$> randomIO
+    KRational          -> CRational <$> randomIO
+
+    -- Rather bad, but OK
+    KFP eb sb          -> do sgn <- randomRIO (0 :: Integer, 1)
+                             let sign = sgn == 1
+                             e   <- randomRIO (0 :: Integer, 2^eb-1)
+                             s   <- randomRIO (0 :: Integer, 2^sb-1)
+                             pure $ CFP $ fpFromRawRep sign (e, eb) (s, sb)
+
+    -- TODO: KString/KChar currently only go for 0..255; include unicode?
+    KString            -> do l <- randomRIO (0, 100)
+                             CString <$> replicateM l (chr <$> randomRIO (0, 255))
+    KChar              -> CChar . chr <$> randomRIO (0, 255)
+
+    -- TODO: Can we do something here?
+    KApp s _           -> error $ "randomCVal: Not supported for KApp: " ++ s
+
+    KADT _ _ cstrs@(_:_) -> do i <- randomRIO (0, length cstrs - 1)
+                               let (c, fks) = cstrs !! i
+                               vs <- mapM randomCVal fks
+                               pure $ CADT (c, zip fks vs)
+    KADT s _ _         -> error $ "randomCVal: Not supported for ADT:  " ++ 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)
+                             pure $ CSet $ if i then RegularSet vals else ComplementSet vals
+
+    KTuple ks          -> CTuple <$> traverse randomCVal ks
+
+    KArray k1 k2       -> do l   <- randomRIO (0, 100)
+                             ks  <- replicateM l (randomCVal k1)
+                             vs  <- replicateM l (randomCVal k2)
+                             def <- randomCVal k2
+                             pure $ CArray $ ArrayModel (zip ks vs) def
+  where
+    bounds :: Bool -> Int -> (Integer, Integer)
+    bounds False w = (0, 2^w - 1)
+    bounds True  w = (-x, x-1) where x = 2^(w-1)
+
+-- | Generate a random constant value (i.e., t'CV') of the correct kind.
+randomCV :: Kind -> IO CV
+randomCV k = CV k <$> randomCVal k
+
+{- HLint ignore module "Redundant if" -}
diff --git a/Data/SBV/Core/Data.hs b/Data/SBV/Core/Data.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Data.hs
@@ -0,0 +1,1095 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Data
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Internal data-structures for the sbv library
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE DefaultSignatures     #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TypeApplications      #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.Data
+ ( SBool, SWord8, SWord16, SWord32, SWord64
+ , SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble
+ , SFloatingPoint, SFPHalf, SFPBFloat, SFPSingle, SFPDouble, SFPQuad
+ , SWord, SInt, WordN, IntN
+ , SRational
+ , SChar, SString, SList, (.:), nil
+ , SArray, ArrayModel(..)
+ , STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+ , RCSet(..), SSet
+ , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
+ , SymVal(..), SymValInsts(..), symValKinds, SymVals(..)
+ , CV(..), CVal(..), AlgReal(..), AlgRealPoly(..), ExtCV(..), GeneralizedCV(..), isRegularCV, cvSameType, cvToBool
+ , mkConstCV , mapCV, mapCV2
+ , SV(..), trueSV, falseSV, trueCV, falseCV, normCV
+ , SVal(..)
+ , sTrue, sFalse, sNot, (.&&), (.||), (.<+>), (.~&), (.~|), (.=>), (.<=>), sAnd, sOr, sAny, sAll, fromBool
+ , SBV(..), NodeId(..), mkSymSBV
+ , sbvToSV, sbvToSymSV, forceSVArg
+ , RList(..), RNil, (:>), rlist2list
+ , SBVs(..), mapMSBVs, foldlSymSBVs
+ , SBVExpr(..), newExpr
+ , cache, Cached, uncache, HasKind(..)
+ , Op(..), PBOp(..), FPOp(..), StrOp(..), RegExOp(..), SeqOp(..), RegExp(..), NamedSymVar(..), OvOp(..), getTableIndex
+ , SBVPgm(..), Symbolic, runSymbolic, State, SInfo(..), getSInfo, getPathCondition
+ , inSMTMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
+ , SolverContext(..), internalConstraint, isCodeGenMode
+ , SBVType(..), newUninterpreted
+ , Quantifier(..), needsExistentials
+ , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension
+ , SolverCapabilities(..)
+ , extractSymbolicSimulationState
+ , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), TPOptions(..)
+ , OptimizeStyle(..), Penalty(..), Objective(..)
+ , QueryState(..), QueryT(..), SMTProblem(..), Constraint(..), Lambda(..), Forall(..), Exists(..), ExistsUnique(..), ForallN(..), ExistsN(..)
+ , QuantifiedBool(..), EqSymbolic(..), QNot(..), Skolemize(SkolemsTo, skolemize, taggedSkolemize)
+ , bvExtract, (#), bvDrop, bvTake
+ , registerType
+ ) where
+
+import GHC.TypeLits (KnownNat, Nat, Symbol, KnownSymbol, symbolVal, AppendSymbol, type (+), type (-), type (<=), natVal)
+
+import Control.DeepSeq        (NFData(..))
+import Control.Monad          (void, replicateM)
+import Control.Monad.Trans    (liftIO, MonadIO)
+import Data.Int               (Int8, Int16, Int32, Int64)
+import Data.Word              (Word8, Word16, Word32, Word64)
+
+import Data.Kind (Type)
+import Data.Proxy
+import Data.Typeable          (Typeable)
+
+import Data.IORef
+import qualified Data.Set as Set (toList)
+
+import GHC.Generics (Generic, U1(..), M1(..), (:*:)(..), K1(..), (:+:)(..))
+import qualified GHC.Generics  as G
+
+import GHC.Exts (IsList(..))
+
+import System.Random
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Sized
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Concrete
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.Operations
+
+import Data.SBV.Control.Types
+
+import Data.SBV.Utils.Lib
+import Data.SBV.Utils.Numeric (RoundingMode(..))
+
+import Test.QuickCheck (Arbitrary(..))
+
+-- | Get the current path condition
+getPathCondition :: State -> SBool
+getPathCondition st = SBV (getSValPathCondition st)
+
+-- | The "Symbolic" value. The parameter @a@ is phantom, but is
+-- extremely important in keeping the user interface strongly typed.
+newtype SBV a = SBV { unSBV :: SVal }
+              deriving (Generic, NFData)
+
+-- | A symbolic boolean/bit
+type SBool   = SBV Bool
+
+-- | 8-bit unsigned symbolic value
+type SWord8  = SBV Word8
+
+-- | 16-bit unsigned symbolic value
+type SWord16 = SBV Word16
+
+-- | 32-bit unsigned symbolic value
+type SWord32 = SBV Word32
+
+-- | 64-bit unsigned symbolic value
+type SWord64 = SBV Word64
+
+-- | 8-bit signed symbolic value, 2's complement representation
+type SInt8   = SBV Int8
+
+-- | 16-bit signed symbolic value, 2's complement representation
+type SInt16  = SBV Int16
+
+-- | 32-bit signed symbolic value, 2's complement representation
+type SInt32  = SBV Int32
+
+-- | 64-bit signed symbolic value, 2's complement representation
+type SInt64  = SBV Int64
+
+-- | Infinite precision signed symbolic value
+type SInteger = SBV Integer
+
+-- | Infinite precision symbolic algebraic real value
+type SReal = SBV AlgReal
+
+-- | IEEE-754 single-precision floating point numbers
+type SFloat = SBV Float
+
+-- | IEEE-754 double-precision floating point numbers
+type SDouble = SBV Double
+
+-- | A symbolic arbitrary precision floating point value
+type SFloatingPoint (eb :: Nat) (sb :: Nat) = SBV (FloatingPoint eb sb)
+
+-- | A symbolic half-precision float
+type SFPHalf = SBV FPHalf
+
+-- | A symbolic brain-float precision float
+type SFPBFloat = SBV FPBFloat
+
+-- | A symbolic single-precision float
+type SFPSingle = SBV FPSingle
+
+-- | A symbolic double-precision float
+type SFPDouble = SBV FPDouble
+
+-- | A symbolic quad-precision float
+type SFPQuad = SBV FPQuad
+
+-- | A symbolic unsigned bit-vector carrying its size info
+type SWord (n :: Nat) = SBV (WordN n)
+
+-- | A symbolic signed bit-vector carrying its size info
+type SInt (n :: Nat) = SBV (IntN n)
+
+-- | A symbolic character. Note that this is the full unicode character set.
+-- see: <https://smt-lib.org/theories-UnicodeStrings.shtml>
+-- for details.
+type SChar = SBV Char
+
+-- | A symbolic string. Note that a symbolic string is /not/ a list of symbolic characters,
+-- that is, it is not the case that @SString = [SChar]@, unlike what one might expect following
+-- Haskell strings. An 'SString' is a symbolic value of its own, of possibly arbitrary but finite length,
+-- and internally processed as one unit as opposed to a fixed-length list of characters.
+type SString = SBV String
+
+-- | A symbolic rational value.
+type SRational = SBV Rational
+
+-- | A symbolic list of items. Note that a symbolic list is /not/ a list of symbolic items,
+-- that is, it is not the case that @SList a = [a]@, unlike what one might expect following
+-- haskell lists\/sequences. An 'SList' is a symbolic value of its own, of possibly arbitrary but finite
+-- length, and internally processed as one unit as opposed to a fixed-length list of items.
+-- Note that lists can be nested, i.e., we do allow lists of lists of ... items.
+type SList a = SBV [a]
+
+-- | Prepend an element, the traditional @cons@.
+--
+-- >>> 1 .: 2 .: 3 .: [4, 5, 6 :: SInteger]
+-- [1,2,3,4,5,6] :: [SInteger]
+infixr 5 .:
+(.:) :: forall a. (SymVal a, SymVal [a]) => SBV a -> SList a -> SList a
+a .: as
+  | Just av  <- unliteral a
+  , Just asv <- unliteral as
+  = literal (av : asv)
+  | Just asv <- unliteral as, null asv  -- singleton: skip the concat with empty
+  = SBV $ SVal kl $ Right $ cache $ \st -> do
+        sva <- sbvToSV st a
+        newExpr st kl (SBVApp (SeqOp (SeqUnit ka)) [sva])
+  | True
+  = SBV $ SVal kl $ Right $ cache r
+  where ka = kindOf (Proxy @a)
+        kl = kindOf (Proxy @[a])
+        r st = do sva  <- sbvToSV st a
+                  svs  <- newExpr st kl (SBVApp (SeqOp (SeqUnit ka)) [sva])
+                  svas <- sbvToSV st as
+                  newExpr st kl (SBVApp (SeqOp (SeqConcat kl)) [svs, svas])
+
+-- | Empty list. This value has the property that it's the only list with length 0. If you use @OverloadedLists@ extension,
+-- you can write it as the familiar @[]@.
+nil :: SymVal [a] => SList a
+nil = literal []
+
+-- | 'IsList' instance allows list literals to be written compactly.
+instance (SymVal a, SymVal [a]) => IsList (SList a) where
+  type Item (SList a) = SBV a
+
+  fromList = foldr (.:) nil -- Don't use [] here for nil, as this is the very definition of doing overloaded lists
+  toList x = case unliteral x of
+               Nothing -> error "IsList.toList used in a symbolic context"
+               Just xs -> map literal xs
+
+-- | Symbolic arrays. A symbolic array is more akin to a function in SMTLib (and thus in SBV),
+-- as opposed to contagious-storage with a finite range as found in many programming languages.
+-- Additionally, the domain uses object-equality in the SMTLib semantics. Object equality is
+-- the same as regular equality for most types, except for IEEE-Floats, where @NaN@ doesn't compare
+-- equal to itself and @+0@ and @-0@ are not distinguished. So, if your index type is a float,
+-- then @NaN@ can be stored correctly, and @0@ and @-0@ will be distinguished. If you don't use
+-- floats, then you can treat this the same as regular equality in Haskell.
+type SArray a b = SBV (ArrayModel a b)
+
+-- | 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. Similar to 'SArray'
+-- the contents are stored with object equality, which makes a difference if the
+-- underlying type contains IEEE Floats.
+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.
+type STuple3 a b c = SBV (a, b, c)
+
+-- | Symbolic 4-tuple.
+type STuple4 a b c d = SBV (a, b, c, d)
+
+-- | Symbolic 5-tuple.
+type STuple5 a b c d e = SBV (a, b, c, d, e)
+
+-- | Symbolic 6-tuple.
+type STuple6 a b c d e f = SBV (a, b, c, d, e, f)
+
+-- | Symbolic 7-tuple.
+type STuple7 a b c d e f g = SBV (a, b, c, d, e, f, g)
+
+-- | Symbolic 8-tuple.
+type STuple8 a b c d e f g h = SBV (a, b, c, d, e, f, g, h)
+
+-- | Not-A-Number for 'Double' and 'Float'. Surprisingly, Haskell
+-- Prelude doesn't have this value defined, so we provide it here.
+nan :: Floating a => a
+nan = 0/0
+
+-- | Infinity for 'Double' and 'Float'. Surprisingly, Haskell
+-- Prelude doesn't have this value defined, so we provide it here.
+infinity :: Floating a => a
+infinity = 1/0
+
+-- | Symbolic variant of Not-A-Number. This value will inhabit
+-- 'SFloat', 'SDouble' and 'SFloatingPoint'. types.
+sNaN :: (Floating a, SymVal a) => SBV a
+sNaN = literal nan
+
+-- | Symbolic variant of infinity. This value will inhabit both
+-- 'SFloat', 'SDouble' and 'SFloatingPoint'. types.
+sInfinity :: (Floating a, SymVal a) => SBV a
+sInfinity = literal infinity
+
+-- | Internal representation of a symbolic simulation result
+newtype SMTProblem = SMTProblem {smtLibPgm :: SMTConfig -> SMTLibPgm} -- ^ SMTLib representation, given the config
+
+-- | Symbolic 'True'
+sTrue :: SBool
+sTrue = SBV (svBool True)
+
+-- | Symbolic 'False'
+sFalse :: SBool
+sFalse = SBV (svBool False)
+
+-- | Symbolic boolean negation
+sNot :: SBool -> SBool
+sNot (SBV b) = SBV (svNot b)
+
+-- | Symbolic conjunction
+infixr 3 .&&
+(.&&) :: SBool -> SBool -> SBool
+SBV x .&& SBV y = SBV (x `svAnd` y)
+
+-- | Symbolic disjunction
+infixr 2 .||
+(.||) :: SBool -> SBool -> SBool
+SBV x .|| SBV y = SBV (x `svOr` y)
+
+-- | Symbolic logical xor
+infixl 6 .<+>
+(.<+>) :: SBool -> SBool -> SBool
+SBV x .<+> SBV y = SBV (x `svXOr` y)
+
+-- | Symbolic nand
+infixr 3 .~&
+(.~&) :: SBool -> SBool -> SBool
+x .~& y = sNot (x .&& y)
+
+-- | Symbolic nor
+infixr 2 .~|
+(.~|) :: SBool -> SBool -> SBool
+x .~| y = sNot (x .|| y)
+
+-- | Symbolic implication
+infixr 1 .=>
+(.=>) :: SBool -> SBool -> SBool
+SBV x .=> SBV y = SBV (x `svImplies` 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 .<=>
+(.<=>) :: SBool -> SBool -> SBool
+SBV x .<=> SBV y = SBV (x `svEqual` y)
+
+-- | Conversion from 'Bool' to 'SBool'
+fromBool :: Bool -> SBool
+fromBool True  = sTrue
+fromBool False = sFalse
+
+-- | Generalization of 'and'
+sAnd :: [SBool] -> SBool
+sAnd = foldr (.&&) sTrue
+
+-- | Generalization of 'or'
+sOr :: [SBool] -> SBool
+sOr  = foldr (.||) sFalse
+
+-- | Generalization of 'any'
+sAny :: (a -> SBool) -> [a] -> SBool
+sAny f = sOr  . map f
+
+-- | Generalization of 'all'
+sAll :: (a -> SBool) -> [a] -> SBool
+sAll f = sAnd . map f
+
+-- | The symbolic variant of 'RoundingMode'
+type SRoundingMode = SBV RoundingMode
+
+-- | A 'Show' instance is not particularly "desirable," when the value is symbolic,
+-- but we do need this instance as otherwise we cannot simply evaluate Haskell functions
+-- that return symbolic values and have their constant values printed easily!
+instance Show (SBV a) where
+  show (SBV sv) = show sv
+
+instance HasKind a => HasKind (SBV a) where
+  kindOf _ = kindOf (Proxy @a)
+
+-- | Convert a symbolic value to a symbolic-word
+sbvToSV :: State -> SBV a -> IO SV
+sbvToSV st (SBV s) = svToSV st s
+
+-- | A datakind for lists with cons on the right
+data RList a = RNil | (RList a) :> a
+
+-- | Convert an 'RList' into a reversed standard list
+rlist2listRev :: RList a -> [a]
+rlist2listRev RNil = []
+rlist2listRev (as :> a) = a : rlist2listRev as
+
+-- | Convert an 'RList' into a standard list
+rlist2list :: RList a -> [a]
+rlist2list = reverse . rlist2listRev
+
+-- | Helper for writing types containing @RNil@
+type RNil = 'RNil
+
+-- | Helper for writing types containing @:>@
+type (:>) = '(:>)
+
+-- | A sequence of elements of types @SBV a1,...,SBV an@ given the list
+-- @[a1,...,an]@ of Haskell types
+data SBVs as where
+  SBVsNil  :: SBVs RNil
+  SBVsCons :: SBVs as -> SBV a -> SBVs (as :> a)
+
+-- | Fold a function over each SBV value in an SBVs sequence in a manner similar
+-- to 'foldr' for lists, except backwards because the lists are stored in
+-- reverse order
+foldlSBVs :: (forall a. r -> SBV a -> r) -> r -> SBVs as -> r
+foldlSBVs _ r SBVsNil             = r
+foldlSBVs f r (SBVsCons args arg) = f (foldlSBVs f r args) arg
+
+-- | Map a monadic function over the SBV values in an SBVs sequence in a
+-- manner similar to 'mapM' for lists
+mapMSBVs :: Monad m => (forall a. SBV a -> m r) -> SBVs as -> m (RList r)
+mapMSBVs f = foldlSBVs (\m arg -> (:>) <$> m <*> f arg) (pure RNil)
+
+-- | Fold a function over each SBV value in an SBVs sequence in a manner similar
+-- to 'foldr' for lists (but backwards because SBVs have cons on the right),
+-- using 'SymVal' instances for each value
+foldlSymSBVs :: (forall a. SymVal a => r -> SBV a -> r) -> r ->
+                SymValInsts as -> SBVs as -> r
+foldlSymSBVs _ r _                   SBVsNil             = r
+foldlSymSBVs f r (SymValsCons symvs) (SBVsCons args arg) =
+  f (foldlSymSBVs f r symvs args) arg
+
+-------------------------------------------------------------------------
+-- * Symbolic Computations
+-------------------------------------------------------------------------
+
+-- | Generalization of 'Data.SBV.mkSymSBV'
+mkSymSBV :: forall a m. MonadSymbolic m => VarContext -> Kind -> Maybe String -> m (SBV a)
+mkSymSBV vc k mbNm = SBV <$> (symbolicEnv >>= liftIO . svMkSymVar vc k mbNm)
+
+-- | Generalization of 'Data.SBV.sbvToSymSW'
+sbvToSymSV :: MonadSymbolic m => SBV a -> m SV
+sbvToSymSV sbv = do
+        st <- symbolicEnv
+        liftIO $ sbvToSV st sbv
+
+-- | Values that we can turn into a constraint
+class MonadSymbolic m => Constraint m a where
+  mkConstraint :: State -> a -> m ()
+
+-- | Base case: simple booleans
+instance MonadSymbolic m => Constraint m SBool where
+  mkConstraint _ out = void $ output out
+
+-- | An existential symbolic variable, used in building quantified constraints. The name
+-- attached via the symbol is used during skolemization to create a skolem-function name
+-- when this variable is eliminated.
+newtype Exists (nm :: Symbol) a = Exists (SBV a)
+
+-- | An existential unique symbolic variable, used in building quantified constraints. The name
+-- attached via the symbol is used during skolemization. It's split into two extra names, suffixed
+-- @_eu1@ and @_eu2@, to name the universals in the equivalent formula:
+-- \(\exists! x\,P(x)\Leftrightarrow \exists x\,P(x) \land \forall x_{eu1} \forall x_{eu2} (P(x_{eu1}) \land P(x_{eu2}) \Rightarrow x_{eu1} = x_{eu2}) \)
+newtype ExistsUnique (nm :: Symbol) a = ExistsUnique (SBV a)
+
+-- | A universal symbolic variable, used in building quantified constraints. The name attached via the symbol is used
+-- during skolemization. It names the corresponding argument to the skolem-functions within the scope of this quantifier.
+newtype Forall (nm :: Symbol) a = Forall (SBV a)
+
+-- | Exactly @n@ existential symbolic variables, used in building quantified constraints. The name attached
+-- will be prefixed in front of @_1@, @_2@, ..., @_n@ to form the names of the variables.
+newtype ExistsN (n :: Nat) (nm :: Symbol) a = ExistsN [SBV a]
+
+-- | Exactly @n@ universal symbolic variables, used in building quantified constraints. The name attached
+-- will be prefixed in front of @_1@, @_2@, ..., @_n@ to form the names of the variables.
+newtype ForallN (n :: Nat) (nm :: Symbol) a = ForallN [SBV a]
+
+-- | make a quantifier argument in the given state
+mkQArg :: forall m a. (HasKind a, MonadIO m) => State -> Quantifier -> m (SBV a)
+mkQArg st q = do let k = kindOf (Proxy @a)
+                 sv <- liftIO $ quantVar q st k
+                 pure $ SBV $ SVal k (Right (cache (const (pure sv))))
+
+-- | Functions of a single existential
+instance (SymVal a, Constraint m r) => Constraint m (Exists nm a -> r) where
+  mkConstraint st fn = mkQArg st EX >>= mkConstraint st . fn . Exists
+
+-- | Functions of a unique single existential
+instance (SymVal a, Constraint m r, EqSymbolic (SBV a), QuantifiedBool r) => Constraint m (ExistsUnique nm a -> r) where
+  mkConstraint st = mkConstraint st . rewriteExistsUnique
+
+-- | Functions of a number of existentials
+instance (KnownNat n, SymVal a, Constraint m r) => Constraint m (ExistsN n nm a -> r) where
+  mkConstraint st fn = replicateM (intOfProxy (Proxy @n)) (mkQArg st EX) >>= mkConstraint st . fn . ExistsN
+
+-- | Functions of a single universal
+instance (SymVal a, Constraint m r) => Constraint m (Forall nm a -> r) where
+  mkConstraint st fn = mkQArg st ALL >>= mkConstraint st . fn . Forall
+
+-- | Functions of a number of universals
+instance (KnownNat n, SymVal a, Constraint m r) => Constraint m (ForallN n nm a -> r) where
+  mkConstraint st fn = replicateM (intOfProxy (Proxy @n)) (mkQArg st ALL) >>= mkConstraint st . fn . ForallN
+
+-- | Functions of a pair of universals
+instance (SymVal a, SymVal b, Constraint m r) => Constraint m ((Forall na a, Forall nb b) -> r) where
+  mkConstraint st fn = do a <- mkQArg st ALL
+                          b <- mkQArg st ALL
+                          mkConstraint st $ fn (Forall a, Forall b)
+
+-- | Values that we can turn into a lambda abstraction
+class MonadSymbolic m => Lambda m a where
+  mkLambda :: State -> a -> m ()
+
+-- | Base case, simple values
+instance MonadSymbolic m => Lambda m (SBV a) where
+  mkLambda _ out = void $ output out
+
+-- | Functions
+instance (SymVal a, Lambda m r) => Lambda m (SBV a -> r) where
+  mkLambda st fn = mkArg >>= mkLambda st . fn
+    where mkArg = do let k = kindOf (Proxy @a)
+                     sv <- liftIO $ lambdaVar st k
+                     pure $ SBV $ SVal k (Right (cache (const (pure sv))))
+
+-- | A value that can be used as a quantified boolean
+class QuantifiedBool a where
+  -- | Turn a quantified boolean into a regular boolean. That is, this function turns an exists/forall quantified
+  -- formula to a simple boolean that can be used as a regular boolean value. An example is:
+  --
+  -- @
+  --   quantifiedBool $ \\(Forall x) (Exists y) -> y .> (x :: SInteger)
+  -- @
+  --
+  -- is equivalent to `sTrue`. You can think of this function as performing quantifier-elimination: It takes
+  -- a quantified formula, and reduces it to a simple boolean that is equivalent to it, but has no quantifiers.
+  quantifiedBool :: a -> SBool
+
+-- | Base case of quantification, simple booleans
+instance {-# OVERLAPPING #-} QuantifiedBool SBool where
+  quantifiedBool = id
+
+-- | Actions we can do in a context: Either at problem description
+-- time or while we are dynamically querying. 'Symbolic' and 'Query' are
+-- 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 :: QuantifiedBool a => a -> m ()
+
+   -- | Add a soft constraint. The solver will try to satisfy this condition if possible, but won't if it cannot.
+   softConstrain :: QuantifiedBool a => a -> m ()
+
+   -- | Add a named constraint. The name is used in unsat-core extraction.
+   namedConstraint :: QuantifiedBool a => String -> a -> m ()
+
+   -- | Add a constraint, with arbitrary attributes.
+   constrainWithAttribute :: QuantifiedBool a => [(String, String)] -> a -> m ()
+
+   -- | Set info. Example: @setInfo ":status" ["unsat"]@.
+   setInfo :: String -> [String] -> m ()
+
+   -- | Set an option.
+   setOption :: SMTOption -> m ()
+
+   -- | Set the logic.
+   setLogic :: Logic -> m ()
+
+   -- | Set a solver time-out value, in milli-seconds. This function
+   -- essentially translates to the SMTLib call @(set-info :timeout val)@,
+   -- and your backend solver may or may not support it! The amount given
+   -- 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
+
+   -- | Get an internal-variable
+   internalVariable :: Kind -> m (SBV a)
+
+   {-# MINIMAL constrain, softConstrain, namedConstraint, constrainWithAttribute, setOption, contextState, internalVariable #-}
+
+   -- time-out, logic, and info are  simply options in our implementation, so default implementation suffices
+   setTimeOut   = setOption . SetTimeOut
+   setLogic     = setOption . SetLogic
+   setInfo    k = setOption . SetInfo k
+
+-- | Register a type with the solver. Like 'Data.SBV.Core.Model.registerFunction', This is typically not necessary
+-- since SBV will register types as it encounters them automatically. But there are cases
+-- where doing this can explicitly can come handy, typically in query contexts.
+registerType :: forall a m. (MonadIO m, SolverContext m, HasKind a) => Proxy a -> m ()
+registerType _ = do st <- contextState
+                    liftIO $ registerKind st (kindOf (Proxy @a))
+
+-- | Various info we use in recoverKinded value
+newtype SInfo = SInfo { sInfoKinds :: [Kind] }
+
+-- | Turn state into SInfo
+getSInfo :: MonadIO m => State -> m SInfo
+getSInfo st = do rk <- liftIO $ readIORef (rUsedKinds st)
+                 pure $ SInfo { sInfoKinds = Set.toList rk }
+
+-- | A class representing what can be returned from a symbolic computation.
+class Outputtable a where
+  -- | Generalization of 'Data.SBV.output'
+  output :: MonadSymbolic m => a -> m a
+
+instance Outputtable (SBV a) where
+  output i = do
+          outputSVal (unSBV i)
+          pure i
+
+instance Outputtable a => Outputtable [a] where
+  output = mapM output
+
+instance Outputtable () where
+  output = pure
+
+instance (Outputtable a, Outputtable b) => Outputtable (a, b) where
+  output = mlift2 (,) output output
+
+instance (Outputtable a, Outputtable b, Outputtable c) => Outputtable (a, b, c) where
+  output = mlift3 (,,) output output output
+
+instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d) => Outputtable (a, b, c, d) where
+  output = mlift4 (,,,) output output output output
+
+instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e) => Outputtable (a, b, c, d, e) where
+  output = mlift5 (,,,,) output output output output output
+
+instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f) => Outputtable (a, b, c, d, e, f) where
+  output = mlift6 (,,,,,) output output output output output output
+
+instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g) => Outputtable (a, b, c, d, e, f, g) where
+  output = mlift7 (,,,,,,) output output output output output output output
+
+instance (Outputtable a, Outputtable b, Outputtable c, Outputtable d, Outputtable e, Outputtable f, Outputtable g, Outputtable h) => Outputtable (a, b, c, d, e, f, g, h) where
+  output = mlift8 (,,,,,,,) output output output output output output output output
+
+-------------------------------------------------------------------------------
+-- * 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, Typeable a, Arbitrary a) => SymVal a where
+  -- | Generalization of 'Data.SBV.mkSymVal'
+  mkSymVal :: MonadSymbolic m => VarContext -> Maybe String -> m (SBV a)
+
+  -- | Certain types (ADTs) might need to do further initialization.
+  mkSymValInit :: State -> SBV a -> IO ()
+  mkSymValInit _ _ = pure ()
+
+  -- | Turn a literal constant to symbolic
+  literal :: a -> SBV a
+
+  -- | Extract a literal, from a CV representation
+  fromCV :: CV -> a
+
+  -- | Does it concretely satisfy the given predicate?
+  isConcretely :: SBV a -> (a -> Bool) -> Bool
+
+  -- | If bounded, what's the min/max value for this type?
+  -- If the underlying type is bounded, we have a default below. Otherwise it's nothing.
+  minMaxBound :: Maybe (a, a)
+
+  {-# MINIMAL literal, fromCV #-}
+
+  default mkSymVal :: MonadSymbolic m => VarContext -> Maybe String -> m (SBV a)
+  mkSymVal vc mbNm = do st <- symbolicEnv
+                        liftIO $ do v <- SBV <$> svMkSymVar vc (kindOf (undefined :: a)) mbNm st
+                                    mkSymValInit st v
+                                    pure v
+
+  default minMaxBound :: Bounded a => Maybe (a, a)
+  minMaxBound = Just (minBound, maxBound)
+
+  isConcretely s p
+    | Just i <- unliteral s = p i
+    | True                  = False
+
+  -- | Generalization of 'Data.SBV.free'
+  free :: MonadSymbolic m => String -> m (SBV a)
+  free = mkSymVal (NonQueryVar Nothing) . Just
+
+  -- | Generalization of 'Data.SBV.free_'
+  free_ :: MonadSymbolic m => m (SBV a)
+  free_ = mkSymVal (NonQueryVar Nothing) Nothing
+
+  -- | Generalization of 'Data.SBV.mkFreeVars'
+  mkFreeVars :: MonadSymbolic m => Int -> m [SBV a]
+  mkFreeVars n = mapM (const free_) [1 .. n]
+
+  -- | Generalization of 'Data.SBV.symbolic'
+  symbolic :: MonadSymbolic m => String -> m (SBV a)
+  symbolic = free
+
+  -- | Generalization of 'Data.SBV.symbolics'
+  symbolics :: MonadSymbolic m => [String] -> m [SBV a]
+  symbolics = mapM symbolic
+
+  -- | Extract a literal, if the value is concrete
+  unliteral :: SBV a -> Maybe a
+  unliteral (SBV (SVal _ (Left c))) = Just $ fromCV c
+  unliteral _                       = Nothing
+
+  -- | Get the underlying CV, if available
+  unlitCV :: SBV a -> Maybe (Kind, CVal)
+  unlitCV (SBV (SVal _ (Left (CV k v)))) = Just (k, v)
+  unlitCV _                              = Nothing
+
+  -- | Is the symbolic word concrete?
+  isConcrete :: SBV a -> Bool
+  isConcrete (SBV (SVal _ (Left _))) = True
+  isConcrete _                       = False
+
+  -- | Is the symbolic word really symbolic?
+  isSymbolic :: SBV a -> Bool
+  isSymbolic = not . isConcrete
+
+-- | A sequence of instance dictionaries for each type @ai@ in the type list
+-- @[a1,...,an]@
+data SymValInsts as where
+  SymValsNil :: SymValInsts RNil
+  SymValsCons :: SymVal a => SymValInsts as -> SymValInsts (as :> a)
+
+-- | Get the 'Kind' of each type in the type list of a 'SymValInsts' sequence
+symValKinds :: SymValInsts as -> [Kind]
+symValKinds = rlist2list . helper where
+  helper :: SymValInsts as -> RList Kind
+  helper SymValsNil = RNil
+  helper insts@(SymValsCons insts') = helper insts' :> kindOf (headPrx insts)
+  headPrx :: SymValInsts (bs :> b) -> Proxy b
+  headPrx _ = Proxy
+
+-- | A 'SymVals' is a list of types that all satisfy 'SymVal'
+class SymVals as where
+  symValInsts :: SymValInsts as
+
+instance SymVals RNil where
+  symValInsts = SymValsNil
+
+instance (SymVal a, SymVals as) => SymVals (as :> a) where
+  symValInsts = SymValsCons symValInsts
+
+instance (Random a, SymVal a) => Random (SBV a) where
+  randomR (l, h) g = case (unliteral l, unliteral h) of
+                       (Just lb, Just hb) -> let (v, g') = randomR (lb, hb) g in (literal (v :: a), g')
+                       _                  -> error "SBV.Random: Cannot generate random values with symbolic bounds"
+  random         g = let (v, g') = random g in (literal (v :: a) , g')
+
+-- | 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.
+--
+-- NB. Equality is a built-in notion in SMTLib, and is object-equality. While this mostly matches Haskell's
+-- notion of equality, the correspondence isn't exact. This mostly shows up in containers with floats inside,
+-- such as sequences of floats, sets of doubles, and arrays of doubles. While SBV tries to maintain Haskell
+-- semantics, it does resort to container equality for compound types. For instance, for an IEEE-float,
+-- -0 == 0. But for an SMTLib sequence, equals is done over objects. i.e., @[0] == [-0]@ in Haskell, but
+-- @literal [0] ./= literal [-0]@ when used as SMTLib sequences. The rabbit-hole goes deep here, especially
+-- when @NaN@ is involved, which does not compare equal to itself per IEEE-semantics.
+--
+-- If you are not using floats, then you can ignore all this. If you do, then SBV will do the right thing for
+-- them when checking equality directly, but not when you use containers with floating-point elements. In the
+-- latter case, object-equality will be used.
+--
+-- Minimal complete definition: None, if the type is instance of @Generic@. Otherwise '(.==)'.
+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
+
+  -- | Returns (symbolic) `sTrue` if all the elements of the given list are different. The second
+  -- list contains exceptions, i.e., if an element belongs to that set, it will be considered
+  -- distinct regardless of repetition.
+  distinctExcept :: [a] -> [a] -> SBool
+
+  -- | Returns (symbolic) 'sTrue' if all the elements of the given list are the same.
+  allEqual :: [a] -> SBool
+
+  -- | Symbolic membership test.
+  sElem    :: a -> [a] -> SBool
+
+  -- | Symbolic negated membership test.
+  sNotElem :: a -> [a] -> SBool
+
+  x ./=  y = sNot (x .==  y)
+  x .=== y = x .== y
+  x ./== y = sNot (x .=== y)
+
+  allEqual []     = sTrue
+  allEqual (x:xs) = sAll (x .==) xs
+
+  -- Default implementation of 'distinct'. Note that we override
+  -- this method for the base types to generate better code.
+  distinct []     = sTrue
+  distinct (x:xs) = sAll (x ./=) xs .&& distinct xs
+
+  -- Default implementation of 'distinctExcept'. Note that we override
+  -- this method for the base types to generate better code.
+  distinctExcept es ignored = go es
+    where isIgnored = (`sElem` ignored)
+
+          go []     = sTrue
+          go (x:xs) = let xOK  = isIgnored x .|| sAll (\y -> isIgnored y .|| x ./= y) xs
+                      in xOK .&& go xs
+
+  x `sElem`    xs = sAny (.== x) xs
+  x `sNotElem` xs = sNot (x `sElem` xs)
+
+  -- Default implementation for '(.==)' if the type is 'Generic'
+  default (.==) :: (G.Generic a, GEqSymbolic (G.Rep a)) => a -> a -> SBool
+  (.==) = symbolicEqDefault
+
+-- | Default implementation of symbolic equality, when the underlying type is generic
+-- Not exported, used with automatic deriving.
+symbolicEqDefault :: (G.Generic a, GEqSymbolic (G.Rep a)) => a -> a -> SBool
+symbolicEqDefault x y = symbolicEq (G.from x) (G.from y)
+
+-- | Not exported, used for implementing generic equality.
+class GEqSymbolic f where
+  symbolicEq :: f a -> f a -> SBool
+
+{-
+ - N.B. A V1 instance like the below would be wrong!
+ - Why? Because in SBV, we use empty data to mean "uninterpreted" sort; not
+ - something that has no constructors. Perhaps that was a bad design
+ - decision. So, do not allow equality checking of such values.
+instance GEqSymbolic V1 where
+  symbolicEq _ _ = sTrue
+-}
+
+instance GEqSymbolic U1 where
+  symbolicEq _ _ = sTrue
+
+instance (EqSymbolic c) => GEqSymbolic (K1 i c) where
+  symbolicEq (K1 x) (K1 y) = x .== y
+
+instance (GEqSymbolic f) => GEqSymbolic (M1 i c f) where
+  symbolicEq (M1 x) (M1 y) = symbolicEq x y
+
+instance (GEqSymbolic f, GEqSymbolic g) => GEqSymbolic (f :*: g) where
+  symbolicEq (x1 :*: y1) (x2 :*: y2) = symbolicEq x1 x2 .&& symbolicEq y1 y2
+
+instance (GEqSymbolic f, GEqSymbolic g) => GEqSymbolic (f :+: g) where
+  symbolicEq (L1 l) (L1 r) = symbolicEq l r
+  symbolicEq (R1 l) (R1 r) = symbolicEq l r
+  symbolicEq (L1 _) (R1 _) = sFalse
+  symbolicEq (R1 _) (L1 _) = sFalse
+
+-- We don't want to do a generic Num a => Num (SBV a) instance; since that would be dangerous. Liftings
+-- would only work for types we already handle. If a user defines his own type and makes an instance
+-- of it, it would do the wrong thing. See https://github.com/LeventErkok/sbv/issues/706 for a discussion.
+-- So, we have to declare the instances individually. I played around doing this via iso-deriving and
+-- other generic mechanisms, but failed to do so. The CPP solution here is crude, but it avoids the
+-- code duplication.
+#define MKSNUM(CSTR, TYPE, KIND)                                                        \
+instance CSTR => Num TYPE where {                                                       \
+  fromInteger i  = SBV $ SVal KIND $ Left $ mkConstCV KIND (fromIntegral i :: Integer); \
+  SBV a + SBV b  = SBV $ a `svPlus`  b;                                                 \
+  SBV a * SBV b  = SBV $ a `svTimes` b;                                                 \
+  SBV a - SBV b  = SBV $ a `svMinus` b;                                                 \
+  abs    (SBV a) = SBV $ svAbs    a;                                                    \
+  signum (SBV a) = SBV $ svSignum a;                                                    \
+  negate (SBV a) = SBV $ svUNeg   a;                                                    \
+}
+
+-- Derive basic instances we need. NB. We don't give the SRational instance here. It's handled
+-- in Data/SBV/Rational due to representation issues.
+MKSNUM((),                 SInteger,               KUnbounded)
+MKSNUM((),                 SWord8,                 (KBounded False  8))
+MKSNUM((),                 SWord16,                (KBounded False 16))
+MKSNUM((),                 SWord32,                (KBounded False 32))
+MKSNUM((),                 SWord64,                (KBounded False 64))
+MKSNUM((),                 SInt8,                  (KBounded True   8))
+MKSNUM((),                 SInt16,                 (KBounded True  16))
+MKSNUM((),                 SInt32,                 (KBounded True  32))
+MKSNUM((),                 SInt64,                 (KBounded True  64))
+MKSNUM((),                 SFloat,                 KFloat)
+MKSNUM((),                 SDouble,                KDouble)
+MKSNUM((),                 SReal,                  KReal)
+MKSNUM((KnownNat n),       (SWord n),              (KBounded False (intOfProxy (Proxy @n))))
+MKSNUM((KnownNat n),       (SInt  n),              (KBounded True  (intOfProxy (Proxy @n))))
+MKSNUM((ValidFloat eb sb), (SFloatingPoint eb sb), (KFP (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))))
+#undef MKSNUM
+
+-- | Extract a portion of bits to form a smaller bit-vector.
+bvExtract :: forall i j n bv proxy. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                                    , KnownNat i
+                                    , KnownNat j
+                                    , i + 1 <= n
+                                    , j <= i
+                                    , BVIsNonZero (i - j + 1)
+                                    ) => proxy i                -- ^ @i@: Start position, numbered from @n-1@ to @0@
+                                      -> proxy j                -- ^ @j@: End position, numbered from @n-1@ to @0@, @j <= i@ must hold
+                                      -> SBV (bv n)             -- ^ Input bit vector of size @n@
+                                      -> SBV (bv (i - j + 1))   -- ^ Output is of size @i - j + 1@
+bvExtract start end = SBV . svExtract i j . unSBV
+   where i  = fromIntegral (natVal start)
+         j  = fromIntegral (natVal end)
+
+-- | Join two bit-vectors.
+(#) :: ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+       , KnownNat m, BVIsNonZero m, SymVal (bv m)
+       ) => SBV (bv n)                     -- ^ First input, of size @n@, becomes the left side
+         -> SBV (bv m)                     -- ^ Second input, of size @m@, becomes the right side
+         -> SBV (bv (n + m))               -- ^ Concatenation, of size @n+m@
+n # m = SBV $ svJoin (unSBV n) (unSBV m)
+infixr 5 #
+
+-- | Drop bits from the top of a bit-vector.
+bvDrop :: forall i n m bv proxy. ( KnownNat n, BVIsNonZero n
+                                 , KnownNat i
+                                 , i + 1 <= n
+                                 , i + m - n <= 0
+                                 , BVIsNonZero (n - i)
+                                 ) => proxy i                    -- ^ @i@: Number of bits to drop. @i < n@ must hold.
+                                   -> SBV (bv n)                 -- ^ Input, of size @n@
+                                   -> SBV (bv m)                 -- ^ Output, of size @m@. @m = n - i@ holds.
+bvDrop i = SBV . svExtract start 0 . unSBV
+  where nv    = intOfProxy (Proxy @n)
+        start = nv - fromIntegral (natVal i) - 1
+
+-- | Take bits from the top of a bit-vector.
+bvTake :: forall i n bv proxy. ( KnownNat n, BVIsNonZero n
+                               , KnownNat i, BVIsNonZero i
+                               , i <= n
+                               ) => proxy i                  -- ^ @i@: Number of bits to take. @0 < i <= n@ must hold.
+                                 -> SBV (bv n)               -- ^ Input, of size @n@
+                                 -> SBV (bv i)               -- ^ Output, of size @i@
+bvTake i = SBV . svExtract start end . unSBV
+  where nv    = intOfProxy (Proxy @n)
+        start = nv - 1
+        end   = start - fromIntegral (natVal i) + 1
+
+-- | A class of values that can be skolemized. Note that we don't export this class. Use
+-- the 'skolemize' function instead.
+class Skolemize a where
+  type SkolemsTo a :: Type
+  skolem :: String -> [(SVal, String)] -> a -> SkolemsTo a
+
+  -- | Skolemization. For any formula, skolemization gives back an equisatisfiable formula that
+  -- has no existential quantifiers in it. You have to provide enough names for all the
+  -- existentials in the argument. (Extras OK, so you can pass an infinite list if you like.)
+  -- The names should be distinct, and also different from any other uninterpreted name
+  -- you might have elsewhere.
+  skolemize :: (Constraint Symbolic (SkolemsTo a), Skolemize a) => a -> SkolemsTo a
+  skolemize = skolem "" []
+
+  -- | If you use the same names for skolemized arguments in different functions, they will
+  -- collide; which is undesirable. Unfortunately there's no easy way for SBV to detect this.
+  -- In such cases, use 'taggedSkolemize' to add a scope to the skolem-function names generated.
+  taggedSkolemize :: (Constraint Symbolic (SkolemsTo a), Skolemize a) => String -> a -> SkolemsTo a
+  taggedSkolemize scope = skolem (scope ++ "_") []
+
+-- | Base case; pure symbolic values
+instance Skolemize (SBV a) where
+  type SkolemsTo (SBV a) = SBV a
+  skolem _ _ = id
+
+-- | Skolemize over a universal quantifier
+instance (KnownSymbol nm, Skolemize r) => Skolemize (Forall nm a -> r) where
+  type SkolemsTo (Forall nm a -> r) = Forall nm a -> SkolemsTo r
+  skolem scope args f arg@(Forall a) = skolem scope (args ++ [(unSBV a, symbolVal (Proxy @nm))]) (f arg)
+
+-- | Skolemize over a o pair universal quantifier
+instance (KnownSymbol na, KnownSymbol nb, Skolemize r) => Skolemize ((Forall na a, Forall nb b) -> r) where
+  type SkolemsTo ((Forall na a, Forall nb b) -> r) = (Forall na a, Forall nb b) -> SkolemsTo r
+  skolem scope args f = uncurry (skolem scope args (curry f))
+
+-- | Skolemize over a number of universal quantifiers
+instance (KnownSymbol nm, Skolemize r) => Skolemize (ForallN n nm a -> r) where
+  type SkolemsTo (ForallN n nm a -> r) = ForallN n nm a -> SkolemsTo r
+  skolem scope args f arg@(ForallN xs) = skolem scope (args ++ zipWith grab xs [(1::Int)..]) (f arg)
+    where pre = symbolVal (Proxy @nm)
+          grab x i = (unSBV x, pre ++ "_" ++ show i)
+
+-- | Skolemize over an existential quantifier
+instance (HasKind a, KnownSymbol nm, Skolemize r) => Skolemize (Exists nm a -> r) where
+  type SkolemsTo (Exists nm a -> r) = SkolemsTo r
+  skolem scope args f = skolem scope args (f (Exists skolemized))
+    where skolemized = SBV $ svUninterpretedNamedArgs (kindOf (Proxy @a)) (UIGiven (scope ++ symbolVal (Proxy @nm))) (UINone True) args
+
+-- | Skolemize over a o pair existential quantifier
+instance (HasKind a, HasKind b, KnownSymbol na, KnownSymbol nb, Skolemize r) => Skolemize ((Exists na a, Exists nb b) -> r) where
+  type SkolemsTo ((Exists na a, Exists nb b) -> r) = SkolemsTo r
+  skolem scope args = skolem scope args . curry
+
+-- | Skolemize over a number of existential quantifiers
+instance (HasKind a, KnownNat n, KnownSymbol nm, Skolemize r) => Skolemize (ExistsN n nm a -> r) where
+  type SkolemsTo (ExistsN n nm a -> r) = SkolemsTo r
+  skolem scope args f = skolem scope args (f (ExistsN skolemized))
+    where need   = intOfProxy (Proxy @n)
+          prefix = symbolVal (Proxy @nm)
+          fs     = [prefix ++ "_" ++ show i | i <- [1 .. need]]
+          skolemized = [SBV $ svUninterpretedNamedArgs (kindOf (Proxy @a)) (UIGiven (scope ++ n)) (UINone True) args | n <- fs]
+
+-- | Skolemize over a unique existential quantifier
+instance (  HasKind a
+          , EqSymbolic (SBV a)
+          , KnownSymbol nm
+          , QuantifiedBool r
+          , Skolemize (Forall (AppendSymbol nm "_eu1") a -> Forall (AppendSymbol nm "_eu2") a -> SBool)
+         ) => Skolemize (ExistsUnique nm a -> r) where
+  type SkolemsTo (ExistsUnique nm a -> r) =  Forall (AppendSymbol nm "_eu1") a
+                                          -> Forall (AppendSymbol nm "_eu2") a
+                                          -> SBool
+  skolem scope args f = skolem scope args (rewriteExistsUnique f (Exists skolemized))
+    where skolemized = SBV $ svUninterpretedNamedArgs (kindOf (Proxy @a)) (UIGiven (scope ++ symbolVal (Proxy @nm))) (UINone True) args
+
+-- | Class of things that we can logically negate
+class QNot a where
+  type NegatesTo a :: Type
+  -- | Negation of a quantified formula. This operation essentially lifts 'sNot' to quantified formulae.
+  -- Note that you can achieve the same using @'sNot' . 'quantifiedBool'@, but that will hide the
+  -- quantifiers, so prefer this version if you want to keep them around.
+  qNot :: a -> NegatesTo a
+
+-- | Base case; pure symbolic boolean
+instance QNot SBool where
+  type NegatesTo SBool = SBool
+  qNot = sNot
+
+-- | Negate over a universal quantifier. Switches to existential.
+instance QNot r => QNot (Forall nm a -> r) where
+  type NegatesTo (Forall nm a -> r) = Exists nm a -> NegatesTo r
+  qNot f (Exists a) = qNot (f (Forall a))
+
+-- | Negate over a number of universal quantifiers
+instance QNot r => QNot (ForallN nm n a -> r) where
+  type NegatesTo (ForallN nm n a -> r) = ExistsN nm n a -> NegatesTo r
+  qNot f (ExistsN xs) = qNot (f (ForallN xs))
+
+-- | Negate over an existential quantifier. Switches to universal.
+instance QNot r => QNot (Exists nm a -> r) where
+  type NegatesTo (Exists nm a -> r) = Forall nm a -> NegatesTo r
+  qNot f (Forall a) = qNot (f (Exists a))
+
+-- | Negate over a number of existential quantifiers
+instance QNot r => QNot (ExistsN nm n a -> r) where
+  type NegatesTo (ExistsN nm n a -> r) = ForallN nm n a -> NegatesTo r
+  qNot f (ForallN xs) = qNot (f (ExistsN xs))
+
+-- | Negate over a unique existential quantifier
+instance (QNot r, QuantifiedBool r, EqSymbolic (SBV a)) => QNot (ExistsUnique nm a -> r) where
+  type NegatesTo (ExistsUnique nm a -> r) =  Forall nm a
+                                          -> Exists (AppendSymbol nm "_eu1") a
+                                          -> Exists (AppendSymbol nm "_eu2") a
+                                          -> SBool
+  qNot = qNot . rewriteExistsUnique
+
+-- | Negate over a pair of universals
+instance QNot r => QNot ((Forall na a, Forall nb b) -> r) where
+  type NegatesTo ((Forall na a, Forall nb b) -> r) = (Exists na a, Exists nb b) -> NegatesTo r
+  qNot f (Exists a, Exists b) = qNot (f (Forall a, Forall b))
+
+-- | Negate over a pair of existentials
+instance QNot r => QNot ((Exists na a, Exists nb b) -> r) where
+  type NegatesTo ((Exists na a, Exists nb b) -> r) = (Forall na a, Forall nb b) -> NegatesTo r
+  qNot f (Forall a, Forall b) = qNot (f (Exists a, Exists b))
+
+-- | Get rid of exists unique.
+rewriteExistsUnique :: ( QuantifiedBool b                 -- If b can be turned into a boolean
+                       , EqSymbolic (SBV a)               -- If we can do equality on symbolic a's
+                       )                                  -- THEN
+                    => (ExistsUnique nm a -> b)           -- Given an unique-existential, we can
+                    -> Exists nm a                        -- Turn it into an existential
+                    -> Forall (AppendSymbol nm "_eu1") a  -- A universal
+                    -> Forall (AppendSymbol nm "_eu2") a  -- Another universal
+                    -> SBool                                  -- Making sure given holds, and if both univers hold, they're the same
+rewriteExistsUnique f (Exists x) (Forall x1) (Forall x2) = fx .&& unique
+  where fx    = quantifiedBool $ f (ExistsUnique x)
+        fx1   = f (ExistsUnique x1)
+        fx2   = f (ExistsUnique x2)
+
+        bothHolds  = quantifiedBool fx1 .&& quantifiedBool fx2
+        mustEqual  = x1 .== x2
+        unique     = bothHolds .=> mustEqual
diff --git a/Data/SBV/Core/Floating.hs b/Data/SBV/Core/Floating.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Floating.hs
@@ -0,0 +1,773 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Floating
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implementation of floating-point operations mapping to SMT-Lib2 floats
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DefaultSignatures    #-}
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE InstanceSigs         #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE TypeOperators        #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.Floating (
+         IEEEFloating(..), IEEEFloatConvertible(..)
+       , sFloatAsSWord32, sDoubleAsSWord64, sFloatingPointAsSWord
+       , sWord32AsSFloat, sWord64AsSDouble, sWordAsSFloatingPoint
+       , blastSFloat, blastSDouble,  blastSFloatingPoint
+       , sFloatAsComparableSWord32,  sDoubleAsComparableSWord64,  sFloatingPointAsComparableSWord
+       , sComparableSWord32AsSFloat, sComparableSWord64AsSDouble, sComparableSWordAsSFloatingPoint
+       , svFloatingPointAsSWord
+       ) where
+
+import Control.Monad (when, guard)
+
+import Data.Bits (testBit)
+import Data.Int  (Int8,  Int16,  Int32,  Int64)
+import Data.Word (Word8, Word16, Word32, Word64)
+
+import Data.Proxy
+
+import Data.SBV.Core.AlgReals (isExactRational)
+import Data.SBV.Core.Sized
+import Data.SBV.Core.SizedFloats hiding (fpIsNaN, fpIsZero)
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Model
+import Data.SBV.Core.Symbolic (addSValOptGoal)
+
+import Data.SBV.Utils.Numeric
+
+import GHC.TypeLits
+
+import LibBF
+
+import Data.SBV.Core.Operations
+
+-- | 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
+-- not concretely evaluate these, but rather pass down to the SMT solver.
+class (SymVal a, RealFloat a) => IEEEFloating a where
+  -- | Compute the floating point absolute value.
+  fpAbs             ::                  SBV a -> SBV a
+
+  -- | Compute the unary negation. Note that @0 - x@ is not equivalent to @-x@ for floating-point, since @-0@ and @0@ are different.
+  fpNeg             ::                  SBV a -> SBV a
+
+  -- | Add two floating point values, using the given rounding mode
+  fpAdd             :: SRoundingMode -> SBV a -> SBV a -> SBV a
+
+  -- | Subtract two floating point values, using the given rounding mode
+  fpSub             :: SRoundingMode -> SBV a -> SBV a -> SBV a
+
+  -- | Multiply two floating point values, using the given rounding mode
+  fpMul             :: SRoundingMode -> SBV a -> SBV a -> SBV a
+
+  -- | Divide two floating point values, using the given rounding mode
+  fpDiv             :: SRoundingMode -> SBV a -> SBV a -> SBV a
+
+  -- | Fused-multiply-add three floating point values, using the given rounding mode. @fpFMA x y z = x*y+z@ but with only
+  -- one rounding done for the whole operation; not two. Note that we will never concretely evaluate this function since
+  -- Haskell lacks an FMA implementation.
+  fpFMA             :: SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
+
+  -- | Compute the square-root of a float, using the given rounding mode
+  fpSqrt            :: SRoundingMode -> SBV a -> SBV a
+
+  -- | Compute the remainder: @x - y * n@, where @n@ is the truncated integer nearest to x/y. The rounding mode
+  -- is implicitly assumed to be @RoundNearestTiesToEven@.
+  fpRem             ::                  SBV a -> SBV a -> SBV a
+
+  -- | Round to the nearest integral value, using the given rounding mode.
+  fpRoundToIntegral :: SRoundingMode -> SBV a -> SBV a
+
+  -- | Compute the minimum of two floats, respects @infinity@ and @NaN@ values
+  fpMin             ::                  SBV a -> SBV a -> SBV a
+
+  -- | Compute the maximum of two floats, respects @infinity@ and @NaN@ values
+  fpMax             ::                  SBV a -> SBV a -> SBV a
+
+  -- | Are the two given floats exactly the same. That is, @NaN@ will compare equal to itself, @+0@ will /not/ compare
+  -- equal to @-0@ etc. This is the object level equality, as opposed to the semantic equality. (For the latter, just use '.=='.)
+  fpIsEqualObject   ::                  SBV a -> SBV a -> SBool
+
+  -- | Is the floating-point number a normal value. (i.e., not denormalized.)
+  fpIsNormal :: SBV a -> SBool
+
+  -- | Is the floating-point number a subnormal value. (Also known as denormal.)
+  fpIsSubnormal :: SBV a -> SBool
+
+  -- | Is the floating-point number 0? (Note that both +0 and -0 will satisfy this predicate.)
+  fpIsZero :: SBV a -> SBool
+
+  -- | Is the floating-point number infinity? (Note that both +oo and -oo will satisfy this predicate.)
+  fpIsInfinite :: SBV a -> SBool
+
+  -- | Is the floating-point number a NaN value?
+  fpIsNaN ::  SBV a -> SBool
+
+  -- | Is the floating-point number negative? Note that -0 satisfies this predicate but +0 does not.
+  fpIsNegative :: SBV a -> SBool
+
+  -- | Is the floating-point number positive? Note that +0 satisfies this predicate but -0 does not.
+  fpIsPositive :: SBV a -> SBool
+
+  -- | Is the floating point number -0?
+  fpIsNegativeZero :: SBV a -> SBool
+
+  -- | Is the floating point number +0?
+  fpIsPositiveZero :: SBV a -> SBool
+
+  -- | Is the floating-point number a regular floating point, i.e., not NaN, nor +oo, nor -oo. Normals or denormals are allowed.
+  fpIsPoint :: SBV a -> SBool
+
+  -- Default definitions. Minimal complete definition: None! All should be taken care by defaults
+  -- Note that we never evaluate FMA concretely, as there's no fma operator in Haskell
+  fpAbs              = lift1  FP_Abs             (Just abs)                Nothing
+  fpNeg              = lift1  FP_Neg             (Just negate)             Nothing
+  fpAdd              = lift2  FP_Add             (Just (+))                . Just
+  fpSub              = lift2  FP_Sub             (Just (-))                . Just
+  fpMul              = lift2  FP_Mul             (Just (*))                . Just
+  fpDiv              = lift2  FP_Div             (Just (/))                . Just
+  fpFMA              = lift3  FP_FMA             Nothing                   . Just
+  fpSqrt             = lift1  FP_Sqrt            (Just sqrt)               . Just
+  fpRem              = lift2  FP_Rem             (Just fpRemH)             Nothing
+  fpRoundToIntegral  = lift1  FP_RoundToIntegral (Just fpRoundToIntegralH) . Just
+  fpMin              = liftMM FP_Min             (Just fpMinH)             Nothing
+  fpMax              = liftMM FP_Max             (Just fpMaxH)             Nothing
+  fpIsEqualObject    = lift2B FP_ObjEqual        (Just fpIsEqualObjectH)   Nothing
+  fpIsNormal         = lift1B FP_IsNormal        fpIsNormalizedH
+  fpIsSubnormal      = lift1B FP_IsSubnormal     isDenormalized
+  fpIsZero           = lift1B FP_IsZero          (== 0)
+  fpIsInfinite       = lift1B FP_IsInfinite      isInfinite
+  fpIsNaN            = lift1B FP_IsNaN           isNaN
+  fpIsNegative       = lift1B FP_IsNegative      (\x -> x < 0 ||       isNegativeZero x)
+  fpIsPositive       = lift1B FP_IsPositive      (\x -> x >= 0 && not (isNegativeZero x))
+  fpIsNegativeZero x = fpIsZero x .&& fpIsNegative x
+  fpIsPositiveZero x = fpIsZero x .&& fpIsPositive x
+  fpIsPoint        x = sNot (fpIsNaN x .|| fpIsInfinite x)
+
+-- | SFloat instance
+instance IEEEFloating Float
+
+-- | SDouble instance
+instance IEEEFloating Double
+
+-- | Conversion to and from floats
+class SymVal a => IEEEFloatConvertible a where
+  -- | Convert from an IEEE74 single precision float.
+  fromSFloat :: SRoundingMode -> SFloat -> SBV a
+  fromSFloat = genericFromFloat
+
+  -- | Convert to an IEEE-754 Single-precision float.
+  toSFloat :: SRoundingMode -> SBV a -> SFloat
+
+  -- default definition if we have an integral like
+  default toSFloat :: Integral a => SRoundingMode -> SBV a -> SFloat
+  toSFloat = genericToFloat (onlyWhenRNE (Just . fromRational . fromIntegral))
+
+  -- | Convert from an IEEE74 double precision float.
+  fromSDouble :: SRoundingMode -> SDouble -> SBV a
+  fromSDouble = genericFromFloat
+
+  -- | Convert to an IEEE-754 Double-precision float.
+  toSDouble :: SRoundingMode -> SBV a -> SDouble
+
+  -- default definition if we have an integral like
+  default toSDouble :: Integral a => SRoundingMode -> SBV a -> SDouble
+  toSDouble = genericToFloat (onlyWhenRNE (Just . fromRational . fromIntegral))
+
+  -- | Convert from an arbitrary floating point.
+  fromSFloatingPoint :: ValidFloat eb sb => SRoundingMode -> SFloatingPoint eb sb -> SBV a
+  fromSFloatingPoint = genericFromFloat
+
+  -- | Convert to an arbitrary floating point.
+  toSFloatingPoint :: ValidFloat eb sb => SRoundingMode -> SBV a -> SFloatingPoint eb sb
+
+  -- -- default definition if we have an integral like
+  default toSFloatingPoint :: (Integral a, ValidFloat eb sb) => SRoundingMode -> SBV a -> SFloatingPoint eb sb
+  toSFloatingPoint = genericToFloat (const (Just . fromRational . fromIntegral))
+
+-- Run the function if the conversion is in RNE. Otherwise return Nothing.
+onlyWhenRNE :: (a -> Maybe b) -> RoundingMode -> a -> Maybe b
+onlyWhenRNE f RoundNearestTiesToEven v = f v
+onlyWhenRNE _ _                      _ = Nothing
+
+-- | 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])
+
+-- | A generic to-float converter, which will constant-fold as necessary, but only in the sRNE mode for regular floats.
+genericToFloat :: forall a r. (IEEEFloatConvertible a, IEEEFloating r)
+               => (RoundingMode -> 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 crm <- unliteral rm, Just result <- converter crm 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 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
+
+-- 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 (onlyWhenRNE (Just . fp2fp))
+
+  toSFloatingPoint rm f = toSFloatingPoint rm $ toSDouble rm f
+
+  fromSFloat  _  f = f
+  fromSDouble rm f
+    | Just RoundNearestTiesToEven <- unliteral rm
+    , Just fv                     <- unliteral f
+    = literal (fp2fp fv)
+    | True
+    = genericFromFloat rm f
+
+instance IEEEFloatConvertible Double where
+  toSFloat      = genericToFloat (onlyWhenRNE (Just . fp2fp))
+  toSDouble _ d = d
+
+  toSFloatingPoint rm sd
+    | Just d <- unliteral sd, Just brm <- rmToRM rm
+    = literal $ FloatingPoint $ FP ei si $ fst (bfRoundFloat (mkBFOpts ei si brm) (bfFromDouble d))
+    | True
+    = res
+    where (k, ei, si) = case kindOf res of
+                         kr@(KFP eb sb) -> (kr, eb, sb)
+                         kr             -> error $ "Unexpected kind in toSFloatingPoint: " ++ show (kr, rm, sd)
+          res = SBV $ SVal k $ Right $ cache r
+          r st = do msv <- sbvToSV st rm
+                    xsv <- sbvToSV st sd
+                    newExpr st k (SBVApp (IEEEFP (FP_Cast KDouble k msv)) [xsv])
+
+  fromSDouble _  d = d
+  fromSFloat  rm d
+    | Just RoundNearestTiesToEven <- unliteral rm
+    , Just dv                     <- unliteral d
+    = literal (fp2fp dv)
+    | True
+    = genericFromFloat rm d
+
+convertWhenExactRational :: Fractional a => AlgReal -> Maybe a
+convertWhenExactRational r
+  | isExactRational r = Just (fromRational (toRational r))
+  | True              = Nothing
+
+-- For AlgReal; be careful to only process exact rationals concretely
+instance IEEEFloatConvertible AlgReal where
+  toSFloat         = genericToFloat (onlyWhenRNE convertWhenExactRational)
+  toSDouble        = genericToFloat (onlyWhenRNE convertWhenExactRational)
+  toSFloatingPoint = genericToFloat (onlyWhenRNE convertWhenExactRational)
+
+-- Arbitrary floats can handle all rounding modes in concrete mode
+instance ValidFloat eb sb => IEEEFloatConvertible (FloatingPoint eb sb) where
+  toSFloat rm i
+    | Just (FloatingPoint (FP _ _ v)) <- unliteral i, Just brm <- rmToRM rm
+    = literal $ fp2fp $ fst (bfToDouble brm (fst (bfRoundFloat (mkBFOpts ei si brm) v)))
+    | True
+    = genericToFloat (\_ _ -> Nothing) rm i
+    where ei = intOfProxy (Proxy @eb)
+          si = intOfProxy (Proxy @sb)
+
+  fromSFloat rm i
+    | Just f <- unliteral i, Just brm <- rmToRM rm
+    = literal $ FloatingPoint $ FP ei si $ fst (bfRoundFloat (mkBFOpts ei si brm) (bfFromDouble (fp2fp f :: Double)))
+    | True
+    = genericFromFloat rm i
+    where ei = intOfProxy (Proxy @eb)
+          si = intOfProxy (Proxy @sb)
+
+  toSDouble rm i
+    | Just (FloatingPoint (FP _ _ v)) <- unliteral i, Just brm <- rmToRM rm
+    = literal $ fst (bfToDouble brm (fst (bfRoundFloat (mkBFOpts ei si brm) v)))
+    | True
+    = genericToFloat (\_ _ -> Nothing) rm i
+    where ei = intOfProxy (Proxy @eb)
+          si = intOfProxy (Proxy @sb)
+
+  fromSDouble rm i
+    | Just f <- unliteral i, Just brm <- rmToRM rm
+    = literal $ FloatingPoint $ FP ei si $ fst (bfRoundFloat (mkBFOpts ei si brm) (bfFromDouble f))
+    | True
+    = genericFromFloat rm i
+    where ei = intOfProxy (Proxy @eb)
+          si = intOfProxy (Proxy @sb)
+
+  toSFloatingPoint :: forall eb1 sb1. (ValidFloat eb sb, ValidFloat eb1 sb1) => SRoundingMode -> SBV (FloatingPoint eb sb) -> SFloatingPoint eb1 sb1
+  toSFloatingPoint rm i
+    | Just (FloatingPoint (FP _ _ v)) <- unliteral i, Just brm <- rmToRM rm
+    = literal $ FloatingPoint $ FP ei si $ fst (bfRoundFloat (mkBFOpts ei si brm) v)
+    | True
+    = genericToFloat (\_ _ -> Nothing) rm i
+    where ei = intOfProxy (Proxy @eb1)
+          si = intOfProxy (Proxy @sb1)
+
+  -- From and To are the same when the source is an arbitrary float!
+  fromSFloatingPoint = toSFloatingPoint
+
+-- | Is this RM safe to concretely calculate with? OK if there's no RM for this op, or if it is RNE
+safeRM :: Maybe SRoundingMode -> Bool
+safeRM Nothing                                                   = True
+safeRM (Just srm) | Just RoundNearestTiesToEven <- unliteral srm = True
+                  | True                                         = False
+
+-- | 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)
+concEval1 mbOp mbRm a = do op <- mbOp
+                           v  <- unliteral a
+                           guard (safeRM mbRm)
+                           pure $ literal (op v)
+
+-- | Concretely evaluate two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
+concEval2 :: SymVal a => Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> Maybe (SBV a)
+concEval2 mbOp mbRm a b = do op <- mbOp
+                             v1 <- unliteral a
+                             v2 <- unliteral b
+                             guard (safeRM mbRm)
+                             pure $ literal (v1 `op` v2)
+
+-- | Concretely evaluate a bool producing two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
+concEval2B :: SymVal a => Maybe (a -> a -> Bool) -> Maybe SRoundingMode -> SBV a -> SBV a -> Maybe SBool
+concEval2B mbOp mbRm a b = do op <- mbOp
+                              v1 <- unliteral a
+                              v2 <- unliteral b
+                              guard (safeRM mbRm)
+                              pure $ literal (v1 `op` v2)
+
+-- | Concretely evaluate two arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
+concEval3 :: SymVal a => Maybe (a -> a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a -> Maybe (SBV a)
+concEval3 mbOp mbRm a b c = do op <- mbOp
+                               v1 <- unliteral a
+                               v2 <- unliteral b
+                               v3 <- unliteral c
+                               guard (safeRM mbRm)
+                               pure $ literal (op v1 v2 v3)
+
+-- | Add the converted rounding mode if given as an argument
+addRM :: State -> Maybe SRoundingMode -> [SV] -> IO [SV]
+addRM _  Nothing   as = pure as
+addRM st (Just rm) as = do svm <- sbvToSV st rm
+                           pure (svm : as)
+
+-- | Lift a 1 arg FP-op
+lift1 :: SymVal a => FPOp -> Maybe (a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a
+lift1 w mbOp mbRm a
+  | Just cv <- concEval1 mbOp mbRm a
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do sva  <- sbvToSV st a
+                  args <- addRM st mbRm [sva]
+                  newExpr st k (SBVApp (IEEEFP w) args)
+
+-- | Lift an FP predicate
+lift1B :: SymVal a => FPOp -> (a -> Bool) -> SBV a -> SBool
+lift1B w f a
+   | Just v <- unliteral a = literal $ f v
+   | True                  = SBV $ SVal KBool $ Right $ cache r
+   where r st = do sva <- sbvToSV st a
+                   newExpr st KBool (SBVApp (IEEEFP w) [sva])
+
+
+-- | Lift a 2 arg FP-op
+lift2 :: SymVal a => FPOp -> Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a
+lift2 w mbOp mbRm a b
+  | Just cv <- concEval2 mbOp mbRm a b
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do sva  <- sbvToSV st a
+                  svb  <- sbvToSV st b
+                  args <- addRM st mbRm [sva, svb]
+                  newExpr st k (SBVApp (IEEEFP w) args)
+
+-- | Lift min/max: Note that we protect against constant folding if args are alternating sign 0's, since
+-- SMTLib is deliberately nondeterministic in this case
+liftMM :: (SymVal a, RealFloat a) => FPOp -> Maybe (a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a
+liftMM w mbOp mbRm a b
+  | Just v1 <- unliteral a
+  , Just v2 <- unliteral b
+  , not ((isN0 v1 && isP0 v2) || (isP0 v1 && isN0 v2))          -- If not +0/-0 or -0/+0
+  , Just cv <- concEval2 mbOp mbRm a b
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where isN0   = isNegativeZero
+        isP0 x = x == 0 && not (isN0 x)
+        k    = kindOf a
+        r st = do sva  <- sbvToSV st a
+                  svb  <- sbvToSV st b
+                  args <- addRM st mbRm [sva, svb]
+                  newExpr st k (SBVApp (IEEEFP w) args)
+
+-- | Lift a 2 arg FP-op, producing bool
+lift2B :: SymVal a => FPOp -> Maybe (a -> a -> Bool) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBool
+lift2B w mbOp mbRm a b
+  | Just cv <- concEval2B mbOp mbRm a b
+  = cv
+  | True
+  = SBV $ SVal KBool $ Right $ cache r
+  where r st = do sva  <- sbvToSV st a
+                  svb  <- sbvToSV st b
+                  args <- addRM st mbRm [sva, svb]
+                  newExpr st KBool (SBVApp (IEEEFP w) args)
+
+-- | Lift a 3 arg FP-op
+lift3 :: SymVal a => FPOp -> Maybe (a -> a -> a -> a) -> Maybe SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
+lift3 w mbOp mbRm a b c
+  | Just cv <- concEval3 mbOp mbRm a b c
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do sva  <- sbvToSV st a
+                  svb  <- sbvToSV st b
+                  svc  <- sbvToSV st c
+                  args <- addRM st mbRm [sva, svb, svc]
+                  newExpr st k (SBVApp (IEEEFP w) args)
+
+-- | Convert an 'SFloat' to an 'SWord32', preserving the bit-correspondence. Note that since the
+-- representation for @NaN@s are not unique, this function will return a symbolic value when given a
+-- concrete @NaN@.
+--
+-- Implementation note: Since there's no corresponding function in SMTLib for conversion to
+-- bit-representation due to partiality, we use a translation trick by allocating a new word variable,
+-- converting it to float, and requiring it to be equivalent to the input. In code-generation mode, we simply map
+-- it to a simple conversion.
+sFloatAsSWord32 :: SFloat -> SWord32
+sFloatAsSWord32 (SBV v) = SBV $ svFloatAsSWord32 v
+
+-- | Convert an 'SDouble' to an 'SWord64', preserving the bit-correspondence. Note that since the
+-- representation for @NaN@s are not unique, this function will return a symbolic value when given a
+-- concrete @NaN@.
+--
+-- See the implementation note for 'sFloatAsSWord32', as it applies here as well.
+sDoubleAsSWord64 :: SDouble -> SWord64
+sDoubleAsSWord64 (SBV v) = SBV $ svDoubleAsSWord64 v
+
+-- | Extract the sign\/exponent\/mantissa of a single-precision float. The output will have
+-- 8 bits in the second argument for exponent, and 23 in the third for the mantissa.
+blastSFloat :: SFloat -> (SBool, [SBool], [SBool])
+blastSFloat = extract . sFloatAsSWord32
+ where extract x = (sTestBit x 31, sExtractBits x [30, 29 .. 23], sExtractBits x [22, 21 .. 0])
+
+-- | Extract the sign\/exponent\/mantissa of a single-precision float. The output will have
+-- 11 bits in the second argument for exponent, and 52 in the third for the mantissa.
+blastSDouble :: SDouble -> (SBool, [SBool], [SBool])
+blastSDouble = extract . sDoubleAsSWord64
+ where extract x = (sTestBit x 63, sExtractBits x [62, 61 .. 52], sExtractBits x [51, 50 .. 0])
+
+-- | Extract the sign\/exponent\/mantissa of an arbitrary precision float. The output will have
+-- @eb@ bits in the second argument for exponent, and @sb-1@ bits in the third for mantissa.
+blastSFloatingPoint :: forall eb sb. (ValidFloat eb sb, KnownNat (eb + sb), BVIsNonZero (eb + sb))
+                    => SFloatingPoint eb sb -> (SBool, [SBool], [SBool])
+blastSFloatingPoint = extract . sFloatingPointAsSWord
+  where ei = intOfProxy (Proxy @eb)
+        si = intOfProxy (Proxy @sb)
+        extract x = (sTestBit x (ei + si - 1), sExtractBits x [ei + si - 2, ei + si - 3 .. si - 1], sExtractBits x [si - 2, si - 3 .. 0])
+
+-- | Reinterpret the bits in a 32-bit word as a single-precision floating point number
+sWord32AsSFloat :: SWord32 -> SFloat
+sWord32AsSFloat fVal
+  | Just f <- unliteral fVal = literal $ wordToFloat f
+  | True                     = SBV (SVal KFloat (Right (cache y)))
+  where y st = do xsv <- sbvToSV st fVal
+                  newExpr st KFloat (SBVApp (IEEEFP (FP_Reinterpret (kindOf fVal) KFloat)) [xsv])
+
+-- | Reinterpret the bits in a 32-bit word as a single-precision floating point number
+sWord64AsSDouble :: SWord64 -> SDouble
+sWord64AsSDouble dVal
+  | Just d <- unliteral dVal = literal $ wordToDouble d
+  | 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) = case blastBE $ sFloatAsSWord32 f of
+                        b : bs -> (b, bs)
+                        []     -> error "sFloatAsComparableSWord32: impossible, blastBE produced empty list"
+
+-- | Inverse transformation to 'sFloatAsComparableSWord32'.
+sComparableSWord32AsSFloat :: SWord32 -> SFloat
+sComparableSWord32AsSFloat w = sWord32AsSFloat $ ite sb (fromBitsBE $ sFalse : rest) (fromBitsBE $ map sNot allBits)
+  where allBits    = blastBE w
+        (sb, rest) = case allBits of
+                        b : bs -> (b, bs)
+                        []     -> error "sComparableSWord32AsSFloat: impossible, blastBE produced empty list"
+
+-- | 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) = case blastBE $ sDoubleAsSWord64 d of
+                        b : bs -> (b, bs)
+                        []     -> error "sDoubleAsComparableSWord64: impossible, blastBE produced empty list"
+
+-- | Inverse transformation to 'sDoubleAsComparableSWord64'. Note that this isn't a perfect inverse, since @-0@ maps to @0@ and back to @0@.
+-- Otherwise, it's faithful:
+sComparableSWord64AsSDouble :: SWord64 -> SDouble
+sComparableSWord64AsSDouble w = sWord64AsSDouble $ ite sb (fromBitsBE $ sFalse : rest) (fromBitsBE $ map sNot allBits)
+  where allBits    = blastBE w
+        (sb, rest) = case allBits of
+                        b : bs -> (b, bs)
+                        []     -> error "sComparableSWord64AsSDouble: impossible, blastBE produced empty list"
+
+-- | '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        = sComparableSWord32AsSFloat
+
+   msMinimize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @Float) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Minimize nm' (toMetricSpace o)
+
+   msMaximize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @Float) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Maximize nm' (toMetricSpace o)
+
+   annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- | '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         = sComparableSWord64AsSDouble
+
+   msMinimize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @Double) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Minimize nm' (toMetricSpace o)
+
+   msMaximize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @Double) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Maximize nm' (toMetricSpace o)
+
+   annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- | RealFloat instance for FloatingPoint. NB. The methods haven't been subjected to much testing, so beware of any floating-point snafus here.
+instance ValidFloat eb sb => RealFloat (FloatingPoint eb sb) where
+  floatRadix     (FloatingPoint f) = floatRadix     f
+  floatDigits    (FloatingPoint f) = floatDigits    f
+  floatRange     (FloatingPoint f) = floatRange     f
+  isNaN          (FloatingPoint f) = isNaN          f
+  isInfinite     (FloatingPoint f) = isInfinite     f
+  isDenormalized (FloatingPoint f) = isDenormalized f
+  isNegativeZero (FloatingPoint f) = isNegativeZero f
+  isIEEE         (FloatingPoint f) = isIEEE         f
+  decodeFloat    (FloatingPoint f) = decodeFloat    f
+
+  encodeFloat m n = res
+     where res = FloatingPoint $ fpEncodeFloat ei si m n
+           ei = intOfProxy (Proxy @eb)
+           si = intOfProxy (Proxy @sb)
+
+-- | Convert a float to the word containing the corresponding bit pattern
+sFloatingPointAsSWord :: forall eb sb. (ValidFloat eb sb, KnownNat (eb + sb), BVIsNonZero (eb + sb)) => SFloatingPoint eb sb -> SWord (eb + sb)
+sFloatingPointAsSWord (SBV v) = SBV (svFloatingPointAsSWord v)
+
+-- | Convert a float to the correct size word, that can be used in lexicographic ordering. Used in optimization.
+sFloatingPointAsComparableSWord :: forall eb sb. (ValidFloat eb sb, KnownNat (eb + sb), BVIsNonZero (eb + sb)) => SFloatingPoint eb sb -> SWord (eb + sb)
+sFloatingPointAsComparableSWord f = ite (fpIsNegativeZero f) posZero (fromBitsBE $ sNot sb : ite sb (map sNot rest) rest)
+  where posZero     = sFloatingPointAsComparableSWord (0 :: SFloatingPoint eb sb)
+        (sb, rest)  = case blastBE (sFloatingPointAsSWord f :: SWord (eb + sb)) of
+                         b : bs -> (b, bs)
+                         []     -> error "sFloatingPointAsComparableSWord: impossible, blastBE produced empty list"
+
+-- | Inverse transformation to 'sFloatingPointAsComparableSWord'. Note that this isn't a perfect inverse, since @-0@ maps to @0@ and back to @0@.
+-- Otherwise, it's faithful:
+sComparableSWordAsSFloatingPoint :: forall eb sb. (KnownNat (eb + sb), BVIsNonZero (eb + sb), ValidFloat eb sb) => SWord (eb + sb) -> SFloatingPoint eb sb
+sComparableSWordAsSFloatingPoint w = sWordAsSFloatingPoint $ ite signBit (fromBitsBE $ sFalse : rest) (fromBitsBE $ map sNot allBits)
+  where allBits        = blastBE w
+        (signBit, rest) = case allBits of
+                             b : bs -> (b, bs)
+                             []     -> error "sComparableSWordAsSFloatingPoint: impossible, blastBE produced empty list"
+
+-- | Convert a word to an arbitrary float, by reinterpreting the bits of the word as the corresponding bits of the float.
+sWordAsSFloatingPoint :: forall eb sb. (KnownNat (eb + sb), BVIsNonZero (eb + sb), ValidFloat eb sb) => SWord (eb + sb) -> SFloatingPoint eb sb
+sWordAsSFloatingPoint sw
+   | Just (f :: WordN (eb + sb)) <- unliteral sw
+   = let ext i = f `testBit` i
+         exts  = map ext
+         (s, ebits, sigbits) = (ext (ei + si - 1), exts [ei + si - 2, ei + si - 3 .. si - 1], exts [si - 2, si - 3 .. 0])
+
+         cvt :: [Bool] -> Integer
+         cvt = foldr (\b sofar -> 2 * sofar + if b then 1 else 0) 0 . reverse
+
+         eIntV = cvt ebits
+         sIntV = cvt sigbits
+         fp    = fpFromRawRep s (eIntV, ei) (sIntV, si)
+     in literal $ FloatingPoint fp
+   | True
+   = SBV (SVal kTo (Right (cache y)))
+   where ei   = intOfProxy (Proxy @eb)
+         si   = intOfProxy (Proxy @sb)
+         kTo  = KFP ei si
+         y st = do xsv <- sbvToSV st sw
+                   newExpr st kTo (SBVApp (IEEEFP (FP_Reinterpret (kindOf sw) kTo)) [xsv])
+
+instance (BVIsNonZero (eb + sb), KnownNat (eb + sb), ValidFloat eb sb) => Metric (FloatingPoint eb sb) where
+
+   type MetricSpace (FloatingPoint eb sb) = WordN (eb + sb)
+   toMetricSpace                          = sFloatingPointAsComparableSWord
+   fromMetricSpace                        = sComparableSWordAsSFloatingPoint
+
+   msMinimize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @(FloatingPoint eb sb)) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Minimize nm' (toMetricSpace o)
+
+   msMaximize nm o = do constrain $ sNot $ fpIsNaN o
+                        let nm' = annotateForMS (Proxy @(FloatingPoint eb sb)) nm
+                        when (nm' /= nm) $ sObserve nm (unSBV o)
+                        addSValOptGoal $ unSBV <$> Maximize nm' (toMetricSpace o)
+
+   annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- Map SBV's rounding modes to LibBF's
+rmToRM :: SRoundingMode -> Maybe RoundMode
+rmToRM srm = roundingModeToRoundMode <$> unliteral srm
+
+-- | Lift a 1 arg Big-float op
+lift1FP :: forall eb sb. ValidFloat eb sb =>
+           (BFOpts -> BigFloat -> (BigFloat, Status))
+        -> (Maybe SRoundingMode -> SFloatingPoint eb sb -> SFloatingPoint eb sb)
+        -> SRoundingMode
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+lift1FP bfOp mkDef rm a
+  | Just (FloatingPoint (FP _ _ v)) <- unliteral a
+  , Just brm <- rmToRM rm
+  = literal $ FloatingPoint (FP ei si (fst (bfOp (mkBFOpts ei si brm) v)))
+  | True
+  = mkDef (Just rm) a
+  where ei = intOfProxy (Proxy @eb)
+        si = intOfProxy (Proxy @sb)
+
+-- | Lift a 2 arg Big-float op
+lift2FP :: forall eb sb. ValidFloat eb sb =>
+           (BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status))
+        -> (Maybe SRoundingMode -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb)
+        -> SRoundingMode
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+lift2FP bfOp mkDef rm a b
+  | Just (FloatingPoint (FP _ _ v1)) <- unliteral a
+  , Just (FloatingPoint (FP _ _ v2)) <- unliteral b
+  , Just brm <- rmToRM rm
+  = literal $ FloatingPoint (FP ei si (fst (bfOp (mkBFOpts ei si brm) v1 v2)))
+  | True
+  = mkDef (Just rm) a b
+  where ei = intOfProxy (Proxy @eb)
+        si = intOfProxy (Proxy @sb)
+
+-- | Lift a 3 arg Big-float op
+lift3FP :: forall eb sb. ValidFloat eb sb =>
+           (BFOpts -> BigFloat -> BigFloat -> BigFloat -> (BigFloat, Status))
+        -> (Maybe SRoundingMode -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb)
+        -> SRoundingMode
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+        -> SFloatingPoint eb sb
+lift3FP bfOp mkDef rm a b c
+  | Just (FloatingPoint (FP _ _ v1)) <- unliteral a
+  , Just (FloatingPoint (FP _ _ v2)) <- unliteral b
+  , Just (FloatingPoint (FP _ _ v3)) <- unliteral c
+  , Just brm <- rmToRM rm
+  = literal $ FloatingPoint (FP ei si (fst (bfOp (mkBFOpts ei si brm) v1 v2 v3)))
+  | True
+  = mkDef (Just rm) a b c
+  where ei = intOfProxy (Proxy @eb)
+        si = intOfProxy (Proxy @sb)
+
+-- Sized-floats have a special instance, since it can handle arbitrary rounding modes when it matters.
+instance ValidFloat eb sb => IEEEFloating (FloatingPoint eb sb) where
+  fpAdd  = lift2FP bfAdd  (lift2 FP_Add  (Just (+)))
+  fpSub  = lift2FP bfSub  (lift2 FP_Sub  (Just (-)))
+  fpMul  = lift2FP bfMul  (lift2 FP_Mul  (Just (*)))
+  fpDiv  = lift2FP bfDiv  (lift2 FP_Div  (Just (/)))
+  fpFMA  = lift3FP bfFMA  (lift3 FP_FMA  Nothing)
+  fpSqrt = lift1FP bfSqrt (lift1 FP_Sqrt (Just sqrt))
+
+  fpRoundToIntegral rm a
+    | Just (FloatingPoint (FP ei si v)) <- unliteral a
+    , Just brm <- rmToRM rm
+    = literal $ FloatingPoint (FP ei si (fst (bfRoundInt brm v)))
+    | True
+    = lift1 FP_RoundToIntegral (Just fpRoundToIntegralH) (Just rm) a
+
+  -- All other operations are agnostic to the rounding mode, hence the defaults are sufficient:
+  --
+  --       fpAbs            :: SBV a -> SBV a
+  --       fpNeg            :: SBV a -> SBV a
+  --       fpRem            :: SBV a -> SBV a -> SBV a
+  --       fpMin            :: SBV a -> SBV a -> SBV a
+  --       fpMax            :: SBV a -> SBV a -> SBV a
+  --       fpIsEqualObject  :: SBV a -> SBV a -> SBool
+  --       fpIsNormal       :: SBV a -> SBool
+  --       fpIsSubnormal    :: SBV a -> SBool
+  --       fpIsZero         :: SBV a -> SBool
+  --       fpIsInfinite     :: SBV a -> SBool
+  --       fpIsNaN          :: SBV a -> SBool
+  --       fpIsNegative     :: SBV a -> SBool
+  --       fpIsPositive     :: SBV a -> SBool
+  --       fpIsNegativeZero :: SBV a -> SBool
+  --       fpIsPositiveZero :: SBV a -> SBool
+  --       fpIsPoint        :: SBV a -> SBool
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/Core/Kind.hs b/Data/SBV/Core/Kind.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Kind.hs
@@ -0,0 +1,523 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Kind
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Internal data-structures for the sbv library
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                  #-}
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE DeriveAnyClass       #-}
+{-# LANGUAGE DeriveDataTypeable   #-}
+{-# LANGUAGE DeriveGeneric        #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE LambdaCase           #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE TypeOperators        #-}
+{-# LANGUAGE ViewPatterns         #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.Kind (
+          Kind(..), HasKind(..), smtType, hasUninterpretedSorts
+        , BVIsNonZero, ValidFloat, intOfProxy
+        , showBaseKind, needsFlattening
+        , eqCheckIsObjectEq, containsFloats, isSomeKindOfFloat, expandKinds
+        , substituteADTVars
+        , kRoundingMode
+        ) where
+
+import qualified Data.Generics as G (Data(..), DataType, dataTypeName, tyconUQname)
+
+import Data.Char (isSpace)
+import Data.Int
+import Data.Word
+import Data.SBV.Core.AlgReals
+import Data.Text (Text)
+import qualified Data.Text as T
+
+import Data.Proxy
+import Data.Kind
+
+import Data.List (intercalate, sort)
+import Control.DeepSeq (NFData)
+
+import Data.Containers.ListUtils (nubOrd)
+
+import Data.Typeable (Typeable)
+import Data.Type.Bool
+import Data.Type.Equality
+
+import GHC.TypeLits
+
+import Data.SBV.Utils.Lib     (isKString, showText)
+import Data.SBV.Utils.Numeric (RoundingMode)
+
+import GHC.Generics
+import qualified Data.Generics.Uniplate.Data as G
+
+-- | Kind of symbolic value
+data Kind =
+          -- Base types
+            KBool
+
+          -- Word and Int. Boolean is True for Int.
+          | KBounded !Bool !Int
+
+          -- Unbounded integers
+          | KUnbounded
+
+          -- Reals
+          | KReal
+
+          -- Floats, standard and generalized
+          | KFloat
+          | KDouble
+          | KFP !Int !Int
+
+          -- Rationals
+          | KRational
+
+          -- Chars and strings
+          | KChar
+          | KString
+
+          -- Algebraic datatypes
+          | KVar String         -- only used temporarily during ADT construction
+          | KApp String [Kind]  -- Application of a constructor to a bunch of types
+          | KADT String
+                 [(String, Kind)]   -- Parameters, applied to these args
+                 [(String, [Kind])] -- Constructors, and their fields
+
+          -- Collections
+          | KList Kind
+          | KSet  Kind
+          | KTuple [Kind]
+
+          -- Arrays
+          | KArray  Kind Kind
+          deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Built in kind for rounding mode
+kRoundingMode :: Kind
+kRoundingMode = KADT "RoundingMode" [] (map (\r -> (show r, [])) [minBound .. maxBound :: RoundingMode])
+
+-- | Expand such that the resulting list has all the kinds we touch
+expandKinds :: Kind -> [Kind]
+expandKinds = sort . nubOrd . G.universe
+
+-- | For an ADT kind, substitute kinds for the variables.
+substituteADTVars :: String -> [(String, Kind)] -> Kind -> Kind
+substituteADTVars t dict = G.transform sub
+  where sub :: Kind -> Kind
+        sub (KVar v)
+          | Just k <- v `lookup` dict = k
+          | True                      = error $ "Data.SBV.ADT: Kind find variable in param subst: " ++ show (t, v, dict)
+        sub k = k
+
+-- | The interesting about the show instance is that it can tell apart two kinds nicely. Otherwise the string produced isn't parsed back.
+instance Show Kind where
+  show (KVar s)           = s
+  show KBool              = "SBool"
+  show (KBounded False n) = pickType n "SWord" "SWord " ++ show n
+  show (KBounded True n)  = pickType n "SInt"  "SInt "  ++ show n
+  show KUnbounded         = "SInteger"
+  show KReal              = "SReal"
+  show (KApp c ks)        = unwords (c : map (T.unpack . kindParen . showBaseKind      )  ks)
+  show (KADT s pks _)     = unwords (s : map (T.unpack . kindParen . showBaseKind . snd) pks)
+  show KFloat             = "SFloat"
+  show KDouble            = "SDouble"
+  show (KFP eb sb)        = "SFloatingPoint " ++ show eb ++ " " ++ show sb
+  show KString            = "SString"
+  show KChar              = "SChar"
+  show (KList e)          = "[" ++ show e ++ "]"
+  show (KSet  e)          = "{" ++ show e ++ "}"
+  show (KTuple m)         = "(" ++ intercalate ", " (show <$> m) ++ ")"
+  show KRational          = "SRational"
+  show (KArray k1 k2)     = "SArray "  ++ T.unpack (kindParen (showBaseKind k1)) ++ " " ++ T.unpack (kindParen (showBaseKind k2))
+
+-- | A version of show for kinds that says Bool instead of SBool, Float instead of SFloat, etc.
+showBaseKind :: Kind -> Text
+showBaseKind = sh
+  where sh (KVar s)           = T.pack s
+        sh k@KBool            = noS (showText k)
+        sh (KBounded False n) = T.pack (pickType n "Word" "WordN ") <> showText n
+        sh (KBounded True n)  = T.pack (pickType n "Int"  "IntN ")  <> showText n
+        sh (KApp s ks)        = T.unwords (T.pack s : map (kindParen . sh) ks)
+        sh k@KUnbounded       = noS (showText k)
+        sh k@KReal            = noS (showText k)
+        sh k@KADT{}           = showText k     -- Leave user-sorts untouched!
+        sh k@KFloat           = noS (showText k)
+        sh k@KDouble          = noS (showText k)
+        sh k@KFP{}            = noS (showText k)
+        sh k@KChar            = noS (showText k)
+        sh k@KString          = noS (showText k)
+        sh KRational          = "Rational"
+        sh (KList k)          = "[" <> sh k <> "]"
+        sh (KSet k)           = "{" <> sh k <> "}"
+        sh (KTuple ks)        = "(" <> T.intercalate ", " (map sh ks) <> ")"
+        sh (KArray  k1 k2)    = "Array "  <> kindParen (sh k1) <> " " <> kindParen (sh k2)
+
+        -- Drop the initial S if it's there
+        noS s = case T.uncons s of
+                  Just ('S', rest) -> rest
+                  _                -> s
+
+-- For historical reasons, we show 8-16-32-64 bit values with no space; others with a space.
+pickType :: Int -> String -> String -> String
+pickType i standard other
+  | i `elem` [8, 16, 32, 64] = standard
+  | True                     = other
+
+-- | Put parens if necessary. This test is rather crummy, but seems to work ok
+kindParen :: Text -> Text
+kindParen s = case T.uncons s of
+                Just ('[', _) -> s
+                Just ('(', _) -> s
+                _             -> if T.any isSpace s
+                                 then T.singleton '(' <> s <> T.singleton ')'
+                                 else s
+
+-- | How the type maps to SMT land
+smtType :: Kind -> Text
+smtType (KVar s)        = T.pack s
+smtType KBool           = "Bool"
+smtType (KBounded _ sz) = "(_ BitVec " <> showText sz <> ")"
+smtType KUnbounded      = "Int"
+smtType KReal           = "Real"
+smtType KFloat          = "(_ FloatingPoint  8 24)"
+smtType KDouble         = "(_ FloatingPoint 11 53)"
+smtType (KFP eb sb)     = "(_ FloatingPoint " <> showText eb <> " " <> showText sb <> ")"
+smtType KString         = "String"
+smtType KChar           = "String"
+smtType (KList k)       = "(Seq "   <> smtType k <> ")"
+smtType (KSet  k)       = "(Array " <> smtType k <> " Bool)"
+smtType (KApp s ks)     = kindParen $ T.unwords (T.pack s : map smtType          ks)
+smtType (KADT s pks _)  = kindParen $ T.unwords (T.pack s : map (smtType . snd) pks)
+smtType (KTuple [])     = "SBVTuple0"
+smtType (KTuple kinds)  = "(SBVTuple" <> showText (length kinds) <> " " <> T.unwords (smtType <$> kinds) <> ")"
+smtType KRational       = "SBVRational"
+smtType (KArray  k1 k2) = "(Array " <> smtType k1 <> " " <> smtType k2 <> ")"
+
+instance Eq G.DataType where
+   a == b = G.tyconUQname (G.dataTypeName a) == G.tyconUQname (G.dataTypeName b)
+
+instance Ord G.DataType where
+   a `compare` b = G.tyconUQname (G.dataTypeName a) `compare` G.tyconUQname (G.dataTypeName b)
+
+-- | Does this kind represent a signed quantity?
+kindHasSign :: Kind -> Bool
+kindHasSign = \case KVar _       -> False
+                    KBool        -> False
+                    KBounded b _ -> b
+                    KUnbounded   -> True
+                    KReal        -> True
+                    KFloat       -> True
+                    KDouble      -> True
+                    KFP{}        -> True
+                    KRational    -> True
+                    KApp{}       -> False
+                    KADT{}       -> False
+                    KString      -> False
+                    KChar        -> False
+                    KList{}      -> False
+                    KSet{}       -> False
+                    KTuple{}     -> False
+                    KArray{}     -> False
+
+-- | A class for capturing values that have a sign and a size (finite or infinite)
+-- minimal complete definition: kindOf, unless you can take advantage of the default
+-- signature: This class can be automatically derived for data-types that have
+-- a 'G.Data' instance; this is useful for creating uninterpreted sorts. So, in
+-- reality, end users should almost never need to define any methods.
+class HasKind a where
+  kindOf          :: a -> Kind
+  hasSign         :: a -> Bool
+  intSizeOf       :: a -> Int
+  isBoolean       :: a -> Bool
+  isBounded       :: a -> Bool   -- NB. This really means word/int; i.e., Real/Float will test False
+  isReal          :: a -> Bool
+  isFloat         :: a -> Bool
+  isDouble        :: a -> Bool
+  isRational      :: a -> Bool
+  isFP            :: a -> Bool
+  isUnbounded     :: a -> Bool
+  isADT           :: a -> Bool
+  isChar          :: a -> Bool
+  isString        :: a -> Bool
+  isList          :: a -> Bool
+  isSet           :: a -> Bool
+  isTuple         :: a -> Bool
+  isArray         :: a -> Bool
+  isRoundingMode  :: a -> Bool
+  isUninterpreted :: a -> Bool
+
+  showType        :: a -> String
+
+  -- defaults
+  hasSign x = kindHasSign (kindOf x)
+
+  intSizeOf x = case kindOf x of
+                  KVar{}        -> error "SBV.HasKind.intSizeOf(KVar)"
+                  KBool         -> error "SBV.HasKind.intSizeOf((S)Bool)"
+                  KBounded _ s  -> s
+                  KUnbounded    -> error "SBV.HasKind.intSizeOf((S)Integer)"
+                  KReal         -> error "SBV.HasKind.intSizeOf((S)Real)"
+                  KFloat        -> 32
+                  KDouble       -> 64
+                  KFP i j       -> i + j
+                  KRational     -> error "SBV.HasKind.intSizeOf((S)Rational)"
+                  KApp s _      -> error $ "SBV.HasKind.intSizeOf: Type application: "    ++ s
+                  KADT s _ _    -> error $ "SBV.HasKind.intSizeOf: Algebraic data type: " ++ s
+                  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
+                  KArray  k1 k2 -> error $ "SBV.HasKind.intSizeOf((S)Array)"  ++ show (k1, k2)
+
+  isBoolean       (kindOf -> KBool{})      = True
+  isBoolean       _                        = False
+
+  isBounded       (kindOf -> KBounded{})   = True
+  isBounded       _                        = False
+
+  isReal          (kindOf -> KReal{})      = True
+  isReal          _                        = False
+
+  isFloat         (kindOf -> KFloat{})     = True
+  isFloat         _                        = False
+
+  isDouble        (kindOf -> KDouble{})    = True
+  isDouble        _                        = False
+
+  isFP            (kindOf -> KFP{})        = True
+  isFP            _                        = False
+
+  isRational      (kindOf -> KRational{})  = True
+  isRational      _                        = False
+
+  isUnbounded     (kindOf -> KUnbounded{}) = True
+  isUnbounded     _                        = False
+
+  isADT           (kindOf -> KADT{})       = True
+  isADT           _                        = False
+
+  isChar          (kindOf -> KChar{})      = True
+  isChar          _                        = False
+
+  isString        (kindOf -> KString{})    = True
+  isString        _                        = False
+
+  isList          (kindOf -> KList{})      = True
+  isList          _                        = False
+
+  isSet           (kindOf -> KSet{})       = True
+  isSet           _                        = False
+
+  isTuple         (kindOf -> KTuple{})     = True
+  isTuple         _                        = False
+
+  isArray         (kindOf -> KArray{})     = True
+  isArray         _                        = False
+
+  -- Derived kinds
+  isRoundingMode  (kindOf -> k)            = k == kRoundingMode
+  isUninterpreted (kindOf -> k)            = case k of
+                                               KADT _ [] [] -> True
+                                               _            -> False
+
+  showType = show . kindOf
+
+  {-# MINIMAL kindOf #-}
+
+-- | This instance allows us to use the `kindOf (Proxy @a)` idiom instead of
+-- the `kindOf (undefined :: a)`, which is safer and looks more idiomatic.
+instance HasKind a => HasKind (Proxy a) where
+  kindOf _ = kindOf (undefined :: a)
+
+instance HasKind Bool         where kindOf _ = KBool
+instance HasKind Int8         where kindOf _ = KBounded True  8
+instance HasKind Word8        where kindOf _ = KBounded False 8
+instance HasKind Int16        where kindOf _ = KBounded True  16
+instance HasKind Word16       where kindOf _ = KBounded False 16
+instance HasKind Int32        where kindOf _ = KBounded True  32
+instance HasKind Word32       where kindOf _ = KBounded False 32
+instance HasKind Int64        where kindOf _ = KBounded True  64
+instance HasKind Word64       where kindOf _ = KBounded False 64
+instance HasKind Integer      where kindOf _ = KUnbounded
+instance HasKind AlgReal      where kindOf _ = KReal
+instance HasKind Rational     where kindOf _ = KRational
+instance HasKind Float        where kindOf _ = KFloat
+instance HasKind Double       where kindOf _ = KDouble
+instance HasKind Char         where kindOf _ = KChar
+instance HasKind RoundingMode where kindOf _ = kRoundingMode
+
+-- | Grab the bit-size from the proxy. If the nat is too large to fit in an int,
+-- we throw an error. (This would mean too big of a bit-size, that we can't
+-- really deal with in any practical realm.) In fact, even the range allowed
+-- by this conversion (i.e., the entire range of a 64-bit int) is just impractical,
+-- but it's hard to come up with a better bound.
+intOfProxy :: KnownNat n => Proxy n -> Int
+intOfProxy p
+  | iv == fromIntegral r = r
+  | True                 = error $ unlines [ "Data.SBV: Too large bit-vector size: " ++ show iv
+                                           , ""
+                                           , "No reasonable proof can be performed with such large bit vectors involved,"
+                                           , "So, cowardly refusing to proceed any further! Please file this as a"
+                                           , "feature request."
+                                           ]
+  where iv :: Integer
+        iv = natVal p
+
+        r :: Int
+        r  = fromEnum iv
+
+-- | Is this a type we can safely do equality on? Essentially it avoids floats (@NaN@ /= @NaN@, @+0 = -0@), and reals (due
+-- to the possible presence of non-exact rationals. In short, this will return True if there are no floats/reals under the hood.
+eqCheckIsObjectEq :: Kind -> Bool
+eqCheckIsObjectEq = not . any bad . expandKinds
+  where bad KReal   = True
+        bad k       = isSomeKindOfFloat k
+
+-- | Same as above, except only for floats
+containsFloats :: Kind -> Bool
+containsFloats = any isSomeKindOfFloat . expandKinds
+
+-- | Is some sort of a float?
+isSomeKindOfFloat :: Kind -> Bool
+isSomeKindOfFloat k = isFloat k || isDouble k || isFP k
+
+-- | Do we have a completely uninterpreted sort lying around anywhere?
+hasUninterpretedSorts :: Kind -> Bool
+hasUninterpretedSorts = any isUninterpreted . expandKinds
+
+instance (Typeable a, HasKind a) => HasKind [a] where
+   kindOf x | isKString @[a] x = KString
+            | True             = KList (kindOf (Proxy @a))
+
+instance HasKind Kind where
+  kindOf = id
+
+instance HasKind () where
+  kindOf _ = KTuple []
+
+instance (HasKind a, HasKind b) => HasKind (a, b) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b)]
+
+instance (HasKind a, HasKind b, HasKind c) => HasKind (a, b, c) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c)]
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d) => HasKind (a, b, c, d) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d)]
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e) => HasKind (a, b, c, d, e) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e)]
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f) => HasKind (a, b, c, d, e, f) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f)]
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g) => HasKind (a, b, c, d, e, f, g) where
+  kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g)]
+
+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 (a -> b) where
+  kindOf _ = KArray (kindOf (Proxy @a)) (kindOf (Proxy @b))
+
+-- | 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 = any check . expandKinds
+  where check KList{}     = True
+        check KSet{}      = True
+        check KTuple{}    = True
+        check KArray{}    = True
+        check KApp{}      = True
+        check k@KADT{}    = not (isUninterpreted k || isRoundingMode k)
+
+        -- no need to expand bases
+        check KVar{}      = False
+        check KBool       = False
+        check KBounded{}  = False
+        check KUnbounded  = False
+        check KReal       = False
+        check KFloat      = False
+        check KDouble     = False
+        check KFP{}       = False
+        check KChar       = False
+        check KString     = False
+        check KRational   = False
+
+-- | Catch 0-width cases
+type BVZeroWidth = 'Text "Zero-width bit-vectors are not allowed."
+
+-- | Type family to create the appropriate non-zero constraint
+type family BVIsNonZero (arg :: Nat) :: Constraint where
+   BVIsNonZero 0 = TypeError BVZeroWidth
+   BVIsNonZero _ = ()
+
+-- Allowed sizes for floats, imposed by LibBF.
+--
+-- NB. In LibBF bindings (and libbf itself as well), minimum number of exponent bits is specified as 3. But this
+-- seems unnecessarily restrictive; that constant doesn't seem to be used anywhere, and furthermore my tests with sb = 2
+-- didn't reveal anything going wrong. I emailed the author of libbf regarding this, and he said:
+--
+--   I had no clear reason to use BF_EXP_BITS_MIN = 3. So if "2" is OK then
+--   why not. The important is that the basic operations are OK. It is likely
+--   there are tricky cases in the transcendental operations but even with
+--   large exponents libbf may have problems with them !
+--
+-- So, in SBV, we allow sb == 2. If this proves problematic, change the number below in definition of FP_MIN_EB to 3!
+--
+-- NB. It would be nice if we could use the LibBF constants expBitsMin, expBitsMax, precBitsMin, precBitsMax
+-- for determining the valid range. Unfortunately this doesn't seem to be possible.
+-- So, we use CPP to work-around that.
+#define FP_MIN_EB 2
+#define FP_MIN_SB 2
+#if WORD_SIZE_IN_BITS == 64
+#define FP_MAX_EB 61
+#define FP_MAX_SB 4611686018427387902
+#else
+#define FP_MAX_EB 29
+#define FP_MAX_SB 1073741822
+#endif
+
+-- | Catch an invalid FP.
+type InvalidFloat (eb :: Nat) (sb :: Nat)
+        =     'Text "Invalid floating point type `SFloatingPoint " ':<>: 'ShowType eb ':<>: 'Text " " ':<>: 'ShowType sb ':<>: 'Text "'"
+        ':$$: 'Text ""
+        ':$$: 'Text "A valid float of type 'SFloatingPoint eb sb' must satisfy:"
+        ':$$: 'Text "     eb `elem` [" ':<>: 'ShowType FP_MIN_EB ':<>: 'Text " .. " ':<>: 'ShowType FP_MAX_EB ':<>: 'Text "]"
+        ':$$: 'Text "     sb `elem` [" ':<>: 'ShowType FP_MIN_SB ':<>: 'Text " .. " ':<>: 'ShowType FP_MAX_SB ':<>: 'Text "]"
+        ':$$: 'Text ""
+        ':$$: 'Text "Given type falls outside of this range, or the sizes are not known naturals."
+
+-- | A valid float has restrictions on eb/sb values.
+-- NB. In the below encoding, I found that CPP is very finicky about substitution of the machine-dependent
+-- macros. If you try to put the conditionals in the same line, it fails to substitute for some reason. Hence the awkward spacing.
+-- Filed this as a bug report for CPPHS at <https://github.com/malcolmwallace/cpphs/issues/25>.
+type family ValidFloat (eb :: Nat) (sb :: Nat) :: Constraint where
+  ValidFloat (eb :: Nat) (sb :: Nat) = ( KnownNat eb
+                                       , KnownNat sb
+                                       , If (   (   eb `CmpNat` FP_MIN_EB == 'EQ
+                                                 || eb `CmpNat` FP_MIN_EB == 'GT)
+                                             && (   eb `CmpNat` FP_MAX_EB == 'EQ
+                                                 || eb `CmpNat` FP_MAX_EB == 'LT)
+                                             && (   sb `CmpNat` FP_MIN_SB == 'EQ
+                                                 || sb `CmpNat` FP_MIN_SB == 'GT)
+                                             && (   sb `CmpNat` FP_MAX_SB == 'EQ
+                                                 || sb `CmpNat` FP_MAX_SB == 'LT))
+                                            (() :: Constraint)
+                                            (TypeError (InvalidFloat eb sb))
+                                       )
diff --git a/Data/SBV/Core/Model.hs b/Data/SBV/Core/Model.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Model.hs
@@ -0,0 +1,4848 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Model
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Instance declarations for our symbolic world
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE AllowAmbiguousTypes     #-}
+{-# LANGUAGE BangPatterns            #-}
+{-# LANGUAGE CPP                     #-}
+{-# LANGUAGE DataKinds               #-}
+{-# LANGUAGE DefaultSignatures       #-}
+{-# LANGUAGE DeriveFunctor           #-}
+{-# LANGUAGE FlexibleContexts        #-}
+{-# LANGUAGE FlexibleInstances       #-}
+{-# LANGUAGE GADTs                   #-}
+{-# LANGUAGE MultiParamTypeClasses   #-}
+{-# LANGUAGE NamedFieldPuns          #-}
+{-# LANGUAGE OverloadedStrings       #-}
+{-# LANGUAGE RankNTypes              #-}
+{-# LANGUAGE ScopedTypeVariables     #-}
+{-# LANGUAGE TypeApplications        #-}
+{-# LANGUAGE TypeFamilies            #-}
+{-# LANGUAGE TypeOperators           #-}
+{-# LANGUAGE UndecidableInstances    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.Model (
+    Mergeable(..), Equality(..), EqSymbolic(..), OrdSymbolic(..)
+  , Zero(..), MeasureOf, Measure(..), MeasureHelper(..)
+  , ContractOf, smtFunction, smtFunctionWithMeasure, smtFunctionWithContract, smtProductiveFunction, smtFunctionNoTermination
+  , checkMutualGroup
+  , SDivisible(..), SMTDefinable(..), QSaturate, qSaturateSavingObservables
+  , Metric(..), minimize, maximize, assertWithPenalty, SIntegral, SFiniteBits(..)
+  , ite, iteLazy, sFromIntegral, sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight, (.^)
+  , some
+  , oneIf, genVar, genVar_
+  , pbAtMost, pbAtLeast, pbExactly, pbLe, pbGe, pbEq, pbMutexed, pbStronglyMutexed
+  , 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
+  , sWord, sWord_, sWords, sInt, sInt_, sInts
+  , sFPHalf, sFPHalf_, sFPHalfs, sFPBFloat, sFPBFloat_, sFPBFloats, sFPSingle, sFPSingle_, sFPSingles, sFPDouble, sFPDouble_, sFPDoubles, sFPQuad, sFPQuad_, sFPQuads, sArray, sArray_, sArrays
+  , sFloatingPoint, sFloatingPoint_, sFloatingPoints
+  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
+  , sRNE, sRNA, sRTP, sRTN, sRTZ
+  , sChar, sChar_, sChars, sString, sString_, sStrings, sList, sList_, sLists
+  , sRational, sRational_, sRationals
+  , SymTuple, sTuple, sTuple_, sTuples
+  , sSet, sSet_, sSets
+  , sEDivMod, sEDiv, sEMod
+  , sDivides
+  , solve
+  , slet
+  , sRealToSInteger, sRealToSIntegerTruncate, label, observe, observeIf, sObserve
+  , sAssert
+  , liftQRem, liftDMod, symbolicMergeWithKind
+  , genLiteral, genFromCV, genMkSymVar
+  , zeroExtend, signExtend
+  , sbvQuickCheck
+  , readArray, writeArray, constArray, freeArray, lambdaArray, listArray
+  , FromSized, ToSized, FromSizedBV(..), ToSizedBV(..)
+  , smtHOFunction, smtHOFunctionWithMeasure, Closure(..)
+  )
+  where
+
+import Control.Applicative    (ZipList(ZipList))
+import Control.Monad          (when, unless, mplus, replicateM)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+
+import qualified Control.Exception as C
+
+import GHC.Generics (M1(..), U1(..), (:*:)(..), K1(..))
+import qualified GHC.Generics as G
+
+import GHC.Stack
+import GHC.TypeLits hiding(SChar)
+
+import Data.Array  (Array, Ix, elems, bounds, rangeSize)
+import qualified Data.Array as DA (listArray)
+
+import Data.Bifunctor (first)
+
+import Data.Bits   (Bits(..))
+import Data.Int    (Int8, Int16, Int32, Int64)
+import Data.Kind   (Type, Constraint)
+import Data.List   (genericLength, genericIndex, genericTake, unzip4, unzip5, unzip6, unzip7
+                   , intercalate, dropWhileEnd, isPrefixOf, partition, nubBy
+#if !MIN_VERSION_base(4,20,0)
+                   , foldl'
+#endif
+                   )
+import Data.Maybe  (fromMaybe, mapMaybe, isJust)
+import Data.String (IsString(..))
+import Data.Word   (Word8, Word16, Word32, Word64)
+
+import Data.List.NonEmpty (NonEmpty(..))
+import qualified Data.List.NonEmpty as NE
+
+import qualified Data.Set as Set
+import qualified Data.Graph as DG
+
+import Data.Proxy
+import Data.Dynamic (fromDynamic, toDyn, Typeable)
+
+import Test.QuickCheck                         (Testable(..), Arbitrary(..))
+import qualified Test.QuickCheck.Test    as QC (isSuccess)
+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, for_)
+import qualified Data.Map.Strict as Map
+import qualified Data.Sequence as Seq
+import qualified Data.Text as T
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Sized
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Data hiding (Constraint)
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.Operations
+import Data.SBV.Core.Kind
+import Data.SBV.Lambda
+import Data.SBV.Utils.ExtractIO (ExtractIO)
+
+import Data.SBV.Provers.Prover (defaultSMTCfg, SafeResult(..), defs2smt, prove, proveWith)
+import Data.SBV.SMT.SMT        (ThmResult(..), showModel)
+import Data.SBV.SMT.Utils      (debug)
+
+import Data.SBV.Utils.Numeric (fpIsEqualObjectH)
+
+import Data.IORef (readIORef, writeIORef, modifyIORef')
+import System.Mem.StableName (makeStableName, hashStableName)
+import Data.SBV.Utils.Lib
+
+import Data.Char
+
+import System.FilePath (dropExtension, takeExtension)
+
+-- Symbolic-Word class instances
+
+import Crypto.Hash.SHA512 (hash)
+import qualified Data.ByteString.Base16 as B
+import qualified Data.ByteString.Char8  as BC
+
+-- | Generate a variable, named
+genVar :: MonadSymbolic m => VarContext -> Kind -> String -> m (SBV a)
+genVar q k = mkSymSBV q k . Just
+
+-- | Generate an unnamed variable
+genVar_ :: MonadSymbolic m => VarContext -> Kind -> m (SBV a)
+genVar_ q k = mkSymSBV q k Nothing
+
+-- | Generate a finite constant bitvector
+genLiteral :: Integral a => Kind -> a -> SBV b
+genLiteral k = SBV . SVal k . Left . mkConstCV k
+
+-- | Convert a constant to an integral value
+genFromCV :: Integral a => CV -> a
+genFromCV (CV _ (CInteger x)) = fromInteger x
+genFromCV c                   = error $ "genFromCV: Unsupported non-integral value: " ++ show c
+
+-- | Generalization of 'Data.SBV.genMkSymVar'
+genMkSymVar :: MonadSymbolic m => Kind -> VarContext -> Maybe String -> m (SBV a)
+genMkSymVar k mbq Nothing  = genVar_ mbq k
+genMkSymVar k mbq (Just s) = genVar  mbq k s
+
+instance SymVal Bool where
+  mkSymVal = genMkSymVar KBool
+  literal  = SBV . svBool
+  fromCV   = cvToBool
+
+instance SymVal Word8 where
+  mkSymVal = genMkSymVar (KBounded False 8)
+  literal  = genLiteral  (KBounded False 8)
+  fromCV   = genFromCV
+
+instance SymVal Int8 where
+  mkSymVal = genMkSymVar (KBounded True 8)
+  literal  = genLiteral  (KBounded True 8)
+  fromCV   = genFromCV
+
+instance SymVal Word16 where
+  mkSymVal = genMkSymVar (KBounded False 16)
+  literal  = genLiteral  (KBounded False 16)
+  fromCV   = genFromCV
+
+instance SymVal Int16 where
+  mkSymVal = genMkSymVar (KBounded True 16)
+  literal  = genLiteral  (KBounded True 16)
+  fromCV   = genFromCV
+
+instance SymVal Word32 where
+  mkSymVal = genMkSymVar (KBounded False 32)
+  literal  = genLiteral  (KBounded False 32)
+  fromCV   = genFromCV
+
+instance SymVal Int32 where
+  mkSymVal = genMkSymVar (KBounded True 32)
+  literal  = genLiteral  (KBounded True 32)
+  fromCV   = genFromCV
+
+instance SymVal Word64 where
+  mkSymVal = genMkSymVar (KBounded False 64)
+  literal  = genLiteral  (KBounded False 64)
+  fromCV   = genFromCV
+
+instance SymVal Int64 where
+  mkSymVal = genMkSymVar (KBounded True 64)
+  literal  = genLiteral  (KBounded True 64)
+  fromCV   = genFromCV
+
+instance SymVal Integer where
+  mkSymVal    = genMkSymVar KUnbounded
+  literal     = SBV . SVal KUnbounded . Left . mkConstCV KUnbounded
+  fromCV      = genFromCV
+  minMaxBound = Nothing
+
+instance SymVal Rational where
+  mkSymVal                    = genMkSymVar KRational
+  literal                     = SBV . SVal KRational  . Left . CV KRational . CRational
+  fromCV (CV _ (CRational r)) = r
+  fromCV c                    = error $ "SymVal.Rational: Unexpected non-rational value: " ++ show c
+  minMaxBound                 = Nothing
+
+instance SymVal AlgReal where
+  mkSymVal                   = genMkSymVar KReal
+  literal                    = SBV . SVal KReal . Left . CV KReal . CAlgReal
+  fromCV (CV _ (CAlgReal a)) = a
+  fromCV c                   = error $ "SymVal.AlgReal: Unexpected non-real value: " ++ show c
+  minMaxBound               = Nothing
+
+  -- AlgReal needs its own definition of isConcretely
+  -- to make sure we avoid using unimplementable Haskell functions
+  isConcretely (SBV (SVal KReal (Left (CV KReal (CAlgReal v))))) p
+     | isExactRational v = p v
+  isConcretely _ _       = False
+
+instance SymVal Float where
+  mkSymVal                 = genMkSymVar KFloat
+  literal                  = SBV . SVal KFloat . Left . CV KFloat . CFloat
+  fromCV (CV _ (CFloat a)) = a
+  fromCV c                 = error $ "SymVal.Float: Unexpected non-float value: " ++ show c
+  minMaxBound              = Nothing
+
+  -- For Float, we conservatively return 'False' for isConcretely. The reason is that
+  -- this function is used for optimizations when only one of the argument is concrete,
+  -- and in the presence of NaN's it would be incorrect to do any optimization
+  isConcretely _ _ = False
+
+instance SymVal Double where
+  mkSymVal                  = genMkSymVar KDouble
+  literal                   = SBV . SVal KDouble . Left . CV KDouble . CDouble
+  fromCV (CV _ (CDouble a)) = a
+  fromCV c                  = error $ "SymVal.Double: Unexpected non-double value: " ++ show c
+  minMaxBound               = Nothing
+
+  -- For Double, we conservatively return 'False' for isConcretely. The reason is that
+  -- this function is used for optimizations when only one of the argument is concrete,
+  -- and in the presence of NaN's it would be incorrect to do any optimization
+  isConcretely _ _ = False
+
+instance SymVal RoundingMode where
+  literal = SBV . svRoundingMode
+  fromCV c =
+    case cvAsRoundingMode c of
+      Just mode -> mode
+      Nothing   -> error $ "SymVal.RoundingMode: Unexpected non-rounding mode value: " ++ show c
+
+-- | Symbolic variant of 'RoundNearestTiesToEven'
+sRoundNearestTiesToEven :: SRoundingMode
+sRoundNearestTiesToEven = literal RoundNearestTiesToEven
+
+-- | Symbolic variant of 'RoundNearestTiesToAway'
+sRoundNearestTiesToAway :: SRoundingMode
+sRoundNearestTiesToAway = literal RoundNearestTiesToAway
+
+-- | Symbolic variant of 'RoundTowardPositive'
+sRoundTowardPositive :: SRoundingMode
+sRoundTowardPositive = literal RoundTowardPositive
+
+-- | Symbolic variant of 'RoundTowardNegative'
+sRoundTowardNegative :: SRoundingMode
+sRoundTowardNegative = literal RoundTowardNegative
+
+-- | Symbolic variant of 'RoundTowardZero'
+sRoundTowardZero :: SRoundingMode
+sRoundTowardZero = literal RoundTowardZero
+
+-- | Alias for 'sRoundNearestTiesToEven'
+sRNE :: SRoundingMode
+sRNE = sRoundNearestTiesToEven
+
+-- | Alias for 'sRoundNearestTiesToAway'
+sRNA :: SRoundingMode
+sRNA = sRoundNearestTiesToAway
+
+-- | Alias for 'sRoundTowardPositive'
+sRTP :: SRoundingMode
+sRTP = sRoundTowardPositive
+
+-- | Alias for 'sRoundTowardNegative'
+sRTN :: SRoundingMode
+sRTN = sRoundTowardNegative
+
+-- | Alias for 'sRoundTowardZero'
+sRTZ :: SRoundingMode
+sRTZ = sRoundTowardZero
+
+
+instance SymVal Char where
+  mkSymVal                = genMkSymVar KChar
+  literal c               = SBV . SVal KChar . Left . CV KChar $ CChar c
+  fromCV (CV _ (CChar a)) = a
+  fromCV c                = error $ "SymVal.String: Unexpected non-char value: " ++ show c
+
+instance SymVal a => SymVal [a] where
+  mkSymVal
+    | isKString @[a] undefined = genMkSymVar KString
+    | True                     = genMkSymVar (KList (kindOf (Proxy @a)))
+
+  literal as
+    | isKString @[a] undefined = case fromDynamic (toDyn as) of
+                                   Just s  -> SBV . SVal KString . Left . CV KString . CString $ s
+                                   Nothing -> error "SString: Cannot construct literal string!"
+    | True                     = let k = KList (kindOf (Proxy @a))
+                                 in SBV $ SVal k $ Left $ CV k $ CList $ map toCV as
+
+  fromCV (CV _ (CString a)) = fromMaybe (error "SString: Cannot extract a literal string!")
+                                        (fromDynamic (toDyn a))
+  fromCV (CV _ (CList a))   = fromCV . CV (kindOf (Proxy @a)) <$> a
+  fromCV c                  = error $ "SymVal.fromCV: Unexpected non-list value: " ++ show c
+
+  minMaxBound               = Nothing
+
+instance ValidFloat eb sb => HasKind (FloatingPoint eb sb) where
+  kindOf _ = KFP (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))
+
+instance ValidFloat eb sb => SymVal (FloatingPoint eb sb) where
+  mkSymVal                   = genMkSymVar (KFP (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb)))
+  literal (FloatingPoint r)  = let k = KFP (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))
+                               in SBV $ SVal k $ Left $ CV k (CFP r)
+  fromCV  (CV _ (CFP r))     = FloatingPoint r
+  fromCV  c                  = error $ "SymVal.FPR: Unexpected non-arbitrary-precision value: " ++ show c
+  minMaxBound                = Nothing
+
+-- | 'SymVal' instance for 'WordN'
+instance (KnownNat n, BVIsNonZero n) => SymVal (WordN n) where
+   literal  x = genLiteral  (kindOf x) x
+   mkSymVal   = genMkSymVar (kindOf (undefined :: WordN n))
+   fromCV     = genFromCV
+
+-- | 'SymVal' instance for 'IntN'
+instance (KnownNat n, BVIsNonZero n) => SymVal (IntN n) where
+   literal  x = genLiteral  (kindOf x) x
+   mkSymVal   = genMkSymVar (kindOf (undefined :: IntN n))
+   fromCV     = genFromCV
+
+toCV :: SymVal a => a -> CVal
+toCV a = case literal a of
+           SBV (SVal _ (Left cv)) -> cvVal cv
+           _                      -> error "SymVal.toCV: Impossible happened, couldn't produce a concrete value"
+
+mkCVTup :: Int -> Kind -> [CVal] -> SBV a
+mkCVTup i k@(KTuple ks) cs
+  | lks == lcs && lks == i
+  = SBV $ SVal k $ Left $ CV k $ CTuple cs
+  | True
+  = error $ "SymVal.mkCVTup: Impossible happened. Malformed tuple received: " ++ show (i, k)
+   where lks = length ks
+         lcs = length cs
+mkCVTup i k _
+  = error $ "SymVal.mkCVTup: Impossible happened. Non-tuple received: " ++ show (i, k)
+
+fromCVTup :: Int -> CV -> [CV]
+fromCVTup i inp@(CV (KTuple ks) (CTuple cs))
+   | lks == lcs && lks == i
+   = zipWith CV ks cs
+   | True
+   = error $ "SymVal.fromCTup: Impossible happened. Malformed tuple received: " ++ show (i, inp)
+   where lks = length ks
+         lcs = length cs
+fromCVTup i inp = error $ "SymVal.fromCVTup: Impossible happened. Non-tuple received: " ++ show (i, inp)
+
+instance (HasKind a, HasKind b, SymVal a, SymVal b) => SymVal (ArrayModel a b) where
+  mkSymVal = genMkSymVar (KArray (kindOf (Proxy @a)) (kindOf (Proxy @b)))
+
+  -- If the table has duplicate entries for keys, then the first one takes precedence.
+  -- That is, [(a, v1), (a, v2)] is equivalent to [(a, v1)]. The best way to think about
+  -- this is as a "stack" of writes. [(a, v1), (a, v2)] means we first "wrote" v2 at
+  -- a, and then wrote v1 at the same address; so the first write of v2 got overwritten.
+  literal (ArrayModel tbl def) = SBV . SVal knd . Left . CV knd $ CArray $ ArrayModel [(toCV k, toCV v) | (k, v) <- tbl] (toCV def)
+    where knd = kindOf (Proxy @(ArrayModel a b))
+
+  fromCV (CV (KArray k1 k2) (CArray (ArrayModel assocs def))) = ArrayModel [(fromCV (CV k1 a), fromCV (CV k2 b)) | (a, b) <- assocs]
+                                                                           (fromCV (CV k2 def))
+
+  fromCV bad = error $ "SymVal.fromCV (SArray): Malformed array received: " ++ show bad
+
+  minMaxBound = Nothing
+
+instance (Arbitrary a, Arbitrary b) => Arbitrary (ArrayModel a b) where
+  arbitrary = ArrayModel <$> arbitrary <*> arbitrary
+
+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
+
+  minMaxBound = Nothing
+
+-- | SymVal for 0-tuple (i.e., unit)
+instance SymVal () where
+  mkSymVal   = genMkSymVar (KTuple [])
+  literal () = mkCVTup 0   (kindOf (Proxy @())) []
+  fromCV cv  = fromCVTup 0 cv `seq` ()
+
+-- | SymVal for 2-tuples
+instance (SymVal a, SymVal b) => SymVal (a, b) where
+   mkSymVal         = genMkSymVar (kindOf (Proxy @(a, b)))
+   literal (v1, v2) = mkCVTup 2   (kindOf (Proxy @(a, b))) [toCV v1, toCV v2]
+   fromCV  cv       = case fromCVTup 2 cv of
+                        [v1, v2] -> (fromCV v1, fromCV v2)
+                        res      -> error $ "Data.SBV.SymVal-Tuple2: Unexpected result: " ++ show res
+
+   minMaxBound = Nothing
+
+-- | SymVal for 3-tuples
+instance (SymVal a, SymVal b, SymVal c) => SymVal (a, b, c) where
+   mkSymVal             = genMkSymVar (kindOf (Proxy @(a, b, c)))
+   literal (v1, v2, v3) = mkCVTup 3   (kindOf (Proxy @(a, b, c))) [toCV v1, toCV v2, toCV v3]
+   fromCV  cv           = case fromCVTup 3 cv of
+                            [v1, v2, v3] -> (fromCV v1, fromCV v2, fromCV v3)
+                            res          -> error $ "Data.SBV.SymVal-Tuple3: Unexpected result: " ++ show res
+   minMaxBound          = Nothing
+
+-- | SymVal for 4-tuples
+instance (SymVal a, SymVal b, SymVal c, SymVal d) => SymVal (a, b, c, d) where
+   mkSymVal                 = genMkSymVar (kindOf (Proxy @(a, b, c, d)))
+   literal (v1, v2, v3, v4) = mkCVTup 4   (kindOf (Proxy @(a, b, c, d))) [toCV v1, toCV v2, toCV v3, toCV v4]
+   fromCV  cv               = case fromCVTup 4 cv of
+                                [v1, v2, v3, v4] -> (fromCV v1, fromCV v2, fromCV v3, fromCV v4)
+                                res              -> error $ "Data.SBV.SymVal-Tuple4: Unexpected result: " ++ show res
+   minMaxBound              = Nothing
+
+-- | SymVal for 5-tuples
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e) => SymVal (a, b, c, d, e) where
+   mkSymVal                     = genMkSymVar (kindOf (Proxy @(a, b, c, d, e)))
+   literal (v1, v2, v3, v4, v5) = mkCVTup 5   (kindOf (Proxy @(a, b, c, d, e))) [toCV v1, toCV v2, toCV v3, toCV v4, toCV v5]
+   fromCV  cv                   = case fromCVTup 5 cv of
+                                    [v1, v2, v3, v4, v5] -> (fromCV v1, fromCV v2, fromCV v3, fromCV v4, fromCV v5)
+                                    res                  -> error $ "Data.SBV.SymVal-Tuple5: Unexpected result: " ++ show res
+   minMaxBound                  = Nothing
+
+-- | SymVal for 6-tuples
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f) => SymVal (a, b, c, d, e, f) where
+   mkSymVal                         = genMkSymVar (kindOf (Proxy @(a, b, c, d, e, f)))
+   literal (v1, v2, v3, v4, v5, v6) = mkCVTup 6   (kindOf (Proxy @(a, b, c, d, e, f))) [toCV v1, toCV v2, toCV v3, toCV v4, toCV v5, toCV v6]
+   fromCV  cv                       = case fromCVTup 6 cv of
+                                        [v1, v2, v3, v4, v5, v6] -> (fromCV v1, fromCV v2, fromCV v3, fromCV v4, fromCV v5, fromCV v6)
+                                        res                      -> error $ "Data.SBV.SymVal-Tuple6: Unexpected result: " ++ show res
+   minMaxBound                      = Nothing
+
+-- | SymVal for 7-tuples
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g) => SymVal (a, b, c, d, e, f, g) where
+   mkSymVal                             = genMkSymVar (kindOf (Proxy @(a, b, c, d, e, f, g)))
+   literal (v1, v2, v3, v4, v5, v6, v7) = mkCVTup 7   (kindOf (Proxy @(a, b, c, d, e, f, g))) [toCV v1, toCV v2, toCV v3, toCV v4, toCV v5, toCV v6, toCV v7]
+   fromCV  cv                           = case fromCVTup 7 cv of
+                                            [v1, v2, v3, v4, v5, v6, v7] -> (fromCV v1, fromCV v2, fromCV v3, fromCV v4, fromCV v5, fromCV v6, fromCV v7)
+                                            res                          -> error $ "Data.SBV.SymVal-Tuple7: Unexpected result: " ++ show res
+   minMaxBound                          = Nothing
+
+-- | SymVal for 8-tuples
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h) => SymVal (a, b, c, d, e, f, g, h) where
+   mkSymVal                                 = genMkSymVar (kindOf (Proxy @(a, b, c, d, e, f, g, h)))
+   literal (v1, v2, v3, v4, v5, v6, v7, v8) = mkCVTup 8   (kindOf (Proxy @(a, b, c, d, e, f, g, h))) [toCV v1, toCV v2, toCV v3, toCV v4, toCV v5, toCV v6, toCV v7, toCV v8]
+   fromCV  cv                               = case fromCVTup 8 cv of
+                                                [v1, v2, v3, v4, v5, v6, v7, v8] -> (fromCV v1, fromCV v2, fromCV v3, fromCV v4, fromCV v5, fromCV v6, fromCV v7, fromCV v8)
+                                                res                              -> error $ "Data.SBV.SymVal-Tuple8: Unexpected result: " ++ show res
+   minMaxBound                              = Nothing
+
+instance IsString SString where
+  fromString = literal
+
+------------------------------------------------------------------------------------
+-- * Smart constructors for creating symbolic values. These are not strictly
+-- 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
+
+-- | Generalization of 'Data.SBV.sWord8'
+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
+
+-- | Generalization of 'Data.SBV.sWord16'
+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
+
+-- | Generalization of 'Data.SBV.sWord32'
+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
+
+-- | Generalization of 'Data.SBV.sWord64'
+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
+
+-- | Generalization of 'Data.SBV.sInt8'
+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
+
+-- | Generalization of 'Data.SBV.sInt16'
+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
+
+-- | Generalization of 'Data.SBV.sInt32'
+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
+
+-- | Generalization of 'Data.SBV.sInt64'
+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
+
+-- | Generalization of 'Data.SBV.sInteger'
+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
+
+-- | Generalization of 'Data.SBV.sReal'
+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
+
+-- | Generalization of 'Data.SBV.sFloat'
+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
+
+-- | Generalization of 'Data.SBV.sDouble'
+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
+
+-- | Generalization of 'Data.SBV.sFPHalf'
+sFPHalf :: String -> Symbolic SFPHalf
+sFPHalf = symbolic
+
+-- | Generalization of 'Data.SBV.sFPHalf_'
+sFPHalf_ :: Symbolic SFPHalf
+sFPHalf_ = free_
+
+-- | Generalization of 'Data.SBV.sFPHalfs'
+sFPHalfs :: [String] -> Symbolic [SFPHalf]
+sFPHalfs = symbolics
+
+-- | Generalization of 'Data.SBV.sFPBFloat'
+sFPBFloat :: String -> Symbolic SFPBFloat
+sFPBFloat = symbolic
+
+-- | Generalization of 'Data.SBV.sFPBFloat_'
+sFPBFloat_ :: Symbolic SFPBFloat
+sFPBFloat_ = free_
+
+-- | Generalization of 'Data.SBV.sFPBFloats'
+sFPBFloats :: [String] -> Symbolic [SFPBFloat]
+sFPBFloats = symbolics
+
+-- | Generalization of 'Data.SBV.sFPSingle'
+sFPSingle :: String -> Symbolic SFPSingle
+sFPSingle = symbolic
+
+-- | Generalization of 'Data.SBV.sFPSingle_'
+sFPSingle_ :: Symbolic SFPSingle
+sFPSingle_ = free_
+
+-- | Generalization of 'Data.SBV.sFPSingles'
+sFPSingles :: [String] -> Symbolic [SFPSingle]
+sFPSingles = symbolics
+
+-- | Generalization of 'Data.SBV.sFPDouble'
+sFPDouble :: String -> Symbolic SFPDouble
+sFPDouble = symbolic
+
+-- | Generalization of 'Data.SBV.sFPDouble_'
+sFPDouble_ :: Symbolic SFPDouble
+sFPDouble_ = free_
+
+-- | Generalization of 'Data.SBV.sFPDoubles'
+sFPDoubles :: [String] -> Symbolic [SFPDouble]
+sFPDoubles = symbolics
+
+-- | Generalization of 'Data.SBV.sFPQuad'
+sFPQuad :: String -> Symbolic SFPQuad
+sFPQuad = symbolic
+
+-- | Generalization of 'Data.SBV.sFPQuad_'
+sFPQuad_ :: Symbolic SFPQuad
+sFPQuad_ = free_
+
+-- | Generalization of 'Data.SBV.sFPQuads'
+sFPQuads :: [String] -> Symbolic [SFPQuad]
+sFPQuads = symbolics
+
+-- | Generalization of 'Data.SBV.sFloatingPoint'
+sFloatingPoint :: ValidFloat eb sb => String -> Symbolic (SFloatingPoint eb sb)
+sFloatingPoint = symbolic
+
+-- | Generalization of 'Data.SBV.sFloatingPoint_'
+sFloatingPoint_ :: ValidFloat eb sb => Symbolic (SFloatingPoint eb sb)
+sFloatingPoint_ = free_
+
+-- | Generalization of 'Data.SBV.sFloatingPoints'
+sFloatingPoints :: ValidFloat eb sb => [String] -> Symbolic [SFloatingPoint eb sb]
+sFloatingPoints = symbolics
+
+-- | Generalization of 'Data.SBV.sWord'
+sWord :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => String -> m (SWord n)
+sWord = symbolic
+
+-- | Generalization of 'Data.SBV.sWord_'
+sWord_ :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => m (SWord n)
+sWord_ = free_
+
+-- | Generalization of 'Data.SBV.sWord64s'
+sWords :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => [String] -> m [SWord n]
+sWords = symbolics
+
+-- | Generalization of 'Data.SBV.sInt'
+sInt :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => String -> m (SInt n)
+sInt = symbolic
+
+-- | Generalization of 'Data.SBV.sInt_'
+sInt_ :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => m (SInt n)
+sInt_ = free_
+
+-- | Generalization of 'Data.SBV.sInts'
+sInts :: (KnownNat n, BVIsNonZero n) => MonadSymbolic m => [String] -> m [SInt n]
+sInts = symbolics
+
+-- | Generalization of 'Data.SBV.sChar'
+sChar :: MonadSymbolic m => String -> m SChar
+sChar = 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
+
+-- | Generalization of 'Data.SBV.sList'
+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
+
+-- | Generalization of 'Data.SBV.sAray'
+sArray :: (SymVal a, SymVal b, MonadSymbolic m) => String -> m (SArray a b)
+sArray = symbolic
+
+-- | Generalization of 'Data.SBV.sList_'
+sArray_ :: (SymVal a, SymVal b, MonadSymbolic m) => m (SArray a b)
+sArray_ = free_
+
+-- | Generalization of 'Data.SBV.sLists'
+sArrays :: (SymVal a, SymVal b, MonadSymbolic m) => [String] -> m [SArray a b]
+sArrays = symbolics
+
+-- | Identify tuple like things. Note that there are no methods, just instances to control type inference
+class SymTuple a
+instance SymTuple ()
+instance SymTuple (a, b)
+instance SymTuple (a, b, c)
+instance SymTuple (a, b, c, d)
+instance SymTuple (a, b, c, d, e)
+instance SymTuple (a, b, c, d, e, f)
+instance SymTuple (a, b, c, d, e, f, g)
+instance SymTuple (a, b, c, d, e, f, g, h)
+
+-- | Generalization of 'Data.SBV.sTuple'
+sTuple :: (SymTuple tup, SymVal tup, MonadSymbolic m) => String -> m (SBV tup)
+sTuple = symbolic
+
+-- | Generalization of 'Data.SBV.sTuple_'
+sTuple_ :: (SymTuple tup, SymVal tup, MonadSymbolic m) => m (SBV tup)
+sTuple_ = free_
+
+-- | Generalization of 'Data.SBV.sTuples'
+sTuples :: (SymTuple tup, SymVal tup, MonadSymbolic m) => [String] -> m [SBV tup]
+sTuples = symbolics
+
+-- | Generalization of 'Data.SBV.sRational'
+sRational :: MonadSymbolic m => String -> m SRational
+sRational = symbolic
+
+-- | Generalization of 'Data.SBV.sRational_'
+sRational_ :: MonadSymbolic m => m SRational
+sRational_ = free_
+
+-- | Generalization of 'Data.SBV.sRationals'
+sRationals :: MonadSymbolic m => [String] -> m [SRational]
+sRationals = 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 = pure . sAnd
+
+-- | Convert an SReal to an SInteger. That is, it computes the
+-- largest integer @n@ that satisfies @sIntegerToSReal n <= r@
+-- essentially giving us the @floor@.
+--
+-- For instance, @1.3@ will be @1@, but @-1.3@ will be @-2@.
+sRealToSInteger :: SReal -> SInteger
+sRealToSInteger x
+  | Just i <- unliteral x, isExactRational i
+  = literal $ floor (toRational i)
+  | True
+  = SBV (SVal KUnbounded (Right (cache y)))
+  where y st = do xsv <- sbvToSV st x
+                  newExpr st KUnbounded (SBVApp (KindCast KReal KUnbounded) [xsv])
+
+-- | Convert an SReal to an SInteger, truncating version. Truncate simply chops of the
+-- fractional part, essentially rounding towards zero.
+sRealToSIntegerTruncate :: SReal -> SInteger
+sRealToSIntegerTruncate x = ite (x .>= 0) (sRealToSInteger x) (- sRealToSInteger (-x))
+
+-- | label: Label the result of an expression. This is essentially a no-op, but useful as it generates a comment in the generated C/SMT-Lib code.
+-- Note that if the argument is a constant, then the label is dropped completely, per the usual constant folding strategy. Compare this to 'observe'
+-- which is good for printing counter-examples.
+label :: SymVal a => String -> SBV a -> SBV a
+label m x
+   | Just _ <- unliteral x = x
+   | True                  = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf x
+        r st = do xsv <- sbvToSV st x
+                  newExpr st k (SBVApp (Label m) [xsv])
+
+
+-- | Observe the value of an expression, if the given condition holds.  Such values are useful in model construction, as they are printed part of a satisfying model, or a
+-- counter-example. The same works for quick-check as well. Useful when we want to see intermediate values, or expected/obtained
+-- pairs in a particular run. Note that an observed expression is always symbolic, i.e., it won't be constant folded. Compare this to 'label'
+-- which is used for putting a label in the generated SMTLib-C code.
+--
+-- NB. If the observed expression happens under a SBV-lambda expression, then it is silently ignored; since
+-- there's no way to access the value of such a value.
+observeIf :: SymVal a => (a -> Bool) -> String -> SBV a -> SBV a
+observeIf cond m x
+  | Just bad <- checkObservableName m
+  = error bad
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf x
+        r st = do xsv <- sbvToSV st (label ("Observing: " ++ m) x)
+                  recordObservable st (T.pack m) (cond . fromCV) xsv
+                  pure xsv
+
+-- | Observe the value of an expression, unconditionally. See 'observeIf' for a generalized version.
+observe :: SymVal a => String -> SBV a -> SBV a
+observe = observeIf (const True)
+
+-- | Symbolic Comparisons. Similar to 'Eq', we cannot implement Haskell's 'Ord' class
+-- since there is no way to return an 'Ordering' value from a symbolic comparison.
+-- Furthermore, 'OrdSymbolic' requires 'Mergeable' to implement if-then-else, for the
+-- benefit of implementing symbolic versions of 'max' and 'min' functions.
+infix 4 .<, .<=, .>, .>=
+class (Mergeable a, EqSymbolic a) => OrdSymbolic a where
+  -- | Symbolic less than.
+  (.<)  :: a -> a -> SBool
+  -- | Symbolic less than or equal to.
+  (.<=) :: a -> a -> SBool
+  -- | Symbolic greater than.
+  (.>)  :: a -> a -> SBool
+  -- | Symbolic greater than or equal to.
+  (.>=) :: a -> a -> SBool
+  -- | Symbolic minimum.
+  smin  :: a -> a -> a
+  -- | Symbolic maximum.
+  smax  :: a -> a -> a
+  -- | Is the value within the allowed /inclusive/ range?
+  inRange    :: a -> (a, a) -> SBool
+
+  {-# MINIMAL (.<) #-}
+
+  a .<= b    = a .< b .|| a .== b
+  a .>  b    = b .<  a
+  a .>= b    = b .<= a
+
+  a `smin` b = ite (a .<= b) a b
+  a `smax` b = ite (a .<= b) b a
+
+  inRange x (y, z) = x .>= y .&& x .<= z
+
+
+{- We can't have a generic instance of the form:
+
+instance Eq a => EqSymbolic a where
+  x .== y = if x == y then true else sFalse
+
+even if we're willing to allow Flexible/undecidable instances..
+This is because if we allow this it would imply EqSymbolic (SBV a);
+since (SBV a) has to be Eq as it must be a Num. But this wouldn't be
+the right choice obviously; as the Eq instance is bogus for SBV
+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 (HasKind a, SymVal a) => 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
+  distinct xs | all isConc xs                             = checkDiff xs
+              | [SBV a, SBV b] <- xs, a `is` svBool True  = SBV $ svNot b
+              | [SBV a, SBV b] <- xs, b `is` svBool True  = SBV $ svNot a
+              | [SBV a, SBV b] <- xs, a `is` svBool False = SBV b
+              | [SBV a, SBV b] <- xs, b `is` svBool False = SBV a
+              -- 3 booleans can't be distinct!
+              | (x : _ : _ : _) <- xs, isBool x           = sFalse
+              | True                                      = SBV (SVal KBool (Right (cache r)))
+    where r st = do xsv <- mapM (sbvToSV st) xs
+                    newExpr st KBool (SBVApp NotEqual xsv)
+
+          -- We call this in case all are concrete, which will
+          -- reduce to a constant and generate no code at all!
+          -- Note that this is essentially the same as the default
+          -- definition, which unfortunately we can no longer call!
+          checkDiff []     = sTrue
+          checkDiff (a:as) = sAll (a ./=) as .&& checkDiff as
+
+          -- Sigh, we can't use isConcrete since that requires SymVal
+          -- constraint that we don't have here. (To support SBools.)
+          isConc (SBV (SVal _ (Left _))) = True
+          isConc _                       = False
+
+          -- Likewise here; need to go lower.
+          SVal k1 (Left c1) `is` SVal k2 (Left c2) = (k1, c1) == (k2, c2)
+          _                 `is` _                 = False
+
+          isBool (SBV (SVal KBool _)) = True
+          isBool _                    = False
+
+  -- Custom version of distinctExcept that generates better code for base types
+  distinctExcept []  _       = sTrue
+  distinctExcept [_] _       = sTrue
+  distinctExcept es  ignored
+    | all isConc (es ++ ignored)
+    = distinct (filter ignoreConc es)
+    | True
+    = SBV (SVal KBool (Right (cache r)))
+    where ignoreConc x = case x `sElem` ignored of
+                           SBV (SVal KBool (Left cv)) -> cvToBool cv
+                           _                          -> error $ "distinctExcept: Impossible happened, concrete sElem failed: " ++ show (es, ignored, x)
+
+          r st = do let incr x table = ite (x `sElem` ignored) (0 :: SInteger) (1 + readArrayNoEq table x)
+
+                        initArray :: SArray a Integer
+                        initArray = constArray 0
+
+                        finalArray = foldl' (\table x -> writeArrayNoKnd table x (incr x table)) initArray es
+
+                    sbvToSV st $ sAll (\e -> readArrayNoEq finalArray e .<= (1 :: SInteger)) es
+
+          -- Sigh, we can't use isConcrete since that requires SymVal
+          -- constraint that we don't have here. (To support SBools.)
+          isConc (SBV (SVal _ (Left _))) = True
+          isConc _                       = False
+
+          -- Version of readArray that doesn't have the Eq constraint, since we don't have it here
+          readArrayNoEq array key = SBV . SVal KUnbounded . Right $ cache g
+             where g st = do f <- sbvToSV st array
+                             k <- sbvToSV st key
+                             newExpr st KUnbounded (SBVApp ReadArray [f, k])
+
+          writeArrayNoKnd :: forall key. HasKind key => SArray key Integer -> SBV key -> SInteger -> SArray key Integer
+          writeArrayNoKnd array key value = SBV . SVal k . Right $ cache g
+              where k  = KArray (kindOf (Proxy @key)) KUnbounded
+
+                    g st = do arr    <- sbvToSV st array
+                              keyVal <- sbvToSV st key
+                              val    <- sbvToSV st value
+                              newExpr st k (SBVApp WriteArray [arr, keyVal, val])
+
+-- We don't want to do a generic OrdSymbolic (SBV a) instance; since that would be dangerous, like the case
+-- for Num. So, we explicitly define for each type we care about.
+
+#define MKSORD(CSTR, TYPE)                                                            \
+instance CSTR => OrdSymbolic TYPE where {                                             \
+  a@(SBV x) .<  b@(SBV y) | smtComparable "<"   a b = SBV (svLessThan x y)            \
+                          | True                    = SBV (svStructuralLessThan x y); \
+                                                                                      \
+  a@(SBV x) .<= b@(SBV y) | smtComparable ".<=" a b = SBV (svLessEq x y)              \
+                          | True                    = a .< b .|| a .== b;             \
+                                                                                      \
+  a@(SBV x) .>  b@(SBV y) | smtComparable ">"   a b = SBV (svGreaterThan x y)         \
+                          | True                    = b .< a;                         \
+                                                                                      \
+  a@(SBV x) .>= b@(SBV y) | smtComparable ">="  a b = SBV (svGreaterEq x y)           \
+                          | True                    = b .<= a;                        \
+}                                                                                     \
+
+-- Derive basic instances we need. NB. We don't give the SRational instance here. It's handled
+-- in Data/SBV/Rational due to representation issues.
+MKSORD((),                          SInteger)
+MKSORD((),                          SWord8)
+MKSORD((),                          SWord16)
+MKSORD((),                          SWord32)
+MKSORD((),                          SWord64)
+MKSORD((),                          SInt8)
+MKSORD((),                          SInt16)
+MKSORD((),                          SInt32)
+MKSORD((),                          SInt64)
+MKSORD((),                          SFloat)
+MKSORD((),                          SChar)
+MKSORD((SymVal a),                  (SList a))
+MKSORD((),                          SDouble)
+MKSORD((),                          SReal)
+MKSORD((KnownNat n, BVIsNonZero n), (SWord n))
+MKSORD((KnownNat n, BVIsNonZero n), (SInt  n))
+MKSORD((ValidFloat eb sb),          (SFloatingPoint eb sb))
+
+-- Tuples
+MKSORD((SymVal a, SymVal b),                                                             (SBV (a, b)))
+MKSORD((SymVal a, SymVal b, SymVal c),                                                   (SBV (a, b, c)))
+MKSORD((SymVal a, SymVal b, SymVal c, SymVal d),                                         (SBV (a, b, c, d)))
+MKSORD((SymVal a, SymVal b, SymVal c, SymVal d, SymVal e),                               (SBV (a, b, c, d, e)))
+MKSORD((SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f),                     (SBV (a, b, c, d, e, f)))
+MKSORD((SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g),           (SBV (a, b, c, d, e, f, g)))
+MKSORD((SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h), (SBV (a, b, c, d, e, f, g, h)))
+#undef MKSORD
+
+-- Is this a type that's comparable by underlying translation to SMTLib?
+-- Note that we allow concrete versions to go through unless the type is a set, as there's really no reason not to.
+smtComparable :: (SymVal a, HasKind a) => String -> SBV a -> SBV a -> Bool
+smtComparable op x y
+  | isConcrete x && isConcrete y && not (isSet k)
+  = True
+  | True
+  = case k of
+      KVar       {} -> False
+      KBool         -> True
+      KBounded   {} -> True
+      KUnbounded {} -> True
+      KReal      {} -> True
+      KApp       {} -> True
+      KADT       {} -> True
+      KFloat        -> True
+      KDouble       -> True
+      KRational  {} -> True
+      KFP        {} -> True
+      KChar         -> True
+      KString       -> True
+      KList      {} -> nope     -- Unfortunately, no way for us to desugar this
+      KSet       {} -> nope     -- Ditto here..
+      KTuple     {} -> False
+      KArray     {} -> True
+ where k    = kindOf x
+       nope = error $ "Data.SBV.OrdSymbolic: SMTLib does not support " ++ op ++ " for " ++ show k
+
+-- Bool
+instance EqSymbolic Bool where
+  x .== y = fromBool $ x == y
+
+-- Lists
+instance EqSymbolic a => EqSymbolic [a] where
+  []     .==  []     = sTrue
+  (x:xs) .==  (y:ys) = x .== y .&& xs .== ys
+  _      .==  _      = sFalse
+
+  []     .=== []     = sTrue
+  (x:xs) .=== (y:ys) = x .=== y .&& xs .=== ys
+  _      .=== _      = sFalse
+
+instance OrdSymbolic a => OrdSymbolic [a] where
+  []     .< []     = sFalse
+  []     .< _      = sTrue
+  _      .< []     = sFalse
+  (x:xs) .< (y:ys) = x .< y .|| (x .== y .&& xs .< ys)
+
+-- NonEmpty
+instance EqSymbolic a => EqSymbolic (NonEmpty a) where
+  (x :| xs) .==  (y :| ys) = x : xs .==  y : ys
+  (x :| xs) .=== (y :| ys) = x : xs .=== y : ys
+
+instance OrdSymbolic a => OrdSymbolic (NonEmpty a) where
+   (x :| xs) .< (y :| ys) = x : xs .< y : ys
+
+-- Maybe
+instance EqSymbolic a => EqSymbolic (Maybe a) where
+  Nothing .== Nothing = sTrue
+  Just a  .== Just b  = a .== b
+  _       .== _       = sFalse
+
+instance OrdSymbolic a => OrdSymbolic (Maybe a) where
+  Nothing .<  Nothing = sFalse
+  Nothing .<  _       = sTrue
+  Just _  .<  Nothing = sFalse
+  Just a  .<  Just b  = a .< b
+
+-- Either
+instance (EqSymbolic a, EqSymbolic b) => EqSymbolic (Either a b) where
+  Left a  .==  Left b  = a .== b
+  Right a .==  Right b = a .== b
+  _       .==  _       = sFalse
+
+  Left a  .=== Left b  = a .=== b
+  Right a .=== Right b = a .=== b
+  _       .=== _       = sFalse
+
+instance (OrdSymbolic a, OrdSymbolic b) => OrdSymbolic (Either a b) where
+  Left a  .< Left b  = a .< b
+  Left _  .< Right _ = sTrue
+  Right _ .< Left _  = sFalse
+  Right a .< Right b = a .< b
+
+-- 2-Tuple
+instance (EqSymbolic a, EqSymbolic b) => EqSymbolic (a, b) where
+  (a0, b0) .==  (a1, b1) = a0 .==  a1 .&& b0 .==  b1
+  (a0, b0) .=== (a1, b1) = a0 .=== a1 .&& b0 .=== b1
+
+instance (OrdSymbolic a, OrdSymbolic b) => OrdSymbolic (a, b) where
+  (a0, b0) .< (a1, b1) = a0 .< a1 .|| (a0 .== a1 .&& b0 .< b1)
+
+-- 3-Tuple
+instance (EqSymbolic a, EqSymbolic b, EqSymbolic c) => EqSymbolic (a, b, c) where
+  (a0, b0, c0) .==  (a1, b1, c1) = (a0, b0) .==  (a1, b1) .&& c0 .==  c1
+  (a0, b0, c0) .=== (a1, b1, c1) = (a0, b0) .=== (a1, b1) .&& c0 .=== c1
+
+instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c) => OrdSymbolic (a, b, c) where
+  (a0, b0, c0) .< (a1, b1, c1) = (a0, b0) .< (a1, b1) .|| ((a0, b0) .== (a1, b1) .&& c0 .< c1)
+
+-- 4-Tuple
+instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d) => EqSymbolic (a, b, c, d) where
+  (a0, b0, c0, d0) .==  (a1, b1, c1, d1) = (a0, b0, c0) .==  (a1, b1, c1) .&& d0 .==  d1
+  (a0, b0, c0, d0) .=== (a1, b1, c1, d1) = (a0, b0, c0) .=== (a1, b1, c1) .&& d0 .=== d1
+
+instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d) => OrdSymbolic (a, b, c, d) where
+  (a0, b0, c0, d0) .< (a1, b1, c1, d1) = (a0, b0, c0) .< (a1, b1, c1) .|| ((a0, b0, c0) .== (a1, b1, c1) .&& d0 .< d1)
+
+-- 5-Tuple
+instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e) => EqSymbolic (a, b, c, d, e) where
+  (a0, b0, c0, d0, e0) .==  (a1, b1, c1, d1, e1) = (a0, b0, c0, d0) .==  (a1, b1, c1, d1) .&& e0 .==  e1
+  (a0, b0, c0, d0, e0) .=== (a1, b1, c1, d1, e1) = (a0, b0, c0, d0) .=== (a1, b1, c1, d1) .&& e0 .=== e1
+
+instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e) => OrdSymbolic (a, b, c, d, e) where
+  (a0, b0, c0, d0, e0) .< (a1, b1, c1, d1, e1) = (a0, b0, c0, d0) .< (a1, b1, c1, d1) .|| ((a0, b0, c0, d0) .== (a1, b1, c1, d1) .&& e0 .< e1)
+
+-- 6-Tuple
+instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e, EqSymbolic f) => EqSymbolic (a, b, c, d, e, f) where
+  (a0, b0, c0, d0, e0, f0) .==  (a1, b1, c1, d1, e1, f1) = (a0, b0, c0, d0, e0) .==  (a1, b1, c1, d1, e1) .&& f0 .==  f1
+  (a0, b0, c0, d0, e0, f0) .=== (a1, b1, c1, d1, e1, f1) = (a0, b0, c0, d0, e0) .=== (a1, b1, c1, d1, e1) .&& f0 .=== f1
+
+instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e, OrdSymbolic f) => OrdSymbolic (a, b, c, d, e, f) where
+  (a0, b0, c0, d0, e0, f0) .< (a1, b1, c1, d1, e1, f1) =    (a0, b0, c0, d0, e0) .<  (a1, b1, c1, d1, e1)
+                                                       .|| ((a0, b0, c0, d0, e0) .== (a1, b1, c1, d1, e1) .&& f0 .< f1)
+
+-- 7-Tuple
+instance (EqSymbolic a, EqSymbolic b, EqSymbolic c, EqSymbolic d, EqSymbolic e, EqSymbolic f, EqSymbolic g) => EqSymbolic (a, b, c, d, e, f, g) where
+  (a0, b0, c0, d0, e0, f0, g0) .==  (a1, b1, c1, d1, e1, f1, g1) = (a0, b0, c0, d0, e0, f0) .==  (a1, b1, c1, d1, e1, f1) .&& g0 .==  g1
+  (a0, b0, c0, d0, e0, f0, g0) .=== (a1, b1, c1, d1, e1, f1, g1) = (a0, b0, c0, d0, e0, f0) .=== (a1, b1, c1, d1, e1, f1) .&& g0 .=== g1
+
+instance (OrdSymbolic a, OrdSymbolic b, OrdSymbolic c, OrdSymbolic d, OrdSymbolic e, OrdSymbolic f, OrdSymbolic g) => OrdSymbolic (a, b, c, d, e, f, g) where
+  (a0, b0, c0, d0, e0, f0, g0) .< (a1, b1, c1, d1, e1, f1, g1) =    (a0, b0, c0, d0, e0, f0) .<  (a1, b1, c1, d1, e1, f1)
+                                                               .|| ((a0, b0, c0, d0, e0, f0) .== (a1, b1, c1, d1, e1, f1) .&& g0 .< g1)
+
+-- | A class of values that capture the notion of a zero for measure values.
+-- Used in termination checking for recursive SMT functions.
+class OrdSymbolic (SBV a) => Zero a where
+  zero   :: SBV a
+  -- | Component-wise non-negativity check. For scalars this is simply @>= 0@.
+  -- For tuples, every component must be @>= 0@, which is stronger than
+  -- lexicographic @>= (0, 0, ..)@. This is required for well-foundedness
+  -- of the lexicographic ordering on the non-negative part.
+  nonNeg :: SBV a -> SBool
+  nonNeg x = x .>= zero
+
+-- | An integer as a measure
+instance Zero Integer where
+   zero = literal 0
+
+-- | Bounded bit-vectors as measures. These are all sound: each is a finite type, so a
+-- non-negative, strictly-decreasing chain of values is necessarily finite. (The default
+-- @nonNeg x = x .>= 0@ works for both the unsigned and signed cases.)
+instance Zero Word8  where zero = literal 0
+instance Zero Word16 where zero = literal 0
+instance Zero Word32 where zero = literal 0
+instance Zero Word64 where zero = literal 0
+instance Zero Int8   where zero = literal 0
+instance Zero Int16  where zero = literal 0
+instance Zero Int32  where zero = literal 0
+instance Zero Int64  where zero = literal 0
+instance (KnownNat n, BVIsNonZero n) => Zero (WordN n) where zero = literal 0
+instance (KnownNat n, BVIsNonZero n) => Zero (IntN  n) where zero = literal 0
+
+-- NB. We would like to use 'Data.SBV.Tuple.untuple' in the 'nonNeg' definitions below,
+-- but 'Data.SBV.Tuple' imports 'Data.SBV.Core.Model', creating a circular dependency.
+-- So we extract components at the SVal level using 'TupleAccess' directly.
+
+-- | A tuple of integers as a measure
+instance Zero (Integer, Integer) where
+  zero   = literal (0, 0)
+  nonNeg = tupleNonNeg 2
+
+-- | A triple of integers as a measure
+instance Zero (Integer, Integer, Integer) where
+  zero   = literal (0, 0, 0)
+  nonNeg = tupleNonNeg 3
+
+-- | A quadruple of integers as a measure
+instance Zero (Integer, Integer, Integer, Integer) where
+  zero   = literal (0, 0, 0, 0)
+  nonNeg = tupleNonNeg 4
+
+-- | A quintuple of integers as a measure
+instance Zero (Integer, Integer, Integer, Integer, Integer) where
+  zero   = literal (0, 0, 0, 0, 0)
+  nonNeg = tupleNonNeg 5
+
+-- | A float as a measure
+instance Zero Float where
+   zero = literal 0
+
+-- | A double as a measure
+instance Zero Double where
+   zero = literal 0
+
+-- | Algebraic reals are /not/ permitted as measures, and we reject them at compile time.
+-- The reals are dense, hence not well-ordered: a merely non-negative and strictly-decreasing
+-- real measure does not imply termination (e.g. the chain @1, 1\/2, 1\/4, ...@ descends forever
+-- without reaching a minimum). Use an integer-valued measure instead.
+instance TypeError (     'Text "A termination measure may not have a real-valued result."
+                   ':$$: 'Text ""
+                   ':$$: 'Text "The reals are not well-ordered: an infinite descending chain such as"
+                   ':$$: 'Text "1, 1/2, 1/4, ... has no least element, so a non-negative and strictly"
+                   ':$$: 'Text "decreasing real measure does not imply termination."
+                   ':$$: 'Text ""
+                   ':$$: 'Text "Use an integer-valued measure instead (e.g. a count of remaining steps)."
+                   ) => Zero AlgReal where
+   zero = error "Data.SBV.Zero(AlgReal): unreachable"
+
+-- | A floating-point as a measure
+instance ValidFloat eb sb => Zero (FloatingPoint eb sb) where
+   zero = literal 0
+
+-- | Component-wise non-negativity for an n-tuple of integers.
+-- Extracts each component via 'TupleAccess' and checks @>= 0@.
+tupleNonNeg :: SymVal a => Int -> SBV a -> SBool
+tupleNonNeg n t = sAll (.>= (0 :: SInteger)) [acc i | i <- [1..n]]
+  where acc i = SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                  sv <- sbvToSV st t
+                  newExpr st KUnbounded (SBVApp (TupleAccess i n) [sv])
+
+-- | Type family that maps a function type to its corresponding measure type.
+-- The measure function takes the same arguments but returns a different type.
+type family MeasureOf f r where
+  MeasureOf (SBV a -> r) r' = SBV a -> MeasureOf r r'
+  MeasureOf (SBV a)      r  = SBV r
+
+-- | Apply a measure function to a list of SVal arguments, producing the measure value.
+-- This is used internally during measure verification.
+class ApplyMeasure a r where
+  applyMeasure :: MeasureOf a r -> [SVal] -> SBV r
+
+instance ApplyMeasure (SBV a) r where
+  applyMeasure m [] = m
+  applyMeasure _ _  = error "Data.SBV.applyMeasure: too many arguments"
+
+instance ApplyMeasure b r => ApplyMeasure (SBV a -> b) r where
+  applyMeasure _ []       = error "Data.SBV.applyMeasure: not enough arguments"
+  applyMeasure m (sv:svs) = applyMeasure @b @r (m (SBV sv)) svs
+
+-- | Type family that maps a function type to its corresponding contract type.
+-- A contract takes the same arguments as the function, plus the result, and returns 'SBool'.
+-- For example, a contract for @SBV Integer -> SBV Integer@ has type @SBV Integer -> SBV Integer -> SBool@
+-- (first arg is the input, second is the output).
+type family ContractOf f where
+  ContractOf (SBV a)      = SBV a -> SBool
+  ContractOf (SBV a -> r) = SBV a -> ContractOf r
+
+-- | Apply a contract function to a list of input t'SVal' arguments and a result t'SVal'.
+class ApplyContract a where
+  applyContract :: ContractOf a -> [SVal] -> SVal -> SBool
+
+instance ApplyContract (SBV a) where
+  applyContract c [] sv = c (SBV sv)
+  applyContract _ _  _  = error "Data.SBV.applyContract: too many arguments"
+
+instance ApplyContract b => ApplyContract (SBV a -> b) where
+  applyContract _ []       _ = error "Data.SBV.applyContract: not enough arguments"
+  applyContract c (sv:svs) r = applyContract @b (c (SBV sv)) svs r
+
+-- | An evaluated measure: captures the ability to apply the measure function
+-- to a list of arguments, along with the ordering and zero constraints.
+data MeasureEval where
+  MeasureEval :: (Zero r, OrdSymbolic (SBV r), SymVal r) => ([SVal] -> SBV r) -> MeasureEval
+
+-- | An evaluated contract: captures the ability to apply a contract predicate
+-- to a list of input arguments and a result value. Used during measure verification
+-- for nested recursive functions, where the inductive hypothesis provides the contract
+-- on recursive call results.
+data ContractEval where
+  ContractEval :: ([SVal] -> SVal -> SBool) -> ContractEval
+
+-- | A measure for a function, used to prove termination of recursive definitions.
+--
+--   * 'AutoMeasure': The function either doesn't need a measure (because it's not recursive),
+--     or SBV will automatically guess one based on argument types.
+--   * 'HasMeasure': The user provided an explicit measure function.
+--   * 'HasContract': The user provided a measure and a contract. The contract is a predicate
+--     on the function's inputs and output that is proven simultaneously with the measure decrease
+--     via well-founded induction. This handles nested recursion (e.g., McCarthy 91) where the
+--     termination argument depends on the function's return value at smaller inputs.
+--   * 'Productive': The function is corecursive (productive). Instead of proving termination via a
+--     measure, SBV checks that every recursive call is guarded by a data constructor (list cons,
+--     ADT constructor, etc.), ensuring the function always produces output incrementally.
+--   * 'Unverified': No termination or productivity check is performed. The function is emitted as
+--     @define-fun-rec@ and the user takes responsibility for well-definedness. Use this for functions
+--     where termination is believed but cannot be proven (e.g., Collatz).
+data Measure f where
+  AutoMeasure  :: Measure f
+  HasMeasure   :: MeasureEval -> [MeasureHelper] -> Measure f
+  HasContract  :: MeasureEval -> ContractEval -> [MeasureHelper] -> Measure f
+  Productive   :: Measure f
+  Unverified   :: Measure f
+
+-- | A helper axiom for measure verification. When a measure's correctness depends on
+-- properties that require induction to prove (e.g., @ifComplexity f > 0@), the user
+-- provides these properties along with their proofs. During the measure check, each
+-- helper is run: the TP proof is executed to confirm the property holds, and the
+-- proven property is asserted as an axiom in the measure verification session.
+--
+-- Use the 'Data.SBV.TP.measureLemma' smart constructor to create these from TP proofs.
+newtype MeasureHelper = MeasureHelper { runMeasureHelper :: SMTConfig -> IO SBool }
+
+-- | Verify that a measure decreases at each recursive call site.
+-- Walks the expression DAG to find recursive calls, computes reaching conditions
+-- via ITE analysis, and verifies the measure property in a separate solver session.
+-- Throws an error with a detailed message if verification fails.
+verifyMeasure :: SMTConfig -> String -> LambdaInfo -> MeasureEval -> [MeasureHelper] -> IO ()
+verifyMeasure cfg funcNm info meval helpers = do
+   -- Run each helper with funcNm added to measuresBeingVerified, preventing re-entrant verification.
+   -- This is needed when a measureLemma proof uses the function whose measure is being checked
+   -- (e.g., revPreservesLen proves length(rev xs) == length xs, using rev itself).
+   let curVerifying = measuresBeingVerified (tpOptions cfg)
+       cfg'         = cfg{tpOptions = (tpOptions cfg){measuresBeingVerified = Set.insert funcNm curVerifying}}
+
+   debug cfg ["[MEASURE] " <> T.pack funcNm <> ": verifying with " <> showText (length helpers) <> " helper(s)"
+              <> if Set.null curVerifying then "" else ", already verifying: " <> showText (Set.toList curVerifying)]
+   axioms <- mapM (`runMeasureHelper` cfg') helpers
+   debug cfg ["[MEASURE] " <> T.pack funcNm <> ": " <> showText (length axioms) <> " helper axiom(s) collected, checking measure"]
+   result <- checkMeasure cfg funcNm False info meval axioms
+   let prettyNm = prettyFuncNm funcNm
+   case result of
+     MeasureOK              -> pure ()
+     MeasureNotNonNeg r     -> error $ unlines $
+        [ ""
+        , "*** Data.SBV: Termination measure is not non-negative."
+        , "***"
+        , "***   Function: " ++ prettyNm
+        , "***"
+        ]
+        ++ ["***   " ++ l | l <- lines (show r)]
+        ++
+        [ "***"
+        , "*** The measure must be non-negative for all inputs."
+        ]
+     MeasureNotDecreasing r -> error $ unlines $
+        [ ""
+        , "*** Data.SBV: Termination measure does not strictly decrease at a recursive call site."
+        , "***"
+        , "***   Function: " ++ prettyNm
+        , "***"
+        ]
+        ++ ["***   " ++ l | l <- lines (show r)]
+        ++
+        [ "***"
+        , "*** The measure must strictly decrease at every recursive call."
+        ]
+
+-- | Result of checking a measure.
+data MeasureCheckResult = MeasureOK                         -- ^ Measure is valid
+                        | MeasureNotNonNeg     ThmResult    -- ^ Measure can be negative
+                        | MeasureNotDecreasing ThmResult    -- ^ Measure doesn't strictly decrease
+
+-- | Check that a measure is valid: non-negative and strictly decreasing at each recursive call.
+-- Returns 'MeasureOK' if valid, or the specific failure otherwise.
+-- If @skipNonNeg@ is 'True', the non-negativity check is skipped (used for ADT size measures
+-- where non-negativity is guaranteed by construction).
+-- The @axioms@ list contains additional properties to assert in the verification session
+-- (used for user-provided measures that depend on inductively-proven helper properties).
+checkMeasure :: SMTConfig -> String -> Bool -> LambdaInfo -> MeasureEval -> [SBool] -> IO MeasureCheckResult
+checkMeasure cfgIn funcNm skipNonNeg LambdaInfo{liAssignments, liParams, liOutput, liConsts} (MeasureEval applyM) axioms = do
+   let -- Use a separate transcript for the measure check, so it doesn't clobber the main one
+       addSuffix s fp = dropExtension fp ++ "_measure_" ++ map (\c -> if c == ' ' then '_' else c) funcNm ++ "_" ++ s ++ takeExtension fp
+       cfgNonNeg      = cfgIn{transcript = addSuffix "nonNeg"   <$> transcript cfgIn}
+       cfgDecrease    = cfgIn{transcript = addSuffix "decrease"  <$> transcript cfgIn}
+       barFuncNm      = barify funcNm
+       recCalls  = [(sv, args) | (sv, SBVApp (Uninterpreted nm) args) <- F.toList liAssignments, nm == T.pack barFuncNm]
+
+   if null recCalls
+     then pure MeasureOK
+     else do
+       let reachConds = computeReachingConditions liAssignments liOutput
+           paramSVs   = map snd liParams
+
+           -- Set up the proving environment: create fresh symbolic parameters,
+           -- constrain any axioms (which may register function definitions in this
+           -- session via the SVal cache mechanism), then replay the function body DAG.
+           -- The order matters: axioms must be constrained BEFORE replaying the DAG,
+           -- so that replayDAG knows which functions are available in this session.
+           mkProveEnv = do
+              st <- symbolicEnv
+              liftIO $ writeIORef (rSkipMeasureChecks st) True
+
+              let singleParam = length paramSVs == 1
+              freshParams <- liftIO $ sequence [svToSV st =<< svMkSymVar (NonQueryVar Nothing) (kindOf sv) (Just (if singleParam then "arg" else "arg" ++ show i)) st
+                                               | (i, sv) <- zip [(0::Int)..] paramSVs
+                                               ]
+              freshConsts <- liftIO $ mapM (\(_, cv) -> svToSV st (SVal (kindOf cv) (Left cv))) liConsts
+
+              -- Constrain axioms first: forcing axiom SBools triggers newUninterpreted
+              -- for any functions they reference, registering those definitions in this session.
+              mapM_ constrain axioms
+
+              -- Now read which functions are actually available in this session
+              sessionDefns <- liftIO $ readIORef (rDefns st)
+              let sessionFuncs = Map.keysSet sessionDefns
+
+              let constMapping = zip (map fst liConsts) freshConsts
+                  paramMapping = zip paramSVs freshParams
+                  initMap      = Map.fromList (constMapping ++ paramMapping)
+                  builtinMap   = Map.fromList [(trueSV, trueSV), (falseSV, falseSV)]
+                  startMap     = Map.union initMap builtinMap
+
+              svMap <- liftIO $ replayDAG cfgIn st (Set.singleton barFuncNm) sessionFuncs startMap (F.toList liAssignments)
+
+              let formalSVals = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) freshParams
+                  mFormal     = applyM formalSVals
+
+              pure (svMap, mFormal)
+
+       -- Check 1: Non-negativity (skipped for ADT size measures, which are non-negative by construction)
+       nonNegOK <- if skipNonNeg
+                   then pure (Right ())
+                   else do nonNegResult <- proveWith cfgNonNeg (do
+                              (_, mFormal) <- mkProveEnv
+                              sObserve "measure" (unSBV mFormal)
+                              pure $ nonNeg mFormal :: Symbolic SBool)
+                           pure $ case nonNegResult of
+                             ThmResult Unsatisfiable{} -> Right ()
+                             _                         -> Left nonNegResult
+
+       case nonNegOK of
+         Right () -> do
+           -- Check 2: Strict decrease at each recursive call
+           decResult <- proveWith cfgDecrease (do
+              (svMap, mFormal) <- mkProveEnv
+
+              -- When we have axioms from measure helpers that reference the function being
+              -- verified (e.g., revPreservesLen references rev), the axioms register the
+              -- function definition in this session via the SVal cache mechanism. We then
+              -- connect the fresh variables (created by replayDAG for recursive calls) to
+              -- actual function calls, so the axioms can reason about them.
+              -- For example, the axiom len(rev(xs)) = len(xs) needs to know that fresh_1
+              -- is actually rev(as) in order to derive len(fresh_1) = len(as).
+              st <- symbolicEnv
+              defns <- liftIO $ readIORef (rDefns st)
+              let funcRegistered = Map.member barFuncNm defns
+              when funcRegistered $
+                liftIO $ mapM_ (\(rcSV, callArgSVs) -> do
+                    let freshSV    = Map.findWithDefault rcSV rcSV svMap
+                        mappedArgs = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                        k          = kindOf rcSV
+                    -- Create the actual function call: f(mapped_args)
+                    actualSV <- newExpr st k (SBVApp (Uninterpreted (T.pack barFuncNm)) mappedArgs)
+                    -- Assert fresh_var == f(mapped_args)
+                    let freshSVal  = SVal k (Right (cache (const (pure freshSV))))
+                        actualSVal = SVal k (Right (cache (const (pure actualSV))))
+                    internalConstraint st False [] (svEqual freshSVal actualSVal)
+                  ) recCalls
+
+              let singleCall = length recCalls == 1
+                  mkObligation (i, (rcSV, callArgSVs)) = do
+                    let mappedArgs = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                        argSVals   = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) mappedArgs
+                        mCall      = applyM argSVals
+
+                        reachSVal  = case Map.lookup rcSV reachConds of
+                                       Just conds -> sAnd [ let sv' = Map.findWithDefault condSV condSV svMap
+                                                                s   = SBV (SVal KBool (Right (cache (\_ -> pure sv'))))
+                                                            in if pol then s else sNot s
+                                                          | (condSV, pol) <- conds
+                                                          ]
+                                       Nothing    -> sTrue
+
+                        tag nm | singleCall = nm
+                               | True       = nm ++ "[" ++ show (i :: Int) ++ "]"
+
+                    sObserve (tag "then")   (unSBV mCall)
+                    pure $ reachSVal .=> mFormal .> mCall
+
+              sObserve "before" (unSBV mFormal)
+              obligations <- mapM mkObligation (zip [1..] recCalls)
+              pure $ sAnd obligations :: Symbolic SBool)
+
+           case decResult of
+             ThmResult Unsatisfiable{} -> pure MeasureOK
+             _                         -> pure $ MeasureNotDecreasing decResult
+
+         Left nonNegResult -> pure $ MeasureNotNonNeg nonNegResult
+
+-- | Verify a measure with a contract for nested recursive functions.
+-- Uses well-founded induction: the inductive hypothesis provides the contract
+-- on recursive call results, and we prove both measure decrease and contract simultaneously.
+-- One-step unfolding of the function body at each recursive call site gives the solver
+-- information about base-case behavior without assuming totality.
+verifyMeasureWithContract :: SMTConfig -> String -> LambdaInfo -> MeasureEval -> ContractEval -> [MeasureHelper] -> IO ()
+verifyMeasureWithContract cfg funcNm info meval ceval helpers = do
+   -- Run helpers with funcNm added to measuresBeingVerified, same as verifyMeasure
+   let curVerifying = measuresBeingVerified (tpOptions cfg)
+       cfg'         = cfg{tpOptions = (tpOptions cfg){measuresBeingVerified = Set.insert funcNm curVerifying}}
+
+   debug cfg ["[MEASURE] " <> T.pack funcNm <> " (contract): verifying with " <> showText (length helpers) <> " helper(s)"]
+   axioms <- mapM (`runMeasureHelper` cfg') helpers
+   debug cfg ["[MEASURE] " <> T.pack funcNm <> " (contract): " <> showText (length axioms) <> " helper axiom(s) collected, checking measure+contract"]
+   result <- checkMeasureWithContract cfg funcNm False info meval ceval axioms
+   let prettyNm = prettyFuncNm funcNm
+   case result of
+     MeasureOK              -> pure ()
+     MeasureNotNonNeg r     -> error $ unlines $
+        [ ""
+        , "*** Data.SBV: Termination measure is not non-negative."
+        , "***"
+        , "***   Function: " ++ prettyNm
+        , "***"
+        ]
+        ++ ["***   " ++ l | l <- lines (show r)]
+        ++
+        [ "***"
+        , "*** The measure must be non-negative for all inputs."
+        ]
+     MeasureNotDecreasing r -> error $ unlines $
+        [ ""
+        , "*** Data.SBV: Measure+contract verification failed."
+        , "***"
+        , "***   Function: " ++ prettyNm
+        , "***"
+        ]
+        ++ ["***   " ++ l | l <- lines (show r)]
+        ++
+        [ "***"
+        , "*** The measure must strictly decrease at every recursive call,"
+        , "*** and the contract must hold for the function's output."
+        , "*** The inductive hypothesis provides the contract on recursive call"
+        , "*** results for inputs with strictly smaller measure."
+        ]
+
+-- | Check a measure with contract: non-negative, strictly decreasing, and contract holds.
+-- Uses one-step unfolding at each recursive call site to give the solver base-case behavior,
+-- and assumes the inductive hypothesis (contract on recursive call results) to handle
+-- nested recursion where a call's argument depends on another call's result.
+checkMeasureWithContract :: SMTConfig -> String -> Bool -> LambdaInfo -> MeasureEval -> ContractEval -> [SBool] -> IO MeasureCheckResult
+checkMeasureWithContract cfgIn funcNm skipNonNeg LambdaInfo{liAssignments, liParams, liOutput, liConsts} (MeasureEval applyM) (ContractEval applyC) axioms = do
+   let addSuffix s fp = dropExtension fp ++ "_measure_" ++ map (\c -> if c == ' ' then '_' else c) funcNm ++ "_" ++ s ++ takeExtension fp
+       cfgNonNeg      = cfgIn{transcript = addSuffix "nonNeg"   <$> transcript cfgIn}
+       cfgDecrease    = cfgIn{transcript = addSuffix "decrease"  <$> transcript cfgIn}
+       barFuncNm      = barify funcNm
+       recCalls  = [(sv, args) | (sv, SBVApp (Uninterpreted nm) args) <- F.toList liAssignments, nm == T.pack barFuncNm]
+
+   if null recCalls
+     then pure MeasureOK
+     else do
+       -- Non-negativity: same as checkMeasure
+       nonNegOK <- if skipNonNeg
+                   then pure (Right ())
+                   else do nonNegResult <- proveWith cfgNonNeg (do
+                              st <- symbolicEnv
+                              liftIO $ writeIORef (rSkipMeasureChecks st) True
+
+                              let singleParam = length paramSVs == 1
+                              freshParams <- liftIO $ sequence [svToSV st =<< svMkSymVar (NonQueryVar Nothing) (kindOf sv) (Just (if singleParam then "arg" else "arg" ++ show i)) st
+                                                                | (i, sv) <- zip [(0::Int)..] paramSVs
+                                                                ]
+                              freshConsts <- liftIO $ mapM (\(_, cv) -> svToSV st (SVal (kindOf cv) (Left cv))) liConsts
+
+                              mapM_ constrain axioms
+                              sessionDefns <- liftIO $ readIORef (rDefns st)
+                              let sessionFuncs = Map.keysSet sessionDefns
+
+                              let constMapping = zip (map fst liConsts) freshConsts
+                                  paramMapping = zip paramSVs freshParams
+                                  initMap      = Map.fromList (constMapping ++ paramMapping)
+                                  builtinMap   = Map.fromList [(trueSV, trueSV), (falseSV, falseSV)]
+                                  startMap     = Map.union initMap builtinMap
+
+                              _ <- liftIO $ replayDAG cfgIn st (Set.singleton barFuncNm) sessionFuncs startMap (F.toList liAssignments)
+
+                              let formalSVals = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) freshParams
+                                  mFormal     = applyM formalSVals
+
+                              sObserve "measure" (unSBV mFormal)
+                              pure $ nonNeg mFormal :: Symbolic SBool)
+                           pure $ case nonNegResult of
+                             ThmResult Unsatisfiable{} -> Right ()
+                             _                         -> Left nonNegResult
+
+       case nonNegOK of
+         Right () -> do
+           -- Decrease + contract check
+           decResult <- proveWith cfgDecrease (do
+              st <- symbolicEnv
+              liftIO $ writeIORef (rSkipMeasureChecks st) True
+
+              let singleParam = length paramSVs == 1
+              freshParams <- liftIO $ sequence [svToSV st =<< svMkSymVar (NonQueryVar Nothing) (kindOf sv) (Just (if singleParam then "arg" else "arg" ++ show i)) st
+                                                | (i, sv) <- zip [(0::Int)..] paramSVs
+                                                ]
+              freshConsts <- liftIO $ mapM (\(_, cv) -> svToSV st (SVal (kindOf cv) (Left cv))) liConsts
+
+              mapM_ constrain axioms
+              sessionDefns <- liftIO $ readIORef (rDefns st)
+              let sessionFuncs = Map.keysSet sessionDefns
+
+              let constMapping = zip (map fst liConsts) freshConsts
+                  paramMapping = zip paramSVs freshParams
+                  initMap      = Map.fromList (constMapping ++ paramMapping)
+                  builtinMap   = Map.fromList [(trueSV, trueSV), (falseSV, falseSV)]
+                  startMap     = Map.union initMap builtinMap
+
+              svMap <- liftIO $ replayDAG cfgIn st (Set.singleton barFuncNm) sessionFuncs startMap (F.toList liAssignments)
+
+              let formalSVals = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) freshParams
+                  mFormal     = applyM formalSVals
+
+              -- One-step unfolding: for each recursive call, replay the function body
+              -- with the call's arguments substituted for the formal parameters.
+              -- This gives the solver base-case behavior without assuming totality.
+              let dagList = F.toList liAssignments
+              liftIO $ F.for_ recCalls $ \(rcSV, callArgSVs) -> do
+                let -- Map the call's arguments through svMap to get the fresh session SVs
+                    mappedCallArgs = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                    -- Build the initial map for the unfolded body: formal params -> call args
+                    unfoldParamMapping = zip paramSVs mappedCallArgs
+                    unfoldConstMapping = zip (map fst liConsts) freshConsts
+                    unfoldInitMap      = Map.fromList (unfoldConstMapping ++ unfoldParamMapping)
+                    unfoldStartMap     = Map.union unfoldInitMap builtinMap
+
+                -- Replay the entire function body with the call's args
+                unfoldSvMap <- replayDAG cfgIn st (Set.singleton barFuncNm) sessionFuncs unfoldStartMap dagList
+
+                -- The unfolded output SV
+                let unfoldedOutputSV = Map.findWithDefault liOutput liOutput unfoldSvMap
+                    -- The fresh variable that was assigned to this recursive call
+                    freshCallSV = Map.findWithDefault rcSV rcSV svMap
+                    -- Assert: fresh_call = unfolded_output
+                    freshSVal    = SVal (kindOf rcSV) (Right (cache (const (pure freshCallSV))))
+                    unfoldedSVal = SVal (kindOf rcSV) (Right (cache (const (pure unfoldedOutputSV))))
+                internalConstraint st False [] (svEqual freshSVal unfoldedSVal)
+
+              -- IH contract: for each recursive call, assume the contract holds on its result.
+              -- This is sound because we also prove measure decrease at each call site.
+              liftIO $ F.for_ recCalls $ \(rcSV, callArgSVs) -> do
+                let mappedArgs    = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                    argSVals      = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) mappedArgs
+                    freshCallSV   = Map.findWithDefault rcSV rcSV svMap
+                    freshResult   = SVal (kindOf rcSV) (Right (cache (const (pure freshCallSV))))
+                    contractHolds = applyC argSVals freshResult
+                internalConstraint st False [] (unSBV contractHolds)
+
+              -- Proof obligations:
+              -- 1. Measure strictly decreases at each reachable recursive call site
+              let reachConds = computeReachingConditions liAssignments liOutput
+                  singleCall = length recCalls == 1
+                  mkDecreaseObligation (i, (rcSV, callArgSVs)) = do
+                    let mappedArgs = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                        argSVals   = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) mappedArgs
+                        mCall      = applyM argSVals
+
+                        reachSVal  = case Map.lookup rcSV reachConds of
+                                       Just conds -> sAnd [ let sv' = Map.findWithDefault condSV condSV svMap
+                                                                s   = SBV (SVal KBool (Right (cache (\_ -> pure sv'))))
+                                                            in if pol then s else sNot s
+                                                          | (condSV, pol) <- conds
+                                                          ]
+                                       Nothing    -> sTrue
+
+                        tag nm | singleCall = nm
+                               | True       = nm ++ "[" ++ show (i :: Int) ++ "]"
+
+                    sObserve (tag "then")   (unSBV mCall)
+                    pure $ reachSVal .=> mFormal .> mCall
+
+              sObserve "before" (unSBV mFormal)
+              decreaseObligations <- mapM mkDecreaseObligation (zip [1..] recCalls)
+
+              -- 2. Contract holds for the function's output
+              let mappedOutput  = Map.findWithDefault liOutput liOutput svMap
+                  resultSVal   = SVal (kindOf liOutput) (Right (cache (const (pure mappedOutput))))
+                  contractObl  = applyC formalSVals resultSVal
+
+              pure $ sAnd decreaseObligations .&& contractObl :: Symbolic SBool)
+
+           case decResult of
+             ThmResult Unsatisfiable{} -> pure MeasureOK
+             _                         -> pure $ MeasureNotDecreasing decResult
+
+         Left nonNegResult -> pure $ MeasureNotNonNeg nonNegResult
+   where paramSVs = map snd liParams
+
+-- | Verify that a function marked as productive is guarded-recursive:
+-- every recursive call must be a direct argument to a data constructor.
+verifyGuardedness :: SMTConfig -> String -> LambdaInfo -> IO ()
+verifyGuardedness cfg funcNm info
+  | isGuardedRecursive (Set.singleton (barify funcNm)) info
+  = debug cfg ["[MEASURE] " <> T.pack funcNm <> ": productive (all recursive calls are guarded by constructors)"]
+  | True
+  = error $ unlines
+      [ ""
+      , "*** Data.SBV: Function marked as productive is not guarded-recursive."
+      , "***"
+      , "***   Function: " ++ prettyFuncNm funcNm
+      , "***"
+      , "*** Every recursive call must be a direct argument to a data constructor"
+      , "*** (list cons, ADT constructor, etc.) to ensure productivity."
+      ]
+
+-- | Check if a recursive function is guarded: every recursive call's result
+-- is consumed by a data constructor (list cons, ADT constructor, tuple constructor).
+-- This ensures the function is productive — it always makes progress by producing
+-- at least one constructor before recursing. The set of barified names covers
+-- all functions in the mutual recursion group (or just the function itself for self-recursion).
+isGuardedRecursive :: Set.Set String -> LambdaInfo -> Bool
+isGuardedRecursive barFuncNms LambdaInfo{liAssignments} = all isGuarded recCallSVs
+  where
+    dagList    = F.toList liAssignments
+    recCallSVs = [sv | (sv, SBVApp (Uninterpreted nm) _) <- dagList, nm `Set.member` Set.map T.pack barFuncNms]
+
+    -- Build a map from SV to the set of operations that consume it
+    consumers :: Map.Map SV [(SV, Op)]
+    consumers = foldl' addConsumers Map.empty dagList
+      where addConsumers m (sv, SBVApp op args) =
+              foldl' (\m' a -> Map.insertWith (\_ old -> (sv, op) : old) a [(sv, op)] m') m args
+
+    -- A recursive call is guarded if at least one of its consumers is a constructor
+    isGuarded sv = case Map.lookup sv consumers of
+                     Nothing   -> False
+                     Just cons -> any (isConstructorOp . snd) cons
+
+    isConstructorOp (SeqOp SeqConcat{})      = True
+    isConstructorOp (ADTOp ADTConstructor{}) = True
+    isConstructorOp (TupleConstructor _)     = True
+    isConstructorOp _                        = False
+
+-- | Generate candidate measures based on parameter kinds.
+-- For list args, we use @length@. For integer args, we use @abs@. For recursive ADTs, we use @sbv.dt.size@.
+-- ADT size measures are tried first (most likely to succeed for structural recursion).
+-- If there are multiple scalar candidates, we also try their sum.
+-- For two or more scalar candidates, we also try lexicographic (tuple) measures
+-- using all pairs and triples, which handles functions like Ackermann that
+-- decrease lexicographically.
+guessMeasures :: [(Quantifier, SV)] -> [(String, MeasureEval, Maybe Int)]
+guessMeasures params = map (\(d, f, mi) -> (d, MeasureEval f, mi)) (adtSingles ++ otherSingles ++ summed) ++ lexPairs ++ lexTriples
+  where
+    singles :: [(String, [SVal] -> SInteger, Maybe Int)]
+    singles = concatMap mkCandidates (zip [0..] params)
+
+    -- ADT size measures are most likely to succeed for ADT-recursive functions, so try them first
+    (adtSingles, otherSingles) = partition (\(_, _, mi) -> isJust mi) singles
+
+    mkCandidates :: (Int, (Quantifier, SV)) -> [(String, [SVal] -> SInteger, Maybe Int)]
+    mkCandidates (i, (_, sv)) = case kindOf sv of
+      KList elemK -> [("length arg" ++ show (i+1), \svs ->
+                       let listSVal = svs !! i
+                       in SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                            s <- sbvToSV st (SBV listSVal)
+                            newExpr st KUnbounded (SBVApp (SeqOp (SeqLen elemK)) [s]), Nothing)]
+
+      -- Strings are sequences of characters in SMTLib
+      KString      -> [("length arg" ++ show (i+1), \svs ->
+                       let strSVal = svs !! i
+                       in SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                            s <- sbvToSV st (SBV strSVal)
+                            newExpr st KUnbounded (SBVApp (SeqOp (SeqLen KChar)) [s]), Nothing)]
+
+      -- Unbounded integers: try abs and smax 0 as measures
+      KUnbounded       -> [ ("abs arg"     ++ show (i+1), \svs ->      abs (SBV (svs !! i)), Nothing)
+                          , ("smax 0 arg"  ++ show (i+1), \svs -> 0 `smax` SBV (svs !! i), Nothing)
+                          ]
+
+      -- Bounded bitvectors: cast to Integer for the measure. Unsigned values are
+      -- already non-negative; signed values need abs to ensure non-negativity.
+      KBounded False _ -> [("arg" ++ show (i+1),     \svs ->      SBV (svFromIntegral KUnbounded (svs !! i)),  Nothing)]
+      KBounded True  _ -> [("abs arg" ++ show (i+1), \svs -> abs (SBV (svFromIntegral KUnbounded (svs !! i))), Nothing)]
+
+      KTuple ks   -> concatMap (mkTupleComponent i (length ks)) (zip [1..] ks)
+      KADT adtName _ ctors
+        | any (any (isRecKind adtName) . snd) ctors ->
+            let sizeName = "sbv.dt.size." ++ adtName
+                adtKind  = kindOf sv
+            in [(sizeName ++ " arg" ++ show (i+1), \svs ->
+                 SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                      ensureADTSizeDefined st sizeName adtKind ctors
+                      s <- sbvToSV st (SBV (svs !! i))
+                      newExpr st KUnbounded (SBVApp (Uninterpreted (T.pack sizeName)) [s]), Just i)]
+      _           -> []
+
+    mkTupleComponent :: Int -> Int -> (Int, Kind) -> [(String, [SVal] -> SInteger, Maybe Int)]
+    mkTupleComponent argIdx nFields (compIdx, compKind) = case compKind of
+      KList elemK -> [("length arg" ++ show (argIdx+1) ++ "._" ++ show compIdx, \svs ->
+                       let comp = SBV $ SVal compKind $ Right $ cache $ \st -> do
+                                    tupSV <- sbvToSV st (SBV (svs !! argIdx))
+                                    newExpr st compKind (SBVApp (TupleAccess compIdx nFields) [tupSV])
+                       in SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                            s <- sbvToSV st comp
+                            newExpr st KUnbounded (SBVApp (SeqOp (SeqLen elemK)) [s]), Nothing)]
+      KUnbounded  -> [("abs arg" ++ show (argIdx+1) ++ "._" ++ show compIdx, \svs ->
+                       abs $ SBV $ SVal KUnbounded $ Right $ cache $ \st -> do
+                         tupSV <- sbvToSV st (SBV (svs !! argIdx))
+                         newExpr st KUnbounded (SBVApp (TupleAccess compIdx nFields) [tupSV]), Nothing)]
+      _           -> []
+
+    summed | length singles > 1 = [( intercalate " + " [d | (d, _, _) <- singles]
+                                   , \svs -> sum [f svs | (_, f, _) <- singles]
+                                   , Nothing
+                                   )]
+           | True               = []
+
+    -- Lexicographic pair measures: try all ordered pairs from the scalar candidates
+    lexPairs :: [(String, MeasureEval, Maybe Int)]
+    lexPairs
+      | length singles < 2 = []
+      | True                = [ ( "(" ++ d1 ++ ", " ++ d2 ++ ")"
+                                , MeasureEval (\svs -> mkPair (f1 svs) (f2 svs))
+                                , Nothing
+                                )
+                              | (d1, f1, _) <- singles
+                              , (d2, f2, _) <- singles
+                              , d1 /= d2
+                              ]
+
+    -- Lexicographic triple measures: try all ordered triples from the scalar candidates
+    lexTriples :: [(String, MeasureEval, Maybe Int)]
+    lexTriples
+      | length singles < 3 = []
+      | True                = [ ( "(" ++ d1 ++ ", " ++ d2 ++ ", " ++ d3 ++ ")"
+                                , MeasureEval (\svs -> mkTriple (f1 svs) (f2 svs) (f3 svs))
+                                , Nothing
+                                )
+                              | (d1, f1, _) <- singles
+                              , (d2, f2, _) <- singles
+                              , d1 /= d2
+                              , (d3, f3, _) <- singles
+                              , d1 /= d3, d2 /= d3
+                              ]
+
+    -- Build an SBV (Integer, Integer) from two SIntegers
+    mkPair :: SInteger -> SInteger -> SBV (Integer, Integer)
+    mkPair a b = SBV $ SVal (KTuple [KUnbounded, KUnbounded]) $ Right $ cache $ \st -> do
+      sa <- sbvToSV st a
+      sb <- sbvToSV st b
+      newExpr st (KTuple [KUnbounded, KUnbounded]) (SBVApp (TupleConstructor 2) [sa, sb])
+
+    -- Build an SBV (Integer, Integer, Integer) from three SIntegers
+    mkTriple :: SInteger -> SInteger -> SInteger -> SBV (Integer, Integer, Integer)
+    mkTriple a b c = SBV $ SVal (KTuple [KUnbounded, KUnbounded, KUnbounded]) $ Right $ cache $ \st -> do
+      sa <- sbvToSV st a
+      sb <- sbvToSV st b
+      sc <- sbvToSV st c
+      newExpr st (KTuple [KUnbounded, KUnbounded, KUnbounded]) (SBVApp (TupleConstructor 3) [sa, sb, sc])
+
+-- | Check if a kind refers back to a given ADT name (i.e., is a recursive field).
+-- Recursive fields in constructor kinds use 'KApp', not 'KADT'.
+isRecKind :: String -> Kind -> Bool
+isRecKind adtName (KApp n _)   = n == adtName
+isRecKind adtName (KADT n _ _) = n == adtName
+isRecKind _       _            = False
+
+-- | Ensure that an ADT size function is defined in the given state. The size function
+-- maps ADT values to non-negative integers, returning 0 for base constructors and
+-- @1 + sum(sizes of recursive fields)@ for recursive constructors.
+-- This is used as a termination measure for functions that recurse on ADT values.
+ensureADTSizeDefined :: State -> String -> Kind -> [(String, [Kind])] -> IO ()
+ensureADTSizeDefined st sizeName adtKind ctors = do
+   defs <- readIORef (rDefns st)
+   unless (Map.member sizeName defs) $ do
+      let argNm      = "x"
+          smtArgType = T.unpack (smtType adtKind)
+
+          -- Build the SMT-Lib body for the size function
+          body = buildBody ctors
+
+          buildBody []  = "0"
+          buildBody [c] = caseExpr c
+          buildBody (c:cs) = "(ite " ++ testerExpr c ++ " " ++ caseExpr c ++ " " ++ buildBody cs ++ ")"
+
+          testerExpr (cName, _) = "(is-" ++ cName ++ " " ++ argNm ++ ")"
+
+          caseExpr (cName, flds) =
+            let recIdxs = [j | (j, k) <- zip [1::Int ..] flds, isRecKind (adtNameOf adtKind) k]
+            in if null recIdxs
+               then "0"
+               else let recCalls = ["(" ++ sizeName ++ " (get" ++ cName ++ "_" ++ show j ++ " " ++ argNm ++ "))" | j <- recIdxs]
+                    in "(+ 1 " ++ smtSum recCalls ++ ")"
+
+          smtSum [x]    = x
+          smtSum (x:xs) = "(+ " ++ x ++ " " ++ smtSum xs ++ ")"
+          smtSum []     = "0"
+
+          paramStr = T.pack $ "((" ++ argNm ++ " " ++ smtArgType ++ "))"
+          smtDef   = SMTDef KUnbounded [sizeName] (Just paramStr) (\n -> T.pack (replicate n ' ' ++ body))
+          sbvTy    = SBVType [adtKind, KUnbounded]
+
+      modifyIORef' (rDefns st) (Map.insert sizeName (smtDef, sbvTy))
+      modifyState st rUIMap (Map.insert sizeName (True, Nothing, sbvTy)) (pure ())
+
+-- | Extract the ADT name from a KADT kind.
+adtNameOf :: Kind -> String
+adtNameOf (KADT n _ _) = n
+adtNameOf _            = ""
+
+-- | Check if a function is structurally recursive on a given parameter.
+-- Returns 'True' if every recursive call passes a strict sub-term of the
+-- formal parameter (obtained via one or more 'ADTAccessor' operations) as
+-- the argument at that parameter position. Structural recursion on an ADT
+-- guarantees termination by the well-foundedness of the datatype, so the
+-- measure check can be skipped.
+isStructurallyDecreasing :: String -> LambdaInfo -> Int -> Bool
+isStructurallyDecreasing funcNm LambdaInfo{liAssignments, liParams} paramIdx =
+    not (null recCalls) && all checkCall recCalls
+  where
+    barFuncNm = barify funcNm
+    paramSV   = snd (liParams !! paramIdx)
+    asgns     = F.toList liAssignments
+    defMap    = Map.fromList asgns
+
+    recCalls = [args | (_, SBVApp (Uninterpreted nm) args) <- asgns, nm == T.pack barFuncNm]
+
+    checkCall callArgs
+      | paramIdx < length callArgs = isProperSubTerm (callArgs !! paramIdx)
+      | True                       = False
+
+    -- An SV is a proper sub-term of the parameter if it is obtained by applying
+    -- one or more ADTAccessor operations to the parameter.
+    isProperSubTerm sv = case Map.lookup sv defMap of
+       Just (SBVApp (ADTOp (ADTAccessor _ _)) [parent]) ->
+            parent == paramSV || isProperSubTerm parent
+       _ -> False
+
+-- | Try to auto-guess a termination measure for a recursive function. Generates candidates
+-- based on parameter kinds and tries each one. Returns the first measure that passes both
+-- non-negativity and strict decrease checks, or 'Nothing' if no guess works.
+autoGuess :: SMTConfig -> String -> LambdaInfo -> IO (Maybe MeasureEval)
+autoGuess cfg funcNm info = do
+    let barFuncNm = barify funcNm
+        recCalls  = [(sv, args) | (sv, SBVApp (Uninterpreted nm) args) <- F.toList (liAssignments info), nm == T.pack barFuncNm]
+        allUIs    = [(nm, length args) | (_, SBVApp (Uninterpreted nm) args) <- F.toList (liAssignments info)]
+    debug cfg ["[MEASURE] " <> T.pack funcNm <> ": barified = " <> showText barFuncNm]
+    debug cfg ["[MEASURE] " <> T.pack funcNm <> ": Uninterpreted ops in DAG: " <> showText allUIs]
+    debug cfg ["[MEASURE] " <> T.pack funcNm <> ": recursive calls found = " <> showText (length recCalls)]
+    go candidates
+  where
+    candidates = guessMeasures (liParams info)
+    go []                    = pure Nothing
+    go ((desc, m, mbIdx):ms) = do let skipNonNeg = "sbv.dt.size." `isPrefixOf` desc
+                                  debug cfg ["[MEASURE] " <> T.pack funcNm <> ": trying " <> T.pack desc]
+                                  -- For ADT size measures, try syntactic sub-term check first.
+                                  -- This avoids calling the solver, which can hang on recursive
+                                  -- define-fun-rec definitions.
+                                  result <- case mbIdx of
+                                              Just idx | isStructurallyDecreasing funcNm info idx -> do
+                                                 debug cfg ["[MEASURE] " <> T.pack funcNm <> ": " <> T.pack desc <> " -> OK (structural recursion)"]
+                                                 pure MeasureOK
+                                              _ -> checkMeasure cfg funcNm skipNonNeg info m []
+                                  case result of
+                                    MeasureOK              -> do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": " <> T.pack desc <> " -> OK"]
+                                                                 pure (Just m)
+                                    MeasureNotNonNeg r     -> do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": " <> T.pack desc <> " failed non-negativity: " <> showText r]
+                                                                 debug cfg ["[MEASURE] " <> T.pack funcNm <> ": trying next candidate.."]
+                                                                 go ms
+                                    MeasureNotDecreasing r -> do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": " <> T.pack desc <> " failed strict decrease: " <> showText r]
+                                                                 debug cfg ["[MEASURE] " <> T.pack funcNm <> ": trying next candidate.."]
+                                                                 go ms
+
+-- | Auto-guess a termination measure, or fail with a helpful error message.
+autoGuessOrFail :: SMTConfig -> String -> LambdaInfo -> IO ()
+autoGuessOrFail cfg funcNm info = do
+   mbMeasure <- autoGuess cfg funcNm info
+   case mbMeasure of
+     Just _  -> pure ()
+     Nothing -> error $ unlines $
+        [ ""
+        , "*** Data.SBV: Cannot determine a termination measure."
+        , "***"
+        , "***   Function: " ++ prettyFuncNm funcNm
+        ]
+        ++ guessLines
+        ++
+        [ "***"
+        , "*** Please use 'smtFunctionWithMeasure' to provide an explicit measure."
+        ]
+  where candidates  = guessMeasures (liParams info)
+        guessLines
+          | null candidates = [ "***"
+                              , "***   No measure candidates could be derived from the argument types."
+                              ]
+          | True            = [ "***"
+                              , "***   Measures tried:"
+                              ]
+                              ++ [ "***     " ++ d | (d, _, _) <- candidates]
+
+-- | Check mutual recursion for a function by computing the SCC from State.
+-- This is called as a deferred closure from rMeasureChecks. It computes the SCC
+-- of the function graph, finds the group containing the given function, and
+-- verifies the whole group if it's a multi-member cycle. Multiple members of the
+-- same group may register this check, but only the first execution does work;
+-- after successful verification, verified members are removed from rFuncLambdaInfos,
+-- so subsequent closures find insufficient infos and skip.
+--
+-- The optional t'MeasureEval' is a user-provided measure (from 'smtFunctionWithMeasure').
+-- If given, it is tried first before falling back to auto-guessing.
+checkMutualFromState :: SMTConfig -> String -> State -> Maybe MeasureEval -> IO ()
+checkMutualFromState cfg funcNm st mbMeasure = do
+   defns     <- readIORef (rDefns st)
+   funcInfos <- readIORef (rFuncLambdaInfos st)
+
+   let barFuncNm = barify funcNm
+       nodes = [(nm, nm, deps) | (nm, (SMTDef _ deps _ _, _)) <- Map.toList defns]
+       sccs  = DG.stronglyConnComp nodes
+
+       -- Find the SCC containing our function (using barified name since rDefns keys are barified)
+       mySCC = [members | DG.CyclicSCC members <- sccs, barFuncNm `elem` members]
+
+   case mySCC of
+     [members] | length members >= 2 -> do
+       -- rFuncLambdaInfos uses plain names, so unbar the SCC member names for lookup.
+       -- Build the infos map with plain names as keys (matching rFuncLambdaInfos convention).
+       let plainMembers = map unBar members
+           infos = Map.fromList [(pnm, v) | pnm <- plainMembers, Just v <- [Map.lookup pnm funcInfos]]
+       if Map.size infos >= 2
+         then do checkMutualGroup cfg infos mbMeasure
+                 -- Remove verified members from rFuncLambdaInfos so that subsequent closures
+                 -- for the same group (registered by other members) find insufficient infos and skip.
+                 modifyIORef' (rFuncLambdaInfos st) (\m -> foldl' (flip Map.delete) m plainMembers)
+         else do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": mutual group already verified, skipping"]
+                 modifyIORef' (rFuncLambdaInfos st) (Map.delete funcNm)
+     _ -> do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": not in a multi-member cycle, skipping mutual check"]
+             modifyIORef' (rFuncLambdaInfos st) (Map.delete funcNm)
+
+-- | Reject mutual recursion for contract-based functions. Deferred to SCC computation time
+-- so that non-mutual cross-refs (helper functions, uninterpreted constants) don't cause false positives.
+rejectMutualContractFromState :: SMTConfig -> String -> State -> IO ()
+rejectMutualContractFromState cfg funcNm st = do
+   defns <- readIORef (rDefns st)
+
+   let barFuncNm = barify funcNm
+       nodes = [(nm, nm, deps) | (nm, (SMTDef _ deps _ _, _)) <- Map.toList defns]
+       sccs  = DG.stronglyConnComp nodes
+       mySCC = [members | DG.CyclicSCC members <- sccs, barFuncNm `elem` members]
+
+   case mySCC of
+     [members] | length members >= 2 ->
+       error $ unlines [ ""
+                        , "*** Data.SBV: smtFunctionWithContract does not support mutual recursion."
+                        , "***"
+                        , "***   Function: " ++ prettyFuncNm funcNm
+                        , "***"
+                        , "*** Please use smtFunction or smtFunctionWithMeasure for mutual recursion groups."
+                        , ""
+                        ]
+     _ -> debug cfg ["[MEASURE] " <> T.pack funcNm <> ": not in a multi-member cycle, skipping mutual contract check"]
+
+-- | Check that all members of a mutual recursion group marked as productive are guarded-recursive,
+-- considering cross-calls as well as self-calls.
+checkMutualProductiveFromState :: SMTConfig -> String -> State -> IO ()
+checkMutualProductiveFromState cfg funcNm st = do
+   defns     <- readIORef (rDefns st)
+   funcInfos <- readIORef (rFuncLambdaInfos st)
+
+   let barFuncNm = barify funcNm
+       nodes = [(nm, nm, deps) | (nm, (SMTDef _ deps _ _, _)) <- Map.toList defns]
+       sccs  = DG.stronglyConnComp nodes
+       mySCC = [members | DG.CyclicSCC members <- sccs, barFuncNm `elem` members]
+
+   case mySCC of
+     [members] | length members >= 2 -> do
+       let plainMembers = map unBar members
+           infos = Map.fromList [(pnm, v) | pnm <- plainMembers, Just v <- [Map.lookup pnm funcInfos]]
+       if Map.size infos >= 2
+         then do let barNames = Set.fromList members
+                     memberNamesStr = intercalate ", " (map prettyFuncNm plainMembers)
+                 debug cfg ["[MEASURE] Checking mutual productive group: {" <> T.pack memberNamesStr <> "}"]
+                 let failed = [(pnm, info) | (pnm, info) <- Map.toList infos, not (isGuardedRecursive barNames info)]
+                 case failed of
+                   [] -> do debug cfg ["[MEASURE] Mutual productive group: all members are guarded"]
+
+                            modifyIORef' (rFuncLambdaInfos st) (\m -> foldl' (flip Map.delete) m plainMembers)
+                   _  -> error $ unlines $
+                            [ ""
+                            , "*** Data.SBV: Mutual productive group has unguarded recursive calls."
+                            , "***"
+                            ]
+                            ++ groupLines (Map.toList infos)
+                            ++
+                            [ "***   Unguarded: " ++ intercalate ", " (map (prettyFuncNm . fst) failed)
+                            , "***"
+                            , "*** Every recursive call (self or cross) must be a direct argument to a data constructor."
+                            , ""
+                            ]
+         else do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": mutual productive group already verified, skipping"]
+                 modifyIORef' (rFuncLambdaInfos st) (Map.delete funcNm)
+     _ -> do debug cfg ["[MEASURE] " <> T.pack funcNm <> ": not in a multi-member cycle, skipping mutual productive check"]
+             modifyIORef' (rFuncLambdaInfos st) (Map.delete funcNm)
+
+-- | Check termination for a mutual recursion group. Each function in the group
+-- gets an auto-guessed measure, and we verify that at every call edge (self or cross),
+-- the caller's measure at formal parameters strictly exceeds the callee's measure at actual arguments.
+--
+-- If a user-provided measure is given ('Just'), it is tried first before auto-guessing.
+checkMutualGroup :: SMTConfig -> Map.Map String LambdaInfo -> Maybe MeasureEval -> IO ()
+checkMutualGroup cfg members mbMeasure = do
+   let memberNames = Map.keys members
+       memberNamesStr = intercalate ", " (map prettyFuncNm memberNames)
+   debug cfg ["[MEASURE] Checking mutual recursion group: {" <> T.pack memberNamesStr <> "}"]
+
+   -- If a user-provided measure is given, try it first
+   let memberList = Map.toList members
+   userOK <- case mbMeasure of
+     Nothing -> pure False
+     Just m  -> do
+       debug cfg ["[MEASURE] Mutual group: trying user-provided measure for all members"]
+       ok <- checkMutualMeasure cfg memberList m
+       if ok
+         then do debug cfg ["[MEASURE] Mutual group: user-provided measure works for all members"]
+                 pure True
+         else do debug cfg ["[MEASURE] Mutual group: user-provided measure failed, falling back to auto-guess"]
+                 pure False
+
+   unless userOK $ do
+     -- Auto-guess: for each function, generate measure candidates
+     let memberCandidates = [(nm, info, guessMeasures (liParams info)) | (nm, info) <- memberList]
+
+     -- Check if any member has no candidates at all
+     case [(nm, info) | (nm, info, []) <- memberCandidates] of
+       (nm, _):_ -> error $ unlines $
+          [ ""
+          , "*** Data.SBV: Cannot determine a termination measure for mutual recursion group."
+          , "***"
+          ]
+          ++ groupLines memberList
+          ++
+          [ "***   Function with no measure candidates: " ++ prettyFuncNm nm
+          , "***"
+          , if isJust mbMeasure
+            then "*** The user-provided measure did not work, and no auto-guess candidates are available."
+            else "*** Please use 'smtFunctionWithMeasure' to provide explicit measures."
+          ]
+       [] -> pure ()
+
+     -- Try to find a working combination. For efficiency, when all members have the same
+     -- parameter kinds, we try the same candidate for all. Otherwise we try combinations.
+     let allCandidateLists = [(nm, info, cs) | (nm, info, cs) <- memberCandidates]
+     tryMeasures allCandidateLists
+
+ where
+   tryMeasures :: [(String, LambdaInfo, [(String, MeasureEval, Maybe Int)])] -> IO ()
+   tryMeasures memberInfos = do
+     -- Collect all unique candidates from all members (by description).
+     -- Different members may have different parameter kinds, yielding different candidates.
+     let allCandidates = nubBy (\(d1,_,_) (d2,_,_) -> d1 == d2)
+                              $ concatMap (\(_, _, cs) -> cs) memberInfos
+
+     result <- go allCandidates
+     case result of
+       Just _  -> pure ()
+       Nothing -> do
+         error $ unlines $
+           [ ""
+           , "*** Data.SBV: Cannot determine a termination measure for mutual recursion group."
+           , "***"
+           ]
+           ++ groupLines (Map.toList members)
+           ++
+           [ "***"
+           , if isJust mbMeasure
+             then "*** The user-provided measure did not work, and auto-guessing also failed."
+             else "*** Please use 'smtFunctionWithMeasure' to provide explicit measures."
+           ]
+
+    where
+     go [] = pure Nothing
+     go ((desc, m, _mbIdx):rest) = do
+       debug cfg ["[MEASURE] Mutual group: trying measure " <> T.pack desc <> " for all members"]
+       -- Try the same measure for all members. Catch exceptions from kind mismatches
+       -- (e.g., applying abs to a list parameter) and treat them as failure.
+       let memberList = [(nm, info) | (nm, info, _) <- memberInfos]
+       result <- C.try $ checkMutualMeasure cfg memberList m
+       case result of
+         Right True -> do debug cfg ["[MEASURE] Mutual group: measure " <> T.pack desc <> " works for all members"]
+                          pure (Just m)
+         Right False -> do debug cfg ["[MEASURE] Mutual group: measure " <> T.pack desc <> " failed, trying next"]
+                           go rest
+         Left (e :: C.SomeException) -> do
+                           debug cfg ["[MEASURE] Mutual group: measure " <> T.pack desc <> " incompatible: " <> showText e]
+                           go rest
+
+-- | Verify that a given measure works for all functions in a mutual recursion group.
+-- Uses the same measure for all members. For each function f, check that at every call
+-- site to any function g in the group, measure(f's formals) > measure(g's actuals).
+checkMutualMeasure :: SMTConfig -> [(String, LambdaInfo)] -> MeasureEval -> IO Bool
+checkMutualMeasure cfgIn members (MeasureEval applyM) = go members
+  where
+    -- Set of barified names of all group members
+    groupBarNames = Set.fromList [barify nm | (nm, _) <- members]
+
+    go [] = pure True
+    go ((funcNm, LambdaInfo{liAssignments, liParams, liOutput, liConsts}):rest) = do
+       -- Find all calls to any member of the mutual group
+       let allGroupCalls = [(sv, args)
+                           | (sv, SBVApp (Uninterpreted calleeNm) args) <- F.toList liAssignments
+                           , calleeNm `Set.member` Set.map T.pack groupBarNames
+                           ]
+
+       if null allGroupCalls
+         then go rest  -- No calls to group members, no decrease needed
+         else do
+           let addSuffix s fp = dropExtension fp ++ "_measure_" ++ map (\c -> if c == ' ' then '_' else c) funcNm ++ "_" ++ s ++ takeExtension fp
+               cfgDecrease    = cfgIn{transcript = addSuffix "mutual_decrease" <$> transcript cfgIn}
+               cfgNonNeg      = cfgIn{transcript = addSuffix "mutual_nonNeg"   <$> transcript cfgIn}
+               paramSVs       = map snd liParams
+               reachConds     = computeReachingConditions liAssignments liOutput
+
+               mkProveEnv = do
+                  st <- symbolicEnv
+                  liftIO $ writeIORef (rSkipMeasureChecks st) True
+                  let singleParam = length paramSVs == 1
+                  freshParams <- liftIO $ sequence
+                    [svToSV st =<< svMkSymVar (NonQueryVar Nothing) (kindOf sv)
+                                              (Just (if singleParam then "arg" else "arg" ++ show i)) st
+                    | (i, sv) <- zip [(0::Int)..] paramSVs
+                    ]
+                  freshConsts <- liftIO $ mapM (\(_, cv) -> svToSV st (SVal (kindOf cv) (Left cv))) liConsts
+                  sessionDefns <- liftIO $ readIORef (rDefns st)
+                  let sessionFuncs = Map.keysSet sessionDefns
+                      constMapping = zip (map fst liConsts) freshConsts
+                      paramMapping = zip paramSVs freshParams
+                      initMap      = Map.fromList (constMapping ++ paramMapping)
+                      builtinMap   = Map.fromList [(trueSV, trueSV), (falseSV, falseSV)]
+                      startMap     = Map.union initMap builtinMap
+                  svMap <- liftIO $ replayDAG cfgIn st groupBarNames sessionFuncs startMap (F.toList liAssignments)
+                  let formalSVals = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) freshParams
+                      mFormal     = applyM formalSVals
+                  pure (svMap, mFormal)
+
+           -- Check 1: Non-negativity of caller's measure
+           nonNegResult <- proveWith cfgNonNeg (do
+               (_, mFormal) <- mkProveEnv
+               sObserve "measure" (unSBV mFormal)
+               pure $ nonNeg mFormal :: Symbolic SBool)
+
+           case nonNegResult of
+             ThmResult Unsatisfiable{} -> do
+               -- Check 2: Strict decrease at each call site
+               decResult <- proveWith cfgDecrease (do
+                   (svMap, mFormal) <- mkProveEnv
+                   let singleCall = length allGroupCalls == 1
+                       mkObligation (i, (rcSV, callArgSVs)) = do
+                         let mappedArgs = map (\sv -> Map.findWithDefault sv sv svMap) callArgSVs
+                             argSVals   = map (\sv -> SVal (kindOf sv) (Right (cache (\_ -> pure sv)))) mappedArgs
+                             mCall      = applyM argSVals
+                             reachSVal  = case Map.lookup rcSV reachConds of
+                                            Just conds -> sAnd [ let sv' = Map.findWithDefault condSV condSV svMap
+                                                                     s   = SBV (SVal KBool (Right (cache (\_ -> pure sv'))))
+                                                                 in if pol then s else sNot s
+                                                               | (condSV, pol) <- conds
+                                                               ]
+                                            Nothing    -> sTrue
+                             tag nm | singleCall = nm
+                                    | True       = nm ++ "[" ++ show (i :: Int) ++ "]"
+                         sObserve (tag "then") (unSBV mCall)
+                         pure $ reachSVal .=> mFormal .> mCall
+                   sObserve "before" (unSBV mFormal)
+                   obligations <- mapM mkObligation (zip [1..] allGroupCalls)
+                   pure $ sAnd obligations :: Symbolic SBool)
+               case decResult of
+                 ThmResult Unsatisfiable{} -> do
+                   debug cfgIn ["[MEASURE] Mutual group: decrease verified for " <> T.pack funcNm]
+                   go rest
+                 _ -> do
+                   debug cfgIn ["[MEASURE] Mutual group: decrease failed for " <> T.pack funcNm <> ": " <> showText decResult]
+                   pure False
+             _ -> do
+               debug cfgIn ["[MEASURE] Mutual group: non-negativity failed for " <> T.pack funcNm]
+               pure False
+
+-- | Pretty-print a function name: turn @"insert @(SBV Integer -> SBV [Integer])"@ into @"insert :: SBV Integer -> SBV [Integer]"@
+prettyFuncNm :: String -> String
+prettyFuncNm m = case break (== '@') m of
+                   (nm, '@':'(':tp) | not (null tp) -> dropWhileEnd (== ' ') nm ++ " :: " ++ init tp
+                   _                                -> m
+
+-- | Format group members on separate lines, aligned on @::@.
+groupLines :: [(String, LambdaInfo)] -> [String]
+groupLines ms = case map (prettyFuncNm . fst) ms of
+  []    -> []
+  names -> let parts    = [(nm, tp) | n <- names, let (nm, tp) = case break (== ':') n of
+                                                                    (a, ':':':':b) -> (dropWhileEnd (== ' ') a, " ::" ++ b)
+                                                                    _              -> (n, "")]
+               maxNm    = maximum (map (length . fst) parts)
+               pad s    = s ++ replicate (maxNm - length s) ' '
+               fmt (n, t) = "***     " ++ pad n ++ " " ++ t
+           in map fmt parts
+
+-- | Replay the DAG in a new state, building up an SV mapping from old to new.
+-- Recursive calls to the functions being verified are replaced with fresh variables.
+-- Calls to other DEFINED functions (present in the parent state's rDefns) are replayed as actual calls.
+-- All other Uninterpreted references (uninterpreted constants, free functions, sentinels)
+-- are replaced with fresh variables since they aren't defined in the fresh proveWith session.
+replayDAG :: SMTConfig -> State -> Set.Set String -> Set.Set String -> Map.Map SV SV -> [(SV, SBVExpr)] -> IO (Map.Map SV SV)
+replayDAG cfg st recFuncNames definedFuncs startMap dag = do
+  let n = length dag
+  let nms = intercalate ", " (map unBar (Set.toList recFuncNames))
+  debug cfg ["[MEASURE] replayDAG {" <> T.pack nms <> "}: replaying " <> showText n <> " node(s)"]
+  go startMap dag
+  where -- Map an SV through the svMap. If it's not found, it's an external captured variable
+        -- (e.g., from a higher-order function's closure). Create a fresh unconstrained variable
+        -- for it to avoid leaking foreign-context SVals into the current state.
+        mapArg svMap a = case Map.lookup a svMap of
+                           Just a' -> pure (a', svMap)
+                           Nothing -> do fresh <- newInternalVariable st (kindOf a)
+                                         pure (fresh, Map.insert a fresh svMap)
+
+        mapArgs svMap []     = pure ([], svMap)
+        mapArgs svMap (a:as) = do (a',  svMap')  <- mapArg svMap a
+                                  (as', svMap'') <- mapArgs svMap' as
+                                  pure (a':as', svMap'')
+
+        go svMap []                = pure svMap
+        go svMap ((sv, expr):rest) = do
+          let SBVApp op args = expr
+          (mappedArgs, svMap') <- mapArgs svMap args
+          newSV' <- case op of
+                      -- For recursive calls (self or mutual), create a fresh uninterpreted value instead of replaying
+                      Uninterpreted nm | nm `Set.member` Set.map T.pack recFuncNames -> newInternalVariable st (kindOf sv)
+                      -- For calls to other defined functions (e.g., partition), replay properly
+                      Uninterpreted nm | nm `Set.member` Set.map T.pack definedFuncs -> do
+                                          let mappedOp = mapOpSVs (\a -> Map.findWithDefault a a svMap') op
+                                          newExpr st (kindOf sv) (SBVApp mappedOp mappedArgs)
+                      -- For everything else that's Uninterpreted (free functions, sentinels, etc.),
+                      -- create fresh values since they aren't defined in the proveWith session
+                      Uninterpreted{} -> newInternalVariable st (kindOf sv)
+                      -- For all other operations (arithmetic, list ops, etc.), replay properly
+                      _ -> do let mappedOp = mapOpSVs (\a -> Map.findWithDefault a a svMap') op
+                              newExpr st (kindOf sv) (SBVApp mappedOp mappedArgs)
+          go (Map.insert sv newSV' svMap') rest
+
+-- | Map any SVs embedded directly in an Op (e.g., in LkUp, FP_Cast)
+mapOpSVs :: (SV -> SV) -> Op -> Op
+mapOpSVs f (LkUp p sv1 sv2)                  = LkUp p (f sv1) (f sv2)
+mapOpSVs f (IEEEFP (FP_Cast fk tk sv))       = IEEEFP (FP_Cast fk tk (f sv))
+mapOpSVs _ (ArrayInit (Right (SMTLambda s)))  = ArrayInit (Right (SMTLambda s))  -- Lambda strings don't contain SVs to map
+mapOpSVs _ op                                 = op
+
+-- | Compute the reaching condition for each SV: under what boolean condition
+-- does the SV's value contribute to the output? Propagates conditions top-down
+-- through ITE, AND, and OR nodes. Each reaching condition is a list of
+-- @(condSV, polarity)@ pairs; the actual condition is the conjunction: for each
+-- pair, @condSV@ if polarity is 'True', @not condSV@ if polarity is 'False'.
+computeReachingConditions :: Seq.Seq (SV, SBVExpr) -> SV -> Map.Map SV [(SV, Bool)]
+computeReachingConditions asgns outSV = go initMap (reverse $ F.toList asgns)
+  where
+    -- The output's reaching condition is True (empty conjunction)
+    initMap = Map.singleton outSV []
+
+    go condMap [] = condMap
+    go condMap ((sv, SBVApp op args) : rest) =
+      case Map.lookup sv condMap of
+        Nothing -> go condMap rest  -- This SV doesn't contribute to the output
+        Just rc ->
+          let condMap' = case (op, args) of
+                (Ite, [c, t, e]) ->
+                  let condMapT = addReach t ((c, True)  : rc) condMap
+                      condMapE = addReach e ((c, False) : rc) condMapT
+                  in condMapE
+                -- For AND: each arg is only relevant when the other is True
+                (And, [a, b]) ->
+                  let condMapA = addReach a ((b, True) : rc) condMap
+                      condMapB = addReach b ((a, True) : rc) condMapA
+                  in condMapB
+                -- For OR: each arg is only relevant when the other is False
+                (Or, [a, b]) ->
+                  let condMapA = addReach a ((b, False) : rc) condMap
+                      condMapB = addReach b ((a, False) : rc) condMapA
+                  in condMapB
+                _ -> foldl' (\m a -> addReach a rc m) condMap args
+          in go condMap' rest
+
+    -- Add a reaching condition to an SV. For shared nodes, keep the first condition found
+    -- (most direct path from the output).
+    addReach sv rc m = Map.insertWith (\_ old -> old) sv rc m
+
+-- | Regular expressions can be compared for equality. Note that we diverge here from the equality
+-- in the concrete sense; i.e., the Eq instance does not match the symbolic case. This is a bit unfortunate,
+-- but unavoidable with the current design of how we "distinguish" operators. Hopefully shouldn't be a big deal,
+-- though one should be careful.
+instance EqSymbolic RegExp where
+  r1 .== r2 = SBV $ SVal KBool $ Right $ cache r
+    where r st = newExpr st KBool $ SBVApp (RegExOp (RegExEq r1 r2))  []
+
+  r1 ./= r2 = SBV $ SVal KBool $ Right $ cache r
+    where r st = newExpr st KBool $ SBVApp (RegExOp (RegExNEq r1 r2)) []
+
+-- | Symbolic Numbers. This is a simple class that simply incorporates all number like
+-- base types together, simplifying writing polymorphic type-signatures that work for all
+-- symbolic numbers, such as 'SWord8', 'SInt8' etc. For instance, we can write a generic
+-- list-minimum function as follows:
+--
+-- @
+--    mm :: SIntegral a => [SBV a] -> SBV a
+--    mm = foldr1 (\a b -> ite (a .<= b) a b)
+-- @
+--
+-- It is similar to the standard 'Integral' class, except ranging over symbolic instances.
+class (SymVal a, Num a, Num (SBV a), Bits a, Integral a) => SIntegral a
+
+-- 'SIntegral' Instances, skips Real/Float/Bool
+instance SIntegral Word8
+instance SIntegral Word16
+instance SIntegral Word32
+instance SIntegral Word64
+instance SIntegral Int8
+instance SIntegral Int16
+instance SIntegral Int32
+instance SIntegral Int64
+instance SIntegral Integer
+instance (KnownNat n, BVIsNonZero n) => SIntegral (WordN n)
+instance (KnownNat n, BVIsNonZero n) => SIntegral (IntN n)
+
+-- | Zero extend a bit-vector.
+zeroExtend :: forall n m bv. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                             , KnownNat m, BVIsNonZero m, SymVal (bv m)
+                             , n + 1 <= m
+                             , SIntegral (bv (m - n))
+                             , BVIsNonZero (m - n)
+                             ) => SBV (bv n)    -- ^ Input, of size @n@
+                               -> SBV (bv m)    -- ^ Output, of size @m@. @n < m@ must hold
+zeroExtend n = SBV $ svZeroExtend i (unSBV n)
+  where nv = intOfProxy (Proxy @n)
+        mv = intOfProxy (Proxy @m)
+        i  = fromIntegral (mv - nv)
+
+-- | Sign extend a bit-vector.
+signExtend :: forall n m bv. ( KnownNat n, BVIsNonZero n, SymVal (bv n)
+                             , KnownNat m, BVIsNonZero m, SymVal (bv m)
+                             , n + 1 <= m
+                             , SFiniteBits (bv n)
+                             , SIntegral   (bv (m - n))
+                             , BVIsNonZero (m - n)
+                             ) => SBV (bv n)  -- ^ Input, of size @n@
+                               -> SBV (bv m)  -- ^ Output, of size @m@. @n < m@ must hold
+signExtend n = SBV $ svSignExtend i (unSBV n)
+  where nv = intOfProxy (Proxy @n)
+        mv = intOfProxy (Proxy @m)
+        i  = fromIntegral (mv - nv)
+
+
+-- | 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 (Ord a, SymVal a, Num a, Num (SBV a), OrdSymbolic (SBV a), Bits a) => SFiniteBits a where
+    -- | Bit size.
+    sFiniteBitSize      :: SBV a -> Int
+    -- | Least significant bit of a word, always stored at index 0.
+    lsb                 :: SBV a -> SBool
+    -- | Most significant bit of a word, always stored at the last position.
+    msb                 :: SBV a -> SBool
+    -- | Big-endian blasting of a word into its bits.
+    blastBE             :: SBV a -> [SBool]
+    -- | Little-endian blasting of a word into its bits.
+    blastLE             :: SBV a -> [SBool]
+    -- | Reconstruct from given bits, given in little-endian.
+    fromBitsBE          :: [SBool] -> SBV a
+    -- | Reconstruct from given bits, given in little-endian.
+    fromBitsLE          :: [SBool] -> SBV a
+    -- | Replacement for 'testBit', returning 'SBool' instead of 'Bool'.
+    sTestBit            :: SBV a -> Int -> SBool
+    -- | Variant of 'sTestBit', where we want to extract multiple bit positions.
+    sExtractBits        :: SBV a -> [Int] -> [SBool]
+    -- | Variant of 'popCount', returning a symbolic value.
+    sPopCount           :: SBV a -> SWord8
+    -- | A combo of 'setBit' and 'clearBit', when the bit to be set is symbolic.
+    setBitTo            :: SBV a -> Int -> SBool -> SBV a
+    -- | Variant of 'setBitTo' when the index is symbolic. If the index it out-of-bounds,
+    -- then the result is underspecified.
+    sSetBitTo           :: Integral a => SBV a -> SBV a -> SBool -> SBV a
+    -- | Full adder, returns carry-out from the addition. Only for unsigned quantities.
+    fullAdder           :: SBV a -> SBV a -> (SBool, SBV a)
+    -- | Full multiplier, returns both high and low-order bits. Only for unsigned quantities.
+    fullMultiplier      :: SBV a -> SBV a -> (SBV a, SBV a)
+    -- | Count leading zeros in a word, big-endian interpretation.
+    sCountLeadingZeros  :: SBV a -> SWord8
+    -- | Count trailing zeros in a word, big-endian interpretation.
+    sCountTrailingZeros :: SBV a -> SWord8
+
+    {-# MINIMAL sFiniteBitSize #-}
+
+    -- Default implementations
+    lsb (SBV v) = SBV (svTestBit v 0)
+    msb x       = sTestBit x (sFiniteBitSize x - 1)
+
+    blastBE   = reverse . blastLE
+    blastLE x = map (sTestBit x) [0 .. intSizeOf x - 1]
+
+    fromBitsBE = fromBitsLE . reverse
+    fromBitsLE bs
+       | length bs /= w
+       = error $ "SBV.SFiniteBits.fromBitsLE/BE: Expected: " ++ show w ++ " bits, received: " ++ show (length bs)
+       | True
+       = result
+       where w = sFiniteBitSize result
+             result = go 0 0 bs
+
+             go !acc _  []     = acc
+             go !acc !i (x:xs) = go (ite x (setBit acc i) acc) (i+1) xs
+
+    sTestBit (SBV x) i = SBV (svTestBit x i)
+    sExtractBits x     = map (sTestBit x)
+
+    -- NB. 'sPopCount' returns an 'SWord8', which can overflow when used on quantities that have
+    -- more than 255 bits. For the regular interface, this suffices for all types we support.
+    -- For the Dynamic interface, if we ever implement this, this will fail for bit-vectors
+    -- larger than that many bits. The alternative would be to return SInteger here, but that
+    -- seems a total overkill for most use cases. If such is required, users are encouraged
+    -- to define their own variants, which is rather easy.
+    sPopCount x
+      | Just v <- unliteral x = go 0 v
+      | True                  = sum [ite b 1 0 | b <- blastLE x]
+      where -- concrete case
+            go !c 0 = c
+            go !c w = go (c+1) (w .&. (w-1))
+
+    setBitTo x i b = ite b (setBit x i) (clearBit x i)
+
+    sSetBitTo x idx b
+      | Just i <- unliteral idx, Just index <- safe i
+      = setBitTo x index b
+      | True
+      = go x [0 .. sFiniteBitSize x - 1]
+      where -- paranoia check: make sure index can fit in an int
+            safe i = let asInteger   = toInteger i
+                         asInt       = fromIntegral asInteger
+                         backInteger = toInteger asInt
+                     in if backInteger == asInteger
+                        then Just asInt
+                        else Nothing
+
+            go v []     = v
+            go v (i:is) = go (ite (idx .== literal (fromIntegral i)) (setBitTo v (fromIntegral i) b) v) is
+
+    fullAdder a b
+      | isSigned a = error "fullAdder: only works on unsigned numbers"
+      | True       = (a .> s .|| b .> s, s)
+      where s = a + b
+
+    -- N.B. The higher-order bits are determined using a simple shift-add multiplier,
+    -- thus involving bit-blasting. It'd be naive to expect SMT solvers to deal efficiently
+    -- with properties involving this function, at least with the current state of the art.
+    fullMultiplier a b
+      | isSigned a = error "fullMultiplier: only works on unsigned numbers"
+      | True       = (go (sFiniteBitSize a) 0 a, a*b)
+      where go 0 p _ = p
+            go n p x = let (c, p')  = ite (lsb x) (fullAdder p b) (sFalse, p)
+                           (o, p'') = shiftIn c p'
+                           (_, x')  = shiftIn o x
+                       in go (n-1) p'' x'
+            shiftIn k v = (lsb v, mask .|. (v `shiftR` 1))
+               where mask = ite k (bit (sFiniteBitSize v - 1)) 0
+
+    -- See the note for 'sPopCount' for a comment on why we return 'SWord8'
+    sCountLeadingZeros x = fromIntegral m - go m
+      where m = sFiniteBitSize x - 1
+
+            -- NB. When i is 0 below, which happens when x is 0 as we count all the way down,
+            -- we return -1, which is equal to 2^n-1, giving us: n-1-(2^n-1) = n-2^n = n, as required, i.e., the bit-size.
+            go :: Int -> SWord8
+            go i | i < 0 = i8
+                 | True  = ite (sTestBit x i) i8 (go (i-1))
+               where i8 = literal (fromIntegral i :: Word8)
+
+    -- See the note for 'sPopCount' for a comment on why we return 'SWord8'
+    sCountTrailingZeros x = go 0
+       where m = sFiniteBitSize x
+
+             go :: Int -> SWord8
+             go i | i >= m = i8
+                  | True   = ite (sTestBit x i) i8 (go (i+1))
+                where i8 = literal (fromIntegral i :: Word8)
+
+-- 'SFiniteBits' Instances, skips Real/Float/Bool/Integer
+instance SFiniteBits Word8  where sFiniteBitSize _ =  8
+instance SFiniteBits Word16 where sFiniteBitSize _ = 16
+instance SFiniteBits Word32 where sFiniteBitSize _ = 32
+instance SFiniteBits Word64 where sFiniteBitSize _ = 64
+instance SFiniteBits Int8   where sFiniteBitSize _ =  8
+instance SFiniteBits Int16  where sFiniteBitSize _ = 16
+instance SFiniteBits Int32  where sFiniteBitSize _ = 32
+instance SFiniteBits Int64  where sFiniteBitSize _ = 64
+instance (KnownNat n, BVIsNonZero n) => SFiniteBits (WordN n) where sFiniteBitSize _ = intOfProxy (Proxy @n)
+instance (KnownNat n, BVIsNonZero n) => SFiniteBits (IntN  n) where sFiniteBitSize _ = intOfProxy (Proxy @n)
+
+-- | Returns 1 if the boolean is 'sTrue', otherwise 0.
+oneIf :: (Ord a, Num (SBV a), SymVal a) => SBool -> SBV a
+oneIf t = ite t 1 0
+
+-- | Lift a pseudo-boolean op, performing checks
+liftPB :: String -> PBOp -> [SBool] -> SBool
+liftPB w o xs
+  | Just e <- check o
+  = error $ "SBV." ++ w ++ ": " ++ e
+  | True
+  = result
+  where check (PB_AtMost  k) = pos k
+        check (PB_AtLeast k) = pos k
+        check (PB_Exactly k) = pos k
+        check (PB_Le cs   k) = pos k `mplus` match cs
+        check (PB_Ge cs   k) = pos k `mplus` match cs
+        check (PB_Eq cs   k) = pos k `mplus` match cs
+
+        pos k
+          | k < 0 = Just $ "comparison value must be positive, received: " ++ show k
+          | True  = Nothing
+
+        match cs
+          | any (< 0) cs = Just $ "coefficients must be non-negative. Received: " ++ show cs
+          | lxs /= lcs   = Just $ "coefficient length must match number of arguments. Received: " ++ show (lcs, lxs)
+          | True         = Nothing
+          where lxs = length xs
+                lcs = length cs
+
+        result = SBV (SVal KBool (Right (cache r)))
+        r st   = do xsv <- mapM (sbvToSV st) xs
+                    -- PseudoBoolean's implicitly require support for integers, so make sure to register that kind!
+                    registerKind st KUnbounded
+                    newExpr st KBool (SBVApp (PseudoBoolean o) xsv)
+
+-- | 'sTrue' if at most @k@ of the input arguments are 'sTrue'
+pbAtMost :: [SBool] -> Int -> SBool
+pbAtMost xs k
+ | k < 0             = error $ "SBV.pbAtMost: Non-negative value required, received: " ++ show k
+ | all isConcrete xs = literal $ sum (map (pbToInteger "pbAtMost" 1) xs) <= fromIntegral k
+ | True              = liftPB "pbAtMost" (PB_AtMost k) xs
+
+-- | 'sTrue' if at least @k@ of the input arguments are 'sTrue'
+pbAtLeast :: [SBool] -> Int -> SBool
+pbAtLeast xs k
+ | k < 0             = error $ "SBV.pbAtLeast: Non-negative value required, received: " ++ show k
+ | all isConcrete xs = literal $ sum (map (pbToInteger "pbAtLeast" 1) xs) >= fromIntegral k
+ | True              = liftPB "pbAtLeast" (PB_AtLeast k) xs
+
+-- | 'sTrue' if exactly @k@ of the input arguments are 'sTrue'
+pbExactly :: [SBool] -> Int -> SBool
+pbExactly xs k
+ | k < 0             = error $ "SBV.pbExactly: Non-negative value required, received: " ++ show k
+ | all isConcrete xs = literal $ sum (map (pbToInteger "pbExactly" 1) xs) == fromIntegral k
+ | True              = liftPB "pbExactly" (PB_Exactly k) xs
+
+-- | 'sTrue' if the sum of coefficients for 'sTrue' elements is at most @k@. Generalizes 'pbAtMost'.
+pbLe :: [(Int, SBool)] -> Int -> SBool
+pbLe xs k
+ | k < 0                     = error $ "SBV.pbLe: Non-negative value required, received: " ++ show k
+ | all (isConcrete . snd) xs = literal $ sum [pbToInteger "pbLe" c b | (c, b) <- xs] <= fromIntegral k
+ | True                      = liftPB "pbLe" (PB_Le (map fst xs) k) (map snd xs)
+
+-- | 'sTrue' if the sum of coefficients for 'sTrue' elements is at least @k@. Generalizes 'pbAtLeast'.
+pbGe :: [(Int, SBool)] -> Int -> SBool
+pbGe xs k
+ | k < 0                     = error $ "SBV.pbGe: Non-negative value required, received: " ++ show k
+ | all (isConcrete . snd) xs = literal $ sum [pbToInteger "pbGe" c b | (c, b) <- xs] >= fromIntegral k
+ | True                      = liftPB "pbGe" (PB_Ge (map fst xs) k) (map snd xs)
+
+-- | 'sTrue' if the sum of coefficients for 'sTrue' elements is exactly least @k@. Useful for coding
+-- /exactly K-of-N/ constraints, and in particular mutex constraints.
+pbEq :: [(Int, SBool)] -> Int -> SBool
+pbEq xs k
+ | k < 0                     = error $ "SBV.pbEq: Non-negative value required, received: " ++ show k
+ | all (isConcrete . snd) xs = literal $ sum [pbToInteger "pbEq" c b | (c, b) <- xs] == fromIntegral k
+ | True                      = liftPB "pbEq" (PB_Eq (map fst xs) k) (map snd xs)
+
+-- | 'sTrue' if there is at most one set bit
+pbMutexed :: [SBool] -> SBool
+pbMutexed xs = pbAtMost xs 1
+
+-- | 'sTrue' if there is exactly one set bit
+pbStronglyMutexed :: [SBool] -> SBool
+pbStronglyMutexed xs = pbExactly xs 1
+
+-- | Convert a concrete pseudo-boolean to given int; converting to integer
+pbToInteger :: String -> Int -> SBool -> Integer
+pbToInteger w c b
+ | c < 0                 = error $ "SBV." ++ w ++ ": Non-negative coefficient required, received: " ++ show c
+ | Just v <- unliteral b = if v then fromIntegral c else 0
+ | True                  = error $ "SBV.pbToInteger: Received a symbolic boolean: " ++ show (c, b)
+
+-- | Predicate for optimizing word operations like (+) and (*).
+isConcreteZero :: SBV a -> Bool
+isConcreteZero (SBV (SVal _     (Left (CV _     (CInteger n))))) = n == 0
+isConcreteZero (SBV (SVal KReal (Left (CV KReal (CAlgReal v))))) = isExactRational v && v == 0
+isConcreteZero _                                                 = False
+
+-- | Predicate for optimizing word operations like (+) and (*).
+isConcreteOne :: SBV a -> Bool
+isConcreteOne (SBV (SVal _     (Left (CV _     (CInteger 1))))) = True
+isConcreteOne (SBV (SVal KReal (Left (CV KReal (CAlgReal v))))) = isExactRational v && v == 1
+isConcreteOne _                                                 = False
+
+-- | Symbolic exponentiation using bit blasting and repeated squaring.
+--
+-- N.B. The exponent must be unsigned/bounded if symbolic. Signed exponents will be rejected.
+(.^) :: (Mergeable b, Num b, SIntegral e) => b -> SBV e -> b
+b .^ e
+  | isConcrete e, Just (x :: Integer) <- unliteral (sFromIntegral e)
+  = if x >= 0 then let go n v
+                        | n == 0 = 1
+                        | even n =     go (n `div` 2) (v * v)
+                        | True   = v * go (n `div` 2) (v * v)
+                   in  go x b
+              else error $ "(.^): exponentiation: negative exponent: " ++ show x
+  | not (isBounded e) || isSigned e
+  = error $ "(.^): exponentiation only works with unsigned bounded symbolic exponents, kind: " ++ show (kindOf e)
+  | True
+  =  -- NB. We can't simply use sTestBit and blastLE since they have SFiniteBit requirement
+     -- but we want to have SIntegral here only.
+     let SBV expt = e
+         expBit i = SBV (svTestBit expt i)
+         blasted  = map expBit [0 .. intSizeOf e - 1]
+     in product $ zipWith (\use n -> ite use n 1)
+                          blasted
+                          (iterate (\x -> x*x) b)
+infixr 8 .^
+
+instance (Ord a, Num (SBV 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
+       where res  = SBV (svDivide x y)
+             -- Identify those kinds where we have a div-0 equals 0 exception
+             div0 = case kindOf sy of
+                      KVar{}             -> error $ "Unexpected Fractional case for: " ++ show (kindOf sy)
+                      KFloat             -> False
+                      KDouble            -> False
+                      KFP{}              -> False
+                      KReal              -> True
+                      KRational          -> True
+                      -- Following cases should not happen since these types should *not* be instances of Fractional
+                      k@KBounded{}  -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KUnbounded  -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KBool       -> error $ "Unexpected Fractional case for: " ++ show k
+                      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@KApp{}      -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KADT{}      -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KTuple{}    -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KArray{}    -> error $ "Unexpected Fractional case for: " ++ show k
+
+-- | Define Floating instance on SBV's; only for base types that are already floating; i.e., 'SFloat', 'SDouble', and 'SReal'.
+-- (See the separate definition below for 'SFloatingPoint'.)  Note that unless you use delta-sat via 'Data.SBV.Provers.dReal' on 'SReal', most
+-- of the fields are "undefined" for symbolic values. We will add methods as they are supported by SMTLib. Currently, the
+-- only symbolically available function in this class is 'sqrt' for 'SFloat', 'SDouble' and 'SFloatingPoint'.
+instance (Ord a, Num (SBV a), SymVal a, Fractional a, Floating a) => Floating (SBV a) where
+  pi      = fromRational . toRational $ (pi :: Double)
+  exp     = lift1FNS "exp"     exp
+  log     = lift1FNS "log"     log
+  sqrt    = lift1F   FP_Sqrt   sqrt
+  sin     = lift1FNS "sin"     sin
+  cos     = lift1FNS "cos"     cos
+  tan     = lift1FNS "tan"     tan
+  asin    = lift1FNS "asin"    asin
+  acos    = lift1FNS "acos"    acos
+  atan    = lift1FNS "atan"    atan
+  sinh    = lift1FNS "sinh"    sinh
+  cosh    = lift1FNS "cosh"    cosh
+  tanh    = lift1FNS "tanh"    tanh
+  asinh   = lift1FNS "asinh"   asinh
+  acosh   = lift1FNS "acosh"   acosh
+  atanh   = lift1FNS "atanh"   atanh
+  (**)    = lift2FNS "**"      (**)
+  logBase = lift2FNS "logBase" logBase
+
+unsupported :: String -> a
+unsupported w = error $ "Data.SBV.FloatingPoint: Unsupported operation: " ++ w ++ ". Please request this as a feature!"
+
+-- | We give a specific instance for 'SFloatingPoint', because the underlying floating-point type doesn't support
+-- fromRational directly. The overlap with the above instance is unfortunate.
+instance {-# OVERLAPPING #-} ValidFloat eb sb => Floating (SFloatingPoint eb sb) where
+  -- Try from double; if there's enough precision this'll work, otherwise will bail out.
+  pi
+   | ei > 11 || si > 53 = unsupported $ "Floating.SFloatingPoint.pi (not-enough-precision for " ++ show (ei, si) ++ ")"
+   | True               = literal $ FloatingPoint $ fpFromRational ei si (toRational (pi :: Double))
+   where ei = intOfProxy (Proxy @eb)
+         si = intOfProxy (Proxy @sb)
+
+  -- Likewise, exponentiation is again limited to precision of double
+  exp i
+   | ei > 11 || si > 53 = unsupported $ "Floating.SFloatingPoint.exp (not-enough-precision for " ++ show (ei, si) ++ ")"
+   | True               = literal e ** i
+   where ei = intOfProxy (Proxy @eb)
+         si = intOfProxy (Proxy @sb)
+         e  = FloatingPoint $ fpFromRational ei si (toRational (exp 1 :: Double))
+
+  log     = lift1FNS "log"     log
+  sqrt    = lift1F   FP_Sqrt   sqrt
+  sin     = lift1FNS "sin"     sin
+  cos     = lift1FNS "cos"     cos
+  tan     = lift1FNS "tan"     tan
+  asin    = lift1FNS "asin"    asin
+  acos    = lift1FNS "acos"    acos
+  atan    = lift1FNS "atan"    atan
+  sinh    = lift1FNS "sinh"    sinh
+  cosh    = lift1FNS "cosh"    cosh
+  tanh    = lift1FNS "tanh"    tanh
+  asinh   = lift1FNS "asinh"   asinh
+  acosh   = lift1FNS "acosh"   acosh
+  atanh   = lift1FNS "atanh"   atanh
+  (**)    = lift2FNS "**"      (**)
+  logBase = lift2FNS "logBase" logBase
+
+-- | Lift a 1 arg FP-op, using sRNE default
+lift1F :: SymVal a => FPOp -> (a -> a) -> SBV a -> SBV a
+lift1F w op a
+  | Just v <- unliteral a
+  = literal $ op v
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do swa  <- sbvToSV st a
+                  swm  <- sbvToSV st sRNE
+                  newExpr st k (SBVApp (IEEEFP w) [swm, swa])
+
+-- | Lift a float/double unary function, only over constants
+lift1FNS :: (SymVal a, Floating a) => String -> (a -> a) -> SBV a -> SBV a
+lift1FNS nm f sv
+  | Just v <- unliteral sv = literal $ f v
+  | True                   = error $ "SBV." ++ nm ++ ": not supported for symbolic values of type " ++ show (kindOf sv)
+
+-- | Lift a float/double binary function, only over constants
+lift2FNS :: (SymVal a, Floating a) => String -> (a -> a -> a) -> SBV a -> SBV a -> SBV a
+lift2FNS nm f sv1 sv2
+  | Just v1 <- unliteral sv1
+  , Just v2 <- unliteral sv2 = literal $ f v1 v2
+  | True                     = error $ "SBV." ++ nm ++ ": not supported for symbolic values of type " ++ show (kindOf sv1)
+
+-- | SReal Floating instance, used in conjunction with the dReal solver for delta-satisfiability. Note that
+-- we do not constant fold these values (except for pi), as Haskell doesn't really have any means of computing
+-- them for arbitrary rationals.
+instance {-# OVERLAPPING #-} Floating SReal where
+  -- Should we support pi? It's a transcendental value, and our SReal type has no way of representing
+  -- this quantity with the required fidelity. (SReal can only support roots of polynomials and rationals
+  -- correctly, not transcendentals.) One option is to use an approximation here. But that goes against the
+  -- whole idea of Real being infinitely precise. Another option is to see if the solver has support for it, such
+  -- as CVC5, which has the constant real.pi. Alas, that has its problems: In models CVC5 uses real.pi as a
+  -- model value, which we have no way of properly supporting back as a Haskell value. Worse: It uses it in
+  -- expressions like 1 + real.pi, which we don't have an evaluator for. So, we simply say not supported.
+  -- If you want it for reals, you'll have to plugin your own "approximation" for it, and thus be aware of the
+  -- limitations of that choice.
+  pi      = error $ unlines [ ""
+                            , "*** Data.SBV.SReal: Cannot represent pi as an SReal value."
+                            , "***"
+                            , "*** Usual trick is to use an approximation if that suits your purpose,"
+                            , "*** or use solver-specific constants when applicable. Please get in touch"
+                            , "*** if you'd like to explore ideas here."
+                            ]
+
+  exp     = lift1SReal NR_Exp
+  log     = lift1SReal NR_Log
+  sqrt    = lift1SReal NR_Sqrt
+  sin     = lift1SReal NR_Sin
+  cos     = lift1SReal NR_Cos
+  tan     = lift1SReal NR_Tan
+  asin    = lift1SReal NR_ASin
+  acos    = lift1SReal NR_ACos
+  atan    = lift1SReal NR_ATan
+  sinh    = lift1SReal NR_Sinh
+  cosh    = lift1SReal NR_Cosh
+  tanh    = lift1SReal NR_Tanh
+  asinh   = error "Data.SBV.SReal: asinh is currently not supported. Please request this as a feature!"
+  acosh   = error "Data.SBV.SReal: acosh is currently not supported. Please request this as a feature!"
+  atanh   = error "Data.SBV.SReal: atanh is currently not supported. Please request this as a feature!"
+  (**)    = lift2SReal NR_Pow
+
+  logBase x y = log y  / log x
+
+-- | Lift an sreal unary function
+lift1SReal :: NROp -> SReal -> SReal
+lift1SReal w a = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do swa <- sbvToSV st a
+                  newExpr st k (SBVApp (NonLinear w) [swa])
+
+-- | Lift an sreal binary function
+lift2SReal :: NROp -> SReal -> SReal -> SReal
+lift2SReal w a b = SBV $ SVal k $ Right $ cache r
+  where k    = kindOf a
+        r st = do swa <- sbvToSV st a
+                  swb <- sbvToSV st b
+                  newExpr st k (SBVApp (NonLinear w) [swa, swb])
+
+-- 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'!.)"
+                                      ]
+
+-- | This instance is only defined so that we can define an instance for
+-- 'Data.Bits.Bits'. '==' and '/=' simply throw an error. Use
+-- 'Data.SBV.EqSymbolic' instead.
+instance SymVal a => Eq (SBV a) where
+  a == b = fromMaybe (noEquals "==" ".==" (show a, show b)) (unliteral (a .== b))
+  a /= b = fromMaybe (noEquals "/=" "./=" (show a, show b)) (unliteral (a ./= b))
+
+-- NB. In the optimizations below, use of -1 is valid as
+-- -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 (Ord a, Num (SBV 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)
+  complement (SBV x) = SBV (svNot x)
+  bitSize  x         = intSizeOf x
+  bitSizeMaybe x     = Just $ intSizeOf x
+  isSigned x         = hasSign x
+  bit i              = 1 `shiftL` i
+  setBit        x i  = x .|. genLiteral (kindOf x) (bit i :: Integer)
+  clearBit      x i  = x .&. genLiteral (kindOf x) (complement (bit i) :: Integer)
+  complementBit x i  = x `xor` genLiteral (kindOf x) (bit i :: Integer)
+  shiftL  (SBV x) i  = SBV (svShl x i)
+  shiftR  (SBV x) i  = SBV (svShr x i)
+  rotateL (SBV x) i  = SBV (svRol x i)
+  rotateR (SBV x) i  = SBV (svRor x i)
+  -- NB. testBit is *not* implementable on non-concrete symbolic words
+  x `testBit` i
+    | SBV (SVal _ (Left (CV _ (CInteger n)))) <- x
+    = testBit n i
+    | True
+    = error $ "SBV.testBit: Called on symbolic value: " ++ show x ++ ". Use sTestBit instead."
+  -- NB. popCount is *not* implementable on non-concrete symbolic words
+  popCount x
+    | SBV (SVal _ (Left (CV (KBounded _ w) (CInteger n)))) <- x
+    = popCount (n .&. (bit w - 1))
+    | True
+    = error $ "SBV.popCount: Called on symbolic value: " ++ show x ++ ". Use sPopCount instead."
+
+-- | Conversion between integral-symbolic values, akin to Haskell's `fromIntegral`
+sFromIntegral :: forall a b. (Integral a, HasKind a, Num a, SymVal a, HasKind b, Num b, SymVal b) => SBV a -> SBV b
+sFromIntegral x
+  | kFrom == kTo
+  = SBV (unSBV x)
+  | isReal x
+  = error "SBV.sFromIntegral: Called on a real value" -- can't really happen due to types, but being overcautious
+  | Just v <- unliteral x
+  = literal (fromIntegral v)
+  | True
+  = result
+  where result = SBV (SVal kTo (Right (cache y)))
+        kFrom  = kindOf x
+        kTo    = kindOf (Proxy @b)
+        y st   = do xsv <- sbvToSV st x
+                    newExpr st kTo (SBVApp (KindCast kFrom kTo) [xsv])
+
+-- | Lift a binary operation thru its dynamic counterpart. Note that
+-- we still want the actual functions here as differ in their type
+-- compared to their dynamic counterparts, but the implementations
+-- are the same.
+liftViaSVal :: (SVal -> SVal -> SVal) -> SBV a -> SBV b -> SBV c
+liftViaSVal f (SBV a) (SBV b) = SBV $ f a b
+
+-- | Generalization of 'shiftL', when the shift-amount is symbolic. Since Haskell's
+-- 'shiftL' only takes an 'Int' as the shift amount, it cannot be used when we have
+-- a symbolic amount to shift with.
+sShiftLeft :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
+sShiftLeft = liftViaSVal svShiftLeft
+
+-- | Generalization of 'shiftR', when the shift-amount is symbolic. Since Haskell's
+-- 'shiftR' only takes an 'Int' as the shift amount, it cannot be used when we have
+-- a symbolic amount to shift with.
+--
+-- NB. If the shiftee is signed, then this is an arithmetic shift; otherwise it's logical,
+-- following the usual Haskell convention. See 'sSignedShiftArithRight' for a variant
+-- that explicitly uses the msb as the sign bit, even for unsigned underlying types.
+sShiftRight :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
+sShiftRight = liftViaSVal svShiftRight
+
+-- | Arithmetic shift-right with a symbolic unsigned shift amount. This is equivalent
+-- to 'sShiftRight' when the argument is signed. However, if the argument is unsigned,
+-- then it explicitly treats its msb as a sign-bit, and uses it as the bit that
+-- gets shifted in. Useful when using the underlying unsigned bit representation to implement
+-- custom signed operations. Note that there is no direct Haskell analogue of this function.
+sSignedShiftArithRight:: (SFiniteBits a, SIntegral b) => SBV a -> SBV b -> SBV a
+sSignedShiftArithRight x i
+  | isSigned i = error "sSignedShiftArithRight: shift amount should be unsigned"
+  | isSigned x = ssa x i
+  | True       = ite (msb x)
+                     (complement (ssa (complement x) i))
+                     (ssa x i)
+  where ssa = liftViaSVal svShiftRight
+
+-- | 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) => 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 bit-vectors, 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`.
+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) => 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.
+sBarrelRotateRight :: (SFiniteBits a, SFiniteBits b) => SBV a -> SBV b -> SBV a
+sBarrelRotateRight = liftViaSVal svBarrelRotateRight
+
+-- | Capturing non-matching instances for better error messages, conversions from sized
+type FromSizedErr (arg :: Type) =     'Text "fromSized: Cannot convert from type: " ':<>: 'ShowType arg
+                                ':$$: 'Text "           Source type must be one of SInt N, SWord N, IntN N, WordN N"
+                                ':$$: 'Text "           where N is 8, 16, 32, or 64."
+
+-- | Capturing non-matching instances for better error messages, conversions to sized
+type ToSizedErr (arg :: Type) =      'Text "toSized: Cannot convert from type: " ':<>: 'ShowType arg
+                              ':$$: 'Text "          Source type must be one of Int8/16/32/64"
+                              ':$$: 'Text "                                  OR Word8/16/32/64"
+                              ':$$: 'Text "                                  OR their symbolic variants."
+
+-- | Capture the correspondence between sized and fixed-sized BVs
+type family FromSized (t :: Type) :: Type where
+   FromSized (WordN  8) = Word8
+   FromSized (WordN 16) = Word16
+   FromSized (WordN 32) = Word32
+   FromSized (WordN 64) = Word64
+   FromSized (IntN   8) = Int8
+   FromSized (IntN  16) = Int16
+   FromSized (IntN  32) = Int32
+   FromSized (IntN  64) = Int64
+   FromSized (SWord  8) = SWord8
+   FromSized (SWord 16) = SWord16
+   FromSized (SWord 32) = SWord32
+   FromSized (SWord 64) = SWord64
+   FromSized (SInt   8) = SInt8
+   FromSized (SInt  16) = SInt16
+   FromSized (SInt  32) = SInt32
+   FromSized (SInt  64) = SInt64
+
+-- | Capture the correspondence, in terms of a constraint
+type family FromSizedCstr (t :: Type) :: Constraint where
+   FromSizedCstr (WordN  8) = ()
+   FromSizedCstr (WordN 16) = ()
+   FromSizedCstr (WordN 32) = ()
+   FromSizedCstr (WordN 64) = ()
+   FromSizedCstr (IntN   8) = ()
+   FromSizedCstr (IntN  16) = ()
+   FromSizedCstr (IntN  32) = ()
+   FromSizedCstr (IntN  64) = ()
+   FromSizedCstr (SWord  8) = ()
+   FromSizedCstr (SWord 16) = ()
+   FromSizedCstr (SWord 32) = ()
+   FromSizedCstr (SWord 64) = ()
+   FromSizedCstr (SInt   8) = ()
+   FromSizedCstr (SInt  16) = ()
+   FromSizedCstr (SInt  32) = ()
+   FromSizedCstr (SInt  64) = ()
+   FromSizedCstr arg        = TypeError (FromSizedErr arg)
+
+-- | Conversion from a sized BV to a fixed-sized bit-vector.
+class FromSizedBV a where
+   -- | Convert a sized bit-vector to the corresponding fixed-sized bit-vector,
+   -- for instance 'SWord 16' to 'SWord16'. See also 'toSized'.
+   fromSized :: a -> FromSized a
+
+   default fromSized :: (Num (FromSized a), Integral a) => a -> FromSized a
+   fromSized = fromIntegral
+
+instance {-# OVERLAPPING  #-} FromSizedBV (WordN   8)
+instance {-# OVERLAPPING  #-} FromSizedBV (WordN  16)
+instance {-# OVERLAPPING  #-} FromSizedBV (WordN  32)
+instance {-# OVERLAPPING  #-} FromSizedBV (WordN  64)
+instance {-# OVERLAPPING  #-} FromSizedBV (IntN    8)
+instance {-# OVERLAPPING  #-} FromSizedBV (IntN   16)
+instance {-# OVERLAPPING  #-} FromSizedBV (IntN   32)
+instance {-# OVERLAPPING  #-} FromSizedBV (IntN   64)
+instance {-# OVERLAPPING  #-} FromSizedBV (SWord   8) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SWord  16) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SWord  32) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SWord  64) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SInt    8) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SInt   16) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SInt   32) where fromSized = sFromIntegral
+instance {-# OVERLAPPING  #-} FromSizedBV (SInt   64) where fromSized = sFromIntegral
+instance {-# OVERLAPPABLE #-} FromSizedCstr arg => FromSizedBV arg where fromSized = error "unreachable"
+
+-- | Capture the correspondence between fixed-sized and sized BVs
+type family ToSized (t :: Type) :: Type where
+   ToSized Word8   = WordN  8
+   ToSized Word16  = WordN 16
+   ToSized Word32  = WordN 32
+   ToSized Word64  = WordN 64
+   ToSized Int8    = IntN   8
+   ToSized Int16   = IntN  16
+   ToSized Int32   = IntN  32
+   ToSized Int64   = IntN  64
+   ToSized SWord8  = SWord  8
+   ToSized SWord16 = SWord 16
+   ToSized SWord32 = SWord 32
+   ToSized SWord64 = SWord 64
+   ToSized SInt8   = SInt   8
+   ToSized SInt16  = SInt  16
+   ToSized SInt32  = SInt  32
+   ToSized SInt64  = SInt  64
+
+-- | Capture the correspondence in terms of a constraint
+type family ToSizedCstr (t :: Type) :: Constraint where
+   ToSizedCstr Word8   = ()
+   ToSizedCstr Word16  = ()
+   ToSizedCstr Word32  = ()
+   ToSizedCstr Word64  = ()
+   ToSizedCstr Int8    = ()
+   ToSizedCstr Int16   = ()
+   ToSizedCstr Int32   = ()
+   ToSizedCstr Int64   = ()
+   ToSizedCstr SWord8  = ()
+   ToSizedCstr SWord16 = ()
+   ToSizedCstr SWord32 = ()
+   ToSizedCstr SWord64 = ()
+   ToSizedCstr SInt8   = ()
+   ToSizedCstr SInt16  = ()
+   ToSizedCstr SInt32  = ()
+   ToSizedCstr SInt64  = ()
+   ToSizedCstr arg     = TypeError (ToSizedErr arg)
+
+-- | Conversion from a fixed-sized BV to a sized bit-vector.
+class ToSizedBV a where
+   -- | Convert a fixed-sized bit-vector to the corresponding sized bit-vector,
+   -- for instance 'SWord16' to 'SWord 16'. See also 'fromSized'.
+   toSized :: a -> ToSized a
+
+   default toSized :: (Num (ToSized a), Integral a) => (a -> ToSized a)
+   toSized = fromIntegral
+
+instance {-# OVERLAPPING  #-} ToSizedBV Word8
+instance {-# OVERLAPPING  #-} ToSizedBV Word16
+instance {-# OVERLAPPING  #-} ToSizedBV Word32
+instance {-# OVERLAPPING  #-} ToSizedBV Word64
+instance {-# OVERLAPPING  #-} ToSizedBV Int8
+instance {-# OVERLAPPING  #-} ToSizedBV Int16
+instance {-# OVERLAPPING  #-} ToSizedBV Int32
+instance {-# OVERLAPPING  #-} ToSizedBV Int64
+instance {-# OVERLAPPING  #-} ToSizedBV SWord8  where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SWord16 where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SWord32 where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SWord64 where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SInt8   where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SInt16  where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SInt32  where toSized = sFromIntegral
+instance {-# OVERLAPPING  #-} ToSizedBV SInt64  where toSized = sFromIntegral
+instance {-# OVERLAPPABLE #-} ToSizedCstr arg => ToSizedBV arg where toSized = error "unreachable"
+
+-- | The 'SDivisible' class captures the essence of division.
+-- Unfortunately we cannot use Haskell's 'Integral' class since the 'Real'
+-- and 'Enum' superclasses are not implementable for symbolic bit-vectors.
+-- However, 'quotRem' and 'divMod' both make perfect sense, and the 'SDivisible' class captures
+-- this operation. One issue is how division by 0 behaves. The verification
+-- technology requires total functions, and there are several design choices
+-- here. We follow Isabelle/HOL approach of assigning the value 0 for division
+-- by 0. Therefore, we impose the following pair of laws:
+--
+-- @
+--      x `sQuotRem` 0 = (0, x)
+--      x `sDivMod`  0 = (0, x)
+-- @
+--
+-- Note that our instances implement this law even when @x@ is @0@ itself.
+--
+-- NB. 'quot' truncates toward zero, while 'div' truncates toward negative infinity.
+--
+-- === C code generation of division operations
+--
+-- In the case of division or modulo of a minimal signed value (e.g. @-128@ for
+-- 'SInt8') by @-1@, SMTLIB and Haskell agree on what the result should be.
+-- Unfortunately the result in C code depends on CPU architecture and compiler
+-- settings, as this is undefined behaviour in C.  **SBV does not guarantee**
+-- what will happen in generated C code in this corner case.
+class SDivisible a where
+  sQuotRem :: a -> a -> (a, a)
+  sDivMod  :: a -> a -> (a, a)
+  sQuot    :: a -> a -> a
+  sRem     :: a -> a -> a
+  sDiv     :: a -> a -> a
+  sMod     :: a -> a -> a
+
+  {-# MINIMAL sQuotRem, sDivMod #-}
+
+  x `sQuot` y = fst $ x `sQuotRem` y
+  x `sRem`  y = snd $ x `sQuotRem` y
+  x `sDiv`  y = fst $ x `sDivMod`  y
+  x `sMod`  y = snd $ x `sDivMod`  y
+
+instance SDivisible Word64 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Int64 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Word32 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Int32 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Word16 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Int16 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Word8 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Int8 where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible Integer where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+instance SDivisible CV where
+  sQuotRem a b
+    | CInteger x <- cvVal a, CInteger y <- cvVal b
+    = let (r1, r2) = sQuotRem x y in (normCV a{ cvVal = CInteger r1 }, normCV b{ cvVal = CInteger r2 })
+  sQuotRem a b = error $ "SBV.sQuotRem: impossible, unexpected args received: " ++ show (a, b)
+  sDivMod a b
+    | CInteger x <- cvVal a, CInteger y <- cvVal b
+    = let (r1, r2) = sDivMod x y in (normCV a{ cvVal = CInteger r1 }, normCV b{ cvVal = CInteger r2 })
+  sDivMod a b = error $ "SBV.sDivMod: impossible, unexpected args received: " ++ show (a, b)
+
+instance SDivisible SWord64 where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SWord32 where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SWord16 where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SWord8  where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SInt64  where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SInt32  where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SInt16  where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+instance SDivisible SInt8   where {sQuotRem = liftQRem; sDivMod  = liftDMod}
+
+-- | 'SDivisible' instance for 'WordN'
+instance (KnownNat n, BVIsNonZero n) => SDivisible (WordN n) where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+-- | 'SDivisible' instance for 'IntN'
+instance (KnownNat n, BVIsNonZero n) => SDivisible (IntN n) where
+  sQuotRem x 0 = (0, x)
+  sQuotRem x y = x `quotRem` y
+  sDivMod  x 0 = (0, x)
+  sDivMod  x y = x `divMod` y
+
+-- | 'SDivisible' instance for 'SWord'
+instance (KnownNat n, BVIsNonZero n) => SDivisible (SWord n) where
+  sQuotRem = liftQRem
+  sDivMod  = liftDMod
+
+-- | 'SDivisible' instance for 'SInt'
+instance (KnownNat n, BVIsNonZero n) => SDivisible (SInt n) where
+  sQuotRem = liftQRem
+  sDivMod  = liftDMod
+
+-- | Does the concrete positive number n divide the given integer?
+sDivides :: Integer -> SInteger -> SBool
+sDivides n v
+  | n < 0
+  = error $ "svDivides: First argument must be a strictly positive integer. Received: " ++ show n
+  | Just x <- unliteral v
+  = if x `mod` n == 0 then sTrue else sFalse
+  | True
+  = SBV $ svDivides n (unSBV v)
+
+-- | Lift 'quotRem' to symbolic words. Division by 0 is defined s.t. @x/0 = 0@; which
+-- holds even when @x@ is @0@ itself.
+liftQRem :: (Eq a, SymVal a) => SBV a -> SBV a -> (SBV a, SBV a)
+liftQRem x y
+  | isConcreteZero x
+  = (x, x)
+  | isConcreteOne y
+  = (x, z)
+{-------------------------------
+ - N.B. The seemingly innocuous variant when y == -1 only holds if the type is signed;
+ - and also is problematic around the minBound.. So, we refrain from that optimization
+  | isConcreteOnes y
+  = (-x, z)
+--------------------------------}
+  | True
+  = ite (y .== z) (z, x) (qr x y)
+  where qr (SBV (SVal sgnsz (Left a))) (SBV (SVal _ (Left b))) = let (q, r) = sQuotRem a b in (SBV (SVal sgnsz (Left q)), SBV (SVal sgnsz (Left r)))
+        qr a@(SBV (SVal sgnsz _))      b                       = (SBV (SVal sgnsz (Right (cache (mk Quot)))), SBV (SVal sgnsz (Right (cache (mk Rem)))))
+                where mk o st = do sw1 <- sbvToSV st a
+                                   sw2 <- sbvToSV st b
+                                   mkSymOp o st sgnsz sw1 sw2
+        z = genLiteral (kindOf x) (0::Integer)
+
+-- | 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 :: (Ord a, SymVal a, Num a, Num (SBV a), SDivisible (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
+liftDMod x y
+  | isConcreteZero x
+  = (x, x)
+  | isConcreteOne y
+  = (x, z)
+{-------------------------------
+ - N.B. The seemingly innocuous variant when y == -1 only holds if the type is signed;
+ - and also is problematic around the minBound.. So, we refrain from that optimization
+  | isConcreteOnes y
+  = (-x, z)
+--------------------------------}
+  | True
+  = ite (y .== z) (z, x) $ ite (signum r .== negate (signum y)) (q-i, r+y) qr
+ where qr@(q, r) = x `sQuotRem` y
+       z = genLiteral (kindOf x) (0::Integer)
+       i = genLiteral (kindOf x) (1::Integer)
+
+-- SInteger instance for quotRem/divMod are tricky!
+-- SMT-Lib only has Euclidean operations, but Haskell
+-- uses "truncate to 0" for quotRem, and "truncate to negative infinity" for divMod.
+-- So, we cannot just use the above liftings directly.
+instance SDivisible SInteger where
+  sDivMod x y = ite (y .> 0) (sEDivMod x y) (liftDMod x y)
+  sQuotRem x y
+    | not (isSymbolic x || isSymbolic y)
+    = liftQRem x y
+    | True
+    = ite (y .== 0) (0, x) (qE+i, rE-i*y)
+    where (qE, rE) = liftQRem x y   -- for integers, this is euclidean due to SMTLib semantics
+          i = ite (x .>= 0 .|| rE .== 0) 0
+            $ ite (y .>  0)              1 (-1)
+
+-- | Euclidian division and modulus.
+sEDivMod :: SInteger -> SInteger -> (SInteger, SInteger)
+sEDivMod a b = (a `sEDiv` b, a `sEMod` b)
+
+-- | Euclidian division. Note that unlike regular division, Euclidian division by @0@
+-- is unconstrained. i.e., it can take any value whatsoever.
+sEDiv :: SInteger -> SInteger -> SInteger
+sEDiv (SBV a) (SBV b) = SBV $ a `svQuot` b
+
+-- | Euclidian modulus. Note that unlike regular modulus, Euclidian division by @0@
+-- is unconstrained. i.e., it can take any value whatsoever.
+sEMod :: SInteger -> SInteger -> SInteger
+sEMod (SBV a) (SBV b) = SBV $ a `svRem` b
+
+-- Quickcheck interface
+instance (SymVal a, Arbitrary a) => Arbitrary (SBV a) where
+  arbitrary = literal <$> arbitrary
+
+-- |  Symbolic conditionals are modeled by the 'Mergeable' class, describing
+-- how to merge the results of an if-then-else call with a symbolic test. SBV
+-- provides all basic types as instances of this class, so users only need
+-- to declare instances for custom data-types of their programs as needed.
+--
+-- A 'Mergeable' instance may be automatically derived for a custom data-type
+-- with a single constructor where the type of each field is an instance of
+-- 'Mergeable', such as a record of symbolic values. Users only need to add
+-- 'G.Generic' and 'Mergeable' to the @deriving@ clause for the data-type. See
+-- 'Documentation.SBV.Examples.Puzzles.U2Bridge.Status' for an example and an
+-- illustration of what the instance would look like if written by hand.
+--
+-- The function 'select' is a total-indexing function out of a list of choices
+-- with a default value, simulating array/list indexing. It's an n-way generalization
+-- of the 'ite' function.
+--
+-- Minimal complete definition: None, if the type is instance of @Generic@. Otherwise
+-- 'symbolicMerge'. Note that most types subject to merging are likely to be
+-- trivial instances of @Generic@.
+class Mergeable a where
+   -- | Merge two values based on the condition. The first argument states
+   -- whether we force the then-and-else branches before the merging, at the
+   -- word level. This is an efficiency concern; one that we'd rather not
+   -- make but unfortunately necessary for getting symbolic simulation
+   -- working efficiently.
+   symbolicMerge :: Bool -> SBool -> a -> a -> a
+
+   -- | Total indexing operation. @select xs default index@ is intuitively
+   -- the same as @xs !! index@, except it evaluates to @default@ if @index@
+   -- underflows/overflows.
+   select :: (Ord b, SymVal b, Num b, Num (SBV b), OrdSymbolic (SBV 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
+   -- "concrete" subwords: If an index is symbolic, then all its bits are
+   -- symbolic as well. So, the binary search only pays off only if the indexed
+   -- list is really humongous, which is not very common in general. (Also,
+   -- for the case when the list is bit-vectors, we use SMT tables anyhow.)
+   select xs err ind
+    | isReal   ind = bad "real"
+    | isFloat  ind = bad "float"
+    | isDouble ind = bad "double"
+    | hasSign  ind = ite (ind .< 0) err (walk xs ind err)
+    | True         =                     walk xs ind err
+    where bad w = error $ "SBV.select: unsupported " ++ w ++ " valued select/index expression"
+          walk []     _ acc = acc
+          walk (e:es) i acc = walk es (i-1) (ite (i .== 0) e acc)
+
+   -- Default implementation for 'symbolicMerge' if the type is 'Generic'
+   default symbolicMerge :: (G.Generic a, GMergeable (G.Rep a)) => Bool -> SBool -> a -> a -> a
+   symbolicMerge = symbolicMergeDefault
+
+-- | If-then-else. This is by definition 'symbolicMerge' with both
+-- branches forced. This is typically the desired behavior, but also
+-- see 'iteLazy' should you need more laziness.
+ite :: Mergeable a => SBool -> a -> a -> a
+ite t a b
+  | Just r <- unliteral t = if r then a else b
+  | True                  = symbolicMerge True t a b
+
+-- | A Lazy version of ite, which does not force its arguments. This might
+-- cause issues for symbolic simulation with large thunks around, so use with
+-- care.
+iteLazy :: Mergeable a => SBool -> a -> a -> a
+iteLazy t a b
+  | Just r <- unliteral t = if r then a else b
+  | True                  = symbolicMerge False t a b
+
+-- | Symbolic assert. Check that the given boolean condition is always 'sTrue' in the given path. The
+-- optional first argument can be used to provide call-stack info via GHC's location facilities.
+sAssert :: HasKind a => Maybe CallStack -> String -> SBool -> SBV a -> SBV a
+sAssert cs msg cond x
+   | Just mustHold <- unliteral cond
+   = if mustHold
+     then x
+     else error $ show $ SafeResult (locInfo . getCallStack <$> cs, msg, Satisfiable defaultSMTCfg (SMTModel [] Nothing [] []))
+   | True
+   = SBV $ SVal k $ Right $ cache r
+  where k     = kindOf x
+        r st  = do xsv <- sbvToSV st x
+                   let pc = getPathCondition st
+                       -- We're checking if there are any cases where the path-condition holds, but not the condition
+                       -- Any violations of this, should be signaled, i.e., whenever the following formula is satisfiable
+                       mustNeverHappen = pc .&& sNot cond
+                   cnd <- sbvToSV st mustNeverHappen
+                   addAssertion st cs msg cnd
+                   pure xsv
+
+        locInfo ps = intercalate ",\n " (map loc ps)
+          where loc (f, sl) = concat [srcLocFile sl, ":", show (srcLocStartLine sl), ":", show (srcLocStartCol sl), ":", f]
+
+-- | Merge two symbolic values, at kind @k@, possibly @force@'ing the branches to make
+-- sure they do not evaluate to the same result. This should only be used for internal purposes;
+-- as default definitions provided should suffice in many cases. (i.e., End users should
+-- only need to define 'symbolicMerge' when needed; which should be rare to start with.)
+symbolicMergeWithKind :: Kind -> Bool -> SBool -> SBV a -> SBV a -> SBV a
+symbolicMergeWithKind k force (SBV t) (SBV a) (SBV b) = SBV (svSymbolicMerge k force t a b)
+
+instance SymVal a => Mergeable (SBV a) where
+    symbolicMerge force t x y
+    -- Carefully use the kindOf instance to avoid strictness issues.
+       | force = symbolicMergeWithKind (kindOf x)          True  t x y
+       | True  = symbolicMergeWithKind (kindOf (Proxy @a)) False t x y
+    -- Custom version of select that translates to SMT-Lib tables at the base type of words
+    select xs err ind
+      | SBV (SVal _ (Left c)) <- ind = case cvVal c of
+                                         CInteger i -> if i < 0 || i >= genericLength xs
+                                                       then err
+                                                       else xs `genericIndex` i
+                                         _          -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
+    select xsOrig err ind = xs `seq` SBV (SVal kElt (Right (cache r)))
+      where kInd = kindOf ind
+            kElt = kindOf err
+            -- Based on the index size, we need to limit the elements. For instance if the index is 8 bits, but there
+            -- are 257 elements, that last element will never be used and we can chop it of..
+            xs   = case kindOf ind of
+                     KBounded False i -> genericTake ((2::Integer) ^ (fromIntegral i     :: Integer)) xsOrig
+                     KBounded True  i -> genericTake ((2::Integer) ^ (fromIntegral (i-1) :: Integer)) xsOrig
+                     KUnbounded       -> xsOrig
+                     _                -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
+            r st  = do sws <- mapM (sbvToSV st) xs
+                       swe <- sbvToSV st err
+                       if all (== swe) sws  -- off-chance that all elts are the same. Note that this also correctly covers the case when list is empty.
+                          then pure swe
+                          else do idx <- getTableIndex st kInd kElt sws
+                                  swi <- sbvToSV st ind
+                                  let len = length xs
+                                  -- NB. No need to worry here that the index might be < 0; as the SMTLib translation takes care of that automatically
+                                  newExpr st kElt (SBVApp (LkUp (idx, kInd, kElt, len) swi swe) [])
+
+-- | 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
+                                           ]
+
+-- | Merge concrete values that can be checked for equality
+concreteMerge :: Show a => String -> String -> (a -> a -> Bool) -> a -> a -> a
+concreteMerge t st eq x y
+  | x `eq` y = x
+  | True     = cannotMerge t
+                           ("Concrete values can only be merged when equal. Got: " ++ show x ++ " vs. " ++ show y)
+                           ("Use an " ++ st ++ " field if the values can differ.")
+
+-- 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..
+
+-- Lists
+instance Mergeable a => Mergeable [a] where
+  symbolicMerge f t xs ys
+    | lxs == lys = zipWith (symbolicMerge f t) xs ys
+    | 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)
+
+-- NonEmpty
+instance Mergeable a => Mergeable (NonEmpty a) where
+   symbolicMerge f t xs ys
+     | lxs == lys = NE.zipWith (symbolicMerge f t) xs ys
+     | True       = cannotMerge "non-empty 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
+instance Mergeable a => Mergeable (ZipList a) where
+  symbolicMerge force test (ZipList xs) (ZipList ys)
+    = ZipList (symbolicMerge force test xs ys)
+
+-- Maybe
+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 = 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 :: Maybe a -> String
+            k Nothing = "Nothing"
+            k _       = "Just"
+
+-- Either
+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 = cannotMerge "'Either' values"
+                                      ("Branches produce different constructors: " ++ show (k a, k b))
+                                      "Consider using a product type by a tag instead."
+     where k :: Either a b -> String
+           k (Left _)  = "Left"
+           k (Right _) = "Right"
+
+-- Arrays
+instance (Ix a, Mergeable b) => Mergeable (Array a b) where
+  symbolicMerge f t a b
+    | ba == bb = DA.listArray ba (zipWith (symbolicMerge f t) (elems a) (elems b))
+    | True     = cannotMerge "'Array' values"
+                             ("Branches produce different ranges: " ++ show (k ba, k bb))
+                             "Consider using SBV's native 'SArray' abstraction."
+    where ba = bounds a
+          bb = bounds b
+          k = rangeSize
+
+-- Functions
+instance Mergeable b => Mergeable (a -> b) where
+  symbolicMerge f t g h x = symbolicMerge f t (g x) (h x)
+  {- Following definition, while correct, is utterly inefficient. Since the
+     application is delayed, this hangs on to the inner list and all the
+     impending merges, even when ind is concrete. Thus, it's much better to
+     simply use the default definition for the function case.
+  -}
+  -- select xs err ind = \x -> select (map ($ x) xs) (err x) ind
+
+-- 2-Tuple
+instance (Mergeable a, Mergeable b) => Mergeable (a, b) where
+  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) = ( 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) = ( 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) = ( 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) = ( 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) = ( 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
+
+-- Base types are mergeable so long as they are equal
+instance Mergeable ()      where symbolicMerge _ _ = concreteMerge "()"      "()"        (==)
+instance Mergeable Integer where symbolicMerge _ _ = concreteMerge "Integer" "SInteger"  (==)
+instance Mergeable Bool    where symbolicMerge _ _ = concreteMerge "Bool"    "SBool"     (==)
+instance Mergeable Char    where symbolicMerge _ _ = concreteMerge "Char"    "SChar"     (==)
+instance Mergeable Float   where symbolicMerge _ _ = concreteMerge "Float"   "SFloat"    fpIsEqualObjectH
+instance Mergeable Double  where symbolicMerge _ _ = concreteMerge "Double"  "SDouble"   fpIsEqualObjectH
+instance Mergeable Word8   where symbolicMerge _ _ = concreteMerge "Word8"   "SWord8"    (==)
+instance Mergeable Word16  where symbolicMerge _ _ = concreteMerge "Word16"  "SWord16"   (==)
+instance Mergeable Word32  where symbolicMerge _ _ = concreteMerge "Word32"  "SWord32"   (==)
+instance Mergeable Word64  where symbolicMerge _ _ = concreteMerge "Word64"  "SWord64"   (==)
+instance Mergeable Int8    where symbolicMerge _ _ = concreteMerge "Int8"    "SInt8"     (==)
+instance Mergeable Int16   where symbolicMerge _ _ = concreteMerge "Int16"   "SInt16"    (==)
+instance Mergeable Int32   where symbolicMerge _ _ = concreteMerge "Int32"   "SInt32"    (==)
+instance Mergeable Int64   where symbolicMerge _ _ = concreteMerge "Int64"   "SInt64"    (==)
+
+-- Arbitrary product types, using GHC.Generics
+--
+-- NB: Because of the way GHC.Generics works, the implementation of
+-- symbolicMerge' is recursive. The derived instance for @data T a = T a a a a@
+-- resembles that for (a, (a, (a, a))), not the flat 4-tuple (a, a, a, a). This
+-- difference should have no effect in practice. Note also that, unlike the
+-- hand-rolled tuple instances, the generic instance does not provide a custom
+-- 'select' implementation, and so does not benefit from the SMT-table
+-- implementation in the 'SBV a' instance.
+
+-- | Not exported. Symbolic merge using the generic representation provided by
+-- 'G.Generics'.
+symbolicMergeDefault :: (G.Generic a, GMergeable (G.Rep a)) => Bool -> SBool -> a -> a -> a
+symbolicMergeDefault force t x y = G.to $ symbolicMerge' force t (G.from x) (G.from y)
+
+-- | Not exported. Used only in 'symbolicMergeDefault'. Instances are provided for
+-- the generic representations of product types where each element is Mergeable.
+class GMergeable f where
+  symbolicMerge' :: Bool -> SBool -> f a -> f a -> f a
+
+{-
+ - N.B. A V1 instance like the below would be wrong!
+ - Why? Because inSBV, we use empty data to mean "uninterpreted" sort; not
+ - something that has no constructors. Perhaps that was a bad design
+ - decision. So, do not allow merging of such values!
+instance GMergeable V1 where
+  symbolicMerge' _ _ x _ = x
+-}
+
+instance GMergeable U1 where
+  symbolicMerge' _ _ _ _ = U1
+
+instance (Mergeable c) => GMergeable (K1 i c) where
+  symbolicMerge' force t (K1 x) (K1 y) = K1 $ symbolicMerge force t x y
+
+instance (GMergeable f) => GMergeable (M1 i c f) where
+  symbolicMerge' force t (M1 x) (M1 y) = M1 $ symbolicMerge' force t x y
+
+instance (GMergeable f, GMergeable g) => GMergeable (f :*: g) where
+  symbolicMerge' force t (x1 :*: y1) (x2 :*: y2) = symbolicMerge' force t x1 x2 :*: symbolicMerge' force t y1 y2
+
+{- A mergeable instance for sum-types isn't possible. Why? It would something like:
+
+instance (GMergeable f, GMergeable g) => GMergeable (f :+: g) where
+  symbolicMerge' force t (L1 x) (L1 y) = L1 $ symbolicMerge' force t x y
+  symbolicMerge' force t (R1 x) (R1 y) = R1 $ symbolicMerge' force t x y
+  symbolicMerge' force t l r
+    | Just tv <- unliteral t = if tv then l else r
+    | True                   = ????
+
+There's really no good code to put in ????. We have no way to ask the SMT solver to merge composite values that
+have different constructors. Calling "error" here would pass the type-checker, but that simply postpones the problem
+to run-time. If you need mergeable on sum-types, you better write one yourself, possibly using the SEither type yourself.
+As we have it, you'll get a type-error; which can be hard to read, but is preferable.
+
+NB. This isn't a problem with the generic version of symbolic equality; since we can simply return sFalse if we
+see different constructors. Such isn't the case when merging.
+-}
+
+-- Bounded instances
+instance {-# OVERLAPPABLE #-} (SymVal a, Bounded a) => Bounded (SBV a) where
+  minBound = literal minBound
+  maxBound = literal maxBound
+
+-- Haskell and SMTLib differ in their default char ranges. In Haskell, maxbound is a lot larger.
+-- But in SMTLib, we only go upto 0x2FFFF. So, we adopt the SMTLib variant here. This is hardly
+-- an issue in practice, but the discrepancy is disconcerting.
+instance {-# OVERLAPPING #-} Bounded SChar where
+  minBound = literal (chr 0)
+  maxBound = literal (chr 0x2FFFF)
+
+-- | Choose a value that satisfies the given predicate. This is Hillbert's choice, essentially. Note that
+-- if the predicate given is not satisfiable (for instance @const sFalse@), then the element returned will be arbitrary.
+-- The only guarantee is that if there's at least one element that satisfies the predicate, then the returned
+-- element will be one of those that do. The returned element is not guaranteed to be unique, least, greatest etc, unless
+-- there happens to be exactly one satisfying element.
+some :: forall a. (SymVal a, HasKind a) => String -> (SBV a -> SBool) -> SBV a
+some inpName cond = mk f
+  where mk = SBV . SVal k . Right . cache
+
+        k = kindOf (Proxy @a)
+
+
+        f st = do ctr <- incrementFreshNameCounter st
+                  let pre = atProxy (Proxy @a) inpName
+                      nm  | ctr == 0 = pre
+                          | True     = pre ++ "_" ++ show ctr
+                  op <- newUninterpreted st (UIGiven nm) Nothing (SBVType [k]) (UINone False)
+                  chosen <- newExpr st k $ SBVApp op []
+                  let ifExists  = quantifiedBool $ \(Exists ex) -> cond ex
+                  internalConstraint st False [] (unSBV (ifExists .=> cond (mk (pure (pure chosen)))))
+                  pure chosen
+
+-- | Find the final part of a kind that looks like an array
+resKind :: Kind -> Kind
+resKind (KArray _ k) = resKind k
+resKind k            = k
+
+-- | SMT definable constants and functions, which can also be uninterpreted.
+-- This class captures functions that we can generate standalone-code for
+-- in the SMT solver. Note that we also allow uninterpreted constants and
+-- functions too. An uninterpreted constant is a value that is indexed by its name. The only
+-- property the prover assumes -- about these values are that they are equivalent to themselves; i.e., (for
+-- functions) they return the same results when applied to same arguments.
+-- We support uninterpreted-functions as a general means of black-box'ing
+-- operations that are /irrelevant/ for the purposes of the proof; i.e., when
+-- the proofs can be performed without any knowledge about the function itself.
+--
+-- Minimal complete definition: 'sbvDefineValue'. However, most instances in
+-- practice are already provided by SBV, so end-users should not need to define their
+-- own instances.
+class SMTDefinable a where
+  -- | Generate the code for this value as an SMTLib function, instead of
+  -- the usual unrolling semantics. This is useful for generating sub-functions
+  -- in generated SMTLib problem, or handling recursive (and mutually-recursive)
+  -- definitions that wouldn't terminate in an unrolling symbolic simulation context.
+  --
+  -- __IMPORTANT NOTE__ The string argument names this function. SBV identifies
+  -- the function by this name: if you use this function twice (or use it recursively),
+  -- it will simply assume this name uniquely identifies the function being defined.
+  -- If two calls to 'smtFunction' (or its variants) use the same name but different
+  -- bodies, SBV will raise an error at runtime.
+  --
+  -- Furthermore, if the call to 'smtFunction' happens in the scope of a parameter, you
+  -- must make sure the string is chosen to keep it unique per parameter value. For instance,
+  -- if you have:
+  --
+  -- @
+  --   bar :: SInteger -> SInteger -> SInteger
+  --   bar k = smtFunction "bar" (\x -> x+k)   -- Note the capture of k!
+  -- @
+  --
+  -- and you call @bar 2@ and @bar 3@, SBV will detect that the two bodies differ and
+  -- raise an error. You should use a concrete argument to make the name unique:
+  --
+  -- @
+  --   bar :: String -> SInteger -> SInteger -> SInteger
+  --   bar tag k = smtFunction ("bar_" ++ tag) (\x -> x+k)   -- Tag should make the name unique!
+  -- @
+  --
+  -- Then, make sure you use @bar "two" 2@ and @bar "three" 3@ etc. to preserve the invariant.
+  --
+  -- Additionally, the function argument must not capture any non-constant variables in the context.
+  -- You can also define higher-order functions, see 'smtHOFunction' for that purpose.
+  smtFunctionDef :: (Typeable a, Lambda Symbolic a) => String -> Measure a -> a -> a
+
+  -- | Register a function. This function is typically not needed as SBV will register functions used
+  -- automatically upon first use. However, there are scenarios (in particular query contexts)
+  -- where the definition isn't used before query-mode starts, and SBV (for historical reasons)
+  -- requires functions to be known before query-mode starts executing. In such cases, use this function
+  -- to register them with the system.
+  registerFunction :: a -> Symbolic ()
+
+  -- | Uninterpret a value, i.e., add this value as a completely undefined value/function that
+  -- the solver is free to instantiate to satisfy other constraints.
+  --
+  -- __Known issues__
+  --
+  -- Usually using an uninterpret function will register itself to the solver, but sometimes the laziness
+  -- of the evaluation might render this unreliable.
+  --
+  -- For example, when working with quantifiers and uninterpreted functions with the following code:
+  --
+  -- > runSMTWith z3 $ do
+  -- >   let f = uninterpret "f" :: SInteger -> SInteger
+  -- >   query $ do
+  -- >     constrain $ \(Forall (b :: SInteger)) -> f b .== f b
+  -- >     checkSat
+  --
+  -- The solver will complain about the unknown constant @f (Int)@.
+  --
+  -- A workaround of this is to explicit register them with 'Data.SBV.Control.registerUISMTFunction':
+  --
+  -- > runSMTWith z3 $ do
+  -- >   let f = uninterpret "f" :: SInteger -> SInteger
+  -- >   registerUISMTFunction f
+  -- >   query $ do
+  -- >     constrain $ \(Forall (b :: SInteger)) -> f b .== f b
+  -- >     checkSat
+  --
+  -- See https://github.com/LeventErkok/sbv/issues/711 for more info.
+  uninterpret :: String -> a
+
+  -- | Uninterpret a value, with named arguments in case of functions. SBV will use these
+  -- names when it shows the values for the arguments. If the given names are more than needed
+  -- we ignore the excess. If not enough, we add from a stock set of variables.
+  uninterpretWithArgs :: String -> [String] -> a
+
+  -- | Uninterpret a value, only for the purposes of code-generation. For execution
+  -- and verification the value is used as is. For code-generation, the alternate
+  -- definition is used. This is useful when we want to take advantage of native
+  -- libraries on the target languages.
+  cgUninterpret :: String -> [String] -> a -> a
+
+  -- | More generalized form of uninterpretation that wraps 'sbvDefineValueFun';
+  -- this function should not be needed by end-user-code
+  sbvDefineValue :: UIName -> Maybe [String] -> UIKind a -> a
+
+  -- | The most generalized form of uninterpretation, that generates an
+  -- uninterpreted function over a sequence of 'SBVs' values; this function is
+  -- internal-only, and should not be needed by end-user-code
+  sbvDefineValueFun :: UIName -> Maybe [String] -> SymValInsts as ->
+                       UIKind (SBVs as -> a) -> SBVs as -> a
+
+  -- | A synonym for 'uninterpret'. Allows us to create variables without
+  -- having to call 'free' explicitly, i.e., without being in the symbolic monad.
+  sym :: String -> a
+
+  -- | Like 'sym', but appends the type's kind to the name, ensuring uniqueness across
+  -- different type instantiations of the same polymorphic definition. Used internally by sCase.
+  symWithKind :: String -> a
+  symWithKind = sym
+
+  -- | Render an uninterpreted value as an SMTLib definition
+  sbv2smt :: ExtractIO m => a -> m String
+
+  -- | Render an uninterpreted value function as an SMTLib definition
+  sbvFun2smt :: (SymVals as, ExtractIO m) => (SBVs as -> a) -> m String
+
+  -- | Make this name a constructor, coming from an ADT. Only used internally
+  mkADTConstructor :: HasKind a => String -> a
+  mkADTTester      :: HasKind a => String -> a
+  mkADTAccessor    :: HasKind a => String -> a
+
+  {-# MINIMAL sbvDefineValueFun, sbvFun2smt, registerFunction #-}
+
+  -- defaults:
+  uninterpret         nm        = sbvDefineValue (UIGiven nm) Nothing   $ UIFree True
+  uninterpretWithArgs nm as     = sbvDefineValue (UIGiven nm) (Just as) $ UIFree True
+  cgUninterpret       nm code v = sbvDefineValue (UIGiven nm) Nothing   $ UICodeC (v, code)
+  sym                           = uninterpret
+  sbv2smt             a         = sbvFun2smt (\(_ :: SBVs RNil) -> a)
+
+  sbvDefineValue nm mbArgs k    =
+    sbvDefineValueFun nm mbArgs SymValsNil (const <$> k) SBVsNil
+
+  mkADTConstructor nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTConstructor (T.pack nm) k)) Nothing $ UIFree True in v
+  mkADTTester      nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTTester      (T.pack nm) k)) Nothing $ UIFree True in v
+  mkADTAccessor    nm = let k = resKind (kindOf v); v = sbvDefineValue (UIADT (ADTAccessor    (T.pack nm) k)) Nothing $ UIFree True in v
+
+  smtFunctionDef nm msr v = sbvDefineValue (UIGiven (atProxy (Proxy @a) nm)) Nothing
+                       $ UIFun (v, \st fk -> do
+                          let funcNm = atProxy (Proxy @a) nm
+                          (def, info) <- lambdaWithInfo st TopLevel fk v
+                          -- Record LambdaInfo for SCC-aware mutual recursion checking
+                          modifyIORef' (rFuncLambdaInfos st) (Map.insert funcNm info)
+                          let barFuncNm    = barify funcNm
+                              tBarFuncNm   = T.pack barFuncNm
+                              isSelfRec    = any (\(_, SBVApp op _) -> case op of
+                                                    Uninterpreted n -> n == tBarFuncNm
+                                                    _               -> False)
+                                                 (liAssignments info)
+                              hasCrossRefs = any (\(_, SBVApp op _) -> case op of
+                                                    Uninterpreted n -> n /= tBarFuncNm
+                                                    _               -> False)
+                                                 (liAssignments info)
+                          case msr of
+                            AutoMeasure -> do
+                              when isSelfRec $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, False, \cfg -> autoGuessOrFail cfg funcNm info) :)
+                              when hasCrossRefs $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, False, \cfg -> checkMutualFromState cfg funcNm st Nothing) :)
+                              pure def
+
+                            HasMeasure eval helpers -> do
+                              when isSelfRec $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, False, \cfg -> verifyMeasure cfg funcNm info eval helpers) :)
+                              when hasCrossRefs $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, False, \cfg -> checkMutualFromState cfg funcNm st (Just eval)) :)
+                              pure def
+
+                            HasContract eval ceval helpers -> do
+                              when hasCrossRefs $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, False, \cfg -> rejectMutualContractFromState cfg funcNm st) :)
+                              modifyIORef' (rMeasureChecks st)
+                                           ((funcNm, False, \cfg -> verifyMeasureWithContract cfg funcNm info eval ceval helpers) :)
+                              pure def
+
+                            Productive -> do
+                              when isSelfRec $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, True, \cfg -> verifyGuardedness cfg funcNm info) :)
+                              when hasCrossRefs $
+                                modifyIORef' (rMeasureChecks st)
+                                             ((funcNm, True, \cfg -> checkMutualProductiveFromState cfg funcNm st) :)
+                              pure def
+
+                            Unverified -> do modifyIORef' (rNoTermCheckFunctions st) (Set.insert nm)
+                                             debug (stCfg st) ["[MEASURE] " <> T.pack funcNm <> ": no termination check (smtFunctionNoTermination)"]
+                                             pure def)
+
+
+-- | Define an SMT function. If the function is recursive, SBV will automatically try to
+-- prove termination by guessing a measure based on argument types. If the guess fails,
+-- use 'smtFunctionWithMeasure' to provide an explicit measure.
+smtFunction :: (SMTDefinable a, Typeable a, Lambda Symbolic a) => String -> a -> a
+smtFunction nm = smtFunctionDef nm AutoMeasure
+
+-- | Define an SMT function with an explicit termination measure. Use this when 'smtFunction'
+-- cannot automatically determine a suitable measure. The measure function takes the same
+-- arguments as the original function but returns a value that must be non-negative and
+-- strictly decrease at each recursive call.
+--
+-- The pair @(measure, helpers)@ provides the measure function and a list of auxiliary
+-- t'MeasureHelper' properties needed to verify the measure. Each helper is first proven
+-- (by running its TP proof), then asserted as an axiom in the measure verification session.
+-- Use 'Data.SBV.TP.measureLemma' to create helpers from TP proofs. Pass @[]@ when no helpers are needed.
+smtFunctionWithMeasure :: forall f r. (SMTDefinable f, Typeable f, Lambda Symbolic f, Zero r, OrdSymbolic (SBV r), SymVal r, ApplyMeasure f r)
+                       => String -> (MeasureOf f r, [MeasureHelper]) -> f -> f
+smtFunctionWithMeasure nm (mf, helpers) = smtFunctionDef nm (HasMeasure (MeasureEval (applyMeasure @f @r mf)) helpers)
+
+-- | Define an SMT function with a termination measure and a contract (post-condition).
+-- Use this for nested recursive functions (like McCarthy's 91 function) where the termination
+-- argument depends on the function's return value at smaller inputs.
+--
+-- The triple @(measure, contract, helpers)@ provides:
+--
+--   * A measure function (same as 'smtFunctionWithMeasure')
+--   * A contract: a predicate on the function's inputs and output that is proven simultaneously
+--     with the measure decrease via well-founded induction. The inductive hypothesis provides
+--     the contract for all inputs with strictly smaller measure.
+--   * A list of auxiliary t'MeasureHelper' properties (pass @[]@ when none are needed)
+--
+-- For example, for McCarthy's 91 function:
+--
+-- @
+-- mcCarthy91 = smtFunctionWithContract \"mcCarthy91\"
+--     ( \\n -> 0 \`smax\` (101 - n)
+--     , \\n r -> n .<= 100 .=> r .== 91
+--     , []
+--     )
+--   $ \\n -> ite (n .> 100) (n - 10) (mcCarthy91 (mcCarthy91 (n + 11)))
+-- @
+--
+-- Here the contract says \"for inputs ≤ 100, the result is 91\". This is needed because the outer
+-- recursive call @mcCarthy91(mcCarthy91(n + 11))@ requires knowing what @mcCarthy91(n + 11)@ returns
+-- in order to verify that the measure decreases.
+smtFunctionWithContract :: forall f r. (SMTDefinable f, Typeable f, Lambda Symbolic f, Zero r, OrdSymbolic (SBV r), SymVal r, ApplyMeasure f r, ApplyContract f)
+                        => String -> (MeasureOf f r, ContractOf f, [MeasureHelper]) -> f -> f
+smtFunctionWithContract nm (mf, cf, helpers) = smtFunctionDef nm (HasContract (MeasureEval (applyMeasure @f @r mf))
+                                                                              (ContractEval (applyContract @f cf))
+                                                                              helpers)
+
+-- | Define a productive (corecursive) SMT function. Use this for functions that intentionally
+-- don't terminate but produce output incrementally, such as infinite list generators.
+-- SBV verifies that every recursive call is guarded by a data constructor (list cons, ADT
+-- constructor, etc.), ensuring the function is productive.
+--
+-- @
+-- go = smtProductiveFunction \"go\" $ \\start delta -> start .: go (start + delta) delta
+-- @
+smtProductiveFunction :: (SMTDefinable a, Typeable a, Lambda Symbolic a) => String -> a -> a
+smtProductiveFunction nm = smtFunctionDef nm Productive
+
+-- | Define a recursive SMT function without any termination check. The function
+-- is emitted as @define-fun-rec@ and the user takes responsibility for well-definedness.
+-- Use this for functions where termination is believed but cannot be proven, such as
+-- the Collatz function. See "Documentation.SBV.Examples.TP.Collatz" for an example use case.
+smtFunctionNoTermination :: (SMTDefinable a, Typeable a, Lambda Symbolic a) => String -> a -> a
+smtFunctionNoTermination nm = smtFunctionDef nm Unverified
+
+-- | Kind of uninterpretation
+data UIKind a = UIFree  Bool                            -- ^ completely uninterpreted. If Bool is true, then this is curried.
+              | UIFun   (a, State -> Kind -> IO SMTDef) -- ^ has code for SMTLib, with final type of kind (note this is the result
+                                                        -- , not the arguments), which can be generated by calling the function on the state.
+              | UICodeC (a, [String])                   -- ^ has code for code-generation, i.e., C
+              deriving Functor
+
+-- Get the code associated with the UI, unless we've already did this once. (To support recursive defs.)
+retrieveUICode :: UIName -> State -> Kind -> UIKind a -> IO UICodeKind
+retrieveUICode _            _  _  (UIFree  c)      = pure $ UINone c
+retrieveUICode (UIADT   _)  _  _  _                = pure $ UINone True
+retrieveUICode (UIGiven nm) st fk (UIFun   (_, f)) = do
+  compilingFuncs <- readIORef (rCompilingFuncs st)
+  if nm `Set.member` compilingFuncs
+    then -- This name is currently being compiled, so this is a recursive (or mutually recursive) self-call.
+         -- Break the cycle by skipping code generation.
+         pure $ UINone True
+    else do userFuncs <- readIORef (rUserFuncs st)
+            sn <- hashStableName <$> makeStableName f
+            case Map.lookup nm userFuncs of
+              Just (knownHashes, origLevel)
+                | sn `Set.member` knownHashes
+                -> -- Same closure we've seen before; skip immediately.
+                   pure $ UINone True
+                | True
+                -> do -- New closure for an already-compiled name. Compile body in an isolated
+                      -- throwaway state (to avoid side-effects like duplicate measure registrations
+                      -- and context-dependent body differences), then compare with the existing definition.
+                      -- We use the SAME lambda level as the original compilation so that SV names
+                      -- in the body text match exactly; this avoids fragile string normalization.
+                      throwaway <- mkNewState ((stCfg st) {verbose = False}) (LambdaGen origLevel)
+                      modifyIORef' (rCompilingFuncs throwaway) (Set.insert nm)
+                      -- If the body captures SVals from the live state's context, the throwaway
+                      -- compilation will throw (e.g., context-mismatch). That is a definite conflict:
+                      -- the body references different state-bound variables.
+                      mbD <- C.try (f throwaway fk)
+                      case mbD of
+                        Left (_ :: C.SomeException)
+                          -> conflictError nm
+                        Right d
+                          -> do defs <- readIORef (rDefns st)
+                                case Map.lookup (barify nm) defs of
+                                  Just (oldDef, _)
+                                    | not (smtDefEq d oldDef)
+                                    -> conflictError nm
+                                  _ -> pure ()
+                                -- Body matches; memoize this StableName hash so future calls
+                                -- with the same closure skip instantly.
+                                modifyState st rUserFuncs (Map.adjust (first (Set.insert sn)) nm) (pure ())
+                      pure $ UINone True
+              Nothing
+                -> do -- First time seeing this name. Record lambda level for future comparison.
+                      ll <- readIORef (rLambdaLevel st)
+                      modifyState st rUserFuncs      (Map.insert nm (Set.singleton sn, ll)) (pure ())
+                      modifyState st rCompilingFuncs (Set.insert nm) (pure ())
+                      d <- UISMT <$> f st fk
+                      modifyState st rCompilingFuncs (Set.delete nm) (pure ())
+                      pure d
+retrieveUICode _            _  _  (UICodeC (_, c)) = pure $ UICgC c
+
+-- Get the constant value associated with the UI
+retrieveConstCode :: UIKind a -> Maybe a
+retrieveConstCode UIFree{}         = Nothing
+retrieveConstCode (UIFun   (v, _)) = Just v
+retrieveConstCode (UICodeC (v, _)) = Just v
+
+instance SymVal a => SMTDefinable (SBV a) where
+  sbvFun2smt (fn :: SBVs as -> SBV a)
+    | SymValsNil <- symValInsts :: SymValInsts as
+    , a <- fn SBVsNil
+    = do st <- mkNewState defaultSMTCfg (LambdaGen (Just 0))
+         s <- lambdaStr st TopLevel (kindOf a) a
+         pure $ intercalate "\n" [ "; Automatically generated by SBV. Do not modify!"
+                                 , "; Type: " ++ T.unpack (smtType (kindOf a))
+                                 , show s
+                                 ]
+  sbvFun2smt fn = defs2smt (\args -> fn args .== fn args)
+
+  sbvDefineValueFun nm mbArgs insts uiKind args
+    | Just v <- retrieveConstCode uiKind
+    , foldlSymSBVs (\r x -> r && isConcrete x) True insts args
+    = v args
+    | ka <- kindOf (Proxy @a)
+    = SBV $ SVal ka $ Right $ cache $ \st ->
+        do isSMT <- inSMTMode st
+           case (isSMT, uiKind) of
+             (True, UICodeC (v, _)) -> sbvToSV st (v args)
+             _                      -> do let ks = symValKinds insts ++ [ka]
+                                          ui <- retrieveUICode nm st ka uiKind
+                                          op <- newUninterpreted st nm mbArgs (SBVType ks) ui
+                                          svs <- rlist2list <$> mapMSBVs (sbvToSV st) args
+                                          mapM_ forceSVArg svs
+                                          newExpr st ka $ SBVApp op svs
+
+  registerFunction x = constrain $ x .== x
+
+  symWithKind nm = sym (nm ++ "_" ++ show (kindOf (Proxy @a)))
+
+
+instance (SymVal a, SMTDefinable b) => SMTDefinable (SBV a -> b) where
+  sbvFun2smt (fn :: SBVs as -> SBV a -> b) =
+    sbvFun2smt (\((SBVsCons as a) :: SBVs (as :> a)) -> fn as a)
+
+  sbvDefineValueFun nm mbArgs insts uiKind args a =
+    sbvDefineValueFun nm mbArgs (SymValsCons insts)
+    ((\f (SBVsCons xs x) -> f xs x) <$> uiKind) (SBVsCons args a)
+
+  registerFunction f = do let k = kindOf (Proxy @a)
+                          st <- symbolicEnv
+                          v <- liftIO $ newInternalVariable st k
+                          let a = SBV $ SVal k $ Right $ cache (const (pure v))
+                          registerFunction $ f a
+
+-- Mark the UIKind as uncurried
+mkUncurried :: UIKind a -> UIKind a
+mkUncurried (UIFree  _) = UIFree  False
+mkUncurried (UIFun   a) = UIFun   a
+mkUncurried (UICodeC a) = UICodeC a
+
+
+uncurrySBVs2 :: (SBVs as -> (SBV c, SBV b) -> SBV a) ->
+                (SBVs (as :> c :> b) -> SBV a)
+uncurrySBVs2 fn (SBVsCons (SBVsCons as c) b) = fn as (c,b)
+
+-- Uncurried functions of two arguments
+instance (SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs2
+
+  registerFunction = registerFunction . curry2
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry2 <$> sbvDefineValueFun nm mbArgs insts (fmap curry2 <$> mkUncurried uiKind)
+
+-- Uncurried functions of three arguments
+instance (SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs3
+    where uncurrySBVs3 :: (SBVs as -> (SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> d :> c :> b) -> SBV a)
+          uncurrySBVs3 fn (SBVsCons (SBVsCons (SBVsCons as d) c) b) = fn as (d,c,b)
+  registerFunction = registerFunction . curry3
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry3 <$> sbvDefineValueFun nm mbArgs insts (fmap curry3 <$> mkUncurried uiKind)
+
+-- Uncurried functions of four arguments
+instance (SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs4
+   where uncurrySBVs4 :: (SBVs as -> (SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs4 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons as e) d) c) b) = fn as (e,d,c,b)
+  registerFunction = registerFunction . curry4
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry4 <$> sbvDefineValueFun nm mbArgs insts (fmap curry4 <$> mkUncurried uiKind)
+
+-- Uncurried functions of five arguments
+instance (SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs5
+   where uncurrySBVs5 :: (SBVs as -> (SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs5 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as f) e) d) c) b) = fn as (f,e,d,c,b)
+  registerFunction = registerFunction . curry5
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry5 <$> sbvDefineValueFun nm mbArgs insts (fmap curry5 <$> mkUncurried uiKind)
+
+-- Uncurried functions of six arguments
+instance (SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs6
+   where uncurrySBVs6 :: (SBVs as -> (SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs6 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as g) f) e) d) c) b) = fn as (g,f,e,d,c,b)
+
+  registerFunction = registerFunction . curry6
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry6 <$> sbvDefineValueFun nm mbArgs insts (fmap curry6 <$> mkUncurried uiKind)
+
+-- Uncurried functions of seven arguments
+instance (SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs7
+   where uncurrySBVs7 :: (SBVs as -> (SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs7 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as h) g) f) e) d) c) b) = fn as (h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry7
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry7 <$> sbvDefineValueFun nm mbArgs insts (fmap curry7 <$> mkUncurried uiKind)
+
+-- Uncurried functions of eight arguments
+instance (SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs8
+   where uncurrySBVs8 :: (SBVs as -> (SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> i :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs8 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as i) h) g) f) e) d) c) b) = fn as (i,h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry8
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry8 <$> sbvDefineValueFun nm mbArgs insts (fmap curry8 <$> mkUncurried uiKind)
+
+-- Uncurried functions of nine arguments
+instance (SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs9
+   where uncurrySBVs9 :: (SBVs as -> (SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> j :> i :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs9 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as j) i) h) g) f) e) d) c) b) = fn as (j,i,h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry9
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry9 <$> sbvDefineValueFun nm mbArgs insts (fmap curry9 <$> mkUncurried uiKind)
+
+-- Uncurried functions of ten arguments
+instance (SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs10
+   where uncurrySBVs10 :: (SBVs as -> (SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> k :> j :> i :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs10 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as k) j) i) h) g) f) e) d) c) b) = fn as (k,j,i,h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry10
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry10 <$> sbvDefineValueFun nm mbArgs insts (fmap curry10 <$> mkUncurried uiKind)
+
+-- Uncurried functions of eleven arguments
+instance (SymVal l, SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV l, SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs11
+   where uncurrySBVs11 :: (SBVs as -> (SBV l, SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> l :> k :> j :> i :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+         uncurrySBVs11 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as l) k) j) i) h) g) f) e) d) c) b) = fn as (l,k,j,i,h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry11
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry11 <$> sbvDefineValueFun nm mbArgs insts (fmap curry11 <$> mkUncurried uiKind)
+
+-- Uncurried functions of twelve arguments
+instance (SymVal m, SymVal l, SymVal k, SymVal j, SymVal i, SymVal h, SymVal g, SymVal f, SymVal e, SymVal d, SymVal c, SymVal b, SymVal a, HasKind a) => SMTDefinable ((SBV m, SBV l, SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) where
+  sbvFun2smt = sbvFun2smt . uncurrySBVs12
+    where uncurrySBVs12 :: (SBVs as -> (SBV m, SBV l, SBV k, SBV j, SBV i, SBV h, SBV g, SBV f, SBV e, SBV d, SBV c, SBV b) -> SBV a) -> (SBVs (as :> m :> l :> k :> j :> i :> h :> g :> f :> e :> d :> c :> b) -> SBV a)
+          uncurrySBVs12 fn (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons (SBVsCons as m) l) k) j) i) h) g) f) e) d) c) b) = fn as (m,l,k,j,i,h,g,f,e,d,c,b)
+  registerFunction = registerFunction . curry12
+  sbvDefineValueFun nm mbArgs insts uiKind = uncurry12 <$> sbvDefineValueFun nm mbArgs insts (fmap curry12 <$> mkUncurried uiKind)
+
+-- | Symbolic computations provide a context for writing symbolic programs.
+instance MonadIO m => SolverContext (SymbolicT m) where
+   constrain                   = imposeConstraint False []               . unSBV . quantifiedBool
+   softConstrain               = imposeConstraint True  []               . unSBV . quantifiedBool
+   namedConstraint        nm   = imposeConstraint False [(":named", nm)] . unSBV . quantifiedBool
+   constrainWithAttribute atts = imposeConstraint False atts             . unSBV . quantifiedBool
+
+   contextState = symbolicEnv
+   setOption o  = addNewSMTOption  o
+
+   internalVariable k = contextState >>= \st -> liftIO $ do
+                           sv <- newInternalVariable st k
+                           pure $ SBV $ SVal k (Right (cache (const (pure sv))))
+
+-- | Generalization of 'Data.SBV.assertWithPenalty'
+assertWithPenalty :: MonadSymbolic m => String -> SBool -> Penalty -> m ()
+assertWithPenalty nm o p = addSValOptGoal $ unSBV <$> AssertWithPenalty nm o p
+
+-- | Class of metrics we can optimize for. Currently, booleans,
+-- bounded signed/unsigned bit-vectors, unbounded integers,
+-- 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'/'annotateForMS', and possibly 'minimize'/'maximize' to add extra constraints as necessary.
+class Metric a where
+  -- | 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
+  type MetricSpace a = a
+
+  -- | 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
+
+  -- | Annotate for the metric space, to clarify the new name. If this result is not identity,
+  -- we will add an sObserve on the original.
+  annotateForMS :: Proxy a -> String -> String
+
+  -- | Minimizing a metric space
+  msMinimize :: (MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+  msMinimize nm o = do let nm' = annotateForMS (Proxy @a) nm
+                       when (nm' /= nm) $ sObserve nm (unSBV o)
+                       addSValOptGoal $ unSBV <$> Minimize nm' (toMetricSpace o)
+
+  -- | Maximizing a metric space
+  msMaximize :: (MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+  msMaximize nm o = do let nm' = annotateForMS (Proxy @a) nm
+                       when (nm' /= nm) $ sObserve nm (unSBV o)
+                       addSValOptGoal $ unSBV <$> 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
+
+  -- Annotations to indicate if the metric space transition was needed
+  default annotateForMS :: (a ~ MetricSpace a) => Proxy a -> String -> String
+  annotateForMS _ s = s
+
+-- 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
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- | 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
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+instance Metric Int16 where
+  type MetricSpace Int16 = Word16
+  toMetricSpace   x = sFromIntegral x + 32768  -- 2^15
+  fromMetricSpace x = sFromIntegral x - 32768
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+instance Metric Int32 where
+  type MetricSpace Int32 = Word32
+  toMetricSpace   x = sFromIntegral x + 2147483648 -- 2^31
+  fromMetricSpace x = sFromIntegral x - 2147483648
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+instance Metric Int64 where
+  type MetricSpace Int64 = Word64
+  toMetricSpace   x = sFromIntegral x + 9223372036854775808  -- 2^63
+  fromMetricSpace x = sFromIntegral x - 9223372036854775808
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- | Optimizing 'WordN'
+instance (KnownNat n, BVIsNonZero n) => Metric (WordN n)
+
+-- | Optimizing 'IntN'
+instance (KnownNat n, BVIsNonZero n) => Metric (IntN n) where
+  type MetricSpace (IntN n) = WordN n
+  toMetricSpace   x = sFromIntegral x + 2 ^ (intOfProxy (Proxy @n) - 1)
+  fromMetricSpace x = sFromIntegral x - 2 ^ (intOfProxy (Proxy @n) - 1)
+  annotateForMS _ s = "toMetricSpace(" ++ s ++ ")"
+
+-- Quickcheck interface on symbolic-booleans..
+instance Testable SBool where
+  property (SBV (SVal _ (Left b))) = property (cvToBool b)
+  property s                       = cantQuickCheck $ "Result did not evaluate to a concrete boolean: " ++ show s
+
+instance Testable (Symbolic SBool) where
+   property prop = QC.monadicIO $ do (cond, r, modelVals) <- QC.run test
+                                     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}) <-
+                                 C.catch (runSymbolic defaultSMTCfg (Concrete Nothing) prop)
+                                         (\(e :: C.SomeException) -> cantQuickCheck (show e))
+
+
+                     let cval = fromMaybe (cantQuickCheck "A constraint did not evaluate to a concrete boolean") . (`lookup` cs)
+                         cond = -- Only pick-up "hard" constraints, as indicated by False in the fist component
+                                and [cvToBool (cval v) | (False, _, v) <- F.toList cstrs]
+
+                         getObservable (nm, f, v) = case v `lookup` cs of
+                                                      Just cv -> if f cv then Just (nm, cv) else Nothing
+                                                      Nothing -> cantQuickCheck "An observable did not evaluate to a concrete value"
+
+                     case map fst unints of
+                       [] -> case unliteral r of
+                               Nothing -> cantQuickCheck "The result did not evaluate to a concrete value"
+                               Just b  -> pure (cond, b, tvals ++ mapMaybe getObservable ovals)
+                       uis -> cantQuickCheck $ "Uninterpreted constants remain: " ++ unwords uis
+
+           complain qcInfo = showModel defaultSMTCfg (SMTModel [] Nothing qcInfo [])
+
+-- Complain if what we got isn't something we can quick-check
+cantQuickCheck :: String -> a
+cantQuickCheck why = error $ unlines [ "*** Data.SBV: Cannot quickcheck the given property."
+                                     , "***"
+                                     , "*** Certain SBV properties cannot be quick-checked. In particular,"
+                                     , "*** SBV can't quick-check in the presence of:"
+                                     , "***"
+                                     , "***   - Uninterpreted constants."
+                                     , "***   - Uninterpreted types."
+                                     , "***   - Floating point operations with rounding modes other than RNE."
+                                     , "***   - Floating point FMA operation, regardless of rounding mode."
+                                     , "***   - Quantified booleans, i.e., uses of Forall/Exists/ExistsUnique."
+                                     , "***   - Uses of quantifiedBool"
+                                     , "***   - Calls to 'observe' (use 'sObserve' instead)"
+                                     , "***"
+                                     , "*** If you can't avoid the above features or run into an issue with"
+                                     , "*** quickcheck even though you haven't used these features, please report this as a bug!"
+                                     , "***"
+                                     , "*** Origin:"
+                                     , "***"
+                                     , why
+                                     ]
+
+-- | Quick check an SBV property. Note that a regular @quickCheck@ call will work just as
+-- well. Use this variant if you want to receive the boolean result.
+sbvQuickCheck :: Symbolic SBool -> IO Bool
+sbvQuickCheck prop = QC.isSuccess <$> QC.quickCheckResult prop
+
+-- Quickcheck interface on dynamically-typed values. A run-time check
+-- ensures that the value has boolean type.
+instance Testable (Symbolic SVal) where
+  property m = property $ do s <- m
+                             when (kindOf s /= KBool) $ error "Cannot quickcheck non-boolean value"
+                             pure (SBV s :: SBool)
+
+-- | Explicit sharing combinator. The SBV library has internal caching/hash-consing mechanisms
+-- built in, based on Andy Gill's type-safe observable sharing technique (see: <http://ku-fpg.github.io/files/Gill-09-TypeSafeReification.pdf>).
+-- However, there might be times where being explicit on the sharing can help, especially in experimental code. The 'slet' combinator
+-- ensures that its first argument is computed once and passed on to its continuation, explicitly indicating the intent of sharing. Most
+-- use cases of the SBV library should simply use Haskell's @let@ construct for this purpose.
+slet :: forall a b. (HasKind a, HasKind b) => SBV a -> (SBV a -> SBV b) -> SBV b
+slet x f = SBV $ SVal k $ Right $ cache r
+    where k    = kindOf (Proxy @b)
+          r st = do xsv <- sbvToSV st x
+                    let xsbv = SBV $ SVal (kindOf x) (Right (cache (const (pure xsv))))
+                        res  = f xsbv
+                    sbvToSV st res
+
+-- | Class of things that we can logically reduce to a boolean, by saturating and then asserting equivalence to itself
+class QSaturate m a where
+  qSaturate :: a -> m ()
+
+-- | Base case; simple variable in the symbolic monad
+instance SolverContext m => QSaturate m SBool where
+  qSaturate b = constrain $ b .== b
+
+-- | Saturate over a universal quantifier
+instance (HasKind a, Monad m, SolverContext m, QSaturate m r) => QSaturate m (Forall nm a -> r) where
+  qSaturate f = qSaturate . f . Forall =<< internalVariable (kindOf (Proxy @a))
+
+-- | Saturate over a pair of universal quantifiers
+instance (HasKind a, HasKind b, Monad m, SolverContext m, QSaturate m r) => QSaturate m ((Forall na a, Forall nb b) -> r) where
+  qSaturate = qSaturate . curry
+
+-- | Saturate over a pair of existential quantifiers
+instance (HasKind a, HasKind b, Monad m, SolverContext m, QSaturate m r) => QSaturate m ((Exists na a, Exists nb b) -> r) where
+  qSaturate = qSaturate . curry
+
+-- | Saturate over a number of universal quantifiers
+instance (KnownNat n, HasKind a, Monad m, SolverContext m, QSaturate m r) => QSaturate m (ForallN n nm a -> r) where
+  qSaturate f = qSaturate . f . ForallN =<< replicateM (intOfProxy (Proxy @n)) (internalVariable (kindOf (Proxy @a)))
+
+-- | Saturate over an existential quantifier
+instance (HasKind a, Monad m, SolverContext m, QSaturate m r) => QSaturate m (Exists nm a -> r) where
+  qSaturate f = qSaturate . f . Exists =<< internalVariable (kindOf (Proxy @a))
+
+-- | Saturate over an a number of existential quantifiers
+instance (KnownNat n, HasKind a, Monad m, SolverContext m, QSaturate m r) => QSaturate m (ExistsN n nm a -> r) where
+  qSaturate f = qSaturate . f . ExistsN =<< replicateM (intOfProxy (Proxy @n)) (internalVariable (kindOf (Proxy @a)))
+
+-- | Saturate over a unique-exists variable
+instance (HasKind a, Monad m, SolverContext m, QSaturate m r) => QSaturate m (ExistsUnique nm a -> r) where
+  qSaturate f = qSaturate . f . ExistsUnique =<< internalVariable (kindOf (Proxy @a))
+
+-- | Saturate a predicate, but save/restore observables so they're not messed up.
+qSaturateSavingObservables :: (Monad m, MonadIO m, SolverContext m, QSaturate m a) => a -> m ()
+qSaturateSavingObservables p = do State{rObservables} <- contextState
+                                  curObservables <- liftIO $ readIORef rObservables
+                                  qSaturate p
+                                  liftIO $ writeIORef rObservables curObservables
+
+-- | Equality as a proof method. Allows for
+-- very concise construction of equivalence proofs, which is very typical in
+-- bit-precise proofs.
+infix 4 ===
+class Equality a where
+  (===) :: a -> a -> IO ThmResult
+
+instance {-# OVERLAPPABLE #-} (SymVal a, EqSymbolic z) => Equality (SBV a -> z) where
+  k === l = prove $ \a -> k a .== l a
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, EqSymbolic z) => Equality (SBV a -> SBV b -> z) where
+  k === l = prove $ \a b -> k a b .== l a b
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, EqSymbolic z) => Equality ((SBV a, SBV b) -> z) where
+  k === l = prove $ \a b -> k (a, b) .== l (a, b)
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> z) where
+  k === l = prove $ \a b c -> k a b c .== l a b c
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c) -> z) where
+  k === l = prove $ \a b c -> k (a, b, c) .== l (a, b, c)
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> z) where
+  k === l = prove $ \a b c d -> k a b c d .== l a b c d
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d) -> z) where
+  k === l = prove $ \a b c d -> k (a, b, c, d) .== l (a, b, c, d)
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> z) where
+  k === l = prove $ \a b c d e -> k a b c d e .== l a b c d e
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e) -> z) where
+  k === l = prove $ \a b c d e -> k (a, b, c, d, e) .== l (a, b, c, d, e)
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> z) where
+  k === l = prove $ \a b c d e f -> k a b c d e f .== l a b c d e f
+
+instance {-# OVERLAPPABLE #-}
+ (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> z) where
+  k === l = prove $ \a b c d e f -> k (a, b, c, d, e, f) .== l (a, b, c, d, e, f)
+
+instance {-# OVERLAPPABLE #-}
+ (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> z) where
+  k === l = prove $ \a b c d e f g -> k a b c d e f g .== l a b c d e f g
+
+instance {-# OVERLAPPABLE #-} (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> z) where
+  k === l = prove $ \a b c d e f g -> k (a, b, c, d, e, f, g) .== l (a, b, c, d, e, f, g)
+
+-- | Reading a value from an array.
+readArray :: forall key val. (SymVal key, SymVal val, HasKind val) => SArray key val -> SBV key -> SBV val
+readArray array key
+   | eqCheckIsObjectEq ka, Just (ArrayModel tbl def) <- unliteral array, Just _ <- unliteral key, Just r <- locate (unSBV key) def tbl
+   = r
+   | True
+   = symRes
+   where symRes = SBV . SVal kb . Right $ cache g
+         ka = kindOf (Proxy @key)
+         kb = kindOf (Proxy @val)
+         g st = do f <- sbvToSV st array
+                   k <- sbvToSV st key
+                   newExpr st kb (SBVApp ReadArray [f, k])
+
+         -- return the first value, since we don't bother deleting previous writes. Note that this might
+         -- fail if we don't have equality; but that's OK; in that case we'll go symbolic.
+         locate skey def vals = go vals
+            where go []              = Just $ literal def
+                  go ((k, v) : rest) = case unliteral (SBV (svStrongEqual skey (unSBV (literal k)))) of
+                                          Nothing    -> Nothing
+                                          Just True  -> Just $ literal v
+                                          Just False -> go rest
+
+-- | Writing a value to an array. For the concrete case, we don't bother deleting earlier entries, we keep a history. The earlier a value is in the list, the "later" it happened; in a stack fashion.
+writeArray :: forall key val. (HasKind key, SymVal key, SymVal val, HasKind val) => SArray key val -> SBV key -> SBV val -> SArray key val
+writeArray array key value
+   | Just (ArrayModel tbl def) <- unliteral array, Just keyVal <- unliteral key, Just val <- unliteral value
+   = literal $ ArrayModel ((keyVal, val) : tbl) def  -- It's important that we "cons" the value here, since it takes precedence in a read
+   | True
+   = SBV . SVal k . Right $ cache g
+   where k  = KArray (kindOf (Proxy @key)) (kindOf (Proxy @val))
+
+         g st = do arr    <- sbvToSV st array
+                   keyVal <- sbvToSV st key
+                   val    <- sbvToSV st value
+                   newExpr st k (SBVApp WriteArray [arr, keyVal, val])
+
+-- | Create a constant array. This is a special case of 'lambdaArray', but it creates a
+-- simpler expression in the case of constants.
+constArray :: forall key val. (SymVal key, SymVal val) => SBV val -> SArray key val
+constArray v
+  | Just v' <- unliteral v
+  = literal $ ArrayModel [] v'
+  | True
+  = SBV . SVal k . Right $ cache g
+  where ka = kindOf (Proxy @key)
+        kb = kindOf (Proxy @val)
+        k  = KArray ka kb
+
+        g st = do sv <- sbvToSV st v
+                  newExpr st k (SBVApp (ArrayInit (Left (ka, kb))) [sv])
+
+-- | Create a completely free array, with no constraints on it, as an expression.
+-- Note that you can create an array in the symbolic context with the regular 'free'
+-- calls. (Or 'sArray' if you prefer.) This variant creates it as an expression, i.e.,
+-- without having to be in the monadic context. We take a name identifier here as an
+-- argument which uniquely identifies this array. Note that this is necessary, as otherwise
+-- there would be no way to distinguish two different calls in the pure context. If you
+-- use the same name, then you'll get the same array, much like uninterpreted functions.
+freeArray :: forall key val. (SymVal key, SymVal val) => String -> SArray key val
+freeArray = lambdaArray . uninterpret
+
+-- | Using a lambda as an array. We can turn a function into an array, relating indexes
+-- to their values. (That is, passing @f@ would create an array where entry @i@
+-- is initialized to value @f i@.) For the special case of initializing with a constant
+-- value, either pass @const val@, or use 'constArray'.
+--
+-- __Arrays vs. uninterpreted functions:__ The basic array theory provides only
+-- @select@ ('readArray'), @store@ ('writeArray'), and @const@ ('constArray'). These operations
+-- can only construct arrays that differ from a constant in finitely many positions. For instance,
+-- the identity array (where @a[i] = i@ for every @i@) cannot be built from 'constArray' plus
+-- finitely many 'writeArray' calls. The @lambdaArray@ function goes beyond this: it uses the
+-- solver's ability to identify arrays with function spaces, allowing the creation of arrays like
+-- @lambdaArray id@ that correspond to arbitrary functions.
+--
+-- This identification has a model-theoretic consequence. The pure array theory (with only
+-- @select@\/@store@\/@const@) is a weaker theory: it admits models where the array sort does
+-- not contain all functions, only those reachable by finitely many stores on constants. This means
+-- certain formulas are satisfiable in the pure theory (because the solver has more freedom in choosing
+-- what arrays exist) that become unsatisfiable when arrays are identified with functions (because the
+-- richer array sort can provide counterexamples). In practice, modern solvers use the stronger
+-- identification, so @lambdaArray@, 'constArray', and 'writeArray' all operate in this richer setting.
+lambdaArray :: forall a b. (SymVal a, HasKind b) => (SBV a -> SBV b) -> SArray a b
+lambdaArray f = SBV . SVal k . Right $ cache g
+  where k = KArray (kindOf (Proxy @a)) (kindOf (Proxy @b))
+
+        g st = do def <- lambdaStr st TopLevel (kindOf (Proxy @b)) f
+                  newExpr st k (SBVApp (ArrayInit (Right def)) [])
+
+-- | Turn a constant association-list and a default into a symbolic array.
+listArray :: (SymVal a, SymVal b) => [(a, b)] -> b -> SArray a b
+listArray ascs def = literal $ ArrayModel ascs def
+
+-- | Create a closure, wrapping the free variables together with the function. When using higher-order functions
+-- in SBV (like map), the function passed must be closed, i.e., not have any free variables. If you need to call
+-- such a function with a function capturing a free variable, you should create a closure instead.
+data Closure env a = Closure { closureEnv :: env
+                             , closureFun :: env -> a
+                             }
+
+-- | Define a higher-order function. Similar to 'smtFunction', but when we have a higher-order argument. Note that
+-- the higher-order argument cannot have free variables. Also, if the function is recursive, you should call
+-- the first argument of the defining function, which SBV uses to tie the recursive knot. (Note that recursive
+-- functions defined via 'smtFunction' don't have this latter requirement as they can figure out the recursion
+-- automatically. Higher-order functions, unfortunately, can't do this: They firstify their high-order argument,
+-- giving the whole function a unique name; captured via the call to the recursive definition.)
+smtHOFunction :: forall a b f.
+                 ( SMTDefinable (a -> SBV b)
+                 , Lambda Symbolic f
+                 , Lambda Symbolic (a -> SBV b)
+                 , HasKind b
+                 , HasKind f
+                 , Typeable a
+                 , Typeable b
+                 , Typeable f
+                 ) => String       -- prefix to use
+                   -> f            -- The higher-order argument. We're very generic here!
+                   -> (a -> SBV b) -- The ho-function we're modeling
+                   ->  a -> SBV b  -- The resulting function, that can be used as is, and will be rendered in SMTLib without unfolding
+smtHOFunction nm f = smtHOFunctionGen nm f AutoMeasure
+
+-- | Like 'smtHOFunction', but with an explicit termination measure. Use this when the
+-- auto-guess measure doesn't work for a higher-order recursive function.
+smtHOFunctionWithMeasure :: forall a b f r.
+                 ( SMTDefinable (a -> SBV b)
+                 , Lambda Symbolic f
+                 , Lambda Symbolic (a -> SBV b)
+                 , HasKind b
+                 , HasKind f
+                 , Typeable a
+                 , Typeable b
+                 , Typeable f
+                 , Zero r, OrdSymbolic (SBV r), SymVal r
+                 , ApplyMeasure (a -> SBV b) r
+                 ) => String                      -- ^ prefix to use
+                   -> f                           -- ^ The higher-order argument
+                   -> MeasureOf (a -> SBV b) r    -- ^ Termination measure
+                   -> (a -> SBV b)                -- ^ The ho-function we're modeling
+                   ->  a -> SBV b                 -- ^ The resulting function
+smtHOFunctionWithMeasure nm f msr = smtHOFunctionGen nm f (HasMeasure (MeasureEval (applyMeasure @(a -> SBV b) @r msr)) [])
+
+-- | Common implementation for higher-order SMT function definitions.
+smtHOFunctionGen :: forall a b f.
+                 ( SMTDefinable (a -> SBV b)
+                 , Lambda Symbolic f
+                 , Lambda Symbolic (a -> SBV b)
+                 , HasKind b
+                 , HasKind f
+                 , Typeable a
+                 , Typeable b
+                 , Typeable f
+                 ) => String               -- ^ prefix to use
+                   -> f                    -- ^ The higher-order argument
+                   -> Measure (a -> SBV b) -- ^ Termination measure
+                   -> (a -> SBV b)         -- ^ The ho-function we're modeling
+                   ->  a -> SBV b          -- ^ The resulting function
+smtHOFunctionGen nm f measure hof arg = SBV $ SVal (kindOf (Proxy @(SBV b))) $ Right $ cache r
+  where r st = do SMTLambda lam <- lambdaStr st HigherOrderArg (arrayResultKind (kindOf (Proxy @f))) f
+                  let uniq = lambdaFingerprint st (T.unpack lam)
+                  sbvToSV st (smtFunctionDef (atProxy (Proxy @f) nm <> "_" <> uniq) measure hof arg)
+
+-- | Chase through nested array kinds to find the final result kind. Higher-order
+-- arguments are firstified into arrays, so we peel off the array wrappers.
+arrayResultKind :: Kind -> Kind
+arrayResultKind (KArray _ k) = arrayResultKind k
+arrayResultKind k            = k
+
+-- | Generate a short fingerprint from a lambda body string, used to give
+-- unique names to firstified higher-order function instantiations.
+lambdaFingerprint :: State -> String -> String
+lambdaFingerprint st lam = take uniqLen (BC.unpack (B.encode (hash (BC.pack (unwords (words lam))))))
+  where uniqLen = firstifyUniqueLen $ stCfg st
+
+{- HLint ignore module "Reduce duplication"   -}
+{- HLint ignore module "Eta reduce"           -}
+{- HLint ignore module "Avoid NonEmpty.unzip" -}
+{- HLint ignore module "Redundant id"         -}
+{- HLint ignore module "Use second"           -}
diff --git a/Data/SBV/Core/Operations.hs b/Data/SBV/Core/Operations.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Operations.hs
@@ -0,0 +1,2058 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Operations
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Constructors and basic operations on symbolic values
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections       #-}
+{-# LANGUAGE ViewPatterns        #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Core.Operations
+  (
+  -- ** Basic constructors
+    svTrue, svFalse, svBool
+  , svInteger, svFloat, svDouble, svFloatingPoint, svRoundingMode
+  , svReal, svEnumFromThenTo, svString, svChar
+  -- ** Basic destructors
+  , svAsBool, svAsInteger
+  , svAsFloat, svAsDouble, svAsFP, svAsRoundingMode, cvAsRoundingMode
+  , svNumerator, svDenominator
+  -- ** Basic operations
+  , svPlus, svTimes, svMinus, svUNeg, svAbs, svSignum
+  , svDivide, svQuot, svRem, svQuotRem, svDivides
+  , svEqual, svNotEqual, svStrongEqual, svImplies
+  , svLessThan, svGreaterThan, svLessEq, svGreaterEq, svStructuralLessThan
+  , svAnd, svOr, svXOr, svNot
+  , svShl, svShr, svRol, svRor
+  , svExtract, svJoin, svZeroExtend, svSignExtend
+  , svIte, svLazyIte, svSymbolicMerge
+  , svSelect
+  , svSign, svUnsign, svSetBit, svWordFromBE, svWordFromLE
+  , svExp, svFromIntegral
+  , svFPNaN, svFPInf, svFPZero
+  , svFPFromIntegerLit, svFPFromRationalLit
+  , svFPIsZero, svFPIsInfinite, svFPIsNegative, svFPIsPositive
+  , svFPIsNaN, svFPIsNormal, svFPIsSubnormal
+  , svFPAdd, svFPSub, svFPMul, svFPDiv, svFPRem, svFPMin, svFPMax
+  , svFPFMA, svFPAbs, svFPNeg, svFPRoundToIntegral, svFPSqrt
+  , svCastToFP, svCastFromFP
+  -- ** Overflows
+  , svMkOverflow1, svMkOverflow2
+  -- ** Derived operations
+  , svToWord1, svFromWord1, svTestBit
+  , svShiftLeft, svShiftRight
+  , svRotateLeft, svRotateRight
+  , svBarrelRotateLeft, svBarrelRotateRight
+  , svBlastLE, svBlastBE
+  , svAddConstant, svIncrement, svDecrement
+  , svSWord32AsFloat, svSWord64AsDouble, svSWordAsFloatingPoint
+  , svFloatAsSWord32, svDoubleAsSWord64, svFloatingPointAsSWord
+  -- Utils
+  , mkSymOp
+  )
+  where
+
+import Prelude hiding (Foldable(..))
+import Data.Bits (Bits(..))
+import Data.List (genericIndex, genericLength, genericTake, foldr, length, foldl', elem, nub, sort, null, elemIndex)
+
+import Data.Maybe (isNothing)
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Concrete
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.SizedFloats
+
+import Data.Ratio
+
+import Data.SBV.Utils.Numeric (RoundingMode(..), {-fp2fp,-} fpIsEqualObjectH, fpIsNormalizedH, fpMaxH, fpMinH, fpRemH, fpRoundToIntegralH, floatToWord, doubleToWord, wordToFloat, wordToDouble)
+
+import LibBF
+
+--------------------------------------------------------------------------------
+-- Basic constructors
+
+-- | Boolean True.
+svTrue :: SVal
+svTrue = SVal KBool (Left trueCV)
+
+-- | Boolean False.
+svFalse :: SVal
+svFalse = SVal KBool (Left falseCV)
+
+-- | Convert from a Boolean.
+svBool :: Bool -> SVal
+svBool b = if b then svTrue else svFalse
+
+-- | Convert from an Integer.
+svInteger :: Kind -> Integer -> SVal
+svInteger k n = SVal k (Left $! mkConstCV k n)
+
+-- | Convert from a Float
+svFloat :: Float -> SVal
+svFloat f = SVal KFloat (Left $! CV KFloat (CFloat f))
+
+-- | Convert from a Double
+svDouble :: Double -> SVal
+svDouble d = SVal KDouble (Left $! CV KDouble (CDouble d))
+
+-- | Convert from a generalized floating point
+svFloatingPoint :: FP -> SVal
+svFloatingPoint f@(FP eb sb _) = SVal k (Left $! CV k (CFP f))
+  where k  = KFP eb sb
+
+-- | Convert from a rounding mode
+svRoundingMode :: RoundingMode -> SVal
+svRoundingMode s = SVal kRoundingMode $ Left $ CV kRoundingMode $ CADT (show s, [])
+
+-- | Convert from a String
+svString :: String -> SVal
+svString s = SVal KString (Left $! CV KString (CString s))
+
+-- | Convert from a Char
+svChar :: Char -> SVal
+svChar c = SVal KChar (Left $! CV KChar (CChar c))
+
+-- | Convert from a Rational
+svReal :: Rational -> SVal
+svReal d = SVal KReal (Left $! CV KReal (CAlgReal (fromRational d)))
+
+--------------------------------------------------------------------------------
+-- Basic destructors
+
+-- | Extract a bool, by properly interpreting the integer stored.
+svAsBool :: SVal -> Maybe Bool
+svAsBool (SVal _ (Left cv)) = Just (cvToBool cv)
+svAsBool _                  = Nothing
+
+-- | Extract an integer from a concrete value.
+svAsInteger :: SVal -> Maybe Integer
+svAsInteger (SVal _ (Left (CV _ (CInteger n)))) = Just n
+svAsInteger _                                   = Nothing
+
+-- | Extract a float from a concrete value.
+svAsFloat :: SVal -> Maybe Float
+svAsFloat (SVal _ (Left (CV _ (CFloat f)))) = Just f
+svAsFloat _ = Nothing
+
+-- | Extract a double from a concrete value.
+svAsDouble :: SVal -> Maybe Double
+svAsDouble (SVal _ (Left (CV _ (CDouble d)))) = Just d
+svAsDouble _ = Nothing
+
+-- | Extract an t'FP' from a concrete value.
+svAsFP :: SVal -> Maybe FP
+svAsFP (SVal _ (Left (CV _ (CFP fp)))) = Just fp
+svAsFP _ = Nothing
+
+-- | Extract a rounding mode from an t'SVal'.
+svAsRoundingMode :: SVal -> Maybe RoundingMode
+svAsRoundingMode (SVal _ (Left cv)) = cvAsRoundingMode cv
+svAsRoundingMode _ = Nothing
+
+-- | Extract a rounding mode from a t'CV'.
+cvAsRoundingMode :: CV -> Maybe RoundingMode
+cvAsRoundingMode (CV k (CADT (s, [])))
+  | k == kRoundingMode
+  , mbMode <- s `lookup` [(show m, m) | m <- [minBound .. maxBound :: RoundingMode]]
+  = mbMode
+cvAsRoundingMode _
+  = Nothing
+
+-- | Grab the numerator of an SReal, if available
+svNumerator :: SVal -> Maybe Integer
+svNumerator (SVal KReal (Left (CV KReal (CAlgReal (AlgRational True r))))) = Just $ numerator r
+svNumerator _                                                              = Nothing
+
+-- | Grab the denominator of an SReal, if available
+svDenominator :: SVal -> Maybe Integer
+svDenominator (SVal KReal (Left (CV KReal (CAlgReal (AlgRational True r))))) = Just $ denominator r
+svDenominator _                                                              = Nothing
+
+-------------------------------------------------------------------------------------
+-- | Constructing [x, y, .. z] and [x .. y]. Only works when all arguments are concrete and integral and the result is guaranteed finite
+-- Note that the it isn't "obviously" clear why the following works; after all we're doing the construction over Integer's and mapping
+-- it back to other types such as SIntN/SWordN. The reason is that the values we receive are guaranteed to be in their domains; and thus
+-- the lifting to Integers preserves the bounds; and then going back is just fine. So, things like @[1, 5 .. 200] :: [SInt8]@ work just
+-- fine (end evaluate to empty list), since we see @[1, 5 .. -56]@ in the @Integer@ domain. Also note the explicit check for @s /= f@
+-- below to make sure we don't stutter and produce an infinite list.
+svEnumFromThenTo :: SVal -> Maybe SVal -> SVal -> Maybe [SVal]
+svEnumFromThenTo bf mbs bt
+  | Just bs <- mbs, Just f <- svAsInteger bf, Just s <- svAsInteger bs, Just t <- svAsInteger bt, s /= f = Just $ map (svInteger (kindOf bf)) [f, s .. t]
+  | Nothing <- mbs, Just f <- svAsInteger bf,                           Just t <- svAsInteger bt         = Just $ map (svInteger (kindOf bf)) [f    .. t]
+  | True                                                                                                 = Nothing
+
+-------------------------------------------------------------------------------------
+-- Basic operations
+
+-- | Addition.
+svPlus :: SVal -> SVal -> SVal
+svPlus x y
+  | isConcreteZero x = y
+  | isConcreteZero y = x
+  | True             = liftSym2 (mkSymOp Plus) [rationalCheck] (+) (+) (+) (+) (+) (+) x y
+
+-- | Multiplication.
+svTimes :: SVal -> SVal -> SVal
+svTimes x y
+  | isConcreteZero x = x
+  | isConcreteZero y = y
+  | isConcreteOne x  = y
+  | isConcreteOne y  = x
+  | True             = liftSym2 (mkSymOp Times) [rationalCheck] (*) (*) (*) (*) (*) (*) x y
+
+-- | Subtraction.
+svMinus :: SVal -> SVal -> SVal
+svMinus x y
+  | isConcreteZero y = x
+  | True             = liftSym2 (mkSymOp Minus) [rationalCheck] (-) (-) (-) (-) (-) (-) x y
+
+-- | Unary minus. We handle arbitrary-FP's specially here, just for the negated literals.
+svUNeg :: SVal -> SVal
+svUNeg = liftSym1 (mkSymOp1 UNeg) negate negate negate negate negate negate
+
+-- | Absolute value.
+svAbs :: SVal -> SVal
+svAbs = liftSym1 (mkSymOp1 Abs) abs abs abs abs abs abs
+
+-- | Signum.
+--
+-- NB. The following "carefully" tests the number for == 0, as Float/Double's NaN and +/-0
+-- cases would cause trouble with explicit equality tests.
+svSignum :: SVal -> SVal
+svSignum a
+  | hasSign a = svIte (a `svGreaterThan` z) i
+              $ svIte (a `svLessThan`    z) (svUNeg i) a
+  | True      = svIte (a `svGreaterThan` z) i a
+  where k = kindOf a
+        z = SVal k $ Left $ mkConstCV k (0 :: Integer)
+        i = SVal k $ Left $ mkConstCV k (1 :: Integer)
+
+-- | Division.
+svDivide :: SVal -> SVal -> SVal
+svDivide = liftSym2 (mkSymOp Quot) [rationalCheck] (/) idiv (/) (/) (/) (/)
+   where idiv x 0 = x
+         idiv x y = x `div` y
+
+-- | Divides predicate
+svDivides :: Integer -> SVal -> SVal
+svDivides n v
+  | n <= 0 = error $ "svDivides: The first argument must be a strictly positive number, received: " ++ show n
+  | True   = case v of
+              SVal KUnbounded (Left (CV KUnbounded (CInteger val))) -> svBool (val `mod` n == 0)
+              _                                                     -> SVal KBool $ Right $ cache c
+  where c st = do sva <- svToSV st v
+                  newExpr st KBool (SBVApp (Divides n) [sva])
+
+-- | Exponentiation.
+svExp :: SVal -> SVal -> SVal
+svExp b e
+  | Just x <- svAsInteger e
+  = if x >= 0 then let go n v
+                        | n == 0 = one
+                        | even n =             go (n `div` 2) (svTimes v v)
+                        | True   = svTimes v $ go (n `div` 2) (svTimes v v)
+                   in  go x b
+              else error $ "svExp: exponentiation: negative exponent: " ++ show x
+  | not (isBounded e) || hasSign e
+  = error $ "svExp: exponentiation only works with unsigned bounded symbolic exponents, kind: " ++ show (kindOf e)
+  | True
+  = prod $ zipWith (\use n -> svIte use n one)
+                   (svBlastLE e)
+                   (iterate (\x -> svTimes x x) b)
+  where prod = foldr svTimes one
+        one  = svInteger (kindOf b) 1
+
+-- | Bit-blast: Little-endian. Assumes the input is a bit-vector or a floating point type.
+svBlastLE :: SVal -> [SVal]
+svBlastLE x = map (svTestBit x) [0 .. intSizeOf x - 1]
+
+-- | Set a given bit at index
+svSetBit :: SVal -> Int -> SVal
+svSetBit x i = x `svOr` svInteger (kindOf x) (bit i :: Integer)
+
+-- | Bit-blast: Big-endian. Assumes the input is a bit-vector or a floating point type.
+svBlastBE :: SVal -> [SVal]
+svBlastBE = reverse . svBlastLE
+
+-- | Un-bit-blast from big-endian representation to a word of the right size.
+-- The input is assumed to be unsigned.
+svWordFromLE :: [SVal] -> SVal
+svWordFromLE bs = go zero 0 bs
+  where zero = svInteger (KBounded False (length bs)) 0
+        go !acc _  []     = acc
+        go !acc !i (x:xs) = go (svIte x (svSetBit acc i) acc) (i+1) xs
+
+-- | Un-bit-blast from little-endian representation to a word of the right size.
+-- The input is assumed to be unsigned.
+svWordFromBE :: [SVal] -> SVal
+svWordFromBE = svWordFromLE . reverse
+
+-- | Add a constant value:
+svAddConstant :: Integral a => SVal -> a -> SVal
+svAddConstant x i = x `svPlus` svInteger (kindOf x) (fromIntegral i)
+
+-- | Increment:
+svIncrement :: SVal -> SVal
+svIncrement x = svAddConstant x (1::Integer)
+
+-- | Decrement:
+svDecrement :: SVal -> SVal
+svDecrement x = svAddConstant x (-1 :: Integer)
+
+-- | Quotient: Overloaded operation whose meaning depends on the kind at which
+-- it is used: For unbounded integers, it corresponds to the SMT-Lib
+-- "div" operator ("Euclidean" division, which always has a
+-- non-negative remainder). For unsigned bitvectors, it is "bvudiv";
+-- and for signed bitvectors it is "bvsdiv", which rounds toward zero.
+-- Note that this variant does not respect the division/reminder by 0. That's handled at the SBV level.
+svQuot :: SVal -> SVal -> SVal
+svQuot x y
+  | not isInteger && isConcreteZero x = x
+  | not isInteger && isConcreteZero y = svInteger (kindOf x) 0
+  | not isInteger && isConcreteOne  y = x
+  | True
+  = liftSym2 (mkSymOp Quot) [nonzeroCheck]
+             (noReal "quot") quot' (noFloat "quot") (noDouble "quot") (noFP "quot") (noRat "quot") x y
+  where
+    isInteger = kindOf x == KUnbounded
+
+    quot' a b | isInteger = div a (abs b) * signum b
+              | True      = quot a b
+
+-- | Remainder: Overloaded operation whose meaning depends on the kind at which
+-- it is used: For unbounded integers, it corresponds to the SMT-Lib
+-- "mod" operator (always non-negative). For unsigned bitvectors, it
+-- is "bvurem"; and for signed bitvectors it is "bvsrem", which rounds
+-- toward zero (sign of remainder matches that of @x@). Division by 0 is
+-- defined s.t. @x/0 = 0@, which holds even when @x@ itself is @0@.
+svRem :: SVal -> SVal -> SVal
+svRem x y
+  | not isInteger && isConcreteZero x = x
+  | not isInteger && isConcreteZero y = x
+  | not isInteger && isConcreteOne  y = svInteger (kindOf x) 0
+  | True
+  = liftSym2 (mkSymOp Rem) [nonzeroCheck]
+             (noReal "rem") rem' (noFloat "rem") (noDouble "rem") (noFP "rem") (noRat "rem") x y
+  where
+    isInteger = kindOf x == KUnbounded
+
+    rem' a b | isInteger = mod a (abs b)
+             | True      = rem a b
+
+-- | Combination of quot and rem
+svQuotRem :: SVal -> SVal -> (SVal, SVal)
+svQuotRem x y = (x `svQuot` y, x `svRem` y)
+
+-- | Implication. Only for booleans.
+svImplies :: SVal -> SVal -> SVal
+svImplies a b
+  | any (\x -> kindOf x /= KBool) [a, b] = error $ "Data.SBV.svImplies: Unexpected arguments: " ++ show (a, kindOf a, b, kindOf b)
+  | isConcreteZero a                     = svTrue  -- F -> _ = T
+  |                     isConcreteOne  b = svTrue  -- _ -> T = T
+  | isConcreteOne  a && isConcreteZero b = svFalse -- T -> F = F
+  | isConcreteOne  a && isConcreteOne  b = svTrue  -- T -> T = T
+  | True                                 = SVal KBool $ Right $ cache c
+  where c st = do sva <- svToSV st a
+                  svb <- svToSV st b
+                  -- One final optimization, equal args is just True!
+                  if sva == svb
+                     then pure trueSV
+                     else newExpr st KBool (SBVApp Implies [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
+                  | isFP x,     Just f1 <- getFP x, Just f2 <- getFP y = svBool $ f1 `fpIsEqualObjectH` f2
+                  | isFloat x || isDouble x || isFP x                  = SVal KBool $ Right $ cache r
+                  | True                                               = compareSV (Equal True) x y
+  where getF (SVal _ (Left (CV _ (CFloat f)))) = Just f
+        getF _                                 = Nothing
+
+        getD (SVal _ (Left (CV _ (CDouble d)))) = Just d
+        getD _                                  = Nothing
+
+        getFP (SVal _ (Left (CV _ (CFP f))))    = Just f
+        getFP _                                 = Nothing
+
+        r st = do sx <- svToSV st x
+                  sy <- svToSV st y
+                  newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [sx, sy])
+
+-- Comparisons have to be careful in making sure we don't rely on CVal ord/eq instance.
+compareSV :: Op -> SVal -> SVal -> SVal
+compareSV op x y
+  -- Make sure we don't get anything we can't handle or expect
+  | op `notElem` [Equal True, Equal False, NotEqual, LessThan, GreaterThan, LessEq, GreaterEq]
+  = error $ "Unexpected call to compareSV: "              ++ show (op, x, y)
+  | kx /= ky
+  = error $ "Mismatched kinds in call to compareSV:"      ++ show (op, x, kindOf x, kindOf y)
+  | (isSet kx || isArray ky) && op `notElem` [Equal True, Equal False, NotEqual]
+  = error $ "Unexpected Set/Array not-equal comparison: " ++ show (op, x, k)
+
+  -- Boolean equality optimizations
+  | k == KBool, Equal{} <- op,    SVal _ (Left xv) <- x, xv == trueCV  = y       -- true  .== y     --> y
+  | k == KBool, Equal{} <- op,    SVal _ (Left yv) <- y, yv == trueCV  = x       -- x     .== true  --> x
+  | k == KBool, Equal{} <- op,    SVal _ (Left xv) <- x, xv == falseCV = svNot y -- false .== y     --> svNot y
+  | k == KBool, Equal{} <- op,    SVal _ (Left yv) <- y, yv == falseCV = svNot x -- x     .== false --> svNot x
+
+  | k == KBool, op == NotEqual, SVal _ (Left xv) <- x, xv == trueCV  = svNot y   -- true  ./= y     --> svNot y
+  | k == KBool, op == NotEqual, SVal _ (Left yv) <- y, yv == trueCV  = svNot x   -- x     ./= true  --> svNot x
+  | k == KBool, op == NotEqual, SVal _ (Left xv) <- x, xv == falseCV = y         -- false ./= y     --> y
+  | k == KBool, op == NotEqual, SVal _ (Left yv) <- y, yv == falseCV = x         -- x     ./= false --> x
+
+  -- Comparison optimizations if one operand is min/max bit-vector
+  | op == LessThan,    isConcreteMax x = svFalse   -- MAX <  _
+  | op == LessThan,    isConcreteMin y = svFalse   -- _   <  MIN
+
+  | op == GreaterThan, isConcreteMin x = svFalse   -- MIN >  _
+  | op == GreaterThan, isConcreteMax y = svFalse   -- _   > MAX
+
+  | op == LessEq,      isConcreteMin x = svTrue    -- MIN <= _
+  | op == LessEq,      isConcreteMax y = svTrue    -- _   <= MAX
+
+  | op == GreaterEq,   isConcreteMax x = svTrue    -- MAX >= _
+  | op == GreaterEq,   isConcreteMin y = svTrue    -- _   >= MIN
+
+  -- General constant folding, but be careful not to be too smart here.
+  | SVal _ (Left xv) <- x, SVal _ (Left yv) <- y
+  = case cCompare k op (cvVal xv) (cvVal yv) of
+      Nothing -> -- cCompare is conservative on floats. Give those one more chance, only at the top-level.
+                 -- (i.e., if stored under a Maybe/Either/List etc., we'll resort to a symbolic result.)
+                 case (k, cvVal xv, cvVal yv) of
+                    (KFloat,   CFloat  a, CFloat  b) -> svBool (a `cFPOp` b)
+                    (KDouble,  CDouble a, CDouble b) -> svBool (a `cFPOp` b)
+                    (KFP{}  ,  CFP     a, CFP     b) -> svBool (a `cFPOp` b)
+                    _                                -> symResult
+      Just r  -> svBool $ case op of
+                            Equal _     -> r == EQ
+                            NotEqual    -> r /= EQ
+                            LessThan    -> r == LT
+                            GreaterThan -> r == GT
+                            LessEq      -> r `elem` [EQ, LT]
+                            GreaterEq   -> r `elem` [EQ, GT]
+                            _           -> error $ "Unexpected call to compareSV: " ++ show (op, x, y)
+
+   -- No constant folding opportunities, turn symbolic
+   | True
+   = symResult
+   where kx = kindOf x
+         ky = kindOf y
+         k  = kx       -- only used after we ensured kx == ky
+
+         -- Are there any floats embedded down from here? if so, we have to be careful due to presence of NaN
+         safeEq =  op == Equal True       -- strong equality ok
+                || isSomeKindOfFloat k    -- top level OK
+                || not (containsFloats k) -- has floats somewhere: not ok
+
+         symResult
+           | safeEq = symResultSafe
+           | True   = symResultFP
+
+         -- This will go down to SMTLib's =. So only use it if we're safe to do so!
+         symResultSafe = SVal KBool $ Right $ cache res
+          where res st = do svx :: SV <- svToSV st x
+                            svy :: SV <- svToSV st y
+
+                            if svx == svy && eqCheckIsObjectEq k
+                               then case op of
+                                       Equal{}     -> pure trueSV
+                                       LessEq      -> pure trueSV
+                                       GreaterEq   -> pure trueSV
+                                       NotEqual    -> pure falseSV
+                                       LessThan    -> pure falseSV
+                                       GreaterThan -> pure falseSV
+                                       _           -> error $ "Unexpected call to compareSV, equal SV case: " ++ show (op, svx)
+                               else newExpr st KBool (SBVApp op [svx, svy])
+
+         a `cFPOp` b = case op of
+                         Equal False -> a == b
+                         Equal True  -> a `fpIsEqualObjectH` b
+                         NotEqual    -> a /= b
+                         LessThan    -> a <  b
+                         GreaterThan -> a >  b
+                         LessEq      -> a <= b
+                         GreaterEq   -> a >= b
+                         _           -> error $ "Unexpected call to cFPOp: " ++ show op
+
+         -- OK, we have a result that has floats embedded in it. So comparison is problematic.
+         -- Certain subsets of this is supported elsewhere. Here, we simply bail out.
+         symResultFP = error $ unlines $  [ ""
+                                          , "*** Data.SBV: Unsupported complicated comparison:"
+                                          , "***"
+                                          , "***   Op  : " ++ show op
+                                          , "***   Type: " ++ show k
+                                          , "***"
+                                          , "*** Due to the presence of NaN, comparisons over this type require"
+                                          , "*** special support in SMTLib. And in general this can lead to"
+                                          , "*** performance issues since the comparison is no longer a natively"
+                                          , "*** supported operation in the logic."
+                                          , "***"
+                                          , "*** NB. If you want the semantics NaN == NaN, and +0 /= -0, then you can use .=== instead."
+                                          , "***"
+                                          ]
+                                       ++ case alternative of
+                                            Nothing -> ["*** Please report this as a feature request."]
+                                            Just a  -> [ "*** For this case, please use: " ++ a
+                                                       , "*** but beware of performance/decidability implications."
+                                                       ]
+
+              where alternative = case (op, k) of
+                                    (Equal False, KList f) | isFloat f || isDouble f || isFP f -> Just "Data.SBV.List.listEq"
+                                    _                                                          -> Nothing
+
+-- Compare two CVals; if we can. We're being conservative here and deferring to a symbolic result if we get something complicated.
+cCompare :: Kind -> Op -> CVal -> CVal -> Maybe Ordering
+cCompare k op x y =
+    case (x, y) of
+
+      -- The presence of NaN's throw this off. Why? Because @NaN `compare` x = GT@ in Haskell. But that's just the wrong thing to do here.
+      -- So protect against NaN's. And a similar story for -0/0.
+      (CFloat  a, CFloat  b) | any (nanOrZero k) [x, y] -> Nothing
+                             | True                     -> Just $ a `compare` b
+
+      (CDouble a, CDouble b) | any (nanOrZero k) [x, y] -> Nothing
+                             | True                     -> Just $ a `compare` b
+
+      (CFP     a, CFP     b) | any (nanOrZero k) [x, y] -> Nothing
+                             | True                      -> Just $ a `compare` b
+
+      -- Simple cases
+      (CInteger  a, CInteger  b) -> Just $ a `compare` b
+      (CRational a, CRational b) -> Just $ a `compare` b
+      (CChar     a, CChar     b) -> Just $ a `compare` b
+      (CString   a, CString   b) -> Just $ a `compare` b
+
+      -- We can handle algreal, so long as they are exact-rationals
+      (CAlgReal     a, CAlgReal  b) | isExactRational a && isExactRational b -> Just $ a `compare` b
+                                    | True                                   -> Nothing
+
+      -- Lists and tuples use lexicographic ordering
+      (CList        a, CList b) -> case k of
+                                     KList ke -> lexCmp (map (ke,) a) (map (ke,) b)
+                                     _        -> error $ "cCompare: Unexpected kind in cCompare for List: " ++ show k
+
+      (CTuple       a, CTuple b) | length a == length b -> case k of
+                                                             KTuple ks | length ks == length a -> lexCmp (zip ks a) (zip ks b)
+                                                             _                                 -> error "cCompare: Unexpected kind in cCompare for tuples"
+                                 | True                 -> error $ "cCompare: Received tuples of differing size: " ++ show (op, length a, length b, k)
+
+      -- Arrays and sets only support equality/inequality. And they have object-equality semantics. So
+      -- if there are any floats or non-exact-rationals down in the index or element kinds, we bail
+      (CSet a, CSet b)     | op `elem` [Equal True, Equal False, NotEqual]
+                           , KSet ke <- k
+                           -> case svSetEqual ke a b of
+                                 Nothing    -> Nothing  -- We don't know
+                                 Just True  -> Just EQ  -- They're equal
+                                 Just False -> Just GT  -- Pick GT; so equality test will fail, inequality will pass
+                           | True
+                           -> error $ "cCompare: Received unexpected set comparison: " ++ show (op, k)
+
+      (CArray a, CArray b) | op `elem` [Equal True, Equal False, NotEqual]
+                           , KArray k1 k2 <- k
+                           -> case svArrEqual k1 k2 a b of
+                                Nothing    -> Nothing  -- We don't know
+                                Just True  -> Just EQ  -- They're equal
+                                Just False -> Just GT  -- Pick GT; so equality test will fail, inequality will pass
+                           | True
+                           -> error $ "cCompare: Received unexpected array comparison: " ++ show (op, k)
+
+
+      -- ADTs. Only equal/inequal on full ADTs. Compares on enumerations.
+      (CADT (s, fks), CADT (s', fks'))
+         -> case k of
+              -- Enumerations. We do a straight comparison on the constructor index
+              KADT _ _ cstrs | all (null . snd) cstrs
+                             -> let cnms = map fst cstrs
+                                in case (s `elemIndex` cnms, s' `elemIndex` cnms) of
+                                     (Just i, Just j) -> Just (i `compare` j)
+                                     r                -> error $ "cCompare: Unable to locate indexes for CADT: " ++ show (k, s, s', r)
+
+              -- Arbitrary ADTs. Only allow equality/inequality
+              _ | op `notElem` [Equal True, Equal False, NotEqual]
+                -> error $ "cCompare: Received unexpected ADT comparison: " ++ show (op, k)
+
+                -- Different constructor
+                | s /= s'
+                -> Just GT -- Pick GT; so equality test will fail, inequality will pass
+
+                -- Same constructor
+                | map fst fks /= map fst fks'
+                -> error $ "cCompare: Mismatching ADT field kinds in comparison: " ++ show (op, k, map fst fks, map fst fks')
+                | True
+                -> let fmatch    = zipWith (\(fk, v1) (_, v2) -> cCompare fk op v1 v2) fks fks'
+                       undecided = any isNothing fmatch   -- Field comparison undecided
+                       allEq     = all (== Just EQ) fmatch -- All fields Equal
+                   in if undecided
+                      then Nothing
+                      else if allEq
+                           then Just EQ
+                           else -- all compared fine, but not all equal
+                                Just GT -- Pick GT; so equality test will fail, inequality will pass
+
+      -- Shouldn't happen:
+      _ -> error $ unlines [ ""
+                           , "*** Data.SBV.cCompare: Bug in SBV: Unhandled rank in comparison fallthru"
+                           , "***"
+                           , "***   Ranks Received: " ++ show (cvRank x, cvRank y, op)
+                           , "***"
+                           , "*** Please report this as a bug!"
+                           ]
+  where -- lexicographic
+        lexCmp :: [(Kind, CVal)] -> [(Kind, CVal)] -> Maybe Ordering
+        lexCmp []     []     = Just EQ
+        lexCmp []     (_:_)  = Just LT
+        lexCmp (_:_)  []     = Just GT
+        lexCmp ((k1, a):as) ((k2, b):bs)
+          | k1 == k2
+          = case cCompare k1 op a b of
+              Just EQ -> as `lexCmp` bs
+              other   -> other
+          | True
+          = error $ "Mismatching kinds in lexicographic comparison: " ++ show (k1, k2)
+
+        nanOrZero KFloat      (CFloat  v) = isNaN v || v == 0
+        nanOrZero KDouble     (CDouble v) = isNaN v || v == 0
+        nanOrZero (KFP eb sb) (CFP     v) = isNaN v || v == fpFromInteger eb sb 0
+        nanOrZero knd         _           = error $ "Unexpected arguments to nanOrZero: " ++ show knd
+
+        -- | Set equality. We return Nothing if the result is too complicated for us to concretely calculate.
+        -- Why? Because the Eq instance of CVal is a bit iffy; it's designed to work as an index into maps, not as
+        -- a means of checking this sort of equality
+        svSetEqual :: Kind -> RCSet CVal -> RCSet CVal -> Maybe Bool
+        svSetEqual ek sa sb
+          | eqCheckIsObjectEq ek, RegularSet a    <- sa, RegularSet b    <- sb = Just $ a == b
+          | eqCheckIsObjectEq ek, ComplementSet a <- sa, ComplementSet b <- sb = Just $ a == b
+          | True                                                               = Nothing
+
+        -- | Array equality. See above comments.
+        svArrEqual :: Kind -> Kind -> ArrayModel CVal CVal -> ArrayModel CVal CVal -> Maybe Bool
+        svArrEqual k1 k2 (ArrayModel asc1 def1) (ArrayModel asc2 def2)
+         | not (all eqCheckIsObjectEq [k1, k2])
+         = Nothing
+         | True
+         = let -- Use of lookup is safe here, because we already made sure equality is *not* problematic above
+               keysMatch = and [key `lookup` asc1 == key `lookup` asc2 | key <- nub (sort (map fst (asc1 ++ asc2)))]
+               defsMatch = def1 == def2
+
+               -- Check if keys cover everything. Clearly, we can't do this for all kinds; but only finite ones
+               -- For the time being, we're restricting ourselves to bool only. Might want to extend this later.
+               complete  = case k1 of
+                             KBool -> let bools       = map cvVal [falseCV, trueCV]
+                                          covered asc = all (`elem` map fst asc) bools
+                                      in covered asc1 && covered asc2
+                             _     -> False
+
+           in case (keysMatch, defsMatch, complete) of
+                (False, _   ,  _)    -> Just False -- keys mismatch. Nothing else matters.
+                (True,  True,  _)    -> Just True  -- keys match, def matches; so all is good. Complete doesn't matter.
+                (True,  False, True) -> Just True  -- keys match, but defs don't. But we keys are complete, so def mismatch is OK
+                _                    -> Nothing    -- otherwise, we don't really know. So, remain symbolic.
+
+-- | Equality. This is SMT object equality.
+svEqual :: SVal -> SVal -> SVal
+svEqual = compareSV (Equal False)
+
+-- | Inequality.
+svNotEqual :: SVal -> SVal -> SVal
+svNotEqual = compareSV NotEqual
+
+-- | Less than.
+svLessThan :: SVal -> SVal -> SVal
+svLessThan = compareSV LessThan
+
+-- | Greater than.
+svGreaterThan :: SVal -> SVal -> SVal
+svGreaterThan = compareSV GreaterThan
+
+-- | Less than or equal to.
+svLessEq :: SVal -> SVal -> SVal
+svLessEq = compareSV LessEq
+
+-- | Greater than or equal to.
+svGreaterEq :: SVal -> SVal -> SVal
+svGreaterEq = compareSV GreaterEq
+
+-- | Bitwise and.
+svAnd :: SVal -> SVal -> SVal
+svAnd x y
+  | isConcreteZero x = x
+  | isConcreteOnes x = y
+  | isConcreteZero y = y
+  | isConcreteOnes y = x
+  | True             = liftSym2 (mkSymOpSC opt And) [] (noReal ".&.") (.&.) (noFloat ".&.") (noDouble ".&.") (noFP ".&.") (noRat ".&") x y
+  where opt a b
+          | a == falseSV || b == falseSV = Just falseSV
+          | a == trueSV                  = Just b
+          | b == trueSV                  = Just a
+          | a == b                       = Just a
+          | True                         = Nothing
+
+-- | Bitwise or.
+svOr :: SVal -> SVal -> SVal
+svOr x y
+  | isConcreteZero x = y
+  | isConcreteOnes x = x
+  | isConcreteZero y = x
+  | isConcreteOnes y = y
+  | True             = liftSym2 (mkSymOpSC opt Or) []
+                       (noReal ".|.") (.|.) (noFloat ".|.") (noDouble ".|.") (noFP ".|.") (noRat ".|.") x y
+  where opt a b
+          | a == trueSV || b == trueSV = Just trueSV
+          | a == falseSV               = Just b
+          | b == falseSV               = Just a
+          | a == b                     = Just a
+          | True                       = Nothing
+
+-- | Bitwise xor.
+svXOr :: SVal -> SVal -> SVal
+svXOr x y
+  | isConcreteZero x = y
+  | isConcreteOnes x = svNot y
+  | isConcreteZero y = x
+  | isConcreteOnes y = svNot x
+  | True             = liftSym2 (mkSymOpSC opt XOr) []
+                       (noReal "xor") xor (noFloat "xor") (noDouble "xor") (noFP "xor") (noRat "xor") x y
+  where opt a b
+          | a == b && swKind a == KBool = Just falseSV
+          | a == falseSV                = Just b
+          | b == falseSV                = Just a
+          | True                        = Nothing
+
+-- | Bitwise complement.
+svNot :: SVal -> SVal
+svNot = liftSym1 (mkSymOp1SC opt Not)
+                 (noRealUnary "complement") complement
+                 (noFloatUnary "complement") (noDoubleUnary "complement") (noFPUnary "complement") (noRatUnary "complement")
+  where opt a
+          | a == falseSV = Just trueSV
+          | a == trueSV  = Just falseSV
+          | True         = Nothing
+
+-- | 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
+  = x
+  | isBounded x, i >= intSizeOf x
+  = svInteger k 0
+  | True
+  = x `svShiftLeft` svInteger k (fromIntegral i)
+  where k = kindOf x
+
+-- | 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
+  = x
+  | isBounded x, i >= intSizeOf x
+  = if not (hasSign x)
+       then z
+       else svIte (x `svLessThan` z) neg1 z
+  | True
+  = x `svShiftRight` svInteger k (fromIntegral i)
+  where k    = kindOf x
+        z    = svInteger k 0
+        neg1 = svInteger k (-1)
+
+-- | 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
+  = x
+  | True
+  = case kindOf x of
+           KBounded _ sz -> liftSym1 (mkSymOp1 (Rol (i `mod` sz)))
+                                     (noRealUnary "rotateL") (rot True sz i)
+                                     (noFloatUnary "rotateL") (noDoubleUnary "rotateL") (noFPUnary "rotateL") (noRatUnary "rotateL") x
+           _ -> svShl x i   -- for unbounded Integers, rotateL is the same as shiftL in Haskell
+
+-- | 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
+  = x
+  | True
+  = case kindOf x of
+      KBounded _ sz -> liftSym1 (mkSymOp1 (Ror (i `mod` sz)))
+                                (noRealUnary "rotateR") (rot False sz i)
+                                (noFloatUnary "rotateR") (noDoubleUnary "rotateR") (noFPUnary "rotateR") (noRatUnary "rotateR") x
+      _ -> svShr x i   -- for unbounded integers, rotateR is the same as shiftR in Haskell
+
+-- | Generic rotation. Since the underlying representation is just Integers, rotations has to be
+-- careful on the bit-size.
+rot :: Bool -> Int -> Int -> Integer -> Integer
+rot toLeft sz amt x
+  | sz < 2 = x
+  | True   = norm x y' `shiftL` y  .|. norm (x `shiftR` y') y
+  where (y, y') | toLeft = (amt `mod` sz, sz - y)
+                | True   = (sz - y', amt `mod` sz)
+        norm v s = v .&. ((1 `shiftL` s) - 1)
+
+-- | Extract bit-sequences.
+svExtract :: Int -> Int -> SVal -> SVal
+svExtract i j x@(SVal (KBounded s _) _)
+  | i < j
+  = SVal k (Left $! CV k (CInteger 0))
+  | SVal _ (Left (CV _ (CInteger v))) <- x
+  = SVal k (Left $! normCV (CV k (CInteger (v `shiftR` j))))
+  | True
+  = SVal k (Right (cache y))
+  where k = KBounded s (i - j + 1)
+        y st = do sv <- svToSV st x
+                  newExpr st k (SBVApp (Extract i j) [sv])
+svExtract i j v@(SVal KFloat _)  = svExtract i j (svFloatAsSWord32  v)
+svExtract i j v@(SVal KDouble _) = svExtract i j (svDoubleAsSWord64 v)
+svExtract i j v@(SVal KFP{} _)   = svExtract i j (svFloatingPointAsSWord v)
+svExtract _ _ _ = error "extract: non-bitvector/float type"
+
+-- | Join two words, by concatenating
+svJoin :: SVal -> SVal -> SVal
+svJoin x@(SVal (KBounded s i) a) y@(SVal (KBounded s' j) b)
+  | s /= s'
+  = error $ "svJoin: received differently signed values: " ++ show (x, y)
+  | i == 0 = y
+  | j == 0 = x
+  | Left (CV _ (CInteger m)) <- a, Left (CV _ (CInteger n)) <- b
+  = let val
+         | s -- signed, arithmetic doesn't work; blast and come back
+         = let xbits = [m `testBit` xi | xi <- [0 .. i-1]]
+               ybits = [n `testBit` yi | yi <- [0 .. j-1]]
+               rbits = zip [0..] (ybits ++ xbits)
+           in foldl' (\acc (idx, set) -> if set then setBit acc idx else acc) 0 rbits
+         | True -- unsigned, go fast
+         = m `shiftL` j .|. n
+    in SVal k (Left $! normCV (CV k (CInteger val)))
+  | True
+  = SVal k (Right (cache z))
+  where
+    k = KBounded s (i + j)
+    z st = do xsw <- svToSV st x
+              ysw <- svToSV st y
+              newExpr st k (SBVApp Join [xsw, ysw])
+svJoin _ _ = error "svJoin: non-bitvector type"
+
+-- | Zero-extend by given number of bits.
+svZeroExtend :: Int -> SVal -> SVal
+svZeroExtend = svExtend True ZeroExtend
+
+-- | Sign-extend by given number of bits.
+svSignExtend :: Int -> SVal -> SVal
+svSignExtend = svExtend False SignExtend
+
+svExtend :: Bool -> (Int -> Op) -> Int -> SVal -> SVal
+svExtend isZeroExtend extender i x@(SVal (KBounded s sz) a)
+  | i < 0
+  = error $ "svExtend: Received negative extension amount: " ++ show i
+  | i == 0
+  = x
+  | Left (CV _ (CInteger cv)) <- a
+  = SVal k' (Left (normCV (CV k' (CInteger (replBit (not isZeroExtend && (cv `testBit` (sz-1))) cv)))))
+  | True
+  = SVal k' (Right (cache z))
+  where k' = KBounded s (sz+i)
+        z st = do xsw <- svToSV st x
+                  newExpr st k' (SBVApp (extender i) [xsw])
+
+        replBit :: Bool -> Integer -> Integer
+        replBit b = go sz
+          where stop = sz + i
+                go k v | k == stop = v
+                       | b         = go (k+1) (v `setBit`   k)
+                       | True      = go (k+1) (v `clearBit` k)
+
+svExtend _ _ _ _ = error "svExtend: non-bitvector type"
+
+-- | If-then-else. This one will force branches.
+svIte :: SVal -> SVal -> SVal -> SVal
+svIte t a b = svSymbolicMerge (kindOf a) True t a b
+
+-- | Lazy If-then-else. This one will delay forcing the branches unless it's really necessary.
+svLazyIte :: Kind -> SVal -> SVal -> SVal -> SVal
+svLazyIte k t a b = svSymbolicMerge k False t a b
+
+-- | Merge two symbolic values, at kind @k@, possibly @force@'ing the branches to make
+-- sure they do not evaluate to the same result.
+svSymbolicMerge :: Kind -> Bool -> SVal -> SVal -> SVal -> SVal
+svSymbolicMerge k force t a b
+  | Just r <- svAsBool t
+  = if r then a else b
+  | force, rationalSBVCheck a b, sameResult a b
+  = a
+  | True
+  = SVal k $ Right $ cache c
+  where sameResult (SVal _ (Left c1)) (SVal _ (Left c2)) = c1 == c2
+        sameResult _                  _                  = False
+
+        c st = do swt <- svToSV st t
+                  case () of
+                    () | swt == trueSV  -> svToSV st a       -- these two cases should never be needed as we expect symbolicMerge to be
+                    () | swt == falseSV -> svToSV st b       -- called with symbolic tests, but just in case..
+                    () -> do {- It is tempting to record the choice of the test expression here as we branch down to the 'then' and 'else' branches. That is,
+                                when we evaluate @a@, we can make use of the fact that the test expression is True, and similarly we can use the fact that it
+                                is False when @b@ is evaluated. In certain cases this can cut down on symbolic simulation significantly, for instance if
+                                repetitive decisions are made in a recursive loop. Unfortunately, the implementation of this idea is quite tricky, due to
+                                our sharing based implementation. As the 'then' branch is evaluated, we will create many expressions that are likely going
+                                to be "reused" when the 'else' branch is executed. But, it would be *dead wrong* to share those values, as they were "cached"
+                                under the incorrect assumptions. To wit, consider the following:
+
+                                   foo x y = ite (y .== 0) k (k+1)
+                                     where k = ite (y .== 0) x (x+1)
+
+                                When we reduce the 'then' branch of the first ite, we'd record the assumption that y is 0. But while reducing the 'then' branch, we'd
+                                like to share @k@, which would evaluate (correctly) to @x@ under the given assumption. When we backtrack and evaluate the 'else'
+                                branch of the first ite, we'd see @k@ is needed again, and we'd look it up from our sharing map to find (incorrectly) that its value
+                                is @x@, which was stored there under the assumption that y was 0, which no longer holds. Clearly, this is unsound.
+
+                                A sound implementation would have to precisely track which assumptions were active at the time expressions get shared. That is,
+                                in the above example, we should record that the value of @k@ was cached under the assumption that @y@ is 0. While sound, this
+                                approach unfortunately leads to significant loss of valid sharing when the value itself had nothing to do with the assumption itself.
+                                To wit, consider:
+
+                                   foo x y = ite (y .== 0) k (k+1)
+                                     where k = x+5
+
+                                If we tracked the assumptions, we would recompute @k@ twice, since the branch assumptions would differ. Clearly, there is no need to
+                                re-compute @k@ in this case since its value is independent of @y@. Note that the whole SBV performance story is based on aggressive sharing,
+                                and losing that would have other significant ramifications.
+
+                                The "proper" solution would be to track, with each shared computation, precisely which assumptions it actually *depends* on, rather
+                                than blindly recording all the assumptions present at that time. SBV's symbolic simulation engine clearly has all the info needed to do this
+                                properly, but the implementation is not straightforward at all. For each subexpression, we would need to chase down its dependencies
+                                transitively, which can require a lot of scanning of the generated program causing major slow-down; thus potentially defeating the
+                                whole purpose of sharing in the first place.
+
+                                Design choice: Keep it simple, and simply do not track the assumption at all. This will maximize sharing, at the cost of evaluating
+                                unreachable branches. I think the simplicity is more important at this point than efficiency.
+
+                                Also note that the user can avoid most such issues by properly combining if-then-else's with common conditions together. That is, the
+                                first program above should be written like this:
+
+                                  foo x y = ite (y .== 0) x (x+2)
+
+                                In general, the following transformations should be done whenever possible:
+
+                                  ite e1 (ite e1 e2 e3) e4  --> ite e1 e2 e4
+                                  ite e1 e2 (ite e1 e3 e4)  --> ite e1 e2 e4
+
+                                This is in accordance with the general rule-of-thumb stating conditionals should be avoided as much as possible. However, we might prefer
+                                the following:
+
+                                  ite e1 (f e2 e4) (f e3 e5) --> f (ite e1 e2 e3) (ite e1 e4 e5)
+
+                                especially if this expression happens to be inside 'f's body itself (i.e., when f is recursive), since it reduces the number of
+                                recursive calls. Clearly, programming with symbolic simulation in mind is another kind of beast altogether.
+                             -}
+                             let sta = st `extendSValPathCondition` svAnd t
+                             let stb = st `extendSValPathCondition` svAnd (svNot t)
+                             swa <- svToSV sta a -- evaluate 'then' branch
+                             swb <- svToSV stb b -- evaluate 'else' branch
+
+                             -- merge, but simplify for certain boolean cases:
+                             case () of
+                               () | swa == swb                      -> pure swa                                       -- if t then a      else a     ==> a
+                               () | swa == trueSV && swb == falseSV -> pure swt                                       -- if t then true   else false ==> t
+                               () | swa == falseSV && swb == trueSV -> newExpr st k (SBVApp Not [swt])                -- if t then false  else true  ==> not t
+                               () | swa == trueSV                   -> newExpr st k (SBVApp Or  [swt, swb])           -- if t then true   else b     ==> t OR b
+                               () | swa == falseSV                  -> do swt' <- newExpr st KBool (SBVApp Not [swt])
+                                                                          newExpr st k (SBVApp And [swt', swb])       -- if t then false  else b     ==> t' AND b
+                               () | swb == trueSV                   -> do swt' <- newExpr st KBool (SBVApp Not [swt])
+                                                                          newExpr st k (SBVApp Or [swt', swa])        -- if t then a      else true  ==> t' OR a
+                               () | swb == falseSV                  -> newExpr st k (SBVApp And [swt, swa])           -- if t then a      else false ==> t AND a
+                               ()                                   -> newExpr st k (SBVApp Ite [swt, swa, swb])
+
+-- | Total indexing operation. @svSelect xs default index@ is
+-- intuitively the same as @xs !! index@, except it evaluates to
+-- @default@ if @index@ overflows. Translates to SMT-Lib tables.
+svSelect :: [SVal] -> SVal -> SVal -> SVal
+svSelect xs err ind
+  | SVal _ (Left c) <- ind =
+    case cvVal c of
+      CInteger i -> if i < 0 || i >= genericLength xs
+                    then err
+                    else xs `genericIndex` i
+      _          -> error $ "SBV.select: unsupported " ++ show (kindOf ind) ++ " valued select/index expression"
+svSelect xsOrig err ind = xs `seq` SVal kElt (Right (cache r))
+  where
+    kInd = kindOf ind
+    kElt = kindOf err
+    -- Based on the index size, we need to limit the elements. For
+    -- instance if the index is 8 bits, but there are 257 elements,
+    -- that last element will never be used and we can chop it off.
+    xs = case kInd of
+           KBounded False i -> genericTake ((2::Integer) ^ i) xsOrig
+           KBounded True  i -> genericTake ((2::Integer) ^ (i-1)) xsOrig
+           KUnbounded       -> xsOrig
+           _                -> error $ "SBV.select: unsupported " ++ show kInd ++ " valued select/index expression"
+    r st = do sws <- mapM (svToSV st) xs
+              swe <- svToSV st err
+              if all (== swe) sws  -- off-chance that all elts are the same
+                 then pure swe
+                 else do idx <- getTableIndex st kInd kElt sws
+                         swi <- svToSV st ind
+                         let len = length xs
+                         -- NB. No need to worry here that the index
+                         -- might be < 0; as the SMTLib translation
+                         -- 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])
+
+-- | Convert a symbolic bitvector from unsigned to signed.
+svSign :: SVal -> SVal
+svSign = svChangeSign True
+
+-- | Convert a symbolic bitvector from signed to unsigned.
+svUnsign :: SVal -> SVal
+svUnsign = svChangeSign False
+
+-- | Convert a symbolic bitvector from one integral kind to another.
+svFromIntegral :: Kind -> SVal -> SVal
+svFromIntegral kTo x
+  | Just v <- svAsInteger x
+  = svInteger kTo v
+  | True
+  = result
+  where result = SVal kTo (Right (cache y))
+        kFrom  = kindOf x
+        y st   = do xsw <- svToSV st x
+                    newExpr st kTo (SBVApp (KindCast kFrom kTo) [xsw])
+
+-- | Create a NaN floating-point value of the given kind.
+svFPNaN :: Kind -> SVal
+svFPNaN k = SVal k $ Left $ fpConstCV k nan nan fpNaN
+  where
+    nan :: forall a. Floating a => a
+    nan = 0/0
+
+-- | Create an infinite floating-point value of the given kind. If the 'Bool'
+-- argument is 'True', then use negative infinity; otherwise, use positive
+-- infinity.
+svFPInf :: Kind -> Bool -> SVal
+svFPInf k neg = SVal k $ Left $ fpConstCV k signedInfinity signedInfinity (fpInf neg)
+  where
+    infinity :: forall a. Floating a => a
+    infinity = 1/0
+
+    signedInfinity :: forall a. Floating a => a
+    signedInfinity = if neg then -infinity else infinity
+
+-- | Create a signed zero value of the given kind. If the 'Bool' argument is
+-- 'True', then use negative zero; otherwise, use positive zero.
+svFPZero :: Kind -> Bool -> SVal
+svFPZero k neg = SVal k $ Left $ fpConstCV k signedZero signedZero (fpZero neg)
+  where
+    signedZero :: forall a. Num a => a
+    signedZero = if neg then -0 else 0
+
+-- | Create a float-point value of the given kind from an 'Integer' literal.
+svFPFromIntegerLit :: Kind -> Integer -> SVal
+svFPFromIntegerLit k r = SVal k $ Left $ fpConstCV k (fromInteger r) (fromInteger r) (\eb sb -> fpFromInteger eb sb r)
+
+-- | Create a float-point value of the given kind from a 'Rational' literal.
+svFPFromRationalLit :: Kind -> Rational -> SVal
+svFPFromRationalLit k r = SVal k $ Left $ fpConstCV k (fromRational r) (fromRational r) (\eb sb -> fpFromRational eb sb r)
+
+-- | Is the given floating-point value a zero value?
+svFPIsZero :: SVal -> SVal
+svFPIsZero = liftFPPred (mkSymOp1 (IEEEFP FP_IsZero)) isZero isZero fpIsZero
+  where
+    isZero :: forall a. RealFloat a => a -> Bool
+    isZero x = x == 0
+
+-- | Is the given floating-point value infinite?
+svFPIsInfinite :: SVal -> SVal
+svFPIsInfinite = liftFPPred (mkSymOp1 (IEEEFP FP_IsInfinite)) isInfinite isInfinite fpIsInf
+
+-- | Is the given floating-point value negative?
+svFPIsNegative :: SVal -> SVal
+svFPIsNegative = liftFPPred (mkSymOp1 (IEEEFP FP_IsNegative)) isNegative isNegative fpIsNeg
+  where
+    isNegative :: forall a. RealFloat a => a -> Bool
+    isNegative x = x < 0 || isNegativeZero x
+
+-- | Is the given floating-point value positive?
+svFPIsPositive :: SVal -> SVal
+svFPIsPositive = liftFPPred (mkSymOp1 (IEEEFP FP_IsPositive)) isPositive isPositive fpIsPos
+  where
+    isPositive :: forall a. RealFloat a => a -> Bool
+    isPositive x = x >= 0 && not (isNegativeZero x)
+
+-- | Is the given floating-point value a NaN value?
+svFPIsNaN :: SVal -> SVal
+svFPIsNaN = liftFPPred (mkSymOp1 (IEEEFP FP_IsNaN)) isNaN isNaN fpIsNaN
+
+-- | Is the given floating-point value \"normal\"? That is, is the value not
+-- zero, infinite, NaN, or subnormal?
+svFPIsNormal :: SVal -> SVal
+svFPIsNormal = liftFPPred (mkSymOp1 (IEEEFP FP_IsNormal)) fpIsNormalizedH fpIsNormalizedH fpIsNormal
+
+-- | Is the given floating-point value subnormal (i.e., denormalized)?
+svFPIsSubnormal :: SVal -> SVal
+svFPIsSubnormal = liftFPPred (mkSymOp1 (IEEEFP FP_IsSubnormal)) isDenormalized isDenormalized fpIsSubnormal
+
+-- | Floating-point addition.
+svFPAdd :: SVal -- ^ Rounding mode
+        -> SVal -> SVal -> SVal
+svFPAdd = liftFPSymRM2 "add" (mkSymOp3 (IEEEFP FP_Add)) (+) (+) fpAdd
+
+-- | Floating-point subtraction.
+svFPSub :: SVal -- ^ Rounding mode
+        -> SVal -> SVal -> SVal
+svFPSub = liftFPSymRM2 "sub" (mkSymOp3 (IEEEFP FP_Sub)) (-) (-) fpSub
+
+-- | Floating-point multiplication.
+svFPMul :: SVal -- ^ Rounding mode
+        -> SVal -> SVal -> SVal
+svFPMul = liftFPSymRM2 "mul" (mkSymOp3 (IEEEFP FP_Mul)) (*) (*) fpMul
+
+-- | Floating-point division.
+svFPDiv :: SVal -- ^ Rounding mode
+        -> SVal -> SVal -> SVal
+svFPDiv = liftFPSymRM2 "div" (mkSymOp3 (IEEEFP FP_Div)) (/) (/) fpDiv
+
+-- | Floating-point remainder.
+svFPRem :: SVal -> SVal -> SVal
+svFPRem = liftFPSym2 "rem" (mkSymOp (IEEEFP FP_Rem)) fpRemH fpRemH (fpRem RoundNearestTiesToEven)
+
+-- | Floating-point minimum.
+svFPMin :: SVal -> SVal -> SVal
+svFPMin = liftFPSym2 "min" (mkSymOp (IEEEFP FP_Min)) fpMinH fpMinH fpMin
+
+-- | Floating-point maximum.
+svFPMax :: SVal -> SVal -> SVal
+svFPMax = liftFPSym2 "max" (mkSymOp (IEEEFP FP_Max)) fpMaxH fpMaxH fpMax
+
+-- | Floating-point fused-multiply-add (FMA).
+
+-- Note that this operation is defined somewhat unusually because Haskell lacks
+-- a native FMA operation to use for concrete evaluation of 'Float's and
+-- 'Double's. See https://github.com/LeventErkok/sbv/issues/777 for more
+-- discussion. As such, concrete FMA evaluation is only supported for t'FP'
+-- values.
+svFPFMA :: SVal -- ^ Rounding mode
+        -> SVal -> SVal -> SVal -> SVal
+svFPFMA (svAsRoundingMode -> Just rm)
+        (SVal k (Left (cvVal -> CFP a)))
+        (SVal _ (Left (cvVal -> CFP b)))
+        (SVal _ (Left (cvVal -> CFP c))) =
+  SVal k $ Left $ CV k $ CFP $ fpFMA rm a b c
+svFPFMA rm a@(SVal k _) b c = SVal k $ Right $ cache ca
+   where ca st = do svrm <- svToSV st rm
+                    sva <- svToSV st a
+                    svb <- svToSV st b
+                    svc <- svToSV st c
+                    newExpr st k (SBVApp (IEEEFP FP_FMA) [svrm, sva, svb, svc])
+
+-- | Floating-point absolute value.
+svFPAbs :: SVal -> SVal
+svFPAbs = liftFPSym1 "abs" (mkSymOp1 (IEEEFP FP_Abs)) abs abs fpAbs
+
+-- | Floating-point negation.
+svFPNeg :: SVal -> SVal
+svFPNeg = liftFPSym1 "negate" (mkSymOp1 (IEEEFP FP_Neg)) negate negate fpNeg
+
+-- | Round the given floating-point value to the nearest integer (represented
+-- as a float with a zero decimal component) using the given rounding mode.
+svFPRoundToIntegral :: SVal -- ^ Rounding mode
+                    -> SVal -> SVal
+svFPRoundToIntegral = liftFPSymRM1 "roundToIntegral" (mkSymOp (IEEEFP FP_RoundToIntegral)) fpRoundToIntegralH fpRoundToIntegralH fpRoundInt
+
+-- | Floating-point square root.
+svFPSqrt :: SVal -- ^ Rounding mode
+         -> SVal -> SVal
+svFPSqrt = liftFPSymRM1 "sqrt" (mkSymOp (IEEEFP FP_Sqrt)) sqrt sqrt fpSqrt
+
+-- | Cast an t'FP' value to a t'CV' of the given floating-point 'Kind' using the
+-- given 'RoundingMode'. This will error if given a non-floating-point 'Kind'.
+cvCastFromFP :: Kind -> RoundingMode -> FP -> CV
+cvCastFromFP kindTo rm fp =
+  fpConstCV
+    kindTo
+    (fpToFloat rm (fpRoundFloat 8 24 rm fp))
+    (fpToDouble rm (fpRoundFloat 11 53 rm fp))
+    (\eb sb -> fpRoundFloat eb sb rm fp)
+
+-- | Cast a 'Rational' value to a t'CV' of the given floating-point 'Kind'. This
+-- will error if given a non-floating-point 'Kind'.
+cvCastFromRational :: Kind -> Rational -> CV
+cvCastFromRational kindTo r =
+  fpConstCV
+    kindTo
+    (fromRational r)
+    (fromRational r)
+    (\eb sb -> fpFromRational eb sb r)
+
+-- | Convert a 'CVal' to an t'FP' value of the appropriate size. This will error
+-- if the 'CVal' is not a floating-point value.
+cvalToFP :: CVal -> FP
+cvalToFP (CFloat f) = fpFromFloat 8 24 f
+cvalToFP (CDouble d) = fpFromDouble 11 53 d
+cvalToFP (CFP fp) = fp
+cvalToFP _ = error "cvalToFP: non-float value"
+
+-- | Convert a value to a floating-point value. The type being converted from
+-- must be one of 'KFloat', 'KDouble', 'KFP', 'KBounded', 'KUnbounded', or
+-- 'KReal'.
+--
+-- Note that converting from a 'KBounded' value returns a float with the same
+-- numeric value as the input bitvector. For a conversion that returns a float
+-- with the same bit pattern as the input bitvector, see 'svSWord32AsFloat',
+-- 'svSWord64AsDouble', and 'svSWordAsFloatingPoint'.
+svCastToFP :: Kind -- ^ The kind to cast to. Must be a floating-point kind.
+           -> SVal -- ^ Rounding mode
+           -> SVal -- ^ The value to be casted.
+           -> SVal
+svCastToFP kindTo (svAsRoundingMode -> Just rm) x@(SVal kindFrom (Left (CV _ x')))
+  | kindFrom == kindTo
+  = x
+
+  | KFloat {} <- kindFrom
+  = fpCastFromFloat
+  | KDouble {} <- kindFrom
+  = fpCastFromFloat
+  | KFP {} <- kindFrom
+  = fpCastFromFloat
+
+  | RoundNearestTiesToEven <- rm
+  , KBounded {} <- kindFrom
+  , CInteger w <- x'
+  = fpCastFromIntegral w
+  | RoundNearestTiesToEven <- rm
+  , KUnbounded {} <- kindFrom
+  , CInteger i <- x'
+  = fpCastFromIntegral i
+
+  | RoundNearestTiesToEven <- rm
+  , CAlgReal r <- x'
+  , isExactRational r
+  = SVal kindTo $ Left $ cvCastFromRational kindTo $ toRational r
+  where fpCastFromFloat :: SVal
+        fpCastFromFloat = SVal kindTo $ Left $ cvCastFromFP kindTo rm $ cvalToFP x'
+
+        fpCastFromIntegral :: forall a. Integral a => a -> SVal
+        fpCastFromIntegral =
+          SVal kindTo . Left . cvCastFromRational kindTo . fromIntegral
+svCastToFP kindTo rm x@(SVal kindFrom _)
+  = SVal kindTo $ Right $ cache y
+  where y st = do svrm <- svToSV st rm
+                  svx <- svToSV st x
+                  mkSymOp (IEEEFP (FP_Cast kindFrom kindTo svrm)) st kindTo svrm svx
+
+-- | Convert a floating-point value to a value of a different type. The type to
+-- convert to must be one of 'KFloat', 'KDouble', 'KFP', 'KBounded',
+-- 'KUnbounded', or 'KReal'.
+--
+-- Note that converting to 'KBounded' returns a bitvector with the same numeric
+-- value as the input float (appropriately rounded). For a lossless conversion
+-- that returns a bitvector with the same bit pattern as the input float, see
+-- 'svFloatAsSWord32', 'svDoubleAsSWord64', and 'svFloatingPointAsSWord'.
+svCastFromFP :: Kind -- ^ The kind to cast to.
+             -> SVal -- ^ Rounding mode
+             -> SVal -- ^ The value to be casted. Must be a floating-point value.
+             -> SVal
+svCastFromFP kindTo (svAsRoundingMode -> Just rm) x@(SVal kindFrom (Left (CV _ x')))
+  | kindFrom == kindTo
+  = x
+
+  | KFloat {} <- kindTo
+  = fpCastToFloat
+  | KDouble {} <- kindTo
+  = fpCastToFloat
+  | KFP {} <- kindTo
+  = fpCastToFloat
+  -- No constant-folding for KBounded, KUnbounded, or KReal, as each of these
+  -- conversions are partial. Rather than painstakingly check which inputs are
+  -- valid, we simply defer to the underlying SMT-LIB operations.
+  where fpCastToFloat :: SVal
+        fpCastToFloat = SVal kindTo $ Left $ cvCastFromFP kindTo rm $ cvalToFP x'
+svCastFromFP kindTo rm x@(SVal kindFrom _)
+  = SVal kindTo $ Right $ cache y
+  where y st = do svrm <- svToSV st rm
+                  svx <- svToSV st x
+                  mkSymOp (IEEEFP (FP_Cast kindFrom kindTo svrm)) st kindTo svrm svx
+
+--------------------------------------------------------------------------------
+-- Derived operations
+
+-- | Convert an SVal from kind Bool to an unsigned bitvector of size 1.
+svToWord1 :: SVal -> SVal
+svToWord1 b = svSymbolicMerge k True b (svInteger k 1) (svInteger k 0)
+  where k = KBounded False 1
+
+-- | Convert an SVal from a bitvector of size 1 (signed or unsigned) to kind Bool.
+svFromWord1 :: SVal -> SVal
+svFromWord1 x = svNotEqual x (svInteger k 0)
+  where k = kindOf x
+
+-- | Test the value of a bit. Note that we do an extract here
+-- as opposed to masking and checking against zero, as we found
+-- extraction to be much faster with large bit-vectors.
+svTestBit :: SVal -> Int -> SVal
+svTestBit x i
+  | i < intSizeOf x = svFromWord1 (svExtract i i x)
+  | True            = svFalse
+
+-- | Generalization of 'svShl', where the shift-amount is symbolic.
+svShiftLeft :: SVal -> SVal -> SVal
+svShiftLeft = svShift True
+
+-- | Generalization of 'svShr', where the shift-amount is symbolic.
+--
+-- NB. If the shiftee is signed, then this is an arithmetic shift;
+-- otherwise it's logical.
+svShiftRight :: SVal -> SVal -> SVal
+svShiftRight = svShift False
+
+-- | Generic shifting of bounded quantities. The shift amount must be non-negative and within the bounds of the argument
+-- for bit vectors. For negative shift amounts, the result is returned unchanged. For overshifts, left-shift produces 0,
+-- right shift produces 0 or -1 depending on the result being signed.
+svShift :: Bool -> SVal -> SVal -> SVal
+svShift toLeft x i
+  | Just r <- constFoldValue
+  = r
+  | cannotOverShift
+  = svIte (i `svLessThan` svInteger ki 0)                                         -- Negative shift, no change
+          x
+          regularShiftValue
+  | True
+  = svIte (i `svLessThan` svInteger ki 0)                                         -- Negative shift, no change
+          x
+          $ svIte (i `svGreaterEq` svInteger ki (fromIntegral (intSizeOf x)))     -- Overshift, by at least the bit-width of x
+                  overShiftValue
+                  regularShiftValue
+
+  where nm | toLeft = "shiftLeft"
+           | True   = "shiftRight"
+
+        kx = kindOf x
+        ki = kindOf i
+
+        -- Constant fold the result if possible. If either quantity is unbounded, then we only support constants
+        -- as there's no easy/meaningful way to map this combo to SMTLib. Should be rarely needed, if ever!
+        -- We also perform basic sanity check here so that if we go past here, we know we have bitvectors only.
+        constFoldValue
+          | Just iv <- getConst i, iv == 0
+          = Just x
+
+          | Just xv <- getConst x, xv == 0
+          = Just x
+
+          | Just xv <- getConst x, Just iv <- getConst i
+          = Just $ SVal kx . Left $! normCV $ CV kx (CInteger (xv `opC` shiftAmount iv))
+
+          | 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)
+          = bailOut $ "Unexpected kinds: " ++ show (kx, ki)
+
+          | True
+          = Nothing
+
+          where bailOut m = error $ "SBV." ++ nm ++ ": " ++ m
+
+                getConst (SVal _ (Left (CV _ (CInteger val)))) = Just val
+                getConst _                                     = Nothing
+
+                opC | toLeft = shiftL
+                    | True   = shiftR
+
+                -- like fromIntegral, but more paranoid
+                shiftAmount :: Integer -> Int
+                shiftAmount 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
+        -- of i. Note that this is a *necessary* check, Consider for instance if we're shifting a
+        -- 32-bit value using a 1-bit shift amount (which can happen if the value is 1 with minimal
+        -- shift widths). We would compare 1 >= 32, but stuffing 32 into bit-vector of size 1 would
+        -- overflow. See http://github.com/LeventErkok/sbv/issues/323 for this case. Thus, we
+        -- make sure that the bit-vector would fit as a value.
+        cannotOverShift = maxRepresentable <= fromIntegral (intSizeOf x)
+          where maxRepresentable :: Integer
+                maxRepresentable
+                  | hasSign i = bit (intSizeOf i - 1) - 1
+                  | True      = bit (intSizeOf i    ) - 1
+
+        -- An overshift occurs if we're shifting by more than or equal to the bit-width of x
+        --     For shift-left: this value is always 0
+        --     For shift-right:
+        --        If x is unsigned: 0
+        --        If x is signed and is less than 0, then -1 else 0
+        overShiftValue | toLeft    = zx
+                       | hasSign x = svIte (x `svLessThan` zx) neg1 zx
+                       | True      = zx
+          where zx   = svInteger kx 0
+                neg1 = svInteger kx (-1)
+
+        -- Regular shift, we know that the shift value fits into the bit-width of x, since it's between 0 and sizeOf x. So, we can just
+        -- turn it into a properly sized argument and ship it to SMTLib
+        regularShiftValue = SVal kx $ Right $ cache result
+           where result st = do sw1 <- svToSV st x
+                                sw2 <- svToSV st i
+
+                                let op | toLeft = Shl
+                                       | True   = Shr
+
+                                adjustedShift <- if kx == ki
+                                                 then pure sw2
+                                                 else newExpr st kx (SBVApp (KindCast ki kx) [sw2])
+
+                                newExpr st kx (SBVApp op [sw1, adjustedShift])
+
+-- | 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 'svRol', where the rotation amount is symbolic.
+-- If the first argument is not bounded, then the this is the same as shift.
+svRotateLeft :: SVal -> SVal -> SVal
+svRotateLeft = svRotate svShiftLeft svRor svRol
+
+-- | 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
+svRotateRight = svRotate svShiftRight svRol svRor
+
+-- | Common implementation for rotations. This is more complicated than it might first seem, since SMTLib does
+-- not allow for non-constant rotation amounts, and only defines rotations for bit-vectors. In SBV, we support
+-- both finite/infinite combos, and also non-constant (i.e., symbolic) rotations. Furthermore, if the rotation
+-- amount is negative, then the direction of the rotation is reversed.
+--
+--   Case 1. Infinite x. In this case, we call unbounded-shifter, since you can't rotate an unbounded integer value.
+--                       This is the Haskell semantics for rotates.
+--   Case 2. Finite x.
+--           Case 2.1. Infinite i, or finite i but i can contain a value > |x|. In this case, wrap-around can happen,
+--                     so we reduce by the size of |x|.
+--           Case 2.2. Finite i, and it can't contain a value > |x|. In this case, no reduction is needed.
+svRotate :: (SVal -> SVal -> SVal) -> (SVal -> Int -> SVal) -> (SVal -> Int -> SVal) -> SVal -> SVal -> SVal
+svRotate unboundedShifter opRot curRot x i
+  | not (isBounded x)
+  = unboundedShifter x i
+  | True
+  = svSelect table (svInteger (kindOf x) 0) curRotate
+ where sx = intSizeOf x
+       si = intSizeOf i
+
+       -- Is it the case that this rotation can never "wrap-around?" This happens if
+       -- i is bounded and the max rotation it can represent is less than the bit-size of the input
+       noWrapAround :: Bool
+       noWrapAround = isBounded i && maxRotate <= toInteger sx
+         where maxRotate :: Integer
+               maxRotate
+                 | hasSign i = 2^(si-1)
+                 | True      = 2^si-1
+
+       ifNegRotate = svIte (svLessThan i (svInteger (kindOf i) 0))
+
+       -- the lookup table has sx entries if index can wrap-around. Otherwise it is just as wide as it needs to be.
+       table :: [SVal]
+       table = map rotK vals
+         where rotK k = ifNegRotate (x `opRot` k) (x `curRot` k)
+               vals | noWrapAround = if hasSign i
+                                        then -- If signed then bit (si-1) is the max abs value. (consider 3 bits, [-4..3] is the range)
+                                             [0 .. bit (si - 1)]
+                                        else [0 .. bit si  - 1]
+                    | True  -- If wrap-around can happen, then compute all rotations up to |x|
+                    = [0 .. sx - 1]
+
+       -- What's the current rotation amount? Here we change the type of the
+       -- index to make it one bit larger if the index is signed, since otherwise
+       -- we run into (-(-1)) = -1 problem. See https://github.com/LeventErkok/sbv/issues/673#issuecomment-1782296700
+       -- Note that curRotate is always non-negative.
+       curRotate :: SVal
+       curRotate
+         | noWrapAround = ifNegRotate (svUNeg i'          ) i'
+         | True         = ifNegRotate (svUNeg i' `svRem` n) (i' `svRem` n)
+
+         where i' | hasSign i && isBounded i = toWord $ svAbs $ enlarge i
+                  | True                     = i
+
+               -- Make sure sx can fit into this many bits
+               si' = (si + 1) `max` bitsNeeded sx
+
+               enlarge
+                 | isBounded i = svFromIntegral (KBounded True  si')  -- Increase bit size
+                 | True        = id
+               toWord
+                 | isBounded i = svFromIntegral (KBounded False si')  -- Treat as word, after call to svAbs above
+                 | True        = id
+
+               n = svInteger (kindOf i') (toInteger sx)
+
+               bitsNeeded :: Int -> Int
+               bitsNeeded = go 0
+                 where go s 0 = s
+                       go s v = let s' = s + 1 in s' `seq` go s' (v `shiftR` 1)
+
+--------------------------------------------------------------------------------
+-- | Overflow detection.
+svMkOverflow1 :: OvOp -> SVal -> SVal
+svMkOverflow1 o x = SVal KBool (Right (cache r))
+    where r st = do sx <- svToSV st x
+                    newExpr st KBool $ SBVApp (OverflowOp o) [sx]
+
+svMkOverflow2 :: OvOp -> SVal -> SVal -> SVal
+svMkOverflow2 o x y = SVal KBool (Right (cache r))
+    where r st = do sx <- svToSV st x
+                    sy <- svToSV st y
+                    newExpr st KBool $ SBVApp (OverflowOp o) [sx, sy]
+
+--------------------------------------------------------------------------------
+-- Utility functions
+
+liftSym1 :: (State -> Kind -> SV -> IO SV) -> (AlgReal  -> AlgReal)
+                                           -> (Integer  -> Integer)
+                                           -> (Float    -> Float)
+                                           -> (Double   -> Double)
+                                           -> (FP       -> FP)
+                                           -> (Rational -> Rational)
+                                           -> SVal      -> SVal
+liftSym1 _   opCR opCI opCF opCD opFP opRA   (SVal k (Left a)) = SVal k . Left  $! mapCV opCR opCI opCF opCD opFP opRA a
+liftSym1 opS _    _    _    _    _    _    a@(SVal k _)        = SVal k $ Right $ cache c
+   where c st = do sva <- svToSV st a
+                   opS st k sva
+
+{- A note on constant folding.
+
+There are cases where we miss out on certain constant foldings. On May 8 2018, Matt Peddie pointed this
+out, as the C code he was getting had redundancies. I was aware that could be missing constant foldings
+due to missed out optimizations, or some other code snafu, but till Matt pointed it out I haven't realized
+that we could be hiding constants inside an if-then-else. The example is:
+
+     proveWith z3{verbose=True} $ \x -> 0 .< ite (x .== (x::SWord8)) 1 (2::SWord8)
+
+If you try this, you'll see that it generates (shortened):
+
+    (define-fun s1 () (_ BitVec 8) #x00)
+    (define-fun s2 () (_ BitVec 8) #x01)
+    (define-fun s3 () Bool (bvult s1 s2))
+
+But clearly we have all the info for s3 to be computed! The issue here is that the reduction of @x .== x@ to @true@
+happens after we start computing the if-then-else, hence we are already committed to an SV at that point. The call
+to ite eventually recognizes this, but at that point it picks up the now constants from SV's, missing the constant
+folding opportunity.
+
+We can fix this, by looking up the constants table in liftSV2, along the lines of:
+
+
+    liftSV2 :: (CV -> CV -> Bool) -> (CV -> CV -> CV) -> (State -> Kind -> SV -> SV -> IO SV) -> Kind -> SVal -> SVal -> Cached SV
+    liftSV2 okCV opCV opS k a b = cache c
+      where c st = do sw1 <- svToSV st a
+                      sw2 <- svToSV st b
+                      cmap <- readIORef (rconstMap st)
+                      let cv1  = [cv | ((_, cv), sv) <- M.toList cmap, sv == sv1]
+                          cv2  = [cv | ((_, cv), sv) <- M.toList cmap, sv == sv2]
+                      case (cv1, cv2) of
+                        ([x], [y]) | okCV x y -> newConst st $ opCV x y
+                        _                     -> opS st k sv1 sv2
+
+(with obvious modifications to call sites to get the proper arguments.)
+
+But this means that we have to grab the constant list for every symbolically lifted operation, also do the
+same for other places, etc.; for the rare opportunity of catching a @x .== x@ optimization. Even then, the
+constants for the branches would still be generated. (i.e., in the above example we would still generate
+@s1@ and @s2@, but would skip @s3@.)
+
+It seems to me that the price to pay is rather high, as this is hardly the most common case; so we're opting
+here to ignore these cases.
+
+See http://github.com/LeventErkok/sbv/issues/379 for some further discussion.
+-}
+liftSV2 :: (State -> Kind -> SV -> SV -> IO SV) -> Kind -> SVal -> SVal -> Cached SV
+liftSV2 opS k a b = cache c
+  where c st = do sw1 <- svToSV st a
+                  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)
+         -> (FP       -> FP      -> FP)
+         -> (Rational -> Rational-> Rational)
+         -> SVal      -> SVal    -> SVal
+liftSym2 _   okCV opCR opCI opCF opCD opFP opRA (SVal k (Left a)) (SVal _ (Left b)) | and [f a b | f <- okCV] = SVal k . Left  $! mapCV2 opCR opCI opCF opCD opFP opRA a b
+liftSym2 opS _    _    _    _    _    _  _      a@(SVal k _)      b                                           = SVal k $ Right $  liftSV2 opS k a b
+
+-- | Lift a unary floating-point operation that can work over 'Float',
+-- 'Double', and t'FP' values.
+liftFPSym1 :: String
+           -> (State -> Kind -> SV -> IO SV)
+           -> (Float -> Float)
+           -> (Double -> Double)
+           -> (FP -> FP)
+           -> SVal -> SVal
+liftFPSym1 o _ opCF opCD opFP (SVal k (Left a))
+  = SVal k . Left  $! mapCV (noRealUnary o) (noIntUnary o) opCF opCD opFP (noRatUnary o) a
+liftFPSym1 _ opS _ _ _ a@(SVal k _) = SVal k $ Right $ cache c
+   where c st = do sva <- svToSV st a
+                   opS st k sva
+
+-- | Like 'liftFPSym1', but with an explicit rounding mode. Note that concrete
+-- evaluation of 'Float's or 'Double's is only supported when the
+-- 'RoundNearestTiesToEven' rounding mode is used (see the Haddocks for
+-- 'floatDoubleRneCheck').
+liftFPSymRM1 :: String
+             -> (State -> Kind -> SV -> SV -> IO SV)
+             -> (Float -> Float)
+             -> (Double -> Double)
+             -> (RoundingMode -> FP -> FP)
+             -> SVal -> SVal -> SVal
+liftFPSymRM1 o _ opCF opCD opFP rm (SVal k (Left a))
+  | Just rm'@RoundNearestTiesToEven <- svAsRoundingMode rm
+  , floatDoubleRneCheck rm' a
+  = SVal k . Left $! mapCV (noRealUnary o) (noIntUnary o) opCF opCD (opFP rm') (noRatUnary o) a
+liftFPSymRM1 _ opS _ _ _ rm a@(SVal k _) = SVal k $ Right $ cache c
+   where c st = do svrm <- svToSV st rm
+                   sva <- svToSV st a
+                   opS st k svrm sva
+
+-- | Lift a binary floating-point operation that can work over 'Float',
+-- 'Double', and t'FP' values.
+liftFPSym2 :: String
+           -> (State -> Kind -> SV -> SV -> IO SV)
+           -> (Float -> Float -> Float)
+           -> (Double -> Double -> Double)
+           -> (FP -> FP -> FP)
+           -> SVal -> SVal -> SVal
+liftFPSym2 o _ opCF opCD opFP (SVal k (Left a)) (SVal _ (Left b))
+  = SVal k . Left $! mapCV2 (noReal o) (noInt o) opCF opCD opFP (noRat o) a b
+liftFPSym2 _ opS _ _ _ a@(SVal k _) b = SVal k $ Right $ cache c
+   where c st = do sva <- svToSV st a
+                   svb <- svToSV st b
+                   opS st k sva svb
+
+-- | Like 'liftFPSym2', but with an explicit rounding mode. Note that concrete
+-- evaluation of 'Float's or 'Double's is only supported when the
+-- 'RoundNearestTiesToEven' rounding mode is used (see the Haddocks for
+-- 'floatDoubleRneCheck').
+liftFPSymRM2 :: String
+             -> (State -> Kind -> SV -> SV -> SV -> IO SV)
+             -> (Float -> Float -> Float)
+             -> (Double -> Double -> Double)
+             -> (RoundingMode -> FP -> FP -> FP)
+             -> SVal -> SVal -> SVal -> SVal
+liftFPSymRM2 o _ opCF opCD opFP rm (SVal k (Left a)) (SVal _ (Left b))
+  | Just rm'@RoundNearestTiesToEven <- svAsRoundingMode rm
+  , floatDoubleRneCheck rm' a
+  = SVal k . Left $! mapCV2 (noReal o) (noInt o) opCF opCD (opFP rm') (noRat o) a b
+liftFPSymRM2 _ opS _ _ _ rm a@(SVal k _) b = SVal k $ Right $ cache c
+   where c st = do svrm <- svToSV st rm
+                   sva <- svToSV st a
+                   svb <- svToSV st b
+                   opS st k svrm sva svb
+
+-- | Lift a unary floating-point predicate that can work over 'Float',
+-- 'Double', and t'FP' values.
+liftFPPred :: (State -> Kind -> SV -> IO SV)
+           -> (Float -> Bool)
+           -> (Double -> Bool)
+           -> (FP -> Bool)
+           -> SVal -> SVal
+liftFPPred _ opCF opCD opFP (SVal k (Left a)) =
+  case cvVal a of
+    CFloat f -> svBool $ opCF f
+    CDouble d -> svBool $ opCD d
+    CFP fp -> svBool $ opFP fp
+
+    CAlgReal {} -> unexpected
+    CInteger {} -> unexpected
+    CRational {} -> unexpected
+    CChar {} -> unexpected
+    CString {} -> unexpected
+    CList {} -> unexpected
+    CSet {} -> unexpected
+    CADT {} -> unexpected
+    CTuple {} -> unexpected
+    CArray {} -> unexpected
+  where unexpected = error $ "Data.SBV.liftFPPred: Unexpected kind: " ++ show k
+liftFPPred opS _ _ _ a = SVal KBool $ Right $ cache c
+   where c st = do sva <- svToSV st a
+                   opS st KBool sva
+
+-- | Create a symbolic two argument operation; with shortcut optimizations
+mkSymOpSC :: (SV -> SV -> Maybe SV) -> Op -> State -> Kind -> SV -> SV -> IO SV
+mkSymOpSC shortCut op st k a b = maybe (newExpr st k (SBVApp op [a, b])) pure (shortCut a b)
+
+-- | Create a symbolic two argument operation; no shortcut optimizations
+mkSymOp :: Op -> State -> Kind -> SV -> SV -> IO SV
+mkSymOp = mkSymOpSC (const (const Nothing))
+
+mkSymOp1SC :: (SV -> Maybe SV) -> Op -> State -> Kind -> SV -> IO SV
+mkSymOp1SC shortCut op st k a = maybe (newExpr st k (SBVApp op [a])) pure (shortCut a)
+
+mkSymOp1 :: Op -> State -> Kind -> SV -> IO SV
+mkSymOp1 = mkSymOp1SC (const Nothing)
+
+mkSymOp3 :: Op -> State -> Kind -> SV -> SV -> SV -> IO SV
+mkSymOp3 op st k a b c = newExpr st k (SBVApp op [a, b, c])
+
+-- | Predicate to check if a value is concrete
+isConcrete :: SVal -> Bool
+isConcrete (SVal _ Left{}) = True
+isConcrete _               = False
+
+-- | Predicate for optimizing word operations like (+) and (*).
+-- NB. We specifically do *not* match for Double/Float; because
+-- FP-arithmetic doesn't obey traditional rules. For instance,
+-- 0 * x = 0 fails if x happens to be NaN or +/- Infinity. So,
+-- we merely return False when given a floating-point value here.
+isConcreteZero :: SVal -> Bool
+isConcreteZero (SVal _     (Left (CV _     (CInteger n)))) = n == 0
+isConcreteZero (SVal KReal (Left (CV KReal (CAlgReal v)))) = isExactRational v && v == 0
+isConcreteZero _                                           = False
+
+-- | Predicate for optimizing word operations like (+) and (*).
+-- NB. See comment on 'isConcreteZero' for why we don't match
+-- for Float/Double values here.
+isConcreteOne :: SVal -> Bool
+isConcreteOne (SVal _     (Left (CV _     (CInteger 1)))) = True
+isConcreteOne (SVal KReal (Left (CV KReal (CAlgReal v)))) = isExactRational v && v == 1
+isConcreteOne _                                           = False
+
+-- | Predicate for optimizing bitwise operations. The unbounded integer case of checking
+-- against -1 might look dubious, but that's how Haskell treats 'Integer' as a member
+-- of the Bits class, try @(-1 :: Integer) `testBit` i@ for any @i@ and you'll get 'True'.
+isConcreteOnes :: SVal -> Bool
+isConcreteOnes (SVal _ (Left (CV (KBounded b w) (CInteger n)))) = n == if b then -1 else bit w - 1
+isConcreteOnes (SVal _ (Left (CV KUnbounded     (CInteger n)))) = n == -1  -- see comment above
+isConcreteOnes (SVal _ (Left (CV KBool          (CInteger n)))) = n == 1
+isConcreteOnes _                                                = False
+
+-- | Predicate for optimizing comparisons.
+isConcreteMax :: SVal -> Bool
+isConcreteMax (SVal _ (Left (CV (KBounded False w) (CInteger n)))) = n == bit w - 1
+isConcreteMax (SVal _ (Left (CV (KBounded True  w) (CInteger n)))) = n == bit (w - 1) - 1
+isConcreteMax (SVal _ (Left (CV KBool              (CInteger n)))) = n == 1
+isConcreteMax _                                                    = False
+
+-- | Predicate for optimizing comparisons.
+isConcreteMin :: SVal -> Bool
+isConcreteMin (SVal _ (Left (CV (KBounded False _) (CInteger n)))) = n == 0
+isConcreteMin (SVal _ (Left (CV (KBounded True  w) (CInteger n)))) = n == - bit (w - 1)
+isConcreteMin (SVal _ (Left (CV KBool              (CInteger n)))) = n == 0
+isConcreteMin _                                                    = False
+
+-- | Most operations on concrete rationals require a compatibility check to avoid faulting
+-- on algebraic reals.
+rationalCheck :: CV -> CV -> Bool
+rationalCheck a b = case (cvVal a, cvVal b) of
+                     (CAlgReal x, CAlgReal y) -> isExactRational x && isExactRational y
+                     _                        -> True
+
+-- | Quot/Rem operations require a nonzero check on the divisor.
+nonzeroCheck :: CV -> CV -> Bool
+nonzeroCheck _ b = cvVal b /= CInteger 0
+
+-- | Same as rationalCheck, except for SBV's
+rationalSBVCheck :: SVal -> SVal -> Bool
+rationalSBVCheck (SVal KReal (Left a)) (SVal KReal (Left b)) = rationalCheck a b
+rationalSBVCheck _                     _                     = True
+
+-- | Predicate to check if a concrete 'Float' or 'Double' value uses the
+-- 'RoundNearestTiesToEven' rounding mode. This is necessary because we assume
+-- this rounding mode when concretely evaluating 'Float's and 'Double's, so
+-- concrete evaluation is not supported for other rounding modes.
+--
+-- Note that this check skips concrete t'FP' values, which support concrete
+-- evaluation with any rounding mode.
+floatDoubleRneCheck :: RoundingMode -> CV -> Bool
+floatDoubleRneCheck rm cv =
+  case cvKind cv of
+    KFloat -> rmIsRne
+    KDouble -> rmIsRne
+    _ -> True
+  where
+    rmIsRne | RoundNearestTiesToEven <- rm = True
+            | True                         = False
+
+noInt :: String -> Integer -> Integer -> a
+noInt o a b = error $ "SBV.Integer." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noReal :: String -> AlgReal -> AlgReal -> a
+noReal o a b = error $ "SBV.AlgReal." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noFloat :: String -> Float -> Float -> a
+noFloat o a b = error $ "SBV.Float." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noDouble :: String -> Double -> Double -> a
+noDouble o a b = error $ "SBV.Double." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noFP :: String -> FP -> FP -> a
+noFP o a b = error $ "SBV.FPR." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noRat:: String -> Rational -> Rational -> a
+noRat o a b = error $ "SBV.Rational." ++ o ++ ": Unexpected arguments: " ++ show (a, b)
+
+noIntUnary :: String -> Integer -> a
+noIntUnary o a = error $ "SBV.Integer." ++ o ++ ": Unexpected argument: " ++ show a
+
+noRealUnary :: String -> AlgReal -> a
+noRealUnary o a = error $ "SBV.AlgReal." ++ o ++ ": Unexpected argument: " ++ show a
+
+noFloatUnary :: String -> Float -> a
+noFloatUnary o a = error $ "SBV.Float." ++ o ++ ": Unexpected argument: " ++ show a
+
+noDoubleUnary :: String -> Double -> a
+noDoubleUnary o a = error $ "SBV.Double." ++ o ++ ": Unexpected argument: " ++ show a
+
+noFPUnary :: String -> FP -> a
+noFPUnary o a = error $ "SBV.FPR." ++ o ++ ": Unexpected argument: " ++ show a
+
+noRatUnary :: String -> Rational -> a
+noRatUnary o a = error $ "SBV.Rational." ++ o ++ ": Unexpected argument: " ++ show a
+
+-- | Given a composite structure, figure out how to compare for less than
+svStructuralLessThan :: SVal -> SVal -> SVal
+svStructuralLessThan x y
+   | isConcrete x && isConcrete y
+   = x `svLessThan` y
+   | KTuple{} <- kx
+   = tupleLT x y
+   | True
+   = x `svLessThan` y
+   where kx = kindOf x
+
+-- | Structural less-than for tuples
+tupleLT :: SVal -> SVal -> SVal
+tupleLT x y = SVal KBool $ Right $ cache res
+  where ks = case kindOf x of
+               KTuple xs -> xs
+               k         -> error $ "Data.SBV: Impossible happened, tupleLT called with: " ++ show (k, x, y)
+
+        n = length ks
+
+        res st = do sx <- svToSV st x
+                    sy <- svToSV st y
+
+                    let chkElt i ek = let xi = SVal ek $ Right $ cache $ \_ -> newExpr st ek $ SBVApp (TupleAccess i n) [sx]
+                                          yi = SVal ek $ Right $ cache $ \_ -> newExpr st ek $ SBVApp (TupleAccess i n) [sy]
+                                          lt = xi `svStructuralLessThan` yi
+                                          eq = xi `svEqual`              yi
+                                       in (lt, eq)
+
+                        walk []                  = svFalse
+                        walk [(lti, _)]          = lti
+                        walk ((lti, eqi) : rest) = lti `svOr` (eqi `svAnd` walk rest)
+
+                    svToSV st $ walk $ zipWith chkElt [1..] ks
+
+-- | Convert an 'Data.SBV.SWord32' to an 'Data.SBV.SFloat', preserving the
+-- bit-correspondence. Note that since the representation for @NaN@s are not
+-- unique, there are multiple word values for which this function will return a
+-- single, distinguished @NaN@ value.
+svSWord32AsFloat :: SVal -> SVal
+svSWord32AsFloat w@(SVal kindFrom x)
+  | KBounded _ 32 <- kindFrom
+  = case x of
+      Left (CV _ (CInteger w'))
+        -> SVal kindTo $ Left $ CV kindTo $ CFloat $ wordToFloat $ fromInteger w'
+      _ -> SVal kindTo $ Right $ cache y
+  | True
+  = error $ "svSWord32AsFloat: not a 32-bit word type: " ++ show kindFrom
+  where kindTo = KFloat
+        y st = do svw <- svToSV st w
+                  mkSymOp1 (IEEEFP (FP_Reinterpret kindFrom kindTo)) st kindTo svw
+
+-- | Convert an 'Data.SBV.SWord64' to an 'Data.SBV.SDouble', preserving the
+-- bit-correspondence. Note that since the representation for @NaN@s are not
+-- unique, there are multiple word values for which this function will return a
+-- single, distinguished @NaN@ value.
+svSWord64AsDouble :: SVal -> SVal
+svSWord64AsDouble w@(SVal kindFrom x)
+  | KBounded _ 64 <- kindFrom
+  = case x of
+      Left (CV _ (CInteger w'))
+        -> SVal kindTo $ Left $ CV kindTo $ CDouble $ wordToDouble $ fromInteger w'
+      _ -> SVal kindTo $ Right $ cache y
+  | True
+  = error $ "svSWord64AsDouble: not a 64-bit word type: " ++ show kindFrom
+  where kindTo = KDouble
+        y st = do svw <- svToSV st w
+                  mkSymOp1 (IEEEFP (FP_Reinterpret kindFrom kindTo)) st kindTo svw
+
+-- | Convert a word to a float (using the given exponent and significand sizes)
+-- containing the word's corresponding bit pattern. Note that since the
+-- representation for @NaN@s are not unique, there are multiple word values for
+-- which this function will return a single, distinguished @NaN@ value.
+svSWordAsFloatingPoint :: Int -- ^ Exponent size
+                       -> Int -- ^ Significand size
+                       -> SVal -> SVal
+svSWordAsFloatingPoint eb sb w@(SVal kindFrom x)
+  | KBounded _ _ <- kindFrom
+  = case x of
+      Left (CV _ (CInteger w'))
+        -> SVal kindTo $ Left $ CV kindTo $ CFP $ fpFromBits eb sb $ fromInteger w'
+      _ -> SVal kindTo $ Right $ cache y
+  | True
+  = error $ "svSWordAsFloatingPoint: non-word type: " ++ show kindFrom
+  where kindTo = KFP eb sb
+        y st = do svw <- svToSV st w
+                  mkSymOp1 (IEEEFP (FP_Reinterpret kindFrom kindTo)) st kindTo svw
+
+-- | Convert an 'Data.SBV.SFloat' to an 'Data.SBV.SWord32', preserving the bit-correspondence. Note that since the
+-- representation for @NaN@s are not unique, this function will return a symbolic value when given a
+-- concrete @NaN@.
+--
+-- Implementation note: Since there's no corresponding function in SMTLib for conversion to
+-- bit-representation due to partiality, we use a translation trick by allocating a new word variable,
+-- converting it to float, and requiring it to be equivalent to the input. In code-generation mode, we simply map
+-- it to a simple conversion.
+svFloatAsSWord32 :: SVal -> SVal
+svFloatAsSWord32 (SVal KFloat (Left (CV KFloat (CFloat f))))
+   | not (isNaN f)
+   = let w32 = KBounded False 32
+     in SVal w32 $ Left $ CV w32 $ CInteger (fromIntegral (floatToWord f))
+svFloatAsSWord32 fVal@(SVal KFloat _)
+  = SVal w32 (Right (cache y))
+  where w32  = KBounded False 32
+        y st = do cg <- isCodeGenMode st
+                  if cg
+                     then do f <- svToSV st fVal
+                             newExpr st w32 (SBVApp (IEEEFP (FP_Reinterpret KFloat w32)) [f])
+                     else do n   <- newInternalVariable st w32
+                             ysw <- newExpr st KFloat (SBVApp (IEEEFP (FP_Reinterpret w32 KFloat)) [n])
+                             internalConstraint st False [] $ fVal `svStrongEqual` SVal KFloat (Right (cache (\_ -> pure ysw)))
+                             pure n
+svFloatAsSWord32 (SVal k _) = error $ "svFloatAsSWord32: non-float type: " ++ show k
+
+-- | Convert an 'Data.SBV.SDouble' to an 'Data.SBV.SWord64', preserving the bit-correspondence. Note that since the
+-- representation for @NaN@s are not unique, this function will return a symbolic value when given a
+-- concrete @NaN@.
+--
+-- Implementation note: Since there's no corresponding function in SMTLib for conversion to
+-- bit-representation due to partiality, we use a translation trick by allocating a new word variable,
+-- converting it to float, and requiring it to be equivalent to the input. In code-generation mode, we simply map
+-- it to a simple conversion.
+svDoubleAsSWord64 :: SVal -> SVal
+svDoubleAsSWord64 (SVal KDouble (Left (CV KDouble (CDouble f))))
+   | not (isNaN f)
+   = let w64 = KBounded False 64
+     in SVal w64 $ Left $ CV w64 $ CInteger (fromIntegral (doubleToWord f))
+svDoubleAsSWord64 fVal@(SVal KDouble _)
+  = SVal w64 (Right (cache y))
+  where w64  = KBounded False 64
+        y st = do cg <- isCodeGenMode st
+                  if cg
+                     then do f <- svToSV st fVal
+                             newExpr st w64 (SBVApp (IEEEFP (FP_Reinterpret KDouble w64)) [f])
+                     else do n   <- newInternalVariable st w64
+                             ysw <- newExpr st KDouble (SBVApp (IEEEFP (FP_Reinterpret w64 KDouble)) [n])
+                             internalConstraint st False [] $ fVal `svStrongEqual` SVal KDouble (Right (cache (\_ -> pure ysw)))
+                             pure n
+svDoubleAsSWord64 (SVal k _) = error $ "svDoubleAsSWord64: non-float type: " ++ show k
+
+-- | Convert a float to the word containing the corresponding bit pattern
+svFloatingPointAsSWord :: SVal -> SVal
+svFloatingPointAsSWord (SVal (KFP eb sb) (Left (CV _ (CFP f@(FP _ _ fpV)))))
+  | not (isNaN f)
+  = let wN = KBounded False (eb + sb)
+    in SVal wN $ Left $ CV wN $ CInteger $ bfToBits (mkBFOpts eb sb NearEven) fpV
+svFloatingPointAsSWord fVal@(SVal kFrom@(KFP eb sb) _)
+  = SVal kTo (Right (cache y))
+  where kTo   = KBounded False (eb + sb)
+        y st = do cg <- isCodeGenMode st
+                  if cg
+                     then do f <- svToSV st fVal
+                             newExpr st kTo (SBVApp (IEEEFP (FP_Reinterpret kFrom kTo)) [f])
+                     else do n   <- newInternalVariable st kTo
+                             ysw <- newExpr st kFrom (SBVApp (IEEEFP (FP_Reinterpret kTo kFrom)) [n])
+                             internalConstraint st False [] $ fVal `svStrongEqual` SVal kFrom (Right (cache (\_ -> pure ysw)))
+                             pure n
+svFloatingPointAsSWord (SVal k _) = error $ "svFloatingPointAsSWord: non-float type: " ++ show k
+
+{- HLint ignore svIte     "Eta reduce"         -}
+{- HLint ignore svLazyIte "Eta reduce"         -}
+{- HLint ignore module    "Reduce duplication" -}
diff --git a/Data/SBV/Core/Sized.hs b/Data/SBV/Core/Sized.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Sized.hs
@@ -0,0 +1,235 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Sized
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Type-level sized bit-vectors. Thanks to Ben Blaxill for providing an
+-- initial implementation of this idea.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Core.Sized (
+        -- * Type-sized unsigned bit-vectors
+          WordN
+        -- * Type-sized signed bit-vectors
+        , IntN
+       ) where
+
+import Data.Bits
+import Data.Maybe (fromJust)
+import Data.Proxy (Proxy(..))
+
+import GHC.TypeLits
+import GHC.Real
+
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.Concrete
+import Data.SBV.Core.Operations
+
+import Test.QuickCheck(Arbitrary(..))
+
+-- | An unsigned bit-vector carrying its size info
+newtype WordN (n :: Nat) = WordN Integer deriving (Eq, Ord)
+
+-- | Show instance for t'WordN'
+instance Show (WordN n) where
+  show (WordN v) = show v
+
+-- | t'WordN' has a kind
+instance (KnownNat n, BVIsNonZero n) => HasKind (WordN n) where
+  kindOf _ = KBounded False (intOfProxy (Proxy @n))
+
+-- | A signed bit-vector carrying its size info
+newtype IntN (n :: Nat) = IntN Integer deriving (Eq, Ord)
+
+-- | Show instance for t'IntN'
+instance Show (IntN n) where
+  show (IntN v) = show v
+
+-- | t'IntN' has a kind
+instance (KnownNat n, BVIsNonZero n) => HasKind (IntN n) where
+  kindOf _ = KBounded True (intOfProxy (Proxy @n))
+
+-- Lift a unary operation via SVal
+lift1 :: (KnownNat n, BVIsNonZero n, HasKind (bv n), Integral (bv n), Show (bv n)) => String -> (SVal -> SVal) -> bv n -> bv n
+lift1 nm op x = uc $ op (c x)
+  where k = kindOf x
+        c = SVal k . Left . normCV . CV k . CInteger . toInteger
+        uc (SVal _ (Left (CV _ (CInteger v)))) = fromInteger v
+        uc r                                   = error $ "Impossible happened while lifting " ++ show nm ++ " over " ++ show (k, x, r)
+
+-- Lift a binary operation via SVal
+lift2 :: (KnownNat n, BVIsNonZero n, HasKind (bv n), Integral (bv n), Show (bv n)) => String -> (SVal -> SVal -> SVal) -> bv n -> bv n -> bv n
+lift2 nm op x y = uc $ c x `op` c y
+  where k = kindOf x
+        c = SVal k . Left . normCV . CV k . CInteger . toInteger
+        uc (SVal _ (Left (CV _ (CInteger v)))) = fromInteger v
+        uc r                                   = error $ "Impossible happened while lifting " ++ show nm ++ " over " ++ show (k, x, y, r)
+
+-- Lift a binary operation via SVal where second argument is an Int
+lift2I :: (KnownNat n, BVIsNonZero n, HasKind (bv n), Integral (bv n), Show (bv n)) => String -> (SVal -> Int -> SVal) -> bv n -> Int -> bv n
+lift2I nm op x i = uc $ c x `op` i
+  where k = kindOf x
+        c = SVal k . Left . normCV . CV k . CInteger . toInteger
+        uc (SVal _ (Left (CV _ (CInteger v)))) = fromInteger v
+        uc r                                   = error $ "Impossible happened while lifting " ++ show nm ++ " over " ++ show (k, x, i, r)
+
+-- Lift a binary operation via SVal where second argument is an Int and returning a Bool
+lift2IB :: (KnownNat n, BVIsNonZero n, HasKind (bv n), Integral (bv n), Show (bv n)) => String -> (SVal -> Int -> SVal) -> bv n -> Int -> Bool
+lift2IB nm op x i = uc $ c x `op` i
+  where k = kindOf x
+        c = SVal k . Left . normCV . CV k . CInteger . toInteger
+        uc (SVal _ (Left v)) = cvToBool v
+        uc r                 = error $ "Impossible happened while lifting " ++ show nm ++ " over " ++ show (k, x, i, r)
+
+-- | 'Bounded' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Bounded (WordN n) where
+   minBound = WordN 0
+   maxBound = let sz = intOfProxy (Proxy @n) in WordN $ 2 ^ sz - 1
+
+-- | 'Bounded' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Bounded (IntN n) where
+   minBound = let sz1 = intOfProxy (Proxy @n) - 1 in IntN $ - (2 ^ sz1)
+   maxBound = let sz1 = intOfProxy (Proxy @n) - 1 in IntN $ 2 ^ sz1 - 1
+
+-- | 'Num' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Num (WordN n) where
+   (+)         = lift2 "(+)"    svPlus
+   (-)         = lift2 "(*)"    svMinus
+   (*)         = lift2 "(*)"    svTimes
+   negate      = lift1 "signum" svUNeg
+   abs         = lift1 "abs"    svAbs
+   signum      = WordN . signum   . toInteger
+   fromInteger = WordN . fromJust . svAsInteger . svInteger (kindOf (undefined :: WordN n))
+
+-- | 'Num' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Num (IntN n) where
+   (+)         = lift2 "(+)"    svPlus
+   (-)         = lift2 "(*)"    svMinus
+   (*)         = lift2 "(*)"    svTimes
+   negate      = lift1 "signum" svUNeg
+   abs         = lift1 "abs"    svAbs
+   signum      = IntN . signum   . toInteger
+   fromInteger = IntN . fromJust . svAsInteger . svInteger (kindOf (undefined :: IntN n))
+
+-- | 'Enum' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Enum (WordN n) where
+   succ x | x == maxBound = error $ "Enum.succ{" ++ show (kindOf x) ++ "}: tried to take `succ' of last tag in enumeration"
+          | True          = x + 1
+
+   pred x | x == minBound = error $ "Enum.pred{" ++ show (kindOf x) ++ "}: tried to take `pred' of first tag in enumeration"
+          | True          = x - 1
+
+   toEnum i | toInteger i < toInteger (minBound :: WordN n) = bad $ show i ++ " < minBound of " ++ show (minBound :: WordN n)
+            | toInteger i > toInteger (maxBound :: WordN n) = bad $ show i ++ " > maxBound of " ++ show (maxBound :: WordN n)
+            | True                                          = fromInteger (toInteger i)
+     where bad why = error $ "Enum." ++ showType (Proxy @(WordN n)) ++ ".toEnum: bad argument: (" ++ why ++ ")"
+
+   fromEnum = fromIntegral . toInteger
+
+   enumFrom       = integralEnumFrom
+   enumFromTo     = integralEnumFromTo
+   enumFromThen   = integralEnumFromThen
+   enumFromThenTo = integralEnumFromThenTo
+
+-- | 'Enum' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Enum (IntN n) where
+   succ x | x == maxBound = error $ "Enum.succ{" ++ show (kindOf x) ++ "}: tried to take `succ' of last tag in enumeration"
+          | True          = x + 1
+
+   pred x | x == minBound = error $ "Enum.pred{" ++ show (kindOf x) ++ "}: tried to take `pred' of first tag in enumeration"
+          | True          = x - 1
+
+   toEnum i | toInteger i < toInteger (minBound :: IntN n) = bad $ show i ++ " < minBound of " ++ show (minBound :: IntN n)
+            | toInteger i > toInteger (maxBound :: IntN n) = bad $ show i ++ " > maxBound of " ++ show (maxBound :: IntN n)
+            | True                                         = fromInteger (toInteger i)
+     where bad why = error $ "Enum." ++ showType (Proxy @(IntN n)) ++ ".toEnum: bad argument: (" ++ why ++ ")"
+
+   fromEnum = fromIntegral . toInteger
+
+   enumFrom       = integralEnumFrom
+   enumFromTo     = integralEnumFromTo
+   enumFromThen   = integralEnumFromThen
+   enumFromThenTo = integralEnumFromThenTo
+
+-- | 'Real' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Real (WordN n) where
+   toRational (WordN x) = toRational x
+
+-- | 'Real' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Real (IntN n) where
+   toRational (IntN x) = toRational x
+
+-- | 'Integral' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Integral (WordN n) where
+   toInteger (WordN x)           = x
+   quotRem   (WordN x) (WordN y) = let (q, r) = quotRem x y in (WordN q, WordN r)
+
+-- | 'Integral' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Integral (IntN n) where
+   toInteger (IntN x)          = x
+   quotRem   (IntN x) (IntN y) = let (q, r) = quotRem x y in (IntN q, IntN r)
+
+--  'Bits' instance for t'WordN'
+instance (KnownNat n, BVIsNonZero n) => Bits (WordN n) where
+   (.&.)        = lift2   "(.&.)"      svAnd
+   (.|.)        = lift2   "(.|.)"      svOr
+   xor          = lift2   "xor"        svXOr
+   complement   = lift1   "complement" svNot
+   shiftL       = lift2I  "shiftL"     svShl
+   shiftR       = lift2I  "shiftR"     svShr
+   rotateL      = lift2I  "rotateL"    svRol
+   rotateR      = lift2I  "rotateR"    svRor
+   testBit      = lift2IB "svTestBit"  svTestBit
+   bitSizeMaybe = Just . const (intOfProxy (Proxy @n))
+   bitSize _    = intOfProxy (Proxy @n)
+   isSigned     = hasSign . kindOf
+   bit i        = 1 `shiftL` i
+   popCount     = fromIntegral . popCount . toInteger
+
+--  'Bits' instance for t'IntN'
+instance (KnownNat n, BVIsNonZero n) => Bits (IntN n) where
+   (.&.)        = lift2   "(.&.)"      svAnd
+   (.|.)        = lift2   "(.|.)"      svOr
+   xor          = lift2   "xor"        svXOr
+   complement   = lift1   "complement" svNot
+   shiftL       = lift2I  "shiftL"     svShl
+   shiftR       = lift2I  "shiftR"     svShr
+   rotateL      = lift2I  "rotateL"    svRol
+   rotateR      = lift2I  "rotateR"    svRor
+   testBit      = lift2IB "svTestBit"  svTestBit
+   bitSizeMaybe = Just . const (intOfProxy (Proxy @n))
+   bitSize _    = intOfProxy (Proxy @n)
+   isSigned     = hasSign . kindOf
+   bit i        = 1 `shiftL` i
+   popCount     = fromIntegral . popCount . toInteger
+
+-- | Quickcheck instance for WordN
+instance KnownNat n => Arbitrary (WordN n) where
+  arbitrary = WordN . norm . abs <$> arbitrary
+    where sz = intOfProxy (Proxy @n)
+
+          norm v | sz == 0 = 0
+                 | True    = v .&. (((1 :: Integer) `shiftL` sz) - 1)
+
+-- | Quickcheck instance for IntN
+instance KnownNat n => Arbitrary (IntN n) where
+  arbitrary = IntN . norm <$> arbitrary
+    where sz = intOfProxy (Proxy @n)
+
+          norm v | sz == 0 = 0
+                 | True  = let rg = 2 ^ (sz - 1)
+                           in case divMod v rg of
+                                     (a, b) | even a -> b
+                                     (_, b)          -> b - rg
diff --git a/Data/SBV/Core/SizedFloats.hs b/Data/SBV/Core/SizedFloats.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/SizedFloats.hs
@@ -0,0 +1,621 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Sized
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Type-level sized floats.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE DeriveDataTypeable   #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.SizedFloats (
+        -- * Type-sized floats
+          FloatingPoint(..), FP(..), FPHalf, FPBFloat, FPSingle, FPDouble, FPQuad
+
+        -- * Constructing values
+        , fpFromRawRep, fpFromBigFloat, fpFromBits, fpNaN, fpInf, fpZero
+
+        -- * Operations
+        , fpFromInteger, fpFromRational, fpFromFloat, fpFromDouble
+        , fpToFloat, fpToDouble
+        , fpEncodeFloat
+        , fpIsFinite, fpIsInf, fpIsZero, fpIsNaN
+        , fpIsNormal, fpIsSubnormal, fpIsNeg, fpIsPos
+        , fpNeg, fpAbs, fpSignum
+        , fpAdd, fpSub, fpMul, fpDiv, fpPow, fpRem, fpSqrt, fpFMA
+        , fpRoundFloat, fpRoundInt
+        , fpMax, fpMin
+
+        -- * Internal operations
+       , arbFPIsEqualObjectH, arbFPCompareObjectH, fprToSMTLib2, mkBFOpts, bfToString, bfRemoveRedundantExp
+       , roundingModeToRoundMode
+       ) where
+
+import Data.Char (intToDigit)
+import Data.List (isSuffixOf)
+import Data.Proxy
+import GHC.TypeLits
+import GHC.Real
+
+import Data.Bits
+import Numeric
+
+import Data.SBV.Core.Kind
+import Data.SBV.Utils.Numeric (RoundingMode(..), floatToWord, fp2fp)
+
+import LibBF (BigFloat, BFOpts, RoundMode, Status, BFRep(..), BFNum(..), bfToRep, Sign(Neg))
+import qualified LibBF as BF
+
+import qualified Data.Generics as G
+
+import Control.DeepSeq(NFData(..))
+
+import Test.QuickCheck (Arbitrary(..))
+
+-- | A floating point value, indexed by its exponent and significand sizes.
+--
+--   An IEEE SP is @FloatingPoint  8 24@
+--           DP is @FloatingPoint 11 53@
+-- etc.
+-- NB. Don't derive Ord for this type automatically, see notes below.
+newtype FloatingPoint (eb :: Nat) (sb :: Nat) = FloatingPoint FP deriving Eq
+
+-- NB. Refrain from letting GHC derive @>@ and @>=@ and define
+-- it ourselves. Why? Because the default definition of @x > y@
+-- is @not (x <= y)@. But when one of the arguments is NaN, this does
+-- the wrong thing, since NaN doesn't compare to other values. (i.e., the
+-- comparison should be always False, but the default will give
+-- you the wrong result.)
+instance Ord (FloatingPoint eb sb) where
+  FloatingPoint f0 <  FloatingPoint f1 = f0 <  f1
+  FloatingPoint f0 <= FloatingPoint f1 = f0 <= f1
+  f0               >  f1               = f1 <  f0       -- See the note above
+  f0               >= f1               = f1 <= f0       -- See the note above
+
+-- | 'Enum' instance for t'FloatingPoint'. Note that Haskell requires
+-- float termination conditions to go over @delta/2@. Also, repeated addition
+-- is wrong; instead we need to use multiplication to avoid accuracy issues per the report.
+instance ValidFloat eb sb => Enum (FloatingPoint eb sb) where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum                      = fromIntegral
+   fromEnum (FloatingPoint fp) = fromInteger (truncate fp)
+
+   enumFrom       = numericEnumFrom
+   enumFromTo     = numericEnumFromTo
+   enumFromThen   = numericEnumFromThen
+   enumFromThenTo = numericEnumFromThenTo
+
+-- | Abbreviation for IEEE half precision float, bit width 16 = 5 + 11.
+type FPHalf = FloatingPoint 5 11
+
+-- | Abbreviation for brain-float precision float, bit width 16 = 8 + 8.
+type FPBFloat = FloatingPoint 8 8
+
+-- | Abbreviation for IEEE single precision float, bit width 32 = 8 + 24.
+type FPSingle = FloatingPoint 8 24
+
+-- | Abbreviation for IEEE double precision float, bit width 64 = 11 + 53.
+type FPDouble = FloatingPoint 11 53
+
+-- | Abbreviation for IEEE quadruple precision float, bit width 128 = 15 + 113.
+type FPQuad = FloatingPoint 15 113
+
+-- | Show instance for Floats. By default we print in base 10, with standard scientific notation.
+instance Show (FloatingPoint eb sb) where
+  show (FloatingPoint r) = show r
+
+-- | Internal representation of a parameterized float.
+--
+-- A note on cardinality: If we have eb exponent bits, and sb significand bits,
+-- then the total number of floats is 2^sb*(2^eb-1) + 3: All exponents except 11..11
+-- is allowed. So we get, 2^eb-1, different combinations, each with a sign, giving
+-- us 2^sb*(2^eb-1) totals. Then we have two infinities, and one NaN, adding 3 more.
+data FP = FP { fpExponentSize    :: !Int
+             , fpSignificandSize :: !Int
+             , fpValue           :: BigFloat
+             }
+             deriving (Eq, G.Data)
+
+-- Not full, but good enough
+instance NFData FP where
+  rnf (FP e s _) = e `seq` s `seq` ()
+
+instance ValidFloat eb sb => Arbitrary (FloatingPoint eb sb) where
+  arbitrary = FloatingPoint . FP (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))  <$> arbitrary
+
+-- | This arbitrary instance is questionable, but seems to work ok. We get an arbitrary double,
+-- and just use that. Probably not good enough for real random work, but good enough here.
+instance Arbitrary BigFloat where
+  arbitrary = BF.bfFromDouble <$> arbitrary
+
+-- Manually implemented instance as GHC generated a non-IEEE 754 compliant instance.
+-- Note that we cannot pack the values in a tuple and then compare them as that will
+-- also give non-IEEE 754 compliant results.
+--
+-- NB. Refrain from letting GHC derive @>@ and @>=@ and define
+-- it ourselves. Why? Because the default definition of @x > y@
+-- is @not (x <= y)@. But when one of the arguments is NaN, this does
+-- the wrong thing, since NaN doesn't compare to other values. (i.e., the
+-- comparison should be always False, but the default will give
+-- you the wrong result.)
+instance Ord FP where
+  FP eb0 sb0 v0 <  FP eb1 sb1 v1 | (eb0, sb0) /= (eb1, sb1) = error $ "FP.<: comparing FPs with different precision: "  <> show (eb0, sb0) <> show (eb1, sb1)
+                                 | True                     = v0 <  v1
+  FP eb0 sb0 v0 <= FP eb1 sb1 v1 | (eb0, sb0) /= (eb1, sb1) = error $ "FP.<=: comparing FPs with different precision: " <> show (eb0, sb0) <> show (eb1, sb1)
+                                 | True                     = v0 <= v1
+  f0 >  f1 = f1 <  f0  -- See note above
+  f0 >= f1 = f1 <= f0  -- See note above
+
+instance Show FP where
+  show = bfRemoveRedundantExp . bfToString 10 False False
+
+-- | Remove redundant p+0 etc.
+bfRemoveRedundantExp :: String -> String
+bfRemoveRedundantExp v = walk useless
+  where walk []              = v
+        walk (s:ss)
+         | s `isSuffixOf` v = reverse . drop (length s) . reverse $ v
+         | True             = walk ss
+
+        -- these suffixes are useless, drop them
+        useless = [c : s ++ "0" | c <- "pe@", s <- ["+", "-", ""]]
+
+-- | Show a big float in the base given.
+-- NB. Do not be tempted to use BF.showFreeMin below; it produces arguably correct
+-- but very confusing results. See <https://github.com/GaloisInc/cryptol/issues/1089>
+-- for a discussion of the issues.
+bfToString :: Int -> Bool -> Bool -> FP -> String
+bfToString b withPrefix forceExponent (FP _ sb a)
+  | BF.bfIsNaN  a = "NaN"
+  | BF.bfIsInf  a = if BF.bfIsPos a then "Infinity" else "-Infinity"
+  | BF.bfIsZero a = if BF.bfIsPos a then "0.0"      else "-0.0"
+  | True
+  = trimZeros $ BF.bfToString b opts' a
+  where opts  = BF.showRnd BF.NearEven <> BF.showFree (Just (fromIntegral prec))
+
+        -- For base 10, use a larger precision. It's really difficult to "pick"
+        -- the correct value here; but 2*sb seems to work ok. Note that even picking
+        -- sb is fine: The output isn't incorrect. It's just confusing.
+        prec | b == 10 = 2*sb
+             | True    = sb
+
+        opts'
+          | withPrefix && forceExponent = BF.addPrefix <> BF.forceExp  <> opts
+          | withPrefix                  = BF.addPrefix                 <> opts
+          | forceExponent               =                 BF.forceExp  <> opts
+          | True                        =                                 opts
+
+        -- In base 10, exponent starts with 'e'. Otherwise (2, 8, 16) it starts with 'p'
+        expChar = if b == 10 then 'e' else 'p'
+
+        trimZeros s
+          | '.' `elem` s = case span (/= expChar) s of
+                            (pre, post) -> let pre' = reverse $ case dropWhile (== '0') $ reverse pre of
+                                                                  res@('.':_) -> '0' : res
+                                                                  res         -> res
+                                           in pre' ++ post
+          | True         = s
+
+-- | Default options for BF options.
+mkBFOpts :: Integral a => a -> a -> RoundMode -> BFOpts
+mkBFOpts eb sb rm = BF.allowSubnormal <> BF.rnd rm <> BF.expBits (fromIntegral eb) <> BF.precBits (fromIntegral sb)
+
+-- | Construct a float, by appropriately rounding
+fpFromBigFloat :: Int -> Int -> BigFloat -> FP
+fpFromBigFloat eb sb r = FP eb sb $ fst $ BF.bfRoundFloat (mkBFOpts eb sb BF.NearEven) r
+
+-- | Convert an integer to a big-float, preserving the bit-correspondence.
+fpFromBits :: Int -> Int -> Integer -> FP
+fpFromBits eb sb val = FP eb sb $ BF.bfFromBits (mkBFOpts eb sb BF.NearEven) val
+
+-- | Convert from an sign/exponent/mantissa representation to a float. The values are the integers
+-- representing the bit-patterns of these values, i.e., the raw representation. We assume that these
+-- integers fit into the ranges given, i.e., no overflow checking is done here.
+fpFromRawRep :: Bool -> (Integer, Int) -> (Integer, Int) -> FP
+fpFromRawRep sign (e, eb) (s, sb) = fpFromBits eb sb val
+  where es, val :: Integer
+        es = (e `shiftL` (sb - 1)) .|. s
+        val | sign = (1 `shiftL` (eb + sb - 1)) .|. es
+            | True =                                es
+
+-- | Make NaN. Exponent is all 1s. Significand is non-zero. The sign is irrelevant.
+fpNaN :: Int -> Int -> FP
+fpNaN eb sb = fpFromBigFloat eb sb BF.bfNaN
+
+-- | Make Infinity. Exponent is all 1s. Significand is 0.
+fpInf :: Bool -> Int -> Int -> FP
+fpInf sign eb sb = fpFromBigFloat eb sb $ if sign then BF.bfNegInf else BF.bfPosInf
+
+-- | Make a signed zero.
+fpZero :: Bool -> Int -> Int -> FP
+fpZero sign eb sb = fpFromBigFloat eb sb $ if sign then BF.bfNegZero else BF.bfPosZero
+
+-- | Make from an integer value.
+fpFromInteger :: Int -> Int -> Integer -> FP
+fpFromInteger eb sb iv = fpFromBigFloat eb sb $ BF.bfFromInteger iv
+
+-- | Make a generalized floating-point value from a 'Rational'.
+fpFromRational :: Int -> Int -> Rational -> FP
+fpFromRational eb sb r = FP eb sb $ fst $ BF.bfDiv (mkBFOpts eb sb BF.NearEven) (BF.bfFromInteger (numerator r))
+                                                                                (BF.bfFromInteger (denominator r))
+
+-- | Represent the FP in SMTLib2 format
+fprToSMTLib2 :: FP -> String
+fprToSMTLib2 (FP eb sb r)
+  | BF.bfIsNaN  r = as "NaN"
+  | BF.bfIsInf  r = as $ if BF.bfIsPos r then "+oo"   else "-oo"
+  | BF.bfIsZero r = as $ if BF.bfIsPos r then "+zero" else "-zero"
+  | True          = generic
+ where e = show eb
+       s = show sb
+
+       bits            = BF.bfToBits (mkBFOpts eb sb BF.NearEven) r
+       significandMask = (1 :: Integer) `shiftL` (sb - 1) - 1
+       exponentMask    = (1 :: Integer) `shiftL` eb       - 1
+
+       fpSign          = bits `testBit` (eb + sb - 1)
+       fpExponent      = (bits `shiftR` (sb - 1)) .&. exponentMask
+       fpSignificand   = bits                     .&. significandMask
+
+       generic = "(fp " ++ unwords [if fpSign then "#b1" else "#b0", mkB eb fpExponent, mkB (sb - 1) fpSignificand] ++ ")"
+
+       as x = "(_ " ++ x ++ " " ++ e ++ " " ++ s ++ ")"
+
+       mkB sz val = "#b" ++ pad sz (showIntAtBase 2 intToDigit val "")
+       pad l str = replicate (l - length str) '0' ++ str
+
+-- | Check that two arbitrary floats are the exact same values, i.e., +0/-0 does not
+-- compare equal, and NaN's compare equal to themselves
+arbFPIsEqualObjectH :: FP -> FP -> Bool
+arbFPIsEqualObjectH (FP eb sb a) (FP eb' sb' b) = case (eb, sb) `compare` (eb', sb') of
+                                                    LT                                 -> False
+                                                    GT                                 -> False
+                                                    EQ | BF.bfIsNaN a                  -> BF.bfIsNaN b
+                                                       | BF.bfIsZero a && BF.bfIsNeg a -> BF.bfIsZero b && BF.bfIsNeg b
+                                                       | BF.bfIsZero a && BF.bfIsPos a -> BF.bfIsZero b && BF.bfIsPos b
+                                                       | True                          -> a == b
+
+-- | Ordering for arbitrary floats, avoiding the +0/-0/NaN issues. Note that this is
+-- essentially used for indexing into a map, so we need to be total.
+--
+-- This function uses the bfCompare function provided by the libBF. As per the libBF's documentation,
+-- it has the semantics: -0 < 0, NaN == NaN, and NaN is larger than all other numbers.
+arbFPCompareObjectH :: FP -> FP -> Ordering
+arbFPCompareObjectH (FP eb sb a) (FP eb' sb' b) = case (eb, sb) `compare` (eb', sb') of
+                                                    LT -> LT
+                                                    GT -> GT
+                                                    EQ -> BF.bfCompare a b
+-- | Compute the signum of a big float
+bfSignum :: BigFloat -> BigFloat
+bfSignum r | BF.bfIsNaN  r = r
+           | BF.bfIsZero r = r
+           | BF.bfIsPos  r = BF.bfFromInteger 1
+           | True          = BF.bfFromInteger (-1)
+
+-- | Num instance for big-floats
+instance Num FP where
+  (+)           = fpAdd RoundNearestTiesToEven
+  (-)           = fpSub RoundNearestTiesToEven
+  (*)           = fpMul RoundNearestTiesToEven
+  abs           = fpAbs
+  signum        = fpSignum
+  fromInteger i = error $ "FP.fromInteger: Not supported for arbitrary floats. Use fpFromInteger instead, specifying the precision. Called on: " ++ show i
+  negate        = fpNeg
+
+-- | Fractional instance for big-floats
+instance Fractional FP where
+  fromRational = error "FP.fromRational: Not supported for arbitrary floats. Use fpFromRational instead, specifying the precision"
+  (/)          = fpDiv RoundNearestTiesToEven
+
+-- | Floating instance for big-floats
+instance Floating FP where
+  sqrt = fpSqrt RoundNearestTiesToEven
+  (**) = fpPow RoundNearestTiesToEven
+
+  pi    = unsupported "Floating.FP.pi"
+  exp   = unsupported "Floating.FP.exp"
+  log   = unsupported "Floating.FP.log"
+  sin   = unsupported "Floating.FP.sin"
+  cos   = unsupported "Floating.FP.cos"
+  tan   = unsupported "Floating.FP.tan"
+  asin  = unsupported "Floating.FP.asin"
+  acos  = unsupported "Floating.FP.acos"
+  atan  = unsupported "Floating.FP.atan"
+  sinh  = unsupported "Floating.FP.sinh"
+  cosh  = unsupported "Floating.FP.cosh"
+  tanh  = unsupported "Floating.FP.tanh"
+  asinh = unsupported "Floating.FP.asinh"
+  acosh = unsupported "Floating.FP.acosh"
+  atanh = unsupported "Floating.FP.atanh"
+
+-- | Real-float instance for big-floats. Beware! Some of these aren't really all that well tested.
+instance RealFloat FP where
+  floatRadix     _            = 2
+  floatDigits    (FP _  sb _) = sb
+  floatRange     (FP eb _  _) = (fromIntegral (-v+3), fromIntegral v)
+     where v :: Integer
+           v = 2 ^ ((fromIntegral eb :: Integer) - 1)
+
+  isNaN            = fpIsNaN
+  isInfinite       = fpIsInf
+  isDenormalized   = fpIsSubnormal
+  isNegativeZero f = fpIsZero f && fpIsNeg f
+  isIEEE         _ = True
+
+  decodeFloat i@(FP _ _ r) = case BF.bfToRep r of
+                               BF.BFNaN     -> decodeFloat (0/0 :: Double)
+                               BF.BFRep s n -> case n of
+                                                BF.Zero    -> (0, 0)
+                                                BF.Inf     -> let (_, m) = floatRange i
+                                                                  x = (2 :: Integer) ^ toInteger (m+1)
+                                                              in (if s == BF.Neg then -x else x, 0)
+                                                BF.Num x y -> -- The value here is x * 2^y
+                                                               (if s == BF.Neg then -x else x, fromIntegral y)
+
+  encodeFloat = error "FP.encodeFloat: Not supported for arbitrary floats. Use fpEncodeFloat instead, specifying the precision"
+
+-- | Encode from exponent/mantissa form to a float representation. Corresponds to 'encodeFloat' in Haskell.
+fpEncodeFloat :: Int -> Int -> Integer -> Int -> FP
+fpEncodeFloat eb sb m n | n < 0 = fpFromRational eb sb (m      % n')
+                        | True  = fpFromRational eb sb (m * n' % 1)
+    where n' :: Integer
+          n' = (2 :: Integer) ^ abs (fromIntegral n :: Integer)
+
+-- | Is a big-float finite?
+fpIsFinite :: FP -> Bool
+fpIsFinite (FP _ _ r) = BF.bfIsFinite r
+
+-- | Is a big-float infinite?
+fpIsInf :: FP -> Bool
+fpIsInf (FP _ _ r) = BF.bfIsInf r
+
+-- | Is a big-float a zero value?
+fpIsZero :: FP -> Bool
+fpIsZero (FP _ _ r) = BF.bfIsZero r
+
+-- | Is a big-float a NaN value?
+fpIsNaN :: FP -> Bool
+fpIsNaN (FP _ _ r) = BF.bfIsNaN r
+
+-- | Is a big-float \"normal\"? That is, is the value not zero, infinite, NaN,
+-- or subnormal?
+fpIsNormal :: FP -> Bool
+fpIsNormal (FP eb sb r) = BF.bfIsNormal (mkBFOpts eb sb BF.NearEven) r
+
+-- | Is a big-float subnormal (i.e., denormalized)?
+fpIsSubnormal :: FP -> Bool
+fpIsSubnormal (FP eb sb r) = BF.bfIsSubnormal (mkBFOpts eb sb BF.NearEven) r
+
+-- | Is a big-float negative?
+fpIsNeg :: FP -> Bool
+fpIsNeg (FP _ _ r) = BF.bfIsNeg r
+
+-- | Is a big-float positive?
+fpIsPos :: FP -> Bool
+fpIsPos (FP _ _ r) = BF.bfIsPos r
+
+-- | Big-float negation.
+fpNeg :: FP -> FP
+fpNeg = lift1 BF.bfNeg
+
+-- | Big-float absolute value.
+fpAbs :: FP -> FP
+fpAbs = lift1 BF.bfAbs
+
+-- | Big-float signum.
+fpSignum :: FP -> FP
+fpSignum = lift1 bfSignum
+
+-- | Big-float addition.
+fpAdd :: RoundingMode -> FP -> FP -> FP
+fpAdd = liftRM2 BF.bfAdd
+
+-- | Big-float subtraction.
+fpSub :: RoundingMode -> FP -> FP -> FP
+fpSub = liftRM2 BF.bfSub
+
+-- | Big-float multiplication.
+fpMul :: RoundingMode -> FP -> FP -> FP
+fpMul = liftRM2 BF.bfMul
+
+-- | Big-float division.
+fpDiv :: RoundingMode -> FP -> FP -> FP
+fpDiv = liftRM2 BF.bfDiv
+
+-- | Big-float exponentiation.
+fpPow :: RoundingMode -> FP -> FP -> FP
+fpPow = liftRM2 BF.bfPow
+
+-- | Big-float remainder.
+fpRem :: RoundingMode -> FP -> FP -> FP
+fpRem = liftRM2 BF.bfRem
+
+-- | Big-float square root.
+fpSqrt :: RoundingMode -> FP -> FP
+fpSqrt = liftRM1 BF.bfSqrt
+
+-- | Big-float fused-multiply-add (FMA).
+fpFMA :: RoundingMode -> FP -> FP -> FP -> FP
+fpFMA = liftRM3 BF.bfFMA
+
+-- | Round a big-float to a float of the given exponent and significand sizes
+-- using the given rounding mode.
+fpRoundFloat :: Int -> Int -> RoundingMode -> FP -> FP
+fpRoundFloat eb sb rm (FP _ _ r) = FP eb sb $ fst $ BF.bfRoundFloat (mkBFOpts eb sb (roundingModeToRoundMode rm)) r
+
+-- | Round a big-float to the nearest integer (represented as a big-float with
+-- a zero decimal component) using the given rounding mode.
+fpRoundInt :: RoundingMode -> FP -> FP
+fpRoundInt rm (FP eb sa a) = FP eb sa $ fst $ BF.bfRoundInt (roundingModeToRoundMode rm) a
+
+-- | SMTLib compliant definition for 'Data.SBV.fpMax'. This is very nearly
+-- identical to 'Data.SBV.Utils.Numeric.fpMaxH', except that this uses
+-- 'fpIsZero' instead of checking for equality against a @0@ literal. (The
+-- latter is not supported for t'FP' values as t'FP' does not implement
+-- 'fromInteger'.)
+fpMax :: FP -> FP -> FP
+fpMax x y
+   | isNaN x                                  = y
+   | isNaN y                                  = x
+   | (isN0 x && isP0 y) || (isN0 y && isP0 x) = error "fpMax: Called with alternating-sign 0's. Not supported"
+   | x > y                                    = x
+   | True                                     = y
+   where isN0   = isNegativeZero
+         isP0 a = fpIsZero a && not (isN0 a)
+
+-- | SMTLib compliant definition for 'Data.SBV.fpMin'. This is very nearly
+-- identical to 'Data.SBV.Utils.Numeric.fpMinH', except that this uses
+-- 'fpIsZero' instead of checking for equality against a @0@ literal. (The
+-- latter is not supported for t'FP' values as t'FP' does not implement
+-- 'fromInteger'.)
+fpMin :: FP -> FP -> FP
+fpMin x y
+   | isNaN x                                  = y
+   | isNaN y                                  = x
+   | (isN0 x && isP0 y) || (isN0 y && isP0 x) = error "fpMin: Called with alternating-sign 0's. Not supported"
+   | x < y                                    = x
+   | True                                     = y
+   where isN0   = isNegativeZero
+         isP0 a = fpIsZero a && not (isN0 a)
+
+-- | Real instance for big-floats. Beware, not that well tested!
+instance Real FP where
+  toRational i
+     | n >= 0  = m * 2 ^ n % 1
+     | True    = m % 2 ^ abs n
+    where (m, n) = decodeFloat i
+
+-- | Real-frac instance for big-floats. Beware, not that well tested!
+instance RealFrac FP where
+  properFraction (FP eb sb r) = (getInt r', FP eb sb r - FP eb sb r')
+       where (r', _)  = BF.bfRoundInt BF.ToZero r
+             getInt x = case BF.bfToRep x of
+                          BF.BFNaN     -> error $ "Data.SBV.FloatingPoint.properFraction: Failed to convert: " ++ show (r, x)
+                          BF.BFRep s n -> case n of
+                                           BF.Zero    -> 0
+                                           BF.Inf     -> error $ "Data.SBV.FloatingPoint.properFraction: Failed to convert: " ++ show (r, x)
+                                           BF.Num v y -> -- The value here is x * 2^y, and is integer if y >= 0
+                                                         let e :: Integer
+                                                             e   = 2 ^ (fromIntegral y :: Integer)
+                                                             sgn = if s == BF.Neg then ((-1) *) else id
+                                                         in if y > 0
+                                                            then fromIntegral $ sgn $ v * e
+                                                            else fromIntegral $ sgn v
+
+-- | Real instance for FloatingPoint. NB. The methods haven't been subjected to much testing, so beware of any floating-point snafus here.
+instance ValidFloat eb sb => Real (FloatingPoint eb sb) where
+  toRational (FloatingPoint (FP _ _ r)) = case bfToRep r of
+                                            BFNaN     -> toRational (0/0 :: Double)
+                                            BFRep s n -> case n of
+                                                           Zero    -> 0 % 1
+                                                           Inf     -> (if s == Neg then -1 else 1) % 0
+                                                           Num x y -> -- The value here is x * 2^y
+                                                                      let v :: Integer
+                                                                          v   = 2 ^ abs (fromIntegral y :: Integer)
+                                                                          sgn = if s == Neg then ((-1) *) else id
+                                                                      in if y > 0
+                                                                            then sgn $ x * v % 1
+                                                                            else sgn $ x % v
+
+-- | RealFrac instance for FloatingPoint. NB. The methods haven't been subjected to much testing, so beware of any floating-point snafus here.
+instance ValidFloat eb sb => RealFrac (FloatingPoint eb sb) where
+  properFraction (FloatingPoint f) = (a, FloatingPoint b)
+     where (a, b) = properFraction f
+
+-- | Num instance for FloatingPoint
+instance ValidFloat eb sb => Num (FloatingPoint eb sb) where
+  FloatingPoint a + FloatingPoint b = FloatingPoint $ a + b
+  FloatingPoint a * FloatingPoint b = FloatingPoint $ a * b
+
+  abs    (FloatingPoint fp) = FloatingPoint (abs    fp)
+  signum (FloatingPoint fp) = FloatingPoint (signum fp)
+  negate (FloatingPoint fp) = FloatingPoint (negate fp)
+
+  fromInteger = FloatingPoint . fpFromInteger (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))
+
+instance ValidFloat eb sb => Fractional (FloatingPoint eb sb) where
+  fromRational = FloatingPoint . fpFromRational (intOfProxy (Proxy @eb)) (intOfProxy (Proxy @sb))
+
+  FloatingPoint a / FloatingPoint b = FloatingPoint (a / b)
+
+unsupported :: String -> a
+unsupported w = error $ "Data.SBV.FloatingPoint: Unsupported operation: " ++ w ++ ". Please request this as a feature!"
+
+-- Float instance. Most methods are left unimplemented.
+instance ValidFloat eb sb => Floating (FloatingPoint eb sb) where
+  pi = FloatingPoint pi
+
+  exp  (FloatingPoint i) = FloatingPoint (exp i)
+  sqrt (FloatingPoint i) = FloatingPoint (sqrt i)
+
+  FloatingPoint a ** FloatingPoint b = FloatingPoint $ a ** b
+
+  log   (FloatingPoint i) = FloatingPoint (log   i)
+  sin   (FloatingPoint i) = FloatingPoint (sin   i)
+  cos   (FloatingPoint i) = FloatingPoint (cos   i)
+  tan   (FloatingPoint i) = FloatingPoint (tan   i)
+  asin  (FloatingPoint i) = FloatingPoint (asin  i)
+  acos  (FloatingPoint i) = FloatingPoint (acos  i)
+  atan  (FloatingPoint i) = FloatingPoint (atan  i)
+  sinh  (FloatingPoint i) = FloatingPoint (sinh  i)
+  cosh  (FloatingPoint i) = FloatingPoint (cosh  i)
+  tanh  (FloatingPoint i) = FloatingPoint (tanh  i)
+  asinh (FloatingPoint i) = FloatingPoint (asinh i)
+  acosh (FloatingPoint i) = FloatingPoint (acosh i)
+  atanh (FloatingPoint i) = FloatingPoint (atanh i)
+
+-- | Lift a unary operation, simple case of function with no status. Here, we call fpFromBigFloat since the big-float isn't size aware.
+lift1 :: (BigFloat -> BigFloat) -> FP -> FP
+lift1 f (FP eb sb a) = fpFromBigFloat eb sb $ f a
+
+-- | Lift a unary operation that returns a big-float and a status.
+liftRM1 :: (BFOpts -> BigFloat -> (BigFloat, Status)) -> RoundingMode -> FP -> FP
+liftRM1 f rm (FP eb sb a) = FP eb sb $ fst $ f (mkBFOpts eb sb (roundingModeToRoundMode rm)) a
+
+-- | Lift a binary operation that returns a big-float and a status.
+liftRM2 :: (BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status)) -> RoundingMode -> FP -> FP -> FP
+liftRM2 f rm (FP eb sb a) (FP _ _ b) = FP eb sb $ fst $ f (mkBFOpts eb sb (roundingModeToRoundMode rm)) a b
+
+-- | Lift a trinary operation that returns a big-float and a status.
+liftRM3 :: (BFOpts -> BigFloat -> BigFloat -> BigFloat -> (BigFloat, Status)) -> RoundingMode -> FP -> FP -> FP -> FP
+liftRM3 f rm (FP eb sb a) (FP _ _ b) (FP _ _ c) = FP eb sb $ fst $ f (mkBFOpts eb sb (roundingModeToRoundMode rm)) a b c
+
+-- | Convert from a IEEE float.
+fpFromFloat :: Int -> Int -> Float -> FP
+fpFromFloat  8 24 f = let fw          = floatToWord f
+                          (sgn, e, s) = (fw `testBit` 31, fromIntegral (fw `shiftR` 23) .&. 0xFF, fromIntegral fw .&. 0x7FFFFF)
+                      in fpFromRawRep sgn (e, 8) (s, 24)
+fpFromFloat eb sb f = error $ "SBV.fpFromFloat: Unexpected input: " ++ show (eb, sb, f)
+
+-- | Convert from a IEEE double.
+fpFromDouble :: Int -> Int -> Double -> FP
+fpFromDouble 11 53 d = FP 11 54 $ BF.bfFromDouble d
+fpFromDouble eb sb d = error $ "SBV.fpFromDouble: Unexpected input: " ++ show (eb, sb, d)
+
+-- | Convert to a IEEE float using the given rounding mode.
+fpToFloat :: RoundingMode -> FP -> Float
+fpToFloat rm (FP _ _ r) = fp2fp $ fst $ BF.bfToDouble (roundingModeToRoundMode rm) r
+
+-- | Convert to a IEEE double using the given rounding mode.
+fpToDouble :: RoundingMode -> FP -> Double
+fpToDouble rm (FP _ _ r) = fst $ BF.bfToDouble (roundingModeToRoundMode rm) r
+
+-- | Map SBV's rounding modes to LibBF's.
+roundingModeToRoundMode :: RoundingMode -> RoundMode
+roundingModeToRoundMode RoundNearestTiesToEven = BF.NearEven
+roundingModeToRoundMode RoundNearestTiesToAway = BF.NearAway
+roundingModeToRoundMode RoundTowardPositive    = BF.ToPosInf
+roundingModeToRoundMode RoundTowardNegative    = BF.ToNegInf
+roundingModeToRoundMode RoundTowardZero        = BF.ToZero
diff --git a/Data/SBV/Core/Symbolic.hs b/Data/SBV/Core/Symbolic.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/Symbolic.hs
@@ -0,0 +1,2337 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.Symbolic
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Symbolic values
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns               #-}
+{-# LANGUAGE DefaultSignatures          #-}
+{-# LANGUAGE DeriveAnyClass             #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveFunctor              #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE DerivingStrategies         #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE LambdaCase                 #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE NamedFieldPuns             #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE RankNTypes                 #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+{-# LANGUAGE StandaloneDeriving         #-}
+{-# LANGUAGE TypeOperators              #-}
+{-# LANGUAGE UndecidableInstances       #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Core.Symbolic
+  ( NodeId(..)
+  , SV(..), swKind, trueSV, falseSV
+  , Op(..), PBOp(..), OvOp(..), FPOp(..), NROp(..), StrOp(..), RegExOp(..), SeqOp(..), SetOp(..), SpecialRelOp(..), ADTOp(..)
+  , RegExp(..), regExpToSMTString, SMTLambda(..)
+  , Quantifier(..), needsExistentials, SBVContext(..), globalSBVContext, VarContext(..)
+  , SBVType(..), svUninterpreted, svUninterpretedNamedArgs, newUninterpreted
+  , SVal(..)
+  , svMkSymVar, sWordN, sWordN_, sIntN, sIntN_
+  , svToSV, svToSymSV, forceSVArg
+  , SBVExpr(..), newExpr, isCodeGenMode, isSafetyCheckingIStage, isRunIStage, isSetupIStage
+  , Cached, cache, uncache, modifyState, modifyIncState
+  , NamedSymVar(..), Name, UserInputs, Inputs(..), getSV, swNodeId
+  , getUserName', getUserName
+  , lookupInput , getSValPathCondition, extendSValPathCondition
+  , getTableIndex, sObserve
+  , SBVPgm(..), MonadSymbolic(..), SymbolicT, Symbolic, runSymbolic, mkNewState, runSymbolicInState, State(..), SMTDef(..), smtDefEq, conflictError, withNewIncState, IncState(..), incrementInternalCounter, incrementFreshNameCounter
+  , inSMTMode, SBVRunMode(..), IStage(..), Result(..), ResultInp(..), UICodeKind(..), UIName(..)
+  , registerKind, registerLabel, recordObservable
+  , addAssertion, addNewSMTOption, imposeConstraint, internalConstraint, newInternalVariable, lambdaVar, quantVar
+  , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension, smtLibPgmText
+  , SolverCapabilities(..)
+  , extractSymbolicSimulationState, CnstMap
+  , OptimizeStyle(..), Objective(..), Penalty(..), objectiveName, addSValOptGoal
+  , MonadQuery(..), QueryT(..), Query, QueryState(..), QueryContext(..)
+  , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), TPOptions(..), SMTEngine
+  , validationRequested, outputSVal, ProgInfo(..), mustIgnoreVar, getRootState
+  , LambdaInfo(..), showNROp
+  ) where
+
+import Control.DeepSeq             (NFData(..))
+import Control.Monad               (when, unless)
+import Control.Monad.Except        (MonadError, ExceptT)
+import Control.Monad.Reader        (MonadReader(..), ReaderT, runReaderT,
+                                    mapReaderT)
+import Control.Monad.State.Lazy    (MonadState)
+import Control.Monad.Trans         (MonadIO(liftIO), MonadTrans(lift))
+import Control.Monad.Trans.Maybe   (MaybeT)
+import Control.Monad.Writer.Strict (MonadWriter)
+import Data.IORef                  (IORef, newIORef, readIORef)
+import Data.List                   (intercalate, isPrefixOf)
+import Data.Maybe                  (fromMaybe)
+import Data.String                 (IsString(fromString))
+
+import Data.Time (getCurrentTime, UTCTime)
+
+import Data.Int (Int64)
+
+import GHC.Stack
+import GHC.Stack.Types
+import GHC.Generics (Generic)
+
+import qualified Control.Exception as C
+import qualified Control.Monad.State.Lazy    as LS
+import qualified Control.Monad.State.Strict  as SS
+import qualified Control.Monad.Writer.Lazy   as LW
+import qualified Control.Monad.Writer.Strict as SW
+import qualified Data.IORef                  as R    (modifyIORef')
+import qualified Data.Generics               as G    (Data(..))
+import qualified Data.Generics.Uniplate.Data as G
+import qualified Data.IntMap.Strict          as IMap (IntMap, empty, lookup, insertWith)
+import qualified Data.Map.Strict             as Map  (Map, empty, toList, lookup, insert, size, keysSet)
+import qualified Data.Set                    as Set  (Set, empty, toList, insert, member, notMember)
+import qualified Data.Foldable               as F    (toList)
+import qualified Data.Sequence               as S    (Seq, empty, (|>), lookup, elemIndexL)
+import qualified Data.Text                   as T
+import           Data.Text                   (Text)
+
+import System.Mem.StableName
+import System.Random
+
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Concrete
+import Data.SBV.SMT.SMTLibNames
+import Data.SBV.Utils.TDiff   (Timing)
+import Data.SBV.Utils.Lib     (stringToQFS, checkObservableName, barify, mapToSortedList, showText)
+import Data.SBV.Utils.Numeric (RoundingMode)
+
+import Data.Containers.ListUtils (nubOrd)
+
+import Data.SBV.Control.Types
+
+
+-- | Context identifier. 0 is reserved global context
+newtype SBVContext = SBVContext Int64 deriving (Eq, Ord, G.Data, Show)
+
+instance NFData SBVContext where
+  rnf (SBVContext i) = i `seq` ()
+
+-- | Global context
+globalSBVContext :: SBVContext
+globalSBVContext = SBVContext 0
+
+-- | Generate context. We make sure it isn't 0, i.e., the global context
+-- The "hope" here is that each time we call this we get a different context number.
+-- A random number doesn't necessarily have to do that, but I think the pseudo-generator
+-- has a large enough period for this to go through OK.
+genSBVContext :: IO SBVContext
+genSBVContext = do ctx <- SBVContext <$> randomIO
+                   if ctx == globalSBVContext   -- unlikely, but possible
+                      then genSBVContext
+                      else pure ctx
+
+-- | A symbolic node id
+newtype NodeId = NodeId { getId :: (SBVContext, Maybe Int, Int) } -- Lambda-level, and node-id
+  deriving (Ord, G.Data)
+
+-- Equality is pair-wise, except we accommodate for negative node-id; which is reserved for true/false
+instance Eq NodeId where
+  NodeId n1@(_, _, i) == NodeId n2@(_, _, j)
+     | i < 0 && j < 0
+     = i == j
+     | True
+     = n1 == n2
+
+-- | A symbolic word, tracking its kind and node representing it
+data SV = SV !Kind !NodeId
+        deriving G.Data
+
+-- | For equality, we merely use the lambda-level/node-id
+instance Eq SV where
+  SV _ n1 == SV _ n2 = n1 == n2
+
+-- | Again, simply use the lambda-level/node-id for ordering
+instance Ord SV where
+  SV _ n1 `compare` SV _ n2 = n1 `compare` n2
+
+instance HasKind SV where
+  kindOf (SV k _) = k
+
+instance Show SV where
+  show (SV _ (NodeId (_, l, n))) = case n of
+                                     -2 -> "false"
+                                     -1 -> "true"
+                                     _  -> prefix ++ 's' : show n
+        where prefix = case l of
+                         Nothing -> "arg"   -- top-level lambda
+                         Just 0  -> ""
+                         Just i  -> 'l' : show i ++ "_"
+
+-- | Kind of a symbolic word.
+swKind :: SV -> Kind
+swKind (SV k _) = k
+
+-- | retrieve the node id of a symbolic word
+swNodeId :: SV -> NodeId
+swNodeId (SV _ nid) = nid
+
+-- | Forcing an argument; this is a necessary evil to make sure all the arguments
+-- to an uninterpreted function are evaluated before called; the semantics of uninterpreted
+-- functions is necessarily strict; deviating from Haskell's
+forceSVArg :: SV -> IO ()
+forceSVArg (SV k n) = k `seq` n `seq` pure ()
+
+-- | Constant False as an t'SV'. Note that this value always occupies slot -2 and level 0.
+falseSV :: SV
+falseSV = SV KBool $ NodeId (globalSBVContext, Just 0, -2)
+
+-- | Constant True as an t'SV'. Note that this value always occupies slot -1 and level 0.
+trueSV :: SV
+trueSV  = SV KBool $ NodeId (globalSBVContext, Just 0, -1)
+
+-- | Symbolic operations
+data Op = Plus
+        | Times
+        | Minus
+        | UNeg
+        | Abs
+        | Quot
+        | Rem
+        | Equal Bool   -- ^ If bool is True then this is strong (i.e., object equality). Matters for floats or structures containing them.
+        | Implies
+        | NotEqual
+        | LessThan
+        | GreaterThan
+        | LessEq
+        | GreaterEq
+        | Ite
+        | And
+        | Or
+        | XOr
+        | Not
+        | Shl
+        | Shr
+        | Rol Int
+        | Ror Int
+        | Divides Integer                       -- divides k n is True if k divides n. k must be > 0 constant
+        | Extract Int Int                       -- Extract i j: extract bits i to j. Least significant bit is 0 (big-endian)
+        | Join                                  -- Concat two words to form a bigger one, in the order given
+        | ZeroExtend Int
+        | SignExtend Int
+        | LkUp (Int, Kind, Kind, Int) !SV !SV   -- (table-index, arg-type, res-type, length of the table) index out-of-bounds-value
+        | KindCast Kind Kind
+        | Uninterpreted T.Text
+        | QuantifiedBool T.Text                 -- When we generate a forall/exists (nested etc.) boolean value. NB. This used to be "QuantifiedBool [Op] String", keeping track of Ops. That turned out to cause memory leaks. So avoid that.
+        | SpecialRelOp Kind SpecialRelOp        -- Generate the equality to the internal operation
+        | Label String                          -- Essentially no-op; useful for code generation to emit comments.
+        | IEEEFP FPOp                           -- Floating-point ops, categorized separately
+        | NonLinear NROp                        -- Non-linear ops (mostly trigonometric), categorized separately
+        | OverflowOp    OvOp                    -- Overflow-ops, categorized separately
+        | PseudoBoolean PBOp                    -- Pseudo-boolean ops, categorized separately
+        | RegExOp RegExOp                       -- RegEx operations, 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
+        | RationalConstructor                   -- Construct a rational. Note that there's no access to numerator or denominator, since we cannot store rationals in canonical form
+        | ADTOp ADTOp                           -- ADT access/construction/testing
+
+        -- Arrays
+        | ArrayInit (Either (Kind, Kind) SMTLambda) -- An array value, created either from a lambda or a symbolic value. Kind is the
+        | ReadArray                                 -- Reading an array value
+        | WriteArray                                -- Writing to an array
+        deriving (Eq, Ord, Generic, G.Data, NFData)
+
+-- | ADT operations
+data ADTOp = ADTConstructor T.Text Kind    -- Construct an ADT. Kind is the kind of the resulting ADT
+           | ADTTester      T.Text Kind    -- Check if top-level constructor matches. Kind is the kind of the argument
+           | ADTAccessor    T.Text Kind    -- Extract a field from an ADT value. Kind is the kind of the argument
+           deriving (Eq, Ord, Generic, G.Data, NFData)
+
+-- | Special relations supported by z3
+data SpecialRelOp = IsPartialOrder         String
+                  | IsLinearOrder          String
+                  | IsTreeOrder            String
+                  | IsPiecewiseLinearOrder String
+                  deriving (Eq, Ord, G.Data, Show)
+
+instance NFData SpecialRelOp where
+  rnf (IsPartialOrder         n) = rnf n
+  rnf (IsLinearOrder          n) = rnf n
+  rnf (IsTreeOrder            n) = rnf n
+  rnf (IsPiecewiseLinearOrder n) = rnf n
+
+-- | Floating point operations
+data FPOp = FP_Cast        Kind Kind SV   -- From-Kind, To-Kind, RoundingMode. This is "value" conversion
+          | FP_Reinterpret Kind Kind      -- From-Kind, To-Kind. This is bit-reinterpretation using IEEE-754 interchange format
+          | FP_Abs
+          | FP_Neg
+          | FP_Add
+          | FP_Sub
+          | FP_Mul
+          | FP_Div
+          | FP_FMA
+          | FP_Sqrt
+          | FP_Rem
+          | FP_RoundToIntegral
+          | FP_Min
+          | FP_Max
+          | FP_ObjEqual
+          | FP_IsNormal
+          | FP_IsSubnormal
+          | FP_IsZero
+          | FP_IsInfinite
+          | FP_IsNaN
+          | FP_IsNegative
+          | FP_IsPositive
+          deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- Note that the show instance maps to the SMTLib names. We need to make sure
+-- this mapping stays correct through SMTLib changes. The only exception
+-- is FP_Cast; where we handle different source/origins explicitly later on.
+instance Show FPOp where
+   show (FP_Cast f t r)      = "(FP_Cast: " ++ show f ++ " -> " ++ show t ++ ", using RM [" ++ show r ++ "])"
+   show (FP_Reinterpret f t) = case t of
+                                  KFloat    -> "(_ to_fp 8 24)"
+                                  KDouble   -> "(_ to_fp 11 53)"
+                                  KFP eb sb -> "(_ to_fp " ++ show eb ++ " " ++ show sb ++ ")"
+                                  _         -> error $ "SBV.FP_Reinterpret: Unexpected conversion: " ++ show f ++ " to " ++ show t
+   show FP_Abs               = "fp.abs"
+   show FP_Neg               = "fp.neg"
+   show FP_Add               = "fp.add"
+   show FP_Sub               = "fp.sub"
+   show FP_Mul               = "fp.mul"
+   show FP_Div               = "fp.div"
+   show FP_FMA               = "fp.fma"
+   show FP_Sqrt              = "fp.sqrt"
+   show FP_Rem               = "fp.rem"
+   show FP_RoundToIntegral   = "fp.roundToIntegral"
+   show FP_Min               = "fp.min"
+   show FP_Max               = "fp.max"
+   show FP_ObjEqual          = "="
+   show FP_IsNormal          = "fp.isNormal"
+   show FP_IsSubnormal       = "fp.isSubnormal"
+   show FP_IsZero            = "fp.isZero"
+   show FP_IsInfinite        = "fp.isInfinite"
+   show FP_IsNaN             = "fp.isNaN"
+   show FP_IsNegative        = "fp.isNegative"
+   show FP_IsPositive        = "fp.isPositive"
+
+-- | Non-linear operations. We do *not* on purpose deriving Show here, nor give a show instance,
+-- since different solvers call these functions with different names.
+data NROp = NR_Sin
+          | NR_Cos
+          | NR_Tan
+          | NR_ASin
+          | NR_ACos
+          | NR_ATan
+          | NR_Sqrt
+          | NR_Sinh
+          | NR_Cosh
+          | NR_Tanh
+          | NR_Exp
+          | NR_Log
+          | NR_Pow
+          deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Show a non-linear op. Unfortunately this can't be generically done since different
+-- solvers use different names for some of these ops.
+showNROp :: Solver -> NROp -> String
+showNROp slvr = sh
+  where sh NR_Sin  = "sin"
+        sh NR_Cos  = "cos"
+        sh NR_Tan  = "tan"
+        sh NR_ASin = arc ++ "sin"
+        sh NR_ACos = arc ++ "cos"
+        sh NR_ATan = arc ++ "tan"
+        sh NR_Sinh = "sinh"
+        sh NR_Cosh = "cosh"
+        sh NR_Tanh = "tanh"
+        sh NR_Sqrt = "sqrt"
+        sh NR_Exp  = "exp"
+        sh NR_Log  = "log"
+        sh NR_Pow  = "pow"
+
+        -- DReal uses asin/acos etc. CVC5 uses arcsin. Other solvers probably
+        -- don't even support these. But this isn't the right place to bail-out
+        -- about it; so we just put "arc" following CVC5 here.
+        arc = case slvr of
+                DReal -> "a"
+                _     -> "arc"
+
+-- | Pseudo-boolean operations
+data PBOp = PB_AtMost  Int        -- ^ At most k
+          | PB_AtLeast Int        -- ^ At least k
+          | PB_Exactly Int        -- ^ Exactly k
+          | PB_Le      [Int] Int  -- ^ At most k,  with coefficients given. Generalizes PB_AtMost
+          | PB_Ge      [Int] Int  -- ^ At least k, with coefficients given. Generalizes PB_AtLeast
+          | PB_Eq      [Int] Int  -- ^ Exactly k,  with coefficients given. Generalized PB_Exactly
+          deriving (Eq, Ord, Show, G.Data, NFData, Generic)
+
+-- | Overflow operations
+data OvOp = PlusOv Bool           -- ^ Addition    overflow.    Bool is True if signed.
+          | SubOv  Bool           -- ^ Subtraction overflow.    Bool is True if signed.
+          | MulOv  Bool           -- ^ Multiplication overflow. Bool is True if signed.
+          | DivOv                 -- ^ Division overflow.       Only signed, since unsigned division does not overflow.
+          | NegOv                 -- ^ Unary negation overflow. Only signed, since unsigned negation does not overflow.
+          deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Show instance. It's important that these follow the SMTLib names.
+instance Show OvOp where
+  show (PlusOv signed) = "bv" ++ (if signed then "s" else "u") ++ "addo"
+  show (SubOv  signed) = "bv" ++ (if signed then "s" else "u") ++ "subo"
+  show (MulOv  signed) = "bv" ++ (if signed then "s" else "u") ++ "mulo"
+  show DivOv           = "bvsdivo" -- This is confusing, the division is called bvsdivo, but negation is bvnego
+  show NegOv           = "bvnego"  -- But SMTLib's choice is deliberate: https://groups.google.com/u/0/g/smt-lib/c/J4D99wT0aKI
+
+-- | String operations.
+data StrOp = StrStrToNat     -- ^ Retrieve integer encoded by string @s@ (ground rewriting only)
+           | StrNatToStr     -- ^ Retrieve string encoded by integer @i@ (ground rewriting only)
+           | StrToCode       -- ^ Equivalent to Haskell's ord
+           | StrFromCode     -- ^ Equivalent to Haskell's chr
+           | StrInRe RegExp  -- ^ Check if string is in the regular expression
+           deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Regular-expression operators. The only thing we can do is to compare for equality/disequality.
+data RegExOp = RegExEq  RegExp RegExp
+             | RegExNEq RegExp RegExp
+             deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Regular expressions. Note that regular expressions themselves are
+-- concrete, but the 'Data.SBV.RegExp.match' function from the 'Data.SBV.RegExp.RegExpMatchable' class
+-- can check membership against a symbolic string/character. Also, we
+-- are preferring a datatype approach here, as opposed to coming up with
+-- some string-representation; there are way too many alternatives
+-- already so inventing one isn't a priority. Please get in touch if you
+-- would like a parser for this type as it might be easier to use.
+data RegExp = Literal String       -- ^ Precisely match the given string
+            | All                  -- ^ Accept every string
+            | AllChar              -- ^ Accept every single character
+            | None                 -- ^ Accept no strings
+            | Range Char Char      -- ^ Accept range of characters
+            | Conc  [RegExp]       -- ^ Concatenation
+            | KStar RegExp         -- ^ Kleene Star: Zero or more
+            | KPlus RegExp         -- ^ Kleene Plus: One or more
+            | Opt   RegExp         -- ^ Zero or one
+            | Comp  RegExp         -- ^ Complement of regular expression
+            | Diff  RegExp RegExp  -- ^ Difference of regular expressions
+            | Loop  Int Int RegExp -- ^ From @n@ repetitions to @m@ repetitions
+            | Power Int     RegExp -- ^ Exactly @n@ repetitions, i.e., nth power
+            | Union [RegExp]       -- ^ Union of regular expressions
+            | Inter RegExp RegExp  -- ^ Intersection of regular expressions
+            deriving (Eq, Ord, G.Data, Generic, NFData)
+
+-- | With overloaded strings, we can have direct literal regular expressions.
+instance IsString RegExp where
+  fromString = Literal
+
+-- | Regular expressions as a 'Num' instance. Note that only some operations make sense and
+-- not in the most obvious way. For instance, we would typically expect @a - b@ to be the
+-- same as @a + negate b@, but that equality does not hold in general. So, use the @Num@
+-- instance only as constructing syntax, not doing algebraic manipulations.
+instance Num RegExp where
+  -- flatten the concats to make them simpler
+  Conc xs * y = Conc (xs ++ [y])
+  x * Conc ys = Conc (x  :  ys)
+  x * y       = Conc [x, y]
+
+  -- flatten the unions to make them simpler
+  Union xs + y = Union (xs ++ [y])
+  x + Union ys = Union (x  : ys)
+  x + y        = Union [x, y]
+
+  x - y = Diff x y
+
+  abs         = error "Num.RegExp: no abs method"
+  signum      = error "Num.RegExp: no signum method"
+
+  fromInteger x
+    | x == 0    = None
+    | x == 1    = Literal ""   -- Unit for concatenation is the empty string
+    | True      = error $ "Num.RegExp: Only 0 and 1 makes sense as a reg-exp, no meaning for: " ++ show x
+
+  negate = Comp
+
+-- | Convert a reg-exp to a Haskell-like string
+instance Show RegExp where
+  show = T.unpack . regExpToText (T.pack . show)
+
+-- | Convert a reg-exp to a SMT-lib acceptable representation
+regExpToSMTString :: RegExp -> Text
+regExpToSMTString = regExpToText (\s -> "\"" <> T.pack (stringToQFS s) <> "\"")
+
+-- | Convert a RegExp to text, parameterized by how strings are converted
+regExpToText :: (String -> Text) -> RegExp -> Text
+regExpToText fs (Literal s)       = "(str.to_re " <> fs s <> ")"
+regExpToText _  All               = "re.all"
+regExpToText _  AllChar           = "re.allchar"
+regExpToText _  None              = "re.nostr"
+regExpToText fs (Range ch1 ch2)   = "(re.range " <> fs [ch1] <> " " <> fs [ch2] <> ")"
+regExpToText _  (Conc [])         = "1"
+regExpToText fs (Conc [x])        = regExpToText fs x
+regExpToText fs (Conc xs)         = "(re.++ " <> T.unwords (map (regExpToText fs) xs) <> ")"
+regExpToText fs (KStar r)         = "(re.* " <> regExpToText fs r <> ")"
+regExpToText fs (KPlus r)         = "(re.+ " <> regExpToText fs r <> ")"
+regExpToText fs (Opt   r)         = "(re.opt " <> regExpToText fs r <> ")"
+regExpToText fs (Comp  r)         = "(re.comp " <> regExpToText fs r <> ")"
+regExpToText fs (Diff  r1 r2)     = "(re.diff " <> regExpToText fs r1 <> " " <> regExpToText fs r2 <> ")"
+regExpToText fs (Loop  lo hi r)
+   | lo >= 0, hi >= lo = "((_ re.loop " <> showText lo <> " " <> showText hi <> ") " <> regExpToText fs r <> ")"
+   | True              = error $ "Invalid regular-expression Loop with arguments: " ++ show (lo, hi)
+regExpToText fs (Power n r)
+   | n >= 0            = regExpToText fs (Loop n n r)
+   | True              = error $ "Invalid regular-expression Power with arguments: " ++ show n
+regExpToText fs (Inter r1 r2)     = "(re.inter " <> regExpToText fs r1 <> " " <> regExpToText fs r2 <> ")"
+regExpToText _  (Union [])        = "re.nostr"
+regExpToText fs (Union [x])       = regExpToText fs x
+regExpToText fs (Union xs)        = "(re.union " <> T.unwords (map (regExpToText fs) xs) <> ")"
+
+-- | Show instance for @StrOp@. Note that the mapping here is important to match the SMTLib equivalents.
+instance Show StrOp where
+  show StrStrToNat = "str.to.int"    -- NB. SMTLib uses "int" here though only nats are supported
+  show StrNatToStr = "int.to.str"    -- NB. SMTLib uses "int" here though only nats are supported
+  show StrToCode   = "str.to_code"
+  show StrFromCode = "str.from_code"
+  -- Note the breakage here with respect to argument order. We fix this explicitly later.
+  show (StrInRe s) = "str.in_re " ++ T.unpack (regExpToSMTString s)
+
+-- | Show instance for @RegExOp@.
+instance Show RegExOp where
+  show (RegExEq  r1 r2) = "(= "        ++ T.unpack (regExpToSMTString r1) ++ " " ++ T.unpack (regExpToSMTString r2) ++ ")"
+  show (RegExNEq r1 r2) = "(distinct " ++ T.unpack (regExpToSMTString r1) ++ " " ++ T.unpack (regExpToSMTString r2) ++ ")"
+
+-- | For now, we represent lambda functions in op with their SMTLib equivalent strings.
+-- This might change in the future.
+newtype SMTLambda = SMTLambda T.Text
+                  deriving (Eq, Ord, G.Data, Generic)
+                  deriving newtype NFData
+
+-- | Simple show instance for SMTLambda
+instance Show SMTLambda where
+  show (SMTLambda s) = T.unpack s
+
+-- | Sequence operations. Indexed by the element kind.
+data SeqOp = SeqLen      Kind
+           | SeqConcat   Kind
+           | SeqNth      Kind
+           | SeqUnit     Kind
+           | SeqSubseq   Kind
+           | SeqIndexOf  Kind
+           | SeqContains Kind
+           | SeqPrefixOf Kind
+           | SeqSuffixOf Kind
+           | SeqReplace  Kind
+  deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- | Pick the correct operator
+pickSeqOp :: Kind -> String -> String -> String
+pickSeqOp KChar st _  = st
+pickSeqOp _     _  sq = sq
+
+-- | Show instance for SeqOp. Again, mapping is important.
+instance Show SeqOp where
+  show (SeqLen      k) = pickSeqOp k "str.len"      "seq.len"
+  show (SeqConcat   k) = pickSeqOp k "str.++"       "seq.++"
+  show (SeqNth      k) = pickSeqOp k "str.at"       "seq.nth"
+  show (SeqUnit     k) = pickSeqOp k "str.unit"     "seq.unit"
+  show (SeqSubseq   k) = pickSeqOp k "str.substr"   "seq.extract"
+  show (SeqIndexOf  k) = pickSeqOp k "str.indexof"  "seq.indexof"
+  show (SeqContains k) = pickSeqOp k "str.contains" "seq.contains"
+  show (SeqPrefixOf k) = pickSeqOp k "str.prefixof" "seq.prefixof"
+  show (SeqSuffixOf k) = pickSeqOp k "str.suffixof" "seq.suffixof"
+  show (SeqReplace  k) = pickSeqOp k "str.replace"  "seq.replace"
+
+-- | Set operations.
+data SetOp = SetEqual
+           | SetMember
+           | SetInsert
+           | SetDelete
+           | SetIntersect
+           | SetUnion
+           | SetSubset
+           | SetDifference
+           | SetComplement
+        deriving (Eq, Ord, G.Data, NFData, Generic)
+
+-- 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
+  show Shl    = "<<"
+  show Shr    = ">>"
+
+  show (Rol i) = "<<<" ++ show i
+  show (Ror i) = ">>>" ++ show i
+
+  show (Extract i j) = "choose [" ++ show i ++ ":" ++ show j ++ "]"
+
+  show (LkUp (ti, at, rt, l) i e)
+        = "lookup(" ++ tinfo ++ ", " ++ show i ++ ", " ++ show e ++ ")"
+        where tinfo = "table" ++ show ti ++ "(" ++ show at ++ " -> " ++ show rt ++ ", " ++ show l ++ ")"
+
+  show (KindCast fr to)     = "cast_" ++ show fr ++ "_" ++ show to
+  show (Uninterpreted i)    = "[uninterpreted] " ++ T.unpack i
+  show (QuantifiedBool i)   = "[quantified boolean] " ++ T.unpack i
+
+  show (Label s)            = "[label] " ++ s
+
+  show (IEEEFP w)           = show w
+
+  show (NonLinear w)        = showNROp DReal w -- Just use DReal here, only used for debugging
+
+  show (PseudoBoolean p)    = show p
+
+  show (OverflowOp o)       = show o
+
+  show (StrOp s)            = show s
+  show (RegExOp s)          = show s
+  show (SeqOp s)            = show s
+  show (SetOp s)            = show s
+
+  show (TupleConstructor   0) = "mkSBVTuple0"
+  show (TupleConstructor   n) = "mkSBVTuple" ++ show n
+  show (TupleAccess      i n) = "proj_" ++ show i ++ "_SBVTuple" ++ show n
+
+  show RationalConstructor    = "SBV.Rational"
+  show (ArrayInit k)          = case k of
+                                  Left (a, b) -> "const-array[" ++ show a ++ " -> " ++ show b ++ "]"
+                                  Right s     -> show s
+  show ReadArray              = "select"
+  show WriteArray             = "store"
+
+  show op
+    | Just s <- op `lookup` syms = s
+    | True                       = error "impossible happened; can't find op!" -- NB. Can't display the OP here! it's the show instance after all.
+    where syms = [ (Plus, "+"), (Times, "*"), (Minus, "-"), (UNeg, "-"), (Abs, "abs")
+                 , (Quot, "quot")
+                 , (Rem,  "rem")
+                 , (Equal True, "==="), (Equal False, "=="), (NotEqual, "/="), (Implies, "=>")
+                 , (LessThan, "<"), (GreaterThan, ">"), (LessEq, "<="), (GreaterEq, ">=")
+                 , (Ite, "if_then_else")
+                 , (And, "&"), (Or, "|"), (XOr, "^"), (Not, "~")
+                 , (Join, "#")
+                 ]
+
+-- | Quantifiers: forall or exists. Note that we allow arbitrary nestings.
+data Quantifier = ALL | EX deriving (Eq, G.Data)
+
+-- | Show instance for 'Quantifier'
+instance Show Quantifier where
+  show ALL = "Forall"
+  show EX  = "Exists"
+
+-- | Which context is this variable being created?
+data VarContext = NonQueryVar (Maybe Quantifier)  -- in this case, it can be quantified
+                | QueryVar                        -- in this case, it is always existential
+
+-- | Are there any existential quantifiers?
+needsExistentials :: [Quantifier] -> Bool
+needsExistentials = (EX `elem`)
+
+-- | A simple type for SBV computations, used mainly for uninterpreted constants.
+-- We keep track of the signedness/size of the arguments. A non-function will
+-- have just one entry in the list.
+newtype SBVType = SBVType [Kind]
+                deriving (Eq, Ord, G.Data)
+
+instance Show SBVType where
+  show (SBVType []) = error "SBV: internal error, empty SBVType"
+  show (SBVType xs) = intercalate " -> " $ map show xs
+
+-- | A symbolic expression
+data SBVExpr = SBVApp !Op ![SV]
+             deriving (Eq, Ord, G.Data)
+
+-- | To improve hash-consing, take advantage of commutative operators by
+-- reordering their arguments.
+reorder :: SBVExpr -> SBVExpr
+reorder s = case s of
+              SBVApp op [a, b] | isCommutative op && a > b -> SBVApp op [b, a]
+              _ -> s
+  where isCommutative :: Op -> Bool
+        isCommutative o = o `elem` [Plus, Times, Equal True, Equal False, NotEqual, And, Or, XOr]
+
+-- Show instance for 'SBVExpr'. Again, only for debugging purposes.
+instance Show SBVExpr where
+  show (SBVApp Ite [t, a, b])           = unwords ["if", show t, "then", show a, "else", show b]
+  show (SBVApp Shl     [a, i])          = unwords [show a, "<<", show i]
+  show (SBVApp Shr     [a, i])          = unwords [show a, ">>", show i]
+  show (SBVApp (Rol i) [a])             = unwords [show a, "<<<", show i]
+  show (SBVApp (Ror i) [a])             = unwords [show a, ">>>", show i]
+  show (SBVApp (PseudoBoolean pb) args) = unwords (show pb : map show args)
+  show (SBVApp (OverflowOp op)    args) = unwords (show op : map show args)
+
+  show (SBVApp op args) | showOpInfix op, length args == 2 = unwords (map show (take 1 args) ++ show op : map show (drop 1 args))
+                        | True                             = unwords (show op : map show args)
+
+-- | Should we display this Op infix?
+showOpInfix :: Op -> Bool
+showOpInfix = (`elem` infixOps)
+  where infixOps = [ Plus, Times, Minus, Quot, Rem, Implies
+                   , Equal True, Equal False, NotEqual, LessThan, GreaterThan, LessEq, GreaterEq
+                   , And, Or, XOr, Join
+                   ]
+
+-- | A program is a sequence of assignments
+newtype SBVPgm = SBVPgm {pgmAssignments :: S.Seq (SV, SBVExpr)}
+               deriving G.Data
+
+-- | Helper synonym for text, in case we switch to something else later.
+type Name = T.Text
+
+-- | t'NamedSymVar' pairs symbolic values and user given/automatically generated names
+data NamedSymVar = NamedSymVar !SV !Name
+                 deriving (Show, Generic, G.Data)
+
+-- | For comparison purposes, we simply use the SV and ignore the name
+instance Eq NamedSymVar where
+  (==) (NamedSymVar l _) (NamedSymVar r _) = l == r
+
+instance Ord NamedSymVar where
+  compare (NamedSymVar l _) (NamedSymVar r _) = compare l r
+
+-- | Convert to a named symvar, from text
+toNamedSV :: SV -> Name -> NamedSymVar
+toNamedSV = NamedSymVar
+
+-- | Get the SV from a named sym var
+getSV :: NamedSymVar -> SV
+getSV (NamedSymVar s _) = s
+
+-- | Get the user-name typed value from named sym var
+getUserName :: NamedSymVar -> Name
+getUserName (NamedSymVar _ nm) = nm
+
+-- | Get the string typed value from named sym var
+getUserName' :: NamedSymVar -> String
+getUserName' = T.unpack . getUserName
+
+-- | Style of optimization. Note that in the pareto case the user is allowed
+-- to specify a max number of fronts to query the solver for, since there might
+-- potentially be an infinite number of them and there is no way to know exactly
+-- how many ahead of time. If 'Nothing' is given, SBV will possibly loop forever
+-- if the number is really infinite.
+data OptimizeStyle = Lexicographic      -- ^ Objectives are optimized in the order given, earlier objectives have higher priority.
+                   | Independent        -- ^ Each objective is optimized independently.
+                   | Pareto (Maybe Int) -- ^ Objectives are optimized according to pareto front: That is, no objective can be made better without making some other worse.
+                   deriving (Eq, Show)
+
+-- | Penalty for a soft-assertion. The default penalty is @1@, with all soft-assertions belonging
+-- to the same objective goal. A positive weight and an optional group can be provided by using
+-- the v'Penalty' constructor.
+data Penalty = DefaultPenalty                  -- ^ Default: Penalty of @1@ and no group attached
+             | Penalty Rational (Maybe String) -- ^ Penalty with a weight and an optional group
+             deriving Show
+
+-- | Objective of optimization. We can minimize, maximize, or give a soft assertion with a penalty
+-- for not satisfying it.
+data Objective a = Minimize          String a         -- ^ Minimize this metric
+                 | Maximize          String a         -- ^ Maximize this metric
+                 | AssertWithPenalty String a Penalty -- ^ A soft assertion, with an associated penalty
+                 deriving (Show, Functor)
+
+-- | The name of the objective
+objectiveName :: Objective a -> String
+objectiveName (Minimize          s _)   = s
+objectiveName (Maximize          s _)   = s
+objectiveName (AssertWithPenalty s _ _) = s
+
+-- | The state we keep track of as we interact with the solver
+data QueryState = QueryState { queryAsk                 :: Maybe Int -> Text -> IO String
+                             , querySend                :: Maybe Int -> Text -> IO ()
+                             , queryRetrieveResponse    :: Maybe Int -> IO String
+                             , queryConfig              :: SMTConfig
+                             , queryTerminate           :: Maybe C.SomeException -> IO ()
+                             , queryTimeOutValue        :: Maybe Int
+                             , queryAssertionStackDepth :: !Int
+                             }
+
+-- | Computations which support query operations.
+class Monad m => MonadQuery m where
+  queryState :: m State
+
+  default queryState :: (MonadTrans t, MonadQuery m', m ~ t m') => m State
+  queryState = lift queryState
+
+instance MonadQuery m             => MonadQuery (ExceptT e m)
+instance MonadQuery m             => MonadQuery (MaybeT m)
+instance MonadQuery m             => MonadQuery (ReaderT r m)
+instance MonadQuery m             => MonadQuery (SS.StateT s m)
+instance MonadQuery m             => MonadQuery (LS.StateT s m)
+instance (MonadQuery m, Monoid w) => MonadQuery (SW.WriterT w m)
+instance (MonadQuery m, Monoid w) => MonadQuery (LW.WriterT w m)
+
+-- | A query is a user-guided mechanism to directly communicate and extract
+-- results from the solver. A generalization of 'Data.SBV.Query'.
+newtype QueryT m a = QueryT { runQueryT :: ReaderT State m a }
+    deriving newtype (Applicative, Functor, Monad, MonadIO, MonadTrans, MonadError e, MonadState s, MonadWriter w)
+
+instance Monad m => MonadQuery (QueryT m) where
+  queryState = QueryT ask
+
+mapQueryT :: (ReaderT State m a -> ReaderT State n b) -> QueryT m a -> QueryT n b
+mapQueryT f = QueryT . f . runQueryT
+{-# INLINE mapQueryT #-}
+
+-- Have to define this one by hand, because we use ReaderT in the implementation
+instance MonadReader r m => MonadReader r (QueryT m) where
+  ask = lift ask
+  local f = mapQueryT $ mapReaderT $ local f
+
+-- | A query is a user-guided mechanism to directly communicate and extract
+-- results from the solver.
+type Query = QueryT IO
+
+instance MonadSymbolic Query where
+   symbolicEnv = queryState
+
+instance NFData OptimizeStyle where
+   rnf x = x `seq` ()
+
+instance NFData Penalty where
+   rnf DefaultPenalty  = ()
+   rnf (Penalty p mbs) = rnf p `seq` rnf mbs
+
+instance NFData a => NFData (Objective a) where
+   rnf (Minimize          s a)   = rnf s `seq` rnf a
+   rnf (Maximize          s a)   = rnf s `seq` rnf a
+   rnf (AssertWithPenalty s a p) = rnf s `seq` rnf a `seq` rnf p
+
+-- | A result can either produce something at the top or as a lambda/constraint. Distinguish by inputs
+data ResultInp = ResultTopInps ([NamedSymVar], [NamedSymVar])  -- user inputs -- trackers
+               | ResultLamInps [(Quantifier, NamedSymVar)]     -- for constraints, we can have quantifiers
+               deriving G.Data
+
+instance NFData ResultInp where
+   rnf (ResultTopInps xs) = rnf xs
+   rnf (ResultLamInps xs) = rnf xs
+
+-- | Several data about the program
+data ProgInfo = ProgInfo { hasQuants         :: !Bool
+                         , progSpecialRels   :: ![SpecialRelOp]
+                         , progTransClosures :: ![(String, String)]
+                         }
+                         deriving G.Data
+
+instance NFData ProgInfo where
+   rnf (ProgInfo a b c) = rnf a `seq` rnf b `seq` rnf c
+
+deriving instance G.Data CallStack
+deriving instance G.Data SrcLoc
+
+-- | Result of running a symbolic computation
+data Result = Result { progInfo       :: ProgInfo                                     -- ^ various info we collect about the program
+                     , reskinds       :: Set.Set Kind                                 -- ^ kinds used in the program
+                     , resTraces      :: [(String, CV)]                               -- ^ quick-check counter-example information (if any)
+                     , resObservables :: [(String, CV -> Bool, SV)]                   -- ^ observable expressions (part of the model)
+                     , resUISegs      :: [(String, [String])]                         -- ^ uninterpreted code segments
+                     , resParams      :: ResultInp                                    -- ^ top-inputs or lambda params
+                     , resConsts      :: (CnstMap, [(SV, CV)])                        -- ^ constants
+                     , resTables      :: [((Int, Kind, Kind), [SV])]                  -- ^ tables (automatically constructed) (tableno, index-type, result-type) elts
+                     , resUIConsts    :: [(String, (Bool, Maybe [String], SBVType))]  -- ^ uninterpreted constants
+                     , resDefinitions :: [(String, (SMTDef, SBVType))]                -- ^ definitions created via smtFunction
+                     , resAsgns       :: SBVPgm                                       -- ^ assignments
+                     , resConstraints :: S.Seq (Bool, [(String, String)], SV)         -- ^ additional constraints (boolean)
+                     , resAssertions  :: [(String, Maybe CallStack, SV)]              -- ^ assertions
+                     , resOutputs     :: [SV]                                         -- ^ outputs
+                     }
+                     deriving G.Data
+
+-- Show instance for 'Result'. Only for debugging purposes.
+instance Show Result where
+  -- If there's nothing interesting going on, just print the constant. Note that the
+  -- definition of interesting here is rather subjective; but essentially if we reduced
+  -- the result to a single constant already, without any reference to anything.
+  show Result{resConsts=(_, cs), resOutputs=[r]}
+    | Just c <- r `lookup` cs
+    = show c
+  show (Result _ kinds _ _ cgs params (_, cs) ts uis defns xs cstrs asserts os) = intercalate "\n" $
+                   (if null usorts then [] else "SORTS" : map ("  " ++) usorts)
+                ++ (case params of
+                      ResultTopInps (i, t) -> "INPUTS" : map shn i ++ (if null t then [] else "TRACKER VARS" : map shn t)
+                      ResultLamInps qs     -> "LAMBDA-CONSTRAINT PARAMS" : map shq qs
+                   )
+                ++ ["CONSTANTS"]
+                ++ concatMap shc cs
+                ++ ["TABLES"]
+                ++ map sht ts
+                ++ ["UNINTERPRETED CONSTANTS"]
+                ++ map shui uis
+                ++ ["USER GIVEN CODE SEGMENTS"]
+                ++ concatMap shcg cgs
+                ++ ["AXIOMS-DEFINITIONS"]
+                ++ map show defns
+                ++ ["DEFINE"]
+                ++ map (\(s, e) -> "  " ++ shs s ++ " = " ++ show e) (F.toList (pgmAssignments xs))
+                ++ ["CONSTRAINTS"]
+                ++ map (("  " ++) . shCstr) (F.toList cstrs)
+                ++ ["ASSERTIONS"]
+                ++ map (("  "++) . shAssert) asserts
+                ++ ["OUTPUTS"]
+                ++ sh2 os
+    where sh2 :: Show a => [a] -> [String]
+          sh2 = map (("  "++) . show)
+
+          usorts = [s | KADT s _ _ <- filter isUninterpreted (Set.toList kinds)]
+
+          shs sv = show sv ++ " :: " ++ show (swKind sv)
+
+          sht ((i, at, rt), es)  = "  Table " ++ show i ++ " : " ++ show at ++ "->" ++ show rt ++ " = " ++ show es
+
+          shc (sv, cv)
+            | sv == falseSV || sv == trueSV
+            = []
+            | True
+            = ["  " ++ show sv ++ " = " ++ show cv]
+
+          shcg (s, ss) = ("Variable: " ++ s) : map ("  " ++) ss
+
+          shn (NamedSymVar sv nm) = "  " ++ ni ++ " :: " ++ show (swKind sv) ++ alias
+            where ni = show sv
+
+                  alias | T.pack ni == nm = ""
+                        | True              = ", aliasing " ++ show nm
+
+          shq (q, v) = shn v ++ ", " ++ if q == ALL then "universal" else "existential"
+
+          shui (nm, t) = "  [uninterpreted] " ++ nm ++ " :: " ++ show t
+
+          shCstr (isSoft, [], c)               = soft isSoft ++ show c
+          shCstr (isSoft, [(":named", nm)], c) = soft isSoft ++ nm ++ ": " ++ show c
+          shCstr (isSoft, attrs, c)            = soft isSoft ++ show c ++ " (attributes: " ++ show attrs ++ ")"
+
+          soft True  = "[SOFT] "
+          soft False = ""
+
+          shAssert (nm, stk, p) = "  -- assertion: " ++ nm ++ " " ++ maybe "[No location]"
+                prettyCallStack
+                stk ++ ": " ++ show p
+
+-- | Expression map, used for hash-consing
+type ExprMap = Map.Map SBVExpr SV
+
+-- | Constants are stored in a map, for hash-consing.
+type CnstMap = Map.Map CV SV
+
+-- | Kinds used in the program; used for determining the final SMT-Lib logic to pick
+type KindSet = Set.Set Kind
+
+-- | Tables generated during a symbolic run
+type TableMap = Map.Map (Kind, Kind, [SV]) Int
+
+-- | Uninterpreted-constants generated during a symbolic run
+type UIMap = Map.Map String (Bool, Maybe [String], SBVType)   -- If Bool is true, then this is a curried function
+
+-- | Code-segments for Uninterpreted-constants, as given by the user
+type CgMap = Map.Map String [String]
+
+-- | Cached values, implementing sharing
+type Cache a = IMap.IntMap [(StableName (State -> IO a), a)]
+
+-- | Stage of an interactive run
+data IStage = ISetup        -- Before we initiate contact.
+            | ISafe         -- In the context of a safe/safeWith call
+            | IRun          -- After the contact is started
+
+-- | Are we checking safety
+isSafetyCheckingIStage :: IStage -> Bool
+isSafetyCheckingIStage s = case s of
+                             ISetup -> False
+                             ISafe  -> True
+                             IRun   -> False
+
+-- | Are we in setup?
+isSetupIStage :: IStage -> Bool
+isSetupIStage s = case s of
+                   ISetup -> True
+                   ISafe  -> False
+                   IRun   -> True
+
+-- | Are we in a run?
+isRunIStage :: IStage -> Bool
+isRunIStage s = case s of
+                  ISetup -> False
+                  ISafe  -> False
+                  IRun   -> True
+
+-- | Different means of running a symbolic piece of code
+data SBVRunMode = SMTMode QueryContext IStage Bool SMTConfig   -- ^ In regular mode, with a stage. Bool is True if this is SAT.
+                | CodeGen                                      -- ^ Code generation mode.
+                | LambdaGen (Maybe Int)                        -- ^ Inside a lambda-expression at level. If Nothing, then closed lambda.
+                | Concrete (Maybe (Bool, [(NamedSymVar, 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 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 LambdaGen{}                  = "Lambda 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
+isCodeGenMode State{runMode} = do rm <- readIORef runMode
+                                  pure $ case rm of
+                                           Concrete{}  -> False
+                                           SMTMode{}   -> False
+                                           LambdaGen{} -> False
+                                           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
+                         , 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
+        tm    <- newIORef Map.empty
+        ui    <- newIORef Map.empty
+        pgm   <- newIORef (SBVPgm S.empty)
+        cstrs <- newIORef S.empty
+        pure IncState { rNewInps        = is
+                      , rNewKinds       = ks
+                      , rNewConsts      = nc
+                      , rNewTbls        = tm
+                      , rNewUIs         = ui
+                      , rNewAsgns       = pgm
+                      , rNewConstraints = cstrs
+                      }
+
+-- | Get a new IncState
+withNewIncState :: State -> (State -> IO a) -> IO (IncState, a)
+withNewIncState st cont = do
+        is <- newIncState
+        R.modifyIORef' (rIncState st) (const is)
+        r  <- cont st
+        finalIncState <- readIORef (rIncState st)
+        pure (finalIncState, r)
+
+-- | User defined inputs
+type UserInputs = S.Seq NamedSymVar
+
+-- | Internally declared
+type InternInps = S.Seq NamedSymVar
+
+-- | Entire set of names, for faster lookup
+type AllInps = Set.Set Name
+
+-- | Inputs as a record of maps and sets. See above type-synonyms for their roles.
+data Inputs = Inputs { userInputs   :: !UserInputs
+                     , internInputs :: !InternInps
+                     , allInputs    :: !AllInps
+                     } deriving (Eq,Show)
+
+-- | Inputs to a lambda-abstraction. These are quantified to handle constraints
+type LambdaInputs = S.Seq (Quantifier, NamedSymVar)
+
+-- | Semigroup instance; combining according to indexes.
+instance Semigroup Inputs where
+  (Inputs lui lii lai) <> (Inputs rui rii rai) = Inputs (lui <> rui) (lii <> rii) (lai <> rai)
+
+-- | Monoid instance, we start with no maps.
+instance Monoid Inputs where
+  mempty = Inputs { userInputs   = mempty
+                  , internInputs = mempty
+                  , allInputs    = mempty
+                  }
+
+-- | Modify the user-inputs field
+onUserInputs :: (UserInputs -> UserInputs) -> Inputs -> Inputs
+onUserInputs f inp@Inputs{userInputs} = inp{userInputs = f userInputs}
+
+-- | Modify the internal-inputs field
+onInternInputs :: (InternInps -> InternInps) -> Inputs -> Inputs
+onInternInputs f inp@Inputs{internInputs} = inp{internInputs = f internInputs}
+
+-- | Modify the all-inputs field
+onAllInputs :: (AllInps -> AllInps) -> Inputs -> Inputs
+onAllInputs f inp@Inputs{allInputs} = inp{allInputs = f allInputs}
+
+-- | Add a new internal input
+addInternInput :: SV -> Name -> Inputs -> Inputs
+addInternInput sv nm = goAll . goIntern
+  where !new = toNamedSV sv nm
+        goIntern = onInternInputs (S.|> new)
+        goAll    = onAllInputs    (Set.insert nm)
+
+-- | Add a new user input
+addUserInput :: SV -> Name -> Inputs -> Inputs
+addUserInput sv nm = goAll . goUser
+  where !new   = toNamedSV sv nm
+        goUser = onUserInputs (S.|> new)        -- add to the end of the sequence
+        goAll  = onAllInputs  (Set.insert nm)
+
+-- | Find a user-input from its SV. Note that only level-0 vars
+-- can be found this way.
+lookupInput :: (a -> SV) -> SV -> S.Seq a -> Maybe a
+lookupInput f sv ns
+   | l == Just 0 = res
+   | True        = Nothing  -- l != Just 0, a lambda var, whether top-level or in a scope, so we ignore
+  where
+    (_, l, i) = getId (swNodeId sv)
+    svs       = f <$> ns
+    res       = case S.lookup i ns of -- Nothing on negative Int or Int > length seq
+                  Nothing    -> secondLookup
+                  x@(Just e) -> if sv == f e then x else secondLookup
+                    -- we try the fast lookup first, if the node ids don't match then
+                    -- we use the more expensive O (n) to find the index and the elem
+    secondLookup = S.elemIndexL sv svs >>= flip S.lookup ns
+
+-- | A defined function/value
+data SMTDef = SMTDef Kind             -- ^ Final kind of the definition (resulting kind, not the params)
+                     [String]         -- ^ other definitions it refers to
+                     (Maybe Text)     -- ^ parameter string
+                     (Int -> Text)    -- ^ Body, in SMTLib syntax, given the tab amount
+            deriving G.Data
+
+-- | For debug purposes
+instance Show SMTDef where
+  show (SMTDef fk frees p body) = unlines [ "-- User defined function:"
+                                                      , "-- Final return type    : " ++ show fk
+                                                      , "-- Refers to            : " ++ intercalate ", " frees
+                                                      , "-- Parameters           : " ++ maybe "NONE" T.unpack p
+                                                      , "-- Body                 : "
+                                                      , T.unpack (body 2)
+                                                      ]
+
+-- | NFData instance for SMTDef
+instance NFData SMTDef where
+  rnf (SMTDef fk frees params body) = rnf fk `seq` rnf frees `seq` rnf params `seq` rnf body
+
+-- | Compare two SMTDef values for semantic equality.
+-- The body is @(Int -> Text)@ where @Int@ is indentation; we compare rendered output at indent 0.
+smtDefEq :: SMTDef -> SMTDef -> Bool
+smtDefEq (SMTDef k1 refs1 params1 body1) (SMTDef k2 refs2 params2 body2)
+  = k1 == k2 && refs1 == refs2 && params1 == params2 && body1 0 == body2 0
+
+-- | Error for conflicting smtFunction definitions with the same name.
+conflictError :: String -> a
+conflictError nm = error $ unlines [ ""
+                                   , "*** Data.SBV: Function '" ++ nm ++ "' defined with conflicting bodies."
+                                   , "***"
+                                   , "*** Two calls to smtFunction (or related) used the name '" ++ nm ++ "'"
+                                   , "*** but with different definitions. This would generate conflicting"
+                                   , "*** SMTLib define-fun-rec declarations."
+                                   , "***"
+                                   , "*** Please use a unique name for each distinct function."
+                                   ]
+
+-- | Information about a compiled lambda body, used for measure verification.
+data LambdaInfo = LambdaInfo
+  { liAssignments :: S.Seq (SV, SBVExpr)  -- ^ The expression DAG
+  , liParams      :: [(Quantifier, SV)]    -- ^ Formal parameters with quantifier
+  , liOutput      :: SV                    -- ^ The output node
+  , liConsts      :: [(SV, CV)]            -- ^ Constants used
+  }
+
+-- | The state of the symbolic interpreter
+data State  = State { sbvContext            :: SBVContext
+                    , pathCond              :: SVal                             -- ^ kind KBool
+                    , stCfg                 :: SMTConfig
+                    , startTime             :: UTCTime
+                    , rProgInfo             :: IORef ProgInfo
+                    , runMode               :: IORef SBVRunMode
+                    , rIncState             :: IORef IncState
+                    , rCInfo                :: IORef [(String, CV)]
+                    , rObservables          :: IORef (S.Seq (Name, CV -> Bool, SV))
+                    , rctr                  :: IORef Int             -- Used for numbering SVs
+                    , freshNameCtr          :: IORef Int             -- Used for calls to some
+                    , rLambdaLevel          :: IORef (Maybe Int)     -- If Nothing, then top-level lambda
+                    , rUsedKinds            :: IORef KindSet
+                    , rUsedLbls             :: IORef (Set.Set String)
+                    , rinps                 :: IORef Inputs
+                    , rlambdaInps           :: IORef LambdaInputs
+                    , rConstraints          :: IORef (S.Seq (Bool, [(String, String)], SV))
+                    , rPartitionVars        :: IORef [String]
+                    , routs                 :: IORef [SV]
+                    , rtblMap               :: IORef TableMap
+                    , spgm                  :: IORef SBVPgm
+                    , rconstMap             :: IORef CnstMap
+                    , rexprMap              :: IORef ExprMap
+                    , rUIMap                :: IORef UIMap
+                    , rUserFuncs            :: IORef (Map.Map String (Set.Set Int, Maybe Int)) -- Functions with explicit code generation; maps name to (verified StableName hashes, lambda level at first compilation)
+                    , rCompilingFuncs       :: IORef (Set.Set String)     -- Functions currently being compiled (used to detect recursive self-calls vs. genuine conflicts)
+                    , rCgMap                :: IORef CgMap
+                    , rDefns                :: IORef (Map.Map String (SMTDef, SBVType))
+                    , rMeasureChecks        :: IORef [(String, Bool, SMTConfig -> IO ())]  -- Measure checks for recursive functions. Bool is True for productive (guarded), False for terminating.
+                    , rFuncLambdaInfos      :: IORef (Map.Map String LambdaInfo)            -- LambdaInfo for all smtFunction definitions, used for mutual recursion checking
+                    , rSkipMeasureChecks    :: IORef Bool                                   -- If True, skip measure checking (used by TP and checker itself)
+                    , rNoTermCheckFunctions :: IORef (Set.Set String)                      -- Functions defined with smtFunctionNoTermination (no termination check)
+                    , rSMTOptions           :: IORef [SMTOption]
+                    , rOptGoals             :: IORef [Objective (SV, SV)]
+                    , rAsserts              :: IORef [(String, Maybe CallStack, SV)]
+                    , rOutstandingAsserts   :: IORef Bool            -- Did we send an assert after the last check-sat call?
+                    , rSVCache              :: IORef (Cache SV)
+                    , rQueryState           :: IORef (Maybe QueryState)
+                    , parentState           :: Maybe State  -- Pointer to our parent if we're in a sublevel
+                    }
+
+-- | Chase to the root state. No infinite chains!
+getRootState :: State -> State
+getRootState st = maybe st getRootState (parentState st)
+
+-- NFData is a bit of a lie, but it's sufficient, most of the content is iorefs that we don't want to touch
+instance NFData State where
+   rnf State{} = ()
+
+-- | Get the current path condition
+getSValPathCondition :: State -> SVal
+getSValPathCondition = pathCond
+
+-- | Extend the path condition with the given test value.
+extendSValPathCondition :: State -> (SVal -> SVal) -> State
+extendSValPathCondition st f = st{pathCond = f (pathCond st)}
+
+-- | Are we running in proof mode?
+inSMTMode :: State -> IO Bool
+inSMTMode State{runMode} = do rm <- readIORef runMode
+                              pure $ case rm of
+                                       CodeGen     -> False
+                                       LambdaGen{} -> False
+                                       Concrete{}  -> False
+                                       SMTMode{}   -> True
+
+-- | The "Symbolic" value. Either a constant (@Left@) or a symbolic
+-- value (@Right Cached@). Note that caching is essential for making
+-- sure sharing is preserved.
+data SVal = SVal !Kind !(Either CV (Cached SV))
+
+-- | Kind instance for SVal simply passes the kind out
+instance HasKind SVal where
+  kindOf (SVal k _) = k
+
+-- Show instance for t'SVal'. Not particularly "desirable", but will do if needed
+-- NB. We do not show the type info on constant KBool values, since there's no
+-- implicit "fromBoolean" applied to Booleans in Haskell; and thus a statement
+-- of the form "True :: SBool" is just meaningless. (There should be a fromBoolean!)
+instance Show SVal where
+  show (SVal KBool (Left c))  = showCV False c
+  show (SVal k     (Left c))  = showCV False c ++ " :: " ++ show k
+  show (SVal k     (Right _)) =         "<symbolic> :: " ++ show k
+
+-- | Things we do not support in interactive mode, at least for now!
+noInteractive :: [String] -> a
+noInteractive ss = error $ unlines $  ""
+                                   :  "*** Data.SBV: Unsupported interactive/query mode feature."
+                                   :  map ("***  " ++) ss
+                                   ++ ["*** Data.SBV: Please report this as a feature request!"]
+
+-- | Things we do not support in interactive mode, nor we ever intend to
+noInteractiveEver :: [String] -> a
+noInteractiveEver ss = error $ unlines $  ""
+                                       :  "*** Data.SBV: Unsupported interactive/query mode feature."
+                                       :  map ("***  " ++) ss
+
+-- | Modification of the state, but carefully handling the interactive tasks.
+-- Note that the state is always updated regardless of the mode, but we get
+-- to also perform extra operation in interactive mode. (Typically error out, but also simply
+-- ignore if it has no impact.)
+modifyState :: State -> (State -> IORef a) -> (a -> a) -> IO () -> IO ()
+modifyState st@State{runMode} field update interactiveUpdate = do
+        R.modifyIORef' (field st) update
+        rm <- readIORef runMode
+        case rm of
+          SMTMode _ IRun _ _ -> interactiveUpdate
+          _                  -> pure ()
+
+-- | Modify the incremental state
+modifyIncState  :: State -> (IncState -> IORef a) -> (a -> a) -> IO ()
+modifyIncState State{rIncState} field update = do
+        incState <- readIORef rIncState
+        R.modifyIORef' (field incState) update
+
+-- | Add an observable
+recordObservable :: State -> Text -> (CV -> Bool) -> SV -> IO ()
+recordObservable st nm chk sv = modifyState st rObservables (S.|> (nm, chk, sv)) (pure ())
+
+-- | Increment the variable counter
+incrementInternalCounter :: State -> IO Int
+incrementInternalCounter st = do ctr <- readIORef (rctr st)
+                                 modifyState st rctr (+1) (pure ())
+                                 pure ctr
+{-# INLINE incrementInternalCounter #-}
+
+-- | Increment the fresh-var counter
+incrementFreshNameCounter :: State -> IO Int
+incrementFreshNameCounter st = do ctr <- readIORef (freshNameCtr st)
+                                  modifyState st freshNameCtr (+1) (pure ())
+                                  pure ctr
+{-# INLINE incrementFreshNameCounter #-}
+
+-- | Kind of code we have for uninterpretation
+data UICodeKind = UINone Bool     -- no code. If bool is true, then curried.
+                | UISMT  SMTDef   -- SMTLib, first argument are the free-variables in it
+                | UICgC  [String] -- Code-gen, currently only C
+
+-- | A newtype wrapper for uninterpreted function names. We distinguish between user names and those of constructors
+data UIName = UIGiven String -- ^ Full name
+            | UIADT   ADTOp  -- ^ The name of an ADT operation based on the constructor
+
+-- | Uninterpreted constants and functions. An uninterpreted constant is
+-- a value that is indexed by its name. The only property the prover assumes
+-- about these values are that they are equivalent to themselves; i.e., (for
+-- functions) they return the same results when applied to same arguments.
+-- We support uninterpreted-functions as a general means of black-box'ing
+-- operations that are /irrelevant/ for the purposes of the proof; i.e., when
+-- the proofs can be performed without any knowledge about the function itself.
+svUninterpreted :: Kind -> UIName -> UICodeKind -> [SVal] -> SVal
+svUninterpreted k nm code args = svUninterpretedGen k nm code args Nothing
+
+svUninterpretedNamedArgs :: Kind -> UIName -> UICodeKind -> [(SVal, String)] -> SVal
+svUninterpretedNamedArgs k nm code args = svUninterpretedGen k nm code (map fst args) (Just (map snd args))
+
+svUninterpretedGen :: Kind -> UIName -> UICodeKind -> [SVal] -> Maybe [String] -> SVal
+svUninterpretedGen k nm code args mbArgNames = SVal k $ Right $ cache result
+  where result st = do let ty = SBVType (map kindOf args ++ [k])
+                       op <- newUninterpreted st nm mbArgNames ty code
+                       sws <- mapM (svToSV st) args
+                       mapM_ forceSVArg sws
+                       newExpr st k $ SBVApp op sws
+
+-- | Create a new value, possibly with user given code. This function might change
+-- the name given, putting bars around it if needed. That's the name returned.
+newUninterpreted :: State -> UIName -> Maybe [String] -> SBVType -> UICodeKind -> IO Op
+newUninterpreted st uiName mbArgNames t uiCode = do
+
+  let (adtOp, candName) = case uiName of
+                            UIGiven n -> (False, n)
+                            UIADT   o -> case o of
+                                           ADTConstructor n _ -> (True, T.unpack n)
+                                           ADTTester      n _ -> (True, T.unpack n)
+                                           ADTAccessor    n _ -> (True, T.unpack n)
+
+  -- determine the final name. We leave constructors alone.
+  let nm = case () of
+             () | "__internal_sbv_" `isPrefixOf` candName -> candName        -- internal names go thru
+                | adtOp                                   -> candName        -- ADT names go thru
+                | True                                    -> barify candName -- surround with bars if not legitimate in SMTLib
+
+      extraComment = case uiName of
+                      UIGiven  n | nm /= n -> " (Given: " ++ n ++ ")"
+                      _                    -> ""
+
+  -- Check if reserved:
+  when (isReserved nm) $
+      error $ unlines [ ""
+                      , "*** Data.SBV: User given name " ++ show nm ++ " is a reserved name in SMTLib."
+                      , "***"
+                      , "*** Please use a different name to avoid collisions."
+                      ]
+
+  isCurried <- case uiCode of
+                 UINone c -> pure c
+                 UISMT d  -> do -- Check for conflicting definitions with the same name
+                                defs <- readIORef (rDefns st)
+                                case Map.lookup nm defs of
+                                  Just (oldDef, _)
+                                    | not (smtDefEq d oldDef)
+                                    -> conflictError nm
+                                  _ -> pure ()
+                                modifyState st rDefns (Map.insert nm (d, t))
+                                  $ noInteractive [ "Defined functions (smtFunction):"
+                                                  , "  Name: " ++ nm ++ extraComment
+                                                  , "  Type: " ++ show t
+                                                  , ""
+                                                  , "You should explicitly register these functions by calling"
+                                                  , "the function 'registerFunction' on them before starting the query section."
+                                                  ]
+                                pure True
+                 UICgC c  -> -- No need to record the code in interactive mode: CodeGen doesn't use interactive
+                             do modifyState st rCgMap (Map.insert nm c) (pure ())
+                                pure True
+
+  let checkType :: SBVType -> r -> r
+      checkType t' cont
+        | t /= t' = error $  "Uninterpreted constant " ++ show nm ++ extraComment ++ " used at incompatible types\n"
+                          ++ "      Current type      : " ++ show t ++ "\n"
+                          ++ "      Previously used at: " ++ show t'
+        | True    = cont
+
+  -- If we're not a constructor, register it:
+  unless adtOp $ do
+    uiMap <- readIORef (rUIMap st)
+    case nm `Map.lookup` uiMap of
+      Just (_, _, t') -> checkType t' (pure ())
+      Nothing         -> modifyState st rUIMap (Map.insert nm (isCurried, mbArgNames, t))
+                           $ modifyIncState st rNewUIs
+                                              (\newUIs -> case nm `Map.lookup` newUIs of
+                                                            Just (_, _, t') -> checkType t' newUIs
+                                                            Nothing         -> Map.insert nm (isCurried, mbArgNames, t) newUIs)
+
+  pure $ let tnm = T.pack nm
+         in case uiName of
+              UIGiven{}                  -> Uninterpreted tnm
+              UIADT (ADTConstructor _ k) -> ADTOp (ADTConstructor tnm k)
+              UIADT (ADTTester      _ k) -> ADTOp (ADTTester      tnm k)
+              UIADT (ADTAccessor    _ k) -> ADTOp (ADTAccessor    tnm k)
+
+-- | Add a new sAssert based constraint
+addAssertion :: State -> Maybe CallStack -> String -> SV -> IO ()
+addAssertion st cs msg cond = modifyState st rAsserts ((msg, cs, cond):)
+                                        $ noInteractive [ "Named assertions (sAssert):"
+                                                        , "  Tag: " ++ msg
+                                                        , "  Loc: " ++ maybe "Unknown" show cs
+                                                        ]
+
+-- | Create an internal variable, which acts as an input but isn't visible to the user.
+-- Such variables are existentially quantified in a SAT context, and universally quantified
+-- in a proof context.
+newInternalVariable :: State -> Kind -> IO SV
+newInternalVariable st k = do NamedSymVar sv nm <- newSV st k
+                              let n = "__internal_sbv_" <> nm
+                                  v = NamedSymVar sv n
+                              modifyState st rinps (addUserInput sv n) $ modifyIncState st rNewInps (v :)
+                              pure sv
+{-# INLINE newInternalVariable #-}
+
+-- | Create a variable to be used in a constraint-expression
+quantVar :: Quantifier -> State -> Kind -> IO SV
+quantVar q st k = do v@(NamedSymVar sv _) <- newSV st k
+                     modifyState st rlambdaInps (S.|> (q, v)) (pure ())
+                     pure sv
+{-# INLINE quantVar #-}
+
+-- | Create a variable to be used in a lambda-expression
+lambdaVar :: State -> Kind -> IO SV
+lambdaVar = quantVar ALL
+{-# INLINE lambdaVar #-}
+
+-- | Create a new SV
+newSV :: State -> Kind -> IO NamedSymVar
+newSV st k = do ctr <- incrementInternalCounter st
+                ll  <- readIORef (rLambdaLevel st)
+                let sv = SV k (NodeId (sbvContext st, ll, ctr))
+                registerKind st k
+                pure $ NamedSymVar sv $ showText sv
+{-# INLINE newSV #-}
+
+-- | Register a new kind with the system, used for uninterpreted sorts.
+-- NB: Is it safe to have new kinds in query mode? It could be that
+-- the new kind might introduce a constraint that effects the logic. For
+-- instance, if we're seeing 'Double' for the first time and using a BV
+-- logic, then things would fall apart. But this should be rare, and hopefully
+-- the success-response checking mechanism will catch the rare cases where this
+-- is an issue. In either case, the user can always arrange for the right
+-- logic by calling 'Data.SBV.setLogic' appropriately, so it seems safe to just
+-- allow for this.
+registerKind :: State -> Kind -> IO ()
+registerKind st k
+  | KADT sortName _ _ <- k, isReserved sortName
+  = error $ "SBV: " ++ show sortName ++ " is a reserved sort; please use a different name."
+  | True
+  = 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)
+
+       -- For ADTs we need to make sure we haven't added it before
+       let adtNameExists s = any (\case KADT s' _ _ -> s == s'; _ -> False) existingKinds
+
+           adtExists = case k of
+                         KADT s _ _  -> adtNameExists s
+                         _           -> False
+
+       unless adtExists $
+          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
+                                  KADT s _ _  -> not (adtNameExists s)
+                                  KList{}     -> k `Set.notMember` existingKinds
+                                  KTuple nks  -> not $ any (\case KTuple oks -> length nks == length oks; _ -> False) existingKinds
+                                  _           -> False
+
+              when needsAdding $ modifyIncState st rNewKinds (Set.insert k)
+
+       -- Don't forget to register subkinds!
+       case k of
+         KVar      {}    -> pure ()
+         KBool     {}    -> pure ()
+         KBounded  {}    -> pure ()
+         KUnbounded{}    -> pure ()
+         KReal     {}    -> pure ()
+         KFloat    {}    -> pure ()
+         KDouble   {}    -> pure ()
+         KFP       {}    -> pure ()
+         KRational {}    -> pure ()
+         KChar     {}    -> pure ()
+         KString   {}    -> pure ()
+
+         KApp _ ks       -> mapM_ (registerKind st) ks
+         KADT _ pks cks  -> mapM_ (registerKind st) (map snd pks ++ concatMap snd cks)
+         KList     ek    -> registerKind st ek
+         KSet      ek    -> registerKind st ek
+         KTuple    eks   -> mapM_ (registerKind st) eks
+         KArray    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 ()
+registerLabel whence st nm
+  | isReserved nm
+  = err "is a reserved string; please use a different name."
+  | '|' `elem` nm
+  = err "contains the character `|', which is not allowed!"
+  | '\\' `elem` nm
+  = err "contains the character `\\', which is not allowed!"
+  | True
+  = do old <- readIORef $ rUsedLbls st
+       if nm `Set.member` old
+          then err "is used multiple times. Please do not use duplicate names!"
+          else modifyState st rUsedLbls (Set.insert nm) (pure ())
+
+  where err w = error $ "SBV (" ++ whence ++ "): " ++ show nm ++ " " ++ w
+
+-- | Create a new constant; hash-cons as necessary
+newConst :: State -> CV -> IO SV
+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 -> pure sv
+    Nothing -> do (NamedSymVar sv _) <- newSV st (kindOf c)
+                  let ins = Map.insert c sv
+                  modifyState st rconstMap ins $ modifyIncState st rNewConsts ins
+                  pure sv
+{-# INLINE newConst #-}
+
+-- | Create a new table; hash-cons as necessary
+getTableIndex :: State -> Kind -> Kind -> [SV] -> IO Int
+getTableIndex st at rt elts = do
+  let key = (at, rt, elts)
+  tblMap <- readIORef (rtblMap st)
+  case key `Map.lookup` tblMap of
+    Just i -> pure i
+    _      -> do let i   = Map.size tblMap
+                     upd = Map.insert key i
+                 modifyState st rtblMap upd $ modifyIncState st rNewTbls upd
+                 pure i
+
+-- | Create a new expression; hash-cons as necessary
+newExpr :: State -> Kind -> SBVExpr -> IO SV
+newExpr st k app = do
+   let e = reorder app
+   exprMap <- readIORef (rexprMap st)
+   case e `Map.lookup` exprMap of
+     -- 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 -> pure sv
+     _                        -> do (NamedSymVar sv _) <- newSV st k
+                                    checkConsistent sv e
+                                    let append (SBVPgm xs) = SBVPgm (xs S.|> (sv, e))
+                                    modifyState st spgm append $ modifyIncState st rNewAsgns append
+                                    modifyState st rexprMap (Map.insert e sv) (pure ())
+                                    pure sv
+{-# INLINE newExpr #-}
+
+-- | In rare cases, we can get a context mismatch; so make sure the expression is well-formed.
+-- This isn't a full solution, but handles the common case (hopefully!)
+checkConsistent :: SV -> SBVExpr -> IO ()
+checkConsistent lhs (SBVApp _ args) = mapM_ check args
+   where SV _ (NodeId (lhsContext, _, _)) = lhs
+         check (SV _ (NodeId (rhsContext, _, _)))
+           | lhsContext `compatibleContext` rhsContext
+           = pure ()
+           | True
+           = contextMismatchError lhsContext rhsContext
+{-# INLINE checkConsistent #-}
+
+-- | Are these compatible contexts? Either the same, or one of them is global
+compatibleContext :: SBVContext -> SBVContext -> Bool
+compatibleContext c1 c2 = c1 == c2 || c1 == globalSBVContext || c2 == globalSBVContext
+{-# INLINE compatibleContext #-}
+
+-- | Convert a symbolic value to an internal SV
+svToSV :: State -> SVal -> IO SV
+svToSV st (SVal _ (Left c))  = newConst st c
+svToSV st (SVal _ (Right f)) = uncache f st
+
+-- | Generalization of 'Data.SBV.svToSymSV'
+svToSymSV :: MonadSymbolic m => SVal -> m SV
+svToSymSV sbv = do st <- symbolicEnv
+                   liftIO $ svToSV st sbv
+
+-------------------------------------------------------------------------
+-- * Symbolic Computations
+-------------------------------------------------------------------------
+-- | A Symbolic computation. Represented by a reader monad carrying the
+-- state of the computation, layered on top of IO for creating unique
+-- references to hold onto intermediate results.
+
+-- | Computations which support symbolic operations
+class MonadIO m => MonadSymbolic m where
+  symbolicEnv :: m State
+
+  default symbolicEnv :: (MonadTrans t, MonadSymbolic m', m ~ t m') => m State
+  symbolicEnv = lift symbolicEnv
+
+instance MonadSymbolic m             => MonadSymbolic (ExceptT e m)
+instance MonadSymbolic m             => MonadSymbolic (MaybeT m)
+instance MonadSymbolic m             => MonadSymbolic (ReaderT r m)
+instance MonadSymbolic m             => MonadSymbolic (SS.StateT s m)
+instance MonadSymbolic m             => MonadSymbolic (LS.StateT s m)
+instance (MonadSymbolic m, Monoid w) => MonadSymbolic (SW.WriterT w m)
+instance (MonadSymbolic m, Monoid w) => MonadSymbolic (LW.WriterT w m)
+
+-- | A generalization of 'Data.SBV.Symbolic'.
+newtype SymbolicT m a = SymbolicT { runSymbolicT :: ReaderT State m a }
+                   deriving newtype ( Applicative, Functor, Monad, MonadIO, MonadTrans
+                            , MonadError e, MonadState s, MonadWriter w
+                            , MonadFail
+                            )
+
+-- | `MonadSymbolic` instance for `SymbolicT m`
+instance MonadIO m => MonadSymbolic (SymbolicT m) where
+  symbolicEnv = SymbolicT ask
+
+-- | Map a computation over the symbolic transformer.
+mapSymbolicT :: (ReaderT State m a -> ReaderT State n b) -> SymbolicT m a -> SymbolicT n b
+mapSymbolicT f = SymbolicT . f . runSymbolicT
+{-# INLINE mapSymbolicT #-}
+
+-- Have to define this one by hand, because we use ReaderT in the implementation
+instance MonadReader r m => MonadReader r (SymbolicT m) where
+  ask = lift ask
+  local f = mapSymbolicT $ mapReaderT $ local f
+
+-- | 'Symbolic' is specialization of t'SymbolicT' to the `IO` monad. Unless you are using
+-- transformers explicitly, this is the type you should prefer.
+type Symbolic = SymbolicT IO
+
+-- | Create a symbolic value, based on the quantifier we have. If an
+-- explicit quantifier is given, we just use that. If not, then we
+-- pick the quantifier appropriately based on the run-mode.
+-- @randomCV@ is used for generating random values for this variable
+-- when used for @quickCheck@ or 'Data.SBV.Tools.GenTest.genTest' purposes.
+svMkSymVar :: VarContext -> Kind -> Maybe String -> State -> IO SVal
+svMkSymVar = svMkSymVarGen False
+
+-- | Create an existentially quantified tracker variable
+svMkTrackerVar :: Kind -> String -> State -> IO SVal
+svMkTrackerVar k nm = svMkSymVarGen True (NonQueryVar (Just EX)) k (Just nm)
+
+-- | Generalization of 'Data.SBV.sWordN'
+sWordN :: MonadSymbolic m => Int -> String -> m SVal
+sWordN w nm = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar Nothing) (KBounded False w) (Just nm)
+
+-- | Generalization of 'Data.SBV.sWordN_'
+sWordN_ :: MonadSymbolic m => Int -> m SVal
+sWordN_ w = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar Nothing) (KBounded False w) Nothing
+
+-- | Generalization of 'Data.SBV.sIntN'
+sIntN :: MonadSymbolic m => Int -> String -> m SVal
+sIntN w nm = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar Nothing) (KBounded True w) (Just nm)
+
+-- | Generalization of 'Data.SBV.sIntN_'
+sIntN_ :: MonadSymbolic m => Int -> m SVal
+sIntN_ w = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar Nothing) (KBounded True w) Nothing
+
+-- | Create a symbolic value, based on the quantifier we have. If an
+-- explicit quantifier is given, we just use that. If not, then we
+-- pick the quantifier appropriately based on the run-mode.
+-- @randomCV@ is used for generating random values for this variable
+-- when used for @quickCheck@ or 'Data.SBV.Tools.GenTest.genTest' purposes.
+svMkSymVarGen :: Bool -> VarContext -> Kind -> Maybe String -> State -> IO SVal
+svMkSymVarGen isTracker varContext k mbNm st = do
+        registerKind st k
+
+        rm <- readIORef (runMode st)
+
+        let varInfo = case mbNm of
+                        Nothing -> "While defining a variable of type " ++ show k
+                        Just nm -> "While defining: " ++ nm ++ " :: " ++ show k
+
+            disallow what  = error $ unlines [ "*** Data.SBV: Unsupported: " ++ what
+                                             , "***"
+                                             , "*** " ++ varInfo
+                                             , "*** "
+                                             , "*** In mode: " ++ show rm
+                                             ]
+
+            (isQueryVar, mbQ) = case varContext of
+                                  NonQueryVar mq -> (False, mq)
+                                  QueryVar       -> (True,  Just EX)
+
+            mkS q = do (NamedSymVar sv internalName) <- newSV st k
+                       let nm = maybe internalName T.pack mbNm
+                       introduceUserName st (isQueryVar, isTracker) nm k q sv
+
+            mkC cv = do modifyState st rCInfo ((fromMaybe "_" mbNm, cv):) (pure ())
+                        pure $ SVal k (Left cv)
+
+        case (mbQ, rm) of
+          (Just q,  SMTMode{}          ) -> mkS q
+          (Nothing, SMTMode _ _ isSAT _) -> mkS (if isSAT then EX else ALL)
+
+          (Just EX, CodeGen{})           -> disallow "Existentially quantified variables"
+          (_      , CodeGen)             -> mkS ALL  -- code generation, pick universal
+
+          (Just EX, Concrete Nothing)    -> disallow "Existentially quantified variables"
+          (_      , Concrete Nothing)    -> randomCV k >>= mkC
+
+          (Just EX, LambdaGen{})         -> disallow "Existentially quantified variables"
+          (_,       LambdaGen{})         -> mkS ALL
+
+          -- Model validation:
+          (_      , Concrete (Just (_isSat, env))) -> do
+                        let bad why conc = error $ unlines [ ""
+                                                           , "*** Data.SBV: " ++ why
+                                                           , "***"
+                                                           , "***   To turn validation off, use `cfg{validateModel = False}`"
+                                                           , "***"
+                                                           , "*** " ++ conc
+                                                           ]
+
+                            report = "Please report this as a bug in SBV!"
+
+                        (NamedSymVar sv internalName) <- newSV st k
+
+                        let nm = maybe internalName T.pack mbNm
+                            nsv = NamedSymVar sv nm
+
+                            -- Ignore the context equivalence check here. When validating, we are in a different
+                            -- context; so they won't match
+                            same (NamedSymVar (SV _ (NodeId (_, ll1, li1))) _)
+                                 (NamedSymVar (SV _ (NodeId (_, ll2, li2))) _) = (ll1, li1) == (ll2, li2)
+
+                            cv = case [v | (nsv', v) <- env, nsv `same` nsv'] of
+                                   []    -> if isTracker
+                                            then  -- The sole purpose of a tracker variable is to send the optimization
+                                                  -- directive to the solver, so we can name "expressions" that are minimized
+                                                  -- or maximized. There will be no constraints on these when we are doing
+                                                  -- the validation; in fact they will not even be used anywhere during a
+                                                  -- validation run. So, simply push a zero value that inhabits all metrics.
+                                                  mkConstCV k (0::Integer)
+                                            else bad ("Cannot locate variable: " ++ show (nsv, k)) report
+                                   [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, Bool) -> Text -> Kind -> Quantifier -> SV -> IO SVal
+introduceUserName st@State{runMode} (isQueryVar, isTracker) nmOrig k q sv = do
+        old <- allInputs <$> readIORef (rinps st)
+
+        let nm  = mkUnique nmOrig old
+
+        -- If this is not a query variable and we're in a query, reject it.
+        -- See https://github.com/LeventErkok/sbv/issues/554 for the rationale.
+        -- In theory, it should be possible to support this, but fixing it is
+        -- rather costly as we'd have to track the regular updates and sync the
+        -- incremental state appropriately. Instead, we issue an error message
+        -- and ask the user to obey the query mode rules.
+        rm <- readIORef runMode
+        case rm of
+          SMTMode _ IRun _ _ | not isQueryVar -> noInteractiveEver [ "Adding a new input variable in query mode: " ++ show nm
+                                                                   , ""
+                                                                   , "Hint: Use freshVar/freshVar_ for introducing new inputs in query mode."
+                                                                   ]
+          _                                   -> pure ()
+
+        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  -> toNamedSV 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 (addInternInput sv nm)
+                                     $ noInteractive ["Adding a new tracker variable in interactive mode: " ++ show nm]
+                      else modifyState st rinps (addUserInput sv nm)
+                                     $ modifyIncState st rNewInps newInp
+                   pure $ SVal k $ Right $ cache (const (pure 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 :: T.Text -> Set.Set Name -> T.Text
+         mkUnique prefix names = case dropWhile (`Set.member` names) (prefix : [prefix <> "_" <> showText i | i <- [(0::Int)..]]) of
+                                   h:_ -> h
+                                   _   -> error $ "mkUnique: Impossible happened! Couldn't get a unique name for " ++ show (prefix, names)
+
+-- | Create a new state
+mkNewState :: MonadIO m => SMTConfig -> SBVRunMode -> m State
+mkNewState cfg currentRunMode = liftIO $ do
+     currTime           <- getCurrentTime
+     progInfo           <- newIORef ProgInfo { hasQuants         = False
+                                             , progSpecialRels   = []
+                                             , progTransClosures = []
+                                             }
+     rm                 <- newIORef currentRunMode
+     ctr                <- newIORef (-2) -- start from -2; False and True will always occupy the first two elements
+     fnctr              <- newIORef 0
+     lambda             <- newIORef $ case currentRunMode of
+                                        SMTMode{}     -> Just 0
+                                        CodeGen{}     -> Just 0
+                                        Concrete{}    -> Just 0
+                                        LambdaGen mbi -> mbi
+     cInfo              <- newIORef []
+     observes           <- newIORef mempty
+     pgm                <- newIORef (SBVPgm S.empty)
+     emap               <- newIORef Map.empty
+     cmap               <- newIORef Map.empty
+     inps               <- newIORef mempty
+     lambdaInps         <- newIORef mempty
+     outs               <- newIORef []
+     tables             <- newIORef Map.empty
+     userFuncs          <- newIORef Map.empty
+     compilingFuncs     <- newIORef Set.empty
+     uis                <- newIORef Map.empty
+     cgs                <- newIORef Map.empty
+     defns              <- newIORef Map.empty
+     measureChecks      <- newIORef []
+     funcLambdaInfos    <- newIORef Map.empty
+     skipMeasureChecks  <- newIORef False
+     noTermCheckFuncs   <- newIORef Set.empty
+     swCache            <- newIORef IMap.empty
+     usedKinds          <- newIORef Set.empty
+     usedLbls           <- newIORef Set.empty
+     cstrs              <- newIORef S.empty
+     pvs                <- newIORef []
+     smtOpts            <- newIORef []
+     optGoals           <- newIORef []
+     asserts            <- newIORef []
+     outstandingAsserts <- newIORef False
+     istate             <- newIORef =<< newIncState
+     qstate             <- newIORef Nothing
+     ctx                <- genSBVContext
+     pure $ State { sbvContext            = ctx
+                  , runMode               = rm
+                  , stCfg                 = cfg
+                  , startTime             = currTime
+                  , rProgInfo             = progInfo
+                  , pathCond              = SVal KBool (Left trueCV)
+                  , rIncState             = istate
+                  , rCInfo                = cInfo
+                  , rObservables          = observes
+                  , rctr                  = ctr
+                  , freshNameCtr          = fnctr
+                  , rLambdaLevel          = lambda
+                  , rUsedKinds            = usedKinds
+                  , rUsedLbls             = usedLbls
+                  , rinps                 = inps
+                  , rlambdaInps           = lambdaInps
+                  , routs                 = outs
+                  , rtblMap               = tables
+                  , spgm                  = pgm
+                  , rconstMap             = cmap
+                  , rexprMap              = emap
+                  , rUserFuncs            = userFuncs
+                  , rCompilingFuncs       = compilingFuncs
+                  , rUIMap                = uis
+                  , rCgMap                = cgs
+                  , rDefns                = defns
+                  , rMeasureChecks        = measureChecks
+                  , rFuncLambdaInfos      = funcLambdaInfos
+                  , rSkipMeasureChecks    = skipMeasureChecks
+                  , rNoTermCheckFunctions = noTermCheckFuncs
+                  , rSVCache              = swCache
+                  , rConstraints          = cstrs
+                  , rPartitionVars        = pvs
+                  , rSMTOptions           = smtOpts
+                  , rOptGoals             = optGoals
+                  , rAsserts              = asserts
+                  , rOutstandingAsserts   = outstandingAsserts
+                  , rQueryState           = qstate
+                  , parentState           = Nothing
+                  }
+
+-- | Generalization of 'Data.SBV.runSymbolic'
+runSymbolic :: MonadIO m => SMTConfig -> SBVRunMode -> SymbolicT m a -> m (a, Result)
+runSymbolic cfg currentRunMode comp = do
+   st <- mkNewState cfg currentRunMode
+   runSymbolicInState st comp
+
+-- | Catch the catastrophic case of context mismatch
+-- NB. We're not printing _ctx1/_ctx2 here (hence the underscored variables).
+-- The reason is that they can get different values; causing test-suite failures with no helpful info.
+contextMismatchError :: SBVContext -> SBVContext -> a
+contextMismatchError _ctx1 _ctx2 = error $ unlines [
+                               "Data.SBV: Mismatched contexts detected."
+                             , "***"
+                             , "*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc."
+                             , "*** while another one is in execution, or use results from one such call in another."
+                             , "*** Please avoid such nested calls, all interactions should be from the same context."
+                             , "*** See https://github.com/LeventErkok/sbv/issues/71 for several examples."
+                             ]
+
+-- | Run a symbolic computation in a given state
+runSymbolicInState :: MonadIO m => State -> SymbolicT m a -> m (a, Result)
+runSymbolicInState st (SymbolicT c) = do
+   _ <- liftIO $ newConst st falseCV -- s(-2) == falseSV
+   _ <- liftIO $ newConst st trueCV  -- s(-1) == trueSV
+   r <- runReaderT c st
+   res <- liftIO $ extractSymbolicSimulationState st
+
+   -- Check that the state wasn't clobbered in any way
+   let check ctx | ctx == sbvContext st || ctx == globalSBVContext
+                 = pure ()
+                 | True
+                 = contextMismatchError (sbvContext st) ctx
+
+   mapM_ check $ nubOrd $ G.universeBi res
+
+   pure (r, res)
+
+-- | Grab the program from a running symbolic simulation state.
+extractSymbolicSimulationState :: State -> IO Result
+extractSymbolicSimulationState st@State{ runMode=rrm
+                                       , spgm=pgm, rinps=inps, rlambdaInps=linps, routs=outs, rtblMap=tables
+                                       , rUIMap=uis, rDefns=defns
+                                       , rAsserts=asserts, rUsedKinds=usedKinds, rCgMap=cgs, rCInfo=cInfo, rConstraints=cstrs
+                                       , rObservables=observes, rProgInfo=progInfo
+                                       } = do
+   SBVPgm rpgm  <- readIORef pgm
+
+   rm <- readIORef rrm
+
+   inpsO <- do Inputs{userInputs, internInputs} <- readIORef inps
+               ls <- readIORef linps
+
+               let lambdaOnly = case rm of
+                                  SMTMode{}   -> False
+                                  CodeGen{}   -> False
+                                  Concrete{}  -> False
+                                  LambdaGen{} -> True
+                   topInps = (F.toList userInputs, F.toList internInputs)
+                   lamInps = F.toList ls
+
+               if lambdaOnly
+                  then case topInps of
+                          ([], []) -> pure $ ResultLamInps (F.toList ls)
+                          (xs, ys) -> error $ unlines [ ""
+                                                      , "*** Data.SBV: Impossible happened; saw inputs in lambda mode."
+                                                      , "***"
+                                                      , "***   Inps    : " ++ show xs
+                                                      , "***   Trackers: " ++ show ys
+                                                      ]
+                  else case lamInps of
+                          [] -> pure $ ResultTopInps topInps
+                          _  -> error $ unlines [ ""
+                                                , "*** Data.SBV: Impossible happened; saw lambda inputs in regular mode."
+                                                , "***"
+                                                , "***   Params: " ++ show lamInps
+                                                ]
+
+   outsO <- reverse <$> readIORef outs
+
+   let arrange (i, (at, rt, es)) = ((i, at, rt), es)
+
+   constMap <- readIORef (rconstMap st)
+   let cnsts = mapToSortedList constMap
+
+   tbls  <- map arrange . mapToSortedList <$> readIORef tables
+   defnMap <- readIORef defns
+   let ds         = Map.toList defnMap
+       definedSet = Map.keysSet defnMap
+   unint <- do unints <- Map.toList <$> readIORef uis
+               -- drop those that has a definition associated with it
+               pure [ui | ui@(nm, _) <- unints, nm `Set.notMember` definedSet]
+   knds  <- readIORef usedKinds
+   cgMap <- Map.toList <$> readIORef cgs
+
+   traceVals   <- reverse <$> readIORef cInfo
+   observables <- fmap (\(n,f,sv) -> (T.unpack n, f, sv)) . F.toList <$> readIORef observes
+   extraCstrs  <- readIORef cstrs
+   assertions  <- reverse <$> readIORef asserts
+
+   pinfo <- readIORef progInfo
+
+   pure $ Result pinfo knds traceVals observables cgMap inpsO (constMap, cnsts) tbls unint ds (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:) (pure ())
+
+-- | 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]
+                                                              internalConstraint st isSoft attrs c
+
+-- | 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
+
+                                          rm <- liftIO $ readIORef (runMode st)
+
+                                          -- Are we running validation? If so, we always want to
+                                          -- add the constraint for debug purposes. Otherwise
+                                          -- we only add it if it's interesting; i.e., not directly
+                                          -- true or has some attributes.
+                                          let isValidating = case rm of
+                                                               SMTMode _ _ _ cfg -> validationRequested cfg
+                                                               CodeGen           -> False
+                                                               LambdaGen{}       -> 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
+
+                        -- create the tracking variable here for the metric
+                        let mkGoal nm orig = liftIO $ do origSV  <- svToSV st orig
+                                                         track   <- svMkTrackerVar (kindOf orig) nm st
+                                                         trackSV <- svToSV st track
+                                                         pure (origSV, trackSV)
+
+                        let walk (Minimize          nm v)     = Minimize nm                     <$> mkGoal nm v
+                            walk (Maximize          nm v)     = Maximize nm                     <$> mkGoal nm v
+                            walk (AssertWithPenalty nm v mbP) = flip (AssertWithPenalty nm) mbP <$> mkGoal nm v
+
+                        !obj' <- walk obj
+                        liftIO $ modifyState st rOptGoals (obj' :)
+                                           $ noInteractive [ "Adding an optimization objective:"
+                                                           , "  Objective: " ++ show obj
+                                                           ]
+
+-- | Generalization of 'Data.SBV.sObserve'
+sObserve :: MonadSymbolic m => String -> SVal -> m ()
+sObserve m x
+  | Just bad <- checkObservableName m
+  = error bad
+  | True
+  = do st <- symbolicEnv
+       liftIO $ do xsv <- svToSV st x
+                   recordObservable st (T.pack m) (const True) xsv
+
+-- | Generalization of 'Data.SBV.outputSVal'
+outputSVal :: MonadSymbolic m => SVal -> m ()
+outputSVal (SVal _ (Left c)) = do
+  st <- symbolicEnv
+  sv <- liftIO $ newConst st c
+  liftIO $ modifyState st routs (sv:) (pure ())
+outputSVal (SVal _ (Right f)) = do
+  st <- symbolicEnv
+  sv <- liftIO $ uncache f st
+  liftIO $ modifyState st routs (sv:) (pure ())
+
+---------------------------------------------------------------------------------
+-- * Cached values
+---------------------------------------------------------------------------------
+
+-- | We implement a peculiar caching mechanism, applicable to the use case in
+-- implementation of SBV's.  Whenever we do a state based computation, we do
+-- not want to keep on evaluating it in the then-current state. That will
+-- produce essentially a semantically equivalent value. Thus, we want to run
+-- it only once, and reuse that result, capturing the sharing at the Haskell
+-- level. This is similar to the "type-safe observable sharing" work, but also
+-- takes into the account of how symbolic simulation executes.
+--
+-- See Andy Gill's type-safe observable sharing trick for the inspiration behind
+-- this technique: <http://ku-fpg.github.io/files/Gill-09-TypeSafeReification.pdf>
+--
+-- Note that this is *not* a general memo utility!
+newtype Cached a = Cached (State -> IO a)
+
+-- | Cache a state-based computation
+cache :: (State -> IO a) -> Cached a
+cache = Cached
+
+-- | Uncache a previously cached computation
+uncache :: Cached SV -> State -> IO SV
+uncache = uncacheGen rSVCache
+
+-- | Generic uncaching. Note that this is entirely safe, since we do it in the IO monad.
+uncacheGen :: (State -> IORef (Cache a)) -> Cached a -> State -> IO a
+uncacheGen getCache (Cached f) st = do
+        let rCache = getCache st
+        stored <- readIORef rCache
+        sn <- f `seq` makeStableName f
+        let h = hashStableName sn
+        case (h `IMap.lookup` stored) >>= (sn `lookup`) of
+          Just r  -> pure r
+          Nothing -> do r <- f st
+                        r `seq` R.modifyIORef' rCache (IMap.insertWith (\_ old -> (sn, r) : old) h [(sn, r)])
+                        pure r
+
+-- | Representation of SMTLib Program versions. As of June 2015, we're dropping support
+-- for SMTLib1, and supporting SMTLib2 only. We keep this data-type around in case
+-- SMTLib3 comes along and we want to support 2 and 3 simultaneously.
+data SMTLibVersion = SMTLib2
+                   deriving (Bounded, Enum, Eq, Show)
+
+-- | The extension associated with the version
+smtLibVersionExtension :: SMTLibVersion -> String
+smtLibVersionExtension SMTLib2 = "smt2"
+
+-- | Representation of an SMT-Lib program. The second Text are the function definitions,
+-- which is *replicated* in the first one. There are cases where that we need the second part on its own.
+data SMTLibPgm = SMTLibPgm SMTLibVersion Text Text
+
+instance NFData SMTLibVersion where rnf a                 = a `seq` ()
+instance NFData SMTLibPgm     where rnf (SMTLibPgm v p d) = rnf v `seq` rnf p `seq` rnf d
+
+instance Show SMTLibPgm where
+  show (SMTLibPgm _ pgm _) = T.unpack pgm
+
+-- | Extract the program text from an SMTLibPgm without converting to String.
+smtLibPgmText :: SMTLibPgm -> Text
+smtLibPgmText (SMTLibPgm _ pgm _) = pgm
+
+-- Other Technicalities..
+instance NFData GeneralizedCV where
+  rnf (ExtendedCV e) = e `seq` ()
+  rnf (RegularCV  c) = c `seq` ()
+
+instance NFData NamedSymVar where
+  rnf (NamedSymVar s n) = rnf s `seq` rnf n
+
+instance NFData Result where
+  rnf (Result hasQuants kindInfo qcInfo obs cgs inps consts tbls uis axs pgm cstr asserts outs)
+        = rnf hasQuants `seq` rnf kindInfo `seq` rnf qcInfo  `seq` rnf obs    `seq` rnf cgs
+                        `seq` rnf inps     `seq` rnf consts  `seq` rnf tbls
+                        `seq` rnf uis      `seq` rnf axs     `seq` rnf pgm
+                        `seq` rnf cstr     `seq` rnf asserts `seq` rnf outs
+instance NFData SV           where rnf a          = seq a ()
+instance NFData SBVExpr      where rnf a          = seq a ()
+instance NFData Quantifier   where rnf a          = seq a ()
+instance NFData SBVType      where rnf a          = seq a ()
+instance NFData SBVPgm       where rnf a          = seq a ()
+instance NFData (Cached a)   where rnf (Cached f) = f `seq` ()
+instance NFData SVal         where rnf (SVal x y) = rnf x `seq` rnf y
+
+instance NFData SMTResult where
+  rnf (Unsatisfiable _   m   ) = rnf m
+  rnf (Satisfiable   _   m   ) = rnf m
+  rnf (DeltaSat      _ p m   ) = rnf m `seq` rnf p
+  rnf (SatExtField   _   m   ) = rnf m
+  rnf (Unknown       _   m   ) = rnf m
+  rnf (ProofError    _   m mr) = rnf m `seq` rnf mr
+
+instance NFData SMTModel where
+  rnf (SMTModel objs bndgs assocs uifuns) = rnf objs `seq` rnf bndgs `seq` rnf assocs `seq` rnf uifuns
+
+instance NFData SMTScript where
+  rnf (SMTScript b m) = rnf b `seq` rnf m
+
+-- | Translation tricks needed for specific capabilities afforded by each solver
+data SolverCapabilities = SolverCapabilities {
+         supportsQuantifiers     :: Bool           -- ^ Supports SMT-Lib2 style quantifiers?
+       , supportsDefineFun       :: Bool           -- ^ Supports define-fun construct?
+       , supportsDistinct        :: Bool           -- ^ Supports calls to distinct?
+       , supportsBitVectors      :: Bool           -- ^ Supports bit-vectors?
+       , supportsADTs            :: Bool           -- ^ Supports SMT-Lib2 style uninterpreted-sorts and ADTs
+       , supportsUnboundedInts   :: Bool           -- ^ Supports unbounded integers?
+       , supportsReals           :: Bool           -- ^ Supports reals?
+       , supportsApproxReals     :: Bool           -- ^ Supports printing of approximations of reals?
+       , supportsDeltaSat        :: Maybe String   -- ^ Supports delta-satisfiability? (With given precision query)
+       , 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?
+       , supportsLambdas         :: Bool           -- ^ Does it support lambdas?
+       , supportsSpecialRels     :: Bool           -- ^ Does it support special relations (orders, transitive closure etc.)
+       , supportsDirectTesters   :: Bool           -- ^ Supports data-type testers without full ascription?
+       , supportsFlattenedModels :: Maybe [String] -- ^ Supports flattened model output? (With given config lines.)
+       }
+
+-- | Solver configuration. See also 'Data.SBV.z3', 'Data.SBV.yices', 'Data.SBV.cvc4', 'Data.SBV.boolector', 'Data.SBV.mathSAT', etc.
+-- which are instantiations of this type for those solvers, with reasonable defaults. In particular, custom configuration can be
+-- created by varying those values. (Such as @z3{verbose=True}@.)
+--
+-- Most fields are self explanatory. The notion of precision for printing algebraic reals stems from the fact that such values does
+-- not necessarily have finite decimal representations, and hence we have to stop printing at some depth. It is important to
+-- emphasize that such values always have infinite precision internally. The issue is merely with how we print such an infinite
+-- precision value on the screen. The field 'printRealPrec' controls the printing precision, by specifying the number of digits after
+-- the decimal point. The default value is 16, but it can be set to any positive integer.
+--
+-- When printing, SBV will add the suffix @...@ at the end of a real-value, if the given bound is not sufficient to represent the real-value
+-- exactly. Otherwise, the number will be written out in standard decimal notation. Note that SBV will always print the whole value if it
+-- is precise (i.e., if it fits in a finite number of digits), regardless of the precision limit. The limit only applies if the representation
+-- of the real value is not finite, i.e., if it is not rational.
+--
+-- The 'printBase' field can be used to print numbers in base 2, 10, or 16.
+--
+-- The 'crackNum' field can be used to display numbers in detail, all its bits and how they are laid out in memory. Works with all bounded number types
+-- (i.e., SWord and SInt), but also with floats. It is particularly useful with floating-point numbers, as it shows you how they are laid out in
+-- memory following the IEEE754 rules.
+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)
+       , crackNum                    :: Bool                -- ^ For each numeric value, show it in detail in the model with its bits spliced out. Good for floats.
+       , crackNumSurfaceVals         :: [(String, Integer)] -- ^ For crackNum: The surface representation of variables, if available
+       , 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.
+       , allSatTrackUFs              :: Bool                -- ^ In a 'Data.SBV.allSat' 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.
+       , optimizeValidateConstraints :: Bool                -- ^ Validate optimization results. NB: Does NOT make sure the model is optimal, just checks they satisfy the constraints.
+       , 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
+       , dsatPrecision               :: Maybe Double        -- ^ Delta-sat precision
+       , solver                      :: SMTSolver           -- ^ The actual SMT solver.
+       , extraArgs                   :: [String]            -- ^ Extra command line arguments to pass to the solver.
+       , roundingMode                :: RoundingMode        -- ^ Rounding mode to use for floating-point calculations. Defaults to RNE.
+       , 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.
+       , firstifyUniqueLen           :: Int                 -- ^ Unique length used for firstified higher-order function names
+       , tpOptions                   :: TPOptions           -- ^ TP specific options
+       }
+
+-- | Configuration for TP
+data TPOptions = TPOptions {
+         ribbonLength          :: Int            -- ^ Line length for TP proofs
+       , quiet                 :: Bool           -- ^ No messages what-so-ever for successful steps. (Will print if something fails)
+       , printAsms             :: Bool           -- ^ Print assumptions as they are proven as separate steps.
+       , printStats            :: Bool           -- ^ Print time/statistics. If quiet is True, then measureTime is ignored.
+       , measuresBeingVerified :: Set.Set String -- ^ Functions whose measures are currently being verified. Used to prevent infinite
+                                                 -- recursion when a measureLemma proof uses the function whose measure is being checked.
+       }
+
+-- | Ignore internal names and those the user told us to
+mustIgnoreVar :: SMTConfig -> T.Text -> Bool
+mustIgnoreVar cfg s = "__internal_sbv" `T.isPrefixOf` s || isNonModelVar cfg (T.unpack s)
+
+-- | We show the name of the solver for the config. Arguably this is misleading, but better than nothing.
+instance Show SMTConfig where
+  show = show . name . solver
+
+-- | Returns true if we have to perform validation
+validationRequested :: SMTConfig -> Bool
+validationRequested SMTConfig{validateModel, optimizeValidateConstraints} = validateModel || optimizeValidateConstraints
+
+-- We're just seq'ing top-level here, it shouldn't really matter. (i.e., no need to go deeper.)
+instance NFData SMTConfig where
+  rnf SMTConfig{} = ()
+
+-- | A model, as returned by a solver
+data SMTModel = SMTModel {
+       modelObjectives :: [(String, GeneralizedCV)]                                     -- ^ Mapping of symbolic values to objective values.
+     , modelBindings   :: Maybe [(NamedSymVar, 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, (Bool, SBVType, Either String ([([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. Left is used when the function returned is too
+                                                                                        -- difficult for SBV to figure out what it means
+     }
+     deriving Show
+
+-- | The result of an SMT solver call. Each constructor is tagged with
+-- the t'SMTConfig' that created it so that further tools can inspect it
+-- 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
+               | DeltaSat      SMTConfig (Maybe String) SMTModel     -- ^ Delta satisfiable with queried string if available and 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 {
+          scriptBody  :: String   -- ^ Initial feed
+        , scriptModel :: [String] -- ^ Continuation script, to extract results
+        }
+
+-- | An SMT engine
+type SMTEngine =  forall res.
+                  SMTConfig         -- ^ current configuration
+               -> State             -- ^ the state in which to run the engine
+               -> Text              -- ^ program
+               -> (State -> IO res) -- ^ continuation
+               -> IO res
+
+-- | Solvers that SBV is aware of
+data Solver = ABC
+            | Boolector
+            | Bitwuzla
+            | CVC4
+            | CVC5
+            | DReal
+            | MathSAT
+            | Yices
+            | Z3
+            | OpenSMT
+            deriving (Show, Enum, Bounded)
+
+-- | An SMT solver
+data SMTSolver = SMTSolver {
+         name           :: Solver                -- ^ The solver in use
+       , executable     :: String                -- ^ The path to its executable
+       , preprocess     :: Text -> Text          -- ^ Each line sent to the solver will be passed through this function (typically id)
+       , options        :: SMTConfig -> [String] -- ^ Options to provide to the solver
+       , engine         :: SMTEngine             -- ^ The solver engine, responsible for interpreting solver output
+       , capabilities   :: SolverCapabilities    -- ^ Various capabilities of the solver
+       }
+
+-- | 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"
+
+{- HLint ignore type FPOp "Use camelCase" -}
+{- HLint ignore type PBOp "Use camelCase" -}
+{- HLint ignore type OvOp "Use camelCase" -}
+{- HLint ignore type NROp "Use camelCase" -}
diff --git a/Data/SBV/Core/TH.hs b/Data/SBV/Core/TH.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Core/TH.hs
@@ -0,0 +1,142 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Core.TH
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Template Haskell utilities for extracting constructor information from
+-- algebraic data types. Factored out to avoid circular dependencies.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE LambdaCase              #-}
+{-# LANGUAGE PackageImports          #-}
+{-# LANGUAGE ScopedTypeVariables     #-}
+{-# LANGUAGE TemplateHaskellQuotes   #-}
+{-# LANGUAGE TupleSections           #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Core.TH (
+         getConstructors
+       , bad
+       , report
+       , sbvName
+       ) where
+
+import Data.Maybe (fromMaybe)
+
+import qualified "template-haskell" Language.Haskell.TH        as TH
+import           "template-haskell" Language.Haskell.TH.Syntax as THS (Name(..), OccName(..), NameFlavour(..), PkgName, ModName(..), NameSpace(..))
+
+import Language.Haskell.TH.ExpandSyns as TH
+
+import Data.SBV.Core.Kind (smtType)
+
+-- | Construct a TH name for a value\/function in the @sbv@ package, given
+-- the fully qualified module name and the unqualified identifier. This avoids
+-- importing the target module (which would create import cycles) while still
+-- producing exact 'NameG' names that resolve correctly in generated TH splices.
+sbvName :: String -> String -> TH.Name
+sbvName modNm fnNm = THS.Name (THS.OccName fnNm) (THS.NameG THS.VarName sbvPkg (THS.ModName modNm))
+  where -- Extract the package key from a known cross-module name in the sbv package
+        sbvPkg :: THS.PkgName
+        sbvPkg = case 'smtType of
+                   THS.Name _ (THS.NameG _ pkg _) -> pkg
+                   _                              -> error "Data.SBV.Core.TH.sbvName: unexpected name flavour"
+
+bad :: MonadFail m => String -> [String] -> m a
+bad what extras = fail $ unlines $ ("mkSymbolic: " ++ what) : map ("      " ++) extras
+
+report :: String
+report = "Please report this as a feature request."
+
+-- | Collect the constructors
+getConstructors :: TH.Name -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+getConstructors typeName = do res@(_, cstrs) <- getConstructorsFromType (TH.ConT typeName)
+
+                              -- make sure accessors are unique
+                              let noDup [] = pure ()
+                                  noDup (n:ns)
+                                    | n `elem` ns = bad "Unsupported field accessor definition."
+                                                        [ "Multiply used: " ++ TH.nameBase n
+                                                        , ""
+                                                        , "SBV does not support cases where accessor fields are replicated."
+                                                        , "Please use each accessor only once."
+                                                        ]
+                                    | True        = noDup ns
+                              noDup [n | (_, fs) <- cstrs, (Just n, _) <- fs]
+
+                              pure res
+
+  where getConstructorsFromType :: TH.Type -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+        getConstructorsFromType ty = do ty' <- expandSyns ty
+                                        case headCon ty' of
+                                          Just (n, args) -> reifyFromHead n args
+                                          Nothing        -> bad "Not a type constructor"
+                                                                [ "Name    : " ++ show typeName
+                                                                , "Type    : " ++ show ty
+                                                                , "Expanded: " ++ show ty'
+                                                                ]
+
+        headCon :: TH.Type -> Maybe (TH.Name, [TH.Type])
+        headCon = go []
+          where go args (TH.ConT n)    = Just (n, reverse args)
+                go args (TH.AppT t a)  = go   (a:args) t
+                go args (TH.SigT t _)  = go      args t
+                go args (TH.ParensT t) = go      args t
+                go _    _              = Nothing
+
+        reifyFromHead :: TH.Name -> [TH.Type] -> TH.Q ([TH.Name], [(TH.Name, [(Maybe TH.Name, TH.Type)])])
+        reifyFromHead n args = do info <- TH.reify n
+                                  case info of
+                                    TH.TyConI (TH.DataD    _ _ tvs _ cons _) -> (map tvName tvs,) <$> mapM (expandCon (mkSubst tvs args)) cons
+                                    TH.TyConI (TH.NewtypeD _ _ tvs _ con  _) -> (map tvName tvs,) <$> mapM (expandCon (mkSubst tvs args)) [con]
+                                    TH.TyConI (TH.TySynD _ tvs rhs)          -> getConstructorsFromType (applySubst (mkSubst tvs args) rhs)
+                                    _ -> bad "Unsupported kind"
+                                             [ "Type : " ++ show typeName
+                                             , "Name : " ++ show n
+                                             , "Kind : " ++ show info
+                                             ]
+
+        onSnd f (a, b) = (a,) <$> f b
+
+        expandCon :: [(TH.Name, TH.Type)] -> TH.Con -> TH.Q (TH.Name, [(Maybe TH.Name, TH.Type)])
+        expandCon sub (TH.NormalC  n fields)          = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(   _,t) -> (Nothing, t))) fields
+        expandCon sub (TH.RecC     n fields)          = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(fn,_,t) -> (Just fn, t))) fields
+        expandCon sub (TH.InfixC   (_, t1) n (_, t2)) = (n,) <$> mapM (onSnd (expandSyns . applySubst sub)) [(Nothing, t1), (Nothing, t2)]
+        {- These don't have proper correspondences in SMTLib; so ignore.
+        expandCon sub (TH.ForallC  _ _ c)             = expandCon sub c
+        expandCon sub (TH.GadtC    [n] fields _)      = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(   _,t) -> (Nothing, t))) fields
+        expandCon sub (TH.RecGadtC [n] fields _)      = (n,) <$> mapM (onSnd (expandSyns . applySubst sub) . (\(fn,_,t) -> (Just fn, t))) fields
+        -}
+        expandCon _   c                               = bad "Unsupported constructor form: "
+                                                            [ "Type       : " ++ show typeName
+                                                            , "Constructor: " ++ show c
+                                                            , ""
+                                                            , report
+                                                            ]
+
+        tvName :: TH.TyVarBndr TH.BndrVis -> TH.Name
+        tvName (TH.PlainTV  n _)   = n
+        tvName (TH.KindedTV n _ _) = n
+
+        -- | Make substitution from type variables to actual args
+        mkSubst :: [TH.TyVarBndr TH.BndrVis] -> [TH.Type] -> [(TH.Name, TH.Type)]
+        mkSubst tvs = zip (map tvName tvs)
+
+        -- | Apply substitution to a Type
+        applySubst :: [(TH.Name, TH.Type)] -> TH.Type -> TH.Type
+        applySubst sub = go
+          where go (TH.VarT    n)        = fromMaybe  (TH.VarT n) (n `lookup` sub)
+                go (TH.AppT    t1 t2)    = TH.AppT    (go t1) (go t2)
+                go (TH.SigT    t k)      = TH.SigT    (go t)  k
+                go (TH.ParensT t)        = TH.ParensT (go t)
+                go (TH.InfixT  t1 n t2)  = TH.InfixT  (go t1) n (go t2)
+                go (TH.UInfixT t1 n t2)  = TH.UInfixT (go t1) n (go t2)
+                go (TH.ForallT bs ctx t) = TH.ForallT bs (map goPred ctx) (go t)
+                go t                     = t
+
+                goPred (TH.AppT t1 t2) = TH.AppT (go t1) (go t2)
+                goPred p               = p
diff --git a/Data/SBV/Dynamic.hs b/Data/SBV/Dynamic.hs
--- a/Data/SBV/Dynamic.hs
+++ b/Data/SBV/Dynamic.hs
@@ -1,56 +1,57 @@
----------------------------------------------------------------------------------
+-----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Dynamic
--- Copyright   :  (c) Brian Huffman
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Dynamic
+-- Copyright : (c) Brian Huffman
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Dynamically typed low-level API to the SBV library, for users who
 -- want to generate symbolic values at run-time. Note that with this
 -- API it is possible to create terms that are not type correct; use
 -- at your own risk!
----------------------------------------------------------------------------------
+-----------------------------------------------------------------------------
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Dynamic
   (
   -- * Programming with symbolic values
   -- ** Symbolic types
   -- *** Abstract symbolic value type
     SVal
-  , HasKind(..), Kind(..), CW(..), CWVal(..), cwToBool
-  -- *** Arrays of symbolic values
-  , SArr
-  , readSArr, resetSArr, writeSArr, mergeSArr, newSArr, eqSArr
-
+  , HasKind(..), Kind(..), CV(..), CVal(..), cvToBool
   -- ** Creating a symbolic variable
   , Symbolic
   , Quantifier(..)
-  , svMkSymVar
+  , svMkSymVar, svNewVar_, svNewVar
+  , sWordN, sWordN_, sIntN, sIntN_
   -- ** Operations on symbolic values
   -- *** Boolean literals
   , svTrue, svFalse, svBool, svAsBool
   -- *** Integer literals
   , svInteger, svAsInteger
   -- *** Float literals
-  , svFloat, svDouble
+  , svFloat, svDouble, svFloatingPoint, svAsFloat, svAsDouble, svAsFP
+  -- *** Rounding mode literals
+  , svRoundingMode, svAsRoundingMode
   -- *** Algebraic reals (only from rationals)
   , svReal, svNumerator, svDenominator
   -- *** Symbolic equality
-  , svEqual, svNotEqual
+  , svEqual, svNotEqual, svStrongEqual
   -- *** Constructing concrete lists
   , svEnumFromThenTo
   -- *** Symbolic ordering
-  , svLessThan, svGreaterThan, svLessEq, svGreaterEq
+  , svLessThan, svGreaterThan, svLessEq, svGreaterEq, svStructuralLessThan
   -- *** Arithmetic operations
   , svPlus, svTimes, svMinus, svUNeg, svAbs
-  , svDivide, svQuot, svRem, svExp
+  , svDivide, svQuot, svRem, svQuotRem, svExp
   , svAddConstant, svIncrement, svDecrement
   -- *** Logical operations
   , svAnd, svOr, svXOr, svNot
   , svShl, svShr, svRol, svRor
   -- *** Splitting, joining, and extending
-  , svExtract, svJoin
+  , svExtract, svJoin, svZeroExtend, svSignExtend
   -- *** Sign-casting
   , svSign, svUnsign
   -- *** Numeric conversions
@@ -61,11 +62,21 @@
   , svToWord1, svFromWord1, svTestBit, svSetBit
   , svShiftLeft, svShiftRight
   , svRotateLeft, svRotateRight
+  , svBarrelRotateLeft, svBarrelRotateRight
   , svWordFromBE, svWordFromLE
   , svBlastLE, svBlastBE
+  -- *** Floating-point operations
+  , svFPNaN, svFPInf, svFPZero
+  , svFPFromIntegerLit, svFPFromRationalLit
+  , svFPIsZero, svFPIsInfinite, svFPIsNegative, svFPIsPositive
+  , svFPIsNaN, svFPIsNormal, svFPIsSubnormal
+  , svFPAdd, svFPSub, svFPMul, svFPDiv, svFPRem, svFPMin, svFPMax
+  , svFPFMA, svFPAbs, svFPNeg, svFPRoundToIntegral, svFPSqrt
+  , svCastToFP, svCastFromFP
+  , svSWord32AsFloat, svSWord64AsDouble, svSWordAsFloatingPoint
+  , svFloatAsSWord32, svDoubleAsSWord64, svFloatingPointAsSWord
   -- ** Conditionals: Mergeable values
   , svIte, svLazyIte, svSymbolicMerge
-  , svIsSatisfiableInCurrentPath
   -- * Uninterpreted sorts, constants, and functions
   , svUninterpreted
   -- * Properties, proofs, and satisfiability
@@ -77,24 +88,25 @@
   , safeWith
   -- * Proving properties using multiple solvers
   , proveWithAll, proveWithAny, satWithAll, satWithAny
+  -- * Proving properties using multiple threads
+  , proveConcurrentWithAll, proveConcurrentWithAny
+  , satConcurrentWithAny, satConcurrentWithAll
   -- * Quick-check
   , svQuickCheck
 
   -- * Model extraction
 
   -- ** Inspecting proof results
-  , ThmResult(..), SatResult(..), SafeResult(..), AllSatResult(..), SMTResult(..)
+  , ThmResult(..), SatResult(..), AllSatResult(..), SafeResult(..), OptimizeResult(..), SMTResult(..)
 
   -- ** Programmable model extraction
-  , genParse, getModel, getModelDictionary
+  , genParse, getModelAssignment, getModelDictionary
   -- * SMT Interface: Configurations and solvers
-  , SMTConfig(..), SMTLibVersion(..), SMTLibLogic(..), Logic(..), OptimizeOpts(..), Solver(..), SMTSolver(..), boolector, cvc4, yices, z3, mathSAT, abc, defaultSolverConfig, sbvCurrentSolver, defaultSMTCfg, sbvCheckSolverInstallation, sbvAvailableSolvers
+  , SMTConfig(..), SMTLibVersion(..), Solver(..), SMTSolver(..), boolector, bitwuzla, cvc4, cvc5, dReal, yices, z3, mathSAT, abc, defaultSolverConfig, defaultSMTCfg, sbvCheckSolverInstallation, getAvailableSolvers
 
   -- * Symbolic computations
   , outputSVal
 
-  -- * Getting SMT-Lib output (for offline analysis)
-  , compileToSMTLib, generateSMTBenchmarks
   -- * Code generation from symbolic programs
   , SBVCodeGen
 
@@ -113,45 +125,50 @@
   -- ** Code generation with uninterpreted functions
   , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert
 
-  -- ** Code generation with 'SInteger' and 'SReal' types
+  -- ** Code generation with 'Data.SBV.SInteger' and 'Data.SBV.SReal' types
   , cgIntegerSize, cgSRealType, CgSRealType(..)
 
   -- ** Compilation to C
   , compileToC, compileToCLib
+
+  -- ** Compilation to SMTLib
+  , generateSMTBenchmarkSat, generateSMTBenchmarkProof
   ) where
 
-import Data.Map (Map)
+import Control.Monad.Trans (liftIO)
 
-import Data.SBV.BitVectors.Kind
-import Data.SBV.BitVectors.Concrete
-import Data.SBV.BitVectors.Symbolic
-import Data.SBV.BitVectors.Operations
+import Data.Map.Strict (Map)
 
-import Data.SBV.Compilers.CodeGen
-  ( SBVCodeGen
-  , svCgInput, svCgInputArr
-  , svCgOutput, svCgOutputArr
-  , svCgReturn, svCgReturnArr
-  , cgPerformRTCs, cgSetDriverValues, cgGenerateDriver, cgGenerateMakefile
-  , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert
-  , cgIntegerSize, cgSRealType, CgSRealType(..)
-  )
-import Data.SBV.Compilers.C    (compileToC, compileToCLib)
-import Data.SBV.Provers.Prover (boolector, cvc4, yices, z3, mathSAT, abc, defaultSMTCfg)
-import Data.SBV.SMT.SMT        (ThmResult(..), SatResult(..), SafeResult(..), AllSatResult(..), genParse)
-import Data.SBV.Tools.Optimize (OptimizeOpts(..))
-import Data.SBV                (sbvCurrentSolver, sbvCheckSolverInstallation, defaultSolverConfig, sbvAvailableSolvers)
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Concrete
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.Operations
 
-import qualified Data.SBV                  as SBV (SBool, proveWithAll, proveWithAny, satWithAll, satWithAny)
-import qualified Data.SBV.BitVectors.Data  as SBV (SBV(..))
-import qualified Data.SBV.BitVectors.Model as SBV (isSatisfiableInCurrentPath, sbvQuickCheck)
-import qualified Data.SBV.Provers.Prover   as SBV (proveWith, satWith, safeWith, allSatWith, compileToSMTLib, generateSMTBenchmarks)
-import qualified Data.SBV.SMT.SMT          as SBV (Modelable(getModel, getModelDictionary))
+import Data.SBV.Compilers.CodeGen ( SBVCodeGen
+                                  , svCgInput, svCgInputArr
+                                  , svCgOutput, svCgOutputArr
+                                  , svCgReturn, svCgReturnArr
+                                  , cgPerformRTCs, cgSetDriverValues, cgGenerateDriver, cgGenerateMakefile
+                                  , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert
+                                  , cgIntegerSize, cgSRealType, CgSRealType(..)
+                                  )
+import Data.SBV.Compilers.C       (compileToC, compileToCLib)
 
--- | Reduce a condition (i.e., try to concretize it) under the given path
-svIsSatisfiableInCurrentPath :: SVal -> Symbolic Bool
-svIsSatisfiableInCurrentPath = SBV.isSatisfiableInCurrentPath . toSBool
+import Data.SBV.Provers.Prover (boolector, bitwuzla, cvc4, cvc5, dReal, yices, z3, mathSAT, abc, defaultSMTCfg)
+import Data.SBV.SMT.SMT        (ThmResult(..), SatResult(..), SafeResult(..), OptimizeResult(..), AllSatResult(..), genParse)
+import Data.SBV                (sbvCheckSolverInstallation, defaultSolverConfig, getAvailableSolvers)
 
+import qualified Data.SBV                as SBV (SBool, proveWithAll, proveWithAny, satWithAll, satWithAny
+                                                , proveConcurrentWithAll, proveConcurrentWithAny
+                                                , satConcurrentWithAny, satConcurrentWithAll
+                                                )
+import qualified Data.SBV.Core.Data      as SBV (SBV(..))
+import qualified Data.SBV.Core.Model     as SBV (sbvQuickCheck)
+import qualified Data.SBV.Provers.Prover as SBV (proveWith, satWith, safeWith, allSatWith, generateSMTBenchmarkSat, generateSMTBenchmarkProof)
+import qualified Data.SBV.SMT.SMT        as SBV (Modelable(getModelAssignment, getModelDictionary))
+
+import Data.Time (NominalDiffTime)
+
 -- | Dynamic variant of quick-check
 svQuickCheck :: Symbolic SVal -> IO Bool
 svQuickCheck = SBV.sbvQuickCheck . fmap toSBool
@@ -159,74 +176,95 @@
 toSBool :: SVal -> SBV.SBool
 toSBool = SBV.SBV
 
--- | Compiles to SMT-Lib and returns the resulting program as a string. Useful for saving
--- the result to a file for off-line analysis, for instance if you have an SMT solver that's not natively
--- supported out-of-the box by the SBV library. It takes two arguments:
---
---    * version: The SMTLib-version to produce. Note that we currently only support SMTLib2.
---
---    * isSat  : If 'True', will translate it as a SAT query, i.e., in the positive. If 'False', will
---               translate as a PROVE query, i.e., it will negate the result. (In this case, the check-sat
---               call to the SMT solver will produce UNSAT if the input is a theorem, as usual.)
-compileToSMTLib :: SMTLibVersion   -- ^ If True, output SMT-Lib2, otherwise SMT-Lib1
-                -> Bool            -- ^ If True, translate directly, otherwise negate the goal. (Use True for SAT queries, False for PROVE queries.)
-                -> Symbolic SVal
-                -> IO String
-compileToSMTLib version isSat s = SBV.compileToSMTLib version isSat (fmap toSBool s)
+-- | Create SMT-Lib benchmark for a sat call
+generateSMTBenchmarkSat :: Symbolic SVal -> IO String
+generateSMTBenchmarkSat s = SBV.generateSMTBenchmarkSat (toSBool <$> s)
 
--- | Create both SMT-Lib1 and SMT-Lib2 benchmarks. The first argument is the basename of the file,
--- SMT-Lib1 version will be written with suffix ".smt1" and SMT-Lib2 version will be written with
--- suffix ".smt2". The 'Bool' argument controls whether this is a SAT instance, i.e., translate the query
--- directly, or a PROVE instance, i.e., translate the negated query. (See the second boolean argument to
--- 'compileToSMTLib' for details.)
-generateSMTBenchmarks :: Bool -> FilePath -> Symbolic SVal -> IO ()
-generateSMTBenchmarks isSat f s = SBV.generateSMTBenchmarks isSat f (fmap toSBool s)
+-- | Create SMT-Lib benchmark for a proof call
+generateSMTBenchmarkProof :: Symbolic SVal -> IO String
+generateSMTBenchmarkProof s = SBV.generateSMTBenchmarkProof (toSBool <$> s)
 
 -- | Proves the predicate using the given SMT-solver
 proveWith :: SMTConfig -> Symbolic SVal -> IO ThmResult
-proveWith cfg s = SBV.proveWith cfg (fmap toSBool s)
+proveWith cfg s = SBV.proveWith cfg (toSBool <$> s)
 
 -- | Find a satisfying assignment using the given SMT-solver
 satWith :: SMTConfig -> Symbolic SVal -> IO SatResult
-satWith cfg s = SBV.satWith cfg (fmap toSBool s)
+satWith cfg s = SBV.satWith cfg (toSBool <$> s)
 
 -- | Check safety using the given SMT-solver
 safeWith :: SMTConfig -> Symbolic SVal -> IO [SafeResult]
-safeWith cfg s = SBV.safeWith cfg (fmap toSBool s)
+safeWith cfg s = SBV.safeWith cfg (toSBool <$> s)
 
 -- | Find all satisfying assignments using the given SMT-solver
 allSatWith :: SMTConfig -> Symbolic SVal -> IO AllSatResult
-allSatWith cfg s = SBV.allSatWith cfg (fmap toSBool s)
+allSatWith cfg s = SBV.allSatWith cfg (toSBool <$> s)
 
 -- | Prove a property with multiple solvers, running them in separate threads. The
 -- results will be returned in the order produced.
-proveWithAll :: [SMTConfig] -> Symbolic SVal -> IO [(Solver, ThmResult)]
-proveWithAll cfgs s = SBV.proveWithAll cfgs (fmap toSBool s)
+proveWithAll :: [SMTConfig] -> Symbolic SVal -> IO [(Solver, NominalDiffTime, ThmResult)]
+proveWithAll cfgs s = SBV.proveWithAll cfgs (toSBool <$> s)
 
 -- | Prove a property with multiple solvers, running them in separate
 -- threads. Only the result of the first one to finish will be
 -- returned, remaining threads will be killed.
-proveWithAny :: [SMTConfig] -> Symbolic SVal -> IO (Solver, ThmResult)
-proveWithAny cfgs s = SBV.proveWithAny cfgs (fmap toSBool s)
+proveWithAny :: [SMTConfig] -> Symbolic SVal -> IO (Solver, NominalDiffTime, ThmResult)
+proveWithAny cfgs s = SBV.proveWithAny cfgs (toSBool <$> s)
 
+-- | Prove a property with query mode using multiple threads. Each query
+-- computation will spawn a thread and a unique instance of your solver to run
+-- asynchronously. The 'Symbolic' t'SVal' is duplicated for each thread. This
+-- function will block until all child threads return.
+proveConcurrentWithAll :: SMTConfig -> Symbolic SVal -> [Query SVal] -> IO [(Solver, NominalDiffTime, ThmResult)]
+proveConcurrentWithAll cfg s queries = SBV.proveConcurrentWithAll cfg queries (toSBool <$> s)
+
+-- | Prove a property with query mode using multiple threads. Each query
+-- computation will spawn a thread and a unique instance of your solver to run
+-- asynchronously. The 'Symbolic' t'SVal' is duplicated for each thread. This
+-- function will return the first query computation that completes, killing the others.
+proveConcurrentWithAny :: SMTConfig -> Symbolic SVal -> [Query SVal] -> IO (Solver, NominalDiffTime, ThmResult)
+proveConcurrentWithAny cfg s queries = SBV.proveConcurrentWithAny cfg queries (toSBool <$> s)
+
 -- | Find a satisfying assignment to a property with multiple solvers,
 -- running them in separate threads. The results will be returned in
 -- the order produced.
-satWithAll :: [SMTConfig] -> Symbolic SVal -> IO [(Solver, SatResult)]
-satWithAll cfgs s = SBV.satWithAll cfgs (fmap toSBool s)
+satWithAll :: [SMTConfig] -> Symbolic SVal -> IO [(Solver, NominalDiffTime, SatResult)]
+satWithAll cfgs s = SBV.satWithAll cfgs (toSBool <$> s)
 
 -- | Find a satisfying assignment to a property with multiple solvers,
 -- running them in separate threads. Only the result of the first one
 -- to finish will be returned, remaining threads will be killed.
-satWithAny :: [SMTConfig] -> Symbolic SVal -> IO (Solver, SatResult)
-satWithAny cfgs s = SBV.satWithAny cfgs (fmap toSBool s)
+satWithAny :: [SMTConfig] -> Symbolic SVal -> IO (Solver, NominalDiffTime, SatResult)
+satWithAny cfgs s = SBV.satWithAny cfgs (toSBool <$> s)
 
+-- | Find a satisfying assignment to a property with multiple threads in query
+-- mode. The 'Symbolic' t'SVal' represents what is known to all child query threads.
+-- Each query thread will spawn a unique instance of the solver. Only the first
+-- one to finish will be returned and the other threads will be killed.
+satConcurrentWithAny :: SMTConfig -> [Query b] -> Symbolic SVal -> IO (Solver, NominalDiffTime, SatResult)
+satConcurrentWithAny cfg qs s = SBV.satConcurrentWithAny cfg qs (toSBool <$> s)
+
+-- | Find a satisfying assignment to a property with multiple threads in query
+-- mode. The 'Symbolic' t'SVal' represents what is known to all child query threads.
+-- Each query thread will spawn a unique instance of the solver. This function
+-- will block until all child threads have completed.
+satConcurrentWithAll :: SMTConfig -> [Query b] -> Symbolic SVal -> IO [(Solver, NominalDiffTime, SatResult)]
+satConcurrentWithAll cfg qs s = SBV.satConcurrentWithAll cfg qs (toSBool <$> s)
+
 -- | Extract a model, the result is a tuple where the first argument (if True)
 -- indicates whether the model was "probable". (i.e., if the solver returned unknown.)
-getModel :: SMTResult -> Either String (Bool, [CW])
-getModel = SBV.getModel
+getModelAssignment :: SMTResult -> Either String (Bool, [CV])
+getModelAssignment = SBV.getModelAssignment
 
 -- | Extract a model dictionary. Extract a dictionary mapping the variables to
--- their respective values as returned by the SMT solver. Also see `getModelDictionaries`.
-getModelDictionary :: SMTResult -> Map String CW
+-- their respective values as returned by the SMT solver. Also see `Data.SBV.SMT.getModelDictionaries`.
+getModelDictionary :: SMTResult -> Map String CV
 getModelDictionary = SBV.getModelDictionary
+
+-- | Create a named fresh existential variable in the current context
+svNewVar :: MonadSymbolic m => Kind -> String -> m SVal
+svNewVar k n = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar (Just EX)) k (Just n)
+
+-- | Create an unnamed fresh existential variable in the current context
+svNewVar_ :: MonadSymbolic m => Kind -> m SVal
+svNewVar_ k = symbolicEnv >>= liftIO . svMkSymVar (NonQueryVar (Just EX)) k Nothing
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,185 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                 #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Either (
+    -- * Constructing sums
+      sLeft, sRight, liftEither, SEither, sEither, sEither_, sEithers
+    -- * Destructing sums
+    , either
+    -- * Mapping functions
+    , bimap, first, second
+    -- * Scrutinizing branches of a sum
+    , isLeft, isRight, fromLeft, fromRight
+    -- * Case analysis (for sCase quasi-quoter)
+    , sCaseEither, getLeft_1, getRight_1
+  ) where
+
+import           Prelude hiding (either)
+import qualified Prelude
+
+import Data.SBV.Client
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model (OrdSymbolic(..))
+import Data.SBV.SCase      (sCase)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Prelude hiding(either)
+-- >>> import Data.SBV
+#endif
+
+-- | Make 'Either' symbolic.
+--
+-- >>> sLeft 3 :: SEither Integer Bool
+-- Left 3 :: Either Integer Bool
+-- >>> isLeft (sLeft 3 :: SEither Integer Bool)
+-- True
+-- >>> isLeft (sRight sTrue :: SEither Integer Bool)
+-- False
+-- >>> sRight sFalse :: SEither Integer Bool
+-- Right False :: Either Integer Bool
+-- >>> isRight (sLeft 3 :: SEither Integer Bool)
+-- False
+-- >>> isRight (sRight sTrue :: SEither Integer Bool)
+-- True
+mkSymbolic [''Either]
+
+-- | Declare a symbolic either.
+sEither :: (SymVal a, SymVal b) => String -> Symbolic (SEither a b)
+sEither = free
+
+-- | Declare a symbolic either, unnamed.
+sEither_ :: (SymVal a, SymVal b) => Symbolic (SEither a b)
+sEither_ = free_
+
+-- | Declare a list of symbolic eithers.
+sEithers :: (SymVal a, SymVal b) => [String] -> Symbolic [SEither a b]
+sEithers = symbolics
+
+-- | Construct an @SEither a b@ from an @Either (SBV a) (SBV b)@
+--
+-- >>> liftEither (Left 3 :: Either SInteger SBool)
+-- Left 3 :: Either Integer Bool
+-- >>> liftEither (Right sTrue :: Either SInteger SBool)
+-- Right True :: Either 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 :: SInteger))
+-- 6 :: SInteger
+-- >>> either (*2) (*3) (sRight (3 :: SInteger))
+-- 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 = [sCase| sab of
+                        Left x  -> brA x
+                        Right x -> brB x
+                     |]
+
+-- | 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, i.e., it can return any 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 = 'A' :: 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 = getLeft_1
+
+-- | Return the value from the right component. The behavior is undefined if
+-- passed a left value, i.e., it can return any 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 2) :: SEither Integer Char))
+-- Satisfiable. Model:
+--   s0 = 'A' :: 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.
+fromRight :: forall a b. (SymVal a, SymVal b) => SEither a b -> SBV b
+fromRight = getRight_1
+
+-- | Custom 'OrdSymbolic' instance over 'SEither'.
+instance (OrdSymbolic (SBV a), OrdSymbolic (SBV b), SymVal a, SymVal b) => OrdSymbolic (SBV (Either a b)) where
+  eab .< ecd = either (\a -> either (a .<)         (const sTrue) ecd)
+                      (\b -> either (const sFalse) (b .<)        ecd)
+                      eab
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/Examples/BitPrecise/BitTricks.hs b/Data/SBV/Examples/BitPrecise/BitTricks.hs
deleted file mode 100644
--- a/Data/SBV/Examples/BitPrecise/BitTricks.hs
+++ /dev/null
@@ -1,59 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.BitPrecise.BitTricks
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Checks the correctness of a few tricks from the large collection found in:
---      <https://graphics.stanford.edu/~seander/bithacks.html>
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.BitPrecise.BitTricks where
-
-import Data.SBV
-
--- | Formalizes <https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax>
-fastMinCorrect :: SInt32 -> SInt32 -> SBool
-fastMinCorrect x y = m .== fm
-  where m  = ite (x .< y) x y
-        fm = y `xor` ((x `xor` y) .&. (-(oneIf (x .< y))));
-
--- | Formalizes <https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax>
-fastMaxCorrect :: SInt32 -> SInt32 -> SBool
-fastMaxCorrect x y = m .== fm
-  where m  = ite (x .< y) y x
-        fm = x `xor` ((x `xor` y) .&. (-(oneIf (x .< y))));
-
--- | Formalizes <https://graphics.stanford.edu/~seander/bithacks.html#DetectOppositeSigns>
-oppositeSignsCorrect :: SInt32 -> SInt32 -> SBool
-oppositeSignsCorrect x y = r .== os
-  where r  = (x .< 0 &&& y .>= 0) ||| (x .>= 0 &&& y .< 0)
-        os = (x `xor` y) .< 0
-
--- | Formalizes <https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching>
-conditionalSetClearCorrect :: SBool -> SWord32 -> SWord32 -> SBool
-conditionalSetClearCorrect f m w = r .== r'
-  where r  = ite f (w .|. m) (w .&. complement m)
-        r' = w `xor` ((-(oneIf f) `xor` w) .&. m);
-
--- | Formalizes <https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2>
-powerOfTwoCorrect :: SWord32 -> SBool
-powerOfTwoCorrect v = f .== s
-  where f = (v ./= 0) &&& ((v .&. (v-1)) .== 0);
-        powers :: [Word32]
-        powers = map ((2::Word32)^) [(0::Word32) .. 31]
-        s = bAny (v .==) $ map literal powers
-
--- | Collection of queries
-queries :: IO ()
-queries =
-  let check :: Provable a => String -> a -> IO ()
-      check w t = do putStr $ "Proving " ++ show w ++ ": "
-                     print =<< prove t
-  in do check "Fast min             " fastMinCorrect
-        check "Fast max             " fastMaxCorrect
-        check "Opposite signs       " oppositeSignsCorrect
-        check "Conditional set/clear" conditionalSetClearCorrect
-        check "PowerOfTwo           " powerOfTwoCorrect
diff --git a/Data/SBV/Examples/BitPrecise/Legato.hs b/Data/SBV/Examples/BitPrecise/Legato.hs
deleted file mode 100644
--- a/Data/SBV/Examples/BitPrecise/Legato.hs
+++ /dev/null
@@ -1,307 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.BitPrecise.Legato
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- An encoding and correctness proof of Legato's multiplier in Haskell. Bill Legato came
--- up with an interesting way to multiply two 8-bit numbers on Mostek, as described here:
---   <http://www.cs.utexas.edu/~moore/acl2/workshop-2004/contrib/legato/Weakest-Preconditions-Report.pdf>
---
--- Here's Legato's algorithm, as coded in Mostek assembly:
---
--- @
---    step1 :       LDX #8         ; load X immediate with the integer 8 
---    step2 :       LDA #0         ; load A immediate with the integer 0 
---    step3 : LOOP  ROR F1         ; rotate F1 right circular through C 
---    step4 :       BCC ZCOEF      ; branch to ZCOEF if C = 0 
---    step5 :       CLC            ; set C to 0 
---    step6 :       ADC F2         ; set A to A+F2+C and C to the carry 
---    step7 : ZCOEF ROR A          ; rotate A right circular through C 
---    step8 :       ROR LOW        ; rotate LOW right circular through C 
---    step9 :       DEX            ; set X to X-1 
---    step10:       BNE LOOP       ; branch to LOOP if Z = 0 
--- @
---
--- This program came to be known as the Legato's challenge in the community, where
--- the challenge was to prove that it indeed does perform multiplication. This file
--- formalizes the Mostek architecture in Haskell and proves that Legato's algorithm
--- is indeed correct.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveGeneric  #-}
-{-# LANGUAGE DeriveAnyClass #-}
-
-module Data.SBV.Examples.BitPrecise.Legato where
-
-import Data.Array (Array, Ix(..), (!), (//), array)
-
-import Data.SBV
-
-import GHC.Generics (Generic)
-
-------------------------------------------------------------------
--- * Mostek architecture
-------------------------------------------------------------------
--- | The memory is addressed by 32-bit words.
-type Address  = SWord32
-
--- | We model only two registers of Mostek that is used in the above algorithm, can add more.
-data Register = RegX  | RegA  deriving (Eq, Ord, Ix, Bounded, Enum)
-
--- | The carry flag ('FlagC') and the zero flag ('FlagZ')
-data Flag = FlagC | FlagZ deriving (Eq, Ord, Ix, Bounded, Enum)
-
--- | Mostek was an 8-bit machine.
-type Value = SWord8
-
--- | Convenient synonym for symbolic machine bits.
-type Bit = SBool
-
--- | Register bank
-type Registers = Array Register Value
-
--- | Flag bank
-type Flags = Array Flag Bit
-
--- | The memory maps 32-bit words to 8-bit words. (The 'Model' data-type is
--- defined later, depending on the verification model used.)
-type Memory = Model Word32 Word8        -- Model defined later
-
--- | Abstraction of the machine: The CPU consists of memory, registers, and flags.
--- Unlike traditional hardware, we assume the program is stored in some other memory area that
--- we need not model. (No self modifying programs!)
---
--- 'Mostek' is equipped with an automatically derived 'Mergeable' instance
--- because each field is 'Mergeable'.
-data Mostek = Mostek { memory    :: Memory
-                     , registers :: Registers
-                     , flags     :: Flags
-                     } deriving (Generic, Mergeable)
-
--- | Given a machine state, compute a value out of it
-type Extract a = Mostek -> a
-
--- | Programs are essentially state transformers (on the machine state)
-type Program = Mostek -> Mostek
-
-------------------------------------------------------------------
--- * Low-level operations
-------------------------------------------------------------------
-
--- | Get the value of a given register
-getReg :: Register -> Extract Value
-getReg r m = registers m ! r
-
--- | Set the value of a given register
-setReg :: Register -> Value -> Program
-setReg r v m = m {registers = registers m // [(r, v)]}
-
--- | Get the value of a flag
-getFlag :: Flag -> Extract Bit
-getFlag f m = flags m ! f
-
--- | Set the value of a flag
-setFlag :: Flag -> Bit -> Program
-setFlag f b m = m {flags = flags m // [(f, b)]}
-
--- | Read memory
-peek :: Address -> Extract Value
-peek a m = readArray (memory m) a
-
--- | Write to memory
-poke :: Address -> Value -> Program
-poke a v m = m {memory = writeArray (memory m) a v}
-
--- | Checking overflow. In Legato's multipler the @ADC@ instruction
--- needs to see if the expression x + y + c overflowed, as checked
--- by this function. Note that we verify the correctness of this check
--- separately below in `checkOverflowCorrect`.
-checkOverflow :: SWord8 -> SWord8 -> SBool -> SBool
-checkOverflow x y c = s .< x ||| s .< y ||| s' .< s
-  where s  = x + y
-        s' = s + ite c 1 0
-
--- | Correctness theorem for our `checkOverflow` implementation.
---
---   We have:
---
---   >>> checkOverflowCorrect
---   Q.E.D.
-checkOverflowCorrect :: IO ThmResult
-checkOverflowCorrect = checkOverflow === overflow
-  where -- Reference spec for overflow. We do the addition
-        -- using 16 bits and check that it's larger than 255
-        overflow :: SWord8 -> SWord8 -> SBool -> SBool
-        overflow x y c = (0 # x) + (0 # y) + ite c 1 0 .> 255
-------------------------------------------------------------------
--- * Instruction set
-------------------------------------------------------------------
-
--- | An instruction is modeled as a 'Program' transformer. We model
--- mostek programs in direct continuation passing style.
-type Instruction = Program -> Program
-
--- | LDX: Set register @X@ to value @v@
-ldx :: Value -> Instruction
-ldx v k = k . setReg RegX v
-
--- | LDA: Set register @A@ to value @v@
-lda :: Value -> Instruction
-lda v k = k . setReg RegA v
-
--- | CLC: Clear the carry flag
-clc :: Instruction
-clc k = k . setFlag FlagC false
-
--- | ROR, memory version: Rotate the value at memory location @a@
--- to the right by 1 bit, using the carry flag as a transfer position.
--- That is, the final bit of the memory location becomes the new carry
--- and the carry moves over to the first bit. This very instruction
--- is one of the reasons why Legato's multiplier is quite hard to understand
--- and is typically presented as a verification challenge.
-rorM :: Address -> Instruction
-rorM a k m = k . setFlag FlagC c' . poke a v' $ m
-  where v  = peek a m
-        c  = getFlag FlagC m
-        v' = setBitTo (v `rotateR` 1) 7 c
-        c' = sTestBit v 0
-
--- | ROR, register version: Same as 'rorM', except through register @r@.
-rorR :: Register -> Instruction
-rorR r k m = k . setFlag FlagC c' . setReg r v' $ m
-  where v  = getReg r m
-        c  = getFlag FlagC m
-        v' = setBitTo (v `rotateR` 1) 7 c
-        c' = sTestBit v 0
-
--- | BCC: branch to label @l@ if the carry flag is false
-bcc :: Program -> Instruction
-bcc l k m = ite (c .== false) (l m) (k m)
-  where c = getFlag FlagC m
-
--- | ADC: Increment the value of register @A@ by the value of memory contents
--- at address @a@, using the carry-bit as the carry-in for the addition.
-adc :: Address -> Instruction
-adc a k m = k . setFlag FlagZ (v' .== 0) . setFlag FlagC c' . setReg RegA v' $ m
-  where v  = peek a m
-        ra = getReg RegA m
-        c  = getFlag FlagC m
-        v' = v + ra + ite c 1 0
-        c' = checkOverflow v ra c
-
--- | DEX: Decrement the value of register @X@
-dex :: Instruction
-dex k m = k . setFlag FlagZ (x .== 0) . setReg RegX x $ m
-  where x = getReg RegX m - 1
-
--- | BNE: Branch if the zero-flag is false
-bne :: Program -> Instruction
-bne l k m = ite (z .== false) (l m) (k m)
-  where z = getFlag FlagZ m
-
--- | The 'end' combinator "stops" our program, providing the final continuation
--- that does nothing.
-end :: Program
-end = id
-
-------------------------------------------------------------------
--- * Legato's algorithm in Haskell/SBV
-------------------------------------------------------------------
-
--- | Parameterized by the addresses of locations of the factors (@F1@ and @F2@),
--- the following program multiplies them, storing the low-byte of the result
--- in the memory location @lowAddr@, and the high-byte in register @A@. The
--- implementation is a direct transliteration of Legato's algorithm given
--- at the top, using our notation.
-legato :: Address -> Address -> Address -> Program
-legato f1Addr f2Addr lowAddr = start
-  where start   =    ldx 8
-                   $ lda 0
-                   $ loop
-        loop    =    rorM f1Addr
-                   $ bcc zeroCoef
-                   $ clc
-                   $ adc f2Addr
-                   $ zeroCoef
-        zeroCoef =   rorR RegA
-                   $ rorM lowAddr
-                   $ dex
-                   $ bne loop
-                   $ end
-
-------------------------------------------------------------------
--- * Verification interface
-------------------------------------------------------------------
--- | Given address/value pairs for F1 and F2, and the location of where the low-byte
--- of the result should go, @runLegato@ takes an arbitrary machine state @m@ and
--- returns the high and low bytes of the multiplication.
-runLegato :: (Address, Value) -> (Address, Value) -> Address -> Mostek -> (Value, Value)
-runLegato (f1Addr, f1Val) (f2Addr, f2Val) loAddr m = (getReg RegA mFinal, peek loAddr mFinal)
-  where m0     = poke f1Addr f1Val $ poke f2Addr f2Val m
-        mFinal = legato f1Addr f2Addr loAddr m0
-
--- | Helper synonym for capturing relevant bits of Mostek
-type InitVals = ( Value      -- Content of Register X
-                , Value      -- Content of Register A
-                , Value      -- Initial contents of memory
-                , Bit        -- Value of FlagC
-                , Bit        -- Value of FlagZ
-                )
-
--- | Create an instance of the Mostek machine, initialized by the memory and the relevant
--- values of the registers and the flags
-initMachine :: Memory -> InitVals -> Mostek
-initMachine mem (rx, ra, mc, fc, fz) = Mostek { memory    = resetArray mem mc
-                                              , registers = array (minBound, maxBound) [(RegX, rx),  (RegA, ra)]
-                                              , flags     = array (minBound, maxBound) [(FlagC, fc), (FlagZ, fz)]
-                                              }
-
--- | The correctness theorem. For all possible memory configurations, the factors (@x@ and @y@ below), the location
--- of the low-byte result and the initial-values of registers and the flags, this function will return True only if
--- running Legato's algorithm does indeed compute the product of @x@ and @y@ correctly.
-legatoIsCorrect :: Memory -> (Address, Value) -> (Address, Value) -> Address -> InitVals -> SBool
-legatoIsCorrect mem (addrX, x) (addrY, y) addrLow initVals
-        = allDifferent [addrX, addrY, addrLow]    -- note the conditional: addresses must be distinct!
-                ==> result .== expected
-    where (hi, lo) = runLegato (addrX, x) (addrY, y) addrLow (initMachine mem initVals)
-          -- NB. perform the comparison over 16 bit values to avoid overflow!
-          -- If Value changes to be something else, modify this accordingly.
-          result, expected :: SWord16
-          result   = 256 * (0 # hi) + (0 # lo)
-          expected = (0 # x) * (0 # y)
-
-------------------------------------------------------------------
--- * Verification
-------------------------------------------------------------------
-
--- | Choose the appropriate array model to be used for modeling the memory. (See 'Memory'.)
--- The 'SFunArray' is the function based model. 'SArray' is the SMT-Lib array's based model.
-type Model = SFunArray
--- type Model = SArray
-
--- | The correctness theorem.
---   On a decent MacBook Pro, this proof takes about 3 minutes with the 'SFunArray' memory model
---   and about 30 minutes with the 'SArray' model, using yices as the SMT solver
-correctnessTheorem :: IO ThmResult
-correctnessTheorem = proveWith yices{timing = PrintTiming} $
-    forAll ["mem", "addrX", "x", "addrY", "y", "addrLow", "regX", "regA", "memVals", "flagC", "flagZ"]
-           legatoIsCorrect
-
-------------------------------------------------------------------
--- * C Code generation
-------------------------------------------------------------------
-
--- | Generate a C program that implements Legato's algorithm automatically.
-legatoInC :: IO ()
-legatoInC = compileToC Nothing "runLegato" $ do
-                x <- cgInput "x"
-                y <- cgInput "y"
-                let (hi, lo) = runLegato (0, x) (1, y) 2 (initMachine (mkSFunArray (const 0)) (0, 0, 0, false, false))
-                cgOutput "hi" hi
-                cgOutput "lo" lo
-
-{-# ANN legato ("HLint: ignore Redundant $" :: String)        #-}
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/Examples/BitPrecise/MergeSort.hs b/Data/SBV/Examples/BitPrecise/MergeSort.hs
deleted file mode 100644
--- a/Data/SBV/Examples/BitPrecise/MergeSort.hs
+++ /dev/null
@@ -1,94 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.BitPrecise.MergeSort
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Symbolic implementation of merge-sort and its correctness.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.BitPrecise.MergeSort where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Implementing Merge-Sort
------------------------------------------------------------------------------
--- | Element type of lists we'd like to sort. For simplicity, we'll just
--- use 'SWord8' here, but we can pick any symbolic type.
-type E = SWord8
-
--- | Merging two given sorted lists, preserving the order.
-merge :: [E] -> [E] -> [E]
-merge []     ys           = ys
-merge xs     []           = xs
-merge xs@(x:xr) ys@(y:yr) = ite (x .< y) (x : merge xr ys) (y : merge xs yr)
-
--- | Simple merge-sort implementation. We simply divide the input list
--- in two two halves so long as it has at least two elements, sort
--- each half on its own, and then merge.
-mergeSort :: [E] -> [E]
-mergeSort []  = []
-mergeSort [x] = [x]
-mergeSort xs  = merge (mergeSort th) (mergeSort bh)
-   where (th, bh) = splitAt (length xs `div` 2) xs
-
------------------------------------------------------------------------------
--- * Proving correctness
--- ${props}
------------------------------------------------------------------------------
-{- $props
-There are two main parts to proving that a sorting algorithm is correct:
-
-       * Prove that the output is non-decreasing
- 
-       * Prove that the output is a permutation of the input
--}
-
--- | Check whether a given sequence is non-decreasing.
-nonDecreasing :: [E] -> SBool
-nonDecreasing []       = true
-nonDecreasing [_]      = true
-nonDecreasing (a:b:xs) = a .<= b &&& nonDecreasing (b:xs)
-
--- | Check whether two given sequences are permutations. We simply check that each sequence
--- is a subset of the other, when considered as a set. The check is slightly complicated
--- for the need to account for possibly duplicated elements.
-isPermutationOf :: [E] -> [E] -> SBool
-isPermutationOf as bs = go as (zip bs (repeat true)) &&& go bs (zip as (repeat true))
-  where go []     _  = true
-        go (x:xs) ys = let (found, ys') = mark x ys in found &&& go xs ys'
-        -- Go and mark off an instance of 'x' in the list, if possible. We keep track
-        -- of unmarked elements by associating a boolean bit. Note that we have to
-        -- keep the lists equal size for the recursive result to merge properly.
-        mark _ []         = (false, [])
-        mark x ((y,v):ys) = ite (v &&& x .== y)
-                                (true, (y, bnot v):ys)
-                                (let (r, ys') = mark x ys in (r, (y,v):ys'))
-
--- | Asserting correctness of merge-sort for a list of the given size. Note that we can
--- only check correctness for fixed-size lists. Also, the proof will get more and more
--- complicated for the backend SMT solver as 'n' increases. A value around 5 or 6 should
--- be fairly easy to prove. For instance, we have:
---
--- >>> correctness 5
--- Q.E.D.
-correctness :: Int -> IO ThmResult
-correctness n = prove $ do xs <- mkFreeVars n
-                           let ys = mergeSort xs
-                           return $ nonDecreasing ys &&& isPermutationOf xs ys
-
------------------------------------------------------------------------------
--- * Generating C code
------------------------------------------------------------------------------
-
--- | Generate C code for merge-sorting an array of size 'n'. Again, we're restricted
--- to fixed size inputs. While the output is not how one would code merge sort in C
--- by hand, it's a faithful rendering of all the operations merge-sort would do as
--- described by its Haskell counterpart.
-codeGen :: Int -> IO ()
-codeGen n = compileToC (Just ("mergeSort" ++ show n)) "mergeSort" $ do
-                xs <- cgInputArr n "xs"
-                cgOutputArr "ys" (mergeSort xs)
diff --git a/Data/SBV/Examples/BitPrecise/MultMask.hs b/Data/SBV/Examples/BitPrecise/MultMask.hs
deleted file mode 100644
--- a/Data/SBV/Examples/BitPrecise/MultMask.hs
+++ /dev/null
@@ -1,50 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.BitPrecise.MultMask
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- An SBV solution to the bit-precise puzzle of shuffling the bits in a
--- 64-bit word in a custom order. The idea is to take a 64-bit value:
---
---    @1.......2.......3.......4.......5.......6.......7.......8.......@
---
--- And turn it into another 64-bit value, that looks like this:
---
---    @12345678........................................................@
---
--- We do not care what happens to the bits that are represented by dots. The
--- problem is to do this with one mask and one multiplication.
---
--- Apparently this operation has several applications, including in programs
--- that play chess of all things. We use SBV to find the appropriate mask and
--- the multiplier.
---
--- Note that this is an instance of the program synthesis problem, where
--- we "fill in the blanks" given a certain skeleton that satisfy a certain
--- property, using quantified formulas.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.BitPrecise.MultMask where
-
-import Data.SBV
-
--- | Find the multiplier and the mask as described. We have:
---
--- >>> maskAndMult
--- Satisfiable. Model:
---   mask = 0x8080808080808080 :: Word64
---   mult = 0x0002040810204081 :: Word64
---
--- 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.
-maskAndMult :: IO ()
-maskAndMult = print =<< satWith z3{printBase=16} find
-  where find = do mask <- exists "mask"
-                  mult <- exists "mult"
-                  inp  <- forall "inp"
-                  let res = (mask .&. inp) * (mult :: SWord64)
-                  solve [inp `sExtractBits` [7, 15 .. 63] .== res `sExtractBits` [56 .. 63]]
diff --git a/Data/SBV/Examples/BitPrecise/PrefixSum.hs b/Data/SBV/Examples/BitPrecise/PrefixSum.hs
deleted file mode 100644
--- a/Data/SBV/Examples/BitPrecise/PrefixSum.hs
+++ /dev/null
@@ -1,194 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.BitPrecise.PrefixSum
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- The PrefixSum algorithm over power-lists and proof of
--- the Ladner-Fischer implementation.
--- See <http://dl.acm.org/citation.cfm?id=197356>
--- and <http://www.cs.utexas.edu/~plaxton/c/337/05f/slides/ParallelRecursion-4.pdf>.
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.Examples.BitPrecise.PrefixSum where
-
-import Data.SBV
-import Data.SBV.Internals (runSymbolic)
-
-----------------------------------------------------------------------
--- * Formalizing power-lists
-----------------------------------------------------------------------
-
--- | A poor man's representation of powerlists and
--- basic operations on them: <http://dl.acm.org/citation.cfm?id=197356>
--- We merely represent power-lists by ordinary lists.
-type PowerList a = [a]
-
--- | The tie operator, concatenation.
-tiePL :: PowerList a -> PowerList a -> PowerList a
-tiePL = (++)
-
--- | The zip operator, zips the power-lists of the same size, returns
--- a powerlist of double the size.
-zipPL :: PowerList a -> PowerList a -> PowerList a
-zipPL []     []     = []
-zipPL (x:xs) (y:ys) = x : y : zipPL xs ys
-zipPL _      _      = error "zipPL: nonsimilar powerlists received"
-
--- | Inverse of zipping.
-unzipPL :: PowerList a -> (PowerList a, PowerList a)
-unzipPL = unzip . chunk2
-  where chunk2 []       = []
-        chunk2 (x:y:xs) = (x,y) : chunk2 xs
-        chunk2 _        = error "unzipPL: malformed powerlist"
-
-----------------------------------------------------------------------
--- * Reference prefix-sum implementation
-----------------------------------------------------------------------
-
--- | Reference prefix sum (@ps@) is simply Haskell's @scanl1@ function.
-ps :: (a, a -> a -> a) -> PowerList a -> PowerList a
-ps (_, f) = scanl1 f
-
-----------------------------------------------------------------------
--- * The Ladner-Fischer parallel version
-----------------------------------------------------------------------
-
--- | The Ladner-Fischer (@lf@) implementation of prefix-sum. See <http://www.cs.utexas.edu/~plaxton/c/337/05f/slides/ParallelRecursion-4.pdf>
--- or pg. 16 of <http://dl.acm.org/citation.cfm?id=197356>
-lf :: (a, a -> a -> a) -> PowerList a -> PowerList a
-lf _ []         = error "lf: malformed (empty) powerlist"
-lf _ [x]        = [x]
-lf (zero, f) pl = zipPL (zipWith f (rsh lfpq) p) lfpq
-   where (p, q) = unzipPL pl
-         pq     = zipWith f p q
-         lfpq   = lf (zero, f) pq
-         rsh xs = zero : init xs
-
-
-----------------------------------------------------------------------
--- * Sample proofs for concrete operators
-----------------------------------------------------------------------
-
--- | Correctness theorem, for a powerlist of given size, an associative operator, and its left-unit element.
-flIsCorrect :: Int -> (forall a. (OrdSymbolic a, Num a, Bits a) => (a, a -> a -> a)) -> Symbolic SBool
-flIsCorrect n zf = do
-        args :: PowerList SWord32 <- mkForallVars n
-        return $ ps zf args .== lf zf args
-
--- | Proves Ladner-Fischer is equivalent to reference specification for addition.
--- @0@ is the left-unit element, and we use a power-list of size @8@.
-thm1 :: IO ThmResult
-thm1 = prove $ flIsCorrect  8 (0, (+))
-
--- | Proves Ladner-Fischer is equivalent to reference specification for the function @max@.
--- @0@ is the left-unit element, and we use a power-list of size @16@.
-thm2 :: IO ThmResult
-thm2 = prove $ flIsCorrect 16 (0, smax)
-
-----------------------------------------------------------------------
--- * Inspecting symbolic traces
-----------------------------------------------------------------------
-
--- | A symbolic trace can help illustrate the action of Ladner-Fischer. This
--- generator produces the actions of Ladner-Fischer for addition, showing how
--- the computation proceeds:
---
--- >>> ladnerFischerTrace 8
--- INPUTS
---   s0 :: SWord8
---   s1 :: SWord8
---   s2 :: SWord8
---   s3 :: SWord8
---   s4 :: SWord8
---   s5 :: SWord8
---   s6 :: SWord8
---   s7 :: SWord8
--- CONSTANTS
---   s_2 = False :: Bool
---   s_1 = True :: Bool
--- TABLES
--- ARRAYS
--- UNINTERPRETED CONSTANTS
--- USER GIVEN CODE SEGMENTS
--- AXIOMS
--- DEFINE
---   s8 :: SWord8 = s0 + s1
---   s9 :: SWord8 = s2 + s8
---   s10 :: SWord8 = s2 + s3
---   s11 :: SWord8 = s8 + s10
---   s12 :: SWord8 = s4 + s11
---   s13 :: SWord8 = s4 + s5
---   s14 :: SWord8 = s11 + s13
---   s15 :: SWord8 = s6 + s14
---   s16 :: SWord8 = s6 + s7
---   s17 :: SWord8 = s13 + s16
---   s18 :: SWord8 = s11 + s17
--- CONSTRAINTS
--- ASSERTIONS
--- OUTPUTS
---   s0
---   s8
---   s9
---   s11
---   s12
---   s14
---   s15
---   s18
-ladnerFischerTrace :: Int -> IO ()
-ladnerFischerTrace n = gen >>= print
-  where gen = runSymbolic (True, defaultSMTCfg) $ do args :: [SWord8] <- mkForallVars n
-                                                     mapM_ output $ lf (0, (+)) args
-
--- | Trace generator for the reference spec. It clearly demonstrates that the reference
--- implementation fewer operations, but is not parallelizable at all:
---
--- >>> scanlTrace 8
--- INPUTS
---   s0 :: SWord8
---   s1 :: SWord8
---   s2 :: SWord8
---   s3 :: SWord8
---   s4 :: SWord8
---   s5 :: SWord8
---   s6 :: SWord8
---   s7 :: SWord8
--- CONSTANTS
---   s_2 = False :: Bool
---   s_1 = True :: Bool
--- TABLES
--- ARRAYS
--- UNINTERPRETED CONSTANTS
--- USER GIVEN CODE SEGMENTS
--- AXIOMS
--- DEFINE
---   s8 :: SWord8 = s0 + s1
---   s9 :: SWord8 = s2 + s8
---   s10 :: SWord8 = s3 + s9
---   s11 :: SWord8 = s4 + s10
---   s12 :: SWord8 = s5 + s11
---   s13 :: SWord8 = s6 + s12
---   s14 :: SWord8 = s7 + s13
--- CONSTRAINTS
--- ASSERTIONS
--- OUTPUTS
---   s0
---   s8
---   s9
---   s10
---   s11
---   s12
---   s13
---   s14
---
-scanlTrace :: Int -> IO ()
-scanlTrace n = gen >>= print
-  where gen = runSymbolic (True, defaultSMTCfg) $ do args :: [SWord8] <- mkForallVars n
-                                                     mapM_ output $ ps (0, (+)) args
-
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/Examples/CodeGeneration/AddSub.hs b/Data/SBV/Examples/CodeGeneration/AddSub.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/AddSub.hs
+++ /dev/null
@@ -1,140 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.AddSub
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Simple code generation example.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.AddSub where
-
-import Data.SBV
-
--- | Simple function that returns add/sum of args
-addSub :: SWord8 -> SWord8 -> (SWord8, SWord8)
-addSub x y = (x+y, x-y)
-
--- | Generate C code for addSub. Here's the output showing the generated C code:
---
--- >>> genAddSub
--- == BEGIN: "Makefile" ================
--- # Makefile for addSub. Automatically generated by SBV. Do not edit!
--- <BLANKLINE>
--- # include any user-defined .mk file in the current directory.
--- -include *.mk
--- <BLANKLINE>
--- CC?=gcc
--- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
--- <BLANKLINE>
--- all: addSub_driver
--- <BLANKLINE>
--- addSub.o: addSub.c addSub.h
--- 	${CC} ${CCFLAGS} -c $< -o $@
--- <BLANKLINE>
--- addSub_driver.o: addSub_driver.c
--- 	${CC} ${CCFLAGS} -c $< -o $@
--- <BLANKLINE>
--- addSub_driver: addSub.o addSub_driver.o
--- 	${CC} ${CCFLAGS} $^ -o $@
--- <BLANKLINE>
--- clean:
--- 	rm -f *.o
--- <BLANKLINE>
--- veryclean: clean
--- 	rm -f addSub_driver
--- == END: "Makefile" ==================
--- == BEGIN: "addSub.h" ================
--- /* Header file for addSub. Automatically generated by SBV. Do not edit! */
--- <BLANKLINE>
--- #ifndef __addSub__HEADER_INCLUDED__
--- #define __addSub__HEADER_INCLUDED__
--- <BLANKLINE>
--- #include <stdio.h>
--- #include <stdlib.h>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <string.h>
--- #include <math.h>
--- <BLANKLINE>
--- /* The boolean type */
--- typedef bool SBool;
--- <BLANKLINE>
--- /* The float type */
--- typedef float SFloat;
--- <BLANKLINE>
--- /* The double type */
--- typedef double SDouble;
--- <BLANKLINE>
--- /* Unsigned bit-vectors */
--- typedef uint8_t  SWord8 ;
--- typedef uint16_t SWord16;
--- typedef uint32_t SWord32;
--- typedef uint64_t SWord64;
--- <BLANKLINE>
--- /* Signed bit-vectors */
--- typedef int8_t  SInt8 ;
--- typedef int16_t SInt16;
--- typedef int32_t SInt32;
--- typedef int64_t SInt64;
--- <BLANKLINE>
--- /* Entry point prototype: */
--- void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
---             SWord8 *dif);
--- <BLANKLINE>
--- #endif /* __addSub__HEADER_INCLUDED__ */
--- == END: "addSub.h" ==================
--- == BEGIN: "addSub_driver.c" ================
--- /* Example driver program for addSub. */
--- /* Automatically generated by SBV. Edit as you see fit! */
--- <BLANKLINE>
--- #include <stdio.h>
--- #include "addSub.h"
--- <BLANKLINE>
--- int main(void)
--- {
---   SWord8 sum;
---   SWord8 dif;
--- <BLANKLINE>
---   addSub(132, 241, &sum, &dif);
--- <BLANKLINE>
---   printf("addSub(132, 241, &sum, &dif) ->\n");
---   printf("  sum = %"PRIu8"\n", sum);
---   printf("  dif = %"PRIu8"\n", dif);
--- <BLANKLINE>
---   return 0;
--- }
--- == END: "addSub_driver.c" ==================
--- == BEGIN: "addSub.c" ================
--- /* File: "addSub.c". Automatically generated by SBV. Do not edit! */
--- <BLANKLINE>
--- #include "addSub.h"
--- <BLANKLINE>
--- void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
---             SWord8 *dif)
--- {
---   const SWord8 s0 = x;
---   const SWord8 s1 = y;
---   const SWord8 s2 = s0 + s1;
---   const SWord8 s3 = s0 - s1;
--- <BLANKLINE>
---   *sum = s2;
---   *dif = s3;
--- }
--- == END: "addSub.c" ==================
---
-genAddSub :: IO ()
-genAddSub = compileToC outDir "addSub" $ do
-        x <- cgInput "x"
-        y <- cgInput "y"
-        -- leave the cgDriverVals call out for generating a driver with random values
-        cgSetDriverValues [132, 241]
-        let (s, d) = addSub x y
-        cgOutput "sum" s
-        cgOutput "dif" d
- where -- use Just "dirName" for putting the output to the named directory
-       -- otherwise, it'll go to standard output
-       outDir = Nothing
diff --git a/Data/SBV/Examples/CodeGeneration/CRC_USB5.hs b/Data/SBV/Examples/CodeGeneration/CRC_USB5.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/CRC_USB5.hs
+++ /dev/null
@@ -1,85 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.CRC_USB5
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computing the CRC symbolically, using the USB polynomial. We also
--- generating C code for it as well. This example demonstrates the
--- use of the 'crcBV' function, along with how CRC's can be computed
--- mathematically using polynomial division. While the results are the
--- same (i.e., proven equivalent, see 'crcGood' below), the internal
--- CRC implementation generates much better code, compare 'cg1' vs 'cg2' below.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.CRC_USB5 where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * The USB polynomial
------------------------------------------------------------------------------
-
--- | The USB CRC polynomial: @x^5 + x^2 + 1@.
--- Although this polynomial needs just 6 bits to represent (5 if higher
--- order bit is implicitly assumed to be set), we'll simply use a 16 bit
--- number for its representation to keep things simple for code generation
--- purposes.
-usb5 :: SWord16
-usb5 = polynomial [5, 2, 0]
-
------------------------------------------------------------------------------
--- * Computing CRCs
------------------------------------------------------------------------------
-
--- | Given an 11 bit message, compute the CRC of it using the USB polynomial,
--- which is 5 bits, and then append it to the msg to get a 16-bit word. Again,
--- the incoming 11-bits is represented as a 16-bit word, with 5 highest bits
--- essentially ignored for input purposes.
-crcUSB :: SWord16 -> SWord16
-crcUSB i = fromBitsBE (ib ++ cb)
-  where ib = drop 5  (blastBE i)    -- only the last 11 bits needed
-        pb = drop 11 (blastBE usb5) -- only the last  5 bits needed
-        cb = crcBV 5 ib pb
-
--- | Alternate method for computing the CRC, /mathematically/. We shift
--- the number to the left by 5, and then compute the remainder from the
--- polynomial division by the USB polynomial. The result is then appended
--- to the end of the message.
-crcUSB' :: SWord16 -> SWord16
-crcUSB' i' = i .|. pMod i usb5
-  where i = i' `shiftL` 5
-
------------------------------------------------------------------------------
--- * Correctness
------------------------------------------------------------------------------
-
--- | Prove that the custom 'crcBV' function is equivalent to the mathematical
--- definition of CRC's for 11 bit messages. We have:
---
--- >>> crcGood
--- Q.E.D.
-crcGood :: IO ThmResult
-crcGood = prove $ \i -> crcUSB i .== crcUSB' i
-
------------------------------------------------------------------------------
--- * Code generation
------------------------------------------------------------------------------
-
--- | Generate a C function to compute the USB CRC, using the internal CRC
--- function.
-cg1 :: IO ()
-cg1 = compileToC (Just "crcUSB1") "crcUSB1" $ do
-        msg <- cgInput "msg"
-        cgOutput "crc" (crcUSB msg)
-
--- | Generate a C function to compute the USB CRC, using the mathematical
--- definition of the CRCs. While this version generates functionally eqivalent
--- C code, it's less efficient; it has about 30% more code. So, the above
--- version is preferable for code generation purposes.
-cg2 :: IO ()
-cg2 = compileToC (Just "crcUSB2") "crcUSB2" $ do
-        msg <- cgInput "msg"
-        cgOutput "crc" (crcUSB' msg)
diff --git a/Data/SBV/Examples/CodeGeneration/Fibonacci.hs b/Data/SBV/Examples/CodeGeneration/Fibonacci.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/Fibonacci.hs
+++ /dev/null
@@ -1,175 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.Fibonacci
--- Copyright   :  (c) Lee Pike, Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computing Fibonacci numbers and generating C code. Inspired by Lee Pike's
--- original implementation, modified for inclusion in the package. It illustrates
--- symbolic termination issues one can have when working with recursive algorithms
--- and how to deal with such, eventually generating good C code.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.Fibonacci where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * A naive implementation
------------------------------------------------------------------------------
-
--- | This is a naive implementation of fibonacci, and will work fine (albeit slow)
--- for concrete inputs:
---
--- >>> map fib0 [0..6]
--- [0 :: SWord64,1 :: SWord64,1 :: SWord64,2 :: SWord64,3 :: SWord64,5 :: SWord64,8 :: SWord64]
---
--- However, it is not suitable for doing proofs or generating code, as it is not
--- symbolically terminating when it is called with a symbolic value @n@. When we
--- recursively call @fib0@ on @n-1@ (or @n-2@), the test against @0@ will always
--- explore both branches since the result will be symbolic, hence will not
--- terminate. (An integrated theorem prover can establish termination
--- after a certain number of unrollings, but this would be quite expensive to
--- implement, and would be impractical.)
-fib0 :: SWord64 -> SWord64
-fib0 n = ite (n .== 0 ||| n .== 1)
-             n
-             (fib0 (n-1) + fib0 (n-2))
-
------------------------------------------------------------------------------
--- * Using a recursion depth, and accumulating parameters
------------------------------------------------------------------------------
-
-{- $genLookup
-One way to deal with symbolic termination is to limit the number of recursive
-calls. In this version, we impose a limit on the index to the function, working
-correctly upto that limit. If we use a compile-time constant, then SBV's code generator
-can produce code as the unrolling will eventually stop.
--}
-
--- | The recursion-depth limited version of fibonacci. Limiting the maximum number to be 20, we can say:
---
--- >>> map (fib1 20) [0..6]
--- [0 :: SWord64,1 :: SWord64,1 :: SWord64,2 :: SWord64,3 :: SWord64,5 :: SWord64,8 :: SWord64]
---
--- The function will work correctly, so long as the index we query is at most @top@, and otherwise
--- will return the value at @top@. Note that we also use accumulating parameters here for efficiency,
--- although this is orthogonal to the termination concern.
---
--- A note on modular arithmetic: The 64-bit word we use to represent the values will of course
--- eventually overflow, beware! Fibonacci is a fast growing function..
-fib1 :: SWord64 -> SWord64 -> SWord64
-fib1 top n = fib' 0 1 0
-  where fib' :: SWord64 -> SWord64 -> SWord64 -> SWord64
-        fib' prev' prev m = ite (m .== top ||| m .== n)          -- did we reach recursion depth, or the index we're looking for
-                                prev'                            -- stop and return the result
-                                (fib' prev (prev' + prev) (m+1)) -- otherwise recurse
-
--- | We can generate code for 'fib1' using the 'genFib1' action. Note that the
--- generated code will grow larger as we pick larger values of @top@, but only linearly,
--- thanks to the accumulating parameter trick used by 'fib1'. The following is an excerpt
--- from the code generated for the call @genFib1 10@, where the code will work correctly
--- for indexes up to 10:
---
--- > SWord64 fib1(const SWord64 x)
--- > {
--- >   const SWord64 s0 = x;
--- >   const SBool   s2 = s0 == 0x0000000000000000ULL;
--- >   const SBool   s4 = s0 == 0x0000000000000001ULL;
--- >   const SBool   s6 = s0 == 0x0000000000000002ULL;
--- >   const SBool   s8 = s0 == 0x0000000000000003ULL;
--- >   const SBool   s10 = s0 == 0x0000000000000004ULL;
--- >   const SBool   s12 = s0 == 0x0000000000000005ULL;
--- >   const SBool   s14 = s0 == 0x0000000000000006ULL;
--- >   const SBool   s17 = s0 == 0x0000000000000007ULL;
--- >   const SBool   s19 = s0 == 0x0000000000000008ULL;
--- >   const SBool   s22 = s0 == 0x0000000000000009ULL;
--- >   const SWord64 s25 = s22 ? 0x0000000000000022ULL : 0x0000000000000037ULL;
--- >   const SWord64 s26 = s19 ? 0x0000000000000015ULL : s25;
--- >   const SWord64 s27 = s17 ? 0x000000000000000dULL : s26;
--- >   const SWord64 s28 = s14 ? 0x0000000000000008ULL : s27;
--- >   const SWord64 s29 = s12 ? 0x0000000000000005ULL : s28;
--- >   const SWord64 s30 = s10 ? 0x0000000000000003ULL : s29;
--- >   const SWord64 s31 = s8 ? 0x0000000000000002ULL : s30;
--- >   const SWord64 s32 = s6 ? 0x0000000000000001ULL : s31;
--- >   const SWord64 s33 = s4 ? 0x0000000000000001ULL : s32;
--- >   const SWord64 s34 = s2 ? 0x0000000000000000ULL : s33;
--- >   
--- >   return s34;
--- > }
-genFib1 :: SWord64 -> IO ()
-genFib1 top = compileToC Nothing "fib1" $ do
-        x <- cgInput "x"
-        cgReturn $ fib1 top x
-
------------------------------------------------------------------------------
--- * Generating a look-up table
------------------------------------------------------------------------------
-
-{- $genLookup
-While 'fib1' generates good C code, we can do much better by taking
-advantage of the inherent partial-evaluation capabilities of SBV to generate
-a look-up table, as follows.
--}
-
--- | Compute the fibonacci numbers statically at /code-generation/ time and
--- put them in a table, accessed by the 'select' call. 
-fib2 :: SWord64 -> SWord64 -> SWord64
-fib2 top = select table 0
-  where table = map (fib1 top) [0 .. top]
-
--- | Once we have 'fib2', we can generate the C code straightforwardly. Below
--- is an excerpt from the code that SBV generates for the call @genFib2 64@. Note
--- that this code is a constant-time look-up table implementation of fibonacci,
--- with no run-time overhead. The index can be made arbitrarily large,
--- naturally. (Note that this function returns @0@ if the index is larger
--- than 64, as specified by the call to 'select' with default @0@.)
---
--- > SWord64 fibLookup(const SWord64 x)
--- > {
--- >   const SWord64 s0 = x;
--- >   static const SWord64 table0[] = {
--- >       0x0000000000000000ULL, 0x0000000000000001ULL,
--- >       0x0000000000000001ULL, 0x0000000000000002ULL,
--- >       0x0000000000000003ULL, 0x0000000000000005ULL,
--- >       0x0000000000000008ULL, 0x000000000000000dULL,
--- >       0x0000000000000015ULL, 0x0000000000000022ULL,
--- >       0x0000000000000037ULL, 0x0000000000000059ULL,
--- >       0x0000000000000090ULL, 0x00000000000000e9ULL,
--- >       0x0000000000000179ULL, 0x0000000000000262ULL,
--- >       0x00000000000003dbULL, 0x000000000000063dULL,
--- >       0x0000000000000a18ULL, 0x0000000000001055ULL,
--- >       0x0000000000001a6dULL, 0x0000000000002ac2ULL,
--- >       0x000000000000452fULL, 0x0000000000006ff1ULL,
--- >       0x000000000000b520ULL, 0x0000000000012511ULL,
--- >       0x000000000001da31ULL, 0x000000000002ff42ULL,
--- >       0x000000000004d973ULL, 0x000000000007d8b5ULL,
--- >       0x00000000000cb228ULL, 0x0000000000148addULL,
--- >       0x0000000000213d05ULL, 0x000000000035c7e2ULL,
--- >       0x00000000005704e7ULL, 0x00000000008cccc9ULL,
--- >       0x0000000000e3d1b0ULL, 0x0000000001709e79ULL,
--- >       0x0000000002547029ULL, 0x0000000003c50ea2ULL,
--- >       0x0000000006197ecbULL, 0x0000000009de8d6dULL,
--- >       0x000000000ff80c38ULL, 0x0000000019d699a5ULL,
--- >       0x0000000029cea5ddULL, 0x0000000043a53f82ULL,
--- >       0x000000006d73e55fULL, 0x00000000b11924e1ULL,
--- >       0x000000011e8d0a40ULL, 0x00000001cfa62f21ULL,
--- >       0x00000002ee333961ULL, 0x00000004bdd96882ULL,
--- >       0x00000007ac0ca1e3ULL, 0x0000000c69e60a65ULL,
--- >       0x0000001415f2ac48ULL, 0x000000207fd8b6adULL,
--- >       0x0000003495cb62f5ULL, 0x0000005515a419a2ULL,
--- >       0x00000089ab6f7c97ULL, 0x000000dec1139639ULL,
--- >       0x000001686c8312d0ULL, 0x000002472d96a909ULL,
--- >       0x000003af9a19bbd9ULL, 0x000005f6c7b064e2ULL, 0x000009a661ca20bbULL
--- >   };
--- >   const SWord64 s65 = s0 >= 65 ? 0x0000000000000000ULL : table0[s0];
--- >   
--- >   return s65;
--- > }
-genFib2 :: SWord64 -> IO ()
-genFib2 top = compileToC Nothing "fibLookup" $ do
-        cgPerformRTCs True       -- protect against potential overflow, our table is not big enough
-        x <- cgInput "x"
-        cgReturn $ fib2 top x
diff --git a/Data/SBV/Examples/CodeGeneration/GCD.hs b/Data/SBV/Examples/CodeGeneration/GCD.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/GCD.hs
+++ /dev/null
@@ -1,145 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.GCD
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computing GCD symbolically, and generating C code for it. This example
--- illustrates symbolic termination related issues when programming with
--- SBV, when the termination of a recursive algorithm crucially depends
--- on the value of a symbolic variable. The technique we use is to statically
--- enforce termination by using a recursion depth counter.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.GCD where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Computing GCD
------------------------------------------------------------------------------
-
--- | The symbolic GCD algorithm, over two 8-bit numbers. We define @sgcd a 0@ to
--- be @a@ for all @a@, which implies @sgcd 0 0 = 0@. Note that this is essentially
--- Euclid's algorithm, except with a recursion depth counter. We need the depth
--- counter since the algorithm is not /symbolically terminating/, as we don't have
--- a means of determining that the second argument (@b@) will eventually reach 0 in a symbolic
--- context. Hence we stop after 12 iterations. Why 12? We've empirically determined that this
--- algorithm will recurse at most 12 times for arbitrary 8-bit numbers. Of course, this is
--- a claim that we shall prove below.
-sgcd :: SWord8 -> SWord8 -> SWord8
-sgcd a b = go a b 12
-  where go :: SWord8 -> SWord8 -> SWord8 -> SWord8
-        go x y c = ite (c .== 0 ||| y .== 0)   -- stop if y is 0, or if we reach the recursion depth
-                       x
-                       (go y y' (c-1))
-          where (_, y') = x `sQuotRem` y
-
------------------------------------------------------------------------------
--- * Verification
------------------------------------------------------------------------------
-
-{- $VerificationIntro
-We prove that 'sgcd' does indeed compute the common divisor of the given numbers.
-Our predicate takes @x@, @y@, and @k@. We show that what 'sgcd' returns is indeed a common divisor,
-and it is at least as large as any given @k@, provided @k@ is a common divisor as well.
--}
-
--- | We have:
---
--- >>> prove sgcdIsCorrect
--- Q.E.D.
-sgcdIsCorrect :: SWord8 -> SWord8 -> SWord8 -> SBool
-sgcdIsCorrect x y k = ite (y  .== 0)                        -- if y is 0
-                          (k' .== x)                        -- then k' must be x, nothing else to prove by definition
-                          (isCommonDivisor k'  &&&          -- otherwise, k' is a common divisor and
-                          (isCommonDivisor k ==> k' .>= k)) -- if k is a common divisor as well, then k' is at least as large as k
-  where k' = sgcd x y
-        isCommonDivisor a = z1 .== 0 &&& z2 .== 0
-           where (_, z1) = x `sQuotRem` a
-                 (_, z2) = y `sQuotRem` a
-
------------------------------------------------------------------------------
--- * Code generation
------------------------------------------------------------------------------
-
-{- $VerificationIntro
-Now that we have proof our 'sgcd' implementation is correct, we can go ahead
-and generate C code for it.
--}
-
--- | This call will generate the required C files. The following is the function
--- body generated for 'sgcd'. (We are not showing the generated header, @Makefile@,
--- and the driver programs for brevity.) Note that the generated function is
--- a constant time algorithm for GCD. It is not necessarily fastest, but it will take
--- precisely the same amount of time for all values of @x@ and @y@.
---
--- > /* File: "sgcd.c". Automatically generated by SBV. Do not edit! */
--- > 
--- > #include <stdio.h>
--- > #include <stdlib.h>
--- > #include <inttypes.h>
--- > #include <stdint.h>
--- > #include <stdbool.h>
--- > #include "sgcd.h"
--- > 
--- > SWord8 sgcd(const SWord8 x, const SWord8 y)
--- > {
--- >   const SWord8 s0 = x;
--- >   const SWord8 s1 = y;
--- >   const SBool  s3 = s1 == 0;
--- >   const SWord8 s4 = (s1 == 0) ? s0 : (s0 % s1);
--- >   const SWord8 s5 = s3 ? s0 : s4;
--- >   const SBool  s6 = 0 == s5;
--- >   const SWord8 s7 = (s5 == 0) ? s1 : (s1 % s5);
--- >   const SWord8 s8 = s6 ? s1 : s7;
--- >   const SBool  s9 = 0 == s8;
--- >   const SWord8 s10 = (s8 == 0) ? s5 : (s5 % s8);
--- >   const SWord8 s11 = s9 ? s5 : s10;
--- >   const SBool  s12 = 0 == s11;
--- >   const SWord8 s13 = (s11 == 0) ? s8 : (s8 % s11);
--- >   const SWord8 s14 = s12 ? s8 : s13;
--- >   const SBool  s15 = 0 == s14;
--- >   const SWord8 s16 = (s14 == 0) ? s11 : (s11 % s14);
--- >   const SWord8 s17 = s15 ? s11 : s16;
--- >   const SBool  s18 = 0 == s17;
--- >   const SWord8 s19 = (s17 == 0) ? s14 : (s14 % s17);
--- >   const SWord8 s20 = s18 ? s14 : s19;
--- >   const SBool  s21 = 0 == s20;
--- >   const SWord8 s22 = (s20 == 0) ? s17 : (s17 % s20);
--- >   const SWord8 s23 = s21 ? s17 : s22;
--- >   const SBool  s24 = 0 == s23;
--- >   const SWord8 s25 = (s23 == 0) ? s20 : (s20 % s23);
--- >   const SWord8 s26 = s24 ? s20 : s25;
--- >   const SBool  s27 = 0 == s26;
--- >   const SWord8 s28 = (s26 == 0) ? s23 : (s23 % s26);
--- >   const SWord8 s29 = s27 ? s23 : s28;
--- >   const SBool  s30 = 0 == s29;
--- >   const SWord8 s31 = (s29 == 0) ? s26 : (s26 % s29);
--- >   const SWord8 s32 = s30 ? s26 : s31;
--- >   const SBool  s33 = 0 == s32;
--- >   const SWord8 s34 = (s32 == 0) ? s29 : (s29 % s32);
--- >   const SWord8 s35 = s33 ? s29 : s34;
--- >   const SBool  s36 = 0 == s35;
--- >   const SWord8 s37 = s36 ? s32 : s35;
--- >   const SWord8 s38 = s33 ? s29 : s37;
--- >   const SWord8 s39 = s30 ? s26 : s38;
--- >   const SWord8 s40 = s27 ? s23 : s39;
--- >   const SWord8 s41 = s24 ? s20 : s40;
--- >   const SWord8 s42 = s21 ? s17 : s41;
--- >   const SWord8 s43 = s18 ? s14 : s42;
--- >   const SWord8 s44 = s15 ? s11 : s43;
--- >   const SWord8 s45 = s12 ? s8 : s44;
--- >   const SWord8 s46 = s9 ? s5 : s45;
--- >   const SWord8 s47 = s6 ? s1 : s46;
--- >   const SWord8 s48 = s3 ? s0 : s47;
--- >   
--- >   return s48;
--- > }
-genGCDInC :: IO ()
-genGCDInC = compileToC Nothing "sgcd" $ do
-                x <- cgInput "x"
-                y <- cgInput "y"
-                cgReturn $ sgcd x y
diff --git a/Data/SBV/Examples/CodeGeneration/PopulationCount.hs b/Data/SBV/Examples/CodeGeneration/PopulationCount.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/PopulationCount.hs
+++ /dev/null
@@ -1,227 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.PopulationCount
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computing population-counts (number of set bits) and autimatically
--- generating C code.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.PopulationCount where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Reference: Slow but /obviously/ correct
------------------------------------------------------------------------------
-
--- | Given a 64-bit quantity, the simplest (and obvious) way to count the
--- number of bits that are set in it is to simply walk through all the bits
--- and add 1 to a running count. This is slow, as it requires 64 iterations,
--- but is simple and easy to convince yourself that it is correct. For instance:
---
--- >>> popCountSlow 0x0123456789ABCDEF
--- 32 :: SWord8
-popCountSlow :: SWord64 -> SWord8
-popCountSlow inp = go inp 0 0
-  where go :: SWord64 -> Int -> SWord8 -> SWord8
-        go _ 64 c = c
-        go x i  c = go (x `shiftR` 1) (i+1) (ite (x .&. 1 .== 1) (c+1) c)
-
------------------------------------------------------------------------------
--- * Faster: Using a look-up table
------------------------------------------------------------------------------
-
--- | Faster version. This is essentially the same algorithm, except we
--- go 8 bits at a time instead of one by one, by using a precomputed table
--- of population-count values for each byte. This algorithm /loops/ only
--- 8 times, and hence is at least 8 times more efficient.
-popCountFast :: SWord64 -> SWord8
-popCountFast inp = go inp 0 0
-  where go :: SWord64 -> Int -> SWord8 -> SWord8
-        go _ 8 c = c
-        go x i c = go (x `shiftR` 8) (i+1) (c + select pop8 0 (x .&. 0xff))
-
--- | Look-up table, containing population counts for all possible 8-bit
--- value, from 0 to 255. Note that we do not \"hard-code\" the values, but
--- merely use the slow version to compute them.
-pop8 :: [SWord8]
-pop8 = map popCountSlow [0 .. 255]
-
------------------------------------------------------------------------------
--- * Verification
------------------------------------------------------------------------------
-
-{- $VerificationIntro
-We prove that `popCountFast` and `popCountSlow` are functionally equivalent.
-This is essential as we will automatically generate C code from `popCountFast`,
-and we would like to make sure that the fast version is correct with
-respect to the slower reference version.
--}
-
--- | States the correctness of faster population-count algorithm, with respect
--- to the reference slow version. (We use yices here as it's quite fast for
--- this problem. Z3 seems to take much longer.) We have:
---
--- >>> proveWith yices fastPopCountIsCorrect
--- Q.E.D.
-fastPopCountIsCorrect :: SWord64 -> SBool
-fastPopCountIsCorrect x = popCountFast x .== popCountSlow x
-
------------------------------------------------------------------------------
--- * Code generation
------------------------------------------------------------------------------
-
--- | Not only we can prove that faster version is correct, but we can also automatically
--- generate C code to compute population-counts for us. This action will generate all the
--- C files that you will need, including a driver program for test purposes.
---
--- Below is the generated header file for `popCountFast`:
---
--- >>> genPopCountInC
--- == BEGIN: "Makefile" ================
--- # Makefile for popCount. Automatically generated by SBV. Do not edit!
--- <BLANKLINE>
--- # include any user-defined .mk file in the current directory.
--- -include *.mk
--- <BLANKLINE>
--- CC?=gcc
--- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
--- <BLANKLINE>
--- all: popCount_driver
--- <BLANKLINE>
--- popCount.o: popCount.c popCount.h
--- 	${CC} ${CCFLAGS} -c $< -o $@
--- <BLANKLINE>
--- popCount_driver.o: popCount_driver.c
--- 	${CC} ${CCFLAGS} -c $< -o $@
--- <BLANKLINE>
--- popCount_driver: popCount.o popCount_driver.o
--- 	${CC} ${CCFLAGS} $^ -o $@
--- <BLANKLINE>
--- clean:
--- 	rm -f *.o
--- <BLANKLINE>
--- veryclean: clean
--- 	rm -f popCount_driver
--- == END: "Makefile" ==================
--- == BEGIN: "popCount.h" ================
--- /* Header file for popCount. Automatically generated by SBV. Do not edit! */
--- <BLANKLINE>
--- #ifndef __popCount__HEADER_INCLUDED__
--- #define __popCount__HEADER_INCLUDED__
--- <BLANKLINE>
--- #include <stdio.h>
--- #include <stdlib.h>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <string.h>
--- #include <math.h>
--- <BLANKLINE>
--- /* The boolean type */
--- typedef bool SBool;
--- <BLANKLINE>
--- /* The float type */
--- typedef float SFloat;
--- <BLANKLINE>
--- /* The double type */
--- typedef double SDouble;
--- <BLANKLINE>
--- /* Unsigned bit-vectors */
--- typedef uint8_t  SWord8 ;
--- typedef uint16_t SWord16;
--- typedef uint32_t SWord32;
--- typedef uint64_t SWord64;
--- <BLANKLINE>
--- /* Signed bit-vectors */
--- typedef int8_t  SInt8 ;
--- typedef int16_t SInt16;
--- typedef int32_t SInt32;
--- typedef int64_t SInt64;
--- <BLANKLINE>
--- /* Entry point prototype: */
--- SWord8 popCount(const SWord64 x);
--- <BLANKLINE>
--- #endif /* __popCount__HEADER_INCLUDED__ */
--- == END: "popCount.h" ==================
--- == BEGIN: "popCount_driver.c" ================
--- /* Example driver program for popCount. */
--- /* Automatically generated by SBV. Edit as you see fit! */
--- <BLANKLINE>
--- #include <stdio.h>
--- #include "popCount.h"
--- <BLANKLINE>
--- int main(void)
--- {
---   const SWord8 __result = popCount(0x1b02e143e4f0e0e5ULL);
--- <BLANKLINE>
---   printf("popCount(0x1b02e143e4f0e0e5ULL) = %"PRIu8"\n", __result);
--- <BLANKLINE>
---   return 0;
--- }
--- == END: "popCount_driver.c" ==================
--- == BEGIN: "popCount.c" ================
--- /* File: "popCount.c". Automatically generated by SBV. Do not edit! */
--- <BLANKLINE>
--- #include "popCount.h"
--- <BLANKLINE>
--- SWord8 popCount(const SWord64 x)
--- {
---   const SWord64 s0 = x;
---   static const SWord8 table0[] = {
---       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
---       3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
---       3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
---       2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
---       3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
---       5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
---       2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
---       4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
---       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
---       4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
---       5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
---       5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
---   };
---   const SWord64 s11 = s0 & 0x00000000000000ffULL;
---   const SWord8  s12 = table0[s11];
---   const SWord64 s13 = s0 >> 8;
---   const SWord64 s14 = 0x00000000000000ffULL & s13;
---   const SWord8  s15 = table0[s14];
---   const SWord8  s16 = s12 + s15;
---   const SWord64 s17 = s13 >> 8;
---   const SWord64 s18 = 0x00000000000000ffULL & s17;
---   const SWord8  s19 = table0[s18];
---   const SWord8  s20 = s16 + s19;
---   const SWord64 s21 = s17 >> 8;
---   const SWord64 s22 = 0x00000000000000ffULL & s21;
---   const SWord8  s23 = table0[s22];
---   const SWord8  s24 = s20 + s23;
---   const SWord64 s25 = s21 >> 8;
---   const SWord64 s26 = 0x00000000000000ffULL & s25;
---   const SWord8  s27 = table0[s26];
---   const SWord8  s28 = s24 + s27;
---   const SWord64 s29 = s25 >> 8;
---   const SWord64 s30 = 0x00000000000000ffULL & s29;
---   const SWord8  s31 = table0[s30];
---   const SWord8  s32 = s28 + s31;
---   const SWord64 s33 = s29 >> 8;
---   const SWord64 s34 = 0x00000000000000ffULL & s33;
---   const SWord8  s35 = table0[s34];
---   const SWord8  s36 = s32 + s35;
---   const SWord64 s37 = s33 >> 8;
---   const SWord64 s38 = 0x00000000000000ffULL & s37;
---   const SWord8  s39 = table0[s38];
---   const SWord8  s40 = s36 + s39;
--- <BLANKLINE>
---   return s40;
--- }
--- == END: "popCount.c" ==================
-genPopCountInC :: IO ()
-genPopCountInC = compileToC Nothing "popCount" $ do
-        cgSetDriverValues [0x1b02e143e4f0e0e5]  -- remove this line to get a random test value
-        x <- cgInput "x"
-        cgReturn $ popCountFast x
diff --git a/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs b/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs
deleted file mode 100644
--- a/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs
+++ /dev/null
@@ -1,59 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.CodeGeneration.Uninterpreted
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates the use of uninterpreted functions for the purposes of
--- code generation. This facility is important when we want to take
--- advantage of native libraries in the target platform, or when we'd
--- like to hand-generate code for certain functions for various
--- purposes, such as efficiency, or reliability.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.CodeGeneration.Uninterpreted where
-
-import Data.Maybe (fromMaybe)
-import Data.SBV
-
--- | A definition of shiftLeft that can deal with variable length shifts.
--- (Note that the ``shiftL`` method from the 'Bits' class requires an 'Int' shift
--- amount.) Unfortunately, this'll generate rather clumsy C code due to the
--- use of tables etc., so we uninterpret it for code generation purposes
--- using the 'cgUninterpret' function.
-shiftLeft :: SWord32 -> SWord32 -> SWord32
-shiftLeft = cgUninterpret "SBV_SHIFTLEFT" cCode hCode
-  where -- the C code we'd like SBV to spit out when generating code. Note that this is
-        -- arbitrary C code. In this case we just used a macro, but it could be a function,
-        -- text that includes files etc. It should essentially bring the name SBV_SHIFTLEFT
-        -- used above into scope when compiled. If no code is needed, one can also just
-        -- provide the empty list for the same effect. Also see 'cgAddDecl', 'cgAddLDFlags',
-        -- and 'cgAddPrototype' functions for further variations.
-        cCode = ["#define SBV_SHIFTLEFT(x, y) ((x) << (y))"]
-        -- the Haskell code we'd like SBV to use when running inside Haskell or when
-        -- translated to SMTLib for verification purposes. This is good old Haskell
-        -- code, as one would typically write.
-        hCode x = select [x * literal (bit b) | b <- [0.. bs x - 1]] (literal 0)
-        bs x = fromMaybe (error "SBV.Example.CodeGeneration.Uninterpreted.shiftLeft: Unexpected non-finite usage!") (bitSizeMaybe x)
-
--- | Test function that uses shiftLeft defined above. When used as a normal Haskell function
--- or in verification the definition is fully used, i.e., no uninterpretation happens. To wit,
--- we have:
---
---  >>> tstShiftLeft 3 4 5
---  224 :: SWord32
---
---  >>> prove $ \x y -> tstShiftLeft x y 0 .== x + y
---  Q.E.D.
-tstShiftLeft ::  SWord32 -> SWord32 -> SWord32 -> SWord32
-tstShiftLeft x y z = x `shiftLeft` z + y `shiftLeft` z
-
--- | Generate C code for "tstShiftLeft". In this case, SBV will *use* the user given definition
--- verbatim, instead of generating code for it. (Also see the functions 'cgAddDecl', 'cgAddLDFlags',
--- and 'cgAddPrototype'.)
-genCCode :: IO ()
-genCCode = compileToC Nothing "tst" $ do
-                [x, y, z] <- cgInputArr 3 "vs"
-                cgReturn $ tstShiftLeft x y z
diff --git a/Data/SBV/Examples/Crypto/AES.hs b/Data/SBV/Examples/Crypto/AES.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Crypto/AES.hs
+++ /dev/null
@@ -1,581 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Crypto.AES
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- An implementation of AES (Advanced Encryption Standard), using SBV.
--- For details on AES, see FIPS-197: <http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf>.
---
--- We do a T-box implementation, which leads to good C code as we can take
--- advantage of look-up tables. Note that we make virtually no attempt to
--- optimize our Haskell code. The concern here is not with getting Haskell running
--- fast at all. The idea is to program the T-Box implementation as naturally and clearly
--- as possible in Haskell, and have SBV's code-generator generate fast C code automatically.
--- Therefore, we merely use ordinary Haskell lists as our data-structures, and do not
--- bother with any unboxing or strictness annotations. Thus, we achieve the separation
--- of concerns: Correctness via clairty and simplicity and proofs on the Haskell side,
--- performance by relying on SBV's code generator. If necessary, the generated code
--- can be FFI'd back into Haskell to complete the loop.
---
--- All 3 valid key sizes (128, 192, and 256) as required by the FIPS-197 standard
--- are supported.
------------------------------------------------------------------------------
-
-{-# LANGUAGE ParallelListComp #-}
-
-module Data.SBV.Examples.Crypto.AES where
-
-import Data.SBV
-import Data.List (transpose)
-
------------------------------------------------------------------------------
--- * Formalizing GF(2^8)
------------------------------------------------------------------------------
-
--- | An element of the Galois Field 2^8, which are essentially polynomials with
--- maximum degree 7. They are conveniently represented as values between 0 and 255.
-type GF28 = SWord8
-
--- | Multiplication in GF(2^8). This is simple polynomial multipliation, followed
--- by the irreducible polynomial @x^8+x^4+x^3+x^1+1@. We simply use the 'pMult'
--- function exported by SBV to do the operation. 
-gf28Mult :: GF28 -> GF28 -> GF28
-gf28Mult x y = pMult (x, y, [8, 4, 3, 1, 0])
-
--- | Exponentiation by a constant in GF(2^8). The implementation uses the usual
--- square-and-multiply trick to speed up the computation.
-gf28Pow :: GF28 -> Int -> GF28
-gf28Pow n = pow
-  where sq x  = x `gf28Mult` x
-        pow 0    = 1
-        pow i
-         | odd i = n `gf28Mult` sq (pow (i `shiftR` 1))
-         | True  = sq (pow (i `shiftR` 1))
-
--- | Computing inverses in GF(2^8). By the mathematical properties of GF(2^8)
--- and the particular irreducible polynomial used @x^8+x^5+x^3+x^1+1@, it
--- turns out that raising to the 254 power gives us the multiplicative inverse.
--- Of course, we can prove this using SBV:
---
--- >>> prove $ \x -> x ./= 0 ==> x `gf28Mult` gf28Inverse x .== 1
--- Q.E.D.
---
--- Note that we exclude @0@ in our theorem, as it does not have a
--- multiplicative inverse.
-gf28Inverse :: GF28 -> GF28
-gf28Inverse x = x `gf28Pow` 254
-
------------------------------------------------------------------------------
--- * Implementing AES
------------------------------------------------------------------------------
-
------------------------------------------------------------------------------
--- ** Types and basic operations
------------------------------------------------------------------------------
--- | AES state. The state consists of four 32-bit words, each of which is in turn treated
--- as four GF28's, i.e., 4 bytes. The T-Box implementation keeps the four-bytes together
--- for efficient representation.
-type State = [SWord32]
-
--- | The key, which can be 128, 192, or 256 bits. Represented as a sequence of 32-bit words.
-type Key = [SWord32]
-
--- | The key schedule. AES executes in rounds, and it treats first and last round keys slightly
--- differently than the middle ones. We reflect that choice by being explicit about it in our type.
--- The length of the middle list of keys depends on the key-size, which in turn determines
--- the number of rounds.
-type KS = (Key, [Key], Key)
-
--- | Conversion from 32-bit words to 4 constituent bytes.
-toBytes :: SWord32 -> [GF28]
-toBytes x = [x1, x2, x3, x4]
-        where (h,  l)  = split x
-              (x1, x2) = split h
-              (x3, x4) = split l
-
--- | Conversion from 4 bytes, back to a 32-bit row, inverse of 'toBytes' above. We
--- have the following simple theorems stating this relationship formally:
---
--- >>> prove $ \a b c d -> toBytes (fromBytes [a, b, c, d]) .== [a, b, c, d]
--- Q.E.D.
---
--- >>> prove $ \r -> fromBytes (toBytes r) .== r
--- Q.E.D.
-fromBytes :: [GF28] -> SWord32
-fromBytes [x1, x2, x3, x4] = (x1 # x2) # (x3 # x4)
-fromBytes xs               = error $ "fromBytes: Unexpected input: " ++ show xs
-
--- | Rotating a state row by a fixed amount to the right.
-rotR :: [GF28] -> Int -> [GF28]
-rotR [a, b, c, d] 1 = [d, a, b, c]
-rotR [a, b, c, d] 2 = [c, d, a, b]
-rotR [a, b, c, d] 3 = [b, c, d, a]
-rotR xs           i = error $ "rotR: Unexpected input: " ++ show (xs, i)
-
------------------------------------------------------------------------------
--- ** The key schedule
------------------------------------------------------------------------------
-
--- | Definition of round-constants, as specified in Section 5.2 of the AES standard.
-roundConstants :: [GF28]
-roundConstants = 0 : [ gf28Pow 2 (k-1) | k <- [1 .. ] ]
-
--- | The @InvMixColumns@ transformation, as described in Section 5.3.3 of the standard. Note
--- that this transformation is only used explicitly during key-expansion in the T-Box implementation
--- of AES.
-invMixColumns :: State -> State
-invMixColumns state = map fromBytes $ transpose $ mmult (map toBytes state)
- where dot f   = foldr1 xor . zipWith ($) f
-       mmult n = [map (dot r) n | r <- [ [mE, mB, mD, m9]
-                                       , [m9, mE, mB, mD]
-                                       , [mD, m9, mE, mB]
-                                       , [mB, mD, m9, mE]
-                                       ]]
-       -- table-lookup versions of gf28Mult with the constants used in invMixColumns
-       mE = select mETable 0
-       mB = select mBTable 0
-       mD = select mDTable 0
-       m9 = select m9Table 0
-       mETable = map (gf28Mult 0xE) [0..255]
-       mBTable = map (gf28Mult 0xB) [0..255]
-       mDTable = map (gf28Mult 0xD) [0..255]
-       m9Table = map (gf28Mult 0x9) [0..255]
-
--- | Key expansion. Starting with the given key, returns an infinite sequence of
--- words, as described by the AES standard, Section 5.2, Figure 11.
-keyExpansion :: Int -> Key -> [Key]
-keyExpansion nk key = chop4 keys
-   where keys :: [SWord32]
-         keys = key ++ [nextWord i prev old | i <- [nk ..] | prev <- drop (nk-1) keys | old <- keys]
-         chop4 :: [a] -> [[a]]
-         chop4 xs = let (f, r) = splitAt 4 xs in f : chop4 r
-         nextWord :: Int -> SWord32 -> SWord32 -> SWord32
-         nextWord i prev old
-           | i `mod` nk == 0           = old `xor` subWordRcon (prev `rotateL` 8) (roundConstants !! (i `div` nk))
-           | i `mod` nk == 4 && nk > 6 = old `xor` subWordRcon prev 0
-           | True                      = old `xor` prev
-         subWordRcon :: SWord32 -> GF28 -> SWord32
-         subWordRcon w rc = fromBytes [a `xor` rc, b, c, d]
-            where [a, b, c, d] = map sbox $ toBytes w
-
------------------------------------------------------------------------------
--- ** The S-box transformation
------------------------------------------------------------------------------
-
--- | The values of the AES S-box table. Note that we describe the S-box programmatically
--- using the mathematical construction given in Section 5.1.1 of the standard. However,
--- the code-generation will turn this into a mere look-up table, as it is just a
--- constant table, all computation being done at \"compile-time\".
-sboxTable :: [GF28]
-sboxTable = [xformByte (gf28Inverse b) | b <- [0 .. 255]]
-  where xformByte :: GF28 -> GF28
-        xformByte b = foldr xor 0x63 [b `rotateR` i | i <- [0, 4, 5, 6, 7]]
-
--- | The sbox transformation. We simply select from the sbox table. Note that we
--- are obliged to give a default value (here @0@) to be used if the index is out-of-bounds
--- as required by SBV's 'select' function. However, that will never happen since
--- the table has all 256 elements in it.
-sbox :: GF28 -> GF28
-sbox = select sboxTable 0
-
------------------------------------------------------------------------------
--- ** The inverse S-box transformation
------------------------------------------------------------------------------
-
--- | The values of the inverse S-box table. Again, the construction is programmatic.
-unSBoxTable :: [GF28]
-unSBoxTable = [gf28Inverse (xformByte b) | b <- [0 .. 255]]
-  where xformByte :: GF28 -> GF28
-        xformByte b = foldr xor 0x05 [b `rotateR` i | i <- [2, 5, 7]]
-
--- | The inverse s-box transformation.
-unSBox :: GF28 -> GF28
-unSBox = select unSBoxTable 0
-
--- | Prove that the 'sbox' and 'unSBox' are inverses. We have:
---
--- >>> prove sboxInverseCorrect
--- Q.E.D.
---
-sboxInverseCorrect :: GF28 -> SBool
-sboxInverseCorrect x = unSBox (sbox x) .== x &&& sbox (unSBox x) .== x
-
------------------------------------------------------------------------------
--- ** AddRoundKey transformation
------------------------------------------------------------------------------
-
--- | Adding the round-key to the current state. We simply exploit the fact
--- that addition is just xor in implementing this transformation.
-addRoundKey :: Key -> State -> State
-addRoundKey = zipWith xor
-
------------------------------------------------------------------------------
--- ** Tables for T-Box encryption
------------------------------------------------------------------------------
-
--- | T-box table generation function for encryption
-t0Func :: GF28 -> [GF28]
-t0Func a = [s `gf28Mult` 2, s, s, s `gf28Mult` 3] where s = sbox a
-
--- | First look-up table used in encryption
-t0 :: GF28 -> SWord32
-t0 = select t0Table 0 where t0Table = [fromBytes (t0Func a)          | a <- [0..255]]
-
--- | Second look-up table used in encryption
-t1 :: GF28 -> SWord32
-t1 = select t1Table 0 where t1Table = [fromBytes (t0Func a `rotR` 1) | a <- [0..255]]
-
--- | Third look-up table used in encryption
-t2 :: GF28 -> SWord32
-t2 = select t2Table 0 where t2Table = [fromBytes (t0Func a `rotR` 2) | a <- [0..255]]
-
--- | Fourth look-up table used in encryption
-t3 :: GF28 -> SWord32
-t3 = select t3Table 0 where t3Table = [fromBytes (t0Func a `rotR` 3) | a <- [0..255]]
-
------------------------------------------------------------------------------
--- ** Tables for T-Box decryption
------------------------------------------------------------------------------
-
--- | T-box table generating function for decryption
-u0Func :: GF28 -> [GF28]
-u0Func a = [s `gf28Mult` 0xE, s `gf28Mult` 0x9, s `gf28Mult` 0xD, s `gf28Mult` 0xB] where s = unSBox a
-
--- | First look-up table used in decryption
-u0 :: GF28 -> SWord32
-u0 = select t0Table 0 where t0Table = [fromBytes (u0Func a)          | a <- [0..255]]
-
--- | Second look-up table used in decryption
-u1 :: GF28 -> SWord32
-u1 = select t1Table 0 where t1Table = [fromBytes (u0Func a `rotR` 1) | a <- [0..255]]
-
--- | Third look-up table used in decryption
-u2 :: GF28 -> SWord32
-u2 = select t2Table 0 where t2Table = [fromBytes (u0Func a `rotR` 2) | a <- [0..255]]
-
--- | Fourth look-up table used in decryption
-u3 :: GF28 -> SWord32
-u3 = select t3Table 0 where t3Table = [fromBytes (u0Func a `rotR` 3) | a <- [0..255]]
-
------------------------------------------------------------------------------
--- ** AES rounds
------------------------------------------------------------------------------
-
--- | Generic round function. Given the function to perform one round, a key-schedule,
--- and a starting state, it performs the AES rounds.
-doRounds :: (Bool -> State -> Key -> State) -> KS -> State -> State
-doRounds rnd (ikey, rkeys, fkey) sIn = rnd True (last rs) fkey
-  where s0 = ikey `addRoundKey` sIn
-        rs = s0 : [rnd False s k | s <- rs | k <- rkeys ]
-
--- | One encryption round. The first argument indicates whether this is the final round
--- or not, in which case the construction is slightly different.
-aesRound :: Bool -> State -> Key -> State
-aesRound isFinal s key = d `addRoundKey` key
-  where d = map (f isFinal) [0..3]
-        a = map toBytes s
-        f True j = fromBytes [ sbox (a !! ((j+0) `mod` 4) !! 0)
-                             , sbox (a !! ((j+1) `mod` 4) !! 1)
-                             , sbox (a !! ((j+2) `mod` 4) !! 2)
-                             , sbox (a !! ((j+3) `mod` 4) !! 3)
-                             ]
-        f False j = e0 `xor` e1 `xor` e2 `xor` e3
-              where e0 = t0 (a !! ((j+0) `mod` 4) !! 0)
-                    e1 = t1 (a !! ((j+1) `mod` 4) !! 1)
-                    e2 = t2 (a !! ((j+2) `mod` 4) !! 2)
-                    e3 = t3 (a !! ((j+3) `mod` 4) !! 3)
-
--- | One decryption round. Similar to the encryption round, the first argument
--- indicates whether this is the final round or not.
-aesInvRound :: Bool -> State -> Key -> State
-aesInvRound isFinal s key = d `addRoundKey` key
-  where d = map (f isFinal) [0..3]
-        a = map toBytes s
-        f True j = fromBytes [ unSBox (a !! ((j+0) `mod` 4) !! 0)
-                             , unSBox (a !! ((j+3) `mod` 4) !! 1)
-                             , unSBox (a !! ((j+2) `mod` 4) !! 2)
-                             , unSBox (a !! ((j+1) `mod` 4) !! 3)
-                             ]
-        f False j = e0 `xor` e1 `xor` e2 `xor` e3
-              where e0 = u0 (a !! ((j+0) `mod` 4) !! 0)
-                    e1 = u1 (a !! ((j+3) `mod` 4) !! 1)
-                    e2 = u2 (a !! ((j+2) `mod` 4) !! 2)
-                    e3 = u3 (a !! ((j+1) `mod` 4) !! 3)
-
------------------------------------------------------------------------------
--- * AES API
------------------------------------------------------------------------------
-
--- | Key schedule. Given a 128, 192, or 256 bit key, expand it to get key-schedules
--- for encryption and decryption. The key is given as a sequence of 32-bit words.
--- (4 elements for 128-bits, 6 for 192, and 8 for 256.)
-aesKeySchedule :: Key -> (KS, KS)
-aesKeySchedule key
-  | nk `elem` [4, 6, 8]
-  = (encKS, decKS)
-  | True
-  = error "aesKeySchedule: Invalid key size"
-  where nk = length key
-        nr = nk + 6
-        encKS@(f, m, l) = (head rKeys, take (nr-1) (tail rKeys), rKeys !! nr)
-        decKS = (l, map invMixColumns (reverse m), f)
-        rKeys = keyExpansion nk key
-
--- | Block encryption. The first argument is the plain-text, which must have
--- precisely 4 elements, for a total of 128-bits of input. The second
--- argument is the key-schedule to be used, obtained by a call to 'aesKeySchedule'.
--- The output will always have 4 32-bit words, which is the cipher-text.
-aesEncrypt :: [SWord32] -> KS -> [SWord32]
-aesEncrypt pt encKS
-  | length pt == 4
-  = doRounds aesRound encKS pt
-  | True
-  = error "aesEncrypt: Invalid plain-text size"
-
--- | Block decryption. The arguments are the same as in 'aesEncrypt', except
--- the first argument is the cipher-text and the output is the corresponding
--- plain-text.
-aesDecrypt :: [SWord32] -> KS -> [SWord32]
-aesDecrypt ct decKS
-  | length ct == 4
-  = doRounds aesInvRound decKS ct
-  | True
-  = error "aesDecrypt: Invalid cipher-text size"
-
------------------------------------------------------------------------------
--- * Test vectors
------------------------------------------------------------------------------
-
------------------------------------------------------------------------------
--- ** 128-bit enc/dec test
------------------------------------------------------------------------------
-
--- | 128-bit encryption test, from Appendix C.1 of the AES standard:
---
--- >>> map hex t128Enc
--- ["69c4e0d8","6a7b0430","d8cdb780","70b4c55a"]
---
-t128Enc :: [SWord32]
-t128Enc = aesEncrypt pt ks
-  where pt  = [0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]
-        (ks, _) = aesKeySchedule key
-
--- | 128-bit decryption test, from Appendix C.1 of the AES standard:
---
--- >>> map hex t128Dec
--- ["00112233","44556677","8899aabb","ccddeeff"]
---
-t128Dec :: [SWord32]
-t128Dec = aesDecrypt ct ks
-  where ct  = [0x69c4e0d8, 0x6a7b0430, 0xd8cdb780, 0x70b4c55a]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]
-        (_, ks) = aesKeySchedule key
-
------------------------------------------------------------------------------
--- ** 192-bit enc/dec test
------------------------------------------------------------------------------
-
--- | 192-bit encryption test, from Appendix C.2 of the AES standard:
---
--- >>> map hex t192Enc
--- ["dda97ca4","864cdfe0","6eaf70a0","ec0d7191"]
---
-t192Enc :: [SWord32]
-t192Enc = aesEncrypt pt ks
-  where pt  = [0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617]
-        (ks, _) = aesKeySchedule key
-
--- | 192-bit decryption test, from Appendix C.2 of the AES standard:
---
--- >>> map hex t192Dec
--- ["00112233","44556677","8899aabb","ccddeeff"]
---
-t192Dec :: [SWord32]
-t192Dec = aesDecrypt ct ks
-  where ct  = [0xdda97ca4, 0x864cdfe0, 0x6eaf70a0, 0xec0d7191]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617]
-        (_, ks) = aesKeySchedule key
-
------------------------------------------------------------------------------
--- ** 256-bit enc/dec test
------------------------------------------------------------------------------
-
--- | 256-bit encryption, from Appendix C.3 of the AES standard:
---
--- >>> map hex t256Enc
--- ["8ea2b7ca","516745bf","eafc4990","4b496089"]
---
-t256Enc :: [SWord32]
-t256Enc = aesEncrypt pt ks
-  where pt  = [0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f]
-        (ks, _) = aesKeySchedule key
-
--- | 256-bit decryption, from Appendix C.3 of the AES standard:
---
--- >>> map hex t256Dec
--- ["00112233","44556677","8899aabb","ccddeeff"]
---
-t256Dec :: [SWord32]
-t256Dec = aesDecrypt ct ks
-  where ct  = [0x8ea2b7ca, 0x516745bf, 0xeafc4990, 0x4b496089]
-        key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f]
-        (_, ks) = aesKeySchedule key
-
-
------------------------------------------------------------------------------
--- * Verification
--- ${verifIntro}
------------------------------------------------------------------------------
-{- $verifIntro
-  While SMT based technologies can prove correct many small properties fairly quickly, it would
-  be naive for them to automatically verify that our AES implementation is correct. (By correct,
-  we mean decryption follewed by encryption yielding the same result.) However, we can state
-  this property precisely using SBV, and use quick-check to gain some confidence.
--}
-
--- | Correctness theorem for 128-bit AES. Ideally, we would run:
---
--- @
---   prove aes128IsCorrect
--- @
---
--- to get a proof automatically. Unfortunately, while SBV will successfully generate the proof
--- obligation for this theorem and ship it to the SMT solver, it would be naive to expect the SMT-solver
--- to finish that proof in any reasonable time with the currently available SMT solving technologies.
--- Instead, we can issue:
---
--- @
---   quickCheck aes128IsCorrect
--- @
--- 
--- and get some degree of confidence in our code. Similar predicates can be easily constructed for 192, and
--- 256 bit cases as well.
-aes128IsCorrect :: (SWord32, SWord32, SWord32, SWord32)  -- ^ plain-text words
-                -> (SWord32, SWord32, SWord32, SWord32)  -- ^ key-words
-                -> SBool                                 -- ^ True if round-trip gives us plain-text back
-aes128IsCorrect (i0, i1, i2, i3) (k0, k1, k2, k3) = pt .== pt'
-   where pt  = [i0, i1, i2, i3]
-         key = [k0, k1, k2, k3]
-         (encKS, decKS) = aesKeySchedule key
-         ct  = aesEncrypt pt encKS
-         pt' = aesDecrypt ct decKS
-
------------------------------------------------------------------------------
--- * Code generation
--- ${codeGenIntro}
------------------------------------------------------------------------------
-{- $codeGenIntro
-   We have emphasized that our T-Box implementation in Haskell was guided by clarity and correctness, not
-   performance. Indeed, our implementation is hardly the fastest AES implementation in Haskell. However,
-   we can use it to automatically generate straight-line C-code that can run fairly fast.
-
-   For the purposes of illustration, we only show here how to generate code for a 128-bit AES block-encrypt
-   function, that takes 8 32-bit words as an argument. The first 4 are the 128-bit input, and the final
-   four are the 128-bit key. The impact of this is that the generated function would expand the key for
-   each block of encryption, a needless task unless we change the key in every block. In a more serios application,
-   we would instead generate code for both the 'aesKeySchedule' and the 'aesEncrypt' functions, thus reusing the
-   key-schedule over many applications of the encryption call. (Unfortunately doing this is rather cumbersome right
-   now, since Haskell does not support fixed-size lists.)
--}
-
--- | Code generation for 128-bit AES encryption.
---
--- The following sample from the generated code-lines show how T-Boxes are rendered as C arrays:
---
--- @
---   static const SWord32 table1[] = {
---       0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
---       0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
---       0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
---       0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
---       ...
---       }
--- @
---
--- The generated program has 5 tables (one sbox table, and 4-Tboxes), all converted to fast C arrays. Here
--- is a sample of the generated straightline C-code:
---
--- @
---   const SWord8  s1915 = (SWord8) s1912;
---   const SWord8  s1916 = table0[s1915];
---   const SWord16 s1917 = (((SWord16) s1914) << 8) | ((SWord16) s1916);
---   const SWord32 s1918 = (((SWord32) s1911) << 16) | ((SWord32) s1917);
---   const SWord32 s1919 = s1844 ^ s1918;
---   const SWord32 s1920 = s1903 ^ s1919;
--- @
---
--- The GNU C-compiler does a fine job of optimizing this straightline code to generate a fairly efficient C implementation.
-cgAES128BlockEncrypt :: IO ()
-cgAES128BlockEncrypt = compileToC Nothing "aes128BlockEncrypt" $ do
-        pt  <- cgInputArr 4 "pt"        -- plain-text as an array of 4 Word32's
-        key <- cgInputArr 4 "key"       -- key as an array of 4 Word32s
-        -- Use the test values from Appendix C.1 of the AES standard as the driver values
-        cgSetDriverValues $    [0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]
-                            ++ [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]
-        let (encKs, _) = aesKeySchedule key
-        cgOutputArr "ct" $ aesEncrypt pt encKs
-
------------------------------------------------------------------------------
--- * C-library generation
--- ${libraryIntro}
------------------------------------------------------------------------------
-{- $libraryIntro
-   The 'cgAES128BlockEncrypt' example shows how to generate code for 128-bit AES encryption. As the generated
-   function performs encryption on a given block, it performs key expansion as necessary. However, this is
-   not quite practical: We would like to expand the key only once, and encrypt the stream of plain-text blocks using
-   the same expanded key (potentially using some crypto-mode), until we decide to change the key. In this
-   section, we show how to use SBV to instead generate a library of functions that can be used in such a scenario.
-   The generated library is a typical @.a@ archive, that can be linked using the C-compiler as usual.
--}
-
--- | Components of the AES-128 implementation that the library is generated from
-aes128LibComponents :: [(String, SBVCodeGen ())]
-aes128LibComponents = [ ("aes128KeySchedule",  keySchedule)
-                      , ("aes128BlockEncrypt", enc128)
-                      , ("aes128BlockDecrypt", dec128)
-                      ]
-  where -- key-schedule
-        keySchedule = do key <- cgInputArr 4 "key"     -- key
-                         let (encKS, decKS) = aesKeySchedule key
-                         cgOutputArr "encKS" (ksToXKey encKS)
-                         cgOutputArr "decKS" (ksToXKey decKS)
-        -- encryption
-        enc128 = do pt   <- cgInputArr 4  "pt"    -- plain-text
-                    xkey <- cgInputArr 44 "xkey"  -- expanded key, for 128-bit AES, the key-expansion has 44 Word32's
-                    cgOutputArr "ct" $ aesEncrypt pt (xkeyToKS xkey)
-        -- decryption
-        dec128 = do pt   <- cgInputArr 4  "ct"    -- cipher-text
-                    xkey <- cgInputArr 44 "xkey"  -- expanded key, for 128-bit AES, the key-expansion has 44 Word32's
-                    cgOutputArr "pt" $ aesDecrypt pt (xkeyToKS xkey)
-        -- Transforming back and forth from our KS type to a flat array used by the generated C code
-        -- Turn a series of expanded keys to our internal KS type
-        xkeyToKS :: [SWord32] -> KS
-        xkeyToKS xs = (f, m, l)
-           where f = take 4 xs                       -- first round key
-                 m = chop4 (take 36 (drop 4 xs))     -- middle rounds
-                 l = drop 40 xs                      -- last round key
-        -- Turn a KS to a series of expanded key words
-        ksToXKey :: KS -> [SWord32]
-        ksToXKey (f, m, l) = f ++ concat m ++ l
-        -- chunk in fours. (This function must be in some standard library, where?)
-        chop4 :: [a] -> [[a]]
-        chop4 [] = []
-        chop4 xs = let (f, r) = splitAt 4 xs in f : chop4 r
-
--- | Generate a C library, containing functions for performing 128-bit enc/dec/key-expansion.
--- A note on performance: In a very rough speed test, the generated code was able to do
--- 6.3 million block encryptions per second on a decent MacBook Pro. On the same machine, OpenSSL
--- reports 8.2 million block encryptions per second. So, the generated code is about 25% slower
--- as compared to the highly optimized OpenSSL implementation. (Note that the speed test was done
--- somewhat simplistically, so these numbers should be considered very rough estimates.)
-cgAES128Library :: IO ()
-cgAES128Library = compileToCLib Nothing "aes128Lib" aes128LibComponents
-
-{-# ANN aesRound    ("HLint: ignore Use head" :: String) #-}
-{-# ANN aesInvRound ("HLint: ignore Use head" :: String) #-}
diff --git a/Data/SBV/Examples/Crypto/RC4.hs b/Data/SBV/Examples/Crypto/RC4.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Crypto/RC4.hs
+++ /dev/null
@@ -1,143 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Crypto.RC4
--- Copyright   :  (c) Austin Seipp
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- An implementation of RC4 (AKA Rivest Cipher 4 or Alleged RC4/ARC4),
--- using SBV. For information on RC4, see: <http://en.wikipedia.org/wiki/RC4>.
---
--- We make no effort to optimize the code, and instead focus on a clear
--- implementation. In fact, the RC4 algorithm relies on in-place update of
--- its state heavily for efficiency, and is therefore unsuitable for a purely
--- functional implementation.
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.Examples.Crypto.RC4 where
-
-import Data.Char  (ord, chr)
-import Data.List  (genericIndex)
-import Data.Maybe (fromJust)
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Types
------------------------------------------------------------------------------
-
--- | RC4 State contains 256 8-bit values. We use the symbolically accessible
--- full-binary type 'STree' to represent the state, since RC4 needs
--- access to the array via a symbolic index and it's important to minimize access time.
-type S = STree Word8 Word8
-
--- | Construct the fully balanced initial tree, where the leaves are simply the numbers @0@ through @255@.
-initS :: S
-initS = mkSTree (map literal [0 .. 255])
-
--- | The key is a stream of 'Word8' values.
-type Key = [SWord8]
-
--- | Represents the current state of the RC4 stream: it is the @S@ array
--- along with the @i@ and @j@ index values used by the PRGA.
-type RC4 = (S, SWord8, SWord8)
-
------------------------------------------------------------------------------
--- * The PRGA
------------------------------------------------------------------------------
-
--- | Swaps two elements in the RC4 array.
-swap :: SWord8 -> SWord8 -> S -> S
-swap i j st = writeSTree (writeSTree st i stj) j sti
-  where sti = readSTree st i
-        stj = readSTree st j
-
--- | Implements the PRGA used in RC4. We return the new state and the next key value generated.
-prga :: RC4 -> (SWord8, RC4)
-prga (st', i', j') = (readSTree st kInd, (st, i, j))
-  where i    = i' + 1
-        j    = j' + readSTree st' i
-        st   = swap i j st'
-        kInd = readSTree st i + readSTree st j
-
------------------------------------------------------------------------------
--- * Key schedule
------------------------------------------------------------------------------
-
--- | Constructs the state to be used by the PRGA using the given key.
-initRC4 :: Key -> S
-initRC4 key
- | keyLength < 1 || keyLength > 256
- = error $ "RC4 requires a key of length between 1 and 256, received: " ++ show keyLength
- | True
- = snd $ foldl mix (0, initS) [0..255]
- where keyLength = length key
-       mix :: (SWord8, S) -> SWord8 -> (SWord8, S)
-       mix (j', s) i = let j = j' + readSTree s i + genericIndex key (fromJust (unliteral i) `mod` fromIntegral keyLength)
-                       in (j, swap i j s)
-
--- | The key-schedule. Note that this function returns an infinite list.
-keySchedule :: Key -> [SWord8]
-keySchedule key = genKeys (initRC4 key, 0, 0)
-  where genKeys :: RC4 -> [SWord8]
-        genKeys st = let (k, st') = prga st in k : genKeys st'
-
--- | Generate a key-schedule from a given key-string.
-keyScheduleString :: String -> [SWord8]
-keyScheduleString = keySchedule . map (literal . fromIntegral . ord)
-
------------------------------------------------------------------------------
--- * Encryption and Decryption
------------------------------------------------------------------------------
-
--- | RC4 encryption. We generate key-words and xor it with the input. The
--- following test-vectors are from Wikipedia <http://en.wikipedia.org/wiki/RC4>:
---
--- >>> concatMap hex $ encrypt "Key" "Plaintext"
--- "bbf316e8d940af0ad3"
---
--- >>> concatMap hex $ encrypt "Wiki" "pedia"
--- "1021bf0420"
---
--- >>> concatMap hex $ encrypt "Secret" "Attack at dawn"
--- "45a01f645fc35b383552544b9bf5"
-encrypt :: String -> String -> [SWord8]
-encrypt key pt = zipWith xor (keyScheduleString key) (map cvt pt)
-  where cvt = literal . fromIntegral . ord
-
--- | RC4 decryption. Essentially the same as decryption. For the above test vectors we have:
---
--- >>> decrypt "Key" [0xbb, 0xf3, 0x16, 0xe8, 0xd9, 0x40, 0xaf, 0x0a, 0xd3]
--- "Plaintext"
---
--- >>> decrypt "Wiki" [0x10, 0x21, 0xbf, 0x04, 0x20]
--- "pedia"
---
--- >>> decrypt "Secret" [0x45, 0xa0, 0x1f, 0x64, 0x5f, 0xc3, 0x5b, 0x38, 0x35, 0x52, 0x54, 0x4b, 0x9b, 0xf5]
--- "Attack at dawn"
-decrypt :: String -> [SWord8] -> String
-decrypt key ct = map cvt $ zipWith xor (keyScheduleString key) ct
-  where cvt = chr . fromIntegral . fromJust . unliteral
-
------------------------------------------------------------------------------
--- * Verification
------------------------------------------------------------------------------
-
--- | Prove that round-trip encryption/decryption leaves the plain-text unchanged.
--- The theorem is stated parametrically over key and plain-text sizes. The expression
--- performs the proof for a 40-bit key (5 bytes) and 40-bit plaintext (again 5 bytes).
---
--- Note that this theorem is trivial to prove, since it is essentially establishing
--- xor'in the same value twice leaves a word unchanged (i.e., @x `xor` y `xor` y = x@).
--- However, the proof takes quite a while to complete, as it gives rise to a fairly
--- large symbolic trace.
-rc4IsCorrect :: IO ThmResult
-rc4IsCorrect = prove $ do
-        key <- mkForallVars 5
-        pt  <- mkForallVars 5
-        let ks  = keySchedule key
-            ct  = zipWith xor ks pt
-            pt' = zipWith xor ks ct
-        return $ pt .== pt'
diff --git a/Data/SBV/Examples/Existentials/CRCPolynomial.hs b/Data/SBV/Examples/Existentials/CRCPolynomial.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Existentials/CRCPolynomial.hs
+++ /dev/null
@@ -1,100 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Existentials.CRCPolynomial
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- This program demonstrates the use of the existentials and the QBVF (quantified
--- bit-vector solver). We generate CRC polynomials of degree 16 that can be used
--- for messages of size 48-bits. The query finds all such polynomials that have hamming
--- distance is at least 4. That is, if the CRC can't tell two different 48-bit messages
--- apart, then they must differ in at least 4 bits.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Existentials.CRCPolynomial where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Modeling 48 bit words
------------------------------------------------------------------------------
--- | SBV doesn't support 48 bit words natively. So, we represent them
--- as a tuple, 32 high-bits and 16 low-bits.
-type SWord48 = (SWord32, SWord16)
-
--- | Compute the 16 bit CRC of a 48 bit message, using the given polynomial
-crc_48_16 :: SWord48 -> SWord16 -> [SBool]
-crc_48_16 msg poly = crcBV 16 msgBits polyBits
-  where (hi, lo) = msg
-        msgBits  = blastBE hi ++ blastBE lo
-        polyBits = blastBE poly
-
--- | Count the differing bits in the message and the corresponding CRC
-diffCount :: (SWord48, [SBool]) -> (SWord48, [SBool]) -> SWord8
-diffCount ((h1, l1), crc1) ((h2, l2), crc2) = count xorBits
-  where bits1   = blastBE h1 ++ blastBE l1 ++ crc1
-        bits2   = blastBE h2 ++ blastBE l2 ++ crc2
-        -- xor will give us a false if bits match, true if they differ
-        xorBits = zipWith (<+>) bits1 bits2
-        count []     = 0
-        count (b:bs) = let r = count bs in ite b (1+r) r
-
--- | Given a hamming distance value @hd@, 'crcGood' returns @true@ if
--- the 16 bit polynomial can distinguish all messages that has at most
--- @hd@ different bits. Note that we express this conversely: If the
--- @sent@ and @received@ messages are different, then it must be the
--- case that that must differ from each other (including CRCs), in
--- more than @hd@ bits.
-crcGood :: SWord8 -> SWord16 -> SWord48 -> SWord48 -> SBool
-crcGood hd poly sent received =
-     sent ./= received ==> diffCount (sent, crcSent) (received, crcReceived) .>= hd
-   where crcSent     = crc_48_16 sent     poly
-         crcReceived = crc_48_16 received poly
-
--- | Generate good CRC polynomials for 48-bit words, given the hamming distance @hd@.
-genPoly :: SWord8 -> IO ()
-genPoly hd = do res <- allSat $ do
-                        -- the polynomial is existentially specified
-                        p <- exists "polynomial"
-                        -- sent word, universal
-                        s <- do sh <- forall "sh"
-                                sl <- forall "sl"
-                                return (sh, sl)
-                        -- received word, universal
-                        r <- do rh <- forall "rh"
-                                rl <- forall "rl"
-                                return (rh, rl)
-                        -- assert that the polynomial @p@ is good. Note
-                        -- that we also supply the extra information that
-                        -- the least significant bit must be set in the
-                        -- polynomial, as all CRC polynomials have the "+1"
-                        -- term in them set. This simplifies the query.
-                        return $ sTestBit p 0 &&& crcGood hd p s r
-                cnt <- displayModels disp res
-                putStrLn $ "Found: " ++ show cnt ++ " polynomail(s)."
-        where disp :: Int -> (Bool, Word16) -> IO ()
-              disp n (_, s) = putStrLn $ "Polynomial #" ++ show n ++ ". x^16 + " ++ showPolynomial False s
-
--- | Find and display all degree 16 polynomials with hamming distance at least 4, for 48 bit messages.
---
--- When run, this function prints:
---
---  @
---    Polynomial #1. x^16 + x^2 + x + 1
---    Polynomial #2. x^16 + x^15 + x^2 + 1
---    Polynomial #3. x^16 + x^15 + x^2 + x + 1
---    Polynomial #4. x^16 + x^14 + x^10 + 1
---    Polynomial #5. x^16 + x^14 + x^9 + 1
---    ...
---  @
---
--- Note that different runs can produce different results, depending on the random
--- numbers used by the solver, solver version, etc. (Also, the solver will take some
--- time to generate these results. On my machine, the first five polynomials were
--- generated in about 5 minutes.)
-findHD4Polynomials :: IO ()
-findHD4Polynomials = genPoly 4
-
-{-# ANN crc_48_16 ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/Data/SBV/Examples/Existentials/Diophantine.hs b/Data/SBV/Examples/Existentials/Diophantine.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Existentials/Diophantine.hs
+++ /dev/null
@@ -1,132 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Existentials.Diophantine
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Finding minimal natural number solutions to linear Diophantine equations,
--- using explicit quantification.
------------------------------------------------------------------------------
-module Data.SBV.Examples.Existentials.Diophantine where
-
-import Data.SBV
-
---------------------------------------------------------------------------------------------------
--- * Representing solutions
---------------------------------------------------------------------------------------------------
--- | For a homogeneous problem, the solution is any linear combination of the resulting vectors.
--- For a non-homogeneous problem, the solution is any linear combination of the vectors in the
--- second component plus one of the vectors in the first component.
-data Solution = Homogeneous    [[Integer]]
-              | NonHomogeneous [[Integer]] [[Integer]]
-              deriving Show
-
---------------------------------------------------------------------------------------------------
--- * Solving diophantine equations
---------------------------------------------------------------------------------------------------
--- | ldn: Solve a (L)inear (D)iophantine equation, returning minimal solutions over (N)aturals.
--- The input is given as a rows of equations, with rhs values separated into a tuple.
-ldn :: [([Integer], Integer)] -> IO Solution
-ldn problem = do solution <- basis (map (map literal) m)
-                 if homogeneous
-                    then return $ Homogeneous solution
-                    else do let ones  = [xs | (1:xs) <- solution]
-                                zeros = [xs | (0:xs) <- solution]
-                            return $ NonHomogeneous ones zeros
-  where rhs = map snd problem
-        lhs = map fst problem
-        homogeneous = all (== 0) rhs
-        m | homogeneous = lhs
-          | True        = zipWith (\x y -> -x : y) rhs lhs
-
--- | Find the basis solution. By definition, the basis has all non-trivial (i.e., non-0) solutions
--- that cannot be written as the sum of two other solutions. We use the mathematically equivalent
--- statement that a solution is in the basis if it's least according to the lexicographic
--- order using the ordinary less-than relation. (NB. We explicitly tell z3 to use the logic
--- AUFLIA for this problem, as the BV solver that is chosen automatically has a performance
--- issue. See: <https://z3.codeplex.com/workitem/88>.)
-basis :: [[SInteger]] -> IO [[Integer]]
-basis m = extractModels `fmap` allSatWith z3{useLogic = Just (PredefinedLogic AUFLIA)} cond
- where cond = do as <- mkExistVars  n
-                 bs <- mkForallVars n
-                 return $ ok as &&& (ok bs ==> as .== bs ||| bnot (bs `less` as))
-       n = if null m then 0 else length (head m)
-       ok xs = bAny (.> 0) xs &&& bAll (.>= 0) xs &&& bAnd [sum (zipWith (*) r xs) .== 0 | r <- m]
-       as `less` bs = bAnd (zipWith (.<=) as bs) &&& bOr (zipWith (.<) as bs)
-
---------------------------------------------------------------------------------------------------
--- * Examples
---------------------------------------------------------------------------------------------------
-
--- | Solve the equation:
---
---    @2x + y - z = 2@
---
--- We have:
---
--- >>> test
--- NonHomogeneous [[0,2,0],[1,0,0]] [[0,1,1],[1,0,2]]
---
--- which means that the solutions are of the form:
---
---    @(1, 0, 0) + k (0, 1, 1) + k' (1, 0, 2) = (1+k', k, k+2k')@
---
--- OR
---
---    @(0, 2, 0) + k (0, 1, 1) + k' (1, 0, 2) = (k', 2+k, k+2k')@
---
--- for arbitrary @k@, @k'@. It's easy to see that these are really solutions
--- to the equation given. It's harder to see that they cover all possibilities,
--- but a moments thought reveals that is indeed the case.
-test :: IO Solution
-test = ldn [([2,1,-1], 2)]
-
--- | A puzzle: Five sailors and a monkey escape from a naufrage and reach an island with
--- coconuts. Before dawn, they gather a few of them and decide to sleep first and share
--- the next day. At night, however, one of them awakes, counts the nuts, makes five parts,
--- gives the remaining nut to the monkey, saves his share away, and sleeps. All other
--- sailors do the same, one by one. When they all wake up in the morning, they again make 5 shares,
--- and give the last remaining nut to the monkey. How many nuts were there at the beginning?
---
--- We can model this as a series of diophantine equations:
---
--- @
---       x_0 = 5 x_1 + 1
---     4 x_1 = 5 x_2 + 1
---     4 x_2 = 5 x_3 + 1
---     4 x_3 = 5 x_4 + 1
---     4 x_4 = 5 x_5 + 1
---     4 x_5 = 5 x_6 + 1
--- @
---
--- We need to solve for x_0, over the naturals. We have:
---
--- >>> sailors
--- [15621,3124,2499,1999,1599,1279,1023]
---
--- That is:
---
--- @
---   * There was a total of 15621 coconuts
---   * 1st sailor: 15621 = 3124*5+1, leaving 15621-3124-1 = 12496
---   * 2nd sailor: 12496 = 2499*5+1, leaving 12496-2499-1 =  9996
---   * 3rd sailor:  9996 = 1999*5+1, leaving  9996-1999-1 =  7996
---   * 4th sailor:  7996 = 1599*5+1, leaving  7996-1599-1 =  6396
---   * 5th sailor:  6396 = 1279*5+1, leaving  6396-1279-1 =  5116
---   * In the morning, they had: 5116 = 1023*5+1.
--- @
---
--- Note that this is the minimum solution, that is, we are guaranteed that there's
--- no solution with less number of coconuts. In fact, any member of @[15625*k-4 | k <- [1..]]@
--- is a solution, i.e., so are @31246@, @46871@, @62496@, @78121@, etc.
-sailors :: IO [Integer]
-sailors = do NonHomogeneous (xs:_) _ <- ldn [ ([1, -5,  0,  0,  0,  0,  0], 1)
-                                            , ([0,  4, -5 , 0,  0,  0,  0], 1)
-                                            , ([0,  0,  4, -5 , 0,  0,  0], 1)
-                                            , ([0,  0,  0,  4, -5,  0,  0], 1)
-                                            , ([0,  0,  0,  0,  4, -5,  0], 1)
-                                            , ([0,  0,  0,  0,  0,  4, -5], 1)
-                                            ]
-             return xs
diff --git a/Data/SBV/Examples/Misc/Auxiliary.hs b/Data/SBV/Examples/Misc/Auxiliary.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/Auxiliary.hs
+++ /dev/null
@@ -1,63 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.Auxiliary
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates model construction with auxiliary variables. Sometimes we
--- need to introduce a variable in our problem as an existential variable,
--- but it's "internal" to the problem and we do not consider it as part of
--- the solution. Also, in an `allSat` scenario, we may not care for models
--- that only differ in these auxiliaries. SBV allows designating such variables
--- as `isNonModelVar` so we can still use them like any other variable, but without
--- considering them explicitly in model construction.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Misc.Auxiliary where
-
-import Data.SBV
-
--- | A simple predicate, based on two variables @x@ and @y@, true when
--- @0 <= x <= 1@ and @x - abs y@ is @0@.
-problem :: Predicate
-problem = do x <- free "x"
-             y <- free "y"
-             constrain $ x .>= 0
-             constrain $ x .<= 1
-             return $ x - abs y .== (0 :: SInteger)
-
--- | Generate all satisfying assignments for our problem. We have:
---
--- >>> allModels
--- Solution #1:
---   x = 0 :: Integer
---   y = 0 :: Integer
--- Solution #2:
---   x =  1 :: Integer
---   y = -1 :: Integer
--- Solution #3:
---   x = 1 :: Integer
---   y = 1 :: Integer
--- Found 3 different solutions.
---
--- Note that solutions @2@ and @3@ share the value @x = 1@, since there are
--- multiple values of @y@ that make this particular choice of @x@ satisfy our constraint.
-allModels :: IO AllSatResult
-allModels = allSat problem
-
--- | Generate all satisfying assignments, but we first tell SBV that @y@ should not be considered
--- as a model problem, i.e., it's auxiliary. We have:
---
--- >>> modelsWithYAux
--- Solution #1:
---   x = 0 :: Integer
--- Solution #2:
---   x = 1 :: Integer
--- Found 2 different solutions.
---
--- Note that we now have only two solutions, one for each unique value of @x@ that satisfy our
--- constraint.
-modelsWithYAux :: IO AllSatResult
-modelsWithYAux = allSatWith z3{isNonModelVar = (`elem` ["y"])} problem
diff --git a/Data/SBV/Examples/Misc/Enumerate.hs b/Data/SBV/Examples/Misc/Enumerate.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/Enumerate.hs
+++ /dev/null
@@ -1,77 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.Enumerate
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates how enumerations can be translated to their SMT-Lib
--- counterparts, without losing any information content. Also see
--- "Data.SBV.Examples.Puzzles.U2Bridge" for a more detailed
--- example involving enumerations.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.Examples.Misc.Enumerate where
-
-import Data.SBV
-import Data.Generics
-
--- | A simple enumerated type, that we'd like to translate to SMT-Lib intact;
--- i.e., this type will not be uninterpreted but rather preserved and will
--- be just like any other symbolic type SBV provides. Note the automatically
--- derived classes we need: 'Eq', 'Ord', 'Data', 'Read', 'Show', 'SymWord',
--- 'HasKind', and 'SatModel'. (The last one is only needed if 'getModel' and friends are used.)
---
--- Also note that we need to @import Data.Generics@ and have the @LANGUAGE@
--- option @DeriveDataTypeable@ and @DeriveAnyClass@ set.
-data E = A | B | C deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Give a name to the symbolic variants of 'E', for convenience
-type SE = SBV E
-
--- | Have the SMT solver enumerate the elements of the domain. We have:
---
--- >>> elts
--- Solution #1:
---   s0 = B :: E
--- Solution #2:
---   s0 = A :: E
--- Solution #3:
---   s0 = C :: E
--- Found 3 different solutions.
-elts :: IO AllSatResult
-elts = allSat $ \(x::SE) -> x .== x
-
--- | Shows that if we require 4 distinct elements of the type 'E', we shall fail; as
--- the domain only has three elements. We have:
---
--- >>> four
--- Unsatisfiable
-four :: IO SatResult
-four = sat $ \a b c (d::SE) -> allDifferent [a, b, c, d]
-
--- | Enumerations are automatically ordered, so we can ask for the maximum
--- element. Note the use of quantification. We have:
---
--- >>> maxE
--- Satisfiable. Model:
---   maxE = C :: E
-maxE :: IO SatResult
-maxE = sat $ do mx <- exists "maxE"
-                e  <- forall "e"
-                return $ mx .>= (e::SE)
-
--- | Similarly, we get the minumum element. We have:
---
--- >>> minE
--- Satisfiable. Model:
---   minE = A :: E
-minE :: IO SatResult
-minE = sat $ do mx <- exists "minE"
-                e  <- forall "e"
-                return $ mx .<= (e::SE)
diff --git a/Data/SBV/Examples/Misc/Floating.hs b/Data/SBV/Examples/Misc/Floating.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/Floating.hs
+++ /dev/null
@@ -1,187 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.Floating
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Several examples involving IEEE-754 floating point numbers, i.e., single
--- precision 'Float' ('SFloat') and double precision 'Double' ('SDouble') types.
---
--- Note that arithmetic with floating point is full of surprises; due to precision
--- issues associativity of arithmetic operations typically do not hold. Also,
--- the presence of @NaN@ is always something to look out for.
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.Examples.Misc.Floating where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * FP addition is not associative
------------------------------------------------------------------------------
-
--- | Prove that floating point addition is not associative. For illustration purposes,
--- we will require one of the inputs to be a @NaN@. We have:
---
--- >>> prove $ assocPlus (0/0)
--- Falsifiable. Counter-example:
---   s0 = 0.0 :: Float
---   s1 = 0.0 :: Float
---
--- Indeed:
---
--- >>> let i = 0/0 :: Float
--- >>> i + (0.0 + 0.0)
--- NaN
--- >>> ((i + 0.0) + 0.0)
--- NaN
---
--- But keep in mind that @NaN@ does not equal itself in the floating point world! We have:
---
--- >>> let nan = 0/0 :: Float in nan == nan
--- False
-assocPlus :: SFloat -> SFloat -> SFloat -> SBool
-assocPlus x y z = x + (y + z) .== (x + y) + z
-
--- | Prove that addition is not associative, even if we ignore @NaN@/@Infinity@ values.
--- To do this, we use the predicate 'fpIsPoint', which is true of a floating point
--- number ('SFloat' or 'SDouble') if it is neither @NaN@ nor @Infinity@. (That is, it's a
--- representable point in the real-number line.)
---
--- We have:
---
--- >>> assocPlusRegular
--- Falsifiable. Counter-example:
---   x =  1.9259302e-34 :: Float
---   y = -1.9259117e-34 :: Float
---   z =  -1.814176e-39 :: Float
---
--- Indeed, we have:
---
--- >>> ((1.9259302e-34) + ((-1.9259117e-34) + (-1.814176e-39))) :: Float
--- 3.4438e-41
--- >>> (((1.9259302e-34) + ((-1.9259117e-34))) + (-1.814176e-39)) :: Float
--- 3.4014e-41
---
--- Note the difference between two additions!
-assocPlusRegular :: IO ThmResult
-assocPlusRegular = prove $ do [x, y, z] <- sFloats ["x", "y", "z"]
-                              let lhs = x+(y+z)
-                                  rhs = (x+y)+z
-                              -- make sure we do not overflow at the intermediate points
-                              constrain $ fpIsPoint lhs
-                              constrain $ fpIsPoint rhs
-                              return $ lhs .== rhs
-
------------------------------------------------------------------------------
--- * FP addition by non-zero can result in no change
------------------------------------------------------------------------------
-
--- | Demonstrate that @a+b = a@ does not necessarily mean @b@ is @0@ in the floating point world,
--- even when we disallow the obvious solution when @a@ and @b@ are @Infinity.@
--- We have:
---
--- >>> nonZeroAddition
--- Falsifiable. Counter-example:
---   a = 2.424457e-38 :: Float
---   b =     -1.0e-45 :: Float
---
--- Indeed, we have:
---
--- >>> (2.424457e-38 + (-1.0e-45)) == (2.424457e-38 :: Float)
--- True
---
--- But:
---
--- >>> -1.0e-45 == (0 :: Float)
--- False
---
-nonZeroAddition :: IO ThmResult
-nonZeroAddition = prove $ do [a, b] <- sFloats ["a", "b"]
-                             constrain $ fpIsPoint a
-                             constrain $ fpIsPoint b
-                             constrain $ a + b .== a
-                             return $ b .== 0
-
------------------------------------------------------------------------------
--- * FP multiplicative inverses may not exist
------------------------------------------------------------------------------
-
--- | This example illustrates that @a * (1/a)@ does not necessarily equal @1@. Again,
--- we protect against division by @0@ and @NaN@/@Infinity@.
---
--- We have:
---
--- >>> multInverse
--- Falsifiable. Counter-example:
---   a = 1.119056263978578e-308 :: Double
---
--- Indeed, we have:
---
--- >>> let a = 1.119056263978578e-308 :: Double
--- >>> a * (1/a)
--- 0.9999999999999999
-multInverse :: IO ThmResult
-multInverse = prove $ do a <- sDouble "a"
-                         constrain $ fpIsPoint a
-                         constrain $ fpIsPoint (1/a)
-                         return $ a * (1/a) .== 1
-
------------------------------------------------------------------------------
--- * Effect of rounding modes
------------------------------------------------------------------------------
-
--- | One interesting aspect of floating-point is that the chosen rounding-mode
--- can effect the results of a computation if the exact result cannot be precisely
--- represented. SBV exports the functions 'fpAdd', 'fpSub', 'fpMul', 'fpDiv', 'fpFMA'
--- and 'fpSqrt' which allows users to specify the IEEE supported 'RoundingMode' for
--- the operation. (Also see the class 'RoundingFloat'.) This example illustrates how SBV
--- can be used to find rounding-modes where, for instance, addition can produce different
--- results. We have:
---
--- >>> roundingAdd
--- Satisfiable. Model:
---   rm = RoundTowardPositive :: RoundingMode
---   x  =              -256.0 :: Float
---   y  =       4.6475088e-10 :: Float
---
--- (Note that depending on your version of Z3, you might get a different result.)
--- Unfortunately we can't directly validate this result at the Haskell level, as Haskell only supports
--- 'RoundNearestTiesToEven'. We have:
---
--- >>> (-256.0 + 4.6475088e-10) :: Float
--- -256.0
---
--- While we cannot directly see the result when the mode is 'RoundTowardPositive' in Haskell, we can use
--- SBV to provide us with that result thusly:
---
--- >>> sat $ \z -> z .== fpAdd sRoundTowardPositive (-256.0) (4.6475088e-10 :: SFloat)
--- Satisfiable. Model:
---   s0 = -255.99998 :: Float
---
--- We can see why these two resuls are indeed different: The 'RoundTowardsPositive'
--- (which rounds towards positive-infinity) produces a larger result. Indeed, if we treat these numbers
--- as 'Double' values, we get:
---
--- >>>  (-256.0 + 4.6475088e-10) :: Double
--- -255.99999999953525
---
--- we see that the "more precise" result is larger than what the 'Float' value is, justifying the
--- larger value with 'RoundTowardPositive'. A more detailed study is beyond our current scope, so we'll
---  merely -- note that floating point representation and semantics is indeed a thorny
--- subject, and point to <https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/02Numerics/Double/paper.pdf> as
--- an excellent guide.
-roundingAdd :: IO SatResult
-roundingAdd = sat $ do m :: SRoundingMode <- free "rm"
-                       constrain $ m ./= literal RoundNearestTiesToEven
-                       x <- sFloat "x"
-                       y <- sFloat "y"
-                       let lhs = fpAdd m x y
-                       let rhs = x + y
-                       constrain $ fpIsPoint lhs
-                       constrain $ fpIsPoint rhs
-                       return $ lhs ./= rhs
diff --git a/Data/SBV/Examples/Misc/ModelExtract.hs b/Data/SBV/Examples/Misc/ModelExtract.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/ModelExtract.hs
+++ /dev/null
@@ -1,46 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.ModelExtract
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates use of programmatic model extraction. When programming with
--- SBV, we typically use `sat`/`allSat` calls to compute models automatically.
--- In more advanced uses, however, the user might want to use programmable
--- extraction features to do fancier programming. We demonstrate some of
--- these utilities here.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Misc.ModelExtract where
-
-import Data.SBV
-
--- | A simple function to generate a new integer value, that is not in the
--- given set of values. We also require the value to be non-negative
-outside :: [Integer] -> IO SatResult
-outside disallow = sat $ do x <- sInteger "x"
-                            let notEq i = constrain $ x ./= literal i
-                            mapM_ notEq disallow
-                            return $ x .>= 0
-
--- | We now use "outside" repeatedly to generate 10 integers, such that we not only disallow
--- previously generated elements, but also any value that differs from previous solutions
--- by less than 5.  Here, we use the `getModelValue` function. We could have also extracted the dictionary
--- via `getModelDictionary` and did fancier programming as well, as necessary. We have:
---
--- >>> genVals
--- [45,40,35,30,25,20,15,10,5,0]
-genVals :: IO [Integer]
-genVals = go [] []
-  where go _ model
-         | length model >= 10 = return model
-        go disallow model
-          = do res <- outside disallow
-               -- Look up the value of "x" in the generated model
-               -- Note that we simply get an integer here; but any
-               -- SBV known type would be OK as well.
-               case "x" `getModelValue` res of
-                 Just c -> go [c-4 .. c+4] (c : model)
-                 _      -> return model
diff --git a/Data/SBV/Examples/Misc/NoDiv0.hs b/Data/SBV/Examples/Misc/NoDiv0.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/NoDiv0.hs
+++ /dev/null
@@ -1,44 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.NoDiv0
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates SBV's assertion checking facilities
------------------------------------------------------------------------------
-
-{-# LANGUAGE ImplicitParams #-}
-
-module Data.SBV.Examples.Misc.NoDiv0 where
-
-import Data.SBV
-import GHC.Stack
-
--- | A simple variant of division, where we explicitly require the
--- caller to make sure the divisor is not 0.
-checkedDiv :: (?loc :: CallStack) => SInt32 -> SInt32 -> SInt32
-checkedDiv x y = sAssert (Just ?loc)
-                         "Divisor should not be 0"
-                         (y ./= 0)
-                         (x `sDiv` y)
-
--- | Check whether an arbitrary call to 'checkedDiv' is safe. Clearly, we do not expect
--- this to be safe:
---
--- >>> test1
--- [Data/SBV/Examples/Misc/NoDiv0.hs:36:14:checkedDiv: Divisor should not be 0: Violated. Model:
---   s0 = 0 :: Int32
---   s1 = 0 :: Int32]
---
-test1 :: IO [SafeResult]
-test1 = safe checkedDiv
-
--- | Repeat the test, except this time we explicitly protect against the bad case. We have:
---
--- >>> test2
--- [Data/SBV/Examples/Misc/NoDiv0.hs:44:41:checkedDiv: Divisor should not be 0: No violations detected]
---
-test2 :: IO [SafeResult]
-test2 = safe $ \x y -> ite (y .== 0) 3 (checkedDiv x y)
diff --git a/Data/SBV/Examples/Misc/Word4.hs b/Data/SBV/Examples/Misc/Word4.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/Word4.hs
+++ /dev/null
@@ -1,149 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.Enumerate
--- Copyright   :  (c) Brian Huffman
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates how new sizes of word/int types can be defined and
--- used with SBV.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveDataTypeable    #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-
-module Data.SBV.Examples.Misc.Word4 where
-
-import GHC.Enum (boundedEnumFrom, boundedEnumFromThen, toEnumError, succError, predError)
-
-import Data.Bits
-import Data.Generics (Data, Typeable)
-import System.Random (Random(..))
-
-import Data.SBV
-import Data.SBV.Internals
-
--- | Word4 as a newtype. Invariant: @Word4 x@ should satisfy @x < 16@.
-newtype Word4 = Word4 Word8
-  deriving (Eq, Ord, Data, Typeable)
-
--- | Smart constructor; simplifies conversion from Word8
-word4 :: Word8 -> Word4
-word4 x = Word4 (x .&. 0x0f)
-
--- | Show instance
-instance Show Word4 where
-  show (Word4 x) = show x
-
--- | Read instance. We read as an 8-bit word, and coerce
-instance Read Word4 where
-  readsPrec p s = [ (word4 x, s') | (x, s') <- readsPrec p s ]
-
--- | Bounded instance; from 0 to 255
-instance Bounded Word4 where
-  minBound = Word4 0x00
-  maxBound = Word4 0x0f
-
--- | Enum instance, trivial definitions.
-instance Enum Word4 where
-  succ (Word4 x) = if x < 0x0f then Word4 (succ x) else succError "Word4"
-  pred (Word4 x) = if x > 0x00 then Word4 (pred x) else predError "Word4"
-  toEnum i | 0x00 <= i && i <= 0x0f = Word4 (toEnum i)
-           | otherwise              = toEnumError "Word4" i (Word4 0x00, Word4 0x0f)
-  fromEnum (Word4 x) = fromEnum x
-  -- Comprehensions
-  enumFrom                                     = boundedEnumFrom
-  enumFromThen                                 = boundedEnumFromThen
-  enumFromTo     (Word4 x) (Word4 y)           = map Word4 (enumFromTo x y)
-  enumFromThenTo (Word4 x) (Word4 y) (Word4 z) = map Word4 (enumFromThenTo x y z)
-
--- | Num instance, merely lifts underlying 8-bit operation and casts back
-instance Num Word4 where
-  Word4 x + Word4 y = word4 (x + y)
-  Word4 x * Word4 y = word4 (x * y)
-  Word4 x - Word4 y = word4 (x - y)
-  negate (Word4 x)  = word4 (negate x)
-  abs (Word4 x)     = Word4 x
-  signum (Word4 x)  = Word4 (if x == 0 then 0 else 1)
-  fromInteger n     = word4 (fromInteger n)
-
--- | Real instance simply uses the Word8 instance
-instance Real Word4 where
-  toRational (Word4 x) = toRational x
-
--- | Integral instance, again using Word8 instance and casting. NB. we do
--- not need to use the smart constructor here as neither the quotient nor
--- the remainder can overflow a Word4.
-instance Integral Word4 where
-  quotRem (Word4 x) (Word4 y) = (Word4 q, Word4 r)
-    where (q, r) = quotRem x y
-  toInteger (Word4 x) = toInteger x
-
--- | Bits instance
-instance Bits Word4 where
-  Word4 x  .&.  Word4 y = Word4 (x  .&.  y)
-  Word4 x  .|.  Word4 y = Word4 (x  .|.  y)
-  Word4 x `xor` Word4 y = Word4 (x `xor` y)
-  complement (Word4 x)  = Word4 (x `xor` 0x0f)
-  Word4 x `shift`  i    = word4 (shift x i)
-  Word4 x `shiftL` i    = word4 (shiftL x i)
-  Word4 x `shiftR` i    = Word4 (shiftR x i)
-  Word4 x `rotate` i    = word4 (x `shiftL` k .|. x `shiftR` (4-k))
-                            where k = i .&. 3
-  bitSize _             = 4
-  bitSizeMaybe _        = Just 4
-  isSigned _            = False
-  testBit (Word4 x)     = testBit x
-  bit i                 = word4 (bit i)
-  popCount (Word4 x)    = popCount x
-
--- | Random instance, used in quick-check
-instance Random Word4 where
-  randomR (Word4 lo, Word4 hi) gen = (Word4 x, gen')
-    where (x, gen') = randomR (lo, hi) gen
-  random gen = (Word4 x, gen')
-    where (x, gen') = randomR (0x00, 0x0f) gen
-
--- | SWord4 type synonym
-type SWord4 = SBV Word4
-
--- | SymWord instance, allowing this type to be used in proofs/sat etc.
-instance SymWord Word4 where
-  mkSymWord  = genMkSymVar (KBounded False 4)
-  literal    = genLiteral  (KBounded False 4)
-  fromCW     = genFromCW
-
--- | HasKind instance; simply returning the underlying kind for the type
-instance HasKind Word4 where
-  kindOf _ = KBounded False 4
-
--- | SatModel instance, merely uses the generic parsing method.
-instance SatModel Word4 where
-  parseCWs = genParse (KBounded False 4)
-
--- | SDvisible instance, using 0-extension
-instance SDivisible Word4 where
-  sQuotRem x 0 = (0, x)
-  sQuotRem x y = x `quotRem` y
-  sDivMod  x 0 = (0, x)
-  sDivMod  x y = x `divMod` y
-
--- | SDvisible instance, using default methods
-instance SDivisible SWord4 where
-  sQuotRem = liftQRem
-  sDivMod  = liftDMod
-
--- | SIntegral instance, using default methods
-instance SIntegral Word4
-
--- | Conversion from bits
-instance FromBits SWord4 where
-  fromBitsLE = checkAndConvert 4
-
--- | Joining/splitting to/from Word8
-instance Splittable Word8 Word4 where
-  split x           = (Word4 (x `shiftR` 4), word4 x)
-  Word4 x # Word4 y = (x `shiftL` 4) .|. y
-  extend (Word4 x)  = x
diff --git a/Data/SBV/Examples/Polynomials/Polynomials.hs b/Data/SBV/Examples/Polynomials/Polynomials.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Polynomials/Polynomials.hs
+++ /dev/null
@@ -1,77 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Polynomials.Polynomials
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Simple usage of polynomials over GF(2^n), using Rijndael's
--- finite field: <http://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field>
---
--- The functions available are:
---
---  [/pMult/] GF(2^n) Multiplication
---
---  [/pDiv/] GF(2^n) Division
---
---  [/pMod/] GF(2^n) Modulus
---
---  [/pDivMod/] GF(2^n) Division/Modulus, packed together
---
--- Note that addition in GF(2^n) is simply `xor`, so no custom function is provided.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Polynomials.Polynomials where
-
-import Data.SBV
-
--- | Helper synonym for representing GF(2^8); which are merely 8-bit unsigned words. Largest
--- term in such a polynomial has degree 7.
-type GF28 = SWord8
-
--- | Multiplication in Rijndael's field; usual polynomial multiplication followed by reduction
--- by the irreducible polynomial.  The irreducible used by Rijndael's field is the polynomial
--- @x^8 + x^4 + x^3 + x + 1@, which we write by giving it's /exponents/ in SBV.
--- See: <http://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field>.
--- Note that the irreducible itself is not in GF28! It has a degree of 8.
---
--- NB. You can use the 'showPoly' function to print polynomials nicely, as a mathematician would write.
-gfMult :: GF28 -> GF28 -> GF28
-a `gfMult` b = pMult (a, b, [8, 4, 3, 1, 0])
-
--- | States that the unit polynomial @1@, is the unit element
-multUnit :: GF28 -> SBool
-multUnit x = (x `gfMult` unit) .== x
-  where unit = polynomial [0]   -- x@0
-
--- | States that multiplication is commutative
-multComm :: GF28 -> GF28 -> SBool
-multComm x y = (x `gfMult` y) .== (y `gfMult` x)
-
--- | States that multiplication is associative, note that associativity
--- proofs are notoriously hard for SAT/SMT solvers
-multAssoc :: GF28 -> GF28 -> GF28 -> SBool
-multAssoc x y z = ((x `gfMult` y) `gfMult` z) .== (x `gfMult` (y `gfMult` z))
-
--- | States that the usual multiplication rule holds over GF(2^n) polynomials
--- Checks:
---
--- @
---    if (a, b) = x `pDivMod` y then x = y `pMult` a + b
--- @
---
--- being careful about @y = 0@. When divisor is 0, then quotient is
--- defined to be 0 and the remainder is the numerator.
--- (Note that addition is simply `xor` in GF(2^8).)
-polyDivMod :: GF28 -> GF28 -> SBool
-polyDivMod x y = ite (y .== 0) ((0, x) .== (a, b)) (x .== (y `gfMult` a) `xor` b)
-  where (a, b) = x `pDivMod` y
-
--- | Queries
-testGF28 :: IO ()
-testGF28 = do
-  print =<< prove multUnit
-  print =<< prove multComm
-  -- print =<< prove multAssoc -- takes too long; see above note..
-  print =<< prove polyDivMod
diff --git a/Data/SBV/Examples/Puzzles/Birthday.hs b/Data/SBV/Examples/Puzzles/Birthday.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Birthday.hs
+++ /dev/null
@@ -1,145 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Birthday
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- This is a formalization of the Cheryl's birtday problem, which went viral in April 2015.
--- (See <http://www.nytimes.com/2015/04/15/science/a-math-problem-from-singapore-goes-viral-when-is-cheryls-birthday.html>.)
---
--- Here's the puzzle:
---
--- @
--- Albert and Bernard just met Cheryl. “When’s your birthday?” Albert asked Cheryl.
---
--- Cheryl thought a second and said, “I’m not going to tell you, but I’ll give you some clues.” She wrote down a list of 10 dates:
---
---   May 15, May 16, May 19
---   June 17, June 18
---   July 14, July 16
---   August 14, August 15, August 17
---
--- “My birthday is one of these,” she said.
---
--- Then Cheryl whispered in Albert’s ear the month — and only the month — of her birthday. To Bernard, she whispered the day, and only the day. 
--- “Can you figure it out now?” she asked Albert.
---
--- Albert: I don’t know when your birthday is, but I know Bernard doesn’t know, either.
--- Bernard: I didn’t know originally, but now I do.
--- Albert: Well, now I know, too!
---
--- When is Cheryl’s birthday?
--- @
---
--- NB. Thanks to Amit Goel for suggesting the formalization strategy used in here.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.Birthday where
-
-import Data.SBV
-
------------------------------------------------------------------------------------------------
--- * Types and values
------------------------------------------------------------------------------------------------
-
--- | Represent month by 8-bit words; We can also use an uninterpreted type, but numbers work well here.
-type Month = SWord8
-
--- | Represent day by 8-bit words; Again, an uninterpreted type would work as well.
-type Day = SWord8
-
--- | Months referenced in the problem.
-may, june, july, august :: SWord8
-[may, june, july, august] = [5, 6, 7, 8]
-
------------------------------------------------------------------------------------------------
--- * Helper predicates
------------------------------------------------------------------------------------------------
-
--- | Check that a given month/day combo is a possible birth-date.
-valid :: Month -> Day -> SBool
-valid month day = (month, day) `sElem` candidates
-  where candidates :: [(Month, Day)]
-        candidates = [ (   may, 15), (   may, 16), (   may, 19)
-                     , (  june, 17), (  june, 18)
-                     , (  july, 14), (  july, 16)
-                     , (august, 14), (august, 15), (august, 17)
-                     ]
-
--- | Assert that the given function holds for one of the possible days.
-existsDay :: (Day -> SBool) -> SBool
-existsDay f = bAny (f . literal) [14 .. 19]
-
--- | Assert that the given function holds for all of the possible days.
-forallDay :: (Day -> SBool) -> SBool
-forallDay f = bAll (f . literal) [14 .. 19]
-
--- | Assert that the given function holds for one of the possible months.
-existsMonth :: (Month -> SBool) -> SBool
-existsMonth f = bAny f [may .. august]
-
--- | Assert that the given function holds for all of the possible months.
-forallMonth :: (Month -> SBool) -> SBool
-forallMonth f = bAll f [may .. august]
-
------------------------------------------------------------------------------------------------
--- * The puzzle
------------------------------------------------------------------------------------------------
-
--- | Encode the conversation as given in the puzzle.
---
--- NB. Lee Pike pointed out that not all the constraints are actually necessary! (Private
--- communication.) The puzzle still has a unique solution if the statements 'a1' and 'b1'
--- (i.e., Albert and Bernard saying they themselves do not know the answer) are removed.
--- To experiment you can simply comment out those statements and observe that there still
--- is a unique solution. Thanks to Lee for pointing this out! In fact, it is instructive to
--- assert the conversation line-by-line, and see how the search-space gets reduced in each
--- step.
-puzzle :: Predicate
-puzzle = do birthDay   <- exists "birthDay"
-            birthMonth <- exists "birthMonth"
-
-            -- Albert: I do not know
-            let a1 m = existsDay $ \d1 -> existsDay $ \d2 ->
-                           d1 ./= d2 &&& valid m d1 &&& valid m d2
-
-            -- Albert: I know that Bernard doesn't know
-            let a2 m = forallDay $ \d -> valid m d ==>
-                          existsMonth (\m1 -> existsMonth $ \m2 ->
-                                m1 ./= m2 &&& valid m1 d &&& valid m2 d)
-
-            -- Bernard: I did not know
-            let b1 d = existsMonth $ \m1 -> existsMonth $ \m2 ->
-                           m1 ./= m2 &&& valid m1 d &&& valid m2 d
-
-            -- Bernard: But now I know
-            let b2p m d = valid m d &&& a1 m &&& a2 m
-                b2  d   = forallMonth $ \m1 -> forallMonth $ \m2 ->
-                                (b2p m1 d &&& b2p m2 d) ==> m1 .== m2
-
-            -- Albert: Now I know too
-            let a3p m d = valid m d &&& a1 m &&& a2 m &&& b1 d &&& b2 d
-                a3 m    = forallDay $ \d1 -> forallDay $ \d2 ->
-                                (a3p m d1 &&& a3p m d2) ==> d1 .== d2
-
-            -- Assert all the statements made:
-            constrain $ a1 birthMonth
-            constrain $ a2 birthMonth
-            constrain $ b1 birthDay
-            constrain $ b2 birthDay
-            constrain $ a3 birthMonth
-
-            -- Find a valid birth-day that satisfies the above constraints:
-            return $ valid birthMonth birthDay
-
--- | Find all solutions to the birthday problem. We have:
---
--- >>> cheryl
--- Solution #1:
---   birthDay   = 16 :: Word8
---   birthMonth =  7 :: Word8
--- This is the only solution.
-cheryl :: IO ()
-cheryl = print =<< allSat puzzle
diff --git a/Data/SBV/Examples/Puzzles/Coins.hs b/Data/SBV/Examples/Puzzles/Coins.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Coins.hs
+++ /dev/null
@@ -1,103 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Coins
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Solves the following puzzle:
---
--- @
--- You and a friend pass by a standard coin operated vending machine and you decide to get a candy bar.
--- The price is US $0.95, but after checking your pockets you only have a dollar (US $1) and the machine
--- only takes coins. You turn to your friend and have this conversation:
---   you: Hey, do you have change for a dollar?
---   friend: Let's see. I have 6 US coins but, although they add up to a US $1.15, I can't break a dollar.
---   you: Huh? Can you make change for half a dollar?
---   friend: No.
---   you: How about a quarter?
---   friend: Nope, and before you ask I cant make change for a dime or nickel either.
---   you: Really? and these six coins are all US government coins currently in production? 
---   friend: Yes.
---   you: Well can you just put your coins into the vending machine and buy me a candy bar, and I'll pay you back?
---   friend: Sorry, I would like to but I cant with the coins I have.
--- What coins are your friend holding?
--- @
---
--- To be fair, the problem has no solution /mathematically/. But there is a solution when one takes into account that
--- vending machines typically do not take the 50 cent coins!
---
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.Coins where
-
-import Data.SBV
-
--- | We will represent coins with 16-bit words (more than enough precision for coins).
-type Coin = SWord16
-
--- | Create a coin. The argument Int argument just used for naming the coin. Note that
--- we constrain the value to be one of the valid U.S. coin values as we create it.
-mkCoin :: Int -> Symbolic Coin
-mkCoin i = do c <- exists $ 'c' : show i
-              constrain $ bAny (.== c) [1, 5, 10, 25, 50, 100]
-              return c
-
--- | Return all combinations of a sequence of values.
-combinations :: [a] -> [[a]]
-combinations coins = concat [combs i coins | i <- [1 .. length coins]]
-  where combs 0 _      = [[]]
-        combs _ []     = []
-        combs k (x:xs) = map (x:) (combs (k-1) xs) ++ combs k xs
-
--- | Constraint 1: Cannot make change for a dollar.
-c1 :: [Coin] -> SBool
-c1 xs = sum xs ./= 100
-
--- | Constraint 2: Cannot make change for half a dollar.
-c2 :: [Coin] -> SBool
-c2 xs = sum xs ./= 50
-
--- | Constraint 3: Cannot make change for a quarter.
-c3 :: [Coin] -> SBool
-c3 xs = sum xs ./= 25
-
--- | Constraint 4: Cannot make change for a dime.
-c4 :: [Coin] -> SBool
-c4 xs = sum xs ./= 10
-
--- | Constraint 5: Cannot make change for a nickel
-c5 :: [Coin] -> SBool
-c5 xs = sum xs ./= 5
-
--- | Constraint 6: Cannot buy the candy either. Here's where we need to have the extra knowledge
--- that the vending machines do not take 50 cent coins.
-c6 :: [Coin] -> SBool
-c6 xs = sum (map val xs) ./= 95
-   where val x = ite (x .== 50) 0 x
-
--- | Solve the puzzle. We have:
---
--- >>> puzzle
--- Satisfiable. Model:
---   c1 = 50 :: Word16
---   c2 = 25 :: Word16
---   c3 = 10 :: Word16
---   c4 = 10 :: Word16
---   c5 = 10 :: Word16
---   c6 = 10 :: Word16
---
--- i.e., your friend has 4 dimes, a quarter, and a half dollar.
-puzzle :: IO SatResult
-puzzle = sat $ do
-        cs <- mapM mkCoin [1..6]
-        -- Assert each of the constraints for all combinations that has
-        -- at least two coins (to make change)
-        mapM_ constrain [c s | s <- combinations cs, length s >= 2, c <- [c1, c2, c3, c4, c5, c6]]
-        -- the following constraint is not necessary for solving the puzzle
-        -- however, it makes sure that the solution comes in decreasing value of coins,
-        -- thus allowing the above test to succeed regardless of the solver used.
-        constrain $ bAnd $ zipWith (.>=) cs (tail cs)
-        -- assert that the sum must be 115 cents.
-        return $ sum cs .== 115
diff --git a/Data/SBV/Examples/Puzzles/Counts.hs b/Data/SBV/Examples/Puzzles/Counts.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Counts.hs
+++ /dev/null
@@ -1,83 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Counts
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Consider the sentence:
---
--- @
---    In this sentence, the number of occurrences of 0 is _, of 1 is _, of 2 is _,
---    of 3 is _, of 4 is _, of 5 is _, of 6 is _, of 7 is _, of 8 is _, and of 9 is _.
--- @
---
--- The puzzle is to fill the blanks with numbers, such that the sentence
--- will be correct. There are precisely two solutions to this puzzle, both of
--- which are found by SBV successfully.
---
---  References:
---
---    * Douglas Hofstadter, Metamagical Themes, pg. 27.
---
---    * <http://mathcentral.uregina.ca/mp/archives/previous2002/dec02sol.html>
---
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.Counts where
-
-import Data.SBV
-
--- | We will assume each number can be represented by an 8-bit word, i.e., can be at most 128.
-type Count  = SWord8
-
--- | Given a number, increment the count array depending on the digits of the number
-count :: Count -> [Count] -> [Count]
-count n cnts = ite (n .< 10)
-                   (upd n cnts)                           -- only one digit
-                   (ite (n .< 100)
-                        (upd d1 (upd d2 cnts))            -- two digits
-                        (upd d1 (upd d2 (upd d3 cnts))))  -- three digits
-  where (r1, d1)   = n  `sQuotRem` 10
-        (d3, d2)   = r1 `sQuotRem` 10
-        upd d = zipWith inc [0..]
-          where inc i c = ite (i .== d) (c+1) c
-
--- | Encoding of the puzzle. The solution is a sequence of 10 numbers
--- for the occurrences of the digits such that if we count each digit,
--- we find these numbers.
-puzzle :: [Count] -> SBool
-puzzle cnt = cnt .== last css
-  where ones = replicate 10 1  -- all digits occur once to start with
-        css  = ones : zipWith count cnt css
-
--- | Finds all two known solutions to this puzzle. We have:
---
--- >>> 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.
--- Found: 2 solution(s).
-counts :: IO ()
-counts = do res <- allSat $ puzzle `fmap` mkExistVars 10
-            cnt <- displayModels disp res
-            putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
-  where disp n (_, s) = do putStrLn $ "Solution #" ++ show n
-                           dispSolution s
-        dispSolution :: [Word8] -> IO ()
-        dispSolution ns = putStrLn soln
-          where soln =  "In this sentence, the number of occurrences"
-                     ++  " of 0 is " ++ show (ns !! 0)
-                     ++ ", of 1 is " ++ show (ns !! 1)
-                     ++ ", of 2 is " ++ show (ns !! 2)
-                     ++ ", of 3 is " ++ show (ns !! 3)
-                     ++ ", of 4 is " ++ show (ns !! 4)
-                     ++ ", of 5 is " ++ show (ns !! 5)
-                     ++ ", of 6 is " ++ show (ns !! 6)
-                     ++ ", of 7 is " ++ show (ns !! 7)
-                     ++ ", of 8 is " ++ show (ns !! 8)
-                     ++ ", of 9 is " ++ show (ns !! 9)
-                     ++ "."
-{-# ANN counts ("HLint: ignore Use head" :: String) #-}
diff --git a/Data/SBV/Examples/Puzzles/DogCatMouse.hs b/Data/SBV/Examples/Puzzles/DogCatMouse.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/DogCatMouse.hs
+++ /dev/null
@@ -1,37 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.DogCatMouse
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Puzzle:
---   Spend exactly 100 dollars and buy exactly 100 animals.
---   Dogs cost 15 dollars, cats cost 1 dollar, and mice cost 25 cents each.
---   You have to buy at least one of each.
---   How many of each should you buy?
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.DogCatMouse where
-
-import Data.SBV
-
--- | Prints the only solution:
---
--- >>> puzzle
--- Solution #1:
---   dog   =  3 :: Integer
---   cat   = 41 :: Integer
---   mouse = 56 :: Integer
--- This is the only solution.
-puzzle :: IO AllSatResult
-puzzle = allSat $ do
-           [dog, cat, mouse] <- sIntegers ["dog", "cat", "mouse"]
-           solve [ dog   .>= 1                                           -- at least one dog
-                 , cat   .>= 1                                           -- at least one cat
-                 , mouse .>= 1                                           -- at least one mouse
-                 , dog + cat + mouse .== 100                             -- buy precisely 100 animals
-                 , 15 `per` dog + 1 `per` cat + 0.25 `per` mouse .== 100 -- spend exactly 100 dollars
-                 ]
-  where p `per` q = p * (sFromIntegral q :: SReal)
diff --git a/Data/SBV/Examples/Puzzles/Euler185.hs b/Data/SBV/Examples/Puzzles/Euler185.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Euler185.hs
+++ /dev/null
@@ -1,49 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Euler185
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- A solution to Project Euler problem #185: <http://projecteuler.net/index.php?section=problems&id=185>
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.Euler185 where
-
-import Data.Char(ord)
-import Data.SBV
-
--- | The given guesses and the correct digit counts, encoded as a simple list.
-guesses :: [(String, SWord8)]
-guesses = [ ("5616185650518293", 2), ("3847439647293047", 1), ("5855462940810587", 3)
-          , ("9742855507068353", 3), ("4296849643607543", 3), ("3174248439465858", 1)
-          , ("4513559094146117", 2), ("7890971548908067", 3), ("8157356344118483", 1)
-          , ("2615250744386899", 2), ("8690095851526254", 3), ("6375711915077050", 1)
-          , ("6913859173121360", 1), ("6442889055042768", 2), ("2321386104303845", 0)
-          , ("2326509471271448", 2), ("5251583379644322", 2), ("1748270476758276", 3)
-          , ("4895722652190306", 1), ("3041631117224635", 3), ("1841236454324589", 3)
-          , ("2659862637316867", 2)
-          ]
-
--- | Encode the problem, note that we check digits are within 0-9 as
--- we use 8-bit words to represent them. Otherwise, the constraints are simply
--- generated by zipping the alleged solution with each guess, and making sure the
--- number of matching digits match what's given in the problem statement.
-euler185 :: Symbolic SBool
-euler185 = do soln <- mkExistVars 16
-              return $ bAll digit soln &&& bAnd (map (genConstr soln) guesses)
-  where genConstr a (b, c) = sum (zipWith eq a b) .== (c :: SWord8)
-        digit x = (x :: SWord8) .>= 0 &&& x .<= 9
-        eq x y =  ite (x .== fromIntegral (ord y - ord '0')) 1 0
-
--- | Print out the solution nicely. We have:
---
--- >>> solveEuler185
--- 4640261571849533
--- Number of solutions: 1
-solveEuler185 :: IO ()
-solveEuler185 = do res <- allSat euler185
-                   cnt <- displayModels disp res
-                   putStrLn $ "Number of solutions: " ++ show cnt
-   where disp _ (_, ss) = putStrLn $ concatMap show (ss :: [Word8])
diff --git a/Data/SBV/Examples/Puzzles/Fish.hs b/Data/SBV/Examples/Puzzles/Fish.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Fish.hs
+++ /dev/null
@@ -1,108 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Fish
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Solves the following logic puzzle:
---
---   - The Briton lives in the red house.
---   - The Swede keeps dogs as pets.
---   - The Dane drinks tea.
---   - The green house is left to the white house.
---   - The owner of the green house drinks coffee.
---   - The person who plays football rears birds.
---   - The owner of the yellow house plays baseball.
---   - The man living in the center house drinks milk.
---   - The Norwegian lives in the first house.
---   - The man who plays volleyball lives next to the one who keeps cats.
---   - The man who keeps the horse lives next to the one who plays baseball.
---   - The owner who plays tennis drinks beer.
---   - The German plays hockey.
---   - The Norwegian lives next to the blue house.
---   - The man who plays volleyball has a neighbor who drinks water.
---
--- Who owns the fish?
-------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveAnyClass      #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.SBV.Examples.Puzzles.Fish where
-
-import Data.Generics
-import Data.SBV
-
--- | Colors of houses
-data Color       = Red      | Green    | White      | Yellow    | Blue   deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Nationalities of the occupants
-data Nationality = Briton   | Dane     | Swede      | Norwegian | German deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Beverage choices
-data Beverage    = Tea      | Coffee   | Milk       | Beer      | Water  deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Pets they keep
-data Pet         = Dog      | Horse    | Cat        | Bird      | Fish   deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Sports they engage in
-data Sport       = Football | Baseball | Volleyball | Hockey    | Tennis deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | We have:
---
--- >>> fishOwner
--- German
---
--- 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!
-fishOwner :: IO ()
-fishOwner = do vs <- getModelValues "fishOwner" `fmap` allSat puzzle
-               case vs of
-                 [Just (v::Nationality)] -> print v
-                 []                      -> error "no solution"
-                 _                       -> error "no unique solution"
- where puzzle = do
-
-          let c = uninterpret "color"
-              n = uninterpret "nationality"
-              b = uninterpret "beverage"
-              p = uninterpret "pet"
-              s = uninterpret "sport"
-
-          let i `neighbor` j = i .== j+1 ||| j .== i+1
-              a `is`       v = a .== literal v
-
-          let fact0   = constrain
-              fact1 f = do i <- free_
-                           constrain $ 1 .<= i &&& i .<= (5 :: SInteger)
-                           constrain $ f i
-              fact2 f = do i <- free_
-                           j <- free_
-                           constrain $ 1 .<= i &&& i .<= (5 :: SInteger)
-                           constrain $ 1 .<= j &&& j .<= 5
-                           constrain $ i ./= j
-                           constrain $ f i j
-
-          fact1 $ \i   -> n i `is` Briton     &&& c i `is` Red
-          fact1 $ \i   -> n i `is` Swede      &&& p i `is` Dog
-          fact1 $ \i   -> n i `is` Dane       &&& b i `is` Tea
-          fact2 $ \i j -> c i `is` Green      &&& c j `is` White    &&& i .== j-1
-          fact1 $ \i   -> c i `is` Green      &&& b i `is` Coffee
-          fact1 $ \i   -> s i `is` Football   &&& p i `is` Bird
-          fact1 $ \i   -> c i `is` Yellow     &&& s i `is` Baseball
-          fact0 $         b 3 `is` Milk
-          fact0 $         n 1 `is` Norwegian
-          fact2 $ \i j -> s i `is` Volleyball &&& p j `is` Cat      &&& i `neighbor` j
-          fact2 $ \i j -> p i `is` Horse      &&& s j `is` Baseball &&& i `neighbor` j
-          fact1 $ \i   -> s i `is` Tennis     &&& b i `is` Beer
-          fact1 $ \i   -> n i `is` German     &&& s i `is` Hockey
-          fact2 $ \i j -> n i `is` Norwegian  &&& c j `is` Blue     &&& i `neighbor` j
-          fact2 $ \i j -> s i `is` Volleyball &&& b j `is` Water    &&& i `neighbor` j
-
-          ownsFish <- free "fishOwner"
-          fact1 $ \i -> n i .== ownsFish &&& p i `is` Fish
-
-          return (true :: SBool)
diff --git a/Data/SBV/Examples/Puzzles/MagicSquare.hs b/Data/SBV/Examples/Puzzles/MagicSquare.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/MagicSquare.hs
+++ /dev/null
@@ -1,75 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.MagicSquare
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Solves the magic-square puzzle. An NxN magic square is one where all entries
--- are filled with numbers from 1 to NxN such that sums of all rows, columns
--- and diagonals is the same.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.MagicSquare where
-
-import Data.List (genericLength, transpose)
-
-import Data.SBV
-
--- | Use 32-bit words for elements.
-type Elem  = SWord32
-
--- | A row is a list of elements
-type Row   = [Elem]
-
--- | The puzzle board is a list of rows
-type Board = [Row]
-
--- | Checks that all elements in a list are within bounds
-check :: Elem -> Elem -> [Elem] -> SBool
-check low high = bAll $ \x -> x .>= low &&& x .<= high
-
--- | Get the diagonal of a square matrix
-diag :: [[a]] -> [a]
-diag ((a:_):rs) = a : diag (map tail rs)
-diag _          = []
-
--- | Test if a given board is a magic square
-isMagic :: Board -> SBool
-isMagic rows = bAnd $ fromBool isSquare : allEqual (map sum items) : allDifferent (concat rows) : map chk items
-  where items = d1 : d2 : rows ++ columns
-        n = genericLength rows
-        isSquare = all (\r -> genericLength r == n) rows
-        columns = transpose rows
-        d1 = diag rows
-        d2 = diag (map reverse rows)
-        chk = check (literal 1) (literal (n*n))
-
--- | Group a list of elements in the sublists of length @i@
-chunk :: Int -> [a] -> [[a]]
-chunk _ [] = []
-chunk i xs = let (f, r) = splitAt i xs in f : chunk i r
-
--- | Given @n@, magic @n@ prints all solutions to the @nxn@ magic square problem
-magic :: Int -> IO ()
-magic n
- | n < 0 = putStrLn $ "n must be non-negative, received: " ++ show n
- | True  = do putStrLn $ "Finding all " ++ show n ++ "-magic squares.."
-              res <- allSat $ (isMagic . chunk n) `fmap` mkExistVars n2
-              cnt <- displayModels disp res
-              putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
-   where n2 = n * n
-         disp i (_, model)
-          | lmod /= n2
-          = error $ "Impossible! Backend solver returned " ++ show n ++ " values, was expecting: " ++ show lmod
-          | True
-          = do putStrLn $ "Solution #" ++ show i
-               mapM_ printRow board
-               putStrLn $ "Valid Check: " ++ show (isMagic sboard)
-               putStrLn "Done."
-          where lmod  = length model
-                board = chunk n model
-                sboard = map (map literal) board
-                sh2 z = let s = show z in if length s < 2 then ' ':s else s
-                printRow r = putStr "   " >> mapM_ (\x -> putStr (sh2 x ++ " ")) r >> putStrLn ""
diff --git a/Data/SBV/Examples/Puzzles/NQueens.hs b/Data/SBV/Examples/Puzzles/NQueens.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/NQueens.hs
+++ /dev/null
@@ -1,46 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.NQueens
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Solves the NQueens puzzle: <http://en.wikipedia.org/wiki/Eight_queens_puzzle>
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.NQueens where
-
-import Data.SBV
-
--- | A solution is a sequence of row-numbers where queens should be placed
-type Solution = [SWord8]
-
--- | Checks that a given solution of @n@-queens is valid, i.e., no queen
--- captures any other.
-isValid :: Int -> Solution -> SBool
-isValid n s = bAll rangeFine s &&& allDifferent s &&& bAll checkDiag ijs
-  where rangeFine x = x .>= 1 &&& x .<= fromIntegral n
-        ijs = [(i, j) | i <- [1..n], j <- [i+1..n]]
-        checkDiag (i, j) = diffR ./= diffC
-           where qi = s !! (i-1)
-                 qj = s !! (j-1)
-                 diffR = ite (qi .>= qj) (qi-qj) (qj-qi)
-                 diffC = fromIntegral (j-i)
-
--- | Given @n@, it solves the @n-queens@ puzzle, printing all possible solutions.
-nQueens :: Int -> IO ()
-nQueens n
- | n < 0 = putStrLn $ "n must be non-negative, received: " ++ show n
- | True  = do putStrLn $ "Finding all " ++ show n ++ "-queens solutions.."
-              res <- allSat $ isValid n `fmap` mkExistVars n
-              cnt <- displayModels disp res
-              putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
-   where disp i (_, s) = do putStr $ "Solution #" ++ show i ++ ": "
-                            dispSolution s
-         dispSolution :: [Word8] -> IO ()
-         dispSolution model
-           | lmod /= n = error $ "Impossible! Backend solver returned " ++ show lmod ++ " values, was expecting: " ++ show n
-           | True      = do putStr $ show model
-                            putStrLn $ " (Valid: " ++ show (isValid n (map literal model)) ++ ")"
-           where lmod  = length model
diff --git a/Data/SBV/Examples/Puzzles/SendMoreMoney.hs b/Data/SBV/Examples/Puzzles/SendMoreMoney.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/SendMoreMoney.hs
+++ /dev/null
@@ -1,45 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.SendMoreMoney
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Solves the classic @send + more = money@ puzzle.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.SendMoreMoney where
-
-import Data.SBV
-
--- | Solve the puzzle. We have:
---
--- >>> sendMoreMoney
--- Solution #1:
---   s = 9 :: Integer
---   e = 5 :: Integer
---   n = 6 :: Integer
---   d = 7 :: Integer
---   m = 1 :: Integer
---   o = 0 :: Integer
---   r = 8 :: Integer
---   y = 2 :: Integer
--- This is the only solution.
---
--- That is:
---
--- >>> 9567 + 1085 == 10652
--- True
-sendMoreMoney :: IO AllSatResult
-sendMoreMoney = allSat $ do
-        ds@[s,e,n,d,m,o,r,y] <- mapM sInteger ["s", "e", "n", "d", "m", "o", "r", "y"]
-        let isDigit x = x .>= 0 &&& x .<= 9
-            val xs    = sum $ zipWith (*) (reverse xs) (iterate (*10) 1)
-            send      = val [s,e,n,d]
-            more      = val [m,o,r,e]
-            money     = val [m,o,n,e,y]
-        constrain $ bAll isDigit ds
-        constrain $ allDifferent ds
-        constrain $ s ./= 0 &&& m ./= 0
-        solve [send + more .== money]
diff --git a/Data/SBV/Examples/Puzzles/Sudoku.hs b/Data/SBV/Examples/Puzzles/Sudoku.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/Sudoku.hs
+++ /dev/null
@@ -1,252 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.Sudoku
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- The Sudoku solver, quintessential SMT solver example!
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Puzzles.Sudoku where
-
-import Data.List  (transpose)
-import Data.Maybe (fromJust)
-
-import Data.SBV
-
--------------------------------------------------------------------
--- * Modeling Sudoku
--------------------------------------------------------------------
--- | A row is a sequence of 8-bit words, too large indeed for representing 1-9, but does not harm
-type Row   = [SWord8]
-
--- | A Sudoku board is a sequence of 9 rows
-type Board = [Row]
-
--- | Given a series of elements, make sure they are all different
--- and they all are numbers between 1 and 9
-check :: [SWord8] -> SBool
-check grp = bAnd $ allDifferent grp : map rangeFine grp
-  where rangeFine x = x .> 0 &&& x .<= 9
-
--- | Given a full Sudoku board, check that it is valid
-valid :: Board -> SBool
-valid rows = bAnd $ literal sizesOK : map check (rows ++ columns ++ squares)
-  where sizesOK = length rows == 9 && all (\r -> length r == 9) rows
-        columns = transpose rows
-        regions = transpose [chunk 3 row | row <- rows]
-        squares = [concat sq | sq <- chunk 3 (concat regions)]
-        chunk :: Int -> [a] -> [[a]]
-        chunk _ [] = []
-        chunk i xs = let (f, r) = splitAt i xs in f : chunk i r
-
--- | A puzzle is a pair: First is the number of missing elements, second
--- is a function that given that many elements returns the final board.
-type Puzzle = (Int, [SWord8] -> Board)
-
--------------------------------------------------------------------
--- * Solving Sudoku puzzles
--------------------------------------------------------------------
-
--- | Solve a given puzzle and print the results
-sudoku :: Puzzle -> IO ()
-sudoku p@(i, f) = do putStrLn "Solving the puzzle.."
-                     model <- getModel `fmap` sat ((valid . f) `fmap` mkExistVars i)
-                     case model of
-                       Right sln -> dispSolution p sln
-                       Left m    -> putStrLn $ "Unsolvable puzzle: " ++ m
-
--- | Helper function to display results nicely, not really needed, but helps presentation
-dispSolution :: Puzzle -> (Bool, [Word8]) -> IO ()
-dispSolution (i, f) (_, fs)
-  | lmod /= i = error $ "Impossible! Backend solver returned " ++ show lmod ++ " values, was expecting: " ++ show i
-  | True      = do putStrLn "Final board:"
-                   mapM_ printRow final
-                   putStrLn $ "Valid Check: " ++ show (valid final)
-                   putStrLn "Done."
-  where lmod = length fs
-        final = f (map literal fs)
-        printRow r = putStr "   " >> mapM_ (\x -> putStr (show (fromJust (unliteral x)) ++ " ")) r >> putStrLn ""
-
--- | Find all solutions to a puzzle
-solveAll :: Puzzle -> IO ()
-solveAll p@(i, f) = do putStrLn "Finding all solutions.."
-                       res <- allSat $ (valid . f) `fmap` mkExistVars i
-                       cnt <- displayModels disp res
-                       putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
-   where disp n s = do putStrLn $ "Solution #" ++ show n
-                       dispSolution p s
-
--------------------------------------------------------------------
--- * Example boards
--------------------------------------------------------------------
-
--- | Find an arbitrary good board
-puzzle0 :: Puzzle
-puzzle0 = (81, f)
-  where f   [ a1, a2, a3, a4, a5, a6, a7, a8, a9,
-              b1, b2, b3, b4, b5, b6, b7, b8, b9,
-              c1, c2, c3, c4, c5, c6, c7, c8, c9,
-              d1, d2, d3, d4, d5, d6, d7, d8, d9,
-              e1, e2, e3, e4, e5, e6, e7, e8, e9,
-              f1, f2, f3, f4, f5, f6, f7, f8, f9,
-              g1, g2, g3, g4, g5, g6, g7, g8, g9,
-              h1, h2, h3, h4, h5, h6, h7, h8, h9,
-              i1, i2, i3, i4, i5, i6, i7, i8, i9 ]
-         = [ [a1, a2, a3, a4, a5, a6, a7, a8, a9],
-             [b1, b2, b3, b4, b5, b6, b7, b8, b9],
-             [c1, c2, c3, c4, c5, c6, c7, c8, c9],
-             [d1, d2, d3, d4, d5, d6, d7, d8, d9],
-             [e1, e2, e3, e4, e5, e6, e7, e8, e9],
-             [f1, f2, f3, f4, f5, f6, f7, f8, f9],
-             [g1, g2, g3, g4, g5, g6, g7, g8, g9],
-             [h1, h2, h3, h4, h5, h6, h7, h8, h9],
-             [i1, i2, i3, i4, i5, i6, i7, i8, i9] ]
-        f _ = error "puzzle0 needs exactly 81 elements!"
-
--- | A random puzzle, found on the internet..
-puzzle1 :: Puzzle
-puzzle1 = (49, f)
-  where f   [ a1,     a3, a4, a5, a6, a7,     a9,
-              b1, b2, b3,             b7, b8, b9,
-                  c2,     c4, c5, c6,     c8,
-                      d3,     d5,     d7,
-              e1, e2,     e4, e5, e6,     e8, e9,
-                      f3,     f5,     f7,
-                  g2,     g4, g5, g6,     g8,
-              h1, h2, h3,             h7, h8, h9,
-              i1,     i3, i4, i5, i6, i7,     i9 ]
-         = [ [a1,  6, a3, a4, a5, a6, a7,  1, a9],
-             [b1, b2, b3,  6,  5,  1, b7, b8, b9],
-             [ 1, c2,  7, c4, c5, c6,  6, c8,  2],
-             [ 6,  2, d3,  3, d5,  5, d7,  9,  4],
-             [e1, e2,  3, e4, e5, e6,  2, e8, e9],
-             [ 4,  8, f3,  9, f5,  7, f7,  3,  6],
-             [ 9, g2,  6, g4, g5, g6,  4, g8,  8],
-             [h1, h2, h3,  7,  9,  4, h7, h8, h9],
-             [i1,  5, i3, i4, i5, i6, i7,  7, i9] ]
-        f _ = error "puzzle1 needs exactly 49 elements!"
-
--- | Another random puzzle, found on the internet..
-puzzle2 :: Puzzle
-puzzle2 = (55, f)
-  where f   [     a2,     a4, a5, a6, a7,     a9,
-              b1, b2,     b4,         b7, b8, b9,
-              c1,     c3, c4, c5, c6, c7, c8, c9,
-                  d2, d3, d4,             d8, d9,
-              e1,     e3,     e5,     e7,     e9,
-              f1, f2,             f6, f7, f8,
-              g1, g2, g3, g4, g5, g6, g7,     g9,
-              h1, h2, h3,         h6,     h8, h9,
-              i1,     i3, i4, i5, i6,     i8     ]
-         = [ [ 1, a2,  3, a4, a5, a6, a7,  8, a9],
-             [b1, b2,  6, b4,  4,  8, b7, b8, b9],
-             [c1,  4, c3, c4, c5, c6, c7, c8, c9],
-             [ 2, d2, d3, d4,  9,  6,  1, d8, d9],
-             [e1,  9, e3,  8, e5,  1, e7,  4, e9],
-             [f1, f2,  4,  3,  2, f6, f7, f8,  8],
-             [g1, g2, g3, g4, g5, g6, g7,  7, g9],
-             [h1, h2, h3,  1,  5, h6,  4, h8, h9],
-             [i1,  6, i3, i4, i5, i6,  2, i8,  3] ]
-        f _ = error "puzzle2 needs exactly 55 elements!"
-
--- | Another random puzzle, found on the internet..
-puzzle3 :: Puzzle
-puzzle3 = (56, f)
-  where f   [     a2, a3, a4,     a6,     a8, a9,
-                  b2,     b4, b5, b6, b7, b8, b9,
-              c1, c2, c3, c4,     c6, c7,     c9,
-              d1,     d3,     d5,     d7,     d9,
-                  e2, e3, e4,     e6, e7, e8,
-              f1,     f3,     f5,     f7,     f9,
-              g1,     g3, g4,     g6, g7, g8, g9,
-              h1, h2, h3, h4, h5, h6,     h8,
-              i1, i2,     i4,     i6, i7, i8     ]
-         = [ [ 6, a2, a3, a4,  1, a6,  5, a8, a9],
-             [ 8, b2,  3, b4, b5, b6, b7, b8, b9],
-             [c1, c2, c3, c4,  6, c6, c7,  2, c9],
-             [d1,  3, d3,  1, d5,  8, d7,  9, d9],
-             [ 1, e2, e3, e4,  9, e6, e7, e8,  4],
-             [f1,  5, f3,  2, f5,  3, f7,  1, f9],
-             [g1,  7, g3, g4,  3, g6, g7, g8, g9],
-             [h1, h2, h3, h4, h5, h6,  3, h8,  6],
-             [i1, i2,  4, i4,  5, i6, i7, i8,  9] ]
-        f _ = error "puzzle3 needs exactly 56 elements!"
-
--- | According to the web, this is the toughest 
--- sudoku puzzle ever.. It even has a name: Al Escargot:
--- <http://zonkedyak.blogspot.com/2006/11/worlds-hardest-sudoku-puzzle-al.html>
-puzzle4 :: Puzzle
-puzzle4 = (58, f)
-  where f   [     a2, a3, a4, a5,     a7,     a9,
-              b1,     b3, b4,     b6, b7, b8,
-              c1, c2,         c5, c6,     c8, c9,
-              d1, d2,         d5, d6,     d8, d9,
-              e1,     e3, e4,     e6, e7, e8,
-                  f2, f3, f4, f5,     f7, f8, f9,
-                  g2, g3, g4, g5, g6, g7,     g9,
-              h1,     h3, h4, h5, h6, h7, h8,
-              i1, i2,     i4, i5, i6,     i8, i9 ]
-         = [ [ 1, a2, a3, a4, a5,  7, a7,  9, a9],
-             [b1,  3, b3, b4,  2, b6, b7, b8,  8],
-             [c1, c2,  9,  6, c5, c6,  5, c8, c9],
-             [d1, d2,  5,  3, d5, d6,  9, d8, d9],
-             [e1,  1, e3, e4,  8, e6, e7, e8,  2],
-             [ 6, f2, f3, f4, f5,  4, f7, f8, f9],
-             [ 3, g2, g3, g4, g5, g6, g7,  1, g9],
-             [h1,  4, h3, h4, h5, h6, h7, h8,  7],
-             [i1, i2,  7, i4, i5, i6,  3, i8, i9] ]
-        f _ = error "puzzle4 needs exactly 58 elements!"
-
--- | This one has been called diabolical, apparently
-puzzle5 :: Puzzle
-puzzle5 = (53, f)
-  where f   [ a1,     a3,     a5, a6,         a9,
-              b1,         b4, b5,     b7,     b9,
-                  c2,     c4, c5, c6, c7, c8, c9,
-              d1, d2,     d4,     d6, d7, d8,
-              e1, e2, e3,     e5,     e7, e8, e9,
-                  f2, f3, f4,     f6,     f8, f9,
-              g1, g2, g3, g4, g5, g6,     g8,
-              h1,     h3,     h5, h6,         h9,
-              i1,         i4, i5,     i7,     i9 ]
-         = [ [a1,  9, a3,  7, a5, a6,  8,  6, a9],
-             [b1,  3,  1, b4, b5,  5, b7,  2, b9],
-             [ 8, c2,  6, c4, c5, c6, c7, c8, c9],
-             [d1, d2,  7, d4,  5, d6, d7, d8,  6],
-             [e1, e2, e3,  3, e5,  7, e7, e8, e9],
-             [ 5, f2, f3, f4,  1, f6,  7, f8, f9],
-             [g1, g2, g3, g4, g5, g6,  1, g8,  9],
-             [h1,  2, h3,  6, h5, h6,  3,  5, h9],
-             [i1,  5,  4, i4, i5,  8, i7,  7, i9] ]
-        f _ = error "puzzle5 needs exactly 53 elements!"
-
--- | The following is nefarious according to
--- <http://haskell.org/haskellwiki/Sudoku>
-puzzle6 :: Puzzle
-puzzle6 = (64, f)
-  where f   [ a1, a2, a3, a4,     a6, a7,     a9,
-              b1,     b3, b4, b5, b6, b7, b8, b9,
-              c1, c2,     c4, c5, c6, c7, c8, c9,
-              d1,     d3, d4, d5, d6,     d8,
-                  e2, e3, e4,     e6, e7, e8, e9,
-              f1, f2, f3, f4, f5, f6,     f8, f9,
-              g1, g2,         g5,     g7, g8, g9,
-                  h2, h3,     h5, h6,     h8, h9,
-              i1, i2, i3, i4, i5, i6, i7,     i9  ]
-         = [ [a1, a2, a3, a4,  6, a6, a7,  8, a9],
-             [b1,  2, b3, b4, b5, b6, b7, b8, b9],
-             [c1, c2,  1, c4, c5, c6, c7, c8, c9],
-             [d1,  7, d3, d4, d5, d6,  1, d8,  2],
-             [ 5, e2, e3, e4,  3, e6, e7, e8, e9],
-             [f1, f2, f3, f4, f5, f6,  4, f8, f9],
-             [g1, g2,  4,  2, g5,  1, g7, g8, g9],
-             [ 3, h2, h3,  7, h5, h6,  6, h8, h9],
-             [i1, i2, i3, i4, i5, i6, i7,  5, i9] ]
-        f _ = error "puzzle6 needs exactly 64 elements!"
-
--- | Solve them all, this takes a fraction of a second to run for each case
-allPuzzles :: IO ()
-allPuzzles = mapM_ sudoku [puzzle0, puzzle1, puzzle2, puzzle3, puzzle4, puzzle5, puzzle6]
diff --git a/Data/SBV/Examples/Puzzles/U2Bridge.hs b/Data/SBV/Examples/Puzzles/U2Bridge.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Puzzles/U2Bridge.hs
+++ /dev/null
@@ -1,272 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Puzzles.U2Bridge
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- The famous U2 bridge crossing puzzle: <http://www.braingle.com/brainteasers/515/u2.html>
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveAnyClass       #-}
-{-# LANGUAGE DeriveDataTypeable   #-}
-{-# LANGUAGE DeriveGeneric        #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Data.SBV.Examples.Puzzles.U2Bridge where
-
-import Control.Monad       (unless)
-import Control.Monad.State (State, runState, put, get, modify, evalState)
-
-import Data.Generics (Data)
-import GHC.Generics (Generic)
-
-import Data.SBV
-
--------------------------------------------------------------
--- * Modeling the puzzle
--------------------------------------------------------------
-
--- | U2 band members. We want to translate this to SMT-Lib
--- as a data-type, and hence the deriving mechanism.
-data U2Member = Bono | Edge | Adam | Larry deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
-
--- | Symbolic shorthand for a 'U2Member'
-type SU2Member = SBV U2Member
-
--- | Shorthands for symbolic versions of the members
-bono, edge, adam, larry :: SU2Member
-[bono, edge, adam, larry] = map literal [Bono, Edge, Adam, Larry]
-
--- | Model time using 32 bits
-type Time  = Word32
-
--- | Symbolic variant for time
-type STime = SBV Time
-
--- | Crossing times for each member of the band
-crossTime :: U2Member -> Time
-crossTime Bono  = 1
-crossTime Edge  = 2
-crossTime Adam  = 5
-crossTime Larry = 10
-
--- | The symbolic variant.. The duplication is unfortunate.
-sCrossTime :: SU2Member -> STime
-sCrossTime m =   ite (m .== bono) (literal (crossTime Bono))
-               $ ite (m .== edge) (literal (crossTime Edge))
-               $ ite (m .== adam) (literal (crossTime Adam))
-                                  (literal (crossTime Larry)) -- Must be Larry
-
--- | Location of the flash
-data Location = Here | There deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
-
--- | Symbolic variant of 'Location'
-type SLocation = SBV Location
-
--- | Shorthands for symbolic versions of locations
-here, there :: SLocation
-[here, there]  = map literal [Here, There]
-
--- | The status of the puzzle after each move
---
--- This type is equipped with an automatically derived 'Mergeable' instance
--- because each field is 'Mergeable'. A 'Generic' instance must also be derived
--- for this to work, and the 'DeriveAnyClass' language extension must be
--- enabled. The derived 'Mergeable' instance simply walks down the structure
--- field by field and merges each one. An equivalent hand-written 'Mergeable'
--- instance is provided in a comment below.
-data Status = Status { time   :: STime       -- ^ elapsed time
-                     , flash  :: SLocation   -- ^ location of the flash
-                     , lBono  :: SLocation   -- ^ location of Bono
-                     , lEdge  :: SLocation   -- ^ location of Edge
-                     , lAdam  :: SLocation   -- ^ location of Adam
-                     , lLarry :: SLocation   -- ^ location of Larry
-                     } deriving (Generic, Mergeable)
-
--- The derived Mergeable instance is equivalent to the following:
---
--- instance Mergeable Status where
---   symbolicMerge f t s1 s2 = Status { time   = symbolicMerge f t (time   s1) (time   s2)
---                                    , flash  = symbolicMerge f t (flash  s1) (flash  s2)
---                                    , lBono  = symbolicMerge f t (lBono  s1) (lBono  s2)
---                                    , lEdge  = symbolicMerge f t (lEdge  s1) (lEdge  s2)
---                                    , lAdam  = symbolicMerge f t (lAdam  s1) (lAdam  s2)
---                                    , lLarry = symbolicMerge f t (lLarry s1) (lLarry s2)
---                                    }
-
--- | Start configuration, time elapsed is 0 and everybody is 'here'
-start :: Status
-start = Status { time   = 0
-               , flash  = here
-               , lBono  = here
-               , lEdge  = here
-               , lAdam  = here
-               , lLarry = here
-               }
-
--- | A puzzle move is modeled as a state-transformer
-type Move a = State Status a
-
--- | Mergeable instance for 'Move' simply pushes the merging the data after run of each branch
--- starting from the same state.
-instance Mergeable a => Mergeable (Move a) where
-  symbolicMerge f t a b
-    = do s <- get
-         let (ar, s1) = runState a s
-             (br, s2) = runState b s
-         put $ symbolicMerge f t s1 s2
-         return $ symbolicMerge f t ar br
-
--- | Read the state via an accessor function
-peek :: (Status -> a) -> Move a
-peek f = do s <- get
-            return (f s)
-
--- | Given an arbitrary member, return his location
-whereIs :: SU2Member -> Move SLocation
-whereIs p =  ite (p .== bono) (peek lBono)
-           $ ite (p .== edge) (peek lEdge)
-           $ ite (p .== adam) (peek lAdam)
-                              (peek lLarry)
-
--- | Transferring the flash to the other side
-xferFlash :: Move ()
-xferFlash = modify $ \s -> s{flash = ite (flash s .== here) there here}
-
--- | Transferring a person to the other side
-xferPerson :: SU2Member -> Move ()
-xferPerson p =  do [lb, le, la, ll] <- mapM peek [lBono, lEdge, lAdam, lLarry]
-                   let move l = ite (l .== here) there here
-                       lb' = ite (p .== bono)  (move lb) lb
-                       le' = ite (p .== edge)  (move le) le
-                       la' = ite (p .== adam)  (move la) la
-                       ll' = ite (p .== larry) (move ll) ll
-                   modify $ \s -> s{lBono = lb', lEdge = le', lAdam = la', lLarry = ll'}
-
--- | Increment the time, when only one person crosses
-bumpTime1 :: SU2Member -> Move ()
-bumpTime1 p = modify $ \s -> s{time = time s + sCrossTime p}
-
--- | Increment the time, when two people cross together
-bumpTime2 :: SU2Member -> SU2Member -> Move ()
-bumpTime2 p1 p2 = modify $ \s -> s{time = time s + sCrossTime p1 `smax` sCrossTime p2}
-
--- | Symbolic version of 'when'
-whenS :: SBool -> Move () -> Move ()
-whenS t a = ite t a (return ())
-
--- | Move one member, remembering to take the flash
-move1 :: SU2Member -> Move ()
-move1 p = do f <- peek flash
-             l <- whereIs p
-             -- only do the move if the person and the flash are at the same side
-             whenS (f .== l) $ do bumpTime1 p
-                                  xferFlash
-                                  xferPerson p
-
--- | Move two members, again with the flash
-move2 :: SU2Member -> SU2Member -> Move ()
-move2 p1 p2 = do f  <- peek flash
-                 l1 <- whereIs p1
-                 l2 <- whereIs p2
-                 -- only do the move if both people and the flash are at the same side
-                 whenS (f .== l1 &&& f .== l2) $ do bumpTime2 p1 p2
-                                                    xferFlash
-                                                    xferPerson p1
-                                                    xferPerson p2
-
--------------------------------------------------------------
--- * Actions
--------------------------------------------------------------
-
--- | A move action is a sequence of triples. The first component is symbolically
--- True if only one member crosses. (In this case the third element of the triple
--- is irrelevant.) If the first component is (symbolically) False, then both members
--- move together
-type Actions = [(SBool, SU2Member, SU2Member)]
-
--- | Run a sequence of given actions.
-run :: Actions -> Move [Status]
-run = mapM step
- where step (b, p1, p2) = ite b (move1 p1) (move2 p1 p2) >> get
-
--------------------------------------------------------------
--- * Recognizing valid solutions
--------------------------------------------------------------
-
--- | Check if a given sequence of actions is valid, i.e., they must all
--- cross the bridge according to the rules and in less than 17 seconds
-isValid :: Actions -> SBool
-isValid as = time end .<= 17 &&& bAll check as &&& zigZag (cycle [there, here]) (map flash states) &&& bAll (.== there) [lBono end, lEdge end, lAdam end, lLarry end]
-  where check (s, p1, p2) =   (bnot s ==> p1 .> p2)      -- for two person moves, ensure first person is "larger"
-                          &&& (s      ==> p2 .== bono)   -- for one person moves, ensure second person is always "bono"
-        states = evalState (run as) start
-        end = last states
-        zigZag reqs locs = bAnd $ zipWith (.==) locs reqs
-
--------------------------------------------------------------
--- * Solving the puzzle
--------------------------------------------------------------
-
--- | See if there is a solution that has precisely @n@ steps
-solveN :: Int -> IO Bool
-solveN n = do putStrLn $ "Checking for solutions with " ++ show n ++ " move" ++ plu n ++ "."
-              let genAct = do b  <- exists_
-                              p1 <- exists_
-                              p2 <- exists_
-                              return (b, p1, p2)
-              res <- allSat $ isValid `fmap` mapM (const genAct) [1..n]
-              cnt <- displayModels disp res
-              if cnt == 0 then return False
-                          else do putStrLn $ "Found: " ++ show cnt ++ " solution" ++ plu cnt ++ " with " ++ show n ++ " move" ++ plu n ++ "."
-                                  return True
-  where plu v = if v == 1 then "" else "s"
-        disp :: Int -> (Bool, [(Bool, U2Member, U2Member)]) -> IO ()
-        disp i (_, ss)
-         | lss /= n = error $ "Expected " ++ show n ++ " results; got: " ++ show lss
-         | True     = do putStrLn $ "Solution #" ++ show i ++ ": "
-                         go False 0 ss
-                         return ()
-         where lss  = length ss
-               go _ t []                   = putStrLn $ "Total time: " ++ show t
-               go l t ((True,  a, _):rest) = do putStrLn $ sh2 t ++ shL l ++ show a
-                                                go (not l) (t + crossTime a) rest
-               go l t ((False, a, b):rest) = do putStrLn $ sh2 t ++ shL l ++ show a ++ ", " ++ show b
-                                                go (not l) (t + crossTime a `max` crossTime b) rest
-               sh2 t = let s = show t in if length s < 2 then ' ' : s else s
-               shL False = " --> "
-               shL True  = " <-- "
-
--- | Solve the U2-bridge crossing puzzle, starting by testing solutions with
--- increasing number of steps, until we find one. We have:
---
--- >>> solveU2
--- Checking for solutions with 1 move.
--- Checking for solutions with 2 moves.
--- Checking for solutions with 3 moves.
--- Checking for solutions with 4 moves.
--- Checking for solutions with 5 moves.
--- Solution #1:
---  0 --> Edge, Bono
---  2 <-- Edge
---  4 --> Larry, Adam
--- 14 <-- Bono
--- 15 --> Edge, Bono
--- Total time: 17
--- Solution #2:
---  0 --> Edge, Bono
---  2 <-- Bono
---  3 --> Larry, Adam
--- 13 <-- Edge
--- 15 --> Edge, Bono
--- Total time: 17
--- Found: 2 solutions with 5 moves.
---
--- Finding all possible solutions to the puzzle.
-solveU2 :: IO ()
-solveU2 = go 1
- where go i = do p <- solveN i
-                 unless p $ go (i+1)
diff --git a/Data/SBV/Examples/Uninterpreted/AUF.hs b/Data/SBV/Examples/Uninterpreted/AUF.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/AUF.hs
+++ /dev/null
@@ -1,93 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.AUF
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Formalizes and proves the following theorem, about arithmetic,
--- uninterpreted functions, and arrays. (For reference, see <http://research.microsoft.com/en-us/um/redmond/projects/z3/fmcad06-slides.pdf>
--- slide number 24):
---
--- @
---    x + 2 = y  implies  f (read (write (a, x, 3), y - 2)) = f (y - x + 1)
--- @
---
--- We interpret the types as follows (other interpretations certainly possible):
---
---    [/x/] 'SWord32' (32-bit unsigned address)
---
---    [/y/] 'SWord32' (32-bit unsigned address)
---
---    [/a/] An array, indexed by 32-bit addresses, returning 32-bit unsigned integers
---
---    [/f/] An uninterpreted function of type @'SWord32' -> 'SWord64'@
---
--- The function @read@ and @write@ are usual array operations.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Uninterpreted.AUF where
-
-import Data.SBV
-
---------------------------------------------------------------
--- * Model using functional arrays
---------------------------------------------------------------
-
--- | The array type, takes symbolic 32-bit unsigned indexes
--- and stores 32-bit unsigned symbolic values. These are
--- functional arrays where reading before writing a cell
--- throws an exception.
-type A = SFunArray Word32 Word32
-
--- | Uninterpreted function in the theorem
-f :: SWord32 -> SWord64
-f = uninterpret "f"
-
--- | Correctness theorem. We state it for all values of @x@, @y@, and 
--- the array @a@. We also take an arbitrary initializer for the array.
-thm1 :: SWord32 -> SWord32 -> A -> SWord32 -> SBool
-thm1 x y a initVal = lhs ==> rhs
-  where a'  = resetArray a initVal -- initialize array
-        lhs = x + 2 .== y
-        rhs =     f (readArray (writeArray a' x 3) (y - 2))
-              .== f (y - x + 1)
-
--- | Prints Q.E.D. when run, as expected
---
--- >>> proveThm1
--- Q.E.D.
-proveThm1 :: IO ThmResult
-proveThm1 = prove $ do
-                x <- free "x"
-                y <- free "y"
-                a <- newArray "a" Nothing
-                i <- free "initVal"
-                return $ thm1 x y a i
-
---------------------------------------------------------------
--- * Model using SMT arrays
---------------------------------------------------------------
-
--- | This version directly uses SMT-arrays and hence does not need an initializer.
--- Reading an element before writing to it returns an arbitrary value.
-type B = SArray Word32 Word32
-
--- | Same as 'thm1', except we don't need an initializer with the 'SArray' model.
-thm2 :: SWord32 -> SWord32 -> B -> SBool
-thm2 x y a = lhs ==> rhs
-  where lhs = x + 2 .== y
-        rhs =     f (readArray (writeArray a x 3) (y - 2))
-              .== f (y - x + 1)
-
--- | Prints Q.E.D. when run, as expected:
---
--- >>> proveThm2
--- Q.E.D.
-proveThm2 :: IO ThmResult
-proveThm2 = prove $ do
-                x <- free "x"
-                y <- free "y"
-                a <- newArray "b" Nothing
-                return $ thm2 x y a
diff --git a/Data/SBV/Examples/Uninterpreted/Deduce.hs b/Data/SBV/Examples/Uninterpreted/Deduce.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/Deduce.hs
+++ /dev/null
@@ -1,95 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.Deduce
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates uninterpreted sorts and how they can be used for deduction.
--- This example is inspired by the discussion at <http://stackoverflow.com/questions/10635783/using-axioms-for-deductions-in-z3>,
--- essentially showing how to show the required deduction using SBV.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-
-module Data.SBV.Examples.Uninterpreted.Deduce where
-
-import Data.Generics
-import Data.SBV
-
--- we will have our own "uninterpreted" functions corresponding
--- to not/or/and, so hide their Prelude counterparts.
-import Prelude hiding (not, or, and)
-
------------------------------------------------------------------------------
--- * Representing uninterpreted booleans
------------------------------------------------------------------------------
-
--- | The uninterpreted sort 'B', corresponding to the carrier.
--- To prevent SBV from translating it to an enumerated type, we simply attach an unused field
-newtype B = B () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-
--- | Handy shortcut for the type of symbolic values over 'B'
-type SB = SBV B
-
------------------------------------------------------------------------------
--- * Uninterpreted connectives over 'B'
------------------------------------------------------------------------------
-
--- | Uninterpreted logical connective 'and'
-and :: SB -> SB -> SB
-and = uninterpret "AND"
-
--- | Uninterpreted logical connective 'or'
-or :: SB -> SB -> SB
-or  = uninterpret "OR"
-
--- | Uninterpreted logical connective 'not'
-not :: SB -> SB
-not = uninterpret "NOT"
-
------------------------------------------------------------------------------
--- * Axioms of the logical system
------------------------------------------------------------------------------
-
--- | Distributivity of OR over AND, as an axiom in terms of
--- the uninterpreted functions we have introduced. Note how
--- variables range over the uninterpreted sort 'B'.
-ax1 :: [String]
-ax1 = [ "(assert (forall ((p B) (q B) (r B))"
-      , "   (= (AND (OR p q) (OR p r))"
-      , "      (OR p (AND q r)))))"
-      ]
-
--- | One of De Morgan's laws, again as an axiom in terms
--- of our uninterpeted logical connectives.
-ax2 :: [String]
-ax2 = [ "(assert (forall ((p B) (q B))"
-      , "   (= (NOT (OR p q))"
-      , "      (AND (NOT p) (NOT q)))))"
-      ]
-
--- | Double negation axiom, similar to the above.
-ax3 :: [String]
-ax3 = ["(assert (forall ((p B)) (= (NOT (NOT p)) p)))"]
-
------------------------------------------------------------------------------
--- * Demonstrated deduction
------------------------------------------------------------------------------
-
--- | Proves the equivalence @NOT (p OR (q AND r)) == (NOT p AND NOT q) OR (NOT p AND NOT r)@,
--- following from the axioms we have specified above. We have:
---
--- >>> test
--- Q.E.D.
-test :: IO ThmResult
-test = prove $ do addAxiom "OR distributes over AND" ax1
-                  addAxiom "de Morgan"               ax2
-                  addAxiom "double negation"         ax3
-                  p <- free "p"
-                  q <- free "q"
-                  r <- free "r"
-                  return $   not (p `or` (q `and` r))
-                         .== (not p `and` not q) `or` (not p `and` not r)
diff --git a/Data/SBV/Examples/Uninterpreted/Function.hs b/Data/SBV/Examples/Uninterpreted/Function.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/Function.hs
+++ /dev/null
@@ -1,25 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.Function
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates function counter-examples
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Uninterpreted.Function where
-
-import Data.SBV
-
--- | An uninterpreted function
-f :: SWord8 -> SWord8 -> SWord16
-f = uninterpret "f"
-
--- | Asserts that @f x z == f (y+2) z@ whenever @x == y+2@. Naturally correct:
---
--- >>> prove thmGood
--- Q.E.D.
-thmGood :: SWord8 -> SWord8 -> SWord8 -> SBool
-thmGood x y z = x .== y+2 ==> f x z .== f (y + 2) z
diff --git a/Data/SBV/Examples/Uninterpreted/Shannon.hs b/Data/SBV/Examples/Uninterpreted/Shannon.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/Shannon.hs
+++ /dev/null
@@ -1,129 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.Shannon
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Proves (instances of) Shannon's expansion theorem and other relevant
--- facts.  See: <http://en.wikipedia.org/wiki/Shannon's_expansion>
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Uninterpreted.Shannon where
-
-import Data.SBV
-
------------------------------------------------------------------------------
--- * Boolean functions
------------------------------------------------------------------------------
-
--- | A ternary boolean function
-type Ternary = SBool -> SBool -> SBool -> SBool
-
--- | A binary boolean function
-type Binary = SBool -> SBool-> SBool
-
------------------------------------------------------------------------------
--- * Shannon cofactors
------------------------------------------------------------------------------
-
--- | Positive Shannon cofactor of a boolean function, with
--- respect to its first argument
-pos :: (SBool -> a) -> a
-pos f = f true
-
--- | Negative Shannon cofactor of a boolean function, with
--- respect to its first argument
-neg :: (SBool -> a) -> a
-neg f = f false
-
------------------------------------------------------------------------------
--- * Shannon expansion theorem
------------------------------------------------------------------------------
-
--- | Shannon's expansion over the first argument of a function. We have:
---
--- >>> shannon
--- Q.E.D.
-shannon :: IO ThmResult
-shannon = prove $ \x y z -> f x y z .== (x &&& pos f y z ||| bnot x &&& neg f y z)
- where f :: Ternary
-       f = uninterpret "f"
-
--- | Alternative form of Shannon's expansion over the first argument of a function. We have:
---
--- >>> shannon2
--- Q.E.D.
-shannon2 :: IO ThmResult
-shannon2 = prove $ \x y z -> f x y z .== ((x ||| neg f y z) &&& (bnot x ||| pos f y z))
- where f :: Ternary
-       f = uninterpret "f"
-
------------------------------------------------------------------------------
--- * Derivatives
------------------------------------------------------------------------------
-
--- | Computing the derivative of a boolean function (boolean difference).
--- Defined as exclusive-or of Shannon cofactors with respect to that
--- variable.
-derivative :: Ternary -> Binary
-derivative f y z = pos f y z <+> neg f y z
-
--- | The no-wiggle theorem: If the derivative of a function with respect to
--- a variable is constant False, then that variable does not "wiggle" the
--- function; i.e., any changes to it won't affect the result of the function.
--- In fact, we have an equivalence: The variable only changes the
--- result of the function iff the derivative with respect to it is not False:
---
--- >>> noWiggle
--- Q.E.D.
-noWiggle :: IO ThmResult
-noWiggle = prove $ \y z -> bnot (f' y z) <=> pos f y z .== neg f y z
-  where f :: Ternary
-        f  = uninterpret "f"
-        f' = derivative f
-
------------------------------------------------------------------------------
--- * Universal quantification
------------------------------------------------------------------------------
-
--- | Universal quantification of a boolean function with respect to a variable.
--- Simply defined as the conjunction of the Shannon cofactors.
-universal :: Ternary -> Binary
-universal f y z = pos f y z &&& neg f y z
-
--- | Show that universal quantification is really meaningful: That is, if the universal
--- quantification with respect to a variable is True, then both cofactors are true for
--- those arguments. Of course, this is a trivial theorem if you think about it for a
--- moment, or you can just let SBV prove it for you:
---
--- >>> univOK
--- Q.E.D.
-univOK :: IO ThmResult
-univOK = prove $ \y z -> f' y z ==> pos f y z &&& neg f y z
-  where f :: Ternary
-        f  = uninterpret "f"
-        f' = universal f
-
------------------------------------------------------------------------------
--- * Existential quantification
------------------------------------------------------------------------------
-
--- | Existential quantification of a boolean function with respect to a variable.
--- Simply defined as the conjunction of the Shannon cofactors.
-existential :: Ternary -> Binary
-existential f y z = pos f y z ||| neg f y z
-
--- | Show that existential quantification is really meaningful: That is, if the existential
--- quantification with respect to a variable is True, then one of the cofactors must be true for
--- those arguments. Again, this is a trivial theorem if you think about it for a moment, but
--- we will just let SBV prove it:
---
--- >>> existsOK
--- Q.E.D.
-existsOK :: IO ThmResult
-existsOK = prove $ \y z -> f' y z ==> pos f y z ||| neg f y z
-  where f :: Ternary
-        f  = uninterpret "f"
-        f' = existential f
diff --git a/Data/SBV/Examples/Uninterpreted/Sort.hs b/Data/SBV/Examples/Uninterpreted/Sort.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/Sort.hs
+++ /dev/null
@@ -1,50 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.Sort
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates uninterpreted sorts, together with axioms.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-
-module Data.SBV.Examples.Uninterpreted.Sort where
-
-import Data.Generics
-import Data.SBV
-
--- | A new data-type that we expect to use in an uninterpreted fashion
--- in the backend SMT solver. Note the custom @deriving@ clause, which
--- takes care of most of the boilerplate. The () field is needed so
--- SBV will not translate it to an enumerated data-type
-newtype Q = Q () deriving (Eq, Ord, Data, Read, Show, SymWord, HasKind)
-
--- | Declare an uninterpreted function that works over Q's
-f :: SBV Q -> SBV Q
-f = uninterpret "f"
-
--- | A satisfiable example, stating that there is an element of the domain
--- 'Q' such that 'f' returns a different element. Note that this is valid only
--- when the domain 'Q' has at least two elements. We have:
---
--- >>> t1
--- Satisfiable. Model:
---   x = Q!val!0 :: Q
-t1 :: IO SatResult
-t1 = sat $ do x <- free "x"
-              return $ f x ./= x
-
--- | This is a variant on the first example, except we also add an axiom
--- for the sort, stating that the domain 'Q' has only one element. In this case
--- the problem naturally becomes unsat. We have:
---
--- >>> t2
--- Unsatisfiable
-t2 :: IO SatResult
-t2 = sat $ do x <- free "x"
-              addAxiom "Q" ["(assert (forall ((x Q) (y Q)) (= x y)))"]
-              return $ f x ./= x
diff --git a/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs b/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs
+++ /dev/null
@@ -1,75 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Uninterpreted.UISortAllSat
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Demonstrates uninterpreted sorts and how all-sat behaves for them.
--- Thanks to Eric Seidel for the idea.
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveDataTypeable #-}
-
-module Data.SBV.Examples.Uninterpreted.UISortAllSat where
-
-import Data.Generics
-import Data.SBV
-
--- | A "list-like" data type, but one we plan to uninterpret at the SMT level.
--- The actual shape is really immaterial for us, but could be used as a proxy
--- to generate test cases or explore data-space in some other part of a program.
--- Note that we neither rely on the shape of this data, nor need the actual
--- constructors.
-data L = Nil
-       | Cons Int L
-       deriving (Eq, Ord, Show, Read, Data)
-
--- | Declare instances to make 'L' a usable uninterpreted sort. First we need the
--- 'SymWord' instance, with the default definition sufficing.
-instance SymWord L
-
--- | Similarly, 'HasKind's default implementation is sufficient.
-instance HasKind L
-
--- | An uninterpreted "classify" function. Really, we only care about
--- the fact that such a function exists, not what it does.
-classify :: SBV L -> SInteger
-classify = uninterpret "classify"
-
--- | Formulate a query that essentially asserts a cardinality constraint on
--- the uninterpreted sort 'L'. The goal is to say there are precisely 3
--- such things, as it might be the case. We manage this by declaring four
--- elements, and asserting that for a free variable of this sort, the
--- shape of the data matches one of these three instances. That is, we
--- assert that all the instances of the data 'L' can be classified into
--- 3 equivalence classes. Then, allSat returns all the possible instances,
--- which of course are all uninterpreted.
---
--- As expected, we have:
---
--- >>> genLs
--- Solution #1:
---   l  = L!val!0 :: L
---   l0 = L!val!0 :: L
---   l1 = L!val!1 :: L
---   l2 = L!val!2 :: L
--- Solution #2:
---   l  = L!val!2 :: L
---   l0 = L!val!0 :: L
---   l1 = L!val!1 :: L
---   l2 = L!val!2 :: L
--- Solution #3:
---   l  = L!val!1 :: L
---   l0 = L!val!0 :: L
---   l1 = L!val!1 :: L
---   l2 = L!val!2 :: L
--- 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
diff --git a/Data/SBV/Float.hs b/Data/SBV/Float.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Float.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Float
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A collection of arbitrary float operations.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Float (
+        -- * Type-sized floats
+        FP(..)
+
+        -- * Constructing values
+        , fpFromRawRep, fpFromBigFloat, fpNaN, fpInf, fpZero
+
+        -- * Operations
+        , fpFromInteger, fpFromRational, fpFromFloat, fpFromDouble, fpEncodeFloat
+        ) where
+
+import Data.SBV.Core.SizedFloats
diff --git a/Data/SBV/Internals.hs b/Data/SBV/Internals.hs
--- a/Data/SBV/Internals.hs
+++ b/Data/SBV/Internals.hs
@@ -1,41 +1,176 @@
----------------------------------------------------------------------------------
+-----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Internals
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Internals
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- 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!)
+-----------------------------------------------------------------------------
 
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes       #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Internals (
   -- * Running symbolic programs /manually/
-  Result(..), SBVRunMode(..)
+    Result(..), SBVRunMode(..), IStage(..), QueryContext(..), VarContext(..), SatModel(..), mkNewState
+
+  -- * Solver capabilities
+  , SolverCapabilities(..)
+
   -- * Internal structures useful for low-level programming
-  , module Data.SBV.BitVectors.Data
+  , module Data.SBV.Core.Data
+
+  -- * Is this name reserved?
+  , isReserved, UIName(..)
+
   -- * Operations useful for instantiating SBV type classes
-  , genLiteral, genFromCW, genMkSymVar, checkAndConvert, genParse, showModel, SMTModel(..), liftQRem, liftDMod
-  -- * Polynomial operations that operate on bit-vectors
-  , ites, mdp, addPoly
-  -- * Compilation to C
+  , genLiteral, genFromCV, CV(..), genMkSymVar, genParse, showModel, SMTModel(..), liftQRem, liftDMod, registerKind, svToSV
+  , ProvableM(), SatisfiableM(), UICodeKind(..)
+
+  -- * Compilation to C, extras
   , compileToC', compileToCLib'
+
   -- * Code generation primitives
   , module Data.SBV.Compilers.CodeGen
+
   -- * Various math utilities around floats
   , module Data.SBV.Utils.Numeric
+
+  -- * Pretty number printing
+  , module Data.SBV.Utils.PrettyNum
+
+  -- * Timing computations
+  , module Data.SBV.Utils.TDiff
+
+  -- * Coordinating with the solver
+  -- $coordinateSolverInfo
+  , sendStringToSolver, sendRequestToSolver, retrieveResponseFromSolver
+
+  -- * Defining new metrics
+  , addSValOptGoal
+  , sFloatAsComparableSWord32,  sDoubleAsComparableSWord64,  sFloatingPointAsComparableSWord
+  , sComparableSWord32AsSFloat, sComparableSWord64AsSDouble, sComparableSWordAsSFloatingPoint
+
+  -- * Generalized floats
+  , svFloatingPointAsSWord
+
+  -- * Lambdas and axioms
+  , lambda, lambdaStr, constraint, constraintStr, Lambda(..), Constraint(..), LambdaScope(..)
+
+  -- * TP induction extras
+  , HasInductionSchema(..), internalAxiom
   ) where
 
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model      (genLiteral, genFromCW, genMkSymVar)
-import Data.SBV.BitVectors.Splittable (checkAndConvert)
-import Data.SBV.BitVectors.Model      (liftQRem, liftDMod)
-import Data.SBV.Compilers.C           (compileToC', compileToCLib')
+import Control.Monad.IO.Class (MonadIO)
+
+import Data.SBV.Core.Data hiding (Forall(..), Exists(..), ForallN(..), ExistsN(..), ExistsUnique(..), Skolemize(..), QNot(..))
+
+import Data.SBV.Core.Kind       (BVIsNonZero, ValidFloat)
+import Data.SBV.Core.Model      (genLiteral, genFromCV, genMkSymVar, liftQRem, liftDMod)
+import Data.SBV.Core.Symbolic   (IStage(..), QueryContext(..), MonadQuery, addSValOptGoal, registerKind, VarContext(..), svToSV, mkNewState, UICodeKind(..), UIName(..))
+
+import Data.SBV.Core.Floating   (sFloatAsComparableSWord32,  sDoubleAsComparableSWord64,  sFloatingPointAsComparableSWord, svFloatingPointAsSWord)
+
+import qualified Data.SBV.Core.Floating as CF (sComparableSWord32AsSFloat, sComparableSWord64AsSDouble, sComparableSWordAsSFloatingPoint)
+
+import Data.SBV.Compilers.C       (compileToC', compileToCLib')
 import Data.SBV.Compilers.CodeGen
-import Data.SBV.SMT.SMT               (genParse, showModel)
-import Data.SBV.Tools.Polynomial      (ites, mdp, addPoly)
+
+import Data.SBV.SMT.SMTLibNames
+import Data.SBV.SMT.SMT (genParse, showModel, SatModel(..))
+
+import Data.SBV.Provers.Prover (ProvableM, SatisfiableM)
+
 import Data.SBV.Utils.Numeric
 
-{-# ANN module ("HLint: ignore Use import/export shortcut" :: String) #-}
+import Data.SBV.Utils.TDiff
+import Data.SBV.Utils.PrettyNum
+
+import GHC.TypeLits
+
+import qualified Data.SBV.Control.Utils as Query
+import qualified Data.Text              as T
+
+import Data.SBV.Lambda
+
+import Data.SBV.TP.Kernel
+
+#ifdef DOCTEST
+--- $setup
+--  >>> :set -XScopedTypeVariables
+--- >>> import Data.SBV
+#endif
+
+-- | Send an arbitrary string to the solver in a query.
+-- Note that this is inherently dangerous as it can put the solver in an arbitrary
+-- state and confuse SBV. If you use this feature, you are on your own!
+sendStringToSolver :: (MonadIO m, MonadQuery m) => String -> m ()
+sendStringToSolver = Query.send False . T.pack
+
+-- | Retrieve multiple responses from the solver, until it responds with a user given
+-- tag that we shall arrange for internally. The optional timeout is in milliseconds.
+-- If the time-out is exceeded, then we will raise an error. Note that this is inherently
+-- dangerous as it can put the solver in an arbitrary state and confuse SBV. If you use this
+-- feature, you are on your own!
+retrieveResponseFromSolver :: (MonadIO m, MonadQuery m) => String -> Maybe Int -> m [String]
+retrieveResponseFromSolver = Query.retrieveResponse
+
+-- | Send an arbitrary string to the solver in a query, and return a response.
+-- Note that this is inherently dangerous as it can put the solver in an arbitrary
+-- state and confuse SBV.
+sendRequestToSolver :: (MonadIO m, MonadQuery m) => String -> m String
+sendRequestToSolver = Query.ask . T.pack
+
+{- $coordinateSolverInfo
+In rare cases it might be necessary to send an arbitrary string down to the solver. Needless to say, this
+should be avoided if at all possible. Users should prefer the provided API. If you do find yourself
+needing 'Data.SBV.Control.Utils.send' and 'Data.SBV.Control.Utils.ask' directly, please get in touch to see if SBV can support a typed API for your use case.
+Similarly, the function 'retrieveResponseFromSolver' might occasionally be necessary to clean-up the communication
+buffer. We would like to hear if you do need these functions regularly so we can provide better support.
+-}
+
+-- | Inverse transformation to 'sFloatAsComparableSWord32'. Note that this isn't a perfect inverse, since @-0@ maps to @0@ and back to @0@.
+-- Otherwise, it's faithful:
+--
+-- >>> prove  $ \x -> let f = sComparableSWord32AsSFloat x in fpIsNaN f .|| fpIsNegativeZero f .|| sFloatAsComparableSWord32 f .== x
+-- Q.E.D.
+-- >>> prove $ \x -> fpIsNegativeZero x .|| sComparableSWord32AsSFloat (sFloatAsComparableSWord32 x) `fpIsEqualObject` x
+-- Q.E.D.
+sComparableSWord32AsSFloat :: SWord32 -> SFloat
+sComparableSWord32AsSFloat = CF.sComparableSWord32AsSFloat
+
+-- | Inverse transformation to 'sDoubleAsComparableSWord64'. Note that this isn't a perfect inverse, since @-0@ maps to @0@ and back to @0@.
+-- Otherwise, it's faithful:
+--
+-- >>> prove  $ \x -> let d = sComparableSWord64AsSDouble x in fpIsNaN d .|| fpIsNegativeZero d .|| sDoubleAsComparableSWord64 d .== x
+-- Q.E.D.
+-- >>> prove $ \x -> fpIsNegativeZero x .|| sComparableSWord64AsSDouble (sDoubleAsComparableSWord64 x) `fpIsEqualObject` x
+-- Q.E.D.
+sComparableSWord64AsSDouble :: SWord64 -> SDouble
+sComparableSWord64AsSDouble = CF.sComparableSWord64AsSDouble
+
+-- | Inverse transformation to 'sFloatingPointAsComparableSWord'. Note that this isn't a perfect inverse, since @-0@ maps to @0@ and back to @0@.
+-- Otherwise, it's faithful:
+--
+-- >>> prove  $ \x -> let d :: SFPHalf = sComparableSWordAsSFloatingPoint x in fpIsNaN d .|| fpIsNegativeZero d .|| sFloatingPointAsComparableSWord d .== x
+-- Q.E.D.
+-- >>> prove $ \x -> fpIsNegativeZero x .|| sComparableSWordAsSFloatingPoint (sFloatingPointAsComparableSWord x) `fpIsEqualObject` (x :: SFPHalf)
+-- Q.E.D.
+sComparableSWordAsSFloatingPoint :: forall eb sb. (KnownNat (eb + sb), BVIsNonZero (eb + sb), ValidFloat eb sb) => SWord (eb + sb) -> SFloatingPoint eb sb
+sComparableSWordAsSFloatingPoint = CF.sComparableSWordAsSFloatingPoint
+
+{- HLint ignore module "Use import/export shortcut" -}
diff --git a/Data/SBV/Lambda.hs b/Data/SBV/Lambda.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Lambda.hs
@@ -0,0 +1,485 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Lambda
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Generating lambda-expressions, constraints, and named functions, for (limited)
+-- higher-order function support in SBV.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE NamedFieldPuns       #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE TupleSections        #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Lambda (
+            lambda,      lambdaStr
+          , lambdaWithInfo, LambdaInfo(..)
+          , constraint,  constraintStr
+          , LambdaScope(..)
+        ) where
+
+import Control.Monad       (join)
+import Control.Monad.Trans (liftIO, MonadIO)
+
+import qualified Data.Text as T
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind
+import Data.SBV.SMT.SMTLib2
+import Data.SBV.Utils.Lib       (showText)
+import Data.SBV.Utils.PrettyNum
+
+import           Data.SBV.Core.Symbolic hiding   (mkNewState)
+import qualified Data.SBV.Core.Symbolic as     S (mkNewState)
+
+import Data.IORef (readIORef, modifyIORef')
+import Data.List
+import Data.Maybe (fromMaybe)
+import qualified Data.Map.Strict as Map
+
+import qualified Data.Foldable as F
+import qualified Data.Set      as Set
+
+import qualified Data.Generics.Uniplate.Data as G
+
+-- | What's the scope of the generated lambda?
+data LambdaScope = HigherOrderArg   -- This lambda will be firstified, hence can't have any free variables
+                 | TopLevel         -- This lambda is used to represent a quantified axiom, can have free vars
+
+-- LambdaInfo is defined in Data.SBV.Core.Symbolic and re-exported from here for backwards compatibility.
+
+data Defn = Defn [String]                        -- The uninterpreted names referred to in the body
+                 [String]                        -- Free variables (i.e., not uninterpreted nor bound in the definition itself)
+                 (Maybe [(Quantifier, T.Text)])  -- Param declaration groups, if any
+                 (Int -> T.Text)                 -- Body, given the tab amount.
+
+-- | Make a new substate from the incoming state, sharing parts as necessary
+inSubState :: MonadIO m => LambdaScope -> State -> (State -> m b) -> m b
+inSubState scope inState comp = do
+
+        newLevel <- do ll <- liftIO $ readIORef (rLambdaLevel inState)
+                       pure $ case ll of
+                                Nothing -> -- We used to error out here, as this is nested-lambda
+                                           -- But the recent fixes to support for higher-order functions made this
+                                           -- unnecessary. (I hope!)
+                                           Just 0
+                                Just i  -> case scope of
+                                             HigherOrderArg -> Nothing
+                                             TopLevel       -> Just $ i + 1
+
+        stEmpty <- S.mkNewState (stCfg inState) (LambdaGen newLevel)
+
+        let share fld = fld inState   -- reuse the field from the parent-context
+            fresh fld = fld stEmpty   -- create a new field here
+
+        -- freshen certain fields, sharing some from the parent, and run the comp
+        -- Here's the guidance:
+        --
+        --    * Anything that's "shared" updates the calling context. It better be the case
+        --      that the caller can handle that info.
+        --    * Anything that's "fresh" will be used in this substate, and will be forgotten.
+        --      It better be the case that in "toLambda" below, you do something with it.
+        --
+        -- Note the above applies to all the IORefs, which is most of the state, though
+        -- not all. For the time being, those are pathCond, stCfg, and startTime; which
+        -- don't really impact anything.
+        comp State {
+                   -- These are not IORefs; so we share by copying  the value; changes won't be copied back
+                     sbvContext = share sbvContext
+                   , pathCond   = share pathCond
+                   , startTime  = share startTime
+
+                   -- These are shared IORef's; and is shared, so they will be copied back to the parent state
+                   , rProgInfo             = share rProgInfo
+                   , rIncState             = share rIncState
+                   , rCInfo                = share rCInfo
+                   , rUsedKinds            = share rUsedKinds
+                   , rUsedLbls             = share rUsedLbls
+                   , rUIMap                = share rUIMap
+                   , rUserFuncs            = share rUserFuncs
+                   , rCompilingFuncs       = share rCompilingFuncs
+                   , rCgMap                = share rCgMap
+                   , rDefns                = share rDefns
+                   , rMeasureChecks        = share rMeasureChecks
+                   , rFuncLambdaInfos      = share rFuncLambdaInfos
+                   , rSkipMeasureChecks    = share rSkipMeasureChecks
+                   , rNoTermCheckFunctions = share rNoTermCheckFunctions
+                   , rSMTOptions           = share rSMTOptions
+                   , rOptGoals             = share rOptGoals
+                   , rAsserts              = share rAsserts
+                   , rOutstandingAsserts   = share rOutstandingAsserts
+                   , rPartitionVars        = share rPartitionVars
+
+                   -- Everything else is fresh in the substate; i.e., will not copy back
+                   , stCfg        = fresh stCfg
+                   , runMode      = fresh runMode
+                   , rctr         = fresh rctr
+                   , freshNameCtr = fresh freshNameCtr
+                   , rLambdaLevel = fresh rLambdaLevel
+                   , rtblMap      = fresh rtblMap
+                   , rinps        = fresh rinps
+                   , rlambdaInps  = fresh rlambdaInps
+                   , rConstraints = fresh rConstraints
+                   , rObservables = fresh rObservables
+                   , routs        = fresh routs
+                   , spgm         = fresh spgm
+                   , rconstMap    = fresh rconstMap
+                   , rexprMap     = fresh rexprMap
+                   , rSVCache     = fresh rSVCache
+                   , rQueryState  = fresh rQueryState
+
+                   -- keep track of our parent
+                   , parentState = Just inState
+                   }
+
+-- In this case, we expect just one group of parameters, with universal quantification
+extractAllUniversals :: [(Quantifier, T.Text)] -> T.Text
+extractAllUniversals [(ALL, s)] = s
+extractAllUniversals other      = error $ unlines [ ""
+                                                  , "*** Data.SBV.Lambda: Impossible happened. Got existential quantifiers."
+                                                  , "***"
+                                                  , "***  Params: " ++ show (map (\(q, t) -> (q, T.unpack t)) other)
+                                                  , "***"
+                                                  , "*** Please report this as a bug!"
+                                                  ]
+
+
+-- | Generic creator for anonymous lambdas.
+lambdaGen :: (MonadIO m, Lambda (SymbolicT m) a) => LambdaScope -> (Defn -> b) -> State -> Kind -> a -> m b
+lambdaGen scope trans inState fk f = inSubState scope inState $ \st -> handle <$> convert st fk (mkLambda st f)
+  where handle d@(Defn _ frees _ _)
+            | null frees
+            = trans d
+            | True
+            = error $ unlines [ ""
+                              , "*** Data.SBV.Lambda: Detected free variables passed to a lambda."
+                              , "***"
+                              , "***  Free vars : " ++ unwords frees
+                              , "***  Definition: " ++ shift (lines (sh d))
+                              , "***"
+                              , "*** SBV currently does not support lambda-functions that capture variables. For"
+                              , "*** instance, consider:"
+                              , "***"
+                              , "***     map (\\x -> map (\\y -> x + y))"
+                              , "***"
+                              , "*** where the inner 'map' uses 'x', bound by the outer 'map'. Instead, create"
+                              , "*** a closure instead:"
+                              , "***"
+                              , "***     map (\\x -> map (Closure { closureEnv = x"
+                              , "***                             , closureFun = \\env y -> env + y"
+                              , "***                             }))"
+                              , "***"
+                              , "*** which will explicitly create the closure before calling 'map'. The environment can"
+                              , "*** be any symbolic value: You can use a tuple to support multiple free variables."
+                              , "***"
+                              , "*** (SBV firstifies higher-order functions via a simple translation to make it fit with"
+                              , "*** SMTLib's first-order logic. This translation does not currently support free"
+                              , "*** variables. In technical terms, we would need to do closure conversion and lambda-lifting."
+                              , "*** SBV isn't capable of doing the closure-conversion part, relying on the user to do so.)"
+                              , "***"
+                              , "*** Please rewrite your program to create a closure and use that as an argument."
+                              , "*** If this solution isn't applicable, or if you'd like help doing so, please get in"
+                              , "*** touch for further possible enhancements."
+                              ]
+
+        sh (Defn _unints _frees Nothing       body) = T.unpack (body 0)
+        sh (Defn _unints _frees (Just params) body) = "(lambda " ++ T.unpack (extractAllUniversals params) ++ "\n" ++ T.unpack (body 2) ++ ")"
+
+        shift []     = []
+        shift (x:xs) = intercalate "\n" (x : map tab xs)
+          where tab s = "***              " ++ s
+
+-- | Create an SMTLib lambda, in the given state.
+lambda :: (MonadIO m, Lambda (SymbolicT m) a) => State -> LambdaScope -> Kind -> a -> m SMTDef
+lambda inState scope fk = lambdaGen scope mkLam inState fk
+   where mkLam (Defn unints _frees params body) = SMTDef fk unints (extractAllUniversals <$> params) body
+
+-- | Like 'lambda', but also returns the sub-state's DAG info for measure verification.
+lambdaWithInfo :: (MonadIO m, Lambda (SymbolicT m) a) => State -> LambdaScope -> Kind -> a -> m (SMTDef, LambdaInfo)
+lambdaWithInfo inState scope fk f = inSubState scope inState $ \st -> do
+   defn <- handleDefn <$> convert st fk (mkLambda st f)
+   info <- liftIO $ extractLambdaInfo st
+   pure (defn, info)
+   where handleDefn d@(Defn _ frees _ _)
+            | null frees = mkLam d
+            | True       = error $ unlines [ ""
+                                           , "*** Data.SBV.Lambda: Detected free variables in a function with a measure."
+                                           , "***  Free vars: " ++ unwords frees
+                                           ]
+         mkLam (Defn unints _frees params body) = SMTDef fk unints (extractAllUniversals <$> params) body
+
+-- | Extract DAG information from a lambda sub-state.
+extractLambdaInfo :: State -> IO LambdaInfo
+extractLambdaInfo st = do
+   SBVPgm asgns <- readIORef (spgm st)
+   linps        <- readIORef (rlambdaInps st)
+   outs         <- readIORef (routs st)
+   cmap         <- readIORef (rconstMap st)
+   let params = [(q, getSV nsv) | (q, nsv) <- F.toList linps]
+       outSV  = case F.toList outs of
+                  [o] -> o
+                  os  -> error $ "Data.SBV.Lambda.extractLambdaInfo: expected exactly one output, got " ++ show (length os)
+   pure LambdaInfo { liAssignments = asgns
+                   , liParams      = params
+                   , liOutput      = outSV
+                   , liConsts      = map swap $ Map.toList cmap
+                   }
+   where swap (a, b) = (b, a)
+
+-- | Create an anonymous lambda, rendered as n SMTLib string. The kind passed is the kind of the final result.
+lambdaStr :: (MonadIO m, Lambda (SymbolicT m) a) => State -> LambdaScope -> Kind -> a -> m SMTLambda
+lambdaStr st scope k a = SMTLambda <$> lambdaGen scope mkLam st k a
+   where mkLam (Defn _unints _frees Nothing       body) = body 0
+         mkLam (Defn _unints _frees (Just params) body) = "(lambda " <> extractAllUniversals params <> "\n" <> body 2 <> ")"
+
+-- | Generic constraint generator.
+constraintGen :: (MonadIO m, Constraint (SymbolicT m) a) => LambdaScope -> ([String] -> (Int -> T.Text) -> b) -> State -> a -> m b
+constraintGen scope trans inState@State{rProgInfo} f = do
+   -- indicate we have quantifiers
+   liftIO $ modifyIORef' rProgInfo (\u -> u{hasQuants = True})
+
+   let mkDef (Defn deps _frees Nothing       body) = trans deps body
+       mkDef (Defn deps _frees (Just params) body) = trans deps $ \i -> T.unwords (map mkGroup params) <> "\n"
+                                                                     <> body (i + 2)
+                                                                     <> T.replicate (length params) ")"
+       mkGroup (ALL, s) = "(forall " <> s
+       mkGroup (EX,  s) = "(exists " <> s
+
+   inSubState scope inState $ \st -> mkDef <$> convert st KBool (mkConstraint st f >>= output >> pure ())
+
+-- | A constraint can be turned into a boolean
+instance Constraint Symbolic a => QuantifiedBool a where
+  quantifiedBool qb = SBV $ SVal KBool $ Right $ cache f
+    where f st = liftIO $ constraint st qb
+
+-- | Generate a constraint.
+-- We allow free variables here (first arg of constraintGen). This might prove to be not kosher!
+constraint :: (MonadIO m, Constraint (SymbolicT m) a) => State -> a -> m SV
+constraint st = join . constraintGen TopLevel mkSV st
+   where mkSV _deps d = liftIO $ newExpr st KBool (SBVApp (QuantifiedBool (d 0)) [])
+
+-- | Generate a constraint, string version
+-- We allow free variables here (first arg of constraintGen). This might prove to be not kosher!
+constraintStr :: (MonadIO m, Constraint (SymbolicT m) a) => State -> a -> m String
+constraintStr = constraintGen TopLevel toStr
+   where toStr deps body = T.unpack $ T.intercalate "\n" [ "; user defined axiom: " <> T.pack (depInfo deps)
+                                                          , "(assert " <> body 2 <> ")"
+                                                          ]
+
+         depInfo [] = ""
+         depInfo ds = "[Refers to: " ++ intercalate ", " ds ++ "]"
+
+-- | Convert to an appropriate SMTLib representation.
+convert :: MonadIO m => State -> Kind -> SymbolicT m () -> m Defn
+convert st expectedKind comp = do
+   ((), res)   <- runSymbolicInState st comp
+   curProgInfo <- liftIO $ readIORef (rProgInfo st)
+   level       <- liftIO $ readIORef (rLambdaLevel st)
+   pure $ toLambda level curProgInfo (stCfg st) expectedKind res
+
+-- | Convert the result of a symbolic run to a more abstract representation
+toLambda :: Maybe Int -> ProgInfo -> SMTConfig -> Kind -> Result -> Defn
+toLambda level curProgInfo cfg expectedKind result@Result{resAsgns = SBVPgm asgnsSeq} = sh result
+ where tbd xs = error $ unlines $ "*** Data.SBV.lambda: Unsupported construct." : map ("*** " ++) ("" : xs ++ ["", report])
+       bad xs = error $ unlines $ "*** Data.SBV.lambda: Impossible happened."   : map ("*** " ++) ("" : xs ++ ["", bugReport])
+       report    = "Please request this as a feature at https://github.com/LeventErkok/sbv/issues"
+       bugReport = "Please report this at https://github.com/LeventErkok/sbv/issues"
+
+       sh (Result _hasQuants    -- Has quantified booleans? Does not apply
+
+                  _ki           -- Kind info, we're assuming that all the kinds used are already available in the surrounding context.
+                                -- There's no way to create a new kind in a lambda. If a new kind is used, it should be registered.
+
+                  _qcInfo       -- Quickcheck info, does not apply, ignored
+
+                  _observables  -- Observables: There's no way to display these, so ignore
+
+                  _codeSegs     -- UI code segments: Again, shouldn't happen; if present, error out
+
+                  is            -- Inputs
+
+                  ( _allConsts  -- Not needed, consts are sufficient for this translation
+                  , consts      -- constants used
+                  )
+
+                  tbls          -- Tables
+
+                  _uis          -- Uninterpreted constants: nothing to do with them
+                  _axs          -- Axioms definitions    : nothing to do with them
+
+                  pgm           -- Assignments
+
+                  cstrs         -- Additional constraints: Not currently supported inside lambda's
+                  assertions    -- Assertions: Not currently supported inside lambda's
+
+                  outputs       -- Outputs of the lambda (should be singular)
+         )
+         | not (null cstrs)
+         = tbd [ "Constraints."
+               , "  Saw: " ++ show (length cstrs) ++ " additional constraint(s)."
+               ]
+         | not (null assertions)
+         = tbd [ "Assertions."
+               , "  Saw: " ++ intercalate ", " [n | (n, _, _) <- assertions]
+               ]
+
+         {- Simply ignore the observables, instead of choking on them,
+          - This allows for more robust coding, though it might be confusing.
+         | not (null observables)
+         = tbd [ "Observables."
+               , "  Saw: " ++ intercalate ", " [n | (n, _, _) <- observables]
+               ]
+         -}
+
+         | kindOf out /= expectedKind
+         = bad [ "Expected kind and final kind do not match"
+               , "   Saw     : " ++ show (kindOf out)
+               , "   Expected: " ++ show expectedKind
+               ]
+         | True
+         = res
+         where res = Defn (nub [T.unpack nm | Uninterpreted nm <- G.universeBi allOps])
+                          frees
+                          mbParam
+                          body
+
+               -- Below can simply be defined as: nub (sort (G.universeBi asgnsSeq))
+               -- Alas, it turns out this is really expensive when we have nested lambdas, so we do an explicit walk
+               allOps = Set.toList $ foldl' (\sofar (_, SBVApp o _) -> Set.insert o sofar) Set.empty asgnsSeq
+
+               params = case is of
+                          ResultTopInps as -> bad [ "Top inputs"
+                                                  , "   Saw: " ++ show as
+                                                  ]
+                          ResultLamInps xs -> map (\(q, v) -> (q, getSV v)) xs
+
+               frees = map show badFrees
+                 where (defs, uses) = unzip [(d, u) | (d, SBVApp _ u) <- F.toList asgnsSeq]
+                       defSet       = Set.fromList (defs ++ map snd params ++ map fst constants)
+                       useSet       = Set.fromList (concat uses)
+                       allFrees     = Set.toList (useSet `Set.difference` defSet)
+                       badFrees     = filter (not . global . getId . swNodeId) allFrees
+
+                       -- is this a global?
+                       global (_, Just 0, _) = True
+                       global (_, _     , n) = n < 0  -- -1/-2 for false true
+
+               mbParam
+                 | null params = Nothing
+                 | True        = Just [(q, paramList (map snd l)) | l@((q, _) : _)  <- pGroups]
+                 where pGroups = groupBy (\(q1, _) (q2, _) -> q1 == q2) params
+                       paramList ps = "(" <> T.unwords (map (\p -> "(" <> showText p <> " " <> smtType (kindOf p) <> ")")  ps) <> ")"
+
+               body tabAmnt
+                 | null constTables
+                 , null nonConstTables
+                 , Just e <- simpleBody (map (, Nothing) constBindings ++ svBindings) out
+                 = tab <> e
+                 | True
+                 = T.intercalate "\n" $ map (tab <>)  $  [mkLet sv  | sv <- constBindings]
+                                                       ++ [mkTable t | t  <- constTables]
+                                                       ++ walk svBindings nonConstTables
+                                                       ++ [shift <> showText out <> T.replicate totalClose ")"]
+
+                 where tab  = T.replicate tabAmnt " "
+
+                       mkBind l r   = shift <> "(let ((" <> l <> " " <> r <> "))"
+                       mkLet (s, v) = mkBind (showText s) v
+
+                       -- Align according to level.
+                       shift = T.replicate (24 + 16 * (fromMaybe 0 level - 1)) " "
+
+                       mkTable (((i, ak, rk), elts), _) = mkBind nm (lambdaTable (T.map (const ' ') nm) ak rk elts)
+                          where nm = "table" <> showText i
+
+                       totalClose = length constBindings
+                                  + length svBindings
+                                  + length constTables
+                                  + length nonConstTables
+
+                       walk []  []        = []
+                       walk []  remaining = error $ "Data.SBV: Impossible: Ran out of bindings, but tables remain: " ++ show remaining
+                       walk (cur@((SV _ nd, _), _) : rest)  remaining =  map (mkTable . snd) ready
+                                                                      ++ [mkLocalBind cur]
+                                                                      ++ walk rest notReady
+                          where (ready, notReady) = partition (\(need, _) -> need < getLLI nd) remaining
+                                mkLocalBind (b, Nothing) = mkLet b
+                                mkLocalBind (b, Just l)  = mkLet b <> " ; " <> T.pack l
+
+               getLLI :: NodeId -> (Int, Int)
+               getLLI (NodeId (_, mbl, i)) = (fromMaybe 0 mbl, i)
+
+               -- if we have just one definition returning it, and if the expression itself is simple enough (single-line), simplify
+               -- If the line has new-lines we typically don't want to mess with it, but that causes a memory leak
+               -- (see https://github.com/LeventErkok/sbv/issues/733), so only do it if we're being verbose for debugging purposes.
+               mkPretty = verbose cfg
+
+               simpleBody :: [((SV, T.Text), Maybe String)] -> SV -> Maybe T.Text
+               simpleBody [((v, e), Nothing)] o | v == o, not mkPretty || not (T.any (== '\n') e) = Just e
+               simpleBody _                   _                                                   = Nothing
+
+               assignments = F.toList (pgmAssignments pgm)
+
+               constants = filter ((`notElem` [falseSV, trueSV]) . fst) consts
+
+               constBindings :: [(SV, T.Text)]
+               constBindings = map mkConst constants
+                 where mkConst :: (SV, CV) -> (SV, T.Text)
+                       mkConst (sv, cv) = (sv, cvToSMTLib cv)
+
+               svBindings :: [((SV, T.Text), Maybe String)]
+               svBindings = map mkAsgn assignments
+                 where mkAsgn (sv, e@(SBVApp (Label l) _)) = ((sv, converter e), Just l)
+                       mkAsgn (sv, e)                      = ((sv, converter e), Nothing)
+
+                       converter = cvtExp cfg curProgInfo (capabilities (solver cfg)) rm tableMap
+
+
+               out :: SV
+               out = case outputs of
+                       [o] -> o
+                       _   -> bad [ "Unexpected non-singular output"
+                                  , "   Saw: " ++ show outputs
+                                  ]
+
+               rm = roundingMode cfg
+
+               -- NB. The following is dead-code, since we ensure tbls is empty
+               -- We used to support this, but there are issues, so dropping support
+               -- See, for instance, https://github.com/LeventErkok/sbv/issues/664
+               (tableMap, constTables, nonConstTablesUnindexed) = constructTables consts tbls
+
+               -- Index each non-const table with the largest index of SV it needs
+               nonConstTables = [ (maximum ((0, 0) : [getLLI n | SV _ n <- elts]), nct)
+                                | nct@((_, elts), _) <- nonConstTablesUnindexed]
+
+               lambdaTable :: T.Text -> Kind -> Kind -> [SV] -> T.Text
+               lambdaTable extraSpace ak rk elts = "(lambda ((" <> lv <> " " <> smtType ak <> "))" <> space <> chain 0 elts <> ")"
+                 where cnst k i = cvtCV (mkConstCV k (i::Integer))
+
+                       lv = "idx"
+
+                       -- If more than 5 elts, use new-lines
+                       long = not (null (drop 5 elts))
+                       space
+                         | long
+                         = "\n                  " <> extraSpace
+                         | True
+                         = " "
+
+                       chain _ []     = cnst rk 0
+                       chain _ [x]    = showText x
+                       chain i (x:xs) = "(ite (= " <> lv <> " " <> cnst ak i <> ") "
+                                           <> showText x <> space
+                                           <> chain (i+1) xs
+                                           <> ")"
+
+{- HLint ignore module "Use second" -}
diff --git a/Data/SBV/List.hs b/Data/SBV/List.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/List.hs
@@ -0,0 +1,1548 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.List
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A collection of list utilities, useful when working with symbolic lists.
+-- To the extent possible, the functions in this module follow those of "Data.List"
+-- so importing qualified is the recommended workflow. Also, it is recommended
+-- you use the @OverloadedLists@ and @OverloadedStrings@ extensions to allow literal
+-- lists and strings to be used as symbolic literals.
+--
+-- You can find proofs of many list related properties in "Data.SBV.TP.List".
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                    #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE OverloadedLists        #-}
+{-# LANGUAGE QuasiQuotes            #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TypeApplications       #-}
+{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE UndecidableInstances   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.List (
+        -- * Length, emptiness
+          length, null
+
+        -- * Deconstructing/Reconstructing
+        , nil, (.:), snoc, head, tail, uncons, init, last, singleton, listToListAt, elemAt, (!!), implode, concat, (++)
+
+        -- * Case analysis (for sCase quasi-quoter)
+        , list
+
+        -- * Containment
+        , elem, notElem, isInfixOf, isSuffixOf, isPrefixOf
+
+        -- * List equality
+        , listEq
+
+        -- * Sublists
+        , take, drop, splitAt, subList, replace, indexOf, offsetIndexOf
+
+        -- * Reverse
+        , reverse
+
+        -- * Mapping
+        , map, concatMap
+
+        -- * Difference
+        , (\\)
+
+        -- * Folding
+        , foldl, foldr
+
+        -- * Zipping
+        , zip, zipWith
+
+        -- * Lookup
+        , lookup
+
+        -- * Filtering
+        , filter, partition, takeWhile, dropWhile
+
+        -- * Predicate transformers
+        , all, any, and, or
+
+        -- * Generators
+        , replicate, inits, tails
+
+        -- * Sum and product
+        , sum, product
+
+        -- * Minimum and maximum of a list
+        , minimum, maximum
+
+        -- * Conversion between strings and naturals
+        , strToNat, natToStr
+
+        -- * Symbolic enumerations
+        , EnumSymbolic(..)
+        ) where
+
+import Prelude hiding (head, tail, init, last, length, take, drop, splitAt, concat, null, elem,
+                       notElem, reverse, (++), (!!), map, concatMap, foldl, foldr, zip, zipWith, filter,
+                       all, any, and, or, replicate, fst, snd, sum, product, Enum(..), lookup,
+                       takeWhile, dropWhile, minimum, maximum, uncurry)
+import qualified Prelude as P
+
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Floating
+import Data.SBV.SCase (sCase)
+import Data.SBV.Tuple
+
+import Data.Maybe (isNothing, catMaybes)
+import qualified Data.Char as C
+
+import Data.List (genericLength, genericIndex, genericDrop, genericTake, genericReplicate)
+import qualified Data.List as L (inits, tails, isSuffixOf, isPrefixOf, isInfixOf, partition, (\\))
+
+import Data.Proxy
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Prelude hiding (head, tail, init, last, length, take, drop, concat, null, elem, notElem, reverse, (++), (!!), map, foldl, foldr, zip, zipWith, filter, all, any, replicate, lookup, splitAt, concatMap, and, or, sum, product, takeWhile, dropWhile, minimum, maximum)
+-- >>> import qualified Prelude as P(map)
+-- >>> import Data.SBV
+-- >>> :set -XDataKinds
+-- >>> :set -XOverloadedLists
+-- >>> :set -XOverloadedStrings
+-- >>> :set -XScopedTypeVariables
+-- >>> :set -XTypeApplications
+-- >>> :set -XQuasiQuotes
+#endif
+
+-- | Length of a list.
+--
+-- >>> sat $ \(l :: SList Word16) -> length l .== 2
+-- Satisfiable. Model:
+--   s0 = [0,0] :: [Word16]
+-- >>> sat $ \(l :: SList Word16) -> length l .< 0
+-- Unsatisfiable
+-- >>> prove $ \(l1 :: SList Word16) (l2 :: SList Word16) -> length l1 + length l2 .== length (l1 ++ l2)
+-- Q.E.D.
+-- >>> sat $ \(s :: SString) -> length s .== 2
+-- Satisfiable. Model:
+--   s0 = "BA" :: String
+-- >>> sat $ \(s :: SString) -> length s .< 0
+-- Unsatisfiable
+-- >>> prove $ \(s1 :: SString) s2 -> length s1 + length s2 .== length (s1 ++ s2)
+-- Q.E.D.
+length :: forall a. SymVal a => SList a -> SInteger
+length = lift1 False (SeqLen (kindOf (Proxy @a))) (Just (fromIntegral . P.length))
+
+-- | @`null` s@ is True iff the list is empty
+--
+-- >>> prove $ \(l :: SList Word16) -> null l .<=> length l .== 0
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Word16) -> null l .<=> l .== []
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> null s .<=> length s .== 0
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> null s .<=> s .== ""
+-- Q.E.D.
+null :: SymVal a => SList a -> SBool
+null l
+  | Just cs <- unliteral l
+  = literal (P.null cs)
+  | True
+  = length l .== 0
+
+-- | @`head`@ returns the first element of a list. Unspecified if the list is empty.
+--
+-- >>> prove $ \c -> head [c] .== (c :: SInteger)
+-- Q.E.D.
+-- >>> prove $ \c -> c .== literal 'A' .=> ([c] :: SString) .== "A"
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> length ([c] :: SString) .== 1
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> head ([c] :: SString) .== c
+-- Q.E.D.
+head :: SymVal a => SList a -> SBV a
+head = (`elemAt` 0)
+
+-- | @`tail`@ returns the tail of a list. Unspecified if the list is empty.
+--
+-- >>> prove $ \(h :: SInteger) t -> tail ([h] ++ t) .== t
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Integer) -> length l .> 0 .=> length (tail l) .== length l - 1
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Integer) -> sNot (null l) .=> [head l] ++ tail l .== l
+-- Q.E.D.
+-- >>> prove $ \(h :: SChar) s -> tail ([h] ++ s) .== s
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> length s .> 0 .=> length (tail s) .== length s - 1
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> sNot (null s) .=> [head s] ++ tail s .== s
+-- Q.E.D.
+tail :: SymVal a => SList a -> SList a
+tail l
+ | Just (_:cs) <- unliteral l
+ = literal cs
+ | True
+ = subList l 1 (length l - 1)
+
+-- | @`uncons`@ returns the pair of the head and tail. Unspecified if the list is empty.
+--
+-- >>> prove $ \(x :: SInteger) xs -> uncons (x .: xs) .== (x, xs)
+-- Q.E.D.
+uncons :: SymVal a => SList a -> (SBV a, SList a)
+uncons l = (head l, tail l)
+
+-- | Case analysis on a symbolic list. If the list is empty, return the first argument.
+-- Otherwise, apply the second argument to the head and tail of the list.
+--
+-- >>> list (0 :: SInteger) (\h _ -> h) ([] :: SList Integer)
+-- 0 :: SInteger
+-- >>> list (0 :: SInteger) (\h _ -> h) ([3, 4, 5] :: SList Integer)
+-- 3 :: SInteger
+-- >>> prove $ \(l :: SList Integer) -> null l .|| list sFalse (\_ _ -> sTrue) l
+-- Q.E.D.
+list :: (SymVal a, SymVal b) => SBV b -> (SBV a -> SList a -> SBV b) -> SList a -> SBV b
+list nilCase consCase xs = [sCase| xs of
+                              []   -> nilCase
+                              h:ts -> consCase h ts
+                           |]
+
+-- | @`init`@ returns all but the last element of the list. Unspecified if the list is empty.
+--
+-- >>> prove $ \(h :: SInteger) t -> init (t ++ [h]) .== t
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) t -> init (t ++ [c]) .== t
+-- Q.E.D.
+init :: SymVal a => SList a -> SList a
+init l
+ | Just cs@(_:_) <- unliteral l
+ = literal $ P.init cs
+ | True
+ = subList l 0 (length l - 1)
+
+-- | @`last`@ returns the last element of the list. Unspecified if the list is empty.
+--
+-- >>> prove $ \(l :: SInteger) i -> last (i ++ [l]) .== l
+-- Q.E.D.
+last :: SymVal a => SList a -> SBV a
+last l = l `elemAt` (length l - 1)
+
+-- | @`singleton` x@ is the list of length 1 that contains the only value @x@.
+--
+-- >>> prove $ \(x :: SInteger) -> head [x] .== x
+-- Q.E.D.
+-- >>> prove $ \(x :: SInteger) -> length [x] .== 1
+-- Q.E.D.
+singleton :: forall a. SymVal a => SBV a -> SList a
+singleton = lift1 False (SeqUnit (kindOf (Proxy @a))) (Just (: []))
+
+-- | @`listToListAt` l offset@. List of length 1 at @offset@ in @l@. Unspecified if
+-- index is out of bounds.
+--
+-- >>> prove $ \(l1 :: SList Integer) l2 -> listToListAt (l1 ++ l2) (length l1) .== listToListAt l2 0
+-- Q.E.D.
+-- >>> sat $ \(l :: SList Word16) -> length l .>= 2 .&& listToListAt l 0 ./= listToListAt l (length l - 1)
+-- Satisfiable. Model:
+--   s0 = [0,32] :: [Word16]
+listToListAt :: SymVal a => SList a -> SInteger -> SList a
+listToListAt s offset = subList s offset 1
+
+-- | @`elemAt` l i@ is the value stored at location @i@, starting at 0. Unspecified if
+-- index is out of bounds.
+--
+-- >>> prove $ \i -> i `inRange` (0, 4) .=> [1,1,1,1,1] `elemAt` i .== (1::SInteger)
+-- Q.E.D.
+-- >>> prove $ \i -> i .>= 0 .&& i .<= 4 .=> "AAAAA" `elemAt` i .== literal 'A'
+-- Q.E.D.
+elemAt :: forall a. SymVal a => SList a -> SInteger -> SBV a
+elemAt l i
+  | Just xs <- unliteral l, Just ci <- unliteral i, ci >= 0, ci < genericLength xs, let x = xs `genericIndex` ci
+  = literal x
+  | True
+  = lift2 False (SeqNth (kindOf (Proxy @a))) Nothing l i
+
+-- | Short cut for 'elemAt'
+--
+-- >>> prove $ \(xs :: SList Integer) i -> xs !! i .== xs `elemAt` i
+-- Q.E.D.
+(!!) :: SymVal a => SList a -> SInteger -> SBV a
+(!!) = elemAt
+
+-- | @`implode` es@ is the list of length @|es|@ containing precisely those
+-- elements. Note that there is no corresponding function @explode@, since
+-- we wouldn't know the length of a symbolic list.
+--
+-- >>> prove $ \(e1 :: SInteger) e2 e3 -> length (implode [e1, e2, e3]) .== 3
+-- Q.E.D.
+-- >>> prove $ \(e1 :: SInteger) e2 e3 -> P.map (elemAt (implode [e1, e2, e3])) (P.map literal [0 .. 2]) .== [e1, e2, e3]
+-- Q.E.D.
+-- >>> prove $ \(c1 :: SChar) c2 c3 -> length (implode [c1, c2, c3]) .== 3
+-- Q.E.D.
+-- >>> prove $ \(c1 :: SChar) c2 c3 -> P.map (elemAt (implode [c1, c2, c3])) (P.map literal [0 .. 2]) .== [c1, c2, c3]
+-- Q.E.D.
+implode :: SymVal a => [SBV a] -> SList a
+implode = P.foldr ((++) . \x -> [x]) (literal [])
+
+-- | Append an element
+--
+-- >>> [1, 2, 3 :: SInteger] `snoc` 4 `snoc` 5 `snoc` 6
+-- [1,2,3,4,5,6] :: [SInteger]
+snoc :: SymVal a => SList a -> SBV a -> SList a
+as `snoc` a = as ++ [a]
+
+-- nil is defined in Data.SBV.Core.Data and re-exported here.
+
+-- | Append two lists.
+--
+-- >>> sat $ \x y (z :: SList Integer) -> length x .== 5 .&& length y .== 1 .&& x ++ y ++ z .== [sEnum|1 .. 12|]
+-- Satisfiable. Model:
+--   s0 =      [1,2,3,4,5] :: [Integer]
+--   s1 =              [6] :: [Integer]
+--   s2 = [7,8,9,10,11,12] :: [Integer]
+-- >>> sat $ \(x :: SString) y z -> length x .== 5 .&& length y .== 1 .&& x ++ y ++ z .== "Hello world!"
+-- Satisfiable. Model:
+--   s0 =  "Hello" :: String
+--   s1 =      " " :: String
+--   s2 = "world!" :: String
+infixr 5 ++
+(++) :: forall a. SymVal a => SList a -> SList a -> SList a
+x ++ y | isConcretelyEmpty x = y
+       | isConcretelyEmpty y = x
+       | True                = lift2 False (SeqConcat (kindOf (Proxy @a))) (Just (P.++)) x y
+
+-- | @`elem` e l@. Does @l@ contain the element @e@?
+--
+-- >>> prove $ \(xs :: SList Integer) x -> x `elem` xs .=> length xs .>= 1
+-- Q.E.D.
+elem :: (Eq a, SymVal a) => SBV a -> SList a -> SBool
+e `elem` l = [e] `isInfixOf` l
+
+-- | @`notElem` e l@. Does @l@ not contain the element @e@?
+--
+-- >>> prove $ \(x :: SList Integer) -> x `notElem` []
+-- Q.E.D.
+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.
+-- >>> prove $ \(s1 :: SString) s2 s3 -> s2 `isInfixOf` (s1 ++ s2 ++ s3)
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 -> s1 `isInfixOf` s2 .&& s2 `isInfixOf` s1 .<=> s1 .== s2
+-- Q.E.D.
+isInfixOf :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
+sub `isInfixOf` l
+  | isConcretelyEmpty sub
+  = literal True
+  | True
+  = lift2 True (SeqContains (kindOf (Proxy @a))) (Just (flip L.isInfixOf)) l sub -- NB. flip, since `SeqContains` takes args in rev order!
+
+-- | @`isPrefixOf` pre l@. Is @pre@ a prefix of @l@?
+--
+-- >>> prove $ \(l1 :: SList Integer) l2 -> l1 `isPrefixOf` (l1 ++ l2)
+-- Q.E.D.
+-- >>> prove $ \(l1 :: SList Integer) l2 -> l1 `isPrefixOf` l2 .=> subList l2 0 (length l1) .== l1
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 -> s1 `isPrefixOf` (s1 ++ s2)
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 -> s1 `isPrefixOf` s2 .=> subList s2 0 (length s1) .== s1
+-- Q.E.D.
+isPrefixOf :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
+pre `isPrefixOf` l
+  | isConcretelyEmpty pre
+  = literal True
+  | True
+  = lift2 True (SeqPrefixOf (kindOf (Proxy @a))) (Just L.isPrefixOf) pre l
+
+-- | @listEq@ is a variant of equality that you can use for lists of floats. It respects @NaN /= NaN@. The reason
+-- we do not do this automatically is that it complicates proof objectives usually, as it does not simply resolve to
+-- the native equality check.
+--
+-- NB. We case-split on @x@ only and use a guard for @y@ being empty, rather than case-splitting on the
+-- tuple @(x, y)@. A 4-way tuple match produces a larger and\/or\/not SMTLib tree that z3 struggles with.
+listEq :: forall a. SymVal a => SList a -> SList a -> SBool
+listEq
+  | containsFloats (kindOf (Proxy @a))
+  = smtFunction "listEq"
+  $ \x y -> [sCase| x of
+                []   -> null y
+                a:xs -> case y of
+                          []     -> sFalse
+                          b : ys -> a .== b .&& xs `listEq` ys
+            |]
+  | True
+  = (.==)
+
+-- | @`isSuffixOf` suf l@. Is @suf@ a suffix of @l@?
+--
+-- >>> prove $ \(l1 :: SList Word16) l2 -> l2 `isSuffixOf` (l1 ++ l2)
+-- Q.E.D.
+-- >>> prove $ \(l1 :: SList Word16) l2 -> l1 `isSuffixOf` l2 .=> subList l2 (length l2 - length l1) (length l1) .== l1
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 -> s2 `isSuffixOf` (s1 ++ s2)
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 -> s1 `isSuffixOf` s2 .=> subList s2 (length s2 - length s1) (length s1) .== s1
+-- Q.E.D.
+isSuffixOf :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SBool
+suf `isSuffixOf` l
+  | isConcretelyEmpty suf
+  = literal True
+  | True
+  = lift2 True (SeqSuffixOf (kindOf (Proxy @a))) (Just L.isSuffixOf) suf l
+
+-- | @`take` len l@. Corresponds to Haskell's `take` on symbolic lists.
+--
+-- >>> prove $ \(l :: SList Integer) i -> i .>= 0 .=> length (take i l) .<= i
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) i -> i .>= 0 .=> length (take i s) .<= i
+-- Q.E.D.
+take :: SymVal a => SInteger -> SList a -> SList a
+take i l = ite (i .<= 0)        (literal [])
+         $ ite (i .>= length l) l
+         $ subList l 0 i
+
+-- | @`drop` len s@. Corresponds to Haskell's `drop` on symbolic-lists.
+--
+-- >>> prove $ \(l :: SList Word16) i -> length (drop i l) .<= length l
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Word16) i -> take i l ++ drop i l .== l
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) i -> length (drop i s) .<= length s
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) i -> take i s ++ drop i s .== s
+-- Q.E.D.
+drop :: SymVal a => SInteger -> SList a -> SList a
+drop i s = ite (i .>= ls) (literal [])
+         $ ite (i .<= 0)  s
+         $ subList s i (ls - i)
+  where ls = length s
+
+-- | @splitAt n xs = (take n xs, drop n xs)@
+--
+-- >>> prove $ \n (xs :: SList Integer) -> let (l, r) = splitAt n xs in l ++ r .== xs
+-- Q.E.D.
+splitAt :: SymVal a => SInteger -> SList a -> (SList a, SList a)
+splitAt n xs = (take n xs, drop n xs)
+
+-- | @`subList` s offset len@ is the sublist of @s@ at offset @offset@ with length @len@.
+-- This function is under-specified when the offset is outside the range of positions in @s@ or @len@
+-- is negative or @offset+len@ exceeds the length of @s@.
+--
+-- >>> prove $ \(l :: SList Integer) i -> i .>= 0 .&& i .< length l .=> subList l 0 i ++ subList l i (length l - i) .== l
+-- Q.E.D.
+-- >>> sat  $ \i j -> subList [sEnum|1..5|] i j .== [sEnum|2..4::SInteger|]
+-- Satisfiable. Model:
+--   s0 = 1 :: Integer
+--   s1 = 3 :: Integer
+-- >>> sat  $ \i j -> subList [sEnum|1..5|] i j .== [sEnum|6..7::SInteger|]
+-- Unsatisfiable
+-- >>> prove $ \(s1 :: SString) (s2 :: SString) -> subList (s1 ++ s2) (length s1) 1 .== subList s2 0 1
+-- Q.E.D.
+-- >>> sat $ \(s :: SString) -> length s .>= 2 .&& subList s 0 1 ./= subList s (length s - 1) 1
+-- Satisfiable. Model:
+--   s0 = "AB" :: String
+-- >>> prove $ \(s :: SString) i -> i .>= 0 .&& i .< length s .=> subList s 0 i ++ subList s i (length s - i) .== s
+-- Q.E.D.
+-- >>> sat  $ \i j -> subList "hello" i j .== ("ell" :: SString)
+-- Satisfiable. Model:
+--   s0 = 1 :: Integer
+--   s1 = 3 :: Integer
+-- >>> sat  $ \i j -> subList "hell" i j .== ("no" :: SString)
+-- Unsatisfiable
+subList :: forall a. SymVal a => SList a -> SInteger -> SInteger -> SList a
+subList l offset len
+  | Just c  <- unliteral l                   -- a constant list
+  , Just o  <- unliteral offset              -- a constant offset
+  , Just sz <- unliteral len                 -- a constant length
+  , let lc = genericLength c                 -- length of the list
+  , let valid x = x >= 0 && x <= lc          -- predicate that checks valid point
+  , valid o                                  -- offset is valid
+  , sz >= 0                                  -- length is not-negative
+  , valid $ o + sz                           -- we don't overrun
+  = literal $ genericTake sz $ genericDrop o c
+  | True                                     -- either symbolic, or something is out-of-bounds
+  = lift3 False (SeqSubseq (kindOf (Proxy @a))) Nothing l offset len
+
+-- | @`replace` l src dst@. Replace the first occurrence of @src@ by @dst@ in @l@
+--
+-- >>> prove $ \l -> replace [sEnum|1..5|] l [sEnum|6..10|] .== [sEnum|6..10|] .=> l .== [sEnum|1..5::SWord8|]
+-- Q.E.D.
+-- >>> prove $ \(l1 :: SList Integer) l2 l3 -> length l2 .> length l1 .=> replace l1 l2 l3 .== l1
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> replace "hello" s "world" .== "world" .=> s .== "hello"
+-- Q.E.D.
+-- >>> prove $ \(s1 :: SString) s2 s3 -> length s2 .> length s1 .=> replace s1 s2 s3 .== s1
+-- Q.E.D.
+replace :: forall a. (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
+  | eqCheckIsObjectEq ka
+  , Just a <- unliteral l
+  , Just b <- unliteral src
+  , Just c <- unliteral dst
+  = literal $ walk a b c
+  | True
+  = lift3 True (SeqReplace ka) Nothing l src dst
+  where walk haystack needle newNeedle = go haystack   -- note that needle is guaranteed non-empty here.
+           where go []       = []
+                 go i@(c:cs)
+                  | needle `L.isPrefixOf` i = newNeedle P.++ genericDrop (genericLength needle :: Integer) i
+                  | True                    = c : go cs
+
+        ka = kindOf (Proxy @a)
+
+-- | @`indexOf` l sub@. Retrieves first position of @sub@ in @l@, @-1@ if there are no occurrences.
+-- Equivalent to @`offsetIndexOf` l sub 0@.
+--
+-- >>> prove $ \(l1 :: SList Word16) l2 -> length l2 .> length l1 .=> indexOf l1 l2 .== -1
+-- Q.E.D.
+-- >>> prove $ \s1 s2 -> length s2 .> length s1 .=> indexOf s1 s2 .== -1
+-- Q.E.D.
+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
+-- after @offset@ in @l@, @-1@ if there are no occurrences.
+--
+-- >>> prove $ \(l :: SList Int8) sub -> offsetIndexOf l sub 0 .== indexOf l sub
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Int8) sub i -> i .>= length l .&& length sub .> 0 .=> offsetIndexOf l sub i .== -1
+-- Q.E.D.
+-- >>> prove $ \(l :: SList Int8) sub i -> i .> length l .=> offsetIndexOf l sub i .== -1
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) sub -> offsetIndexOf s sub 0 .== indexOf s sub
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) sub i -> i .>= length s .&& length sub .> 0 .=> offsetIndexOf s sub i .== -1
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) sub i -> i .> length s .=> offsetIndexOf s sub i .== -1
+-- Q.E.D.
+offsetIndexOf :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SInteger -> SInteger
+offsetIndexOf s sub offset
+  | eqCheckIsObjectEq ka
+  , Just c <- unliteral s        -- a constant list
+  , Just n <- unliteral sub      -- a constant search pattern
+  , Just o <- unliteral offset   -- at a constant offset
+  , o >= 0, o <= genericLength c        -- offset is good
+  = case [i | (i, t) <- P.zip [o ..] (L.tails (genericDrop o c)), n `L.isPrefixOf` t] of
+      (i:_) -> literal i
+      _     -> -1
+  | True
+  = lift3 True (SeqIndexOf ka) Nothing s sub offset
+  where ka = kindOf (Proxy @a)
+
+-- | @`reverse` s@ reverses the sequence.
+--
+-- NB. We can define @reverse@ in terms of @foldl@ as: @foldl (\soFar elt -> [elt] ++ soFar) []@
+-- But in my experiments, I found that this definition performs worse instead of the recursive definition
+-- SBV generates for reverse calls. So we're keeping it intact.
+--
+-- >>> sat $ \(l :: SList Integer) -> reverse l .== literal [3, 2, 1]
+-- Satisfiable. Model:
+--   s0 = [1,2,3] :: [Integer]
+-- >>> prove $ \(l :: SList Word32) -> reverse l .== [] .<=> null l
+-- Q.E.D.
+-- >>> sat $ \(l :: SString ) -> reverse l .== "321"
+-- Satisfiable. Model:
+--   s0 = "123" :: String
+-- >>> prove $ \(l :: SString) -> reverse l .== "" .<=> null l
+-- Q.E.D.
+reverse :: forall a. SymVal a => SList a -> SList a
+reverse l
+  | Just l' <- unliteral l
+  = literal (P.reverse l')
+  | True
+  = def l
+  where def = smtFunction "sbv.reverse"
+            $ \xs -> [sCase| xs of
+                        []   -> []
+                        h:ts -> def ts ++ [h]
+                      |]
+
+-- | A class of mappable functions. In SBV, we make a distinction between closures and regular functions, and
+-- we instantiate this class appropriately so it can handle both cases.
+class (SymVal a, SymVal b) => SMap func a b | func -> a b where
+  -- | Map a function (or a closure) over a symbolic list.
+  --
+  -- >>> map (+ (1 :: SInteger)) [sEnum|1 .. 5 :: SInteger|]
+  -- [2,3,4,5,6] :: [SInteger]
+  -- >>> map (+ (1 :: SWord 8)) [sEnum|1 .. 5 :: SWord 8|]
+  -- [2,3,4,5,6] :: [SWord8]
+  -- >>> map (\x -> [x] :: SList Integer) [sEnum|1 .. 3 :: SInteger|]
+  -- [[1],[2],[3]] :: [[SInteger]]
+  -- >>> import Data.SBV.Tuple
+  -- >>> map (\t -> t^._1 + t^._2) (literal [(x, y) | x <- [1..3], y <- [4..6]] :: SList (Integer, Integer))
+  -- [5,6,7,6,7,8,7,8,9] :: [SInteger]
+  --
+  -- Of course, SBV's 'map' can also be reused in reverse:
+  --
+  -- >>> sat $ \l -> map (+(1 :: SInteger)) l .== [1,2,3 :: SInteger]
+  -- Satisfiable. Model:
+  --   s0 = [0,1,2] :: [Integer]
+  map :: func -> SList a -> SList b
+
+  -- | Handle the concrete case of mapping. Used internally only.
+  concreteMap :: func -> (SBV a -> SBV b) -> SList a -> Maybe [b]
+  concreteMap _ f sas
+    | Just as <- unliteral sas
+    = case P.map (unliteral . f . literal) as of
+         bs | P.any isNothing bs -> Nothing
+            | True               -> Just (catMaybes bs)
+    | True
+    = Nothing
+
+-- | Mapping symbolic functions.
+instance (SymVal a, SymVal b) => SMap (SBV a -> SBV b) a b where
+  -- | @`map` f s@ maps the operation on to sequence.
+  map f l
+    | Just concResult <- concreteMap f f l
+    = literal concResult
+    | True
+    = sbvMap l
+    where sbvMap = smtHOFunction "sbv.map" f
+                 $ \xs -> [sCase| xs of
+                             []    -> []
+                             h : t -> f h .: sbvMap t
+                          |]
+
+-- | Mapping symbolic closures.
+instance (SymVal env, SymVal a, SymVal b) => SMap (Closure (SBV env) (SBV a -> SBV b)) a b where
+  map cls@Closure{closureEnv, closureFun} l
+    | Just concResult <- concreteMap cls (closureFun closureEnv) l
+    = literal concResult
+    | True
+    = sbvMap (tuple (closureEnv, l))
+    where sbvMap = smtHOFunction "sbv.closureMap" closureFun
+                 $ \envxs -> [sCase| envxs of
+                                (_,    [])    -> []
+                                (cEnv, h : t) -> closureFun cEnv h .: sbvMap (tuple (cEnv, t))
+                            |]
+
+-- | @concatMap f xs@ maps f over elements and concats the result.
+--
+-- >>> concatMap (\x -> [x, x] :: SList Integer) [sEnum|1 .. 3|]
+-- [1,1,2,2,3,3] :: [SInteger]
+concatMap :: (SMap func a [b], SymVal b) => func -> SList a -> SList b
+concatMap f = concat . map f
+
+-- | A class of left foldable functions. In SBV, we make a distinction between closures and regular functions, and
+-- we instantiate this class appropriately so it can handle both cases.
+class (SymVal a, SymVal b) => SFoldL func a b | func -> a b where
+  -- | @`foldl` f base s@ folds the from the left.
+  --
+  -- >>> foldl ((+) @SInteger) 0 [sEnum|1 .. 5|]
+  -- 15 :: SInteger
+  -- >>> foldl ((*) @SInteger) 1 [sEnum|1 .. 5|]
+  -- 120 :: SInteger
+  -- >>> foldl (\soFar elt -> [elt] ++ soFar) ([] :: SList Integer) [sEnum|1 .. 5|]
+  -- [5,4,3,2,1] :: [SInteger]
+  --
+  -- Again, we can use 'sbv.foldl' in the reverse too:
+  --
+  -- >>> sat $ \l -> foldl (\soFar elt -> [elt] ++ soFar) ([] :: SList Integer) l .== [5, 4, 3, 2, 1 :: SInteger]
+  -- Satisfiable. Model:
+  --   s0 = [1,2,3,4,5] :: [Integer]
+  foldl :: (SymVal a, SymVal b) => func -> SBV b -> SList a -> SBV b
+
+  -- | Handle the concrete case for folding left. Used internally only.
+  concreteFoldl :: func -> (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> Maybe b
+  concreteFoldl _ f sb sas
+     | Just b <- unliteral sb, Just as <- unliteral sas
+     = go b as
+     | True
+     = Nothing
+     where go b []     = Just b
+           go b (e:es) = case unliteral (literal b `f` literal e) of
+                           Nothing -> Nothing
+                           Just b' -> go b' es
+
+-- | Folding left with symbolic functions.
+instance (SymVal a, SymVal b) => SFoldL (SBV b -> SBV a -> SBV b) a b where
+  -- | @`foldl` f b s@ folds the sequence from the left.
+  foldl f base l
+    | Just concResult <- concreteFoldl f f base l
+    = literal concResult
+    | True
+    = sbvFoldl $ tuple (base, l)
+    where sbvFoldl = smtHOFunction "sbv.foldl" (uncurry f)
+                   $ \exs -> [sCase| exs of
+                                (e, [])    -> e
+                                (e, h : t) -> sbvFoldl (tuple (e `f` h, t))
+                             |]
+
+-- | Folding left with symbolic closures.
+instance (SymVal env, SymVal a, SymVal b) => SFoldL (Closure (SBV env) (SBV b -> SBV a -> SBV b)) a b where
+  foldl cls@Closure{closureEnv, closureFun} base l
+    | Just concResult <- concreteFoldl cls (closureFun closureEnv) base l
+    = literal concResult
+    | True
+    = sbvFoldl $ tuple (closureEnv, base, l)
+    where sbvFoldl = smtHOFunction "sbv.closureFoldl" closureFun
+                   $ \envxs -> [sCase| envxs of
+                                  (_,    e, [])    -> e
+                                  (cEnv, e, h : t) -> sbvFoldl (tuple (cEnv, closureFun closureEnv e h, t))
+                               |]
+
+-- | A class of right foldable functions. In SBV, we make a distinction between closures and regular functions, and
+-- we instantiate this class appropriately so it can handle both cases.
+class (SymVal a, SymVal b) => SFoldR func a b | func -> a b where
+  -- | @`foldr` f base s@ folds the from the right.
+  --
+  -- >>> foldr ((+) @SInteger) 0 [sEnum|1 .. 5|]
+  -- 15 :: SInteger
+  -- >>> foldr ((*) @SInteger) 1 [sEnum|1 .. 5|]
+  -- 120 :: SInteger
+  -- >>> foldr (\elt soFar -> soFar ++ [elt]) ([] :: SList Integer) [sEnum|1 .. 5|]
+  -- [5,4,3,2,1] :: [SInteger]
+  foldr :: func -> SBV b -> SList a -> SBV b
+
+  -- | Handle the concrete case for folding right. Used internally only.
+  concreteFoldr :: func -> (SBV a -> SBV b -> SBV b) -> SBV b -> SList a -> Maybe b
+  concreteFoldr _ f sb sas
+     | Just b <- unliteral sb, Just as <- unliteral sas
+     = go b as
+     | True
+     = Nothing
+     where go b []     = Just b
+           go b (e:es) = case go b es of
+                           Nothing  -> Nothing
+                           Just res -> unliteral (literal e `f` literal res)
+
+-- | Folding right with symbolic functions.
+instance (SymVal a, SymVal b) => SFoldR (SBV a -> SBV b -> SBV b) a b where
+  -- | @`foldr` f base s@ folds the sequence from the right.
+  foldr f base l
+    | Just concResult <- concreteFoldr f f base l
+    = literal concResult
+    | True
+    = sbvFoldr $ tuple (base, l)
+    where sbvFoldr = smtHOFunction "sbv.foldr" (uncurry f)
+                   $ \exs -> [sCase| exs of
+                                (e, [])    -> e
+                                (e, h : t) -> h `f` sbvFoldr (tuple (e, t))
+                             |]
+
+-- | Folding right with symbolic closures.
+instance (SymVal env, SymVal a, SymVal b) => SFoldR (Closure (SBV env) (SBV a -> SBV b -> SBV b)) a b where
+  foldr cls@Closure{closureEnv, closureFun} base l
+    | Just concResult <- concreteFoldr cls (closureFun closureEnv) base l
+    = literal concResult
+    | True
+    = sbvFoldr $ tuple (closureEnv, base, l)
+    where sbvFoldr = smtHOFunction "sbv.closureFoldr" closureFun
+                   $ \envxs -> [sCase| envxs of
+                                  (_,    e, [])    -> e
+                                  (cEnv, e, h : t) -> closureFun closureEnv h (sbvFoldr (tuple (cEnv, e, t)))
+                               |]
+
+-- | @`zip` xs ys@ zips the lists to give a list of pairs. The length of the final list is
+-- the minimum of the lengths of the given lists.
+--
+-- >>> zip [sEnum|1..10 :: SInteger|] [sEnum|11..20 :: SInteger|]
+-- [(1,11),(2,12),(3,13),(4,14),(5,15),(6,16),(7,17),(8,18),(9,19),(10,20)] :: [(SInteger, SInteger)]
+-- >>> import Data.SBV.Tuple
+-- >>> foldr ((+) @SInteger) 0 (map (\t -> t^._1+t^._2::SInteger) (zip [sEnum|1..10|] [sEnum|10, 9..1|]))
+-- 110 :: SInteger
+zip :: forall a b. (SymVal a, SymVal b) => SList a -> SList b -> SList (a, b)
+zip xs ys
+ | Just xs' <- unliteral xs, Just ys' <- unliteral ys
+ = literal $ P.zip xs' ys'
+ | True
+ = def xs ys
+ where def = smtFunction "sbv.zip"
+           $ \x y -> [sCase| tuple (x, y) of
+                         ([],   _   ) -> []
+                         (_,    []  ) -> []
+                         (a:as, b:bs) -> tuple (a, b) .: def as bs
+                     |]
+
+-- | A class of function that we can zip-with. In SBV, we make a distinction between closures and regular
+-- functions, and we instantiate this class appropriately so it can handle both cases.
+class (SymVal a, SymVal b, SymVal c) => SZipWith func a b c | func -> a b c where
+  -- | @`zipWith` f xs ys@ zips the lists to give a list of pairs, applying the function to each pair of elements.
+  -- The length of the final list is the minimum of the lengths of the given lists.
+   --
+   -- >>> zipWith ((+) @SInteger) ([sEnum|1..10::SInteger|]) ([sEnum|11..20::SInteger|])
+   -- [12,14,16,18,20,22,24,26,28,30] :: [SInteger]
+   -- >>> foldr ((+) @SInteger) 0 (zipWith ((+) @SInteger) [sEnum|1..10 :: SInteger|] [sEnum|10, 9..1 :: SInteger|])
+   -- 110 :: SInteger
+  zipWith :: func -> SList a -> SList b -> SList c
+
+  -- | Handle the concrete case of zipping. Used internally only.
+  concreteZipWith :: func -> (SBV a -> SBV b -> SBV c) -> SList a -> SList b -> Maybe [c]
+  concreteZipWith _ f sas sbs
+   | Just as <- unliteral sas, Just bs <- unliteral sbs
+   = go as bs
+   | True
+   = Nothing
+   where go []     _      = Just []
+         go _      []     = Just []
+         go (a:as) (b:bs) = (:) <$> unliteral (literal a `f` literal b) <*> go as bs
+
+-- | Zipping with symbolic functions.
+instance (SymVal a, SymVal b, SymVal c) => SZipWith (SBV a -> SBV b -> SBV c) a b c where
+   -- | @`zipWith`@ zips two sequences with a symbolic function.
+   zipWith f xs ys
+    | Just concResult <- concreteZipWith f f xs ys
+    = literal concResult
+    | True
+    = sbvZipWith $ tuple (xs, ys)
+    where sbvZipWith = smtHOFunction "sbv.zipWith" (uncurry f)
+                     $ \asbs -> [sCase| asbs of
+                                   ([],   _   ) -> []
+                                   (_,    []  ) -> []
+                                   (a:as, b:bs) -> f a b .: sbvZipWith (tuple (as, bs))
+                                |]
+
+-- | Zipping with closures.
+instance (SymVal env, SymVal a, SymVal b, SymVal c) => SZipWith (Closure (SBV env) (SBV a -> SBV b -> SBV c)) a b c where
+   zipWith cls@Closure{closureEnv, closureFun} xs ys
+    | Just concResult <- concreteZipWith cls (closureFun closureEnv) xs ys
+    = literal concResult
+    | True
+    = sbvZipWith $ tuple (closureEnv, xs, ys)
+    where sbvZipWith = smtHOFunction "sbv.closureZipWith" closureFun
+                     $ \envasbs -> [sCase| envasbs of
+                                      (_,    [],   _   ) -> []
+                                      (_,    _,    []  ) -> []
+                                      (cEnv, a:as, b:bs) -> closureFun cEnv a b .: sbvZipWith (tuple (cEnv, as, bs))
+                                   |]
+
+-- | Concatenate list of lists.
+--
+-- >>> concat [[sEnum|1..3::SInteger|], [sEnum|4..7|], [sEnum|8..10|]]
+-- [1,2,3,4,5,6,7,8,9,10] :: [SInteger]
+concat :: forall a. SymVal a => SList [a] -> SList a
+concat = foldr (++) []
+
+-- | Check all elements satisfy the predicate.
+--
+-- >>> let isEven x = x `sMod` 2 .== 0
+-- >>> all isEven [2, 4, 6, 8, 10 :: SInteger]
+-- True
+-- >>> all isEven [2, 4, 6, 1, 8, 10 :: SInteger]
+-- False
+all :: forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
+all f = foldr ((.&&) . f) sTrue
+
+-- | Check some element satisfies the predicate.
+--
+-- >>> let isEven x = x `sMod` 2 .== 0
+-- >>> any (sNot . isEven) [2, 4, 6, 8, 10 :: SInteger]
+-- False
+-- >>> any isEven [2, 4, 6, 1, 8, 10 :: SInteger]
+-- True
+any :: forall a. SymVal a => (SBV a -> SBool) -> SList a -> SBool
+any f = foldr ((.||) . f) sFalse
+
+-- | Conjunction of all the elements.
+--
+-- >>> and []
+-- True
+-- >>> prove $ \s -> and [s, sNot s] .== sFalse
+-- Q.E.D.
+and :: SList Bool -> SBool
+and = all id
+
+-- | Disjunction of all the elements.
+--
+-- >>> or []
+-- False
+-- >>> prove $ \s -> or [s, sNot s]
+-- Q.E.D.
+or :: SList Bool -> SBool
+or = any id
+
+-- | Replicate an element a given number of times.
+--
+-- >>> replicate 3 (2 :: SInteger) .== [2, 2, 2 :: SInteger]
+-- True
+-- >>> replicate (-2) (2 :: SInteger) .== ([] :: SList Integer)
+-- True
+replicate :: forall a. SymVal a => SInteger -> SBV a -> SList a
+replicate c e
+ | Just c' <- unliteral c, Just e' <- unliteral e
+ = literal (genericReplicate c' e')
+ | True
+ = def c e
+ where def = smtFunction "sbv.replicate"
+           $ \count elt -> [sCase| count of
+                               _ | count .<= 0 -> []
+                               _               -> elt .: def (count - 1) elt
+                           |]
+
+-- | inits of a list.
+--
+-- >>> inits ([] :: SList Integer)
+-- [[]] :: [[SInteger]]
+-- >>> inits [1,2,3,4::SInteger]
+-- [[],[1],[1,2],[1,2,3],[1,2,3,4]] :: [[SInteger]]
+inits :: forall a. SymVal a => SList a -> SList [a]
+inits xs
+ | Just xs' <- unliteral xs
+ = literal (L.inits xs')
+ | True
+ = def xs
+ where def = smtFunction "sbv.inits"
+           $ \l -> [sCase| l of
+                      []    -> [[]]
+                      _ : _ -> def (init l) ++ [l]
+                   |]
+
+-- | tails of a list.
+--
+-- >>> tails ([] :: SList Integer)
+-- [[]] :: [[SInteger]]
+-- >>> tails [1,2,3,4::SInteger]
+-- [[1,2,3,4],[2,3,4],[3,4],[4],[]] :: [[SInteger]]
+tails :: forall a. SymVal a => SList a -> SList [a]
+tails xs
+ | Just xs' <- unliteral xs
+ = literal (L.tails xs')
+ | True
+ = def xs
+ where def = smtFunction "sbv.tails"
+           $ \l -> [sCase| l of
+                      []      -> [[]]
+                      _ : tl  -> l .: def tl
+                   |]
+
+-- | Minimum of a list that has symbolic-ordering. If the list is empty, then
+-- the result is underspecified, i.e., it is an arbitrary element of the element type.
+--
+-- >>> minimum ([1,2,3] :: SList Integer)
+-- 1 :: SInteger
+-- >>> sat $ 512 .== minimum (literal [] :: SList Integer)
+-- Satisfiable. Model:
+--   SList.minimum @Integer = 512 :: Integer
+minimum :: forall a. (SymVal a, Ord a, OrdSymbolic (SBV a)) => SList a -> SBV a
+minimum xs
+  | Just lxs@(_:_) <- unliteral xs
+  = literal (P.minimum lxs)
+  | True
+  = foldr (smin @(SBV a)) (some "SList.minimum" (const sTrue)) xs
+
+-- | Maximum of a list that has symbolic-ordering. If the list is empty, then
+-- the result is underspecified, i.e., it is an arbitrary element of the element type.
+--
+-- >>> maximum ([1,2,3] :: SList Integer)
+-- 3 :: SInteger
+-- >>> sat $ 512 .== maximum (literal [] :: SList Integer)
+-- Satisfiable. Model:
+--   SList.maximum @Integer = 512 :: Integer
+maximum :: forall a. (SymVal a, Ord a, OrdSymbolic (SBV a)) => SList a -> SBV a
+maximum xs
+  | Just lxs@(_:_) <- unliteral xs
+  = literal (P.maximum lxs)
+  | True
+  = foldr (smax @(SBV a)) (some "SList.maximum" (const sTrue)) xs
+
+-- | Difference.
+--
+-- >>> [1, 2] \\ [3, 4 :: SInteger]
+-- [1,2] :: [SInteger]
+-- >>> [1, 2] \\ [2, 4 :: SInteger]
+-- [1] :: [SInteger]
+(\\) :: forall a. (Eq a, SymVal a) => SList a -> SList a -> SList a
+xs \\ ys
+ | Just xs' <- unliteral xs, Just ys' <- unliteral ys
+ = literal (xs' L.\\ ys')
+ | True
+ = def xs ys
+ where def = smtFunction "sbv.diff"
+           $ \x y -> [sCase| x of
+                        []    -> []
+                        h : t -> let r = def t y
+                                 in ite (h `elem` y) r (h .: r)
+                     |]
+infix 5 \\  -- CPP: do not eat the final newline
+
+-- | A class of filtering-like functions. In SBV, we make a distinction between closures and regular functions,
+-- and we instantiate this class appropriately so it can handle both cases.
+class SymVal a => SFilter func a | func -> a where
+  -- | Filter a list via a predicate.
+  --
+  -- >>> filter (\(x :: SInteger) -> x `sMod` 2 .== 0) (literal [1 .. 10])
+  -- [2,4,6,8,10] :: [SInteger]
+  -- >>> filter (\(x :: SInteger) -> x `sMod` 2 ./= 0) (literal [1 .. 10])
+  -- [1,3,5,7,9] :: [SInteger]
+  filter :: func -> SList a -> SList a
+
+  -- | Handle the concrete case of filtering. Used internally only.
+  concreteFilter :: func -> (SBV a -> SBool) -> SList a -> Maybe [a]
+  concreteFilter _ f sas
+   | Just as <- unliteral sas
+   = case P.map (unliteral . f . literal) as of
+        xs | P.any isNothing xs -> Nothing
+           | True               -> Just [e | (True, e) <- P.zip (catMaybes xs) as]
+   | True
+   = Nothing
+
+  -- | Partition a symbolic list according to a predicate.
+  --
+  -- >>> partition (\(x :: SInteger) -> x `sMod` 2 .== 0) (literal [1 .. 10])
+  -- ([2,4,6,8,10],[1,3,5,7,9]) :: ([SInteger], [SInteger])
+  partition :: func -> SList a -> STuple [a] [a]
+
+  -- | Handle the concrete case of partitioning. Used internally only.
+  concretePartition :: func -> (SBV a -> SBool) -> SList a -> Maybe ([a], [a])
+  concretePartition _ f l
+    | Just l' <- unliteral l
+    = case P.map (unliteral . f . literal) l' of
+        xs | P.any isNothing xs -> Nothing
+           | True               -> let (ts, fs) = L.partition P.fst (P.zip (catMaybes xs) l')
+                                   in Just (P.map P.snd ts, P.map P.snd fs)
+    | True
+    = Nothing
+
+  -- | Symbolic equivalent of @takeWhile@
+  --
+  -- >>> takeWhile (\(x :: SInteger) -> x `sMod` 2 .== 0) (literal [1..10])
+  -- [] :: [SInteger]
+  -- >>> takeWhile (\(x :: SInteger) -> x `sMod` 2 ./= 0) (literal [1..10])
+  -- [1] :: [SInteger]
+  takeWhile :: func -> SList a -> SList a
+
+  -- | Handle the concrete case of take-while. Used internally only.
+  concreteTakeWhile :: func -> (SBV a -> SBool) -> SList a -> Maybe [a]
+  concreteTakeWhile _ f sas
+   | Just as <- unliteral sas
+   = case P.map (unliteral . f . literal) as of
+        xs | P.any isNothing xs -> Nothing
+           | True               -> Just (P.map P.snd (P.takeWhile P.fst (P.zip (catMaybes xs) as)))
+   | True
+   = Nothing
+
+  -- | Symbolic equivalent of @dropWhile@
+  -- >>> dropWhile (\(x :: SInteger) -> x `sMod` 2 .== 0) (literal [1..10])
+  -- [1,2,3,4,5,6,7,8,9,10] :: [SInteger]
+  -- >>> dropWhile (\(x :: SInteger) -> x `sMod` 2 ./= 0) (literal [1..10])
+  -- [2,3,4,5,6,7,8,9,10] :: [SInteger]
+  dropWhile :: func -> SList a -> SList a
+
+  -- | Handle the concrete case of drop-while. Used internally only.
+  concreteDropWhile :: func -> (SBV a -> SBool) -> SList a -> Maybe [a]
+  concreteDropWhile _ f sas
+   | Just as <- unliteral sas
+   = case P.map (unliteral . f . literal) as of
+        xs | P.any isNothing xs -> Nothing
+           | True               -> Just (P.map P.snd (P.dropWhile P.fst (P.zip (catMaybes xs) as)))
+   | True
+   = Nothing
+
+-- | Filtering with symbolic functions.
+instance SymVal a => SFilter (SBV a -> SBool) a where
+  -- | @filter f xs@ filters the list with the given predicate.
+  filter f l
+    | Just concResult <- concreteFilter f f l
+    = literal concResult
+    | True
+    = sbvFilter l
+    where sbvFilter = smtHOFunction "sbv.filter" f
+                    $ \xs -> [sCase| xs of
+                                []    -> []
+                                h : t -> let r = sbvFilter t
+                                         in ite (f h) (h .: r) r
+                             |]
+
+  -- | @partition f xs@ splits the list into two and returns those that satisfy the predicate in the
+  -- first element, and those that don't in the second.
+  partition f l
+    | Just concResult <- concretePartition f f l
+    = literal concResult
+    | True
+    = sbvPartition l
+    where sbvPartition = smtHOFunction "sbv.partition" f
+                       $ \xs -> [sCase| xs of
+                                   []    -> tuple ([], [])
+                                   h : t -> case sbvPartition t of
+                                              (as, bs) | f h  -> tuple (h .: as, bs)
+                                                       | True -> tuple (as, h .: bs)
+                                |]
+
+  -- | @takeWhile f xs@ takes the prefix of @xs@ that satisfy the predicate.
+  takeWhile f l
+    | Just concResult <- concreteTakeWhile f f l
+    = literal concResult
+    | True
+    = sbvTakeWhile l
+    where sbvTakeWhile = smtHOFunction "sbv.takeWhile" f
+                       $ \xs -> [sCase| xs of
+                                   []           -> []
+                                   h : t | f h  -> h .: sbvTakeWhile t
+                                         | True -> []
+                                |]
+
+  -- | @dropWhile f xs@ drops the prefix of @xs@ that satisfy the predicate.
+  dropWhile f l
+    | Just concResult <- concreteDropWhile f f l
+    = literal concResult
+    | True
+    = sbvDropWhile l
+    where sbvDropWhile = smtHOFunction "sbv.dropWhile" f
+                       $ \xs -> [sCase| xs of
+                                   []           -> []
+                                   h : t | f h  -> sbvDropWhile t
+                                         | True -> xs
+                                |]
+
+-- | Filtering with closures.
+instance (SymVal env, SymVal a) => SFilter (Closure (SBV env) (SBV a -> SBool)) a where
+  filter cls@Closure{closureEnv, closureFun} l
+    | Just concResult <- concreteFilter cls (closureFun closureEnv) l
+    = literal concResult
+    | True
+    = sbvFilter (tuple (closureEnv, l))
+    where sbvFilter = smtHOFunction "sbv.closureFilter" closureFun
+                    $ \envxs -> [sCase| envxs of
+                                   (_,    [])    -> []
+                                   (cEnv, h : t) -> let r = sbvFilter (tuple (cEnv, t))
+                                                    in ite (closureFun cEnv h) (h .: r) r
+                                |]
+
+  partition cls@Closure{closureEnv, closureFun} l
+    | Just concResult <- concretePartition cls (closureFun closureEnv) l
+    = literal concResult
+    | True
+    = sbvPartition (tuple (closureEnv, l))
+    where sbvPartition = smtHOFunction "sbv.closurePartition" closureFun
+                       $ \envxs -> [sCase| envxs of
+                                      (_, [])       -> tuple ([], [])
+                                      (cEnv, h : t) -> case sbvPartition (tuple (cEnv, t)) of
+                                                          (as, bs) | closureFun cEnv h -> tuple (h .: as, bs)
+                                                                   | True              -> tuple (as, h .: bs)
+                                   |]
+
+  takeWhile cls@Closure{closureEnv, closureFun} l
+    | Just concResult <- concreteTakeWhile cls (closureFun closureEnv) l
+    = literal concResult
+    | True
+    = sbvTakeWhile (tuple (closureEnv, l))
+    where sbvTakeWhile = smtHOFunction "sbv.closureTakeWhile" closureFun
+                       $ \envxs -> [sCase| envxs of
+                                      (_,    [])                        -> []
+                                      (cEnv, h : t) | closureFun cEnv h -> h .: sbvTakeWhile (tuple (cEnv, t))
+                                                    | True              -> []
+                                   |]
+
+  dropWhile cls@Closure{closureEnv, closureFun} l
+    | Just concResult <- concreteDropWhile cls (closureFun closureEnv) l
+    = literal concResult
+    | True
+    = sbvDropWhile (tuple (closureEnv, l))
+    where sbvDropWhile = smtHOFunction "sbv.closureDropWhile" closureFun
+                       $ \envxs -> [sCase| envxs of
+                                      (_,    [])                              -> []
+                                      (cEnv, lst@(h : t)) | closureFun cEnv h -> sbvDropWhile (tuple (cEnv, t))
+                                                          | True              -> lst
+                                   |]
+
+-- | @`sum` s@. Sum the given sequence.
+--
+-- >>> sum [sEnum|1 .. 10::SInteger|]
+-- 55 :: SInteger
+sum :: forall a. (SymVal a, Num (SBV a)) => SList a -> SBV a
+sum = foldr ((+) @(SBV a)) 0
+
+-- | @`product` s@. Multiply out the given sequence.
+--
+-- >>> product [sEnum|1 .. 10::SInteger|]
+-- 3628800 :: SInteger
+product :: forall a. (SymVal a, Num (SBV a)) => SList a -> SBV a
+product = foldr ((*) @(SBV a)) 1
+
+-- | A class of symbolic aware enumerations. This is similar to Haskell's @Enum@ class,
+-- except some of the methods are generalized to work with symbolic values. Together
+-- with the 'Data.SBV.sEnum' quasiquoter, you can write symbolic arithmetic progressions,
+-- such as:
+--
+-- >>> [sEnum| 5, 7 .. 16::SInteger|]
+-- [5,7,9,11,13,15] :: [SInteger]
+-- >>> [sEnum| 4 ..|] :: SList (WordN 4)
+-- [4,5,6,7,8,9,10,11,12,13,14,15] :: [SWord 4]
+-- >>> [sEnum| 9, 12 ..|] :: SList (IntN 4)
+-- [-7,-4,-1,2,5] :: [SInt 4]
+class EnumSymbolic a where
+   -- | @`succ`@, same as in the @Enum@ class
+   succ :: SBV a -> SBV a
+
+   -- | @`pred`@, same as in the @Enum@ class
+   pred :: SBV a -> SBV a
+
+   -- | @`toEnum`@, same as in the @Enum@ class, except it takes an 'SInteger'
+   toEnum :: SInteger -> SBV a
+
+   -- | @`fromEnum`@, same as in the @Enum@ class, except it returns an 'SInteger'
+   fromEnum :: SBV a -> SInteger
+
+   -- | @`enumFrom` m@. Symbolic version of @[m ..]@
+   enumFrom :: SBV a -> SList a
+
+   -- | @`enumFromThen` m@. Symbolic version of @[m, m' ..]@
+   enumFromThen :: SBV a -> SBV a -> SList a
+
+   -- | @`enumFromTo` m n@. Symbolic version of @[m .. n]@
+   enumFromTo :: SymVal a => SBV a -> SBV a -> SList a
+
+   -- | @`enumFromThenTo` m n@. Symbolic version of @[m, m' .. n]@
+   enumFromThenTo :: SymVal a => SBV a -> SBV a -> SBV a -> SList a
+
+   -- | @`enumFromThenTo`@ with an optionally statically-known integer step. The sEnum quasiquoter
+   -- supplies @`Just` d@ for @[m, m' .. n]@ when @m'@ is @m@ shifted by a compile-time integer
+   -- constant (e.g. @[m, m-1 .. n]@ gives @-1@); otherwise it supplies `Nothing`. Instances with
+   -- exact arithmetic (integers, reals) use the hint to constant-fold the step, so the @step == 0@
+   -- infinite-list branch (and its productive helper) drops out; every other instance ignores the
+   -- hint and falls back to 'enumFromThenTo', preserving its exact semantics. Not meant to be called
+   -- directly; the default is correct for any instance.
+   enumFromThenToH :: SymVal a => SBV a -> SBV a -> SBV a -> Maybe Integer -> SList a
+   enumFromThenToH from thn to _ = enumFromThenTo from thn to
+
+-- | 'EnumSymbolic' instance for words
+instance {-# OVERLAPPABLE #-} (SymVal a, Bounded a, Integral a, Num a, Num (SBV a)) => EnumSymbolic a where
+  succ = smtFunction "EnumSymbolic.succ" (\x -> ite (x .== maxBound) (some "EnumSymbolic.succ.maxBound" (const sTrue)) (x+1))
+  pred = smtFunction "EnumSymbolic.pred" (\x -> ite (x .== minBound) (some "EnumSymbolic.pred.minBound" (const sTrue)) (x-1))
+
+  toEnum = smtFunction "EnumSymbolic.toEnum" $ \x ->
+                         ite (x .< sFromIntegral (minBound @(SBV a))) (some "EnumSymbolic.toEnum.<minBound" (const sTrue))
+                       $ ite (x .> sFromIntegral (maxBound @(SBV a))) (some "EnumSymbolic.toEnum.>maxBound" (const sTrue))
+                       $ sFromIntegral x
+
+  fromEnum = sFromIntegral
+
+  enumFrom n   = map sFromIntegral (enumFromTo @Integer (sFromIntegral n) (sFromIntegral (maxBound @(SBV a))))
+  enumFromThen = smtFunction "EnumSymbolic.enumFromThen" $ \n1 n2 ->
+                             let i_n1, i_n2 :: SInteger
+                                 i_n1 = sFromIntegral n1
+                                 i_n2 = sFromIntegral n2
+                             in map sFromIntegral (ite (i_n2 .>= i_n1)
+                                                       (enumFromThenTo i_n1 i_n2 (sFromIntegral (maxBound @(SBV a))))
+                                                       (enumFromThenTo i_n1 i_n2 (sFromIntegral (minBound @(SBV a)))))
+
+  enumFromTo     n m   = map sFromIntegral (enumFromTo     @Integer (sFromIntegral n) (sFromIntegral m))
+  enumFromThenTo n m t = map sFromIntegral (enumFromThenTo @Integer (sFromIntegral n) (sFromIntegral m) (sFromIntegral t))
+
+-- | 'EnumSymbolic' instance for integer. NB. The above definition goes thru integers, hence we need to define this explicitly.
+instance {-# OVERLAPPING #-} EnumSymbolic Integer where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum   = id
+   fromEnum = id
+
+   enumFrom   n   = enumFromThen          n (n+1)
+   enumFromTo n m = enumFromThenToInteger n m 1
+
+   enumFromThen x y = go x (y-x)
+     where go = smtProductiveFunction "EnumSymbolic.Integer.enumFromThen" $ \start delta -> start .: go (start+delta) delta
+
+   enumFromThenTo x y z = enumFromThenToInteger x z (y - x)
+
+   enumFromThenToH x y z mStep = enumFromThenToInteger x z (maybe (y - x) fromIntegral mStep)
+
+-- When the step is 0 (i.e., y == x), Haskell produces an infinite list of x's
+-- if x <= z, and the empty list otherwise. We mirror that here.
+enumFromThenToInteger :: SInteger -> SInteger -> SInteger -> SList Integer
+enumFromThenToInteger x z delta = ite (delta .== 0)
+                                      (ite (x .<= z) (enumFromThen x x) [])
+                                $ ite (delta .>  0) (up x delta z) (down x delta z)
+  where -- The d==0 case is handled: 'up'/'down' are only *called* with d>0/d<0 (the d==0 case
+        -- is routed to the infinite-list branch above), and the guard's @d .<= 0@/@d .>= 0@ test
+        -- puts @d>0@/@d<0@ into the reaching condition, so measure verification never sees d==0.
+        -- (The integer measure does not divide by d, so there's no zero-denominator to worry about.)
+        up, down :: SInteger -> SInteger -> SInteger -> SList Integer
+        up    = smtFunctionWithMeasure "EnumSymbolic.Integer.enumFromThenTo.up"
+                                       (\start _d end -> 0 `smax` (end - start + 1), [])
+              $ \start d end -> ite (start .> end .|| d .<= 0) [] (start .: up   (start + d) d end)
+        down  = smtFunctionWithMeasure "EnumSymbolic.Integer.enumFromThenTo.down"
+                                       (\start _d end -> 0 `smax` (start - end + 1), [])
+              $ \start d end -> ite (start .< end .|| d .>= 0) [] (start .: down (start + d) d end)
+
+-- | 'EnumSymbolic instance for 'Float'. Note that the termination requirement as defined by the Haskell standard for floats state:
+--      > For Float and Double, the semantics of the enumFrom family is given by the rules for Int above,
+--      > except that the list terminates when the elements become greater than @e3 + i/2@ for positive increment @i@,
+--      > or when they become less than @e3 + i/2@ for negative @i@.
+instance {-# OVERLAPPING #-} EnumSymbolic Float where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum   = sFromIntegral
+   fromEnum = fromSFloat sRTZ
+
+   enumFrom   n   = enumFromThen        n (n+1)
+   enumFromTo n m = enumFromThenToFloat n m 1
+
+   enumFromThen x y = go 0 x (y-x)
+     where go = smtProductiveFunction "EnumSymbolic.Float.enumFromThen" $ \k n d -> (n + k * d) .: go (k+1) n d
+
+   enumFromThenTo x y zIn = enumFromThenToFloat x zIn (y - x)
+
+-- When the step is 0 (i.e., y == x), Haskell produces an infinite list of x's
+-- if x <= z, and the empty list otherwise. We mirror that here.
+enumFromThenToFloat :: SFloat -> SFloat -> SFloat -> SList Float
+enumFromThenToFloat x zIn delta = ite (delta .== 0)
+                                      (ite (x .<= z) (enumFromThen x x) [])
+                                $ ite (delta .>  0) (up 0 x delta z) (down 0 x delta z)
+  where z :: SFloat
+        z = zIn + delta / 2
+
+        -- Unlike the Integer/AlgReal instances, these are NOT given a termination measure:
+        -- floating-point enumeration is genuinely partial. The step @k * d@ can saturate (once
+        -- @k * d@ falls below the ULP of @n@, or once the float @k@ itself stops incrementing),
+        -- so for some inputs @n + k * d@ never exceeds @end@ and the recursion does not terminate
+        -- -- exactly as Haskell's own float enumeration diverges in those cases. A termination
+        -- measure would therefore be unsound: no measure can certify termination of a function
+        -- that does not always terminate. Instead we mark these productive -- each recursive call
+        -- is guarded by a cons, so the definition is well-formed corecursion (finite when the
+        -- enumeration terminates, infinite when it saturates). The d==0 case never reaches here:
+        -- it is routed to the infinite-list branch above.
+        up, down :: SFloat -> SFloat -> SFloat -> SFloat -> SList Float
+        up   = smtProductiveFunction "EnumSymbolic.Float.enumFromThenTo.up"
+             $ \k n d end -> let c = n + k * d in ite (c .> end) [] (c .: up   (k+1) n d end)
+        down = smtProductiveFunction "EnumSymbolic.Float.enumFromThenTo.down"
+             $ \k n d end -> let c = n + k * d in ite (c .< end) [] (c .: down (k+1) n d end)
+
+-- | 'EnumSymbolic instance for 'Double'
+instance {-# OVERLAPPING #-} EnumSymbolic Double where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum   = sFromIntegral
+   fromEnum = fromSDouble sRTZ
+
+   enumFrom   n   = enumFromThen         n (n+1)
+   enumFromTo n m = enumFromThenToDouble n m 1
+
+   enumFromThen x y = go 0 x (y-x)
+     where go = smtProductiveFunction "EnumSymbolic.Double.enumFromThen" $ \k n d -> (n + k * d) .: go (k+1) n d
+
+   enumFromThenTo x y zIn = enumFromThenToDouble x zIn (y - x)
+
+-- When the step is 0 (i.e., y == x), Haskell produces an infinite list of x's
+-- if x <= z, and the empty list otherwise. We mirror that here.
+enumFromThenToDouble :: SDouble -> SDouble -> SDouble -> SList Double
+enumFromThenToDouble x zIn delta = ite (delta .== 0)
+                                       (ite (x .<= z) (enumFromThen x x) [])
+                                 $ ite (delta .>  0) (up 0 x delta z) (down 0 x delta z)
+  where z :: SDouble
+        z = zIn + delta / 2
+
+        -- See the Float instance for why these are productive rather than measured:
+        -- floating-point enumeration is genuinely partial (the @k * d@ step can saturate), so a
+        -- termination measure would be unsound. Each recursive call is guarded by a cons, so the
+        -- definition is well-formed corecursion. The d==0 case is routed to the branch above.
+        up, down :: SDouble -> SDouble -> SDouble -> SDouble -> SList Double
+        up   = smtProductiveFunction "EnumSymbolic.Double.enumFromThenTo.up"
+             $ \k n d end -> let c = n + k * d in ite (c .> end) [] (c .: up   (k+1) n d end)
+        down = smtProductiveFunction "EnumSymbolic.Double.enumFromThenTo.down"
+             $ \k n d end -> let c = n + k * d in ite (c .< end) [] (c .: down (k+1) n d end)
+
+-- | 'EnumSymbolic instance for arbitrary floats
+instance {-# OVERLAPPING #-} ValidFloat eb sb => EnumSymbolic (FloatingPoint eb sb) where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum   = sFromIntegral
+   fromEnum = fromSFloatingPoint sRTZ
+
+   enumFrom   n   = enumFromThen                 n (n+1)
+   enumFromTo n m = enumFromThenToFloatingPoint  n m 1
+
+   enumFromThen x y = go 0 x (y-x)
+     where go = smtProductiveFunction "EnumSymbolic.FloatingPoint.enumFromThen" $ \k n d -> (n + k * d) .: go (k+1) n d
+
+   enumFromThenTo x y zIn = enumFromThenToFloatingPoint x zIn (y - x)
+
+-- When the step is 0 (i.e., y == x), Haskell produces an infinite list of x's
+-- if x <= z, and the empty list otherwise. We mirror that here.
+enumFromThenToFloatingPoint :: forall eb sb. ValidFloat eb sb => SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SList (FloatingPoint eb sb)
+enumFromThenToFloatingPoint x zIn delta = ite (delta .== 0)
+                                              (ite (x .<= z) (enumFromThen x x) [])
+                                        $ ite (delta .>  0) (up 0 x delta z) (down 0 x delta z)
+  where z :: SFloatingPoint eb sb
+        z = zIn + delta / 2
+
+        -- See the Float instance for why these are productive rather than measured:
+        -- floating-point enumeration is genuinely partial (the @k * d@ step can saturate), so a
+        -- termination measure would be unsound. Each recursive call is guarded by a cons, so the
+        -- definition is well-formed corecursion. The d==0 case is routed to the branch above.
+        up, down :: SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SFloatingPoint eb sb -> SList (FloatingPoint eb sb)
+        up   = smtProductiveFunction "EnumSymbolic.FloatingPoint.enumFromThenTo.up"
+             $ \k n d end -> let c = n + k * d in ite (c .> end) [] (c .: up   (k+1) n d end)
+        down = smtProductiveFunction "EnumSymbolic.FloatingPoint.enumFromThenTo.down"
+             $ \k n d end -> let c = n + k * d in ite (c .< end) [] (c .: down (k+1) n d end)
+
+-- | 'EnumSymbolic instance for arbitrary AlgReal. We don't have to use the multiplicative trick here
+-- since alg-reals are precise. But, following rational in Haskell, we do use the stopping point of @z + delta / 2@.
+instance {-# OVERLAPPING #-} EnumSymbolic AlgReal where
+   succ x = x + 1
+   pred x = x - 1
+
+   toEnum   = sFromIntegral
+   fromEnum = sRealToSIntegerTruncate
+
+   enumFrom   n   = enumFromThen          n (n+1)
+   enumFromTo n m = enumFromThenToAlgReal n m 1
+
+   enumFromThen x y = go x (y-x)
+     where go = smtProductiveFunction "EnumSymbolic.AlgReal.enumFromThen" $ \start delta -> start .: go (start+delta) delta
+
+   enumFromThenTo x y zIn = enumFromThenToAlgReal x zIn (y - x)
+
+   enumFromThenToH x y zIn mStep = enumFromThenToAlgReal x zIn (maybe (y - x) fromIntegral mStep)
+
+-- When the step is 0 (i.e., y == x), Haskell produces an infinite list of x's
+-- if x <= z, and the empty list otherwise. We mirror that here.
+enumFromThenToAlgReal :: SReal -> SReal -> SReal -> SList AlgReal
+enumFromThenToAlgReal x zIn delta = ite (delta .== 0)
+                                        (ite (x .<= z) (enumFromThen x x) [])
+                                  $ ite (delta .>  0) (up x delta z) (down x delta z)
+  where z :: SReal
+        z = zIn + delta / 2
+
+        -- The measure is the number of remaining recursive steps, which is an INTEGER:
+        -- @floor ((end - start) / d) + 1@ (clamped at 0). A real-valued measure would be
+        -- unsound here, since the reals are not well-ordered (an infinite descending chain
+        -- like 1, 1/2, 1/4, ... never reaches a minimum). 'sRealToSInteger' is @floor@, and
+        -- @(end - start) / d@ is non-negative in both the up (d>0) and down (d<0) regimes, so
+        -- the same expression serves both.
+        --
+        -- The d==0 case is handled: 'up'/'down' are only *called* with d>0/d<0 (the d==0 case is
+        -- routed to the infinite-list branch above), and for measure *verification* the guard's
+        -- @d .<= 0@/@d .>= 0@ test puts @d>0@/@d<0@ into the reaching condition, so the decrease
+        -- obligation never sees d==0; the @0 `smax`@ keeps non-negativity vacuously true even for
+        -- the unreachable zero-denominator value of @(end - start) / d@.
+        up, down :: SReal -> SReal -> SReal -> SList AlgReal
+        up   = smtFunctionWithMeasure "EnumSymbolic.AlgReal.enumFromThenTo.up"   (\start d end -> 0 `smax` (sRealToSInteger ((end - start) / d) + 1), [])
+             $ \start d end -> ite (start .> end .|| d .<= 0) [] (start .: up   (start + d) d end)
+        down = smtFunctionWithMeasure "EnumSymbolic.AlgReal.enumFromThenTo.down" (\start d end -> 0 `smax` (sRealToSInteger ((end - start) / d) + 1), [])
+             $ \start d end -> ite (start .< end .|| d .>= 0) [] (start .: down (start + d) d end)
+
+-- | Lookup. If we can't find, then the result is unspecified.
+--
+-- >>> lookup (4 :: SInteger) (literal [(5, 12), (4, 3), (2, 6 :: Integer)])
+-- 3 :: SInteger
+-- >>> prove  $ \(x :: SInteger) -> x .== lookup 9 (literal [(5, 12), (4, 3), (2, 6 :: Integer)])
+-- Falsifiable. Counter-example:
+--   sbv.lookup_notFound @Integer = 0 :: Integer
+--   s0                           = 1 :: Integer
+lookup :: (SymVal k, SymVal v) => SBV k -> SList (k, v) -> SBV v
+lookup = smtFunction "sbv.lookup"
+       $ \k lst -> [sCase| lst of
+                       []                        -> some "sbv.lookup_notFound" (const sTrue)
+                       (k', v) : rest | k .== k' -> v
+                                      | True     -> lookup k rest
+                   |]
+
+-- | @`strToNat` s@. Retrieve integer encoded by string @s@ (ground rewriting only).
+-- Note that by definition this function only works when @s@ only contains digits,
+-- that is, if it encodes a natural number. Otherwise, it returns '-1'.
+--
+-- >>> prove $ \s -> let n = strToNat s in length s .== 1 .=> (-1) .<= n .&& n .<= 9
+-- Q.E.D.
+strToNat :: SString -> SInteger
+strToNat s
+ | Just a <- unliteral s
+ = if P.all C.isDigit a && not (P.null a)
+   then literal (read a)
+   else -1
+ | True
+ = lift1Str StrStrToNat Nothing s
+
+-- | @`natToStr` i@. Retrieve string encoded by integer @i@ (ground rewriting only).
+-- Again, only naturals are supported, any input that is not a natural number
+-- produces empty string, even though we take an integer as an argument.
+--
+-- >>> prove $ \i -> length (natToStr i) .== 3 .=> i .<= 999
+-- Q.E.D.
+natToStr :: SInteger -> SString
+natToStr i
+ | Just v <- unliteral i
+ = literal $ if v >= 0 then show v else ""
+ | True
+ = lift1Str StrNatToStr Nothing i
+
+-- | Lift a unary operator over lists.
+lift1 :: forall a b. (SymVal a, SymVal b) => Bool -> SeqOp -> Maybe (a -> b) -> SBV a -> SBV b
+lift1 simpleEq w mbOp a
+  | Just cv <- concEval1 simpleEq mbOp a
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf (Proxy @b)
+        r st = do sva <- sbvToSV st a
+                  newExpr st k (SBVApp (SeqOp w) [sva])
+
+-- | Lift a binary operator over lists.
+lift2 :: forall a b c. (SymVal a, SymVal b, SymVal c) => Bool -> SeqOp -> Maybe (a -> b -> c) -> SBV a -> SBV b -> SBV c
+lift2 simpleEq w mbOp a b
+  | Just cv <- concEval2 simpleEq mbOp a b
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf (Proxy @c)
+        r st = do sva <- sbvToSV st a
+                  svb <- sbvToSV st b
+                  newExpr st k (SBVApp (SeqOp w) [sva, svb])
+
+-- | Lift a ternary operator over lists.
+lift3 :: forall a b c d. (SymVal a, SymVal b, SymVal c, SymVal d) => Bool -> SeqOp -> Maybe (a -> b -> c -> d) -> SBV a -> SBV b -> SBV c -> SBV d
+lift3 simpleEq w mbOp a b c
+  | Just cv <- concEval3 simpleEq mbOp a b c
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf (Proxy @d)
+        r st = do sva <- sbvToSV st a
+                  svb <- sbvToSV st b
+                  svc <- sbvToSV st c
+                  newExpr st k (SBVApp (SeqOp w) [sva, svb, svc])
+
+-- | Concrete evaluation for unary ops
+concEval1 :: forall a b. (SymVal a, SymVal b) => Bool -> Maybe (a -> b) -> SBV a -> Maybe (SBV b)
+concEval1 simpleEq mbOp a
+  | not simpleEq || eqCheckIsObjectEq (kindOf (Proxy @a)) = literal <$> (mbOp <*> unliteral a)
+  | True                                                  = Nothing
+
+-- | Concrete evaluation for binary ops
+concEval2 :: forall a b c. (SymVal a, SymVal b, SymVal c) => Bool -> Maybe (a -> b -> c) -> SBV a -> SBV b -> Maybe (SBV c)
+concEval2 simpleEq mbOp a b
+  | not simpleEq || eqCheckIsObjectEq (kindOf (Proxy @a)) = literal <$> (mbOp <*> unliteral a <*> unliteral b)
+  | True                                                  = Nothing
+
+-- | Concrete evaluation for ternary ops
+concEval3 :: forall a b c d. (SymVal a, SymVal b, SymVal c, SymVal d) => Bool -> Maybe (a -> b -> c -> d) -> SBV a -> SBV b -> SBV c -> Maybe (SBV d)
+concEval3 simpleEq mbOp a b c
+  | not simpleEq || eqCheckIsObjectEq (kindOf (Proxy @a)) = literal <$> (mbOp <*> unliteral a <*> unliteral b <*> unliteral c)
+  | True                                                  = Nothing
+
+-- | Is the list concretely known empty?
+isConcretelyEmpty :: SymVal a => SList a -> Bool
+isConcretelyEmpty sl | Just l <- unliteral sl = P.null l
+                     | True                   = False
+
+-- | Lift a unary operator over strings.
+lift1Str :: forall a b. (SymVal a, SymVal b) => StrOp -> Maybe (a -> b) -> SBV a -> SBV b
+lift1Str w mbOp a
+  | Just cv <- literal <$> (mbOp <*> unliteral a)
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf (Proxy @b)
+        r st = do sva <- sbvToSV st a
+                  newExpr st k (SBVApp (StrOp w) [sva])
+
+{- HLint ignore implode   "Use :" -}
+{- HLint ignore replicate "Use const" -}
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,181 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                 #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Maybe (
+  -- * Constructing optional values
+    sJust, sNothing, liftMaybe, SMaybe, sMaybe, sMaybe_, sMaybes
+
+  -- * Destructing optionals
+  , maybe
+
+  -- * Mapping functions
+  , map, map2
+
+  -- * Scrutinizing the branches of an option
+  , isNothing, isJust, fromMaybe, fromJust
+
+  -- * Case analysis (for sCase quasi-quoter)
+  , sCaseMaybe, getJust_1
+  ) where
+
+import           Prelude hiding (maybe, map)
+import qualified Prelude
+
+import Data.SBV.Client
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model (ite, OrdSymbolic(..))
+import Data.SBV.SCase      (sCase)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Prelude hiding (maybe, map)
+-- >>> import Data.SBV
+#endif
+
+-- | Make 'Maybe' symbolic.
+--
+-- >>> sNothing :: SMaybe Integer
+-- Nothing :: Maybe Integer
+-- >>> isNothing (sNothing :: SMaybe Integer)
+-- True
+-- >>> isNothing (sJust (literal "nope"))
+-- False
+-- >>> sJust (3 :: SInteger)
+-- Just 3 :: Maybe Integer
+-- >>> isJust (sNothing :: SMaybe Integer)
+-- False
+-- >>> isJust (sJust (literal "yep"))
+-- True
+-- >>> prove $ \x -> isJust (sJust (x :: SInteger))
+-- Q.E.D.
+mkSymbolic [''Maybe]
+
+-- | Declare a symbolic maybe.
+sMaybe :: SymVal a => String -> Symbolic (SMaybe a)
+sMaybe = free
+
+-- | Declare a symbolic maybe, unnamed.
+sMaybe_ :: SymVal a => Symbolic (SMaybe a)
+sMaybe_ = free_
+
+-- | Declare a list of symbolic maybes.
+sMaybes :: SymVal a => [String] -> Symbolic [SMaybe a]
+sMaybes = symbolics
+
+-- | Return the value of an optional value. The default is returned if Nothing. Compare to 'fromJust'.
+--
+-- >>> fromMaybe 2 (sNothing :: SMaybe Integer)
+-- 2 :: SInteger
+-- >>> sat $ \x -> fromMaybe 2 (sJust 5 :: SMaybe Integer) .== x
+-- Satisfiable. Model:
+--   s0 = 5 :: Integer
+-- >>> 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, i.e., it can return any value. Compare to 'fromMaybe'.
+--
+-- >>> sat $ \x -> fromJust (sJust (literal 'a')) .== x
+-- Satisfiable. Model:
+--   s0 = 'a' :: Char
+-- >>> prove $ \x -> fromJust (sJust x) .== (x :: SChar)
+-- Q.E.D.
+-- >>> sat $ \x -> x .== (fromJust sNothing :: SChar)
+-- Satisfiable. Model:
+--   s0 = 'A' :: 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 = getJust_1
+
+-- | Construct an @SMaybe a@ from a @Maybe (SBV a)@.
+--
+-- >>> liftMaybe (Just (3 :: SInteger))
+-- Just 3 :: Maybe Integer
+-- >>> liftMaybe (Nothing :: Maybe SInteger)
+-- Nothing :: Maybe 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::SInteger)
+-- 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 sNothing (sJust . f)
+
+-- | Map over two maybe values.
+map2 :: forall a b c. (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b -> SBV c) -> SMaybe a -> SMaybe b -> SMaybe c
+map2 op mx my = ite (isJust mx .&& isJust my)
+                    (sJust (fromJust mx `op` fromJust my))
+                    sNothing
+
+-- | Case analysis for symbolic 'Maybe's. If the value 'isNothing', return the
+-- default value; if it 'isJust', apply the function.
+--
+-- >>> sat $ \x -> x .== maybe 0 (`sMod` 2) (sJust (3 :: SInteger))
+-- Satisfiable. Model:
+--   s0 = 1 :: Integer
+-- >>> sat $ \x -> x .== maybe 0 (`sMod` 2) (sNothing :: SMaybe Integer)
+-- Satisfiable. Model:
+--   s0 = 0 :: Integer
+-- >>> 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 = [sCase| ma of
+                               Nothing -> brNothing
+                               Just x  -> brJust x
+                            |]
+
+-- | Custom 'Num' instance over 'SMaybe'
+instance (Ord a, SymVal a, Num a, Num (SBV a)) => Num (SBV (Maybe a)) where
+  (+)         = map2 (+)
+  (-)         = map2 (-)
+  (*)         = map2 (*)
+  abs         = map  abs
+  signum      = map  signum
+  fromInteger = sJust . fromInteger
+
+-- | Custom 'OrdSymbolic' instance over 'SMaybe'.
+instance (OrdSymbolic (SBV a), SymVal a) => OrdSymbolic (SBV (Maybe a)) where
+  ma .< mb = maybe sFalse (\b -> maybe sTrue (.< b) ma) mb
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,17 +1,19 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.ABC
--- Copyright   :  (c) Adam Foltzer
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.ABC
+-- Copyright : (c) Adam Foltzer
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the ABC verification and synthesis tool
 -----------------------------------------------------------------------------
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Provers.ABC(abc) where
 
-import Data.SBV.BitVectors.Data
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
 
 -- | The description of abc. The default executable is @\"abc\"@,
@@ -23,19 +25,29 @@
 abc = SMTSolver {
            name         = ABC
          , executable   = "abc"
-         , options      = ["-S", "%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000"]
-         , engine       = standardEngine "SBV_ABC" "SBV_ABC_OPTIONS" addTimeOut standardModel
+         , preprocess   = id
+         , options      = const ["-S", "%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000"]
+         , engine       = standardEngine "SBV_ABC" "SBV_ABC_OPTIONS"
          , capabilities = SolverCapabilities {
-                                capSolverName              = "ABC"
-                              , mbDefaultLogic             = const Nothing
-                              , supportsMacros             = True
-                              , supportsProduceModels      = True
-                              , supportsQuantifiers        = False
-                              , supportsUninterpretedSorts = False
-                              , supportsUnboundedInts      = False
-                              , supportsReals              = False
-                              , supportsFloats             = False
-                              , supportsDoubles            = False
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = False
+                              , supportsGlobalDecls     = False
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
-  where addTimeOut _ _ = error "ABC: Timeout values are not supported"
diff --git a/Data/SBV/Provers/Bitwuzla.hs b/Data/SBV/Provers/Bitwuzla.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Provers/Bitwuzla.hs
@@ -0,0 +1,51 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Provers.Bitwuzla
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The connection to the Bitwuzla SMT solver
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Provers.Bitwuzla(bitwuzla) where
+
+import Data.SBV.Core.Data
+import Data.SBV.SMT.SMT
+
+-- | The description of the Bitwuzla SMT solver
+-- The default executable is @\"bitwuzla\"@, which must be in your path. You can use the @SBV_BITWUZLA@ environment variable to point to the executable on your system.
+-- You can use the @SBV_BITWUZLA_OPTIONS@ environment variable to override the options.
+bitwuzla :: SMTSolver
+bitwuzla = SMTSolver {
+           name         = Bitwuzla
+         , executable   = "bitwuzla"
+         , preprocess   = id
+         , options      = const ["--produce-models"]
+         , engine       = standardEngine "SBV_BITWUZLA" "SBV_BITWUZLA_OPTIONS"
+         , capabilities = SolverCapabilities {
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = 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,40 +1,51 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.Boolector
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.Boolector
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the Boolector SMT solver
 -----------------------------------------------------------------------------
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Provers.Boolector(boolector) where
 
-import Data.SBV.BitVectors.Data
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
 
 -- | The description of the Boolector SMT solver
 -- The default executable is @\"boolector\"@, which must be in your path. You can use the @SBV_BOOLECTOR@ environment variable to point to the executable on your system.
--- The default options are @\"-m --smt2\"@. You can use the @SBV_BOOLECTOR_OPTIONS@ environment variable to override the options.
+-- You can use the @SBV_BOOLECTOR_OPTIONS@ environment variable to override the options.
 boolector :: SMTSolver
 boolector = SMTSolver {
            name         = Boolector
          , executable   = "boolector"
-         , options      = ["--smt2", "--smt2-model", "--no-exit-codes"]
-         , engine       = standardEngine "SBV_BOOLECTOR" "SBV_BOOLECTOR_OPTIONS" addTimeOut standardModel
+         , preprocess   = id
+         , options      = const ["--smt2", "-m", "--output-format=smt2", "--no-exit-codes", "--incremental"]
+         , engine       = standardEngine "SBV_BOOLECTOR" "SBV_BOOLECTOR_OPTIONS"
          , capabilities = SolverCapabilities {
-                                capSolverName              = "Boolector"
-                              , mbDefaultLogic             = const Nothing
-                              , supportsMacros             = False
-                              , supportsProduceModels      = True
-                              , supportsQuantifiers        = False
-                              , supportsUninterpretedSorts = False
-                              , supportsUnboundedInts      = False
-                              , supportsReals              = False
-                              , supportsFloats             = False
-                              , supportsDoubles            = False
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = False
+                              , supportsReals           = False
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
- where addTimeOut o i | i < 0 = error $ "Boolector: Timeout value must be non-negative, received: " ++ show i
-                      | True  = o ++ ["-t=" ++ show i]
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,42 +1,70 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.CVC4
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.CVC4
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the CVC4 SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings #-}
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Provers.CVC4(cvc4) where
 
-import Data.SBV.BitVectors.Data
+import Data.Char (isSpace)
+
+import qualified Data.Text as T
+
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
 
 -- | The description of the CVC4 SMT solver
 -- The default executable is @\"cvc4\"@, which must be in your path. You can use the @SBV_CVC4@ environment variable to point to the executable on your system.
--- The default options are @\"--lang smt\"@. You can use the @SBV_CVC4_OPTIONS@ environment variable to override the options.
+-- You can use the @SBV_CVC4_OPTIONS@ environment variable to override the options.
 cvc4 :: SMTSolver
 cvc4 = SMTSolver {
            name         = CVC4
          , executable   = "cvc4"
-         , options      = ["--lang", "smt"]
-         , engine       = standardEngine "SBV_CVC4" "SBV_CVC4_OPTIONS" addTimeOut standardModel
+         , preprocess   = clean
+         , options      = const ["--lang", "smt", "--incremental", "--interactive", "--no-interactive-prompt", "--model-witness-value"]
+         , engine       = standardEngine "SBV_CVC4" "SBV_CVC4_OPTIONS"
          , capabilities = SolverCapabilities {
-                                capSolverName              = "CVC4"
-                              , mbDefaultLogic             = const (Just "ALL_SUPPORTED")  -- CVC4 is not happy if we don't set the logic, so fall-back to this if necessary
-                              , supportsMacros             = True
-                              , supportsProduceModels      = True
-                              , supportsQuantifiers        = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True  -- Not quite the same capability as Z3; but works more or less..
-                              , supportsFloats             = False
-                              , supportsDoubles            = False
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True  -- Not quite the same capability as Z3; but works more or less..
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
                               }
          }
- where addTimeOut o i | i < 0 = error $ "CVC4: Timeout value must be non-negative, received: " ++ show i
-                      | True  = o ++ ["--tlimit=" ++ show i ++ "000"]  -- SBV takes seconds, CVC4 wants milli-seconds
+  where -- CVC4 wants all input on one line
+        clean = T.map simpleSpace . noComment
+
+        noComment t
+          | T.null t  = T.empty
+          | True      = case T.break (== ';') t of
+                          (before, rest)
+                            | T.null rest -> before
+                            | True        -> before <> noComment (T.dropWhile (/= '\n') (T.tail rest))
+
+        simpleSpace c
+          | isSpace c = ' '
+          | True      = c
diff --git a/Data/SBV/Provers/CVC5.hs b/Data/SBV/Provers/CVC5.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Provers/CVC5.hs
@@ -0,0 +1,70 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Provers.CVC5
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The connection to the CVC5 SMT solver
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Provers.CVC5(cvc5) where
+
+import Data.Char (isSpace)
+
+import qualified Data.Text as T
+
+import Data.SBV.Core.Data
+import Data.SBV.SMT.SMT
+
+-- | The description of the CVC5 SMT solver
+-- The default executable is @\"cvc5\"@, which must be in your path. You can use the @SBV_CVC5@ environment variable to point to the executable on your system.
+-- You can use the @SBV_CVC5_OPTIONS@ environment variable to override the options.
+cvc5 :: SMTSolver
+cvc5 = SMTSolver {
+           name         = CVC5
+         , executable   = "cvc5"
+         , preprocess   = clean
+         , options      = const ["--lang", "smt", "--incremental", "--nl-cov"]
+         , engine       = standardEngine "SBV_CVC5" "SBV_CVC5_OPTIONS"
+         , capabilities = SolverCapabilities {
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True  -- Not quite the same capability as Z3; but works more or less..
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = True
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
+                              }
+         }
+  where -- CVC5 wants all input on one line
+        clean = T.map simpleSpace . noComment
+
+        noComment t
+          | T.null t  = T.empty
+          | True      = case T.break (== ';') t of
+                          (before, rest)
+                            | T.null rest -> before
+                            | True        -> before <> noComment (T.dropWhile (/= '\n') (T.tail rest))
+
+        simpleSpace c
+          | isSpace c = ' '
+          | True      = c
diff --git a/Data/SBV/Provers/DReal.hs b/Data/SBV/Provers/DReal.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Provers/DReal.hs
@@ -0,0 +1,64 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Provers.DReal
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The connection to the dReal SMT solver
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Provers.DReal(dReal) where
+
+import Data.SBV.Core.Data
+import Data.SBV.SMT.SMT
+
+import Numeric
+
+-- | The description of the dReal SMT solver
+-- The default executable is @\"dReal\"@, which must be in your path. You can use the @SBV_DREAL@ environment variable to point to the executable on your system.
+-- You can use the @SBV_DREAL_OPTIONS@ environment variable to override the options.
+dReal :: SMTSolver
+dReal = SMTSolver {
+           name         = DReal
+         , executable   = "dReal"
+         , preprocess   = id
+         , options      = modConfig ["--in", "--format", "smt2"]
+         , engine       = standardEngine "SBV_DREAL" "SBV_DREAL_OPTIONS"
+         , capabilities = SolverCapabilities {
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = False
+                              , supportsBitVectors      = False
+                              , supportsADTs            = False
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Just "(get-option :precision)"
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = False
+                              , supportsGlobalDecls     = False
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
+                              }
+         }
+  where -- If dsat precision is given, pass that as an argument
+       modConfig :: [String] -> SMTConfig -> [String]
+       modConfig opts cfg = case dsatPrecision cfg of
+                              Nothing -> opts
+                              Just d  -> let sd = showFFloat Nothing d ""
+                                         in if d > 0
+                                            then opts ++ ["--precision", sd]
+                                            else error $ unlines [ ""
+                                                                 , "*** Data.SBV: Invalid precision to dReal: " ++ sd
+                                                                 , "***           Precision must be non-negative."
+                                                                 ]
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,41 +1,61 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.MathSAT
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.MathSAT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the MathSAT SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.MathSAT(mathSAT) where
 
-import Data.SBV.BitVectors.Data
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
 
+import Data.SBV.Control.Types
+
 -- | The description of the MathSAT SMT solver
 -- The default executable is @\"mathsat\"@, which must be in your path. You can use the @SBV_MATHSAT@ environment variable to point to the executable on your system.
--- The default options are @\"-input=smt2\"@. You can use the @SBV_MATHSAT_OPTIONS@ environment variable to override the options.
+-- You can use the @SBV_MATHSAT_OPTIONS@ environment variable to override the options.
 mathSAT :: SMTSolver
 mathSAT = SMTSolver {
            name         = MathSAT
          , executable   = "mathsat"
-         , options      = ["-input=smt2", "-theory.fp.minmax_zero_mode=4"]
-         , engine       = standardEngine "SBV_MATHSAT" "SBV_MATHSAT_OPTIONS" addTimeOut standardModel
+         , preprocess   = id
+         , options      = modConfig ["-input=smt2", "-theory.fp.minmax_zero_mode=4"]
+         , engine       = standardEngine "SBV_MATHSAT" "SBV_MATHSAT_OPTIONS"
          , capabilities = SolverCapabilities {
-                                capSolverName              = "MathSAT"
-                              , mbDefaultLogic             = const Nothing
-                              , supportsMacros             = False
-                              , supportsProduceModels      = True
-                              , supportsQuantifiers        = True
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsFloats             = True
-                              , supportsDoubles            = True
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = True
+                              , supportsFlattenedModels = Nothing
                               }
          }
- where addTimeOut _ _ = error "MathSAT: Timeout values are not supported"
+
+ where -- If unsat cores are needed, MathSAT requires an explicit command-line argument
+       modConfig :: [String] -> SMTConfig -> [String]
+       modConfig opts cfg
+        | or [b | ProduceUnsatCores b <- solverSetOptions cfg]
+        = opts ++ ["-unsat_core_generation=3"]
+        | True
+        = opts
diff --git a/Data/SBV/Provers/OpenSMT.hs b/Data/SBV/Provers/OpenSMT.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Provers/OpenSMT.hs
@@ -0,0 +1,54 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Provers.OpenSMT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The connection to the OpenSMT SMT solver
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Provers.OpenSMT(openSMT) where
+
+import Data.SBV.Core.Data
+import Data.SBV.SMT.SMT
+
+-- | The description of the OpenSMT SMT solver.
+-- The default executable is @\"opensmt\"@, which must be in your path. You can use the @SBV_OpenSMT@ environment variable to point to the executable on your system.
+-- You can use the @SBV_OpenSMT_OPTIONS@ environment variable to override the options.
+openSMT :: SMTSolver
+openSMT = SMTSolver {
+           name         = OpenSMT
+         , executable   = "openSMT"
+         , preprocess   = id
+         , options      = modConfig []
+         , engine       = standardEngine "SBV_OpenSMT" "SBV_OpenSMT_OPTIONS"
+         , capabilities = SolverCapabilities {
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = False
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
+                              }
+         }
+
+ where modConfig :: [String] -> SMTConfig -> [String]
+       modConfig opts _cfg = opts
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,510 +1,928 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.Prover
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Provable abstraction and the connection to SMT solvers
------------------------------------------------------------------------------
-
-{-# LANGUAGE CPP                  #-}
-{-# LANGUAGE BangPatterns         #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE NamedFieldPuns       #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Data.SBV.Provers.Prover (
-         SMTSolver(..), SMTConfig(..), Predicate, Provable(..)
-       , ThmResult(..), SatResult(..), SafeResult(..), AllSatResult(..), SMTResult(..)
-       , isSatisfiable, isSatisfiableWith, isTheorem, isTheoremWith
-       , prove, proveWith
-       , sat, satWith
-       , safe, safeWith, isSafe
-       , allSat, allSatWith
-       , isVacuous, isVacuousWith
-       , SatModel(..), Modelable(..), displayModels, extractModels
-       , getModelDictionaries, getModelValues, getModelUninterpretedValues
-       , boolector, cvc4, yices, z3, mathSAT, abc, defaultSMTCfg
-       , compileToSMTLib, generateSMTBenchmarks
-       , internalSATCheck
-       ) where
-
-import Control.Monad    (when, unless)
-import Data.List        (intercalate)
-import System.FilePath  (addExtension, splitExtension)
-import System.Time      (getClockTime)
-import System.IO.Unsafe (unsafeInterleaveIO)
-
-import GHC.Stack.Compat
-#if !MIN_VERSION_base(4,9,0)
-import GHC.SrcLoc.Compat
-#endif
-
-import qualified Data.Set as Set (Set, toList)
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.TDiff
-
-import Control.DeepSeq (rnf)
-
-import qualified Data.SBV.Provers.Boolector  as Boolector
-import qualified Data.SBV.Provers.CVC4       as CVC4
-import qualified Data.SBV.Provers.Yices      as Yices
-import qualified Data.SBV.Provers.Z3         as Z3
-import qualified Data.SBV.Provers.MathSAT    as MathSAT
-import qualified Data.SBV.Provers.ABC        as ABC
-
-mkConfig :: SMTSolver -> SMTLibVersion -> [String] -> SMTConfig
-mkConfig s smtVersion tweaks = SMTConfig { verbose        = False
-                                         , timing         = NoTiming
-                                         , sBranchTimeOut = Nothing
-                                         , timeOut        = Nothing
-                                         , printBase      = 10
-                                         , printRealPrec  = 16
-                                         , smtFile        = Nothing
-                                         , solver         = s
-                                         , solverTweaks   = tweaks
-                                         , smtLibVersion  = smtVersion
-                                         , satCmd         = "(check-sat)"
-                                         , isNonModelVar  = const False  -- i.e., everything is a model-variable by default
-                                         , roundingMode   = RoundNearestTiesToEven
-                                         , useLogic       = Nothing
-                                         }
-
--- | Default configuration for the Boolector SMT solver
-boolector :: SMTConfig
-boolector = mkConfig Boolector.boolector SMTLib2 []
-
--- | Default configuration for the CVC4 SMT Solver.
-cvc4 :: SMTConfig
-cvc4 = mkConfig CVC4.cvc4 SMTLib2 []
-
--- | Default configuration for the Yices SMT Solver.
-yices :: SMTConfig
-yices = mkConfig Yices.yices SMTLib2 []
-
--- | Default configuration for the Z3 SMT solver
-z3 :: SMTConfig
-z3 = mkConfig Z3.z3 SMTLib2 ["(set-option :smt.mbqi true) ; use model based quantifier instantiation"]
-
--- | Default configuration for the MathSAT SMT solver
-mathSAT :: SMTConfig
-mathSAT = mkConfig MathSAT.mathSAT SMTLib2 []
-
--- | Default configuration for the ABC synthesis and verification tool.
-abc :: SMTConfig
-abc = mkConfig ABC.abc SMTLib2 []
-
--- | The default solver used by SBV. This is currently set to z3.
-defaultSMTCfg :: SMTConfig
-defaultSMTCfg = z3
-
--- | A predicate is a symbolic program that returns a (symbolic) boolean value. For all intents and
--- purposes, it can be treated as an n-ary function from symbolic-values to a boolean. The 'Symbolic'
--- monad captures the underlying representation, and can/should be ignored by the users of the library,
--- unless you are building further utilities on top of SBV itself. Instead, simply use the 'Predicate'
--- type when necessary.
-type Predicate = Symbolic SBool
-
--- | A type @a@ is provable if we can turn it into a predicate.
--- Note that a predicate can be made from a curried function of arbitrary arity, where
--- each element is either a symbolic type or up-to a 7-tuple of symbolic-types. So
--- predicates can be constructed from almost arbitrary Haskell functions that have arbitrary
--- shapes. (See the instance declarations below.)
-class Provable a where
-  -- | Turns a value into a universally quantified predicate, internally naming the inputs.
-  -- In this case the sbv library will use names of the form @s1, s2@, etc. to name these variables
-  -- Example:
-  --
-  -- >  forAll_ $ \(x::SWord8) y -> x `shiftL` 2 .== y
-  --
-  -- is a predicate with two arguments, captured using an ordinary Haskell function. Internally,
-  -- @x@ will be named @s0@ and @y@ will be named @s1@.
-  forAll_ :: a -> Predicate
-  -- | Turns a value into a predicate, allowing users to provide names for the inputs.
-  -- If the user does not provide enough number of names for the variables, the remaining ones
-  -- will be internally generated. Note that the names are only used for printing models and has no
-  -- other significance; in particular, we do not check that they are unique. Example:
-  --
-  -- >  forAll ["x", "y"] $ \(x::SWord8) y -> x `shiftL` 2 .== y
-  --
-  -- This is the same as above, except the variables will be named @x@ and @y@ respectively,
-  -- simplifying the counter-examples when they are printed.
-  forAll  :: [String] -> a -> Predicate
-  -- | Turns a value into an existentially quantified predicate. (Indeed, 'exists' would have been
-  -- a better choice here for the name, but alas it's already taken.)
-  forSome_ :: a -> Predicate
-  -- | Version of 'forSome' that allows user defined names
-  forSome :: [String] -> a -> Predicate
-
-instance Provable Predicate where
-  forAll_    = id
-  forAll []  = id
-  forAll xs  = error $ "SBV.forAll: Extra unmapped name(s) in predicate construction: " ++ intercalate ", " xs
-  forSome_   = id
-  forSome [] = id
-  forSome xs = error $ "SBV.forSome: Extra unmapped name(s) in predicate construction: " ++ intercalate ", " xs
-
-instance Provable SBool where
-  forAll_   = return
-  forAll _  = return
-  forSome_  = return
-  forSome _ = return
-
-{-
--- The following works, but it lets us write properties that
--- are not useful.. Such as: prove $ \x y -> (x::SInt8) == y
--- Running that will throw an exception since Haskell's equality
--- is not be supported by symbolic things. (Needs .==).
-instance Provable Bool where
-  forAll_  x  = forAll_   (if x then true else false :: SBool)
-  forAll s x  = forAll s  (if x then true else false :: SBool)
-  forSome_  x = forSome_  (if x then true else false :: SBool)
-  forSome s x = forSome s (if x then true else false :: SBool)
--}
-
--- Functions
-instance (SymWord a, Provable p) => Provable (SBV a -> p) where
-  forAll_        k = forall_   >>= \a -> forAll_   $ k a
-  forAll (s:ss)  k = forall s  >>= \a -> forAll ss $ k a
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ k a
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ k a
-  forSome []     k = forSome_ k
-
--- SFunArrays (memory, functional representation), only supported universally for the time being
-instance (HasKind a, HasKind b, Provable p) => Provable (SArray a b -> p) where
-  forAll_       k = declNewSArray (\t -> "array_" ++ show t) Nothing >>= \a -> forAll_   $ k a
-  forAll (s:ss) k = declNewSArray (const s)                  Nothing >>= \a -> forAll ss $ k a
-  forAll []     k = forAll_ k
-  forSome_      _ = error "SBV.forSome: Existential arrays are not currently supported."
-  forSome _     _ = error "SBV.forSome: Existential arrays are not currently supported."
-
--- SArrays (memory, SMT-Lib notion of arrays), only supported universally for the time being
-instance (HasKind a, HasKind b, Provable p) => Provable (SFunArray a b -> p) where
-  forAll_       k = declNewSFunArray Nothing >>= \a -> forAll_   $ k a
-  forAll (_:ss) k = declNewSFunArray Nothing >>= \a -> forAll ss $ k a
-  forAll []     k = forAll_ k
-  forSome_      _ = error "SBV.forSome: Existential arrays are not currently supported."
-  forSome _     _ = error "SBV.forSome: Existential arrays are not currently supported."
-
--- 2 Tuple
-instance (SymWord a, SymWord b, Provable p) => Provable ((SBV a, SBV b) -> p) where
-  forAll_        k = forall_  >>= \a -> forAll_   $ \b -> k (a, b)
-  forAll (s:ss)  k = forall s >>= \a -> forAll ss $ \b -> k (a, b)
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b -> k (a, b)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b -> k (a, b)
-  forSome []     k = forSome_ k
-
--- 3 Tuple
-instance (SymWord a, SymWord b, SymWord c, Provable p) => Provable ((SBV a, SBV b, SBV c) -> p) where
-  forAll_       k  = forall_  >>= \a -> forAll_   $ \b c -> k (a, b, c)
-  forAll (s:ss) k  = forall s >>= \a -> forAll ss $ \b c -> k (a, b, c)
-  forAll []     k  = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b c -> k (a, b, c)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b c -> k (a, b, c)
-  forSome []     k = forSome_ k
-
--- 4 Tuple
-instance (SymWord a, SymWord b, SymWord c, SymWord d, Provable p) => Provable ((SBV a, SBV b, SBV c, SBV d) -> p) where
-  forAll_        k = forall_  >>= \a -> forAll_   $ \b c d -> k (a, b, c, d)
-  forAll (s:ss)  k = forall s >>= \a -> forAll ss $ \b c d -> k (a, b, c, d)
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b c d -> k (a, b, c, d)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b c d -> k (a, b, c, d)
-  forSome []     k = forSome_ k
-
--- 5 Tuple
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, Provable p) => Provable ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
-  forAll_        k = forall_  >>= \a -> forAll_   $ \b c d e -> k (a, b, c, d, e)
-  forAll (s:ss)  k = forall s >>= \a -> forAll ss $ \b c d e -> k (a, b, c, d, e)
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b c d e -> k (a, b, c, d, e)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b c d e -> k (a, b, c, d, e)
-  forSome []     k = forSome_ k
-
--- 6 Tuple
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, Provable p) => Provable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
-  forAll_        k = forall_  >>= \a -> forAll_   $ \b c d e f -> k (a, b, c, d, e, f)
-  forAll (s:ss)  k = forall s >>= \a -> forAll ss $ \b c d e f -> k (a, b, c, d, e, f)
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b c d e f -> k (a, b, c, d, e, f)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b c d e f -> k (a, b, c, d, e, f)
-  forSome []     k = forSome_ k
-
--- 7 Tuple
-instance (SymWord a, SymWord b, SymWord c, SymWord d, SymWord e, SymWord f, SymWord g, Provable p) => Provable ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
-  forAll_        k = forall_  >>= \a -> forAll_   $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  forAll (s:ss)  k = forall s >>= \a -> forAll ss $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  forAll []      k = forAll_ k
-  forSome_       k = exists_  >>= \a -> forSome_   $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  forSome (s:ss) k = exists s >>= \a -> forSome ss $ \b c d e f g -> k (a, b, c, d, e, f, g)
-  forSome []     k = forSome_ k
-
--- | Prove a predicate, equivalent to @'proveWith' 'defaultSMTCfg'@
-prove :: Provable a => a -> IO ThmResult
-prove = proveWith defaultSMTCfg
-
--- | Find a satisfying assignment for a predicate, equivalent to @'satWith' 'defaultSMTCfg'@
-sat :: Provable a => a -> IO SatResult
-sat = satWith defaultSMTCfg
-
--- | Check that all the 'sAssert' calls are safe, equivalent to @'safeWith' 'defaultSMTCfg'@
-safe :: SExecutable a => a -> IO [SafeResult]
-safe = safeWith defaultSMTCfg
-
--- | Return all satisfying assignments for a predicate, equivalent to @'allSatWith' 'defaultSMTCfg'@.
--- Satisfying assignments are constructed lazily, so they will be available as returned by the solver
--- and on demand.
---
--- NB. Uninterpreted constant/function values and counter-examples for array values are ignored for
--- the purposes of @'allSat'@. That is, only the satisfying assignments modulo uninterpreted functions and
--- array inputs will be returned. This is due to the limitation of not having a robust means of getting a
--- function counter-example back from the SMT solver.
-allSat :: Provable a => a -> IO AllSatResult
-allSat = allSatWith defaultSMTCfg
-
--- | Check if the given constraints are satisfiable, equivalent to @'isVacuousWith' 'defaultSMTCfg'@.
--- See the function 'constrain' for an example use of 'isVacuous'.
-isVacuous :: Provable a => a -> IO Bool
-isVacuous = isVacuousWith defaultSMTCfg
-
--- Decision procedures (with optional timeout)
-
--- | Check whether a given property is a theorem, with an optional time out and the given solver.
--- Returns @Nothing@ if times out, or the result wrapped in a @Just@ otherwise.
-isTheoremWith :: Provable a => SMTConfig -> Maybe Int -> a -> IO (Maybe Bool)
-isTheoremWith cfg mbTo p = do r <- proveWith cfg{timeOut = mbTo} p
-                              case r of
-                                ThmResult (Unsatisfiable _) -> return $ Just True
-                                ThmResult (Satisfiable _ _) -> return $ Just False
-                                ThmResult (TimeOut _)       -> return Nothing
-                                _                           -> error $ "SBV.isTheorem: Received:\n" ++ show r
-
--- | Check whether a given property is satisfiable, with an optional time out and the given solver.
--- Returns @Nothing@ if times out, or the result wrapped in a @Just@ otherwise.
-isSatisfiableWith :: Provable a => SMTConfig -> Maybe Int -> a -> IO (Maybe Bool)
-isSatisfiableWith cfg mbTo p = do r <- satWith cfg{timeOut = mbTo} p
-                                  case r of
-                                    SatResult (Satisfiable _ _) -> return $ Just True
-                                    SatResult (Unsatisfiable _) -> return $ Just False
-                                    SatResult (TimeOut _)       -> return Nothing
-                                    _                           -> error $ "SBV.isSatisfiable: Received: " ++ show r
-
--- | Checks theoremhood within the given optional time limit of @i@ seconds.
--- Returns @Nothing@ if times out, or the result wrapped in a @Just@ otherwise.
-isTheorem :: Provable a => Maybe Int -> a -> IO (Maybe Bool)
-isTheorem = isTheoremWith defaultSMTCfg
-
--- | Checks satisfiability within the given optional time limit of @i@ seconds.
--- Returns @Nothing@ if times out, or the result wrapped in a @Just@ otherwise.
-isSatisfiable :: Provable a => Maybe Int -> a -> IO (Maybe Bool)
-isSatisfiable = isSatisfiableWith defaultSMTCfg
-
--- | Compiles to SMT-Lib and returns the resulting program as a string. Useful for saving
--- the result to a file for off-line analysis, for instance if you have an SMT solver that's not natively
--- supported out-of-the box by the SBV library. It takes two arguments:
---
---    * version: The SMTLib-version to produce. Note that we currently only support SMTLib2.
---
---    * isSat  : If 'True', will translate it as a SAT query, i.e., in the positive. If 'False', will
---               translate as a PROVE query, i.e., it will negate the result. (In this case, the check-sat
---               call to the SMT solver will produce UNSAT if the input is a theorem, as usual.)
-compileToSMTLib :: Provable a => SMTLibVersion   -- ^ Version of SMTLib to compile to. (Only SMTLib2 supported currently.)
-                              -> Bool            -- ^ If True, translate directly, otherwise negate the goal. (Use True for SAT queries, False for PROVE queries.)
-                              -> a
-                              -> IO String
-compileToSMTLib version isSat a = do
-        t <- getClockTime
-        let comments = ["Created on " ++ show t]
-            cvt = case version of
-                    SMTLib2 -> toSMTLib2
-        (_, _, _, _, smtLibPgm) <- simulate cvt defaultSMTCfg isSat comments a
-        let out = show smtLibPgm
-        return $ out ++ "\n(check-sat)\n"
-
--- | Create SMT-Lib benchmarks, for supported versions of SMTLib. The first argument is the basename of the file.
--- The 'Bool' argument controls whether this is a SAT instance, i.e., translate the query
--- directly, or a PROVE instance, i.e., translate the negated query. (See the second boolean argument to
--- 'compileToSMTLib' for details.)
-generateSMTBenchmarks :: Provable a => Bool -> FilePath -> a -> IO ()
-generateSMTBenchmarks isSat f a = mapM_ gen [minBound .. maxBound]
-  where gen v = do s <- compileToSMTLib v isSat a
-                   let fn = f `addExtension` smtLibVersionExtension v
-                   writeFile fn s
-                   putStrLn $ "Generated " ++ show v ++ " benchmark " ++ show fn ++ "."
-
--- | Proves the predicate using the given SMT-solver
-proveWith :: Provable a => SMTConfig -> a -> IO ThmResult
-proveWith config a = simulate cvt config False [] a >>= callSolver False "Checking Theoremhood.." ThmResult config
-  where cvt = case smtLibVersion config of
-                SMTLib2 -> toSMTLib2
-
--- | Find a satisfying assignment using the given SMT-solver
-satWith :: Provable a => SMTConfig -> a -> IO SatResult
-satWith config a = simulate cvt config True [] a >>= callSolver True "Checking Satisfiability.." SatResult config
-  where cvt = case smtLibVersion config of
-                SMTLib2 -> toSMTLib2
-
--- | Check if any of the assertions can be violated
-safeWith :: SExecutable a => SMTConfig -> a -> IO [SafeResult]
-safeWith cfg a = do
-        res@Result{resAssertions=asserts} <- runSymbolic (True, cfg) $ sName_ a >>= output
-        mapM (verify res) asserts
-  where locInfo (Just ps) = Just $ let loc (f, sl) = concat [srcLocFile sl, ":", show (srcLocStartLine sl), ":", show (srcLocStartCol sl), ":", f]
-                                   in intercalate ",\n " (map loc ps)
-        locInfo _         = Nothing
-        verify res (msg, cs, cond) = do SatResult result <- runProofOn cvt cfg True [] pgm >>= callSolver True msg SatResult cfg
-                                        return $ SafeResult (locInfo (getCallStack `fmap` cs), msg, result)
-           where pgm = res { resInputs  = [(EX, n) | (_, n) <- resInputs res]   -- make everything existential
-                           , resOutputs = [cond]
-                           }
-                 cvt = case smtLibVersion cfg of
-                         SMTLib2 -> toSMTLib2
-
--- | Check if a safe-call was safe or not, turning a 'SafeResult' to a Bool.
-isSafe :: SafeResult -> Bool
-isSafe (SafeResult (_, _, result)) = case result of
-                                       Unsatisfiable{} -> True
-                                       Satisfiable{}   -> False
-                                       Unknown{}       -> False   -- conservative
-                                       ProofError{}    -> False   -- conservative
-                                       TimeOut{}       -> False   -- conservative
-
--- | Determine if the constraints are vacuous using the given SMT-solver
-isVacuousWith :: Provable a => SMTConfig -> a -> IO Bool
-isVacuousWith config a = do
-        Result ki tr uic is cs ts as uis ax asgn cstr asserts _ <- runSymbolic (True, config) $ forAll_ a >>= output
-        case cstr of
-           [] -> return False -- no constraints, no need to check
-           _  -> do let is'  = [(EX, i) | (_, i) <- is] -- map all quantifiers to "exists" for the constraint check
-                        res' = Result ki tr uic is' cs ts as uis ax asgn cstr asserts [trueSW]
-                        cvt  = case smtLibVersion config of
-                                 SMTLib2 -> toSMTLib2
-                    SatResult result <- runProofOn cvt config True [] res' >>= callSolver True "Checking Satisfiability.." SatResult config
-                    case result of
-                      Unsatisfiable{} -> return True  -- constraints are unsatisfiable!
-                      Satisfiable{}   -> return False -- constraints are satisfiable!
-                      Unknown{}       -> error "SBV: isVacuous: Solver returned unknown!"
-                      ProofError _ ls -> error $ "SBV: isVacuous: error encountered:\n" ++ unlines ls
-                      TimeOut _       -> error "SBV: isVacuous: time-out."
-
--- | Find all satisfying assignments using the given SMT-solver
-allSatWith :: Provable a => SMTConfig -> a -> IO AllSatResult
-allSatWith config p = do
-        let converter  = case smtLibVersion config of
-                           SMTLib2 -> toSMTLib2
-        msg "Checking Satisfiability, all solutions.."
-        sbvPgm@(qinps, _, ki, _, _) <- simulate converter config True [] p
-        let usorts = [s | us@(KUserSort s _) <- Set.toList ki, isFree us]
-                where isFree (KUserSort _ (Left _)) = True
-                      isFree _                      = False
-        unless (null usorts) $ msg $  "SBV.allSat: Uninterpreted sorts present: " ++ unwords usorts
-                                   ++ "\n               SBV will use equivalence classes to generate all-satisfying instances."
-        results <- unsafeInterleaveIO $ go sbvPgm (1::Int) []
-        -- See if there are any existentials below any universals
-        -- If such is the case, then the solutions are unique upto prefix existentials
-        let w = ALL `elem` map fst qinps
-        return $ AllSatResult (w,  results)
-  where msg = when (verbose config) . putStrLn . ("** " ++)
-        go sbvPgm = loop
-          where loop !n nonEqConsts = do
-                  curResult <- invoke nonEqConsts n sbvPgm
-                  case curResult of
-                    Nothing            -> return []
-                    Just (SatResult r) -> let cont model = do let modelOnlyAssocs = [v | v@(x, _) <- modelAssocs model, not (isNonModelVar config x)]
-                                                              rest <- unsafeInterleaveIO $ loop (n+1) (modelOnlyAssocs : nonEqConsts)
-                                                              return (r : rest)
-                                          in case r of
-                                               Satisfiable   _ (SMTModel []) -> return [r]
-                                               Unknown       _ (SMTModel []) -> return [r]
-                                               ProofError    _ _             -> return [r]
-                                               TimeOut       _               -> return []
-                                               Unsatisfiable _               -> return []
-                                               Satisfiable   _ model         -> cont model
-                                               Unknown       _ model         -> cont model
-        invoke nonEqConsts n (qinps, skolemMap, _, _, smtLibPgm) = do
-               msg $ "Looking for solution " ++ show n
-               case addNonEqConstraints (roundingMode config) qinps nonEqConsts smtLibPgm of
-                 Nothing ->  -- no new constraints added, stop
-                            return Nothing
-                 Just finalPgm -> do msg $ "Generated SMTLib program:\n" ++ finalPgm
-                                     smtAnswer <- engine (solver config) (updateName (n-1) config) True qinps skolemMap finalPgm
-                                     msg "Done.."
-                                     return $ Just $ SatResult smtAnswer
-        updateName i cfg = cfg{smtFile = upd `fmap` smtFile cfg}
-               where upd nm = let (b, e) = splitExtension nm in b ++ "_allSat_" ++ show i ++ e
-
-type SMTProblem = ( [(Quantifier, NamedSymVar)]      -- inputs
-                  , [Either SW (SW, [SW])]           -- skolem-map
-                  , Set.Set Kind                     -- kinds used
-                  , [(String, Maybe CallStack, SW)]  -- assertions
-                  , SMTLibPgm                        -- SMTLib representation
-                  )
-
-callSolver :: Bool -> String -> (SMTResult -> b) -> SMTConfig -> SMTProblem -> IO b
-callSolver isSat checkMsg wrap config (qinps, skolemMap, _, _, smtLibPgm) = do
-       let msg = when (verbose config) . putStrLn . ("** " ++)
-       msg checkMsg
-       let finalPgm = intercalate "\n" (pre ++ post) where SMTLibPgm _ (_, pre, post) = smtLibPgm
-       msg $ "Generated SMTLib program:\n" ++ finalPgm
-       smtAnswer <- engine (solver config) config isSat qinps skolemMap finalPgm
-       msg "Done.."
-       return $ wrap smtAnswer
-
-simulate :: Provable a => SMTLibConverter -> SMTConfig -> Bool -> [String] -> a -> IO SMTProblem
-simulate converter config isSat comments predicate = do
-        let msg = when (verbose config) . putStrLn . ("** " ++)
-            isTiming = timing config
-        msg "Starting symbolic simulation.."
-        res <- timeIf isTiming ProblemConstruction $ runSymbolic (isSat, config) $ (if isSat then forSome_ else forAll_) predicate >>= output
-        msg $ "Generated symbolic trace:\n" ++ show res
-        msg "Translating to SMT-Lib.."
-        runProofOn converter config isSat comments res
-
-runProofOn :: SMTLibConverter -> SMTConfig -> Bool -> [String] -> Result -> IO SMTProblem
-runProofOn converter config isSat comments res =
-        let isTiming   = timing config
-            solverCaps = capabilities (solver config)
-        in case res of
-             Result ki _qcInfo _codeSegs is consts tbls arrs uis axs pgm cstrs assertions [o@(SW KBool _)] ->
-               timeIf isTiming Translation
-                $ let skolemMap = skolemize (if isSat then is else map flipQ is)
-                           where flipQ (ALL, x) = (EX, x)
-                                 flipQ (EX, x)  = (ALL, x)
-                                 skolemize :: [(Quantifier, NamedSymVar)] -> [Either SW (SW, [SW])]
-                                 skolemize qinps = go qinps ([], [])
-                                   where go []                   (_,  sofar) = reverse sofar
-                                         go ((ALL, (v, _)):rest) (us, sofar) = go rest (v:us, Left v : sofar)
-                                         go ((EX,  (v, _)):rest) (us, sofar) = go rest (us,   Right (v, reverse us) : sofar)
-                      smtScript = converter (roundingMode config) (useLogic config) solverCaps ki isSat comments is skolemMap consts tbls arrs uis axs pgm cstrs o
-                      result = (is, skolemMap, ki, assertions, smtScript)
-                  in rnf smtScript `seq` return result
-             Result{resOutputs = os} -> case length os of
-                           0  -> error $ "Impossible happened, unexpected non-outputting result\n" ++ show res
-                           1  -> error $ "Impossible happened, non-boolean output in " ++ show os
-                                       ++ "\nDetected while generating the trace:\n" ++ show res
-                           _  -> error $ "User error: Multiple output values detected: " ++ show os
-                                       ++ "\nDetected while generating the trace:\n" ++ show res
-                                       ++ "\n*** Check calls to \"output\", they are typically not needed!"
-
--- | Run an external proof on the given condition to see if it is satisfiable.
-internalSATCheck :: SMTConfig -> SBool -> State -> String -> IO SatResult
-internalSATCheck cfg condInPath st msg = do
-   sw <- sbvToSW st condInPath
-   () <- forceSWArg sw
-   Result ki tr uic is cs ts as uis ax asgn cstr assertions _ <- extractSymbolicSimulationState st
-   let -- Construct the corresponding sat-checker for the branch. Note that we need to
-       -- forget about the quantifiers and just use an "exist", as we're looking for a
-       -- point-satisfiability check here; whatever the original program was.
-       pgm = Result ki tr uic [(EX, n) | (_, n) <- is] cs ts as uis ax asgn cstr assertions [sw]
-       cvt = case smtLibVersion cfg of
-                SMTLib2 -> toSMTLib2
-   runProofOn cvt cfg True [] pgm >>= callSolver True msg SatResult cfg
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
+-- Module    : Data.SBV.Provers.Prover
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Provable abstraction and the connection to SMT solvers
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ConstraintKinds       #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TupleSections         #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Provers.Prover (
+         SMTSolver(..), SMTConfig(..), Predicate
+       , ProvableM(..), Provable, SatisfiableM(..), Satisfiable
+       , generateSMTBenchmarkSat, generateSMTBenchmarkProof, defs2smt, ConstraintSet
+       , ThmResult(..), SatResult(..), AllSatResult(..), SafeResult(..), OptimizeResult(..), SMTResult(..)
+       , SExecutable(..), isSafe
+       , runSMT, runSMTWith
+       , SatModel(..), Modelable(..), displayModels, extractModels
+       , getModelDictionaries, getModelValues
+       , abc, boolector, bitwuzla, cvc4, cvc5, dReal, mathSAT, yices, z3, openSMT, defaultSMTCfg, defaultDeltaSMTCfg
+       , proveWithAny, proveWithAll, proveConcurrentWithAny, proveConcurrentWithAll
+       , satWithAny,   satWithAll,   satConcurrentWithAny,   satConcurrentWithAll
+       ) where
+
+
+import Control.Monad          (unless)
+import Control.Monad.IO.Class (MonadIO, liftIO)
+import Control.DeepSeq        (rnf, NFData(..))
+
+import Control.Concurrent.Async (async, waitAny, asyncThreadId, Async, mapConcurrently)
+import Control.Exception (finally, throwTo)
+import System.Exit (ExitCode(ExitSuccess))
+
+import System.IO.Unsafe (unsafeInterleaveIO)             -- only used safely!
+
+import System.Directory  (getCurrentDirectory)
+import Data.Time (getZonedTime, NominalDiffTime, UTCTime, getCurrentTime, diffUTCTime)
+import Data.List (intercalate, isPrefixOf)
+
+import Data.Maybe (mapMaybe, listToMaybe)
+
+import qualified Data.Set as Set (empty)
+
+import qualified Data.Foldable   as S (toList)
+import qualified Data.Text       as T
+
+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.Lib    (showText)
+import Data.SBV.Utils.TDiff
+
+import Data.SBV.Lambda () -- instances only
+
+import qualified Data.SBV.Trans.Control as Control
+import qualified Data.SBV.Control.Query as Control
+import qualified Data.SBV.Control.Utils as Control
+
+import GHC.Stack
+
+import qualified Data.SBV.Provers.ABC       as ABC
+import qualified Data.SBV.Provers.Boolector as Boolector
+import qualified Data.SBV.Provers.Bitwuzla  as Bitwuzla
+import qualified Data.SBV.Provers.CVC4      as CVC4
+import qualified Data.SBV.Provers.CVC5      as CVC5
+import qualified Data.SBV.Provers.DReal     as DReal
+import qualified Data.SBV.Provers.MathSAT   as MathSAT
+import qualified Data.SBV.Provers.Yices     as Yices
+import qualified Data.SBV.Provers.Z3        as Z3
+import qualified Data.SBV.Provers.OpenSMT   as OpenSMT
+
+import GHC.TypeLits
+
+mkConfig :: SMTSolver -> SMTLibVersion -> [Control.SMTOption] -> SMTConfig
+mkConfig s smtVersion startOpts = SMTConfig { verbose                     = False
+                                            , timing                      = NoTiming
+                                            , printBase                   = 10
+                                            , printRealPrec               = 16
+                                            , crackNum                    = False
+                                            , crackNumSurfaceVals         = []
+                                            , transcript                  = Nothing
+                                            , solver                      = s
+                                            , smtLibVersion               = smtVersion
+                                            , dsatPrecision               = Nothing
+                                            , extraArgs                   = []
+                                            , satCmd                      = "(check-sat)"
+                                            , allSatTrackUFs              = 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
+                                            , optimizeValidateConstraints = False
+                                            , roundingMode                = RoundNearestTiesToEven
+                                            , solverSetOptions            = startOpts
+                                            , ignoreExitCode              = False
+                                            , redirectVerbose             = Nothing
+                                            , firstifyUniqueLen           = 10
+                                            , tpOptions                   = TPOptions { ribbonLength          = 40
+                                                                                      , quiet                 = False
+                                                                                      , printAsms             = False
+                                                                                      , printStats            = False
+                                                                                      , measuresBeingVerified = Set.empty
+                                                                                      }
+                                            }
+
+-- | If supported, this makes all output go to stdout, which works better with SBV
+-- Alas, not all solvers support it..
+allOnStdOut :: Control.SMTOption
+allOnStdOut = Control.DiagnosticOutputChannel "stdout"
+
+-- | Default configuration for the ABC synthesis and verification tool.
+abc :: SMTConfig
+abc = mkConfig ABC.abc SMTLib2 [allOnStdOut]
+
+-- | Default configuration for the Boolector SMT solver
+boolector :: SMTConfig
+boolector = mkConfig Boolector.boolector SMTLib2 []
+
+-- | Default configuration for the Bitwuzla SMT solver
+bitwuzla :: SMTConfig
+bitwuzla = mkConfig Bitwuzla.bitwuzla SMTLib2 []
+
+-- | Default configuration for the CVC4 SMT Solver.
+cvc4 :: SMTConfig
+cvc4 = mkConfig CVC4.cvc4 SMTLib2 [allOnStdOut]
+
+-- | Default configuration for the CVC5 SMT Solver.
+cvc5 :: SMTConfig
+cvc5 = mkConfig CVC5.cvc5 SMTLib2 [allOnStdOut]
+
+-- | Default configuration for the Yices SMT Solver.
+dReal :: SMTConfig
+dReal = mkConfig DReal.dReal SMTLib2 [ Control.OptionKeyword ":smtlib2_compliant" ["true"]
+                                     ]
+
+-- | Default configuration for the MathSAT SMT solver
+mathSAT :: SMTConfig
+mathSAT = mkConfig MathSAT.mathSAT SMTLib2 [allOnStdOut]
+
+-- | Default configuration for the Yices SMT Solver.
+yices :: SMTConfig
+yices = mkConfig Yices.yices SMTLib2 []
+
+-- | Default configuration for the Z3 SMT solver
+z3 :: SMTConfig
+z3 = mkConfig Z3.z3 SMTLib2 [ Control.OptionKeyword ":smtlib2_compliant" ["true"]
+                            , allOnStdOut
+                            ]
+
+-- | Default configuration for the OpenSMT SMT solver
+openSMT :: SMTConfig
+openSMT = mkConfig OpenSMT.openSMT SMTLib2 [ Control.OptionKeyword ":smtlib2_compliant" ["true"]
+                                           , allOnStdOut
+                                           ]
+
+-- | The default solver used by SBV. This is currently set to z3.
+defaultSMTCfg :: SMTConfig
+defaultSMTCfg = z3
+
+-- | The default solver used by SBV for delta-satisfiability problems. This is currently set to dReal,
+-- which is also the only solver that supports delta-satisfiability.
+defaultDeltaSMTCfg :: SMTConfig
+defaultDeltaSMTCfg = dReal
+
+-- | A predicate is a symbolic program that returns a (symbolic) boolean value. For all intents and
+-- purposes, it can be treated as an n-ary function from symbolic-values to a boolean. The 'Symbolic'
+-- monad captures the underlying representation, and can/should be ignored by the users of the library,
+-- unless you are building further utilities on top of SBV itself. Instead, simply use the 'Predicate'
+-- type when necessary.
+type Predicate = Symbolic SBool
+
+-- | A constraint set is a symbolic program that returns no values. The idea is that the constraints/min-max
+-- goals will serve as the collection of constraints that will be used for sat/optimize calls.
+type ConstraintSet = Symbolic ()
+
+-- | `Provable` is specialization of `ProvableM` to the `IO` monad. Unless you are using
+-- transformers explicitly, this is the type you should prefer.
+type Provable = ProvableM IO
+
+-- | `Data.SBV.Provers.Satisfiable` is specialization of `SatisfiableM` to the `IO` monad. Unless you are using
+-- transformers explicitly, this is the type you should prefer.
+type Satisfiable = SatisfiableM IO
+
+-- | A type @a@ is satisfiable if it has constraints, potentially returning a boolean. This class
+-- captures essentially sat and optimize calls.
+class ExtractIO m => SatisfiableM m a where
+  -- | Reduce an arg, for sat purposes.
+  satArgReduce :: a -> SymbolicT m SBool
+
+  -- | Generalization of 'Data.SBV.sat'
+  sat :: a -> m SatResult
+  sat = satWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.satWith'
+  satWith :: SMTConfig -> a -> m SatResult
+  satWith cfg a = do r <- runWithQuery satArgReduce True (checkNoOptimizations >> Control.getSMTResult) cfg a
+                     SatResult <$> if validationRequested cfg
+                                   then validate satArgReduce True cfg a r
+                                   else pure r
+
+  -- | Generalization of 'Data.SBV.sat'
+  dsat :: a -> m SatResult
+  dsat = dsatWith defaultDeltaSMTCfg
+
+  -- | Generalization of 'Data.SBV.satWith'
+  dsatWith :: SMTConfig -> a -> m SatResult
+  dsatWith cfg a = do r <- runWithQuery satArgReduce True (checkNoOptimizations >> Control.getSMTResult) cfg a
+                      SatResult <$> if validationRequested cfg
+                                    then validate satArgReduce True cfg a r
+                                    else pure r
+
+  -- | Generalization of 'Data.SBV.allSat'
+  allSat :: a -> m AllSatResult
+  allSat = allSatWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.allSatWith'
+  allSatWith :: SMTConfig -> a -> m AllSatResult
+  allSatWith cfg a = do asr <- runWithQuery satArgReduce True (checkNoOptimizations >> Control.getAllSatResult) cfg a
+                        if validationRequested cfg
+                           then do rs' <- mapM (validate satArgReduce True cfg a) (allSatResults asr)
+                                   pure asr{allSatResults = rs'}
+                           else pure asr
+
+  -- | Generalization of 'Data.SBV.isSatisfiable'
+  isSatisfiable :: a -> m Bool
+  isSatisfiable = isSatisfiableWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.isSatisfiableWith'
+  isSatisfiableWith :: SMTConfig -> a -> m Bool
+  isSatisfiableWith cfg p = do r <- satWith cfg p
+                               case r of
+                                 SatResult Satisfiable{}   -> pure True
+                                 SatResult Unsatisfiable{} -> pure False
+                                 _                         -> error $ "SBV.isSatisfiable: Received: " ++ show r
+
+  -- | Generalization of 'Data.SBV.optimize'
+  optimize :: OptimizeStyle -> a -> m OptimizeResult
+  optimize = optimizeWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.optimizeWith'
+  optimizeWith :: SMTConfig -> OptimizeStyle -> a -> m OptimizeResult
+  optimizeWith config style optGoal = do
+                   res <- runWithQuery satArgReduce True opt config optGoal
+                   if not (optimizeValidateConstraints config)
+                      then pure res
+                      else let v :: SMTResult -> m SMTResult
+                               v = validate satArgReduce True config optGoal
+                           in case res of
+                                LexicographicResult m -> LexicographicResult <$> v m
+                                IndependentResult xs  -> let w []            sofar = pure (reverse sofar)
+                                                             w ((n, m):rest) sofar = v m >>= \m' -> w rest ((n, m') : sofar)
+                                                         in IndependentResult <$> w xs []
+                                ParetoResult (b, rs)  -> ParetoResult . (b, ) <$> mapM v rs
+
+    where opt = do mbDirs <- Control.startOptimizer config style
+
+                   case mbDirs of
+                     Nothing   -> error $ unlines [ ""
+                                                  , "*** Data.SBV: Unsupported call to optimize when no objectives are present."
+                                                  , "*** Use \"sat\" for plain satisfaction"
+                                                  ]
+                     Just (objectives, optimizerDirectives) -> do
+                       mapM_ (Control.send True . T.pack) optimizerDirectives
+
+                       case style of
+                         Lexicographic -> LexicographicResult <$> Control.getLexicographicOptResults
+                         Independent   -> IndependentResult   <$> Control.getIndependentOptResults (map objectiveName objectives)
+                         Pareto mbN    -> ParetoResult        <$> Control.getParetoOptResults mbN
+
+-- | Find a satisfying assignment to a property with multiple solvers, running them in separate threads. The
+-- results will be returned in the order produced.
+satWithAll :: Satisfiable a => [SMTConfig] -> a -> IO [(Solver, NominalDiffTime, SatResult)]
+satWithAll = (`sbvWithAll` satWith)
+
+-- | Find a satisfying assignment to a property with multiple solvers, running them in separate threads. Only
+-- the result of the first one to finish will be returned, remaining threads will be killed.
+-- Note that we send an exception to the losing processes, but we do *not* actually wait for them
+-- to finish. In rare cases this can lead to zombie processes. In previous experiments, we found
+-- that some processes take their time to terminate. So, this solution favors quick turnaround.
+satWithAny :: Satisfiable a => [SMTConfig] -> a -> IO (Solver, NominalDiffTime, SatResult)
+satWithAny = (`sbvWithAny` satWith)
+
+-- | Find a satisfying assignment to a property using a single solver, but
+-- providing several query problems of interest, with each query running in a
+-- separate thread and return the first one that returns. This can be useful to
+-- use symbolic mode to drive to a location in the search space of the solver
+-- and then refine the problem in query mode. If the computation is very hard to
+-- solve for the solver than running in concurrent mode may provide a large
+-- performance benefit.
+satConcurrentWithAny :: Satisfiable a => SMTConfig -> [Query b] -> a -> IO (Solver, NominalDiffTime, SatResult)
+satConcurrentWithAny solver qs a = do (slvr,time,result) <- sbvConcurrentWithAny solver go qs a
+                                      pure (slvr, time, SatResult result)
+  where go cfg a' q = runWithQuery satArgReduce True (do _ <- q; checkNoOptimizations >> Control.getSMTResult) cfg a'
+
+-- | Find a satisfying assignment to a property using a single solver, but run
+-- each query problem in a separate isolated thread and wait for each thread to
+-- finish. See 'satConcurrentWithAny' for more details.
+satConcurrentWithAll :: Satisfiable a => SMTConfig -> [Query b] -> a -> IO [(Solver, NominalDiffTime, SatResult)]
+satConcurrentWithAll solver qs a = do results <- sbvConcurrentWithAll solver go qs a
+                                      pure $ (\(a',b,c) -> (a',b,SatResult c)) <$> results
+  where go cfg a' q = runWithQuery satArgReduce True (do _ <- q; checkNoOptimizations >> Control.getSMTResult) cfg a'
+
+-- | A type @a@ is provable if we can turn it into a predicate, i.e., it has to return a boolean.
+-- This class captures essentially prove calls.
+class ExtractIO m => ProvableM m a where
+  -- | Reduce an arg, for proof purposes.
+  proofArgReduce :: a -> SymbolicT m SBool
+
+  -- | Generalization of 'Data.SBV.prove'
+  prove :: a -> m ThmResult
+  prove = proveWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.proveWith'
+  proveWith :: SMTConfig -> a -> m ThmResult
+  proveWith cfg a = do r <- runWithQuery proofArgReduce False (checkNoOptimizations >> Control.getSMTResult) cfg a
+                       ThmResult <$> if validationRequested cfg
+                                     then validate proofArgReduce False cfg a r
+                                     else pure r
+
+  -- | Generalization of 'Data.SBV.dprove'
+  dprove :: a -> m ThmResult
+  dprove = dproveWith defaultDeltaSMTCfg
+
+  -- | Generalization of 'Data.SBV.dproveWith'
+  dproveWith :: SMTConfig -> a -> m ThmResult
+  dproveWith cfg a = do r <- runWithQuery proofArgReduce False (checkNoOptimizations >> Control.getSMTResult) cfg a
+                        ThmResult <$> if validationRequested cfg
+                                      then validate proofArgReduce False cfg a r
+                                      else pure r
+
+  -- | Generalization of 'Data.SBV.isVacuousProof'
+  isVacuousProof :: a -> m Bool
+  isVacuousProof = isVacuousProofWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.isVacuousProofWith'
+  isVacuousProofWith :: SMTConfig -> a -> m Bool
+  isVacuousProofWith cfg a = -- NB. Can't call runWithQuery since last constraint would become the implication!
+       fst <$> runSymbolic cfg (SMTMode QueryInternal ISetup True cfg) (proofArgReduce a >> Control.executeQuery QueryInternal check)
+     where
+       check = do cs <- Control.checkSat
+                  case cs of
+                    Control.Unsat  -> pure True
+                    Control.Sat    -> pure False
+                    Control.DSat{} -> pure False
+                    Control.Unk    -> error "SBV: isVacuous: Solver returned unknown!"
+
+  -- | Generalization of 'Data.SBV.isTheorem'
+  isTheorem :: a -> m Bool
+  isTheorem = isTheoremWith defaultSMTCfg
+
+  -- | Generalization of 'Data.SBV.isTheoremWith'
+  isTheoremWith :: SMTConfig -> a -> m Bool
+  isTheoremWith cfg p = do r <- proveWith cfg p
+                           let bad = error $ "SBV.isTheorem: Received:\n" ++ show r
+                           case r of
+                             ThmResult Unsatisfiable{} -> pure True
+                             ThmResult Satisfiable{}   -> pure False
+                             ThmResult DeltaSat{}      -> pure False
+                             ThmResult SatExtField{}   -> pure False
+                             ThmResult Unknown{}       -> bad
+                             ThmResult ProofError{}    -> bad
+
+-- | Prove a property with multiple solvers, running them in separate threads. Only
+-- the result of the first one to finish will be returned, remaining threads will be killed.
+-- Note that we send an exception to the losing processes, but we do *not* actually wait for them
+-- to finish. In rare cases this can lead to zombie processes. In previous experiments, we found
+-- that some processes take their time to terminate. So, this solution favors quick turnaround.
+proveWithAny :: Provable a => [SMTConfig] -> a -> IO (Solver, NominalDiffTime, ThmResult)
+proveWithAny  = (`sbvWithAny` proveWith)
+
+-- | Prove a property with multiple solvers, running them in separate threads. The
+-- results will be returned in the order produced.
+proveWithAll :: Provable a => [SMTConfig] -> a -> IO [(Solver, NominalDiffTime, ThmResult)]
+proveWithAll  = (`sbvWithAll` proveWith)
+
+-- | Prove a property by running many queries each isolated to their own thread
+-- concurrently and return the first that finishes, killing the others
+proveConcurrentWithAny :: Provable a => SMTConfig -> [Query b] -> a -> IO (Solver, NominalDiffTime, ThmResult)
+proveConcurrentWithAny solver qs a = do (slvr,time,result) <- sbvConcurrentWithAny solver go qs a
+                                        pure (slvr, time, ThmResult result)
+  where go cfg a' q = runWithQuery proofArgReduce False (do _ <- q;  checkNoOptimizations >> Control.getSMTResult) cfg a'
+
+-- | Prove a property by running many queries each isolated to their own thread
+-- concurrently and wait for each to finish returning all results
+proveConcurrentWithAll :: Provable a => SMTConfig -> [Query b] -> a -> IO [(Solver, NominalDiffTime, ThmResult)]
+proveConcurrentWithAll solver qs a = do results <- sbvConcurrentWithAll solver go qs a
+                                        pure $ (\(a',b,c) -> (a',b,ThmResult c)) <$> results
+  where go cfg a' q = runWithQuery proofArgReduce False (do _ <- q; checkNoOptimizations >> Control.getSMTResult) cfg a'
+
+-- | Validate a model obtained from the solver
+validate :: MonadIO m => (a -> SymbolicT m SBool) -> Bool -> SMTConfig -> a -> SMTResult -> m SMTResult
+validate reducer isSAT cfg p res =
+     case res of
+       Unsatisfiable{} -> pure res
+       Satisfiable _ m -> case modelBindings m of
+                            Nothing  -> error "Data.SBV.validate: Impossible happened; no bindings generated during model validation."
+                            Just env -> check env
+
+       DeltaSat {}     -> cant [ "The model is delta-satisfiable."
+                               , "Cannot validate delta-satisfiable models."
+                               ]
+
+       SatExtField{}   -> cant [ "The model requires an extension field value."
+                               , "Cannot validate models with infinities/epsilons produced during optimization."
+                               , ""
+                               , "To turn validation off, use `cfg{optimizeValidateConstraints = False}`"
+                               ]
+
+       Unknown{}       -> pure res
+       ProofError{}    -> pure res
+
+  where cant msg = pure $ ProofError cfg (msg ++ [ ""
+                                                   , "Unable to validate the produced model."
+                                                   ]) (Just res)
+
+        check env = do let envShown = showModelDictionary True True cfg modelBinds
+                              where modelBinds = [(T.unpack n, RegularCV v) | (NamedSymVar _ n, v) <- env]
+
+                           notify s
+                             | not (verbose cfg) = pure ()
+                             | True              = debug cfg ["[VALIDATE] " `alignPlain` T.pack s]
+
+                       notify $ "Validating the model. " ++ if null env then "There are no assignments." else "Assignment:"
+                       mapM_ notify ["    " ++ l | l <- lines envShown]
+
+                       result <- snd <$> runSymbolic cfg (Concrete (Just (isSAT, env))) (reducer p >>= output)
+
+                       let explain  = [ ""
+                                      , "Assignment:"  ++ if null env then " <none>" else ""
+                                      ]
+                                   ++ [ ""          | not (null env)]
+                                   ++ [ "    " ++ l | l <- lines envShown]
+                                   ++ [ "" ]
+
+                           wrap tag extras = pure $ 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)
+                                                 )
+                                where perhaps Nothing  = case resObservables result of
+                                                           [] -> []
+                                                           xs -> [ "There are observable values in the model: " ++ unwords [show n | (n, _, _) <- xs]
+                                                                 , "SBV cannot validate in the presence of observables, unfortunately."
+                                                                 , "Try validation after removing calls to 'observe'."
+                                                                 ]
+
+                                      perhaps (Just x) = [ x
+                                                         , ""
+                                                         , "SBV's model validator is incomplete, and cannot handle this particular case."
+                                                         , "Please report this as a feature request or possibly a bug!"
+                                                         ]
+
+                                      -- 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
+                                                                        QuantifiedBool{} -> Just "The value depends on a quantified variable."
+                                                                        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."
+                                                                        Uninterpreted v
+                                                                          | any isADT as -> Just "Models containing ADTs are currently only partially supported."
+                                                                          | True         -> Just $ "The value depends on the uninterpreted constant " ++ T.unpack v ++ "."
+                                                                        _                -> 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."
+                                  pure 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."
+                                                    pure 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))
+
+-- | Given a satisfiability problem, extract the function definitions in it
+defs2smt :: SatisfiableM m a => a -> m String
+defs2smt = generateSMTBenchMarkGen True satArgReduce defs
+  where defs (SMTLibPgm _ _ ds) = T.unpack ds
+
+-- | Create an SMT-Lib2 benchmark, for a SAT query.
+generateSMTBenchmarkSat :: SatisfiableM m a => a -> m String
+generateSMTBenchmarkSat = generateSMTBenchMarkGen True satArgReduce (\p -> show p ++ "\n(check-sat)\n")
+
+-- | Create an SMT-Lib2 benchmark, for a Proof query.
+generateSMTBenchmarkProof :: ProvableM m a => a -> m String
+generateSMTBenchmarkProof = generateSMTBenchMarkGen False proofArgReduce (\p -> show p ++ "\n(check-sat)\n")
+
+-- | Generic benchmark creator
+generateSMTBenchMarkGen :: MonadIO m => Bool -> (a -> SymbolicT m SBool) -> (SMTLibPgm -> b) -> a -> m b
+generateSMTBenchMarkGen isSat reduce render a = do
+      t <- liftIO getZonedTime
+
+      let comments = ["Automatically created by SBV on " ++ show t]
+          cfg      = defaultSMTCfg { smtLibVersion = SMTLib2 }
+
+      (_, res) <- runSymbolic cfg (SMTMode QueryInternal ISetup isSat cfg) $ reduce a >>= output
+
+      let SMTProblem{smtLibPgm} = Control.runProofOn (SMTMode QueryInternal IRun isSat cfg) QueryInternal comments res
+
+      pure $ render (smtLibPgm cfg)
+
+checkNoOptimizations :: MonadIO m => QueryT m ()
+checkNoOptimizations = do objectives <- Control.getObjectives
+
+                          unless (null objectives) $
+                                error $ unlines [ ""
+                                                , "*** Data.SBV: Unsupported call sat/prove when optimization objectives are present."
+                                                , "*** Use \"optimize\"/\"optimizeWith\" to calculate optimal satisfaction!"
+                                                ]
+
+instance ExtractIO m => SatisfiableM m (SymbolicT m ()) where satArgReduce a = satArgReduce ((a >> pure sTrue) :: SymbolicT m SBool)
+-- instance ExtractIO m => ProvableM m (SymbolicT m ())  -- NO INSTANCE ON PURPOSE; don't want to prove goals
+
+instance ExtractIO m => SatisfiableM m (SymbolicT m SBool) where satArgReduce   = id
+instance ExtractIO m => ProvableM    m (SymbolicT m SBool) where proofArgReduce = id
+
+instance ExtractIO m => SatisfiableM m SBool where satArgReduce   = pure
+instance ExtractIO m => ProvableM    m SBool where proofArgReduce = pure
+
+instance {-# OVERLAPPABLE #-} (ExtractIO m, SatisfiableM m a) => SatisfiableM m (SymbolicT m a) where satArgReduce   a = a >>= satArgReduce
+instance {-# OVERLAPPABLE #-} (ExtractIO m, ProvableM    m a) => ProvableM    m (SymbolicT m a) where proofArgReduce a = a >>= proofArgReduce
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, SatisfiableM m r) => SatisfiableM m (Forall nm a -> r) where
+  satArgReduce = satArgReduce . quantifiedBool
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, ProvableM m r) => ProvableM m (Forall nm a -> r) where
+  proofArgReduce = proofArgReduce . quantifiedBool
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, SatisfiableM m r) => SatisfiableM m (Exists nm a -> r) where
+  satArgReduce = satArgReduce . quantifiedBool
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, SatisfiableM m r, EqSymbolic (SBV a)) => SatisfiableM m (ExistsUnique nm a -> r) where
+  satArgReduce = satArgReduce . quantifiedBool
+
+instance (KnownNat n, ExtractIO m, SymVal a, Constraint Symbolic r, ProvableM m r) => ProvableM m (ForallN n nm a -> r) where
+  proofArgReduce = proofArgReduce . quantifiedBool
+
+instance (KnownNat n, ExtractIO m, SymVal a, Constraint Symbolic r, SatisfiableM m r) => SatisfiableM m (ExistsN n nm a -> r) where
+  satArgReduce = satArgReduce . quantifiedBool
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, ProvableM m r) => ProvableM m (Exists nm a -> r) where
+  proofArgReduce = proofArgReduce . quantifiedBool
+
+instance (ExtractIO m, SymVal a, Constraint Symbolic r, ProvableM m r, EqSymbolic (SBV a)) => ProvableM m (ExistsUnique nm a -> r) where
+  proofArgReduce = proofArgReduce . quantifiedBool
+
+instance (KnownNat n, ExtractIO m, SymVal a, Constraint Symbolic r, SatisfiableM m r) => SatisfiableM m (ForallN n nm a -> r) where
+  satArgReduce = satArgReduce . quantifiedBool
+
+instance (KnownNat n, ExtractIO m, SymVal a, Constraint Symbolic r, ProvableM m r) => ProvableM m (ExistsN n nm a -> r) where
+  proofArgReduce = proofArgReduce . quantifiedBool
+
+{-
+-- The following is a possible definition, but it lets us write properties that
+-- are not useful.. Such as: prove $ \x y -> (x::SInt8) == y
+-- Running that will throw an exception since Haskell's equality is not be supported by symbolic things. (Needs .==).
+-- So, we avoid these instances.
+instance ExtractIO m => ProvableM m Bool where
+  proofArgReduce x  = proofArgReduce (if x then sTrue else sFalse :: SBool)
+
+instance ExtractIO m => SatisfiableM m Bool where
+  satArgReduce x  = satArgReduce (if x then sTrue else sFalse :: SBool)
+-}
+
+-- | Create an argument
+mkArg :: (SymVal a, MonadSymbolic m) => m (SBV a)
+mkArg = mkSymVal (NonQueryVar Nothing) Nothing
+
+-- Functions
+instance (SymVal a, SatisfiableM m p) => SatisfiableM m (SBV a -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ fn a
+
+instance (SymVal a, ProvableM m p) => ProvableM m (SBV a -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ fn a
+
+-- | Create an 'SBVs' sequence of arguments
+mkArgs :: MonadSymbolic m => SymValInsts as -> m (SBVs as)
+mkArgs SymValsNil = pure SBVsNil
+mkArgs (SymValsCons insts) = SBVsCons <$> mkArgs insts <*> mkArg
+
+-- Multi-arity Functions
+instance (SymVals as, SatisfiableM m p) => SatisfiableM m (SBVs as -> p) where
+  satArgReduce fn = mkArgs symValInsts >>= \args -> satArgReduce $ fn args
+
+instance (SymVals as, ProvableM m p) => ProvableM m (SBVs as -> p) where
+  proofArgReduce fn = mkArgs symValInsts >>= \args -> proofArgReduce $ fn args
+
+-- 2 Tuple
+instance (SymVal a, SymVal b, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b -> fn (a, b)
+
+instance (SymVal a, SymVal b, ProvableM m p) => ProvableM m ((SBV a, SBV b) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b -> fn (a, b)
+
+-- 3 Tuple
+instance (SymVal a, SymVal b, SymVal c, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c -> fn (a, b, c)
+
+instance (SymVal a, SymVal b, SymVal c, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c -> fn (a, b, c)
+
+-- 4 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d) -> p) where
+  satArgReduce fn = mkArg  >>= \a -> satArgReduce $ \b c d -> fn (a, b, c, d)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d) -> p) where
+  proofArgReduce fn = mkArg  >>= \a -> proofArgReduce $ \b c d -> fn (a, b, c, d)
+
+-- 5 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e -> fn (a, b, c, d, e)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e -> fn (a, b, c, d, e)
+
+-- 6 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f -> fn (a, b, c, d, e, f)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f -> fn (a, b, c, d, e, f)
+
+-- 7 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g -> fn (a, b, c, d, e, f, g)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g -> fn (a, b, c, d, e, f, g)
+
+-- 8 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g h -> fn (a, b, c, d, e, f, g, h)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g h -> fn (a, b, c, d, e, f, g, h)
+
+-- 9 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g h i -> fn (a, b, c, d, e, f, g, h, i)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g h i -> fn (a, b, c, d, e, f, g, h, i)
+
+-- 10 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g h i j -> fn (a, b, c, d, e, f, g, h, i, j)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g h i j -> fn (a, b, c, d, e, f, g, h, i, j)
+
+-- 11 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, SymVal k, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j, SBV k) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g h i j k -> fn (a, b, c, d, e, f, g, h, i, j, k)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, SymVal k, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j, SBV k) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g h i j k -> fn (a, b, c, d, e, f, g, h, i, j, k)
+
+-- 12 Tuple
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, SymVal k, SymVal l, SatisfiableM m p) => SatisfiableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j, SBV k, SBV l) -> p) where
+  satArgReduce fn = mkArg >>= \a -> satArgReduce $ \b c d e f g h i j k l -> fn (a, b, c, d, e, f, g, h, i, j, k, l)
+
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h, SymVal i, SymVal j, SymVal k, SymVal l, ProvableM m p) => ProvableM m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h, SBV i, SBV j, SBV k, SBV l) -> p) where
+  proofArgReduce fn = mkArg >>= \a -> proofArgReduce $ \b c d e f g h i j k l -> fn (a, b, c, d, e, f, g, h, i, j, k, l)
+
+-- | Generalization of 'Data.SBV.runSMT'
+runSMT :: MonadIO m => SymbolicT m a -> m a
+runSMT = runSMTWith defaultSMTCfg
+
+-- | Generalization of 'Data.SBV.runSMTWith'
+runSMTWith :: MonadIO m => SMTConfig -> SymbolicT m a -> m a
+runSMTWith cfg a = fst <$> runSymbolic cfg (SMTMode QueryExternal ISetup True cfg) a
+
+-- | Runs with a query.
+runWithQuery :: ExtractIO m => (a -> SymbolicT m SBool) -> Bool -> QueryT m b -> SMTConfig -> a -> m b
+runWithQuery reducer isSAT q cfg a = fst <$> runSymbolic cfg (SMTMode QueryInternal ISetup isSAT cfg) comp
+  where comp =  do _ <- reducer a >>= output
+                   Control.executeQuery QueryInternal q
+
+-- | Check if a safe-call was safe or not, turning a t'SafeResult' to a Bool.
+isSafe :: SafeResult -> Bool
+isSafe (SafeResult (_, _, result)) = case result of
+                                       Unsatisfiable{} -> True
+                                       Satisfiable{}   -> False
+                                       DeltaSat{}      -> False   -- conservative
+                                       SatExtField{}   -> False   -- conservative
+                                       Unknown{}       -> False   -- conservative
+                                       ProofError{}    -> False   -- conservative
+
+-- | Perform an action asynchronously, returning results together with diff-time.
+runInThread :: NFData b => UTCTime -> (SMTConfig -> IO b) -> SMTConfig -> IO (Async (Solver, NominalDiffTime, b))
+runInThread beginTime action config = async $ do
+                result  <- action config
+                endTime <- rnf result `seq` getCurrentTime
+                pure (name (solver config), endTime `diffUTCTime` beginTime, result)
+
+-- | Perform action for all given configs, return the first one that wins. Note that we do
+-- not wait for the other asyncs to terminate; hopefully they'll do so quickly.
+sbvWithAny :: NFData b => [SMTConfig] -> (SMTConfig -> a -> IO b) -> a -> IO (Solver, NominalDiffTime, b)
+sbvWithAny []      _    _ = error "SBV.withAny: No solvers given!"
+sbvWithAny solvers what a = do beginTime <- getCurrentTime
+                               snd <$> (mapM (runInThread beginTime (`what` a)) solvers >>= waitAnyFastCancel)
+   where -- Async's `waitAnyCancel` nicely blocks; so we use this variant to ignore the
+         -- wait part for killed threads.
+         waitAnyFastCancel asyncs = waitAny asyncs `finally` mapM_ cancelFast asyncs
+         cancelFast other = throwTo (asyncThreadId other) ExitSuccess
+
+
+sbvConcurrentWithAny :: NFData c => SMTConfig -> (SMTConfig -> a -> QueryT m b -> IO c) -> [QueryT m b] -> a -> IO (Solver, NominalDiffTime, c)
+sbvConcurrentWithAny solver what queries a = snd <$> (mapM runQueryInThread queries >>= waitAnyFastCancel)
+  where  -- Async's `waitAnyCancel` nicely blocks; so we use this variant to ignore the
+         -- wait part for killed threads.
+         waitAnyFastCancel asyncs = waitAny asyncs `finally` mapM_ cancelFast asyncs
+         cancelFast other = throwTo (asyncThreadId other) ExitSuccess
+         runQueryInThread q = do beginTime <- getCurrentTime
+                                 runInThread beginTime (\cfg -> what cfg a q) solver
+
+
+sbvConcurrentWithAll :: NFData c => SMTConfig -> (SMTConfig -> a -> QueryT m b -> IO c) -> [QueryT m b] -> a -> IO [(Solver, NominalDiffTime, c)]
+sbvConcurrentWithAll solver what queries a = mapConcurrently runQueryInThread queries  >>= unsafeInterleaveIO . go
+  where  runQueryInThread q = do beginTime <- getCurrentTime
+                                 runInThread beginTime (\cfg -> what cfg a q) solver
+
+         go []  = pure []
+         go as  = do (d, r) <- waitAny as
+                     -- The following filter works because the Eq instance on Async
+                     -- checks the thread-id; so we know that we're removing the
+                     -- correct solver from the list. This also allows for
+                     -- running the same-solver (with different options), since
+                     -- they will get different thread-ids.
+                     rs <- unsafeInterleaveIO $ go (filter (/= d) as)
+                     pure (r : rs)
+
+-- | Perform action for all given configs, return all the results.
+sbvWithAll :: NFData b => [SMTConfig] -> (SMTConfig -> a -> IO b) -> a -> IO [(Solver, NominalDiffTime, b)]
+sbvWithAll solvers what a = do beginTime <- getCurrentTime
+                               mapM (runInThread beginTime (`what` a)) solvers >>= (unsafeInterleaveIO . go)
+   where go []  = pure []
+         go as  = do (d, r) <- waitAny as
+                     -- The following filter works because the Eq instance on Async
+                     -- checks the thread-id; so we know that we're removing the
+                     -- correct solver from the list. This also allows for
+                     -- running the same-solver (with different options), since
+                     -- they will get different thread-ids.
+                     rs <- unsafeInterleaveIO $ go (filter (/= d) as)
+                     pure (r : rs)
+
+-- | Symbolically executable program fragments. This class is mainly used for 'safe' calls, and is sufficiently populated internally to cover most use
+-- cases. Users can extend it as they wish to allow 'safe' checks for SBV programs that return/take types that are user-defined.
+class ExtractIO m => SExecutable m a where
+   -- | Generalization of 'Data.SBV.sName'
+   sName :: a -> SymbolicT m ()
+
+   -- | Generalization of 'Data.SBV.safe'
+   safe :: a -> m [SafeResult]
+   safe = safeWith defaultSMTCfg
+
+   -- | Generalization of 'Data.SBV.safeWith'
+   safeWith :: SMTConfig -> a -> m [SafeResult]
+   safeWith cfg a = do cwd <- (++ "/") <$> liftIO getCurrentDirectory
+                       let mkRelative path
+                              | cwd `isPrefixOf` path = drop (length cwd) path
+                              | True                  = path
+                       fst <$> runSymbolic cfg (SMTMode QueryInternal ISafe True cfg) (sName a >> check mkRelative)
+     where check :: (FilePath -> FilePath) -> SymbolicT m [SafeResult]
+           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
+           verify :: (FilePath -> FilePath) -> (String, Maybe CallStack, SV) -> QueryT m SafeResult
+           verify mkRelative (msg, cs, cond) = do
+                   let locInfo ps = let loc (f, sl) = concat [mkRelative (srcLocFile sl), ":", show (srcLocStartLine sl), ":", show (srcLocStartCol sl), ":", f]
+                                    in intercalate ",\n " (map loc ps)
+                       location   = locInfo . getCallStack <$> cs
+
+                   result <- do Control.push 1
+                                Control.send True $ "(assert " <> showText cond <> ")"
+                                r <- Control.getSMTResult
+                                Control.pop 1
+                                pure r
+
+                   pure $ SafeResult (location, msg, result)
+
+instance (ExtractIO m, NFData a) => SExecutable m (SymbolicT m a) where
+   sName a = a >>= \r -> rnf r `seq` pure ()
+
+instance ExtractIO m => SExecutable m (SBV a) where
+   sName v = sName (output v :: SymbolicT m (SBV a))
+
+-- Unit output
+instance ExtractIO m => SExecutable m () where
+   sName () = sName (output () :: SymbolicT m ())
+
+-- List output
+instance ExtractIO m => SExecutable m [SBV a] where
+   sName vs = sName (output vs :: SymbolicT m [SBV a])
+
+-- 2 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b) => SExecutable m (SBV a, SBV b) where
+  sName (a, b) = sName (output a >> output b :: SymbolicT m (SBV b))
+
+-- 3 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b, NFData c, SymVal c) => SExecutable m (SBV a, SBV b, SBV c) where
+  sName (a, b, c) = sName (output a >> output b >> output c :: SymbolicT m (SBV c))
+
+-- 4 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b, NFData c, SymVal c, NFData d, SymVal d) => SExecutable m (SBV a, SBV b, SBV c, SBV d) where
+  sName (a, b, c, d) = sName (output a >> output b >> output c >> output c >> output d :: SymbolicT m (SBV d))
+
+-- 5 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b, NFData c, SymVal c, NFData d, SymVal d, NFData e, SymVal e) => SExecutable m (SBV a, SBV b, SBV c, SBV d, SBV e) where
+  sName (a, b, c, d, e) = sName (output a >> output b >> output c >> output d >> output e :: SymbolicT m (SBV e))
+
+-- 6 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b, NFData c, SymVal c, NFData d, SymVal d, NFData e, SymVal e, NFData f, SymVal f) => SExecutable m (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) where
+  sName (a, b, c, d, e, f) = sName (output a >> output b >> output c >> output d >> output e >> output f :: SymbolicT m (SBV f))
+
+-- 7 Tuple output
+instance (ExtractIO m, NFData a, SymVal a, NFData b, SymVal b, NFData c, SymVal c, NFData d, SymVal d, NFData e, SymVal e, NFData f, SymVal f, NFData g, SymVal g) => SExecutable m (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) where
+  sName (a, b, c, d, e, f, g) = sName (output a >> output b >> output c >> output d >> output e >> output f >> output g :: SymbolicT m (SBV g))
+
+-- Functions
+instance (SymVal a, SExecutable m p) => SExecutable m (SBV a -> p) where
+   sName k = mkArg >>= \a -> sName $ k a
+
+-- 2 Tuple input
+instance (SymVal a, SymVal b, SExecutable m p) => SExecutable m ((SBV a, SBV b) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b -> k (a, b)
+
+-- 3 Tuple input
+instance (SymVal a, SymVal b, SymVal c, SExecutable m p) => SExecutable m ((SBV a, SBV b, SBV c) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b c -> k (a, b, c)
+
+-- 4 Tuple input
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SExecutable m p) => SExecutable m ((SBV a, SBV b, SBV c, SBV d) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b c d -> k (a, b, c, d)
+
+-- 5 Tuple input
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SExecutable m p) => SExecutable m ((SBV a, SBV b, SBV c, SBV d, SBV e) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b c d e -> k (a, b, c, d, e)
+
+-- 6 Tuple input
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SExecutable m p) => SExecutable m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b c d e f -> k (a, b, c, d, e, f)
+
+-- 7 Tuple input
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SExecutable m p) => SExecutable m ((SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) -> p) where
+  sName k = mkArg >>= \a -> sName $ \b c d e f g -> k (a, b, c, d, e, f, g)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/Provers/SExpr.hs b/Data/SBV/Provers/SExpr.hs
deleted file mode 100644
--- a/Data/SBV/Provers/SExpr.hs
+++ /dev/null
@@ -1,179 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Provers.SExpr
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Parsing of S-expressions (mainly used for parsing SMT-Lib get-value output)
------------------------------------------------------------------------------
-
-module Data.SBV.Provers.SExpr where
-
-import Data.Bits           (setBit, testBit)
-import Data.Word           (Word32, Word64)
-import Data.Char           (isDigit, ord)
-import Data.List           (isPrefixOf)
-import Data.Maybe          (fromMaybe, listToMaybe)
-import Numeric             (readInt, readDec, readHex, fromRat)
-import Data.Binary.IEEE754 (wordToFloat, wordToDouble)
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data (nan, infinity, RoundingMode(..))
-
--- | ADT S-Expression format, suitable for representing get-model output of SMT-Lib
-data SExpr = ECon    String
-           | ENum    (Integer, Maybe Int)  -- Second argument is how wide the field was in bits, if known. Useful in FP parsing.
-           | EReal   AlgReal
-           | EFloat  Float
-           | EDouble Double
-           | EApp    [SExpr]
-           deriving Show
-
--- | Parse a string into an SExpr, potentially failing with an error message
-parseSExpr :: String -> Either String SExpr
-parseSExpr inp = do (sexp, extras) <- parse inpToks
-                    if null extras
-                       then return sexp
-                       else die "Extra tokens after valid input"
-  where inpToks = let cln ""          sofar = sofar
-                      cln ('(':r)     sofar = cln r (" ( " ++ sofar)
-                      cln (')':r)     sofar = cln r (" ) " ++ sofar)
-                      cln (':':':':r) sofar = cln r (" :: " ++ sofar)
-                      cln (c:r)       sofar = cln r (c:sofar)
-                  in reverse (map reverse (words (cln inp "")))
-        die w = fail $  "SBV.Provers.SExpr: Failed to parse S-Expr: " ++ w
-                     ++ "\n*** Input : <" ++ inp ++ ">"
-        parse []         = die "ran out of tokens"
-        parse ("(":toks) = do (f, r) <- parseApp toks []
-                              f' <- cvt (EApp f)
-                              return (f', r)
-        parse (")":_)    = die "extra tokens after close paren"
-        parse [tok]      = do t <- pTok tok
-                              return (t, [])
-        parse _          = die "ill-formed s-expr"
-        parseApp []         _     = die "failed to grab s-expr application"
-        parseApp (")":toks) sofar = return (reverse sofar, toks)
-        parseApp ("(":toks) sofar = do (f, r) <- parse ("(":toks)
-                                       parseApp r (f : sofar)
-        parseApp (tok:toks) sofar = do t <- pTok tok
-                                       parseApp toks (t : sofar)
-        pTok "false"              = return $ ENum (0, Nothing)
-        pTok "true"               = return $ ENum (1, Nothing)
-        pTok ('0':'b':r)          = mkNum (Just (length r))     $ readInt 2 (`elem` "01") (\c -> ord c - ord '0') r
-        pTok ('b':'v':r)          = mkNum Nothing               $ readDec (takeWhile (/= '[') r)
-        pTok ('#':'b':r)          = mkNum (Just (length r))     $ readInt 2 (`elem` "01") (\c -> ord c - ord '0') r
-        pTok ('#':'x':r)          = mkNum (Just (4 * length r)) $ readHex r
-        pTok n
-          | not (null n) && isDigit (head n)
-          = if '.' `elem` n then getReal n
-            else mkNum Nothing $ readDec n
-        pTok n                 = return $ ECon (constantMap n)
-        mkNum l [(n, "")] = return $ ENum (n, l)
-        mkNum _ _         = die "cannot read number"
-        getReal n = return $ EReal $ mkPolyReal (Left (exact, n'))
-          where exact = not ("?" `isPrefixOf` reverse n)
-                n' | exact = n
-                   | True  = init n
-        -- simplify numbers and root-obj values
-        cvt (EApp [ECon "/", EReal a, EReal b])                    = return $ EReal (a / b)
-        cvt (EApp [ECon "/", EReal a, ENum  b])                    = return $ EReal (a                   / fromInteger (fst b))
-        cvt (EApp [ECon "/", ENum  a, EReal b])                    = return $ EReal (fromInteger (fst a) /             b      )
-        cvt (EApp [ECon "/", ENum  a, ENum  b])                    = return $ EReal (fromInteger (fst a) / fromInteger (fst b))
-        cvt (EApp [ECon "-", EReal a])                             = return $ EReal (-a)
-        cvt (EApp [ECon "-", ENum a])                              = return $ ENum  (-(fst a), snd a)
-        -- bit-vector value as CVC4 prints: (_ bv0 16) for instance
-        cvt (EApp [ECon "_", ENum a, ENum _b])                     = return $ ENum a
-        cvt (EApp [ECon "root-obj", EApp (ECon "+":trms), ENum k]) = do ts <- mapM getCoeff trms
-                                                                        return $ EReal $ mkPolyReal (Right (fst k, ts))
-        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum (11, _), ENum (53, _)]]) = getDouble n
-        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum ( 8, _), ENum (24, _)]]) = getFloat  n
-        cvt (EApp [ECon "as", n, ECon "Float64"])                                                    = getDouble n
-        cvt (EApp [ECon "as", n, ECon "Float32"])                                                    = getFloat  n
-        -- NB. Note the lengths on the mantissa for the following two are 23/52; not 24/53!
-        cvt (EApp [ECon "fp",    ENum (s, Just 1), ENum ( e, Just 8),  ENum (m, Just 23)])           = return $ EFloat  $ getTripleFloat  s e m
-        cvt (EApp [ECon "fp",    ENum (s, Just 1), ENum ( e, Just 11), ENum (m, Just 52)])           = return $ EDouble $ getTripleDouble s e m
-        cvt (EApp [ECon "_",     ECon "NaN",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  nan
-        cvt (EApp [ECon "_",     ECon "NaN",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble nan
-        cvt (EApp [ECon "_",     ECon "+oo",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  infinity
-        cvt (EApp [ECon "_",     ECon "+oo",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble infinity
-        cvt (EApp [ECon "_",     ECon "-oo",       ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  (-infinity)
-        cvt (EApp [ECon "_",     ECon "-oo",       ENum (11, _),       ENum (53,      _)])           = return $ EDouble (-infinity)
-        cvt (EApp [ECon "_",     ECon "+zero",     ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  0
-        cvt (EApp [ECon "_",     ECon "+zero",     ENum (11, _),       ENum (53,      _)])           = return $ EDouble 0
-        cvt (EApp [ECon "_",     ECon "-zero",     ENum ( 8, _),       ENum (24,      _)])           = return $ EFloat  (-0)
-        cvt (EApp [ECon "_",     ECon "-zero",     ENum (11, _),       ENum (53,      _)])           = return $ EDouble (-0)
-        cvt x                                                                                        = return x
-        getCoeff (EApp [ECon "*", ENum k, EApp [ECon "^", ECon "x", ENum p]]) = return (fst k, fst p)  -- kx^p
-        getCoeff (EApp [ECon "*", ENum k,                 ECon "x"        ] ) = return (fst k,     1)  -- kx
-        getCoeff (                        EApp [ECon "^", ECon "x", ENum p] ) = return (    1, fst p)  --  x^p
-        getCoeff (                                        ECon "x"          ) = return (    1,     1)  --  x
-        getCoeff (                ENum k                                    ) = return (fst k,     0)  -- k
-        getCoeff x = die $ "Cannot parse a root-obj,\nProcessing term: " ++ show x
-        getDouble (ECon s)  = case (s, rdFP (dropWhile (== '+') s)) of
-                                ("plusInfinity",  _     ) -> return $ EDouble infinity
-                                ("minusInfinity", _     ) -> return $ EDouble (-infinity)
-                                ("oo",            _     ) -> return $ EDouble infinity
-                                ("-oo",           _     ) -> return $ EDouble (-infinity)
-                                ("zero",          _     ) -> return $ EDouble 0
-                                ("-zero",         _     ) -> return $ EDouble (-0)
-                                ("NaN",           _     ) -> return $ EDouble nan
-                                (_,               Just v) -> return $ EDouble v
-                                _               -> die $ "Cannot parse a double value from: " ++ s
-        getDouble (EApp [_, s, _, _]) = getDouble s
-        getDouble (EReal r) = return $ EDouble $ fromRat $ toRational r
-        getDouble x         = die $ "Cannot parse a double value from: " ++ show x
-        getFloat (ECon s)   = case (s, rdFP (dropWhile (== '+') s)) of
-                                ("plusInfinity",  _     ) -> return $ EFloat infinity
-                                ("minusInfinity", _     ) -> return $ EFloat (-infinity)
-                                ("oo",            _     ) -> return $ EFloat infinity
-                                ("-oo",           _     ) -> return $ EFloat (-infinity)
-                                ("zero",          _     ) -> return $ EFloat 0
-                                ("-zero",         _     ) -> return $ EFloat (-0)
-                                ("NaN",           _     ) -> return $ EFloat nan
-                                (_,               Just v) -> return $ EFloat v
-                                _               -> die $ "Cannot parse a float value from: " ++ s
-        getFloat (EReal r)  = return $ EFloat $ fromRat $ toRational r
-        getFloat (EApp [_, s, _, _]) = getFloat s
-        getFloat x          = die $ "Cannot parse a float value from: " ++ show x
-
--- | Parses the Z3 floating point formatted numbers like so: 1.321p5/1.2123e9 etc.
-rdFP :: (Read a, RealFloat a) => String -> Maybe a
-rdFP s = case break (`elem` "pe") s of
-           (m, 'p':e) -> rd m >>= \m' -> rd e >>= \e' -> return $ m' * ( 2 ** e')
-           (m, 'e':e) -> rd m >>= \m' -> rd e >>= \e' -> return $ m' * (10 ** e')
-           (m, "")    -> rd m
-           _          -> Nothing
- where rd v = case reads v of
-                [(n, "")] -> Just n
-                _         -> Nothing
-
--- | Convert an (s, e, m) triple to a float value
-getTripleFloat :: Integer -> Integer -> Integer -> Float
-getTripleFloat s e m = wordToFloat w32
-  where sign      = [s == 1]
-        expt      = [e `testBit` i | i <- [ 7,  6 .. 0]]
-        mantissa  = [m `testBit` i | i <- [22, 21 .. 0]]
-        positions = [i | (i, b) <- zip [31, 30 .. 0] (sign ++ expt ++ mantissa), b]
-        w32       = foldr (flip setBit) (0::Word32) positions
-
--- | Convert an (s, e, m) triple to a float value
-getTripleDouble :: Integer -> Integer -> Integer -> Double
-getTripleDouble s e m = wordToDouble w64
-  where sign      = [s == 1]
-        expt      = [e `testBit` i | i <- [10,  9 .. 0]]
-        mantissa  = [m `testBit` i | i <- [51, 50 .. 0]]
-        positions = [i | (i, b) <- zip [63, 62 .. 0] (sign ++ expt ++ mantissa), b]
-        w64       = foldr (flip setBit) (0::Word64) positions
-
--- | Special constants of SMTLib2 and their internal translation. Mainly
--- rounding modes for now.
-constantMap :: String -> String
-constantMap n = fromMaybe n (listToMaybe [to | (from, to) <- special, n `elem` from])
- where special = [ (["RNE", "roundNearestTiesToEven"], show RoundNearestTiesToEven)
-                 , (["RNA", "roundNearestTiesToAway"], show RoundNearestTiesToAway)
-                 , (["RTP", "roundTowardPositive"],    show RoundTowardPositive)
-                 , (["RTN", "roundTowardNegative"],    show RoundTowardNegative)
-                 , (["RTZ", "roundTowardZero"],        show RoundTowardZero)
-                 ]
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,45 +1,51 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.Yices
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.Yices
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the Yices SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.Yices(yices) where
 
-import Data.SBV.BitVectors.Data
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
 
 -- | The description of the Yices SMT solver
 -- The default executable is @\"yices-smt2\"@, which must be in your path. You can use the @SBV_YICES@ environment variable to point to the executable on your system.
--- SBV does not pass any arguments to yices. You can use the @SBV_YICES_OPTIONS@ environment variable to override the options.
+-- You can use the @SBV_YICES_OPTIONS@ environment variable to override the options.
 yices :: SMTSolver
 yices = SMTSolver {
            name         = Yices
          , executable   = "yices-smt2"
-         , options      = []
-         , engine       = standardEngine "SBV_YICES" "SBV_YICES_OPTIONS" addTimeOut standardModel
+         , preprocess   = id
+         , options      = const ["--incremental"]
+         , engine       = standardEngine "SBV_YICES" "SBV_YICES_OPTIONS"
          , capabilities = SolverCapabilities {
-                                capSolverName              = "Yices"
-                              , mbDefaultLogic             = logic
-                              , supportsMacros             = True
-                              , supportsProduceModels      = True
-                              , supportsQuantifiers        = False
-                              , supportsUninterpretedSorts = True
-                              , supportsUnboundedInts      = True
-                              , supportsReals              = True
-                              , supportsFloats             = False
-                              , supportsDoubles            = False
+                                supportsQuantifiers     = False
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = False
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = False
+                              , supportsSets            = False
+                              , supportsOptimization    = False
+                              , supportsPseudoBooleans  = False
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = False
+                              , supportsLambdas         = False
+                              , supportsSpecialRels     = False
+                              , supportsDirectTesters   = False
+                              , supportsFlattenedModels = Nothing
                               }
          }
-  where addTimeOut _ _ = error "Yices: Timeout values are not supported by Yices"
-        -- Yices doesn't like it if we don't set the logic; so pick one and hope for the best
-        logic hasReals
-          | hasReals   = Just "QF_UFLRA"
-          | True       = Just "QF_AUFLIA"
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,106 +1,57 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Provers.Z3
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Provers.Z3
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- The connection to the Z3 SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
 
 module Data.SBV.Provers.Z3(z3) where
 
-import qualified Control.Exception as C
-
-import Data.Char          (toLower)
-import Data.Function      (on)
-import Data.List          (sortBy, intercalate, groupBy)
-import System.Environment (getEnv)
-import qualified System.Info as S(os)
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum
+import Data.SBV.Core.Data
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
--- Choose the correct prefix character for passing options
--- TBD: Is there a more foolproof way of determining this?
-optionPrefix :: Char
-optionPrefix
-  | map toLower S.os `elem` ["linux", "darwin"] = '-'
-  | True                                        = '/'   -- windows
-
--- | The description of the Z3 SMT solver
+-- | The description of the Z3 SMT solver.
 -- The default executable is @\"z3\"@, which must be in your path. You can use the @SBV_Z3@ environment variable to point to the executable on your system.
--- The default options are @\"-in -smt2\"@, which is valid for Z3 4.1. You can use the @SBV_Z3_OPTIONS@ environment variable to override the options.
+-- You can use the @SBV_Z3_OPTIONS@ environment variable to override the options.
 z3 :: SMTSolver
 z3 = SMTSolver {
-           name           = Z3
-         , executable     = "z3"
-         , options        = map (optionPrefix:) ["nw", "in", "smt2"]
-         , engine         = \cfg isSat qinps skolemMap pgm -> do
-                                    execName <-                   getEnv "SBV_Z3"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap` getEnv "SBV_Z3_OPTIONS") `C.catch` (\(_ :: C.SomeException) -> return (options (solver cfg)))
-                                    let cfg' = cfg { solver = (solver cfg) {executable = execName, options = addTimeOut (timeOut cfg) execOpts} }
-                                        tweaks = case solverTweaks cfg' of
-                                                   [] -> ""
-                                                   ts -> unlines $ "; --- user given solver tweaks ---" : ts ++ ["; --- end of user given tweaks ---"]
-                                        dlim = printRealPrec cfg'
-                                        ppDecLim = "(set-option :pp.decimal_precision " ++ show dlim ++ ")\n"
-                                        script = SMTScript {scriptBody = tweaks ++ ppDecLim ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps))
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "Z3"
-                                , mbDefaultLogic             = const Nothing
-                                , supportsMacros             = True
-                                , supportsProduceModels      = True
-                                , supportsQuantifiers        = True
-                                , supportsUninterpretedSorts = True
-                                , supportsUnboundedInts      = True
-                                , supportsReals              = True
-                                , supportsFloats             = True
-                                , supportsDoubles            = True
-                                }
+           name         = Z3
+         , executable   = "z3"
+         , preprocess   = id
+         , options      = modConfig ["-nw", "-in", "-smt2"]
+         , engine       = standardEngine "SBV_Z3" "SBV_Z3_OPTIONS"
+         , capabilities = SolverCapabilities {
+                                supportsQuantifiers     = True
+                              , supportsDefineFun       = True
+                              , supportsDistinct        = True
+                              , supportsBitVectors      = True
+                              , supportsADTs            = True
+                              , supportsUnboundedInts   = True
+                              , supportsReals           = True
+                              , supportsApproxReals     = True
+                              , supportsDeltaSat        = Nothing
+                              , supportsIEEE754         = True
+                              , supportsSets            = True
+                              , supportsOptimization    = True
+                              , supportsPseudoBooleans  = True
+                              , supportsCustomQueries   = True
+                              , supportsGlobalDecls     = True
+                              , supportsDataTypes       = True
+                              , supportsLambdas         = True
+                              , supportsSpecialRels     = True
+                              , supportsDirectTesters   = False -- Needs ascriptions. (See the CVC4 version of this)
+                              , supportsFlattenedModels = Just [ "(set-option :pp.max_depth      4294967295)"
+                                                               , "(set-option :pp.min_alias_size 4294967295)"
+                                                               , "(set-option :model.inline_def  true      )"
+                                                               ]
+                              }
          }
- where cont rm skolemMap = intercalate "\n" $ concatMap extract skolemMap
-        where -- In the skolemMap:
-              --    * Left's are universals: i.e., the model should be true for
-              --      any of these. So, we simply "echo 0" for these values.
-              --    * Right's are existentials. If there are no dependencies (empty list), then we can
-              --      simply use get-value to extract it's value. Otherwise, we have to apply it to
-              --      an appropriate number of 0's to get the final value.
-              extract (Left s)        = ["(echo \"((" ++ show s ++ " " ++ mkSkolemZero rm (kindOf s) ++ "))\")"]
-              extract (Right (s, [])) = let g = "(get-value (" ++ show s ++ "))" in getVal (kindOf s) g
-              extract (Right (s, ss)) = let g = "(get-value ((" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ ")))" in getVal (kindOf s) g
-              getVal KReal g = ["(set-option :pp.decimal false) " ++ g, "(set-option :pp.decimal true)  " ++ g]
-              getVal _     g = [g]
-       addTimeOut Nothing  o   = o
-       addTimeOut (Just i) o
-         | i < 0               = error $ "Z3: Timeout value must be non-negative, received: " ++ show i
-         | True                = o ++ [optionPrefix : "T:" ++ show i]
 
-extractMap :: Bool -> [(Quantifier, NamedSymVar)] -> [String] -> SMTModel
-extractMap isSat qinps solverLines =
-   SMTModel { modelAssocs = map snd $ squashReals $ sortByNodeId $ concatMap (interpretSolverModelLine inps) solverLines }
-  where sortByNodeId :: [(Int, a)] -> [(Int, a)]
-        sortByNodeId = sortBy (compare `on` fst)
-        inps -- for "sat", display the prefix existentials. For completeness, we will drop
-             -- only the trailing foralls. Exception: Don't drop anything if it's all a sequence of foralls
-             | isSat = map snd $ if all (== ALL) (map fst qinps)
-                                 then qinps
-                                 else reverse $ dropWhile ((== ALL) . fst) $ reverse qinps
-             -- for "proof", just display the prefix universals
-             | True  = map snd $ takeWhile ((== ALL) . fst) qinps
-        squashReals :: [(Int, (String, CW))] -> [(Int, (String, CW))]
-        squashReals = concatMap squash . groupBy ((==) `on` fst)
-          where squash [(i, (n, cw1)), (_, (_, cw2))] = [(i, (n, mergeReals n cw1 cw2))]
-                squash xs = xs
-                mergeReals :: String -> CW -> CW -> CW
-                mergeReals n (CW KReal (CWAlgReal a)) (CW KReal (CWAlgReal b)) = CW KReal (CWAlgReal (mergeAlgReals (bad n a b) a b))
-                mergeReals n a b = bad n a b
-                bad n a b = error $ "SBV.Z3: Cannot merge reals for variable: " ++ n ++ " received: " ++ show (a, b)
+ where modConfig :: [String] -> SMTConfig -> [String]
+       modConfig opts _cfg = opts
diff --git a/Data/SBV/Rational.hs b/Data/SBV/Rational.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Rational.hs
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Rational
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Symbolic rationals, corresponds to Haskell's 'Rational' type
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Rational (
+    -- * Constructing rationals
+      (.%)
+  ) where
+
+import qualified Data.Ratio as R
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model
+
+infixl 7 .%
+
+-- | Construct a symbolic rational from a given numerator and denominator. Note that
+-- it is not possible to deconstruct a rational by taking numerator and denominator
+-- fields, since we do not represent them canonically. (This is due to the fact that
+-- SMTLib has no functions to compute the GCD. While we can define a recursive function
+-- to do so, it would almost always imply non-decidability for even the simplest queries.)
+(.%) :: SInteger -> SInteger -> SRational
+top .% bot
+ | Just t <- unliteral top
+ , Just b <- unliteral bot
+ = literal $ t R.% b
+ | True
+ = SBV $ SVal KRational $ Right $ cache res
+ where res st = do t <- sbvToSV st top
+                   b <- sbvToSV st bot
+                   newExpr st KRational $ SBVApp RationalConstructor [t, b]
+
+-- | Get the numerator. Note that this is always symbolic since we don't have a concrete representation.
+-- Furthermore this is only used internally and is not exported to the user, since it is not canonical.
+doNotExport_numerator :: SRational -> SInteger
+doNotExport_numerator x = SBV $ SVal KUnbounded $ Right $ cache res
+  where res st = do xv <- sbvToSV st x
+                    newExpr st KUnbounded $ SBVApp (Uninterpreted "sbv.rat.numerator") [xv]
+
+-- | Get the numerator. Note that this is always symbolic since we don't have a concrete representation.
+-- Furthermore this is only used internally and is not exported to the user, since it is not canonical.
+doNotExport_denominator :: SRational -> SInteger
+doNotExport_denominator x = SBV $ SVal KUnbounded $ Right $ cache res
+  where res st = do xv <- sbvToSV st x
+                    newExpr st KUnbounded $ SBVApp (Uninterpreted "sbv.rat.denominator") [xv]
+
+-- | Num instance for SRational. Note that denominators are always positive.
+instance Num SRational where
+  fromInteger i  = SBV $ SVal KRational $ Left $ mkConstCV KRational (fromIntegral i :: Integer)
+  (+)            = lift2 (+)    (\(t1, b1) (t2, b2) -> (t1 * b2 + t2 * b1) .% (b1 * b2))
+  (-)            = lift2 (-)    (\(t1, b1) (t2, b2) -> (t1 * b2 - t2 * b1) .% (b1 * b2))
+  (*)            = lift2 (*)    (\(t1, b1) (t2, b2) -> (t1      * t2     ) .% (b1 * b2))
+  abs            = lift1 abs    (\(t, b) -> abs    t .% b)
+  negate         = lift1 negate (\(t, b) -> negate t .% b)
+  signum a       = ite (a .> 0) 1 $ ite (a .< 0) (-1) 0
+
+-- | Symbolic ordering for SRational. Note that denominators are always positive.
+instance OrdSymbolic SRational where
+   (.<)  = lift2 (<)  (\(t1, b1) (t2, b2) -> (t1 * b2) .<  (b1 * t2))
+   (.<=) = lift2 (<=) (\(t1, b1) (t2, b2) -> (t1 * b2) .<= (b1 * t2))
+   (.>)  = lift2 (>)  (\(t1, b1) (t2, b2) -> (t1 * b2) .>  (b1 * t2))
+   (.>=) = lift2 (>=) (\(t1, b1) (t2, b2) -> (t1 * b2) .>= (b1 * t2))
+
+-- | Get the top and bottom parts. Internal only; do not export!
+doNotExport_getTB :: SRational -> (SInteger, SInteger)
+doNotExport_getTB a = (doNotExport_numerator a, doNotExport_denominator a)
+
+-- | Lift a function over one rational
+lift1 :: SymVal t => (Rational -> t) -> ((SInteger,  SInteger) -> SBV t) -> SRational -> SBV t
+lift1 cf f a
+ | Just va <- unliteral a
+ = literal (cf va)
+ | True
+ = f (doNotExport_getTB a)
+
+-- | Lift a function over two rationals
+lift2 :: SymVal t => (Rational -> Rational -> t) -> ((SInteger,  SInteger) -> (SInteger,  SInteger) -> SBV t) -> SRational -> SRational -> SBV t
+lift2 cf f a b
+ | Just va <- unliteral a, Just vb <- unliteral b
+ = literal (va `cf` vb)
+ | True
+ = f (doNotExport_getTB a) (doNotExport_getTB b)
+
+{- HLint ignore type doNotExport_numerator   "Use camelCase" -}
+{- HLint ignore type doNotExport_denominator "Use camelCase" -}
+{- HLint ignore type doNotExport_getTB       "Use camelCase" -}
diff --git a/Data/SBV/RegExp.hs b/Data/SBV/RegExp.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/RegExp.hs
@@ -0,0 +1,388 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.RegExp
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A collection of regular-expression related utilities. The recommended
+-- workflow is to import this module qualified as the names of the functions
+-- are specifically chosen to be common identifiers. Also, it is recommended
+-- you use the @OverloadedStrings@ extension to allow literal strings to be
+-- used as symbolic-strings and regular-expressions when working with
+-- this module.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.RegExp (
+        -- * Regular expressions
+        -- $regexpeq
+        RegExp(..)
+        -- * Matching
+        -- $matching
+        , RegExpMatchable(..)
+        -- * Constructing regular expressions
+        -- ** Basics
+        , everything, nothing, anyChar
+        -- ** Literals
+        , exactly
+        -- ** A class of characters
+        , oneOf
+        -- ** Spaces
+        , newline, whiteSpaceNoNewLine, whiteSpace
+        -- ** Separators
+        , tab, punctuation
+        -- ** Letters
+        , asciiLetter, asciiLower, asciiUpper
+        -- ** Digits
+        , digit, octDigit, hexDigit
+        -- ** Numbers
+        , decimal, octal, hexadecimal, floating
+        -- ** Identifiers
+        , identifier
+        ) where
+
+import Prelude hiding (length, take, elem, notElem, head, replicate, filter, map)
+
+import qualified Prelude   as P
+import qualified Data.List as L
+
+import Data.SBV.Core.Data
+
+import Data.SBV.List
+import qualified Data.Char as C
+
+import Data.Proxy
+
+-- For testing only
+import Data.SBV.Char
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Char
+-- >>> import Data.SBV.List
+-- >>> import Prelude hiding (length, take, elem, notElem, head, map)
+-- >>> import qualified Prelude as P
+-- >>> :set -XOverloadedStrings
+-- >>> :set -XScopedTypeVariables
+#endif
+
+-- | Matchable class. Things we can match against a 'RegExp'.
+--
+-- For instance, you can generate valid-looking phone numbers like this:
+--
+-- >>> :set -XOverloadedStrings
+-- >>> let dig09 = Range '0' '9'
+-- >>> let dig19 = Range '1' '9'
+-- >>> let pre   = dig19 * Loop 2 2 dig09
+-- >>> let post  = dig19 * Loop 3 3 dig09
+-- >>> let phone = pre * "-" * post
+-- >>> sat $ \(s :: SString) -> s `match` phone
+-- Satisfiable. Model:
+--   s0 = "422-2222" :: String
+class RegExpMatchable a where
+   -- | @`match` s r@ checks whether @s@ is in the language generated by @r@.
+   match :: a -> RegExp -> SBool
+
+-- | Matching a character simply means the singleton string matches the regex.
+instance RegExpMatchable SChar where
+   match = match . singleton
+
+-- | Matching symbolic strings.
+instance RegExpMatchable SString where
+   match input regExp = lift1 (StrInRe regExp) (Just (go regExp P.null)) input
+     where -- This isn't super efficient, but it gets the job done.
+           go :: RegExp -> (String -> Bool) -> String -> Bool
+           go (Literal l)    k s      = l `L.isPrefixOf` s && k (P.drop (P.length l) s)
+           go All            _ _      = True
+           go AllChar        k s      = not (P.null s) && k (P.drop 1 s)
+           go None           _ _      = False
+           go (Range _ _)    _ []     = False
+           go (Range a b)    k (c:cs) = a <= c && c <= b && k cs
+           go (Conc [])      k s      = k s
+           go (Conc (r:rs))  k s      = go r (go (Conc rs) k) s
+           go (KStar r)      k s      = k s || go r (smaller (P.length s) (go (KStar r) k)) s
+           go (KPlus r)      k s      = go (Conc [r, KStar r]) k s
+           go (Opt r)        k s      = k s || go r k s
+           go (Comp r)       k s      = not $ go r k s
+           go (Diff r1 r2)   k s      = go r1 k s && not (go r2 k s)
+           go (Loop i j r)   k s      = go (Conc (P.replicate i r P.++ P.replicate (j - i) (Opt r))) k s
+           go (Power n r)    k s      = go (Loop n n r) k s
+           go (Union [])     _ _      = False
+           go (Union [x])    k s      = go x k s
+           go (Union (x:xs)) k s      = go x k s || go (Union xs) k s
+           go (Inter a b)    k s      = go a k s && go b k s
+
+           -- In the KStar case, make sure the continuation is called with something
+           -- smaller to avoid infinite recursion!
+           smaller orig k inp = P.length inp < orig && k inp
+
+-- | Match everything, universal acceptor.
+--
+-- >>> prove $ \(s :: SString) -> s `match` everything
+-- Q.E.D.
+everything :: RegExp
+everything = All
+
+-- | Match nothing, universal rejector.
+--
+-- >>> prove $ \(s :: SString) -> sNot (s `match` nothing)
+-- Q.E.D.
+nothing :: RegExp
+nothing = None
+
+-- | Match any character, i.e., strings of length 1
+--
+-- >>> prove $ \(s :: SString) -> s `match` anyChar .<=> length s .== 1
+-- Q.E.D.
+anyChar :: RegExp
+anyChar = AllChar
+
+-- | A literal regular-expression, matching the given string exactly. Note that
+-- with @OverloadedStrings@ extension, you can simply use a Haskell
+-- string to mean the same thing, so this function is rarely needed.
+--
+-- >>> prove $ \(s :: SString) -> s `match` exactly "LITERAL" .<=> s .== "LITERAL"
+-- Q.E.D.
+exactly :: String -> RegExp
+exactly = Literal
+
+-- | Helper to define a character class.
+--
+-- >>> prove $ \(c :: SChar) -> c `match` oneOf "ABCD" .<=> sAny (c .==) (P.map literal "ABCD")
+-- Q.E.D.
+oneOf :: String -> RegExp
+oneOf xs = Union [exactly [x] | x <- xs]
+
+-- | Recognize a newline. Also includes carriage-return and form-feed.
+--
+-- >>> newline
+-- (re.union (str.to_re "\n") (str.to_re "\r") (str.to_re "\f"))
+-- >>> prove $ \c -> c `match` newline .=> isSpaceL1 c
+-- Q.E.D.
+newline :: RegExp
+newline = oneOf "\n\r\f"
+
+-- | Recognize a tab.
+--
+-- >>> tab
+-- (str.to_re "\t")
+-- >>> prove $ \c -> c `match` tab .=> c .== literal '\t'
+-- Q.E.D.
+tab :: RegExp
+tab = oneOf "\t"
+
+-- | Lift a char function to a regular expression that recognizes it.
+liftPredL1 :: (Char -> Bool) -> RegExp
+liftPredL1 predicate = oneOf $ P.filter predicate (P.map C.chr [0 .. 255])
+
+-- | Recognize white-space, but without a new line.
+--
+-- >>> prove $ \c -> c `match` whiteSpaceNoNewLine .=> c `match` whiteSpace .&& c ./= literal '\n'
+-- Q.E.D.
+whiteSpaceNoNewLine :: RegExp
+whiteSpaceNoNewLine = liftPredL1 (\c -> C.isSpace c && c `P.notElem` ("\n" :: String))
+
+-- | Recognize white space.
+--
+-- >>> prove $ \c -> c `match` whiteSpace .=> isSpaceL1 c
+-- Q.E.D.
+whiteSpace :: RegExp
+whiteSpace = liftPredL1 C.isSpace
+
+-- | Recognize a punctuation character.
+--
+-- >>> prove $ \c -> c `match` punctuation .=> isPunctuationL1 c
+-- Q.E.D.
+punctuation :: RegExp
+punctuation = liftPredL1 C.isPunctuation
+
+-- | Recognize an alphabet letter, i.e., @A@..@Z@, @a@..@z@.
+asciiLetter :: RegExp
+asciiLetter = asciiLower + asciiUpper
+
+-- | Recognize an ASCII lower case letter
+--
+-- >>> asciiLower
+-- (re.range "a" "z")
+-- >>> prove $ \(c :: SChar) -> c `match` asciiLower  .=> c `match` asciiLetter
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` asciiLower  .=> toUpperL1 c `match` asciiUpper
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` asciiLetter .=> toLowerL1 c `match` asciiLower
+-- Q.E.D.
+asciiLower :: RegExp
+asciiLower = Range 'a' 'z'
+
+-- | Recognize an upper case letter
+--
+-- >>> asciiUpper
+-- (re.range "A" "Z")
+-- >>> prove $ \(c :: SChar) -> c `match` asciiUpper  .=> c `match` asciiLetter
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` asciiUpper  .=> toLowerL1 c `match` asciiLower
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` asciiLetter .=> toUpperL1 c `match` asciiUpper
+-- Q.E.D.
+asciiUpper :: RegExp
+asciiUpper = Range 'A' 'Z'
+
+-- | Recognize a digit. One of @0@..@9@.
+--
+-- >>> digit
+-- (re.range "0" "9")
+-- >>> prove $ \c -> c `match` digit .<=> let v = digitToInt c in 0 .<= v .&& v .< 10
+-- Q.E.D.
+-- >>> prove $ \c -> sNot ((c::SChar) `match` (digit - digit))
+-- Q.E.D.
+digit :: RegExp
+digit = Range '0' '9'
+
+-- | Recognize an octal digit. One of @0@..@7@.
+--
+-- >>> octDigit
+-- (re.range "0" "7")
+-- >>> prove $ \c -> c `match` octDigit .<=> let v = digitToInt c in 0 .<= v .&& v .< 8
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` octDigit .=> c `match` digit
+-- Q.E.D.
+octDigit :: RegExp
+octDigit = Range '0' '7'
+
+-- | Recognize a hexadecimal digit. One of @0@..@9@, @a@..@f@, @A@..@F@.
+--
+-- >>> hexDigit
+-- (re.union (re.range "0" "9") (re.range "a" "f") (re.range "A" "F"))
+-- >>> prove $ \c -> c `match` hexDigit .<=> let v = digitToInt c in 0 .<= v .&& v .< 16
+-- Q.E.D.
+-- >>> prove $ \(c :: SChar) -> c `match` digit .=> c `match` hexDigit
+-- Q.E.D.
+hexDigit :: RegExp
+hexDigit = digit + Range 'a' 'f' + Range 'A' 'F'
+
+-- | Recognize a decimal number.
+--
+-- >>> decimal
+-- (re.+ (re.range "0" "9"))
+-- >>> prove $ \(s :: SString) -> s `match` decimal .=> sNot (s `match` KStar asciiLetter)
+-- Q.E.D.
+decimal :: RegExp
+decimal = KPlus digit
+
+-- | Recognize an octal number. Must have a prefix of the form @0o@\/@0O@.
+--
+-- >>> octal
+-- (re.++ (re.union (str.to_re "0o") (str.to_re "0O")) (re.+ (re.range "0" "7")))
+-- >>> prove $ \(s :: SString) -> s `match` octal .=> sAny (.== take 2 s) ["0o", "0O"]
+-- Q.E.D.
+octal :: RegExp
+octal = ("0o" + "0O") * KPlus octDigit
+
+-- | Recognize a hexadecimal number. Must have a prefix of the form @0x@\/@0X@.
+--
+-- >>> hexadecimal
+-- (re.++ (re.union (str.to_re "0x") (str.to_re "0X")) (re.+ (re.union (re.range "0" "9") (re.range "a" "f") (re.range "A" "F"))))
+-- >>> prove $ \(s :: SString) -> s `match` hexadecimal .=> sAny (.== take 2 s) ["0x", "0X"]
+-- Q.E.D.
+hexadecimal :: RegExp
+hexadecimal = ("0x" + "0X") * KPlus hexDigit
+
+-- | Recognize a floating point number. The exponent part is optional if a fraction
+-- is present. The exponent may or may not have a sign.
+--
+-- >>> prove $ \(s :: SString) -> s `match` floating .=> length s .>= 3
+-- Q.E.D.
+floating :: RegExp
+floating = withFraction + withoutFraction
+  where withFraction    = decimal * "." * decimal * Opt expt
+        withoutFraction = decimal * expt
+        expt            = ("e" + "E") * Opt (oneOf "+-") * decimal
+
+-- | For the purposes of this regular expression, an identifier consists of a letter
+-- followed by zero or more letters, digits, underscores, and single quotes. The first
+-- letter must be lowercase.
+--
+-- >>> prove $ \(s :: SString) -> s `match` identifier .=> isAsciiLower (head s)
+-- Q.E.D.
+-- >>> prove $ \(s :: SString) -> s `match` identifier .=> length s .>= 1
+-- Q.E.D.
+identifier :: RegExp
+identifier = asciiLower * KStar (asciiLetter + digit + "_" + "'")
+
+-- | Lift a unary operator over strings.
+lift1 :: forall a b. (SymVal a, SymVal b) => StrOp -> Maybe (a -> b) -> SBV a -> SBV b
+lift1 w mbOp a
+  | Just cv <- concEval1 mbOp a
+  = cv
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf (Proxy @b)
+        r st = do sva <- sbvToSV st a
+                  newExpr st k (SBVApp (StrOp w) [sva])
+
+-- | Concrete evaluation for unary ops
+concEval1 :: (SymVal a, SymVal b) => Maybe (a -> b) -> SBV a -> Maybe (SBV b)
+concEval1 mbOp a = literal <$> (mbOp <*> unliteral a)
+
+-- | Quiet GHC about testing only imports
+__unused :: a
+__unused = undefined isSpaceL1
+
+{- $matching
+A symbolic string or a character ('SString' or 'SChar') can be matched against a regular-expression. Note
+that the regular-expression itself is not a symbolic object: It's a fully concrete representation, as
+captured by the 'RegExp' class. The 'RegExp' class is an instance of the @IsString@ class, which makes writing
+literal matches easier. The 'RegExp' type also has a (somewhat degenerate) 'Num' instance: Concatenation
+corresponds to multiplication, union corresponds to addition, and @0@ corresponds to the empty language.
+
+Note that since `match` is a method of 'RegExpMatchable' class, both 'SChar' and 'SString' can be used as
+an argument for matching. In practice, this means you might have to disambiguate with a type-ascription
+if it is not deducible from context.
+
+>>> prove $ \(s :: SString) -> s `match` "hello" .<=> s .== "hello"
+Q.E.D.
+>>> prove $ \(s :: SString) -> s `match` Loop 2 5 "xyz" .=> length s .>= 6
+Q.E.D.
+>>> prove $ \(s :: SString) -> s `match` Loop 2 5 "xyz" .=> length s .<= 15
+Q.E.D.
+>>> prove $ \(s :: SString) -> s `match` Power 3 "xyz" .=> length s .== 9
+Q.E.D.
+>>> prove $ \(s :: SString) -> s `match`  (exactly "xyz" ^ 3) .=> length s .== 9
+Q.E.D.
+>>> prove $ \(s :: SString) -> match s (Loop 2 5 "xyz") .=> length s .>= 7
+Falsifiable. Counter-example:
+  s0 = "xyzxyz" :: String
+>>> prove $ \(s :: SString) -> s `match` "hello" .=> s `match` ("hello" + "world")
+Q.E.D.
+>>> prove $ \(s :: SString) -> sNot $ s `match` ("so close" * 0)
+Q.E.D.
+>>> prove $ \c -> (c :: SChar) `match` oneOf "abcd" .=> ord c .>= ord (literal 'a') .&& ord c .<= ord (literal 'd')
+Q.E.D.
+-}
+
+
+{- $regexpeq
+/A note on Equality/ Regular expressions can be symbolically compared for equality. Note that the regular Haskell 'Eq'
+instance and the symbolic version differ in semantics: 'Eq' instance checks for "structural" equality, i.e., that the two regular expressions
+are constructed in precisely the same way. The symbolic equality, however, checks for language equality, i.e., that
+the regular expressions correspond to the same set of strings. This is a bit unfortunate, but hopefully should not
+cause much trouble in practice. Note that the only reason we support symbolic equality is to take advantage of
+the internal decision procedures z3 provides for this case: A similar goal can be achieved by showing there is
+no string accepted by one but not the other. However, this encoding doesn't perform well in z3.
+
+>>> prove $ ("a" * KStar ("b" * "a")) .== (KStar ("a" * "b") * "a")
+Q.E.D.
+>>> prove $ ("a" * KStar ("b" * "a")) .== (KStar ("a" * "b") * "c")
+Falsifiable
+>>> prove $ ("a" * KStar ("b" * "a")) ./= (KStar ("a" * "b") * "c")
+Q.E.D.
+-}
diff --git a/Data/SBV/SCase.hs b/Data/SBV/SCase.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/SCase.hs
@@ -0,0 +1,1409 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.SCase
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Add support for symbolic case expressions. Constructed with the help of ChatGPT,
+-- which was remarkably good at giving me the basic structure.
+--
+-- Provides a quasiquoter  `[sCase| expr of ... |]` for symbolic cases
+-- where @Expr@ is the underlying type. Plain @case@ expressions inside
+-- @sCase@ are automatically treated as symbolic case-splits, enabling
+-- nested symbolic pattern matching.
+--
+-- Also provides `[pCase| expr of ... |]` for proof case-splits. Plain
+-- @case@ expressions inside @pCase@ are automatically treated as nested
+-- proof case-splits (generating @cases [...]@ calls).
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE LambdaCase            #-}
+{-# LANGUAGE TemplateHaskellQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SCase (sCase, pCase) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+import qualified Language.Haskell.Meta.Parse            as Meta
+import qualified Language.Haskell.Meta.Syntax.Translate as Meta
+
+import qualified Language.Haskell.Exts as E
+
+import Control.Monad (unless, when, zipWithM)
+
+import Data.SBV.Core.TH    (getConstructors, sbvName)
+import Data.SBV.Core.Model (ite, symWithKind)
+import Data.SBV.Core.Data  (sTrue, sNot, (.&&), (.||), (.==), (.===), (.:), literal)
+
+import Data.Char  (isDigit)
+import Data.List  (intercalate, stripPrefix)
+import Data.Maybe (isJust, fromMaybe, catMaybes)
+
+import Prelude hiding (fail)
+import qualified Prelude as P(fail)
+
+import Data.Generics (everywhereM, mkM)
+import qualified Data.Map.Strict as Map
+import qualified Data.Set as Set
+import Data.Set (Set)
+
+import System.FilePath
+
+-- | Conjoin a list of TH boolean expressions with (.&&), filtering out trivially true guards.
+sAndAll :: [Exp] -> Exp
+sAndAll = go . filter (not . isTriviallyTrue)
+  where go []  = VarE 'sTrue
+        go [g] = g
+        go gs  = foldr1 (\a b -> foldl1 AppE [VarE '(.&&), a, b]) gs
+
+        isTriviallyTrue (VarE nm) = nameBase nm == nameBase 'sTrue
+        isTriviallyTrue (ConE nm) = nameBase nm == "True"
+        isTriviallyTrue _         = False
+
+-- | TH parse trees don't have location. Let's have a simple mechanism to keep track of them for our use case
+data Offset = Unknown | OffBy Int Int Int
+ deriving Show
+
+-- | Better fail method, keeping track of offsets
+fail :: Offset -> String -> Q a
+fail Unknown     s = P.fail s
+fail off@OffBy{} s = do loc <- location
+                        P.fail (fmtLoc loc off ++ ": " ++  s)
+
+-- | Format a given location by the offset
+fmtLoc :: Loc -> Offset -> String
+fmtLoc loc@Loc{loc_start = (sl, _)} off = takeFileName (loc_filename newLoc) ++ ":" ++ sh (loc_start newLoc) (loc_end newLoc)
+  where sh ab@(a, b) cd@(c, d) | a == c = show a ++ ":" ++ show b ++ if b == d then "" else '-' : show d
+                               | True   = show ab ++ "-" ++ show cd
+
+        newLoc = case off of
+                   Unknown       -> loc
+                   OffBy lo co w -> loc {loc_start = (sl + lo, co + 1), loc_end = (sl + lo, co + w)}
+
+-- | Built-in types recognized by sCase/pCase. Maybe and Either do have mkSymbolic-generated
+-- infrastructure, but we treat them as built-in so that the generated code uses TH-quoted names
+-- (which resolve at SCase.hs compile time) instead of mkName-based references (which would
+-- require the user to have the testers/accessors in scope at the splice site).
+data BuiltinType = BTBool | BTMaybe | BTEither | BTList | BTTuple Int
+  deriving Show
+
+-- | Compare two Names by their base (unqualified) name. This is needed because
+-- built-in constructor names (created with mkName) won't match the fully-qualified
+-- names that GHC resolves patterns to (e.g., mkName "Nothing" vs GHC.Internal.Maybe.Nothing).
+-- Since constructor names are unique within a type, comparing by nameBase is safe.
+sameBase :: Name -> Name -> Bool
+sameBase a b = nameBase a == nameBase b
+
+-- | Lookup by nameBase instead of Name equality.
+lookupBase :: Name -> [(Name, a)] -> Maybe a
+lookupBase _  []          = Nothing
+lookupBase nm ((k,v):kvs)
+  | sameBase nm k = Just v
+  | True          = lookupBase nm kvs
+
+-- | Recognize built-in type names.
+recognizeBuiltin :: String -> Maybe BuiltinType
+recognizeBuiltin "Bool"   = Just BTBool
+recognizeBuiltin "Maybe"  = Just BTMaybe
+recognizeBuiltin "Either" = Just BTEither
+recognizeBuiltin "List"   = Just BTList
+recognizeBuiltin s
+  | Just n <- stripPrefix "Tuple" s, not (null n), all isDigit n, let k = read n, k >= 2, k <= 8
+  = Just (BTTuple k)
+recognizeBuiltin _ = Nothing
+
+-- | Recognize a constructor name as belonging to a built-in type. Used in flattenPat
+-- to generate TH-quoted tester/accessor references for nested built-in constructors.
+recognizeBuiltinCon :: String -> Maybe BuiltinType
+recognizeBuiltinCon "True"    = Just BTBool
+recognizeBuiltinCon "False"   = Just BTBool
+recognizeBuiltinCon "Nothing" = Just BTMaybe
+recognizeBuiltinCon "Just"    = Just BTMaybe
+recognizeBuiltinCon "Left"    = Just BTEither
+recognizeBuiltinCon "Right"   = Just BTEither
+recognizeBuiltinCon "[]"      = Just BTList
+recognizeBuiltinCon ":"       = Just BTList
+recognizeBuiltinCon _         = Nothing
+
+-- | Infer the type from the constructor names used in the pattern matches.
+-- Examines top-level patterns to find the first informative one (i.e., not a wildcard),
+-- then resolves the constructor via TH to determine the parent type.
+-- Returns 'Nothing' if all branches use wildcards (wildcard-only mode).
+inferType :: String -> [Match] -> Q (Maybe (String, Maybe BuiltinType))
+inferType label matches = case firstInfo matches of
+    Just (Left n)            -> pure $ Just ("Tuple" ++ show n, Just (BTTuple n))
+    Just (Right Nothing)     -> pure $ Just ("List", Just BTList)
+    Just (Right (Just name)) -> Just <$> resolveConType name
+    Nothing                  -> pure Nothing
+  where
+    -- Left n = tuple of arity n, Right Nothing = list, Right (Just name) = constructor name
+    firstInfo [] = Nothing
+    firstInfo (Match pat _ _ : rest) = case patInfo pat of
+                                         Just info -> Just info
+                                         Nothing   -> firstInfo rest
+
+    patInfo (ConP n _ _)                              = Just (Right (Just n))
+    patInfo (RecP n _)                                = Just (Right (Just n))
+    patInfo (InfixP _ n _)  | nameBase n == ":"       = Just (Right Nothing)
+    patInfo (UInfixP _ n _) | nameBase n == ":"       = Just (Right Nothing)
+    patInfo (TupP ps)                                 = Just (Left (length ps))
+    patInfo (ListP _)                                 = Just (Right Nothing)
+    patInfo (ParensP p)                               = patInfo p
+    patInfo (AsP _ p)                                 = patInfo p
+    patInfo _                                         = Nothing
+
+    -- Resolve a constructor name to its parent type via TH
+    resolveConType conName = do
+      let base = nameBase conName
+      -- Check if it's a known built-in constructor first (for cases where lookupValueName
+      -- might not resolve, e.g., "[]" as a value name)
+      case recognizeBuiltinCon base of
+        Just bt -> pure (builtinTypeName bt, Just bt)
+        Nothing -> do
+          mbResolved <- lookupValueName base
+          case mbResolved of
+            Nothing -> fail Unknown $ unlines [ label ++ ": Unknown constructor: " ++ base
+                                              , ""
+                                              , "        Cannot find this constructor in scope."
+                                              , "        Make sure the type is declared and mkSymbolic is called."
+                                              ]
+            Just resolved -> do
+              info <- reify resolved
+              case info of
+                DataConI _ _ parentName -> let typName = nameBase parentName
+                                           in pure (typName, recognizeBuiltin typName)
+                _ -> fail Unknown $ label ++ ": " ++ base ++ " is not a data constructor."
+
+    builtinTypeName BTBool      = "Bool"
+    builtinTypeName BTMaybe     = "Maybe"
+    builtinTypeName BTEither    = "Either"
+    builtinTypeName BTList      = "List"
+    builtinTypeName (BTTuple n) = "Tuple" ++ show n
+
+-- | Constructor info for a built-in type: (name, arity).
+builtinConstructors :: BuiltinType -> [(Name, Int)]
+builtinConstructors BTBool        = [(mkName "True", 0), (mkName "False", 0)]
+builtinConstructors BTMaybe       = [(mkName "Nothing", 0), (mkName "Just", 1)]
+builtinConstructors BTEither      = [(mkName "Left", 1), (mkName "Right", 1)]
+builtinConstructors BTList        = [(mkName "[]", 0), (mkName ":", 2)]
+builtinConstructors (BTTuple n)   = [(tupleDataName n, n)]
+
+-- | Generate a tester expression for a built-in type constructor.
+builtinTester :: BuiltinType -> Name -> Exp -> Exp
+builtinTester BTBool nm scrut
+  | nameBase nm == "True"  = scrut
+  | nameBase nm == "False" = AppE (VarE 'sNot) scrut
+builtinTester BTMaybe nm scrut
+  | nameBase nm == "Nothing" = AppE (VarE (sbvName "Data.SBV.Maybe" "isNothing")) scrut
+  | nameBase nm == "Just"    = AppE (VarE (sbvName "Data.SBV.Maybe" "isJust"))    scrut
+builtinTester BTEither nm scrut
+  | nameBase nm == "Left"  = AppE (VarE (sbvName "Data.SBV.Either" "isLeft"))  scrut
+  | nameBase nm == "Right" = AppE (VarE (sbvName "Data.SBV.Either" "isRight")) scrut
+builtinTester BTList nm scrut
+  | nameBase nm == "[]" = AppE (VarE (sbvName "Data.SBV.List" "null")) scrut
+  | nameBase nm == ":"  = AppE (VarE 'sNot) (AppE (VarE (sbvName "Data.SBV.List" "null")) scrut)
+builtinTester (BTTuple _) _ _ = VarE 'sTrue
+builtinTester bt nm _ = error $ "sCase: builtinTester: unexpected constructor " ++ nameBase nm ++ " for " ++ show bt
+
+-- | Generate an accessor expression for a built-in type constructor field.
+builtinAccessor :: BuiltinType -> Name -> Int -> Exp -> Exp
+builtinAccessor BTBool nm _ _ = error $ "sCase: builtinAccessor: Bool constructor " ++ nameBase nm ++ " has no fields"
+builtinAccessor BTMaybe nm i scrut
+  | nameBase nm == "Just", i == 1 = AppE (VarE (sbvName "Data.SBV.Maybe" "getJust_1")) scrut
+builtinAccessor BTEither nm i scrut
+  | nameBase nm == "Left",  i == 1 = AppE (VarE (sbvName "Data.SBV.Either" "getLeft_1"))  scrut
+  | nameBase nm == "Right", i == 1 = AppE (VarE (sbvName "Data.SBV.Either" "getRight_1")) scrut
+builtinAccessor BTList nm i scrut
+  | nameBase nm == ":", i == 1 = AppE (VarE (sbvName "Data.SBV.List" "head")) scrut
+  | nameBase nm == ":", i == 2 = AppE (VarE (sbvName "Data.SBV.List" "tail")) scrut
+builtinAccessor (BTTuple _) _ i scrut
+  -- Simplify _i (tuple (a, b, ...)) to just the i-th component
+  | AppE (VarE f) (TupE components) <- scrut
+  , nameBase f == "tuple"
+  , let cs = catMaybes components
+  , i >= 1, i <= length cs
+  = cs !! (i - 1)
+  | True
+  = AppE (VarE (tupleAccessorName i)) scrut
+  where tupleAccessorName 1 = sbvName "Data.SBV.Tuple" "_1"
+        tupleAccessorName 2 = sbvName "Data.SBV.Tuple" "_2"
+        tupleAccessorName 3 = sbvName "Data.SBV.Tuple" "_3"
+        tupleAccessorName 4 = sbvName "Data.SBV.Tuple" "_4"
+        tupleAccessorName 5 = sbvName "Data.SBV.Tuple" "_5"
+        tupleAccessorName 6 = sbvName "Data.SBV.Tuple" "_6"
+        tupleAccessorName 7 = sbvName "Data.SBV.Tuple" "_7"
+        tupleAccessorName 8 = sbvName "Data.SBV.Tuple" "_8"
+        tupleAccessorName n = error $ "sCase: tupleAccessorName: unsupported index " ++ show n
+builtinAccessor bt nm i _ = error $ "sCase: builtinAccessor: unexpected constructor " ++ nameBase nm ++ " field " ++ show i ++ " for " ++ show bt
+
+-- | Generate a tester expression for a constructor, dispatching to builtinTester for
+-- recognized built-in constructors or falling back to @is\<Con\>@ for user ADTs.
+mkTester :: Name -> Exp -> Exp
+mkTester nm scrut = case recognizeBuiltinCon (nameBase nm) of
+    Just bt -> builtinTester bt nm scrut
+    Nothing -> AppE (VarE (mkName ("is" ++ nameBase nm))) scrut
+
+-- | Generate an accessor expression for a constructor field, dispatching to builtinAccessor for
+-- recognized built-in constructors or falling back to @get\<Con\>_i@ for user ADTs.
+mkAccessor :: Name -> Int -> Exp -> Exp
+mkAccessor nm i scrut = case recognizeBuiltinCon (nameBase nm) of
+    Just bt -> builtinAccessor bt nm i scrut
+    Nothing -> AppE (VarE (mkName ("get" ++ nameBase nm ++ "_" ++ show i))) scrut
+
+-- | Like 'mkTester', but when the built-in type is already known from the scrutinee type.
+-- Used in top-level sCase/pCase code generation.
+mkTesterFor :: Maybe BuiltinType -> Name -> Exp -> Exp
+mkTesterFor (Just bt) nm scrut = builtinTester bt nm scrut
+mkTesterFor Nothing   nm scrut = AppE (VarE (mkName ("is" ++ nameBase nm))) scrut
+
+-- | Like 'mkAccessor', but when the built-in type is already known from the scrutinee type.
+mkAccessorFor :: Maybe BuiltinType -> Name -> Int -> Exp -> Exp
+mkAccessorFor (Just bt) nm i scrut = builtinAccessor bt nm i scrut
+mkAccessorFor Nothing   nm i scrut = AppE (VarE (mkName ("get" ++ nameBase nm ++ "_" ++ show i))) scrut
+
+-- | What kind of case-match are we given. In each case, the last maybe exp is the possible guard.
+data Case = CMatch Offset          -- regular match
+                   Name            -- name of the constructor
+                   (Maybe [Pat])   -- [a, b, c] in C a b c. Or Nothing if C{}
+                   (Maybe Exp)     -- guard
+                   Exp             -- rhs
+                   (Set Name)      -- All variables used all RHSs and All guards
+          | CWild  Offset          -- wild card
+                   (Maybe Exp)     -- guard
+                   Exp             -- rhs
+
+-- | What's the offset?
+caseOffset :: Case -> Offset
+caseOffset (CMatch o _ _ _ _ _) = o
+caseOffset (CWild  o       _ _) = o
+
+-- | Show a case nicely
+showCase :: Case -> String
+showCase = showCaseGen Nothing
+
+-- | Show a case nicely, with location
+showCaseGen :: Maybe Loc -> Case -> String
+showCaseGen mbLoc sc = case sc of
+                         CMatch _ c (Just ps) mbG _ _ -> loc ++ unwords (nameBase c : map pprint ps ++ shGuard mbG)
+                         CMatch _ c Nothing   mbG _ _ -> loc ++ unwords (nameBase c : "{}"           : shGuard mbG)
+                         CWild  _             mbG _   -> loc ++ unwords ("_"                         : shGuard mbG)
+ where shGuard Nothing  = []
+       shGuard (Just e) = ["|", pprint e]
+
+       loc = case mbLoc of
+               Nothing -> ""
+               Just l  -> fmtLoc l (caseOffset sc) ++ ": "
+
+-- | Get the name of the constructor, if any
+getCaseConstructor :: Case -> Maybe Name
+getCaseConstructor (CMatch _ nm _ _ _ _) = Just nm
+getCaseConstructor CWild{}               = Nothing
+
+-- | Get the guard, if any
+getCaseGuard :: Case -> Maybe Exp
+getCaseGuard (CMatch _ _ _ mbg _ _) = mbg
+getCaseGuard (CWild  _     mbg _  ) = mbg
+
+-- | Is there a guard?
+isGuarded :: Case -> Bool
+isGuarded = isJust . getCaseGuard
+
+-- | Find offset of each successive match. This isn't perfect, but it does the job
+findOffsets :: String -> [Offset]
+findOffsets s = analyze $ E.parseExpWithMode E.defaultParseMode $ "case ()" ++ tab ++ rest
+  where rest = relevant s
+        -- there's a chance the replication below might yield a negative value, which can make our
+        -- offset calculation slightly off. But this should be exceedingly rare because it'd have to be that
+        -- matches are on the same line and the "Type expr" part of the original must be shorter than 7 chars.
+        -- Let's ignore that possibility.
+        tab  = replicate (length s - length rest - 7) ' '
+        relevant r@(' ':'o':'f':_) = r
+        relevant ""                = ""
+        relevant (_:cs)            = relevant cs
+
+        analyze E.ParseFailed{} = [] -- Just ignore
+        analyze (E.ParseOk e)   = case e of
+                                   E.Case _ _ alts -> map getOff alts
+                                   _               -> []
+          where getOff (E.Alt l p _ _) = OffBy (E.srcSpanStartLine as - 1) (E.srcSpanStartColumn as - 1) w
+                   where as = E.srcInfoSpan l
+                         cs = E.srcInfoSpan (E.ann p)
+                         w  = E.srcSpanEndColumn cs - E.srcSpanStartColumn cs
+
+-- * Shared parsing infrastructure
+
+-- | Parse a Haskell expression using haskell-src-exts
+metaParse :: String -> Either String Exp
+metaParse = fmap Meta.toExp . Meta.parseResultToEither . E.parseExpWithMode pm
+  where pm = E.defaultParseMode { E.parseFilename = []
+                                , E.baseLanguage  = E.Haskell2010
+                                , E.extensions = map E.EnableExtension (exts ++ extras)
+                                }
+        exts = [ E.PostfixOperators
+               , E.QuasiQuotes
+               , E.UnicodeSyntax
+               , E.PatternSignatures
+               , E.MagicHash
+               , E.ForeignFunctionInterface
+               , E.TemplateHaskell
+               , E.RankNTypes
+               , E.MultiParamTypeClasses
+               , E.RecursiveDo
+               , E.TypeApplications
+               ]
+
+        -- The above just mimics the defaults. These our extras.
+        extras = [E.DataKinds]
+
+-- | Handle a metaParse error by mapping the parse-error column back to the source file.
+-- metaParse operates on @"case " <> src@ (5 extra chars), so we subtract 5 from its column.
+-- For line 1 errors, we also add the quasi-quote content's starting column since the first
+-- line of src is offset from the start of the source line. For subsequent lines, the columns
+-- in the quasi-quote content already correspond to source file columns.
+handleParseError :: String -> String -> Q a
+handleParseError label err = do
+    loc <- location
+    let qqCol = snd (loc_start loc) -- 1-based column where quasi-quote content starts
+    case lines err of
+      (_:locLine:res) | ["SrcLoc", _, l, c] <- words locLine, all isDigit l, all isDigit c
+         -> let mc    = read c
+                line  = read l
+                -- Line 1: column is relative to "case " <> src, need to add quasi-quote offset
+                -- Lines 2+: column is already a source file column (verbatim from source)
+                col = if line == 1 then qqCol + mc - 7 else mc - 1
+            in fail (OffBy (line - 1) col 1) (unlines res)
+      _  -> fail Unknown $ label ++ " parse error: " <> err
+
+
+-- | Extract guards from a match body
+getGuards :: Body -> [Dec] -> Q [(Maybe Exp, Exp)]
+getGuards (NormalB  rhs)  locals = pure [(Nothing, addLocals locals rhs)]
+getGuards (GuardedB exps) locals = mapM get exps
+  where get (NormalG e,  rhs)
+          | isSTrue e
+          = pure (Nothing, addLocals locals rhs)
+          | True
+          = pure (Just e, addLocals locals rhs)
+        get (PatG stmts, rhs)
+          | all isNoBindS stmts
+          = let guards = [e | NoBindS e <- stmts]
+                conj   = sAndAll guards
+            in pure (if isSTrue conj then Nothing else Just conj, addLocals locals rhs)
+          | True
+          = fail Unknown $ unlines $  "sCase/pCase: Pattern guards are not supported: "
+                                   : ["        " ++ pprint s | s <- stmts]
+          where isNoBindS (NoBindS _) = True
+                isNoBindS _           = False
+
+        -- Is this literally sTrue (or True)? This is a bit dangerous since
+        -- we just look at the base-name, but good enough
+        isSTrue (VarE  nm) = nameBase nm == nameBase 'sTrue
+        isSTrue (ConE  nm) = nameBase nm == "True"
+        isSTrue _          = False
+
+-- | Turn where clause into simple let
+addLocals :: [Dec] -> Exp -> Exp
+addLocals [] e = e
+addLocals ds e = LetE ds e
+
+-- | Given an occurrence of a name, find what it refers to
+getReference :: Offset -> Name -> Q Name
+getReference off refName = do mbN <- lookupValueName (nameBase refName)
+                              case mbN of
+                                Nothing -> fail off $ "sCase/pCase: Not in scope: data constructor: " <> pprint refName
+                                Just n  -> pure n
+
+-- | Convert a match into a list of cases
+matchToPair :: Exp -> Offset -> Match -> Q [Case]
+matchToPair scrut off (Match pat grhs locals) = do
+  rhss <- getGuards grhs locals
+  let allUsed = Set.unions (map (\(mbG, e) -> maybe Set.empty freeVars mbG `Set.union` freeVars e) rhss)
+
+      -- Common logic for constructor-like patterns: flatten sub-patterns, merge synthetic guards
+      flattenAndMerge :: Name -> (Int -> Exp) -> [Pat] -> Q [Case]
+      flattenAndMerge con accessor subpats = do
+          flatResults <- zipWithM (flattenPat off . accessor) [(1::Int)..] subpats
+          let ps      = map fstOf3 flatResults
+              subGrds = concatMap sndOf3 flatResults
+              subDecs = concatMap thdOf3 flatResults
+
+              merge (mbG, rhs) =
+                let usedInRhs  = freeVars rhs
+                    usedInGrd  = maybe Set.empty freeVars mbG
+                    decsFor s  = [ d | d@(ValD (VarP v) _ _) <- subDecs, v `Set.member` s ]
+                    rhs' = addLocals (decsFor usedInRhs) rhs
+                    mbG' = case (subGrds, mbG) of
+                              ([], Nothing) -> Nothing
+                              ([], Just g ) -> Just (addLocals (decsFor usedInGrd) g)
+                              (gs, Nothing) -> Just (sAndAll gs)
+                              (gs, Just g ) -> Just (sAndAll (gs ++ [addLocals (decsFor usedInGrd) g]))
+                in (mbG', rhs')
+
+          pure [CMatch off con (Just ps) mbG rhs allUsed | (mbG, rhs) <- map merge rhss]
+
+  case pat of
+    ConP conName _ subpats -> do
+      con <- getReference off conName
+      flattenAndMerge con (\i -> mkAccessor con i scrut) subpats
+
+    RecP conName []        -> do con <- getReference off conName
+                                 pure [CMatch off con Nothing   mbG rhs allUsed | (mbG, rhs) <- rhss]
+
+    WildP                  ->    pure [CWild  off               mbG rhs         | (mbG, rhs) <- rhss]
+
+    -- List cons pattern: y : ys  (InfixP or UInfixP from the parser)
+    InfixP p1 conName p2
+      | nameBase conName == ":" -> let con = mkName ":" in flattenAndMerge con (\i -> mkAccessorFor (Just BTList) con i scrut) [p1, p2]
+    UInfixP p1 conName p2
+      | nameBase conName == ":" -> let con = mkName ":" in flattenAndMerge con (\i -> mkAccessorFor (Just BTList) con i scrut) [p1, p2]
+
+    -- Tuple pattern: (a, b, ...)
+    TupP subpats -> do
+          let n   = length subpats
+              con = tupleDataName n
+          flattenAndMerge con (\i -> mkAccessorFor (Just (BTTuple n)) con i scrut) subpats
+
+    -- List nil pattern: []
+    ListP [] ->        pure [CMatch off (mkName "[]") (Just []) mbG rhs allUsed | (mbG, rhs) <- rhss]
+
+    -- List pattern with elements: [a], [a, b], etc. Desugar to nested cons: a : (b : [])
+    ListP ps -> let desugar []     = ListP []
+                    desugar (p:rest) = InfixP p (mkName ":") (desugar rest)
+                in matchToPair scrut off (Match (desugar ps) grhs locals)
+
+    -- Parenthesized pattern: unwrap and recurse
+    ParensP p -> matchToPair scrut off (Match p grhs locals)
+
+    -- Literal pattern at top level: 0, 1, "hello", etc.
+    -- Treated as a wildcard with a guard: scrut .== literal
+    LitP lit -> do eq <- litToEq off scrut lit
+                   pure [CWild off (Just (maybe eq (\g -> sAndAll [eq, g]) mbG)) rhs | (mbG, rhs) <- rhss]
+
+    -- Variable pattern at top level: binds the scrutinee (only when used)
+    VarP v   -> let bindScrut e | v `Set.member` freeVars e = LetE [ValD (VarP v) (NormalB scrut) []] e
+                                | True                      = e
+                in pure [CWild off (bindScrut <$> mbG) (bindScrut rhs) | (mbG, rhs) <- rhss]
+
+    -- As-pattern at top level: name@subpat — bind name to scrutinee, then process inner pattern
+    AsP name subpat -> do
+        cases <- matchToPair scrut off (Match subpat grhs locals)
+        let bindAs e | name `Set.member` freeVars e = LetE [ValD (VarP name) (NormalB scrut) []] e
+                     | True                         = e
+            addBind (CMatch o cn ps mbG' rhs' used) = CMatch o cn ps (bindAs <$> mbG') (bindAs rhs') used
+            addBind (CWild  o        mbG' rhs')     = CWild  o        (bindAs <$> mbG') (bindAs rhs')
+        pure (map addBind cases)
+
+    _ -> fail Unknown $ unlines [ "sCase/pCase: Unsupported pattern:"
+                                , "            Saw: " <> pprint pat
+                                , ""
+                                , "        Supported patterns: constructors (Cstr a b _ d),"
+                                , "        empty records (Cstr{}), wildcards (_), variables,"
+                                , "        as-patterns (x@pat), and integer/string literals."
+                                ]
+
+-- | Flatten a sub-pattern against a given accessor expression.
+-- Returns: a simple VarP/WildP for the flat pattern list, a list of
+-- synthetic isCstr guard expressions, and let-bindings that bring
+-- nested-pattern variables into scope.
+flattenPat :: Offset -> Exp -> Pat -> Q (Pat, [Exp], [Dec])
+flattenPat _   _   WildP                    = pure (WildP, [], [])
+flattenPat _   _   p@(VarP _)               = pure (p,     [], [])
+flattenPat off arg (ParensP p)              = flattenPat off arg p
+flattenPat off arg (ConP conName _ subpats) = do
+  con   <- getReference off conName
+  -- Arity check: reify the constructor to find its actual field count
+  DataConI _ conType parentName <- reify con
+  let arity = countArgs conType
+  unless (arity == length subpats) $
+    fail off $ unlines [ "sCase/pCase: Arity mismatch in nested pattern."
+                       , "        Constructor: " ++ nameBase con
+                       , "        Expected   : " ++ show arity
+                       , "        Given      : " ++ show (length subpats)
+                       ]
+  -- Check if the parent type has only one constructor; if so, the tester is trivially true
+  singleCon <- isSingleConstructorType parentName
+  let tester      = mkTester con arg
+      accessor i  = mkAccessor con i arg
+  subResults <- zipWithM (flattenPat off . accessor) [(1::Int)..] subpats
+  let subGrds = concatMap sndOf3 subResults
+      subDecs = concatMap thdOf3 subResults
+      subPats = map fstOf3 subResults
+      patDecs = [ ValD (VarP v) (NormalB (accessor i)) []
+                | (i, VarP v) <- zip [(1::Int)..] subPats ]
+      -- Skip the tester guard for single-constructor types (it's always true)
+      guards  = (if singleCon then id else (tester :)) subGrds
+  pure (WildP, guards, patDecs ++ subDecs)
+flattenPat off arg (LitP lit) = do
+  eq <- litToEq off arg lit
+  pure (WildP, [eq], [])
+-- Nested list cons pattern: x : xs (InfixP or UInfixP from the parser)
+flattenPat off arg (InfixP p1 conName p2)
+  | nameBase conName == ":" = flattenCons off arg p1 p2
+flattenPat off arg (UInfixP p1 conName p2)
+  | nameBase conName == ":" = flattenCons off arg p1 p2
+-- Nested empty list pattern: []
+flattenPat _   arg (ListP []) =
+  pure (WildP, [AppE (VarE (sbvName "Data.SBV.List" "null")) arg], [])
+-- Nested list pattern with elements: [a], [a, b], etc. Desugar to nested cons.
+flattenPat off arg (ListP (p:ps)) =
+  flattenPat off arg (InfixP p (mkName ":") (ListP ps))
+-- Nested tuple pattern: (a, b, ...)
+flattenPat off arg (TupP pats) = do
+  let n = length pats
+      accessor i = mkAccessorFor (Just (BTTuple n)) (tupleDataName n) i arg
+  subResults <- zipWithM (flattenPat off . accessor) [(1::Int)..] pats
+  let subGrds = concatMap sndOf3 subResults
+      subDecs = concatMap thdOf3 subResults
+      patDecs = [ ValD (VarP v) (NormalB (accessor i)) []
+                | (i, VarP v) <- zip [(1::Int)..] (map fstOf3 subResults) ]
+  pure (WildP, subGrds, patDecs ++ subDecs)
+-- Nested as-pattern: name@subpat — bind name to accessor, then process inner pattern
+flattenPat off arg (AsP name subpat) = do
+    (pat', guards, decs) <- flattenPat off arg subpat
+    let asDec = ValD (VarP name) (NormalB arg) []
+    pure (pat', guards, asDec : decs)
+-- Nested empty record pattern: Cstr{} — equivalent to Cstr with all wildcards
+flattenPat off arg (RecP conName []) = do
+    con <- getReference off conName
+    DataConI _ conType _ <- reify con
+    let arity = countArgs conType
+    flattenPat off arg (ConP con [] (replicate arity WildP))
+flattenPat o _ p = fail o $ unlines [ "sCase/pCase: Unsupported complex pattern match."
+                                    , "        Saw: " <> pprint p
+                                    , ""
+                                    , "      Only variables, wildcards, as-patterns, nested constructors, and integer/string literals are supported."
+                                    ]
+
+-- | Flatten a nested list cons pattern (x : xs) against an accessor expression.
+-- We include a destructuring equality (arg .=== head arg .: tail arg) because lists use
+-- SMT Seq, not declare-datatypes, so the solver doesn't automatically know this relationship.
+-- This is critical for pCase proof progress; harmless for sCase (redundant guard in ite-chain).
+-- NB. For top-level list cons patterns in pCase, the same equality is added by processProofCases.
+flattenCons :: Offset -> Exp -> Pat -> Pat -> Q (Pat, [Exp], [Dec])
+flattenCons off arg p1 p2 = do
+    let headExpr = mkAccessorFor (Just BTList) (mkName ":") 1 arg
+        tailExpr = mkAccessorFor (Just BTList) (mkName ":") 2 arg
+        tester   = mkTesterFor (Just BTList) (mkName ":") arg
+        destruct = foldl1 AppE [VarE '(.===), arg, InfixE (Just headExpr) (VarE '(.:)) (Just tailExpr)]
+    sub1 <- flattenPat off headExpr p1
+    sub2 <- flattenPat off tailExpr p2
+    let subGrds = sndOf3 sub1 ++ sndOf3 sub2
+        subDecs = thdOf3 sub1 ++ thdOf3 sub2
+        patDecs = [ ValD (VarP v) (NormalB headExpr) [] | VarP v <- [fstOf3 sub1] ]
+               ++ [ ValD (VarP v) (NormalB tailExpr) [] | VarP v <- [fstOf3 sub2] ]
+    pure (WildP, tester : destruct : subGrds, patDecs ++ subDecs)
+
+-- | Check if a type has only one constructor. Used to skip trivially-true tester guards
+-- in nested patterns (e.g., @Just (Pocket n3 n5)@ where @Pocket@ is the sole constructor).
+isSingleConstructorType :: Name -> Q Bool
+isSingleConstructorType tyName = do
+  info <- reify tyName
+  pure $ case info of
+    TyConI (DataD    _ _ _ _ [_] _) -> True
+    TyConI (NewtypeD {})            -> True
+    _                               -> False
+
+fstOf3 :: (a, b, c) -> a
+fstOf3 (a, _, _) = a
+
+sndOf3 :: (a, b, c) -> b
+sndOf3 (_, b, _) = b
+
+thdOf3 :: (a, b, c) -> c
+thdOf3 (_, _, c) = c
+
+-- | Get the constructor list for a type. For built-in types, return synthetic entries;
+-- for user ADTs, reify via getConstructors.
+getCstrs :: Maybe BuiltinType -> String -> Q [(Name, [Type])]
+getCstrs (Just bt) _   = pure [(nm, replicate ar WildCardT) | (nm, ar) <- builtinConstructors bt]
+getCstrs Nothing   typ = let dropFieldNames (c, nts) = (c, map snd nts)
+                          in map dropFieldNames . snd <$> getConstructors (mkName typ)
+
+-- | Validate wildcard placement: unguarded wildcard must be last.
+checkWildcard :: String -> Loc -> [Case] -> Q ()
+checkWildcard label loc cs = do go cs; checkExhaustive cs
+  where go []                         = pure ()
+        go (CMatch{}          : rest) = go rest
+        go (CWild _ Just{}  _ : rest) = go rest
+        go (CWild o Nothing _ : rest) =
+              case rest of
+                []  -> pure ()
+                red -> fail o $ unlines $ (label ++ ": Wildcard makes the remaining matches redundant:")
+                                         : ["        " ++ showCaseGen (Just loc) r | r <- red]
+
+        -- If all cases are wildcards (no CMatch), then we need an unguarded wildcard
+        -- as a catch-all. Otherwise, guarded-only wildcards on an infinite domain
+        -- (Integer, String, etc.) silently produce a free variable for unmatched cases.
+        checkExhaustive cases
+          | any isCMatch cases           = pure ()  -- Has constructor patterns; exhaustiveness checked elsewhere
+          | any isUnguardedWild cases    = pure ()  -- Has an unguarded catch-all
+          | True                         = fail (headOffset cases) $ unlines
+              [ label ++ ": Non-exhaustive pattern match."
+              , "        All branches are guarded; add an unguarded wildcard or variable"
+              , "        as the last branch to ensure all cases are covered."
+              ]
+
+        isCMatch CMatch{} = True
+        isCMatch _        = False
+
+        isUnguardedWild (CWild _ Nothing _) = True
+        isUnguardedWild _                   = False
+
+        headOffset (c:_) = caseOffset c
+        headOffset []    = Unknown
+
+-- | Validate that each constructor exists and has the right arity.
+checkArities :: String -> String -> [(Name, [Type])] -> [Case] -> Q ()
+checkArities label typ cstrs = mapM_ chk1
+  where chk1 c = case c of
+                    CMatch o nm ps _ _ _ -> isSafe o nm (length <$> ps)
+                    CWild  {}            -> pure ()
+        isSafe o nm mbLen
+          | Just ts <- lookupBase nm cstrs
+          = case mbLen of
+               Nothing  -> pure ()
+               Just cnt -> unless (length ts == cnt)
+                                $ fail o $ unlines [ label ++ ": Arity mismatch."
+                                                   , "        Type       : " ++ typ
+                                                   , "        Constructor: " ++ nameBase nm
+                                                   , "        Expected   : " ++ show (length ts)
+                                                   , "        Given      : " ++ show cnt
+                                                   ]
+          | True
+          = fail o $ unlines [ label ++ ": Unknown constructor:"
+                             , "        Type          : " ++ typ
+                             , "        Saw           : " ++ pprint nm
+                             , "        Must be one of: " ++ intercalate ", " (map (pprint . fst) cstrs)
+                             ]
+
+-- * sCase
+
+-- | Quasi-quoter for symbolic case expressions.
+sCase :: QuasiQuoter
+sCase = QuasiQuoter
+  { quoteExp  = extract
+  , quotePat  = bad "pattern"
+  , quoteType = bad "type"
+  , quoteDec  = bad "declaration"
+  }
+  where
+    bad ctx _ = fail Unknown $ "sCase: not usable in " <> ctx <> " context"
+
+    extract :: String -> ExpQ
+    extract src = do
+      let fullCase = "case " <> src
+          offsets  = findOffsets src
+      case metaParse fullCase of
+        Right (CaseE scrut matches) -> processCaseExp offsets scrut matches
+        Right _  -> fail Unknown "sCase: Parse error, cannot extract a case-expression."
+        Left err -> handleParseError "sCase" err
+
+-- | Core sCase pipeline: given a scrutinee and matches (already in TH AST form),
+-- run type inference, match conversion, validation, and code generation.
+-- Factored out of 'sCase' so that 'transformNestedCases' can call it for
+-- inner @case@ expressions.
+processCaseExp :: [Offset] -> Exp -> [Match] -> Q Exp
+processCaseExp offsets scrut0 matches0 = do
+    -- Transform any nested case expressions in the RHS/guards of each match.
+    -- This ensures inner cases become symbolic before the outer case processes them.
+    matches <- transformMatches matches0
+    scrut   <- transformNestedCases scrut0
+    mbTypeInfo <- inferType "sCase" matches
+    case mbTypeInfo of
+      Nothing -> do
+        -- Wildcard-only: no type needed, generate ite-chain directly
+        allCases <- concat <$> zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches
+        loc <- location
+        checkWildcard "sCase" loc allCases
+        let wilds = [(mbG, rhs) | CWild _ mbG rhs <- allCases]
+            -- An unguarded wildcard is the base case (no ite wrapper needed).
+            -- checkWildcard guarantees an unguarded wildcard is last if present.
+            iteChain []                       = do uniq <- newName "u"
+                                                   let suffix = drop 2 (show uniq)
+                                                   pure $ AppE (VarE 'symWithKind) (LitE (StringL ("unmatched_sCase_wildcard_" ++ suffix)))
+            iteChain ((Nothing, rhs) : _)     = pure rhs
+            iteChain ((Just g,  rhs) : rest)  = do r <- iteChain rest
+                                                   pure $ foldl AppE (VarE 'ite) [g, rhs, r]
+        iteChain wilds
+      Just (typ, mbt) -> do
+        mbFnName <- case mbt of
+          Just BTBool      -> pure Nothing
+          Just BTList      -> pure Nothing  -- Strategy B; see noAnalyzer comment above
+          Just BTMaybe     -> pure (Just (VarE (sbvName "Data.SBV.Maybe"  "sCaseMaybe")))
+          Just BTEither    -> pure (Just (VarE (sbvName "Data.SBV.Either" "sCaseEither")))
+          Just (BTTuple _) -> pure Nothing
+          Nothing -> let fnTok = "sCase" <> typ
+                     in lookupValueName fnTok >>= \case
+                          Just n  -> pure (Just (VarE n))
+                          Nothing -> fail Unknown $ unlines [ "sCase: Unknown symbolic ADT: " <> typ
+                                                            , ""
+                                                            , "        To use a symbolic case expression, declare your ADT, and then:"
+                                                            , "             mkSymbolic [''" <> typ <> "]"
+                                                            , "        In a template-haskell context."
+                                                            ]
+        let anyUserGuards = any (\(Match _ grhs _) -> case grhs of { GuardedB{} -> True; _ -> False }) matches
+        cases <- zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches >>= checkCase scrut typ mbt anyUserGuards . concat
+        buildCase typ mbFnName scrut cases
+  where
+    buildCase :: String -> Maybe Exp -> Exp -> Either [Exp] [(Exp, Exp)] -> ExpQ
+    buildCase _    (Just caseFunc) s (Left  cases) = pure $ AppE (foldl AppE caseFunc cases) s
+    buildCase _    Nothing         _     (Left  _)     = error "sCase: impossible: Strategy A without case function"
+    buildCase typ  _               _scrut (Right cases) = do
+        uniq <- newName "u"
+        let suffix = drop 2 (show uniq)
+            fallback  = AppE (VarE 'symWithKind) (LitE (StringL ("unmatched_sCase_" ++ typ ++ "_" ++ suffix)))
+
+            iteChain []              = pure fallback
+            iteChain ((t, e) : rest)
+              -- Last branch with a trivially-true guard (e.g., unguarded wildcard, or the last
+              -- constructor in a complete match): use its rhs directly as the default,
+              -- avoiding an unreachable fallback variable.
+              | null rest, isTriviallyTrue t = pure e
+              | True                         = do r <- iteChain rest
+                                                  pure $ foldl AppE (VarE 'ite) [t, e, r]
+
+            isTriviallyTrue (VarE nm) = nameBase nm == nameBase 'sTrue
+            isTriviallyTrue (ConE nm) = nameBase nm == "True"
+            isTriviallyTrue _         = False
+        iteChain cases
+
+    -- Make sure things are in good-shape and decide if we have guards
+    checkCase :: Exp -> String -> Maybe BuiltinType -> Bool -> [Case] -> Q (Either [Exp] [(Exp, Exp)])
+    checkCase s typ mbt anyUserGuards cases = do
+        loc   <- location
+        cstrs <- getCstrs mbt typ
+
+        -- Is there a catch all clause?
+        let hasCatchAll = or [True | CWild _ Nothing _ <- cases]
+
+        checkWildcard "sCase" loc cases
+        checkArities  "sCase" typ cstrs cases
+
+        -- Step 2: Make sure constructor matches are not overlapping
+        let problem w extras x = fail (caseOffset x) $ unlines $ [ "sCase: " ++ w ++ ":"
+                                                                 , "        Type       : " ++ typ
+                                                                 , "        Constructor: " ++ showCase x
+                                                                 ]
+                                                              ++ [ "      " ++ e | e <- extras]
+
+            overlap x xs = problem "Overlapping case constructors" extras x
+              where extras = "Overlaps with:" : ["  " ++ p | p <- map (showCaseGen (Just loc)) xs]
+
+            unmatched x
+             | isGuarded x = problem "Non-exhaustive match" ["NB. Guarded match might fail."] x
+             | True        = problem "Non-exhaustive match" []                                x
+
+            nonExhaustive o cstr = fail o $ unlines [ "sCase: Pattern match(es) are non-exhaustive."
+                                                    , "        Not matched     : " ++ nameBase cstr
+                                                    , "        Patterns of type: " ++ typ
+                                                    , "        Must match each : " ++ intercalate ", " (map (nameBase . fst) cstrs)
+                                                    , ""
+                                                    , "      You can use a '_' to match multiple cases."
+                                                    ]
+            -- We're done
+            chk2 _ [] = pure ()
+
+            -- If we have a non-guarded match, then there must be no matches for this constructor later on. If so, they're redundant.
+            chk2 seen (c@(CMatch _ nm _ Nothing _ _) : rest)
+              = case filter (maybe False (sameBase nm) . getCaseConstructor) rest of
+                  [] -> chk2 (Set.insert (nameBase nm) seen) rest
+                  os -> overlap (last os) (c : init os)
+
+            -- If we have a guarded match, then this guard can fail. So either there must be a match
+            -- for it later on, or there must be a catch-all. We also accept it if the same constructor
+            -- was seen earlier (e.g., multiple nested-pattern alternatives like Left (x:_) / Left []).
+            chk2 seen (c@(CMatch _ nm _ Just{} _ _) : rest)
+              | hasCatchAll || any (maybe False (sameBase nm) . getCaseConstructor) rest || nameBase nm `Set.member` seen
+              = chk2 (Set.insert (nameBase nm) seen) rest
+              | True
+              = unmatched c
+
+            -- If there's a guarded wildcard, must make sure there's a catch all afterwards
+            chk2 seen (c@(CWild _ Just{} _) : rest)
+              | hasCatchAll
+              = chk2 seen rest
+              | True
+              = unmatched c
+
+            -- No need to worry about anything following catch-all, since we already covered that before
+            chk2 seen (CWild _ Nothing _ : rest) = chk2 seen rest
+
+        chk2 Set.empty cases
+
+        -- At this point, we either have a simple case with no guards, in which case
+        -- we translate this to an sCase for that type. So find all alternatives.
+        -- Otherwise, this will become an ite-chain.
+        -- Bool, List, and Tuple use the ite-chain path (Strategy B) directly.
+        -- List is excluded from Strategy A because the case-analysis combinator 'list' is itself
+        -- a candidate for sCase rewriting; calling it here would create a circular dependency.
+        -- Maybe, Either, and user ADTs can use Strategy A (calling sCaseMaybe/sCaseEither/sCaseADT).
+        let hasGuards    = any isGuarded cases
+            noAnalyzer   = case mbt of { Just BTBool -> True; Just BTList -> True; Just (BTTuple _) -> True; _ -> False }
+            useIteChain  = hasGuards || noAnalyzer
+
+        if not useIteChain
+           then do defaultCase <- case [((e, mbg), c) | c@(CWild _ mbg e) <- cases] of
+                                    []                  -> pure Nothing
+                                    [((e, Nothing), c)] -> pure $ Just (caseOffset c, e)
+                                    cs@((_, c):_)       -> fail (caseOffset c)
+                                                         $ unlines $   "sCase: Impossible happened; found unexpected cases:"
+                                                                   :  [ "        " ++ showCase curc | curc <- map snd cs]
+                                                                   ++ [ ""
+                                                                      , "      Please report this as a bug."
+                                                                      ]
+                   let find _ []     = Nothing
+                       find w (c:cs)
+                         | mtches = Just c
+                         | True   = find w cs
+                         where mtches = case c of
+                                          CMatch _ nm _ _ _ _ -> sameBase nm w
+                                          CWild  {}           -> False
+
+                       case2rhs :: Case -> [Type] -> (Maybe Exp, Exp)
+                       case2rhs cs ts = (LamE pats <$> mbGuard, LamE pats e)
+                         where (mbGuard, e, pats) = case cs of
+                                                      CMatch _ _ (Just ps) mbG rhs _ -> (mbG, rhs, ps)
+                                                      CMatch _ _ Nothing   mbG rhs _ -> (mbG, rhs, map (const WildP) ts)
+                                                      CWild  _             mbG rhs   -> (mbG, rhs, map (const WildP) ts)
+
+                       collect (cstr, ts)
+                         | Just e <- find cstr cases
+                         = pure $ case2rhs e ts
+                         | True
+                         = case defaultCase of
+                             Nothing -> nonExhaustive Unknown cstr
+                             Just (_, de) -> do let ps = map (const WildP) ts
+                                                pure (Nothing, LamE ps de)
+
+                   res <- mapM collect cstrs
+
+                   -- If we reached here, all is well; except we might have an extra wildcard that we did not use
+                   when (length cases > length cstrs) $
+                     case defaultCase of
+                       Nothing     -> pure ()
+                       Just (o, _) -> fail o "sCase: Wildcard match is redundant"
+
+                   -- Double check that we had no guards and return the cases
+                   case [r | (Just{}, r) <- res] of
+                     [] -> pure $ Left $ map snd res
+                     rs -> fail Unknown $ unlines $    "sCase: Impossible happened; found a guard in no-guard case."
+                                                  :  [ "        " ++ pprint r | r <- rs]
+                                                  ++ [ ""
+                                                    , "      Please report this as a bug."
+                                                    ]
+
+           else do -- We have guards.
+                   defaultCase <- case [(c, e) | c@(CWild _ Nothing e) <- cases] of
+                                    []         -> pure Nothing
+                                    ((c, e):_) -> pure $ Just (caseOffset c, e)
+
+                   -- Collect, for each constructor, the corresponding cases:
+                   let cstrMatches :: [(Name, ([Type], [Case]))]
+                       cstrMatches = map (\(cstr, ts) -> (cstr, (ts, concatMap (mtches cstr) cases))) cstrs
+                         where mtches cstr c | Just n <- getCaseConstructor c, sameBase n cstr = [c]
+                                             | True                                            = []
+
+                   -- Make sure we have a match for every constructor or a catch-all
+                   unless hasCatchAll $ case [nm | (nm, (_, [])) <- cstrMatches] of
+                                          []    -> pure ()
+                                          (x:_) -> nonExhaustive Unknown x
+
+                   -- If every constructor have a full match, then catch-all, if exists, is redundant:
+                   case defaultCase of
+                     Nothing     -> pure ()
+                     Just (o, _)
+                       | map fst cstrs == [nm | (nm, (_, cs)) <- cstrMatches, not (all isGuarded cs)]
+                       -> fail o "sCase: Wildcard match is redundant"
+                       | True
+                       -> pure ()
+
+                   let collect :: Case -> Q (Exp, Exp)
+                       collect (CWild  _        mbG rhs        ) = pure (fromMaybe (VarE 'sTrue) mbG, rhs)
+                       collect (CMatch o nm mbp mbG rhs allUsed) = do
+                           case lookupBase nm cstrs of
+                             Nothing -> fail o $ unlines [ "sCase: Impossible happened."
+                                                         , "        Unable to determine params for: " <> pprint nm
+                                                         ]
+                             Just ts -> do let pats = fromMaybe (map (const WildP) ts) mbp
+                                               args = [mkAccessorFor mbt nm i s | (i, _) <- zip [(1 :: Int) ..] ts]
+                                               testerExpr = mkTesterFor mbt nm s
+
+                                               -- What are the free variables in the guard and the rhs that we bind?
+                                               used    = Set.fromList [n | VarP n <- pats] `Set.intersection` allUsed
+                                               close e = foldr1 (AppE . AppE (VarE 'const)) (e:extras)
+                                                 where extras = map VarE $ Set.toList (used Set.\\ freeVars e)
+
+                                               mkApp f | null pats = f
+                                                       | True      = foldl AppE (LamE pats f) args
+
+                                               grd :: Exp
+                                               grd = case mbG of
+                                                       Nothing -> testerExpr
+                                                       Just g  -> sAndAll [testerExpr, mkApp (close g)]
+
+                                           pure (grd, mkApp (close rhs))
+
+                   pairs <- mapM collect cases
+
+                   -- When every constructor has at least one unguarded match, the pattern
+                   -- is exhaustive. The last entry's tester is then redundant — replace it
+                   -- with sTrue so buildCase uses it as the default, avoiding an unreachable
+                   -- fallback variable.
+                   -- For single-constructor types (tuples), all branches match the sole
+                   -- constructor, with guards from nested patterns only. When there are no
+                   -- user-provided guards, the nested patterns partition the space and the
+                   -- last branch is the default.
+                   let allCovered = all hasUnguarded cstrs
+                                 || (length cstrs == 1 && not anyUserGuards)
+                       hasUnguarded (cstr, _) = any (\case CMatch _ nm _ Nothing _ _ -> sameBase nm cstr; _ -> False) cases
+                       optimize ps | allCovered, not (null ps)
+                                   = init ps ++ [(VarE 'sTrue, snd (last ps))]
+                                   | True      = ps
+
+                   pure $ Right (optimize pairs)
+
+-- | Transform nested @case@ expressions inside a TH 'Exp' into symbolic case expressions.
+-- Walks the expression bottom-up: inner cases are transformed before outer ones.
+-- This is what enables @case@ expressions inside @[sCase| ... |]@ to work as symbolic cases.
+transformNestedCases :: Exp -> Q Exp
+transformNestedCases = everywhereM (mkM go)
+  where go :: Exp -> Q Exp
+        go (CaseE s ms) = processCaseExp (repeat Unknown) s ms
+        go e            = pure e
+
+-- | Transform nested @case@ expressions inside a TH 'Exp' into proof case-splits.
+-- Like 'transformNestedCases', but generates @cases [cond ==> rhs, ...]@ instead of
+-- @ite@ chains. This is what enables @case@ expressions inside @[pCase| ... |]@ to work
+-- as nested proof case-splits.
+transformNestedCasesProof :: Exp -> Q Exp
+transformNestedCasesProof = everywhereM (mkM go)
+  where go :: Exp -> Q Exp
+        go (CaseE s ms) = processProofCaseExp s ms
+        go e            = pure e
+
+-- | Transform the matches of an outer sCase expression, resolving any nested
+-- @case@ expressions in the RHS and guards before the outer case processes them.
+transformMatches :: [Match] -> Q [Match]
+transformMatches = transformMatchesWith transformNestedCases
+
+-- | Transform the matches of an outer pCase expression, resolving any nested
+-- @case@ expressions in the RHS and guards as proof case-splits.
+transformMatchesProof :: [Match] -> Q [Match]
+transformMatchesProof = transformMatchesWith transformNestedCasesProof
+
+-- | Generic match transformer parameterized by the nested-case handler.
+transformMatchesWith :: (Exp -> Q Exp) -> [Match] -> Q [Match]
+transformMatchesWith xform = mapM transformMatch
+  where transformMatch (Match pat body locals) = do
+          body'   <- transformBody body
+          locals' <- mapM transformDec locals
+          pure (Match pat body' locals')
+
+        transformBody (NormalB e)    = NormalB <$> xform e
+        transformBody (GuardedB gs)  = GuardedB <$> mapM transformGuarded gs
+
+        transformGuarded (g, e) = do g' <- transformGuard g
+                                     e' <- xform e
+                                     pure (g', e')
+
+        transformGuard (NormalG e) = NormalG <$> xform e
+        transformGuard (PatG ss)   = PatG <$> mapM transformStmt ss
+
+        transformStmt (NoBindS e)  = NoBindS <$> xform e
+        transformStmt s            = pure s
+
+        transformDec (ValD p b ls) = do b'  <- transformBody b
+                                        ls' <- mapM transformDec ls
+                                        pure (ValD p b' ls')
+        transformDec (FunD n cs)   = FunD n <$> mapM transformClause cs
+        transformDec d             = pure d
+
+        transformClause (Clause ps b ls) = do b'  <- transformBody b
+                                              ls' <- mapM transformDec ls
+                                              pure (Clause ps b' ls')
+
+-- | Core proof-case pipeline: given a scrutinee and matches (in TH AST form),
+-- generate @cases [cond ==> rhs, ...]@. This is the proof-level counterpart of
+-- 'processCaseExp', used by 'transformNestedCasesProof' to handle inner @case@
+-- expressions inside @[pCase| ... |]@.
+processProofCaseExp :: Exp -> [Match] -> Q Exp
+processProofCaseExp scrut0 matches0 = do
+    -- Recursively transform any nested case expressions as proof case-splits.
+    matches <- transformMatchesProof matches0
+    scrut   <- transformNestedCasesProof scrut0
+    mbTypeInfo <- inferType "pCase" matches
+    let offsets = repeat Unknown
+    case mbTypeInfo of
+      Nothing -> do
+        allCases <- concat <$> zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches
+        loc <- location
+        checkWildcard "pCase" loc allCases
+        allPairs <- processProofCases scrut [] Nothing [] allCases
+        let casesName   = mkName "cases"
+            impliesName = mkName "==>"
+            mkPair (g, r) = InfixE (Just g) (VarE impliesName) (Just r)
+        pure $ AppE (VarE casesName) (ListE (map mkPair allPairs))
+      Just (typ, mbt) -> do
+        cs <- zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches
+        let cases = concat cs
+        loc <- location
+        cstrs <- getCstrs mbt typ
+        checkWildcard "pCase" loc cases
+        checkArities  "pCase" typ cstrs cases
+        allPairs <- processProofCases scrut cstrs mbt [] cases
+        let casesName   = mkName "cases"
+            impliesName = mkName "==>"
+            mkPair (g, r) = InfixE (Just g) (VarE impliesName) (Just r)
+        pure $ AppE (VarE casesName) (ListE (map mkPair allPairs))
+
+-- * pCase
+
+-- | Quasi-quoter for proof case-splits.
+--
+-- Like 'sCase', but generates @cases [cond ==> proof, ...]@ instead of
+-- @ite@ chains. Wildcards are allowed as the last scrutinee (with or
+-- without guards), and exhaustiveness is checked at proof time by the
+-- @cases@ combinator rather than at compile time.
+--
+-- Guards within the same constructor accumulate negations: a second guard
+-- implicitly assumes the first guard failed. A wildcard guard is the
+-- negation of the disjunction of all prior guards (De Morgan).
+pCase :: QuasiQuoter
+pCase = QuasiQuoter
+  { quoteExp  = extractProof
+  , quotePat  = bad "pattern"
+  , quoteType = bad "type"
+  , quoteDec  = bad "declaration"
+  }
+  where
+    bad ctx _ = fail Unknown $ "pCase: not usable in " <> ctx <> " context"
+
+    extractProof :: String -> ExpQ
+    extractProof src = do
+      let fullCase = "case " <> src
+          offsets  = findOffsets src
+      case metaParse fullCase of
+        Right (CaseE scrut0 matches0) -> do
+          -- Transform any nested case expressions in the RHS/guards of each match.
+          -- Inner case expressions become proof case-splits (cases [...]),
+          -- just like inner cases in sCase become symbolic ite-chains.
+          matches <- transformMatchesProof matches0
+          scrut   <- transformNestedCasesProof scrut0
+          mbTypeInfo <- inferType "pCase" matches
+          case mbTypeInfo of
+            Nothing -> do
+              -- Wildcard-only: no type needed, build proof cases directly
+              allCases <- concat <$> zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches
+              loc <- location
+              checkWildcard "pCase" loc allCases
+              allPairs <- processProofCases scrut [] Nothing [] allCases
+              let casesName   = mkName "cases"
+                  impliesName = mkName "==>"
+                  mkPair (g, r) = InfixE (Just g) (VarE impliesName) (Just r)
+              pure $ AppE (VarE casesName) (ListE (map mkPair allPairs))
+            Just (typ, mbt) -> do
+              cs <- zipWithM (matchToPair scrut) (offsets ++ repeat Unknown) matches
+              validated <- checkProofCase typ mbt (concat cs)
+              buildProofCase scrut typ mbt validated
+        Right _  -> fail Unknown "pCase: Parse error, cannot extract a case-expression."
+        Left err -> handleParseError "pCase" err
+
+    -- | Validate cases for proof context
+    checkProofCase :: String -> Maybe BuiltinType -> [Case] -> Q [Case]
+    checkProofCase typ mbt cases = do
+        loc <- location
+        cstrs <- getCstrs mbt typ
+
+        checkWildcard "pCase" loc cases
+        checkArities  "pCase" typ cstrs cases
+
+        -- Wildcards must come after all explicit constructor matches
+        let checkWildBeforeCstr [] = pure ()
+            checkWildBeforeCstr (CWild o _ _ : rest)
+              | any (\case CMatch{} -> True; _ -> False) rest
+              = fail o $ unlines $ "pCase: Wildcard must come after all constructor matches:"
+                                 : ["        " ++ showCaseGen (Just loc) r | r <- filter (\case CMatch{} -> True; _ -> False) rest]
+            checkWildBeforeCstr (_ : rest) = checkWildBeforeCstr rest
+        checkWildBeforeCstr cases
+
+        -- Check overlap: unguarded constructor match followed by same constructor
+        let chk2 [] = pure ()
+            chk2 (c@(CMatch _ nm _ Nothing _ _) : rest)
+              = case filter (maybe False (sameBase nm) . getCaseConstructor) rest of
+                  [] -> chk2 rest
+                  os -> overlap loc (last os) (c : init os)
+            chk2 (_ : rest) = chk2 rest
+
+        chk2 cases
+
+        -- If every constructor has an unguarded match, any wildcard is redundant
+        let fullyCovered = [ cstr | (cstr, _) <- cstrs
+                                  , any (\c -> maybe False (sameBase cstr) (getCaseConstructor c) && not (isGuarded c)) cases
+                                  ]
+        case [c | c@CWild{} <- cases] of
+          []    -> pure ()
+          (c:_) | length fullyCovered == length cstrs
+                -> fail (caseOffset c) "pCase: Wildcard match is redundant"
+                | True
+                -> pure ()
+
+        -- No exhaustiveness check: the `cases` combinator checks completeness at proof time.
+        pure cases
+
+    overlap loc x xs = fail (caseOffset x) $ unlines $ [ "pCase: Overlapping case constructors:"
+                                                        , "        Constructor: " ++ showCase x
+                                                        ]
+                                                     ++ [ "      Overlaps with:" ]
+                                                     ++ [ "        " ++ showCaseGen (Just loc) p | p <- xs]
+
+    -- | Build the proof case expression
+    buildProofCase :: Exp -> String -> Maybe BuiltinType -> [Case] -> ExpQ
+    buildProofCase scrut typ mbt cases = do
+        cstrs <- getCstrs mbt typ
+        allPairs <- processProofCases scrut cstrs mbt [] cases
+        let casesName   = mkName "cases"
+            impliesName = mkName "==>"
+            mkPair (g, r) = InfixE (Just g) (VarE impliesName) (Just r)
+        pure $ AppE (VarE casesName) (ListE (map mkPair allPairs))
+
+-- * Proof case processing
+
+-- | Process all proof cases linearly, accumulating prior guards.
+-- Shared between the top-level @pCase@ quasi-quoter and 'processProofCaseExp'
+-- (which handles nested @case@ expressions inside @[pCase| ... |]@).
+--
+-- Prior guards are tagged with their constructor name (Nothing for wildcards).
+-- Each entry stores (constructor, fullGuard, userGuardOnly):
+--
+--   * fullGuard    = the complete guard expression (used for wildcard De Morgan negation)
+--   * userGuardOnly = Just the user guard part (used for same-constructor negation),
+--                     Nothing if unguarded (same-constructor arms don't negate unguarded matches)
+processProofCases :: Exp -> [(Name, [Type])] -> Maybe BuiltinType -> [(Maybe Name, Exp, Maybe Exp)] -> [Case] -> Q [(Exp, Exp)]
+processProofCases scrut cstrs mbt priorGuards0 cases0 = go priorGuards0 cases0
+  where
+    -- Aggregate, per constructor, the variables used in any guard or RHS across all arms with that constructor.
+    -- A pattern var used in *some* same-constructor arm but not in *this* arm's RHS is dropped from the
+    -- RHS bindings (the guard handles its own bindings via 'grdBindings'), avoiding false unused-binding
+    -- warnings. A pattern var truly unused everywhere is kept so GHC can flag the user oversight.
+    cstrUsedVars :: Map.Map Name (Set Name)
+    cstrUsedVars = Map.fromListWith Set.union
+                     [ (nm, allUsed) | CMatch _ nm _ _ _ allUsed <- cases0 ]
+
+    go _           []         = pure []
+    go priorGuards (c:rest) = case c of
+      CWild _ mbG rhs -> do
+        -- Wildcard: negate the disjunction of ALL prior full guards (De Morgan)
+        let allGuards  = [g | (_, g, _) <- priorGuards]
+            baseGuard  = negateAllGuards allGuards
+            finalGuard = case mbG of
+                           Nothing -> baseGuard
+                           Just g  -> sAndAll [baseGuard, g]
+        rest' <- go (priorGuards ++ [(Nothing, finalGuard, Nothing)]) rest
+        pure $ (finalGuard, rhs) : rest'
+
+      CMatch _o nm mbp mbG rhs _allUsed -> do
+        let ts   = case lookupBase nm cstrs of
+                     Just t  -> t
+                     Nothing -> error $ "pCase: impossible: unknown constructor " ++ nameBase nm
+            pats = fromMaybe (map (const WildP) ts) mbp
+
+            -- Build let-bindings for pattern variables
+            args    = [(i, mkAccessorFor mbt nm i scrut) | (i, _) <- zip [(1 :: Int) ..] ts]
+            bindings = [ ValD (VarP v) (NormalB acc) []
+                       | (i, acc) <- args, VarP v <- [pats !! (i - 1)] ]
+
+            testerGuard = mkTesterFor mbt nm scrut
+
+            -- For list cons patterns in pCase, add a destructuring equality:
+            --   scrut .=== head scrut .: tail scrut
+            -- Lists use SMT Seq (not declare-datatypes), so the solver doesn't automatically
+            -- know that xs = head xs .: tail xs from sNot (null xs). We must add an explicit
+            -- equality to give the solver this information, mirroring what 'split' does.
+            -- All other types (ADTs, Maybe, Either, Tuple) use declare-datatypes and get
+            -- these axioms for free.
+            -- NB. For nested list cons patterns, the same equality is added by 'flattenCons'.
+            destructEq
+              | Just BTList <- mbt, nameBase nm == ":"
+              = let hd = AppE (VarE (sbvName "Data.SBV.List" "head")) scrut
+                    tl = AppE (VarE (sbvName "Data.SBV.List" "tail")) scrut
+                in [foldl1 AppE [VarE '(.===), scrut, InfixE (Just hd) (VarE '(.:)) (Just tl)]]
+              | True
+              = []
+
+            -- Only negate prior USER guards for the SAME constructor (others are mutually exclusive)
+            sameUserGuards = [ ug | (Just cn, _, Just ug) <- priorGuards, sameBase cn nm ]
+            negPriors      = map (AppE (VarE 'sNot)) sameUserGuards
+
+            -- Build the final guard (wrap user guard in bindings so pattern vars are in scope)
+            grdVars     = maybe Set.empty freeVars mbG
+            grdBindings = filter (\case
+                                     ValD (VarP v) _ _ -> v `Set.member` grdVars
+                                     _                 -> True) bindings
+            guardParts  = [testerGuard] ++ destructEq ++ negPriors ++ maybe [] (pure . addLocals grdBindings) mbG
+            finalGuard  = sAndAll guardParts
+
+            -- Wrap RHS with let-bindings. Keep a binding when the variable is used in this RHS, OR when
+            -- it isn't used in any same-constructor arm (so GHC can warn about a truly unused pattern var).
+            -- Drop it when used in some same-constructor arm but not here, to avoid spurious warnings.
+            cstrUsed = Map.findWithDefault Set.empty nm cstrUsedVars
+            rhsVars  = freeVars rhs
+            rhs'     = addLocals (filter (\case
+                                             ValD (VarP v) _ _ -> v `Set.member` rhsVars
+                                                               || not (v `Set.member` cstrUsed)
+                                             _                 -> True) bindings) rhs
+
+            -- Track: full guard for wildcard negation, user guard for same-constructor negation
+            userGuardOnly = case mbG of
+                              Just g  -> Just (addLocals grdBindings g)
+                              Nothing -> Nothing
+            priorGuards' = priorGuards ++ [(Just nm, finalGuard, userGuardOnly)]
+
+        rest' <- go priorGuards' rest
+        pure $ (finalGuard, rhs') : rest'
+
+-- | Negate the disjunction of all given guards using De Morgan: sNot (g1 .|| g2 .|| ...)
+negateAllGuards :: [Exp] -> Exp
+negateAllGuards [] = VarE 'sTrue
+negateAllGuards gs = AppE (VarE 'sNot) (foldl1 (\a b -> foldl1 AppE [VarE '(.||), a, b]) gs)
+
+-- * Standalone helpers
+
+-- | Free variables of an expression, respecting lexical scope.
+-- A variable is free if it is used (VarE) and not bound by any enclosing
+-- LetE, LamE, or CaseE at its use site.
+freeVars :: Exp -> Set Name
+freeVars = go Set.empty
+ where
+   go :: Set Name -> Exp -> Set Name
+   go bound = \case
+     VarE n          -> if n `Set.member` bound then Set.empty else Set.singleton n
+     ConE {}         -> Set.empty
+     LitE {}         -> Set.empty
+     AppE f x        -> go bound f <> go bound x
+     AppTypeE e _    -> go bound e
+     InfixE ml o mr  -> maybe Set.empty (go bound) ml <> go bound o <> maybe Set.empty (go bound) mr
+     UInfixE l o r   -> go bound l <> go bound o <> go bound r
+     ParensE e       -> go bound e
+     CondE c t f     -> go bound c <> go bound t <> go bound f
+     TupE mes        -> foldMap (maybe Set.empty (go bound)) mes
+     UnboxedTupE mes -> foldMap (maybe Set.empty (go bound)) mes
+     ListE es        -> foldMap (go bound) es
+     SigE e _        -> go bound e
+     RecConE _ fes   -> foldMap (go bound . snd) fes
+     RecUpdE e fes   -> go bound e <> foldMap (go bound . snd) fes
+     -- Binding forms: extend the bound set in the appropriate scope
+     LamE ps body    -> go (bound <> patsNames ps) body
+     LetE ds body    -> let bound' = bound <> decsNames ds
+                        in foldMap (goDec bound') ds <> go bound' body
+     CaseE scr ms    -> go bound scr <> foldMap (goMatch bound) ms
+     -- Fallback for other expression forms: conservatively report all
+     -- VarE names minus known bound (may over-report, never under-report)
+     other           -> allVarE other Set.\\ bound
+
+   goMatch :: Set Name -> Match -> Set Name
+   goMatch bound (Match pat body ds) =
+     let bound' = bound <> patNames pat <> decsNames ds
+     in goBody bound' body <> foldMap (goDec bound') ds
+
+   goBody :: Set Name -> Body -> Set Name
+   goBody bound (NormalB e)   = go bound e
+   goBody bound (GuardedB gs) = foldMap (\(g, e) -> goGuard bound g <> go bound e) gs
+
+   goGuard :: Set Name -> Guard -> Set Name
+   goGuard bound (NormalG e) = go bound e
+   goGuard _     _           = Set.empty
+
+   goDec :: Set Name -> Dec -> Set Name
+   goDec bound (ValD _ body ds)       = goBody bound body <> foldMap (goDec bound) ds
+   goDec bound (FunD _ cs)            = foldMap (goClause bound) cs
+   goDec _     _                      = Set.empty
+
+   goClause :: Set Name -> Clause -> Set Name
+   goClause bound (Clause ps body ds) =
+     let bound' = bound <> patsNames ps <> decsNames ds
+     in goBody bound' body <> foldMap (goDec bound') ds
+
+   -- Extract bound names from patterns
+   patNames :: Pat -> Set Name
+   patNames (VarP n)          = Set.singleton n
+   patNames (AsP n p)         = Set.singleton n <> patNames p
+   patNames (ConP _ _ ps)     = patsNames ps
+   patNames (InfixP p1 _ p2)  = patNames p1 <> patNames p2
+   patNames (UInfixP p1 _ p2) = patNames p1 <> patNames p2
+   patNames (TupP ps)         = patsNames ps
+   patNames (UnboxedTupP ps)  = patsNames ps
+   patNames (ListP ps)        = patsNames ps
+   patNames (SigP p _)        = patNames p
+   patNames (ParensP p)       = patNames p
+   patNames (TildeP p)        = patNames p
+   patNames (BangP p)         = patNames p
+   patNames (ViewP _ p)       = patNames p
+   patNames WildP             = Set.empty
+   patNames (LitP _)          = Set.empty
+   patNames _                 = Set.empty
+
+   patsNames :: [Pat] -> Set Name
+   patsNames = foldMap patNames
+
+   -- Extract bound names from declarations
+   decsNames :: [Dec] -> Set Name
+   decsNames ds = Set.fromList $ [n | ValD (VarP n) _ _ <- ds] ++ [n | FunD n _ <- ds]
+
+   -- Collect all VarE names in an expression (scope-unaware, for fallback only)
+   allVarE :: Exp -> Set Name
+   allVarE = \case
+     VarE n          -> Set.singleton n
+     AppE f x        -> allVarE f <> allVarE x
+     AppTypeE e _    -> allVarE e
+     InfixE ml o mr  -> maybe Set.empty allVarE ml <> allVarE o <> maybe Set.empty allVarE mr
+     UInfixE l o r   -> allVarE l <> allVarE o <> allVarE r
+     ParensE e       -> allVarE e
+     CondE c t f     -> allVarE c <> allVarE t <> allVarE f
+     TupE mes        -> foldMap (maybe Set.empty allVarE) mes
+     UnboxedTupE mes -> foldMap (maybe Set.empty allVarE) mes
+     ListE es        -> foldMap allVarE es
+     SigE e _        -> allVarE e
+     RecConE _ fes   -> foldMap (allVarE . snd) fes
+     RecUpdE e fes   -> allVarE e <> foldMap (allVarE . snd) fes
+     LamE _ body     -> allVarE body
+     LetE ds body    -> foldMap allVarEDec ds <> allVarE body
+     CaseE scr ms    -> allVarE scr <> foldMap allVarEMatch ms
+     _               -> Set.empty
+
+   allVarEMatch :: Match -> Set Name
+   allVarEMatch (Match _ body ds) = allVarEBody body <> foldMap allVarEDec ds
+
+   allVarEBody :: Body -> Set Name
+   allVarEBody (NormalB e)   = allVarE e
+   allVarEBody (GuardedB gs) = foldMap (\(_, e) -> allVarE e) gs
+
+   allVarEDec :: Dec -> Set Name
+   allVarEDec (ValD _ body ds) = allVarEBody body <> foldMap allVarEDec ds
+   allVarEDec (FunD _ cs)      = foldMap (\(Clause _ body ds) -> allVarEBody body <> foldMap allVarEDec ds) cs
+   allVarEDec _                = Set.empty
+
+-- | Count the number of arguments in a constructor type by counting arrows.
+-- e.g., @Integer -> String -> Bool@ has 2 arguments.
+-- Handles both plain ArrowT and multiplicity-annotated arrows (MulArrowT).
+countArgs :: Type -> Int
+countArgs (AppT (AppT ArrowT _) rest)            = 1 + countArgs rest
+countArgs (AppT (AppT (AppT MulArrowT _) _) rest) = 1 + countArgs rest
+countArgs (ForallT _ _ t)                         = countArgs t
+countArgs _                                       = 0
+
+-- | Generate a symbolic equality guard for a literal pattern.
+-- @litToEq off arg lit@ produces the expression @arg .== litVal@.
+-- For integers, the literal is used directly (relying on @fromInteger@).
+-- For characters and strings, the literal is wrapped with @literal@.
+litToEq :: Offset -> Exp -> Lit -> Q Exp
+litToEq _   arg (IntegerL n) = pure $ foldl1 AppE [VarE '(.==), arg, LitE (IntegerL n)]
+litToEq _   arg (CharL    c) = pure $ foldl1 AppE [VarE '(.==), arg, AppE (VarE 'literal) (LitE (CharL c))]
+litToEq _   arg (StringL  s) = pure $ foldl1 AppE [VarE '(.==), arg, AppE (VarE 'literal) (LitE (StringL s))]
+litToEq off _   lit          = fail off $ unlines
+  [ "sCase/pCase: Unsupported literal in pattern: " ++ show lit
+  , "       Only integer, character, and string literals are supported."
+  ]
diff --git a/Data/SBV/SEnum.hs b/Data/SBV/SEnum.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/SEnum.hs
@@ -0,0 +1,203 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.SEnum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Add support for symbolic enumerations via a quasi-quoter. The code in this
+-- file was initially generated by ChatGPT, which didn't quite work but was
+-- close enough to let me finish it off.
+--
+-- Provides a quasiquoter `[sEnum| ... |]` for enumerations, like:
+--
+-- > [sEnum| a .. |]       ==> enumFrom a
+-- > [sEnum| a, b .. |]    ==> enumFromThen a b
+-- > [sEnum| a .. c |]     ==> enumFromTo a c
+-- > [sEnum| a, b .. c |]  ==> enumFromThenTo a b c
+--
+-- All of @a@, @b@, @c@ can be arbitrary expressions.
+--
+-- If you pass invalid Haskell expressions or incorrect format, a detailed
+-- error is raised with source location.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskellQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SEnum (sEnum) where
+
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+
+import qualified Language.Haskell.Exts                  as Exts
+import qualified Language.Haskell.Meta.Parse            as Meta
+import qualified Language.Haskell.Meta.Syntax.Translate as Meta
+
+import Data.Char (isSpace)
+
+import Prelude hiding (enumFrom, enumFromThen, enumFromTo, enumFromThenTo)
+import Data.SBV.List  (enumFrom, enumFromThen, enumFromTo, enumFromThenToH)
+
+import Control.Monad (unless)
+import Data.List (isInfixOf, intercalate)
+
+-- | The `sEnum` quasiquoter.
+--
+-- Supports formats:
+--
+--   * [sEnum| a    ..   |]
+--   * [sEnum| a, b ..   |]
+--   * [sEnum| a    .. c |]
+--   * [sEnum| a, b .. c |]
+--
+-- All expressions may be arbitrary Haskell expressions, including floating point.
+sEnum :: QuasiQuoter
+sEnum = QuasiQuoter { quoteExp  = parseSEnumExpr
+                    , quotePat  = err "patterns"
+                    , quoteType = err "types"
+                    , quoteDec  = err "declarations"
+                    }
+  where err ctx = error $ "Data.SBV.sEnum does not support " ++ ctx
+
+-- | Parse the sequence syntax into a TH Exp. This isn't the most robust parser, but it gets the job done.
+parseSEnumExpr :: String -> Q Exp
+parseSEnumExpr input = do
+  loc <- location
+
+  -- Make sure there's a .. somewhere
+  unless (".." `isInfixOf` input) $ errorWithLoc loc "There must be exactly one occurrence of '..'"
+
+  -- Find that occurrence of ..
+  (prefix, mEnd) <- do
+        let walk ('.':'.':cs) sofar
+             | ".." `isInfixOf` cs = errorWithLoc loc "Unexpected multiple occurrences of '..'"
+             | True                = pure (reverse sofar, cs)
+            walk (c:cs)         sofar = walk cs (c : sofar)
+            walk ""             sofar = pure (reverse sofar, "")
+
+        (pre, post) <- walk (trim input) ""
+        pure (trim pre, case trim post of
+                          "" -> Nothing
+                          s  -> Just s)
+
+  -- Now find the comma in the prefix. We only expect one comma here; though I suspect there might be more
+  -- in complicated expressions. Let's ignore that for now.
+  prefixParts <- do
+       let walk (',':cs) sofar
+            | ',' `elem` cs = errorWithLoc loc "Unexpected multiple commas."
+            | True          = pure (reverse sofar, cs)
+           walk (c:cs) sofar = walk cs (c : sofar)
+           walk ""     sofar = pure (reverse sofar, "")
+
+           hasComma = ',' `elem` prefix
+
+       (pre, post) <- walk prefix ""
+
+       -- post can be empty but pre can't
+       case (trim pre, trim post) of
+         ("", _)  | hasComma -> errorWithLoc loc "parse error on input ','"
+                  | True     -> errorWithLoc loc "parse error on input '..'"
+         (a,  "") | hasComma -> errorWithLoc loc "parse error on input '..'"
+                  | True     -> pure [a]
+         (a,  b)             -> pure [a, b]
+
+  case (prefixParts, mEnd) of
+    ([a],    Nothing) -> varE 'enumFrom       `appE` parseHaskellExpr loc a
+    ([a, b], Nothing) -> varE 'enumFromThen   `appE` parseHaskellExpr loc a `appE` parseHaskellExpr loc b
+    ([a],    Just c)  -> varE 'enumFromTo     `appE` parseHaskellExpr loc a `appE`                               parseHaskellExpr loc c
+    ([a, b], Just c)  -> do ea <- parseHaskellExpr loc a
+                            eb <- parseHaskellExpr loc b
+                            ec <- parseHaskellExpr loc c
+                            -- Pass the from/then step as a hint when it's a statically-known integer
+                            -- (e.g. @[m, m-1 .. n]@ => @-1@). Exact-arithmetic instances fold it; the
+                            -- rest ignore it. See 'constStep'.
+                            varE 'enumFromThenToH `appE` pure ea `appE` pure eb `appE` pure ec `appE` liftMStep (constStep ea eb)
+
+    _ -> errorWithLoc loc $ unlines [ "Data.SBV.Enum: Invalid format. Use one of:"
+                                    , ""
+                                    , "  [sEnum| a    ..   |]"
+                                    , "  [sEnum| a, b ..   |]"
+                                    , "  [sEnum| a    .. c |]"
+                                    , "  [sEnum| a, b .. c |]"
+                                    ]
+
+-- | Read a parsed expression as @base + offset@: a single opaque atom plus an integer constant.
+-- @Nothing@ base means the whole thing is a pure integer constant. We only look through @+@ and @-@
+-- of integer literals; anything else is treated as an atom. This is intentionally a single-base
+-- peel, not a general linear normalizer -- it's exactly enough to recognize @m@, @m-1@, @m+k@, etc.
+peel :: Exp -> (Maybe Exp, Integer)
+peel (LitE (IntegerL n)) = (Nothing, n)
+peel (ParensE e)         = peel e
+peel (SigE e _)          = peel e
+peel (InfixE  (Just l)               (VarE op) (Just (LitE (IntegerL n)))) = shift op l n
+peel (UInfixE l                      (VarE op)       (LitE (IntegerL n)))   = shift op l n
+peel (InfixE  (Just (LitE (IntegerL n))) (VarE op) (Just r)) | base op == "+" = add (peel r) n
+peel (UInfixE (LitE (IntegerL n))        (VarE op)       r)  | base op == "+" = add (peel r) n
+peel e                   = (Just e, 0)
+
+-- | Helper for 'peel': fold a @base <op> lit@ where @op@ is @+@ or @-@.
+shift :: Name -> Exp -> Integer -> (Maybe Exp, Integer)
+shift op l n = case base op of
+                 "+" -> add (peel l) n
+                 "-" -> add (peel l) (negate n)
+                 _   -> (Just (UInfixE l (VarE op) (LitE (IntegerL n))), 0)
+
+-- | Add a constant to a peeled @(base, offset)@.
+add :: (Maybe Exp, Integer) -> Integer -> (Maybe Exp, Integer)
+add (b, k) n = (b, k + n)
+
+-- | Unqualified name of an operator (haskell-src-meta may leave it unqualified, so compare by base).
+base :: Name -> String
+base = nameBase
+
+-- | The from->then step @then - from@, when it's a statically-known integer (same atom on both
+-- sides, so the atoms cancel). Returns @Nothing@ for genuinely-symbolic steps (distinct atoms),
+-- in which case the quasiquoter falls back to the ordinary, hint-free behavior.
+constStep :: Exp -> Exp -> Maybe Integer
+constStep from thn
+  | bf == bt  = Just (kt - kf)
+  | True      = Nothing
+  where (bf, kf) = peel from
+        (bt, kt) = peel thn
+
+-- | Splice a @`Maybe` `Integer`@ step hint into the generated call.
+liftMStep :: Maybe Integer -> Q Exp
+liftMStep Nothing  = conE 'Nothing
+liftMStep (Just n) = conE 'Just `appE` litE (integerL n)
+
+-- | Parses a string into a Haskell TH Exp using haskell-src-meta
+parseHaskellExpr :: Loc -> String -> Q Exp
+parseHaskellExpr loc s = case parse (trim s) of
+                           Left err -> errorWithLoc loc $ intercalate "\n"
+                                                             [ "*** Could not parse expression:"
+                                                             , "***"
+                                                             , "***   " ++ s ++ if all isSpace s then "<empty>" else ""
+                                                             , "***"
+                                                             , "*** Error: " ++ err
+                                                             ]
+                           Right e  -> return e
+  where parse = fmap Meta.toExp . Meta.parseResultToEither . Exts.parseExpWithMode mode
+        mode = Exts.defaultParseMode {
+                  Exts.extensions = Exts.extensions Exts.defaultParseMode
+                                        ++ [ Exts.EnableExtension Exts.TypeApplications
+                                           , Exts.EnableExtension Exts.DataKinds
+                                           ]
+              }
+
+-- | Utility: add filename and line number to an error
+errorWithLoc :: Loc -> String -> Q a
+errorWithLoc loc msg = fail $ intercalate "\n" $ ("Data.SBV.sEnum: error at " ++ formatLoc loc)
+                                               : map ("        " ++) (lines msg)
+
+-- | Show `file.hs:line:col`
+formatLoc :: Loc -> String
+formatLoc loc = loc_filename loc ++ ":" ++ show line ++ ":" ++ show col
+  where (line, col) = loc_start loc
+
+-- | Trim whitespace from both ends
+trim :: String -> String
+trim = f . f
+  where f = reverse . dropWhile isSpace
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,566 +1,1092 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.SMT.SMT
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Abstraction of SMT solvers
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE DefaultSignatures   #-}
-
-module Data.SBV.SMT.SMT where
-
-import qualified Control.Exception as C
-
-import Control.Concurrent (newEmptyMVar, takeMVar, putMVar, forkIO)
-import Control.DeepSeq    (NFData(..))
-import Control.Monad      (when, zipWithM)
-import Data.Char          (isSpace)
-import Data.Int           (Int8, Int16, Int32, Int64)
-import Data.Function      (on)
-import Data.List          (intercalate, isPrefixOf, isInfixOf, sortBy)
-import Data.Word          (Word8, Word16, Word32, Word64)
-import System.Directory   (findExecutable)
-import System.Environment (getEnv)
-import System.Exit        (ExitCode(..))
-import System.IO          (hClose, hFlush, hPutStr, hGetContents, hGetLine)
-import System.Process     (runInteractiveProcess, waitForProcess, terminateProcess)
-
-import qualified Data.Map as M
-
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum
-import Data.SBV.BitVectors.Symbolic   (SMTEngine)
-import Data.SBV.SMT.SMTLib            (interpretSolverOutput, interpretSolverModelLine)
-import Data.SBV.Utils.Lib             (joinArgs, splitArgs)
-import Data.SBV.Utils.TDiff
-
--- | Extract the final configuration from a result
-resultConfig :: SMTResult -> SMTConfig
-resultConfig (Unsatisfiable c) = c
-resultConfig (Satisfiable c _) = c
-resultConfig (Unknown c _)     = c
-resultConfig (ProofError c _)  = c
-resultConfig (TimeOut c)       = c
-
--- | A 'prove' call results in a 'ThmResult'
-newtype ThmResult    = ThmResult    SMTResult
-
--- | A 'sat' call results in a 'SatResult'
--- The reason for having a separate 'SatResult' is to have a more meaningful 'Show' instance.
-newtype SatResult    = SatResult    SMTResult
-
--- | A 'safe' call results in a 'SafeResult'
-newtype SafeResult   = SafeResult   (Maybe String, String, SMTResult)
-
--- | An 'allSat' call results in a 'AllSatResult'. The boolean says whether
--- we should warn the user about prefix-existentials.
-newtype AllSatResult = AllSatResult (Bool, [SMTResult])
-
--- | User friendly way of printing theorem results
-instance Show ThmResult where
-  show (ThmResult r) = showSMTResult "Q.E.D."
-                                     "Unknown"     "Unknown. Potential counter-example:\n"
-                                     "Falsifiable" "Falsifiable. Counter-example:\n" r
-
--- | User friendly way of printing satisfiablity results
-instance Show SatResult where
-  show (SatResult r) = showSMTResult "Unsatisfiable"
-                                     "Unknown"     "Unknown. Potential model:\n"
-                                     "Satisfiable" "Satisfiable. Model:\n" r
-
--- | User friendly way of printing safety results
-instance Show SafeResult where
-   show (SafeResult (mbLoc, msg, r)) = showSMTResult (tag "No violations detected")
-                                                     (tag "Unknown")  (tag "Unknown. Potential violating model:\n")
-                                                     (tag "Violated") (tag "Violated. Model:\n") r
-        where loc   = maybe "" (++ ": ") mbLoc
-              tag s = loc ++ msg ++ ": " ++ s
-
--- | 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 (e, xs)) = go (0::Int) xs
-    where uniqueWarn | e    = " (Unique up to prefix existentials.)"
-                     | True = ""
-          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 c of
-                          0 -> "No solutions found."
-                          1 -> "This is the only solution." ++ uniqueWarn
-                          _ -> "Found " ++ show c ++ " different solutions." ++ uniqueWarn
-          sh i c = (ok, showSMTResult "Unsatisfiable"
-                                      "Unknown" "Unknown. Potential model:\n"
-                                      ("Solution #" ++ show i ++ ":\nSatisfiable") ("Solution #" ++ show i ++ ":\n") c)
-              where ok = case c of
-                           Satisfiable{} -> True
-                           _             -> False
-
--- | Instances of 'SatModel' can be automatically extracted from models returned by the
--- solvers. The idea is that the sbv infrastructure provides a stream of 'CW''s (constant-words)
--- coming from the solver, and the type @a@ is interpreted based on these constants. Many typical
--- instances are already provided, so new instances can be declared with relative ease.
---
--- Minimum complete definition: 'parseCWs'
-class SatModel a where
-  -- | Given a sequence of constant-words, extract one instance of the type @a@, returning
-  -- the remaining elements untouched. If the next element is not what's expected for this
-  -- type you should return 'Nothing'
-  parseCWs  :: [CW] -> Maybe (a, [CW])
-  -- | Given a parsed model instance, transform it using @f@, and return the result.
-  -- The default definition for this method should be sufficient in most use cases.
-  cvtModel  :: (a -> Maybe b) -> Maybe (a, [CW]) -> Maybe (b, [CW])
-  cvtModel f x = x >>= \(a, r) -> f a >>= \b -> return (b, r)
-
-  default parseCWs :: Read a => [CW] -> Maybe (a, [CW])
-  parseCWs (CW _ (CWUserSort (_, s)) : r) = Just (read s, r)
-  parseCWs _                              = Nothing
-
--- | Parse a signed/sized value from a sequence of CWs
-genParse :: Integral a => Kind -> [CW] -> Maybe (a, [CW])
-genParse k (x@(CW _ (CWInteger i)):r) | kindOf x == k = Just (fromIntegral i, r)
-genParse _ _                                          = Nothing
-
--- | Base case for 'SatModel' at unit type. Comes in handy if there are no real variables.
-instance SatModel () where
-  parseCWs xs = return ((), xs)
-
--- | 'Bool' as extracted from a model
-instance SatModel Bool where
-  parseCWs xs = do (x, r) <- genParse KBool xs
-                   return ((x :: Integer) /= 0, r)
-
--- | 'Word8' as extracted from a model
-instance SatModel Word8 where
-  parseCWs = genParse (KBounded False 8)
-
--- | 'Int8' as extracted from a model
-instance SatModel Int8 where
-  parseCWs = genParse (KBounded True 8)
-
--- | 'Word16' as extracted from a model
-instance SatModel Word16 where
-  parseCWs = genParse (KBounded False 16)
-
--- | 'Int16' as extracted from a model
-instance SatModel Int16 where
-  parseCWs = genParse (KBounded True 16)
-
--- | 'Word32' as extracted from a model
-instance SatModel Word32 where
-  parseCWs = genParse (KBounded False 32)
-
--- | 'Int32' as extracted from a model
-instance SatModel Int32 where
-  parseCWs = genParse (KBounded True 32)
-
--- | 'Word64' as extracted from a model
-instance SatModel Word64 where
-  parseCWs = genParse (KBounded False 64)
-
--- | 'Int64' as extracted from a model
-instance SatModel Int64 where
-  parseCWs = genParse (KBounded True 64)
-
--- | 'Integer' as extracted from a model
-instance SatModel Integer where
-  parseCWs = genParse KUnbounded
-
--- | 'AlgReal' as extracted from a model
-instance SatModel AlgReal where
-  parseCWs (CW KReal (CWAlgReal i) : r) = Just (i, r)
-  parseCWs _                            = Nothing
-
--- | 'Float' as extracted from a model
-instance SatModel Float where
-  parseCWs (CW KFloat (CWFloat i) : r) = Just (i, r)
-  parseCWs _                           = Nothing
-
--- | 'Double' as extracted from a model
-instance SatModel Double where
-  parseCWs (CW KDouble (CWDouble i) : r) = Just (i, r)
-  parseCWs _                             = Nothing
-
--- | 'CW' as extracted from a model; trivial definition
-instance SatModel CW where
-  parseCWs (cw : r) = Just (cw, r)
-  parseCWs []       = Nothing
-
--- | A rounding mode, extracted from a model. (Default definition suffices)
-instance SatModel RoundingMode
-
--- | A list of values as extracted from a model. When reading a list, we
--- go as long as we can (maximal-munch). Note that this never fails, as
--- we can always return the empty list!
-instance SatModel a => SatModel [a] where
-  parseCWs [] = Just ([], [])
-  parseCWs xs = case parseCWs xs of
-                  Just (a, ys) -> case parseCWs ys of
-                                    Just (as, zs) -> Just (a:as, zs)
-                                    Nothing       -> Just ([], ys)
-                  Nothing     -> Just ([], xs)
-
--- | Tuples extracted from a model
-instance (SatModel a, SatModel b) => SatModel (a, b) where
-  parseCWs as = do (a, bs) <- parseCWs as
-                   (b, cs) <- parseCWs bs
-                   return ((a, b), cs)
-
--- | 3-Tuples extracted from a model
-instance (SatModel a, SatModel b, SatModel c) => SatModel (a, b, c) where
-  parseCWs as = do (a,      bs) <- parseCWs as
-                   ((b, c), ds) <- parseCWs bs
-                   return ((a, b, c), ds)
-
--- | 4-Tuples extracted from a model
-instance (SatModel a, SatModel b, SatModel c, SatModel d) => SatModel (a, b, c, d) where
-  parseCWs as = do (a,         bs) <- parseCWs as
-                   ((b, c, d), es) <- parseCWs bs
-                   return ((a, b, c, d), es)
-
--- | 5-Tuples extracted from a model
-instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e) => SatModel (a, b, c, d, e) where
-  parseCWs as = do (a, bs)            <- parseCWs as
-                   ((b, c, d, e), fs) <- parseCWs bs
-                   return ((a, b, c, d, e), fs)
-
--- | 6-Tuples extracted from a model
-instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e, SatModel f) => SatModel (a, b, c, d, e, f) where
-  parseCWs as = do (a, bs)               <- parseCWs as
-                   ((b, c, d, e, f), gs) <- parseCWs bs
-                   return ((a, b, c, d, e, f), gs)
-
--- | 7-Tuples extracted from a model
-instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e, SatModel f, SatModel g) => SatModel (a, b, c, d, e, f, g) where
-  parseCWs as = do (a, bs)                  <- parseCWs as
-                   ((b, c, d, e, f, g), hs) <- parseCWs bs
-                   return ((a, b, c, d, e, f, g), hs)
-
--- | Various SMT results that we can extract models out of.
-class Modelable a where
-  -- | Is there a model?
-  modelExists :: a -> Bool
-  -- | Extract a model, the result is a tuple where the first argument (if True)
-  -- indicates whether the model was "probable". (i.e., if the solver returned unknown.)
-  getModel :: SatModel b => a -> Either String (Bool, b)
-  -- | Extract a model dictionary. Extract a dictionary mapping the variables to
-  -- their respective values as returned by the SMT solver. Also see `getModelDictionaries`.
-  getModelDictionary :: a -> M.Map String CW
-  -- | Extract a model value for a given element. Also see `getModelValues`.
-  getModelValue :: SymWord b => String -> a -> Maybe b
-  getModelValue v r = fromCW `fmap` (v `M.lookup` getModelDictionary r)
-  -- | Extract a representative name for the model value of an uninterpreted kind.
-  -- This is supposed to correspond to the value as computed internally by the
-  -- SMT solver; and is unportable from solver to solver. Also see `getModelUninterpretedValues`.
-  getModelUninterpretedValue :: String -> a -> Maybe String
-  getModelUninterpretedValue v r = case v `M.lookup` getModelDictionary r of
-                                     Just (CW _ (CWUserSort (_, s))) -> Just s
-                                     _                               -> Nothing
-
-  -- | A simpler variant of 'getModel' to get a model out without the fuss.
-  extractModel :: SatModel b => a -> Maybe b
-  extractModel a = case getModel a of
-                     Right (_, b) -> Just b
-                     _            -> Nothing
-
--- | Return all the models from an '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 getModel xs]
-
--- | Get dictionaries from an all-sat call. Similar to `getModelDictionary`.
-getModelDictionaries :: AllSatResult -> [M.Map String CW]
-getModelDictionaries (AllSatResult (_, xs)) = map getModelDictionary xs
-
--- | Extract value of a variable from an all-sat call. Similar to `getModelValue`.
-getModelValues :: SymWord b => String -> AllSatResult -> [Maybe b]
-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
-
--- | 'ThmResult' as a generic model provider
-instance Modelable ThmResult where
-  getModel           (ThmResult r) = getModel r
-  modelExists        (ThmResult r) = modelExists r
-  getModelDictionary (ThmResult r) = getModelDictionary r
-
--- | 'SatResult' as a generic model provider
-instance Modelable SatResult where
-  getModel           (SatResult r) = getModel r
-  modelExists        (SatResult r) = modelExists r
-  getModelDictionary (SatResult r) = getModelDictionary r
-
--- | 'SMTResult' as a generic model provider
-instance Modelable SMTResult where
-  getModel (Unsatisfiable _) = Left "SBV.getModel: Unsatisfiable result"
-  getModel (Unknown _ m)     = Right (True, parseModelOut m)
-  getModel (ProofError _ s)  = error $ unlines $ "Backend solver complains: " : s
-  getModel (TimeOut _)       = Left "Timeout"
-  getModel (Satisfiable _ m) = Right (False, parseModelOut m)
-  modelExists Satisfiable{}   = True
-  modelExists Unknown{}       = False -- don't risk it
-  modelExists _               = False
-  getModelDictionary (Unsatisfiable _) = M.empty
-  getModelDictionary (Unknown _ m)     = M.fromList (modelAssocs m)
-  getModelDictionary (ProofError _ _)  = M.empty
-  getModelDictionary (TimeOut _)       = M.empty
-  getModelDictionary (Satisfiable _ m) = M.fromList (modelAssocs m)
-
--- | Extract a model out, will throw error if parsing is unsuccessful
-parseModelOut :: SatModel a => SMTModel -> a
-parseModelOut m = case parseCWs [c | (_, c) <- modelAssocs m] of
-                   Just (x, []) -> x
-                   Just (_, ys) -> error $ "SBV.getModel: Partially constructed model; remaining elements: " ++ show ys
-                   Nothing      -> error $ "SBV.getModel: Cannot construct a model from: " ++ show m
-
--- | Given an 'allSat' call, we typically want to iterate over it and print the results in sequence. The
--- 'displayModels' function automates this task by calling 'disp' on each result, consecutively. The first
--- '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
-    inds <- zipWithM display [a | Right a <- map (getModel . SatResult) ms] [(1::Int)..]
-    return $ last (0:inds)
-  where display r i = disp i r >> return i
-
--- | Show an SMTResult; generic version
-showSMTResult :: String -> String -> String -> String -> String -> SMTResult -> String
-showSMTResult unsatMsg unkMsg unkMsgModel satMsg satMsgModel result = case result of
-  Unsatisfiable _             -> unsatMsg
-  Satisfiable _ (SMTModel []) -> satMsg
-  Satisfiable _ m             -> satMsgModel ++ showModel cfg m
-  Unknown     _ (SMTModel []) -> unkMsg
-  Unknown     _ m             -> unkMsgModel ++ showModel cfg m
-  ProofError  _ []            -> "*** An error occurred. No additional information available. Try running in verbose mode"
-  ProofError  _ ls            -> "*** An error occurred.\n" ++ intercalate "\n" (map ("***  " ++) ls)
-  TimeOut     _               -> "*** Timeout"
- where cfg = resultConfig result
-
--- | 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
-   | null allVars
-   = "[There are no variables bound by the model.]"
-   | null relevantVars
-   = "[There are no model-variables bound by the model.]"
-   | True
-   = intercalate "\n" . display . map shM $ relevantVars
-  where allVars       = modelAssocs model
-        relevantVars  = filter (not . ignore) allVars
-        ignore (s, _) = "__internal_sbv_" `isPrefixOf` s || isNonModelVar cfg s
-        shM (s, v)    = let vs = shCW cfg v in ((length s, s), (vlength vs, vs))
-        display svs   = map line svs
-           where line ((_, s), (_, v)) = "  " ++ right (nameWidth - length s) s ++ " = " ++ left (valWidth - lTrimRight (valPart v)) v
-                 nameWidth             = maximum $ 0 : [l | ((l, _), _) <- svs]
-                 valWidth              = maximum $ 0 : [l | (_, (l, _)) <- svs]
-        right p s = s ++ replicate p ' '
-        left  p s = replicate p ' ' ++ s
-        vlength s = case dropWhile (/= ':') (reverse (takeWhile (/= '\n') s)) of
-                      (':':':':r) -> length (dropWhile isSpace r)
-                      _           -> length s -- conservative
-        valPart ""          = ""
-        valPart (':':':':_) = ""
-        valPart (x:xs)      = x : valPart xs
-        lTrimRight = length . dropWhile isSpace . reverse
-
--- | Show a constant value, in the user-specified base
-shCW :: SMTConfig -> CW -> String
-shCW = sh . printBase
-  where sh 2  = binS
-        sh 10 = show
-        sh 16 = hexS
-        sh n  = \w -> show w ++ " -- Ignoring unsupported printBase " ++ show n ++ ", use 2, 10, or 16."
-
--- | Print uninterpreted function values from models. Very, very crude..
-shUI :: (String, [String]) -> [String]
-shUI (flong, cases) = ("  -- uninterpreted: " ++ f) : map shC cases
-  where tf = dropWhile (/= '_') flong
-        f  =  if null tf then flong else tail tf
-        shC s = "       " ++ s
-
--- | Print uninterpreted array values from models. Very, very crude..
-shUA :: (String, [String]) -> [String]
-shUA (f, cases) = ("  -- array: " ++ f) : map shC cases
-  where shC s = "       " ++ s
-
--- | Helper function to spin off to an SMT solver.
-pipeProcess :: SMTConfig -> String -> [String] -> SMTScript -> (String -> String) -> IO (Either String [String])
-pipeProcess cfg execName opts script cleanErrs = do
-        let nm = show (name (solver cfg))
-        mbExecPath <- findExecutable execName
-        case mbExecPath of
-          Nothing       -> return $ Left $ "Unable to locate executable for " ++ nm
-                                        ++ "\nExecutable specified: " ++ show execName
-          Just execPath ->
-                   do solverResult <- dispatchSolver cfg execPath opts script
-                      case solverResult of
-                        Left s                          -> return $ Left s
-                        Right (ec, contents, allErrors) ->
-                          let errors = dropWhile isSpace (cleanErrs allErrors)
-                          in case (null errors, ec) of
-                                (True, ExitSuccess)  -> return $ Right $ map clean (filter (not . null) (lines contents))
-                                (_, ec')             -> let errors' = if null errors
-                                                                      then (if null (dropWhile isSpace contents)
-                                                                            then "(No error message printed on stderr by the executable.)"
-                                                                            else contents)
-                                                                      else errors
-                                                            finalEC = case (ec', ec) of
-                                                                        (ExitFailure n, _) -> n
-                                                                        (_, ExitFailure n) -> n
-                                                                        _                  -> 0 -- can happen if ExitSuccess but there is output on stderr
-                                                        in return $ Left $  "Failed to complete the call to " ++ nm
-                                                                         ++ "\nExecutable   : " ++ show execPath
-                                                                         ++ "\nOptions      : " ++ joinArgs opts
-                                                                         ++ "\nExit code    : " ++ show finalEC
-                                                                         ++ "\nSolver output: "
-                                                                         ++ "\n" ++ line ++ "\n"
-                                                                         ++ intercalate "\n" (filter (not . null) (lines errors'))
-                                                                         ++ "\n" ++ line
-                                                                         ++ "\nGiving up.."
-  where clean = reverse . dropWhile isSpace . reverse . dropWhile isSpace
-        line  = replicate 78 '='
-
--- | The standard-model that most SMT solvers should happily work with
-standardModel :: (Bool -> [(Quantifier, NamedSymVar)] -> [String] -> SMTModel, SW -> String -> [String])
-standardModel = (standardModelExtractor, standardValueExtractor)
-
--- | Some solvers (Z3) require multiple calls for certain value extractions; as in multi-precision reals. Deal with that here
-standardValueExtractor :: SW -> String -> [String]
-standardValueExtractor _ l = [l]
-
--- | A standard post-processor: Reading the lines of solver output and turning it into a model:
-standardModelExtractor :: Bool -> [(Quantifier, NamedSymVar)] -> [String] -> SMTModel
-standardModelExtractor isSat qinps solverLines = SMTModel { modelAssocs = map snd $ sortByNodeId $ concatMap (interpretSolverModelLine inps) solverLines }
-         where sortByNodeId :: [(Int, a)] -> [(Int, a)]
-               sortByNodeId = sortBy (compare `on` fst)
-               inps -- for "sat", display the prefix existentials. For completeness, we will drop
-                    -- only the trailing foralls. Exception: Don't drop anything if it's all a sequence of foralls
-                    | isSat = map snd $ if all (== ALL) (map fst qinps)
-                                        then qinps
-                                        else reverse $ dropWhile ((== ALL) . fst) $ reverse qinps
-                    -- for "proof", just display the prefix universals
-                    | True  = map snd $ takeWhile ((== ALL) . fst) qinps
-
--- | A standard engine interface. Most solvers follow-suit here in how we "chat" to them..
-standardEngine :: String
-               -> String
-               -> ([String] -> Int -> [String])
-               -> (Bool -> [(Quantifier, NamedSymVar)] -> [String] -> SMTModel, SW -> String -> [String])
-               -> SMTEngine
-standardEngine envName envOptName addTimeOut (extractMap, extractValue) cfg isSat qinps skolemMap pgm = do
-    execName <-                    getEnv envName     `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-    execOpts <- (splitArgs `fmap`  getEnv envOptName) `C.catch` (\(_ :: C.SomeException) -> return (options (solver cfg)))
-    let cfg'    = cfg {solver = (solver cfg) {executable = execName, options = maybe execOpts (addTimeOut execOpts) (timeOut cfg)}}
-        tweaks  = case solverTweaks cfg' of
-                    [] -> ""
-                    ts -> unlines $ "; --- user given solver tweaks ---" : ts ++ ["; --- end of user given tweaks ---"]
-        cont rm = intercalate "\n" $ concatMap extract skolemMap
-           where extract (Left s)        = extractValue s $ "(echo \"((" ++ show s ++ " " ++ mkSkolemZero rm (kindOf s) ++ "))\")"
-                 extract (Right (s, [])) = extractValue s $ "(get-value (" ++ show s ++ "))"
-                 extract (Right (s, ss)) = extractValue s $ "(get-value (" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ "))"
-        script = SMTScript {scriptBody = tweaks ++ pgm, scriptModel = Just (cont (roundingMode cfg))}
-    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps))
-
--- | A standard solver interface. If the solver is SMT-Lib compliant, then this function should suffice in
--- communicating with it.
-standardSolver :: SMTConfig -> SMTScript -> (String -> String) -> ([String] -> a) -> ([String] -> a) -> IO a
-standardSolver config script cleanErrs failure success = do
-    let msg      = when (verbose config) . putStrLn . ("** " ++)
-        smtSolver= solver config
-        exec     = executable smtSolver
-        opts     = options smtSolver
-        isTiming = timing config
-        nmSolver = show (name smtSolver)
-    msg $ "Calling: " ++ show (unwords (exec:[joinArgs opts]))
-    case smtFile config of
-      Nothing -> return ()
-      Just f  -> do msg $ "Saving the generated script in file: " ++ show f
-                    writeFile f (scriptBody script)
-    contents <- timeIf isTiming (WorkByProver nmSolver) $ pipeProcess config  exec opts script cleanErrs
-    msg $ nmSolver ++ " output:\n" ++ either id (intercalate "\n") contents
-    case contents of
-      Left e   -> return $ failure (lines e)
-      Right xs -> return $ success (mergeSExpr xs)
-
--- | Wrap the solver call to protect against any exceptions
-dispatchSolver :: SMTConfig -> FilePath -> [String] -> SMTScript -> IO (Either String (ExitCode, String, String))
-dispatchSolver cfg execPath opts script = rnf script `seq` (Right `fmap` runSolver cfg execPath opts script) `C.catch` (\(e::C.SomeException) -> bad (show e))
-  where bad s = return $ Left $ unlines [ "Failed to start the external solver: " ++ s
-                                        , "Make sure you can start " ++ show execPath
-                                        , "from the command line without issues."
-                                        ]
-
--- | A variant of 'readProcessWithExitCode'; except it knows about continuation strings
--- and can speak SMT-Lib2 (just a little).
-runSolver :: SMTConfig -> FilePath -> [String] -> SMTScript -> IO (ExitCode, String, String)
-runSolver cfg execPath opts script
- = do (send, ask, cleanUp, pid) <- do
-                (inh, outh, errh, pid) <- runInteractiveProcess execPath opts Nothing Nothing
-                let send l    = hPutStr inh (l ++ "\n") >> hFlush inh
-                    recv      = hGetLine outh
-                    ask l     = send l >> recv
-                    cleanUp response
-                        = do hClose inh
-                             outMVar <- newEmptyMVar
-                             out <- hGetContents outh
-                             _ <- forkIO $ C.evaluate (length out) >> putMVar outMVar ()
-                             err <- hGetContents errh
-                             _ <- forkIO $ C.evaluate (length err) >> putMVar outMVar ()
-                             takeMVar outMVar
-                             takeMVar outMVar
-                             hClose outh
-                             hClose errh
-                             ex <- waitForProcess pid
-                             return $ case response of
-                                        Nothing        -> (ex, out, err)
-                                        Just (r, vals) -> -- if the status is unknown, prepare for the possibility of not having a model
-                                                          -- TBD: This is rather crude and potentially Z3 specific
-                                                          let finalOut = intercalate "\n" (r : vals)
-                                                              notAvail = "model is not available" `isInfixOf` (finalOut ++ out ++ err)
-                                                          in if "unknown" `isPrefixOf` r && notAvail
-                                                             then (ExitSuccess, "unknown"              , "")
-                                                             else (ex,          finalOut ++ "\n" ++ out, err)
-                return (send, ask, cleanUp, pid)
-      let executeSolver = do mapM_ send (lines (scriptBody script))
-                             response <- case scriptModel script of
-                                           Nothing -> do send $ satCmd cfg
-                                                         return Nothing
-                                           Just ls -> do r <- ask $ satCmd cfg
-                                                         vals <- if any (`isPrefixOf` r) ["sat", "unknown"]
-                                                                 then do let mls = lines ls
-                                                                         when (verbose cfg) $ do putStrLn "** Sending the following model extraction commands:"
-                                                                                                 mapM_ putStrLn mls
-                                                                         mapM ask mls
-                                                                 else return []
-                                                         return $ Just (r, vals)
-                             cleanUp response
-      executeSolver `C.onException`  (terminateProcess pid >> waitForProcess pid)
-
--- | 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. We'll ignore things like parentheses inside quotes
--- etc., as it should not be an issue
-mergeSExpr :: [String] -> [String]
-mergeSExpr []       = []
-mergeSExpr (x:xs)
- | d == 0 = x : mergeSExpr xs
- | True   = let (f, r) = grab d xs in unwords (x:f) : mergeSExpr r
- where d = parenDiff x
-       parenDiff :: String -> Int
-       parenDiff = go 0
-         where go i ""       = i
-               go i ('(':cs) = let i'= i+1 in i' `seq` go i' cs
-               go i (')':cs) = let i'= i-1 in i' `seq` go i' cs
-               go i (_  :cs) = go i cs
-       grab i ls
-         | i <= 0    = ([], ls)
-       grab _ []     = ([], [])
-       grab i (l:ls) = let (a, b) = grab (i+parenDiff l) ls in (l:a, b)
+-- Module    : Data.SBV.SMT.SMT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Abstraction of SMT solvers
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns               #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NamedFieldPuns             #-}
+{-# LANGUAGE NumericUnderscores         #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE RankNTypes                 #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+{-# LANGUAGE TypeApplications           #-}
+{-# LANGUAGE UndecidableInstances       #-}
+{-# LANGUAGE ViewPatterns               #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SMT.SMT (
+       -- * Model extraction
+         Modelable(..)
+       , SatModel(..), genParse
+       , extractModels, getModelValues
+       , getModelDictionaries
+       , displayModels, showModel, shCV, showModelDictionary
+
+       -- * Standard prover engine
+       , standardEngine
+
+       -- * Results of various tasks
+       , ThmResult(..)
+       , SatResult(..)
+       , AllSatResult(..)
+       , SafeResult(..)
+       , OptimizeResult(..)
+       )
+       where
+
+import qualified Control.Exception as C
+
+import Control.Concurrent (newEmptyMVar, takeMVar, putMVar, forkIO)
+import Control.DeepSeq    (NFData(..))
+import Control.Monad      (zipWithM, mplus)
+import Data.Char          (isSpace)
+import Data.Maybe         (isJust)
+import Data.Int           (Int8, Int16, Int32, Int64)
+import Data.List          (intercalate, isPrefixOf, transpose, isInfixOf)
+import Data.Word          (Word8, Word16, Word32, Word64)
+
+import GHC.TypeLits
+import Data.Proxy
+
+import Data.IORef (readIORef, writeIORef)
+
+import Data.Either (rights)
+
+import System.Directory   (findExecutable)
+import System.Environment (getEnv, lookupEnv)
+import System.Exit        (ExitCode(..))
+import System.IO          (hClose, hFlush, hGetContents, hGetLine, hReady, hGetChar)
+import System.Process     (runInteractiveProcess, waitForProcess, terminateProcess)
+
+import qualified Data.Map.Strict as M
+import qualified Data.Text       as T
+import qualified Data.Text.IO    as TIO
+import Text.Read (readMaybe)
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Data
+import Data.SBV.Core.Symbolic (SMTEngine, State(..), mustIgnoreVar)
+import Data.SBV.Core.Concrete (showCV)
+import Data.SBV.Core.Kind     (showBaseKind, intOfProxy, BVIsNonZero)
+
+import Data.SBV.Core.SizedFloats(FloatingPoint(..))
+
+import Data.SBV.SMT.Utils     ( showTimeoutValue, alignPlain, debug, mergeSExpr, SBVException(..)
+                              , startTranscript, recordTranscript, finalizeTranscript, recordEndTime, recordException, TranscriptMsg(..)
+                              )
+
+import Data.SBV.Utils.PrettyNum
+import Data.SBV.Utils.Lib       (joinArgs, splitArgs, needsBars, showText, unQuote)
+import Data.SBV.Utils.SExpr     (parenDeficit, nameSupply)
+
+import qualified System.Timeout as Timeout (timeout)
+
+import Numeric
+
+import qualified Data.SBV.Utils.CrackNum as CN
+
+-- | Extract the final configuration from a result
+resultConfig :: SMTResult -> SMTConfig
+resultConfig (Unsatisfiable c _  ) = c
+resultConfig (Satisfiable   c _  ) = c
+resultConfig (DeltaSat      c _ _) = c
+resultConfig (SatExtField   c _  ) = c
+resultConfig (Unknown       c _  ) = c
+resultConfig (ProofError    c _ _) = c
+
+-- | A 'Data.SBV.prove' call results in a t'ThmResult'
+newtype ThmResult = ThmResult SMTResult
+                  deriving NFData
+
+-- | A 'Data.SBV.sat' call results in a t'SatResult'
+-- The reason for having a separate t'SatResult' is to have a more meaningful 'Show' instance.
+newtype SatResult = SatResult SMTResult
+                  deriving NFData
+
+-- | An 'Data.SBV.allSat' call results in a t'AllSatResult'
+data AllSatResult = AllSatResult { allSatMaxModelCountReached  :: !Bool          -- ^ Did we reach the user given model count limit?
+                                 , allSatSolverReturnedUnknown :: !Bool          -- ^ Did the solver report unknown at the end?
+                                 , allSatSolverReturnedDSat    :: !Bool          -- ^ Did the solver report delta-satisfiable at the end?
+                                 , allSatResults               :: ![SMTResult]   -- ^ All satisfying models
+                                 }
+
+-- | A 'Data.SBV.safe' call results in a t'SafeResult'
+newtype SafeResult = SafeResult (Maybe String, String, SMTResult)
+
+-- | An 'Data.SBV.optimize' call results in a 'OptimizeResult'. In the 'ParetoResult' case, the boolean is 'True'
+-- if we reached pareto-query limit and so there might be more unqueried results remaining. If 'False',
+-- it means that we have all the pareto fronts returned. See the 'Pareto' 'OptimizeStyle' for details.
+data OptimizeResult = LexicographicResult SMTResult
+                    | ParetoResult        (Bool, [SMTResult])
+                    | IndependentResult   [(String, SMTResult)]
+
+-- | What's the precision of a delta-sat query?
+getPrecision :: SMTResult -> Maybe String -> String
+getPrecision r queriedPrecision = case (queriedPrecision, dsatPrecision (resultConfig r)) of
+                                   (Just s, _     ) -> s
+                                   (_,      Just d) -> showFFloat Nothing d ""
+                                   _                -> "tool default"
+
+-- User friendly way of printing theorem results
+instance Show ThmResult where
+  show (ThmResult r) = showSMTResult "Q.E.D."
+                                     "Unknown"
+                                     "Falsifiable"
+                                     "Falsifiable. Counter-example:\n"
+                                     (\mbP -> "Delta falsifiable, precision: " ++ getPrecision r mbP ++ ". Counter-example:\n")
+                                     "Falsifiable in an extension field:\n"
+                                     r
+
+-- User friendly way of printing satisfiability results
+instance Show SatResult where
+  show (SatResult r) = showSMTResult "Unsatisfiable"
+                                     "Unknown"
+                                     "Satisfiable"
+                                     "Satisfiable. Model:\n"
+                                     (\mbP -> "Delta satisfiable, precision: " ++ getPrecision r mbP ++ ". Model:\n")
+                                     "Satisfiable in an extension field. Model:\n"
+                                     r
+
+-- User friendly way of printing safety results
+instance Show SafeResult where
+   show (SafeResult (mbLoc, msg, r)) = showSMTResult (tag "No violations detected")
+                                                     (tag "Unknown")
+                                                     (tag "Violated")
+                                                     (tag "Violated. Model:\n")
+                                                     (\mbP -> tag "Violated in a delta-satisfiable context, precision: " ++ getPrecision r mbP ++ ". Model:\n")
+                                                     (tag "Violated in an extension field:\n")
+                                                     r
+        where loc   = maybe "" (++ ": ") mbLoc
+              tag s = loc ++ msg ++ ": " ++ s
+
+-- The Show instance of AllSatResults.
+instance Show AllSatResult where
+  show AllSatResult { allSatMaxModelCountReached  = l
+                    , allSatSolverReturnedUnknown = u
+                    , allSatSolverReturnedDSat    = d
+                    , allSatResults               = xs
+                    } = go (0::Int) xs
+    where warnings | u    = " (Search stopped since solver has returned unknown.)"
+                   | True = ""
+
+          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, d, c) of
+                          (True,  _   , _) -> "Search stopped since model count request was reached."  ++ warnings
+                          (_   ,  True, _) -> "Search stopped since the result was delta-satisfiable." ++ warnings
+                          (False, _   , 0) -> "No solutions found."
+                          (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")
+                                      (\mbP -> "Solution $" ++ show i ++ " with delta-satisfiability, precision: " ++ getPrecision c mbP ++ ":\n")
+                                      ("Solution $" ++ show i ++ " in an extension field:\n")
+                                      c)
+              where ok = case c of
+                           Satisfiable{} -> True
+                           _             -> False
+
+-- Show instance for optimization results
+instance Show OptimizeResult where
+  show res = case res of
+               LexicographicResult r   -> sh id r
+
+               IndependentResult   rs  -> multi "objectives" (map (uncurry shI) rs)
+
+               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."
+                                           ++ "\n***       There might be many other results!"
+
+       where multi w [] = "There are no " ++ w ++ " to display models for."
+             multi _ xs = intercalate "\n" xs
+
+             shI n = sh (\s -> "Objective "     ++ show n ++ ": " ++ s)
+             shP i = sh (\s -> "Pareto front #" ++ show i ++ ": " ++ s)
+
+             sh tag r = showSMTResult (tag "Unsatisfiable.")
+                                      (tag "Unknown.")
+                                      (tag "Optimal with no assignments.")
+                                      (tag "Optimal model:" ++ "\n")
+                                      (\mbP -> tag "Optimal model with delta-satisfiability, precision: " ++ getPrecision r mbP ++ ":" ++ "\n")
+                                      (tag "Optimal in an extension field:" ++ "\n")
+                                      r
+
+-- | Instances of 'SatModel' can be automatically extracted from models returned by the
+-- solvers. The idea is that the sbv infrastructure provides a stream of CV's (constant values)
+-- coming from the solver, and the type @a@ is interpreted based on these constants. Many typical
+-- instances are already provided, so new instances can be declared with relative ease.
+--
+-- Minimum complete definition: 'parseCVs'
+class SatModel a where
+  -- | Given a sequence of constant-words, extract one instance of the type @a@, returning
+  -- the remaining elements untouched. If the next element is not what's expected for this
+  -- type you should return 'Nothing'
+  parseCVs :: [CV] -> Maybe (a, [CV])
+
+  -- | Given a parsed model instance, transform it using @f@, and return the result.
+  -- The default definition for this method should be sufficient in most use cases.
+  cvtModel :: (a -> Maybe b) -> Maybe (a, [CV]) -> Maybe (b, [CV])
+  cvtModel f x = x >>= \(a, r) -> f a >>= \b -> pure (b, r)
+
+  {-# MINIMAL parseCVs #-}
+
+-- | Parse a signed/sized value from a sequence of CVs
+genParse :: Integral a => Kind -> [CV] -> Maybe (a, [CV])
+genParse k (x@(CV _ (CInteger i)):r) | kindOf x == k = Just (fromIntegral i, r)
+genParse _ _                                         = Nothing
+
+-- | Base case for 'SatModel' at unit type. Comes in handy if there are no real variables.
+instance SatModel () where
+  parseCVs xs = pure ((), xs)
+
+-- | 'Bool' as extracted from a model
+instance SatModel Bool where
+  parseCVs xs = do (x, r) <- genParse KBool xs
+                   pure ((x :: Integer) /= 0, r)
+
+-- | 'Word8' as extracted from a model
+instance SatModel Word8 where
+  parseCVs = genParse (KBounded False 8)
+
+-- | 'Int8' as extracted from a model
+instance SatModel Int8 where
+  parseCVs = genParse (KBounded True 8)
+
+-- | 'Word16' as extracted from a model
+instance SatModel Word16 where
+  parseCVs = genParse (KBounded False 16)
+
+-- | 'Int16' as extracted from a model
+instance SatModel Int16 where
+  parseCVs = genParse (KBounded True 16)
+
+-- | 'Word32' as extracted from a model
+instance SatModel Word32 where
+  parseCVs = genParse (KBounded False 32)
+
+-- | 'Int32' as extracted from a model
+instance SatModel Int32 where
+  parseCVs = genParse (KBounded True 32)
+
+-- | 'Word64' as extracted from a model
+instance SatModel Word64 where
+  parseCVs = genParse (KBounded False 64)
+
+-- | 'Int64' as extracted from a model
+instance SatModel Int64 where
+  parseCVs = genParse (KBounded True 64)
+
+-- | 'Integer' as extracted from a model
+instance SatModel Integer where
+  parseCVs = genParse KUnbounded
+
+-- | 'AlgReal' as extracted from a model
+instance SatModel AlgReal where
+  parseCVs (CV KReal (CAlgReal i) : r) = Just (i, r)
+  parseCVs _                           = Nothing
+
+-- | 'Float' as extracted from a model
+instance SatModel Float where
+  parseCVs (CV KFloat (CFloat i) : r) = Just (i, r)
+  parseCVs _                          = Nothing
+
+-- | 'Double' as extracted from a model
+instance SatModel Double where
+  parseCVs (CV KDouble (CDouble i) : r) = Just (i, r)
+  parseCVs _                            = Nothing
+
+-- | A general floating-point extracted from a model
+instance (KnownNat eb, KnownNat sb) => SatModel (FloatingPoint eb sb) where
+  parseCVs (CV (KFP ei si) (CFP fp) : r)
+    | intOfProxy (Proxy @eb) == ei , intOfProxy (Proxy @sb) == si = Just (FloatingPoint fp, r)
+  parseCVs _                                                      = Nothing
+
+-- | Constructing models for 'WordN'
+instance (KnownNat n, BVIsNonZero n) => SatModel (WordN n) where
+  parseCVs = genParse (kindOf (undefined :: WordN n))
+
+-- | Constructing models for 'IntN'
+instance (KnownNat n, BVIsNonZero n) => SatModel (IntN n) where
+  parseCVs = genParse (kindOf (undefined :: IntN n))
+
+-- | Constructing models for t'ArrayModel'
+instance (SatModel k, SatModel v) => SatModel (ArrayModel k v) where
+  parseCVs (CV (KArray kk kv) (CArray (ArrayModel tbl def)) : r)
+    | Just (def', _) <- parseCVs @v [CV kv def]
+    , let convert (k, v) = do
+            (k', _) <- parseCVs @k [CV kk k]
+            (v', _) <- parseCVs @v [CV kv v]
+            pure (k', v')
+    , Just tbl' <- traverse convert tbl
+    = Just (ArrayModel tbl' def', r)
+  parseCVs _ = Nothing
+
+-- | @CV@ as extracted from a model; trivial definition
+instance SatModel CV where
+  parseCVs (cv : r) = Just (cv, r)
+  parseCVs []       = Nothing
+
+-- | A rounding mode, extracted from a model. (Default definition suffices)
+instance SatModel RoundingMode where
+  parseCVs (CV k (CADT (s, [])) : r)
+    | isRoundingMode k
+    , Just mode <- s `lookup` [(show m, m) | m <- [minBound .. maxBound :: RoundingMode]]
+    = Just (mode, r)
+  parseCVs _ = Nothing
+
+-- | 'String' as extracted from a model
+instance {-# OVERLAPS #-} SatModel [Char] where
+  parseCVs (CV _ (CString c):r) = Just (c, r)
+  parseCVs _                    = Nothing
+
+-- | 'Char' as extracted from a model
+instance SatModel Char where
+  parseCVs (CV _ (CChar c):r) = Just (c, r)
+  parseCVs _                  = Nothing
+
+-- | A list of values as extracted from a model. When reading a list, we
+-- go as long as we can (maximal-munch). Note that this never fails, as
+-- we can always return the empty list!
+instance {-# OVERLAPPABLE #-} SatModel a => SatModel [a] where
+  parseCVs [] = Just ([], [])
+  parseCVs xs = case parseCVs xs of
+                  Just (a, ys) -> case parseCVs ys of
+                                    Just (as, zs) -> Just (a:as, zs)
+                                    Nothing       -> Just ([], ys)
+                  Nothing     -> Just ([], xs)
+
+-- | Tuples extracted from a model
+instance (SatModel a, SatModel b) => SatModel (a, b) where
+  parseCVs as = do (a, bs) <- parseCVs as
+                   (b, cs) <- parseCVs bs
+                   pure ((a, b), cs)
+
+-- | 3-Tuples extracted from a model
+instance (SatModel a, SatModel b, SatModel c) => SatModel (a, b, c) where
+  parseCVs as = do (a,      bs) <- parseCVs as
+                   ((b, c), ds) <- parseCVs bs
+                   pure ((a, b, c), ds)
+
+-- | 4-Tuples extracted from a model
+instance (SatModel a, SatModel b, SatModel c, SatModel d) => SatModel (a, b, c, d) where
+  parseCVs as = do (a,         bs) <- parseCVs as
+                   ((b, c, d), es) <- parseCVs bs
+                   pure ((a, b, c, d), es)
+
+-- | 5-Tuples extracted from a model
+instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e) => SatModel (a, b, c, d, e) where
+  parseCVs as = do (a, bs)            <- parseCVs as
+                   ((b, c, d, e), fs) <- parseCVs bs
+                   pure ((a, b, c, d, e), fs)
+
+-- | 6-Tuples extracted from a model
+instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e, SatModel f) => SatModel (a, b, c, d, e, f) where
+  parseCVs as = do (a, bs)               <- parseCVs as
+                   ((b, c, d, e, f), gs) <- parseCVs bs
+                   pure ((a, b, c, d, e, f), gs)
+
+-- | 7-Tuples extracted from a model
+instance (SatModel a, SatModel b, SatModel c, SatModel d, SatModel e, SatModel f, SatModel g) => SatModel (a, b, c, d, e, f, g) where
+  parseCVs as = do (a, bs)                  <- parseCVs as
+                   ((b, c, d, e, f, g), hs) <- parseCVs bs
+                   pure ((a, b, c, d, e, f, g), hs)
+
+-- | Various SMT results that we can extract models out of.
+class Modelable a where
+  -- | Is there a model?
+  modelExists :: a -> Bool
+
+  -- | Extract assignments of a model, the result is a tuple where the first argument (if True)
+  -- indicates whether the model was "probable". (i.e., if the solver returned unknown.)
+  getModelAssignment :: SatModel b => a -> Either String (Bool, b)
+
+  -- | Extract a model dictionary. Extract a dictionary mapping the variables to
+  -- their respective values as returned by the SMT solver. Also see `getModelDictionaries`.
+  getModelDictionary :: a -> M.Map String CV
+
+  -- | Extract a model value for a given element. Also see `getModelValues`.
+  getModelValue :: SymVal b => String -> a -> Maybe b
+  getModelValue v r = fromCV <$> (v `M.lookup` getModelDictionary r)
+
+  -- | A simpler variant of 'getModelAssignment' to get a model out without the fuss.
+  extractModel :: SatModel b => a -> Maybe b
+  extractModel a = case getModelAssignment a of
+                     Right (_, b) -> Just b
+                     _            -> Nothing
+
+  -- | Extract model objective values, for all optimization goals.
+  getModelObjectives :: a -> M.Map String GeneralizedCV
+
+  -- | Extract the value of an objective
+  getModelObjectiveValue :: String -> a -> Maybe GeneralizedCV
+  getModelObjectiveValue v r = v `M.lookup` getModelObjectives r
+
+  -- | Extract model uninterpreted-functions
+  getModelUIFuns :: a -> M.Map String (Bool, SBVType, Either String ([([CV], CV)], CV))
+
+  -- | Extract the value of an uninterpreted-function as an association list
+  getModelUIFunValue :: String -> a -> Maybe (Bool, SBVType, Either String ([([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{allSatResults = 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{allSatResults = 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{allSatResults = xs} =  map (s `getModelValue`) xs
+
+-- | t'ThmResult' as a generic model provider
+instance Modelable ThmResult where
+  getModelAssignment (ThmResult r) = getModelAssignment r
+  modelExists        (ThmResult r) = modelExists        r
+  getModelDictionary (ThmResult r) = getModelDictionary r
+  getModelObjectives (ThmResult r) = getModelObjectives r
+  getModelUIFuns     (ThmResult r) = getModelUIFuns     r
+
+-- | t'SatResult' as a generic model provider
+instance Modelable SatResult where
+  getModelAssignment (SatResult r) = getModelAssignment 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 (DeltaSat      _ _ 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
+  modelExists _               = False
+
+  getModelDictionary Unsatisfiable{}     = M.empty
+  getModelDictionary (Satisfiable _   m) = M.fromList (modelAssocs m)
+  getModelDictionary (DeltaSat    _ _ m) = M.fromList (modelAssocs m)
+  getModelDictionary SatExtField{}       = M.empty
+  getModelDictionary Unknown{}           = M.empty
+  getModelDictionary ProofError{}        = M.empty
+
+  getModelObjectives Unsatisfiable{}     = M.empty
+  getModelObjectives (Satisfiable _ m  ) = M.fromList (modelObjectives m)
+  getModelObjectives (DeltaSat    _ _ m) = M.fromList (modelObjectives m)
+  getModelObjectives (SatExtField _ m  ) = M.fromList (modelObjectives m)
+  getModelObjectives Unknown{}           = M.empty
+  getModelObjectives ProofError{}        = M.empty
+
+  getModelUIFuns Unsatisfiable{}     = M.empty
+  getModelUIFuns (Satisfiable _ m  ) = M.fromList (modelUIFuns m)
+  getModelUIFuns (DeltaSat    _ _ 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
+                   Just (x, []) -> x
+                   Just (_, ys) -> error $ "SBV.parseModelOut: Partially constructed model; remaining elements: " ++ show ys
+                   Nothing      -> error $ "SBV.parseModelOut: Cannot construct a model from: " ++ show m
+
+-- | Given an 'Data.SBV.allSat' call, we typically want to iterate over it and print the results in sequence. The
+-- 'displayModels' function automates this task by calling @disp@ on each result, consecutively. The first
+-- '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, returning Unknown).
+-- The arrange argument can sort the results in any way you like, if necessary.
+displayModels :: SatModel a => ([(Bool, a)] -> [(Bool, a)]) -> (Int -> (Bool, a) -> IO ()) -> AllSatResult -> IO Int
+displayModels arrange disp AllSatResult{allSatResults = ms} = do
+    let models = rights (map (getModelAssignment . SatResult) ms)
+    inds <- zipWithM display (arrange models) [(1::Int)..]
+    pure $ last (0:inds)
+  where display r i = disp i r >> pure i
+
+-- | Show an SMTResult; generic version
+showSMTResult :: String -> String -> String -> String -> (Maybe String -> String) -> String -> SMTResult -> String
+showSMTResult unsatMsg unkMsg satMsg satMsgModel dSatMsgModel satExtMsg result = case result of
+  Unsatisfiable _ uc                 -> unsatMsg ++ showUnsatCore uc
+  Satisfiable _ (SMTModel _ _ [] []) -> satMsg
+  Satisfiable _   m                  -> satMsgModel    ++ showModel cfg m
+  DeltaSat    _ p m                  -> dSatMsgModel p ++ showModel cfg m
+  SatExtField _ (SMTModel b _ _ _)   -> satExtMsg   ++ showModelDictionary True False cfg b
+  Unknown     _ r                    -> unkMsg ++ ".\n" ++ T.unpack ("  Reason: " `alignPlain` showText 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 dSatMsgModel satExtMsg r)]
+
+ where cfg = resultConfig result
+       showUnsatCore Nothing   = ""
+       showUnsatCore (Just xs) = ". Unsat core:\n" ++ intercalate "\n" ["    " ++ x | x <- xs]
+
+-- | 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
+   | 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 :: Bool -> Bool -> SMTConfig -> [(String, GeneralizedCV)] -> String
+showModelDictionary warnEmpty includeEverything cfg allVars
+   | null allVars
+   = warn "[There are no variables bound by the model.]"
+   | null relevantVars
+   = warn "[There are no model-variables bound by the model.]"
+   | True
+   = intercalate "\n" . display . map shM $ relevantVars
+  where warn s = if warnEmpty then s else ""
+
+        relevantVars  = filter (not . ignore) allVars
+        ignore (T.pack -> s, _)
+          | includeEverything = False
+          | True              = mustIgnoreVar cfg s
+
+        shM (s, RegularCV v) = let vs = shCV cfg s v in ((length s, s), (vlength vs, vs))
+        shM (s, other)       = let vs = show other   in ((length s, s), (vlength vs, vs))
+
+        display svs   = map line svs
+           where line ((_, s), (_, v)) = "  " ++ right (nameWidth - length s) s ++ " = " ++ left (valWidth - lTrimRight (valPart v)) v
+                 nameWidth             = maximum $ 0 : [l | ((l, _), _) <- svs]
+                 valWidth              = maximum $ 0 : [l | (_, (l, _)) <- svs]
+
+        right p s = s ++ replicate p ' '
+        left  p s = replicate p ' ' ++ s
+        vlength s = case dropWhile (/= ':') (reverse (takeWhile (/= '\n') s)) of
+                      (':':':':r) -> length (dropWhile isSpace r)
+                      _           -> length s -- conservative
+
+        valPart ""          = ""
+        valPart (':':':':_) = ""
+        valPart (x:xs)      = x : valPart xs
+
+        lTrimRight = length . dropWhile isSpace . reverse
+
+-- | Show an uninterpreted function
+showModelUI :: SMTConfig -> (String, (Bool, SBVType, Either String ([([CV], CV)], CV))) -> String
+showModelUI cfg (nm, (isCurried, SBVType ts, interp))
+  = intercalate "\n" $ case interp of
+                         Left  e  -> ["  " ++ trim l | l <- [sig, e]]
+                         Right ds -> ["  " ++ trim l | l <- sig : mkBody ds]
+  where noOfArgs = length ts - 1
+
+        trim = reverse . dropWhile isSpace . reverse
+
+        (ats, rt) = case map (T.unpack . showBaseKind) ts of
+                     []  -> error $ "showModelUI: Unexpected type: " ++ show (SBVType ts)
+                     tss -> (init tss, last tss)
+
+        -- signatures require parens if this is a non-ascii name, i.e., needs bars
+        sigName | needsBars nm = '(' : nm ++ ")"
+                | True         = nm
+
+        sig | isCurried = sigName ++ " :: "  ++ intercalate " -> " ats ++  " -> " ++ rt
+            | True      = sigName ++ " :: (" ++ intercalate ", "   ats ++ ") -> " ++ rt
+
+        mkBody (defs, dflt) = map align body
+          where ls       = map line defs
+                body     = ls ++ [defLine]
+
+                -- is the default an argument? This is likely to be z3 specific
+                defVal = scv dflt
+                defPos = case span (/= '!') defVal of
+                           (_, '!':n) | Just (i :: Int) <- readMaybe n, i > 0 -> Just (i, nameSupply [] !! (i-1)) -- default is the ith argument
+                           _                                                  -> Nothing                          -- default is a constant (or something else?)
+                defLine = case defPos of
+                            Just (i, a) | i > 0 -> (replicate (i - 1) "_" ++ a : replicate (noOfArgs - i) "_", a)
+                            _                   -> (replicate noOfArgs "_",                                    defVal)
+
+                colWidths = [maximum (0 : map length col) | col <- transpose (map fst body)]
+
+                resWidth  = maximum  (0 : map (length . snd) body)
+
+                align (xs, r) = nm ++ " " ++ merge (zipWith left colWidths xs) ++ " = " ++ left resWidth r
+                   where left i x = take i (x ++ repeat ' ')
+
+                         merge as | isCurried = unwords as
+                                  | True      = '(' : intercalate ", " as ++ ")"
+
+        -- NB. We'll ignore crackNum here. Seems to be overkill while displaying an
+        -- uninterpreted function.
+        scv = sh (printBase cfg)
+          where sh 2  = T.unpack . binP
+                sh 10 = showCV False
+                sh 16 = T.unpack . 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) = (map (paren isCurried . scv) args, scv r)
+          where -- If negative and if we're curried, parenthesize. I think this is the only case
+                -- we need to worry about. Hopefully!
+                paren :: Bool -> String -> String
+                paren True x@('-':_) = '(' : x ++ ")"
+                paren _    x         = x
+
+-- | Show a constant value, in the user-specified base
+shCV :: SMTConfig -> String -> CV -> String
+shCV SMTConfig{printBase, crackNum, verbose, crackNumSurfaceVals} nm cv = cracked (sh printBase cv)
+  where sh 2  = T.unpack . binS
+        sh 10 = show
+        sh 16 = T.unpack . hexS
+        sh n  = \w -> show w ++ " -- Ignoring unsupported printBase " ++ show n ++ ", use 2, 10, or 16."
+
+        cracked def
+          | not crackNum = def
+          | True         = case CN.crackNum cv verbose (nm `lookup` crackNumSurfaceVals) of
+                             Nothing -> def
+                             Just cs -> def ++ "\n" ++ cs
+
+-- | Helper function to spin off to an SMT solver.
+pipeProcess :: SMTConfig -> State -> String -> [String] -> T.Text -> (State -> IO a) -> IO a
+pipeProcess cfg ctx execName opts pgm continuation = do
+    mbExecPath <- findExecutable execName
+    case mbExecPath of
+      Nothing      -> error $ unlines [ "Unable to locate executable for " ++ show (name (solver cfg))
+                                      , "Executable specified: " ++ show execName
+                                      ]
+
+      Just execPath -> runSolver cfg ctx execPath opts pgm continuation
+                       `C.catches`
+                        [ C.Handler (\(e :: SBVException)    -> C.throwIO e)
+                        , C.Handler (\(e :: C.ErrorCall)     -> C.throwIO e)
+                        , C.Handler (\(e :: C.SomeException) -> handleAsync e $ error $ unlines [ "Failed to start the external solver:\n" ++ show e
+                                                                                                , "Make sure you can start " ++ show execPath
+                                                                                                , "from the command line without issues."
+                                                                                                ])
+                        ]
+
+-- Communication-level timeouts (microseconds). These are NOT solver timeouts
+-- (i.e., how long check-sat takes); they govern how long SBV waits for the
+-- solver process to respond to individual IPC commands.
+--
+-- Adjust via the @SBV_COMM_TIMEOUT_FACTOR@ environment variable (default: 1).
+-- For instance, setting it to 2 doubles all communication timeouts.
+
+-- | Timeout for @set-option@ commands (expected to be fast).
+setCommandTimeOut :: Int
+setCommandTimeOut = 2_000_000   -- 2 seconds
+
+-- | Timeout for subsequent response lines once the solver starts responding,
+--   and for heartbeat\/sync-point reads.
+defaultLineTimeOut :: Int
+defaultLineTimeOut = 5_000_000  -- 5 seconds
+
+-- | Read @SBV_COMM_TIMEOUT_FACTOR@ and return a function that scales timeout values.
+-- If the variable is unset, the identity function is returned. If set to an invalid
+-- value (not a positive number), an error is raised.
+commTimeOutScaler :: IO (Int -> Int)
+commTimeOutScaler = do
+   mbFactor <- lookupEnv "SBV_COMM_TIMEOUT_FACTOR"
+   case mbFactor of
+     Nothing -> pure id
+     Just s  -> case reads s of
+                  [(f, "")] | f > (0 :: Double) -> pure (round . (f *) . fromIntegral)
+                  _                              -> error $ "SBV_COMM_TIMEOUT_FACTOR: invalid value " ++ show s ++ ". Must be a positive number."
+
+-- | A standard engine interface. Most solvers follow-suit here in how we "chat" to them..
+standardEngine :: String
+               -> String
+               -> SMTEngine
+standardEngine envName envOptName cfg ctx pgm continuation = do
+
+    execName <-                    getEnv envName     `C.catch` (\(e :: C.SomeException) -> handleAsync e (pure (executable (solver cfg))))
+    execOpts <- (splitArgs <$> getEnv envOptName) `C.catch` (\(e :: C.SomeException) -> handleAsync e (pure (options (solver cfg) cfg)))
+
+    let cfg' = cfg {solver = (solver cfg) {executable = execName, options = const execOpts}}
+
+    standardSolver cfg' ctx pgm continuation
+
+-- | A standard solver interface. If the solver is SMT-Lib compliant, then this function should suffice in
+-- communicating with it.
+standardSolver :: SMTConfig       -- ^ The current configuration
+               -> State           -- ^ Context in which we are running
+               -> T.Text          -- ^ The program
+               -> (State -> IO a) -- ^ The continuation
+               -> IO a
+standardSolver config ctx pgm continuation = do
+    let msg s    = debug config ["** " <> s]
+        smtSolver= solver config
+        exec     = executable smtSolver
+        opts     = options smtSolver config ++ extraArgs config
+    msg $ "Calling: "  <> T.pack (exec ++ (if null opts then "" else " ") ++ joinArgs opts)
+    rnf pgm `seq` pipeProcess config ctx exec opts pgm continuation
+
+-- | An internal type to track of solver interactions
+data SolverLine = SolverRegular   String -- ^ All is well
+                | SolverTimeout   String -- ^ Timeout expired
+                | SolverException String -- ^ Something else went wrong
+
+-- | A variant of @readProcessWithExitCode@; except it deals with SBV continuations
+runSolver :: SMTConfig -> State -> FilePath -> [String] -> T.Text -> (State -> IO a) -> IO a
+runSolver cfg ctx execPath opts pgm continuation
+ = do scaler <- commTimeOutScaler
+
+      let nm  = show (name (solver cfg))
+          msg = debug cfg . map ("*** " <>)
+
+          clean = preprocess (solver cfg)
+
+          -- the very first command we send
+          heartbeat = "(set-option :print-success true)"
+
+          -- Scaled communication timeouts
+          setCommandTO  = Just (scaler setCommandTimeOut)
+          defaultLineTO = Just (scaler defaultLineTimeOut)
+
+          -- Default SBVException with solver config baked in; callers override fields as needed
+          solverException desc =
+             let (errOut, description)
+                    | "(error" `isPrefixOf` desc
+                    = ( Just $ unQuote (dropWhile isSpace (dropWhile (not . isSpace) (init desc)))
+                      , "Unexpected solver error"
+                      )
+                    | True
+                    = (Nothing, desc)
+             in SBVException { sbvExceptionDescription = description
+                             , sbvExceptionSent        = Nothing
+                             , sbvExceptionExpected    = Nothing
+                             , sbvExceptionReceived    = Nothing
+                             , sbvExceptionStdOut      = Nothing
+                             , sbvExceptionStdErr      = errOut
+                             , sbvExceptionExitCode    = Nothing
+                             , sbvExceptionConfig      = cfg { solver = (solver cfg) { executable = execPath } }
+                             , sbvExceptionReason      = Nothing
+                             , sbvExceptionHint        = Nothing
+                             }
+
+      (send, ask, getResponseFromSolver, terminateSolver, cleanUp, pid) <- do
+                (inh, outh, errh, pid) <- runInteractiveProcess execPath opts Nothing Nothing
+
+                let send :: Maybe Int -> T.Text -> IO ()
+                    send mbTimeOut command = do TIO.hPutStrLn inh (clean command)
+                                                hFlush inh
+                                                recordTranscript (transcript cfg) $ SentMsg command mbTimeOut
+
+                    -- is this a set-command? Then we expect faster response; except for the heartbeat
+                    isSetCommand = maybe False chk
+                      where chk cmd = cmd /= heartbeat && "(set-option :" `isPrefixOf` cmd
+
+                    -- Send a line, get a whole s-expr. We ignore the pathetic case that there might be a string with an unbalanced parentheses in it in a response.
+                    ask :: Maybe Int -> T.Text -> IO String
+                    ask mbTimeOut command =
+                                  let -- solvers don't respond to empty lines or comments; we just pass back
+                                      -- success in these cases to keep the illusion of everything has a response
+                                      cmd = T.dropWhile isSpace command
+
+                                  in if T.null cmd || ";" `T.isPrefixOf` cmd
+                                     then pure "success"
+                                     else do send mbTimeOut command
+                                             getResponseFromSolver (Just (T.unpack command)) mbTimeOut
+
+                    -- Get a response from the solver, with an optional time-out on how long
+                    -- to wait. Note that there's *always* a time-out once we get the
+                    -- first line of response, as while the solver might take its time to respond,
+                    -- once it starts responding successive lines should come quickly.
+                    getResponseFromSolver :: Maybe String -> Maybe Int -> IO String
+                    getResponseFromSolver mbCommand mbTimeOut = do
+                                response <- go True 0 []
+                                let collated = intercalate "\n" $ reverse response
+                                recordTranscript (transcript cfg) $ RecvMsg collated
+                                pure collated
+
+                      where safeGetLine isFirst h =
+                                         let timeOutToUse | isSetCommand mbCommand = setCommandTO
+                                                          | isFirst                = mbTimeOut
+                                                          | True                   = defaultLineTO
+                                             timeOutMsg t | isFirst = "User specified timeout of " ++ T.unpack (showTimeoutValue t) ++ " exceeded"
+                                                          | True    = "A multiline complete response wasn't received before " ++ T.unpack (showTimeoutValue t) ++ " exceeded"
+
+                                             -- Like hGetLine, except it keeps getting lines if inside a string.
+                                             getFullLine :: IO String
+                                             getFullLine = intercalate "\n" . reverse <$> collect False []
+                                                where collect inString sofar = do ln <- hGetLine h
+
+                                                                                  let walk inside []           = inside
+                                                                                      walk inside ('"':cs)     = walk (not inside) cs
+                                                                                      walk inside (_:cs)       = walk inside       cs
+
+                                                                                      stillInside = walk inString ln
+
+                                                                                      sofar' = ln : sofar
+
+                                                                                  if stillInside
+                                                                                     then collect True sofar'
+                                                                                     else pure sofar'
+
+                                             -- Carefully grab things as they are ready. But don't block!
+                                             collectH handle = reverse <$> coll ""
+                                               where coll sofar = do b <- hReady handle
+                                                                     if b
+                                                                        then hGetChar handle >>= \c -> coll (c:sofar)
+                                                                        else pure sofar
+
+                                             -- grab the contents of a handle, and return it trimmed if any
+                                             grab handle = do mbCts <- (Just <$> collectH handle) `C.catch` (\(_ :: C.SomeException) -> pure Nothing)
+                                                              pure $ dropWhile isSpace <$> mbCts
+
+                                         in case timeOutToUse of
+                                              Nothing -> do l <- getFullLine
+                                                            -- If we see the line starting with error, we're about to die, so give up:
+                                                            pure $ if "(error" `isPrefixOf` l
+                                                                      then SolverException l
+                                                                      else SolverRegular   l
+                                              Just t  -> do r <- Timeout.timeout t getFullLine
+                                                            case r of
+                                                              Just l  -> pure $ SolverRegular l
+                                                              Nothing -> do out <- grab outh
+                                                                            err <- grab errh
+                                                                            -- in this case, if we have something on out/err pass that back as regular
+                                                                            case err `mplus` out of
+                                                                              Just x | not (null x) -> pure $ SolverRegular x
+                                                                              _                     -> pure $ SolverTimeout (timeOutMsg t)
+
+                            go isFirst i sofar = do
+                                            errln <- safeGetLine isFirst outh `C.catch` (\(e :: C.SomeException) -> handleAsync e (pure (SolverException (show e))))
+                                            case errln of
+                                              SolverRegular ln -> let !need = i + parenDeficit ln
+                                                                      -- make sure we get *something*
+                                                                      empty = case dropWhile isSpace ln of
+                                                                                []      -> True
+                                                                                (';':_) -> True   -- yes this does happen! I've seen z3 print out comments on stderr.
+                                                                                _       -> False
+                                                                  in case (empty, need <= 0) of
+                                                                        (True, _)      -> do debug cfg ["[SKIP] " `alignPlain` T.pack ln]
+                                                                                             go isFirst need sofar
+                                                                        (False, False) -> go False   need (ln:sofar)
+                                                                        (False, True)  -> pure (ln:sofar)
+
+                                              SolverException e -> do terminateProcess pid
+                                                                      C.throwIO (solverException e)
+                                                                                { sbvExceptionSent     = mbCommand
+                                                                                , sbvExceptionReceived = Just $ unlines (reverse sofar)
+                                                                                , sbvExceptionHint     = if "hGetLine: end of file" `isInfixOf` e
+                                                                                                         then Just [ "Solver process prematurely ended communication."
+                                                                                                                   , ""
+                                                                                                                   , "It is likely it was terminated because of a seg-fault."
+                                                                                                                   , "Run with 'transcript=Just \"bad.smt2\"' option, and feed"
+                                                                                                                   , "the generated \"bad.smt2\" file directly to the solver"
+                                                                                                                   , "outside of SBV for further information."
+                                                                                                                   ]
+                                                                                                         else Nothing
+                                                                                }
+
+                                              SolverTimeout e -> do terminateProcess pid -- NB. Do not *wait* for the process, just quit.
+
+                                                                    C.throwIO (solverException ("Timeout! " ++ e))
+                                                                              { sbvExceptionSent     = mbCommand
+                                                                              , sbvExceptionReceived = Just $ unlines (reverse sofar)
+                                                                              , sbvExceptionHint     = if not (verbose cfg)
+                                                                                                       then Just ["Run with 'verbose=True' for further information"]
+                                                                                                       else Nothing
+                                                                              }
+
+                    terminateSolver = do hClose inh
+                                         outMVar <- newEmptyMVar
+                                         out <- hGetContents outh `C.catch`  (\(e :: C.SomeException) -> handleAsync e (pure (show e)))
+                                         _ <- forkIO $ C.evaluate (length out) >> putMVar outMVar ()
+                                         err <- hGetContents errh `C.catch`  (\(e :: C.SomeException) -> handleAsync e (pure (show e)))
+                                         _ <- forkIO $ C.evaluate (length err) >> putMVar outMVar ()
+                                         takeMVar outMVar
+                                         takeMVar outMVar
+                                         hClose outh `C.catch`  (\(e :: C.SomeException) -> handleAsync e (pure ()))
+                                         hClose errh `C.catch`  (\(e :: C.SomeException) -> handleAsync e (pure ()))
+                                         ex <- waitForProcess pid `C.catch` (\(e :: C.SomeException) -> handleAsync e (pure (ExitFailure (-999))))
+                                         pure (out, err, ex)
+
+                    cleanUp maybeForwardedException
+                      = do (out, err, ex) <- terminateSolver
+
+                           msg $   [ "Solver   : " <> T.pack nm
+                                   , "Exit code: " <> showText ex
+                                   ]
+                                <> [ "Std-out  : " <> T.pack (intercalate "\n           " (lines out)) | not (null out)]
+                                <> [ "Std-err  : " <> T.pack (intercalate "\n           " (lines err)) | not (null err)]
+
+                           finalizeTranscript (transcript cfg) ex
+                           recordEndTime cfg ctx
+
+                           case (ex, maybeForwardedException) of
+                             (_,           Just forwardedException) -> C.throwIO forwardedException
+                             (ExitSuccess, _)                       -> pure ()
+                             _                                      -> if ignoreExitCode cfg
+                                                                          then msg ["Ignoring non-zero exit code of " <> showText ex <> " per user request!"]
+                                                                          else C.throwIO (solverException ("Failed to complete the call to " ++ nm))
+                                                                                                      { sbvExceptionStdOut    = Just out
+                                                                                                      , sbvExceptionStdErr    = Just err
+                                                                                                      , sbvExceptionExitCode  = Just ex
+                                                                                                      , sbvExceptionHint      = if not (verbose cfg)
+                                                                                                                                then Just ["Run with 'verbose=True' for further information"]
+                                                                                                                                else Nothing
+                                                                                                      }
+
+                pure (send, ask, getResponseFromSolver, terminateSolver, cleanUp, pid)
+
+      let executeSolver = do let sendAndGetSuccess :: Maybe Int -> T.Text -> IO ()
+                                 sendAndGetSuccess mbTimeOut l
+                                   -- The pathetic case when the solver doesn't support queries, so we pretend it responded "success"
+                                   -- Currently ABC is the only such solver.
+                                   | not (supportsCustomQueries (capabilities (solver cfg)))
+                                   = do send mbTimeOut l
+                                        debug cfg ["[ISSUE] " `alignPlain` l]
+                                   | True
+                                   = do r <- ask mbTimeOut l
+                                        case words r of
+                                          ["success"] -> debug cfg ["[GOOD] " `alignPlain` l]
+                                          _           -> do debug cfg ["[FAIL] " `alignPlain` l]
+
+                                                            let isOption = T.isPrefixOf "(set-option" (T.dropWhile isSpace l)
+
+                                                                reason | isOption = [ "Backend solver reports it does not support this option."
+                                                                                    , "Check the spelling, and if correct please report this as a"
+                                                                                    , "bug/feature request with the solver!"
+                                                                                    ]
+                                                                       | True     = [ "Check solver response for further information. If your code is correct,"
+                                                                                    , "please report this as an issue either with SBV or the solver itself!"
+                                                                                    ]
+
+                                                            -- put a sync point here before we die so we consume everything
+                                                            mbExtras <- (Right <$> getResponseFromSolver Nothing defaultLineTO)
+                                                                        `C.catch` (\(e :: C.SomeException) -> handleAsync e (pure (Left (show e))))
+
+                                                            -- Ignore any exceptions from last sync, pointless.
+                                                            let extras = case mbExtras of
+                                                                           Left _   -> []
+                                                                           Right xs -> xs
+
+                                                            (outOrig, errOrig, ex) <- terminateSolver
+                                                            let out = intercalate "\n" . lines $ outOrig
+                                                                err = intercalate "\n" . lines $ errOrig
+
+                                                                exc = (solverException ("Unexpected non-success response from " ++ nm))
+                                                                                   { sbvExceptionSent     = Just (T.unpack l)
+                                                                                   , sbvExceptionExpected = Just "success"
+                                                                                   , sbvExceptionReceived = Just $ r ++ "\n" ++ extras
+                                                                                   , sbvExceptionStdOut   = Just out
+                                                                                   , sbvExceptionStdErr   = Just err
+                                                                                   , sbvExceptionExitCode = Just ex
+                                                                                   , sbvExceptionReason   = Just reason
+                                                                                   }
+
+                                                            C.throwIO exc
+
+                             -- Mark in the log, mostly.
+                             sendAndGetSuccess Nothing "; Automatically generated by SBV. Do not edit."
+
+                             -- First check that the solver supports :print-success
+                             let backend = name $ solver cfg
+                             if not (supportsCustomQueries (capabilities (solver cfg)))
+                                then debug cfg ["** Skipping heart-beat for the solver " <> showText backend]
+                                else do r <- ask defaultLineTO (T.pack heartbeat)
+                                        case words r of
+                                          ["success"]     -> debug cfg ["[GOOD] " <> T.pack heartbeat]
+                                          ["unsupported"] -> error $ unlines [ ""
+                                                                             , "*** Backend solver (" ++  show backend ++ ") does not support the command:"
+                                                                             , "***"
+                                                                             , "***     (set-option :print-success true)"
+                                                                             , "***"
+                                                                             , "*** SBV relies on this feature to coordinate communication!"
+                                                                             , "*** Please request this as a feature!"
+                                                                             ]
+                                          _               -> error $ unlines [ ""
+                                                                             , "*** Data.SBV: Failed to initiate contact with the solver!"
+                                                                             , "***"
+                                                                             , "***   Sent    : " ++ heartbeat
+                                                                             , "***   Expected: success"
+                                                                             , "***   Received: " ++ r
+                                                                             , "***"
+                                                                             , "*** Try running in debug mode for further information."
+                                                                             ]
+
+                             -- For push/pop support, we require :global-declarations to be true. But not all solvers
+                             -- support this. Issue it if supported. (If not, we'll reject pop calls.)
+                             if not (supportsGlobalDecls (capabilities (solver cfg)))
+                                then debug cfg [ "** Backend solver " <> showText backend <> " does not support global decls."
+                                               , "** Some incremental calls, such as pop, will be limited."
+                                               ]
+                                else sendAndGetSuccess Nothing "(set-option :global-declarations true)"
+
+                             -- Now dump the program!
+                             mapM_ (sendAndGetSuccess Nothing) (mergeSExpr (T.lines pgm))
+
+                             -- Prepare the query context and ship it off
+                             let qs = QueryState { queryAsk                 = ask
+                                                 , querySend                = send
+                                                 , queryRetrieveResponse    = getResponseFromSolver Nothing
+                                                 , queryConfig              = cfg
+                                                 , queryTerminate           = cleanUp
+                                                 , queryTimeOutValue        = Nothing
+                                                 , queryAssertionStackDepth = 0
+                                                 }
+                                 qsp = rQueryState ctx
+
+                             mbQS <- readIORef qsp
+
+                             case mbQS of
+                               Nothing -> writeIORef qsp (Just qs)
+                               Just _  -> error $ unlines [ ""
+                                                          , "Data.SBV: Impossible happened, query-state was already set."
+                                                          , "Please report this as a bug!"
+                                                          ]
+
+                             -- off we go!
+                             continuation ctx
+
+      -- NB. Don't use 'bracket' here, as it wouldn't have access to the exception.
+      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) ec
+                                                                            recordEndTime cfg ctx
+                                                                            C.throwIO e)
+
+-- We should not be catching/processing asynchronous exceptions.
+-- See http://github.com/LeventErkok/sbv/issues/410
+handleAsync :: C.SomeException -> IO a -> IO a
+handleAsync e cont
+  | isAsynchronous = C.throwIO e
+  | True           = cont
+  where -- Stealing this definition from the asynchronous exceptions package to reduce dependencies
+        isAsynchronous :: Bool
+        isAsynchronous = isJust (C.fromException e :: Maybe C.AsyncException) || isJust (C.fromException e :: Maybe C.SomeAsyncException)
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,119 +1,48 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.SMT.SMTLib
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.SMT.SMTLib
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Conversion of symbolic programs to SMTLib format
 -----------------------------------------------------------------------------
 
-module Data.SBV.SMT.SMTLib(SMTLibPgm, SMTLibConverter, toSMTLib2, addNonEqConstraints, interpretSolverOutput, interpretSolverModelLine) where
+{-# LANGUAGE NamedFieldPuns #-}
 
-import Data.Char (isDigit)
+{-# OPTIONS_GHC -Wall -Werror #-}
 
-import Data.SBV.BitVectors.Data
-import Data.SBV.Provers.SExpr
+module Data.SBV.SMT.SMTLib (
+          SMTLibPgm
+        , toSMTLib
+        , toIncSMTLib
+        ) where
+
+import Data.SBV.Core.Data
+
+import Data.SBV.SMT.Utils
 import qualified Data.SBV.SMT.SMTLib2 as SMT2
-import qualified Data.Set as Set (Set, member, toList)
+import           Data.Text            (Text)
 
--- | An instance of SMT-Lib converter; instantiated for SMT-Lib v1 and v2. (And potentially for newer versions in the future.)
-type SMTLibConverter =  RoundingMode                 -- ^ User selected rounding mode to be used for floating point arithmetic
-                     -> Maybe Logic                  -- ^ User selected logic to use. If Nothing, pick automatically.
-                     -> SolverCapabilities           -- ^ Capabilities of the backend solver targeted
-                     -> Set.Set Kind                 -- ^ Kinds used in the problem
-                     -> Bool                         -- ^ is this a sat problem?
-                     -> [String]                     -- ^ extra comments to place on top
-                     -> [(Quantifier, NamedSymVar)]  -- ^ inputs and aliasing names
-                     -> [Either SW (SW, [SW])]       -- ^ skolemized inputs
-                     -> [(SW, CW)]                   -- ^ constants
-                     -> [((Int, Kind, Kind), [SW])]  -- ^ auto-generated tables
-                     -> [(Int, ArrayInfo)]           -- ^ user specified arrays
-                     -> [(String, SBVType)]          -- ^ uninterpreted functions/constants
-                     -> [(String, [String])]         -- ^ user given axioms
-                     -> SBVPgm                       -- ^ assignments
-                     -> [SW]                         -- ^ extra constraints
-                     -> SW                           -- ^ output variable
-                     -> SMTLibPgm
+-- | Convert to SMT-Lib, in a full program context.
+toSMTLib :: SMTConfig -> SMTLibConverter SMTLibPgm
+toSMTLib SMTConfig{smtLibVersion} = case smtLibVersion of
+                                      SMTLib2 -> toSMTLib2
 
+-- | Convert to SMT-Lib, in an incremental query context.
+toIncSMTLib :: SMTConfig -> SMTLibIncConverter [Text]
+toIncSMTLib SMTConfig{smtLibVersion} = case smtLibVersion of
+                                         SMTLib2 -> toIncSMTLib2
 -- | Convert to SMTLib-2 format
-toSMTLib2 :: SMTLibConverter
+toSMTLib2 :: SMTLibConverter SMTLibPgm
 toSMTLib2 = cvt SMTLib2
-  where cvt v roundMode smtLogic solverCaps kindInfo isSat comments qinps skolemMap consts tbls arrs uis axs asgnsSeq cstrs out
-         | KUnbounded `Set.member` kindInfo && not (supportsUnboundedInts solverCaps)
-         = unsupported "unbounded integers"
-         | KReal `Set.member` kindInfo  && not (supportsReals solverCaps)
-         = unsupported "algebraic reals"
-         | needsFloats && not (supportsFloats solverCaps)
-         = unsupported "single-precision floating-point numbers"
-         | needsDoubles && not (supportsDoubles solverCaps)
-         = unsupported "double-precision floating-point numbers"
-         | needsQuantifiers && not (supportsQuantifiers solverCaps)
-         = unsupported "quantifiers"
-         | not (null sorts) && not (supportsUninterpretedSorts solverCaps)
-         = unsupported "uninterpreted sorts"
-         | True
-         = SMTLibPgm v (aliasTable, pre, post)
-         where sorts = [s | KUserSort s _ <- Set.toList kindInfo]
-               unsupported w = error $ "SBV: Given problem needs " ++ w ++ ", which is not supported by SBV for the chosen solver: " ++ capSolverName solverCaps
-               aliasTable  = map (\(_, (x, y)) -> (y, x)) qinps
-               converter   = case v of
+  where cvt v ctx progInfo kindInfo isSat comments qinps consts tbls uis axs asgnsSeq cstrs out config = SMTLibPgm v pgm defs
+         where converter   = case v of
                                SMTLib2 -> SMT2.cvt
-               (pre, post) = converter roundMode smtLogic solverCaps kindInfo isSat comments qinps skolemMap consts tbls arrs uis axs asgnsSeq cstrs out
-               needsFloats  = KFloat  `Set.member` kindInfo
-               needsDoubles = KDouble `Set.member` kindInfo
-               needsQuantifiers
-                 | isSat = ALL `elem` quantifiers
-                 | True  = EX  `elem` quantifiers
-                 where quantifiers = map fst qinps
-
--- | Add constraints generated from older models, used for querying new models
-addNonEqConstraints :: RoundingMode -> [(Quantifier, NamedSymVar)] -> [[(String, CW)]] -> SMTLibPgm -> Maybe String
-addNonEqConstraints rm  qinps cs p@(SMTLibPgm SMTLib2 _) = SMT2.addNonEqConstraints rm qinps cs p
-
--- | Interpret solver output based on SMT-Lib standard output responses
-interpretSolverOutput :: SMTConfig -> ([String] -> SMTModel) -> [String] -> SMTResult
-interpretSolverOutput cfg _          ("unsat":_)      = Unsatisfiable cfg
-interpretSolverOutput cfg extractMap ("unknown":rest) = Unknown       cfg  $ extractMap rest
-interpretSolverOutput cfg extractMap ("sat":rest)     = Satisfiable   cfg  $ extractMap rest
-interpretSolverOutput cfg _          ("timeout":_)    = TimeOut       cfg
-interpretSolverOutput cfg _          ls               = ProofError    cfg  ls
-
--- | Get a counter-example from an SMT-Lib2 like model output line
--- This routing is necessarily fragile as SMT solvers tend to print output
--- in whatever form they deem convenient for them.. Currently, it's tuned to
--- work with Z3 and CVC4; if new solvers are added, we might need to rework
--- the logic here.
-interpretSolverModelLine :: [NamedSymVar] -> String -> [(Int, (String, CW))]
-interpretSolverModelLine inps line = either err extract (parseSExpr line)
-  where err r =  error $  "*** Failed to parse SMT-Lib2 model output from: "
-                       ++ "*** " ++ show line ++ "\n"
-                       ++ "*** Reason: " ++ r ++ "\n"
-        getInput (ECon v)            = isInput v
-        getInput (EApp (ECon v : _)) = isInput v
-        getInput _                   = Nothing
-        isInput ('s':v)
-          | all isDigit v = let inpId :: Int
-                                inpId = read v
-                            in case [(s, nm) | (s@(SW _ (NodeId n)), nm) <-  inps, n == inpId] of
-                                 []        -> Nothing
-                                 [(s, nm)] -> Just (inpId, s, nm)
-                                 matches -> error $  "SBV.SMTLib2: Cannot uniquely identify value for "
-                                                  ++ 's':v ++ " in "  ++ show matches
-        isInput _       = Nothing
-        getUIIndex (KUserSort  _ (Right xs)) i = i `lookup` zip xs [0..]
-        getUIIndex _                         _ = Nothing
-        extract (EApp [EApp [v, ENum    i]]) | Just (n, s, nm) <- getInput v                    = [(n, (nm, mkConstCW (kindOf s) (fst i)))]
-        extract (EApp [EApp [v, EReal   i]]) | Just (n, s, nm) <- getInput v, isReal s          = [(n, (nm, CW KReal (CWAlgReal i)))]
-        extract (EApp [EApp [v, ECon    i]]) | Just (n, s, nm) <- getInput v, isUninterpreted s = let k = kindOf s in [(n, (nm, CW k (CWUserSort (getUIIndex k i, i))))]
-        extract (EApp [EApp [v, EDouble i]]) | Just (n, s, nm) <- getInput v, isDouble s        = [(n, (nm, CW KDouble (CWDouble i)))]
-        extract (EApp [EApp [v, EFloat  i]]) | Just (n, s, nm) <- getInput v, isFloat s         = [(n, (nm, CW KFloat (CWFloat i)))]
-        -- weird lambda app that CVC4 seems to throw out.. logic below derived from what I saw CVC4 print, hopefully sufficient
-        extract (EApp (EApp (v : EApp (ECon "LAMBDA" : xs) : _) : _)) | Just{} <- getInput v, not (null xs) = extract (EApp [EApp [v, last xs]])
-        extract (EApp [EApp (v : r)])      | Just (_, _, nm) <- getInput v = error $   "SBV.SMTLib2: Cannot extract value for " ++ show nm
-                                                                                   ++ "\n\tInput: " ++ show line
-                                                                                   ++ "\n\tParse: " ++  show r
-        extract _                                                          = []
+               (pgm, defs) = converter ctx progInfo kindInfo isSat comments qinps consts tbls uis axs asgnsSeq cstrs out config
 
-{-# ANN interpretSolverModelLine  ("HLint: ignore Use elemIndex" :: String) #-}
+-- | Convert to SMTLib-2 format
+toIncSMTLib2 :: SMTLibIncConverter [Text]
+toIncSMTLib2 = cvt SMTLib2
+  where cvt SMTLib2 = SMT2.cvtInc
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,640 +1,1370 @@
-----------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.SMT.SMTLib2
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Conversion of symbolic programs to SMTLib format, Using v2 of the standard
------------------------------------------------------------------------------
-{-# LANGUAGE PatternGuards #-}
-
-module Data.SBV.SMT.SMTLib2(cvt, addNonEqConstraints) where
-
-import Data.Bits     (bit)
-import Data.Function (on)
-import Data.Ord      (comparing)
-import Data.List     (intercalate, partition, groupBy, sortBy)
-
-import qualified Data.Foldable as F (toList)
-import qualified Data.Map      as M
-import qualified Data.IntMap   as IM
-import qualified Data.Set      as Set
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (smtRoundingMode, cwToSMTLib)
-
--- | Add constraints to generate /new/ models. This function is used to query the SMT-solver, while
--- disallowing a previous model.
-addNonEqConstraints :: RoundingMode -> [(Quantifier, NamedSymVar)] -> [[(String, CW)]] -> SMTLibPgm -> Maybe String
-addNonEqConstraints rm qinps allNonEqConstraints (SMTLibPgm _ (aliasTable, pre, post))
-  | null allNonEqConstraints
-  = Just $ intercalate "\n" $ pre ++ post
-  | null refutedModel
-  = Nothing
-  | True
-  = Just $ intercalate "\n" $ pre
-    ++ [ "; --- refuted-models ---" ]
-    ++ refutedModel
-    ++ post
- where refutedModel = concatMap (nonEqs rm . map intName) nonEqConstraints
-       intName (s, c)
-          | Just sw <- s `lookup` aliasTable = (show sw, c)
-          | True                             = (s, c)
-       -- with existentials, we only add top-level existentials to the refuted-models list
-       nonEqConstraints = filter (not . null) $ map (filter (\(s, _) -> s `elem` topUnivs)) allNonEqConstraints
-       topUnivs = [s | (_, (_, s)) <- takeWhile (\p -> fst p == EX) qinps]
-
-nonEqs :: RoundingMode -> [(String, CW)] -> [String]
-nonEqs rm scs = format $ interp ps ++ disallow (map eqClass uninterpClasses)
-  where isFree (KUserSort _ (Left _)) = True
-        isFree _                      = False
-        (ups, ps) = partition (isFree . kindOf . snd) scs
-        format []     =  []
-        format [m]    =  ["(assert " ++ m ++ ")"]
-        format (m:ms) =  ["(assert (or " ++ m]
-                      ++ map ("            " ++) ms
-                      ++ ["        ))"]
-        -- Regular (or interpreted) sorts simply get a constraint that we disallow the current assignment
-        interp = map $ nonEq rm
-        -- Determine the equivalence classes of uninterpreted sorts:
-        uninterpClasses = filter (\l -> length l > 1) -- Only need this class if it has at least two members
-                        . map (map fst)               -- throw away sorts, we only need the names
-                        . groupBy ((==) `on` snd)     -- make sure they belong to the same sort and have the same value
-                        . sortBy (comparing snd)      -- sort them according to their sorts first
-                        $ ups                         -- take the uninterpreted sorts
-        -- Uninterpreted sorts get a constraint that says the equivalence classes as determined by the solver are disallowed:
-        eqClass :: [String] -> String
-        eqClass [] = error "SBV.allSat.nonEqs: Impossible happened, disallow received an empty list"
-        eqClass cs = "(= " ++ unwords cs ++ ")"
-        -- Now, take the conjunction of equivalence classes and assert it's negation:
-        disallow = map $ \ec -> "(not " ++ ec ++ ")"
-
-nonEq :: RoundingMode -> (String, CW) -> String
-nonEq rm (s, c) = "(not (= " ++ s ++ " " ++ cvtCW rm c ++ "))"
-
-tbd :: String -> a
-tbd e = error $ "SBV.SMTLib2: Not-yet-supported: " ++ e
-
--- | Translate a problem into an SMTLib2 script
-cvt :: RoundingMode                 -- ^ User selected rounding mode to be used for floating point arithmetic
-    -> Maybe Logic                  -- ^ SMT-Lib logic, if requested by the user
-    -> SolverCapabilities           -- ^ capabilities of the current solver
-    -> Set.Set Kind                 -- ^ kinds used
-    -> Bool                         -- ^ is this a sat problem?
-    -> [String]                     -- ^ extra comments to place on top
-    -> [(Quantifier, NamedSymVar)]  -- ^ inputs
-    -> [Either SW (SW, [SW])]       -- ^ skolemized version inputs
-    -> [(SW, CW)]                   -- ^ constants
-    -> [((Int, Kind, Kind), [SW])]  -- ^ auto-generated tables
-    -> [(Int, ArrayInfo)]           -- ^ user specified arrays
-    -> [(String, SBVType)]          -- ^ uninterpreted functions/constants
-    -> [(String, [String])]         -- ^ user given axioms
-    -> SBVPgm                       -- ^ assignments
-    -> [SW]                         -- ^ extra constraints
-    -> SW                           -- ^ output variable
-    -> ([String], [String])
-cvt rm smtLogic solverCaps kindInfo isSat comments inputs skolemInps consts tbls arrs uis axs (SBVPgm asgnsSeq) cstrs out = (pre, [])
-  where -- the logic is an over-approaximation
-        hasInteger     = KUnbounded `Set.member` kindInfo
-        hasReal        = KReal      `Set.member` kindInfo
-        hasFloat       = KFloat     `Set.member` kindInfo
-        hasDouble      = KDouble    `Set.member` kindInfo
-        hasBVs         = not $ null [() | KBounded{} <- Set.toList kindInfo]
-        usorts         = [(s, dt) | KUserSort s dt <- Set.toList kindInfo]
-        hasNonBVArrays = (not . null) [() | (_, (_, (k1, k2), _)) <- arrs, not (isBounded k1 && isBounded k2)]
-        logic
-           | Just l <- smtLogic
-           = ["(set-logic " ++ show l ++ ") ; NB. User specified."]
-           | hasDouble || hasFloat    -- NB. We don't check for quantifiers here, we probably should..
-           = if hasBVs
-             then ["(set-logic QF_FPBV)"]
-             else ["(set-logic QF_FP)"]
-           | hasInteger || hasReal || not (null usorts) || hasNonBVArrays
-           = let why | hasInteger        = "has unbounded values"
-                     | hasReal           = "has algebraic reals"
-                     | not (null usorts) = "has user-defined sorts"
-                     | hasNonBVArrays    = "has non-bitvector arrays"
-                     | True              = "cannot determine the SMTLib-logic to use"
-             in case mbDefaultLogic solverCaps hasReal of
-                  Nothing -> ["; " ++ why ++ ", no logic specified."]
-                  Just l  -> ["(set-logic " ++ l ++ "); " ++ why ++ ", using solver-default logic."]
-           | True
-           = ["(set-logic " ++ qs ++ as ++ ufs ++ "BV)"]
-          where qs  | null foralls && null axs = "QF_"  -- axioms are likely to contain quantifiers
-                    | True                     = ""
-                as  | null arrs                = ""
-                    | True                     = "A"
-                ufs | null uis && null tbls    = ""     -- we represent tables as UFs
-                    | True                     = "UF"
-        getModels
-          | supportsProduceModels solverCaps = ["(set-option :produce-models true)"]
-          | True                             = []
-        pre  =  ["; Automatically generated by SBV. Do not edit."]
-             ++ map ("; " ++) comments
-             ++ getModels
-             ++ logic
-             ++ [ "; --- uninterpreted sorts ---" ]
-             ++ concatMap declSort usorts
-             ++ [ "; --- literal constants ---" ]
-             ++ concatMap (declConst (supportsMacros solverCaps)) consts
-             ++ [ "; --- skolem constants ---" ]
-             ++ [ "(declare-fun " ++ show s ++ " " ++ swFunType ss s ++ ")" ++ userName s | Right (s, ss) <- skolemInps]
-             ++ [ "; --- constant tables ---" ]
-             ++ concatMap constTable constTables
-             ++ [ "; --- skolemized tables ---" ]
-             ++ map (skolemTable (unwords (map swType foralls))) skolemTables
-             ++ [ "; --- arrays ---" ]
-             ++ concat arrayConstants
-             ++ [ "; --- uninterpreted constants ---" ]
-             ++ concatMap declUI uis
-             ++ [ "; --- user given axioms ---" ]
-             ++ map declAx axs
-             ++ [ "; --- formula ---" ]
-             ++ [if null foralls
-                 then "(assert ; no quantifiers"
-                 else "(assert (forall (" ++ intercalate "\n                 "
-                                             ["(" ++ show s ++ " " ++ swType s ++ ")" | s <- foralls] ++ ")"]
-             ++ map (letAlign . mkLet) asgns
-             ++ map letAlign (if null delayedEqualities then [] else ("(and " ++ deH) : map (align 5) deTs)
-             ++ [ impAlign (letAlign assertOut) ++ replicate noOfCloseParens ')' ]
-        noOfCloseParens = length asgns + (if null foralls then 1 else 2) + (if null delayedEqualities then 0 else 1)
-        (constTables, skolemTables) = ([(t, d) | (t, Left d) <- allTables], [(t, d) | (t, Right d) <- allTables])
-        allTables = [(t, genTableData rm skolemMap (not (null foralls), forallArgs) (map fst consts) t) | t <- tbls]
-        (arrayConstants, allArrayDelayeds) = unzip $ map (declArray (not (null foralls)) (map fst consts) skolemMap) arrs
-        delayedEqualities@(~(deH:deTs)) = concatMap snd skolemTables ++ concat allArrayDelayeds
-        foralls = [s | Left s <- skolemInps]
-        forallArgs = concatMap ((" " ++) . show) foralls
-        letAlign s
-          | null foralls = "   " ++ s
-          | True         = "            " ++ s
-        impAlign s
-          | null delayedEqualities = s
-          | True                   = "     " ++ s
-        align n s = replicate n ' ' ++ s
-        -- if sat,   we assert cstrs /\ out
-        -- if prove, we assert ~(cstrs => out) = cstrs /\ not out
-        assertOut
-           | null cstrs = o
-           | True       = "(and " ++ unwords (map mkConj cstrs ++ [o]) ++ ")"
-           where mkConj = cvtSW skolemMap
-                 o | isSat =            mkConj out
-                   | True  = "(not " ++ mkConj out ++ ")"
-        skolemMap = M.fromList [(s, ss) | Right (s, ss) <- skolemInps, not (null ss)]
-        tableMap  = IM.fromList $ map mkConstTable constTables ++ map mkSkTable skolemTables
-          where mkConstTable (((t, _, _), _), _) = (t, "table" ++ show t)
-                mkSkTable    (((t, _, _), _), _) = (t, "table" ++ show t ++ forallArgs)
-        asgns = F.toList asgnsSeq
-        mkLet (s, SBVApp (Label m) [e]) = "(let ((" ++ show s ++ " " ++ cvtSW     skolemMap          e ++ ")) ; " ++ m
-        mkLet (s, e)                    = "(let ((" ++ show s ++ " " ++ cvtExp rm skolemMap tableMap e ++ "))"
-        declConst useDefFun (s, c)
-          | useDefFun = ["(define-fun "   ++ varT ++ " " ++ cvtCW rm c ++ ")"]
-          | True      = [ "(declare-fun " ++ varT ++ ")"
-                        , "(assert (= "   ++ show s ++ " " ++ cvtCW rm c ++ "))"
-                        ]
-          where varT = show s ++ " " ++ swFunType [] s
-        userName s = case s `lookup` map snd inputs of
-                        Just u  | show s /= u -> " ; tracks user variable " ++ show u
-                        _ -> ""
-        -- following sorts are built-in; do not translate them:
-        builtInSort = (`elem` ["RoundingMode"])
-        declSort (s, _)
-          | builtInSort s           = []
-        declSort (s, Left  r ) = ["(declare-sort " ++ s ++ " 0)  ; N.B. Uninterpreted: " ++ r]
-        declSort (s, Right fs) = [ "(declare-datatypes () ((" ++ s ++ " " ++ unwords (map (\c -> "(" ++ c ++ ")") fs) ++ ")))"
-                                 , "(define-fun " ++ s ++ "_constrIndex ((x " ++ s ++ ")) Int"
-                                 ] ++ ["   " ++ body fs (0::Int)] ++ [")"]
-                where body []     _ = ""
-                      body [_]    i = show i
-                      body (c:cs) i = "(ite (= x " ++ c ++ ") " ++ show i ++ " " ++ body cs (i+1) ++ ")"
-
-declUI :: (String, SBVType) -> [String]
-declUI (i, t) = ["(declare-fun " ++ i ++ " " ++ cvtType t ++ ")"]
-
--- NB. We perform no check to as to whether the axiom is meaningful in any way.
-declAx :: (String, [String]) -> String
-declAx (nm, ls) = (";; -- user given axiom: " ++ nm ++ "\n") ++ intercalate "\n" ls
-
-constTable :: (((Int, Kind, Kind), [SW]), [String]) -> [String]
-constTable (((i, ak, rk), _elts), is) = decl : map wrap is
-  where t       = "table" ++ show i
-        decl    = "(declare-fun " ++ t ++ " (" ++ smtType ak ++ ") " ++ smtType rk ++ ")"
-        wrap  s = "(assert " ++ s ++ ")"
-
-skolemTable :: String -> (((Int, Kind, Kind), [SW]), [String]) -> String
-skolemTable qsIn (((i, ak, rk), _elts), _) = decl
-  where qs   = if null qsIn then "" else qsIn ++ " "
-        t    = "table" ++ show i
-        decl = "(declare-fun " ++ t ++ " (" ++ qs ++ smtType ak ++ ") " ++ smtType rk ++ ")"
-
--- Left if all constants, Right if otherwise
-genTableData :: RoundingMode -> SkolemMap -> (Bool, String) -> [SW] -> ((Int, Kind, Kind), [SW]) -> Either [String] [String]
-genTableData rm skolemMap (_quantified, args) consts ((i, aknd, _), elts)
-  | null post = Left  (map (topLevel . snd) pre)
-  | True      = Right (map (nested   . snd) (pre ++ post))
-  where ssw = cvtSW skolemMap
-        (pre, post) = partition fst (zipWith mkElt elts [(0::Int)..])
-        t           = "table" ++ show i
-        mkElt x k   = (isReady, (idx, ssw x))
-          where idx = cvtCW rm (mkConstCW aknd k)
-                isReady = x `Set.member` constsSet
-        topLevel (idx, v) = "(= (" ++ t ++ " " ++ idx ++ ") " ++ v ++ ")"
-        nested   (idx, v) = "(= (" ++ t ++ args ++ " " ++ idx ++ ") " ++ v ++ ")"
-        constsSet = Set.fromList consts
-
--- TODO: We currently do not support non-constant arrays when quantifiers are present, as
--- we might have to skolemize those. Implement this properly.
--- The difficulty is with the ArrayReset/Mutate/Merge: We have to postpone an init if
--- the components are themselves postponed, so this cannot be implemented as a simple map.
-declArray :: Bool -> [SW] -> SkolemMap -> (Int, ArrayInfo) -> ([String], [String])
-declArray quantified consts skolemMap (i, (_, (aKnd, bKnd), ctx)) = (adecl : map wrap pre, map snd post)
-  where topLevel = not quantified || case ctx of
-                                       ArrayFree Nothing -> True
-                                       ArrayFree (Just sw) -> sw `elem` consts
-                                       ArrayReset _ sw     -> sw `elem` consts
-                                       ArrayMutate _ a b   -> all (`elem` consts) [a, b]
-                                       ArrayMerge c _ _    -> c `elem` consts
-        (pre, post) = partition fst ctxInfo
-        nm = "array_" ++ show i
-        ssw sw
-         | topLevel || sw `elem` consts
-         = cvtSW skolemMap sw
-         | True
-         = tbd "Non-constant array initializer in a quantified context"
-        adecl = "(declare-fun " ++ nm ++ " () (Array " ++ smtType aKnd ++ " " ++ smtType bKnd ++ "))"
-        ctxInfo = case ctx of
-                    ArrayFree Nothing   -> []
-                    ArrayFree (Just sw) -> declA sw
-                    ArrayReset _ sw     -> declA sw
-                    ArrayMutate j a b -> [(all (`elem` consts) [a, b], "(= " ++ nm ++ " (store array_" ++ show j ++ " " ++ ssw a ++ " " ++ ssw b ++ "))")]
-                    ArrayMerge  t j k -> [(t `elem` consts,            "(= " ++ nm ++ " (ite " ++ ssw t ++ " array_" ++ show j ++ " array_" ++ show k ++ "))")]
-        declA sw = let iv = nm ++ "_freeInitializer"
-                   in [ (True,             "(declare-fun " ++ iv ++ " () " ++ smtType aKnd ++ ")")
-                      , (sw `elem` consts, "(= (select " ++ nm ++ " " ++ iv ++ ") " ++ ssw sw ++ ")")
-                      ]
-        wrap (False, s) = s
-        wrap (True, s)  = "(assert " ++ s ++ ")"
-
-swType :: SW -> String
-swType s = smtType (kindOf s)
-
-swFunType :: [SW] -> SW -> String
-swFunType ss s = "(" ++ unwords (map swType ss) ++ ") " ++ swType s
-
-smtType :: Kind -> String
-smtType KBool           = "Bool"
-smtType (KBounded _ sz) = "(_ BitVec " ++ show sz ++ ")"
-smtType KUnbounded      = "Int"
-smtType KReal           = "Real"
-smtType KFloat          = "(_ FloatingPoint  8 24)"
-smtType KDouble         = "(_ FloatingPoint 11 53)"
-smtType (KUserSort s _) = s
-
-cvtType :: SBVType -> String
-cvtType (SBVType []) = error "SBV.SMT.SMTLib2.cvtType: internal: received an empty type!"
-cvtType (SBVType xs) = "(" ++ unwords (map smtType body) ++ ") " ++ smtType ret
-  where (body, ret) = (init xs, last xs)
-
-type SkolemMap = M.Map  SW [SW]
-type TableMap  = IM.IntMap String
-
-cvtSW :: SkolemMap -> SW -> String
-cvtSW skolemMap s
-  | Just ss <- s `M.lookup` skolemMap
-  = "(" ++ show s ++ concatMap ((" " ++) . show) ss ++ ")"
-  | True
-  = show s
-
-cvtCW :: RoundingMode -> CW -> String
-cvtCW = cwToSMTLib
-
-getTable :: TableMap -> Int -> String
-getTable m i
-  | Just tn <- i `IM.lookup` m = tn
-  | True                       = error $ "SBV.SMTLib2: Cannot locate table " ++ show i
-
-cvtExp :: RoundingMode -> SkolemMap -> TableMap -> SBVExpr -> String
-cvtExp rm skolemMap tableMap expr@(SBVApp _ arguments) = sh expr
-  where ssw = cvtSW skolemMap
-        bvOp     = all isBounded       arguments
-        intOp    = any isInteger       arguments
-        realOp   = any isReal          arguments
-        doubleOp = any isDouble        arguments
-        floatOp  = any isFloat         arguments
-        boolOp   = all isBoolean       arguments
-        bad | intOp = error $ "SBV.SMTLib2: Unsupported operation on unbounded integers: " ++ show expr
-            | True  = error $ "SBV.SMTLib2: Unsupported operation on real values: " ++ show expr
-        ensureBVOrBool = bvOp || boolOp || bad
-        ensureBV       = bvOp || bad
-        addRM s = s ++ " " ++ smtRoundingMode rm
-        lift2  o _ [x, y] = "(" ++ o ++ " " ++ x ++ " " ++ y ++ ")"
-        lift2  o _ sbvs   = error $ "SBV.SMTLib2.sh.lift2: Unexpected arguments: "   ++ show (o, sbvs)
-        -- lift a binary operation with rounding-mode added; used for floating-point arithmetic
-        lift2WM o fo | doubleOp || floatOp = lift2 (addRM fo)
-                     | True                = lift2 o
-        lift1FP o fo | doubleOp || floatOp = lift1 fo
-                     | True                = lift1 o
-        liftAbs sgned args | doubleOp || floatOp = lift1 "fp.abs" sgned args
-                           | intOp               = lift1 "abs"    sgned args
-                           | bvOp, sgned         = mkAbs (head args) "bvslt" "bvneg"
-                           | bvOp                = head args
-                           | True                = mkAbs (head args) "<"     "-"
-          where mkAbs x cmp neg = "(ite " ++ ltz ++ " " ++ nx ++ " " ++ x ++ ")"
-                  where ltz = "(" ++ cmp ++ " " ++ x ++ " " ++ z ++ ")"
-                        nx  = "(" ++ neg ++ " " ++ x ++ ")"
-                        z   = cvtCW rm (mkConstCW (kindOf (head arguments)) (0::Integer))
-        lift2B bOp vOp
-          | boolOp = lift2 bOp
-          | True   = lift2 vOp
-        lift1B bOp vOp
-          | boolOp = lift1 bOp
-          | True   = lift1 vOp
-        eqBV  = lift2 "="
-        neqBV = lift2 "distinct"
-        equal sgn sbvs
-          | doubleOp = lift2 "fp.eq" sgn sbvs
-          | floatOp  = lift2 "fp.eq" sgn sbvs
-          | True     = lift2 "=" sgn sbvs
-        notEqual sgn sbvs
-          | doubleOp = "(not " ++ equal sgn sbvs ++ ")"
-          | floatOp  = "(not " ++ equal sgn sbvs ++ ")"
-          | True     = lift2 "distinct" sgn sbvs
-        lift2S oU oS sgn = lift2 (if sgn then oS else oU) sgn
-        lift2Cmp o fo | doubleOp || floatOp = lift2 fo
-                      | True                = lift2 o
-        unintComp o [a, b]
-          | KUserSort s (Right _) <- kindOf (head arguments)
-          = let idx v = "(" ++ s ++ "_constrIndex " ++ " " ++ v ++ ")" in "(" ++ o ++ " " ++ idx a ++ " " ++ idx b ++ ")"
-        unintComp o sbvs = error $ "SBV.SMT.SMTLib2.sh.unintComp: Unexpected arguments: "   ++ show (o, sbvs)
-        lift1  o _ [x]    = "(" ++ o ++ " " ++ x ++ ")"
-        lift1  o _ sbvs   = error $ "SBV.SMT.SMTLib2.sh.lift1: Unexpected arguments: "   ++ show (o, sbvs)
-        sh (SBVApp Ite [a, b, c]) = "(ite " ++ ssw a ++ " " ++ ssw b ++ " " ++ ssw c ++ ")"
-        sh (SBVApp (LkUp (t, aKnd, _, l) i e) [])
-          | needsCheck = "(ite " ++ cond ++ ssw e ++ " " ++ lkUp ++ ")"
-          | True       = lkUp
-          where needsCheck = case aKnd of
-                              KBool         -> (2::Integer) > fromIntegral l
-                              KBounded _ n  -> (2::Integer)^n > fromIntegral l
-                              KUnbounded    -> True
-                              KReal         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected real valued index"
-                              KFloat        -> error "SBV.SMT.SMTLib2.cvtExp: unexpected float valued index"
-                              KDouble       -> error "SBV.SMT.SMTLib2.cvtExp: unexpected double valued index"
-                              KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
-                lkUp = "(" ++ getTable tableMap t ++ " " ++ ssw i ++ ")"
-                cond
-                 | hasSign i = "(or " ++ le0 ++ " " ++ gtl ++ ") "
-                 | True      = gtl ++ " "
-                (less, leq) = case aKnd of
-                                KBool         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected boolean valued index"
-                                KBounded{}    -> if hasSign i then ("bvslt", "bvsle") else ("bvult", "bvule")
-                                KUnbounded    -> ("<", "<=")
-                                KReal         -> ("<", "<=")
-                                KFloat        -> ("fp.lt", "fp.leq")
-                                KDouble       -> ("fp.lt", "fp.geq")
-                                KUserSort s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
-                mkCnst = cvtCW rm . mkConstCW (kindOf i)
-                le0  = "(" ++ less ++ " " ++ ssw i ++ " " ++ mkCnst 0 ++ ")"
-                gtl  = "(" ++ leq  ++ " " ++ mkCnst l ++ " " ++ ssw i ++ ")"
-        sh (SBVApp (KindCast f t) [a]) = handleKindCast f t (ssw a)
-        sh (SBVApp (ArrEq i j) [])  = "(= array_" ++ show i ++ " array_" ++ show j ++")"
-        sh (SBVApp (ArrRead i) [a]) = "(select array_" ++ show i ++ " " ++ ssw a ++ ")"
-        sh (SBVApp (Uninterpreted nm) [])   = nm
-        sh (SBVApp (Uninterpreted nm) args) = "(" ++ nm ++ " " ++ unwords (map ssw args) ++ ")"
-        sh (SBVApp (Extract i j) [a]) | ensureBV = "((_ extract " ++ show i ++ " " ++ show j ++ ") " ++ ssw a ++ ")"
-        sh (SBVApp (Rol i) [a])
-           | bvOp  = rot  ssw "rotate_left"  i a
-           | intOp = sh (SBVApp (Shl i) [a])       -- Haskell treats rotateL as shiftL for unbounded values
-           | True  = bad
-        sh (SBVApp (Ror i) [a])
-           | bvOp  = rot  ssw "rotate_right" i a
-           | intOp = sh (SBVApp (Shr i) [a])     -- Haskell treats rotateR as shiftR for unbounded values
-           | True  = bad
-        sh (SBVApp (Shl i) [a])
-           | bvOp   = shft rm ssw "bvshl"  "bvshl"  i a
-           | i < 0  = sh (SBVApp (Shr (-i)) [a])  -- flip sign/direction
-           | intOp  = "(* " ++ ssw a ++ " " ++ show (bit i :: Integer) ++ ")"  -- Implement shiftL by multiplication by 2^i
-           | True   = bad
-        sh (SBVApp (Shr i) [a])
-           | bvOp  = shft rm ssw "bvlshr" "bvashr" i a
-           | i < 0 = sh (SBVApp (Shl (-i)) [a])  -- flip sign/direction
-           | intOp = "(div " ++ ssw a ++ " " ++ show (bit i :: Integer) ++ ")"  -- Implement shiftR by division by 2^i
-           | True  = bad
-        sh (SBVApp op args)
-          | Just f <- lookup op smtBVOpTable, ensureBVOrBool
-          = f (any hasSign args) (map ssw args)
-          where -- The first 4 operators below do make sense for Integer's in Haskell, but there's
-                -- no obvious counterpart for them in the SMTLib translation.
-                -- TODO: provide support for these.
-                smtBVOpTable = [ (And,  lift2B "and" "bvand")
-                               , (Or,   lift2B "or"  "bvor")
-                               , (XOr,  lift2B "xor" "bvxor")
-                               , (Not,  lift1B "not" "bvnot")
-                               , (Join, lift2 "concat")
-                               ]
-        sh (SBVApp (Label _)                       [a]) = cvtSW skolemMap a  -- This won't be reached; but just in case!
-        sh (SBVApp (IEEEFP (FP_Cast kFrom kTo m)) args) = handleFPCast kFrom kTo (ssw m) (unwords (map ssw args))
-        sh (SBVApp (IEEEFP w                    ) args) = "(" ++ show w ++ " " ++ unwords (map ssw args) ++ ")"
-        sh inp@(SBVApp op args)
-          | intOp, Just f <- lookup op smtOpIntTable
-          = f True (map ssw args)
-          | boolOp, Just f <- lookup op boolComps
-          = f (map ssw args)
-          | bvOp, Just f <- lookup op smtOpBVTable
-          = f (any hasSign args) (map ssw args)
-          | realOp, Just f <- lookup op smtOpRealTable
-          = f (any hasSign args) (map ssw args)
-          | floatOp || doubleOp, Just f <- lookup op smtOpFloatDoubleTable
-          = f (any hasSign args) (map ssw args)
-          | Just f <- lookup op uninterpretedTable
-          = f (map ssw args)
-          | True
-          = error $ "SBV.SMT.SMTLib2.cvtExp.sh: impossible happened; can't translate: " ++ show inp
-          where smtOpBVTable  = [ (Plus,          lift2   "bvadd")
-                                , (Minus,         lift2   "bvsub")
-                                , (Times,         lift2   "bvmul")
-                                , (UNeg,          lift1B  "not"    "bvneg")
-                                , (Abs,           liftAbs)
-                                , (Quot,          lift2S  "bvudiv" "bvsdiv")
-                                , (Rem,           lift2S  "bvurem" "bvsrem")
-                                , (Equal,         eqBV)
-                                , (NotEqual,      neqBV)
-                                , (LessThan,      lift2S  "bvult" "bvslt")
-                                , (GreaterThan,   lift2S  "bvugt" "bvsgt")
-                                , (LessEq,        lift2S  "bvule" "bvsle")
-                                , (GreaterEq,     lift2S  "bvuge" "bvsge")
-                                ]
-                -- Boolean comparisons.. SMTLib's bool type doesn't do comparisons, but Haskell does.. Sigh
-                boolComps      = [ (LessThan,      blt)
-                                 , (GreaterThan,   blt . swp)
-                                 , (LessEq,        blq)
-                                 , (GreaterEq,     blq . swp)
-                                 ]
-                               where blt [x, y] = "(and (not " ++ x ++ ") " ++ y ++ ")"
-                                     blt xs     = error $ "SBV.SMT.SMTLib2.boolComps.blt: Impossible happened, incorrect arity (expected 2): " ++ show xs
-                                     blq [x, y] = "(or (not " ++ x ++ ") " ++ y ++ ")"
-                                     blq xs     = error $ "SBV.SMT.SMTLib2.boolComps.blq: Impossible happened, incorrect arity (expected 2): " ++ show xs
-                                     swp [x, y] = [y, x]
-                                     swp xs     = error $ "SBV.SMT.SMTLib2.boolComps.swp: Impossible happened, incorrect arity (expected 2): " ++ show xs
-                smtOpRealTable =  smtIntRealShared
-                               ++ [ (Quot,        lift2WM "/" "fp.div")
-                                  ]
-                smtOpIntTable  = smtIntRealShared
-                               ++ [ (Quot,        lift2   "div")
-                                  , (Rem,         lift2   "mod")
-                                  ]
-                smtOpFloatDoubleTable = smtIntRealShared
-                                  ++ [(Quot, lift2WM "/" "fp.div")]
-                smtIntRealShared  = [ (Plus,          lift2WM "+" "fp.add")
-                                    , (Minus,         lift2WM "-" "fp.sub")
-                                    , (Times,         lift2WM "*" "fp.mul")
-                                    , (UNeg,          lift1FP "-" "fp.neg")
-                                    , (Abs,           liftAbs)
-                                    , (Equal,         equal)
-                                    , (NotEqual,      notEqual)
-                                    , (LessThan,      lift2Cmp  "<"  "fp.lt")
-                                    , (GreaterThan,   lift2Cmp  ">"  "fp.gt")
-                                    , (LessEq,        lift2Cmp  "<=" "fp.leq")
-                                    , (GreaterEq,     lift2Cmp  ">=" "fp.geq")
-                                    ]
-                -- equality and comparisons are the only thing that works on uninterpreted sorts
-                uninterpretedTable = [ (Equal,       lift2S "="        "="        True)
-                                     , (NotEqual,    lift2S "distinct" "distinct" True)
-                                     , (LessThan,    unintComp "<")
-                                     , (GreaterThan, unintComp ">")
-                                     , (LessEq,      unintComp "<=")
-                                     , (GreaterEq,   unintComp ">=")
-                                     ]
-
------------------------------------------------------------------------------------------------
--- Casts supported by SMTLib. (From: <http://smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml>)
---   ; from another floating point sort
---   ((_ to_fp eb sb) RoundingMode (_ FloatingPoint mb nb) (_ FloatingPoint eb sb))
---
---   ; from real
---   ((_ to_fp eb sb) RoundingMode Real (_ FloatingPoint eb sb))
---
---   ; from signed machine integer, represented as a 2's complement bit vector
---   ((_ to_fp eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb))
---
---   ; from unsigned machine integer, represented as bit vector
---   ((_ to_fp_unsigned eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb))
---
---   ; to unsigned machine integer, represented as a bit vector
---   ((_ fp.to_ubv m) RoundingMode (_ FloatingPoint eb sb) (_ BitVec m))
---
---   ; to signed machine integer, represented as a 2's complement bit vector
---   ((_ fp.to_sbv m) RoundingMode (_ FloatingPoint eb sb) (_ BitVec m)) 
---
---   ; to real
---   (fp.to_real (_ FloatingPoint eb sb) Real)
------------------------------------------------------------------------------------------------
-
-handleFPCast :: Kind -> Kind -> String -> String -> String
-handleFPCast kFrom kTo rm input
-  | kFrom == kTo
-  = input
-  | True
-  = "(" ++ 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 ++ ")"
-        cast KFloat             KUnbounded         a = "to_int (fp.to_real " ++ a ++ ")"
-        cast KDouble            KUnbounded         a = "to_int (fp.to_real " ++ a ++ ")"
-
-        -- To float/double
-        cast (KBounded False _) KFloat             a = addRM a "(_ to_fp_unsigned 8 24)"
-        cast (KBounded False _) KDouble            a = addRM a "(_ to_fp_unsigned 11 53)"
-        cast (KBounded True  _) KFloat             a = addRM a "(_ to_fp 8 24)"
-        cast (KBounded True  _) KDouble            a = addRM a "(_ to_fp 11 53)"
-        cast KReal              KFloat             a = addRM a "(_ to_fp 8 24)"
-        cast KReal              KDouble            a = addRM a "(_ to_fp 11 53)"
-
-        -- Between floats
-        cast KFloat             KFloat             a = addRM a "(_ to_fp 8 24)"
-        cast KFloat             KDouble            a = addRM a "(_ to_fp 11 53)"
-        cast KDouble            KFloat             a = addRM a "(_ to_fp 8 24)"
-        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 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
-
-        -- Nothing else should come up:
-        cast f                  d                  _ = error $ "SBV.SMTLib2: Unexpected FPCast from: " ++ show f ++ " to " ++ show d
-
-rot :: (SW -> String) -> String -> Int -> SW -> String
-rot ssw o c x = "((_ " ++ o ++ " " ++ show c ++ ") " ++ ssw x ++ ")"
-
-shft :: RoundingMode -> (SW -> String) -> String -> String -> Int -> SW -> String
-shft rm ssw oW oS c x = "(" ++ o ++ " " ++ ssw x ++ " " ++ cvtCW rm c' ++ ")"
-   where s  = hasSign x
-         c' = mkConstCW (kindOf x) c
-         o  = if s then oS else oW
-
--- Various casts
-handleKindCast :: Kind -> Kind -> String -> String
-handleKindCast kFrom kTo a
-  | kFrom == kTo
-  = a
-  | True
-  = case kFrom of
-      KBounded s m -> case kTo of
-                        KBounded _ n -> fromBV (if s then signExtend else zeroExtend) m n
-                        KUnbounded   -> b2i s m
-                        _            -> tryFPCast
-
-      KUnbounded   -> case kTo of
-                        KReal        -> "(to_real " ++ a ++ ")"
-                        KBounded _ n -> i2b n
-                        _            -> tryFPCast
-
-      KReal        -> case kTo of
-                        KUnbounded   -> "(to_int " ++ a ++ ")"
-                        _            -> tryFPCast
-
-      _            -> tryFPCast
-
-  where -- See if we can push this down to a float-cast, using sRNE. This happens if one of the kinds is a float/double.
-        -- Otherwise complain
-        tryFPCast
-          | any (\k -> isFloat k || isDouble k) [kFrom, kTo]
-          = handleFPCast kFrom kTo (smtRoundingMode RoundNearestTiesToEven) a
-          | True
-          = error $ "SBV.SMTLib2: Unexpected cast from: " ++ show kFrom ++ " to " ++ show kTo
-
-        fromBV upConv m n
-         | n > m  = upConv  (n - m)
-         | m == n = a
-         | True   = extract (n - 1)
-
-        i2b n = "(let (" ++ reduced ++ ") (let (" ++ defs ++ ") " ++ body ++ "))"
-          where b i      = show (bit i :: Integer)
-                reduced  = "(__a (mod " ++ a ++ " " ++ b n ++ "))"
-                mkBit 0  = "(__a0 (ite (= (mod __a 2) 0) #b0 #b1))"
-                mkBit i  = "(__a" ++ show i ++ " (ite (= (mod (div __a " ++ b i ++ ") 2) 0) #b0 #b1))"
-                defs     = unwords (map mkBit [0 .. n - 1])
-                body     = foldr1 (\c r -> "(concat " ++ c ++ " " ++ r ++ ")") ["__a" ++ show i | i <- [n-1, n-2 .. 0]]
-
-        b2i s m
-          | s    = "(- " ++ val ++ " " ++ valIf (2^m) sign ++ ")"
-          | True = val
-          where valIf v b = "(ite (= " ++ b ++ " #b1) " ++ show (v::Integer) ++ " 0)"
-                getBit i  = "((_ extract " ++ show i ++ " " ++ show i ++ ") " ++ a ++ ")"
-                bitVal i  = valIf (2^i) (getBit i)
-                val       = "(+ " ++ unwords (map bitVal [0 .. m-1]) ++ ")"
-                sign      = getBit (m-1)
-
-        signExtend i = "((_ sign_extend " ++ show i ++  ") "  ++ a ++ ")"
-        zeroExtend i = "((_ zero_extend " ++ show i ++  ") "  ++ a ++ ")"
-        extract    i = "((_ extract "     ++ show i ++ " 0) " ++ a ++ ")"
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.SMT.SMTLib2
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Conversion of symbolic programs to SMTLib format, Using v2 of the standard
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ViewPatterns        #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SMT.SMTLib2(cvt, cvtExp, cvtCV, cvtInc, declUserFuns, constructTables, setSMTOption) where
+
+import Data.List  (intercalate, partition, nub, elemIndex)
+import Data.Maybe (listToMaybe, catMaybes)
+
+import qualified Data.Foldable as F (toList, foldl')
+import qualified Data.Map.Strict      as M
+import qualified Data.IntMap.Strict   as IM
+import           Data.Set             (Set)
+import qualified Data.Set             as Set
+import qualified Data.Text            as T
+import           Data.Text            (Text)
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind (smtType, needsFlattening, expandKinds, substituteADTVars)
+import Data.SBV.Control.Types
+
+import Data.SBV.SMT.Utils
+
+import Data.SBV.Core.Symbolic ( QueryContext(..), SetOp(..), getUserName, getUserName', getSV, regExpToSMTString, NROp(..), showNROp
+                              , SMTDef(..), SMTLambda(..), ResultInp(..), ProgInfo(..), SpecialRelOp(..), ADTOp(..)
+                              )
+
+import Data.SBV.Utils.PrettyNum (smtRoundingMode, cvToSMTLib)
+import Data.SBV.Utils.Lib       (showText)
+
+import qualified Data.Generics.Uniplate.Data as G
+
+import qualified Data.Graph as DG
+
+
+-- Check that all ADT subkinds are registered. If not, tell the user to do so
+-- NB. This should not be the case as we "automatically" register the subkinds
+-- as we encounter them. But this is mostly a if-something-goes-wrong check.
+checkKinds :: [Kind] -> Maybe String
+checkKinds ks = case [m | m@(n, _) <- apps, n `notElem` defs] of
+                  []       -> Nothing
+                  xs@(f:_) -> let (h, cnt) = case [p | p@(_, i) <- xs, i > 0] of
+                                               (p:_) -> p
+                                               _     -> f
+                                  plu | length xs > 1 = "s are"
+                                      | True          = " is"
+                                  msg = T.unlines $ [
+                                      "Data.SBV.mkSymbolic: Impossible happened! Unregistered subkinds."
+                                    , "***"
+                                    , "*** The following kind" <> plu <> " not registered: " <> T.unwords (map (T.pack . fst) xs)
+                                    , "***"
+                                    , "*** Please report this as a bug."
+                                    , "***"
+                                    , "*** As a workaround, you can try registering each ADT subfield, using: "
+                                    , "***"
+                                    , "***    {-# LANGUAGE TypeApplications #-}"
+                                    , "***"
+                                    , "***    import Data.Proxy"
+                                    , "***    registerType (Proxy @" <> mkProxy h cnt <> ")"
+                                    ]
+                                    ++ extras cnt
+                                    ++ [ "***"
+                                       , "*** Even if the workaround does the trick for you, it should not"
+                                       , "*** be needed. Please report this as a bug!"
+                                       ]
+                              in Just $ T.unpack msg
+
+
+  where apps = nub [(n, length as) | KApp n as <- concatMap expandKinds ks]
+        defs = nub [n | KADT n _ _ <- ks]
+        mkProxy h 0 = T.pack h
+        mkProxy h n = "(" <> T.unwords (T.pack h : replicate n "Integer") <> ")"
+
+        extras 0 = []
+        extras _ = [ "***"
+                   , "*** NB. You can use any base type as arguments, not just 'Integer'."
+                   , "*** It does not need to match the actual use cases, just one instance"
+                   , "*** at some base type is sufficent."
+                   ]
+
+-- | Translate a problem into an SMTLib2 script
+cvt :: SMTLibConverter (Text, Text)
+cvt ctx curProgInfo kindInfo isSat comments allInputs (_, consts) tbls uis defs (SBVPgm asgnsSeq) cstrs out cfg
+   | Just s <- checkKinds allKinds
+   = error s
+   | True
+   = (T.intercalate "\n" pgm, T.intercalate "\n" exportedDefs)
+  where allKinds       = Set.toList kindInfo
+
+        -- Below can simply be defined as: nub (sort (G.universeBi asgnsSeq))
+        -- Alas, it turns out this is really expensive when we have nested lambdas, so we do an explicit walk
+        allTopOps = Set.toList $ F.foldl' (\sofar (_, SBVApp o _) -> Set.insert o sofar) Set.empty asgnsSeq
+
+        hasInteger     = KUnbounded `Set.member` kindInfo
+        hasArrays      = not (null [() | KArray{}     <- allKinds])
+        hasNonBVArrays = not (null [() | KArray k1 k2 <- allKinds, not (isBounded k1 && isBounded k2)])
+        hasReal        = KReal      `Set.member` kindInfo
+        hasFP          =  not (null [() | KFP{} <- allKinds])
+                       || KFloat     `Set.member` kindInfo
+                       || KDouble    `Set.member` kindInfo
+        hasString      = KString     `Set.member` kindInfo
+        hasRegExp      = (not . null) [() | (_ :: RegExOp) <- G.universeBi allTopOps]
+        hasChar        = KChar      `Set.member` kindInfo
+        hasRounding    = any isRoundingMode allKinds
+        hasBVs         = not (null [() | KBounded{} <- allKinds])
+        adtsNoRM       = [(s, ps, cs) | k@(KADT s ps cs) <- allKinds, not (isRoundingMode k)]
+        tupleArities   = findTupleArities kindInfo
+        hasOverflows   = (not . null) [() | (_ :: OvOp) <- G.universeBi allTopOps]
+        hasQuantBools  = (not . null) [() | QuantifiedBool{} <- G.universeBi allTopOps]
+        hasList        = any isList kindInfo
+        hasSets        = any isSet kindInfo
+        hasTuples      = not . null $ tupleArities
+        hasRational    = any isRational kindInfo
+        hasADTs        = not . null $ adtsNoRM
+        solverCaps     = capabilities (solver cfg)
+
+        (needsQuantifiers, needsSpecialRels) = case curProgInfo of
+           ProgInfo hasQ srs tcs -> (hasQ, not (null srs && null tcs))
+
+        -- 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 solverCaps)]
+           where checks = [ ("data types",             supportsDataTypes,          hasTuples || hasADTs)
+                          , ("set operations",         supportsSets,               hasSets)
+                          , ("bit vectors",            supportsBitVectors,         hasBVs)
+                          , ("special relations",      supportsSpecialRels,        needsSpecialRels)
+                          , ("needs quantifiers",      supportsQuantifiers,        needsQuantifiers)
+                          , ("unbounded integers",     supportsUnboundedInts,      hasInteger)
+                          , ("algebraic reals",        supportsReals,              hasReal)
+                          , ("floating-point numbers", supportsIEEE754,            hasFP)
+                          , ("has data-types/sorts",   supportsADTs,               not (null adtsNoRM))
+                          ]
+
+                 nope w = [ "***     Given problem requires support for " <> T.pack w
+                          , "***     But the chosen solver (" <> showText (name (solver cfg)) <> ") doesn't support this feature."
+                          ]
+
+        -- Some cases require all, some require none.
+        setAll reason = [logicString cfg Logic_ALL <> " ; "  <> T.pack reason <> ", using catch-all."]
+
+        -- Determining the logic is surprisingly tricky!
+        logic :: [Text]
+        logic
+           -- user told us what to do: so just take it:
+           | Just l <- case [l | SetLogic l <- solverSetOptions cfg] of
+                         []  -> Nothing
+                         [l] -> Just l
+                         ls  -> error $ T.unpack $ T.unlines [ ""
+                                                             , "*** Only one setOption call to 'setLogic' is allowed, found: " <> showText (length ls)
+                                                             , "***  " <> T.unwords (map showText ls)
+                                                             ]
+           = case l of
+               Logic_NONE -> ["; NB. Not setting the logic per user request of Logic_NONE"]
+               _          -> [logicString cfg l <> " ; NB. User specified."]
+
+           -- There's a reason why we can't handle this problem:
+           | Just cantDo <- doesntHandle
+           = let msg = T.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."
+                                ]
+             in error $ T.unpack msg
+
+           -- Otherwise, we try to determine the most suitable logic.
+           -- NB. This isn't really fool proof!
+
+           -- we never set QF_S (ALL seems to work better in all cases)
+
+           | needsSpecialRels      = ["; has special relations, no logic set."]
+
+           -- Things that require ALL
+           | hasInteger            = setAll "has unbounded values"
+           | hasRational           = setAll "has rational values"
+           | hasReal               = setAll "has algebraic reals"
+           | hasADTs               = setAll "has user-defined data-types"
+           | hasNonBVArrays        = setAll "has non-bitvector arrays"
+           | hasTuples             = setAll "has tuples"
+           | hasSets               = setAll "has sets"
+           | hasList               = setAll "has lists"
+           | hasChar               = setAll "has chars"
+           | hasString             = setAll "has strings"
+           | hasRegExp             = setAll "has regular expressions"
+           | hasOverflows          = setAll "has overflow checks"
+           | hasQuantBools         = setAll "has quantified booleans"
+
+           | hasFP || hasRounding
+           = if needsQuantifiers
+             then [logicString cfg Logic_ALL]
+             else [logicString cfg (if hasBVs then QF_FPBV else QF_FP)]
+
+           -- If we're in a user query context, we'll pick ALL, otherwise
+           -- we'll stick to some bit-vector logic based on what we see in the problem.
+           -- This is controversial, but seems to work well in practice.
+           | True
+           = case ctx of
+               QueryExternal -> [logicString cfg Logic_ALL <> " ; external query, using all logics."]
+               QueryInternal -> if supportsBitVectors solverCaps
+                                then [logicString cfg picked]
+                                else [logicString cfg Logic_ALL] -- fall-thru
+          where picked
+                  | needsQuantifiers = Logic_ALL
+                  | True             = case (hasArrays, null uis && null tbls) of
+                                         (False, False) -> QF_UFBV
+                                         (False, True)  -> QF_BV
+                                         (True,  False) -> QF_AUFBV
+                                         (True,  True)  -> QF_ABV
+
+        -- SBV always requires the production of models!
+        getModels :: [Text]
+        getModels   = "(set-option :produce-models true)"
+                    : concat [map T.pack flattenConfig | any needsFlattening kindInfo, Just flattenConfig <- [supportsFlattenedModels solverCaps]]
+
+        -- process all other settings we're given. If an option cannot be repeated, we only take the last one.
+        userSettings = map (setSMTOption cfg) $ filter (not . isLogic) $ foldr comb [] $ solverSetOptions cfg
+           where -- Logic is already processed, so drop it:
+                 isLogic SetLogic{} = True
+                 isLogic _          = False
+
+                 -- SBV sets diagnostic-output channel on some solvers. If the user also gives it, let's just
+                 -- take it by only taking the last one
+                 isDiagOutput DiagnosticOutputChannel{} = True
+                 isDiagOutput _                         = False
+
+                 comb o rest
+                   | isDiagOutput o && any isDiagOutput rest =     rest
+                   | True                                    = o : rest
+
+        settings =  userSettings        -- NB. Make sure this comes first!
+                 <> getModels
+                 <> logic
+
+        (inputs, trackerVars)
+            = case allInputs of
+                ResultTopInps ists -> ists
+                ResultLamInps ps   -> error $ unlines [ ""
+                                                      , "*** Data.SBV.smtLib2: Unexpected lambda inputs in conversion"
+                                                      , "***"
+                                                      , "*** Saw: " ++ show ps
+                                                      ]
+
+        pgm  =  map (T.pack . ("; " <>)) comments
+             <> settings
+             <> [ "; --- tuples ---" ]
+             <> concatMap declTuple tupleArities
+             <> [ "; --- sums ---" ]
+             <> (if containsRationals kindInfo then declRationals else [])
+             <> [ "; --- ADTs  --- " | not (null adtsNoRM)]
+             <> declADT adtsNoRM
+             <> [ "; --- literal constants ---" ]
+             <> concatMap (declConst cfg) consts
+             <> [ "; --- top level inputs ---"]
+             <> concat [declareFun s (SBVType [kindOf s]) (userName s) | var <- inputs, let s = getSV var]
+             <> [ "; --- optimization tracker variables ---" | not (null trackerVars) ]
+             <> concat [declareFun s (SBVType [kindOf s]) (Just ("tracks " <> getUserName var)) | var <- trackerVars, let s = getSV var]
+             <> [ "; --- constant tables ---" ]
+             <> concatMap (uncurry (:) . mkTable) constTables
+             <> [ "; --- non-constant tables ---" ]
+             <> map nonConstTable nonConstTables
+             <> [ "; --- uninterpreted constants ---" ]
+             <> concatMap (declUI curProgInfo) uis
+             <> [ "; --- user defined functions ---"]
+             <> userDefs
+             <> [ "; --- assignments ---" ]
+             <> concatMap (declDef curProgInfo cfg tableMap) asgns
+             <> [ "; --- delayedEqualities ---" ]
+             <> map (\s -> "(assert " <> s <> ")") delayedEqualities
+             <> [ "; --- formula ---" ]
+             <> finalAssert
+
+        userDefs = declUserFuns defs
+        exportedDefs
+          | null userDefs
+          = ["; No calls to 'smtFunction' found."]
+          | True
+          = "; Automatically generated by SBV. Do not modify!" : userDefs
+
+
+        (tableMap, constTables, nonConstTables) = constructTables consts tbls
+
+        delayedEqualities = concatMap snd nonConstTables
+
+        finalAssert
+          | noConstraints = []
+          | True          =    map (\(attr, v) -> "(assert "      <> addAnnotations attr (mkLiteral v) <> ")") hardAsserts
+                            <> map (\(attr, v) -> "(assert-soft " <> addAnnotations attr (mkLiteral v) <> ")") softAsserts
+          where mkLiteral (Left  v) =            cvtSV v
+                mkLiteral (Right v) = "(not " <> cvtSV v <> ")"
+
+                (noConstraints, assertions) = finalAssertions
+
+                hardAsserts, softAsserts :: [([(String, String)], Either SV SV)]
+                hardAsserts = [(attr, v) | (False, attr, v) <- assertions]
+                softAsserts = [(attr, v) | (True,  attr, v) <- assertions]
+
+        finalAssertions :: (Bool, [(Bool, [(String, String)], Either SV SV)])  -- If Left: positive, Right: negative
+        finalAssertions
+           | null finals = (True,  [(False, [], Left trueSV)])
+           | True        = (False, finals)
+
+           where finals  = cstrs' ++ maybe [] (\r -> [(False, [], r)]) mbO
+
+                 cstrs' =  [(isSoft, attrs, c') | (isSoft, attrs, c) <- F.toList cstrs, Just c' <- [pos c]]
+
+                 mbO | isSat = pos out
+                     | True  = neg out
+
+                 neg s
+                  | s == falseSV = Nothing
+                  | s == trueSV  = Just $ Left falseSV
+                  | True         = Just $ Right s
+
+                 pos s
+                  | s == trueSV  = Nothing
+                  | s == falseSV = Just $ Left falseSV
+                  | True         = Just $ Left s
+
+        asgns = F.toList asgnsSeq
+
+        userNameMap = M.fromList $ map (\nSymVar -> (getSV nSymVar, getUserName' nSymVar)) inputs
+        userName s = case M.lookup s userNameMap of
+                        Just u  | show s /= u -> Just $ "tracks user variable " <> showText u
+                        _                     -> Nothing
+
+-- | Declare ADTs
+declADT :: [(String, [(String, Kind)], [(String, [Kind])])] -> [Text]
+declADT = concatMap declGroup . DG.stronglyConnComp . map mkNode
+  where mkNode adt@(n, pks, cstrs) = (adt, n, [s | KApp s _ <- concatMap expandKinds (map snd pks ++ concatMap snd cstrs)])
+
+        declGroup (DG.AcyclicSCC d )  = singleADT d
+        declGroup (DG.CyclicSCC  ds)
+            = case ds of
+                []  -> error "Data.SBV.declADT: Impossible happened: an empty cyclic group was returned!"
+                [d] -> singleADT d
+                _   -> multiADT ds
+
+        parParens :: [(String, Kind)] -> (Text, Text)
+        parParens [] = ("", "")
+        parParens ps = (" (par (" <> T.unwords (map (T.pack . fst) ps) <> ")", ")")
+
+        mkC (nm, []) = T.pack nm
+        mkC (nm, ts) = T.pack nm <> " " <> T.unwords ['(' `T.cons` mkF (nm <> "_" <> show i) t <> ")" | (i, t) <- zip [(1::Int)..] ts]
+          where mkF a t  = "get" <> T.pack a <> " " <> smtType t
+
+        singleADT :: (String, [(String, Kind)], [(String, [Kind])]) -> [Text]
+        singleADT (tName, [], []) = ["(declare-sort " <> T.pack tName <> " 0) ; N.B. Uninterpreted sort."]
+        singleADT (tName, pks, cstrs) = ("; User defined ADT: " <> T.pack tName) : decl
+          where decl =  ("(declare-datatype " <> T.pack tName <> parOpen <> " (")
+                     :  ["    (" <> mkC c <> ")" | c <- cstrs]
+                     <> ["))" <> parClose]
+
+                (parOpen, parClose) = parParens pks
+
+        multiADT :: [(String, [(String, Kind)], [(String, [Kind])])] -> [Text]
+        multiADT adts = ("; User defined mutually-recursive ADTs: " <> T.intercalate ", " (map (\(a, _, _) -> T.pack a) adts)) : decl
+          where decl = ("(declare-datatypes (" <> typeDecls <> ") (")
+                     : concatMap adtBody adts
+                    <> ["))"]
+
+                typeDecls = T.unwords ['(' `T.cons` T.pack name <> " " <> showText (length pks) <> ")" | (name, pks, _) <- adts]
+
+                adtBody (_, pks, cstrs) = body
+                  where (parOpen, parClose) = parParens pks
+                        body =  ("    " <> parOpen <> " (")
+                             :  ["        (" <> mkC c <> ")" | c <- cstrs]
+                             <> ["     )" <> parClose]
+
+-- | Declare tuple datatypes
+--
+-- eg:
+--
+-- @
+-- (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+--                                     ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+--                                                   (proj_2_SBVTuple2 T2))))))
+-- @
+declTuple :: Int -> [Text]
+declTuple arity
+  | arity == 0 = ["(declare-datatypes ((SBVTuple0 0)) (((mkSBVTuple0))))"]
+  | arity == 1 = error "Data.SBV.declTuple: Unexpected one-tuple"
+  | True       =    (l1 <> "(par (" <> T.unwords [param i | i <- [1..arity]] <> ")")
+                 :  [pre i <> proj i <> post i    | i <- [1..arity]]
+  where l1     = "(declare-datatypes ((SBVTuple" <> showText arity <> " " <> showText arity <> ")) ("
+        l2     = T.replicate (T.length l1) " " <> "((mkSBVTuple" <> showText arity <> " "
+        tab    = T.replicate (T.length l2) " "
+
+        pre 1  = l2
+        pre _  = tab
+
+        proj i = "(proj_" <> showText i <> "_SBVTuple" <> showText arity <> " " <> param i <> ")"
+
+        post i = if i == arity then ")))))" else ""
+
+        param i = "T" <> showText i
+
+-- | Find the set of tuple sizes to declare, eg (2-tuple, 5-tuple).
+-- NB. We do *not* need to recursively go into list/tuple kinds here,
+-- because register-kind function automatically registers all subcomponent
+-- kinds, thus everything we need is available at the top-level.
+findTupleArities :: Set Kind -> [Int]
+findTupleArities ks = Set.toAscList
+                    $ Set.map length
+                    $ Set.fromList [ tupKs | KTuple tupKs <- Set.toList ks ]
+
+-- | Is @Rational@ being used?
+containsRationals :: Set Kind -> Bool
+containsRationals = not . Set.null . Set.filter isRational
+
+-- Internally, we do *not* keep the rationals in reduced form! So, the boolean operators explicitly do the math
+-- to make sure equivalent values are treated correctly.
+declRationals :: [Text]
+declRationals = [ "(declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))"
+                , ""
+                , "(define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool"
+                , "   (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))"
+                , "      (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))"
+                , ")"
+                , ""
+                , "(define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool"
+                , "   (not (sbv.rat.eq x y))"
+                , ")"
+                ]
+
+-- | 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 :: SMTLibIncConverter [Text]
+cvtInc curProgInfo inps newKs (_, consts) tbls uis (SBVPgm asgnsSeq) cstrs cfg =
+            -- any new settings?
+               settings
+            -- sorts
+            <> declADT [(s, pks, cs) | k@(KADT s pks cs) <- newKinds, not (isRoundingMode k)]
+            -- tuples. NB. Only declare the new sizes, old sizes persist.
+            <> concatMap declTuple (findTupleArities newKs)
+            -- constants
+            <> concatMap (declConst cfg) consts
+            -- inputs
+            <> concatMap declInp inps
+            -- uninterpreteds
+            <> concatMap (declUI curProgInfo) uis
+            -- table declarations
+            <> tableDecls
+            -- expressions
+            <> concatMap (declDef curProgInfo cfg tableMap) asgnsSeq
+            -- table setups
+            <> concat tableAssigns
+            -- extra constraints
+            <> map (\(isSoft, attr, v) -> "(assert" <> (if isSoft then "-soft " else " ") <> addAnnotations attr (cvtSV v) <> ")") (F.toList cstrs)
+  where newKinds = Set.toList newKs
+
+        declInp (getSV -> s) = declareFun s (SBVType [kindOf s]) Nothing
+
+        (tableMap, allTables) = (tm, ct <> nct)
+            where (tm, ct, nct) = constructTables consts tbls
+
+        (tableDecls, tableAssigns) = unzip $ map mkTable allTables
+
+        -- If we need flattening in models, do emit the required lines if preset
+        settings
+          | any needsFlattening newKinds
+          = concat (catMaybes [map T.pack <$> supportsFlattenedModels solverCaps])
+          | True
+          = []
+          where solverCaps = capabilities (solver cfg)
+
+declDef :: ProgInfo -> SMTConfig -> TableMap -> (SV, SBVExpr) -> [Text]
+declDef curProgInfo cfg tableMap (s, expr) =
+        case expr of
+          SBVApp  (Label m) [e] -> defineFun cfg (s, cvtSV                                   e) (Just $ T.pack m)
+          e                     -> defineFun cfg (s, cvtExp cfg curProgInfo caps rm tableMap e) Nothing
+  where caps = capabilities (solver cfg)
+        rm   = roundingMode cfg
+
+defineFun :: SMTConfig -> (SV, Text) -> Maybe Text -> [Text]
+defineFun cfg (s, def) mbComment
+   | hasDefFun = ["(define-fun "  <> varT <> " " <> def <> ")" <> cmnt]
+   | True      = [ "(declare-fun " <> varT <> ")" <> cmnt
+                 , "(assert (= " <> var <> " " <> def <> "))"
+                 ]
+  where var  = showText s
+        varT = var <> " " <> svFunType [] s
+        cmnt = maybe "" (" ; " <>) mbComment
+
+        hasDefFun = supportsDefineFun $ capabilities (solver cfg)
+
+-- Declare constants. NB. We don't declare true/false; but just inline those as necessary
+declConst :: SMTConfig -> (SV, CV) -> [Text]
+declConst cfg (s, c)
+  | s == falseSV || s == trueSV
+  = []
+  | True
+  = defineFun cfg (s, cvtCV c) Nothing
+
+-- Make a function equality of nm against the internal function fun
+mkRelEq :: Text -> (Text, Text) -> Kind -> Text
+mkRelEq nm (fun, order) ak = res
+   where lhs = "(" <> nm <> " x y)"
+         rhs = "((_ " <> fun <> " " <> order <> ") x y)"
+         tk  = smtType ak
+         res = "(forall ((x " <> tk <> ") (y " <> tk <> ")) (= " <> lhs <> " " <> rhs <> "))"
+
+declUI :: ProgInfo -> (String, (Bool, Maybe [String], SBVType)) -> [Text]
+declUI ProgInfo{progTransClosures} (i, (_, _, t)) = declareName (T.pack i) t Nothing <> declClosure
+  where declClosure | Just external <- lookup i progTransClosures
+                    =  declareName (T.pack external) t Nothing
+                    <> ["(assert " <> mkRelEq (T.pack external) ("transitive-closure", T.pack i) (argKind t) <> ")"]
+                    | True
+                    = []
+
+        argKind (SBVType [ka, _, KBool]) = ka
+        argKind _                        = error $ "declUI: Unexpected type for name: " <> show (i, t)
+
+-- Note that even though we get all user defined-functions here (i.e., lambda and axiom), we can only have defined-functions
+-- and axioms. We spit axioms as is; and topologically sort the definitions.
+declUserFuns :: [(String, (SMTDef, SBVType))] -> [Text]
+declUserFuns ds = map declGroup sorted
+  where mkNode d = (d, fst d, getDeps d)
+
+        getDeps (_, (SMTDef _ d _ _, _)) = d
+
+        mkDecl Nothing  rt = "() " <> rt
+        mkDecl (Just p) rt = p <> " " <> rt
+
+        sorted = DG.stronglyConnComp (map mkNode ds)
+
+        declGroup (DG.AcyclicSCC b)  = declUserDef False b
+        declGroup (DG.CyclicSCC  bs) = case bs of
+                                         []  -> error "Data.SBV.declFuns: Impossible happened: an empty cyclic group was returned!"
+                                         [x] -> declUserDef True x
+                                         xs  -> declUserDefMulti xs
+
+        declUserDef isRec (nm, (SMTDef fk deps param body, ty)) =
+          "; " <> T.pack nm <> " :: " <> showText ty <> recursive <> frees <> "\n" <> s
+           where (recursive, definer) | isRec = (" [Recursive]", "define-fun-rec")
+                                      | True  = ("",             "define-fun")
+
+                 otherDeps = filter (/= nm) deps
+                 frees | null otherDeps = ""
+                       | True           = " [Refers to: " <> T.intercalate ", " (map T.pack otherDeps) <> "]"
+
+                 decl = mkDecl param (smtType fk)
+
+                 s = "(" <> definer <> " " <> T.pack nm <> " " <> decl <> "\n" <> body 2 <> ")"
+
+        -- declare a bunch of mutually-recursive functions
+        declUserDefMulti bs = render $ map collect bs
+          where collect (nm, (SMTDef fk deps param body, ty)) = (deps, nm, ty, "(" <> T.pack nm <> " " <> decl <> ")", body 3)
+                  where decl = mkDecl param (smtType fk)
+
+                render defs = T.intercalate "\n" $
+                                  [ "; " <> T.intercalate ", " [T.pack n <> " :: " <> showText ty | (_, n, ty, _, _) <- defs]
+                                  , "(define-funs-rec"
+                                  ]
+                               <> [ open i <> param d <> close1 i | (i, d) <- zip [1..] defs]
+                               <> [ open i <> dump  d <> close2 i | (i, d) <- zip [1..] defs]
+                     where open 1 = "  ("
+                           open _ = "   "
+
+                           param (_deps, _nm, _ty, p, _body) = p
+
+                           dump (deps, nm, ty, _, body) = "; Definition of: " <> T.pack nm <> " :: " <> showText ty <> ". [Refers to: " <> T.intercalate ", " (map T.pack deps) <> "]"
+                                                        <> "\n" <> body
+
+                           ld = length defs
+
+                           close1 n = if n == ld then ")"  else ""
+                           close2 n = if n == ld then "))" else ""
+
+mkTable :: (((Int, Kind, Kind), [SV]), [Text]) -> (Text, [Text])
+mkTable (((i, ak, rk), _elts), is) = (decl, zipWith wrap [(0::Int)..] is <> setup)
+  where t       = "table" <> showText i
+        decl    = "(declare-fun " <> t <> " (" <> smtType ak <> ") " <> smtType rk <> ")"
+
+        -- Arrange for initializers
+        mkInit idx   = "table" <> showText i <> "_initializer_" <> showText (idx :: Int)
+        initializer  = "table" <> showText i <> "_initializer"
+
+        wrap index s = "(define-fun " <> mkInit index <> " () Bool " <> s <> ")"
+
+        lis  = length is
+
+        setup
+          | lis == 0       = [ "(define-fun " <> initializer <> " () Bool true) ; no initialization needed"
+                             ]
+          | lis == 1       = [ "(define-fun " <> initializer <> " () Bool " <> mkInit 0 <> ")"
+                             , "(assert " <> initializer <> ")"
+                             ]
+          | True           = [ "(define-fun " <> initializer <> " () Bool (and " <> T.unwords (map mkInit [0..lis - 1]) <> "))"
+                             , "(assert " <> initializer <> ")"
+                             ]
+nonConstTable :: (((Int, Kind, Kind), [SV]), [Text]) -> Text
+nonConstTable (((i, ak, rk), _elts), _) = decl
+  where t    = "table" <> showText i
+        decl = "(declare-fun " <> t <> " (" <> smtType ak <> ") " <> smtType rk <> ")"
+
+constructTables :: [(SV, CV)] -> [((Int, Kind, Kind), [SV])]
+                -> ( IM.IntMap Text                              -- table enumeration
+                   , [(((Int, Kind, Kind), [SV]), [Text])]       -- constant tables
+                   , [(((Int, Kind, Kind), [SV]), [Text])]       -- non-constant tables
+                   )
+constructTables consts tbls = (tableMap, constTables, nonConstTables)
+ where allTables      = [(t, genTableData (map fst consts) t) | t <- tbls]
+       constTables    = [(t, d) | (t, Left  d) <- allTables]
+       nonConstTables = [(t, d) | (t, Right d) <- allTables]
+       tableMap       = IM.fromList $ map grab allTables
+
+       grab (((t, _, _), _), _) = (t, "table" <> showText t)
+
+-- Left if all constants, Right if otherwise
+genTableData :: [SV] -> ((Int, Kind, Kind), [SV]) -> Either [Text] [Text]
+genTableData consts ((i, aknd, _), elts)
+  | null post = Left  (map (mkEntry . snd) pre)
+  | True      = Right (map (mkEntry . snd) (pre ++ post))
+  where (pre, post) = partition fst (zipWith mkElt elts [(0::Int)..])
+        t           = "table" <> showText i
+
+        mkElt x k   = (isReady, (idx, cvtSV x))
+          where idx = cvtCV (mkConstCV aknd k)
+                isReady = x `Set.member` constsSet
+
+        mkEntry (idx, v) = "(= (" <> t <> " " <> idx <> ") " <> v <> ")"
+
+        constsSet = Set.fromList consts
+
+svType :: SV -> Text
+svType s = smtType (kindOf s)
+
+svFunType :: [SV] -> SV -> Text
+svFunType ss s = "(" <> T.unwords (map svType ss) <> ") " <> svType s
+
+cvtType :: SBVType -> Text
+cvtType (SBVType []) = error "SBV.SMT.SMTLib2.cvtType: internal: received an empty type!"
+cvtType (SBVType xs) = "(" <> T.unwords (map smtType body) <> ") " <> smtType ret
+  where (body, ret) = (init xs, last xs)
+
+type TableMap = IM.IntMap Text
+
+-- Present an SV, simply show
+cvtSV :: SV -> Text
+cvtSV = showText
+
+cvtCV :: CV -> Text
+cvtCV = cvToSMTLib
+
+getTable :: TableMap -> Int -> Text
+getTable m i
+  | Just tn <- i `IM.lookup` m = tn
+  | True                       = "table" <> showText i
+
+cvtExp :: SMTConfig -> ProgInfo -> SolverCapabilities -> RoundingMode -> TableMap -> SBVExpr -> Text
+cvtExp cfg curProgInfo caps rm tableMap expr@(SBVApp _ arguments) = sh expr
+  where hasPB       = supportsPseudoBooleans caps
+        hasDistinct = supportsDistinct       caps
+        specialRels = progSpecialRels        curProgInfo
+
+        bvOp     = all isBounded   arguments
+        intOp    = any isUnbounded arguments
+        ratOp    = any isRational  arguments
+        realOp   = any isReal      arguments
+        fpOp     = any (\a -> isDouble a || isFloat a || isFP a) 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
+
+        ensureBVOrBool = bvOp || boolOp || bad
+        ensureBV       = bvOp || bad
+
+        addRM s = s <> " " <> smtRoundingMode rm
+
+        isZ3 = case name (solver cfg) of
+                 Z3 -> True
+                 _  -> False
+
+        isCVC5 = case name (solver cfg) of
+                   CVC5 -> True
+                   _    -> False
+
+        hd _ (a:_) = a
+        hd w []    = error $ "Impossible: " ++ w ++ ": Received empty list of args!"
+
+        -- lift a binary op
+        lift2  o _ [x, y] = "(" <> o <> " " <> x <> " " <> y <> ")"
+        lift2  o _ sbvs   = error $ "SBV.SMTLib2.sh.lift2: Unexpected arguments: " ++ show (o, sbvs)
+
+        -- lift an arbitrary arity operator
+        liftN o _ xs = "(" <> o <> " " <> T.unwords xs <> ")"
+
+        -- lift a binary operation with rounding-mode added; used for floating-point arithmetic
+        lift2WM o fo | fpOp = lift2 (addRM fo)
+                     | True = lift2 o
+
+        lift1FP o fo | fpOp = lift1 fo
+                     | True = lift1 o
+
+        liftAbs sgned args | fpOp        = lift1 "fp.abs" sgned args
+                           | intOp       = lift1 "abs"    sgned args
+                           | bvOp, sgned = mkAbs fArg "bvslt" "bvneg"
+                           | bvOp        = fArg
+                           | True        = mkAbs fArg "<"     "-"
+          where fArg = hd "liftAbs" args
+                mkAbs x cmp neg = "(ite " <> ltz <> " " <> nx <> " " <> x <> ")"
+                  where ltz = "(" <> cmp <> " " <> x <> " " <> z <> ")"
+                        nx  = "(" <> neg <> " " <> x <> ")"
+                        z   = cvtCV (mkConstCV (kindOf (hd "liftAbs.arguments" arguments)) (0::Integer))
+
+        lift2B bOp vOp
+          | boolOp = lift2 bOp
+          | True   = lift2 vOp
+
+        lift1B bOp vOp
+          | boolOp = lift1 bOp
+          | True   = lift1 vOp
+
+        eqBV  = lift2 "="
+        neqBV = liftN "distinct"
+
+        equal sgn sbvs
+          | fpOp = lift2 "fp.eq" sgn sbvs
+          | True = lift2 "="     sgn sbvs
+
+        -- Do not use distinct on floats; because +0/-0, and NaNs mess
+        -- up the meaning. Just go with regular equals.
+        notEqual sgn sbvs
+          | fpOp || not hasDistinct = liftP sbvs
+          | True                    = liftN "distinct" sgn sbvs
+          where liftP xs@[_, _] = "(not " <> equal sgn xs <> ")"
+                liftP args      = "(and " <> T.unwords (walk args) <> ")"
+
+                walk []     = []
+                walk (e:es) = map (\e' -> liftP [e, e']) es <> walk es
+
+        lift2S oU oS sgn = lift2 (if sgn then oS else oU) sgn
+        liftNS oU oS sgn = liftN (if sgn then oS else oU) sgn
+
+        lift2Cmp o fo | fpOp = lift2 fo
+                      | True = lift2 o
+
+        stringOrChar KString = True
+        stringOrChar KChar   = True
+        stringOrChar _       = False
+        stringCmp swap o [a, b]
+          | stringOrChar (kindOf (hd "stringCmp" arguments))
+          = let (a1, a2) | swap = (b, a)
+                         | True = (a, b)
+            in "(" <> o <> " " <> a1 <> " " <> a2 <> ")"
+        stringCmp _ o sbvs = error $ "SBV.SMT.SMTLib2.sh.stringCmp: Unexpected arguments: " ++ show (o, sbvs)
+
+        -- NB. Likewise for sequences
+        seqCmp swap o [a, b]
+          | KList{} <- kindOf (hd "seqCmp" arguments)
+          = let (a1, a2) | swap = (b, a)
+                         | True = (a, b)
+            in "(" <> o <> " " <> a1 <> " " <> a2 <> ")"
+        seqCmp _ o sbvs = error $ "SBV.SMT.SMTLib2.sh.seqCmp: Unexpected arguments: " ++ show (o, sbvs)
+
+        lift1  o _ [x]    = "(" <> o <> " " <> x <> ")"
+        lift1  o _ sbvs   = error $ "SBV.SMTLib2.sh.lift1: Unexpected arguments: " ++ show (o, sbvs)
+
+        sh (SBVApp Ite [a, b, c]) = "(ite " <> cvtSV a <> " " <> cvtSV b <> " " <> cvtSV c <> ")"
+
+        sh (SBVApp (LkUp (t, aKnd, _, l) i e) [])
+          | needsCheck = "(ite " <> cond <> cvtSV e <> " " <> lkUp <> ")"
+          | True       = lkUp
+          where unexpected = error $ "SBV.SMT.SMTLib2.cvtExp: Unexpected: " ++ show aKnd
+                needsCheck = case aKnd of
+                              KVar{}        -> unexpected
+                              KBool         -> (2::Integer) > fromIntegral l
+                              KBounded _ n  -> (2::Integer)^n > fromIntegral l
+                              KUnbounded    -> True
+                              KApp _ _      -> unexpected
+                              KADT _ _ _    -> unexpected
+                              KReal         -> unexpected
+                              KFloat        -> unexpected
+                              KDouble       -> unexpected
+                              KFP _ _       -> unexpected
+                              KRational     -> unexpected
+                              KChar         -> unexpected
+                              KString       -> unexpected
+                              KList _       -> unexpected
+                              KSet  _       -> unexpected
+                              KTuple _      -> unexpected
+                              KArray  _ _   -> unexpected
+
+                lkUp = "(" <> getTable tableMap t <> " " <> cvtSV i <> ")"
+
+                cond
+                 | hasSign i = "(or " <> le0 <> " " <> gtl <> ") "
+                 | True      = gtl <> " "
+
+                (less, leq) = case aKnd of
+                                KVar{}        -> error "SBV.SMT.SMTLib2.cvtExp: unexpected variable index"
+                                KBool         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected boolean valued index"
+                                KBounded{}    -> if hasSign i then ("bvslt", "bvsle") else ("bvult", "bvule")
+                                KUnbounded    -> ("<", "<=")
+                                KReal         -> ("<", "<=")
+                                KFloat        -> ("fp.lt", "fp.leq")
+                                KDouble       -> ("fp.lt", "fp.leq")
+                                KRational     -> ("sbv.rat.lt", "sbv.rat.leq")
+                                KFP{}         -> ("fp.lt", "fp.leq")
+                                KChar         -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
+                                KString       -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
+                                KApp  s _     -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected ADT applied index: " ++ s
+                                KADT  s _ _   -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected ADT valued index: " ++ s
+                                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
+                                KArray  k1 k2 -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected array valued index: " ++ show (k1, k2)
+
+                mkCnst = cvtCV . mkConstCV (kindOf i)
+                le0  = "(" <> less <> " " <> cvtSV i <> " " <> mkCnst 0 <> ")"
+                gtl  = "(" <> leq  <> " " <> mkCnst l <> " " <> cvtSV i <> ")"
+
+        sh (SBVApp (KindCast f t) [a]) = handleKindCast f t (cvtSV a)
+
+        sh (SBVApp (ArrayInit (Left (f, t))) [a])        = "((as const (Array " <> smtType f <> " " <> smtType t <> ")) " <> cvtSV a <> ")"
+        sh (SBVApp (ArrayInit (Right (SMTLambda s))) []) = s
+        sh (SBVApp ReadArray             [a, i])         = "(select " <> cvtSV a <> " " <> cvtSV i <> ")"
+        sh (SBVApp WriteArray            [a, i, e])      = "(store "  <> cvtSV a <> " " <> cvtSV i <> " " <> cvtSV e <> ")"
+
+        sh (SBVApp (Uninterpreted nm) [])   = nm
+        sh (SBVApp (Uninterpreted nm) args) = "(" <> nm <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        sh (SBVApp (ADTOp aop) args) = handleADT caps aop args
+
+        sh (SBVApp (QuantifiedBool i) [])   = i
+        sh (SBVApp (QuantifiedBool i) args) = error $ "SBV.SMT.SMTLib2.cvtExp: unexpected arguments to quantified boolean: " ++ show (T.unpack i, args)
+
+        sh a@(SBVApp (SpecialRelOp k o) args)
+          | not (null args)
+          = error $ "SBV.SMT.SMTLib2.cvtExp: unexpected arguments to special op: " ++ show a
+          | True
+          = let order = case o `elemIndex` specialRels of
+                          Just i -> i
+                          Nothing -> error $ unlines [ "SBV.SMT.SMTLib2.cvtExp: Cannot find " ++ show o ++ " in the special-relations list."
+                                                     , "Known relations: " ++ intercalate ", " (map show specialRels)
+                                                     ]
+                asrt nm fun = mkRelEq (T.pack nm) (T.pack fun, showText order) k
+            in case o of
+                 IsPartialOrder         nm -> asrt nm "partial-order"
+                 IsLinearOrder          nm -> asrt nm "linear-order"
+                 IsTreeOrder            nm -> asrt nm "tree-order"
+                 IsPiecewiseLinearOrder nm -> asrt nm "piecewise-linear-order"
+
+        sh (SBVApp (Divides n) [a]) = "((_ divisible " <> showText n <> ") " <> cvtSV a <> ")"
+
+        sh (SBVApp (Extract i j) [a]) | ensureBV = "((_ extract " <> showText i <> " " <> showText j <> ") " <> cvtSV a <> ")"
+
+        sh (SBVApp (Rol i) [a])
+           | bvOp  = rot "rotate_left"  i a
+           | True  = bad
+
+        sh (SBVApp (Ror i) [a])
+           | bvOp  = rot  "rotate_right" i a
+           | True  = bad
+
+        sh (SBVApp Shl [a, i])
+           | bvOp   = shft "bvshl"  "bvshl" a i
+           | True   = bad
+
+        sh (SBVApp Shr [a, i])
+           | bvOp  = shft "bvlshr" "bvashr" a i
+           | True  = bad
+
+        sh (SBVApp (ZeroExtend i) [a])
+          | bvOp = "((_ zero_extend " <> showText i <> ") " <> cvtSV a <> ")"
+          | True = bad
+
+        sh (SBVApp (SignExtend i) [a])
+          | bvOp = "((_ sign_extend " <> showText i <> ") " <> cvtSV a <> ")"
+          | True = bad
+
+        sh (SBVApp op args)
+          | Just f <- lookup op smtBVOpTable, ensureBVOrBool
+          = f (any hasSign args) (map cvtSV args)
+          where -- The first 4 operators below do make sense for Integer's in Haskell, but there's
+                -- no obvious counterpart for them in the SMTLib translation.
+                -- TODO: provide support for these.
+                smtBVOpTable = [ (And,  lift2B "and" "bvand")
+                               , (Or,   lift2B "or"  "bvor")
+                               , (XOr,  lift2B "xor" "bvxor")
+                               , (Not,  lift1B "not" "bvnot")
+                               , (Join, lift2 "concat")
+                               ]
+
+        sh (SBVApp (Label _) [a]) = cvtSV a  -- This won't be reached; but just in case!
+
+        sh (SBVApp (IEEEFP (FP_Cast kFrom kTo m)) args) = handleFPCast kFrom kTo (cvtSV m) (T.unwords (map cvtSV args))
+        sh (SBVApp (IEEEFP w                    ) args) = "(" <> showText w <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        -- Some non-linear operators are supported by z3/CVC5 specifically, so do the custom translation Otherwise
+        -- we pass them along.
+        sh (SBVApp (NonLinear NR_Sqrt) [a])    | isZ3   = "(^ "    <> cvtSV a <> " 0.5)"
+                                               | isCVC5 = "(sqrt " <> cvtSV a <>     ")"
+
+        sh (SBVApp (NonLinear NR_Pow)  [a, b]) | isZ3 || isCVC5  = "(^  " <> cvtSV a <> " " <> cvtSV b <> ")"
+
+        sh (SBVApp (NonLinear w) [])   =        T.pack (showNROp (name (solver cfg)) w)
+        sh (SBVApp (NonLinear w) args) = "(" <> T.pack (showNROp (name (solver cfg)) w) <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        sh (SBVApp (PseudoBoolean pb) args)
+          | hasPB = handlePB pb args'
+          | True  = reducePB pb args'
+          where args' = map cvtSV args
+
+        sh (SBVApp (OverflowOp op) args) = "(" <> showText op <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        -- Note the unfortunate reversal in StrInRe..
+        sh (SBVApp (StrOp (StrInRe r)) args) = "(str.in_re " <> T.unwords (map cvtSV args) <> " " <> regExpToSMTString r <> ")"
+        sh (SBVApp (StrOp op)          args) = "(" <> showText op <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        sh (SBVApp (RegExOp o@RegExEq{})  []) = showText o
+        sh (SBVApp (RegExOp o@RegExNEq{}) []) = showText o
+
+        -- Sequences. The only interesting thing here is that unit over KChar is a no-op since SMTLib doesn't distinguish
+        -- Strings and Characters, but SBV does.
+        sh (SBVApp (SeqOp (SeqUnit KChar)) [a]) = cvtSV a
+        sh (SBVApp (SeqOp op)             args) = "(" <> showText op <> " " <> T.unwords (map cvtSV args) <> ")"
+
+        sh (SBVApp (SetOp SetEqual)      args)   = "(= "      <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (SetOp SetMember)     [e, s]) = "(select " <> cvtSV s <> " " <> cvtSV e <> ")"
+        sh (SBVApp (SetOp SetInsert)     [e, s]) = "(store "  <> cvtSV s <> " " <> cvtSV e <> " true)"
+        sh (SBVApp (SetOp SetDelete)     [e, s]) = "(store "  <> cvtSV s <> " " <> cvtSV e <> " false)"
+        sh (SBVApp (SetOp SetIntersect)  args)   = "(intersection " <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (SetOp SetUnion)      args)   = "(union "        <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (SetOp SetSubset)     args)   = "(subset "       <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (SetOp SetDifference) args)   = "(setminus "     <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (SetOp SetComplement) args)   = "(complement "   <> T.unwords (map cvtSV args) <> ")"
+
+        sh (SBVApp (TupleConstructor 0)   [])    = "mkSBVTuple0"
+        sh (SBVApp (TupleConstructor n)   args)  = "((as mkSBVTuple" <> showText n <> " " <> smtType (KTuple (map kindOf args)) <> ") " <> T.unwords (map cvtSV args) <> ")"
+        sh (SBVApp (TupleAccess      i n) [tup]) = "(proj_" <> showText i <> "_SBVTuple" <> showText n <> " " <> cvtSV tup <> ")"
+
+        sh (SBVApp  RationalConstructor    [t, b]) = "(SBV.Rational " <> cvtSV t <> " " <> cvtSV b <> ")"
+
+        sh (SBVApp Implies [a, b]) = "(=> " <> cvtSV a <> " " <> cvtSV b <> ")"
+
+        sh inp@(SBVApp op args)
+          | intOp, Just f <- lookup op smtOpIntTable
+          = f True (map cvtSV args)
+          | boolOp, Just f <- lookup op boolComps
+          = f (map cvtSV args)
+          | bvOp, Just f <- lookup op smtOpBVTable
+          = f (any hasSign args) (map cvtSV args)
+          | realOp, Just f <- lookup op smtOpRealTable
+          = f (any hasSign args) (map cvtSV args)
+          | ratOp, Just f <- lookup op ratOpTable
+          = f (map cvtSV args)
+          | fpOp, Just f <- lookup op smtOpFloatDoubleTable
+          = f (any hasSign args) (map cvtSV args)
+          | charOp || stringOp, Just f <- lookup op smtStringTable
+          = f (map cvtSV args)
+          | listOp, Just f <- lookup op smtListTable
+          = f (map cvtSV args)
+          | Just f <- lookup op uninterpretedTable
+          = f (map cvtSV args)
+          | True
+          = error $ unlines [ ""
+                            , "*** SBV.SMT.SMTLib2.cvtExp.sh: impossible happened; can't translate: " ++ show inp
+                            , "***"
+                            , "*** Applied to arguments of type: " ++ intercalate ", " (nub (map (show . kindOf) args))
+                            , "***"
+                            , "*** This can happen if the Num instance isn't properly defined for a lifted kind."
+                            , "*** (See https://github.com/LeventErkok/sbv/issues/698 for a discussion.)"
+                            , "***"
+                            , "*** If you believe this is in error, please report!"
+                            ]
+          where smtOpBVTable  = [ (Plus,          lift2   "bvadd")
+                                , (Minus,         lift2   "bvsub")
+                                , (Times,         lift2   "bvmul")
+                                , (UNeg,          lift1B  "not"    "bvneg")
+                                , (Abs,           liftAbs)
+                                , (Quot,          lift2S  "bvudiv" "bvsdiv")
+                                , (Rem,           lift2S  "bvurem" "bvsrem")
+                                , (Equal True,    eqBV)
+                                , (Equal False,   eqBV)
+                                , (NotEqual,      neqBV)
+                                , (LessThan,      lift2S  "bvult" "bvslt")
+                                , (GreaterThan,   lift2S  "bvugt" "bvsgt")
+                                , (LessEq,        lift2S  "bvule" "bvsle")
+                                , (GreaterEq,     lift2S  "bvuge" "bvsge")
+                                ]
+
+                -- Boolean comparisons.. SMTLib's bool type doesn't do comparisons, but Haskell does.. Sigh
+                boolComps      = [ (LessThan,      blt)
+                                 , (GreaterThan,   blt . swp)
+                                 , (LessEq,        blq)
+                                 , (GreaterEq,     blq . swp)
+                                 ]
+                               where blt [x, y] = "(and (not " <> x <> ") " <> y <> ")"
+                                     blt xs     = error $ "SBV.SMT.SMTLib2.boolComps.blt: Impossible happened, incorrect arity (expected 2): " ++ show xs
+                                     blq [x, y] = "(or (not " <> x <> ") " <> y <> ")"
+                                     blq xs     = error $ "SBV.SMT.SMTLib2.boolComps.blq: Impossible happened, incorrect arity (expected 2): " ++ show xs
+                                     swp [x, y] = [y, x]
+                                     swp xs     = error $ "SBV.SMT.SMTLib2.boolComps.swp: Impossible happened, incorrect arity (expected 2): " ++ show xs
+
+                smtOpRealTable =  smtIntRealShared
+                               ++ [ (Quot,        lift2WM "/" "fp.div")
+                                  ]
+
+                smtOpIntTable  = smtIntRealShared
+                               ++ [ (Quot,        lift2   "div")
+                                  , (Rem,         lift2   "mod")
+                                  ]
+
+                smtOpFloatDoubleTable = smtIntRealShared
+                                  ++ [(Quot, lift2WM "/" "fp.div")]
+
+                smtIntRealShared  = [ (Plus,          lift2WM "+" "fp.add")
+                                    , (Minus,         lift2WM "-" "fp.sub")
+                                    , (Times,         lift2WM "*" "fp.mul")
+                                    , (UNeg,          lift1FP "-" "fp.neg")
+                                    , (Abs,           liftAbs)
+                                    , (Equal True,    equal)
+                                    , (Equal False,   equal)
+                                    , (NotEqual,      notEqual)
+                                    , (LessThan,      lift2Cmp  "<"  "fp.lt")
+                                    , (GreaterThan,   lift2Cmp  ">"  "fp.gt")
+                                    , (LessEq,        lift2Cmp  "<=" "fp.leq")
+                                    , (GreaterEq,     lift2Cmp  ">=" "fp.geq")
+                                    ]
+
+                ratOpTable = [ (Equal True,  lift2Rat "sbv.rat.eq")
+                             , (Equal False, lift2Rat "sbv.rat.eq")
+                             , (NotEqual,    lift2Rat "sbv.rat.notEq")
+                             ]
+                        where lift2Rat o [x, y] = "(" <> o <> " " <> x <> " " <> y <> ")"
+                              lift2Rat o sbvs   = error $ "SBV.SMTLib2.sh.lift2Rat: Unexpected arguments: " ++ show (o, sbvs)
+
+                -- equality and comparisons are the only thing that works on uninterpreted sorts and pretty much everything else
+                uninterpretedTable = [ (Equal True,  lift2S "="        "="        True)
+                                     , (Equal False, lift2S "="        "="        True)
+                                     , (NotEqual,    liftNS "distinct" "distinct" True)
+                                     ]
+
+                -- For strings, equality and comparisons are the only operators
+                smtStringTable = [ (Equal True,  lift2S "="        "="        True)
+                                 , (Equal False, lift2S "="        "="        True)
+                                 , (NotEqual,    liftNS "distinct" "distinct" True)
+                                 , (LessThan,    stringCmp False "str.<")
+                                 , (GreaterThan, stringCmp True  "str.<")
+                                 , (LessEq,      stringCmp False "str.<=")
+                                 , (GreaterEq,   stringCmp True  "str.<=")
+                                 ]
+
+                -- For lists, equality is really the only operator. Also, not strong-equality due to lists of floats.
+                -- Likewise here, things might change for comparisons
+                smtListTable = [ (Equal False, lift2S "="        "="        True)
+                               , (NotEqual,    liftNS "distinct" "distinct" True)
+                               , (LessThan,    seqCmp False "seq.<")
+                               , (GreaterThan, seqCmp True  "seq.<")
+                               , (LessEq,      seqCmp False "seq.<=")
+                               , (GreaterEq,   seqCmp True  "seq.<=")
+                               ]
+
+declareFun :: SV -> SBVType -> Maybe Text -> [Text]
+declareFun sv = declareName (showText sv)
+
+-- If we have a char, we have to make sure it's and SMTLib string of length exactly one
+-- If we have a rational, we have to make sure the denominator is > 0
+-- Otherwise, we just declare the name
+declareName :: Text -> SBVType -> Maybe Text -> [Text]
+declareName s t@(SBVType inputKS) mbCmnt = decl : restrict
+  where decl = "(declare-fun " <> s <> " " <> cvtType t <> ")" <> maybe "" (" ; " <>) mbCmnt
+
+        (args, result) = case inputKS of
+                          [] -> error $ "SBV.declareName: Unexpected empty type for: " ++ T.unpack s
+                          _  -> (init inputKS, last inputKS)
+
+        -- Does the kind KChar and KRational *not* occur in the kind anywhere?
+        charRatFree k = all notCharOrRat (expandKinds k)
+           where notCharOrRat KChar     = False
+                 notCharOrRat KRational = False
+                 notCharOrRat _         = True
+
+        noCharOrRat   = charRatFree result
+        needsQuant    = not $ null args
+
+        resultVar | needsQuant = "result"
+                  | True       = s
+
+        argList   = ["a" <> showText i | (i, _) <- zip [1::Int ..] args]
+        argTList  = ["(" <> a <> " " <> smtType k <> ")" | (a, k) <- zip argList args]
+        resultExp = "(" <> s <> " " <> T.unwords argList <> ")"
+
+        restrict | noCharOrRat = []
+                 | needsQuant  =    [               "(assert (forall (" <> T.unwords argTList <> ")"
+                                    ,               "                (let ((" <> resultVar <> " " <> resultExp <> "))"
+                                    ]
+                                 <> (case constraints of
+                                       []     ->  [ "                     true"]
+                                       [x]    ->  [ "                     " <> x]
+                                       (x:xs) ->  ( "                     (and " <> x)
+                                               :  [ "                          " <> c | c <- xs]
+                                               <> [ "                     )"])
+                                 <> [        "                )))"]
+                 | True        = case constraints of
+                                  []     -> []
+                                  [x]    -> ["(assert " <> x <> ")"]
+                                  (x:xs) -> ( "(assert (and " <> x)
+                                         :  [ "             " <> c | c <- xs]
+                                         <> [ "        ))"]
+
+        constraints = walk 0 resultVar cstr result
+          where cstr KChar     nm = ["(= 1 (str.len " <> nm <> "))"]
+                cstr KRational nm = ["(< 0 (sbv.rat.denominator " <> nm <> "))"]
+                cstr _         _  = []
+
+        mkAnd [] _context = []
+        mkAnd [c] context = context c
+        mkAnd cs  context = context $ "(and " <> T.unwords cs <> ")"
+
+        walk :: Int -> Text -> (Kind -> Text -> [Text]) -> Kind -> [Text]
+        walk _d nm f k@KVar      {}         = f k nm
+        walk _d nm f k@KBool     {}         = f k nm
+        walk _d nm f k@KBounded  {}         = f k nm
+        walk _d nm f k@KUnbounded{}         = f k nm
+        walk _d nm f k@KReal     {}         = f k nm
+        walk _d nm f k@KApp      {}         = f k nm
+        walk _d nm f k@KFloat    {}         = f k nm
+        walk _d nm f k@KDouble   {}         = f k nm
+        walk _d nm f k@KRational {}         = f k nm
+        walk _d nm f k@KFP       {}         = f k nm
+        walk _d nm f k@KChar     {}         = f k nm
+        walk _d nm f k@KString   {}         = f k nm
+        walk  d nm f  (KList k)
+          | charRatFree k                 = []
+          | True                          = let fnm   = "seq" <> showText d
+                                                cstrs = walk (d+1) ("(seq.nth " <> nm <> " " <> fnm <> ")") f k
+                                            in mkAnd cstrs $ \hole -> ["(forall ((" <> fnm <> " " <> smtType KUnbounded <> ")) (=> (and (>= " <> fnm <> " 0) (< " <> fnm <> " (seq.len " <> nm <> "))) " <> hole <> "))"]
+        walk  d  nm f (KSet k)
+          | charRatFree k                 = []
+          | True                          = let fnm    = "set" <> showText d
+                                                cstrs  = walk (d+1) nm (\sk snm -> ["(=> (select " <> snm <> " " <> fnm <> ") " <> c <> ")" | c <- f sk fnm]) k
+                                            in mkAnd cstrs $ \hole -> ["(forall ((" <> fnm <> " " <> smtType k <> ")) " <> hole <> ")"]
+        walk  d  nm  f (KTuple ks)        = let tt        = "SBVTuple" <> showText (length ks)
+                                                project i = "(proj_" <> showText i <> "_" <> tt <> " " <> nm <> ")"
+                                                nmks      = [(project i, k) | (i, k) <- zip [1::Int ..] ks]
+                                            in concatMap (\(n, k) -> walk (d+1) n f k) nmks
+        walk d  nm f  (KArray k1 k2)
+          | all charRatFree [k1, k2]      = []
+          | True                          = let fnm   = "array" <> showText d
+                                                cstrs = walk (d+1) ("(select " <> nm <> " " <> fnm <> ")") f k2
+                                            in mkAnd cstrs $ \hole -> ["(forall ((" <> fnm <> " " <> smtType k1 <> ")) " <> hole <> ")"]
+        walk d nm f (KADT ty dict pureFS) = let fs = [(c, map (substituteADTVars ty dict) ks) | (c, ks) <- pureFS]
+                                                nmks  = [("(get" <> T.pack c <> "_" <> showText i <> " " <> nm <> ")", k) | (c, ks) <- fs, (i, k) <- zip [(1::Int)..] ks]
+                                            in concatMap (\(n, k) -> walk (d+1) n f k) nmks
+
+-----------------------------------------------------------------------------------------------
+-- Casts supported by SMTLib. (From: <https://smt-lib.org/theories-FloatingPoint.shtml>)
+--   ; from another floating point sort
+--   ((_ to_fp eb sb) RoundingMode (_ FloatingPoint mb nb) (_ FloatingPoint eb sb))
+--
+--   ; from real
+--   ((_ to_fp eb sb) RoundingMode Real (_ FloatingPoint eb sb))
+--
+--   ; from signed machine integer, represented as a 2's complement bit vector
+--   ((_ to_fp eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb))
+--
+--   ; from unsigned machine integer, represented as bit vector
+--   ((_ to_fp_unsigned eb sb) RoundingMode (_ BitVec m) (_ FloatingPoint eb sb))
+--
+--   ; to unsigned machine integer, represented as a bit vector
+--   ((_ fp.to_ubv m) RoundingMode (_ FloatingPoint eb sb) (_ BitVec m))
+--
+--   ; to signed machine integer, represented as a 2's complement bit vector
+--   ((_ fp.to_sbv m) RoundingMode (_ FloatingPoint eb sb) (_ BitVec m))
+--
+--   ; to real
+--   (fp.to_real (_ FloatingPoint eb sb) Real)
+-----------------------------------------------------------------------------------------------
+
+handleFPCast :: Kind -> Kind -> Text -> Text -> Text
+handleFPCast kFromIn kToIn rm input
+  | kFrom == kTo
+  = input
+  | True
+  = "(" <> cast kFrom kTo input <> ")"
+  where addRM a s = s <> " " <> rm <> " " <> a
+
+        kFrom = simplify kFromIn
+        kTo   = simplify kToIn
+
+        simplify KFloat  = KFP   8 24
+        simplify KDouble = KFP  11 53
+        simplify k       = k
+
+        size (eb, sb) = showText eb <> " " <> showText sb
+
+        -- To go and back from Ints, we detour through reals
+        cast KUnbounded (KFP eb sb) a = "(_ to_fp " <> size (eb, sb) <> ") "  <> rm <> " (to_real " <> a <> ")"
+        cast KFP{}      KUnbounded  a = "to_int (fp.to_real (fp.roundToIntegral " <> rm <> " " <> a <> "))"
+
+        -- To floats
+        cast (KBounded False _) (KFP eb sb) a = addRM a $ "(_ to_fp_unsigned " <> size (eb, sb) <> ")"
+        cast (KBounded True  _) (KFP eb sb) a = addRM a $ "(_ to_fp "          <> size (eb, sb) <> ")"
+        cast KReal              (KFP eb sb) a = addRM a $ "(_ to_fp "          <> size (eb, sb) <> ")"
+        cast KFP{}              (KFP eb sb) a = addRM a $ "(_ to_fp "          <> size (eb, sb) <> ")"
+
+        -- From float/double
+        cast KFP{} (KBounded False m) a = addRM a $ "(_ fp.to_ubv " <> showText m <> ")"
+        cast KFP{} (KBounded True  m) a = addRM a $ "(_ fp.to_sbv " <> showText m <> ")"
+
+        -- To real
+        cast KFP{} KReal a = "fp.to_real" <> " " <> a
+
+        -- Nothing else should come up:
+        cast f  d  _ = error $ "SBV.SMTLib2: Unexpected FPCast from: " ++ show f ++ " to " ++ show d
+
+rot :: Text -> Int -> SV -> Text
+rot o c x = "((_ " <> o <> " " <> showText c <> ") " <> cvtSV x <> ")"
+
+shft :: Text -> Text -> SV -> SV -> Text
+shft oW oS x c = "(" <> o <> " " <> cvtSV x <> " " <> cvtSV c <> ")"
+   where o = if hasSign x then oS else oW
+
+-- ADT operations
+handleADT :: SolverCapabilities -> ADTOp -> [SV] -> Text
+handleADT caps op args = case args of
+                          [] -> f
+                          _  -> "(" <> f <> " " <> T.unwords (map cvtSV args) <> ")"
+  where f = case op of
+              ADTConstructor nm k -> ascribe nm k
+              ADTTester      nm k -> if supportsDirectTesters caps
+                                     then nm
+                                     else ascribe nm k
+              ADTAccessor    nm _ -> nm
+
+        ascribe nm k = "(as " <> nm <> " " <> smtType k <> ")"
+
+-- Various casts
+handleKindCast :: Kind -> Kind -> Text -> Text
+handleKindCast kFrom kTo a
+  | kFrom == kTo
+  = a
+  | True
+  = case kFrom of
+      KBounded s m -> case kTo of
+                        KBounded _ n -> fromBV (if s then signExtend else zeroExtend) m n
+                        KUnbounded   -> if s then "(sbv_to_int " <> a <> ")"
+                                             else "(ubv_to_int " <> a <> ")"
+                        _            -> tryFPCast
+
+      KUnbounded   -> case kTo of
+                        KReal        -> "(to_real " <> a <> ")"
+                        KBounded _ n -> "((_ int_to_bv " <> showText n <> ") " <> a <> ")"
+                        _            -> tryFPCast
+
+      KReal        -> case kTo of
+                        KUnbounded   -> "(to_int " <> a <> ")"
+                        _            -> tryFPCast
+
+      _            -> tryFPCast
+
+  where -- See if we can push this down to a float-cast, using sRNE. This happens if one of the kinds is a float/double.
+        -- Otherwise complain
+        tryFPCast
+          | any (\k -> isFloat k || isDouble k) [kFrom, kTo]
+          = handleFPCast kFrom kTo (smtRoundingMode RoundNearestTiesToEven) a
+          | True
+          = error $ "SBV.SMTLib2: Unexpected cast from: " ++ show kFrom ++ " to " ++ show kTo
+
+        fromBV upConv m n
+         | n > m  = upConv  (n - m)
+         | m == n = a
+         | True   = extract (n - 1)
+
+        signExtend i = "((_ sign_extend " <> showText i <> ") "   <> a <> ")"
+        zeroExtend i = "((_ zero_extend " <> showText i <> ") "   <> a <> ")"
+        extract    i = "((_ extract "     <> showText i <> " 0) " <> a <> ")"
+
+-- Translation of pseudo-booleans, in case the solver supports them
+handlePB :: PBOp -> [Text] -> Text
+handlePB (PB_AtMost  k) args = "((_ at-most "  <> showText k                                               <> ") " <> T.unwords args <> ")"
+handlePB (PB_AtLeast k) args = "((_ at-least " <> showText k                                               <> ") " <> T.unwords args <> ")"
+handlePB (PB_Exactly k) args = "((_ pbeq "     <> T.unwords (map showText (k : replicate (length args) 1)) <> ") " <> T.unwords args <> ")"
+handlePB (PB_Eq cs   k) args = "((_ pbeq "     <> T.unwords (map showText (k : cs))                        <> ") " <> T.unwords args <> ")"
+handlePB (PB_Le cs   k) args = "((_ pble "     <> T.unwords (map showText (k : cs))                        <> ") " <> T.unwords args <> ")"
+handlePB (PB_Ge cs   k) args = "((_ pbge "     <> T.unwords (map showText (k : cs))                        <> ") " <> T.unwords args <> ")"
+
+-- Translation of pseudo-booleans, in case the solver does *not* support them
+reducePB :: PBOp -> [Text] -> Text
+reducePB op args = case op of
+                     PB_AtMost  k -> "(<= " <> addIf (repeat 1) <> " " <> showText k <> ")"
+                     PB_AtLeast k -> "(>= " <> addIf (repeat 1) <> " " <> showText k <> ")"
+                     PB_Exactly k -> "(=  " <> addIf (repeat 1) <> " " <> showText k <> ")"
+                     PB_Le cs   k -> "(<= " <> addIf cs         <> " " <> showText k <> ")"
+                     PB_Ge cs   k -> "(>= " <> addIf cs         <> " " <> showText k <> ")"
+                     PB_Eq cs   k -> "(=  " <> addIf cs         <> " " <> showText k <> ")"
+
+  where addIf :: [Int] -> Text
+        addIf cs = "(+ " <> T.unwords ["(ite " <> a <> " " <> showText c <> " 0)" | (a, c) <- zip args cs] <> ")"
+
+-- | Translate an option setting to SMTLib. Note the SetLogic/SetInfo discrepancy.
+setSMTOption :: SMTConfig -> SMTOption -> Text
+setSMTOption cfg = set
+  where set (DiagnosticOutputChannel   f) = opt   [":diagnostic-output-channel",   showText f]
+        set (ProduceAssertions         b) = opt   [":produce-assertions",          smtBool b]
+        set (ProduceAssignments        b) = opt   [":produce-assignments",         smtBool b]
+        set (ProduceProofs             b) = opt   [":produce-proofs",              smtBool b]
+        set (ProduceInterpolants       b) = opt   [":produce-interpolants",        smtBool b]
+        set (ProduceUnsatAssumptions   b) = opt   [":produce-unsat-assumptions",   smtBool b]
+        set (ProduceUnsatCores         b) = opt   [":produce-unsat-cores",         smtBool b]
+        set (ProduceAbducts            b) = opt   [":produce-abducts",             smtBool b]
+        set (RandomSeed                i) = opt   [":random-seed",                 showText i]
+        set (ReproducibleResourceLimit i) = opt   [":reproducible-resource-limit", showText i]
+        set (SMTVerbosity              i) = opt   [":verbosity",                   showText i]
+        set (OptionKeyword          k as) = opt   (T.pack k : map T.pack as)
+        set (SetLogic                  l) = logicString cfg l
+        set (SetInfo                k as) = info  (T.pack k : map T.pack as)
+        set (SetTimeOut                i) = opt   $ timeOut i
+
+        opt   xs = "(set-option " <> T.unwords xs <> ")"
+        info  xs = "(set-info "   <> T.unwords xs <> ")"
+
+        -- timeout is not standard. We distinguish between CVC/Z3. All else follows z3
+        -- The value is in milliseconds, which is how z3/CVC interpret it
+        timeOut i = case name (solver cfg) of
+                     CVC4 -> [":tlimit-per", showText i]
+                     CVC5 -> [":tlimit-per", showText i]
+                     _    -> [":timeout",    showText i]
+
+        -- SMTLib's True/False is spelled differently than Haskell's.
+        smtBool :: Bool -> Text
+        smtBool True  = "true"
+        smtBool False = "false"
+
+-- | Set the logic, accounting for solver inconsistencies.
+logicString :: SMTConfig -> Logic -> Text
+logicString cfg = pick
+  where
+    slvr = name (solver cfg)
+
+    -- This is more or less showText, but with exceptions:
+    --
+    --    Logic_ALL : HO_ALL for CVC5 to get support for higher-order features.
+    --    QF_FPBV   : Bitwuzla calls it QF_BVFP. See: https://github.com/LeventErkok/sbv/issues/774
+    --    Logic_NONE: Sets nothing, just sets a comment
+    pick Logic_ALL | CVC5     <- slvr = wrap "HO_ALL"
+    pick QF_FPBV   | Bitwuzla <- slvr = wrap "QF_BVFP"
+    pick Logic_NONE                   = "; NB. not setting the logic per user request of Logic_NONE"
+
+    -- Fall thru
+    pick l = wrap (showText l)
+
+    wrap l = "(set-logic " <> l <> ")"
+
+{- HLint ignore module "Use record patterns" -}
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,19 +1,21 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.SMT.SMTLibNames
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.SMT.SMTLibNames
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- SMTLib Reserved names
 -----------------------------------------------------------------------------
 
-module Data.SBV.SMT.SMTLibNames where
+{-# OPTIONS_GHC -Wall -Werror #-}
 
+module Data.SBV.SMT.SMTLibNames (isReserved) where
+
 import Data.Char (toLower)
 
--- | Names reserved by SMTLib. This list is current as of Dec 6 2015; but of course
+-- | Names reserved by SMTLib, all lower-case. This list is current as of Dec 6 2015; but of course
 -- there's no guarantee it'll stay that way.
 smtLibReservedNames :: [String]
 smtLibReservedNames = map (map toLower)
@@ -21,5 +23,12 @@
                         , "!", "_", "as", "BINARY", "DECIMAL", "exists", "HEXADECIMAL", "forall", "let", "NUMERAL", "par", "STRING", "CHAR"
                         , "assert", "check-sat", "check-sat-assuming", "declare-const", "declare-fun", "declare-sort", "define-fun", "define-fun-rec"
                         , "define-sort", "echo", "exit", "get-assertions", "get-assignment", "get-info", "get-model", "get-option", "get-proof", "get-unsat-assumptions"
-                        , "get-unsat-core", "get-value", "pop", "push", "reset", "reset-assertions", "set-info", "set-logic", "set-option"
+                        , "get-unsat-core", "get-value", "pop", "push", "reset", "reset-assertions", "set-info", "set-logic", "set-option", "match"
+                        --
+                        -- The following are most likely Z3 specific
+                        , "interval", "assert-soft"
                         ]
+
+-- | Is this name reserved? Note that we'll ignore case in checking here. This is probably over-cautious.
+isReserved :: String -> Bool
+isReserved = (`elem` smtLibReservedNames)
diff --git a/Data/SBV/SMT/Utils.hs b/Data/SBV/SMT/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/SMT/Utils.hs
@@ -0,0 +1,302 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.SMT.Utils
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A few internally used types/routines
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE OverloadedStrings   #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.SMT.Utils (
+          SMTLibConverter
+        , SMTLibIncConverter
+        , addAnnotations
+        , showTimeoutValue
+        , alignPlain
+        , debug
+        , mergeSExpr
+        , SBVException(..)
+        , startTranscript
+        , finalizeTranscript
+        , recordTranscript
+        , recordException
+        , recordEndTime
+        , TranscriptMsg(..)
+       )
+       where
+
+import qualified Control.Exception as C
+
+import Control.Monad.Trans (MonadIO, liftIO)
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Symbolic (QueryContext, CnstMap, SMTDef, ResultInp(..), ProgInfo(..), startTime)
+
+import Data.SBV.Utils.Lib   (joinArgs, showText)
+import Data.SBV.Utils.TDiff (Timing(..), showTDiff)
+
+import Data.IORef (writeIORef)
+import Data.Time  (getZonedTime, defaultTimeLocale, formatTime, diffUTCTime, getCurrentTime)
+
+import Data.Char  (isSpace)
+import Data.Maybe (fromMaybe)
+
+import qualified Data.Set      as Set (Set)
+import qualified Data.Sequence as S   (Seq)
+
+import qualified Data.Text    as T
+import qualified Data.Text.IO as TIO
+import           Data.Text (Text)
+
+import System.Directory (findExecutable)
+import System.Exit      (ExitCode(..))
+
+-- | An instance of SMT-Lib converter; instantiated for SMT-Lib v1 and v2. (And potentially for newer versions in the future.)
+type SMTLibConverter a =  QueryContext                                   -- ^ Internal or external query?
+                       -> ProgInfo                                       -- ^ Various program info
+                       -> Set.Set Kind                                   -- ^ Kinds used in the problem
+                       -> Bool                                           -- ^ is this a sat problem?
+                       -> [String]                                       -- ^ extra comments to place on top
+                       -> ResultInp                                      -- ^ inputs or params
+                       -> (CnstMap, [(SV, CV)])                          -- ^ constants. The map, and as rendered in order
+                       -> [((Int, Kind, Kind), [SV])]                    -- ^ auto-generated tables
+                       -> [(String, (Bool, Maybe [String], SBVType))]    -- ^ uninterpreted functions/constants
+                       -> [(String, (SMTDef, SBVType))]                  -- ^ user given axioms/definitions
+                       -> SBVPgm                                         -- ^ assignments
+                       -> 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 =  ProgInfo                                    -- ^ Various prog info
+                          -> [NamedSymVar]                               -- ^ inputs
+                          -> Set.Set Kind                                -- ^ new kinds
+                          -> (CnstMap, [(SV, CV)])                       -- ^ all constants sofar, and new constants
+                          -> [((Int, Kind, Kind), [SV])]                 -- ^ newly created tables
+                          -> [(String, (Bool, Maybe [String], SBVType))] -- ^ newly created uninterpreted functions/constants
+                          -> SBVPgm                                      -- ^ assignments
+                          -> S.Seq (Bool, [(String, String)], SV)        -- ^ extra constraints
+                          -> SMTConfig                                   -- ^ configuration
+                          -> a
+
+-- | Create an annotated term
+addAnnotations :: [(String, String)] -> Text -> Text
+addAnnotations []   x = x
+addAnnotations atts x = "(! " <> x <> " " <> T.unwords (map (T.pack . mkAttr) atts) <> ")"
+  where mkAttr (a, v) = a ++ " |" ++ concatMap sanitize v ++ "|"
+        sanitize '|'  = "_bar_"
+        sanitize '\\' = "_backslash_"
+        sanitize c    = [c]
+
+-- | Show a millisecond time-out value somewhat nicely
+showTimeoutValue :: Int -> Text
+showTimeoutValue i = case (i `quotRem` 1000000, i `quotRem` 500000) of
+                       ((s, 0), _)  -> showText s                              <> "s"
+                       (_, (hs, 0)) -> showText (fromIntegral hs / (2::Float)) <> "s"
+                       _            -> showText i <> "ms"
+
+-- | Nicely align a potentially multi-line message with some tag, but prefix with three stars
+alignDiagnostic :: Text -> Text -> Text
+alignDiagnostic = alignWithPrefix "*** "
+
+-- | Nicely align a potentially multi-line message with some tag, no prefix.
+alignPlain :: Text -> Text -> Text
+alignPlain = alignWithPrefix ""
+
+-- | Align with some given prefix
+alignWithPrefix :: Text -> Text -> Text -> Text
+alignWithPrefix pre tag multi = T.intercalate "\n" $ zipWith (<>) (tag : repeat (pre <> T.replicate (T.length tag - T.length pre) " ")) (filter (not . T.null) (T.lines multi))
+
+-- | Diagnostic message when verbose
+debug :: MonadIO m => SMTConfig -> [Text] -> m ()
+debug cfg
+  | not (verbose cfg)             = const (pure ())
+  | Just f <- redirectVerbose cfg = liftIO . mapM_ (\t -> TIO.appendFile f (t <> "\n"))
+  | True                          = liftIO . mapM_ TIO.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.
+mergeSExpr :: [Text] -> [Text]
+mergeSExpr []       = []
+mergeSExpr (x:xs)
+ | d == 0 = x : mergeSExpr xs
+ | True   = let (f, r) = grab d xs in T.unlines (x:f) : mergeSExpr r
+ where d = parenDiff x
+
+       parenDiff :: Text -> Int
+       parenDiff = go 0
+         where go i t = case T.uncons t of
+                 Nothing       -> i
+                 Just ('(', r) -> let i' = i+1 in i' `seq` go i' r
+                 Just (')', r) -> let i' = i-1 in i' `seq` go i' r
+                 Just ('"', r) -> go i (skipString r)
+                 Just ('|', r) -> go i (skipBar r)
+                 Just (';', r) -> go i (T.drop 1 (T.dropWhile (/= '\n') r))
+                 Just (_,   r) -> go i r
+
+       grab i ls
+         | i <= 0    = ([], ls)
+       grab _ []     = ([], [])
+       grab i (l:ls) = let (a, b) = grab (i+parenDiff l) ls in (l:a, b)
+
+       skipString t = case T.uncons t of
+         Nothing       -> T.empty             -- Oh dear, line finished, but the string didn't. We're in trouble. Ignore!
+         Just ('"', r) -> case T.uncons r of
+           Just ('"', r') -> skipString r'    -- escaped quote
+           _              -> r                -- end of string
+         Just (_,   r) -> skipString r
+
+       skipBar t = case T.uncons t of
+         Nothing       -> T.empty             -- Oh dear, line finished, but the bar didn't. We're in trouble. Ignore!
+         Just ('|', r) -> r
+         Just (_,   r) -> skipBar r
+
+-- | An exception thrown from SBV. If the solver ever responds with a non-success value for a command,
+-- SBV will throw an t'SBVException', it so the user can process it as required. The provided 'Show' instance
+-- will render the failure nicely. Note that if you ever catch this exception, the solver is no longer alive:
+-- You should either -- throw the exception up, or do other proper clean-up before continuing.
+data SBVException = SBVException {
+                          sbvExceptionDescription :: String
+                        , sbvExceptionSent        :: Maybe String
+                        , sbvExceptionExpected    :: Maybe String
+                        , sbvExceptionReceived    :: Maybe String
+                        , sbvExceptionStdOut      :: Maybe String
+                        , sbvExceptionStdErr      :: Maybe String
+                        , sbvExceptionExitCode    :: Maybe ExitCode
+                        , sbvExceptionConfig      :: SMTConfig
+                        , sbvExceptionReason      :: Maybe [String]
+                        , sbvExceptionHint        :: Maybe [String]
+                        }
+
+-- | SBVExceptions are throwable. A simple "show" will render this exception nicely
+-- though of course you can inspect the individual fields as necessary.
+instance C.Exception SBVException
+
+-- | A fairly nice rendering of the exception, for display purposes.
+instance Show SBVException where
+ show SBVException { sbvExceptionDescription
+                   , sbvExceptionSent
+                   , sbvExceptionExpected
+                   , sbvExceptionReceived
+                   , sbvExceptionStdOut
+                   , sbvExceptionStdErr
+                   , sbvExceptionExitCode
+                   , sbvExceptionConfig
+                   , sbvExceptionReason
+                   , sbvExceptionHint
+                   }
+
+         = let grp1 = [ ""
+                      , "*** Data.SBV: " <> T.pack sbvExceptionDescription <> ":"
+                      ]
+
+               grp2 =  ["***    Sent      : " `alignDiagnostic` T.pack snt  | Just snt  <- [sbvExceptionSent],     not $ null snt ]
+                    <> ["***    Expected  : " `alignDiagnostic` T.pack excp | Just excp <- [sbvExceptionExpected], not $ null excp]
+                    <> ["***    Received  : " `alignDiagnostic` T.pack rcvd | Just rcvd <- [sbvExceptionReceived], not $ null rcvd]
+
+               grp3 =  ["***    Stdout    : " `alignDiagnostic` T.pack out  | Just out  <- [sbvExceptionStdOut],   not $ null out ]
+                    <> ["***    Stderr    : " `alignDiagnostic` T.pack err  | Just err  <- [sbvExceptionStdErr],   not $ null err ]
+                    <> ["***    Exit code : " `alignDiagnostic` showText ec | Just ec   <- [sbvExceptionExitCode]                 ]
+                    <> ["***    Executable: " `alignDiagnostic` T.pack (executable (solver sbvExceptionConfig))                           ]
+                    <> ["***    Options   : " `alignDiagnostic` T.pack (joinArgs (options (solver sbvExceptionConfig) sbvExceptionConfig))]
+
+               grp4 =  ["***    Reason    : " `alignDiagnostic` T.pack (unlines rsn) | Just rsn <- [sbvExceptionReason]]
+                    <> ["***    Hint      : " `alignDiagnostic` T.pack (unlines hnt) | Just hnt <- [sbvExceptionHint  ]]
+
+               join []     = []
+               join [x]    = x
+               join (g:gs) = case join gs of
+                               []    -> g
+                               rest  -> g <> ["***"] <> rest
+
+          in T.unpack $ T.unlines $ join [grp1, grp2, grp3, grp4]
+
+-- | Compute and report the end time
+recordEndTime :: SMTConfig -> State -> IO ()
+recordEndTime SMTConfig{timing} state = case timing of
+                                           NoTiming        -> pure ()
+                                           PrintTiming     -> do e <- elapsed
+                                                                 putStrLn $ "*** SBV: Elapsed time: " ++ showTDiff e
+                                           SaveTiming here -> writeIORef here =<< elapsed
+  where elapsed = getCurrentTime >>= \end -> pure $ diffUTCTime end (startTime state)
+
+-- | Start a transcript file, if requested.
+startTranscript :: Maybe FilePath -> SMTConfig -> IO ()
+startTranscript Nothing  _   = pure ()
+startTranscript (Just f) cfg = do ts <- show <$> getZonedTime
+                                  mbExecPath <- findExecutable (executable (solver cfg))
+                                  writeFile f $ start ts mbExecPath
+  where SMTSolver{name, options} = solver cfg
+        start ts mbPath = unlines [ ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                                  , ";;; SBV: Starting at " ++ ts
+                                  , ";;;"
+                                  , ";;;           Solver    : " ++ show name
+                                  , ";;;           Executable: " ++ fromMaybe "Unable to locate the executable" mbPath
+                                  , ";;;           Options   : " ++ unwords (options cfg ++ extraArgs cfg)
+                                  , ";;;"
+                                  , ";;; This file is an auto-generated loadable SMT-Lib file."
+                                  , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                                  , ""
+                                  ]
+
+-- | Finish up the transcript file.
+finalizeTranscript :: Maybe FilePath -> ExitCode -> IO ()
+finalizeTranscript Nothing  _  = pure ()
+finalizeTranscript (Just f) ec = do ts <- show <$> getZonedTime
+                                    appendFile f $ end ts
+  where end ts = unlines [ ""
+                         , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                         , ";;;"
+                         , ";;; SBV: Finished at " ++ ts
+                         , ";;;"
+                         , ";;; Exit code: " ++ show ec
+                         , ";;;"
+                         , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                         ]
+
+-- Kind of things we can record
+data TranscriptMsg = SentMsg  Text   (Maybe Int) -- ^ Message sent, and time-out if any
+                   | RecvMsg  String             -- ^ Message received
+                   | DebugMsg Text               -- ^ A debug message; neither sent nor received
+
+-- If requested, record in the transcript file
+recordTranscript :: Maybe FilePath -> TranscriptMsg -> IO ()
+recordTranscript Nothing  _ = pure ()
+recordTranscript (Just f) m = do tsPre <- formatTime defaultTimeLocale "; [%T%Q" <$> getZonedTime
+                                 let ts = take 15 $ tsPre ++ repeat '0'
+                                 case m of
+                                   SentMsg sent mbTimeOut  -> TIO.appendFile f $ T.unlines $ (T.pack ts <> "] " <> to mbTimeOut <> "Sending:") : T.lines sent
+                                   RecvMsg recv            -> appendFile f $ unlines $ case lines (dropWhile isSpace recv) of
+                                                                                        []  -> [ts ++ "] Received: <NO RESPONSE>"]  -- can't really happen.
+                                                                                        [x] -> [ts ++ "] Received: " ++ x]
+                                                                                        xs  -> (ts ++ "] Received: ") : map (";   " ++) xs
+                                   DebugMsg msg            -> let tag = T.pack ts <> "] "
+                                                                  emp = T.cons ';' (T.replicate (T.length tag - 1) " ")
+                                                              in TIO.appendFile f $ T.unlines $ zipWith (<>) (tag : repeat emp) (T.lines msg)
+        where to Nothing  = ""
+              to (Just i) = "[Timeout: " <> showTimeoutValue i <> "] "
+{-# INLINE recordTranscript #-}
+
+-- Record the exception
+recordException :: Maybe FilePath -> String -> IO ()
+recordException Nothing  _ = pure ()
+recordException (Just f) m = do ts <- show <$> getZonedTime
+                                appendFile f $ exc ts
+  where exc ts = unlines $ [ ""
+                           , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                           , ";;;"
+                           , ";;; SBV: Caught an exception at " ++ ts
+                           , ";;;"
+                           ]
+                        ++ [ ";;;   " ++ l | l <- dropWhile null (lines m) ]
+                        ++ [ ";;;"
+                           , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                           ]
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,538 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                 #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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 () -- instances only
+import Data.SBV.Core.Symbolic (SetOp(..))
+
+import Data.SBV.Core.Kind
+
+#ifdef DOCTEST
+-- $setup
+-- >>> -- For doctest purposes only:
+-- >>> import Prelude hiding(null)
+-- >>> import Data.SBV hiding(complement)
+-- >>> import Data.SBV.Maybe
+-- >>> :set -XScopedTypeVariables
+#endif
+
+-- | 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
+  | KChar `elem` expandKinds k
+  = error $ unlines [ "*** Data.SBV: Set.complement is not available for the type " ++ show k
+                    , "***"
+                    , "*** See: https://github.com/LeventErkok/sbv/issues/601 for a discussion"
+                    , "*** on why SBV does not support this operation at this type."
+                    , "***"
+                    , "*** Alternative: Use sets of strings instead, though the match isn't perfect."
+                    , "*** If you run into this issue, please comment on the above ticket for"
+                    , "*** possible improvements."
+                    ]
+  | eqCheckIsObjectEq ek, Just (RegularSet rs)    <- unliteral ss = literal $ ComplementSet rs
+  | eqCheckIsObjectEq ek, Just (ComplementSet cs) <- unliteral ss = literal $ RegularSet cs
+  | True                                                          = SBV $ SVal k $ Right $ cache r
+  where ek = kindOf (Proxy @a)
+        k  = KSet ek
+
+        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 = 2 :: Integer
+--   s1 = U :: {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:
+  | eqCheckIsObjectEq ka, 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:
+  | eqCheckIsObjectEq ka, 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 =       2 :: Integer
+--   s1 = U - {2} :: {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:
+  | eqCheckIsObjectEq ka, 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:
+  | eqCheckIsObjectEq ka, 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 :: forall a. (Ord a, SymVal a) => SBV a -> SSet a -> SBool
+member se ss
+  -- Case 1: Constant regular set, just check:
+  | eqCheckIsObjectEq ka, Just e <- unliteral se, Just (RegularSet rs) <- unliteral ss
+  = literal $ e `Set.member` rs
+
+  -- Case 2: Constant complement set, check for non-member
+  | eqCheckIsObjectEq ka, 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]
+
+        ka = kindOf (Proxy @a)
+
+-- | Test for non-membership.
+--
+-- >>> prove $ \x -> x `notMember` observe "set" (singleton (x :: SInteger))
+-- Falsifiable. Counter-example:
+--   s0  =   0 :: Integer
+--   set = {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 :: (Ord a, SymVal a, HasKind a) => SSet a -> SBool
+null = (.== empty)
+
+-- | Synonym for 'Data.SBV.Set.null'.
+isEmpty :: (Ord a, SymVal a, 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:
+--   s0  =       0 :: Integer
+--   set = U - {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 :: (Ord a, SymVal a, HasKind a) => SSet a -> SBool
+isFull = (.== full)
+
+-- | Synonym for 'Data.SBV.Set.isFull'.
+isUniversal :: (Ord a, SymVal a, 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 :: forall a. (Ord a, SymVal a) => SSet a -> SSet a -> SBool
+isSubsetOf sa sb
+  -- Case 1: Constant regular sets, just check:
+  | eqCheckIsObjectEq ka, 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:
+  | eqCheckIsObjectEq ka, 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]
+
+        ka = kindOf (Proxy @a)
+
+-- | 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 = 2 :: Integer
+--   s1 = U :: {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 =         2 :: Integer
+--   s1 = U - {2,3} :: {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 :: forall a. (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+union sa sb
+  -- Case 1: Constant regular sets, just compute
+  | eqCheckIsObjectEq ka, Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ RegularSet $ a `Set.union` b
+
+  -- Case 2: Constant complement sets, complement the intersection:
+  | eqCheckIsObjectEq ka, 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]
+
+        ka = kindOf (Proxy @a)
+
+-- | 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 :: forall a. (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+intersection sa sb
+  -- Case 1: Constant regular sets, just compute
+  | eqCheckIsObjectEq ka, Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ RegularSet $ a `Set.intersection` b
+
+  -- Case 2: Constant complement sets, complement the union:
+  | eqCheckIsObjectEq ka, 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]
+
+        ka = kindOf (Proxy @a)
+
+-- | 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 :: forall a. (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+difference sa sb
+  -- Only constant fold the regular case, others are left symbolic
+  | eqCheckIsObjectEq ka, 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]
+
+        ka = kindOf (Proxy @a)
+
+-- | Synonym for 'Data.SBV.Set.difference'.
+infix 5 \\  -- This comment avoids CPP to eat up the trailing backspace in this line  Do not remove!
+(\\) :: (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 = {Just 2} :: {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/TP.hs b/Data/SBV/TP.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/TP.hs
@@ -0,0 +1,84 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.TP
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A lightweight theorem proving like interface, built on top of SBV.
+-- Originally inspired by Philip Zucker's tool KnuckleDragger
+-- see <http://github.com/philzook58/knuckledragger>, though SBV's
+-- version is different in its scope and design significantly.
+--
+-- See the directory Documentation.SBV.Examples.TP for various examples.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.TP (
+       -- * Propositions and their proofs
+         Proposition, Proof, proofOf, assumptionFromProof
+
+       -- * Getting the proof tree
+       , rootOfTrust, RootOfTrust(..), ProofTree(..), showProofTree, showProofTreeHTML
+
+       -- * Adding axioms/definitions
+       , axiom
+
+       -- * Basic proofs
+       , lemma, lemmaWith
+
+       -- * Basic proofs, with induction schema
+       , inductiveLemma, inductiveLemmaWith
+
+       -- * Reasoning via calculation
+       , calc, calcWith
+
+       -- * Reasoning via explicit regular induction
+       , induct, inductWith
+
+       -- * Reasoning via explicit measure-based strong induction
+       , sInduct, sInductWith
+
+       -- * Creating instances of proofs
+       , at, Inst(..)
+
+       -- * Faking proofs
+       , sorry
+
+       -- * Running TP proofs
+       , TP, runTP, runTPWith, tpQuiet, tpStats, tpAsms
+
+       -- * Dry run guards
+       , whenDryRun, unlessDryRun
+
+       -- * Measure helpers for smtFunctionWithMeasure
+       , measureLemma, measureLemmaWith
+
+       -- * Starting a calculation proof
+       , (|-), (⊢), (|->)
+
+       -- * Sequence of calculation steps
+       , (=:), (≡)
+
+       -- * Supplying hints for a calculation step
+       , (??), (∵)
+
+       -- * Using quickcheck
+       , qc, qcWith
+
+       -- * Case splits
+       , split, split2, cases, (⟹), (==>)
+
+       -- * Finishing up a calculational proof
+       , qed, trivial, contradiction
+
+       -- * Displaying intermediate values of expressions
+       , disp
+
+       -- * Recall an old proof, using the cache
+       , recall, recallWith
+       ) where
+
+import Data.SBV.TP.TP
diff --git a/Data/SBV/TP/Kernel.hs b/Data/SBV/TP/Kernel.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/TP/Kernel.hs
@@ -0,0 +1,379 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.TP.Kernel
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Kernel of the TP prover API.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ConstraintKinds     #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.TP.Kernel (
+         Proposition,  Proof(..)
+       , axiom
+       , lemma,          lemmaWith
+       , inductiveLemma, inductiveLemmaWith
+       , internalAxiom
+       , TPProofContext (..), smtProofStep, HasInductionSchema(..)
+       , tpMergeCfg, checkNewMeasures
+       ) where
+
+import Control.Monad        (unless)
+import Control.Monad.Trans  (liftIO, MonadIO)
+
+import Data.List  (intercalate)
+import Data.Maybe (catMaybes)
+
+import Data.SBV.Core.Data     hiding (None)
+import Data.SBV.Trans.Control hiding (getProof)
+import Data.SBV.Core.Symbolic (MonadSymbolic(..), rSkipMeasureChecks, rMeasureChecks, rNoTermCheckFunctions)
+
+import Data.SBV.SMT.SMT
+import Data.SBV.Core.Model
+import Data.SBV.Provers.Prover
+import Data.SBV.Utils.Lib     (showText)
+
+import Data.SBV.TP.Utils
+
+import Data.Time (NominalDiffTime)
+import Data.SBV.Utils.TDiff
+
+import Data.Dynamic
+import Data.IORef (readIORef, writeIORef, modifyIORef')
+import qualified Data.Set as Set
+
+import Type.Reflection (typeRep)
+
+-- | A proposition is something SBV is capable of proving/disproving in TP.
+type Proposition a = ( QNot a
+                     , QuantifiedBool a
+                     , QSaturate Symbolic a
+                     , Skolemize (NegatesTo a)
+                     , Satisfiable (Symbolic (SkolemsTo (NegatesTo a)))
+                     , Constraint  Symbolic  (SkolemsTo (NegatesTo a))
+                     , Typeable a
+                     )
+
+-- | An inductive proposition is a proposition that has an induction scheme associated with it.
+type Inductive a = (HasInductionSchema a, Proposition a)
+
+-- | A class of values that has an associated induction schema. SBV manages this internally.
+class HasInductionSchema a where
+  inductionSchema :: a -> ProofObj
+
+-- | Induction schema for integers. Note that this is good for proving properties over naturals really.
+-- There are other instances that would apply to all integers, but this one is really the most useful
+-- in practice.
+instance HasInductionSchema (Forall nm Integer -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger" ax
+     where pf = p . Forall
+           ax =   sAnd [pf 0, quantifiedBool (\(Forall i) -> (i .>= 0 .=> pf i) .=> pf (i + 1))]
+              .=> quantifiedBool (\(Forall i) -> pf i)
+
+-- | Induction schema for integers with one extra argument
+instance SymVal at => HasInductionSchema (Forall nm Integer -> Forall an at -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger1" ax
+     where pf i a = p (Forall i) (Forall a)
+           ax     = sAnd [ quantifiedBool (\           (Forall a) -> pf 0 a)
+                         , quantifiedBool (\(Forall i) (Forall a) -> (i .>= 0 .=> pf i a) .=> pf (i + 1) a)]
+                    .=>    quantifiedBool (\(Forall i) (Forall a) -> pf i a)
+
+-- | Induction schema for integers with two extra arguments
+instance (SymVal at, SymVal bt) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger2" ax
+     where pf i a b = p (Forall i) (Forall a) (Forall b)
+           ax       = sAnd [ quantifiedBool (\           (Forall a) (Forall b) -> pf 0 a b)
+                           , quantifiedBool (\(Forall i) (Forall a) (Forall b) -> (i .>= 0 .=> pf i a b) .=> pf (i + 1) a b)]
+                      .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) -> pf i a b)
+
+-- | Induction schema for integers with three extra arguments
+instance (SymVal at, SymVal bt, SymVal ct) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger3" ax
+     where pf i a b c = p (Forall i) (Forall a) (Forall b) (Forall c)
+           ax         = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) -> pf 0 a b c)
+                             , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) -> (i .>= 0 .=> pf i a b c) .=> pf (i + 1) a b c)]
+                        .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) -> pf i a b c)
+
+-- | Induction schema for integers with four extra arguments
+instance (SymVal at, SymVal bt, SymVal ct, SymVal dt) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger4" ax
+     where pf i a b c d = p (Forall i) (Forall a) (Forall b) (Forall c) (Forall d)
+           ax           = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) (Forall d) -> pf 0 a b c d)
+                               , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) -> (i .>= 0 .=> pf i a b c d) .=> pf (i + 1) a b c d)]
+                          .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) -> pf i a b c d)
+
+-- | Induction schema for integers with five extra arguments
+instance (SymVal at, SymVal bt, SymVal ct, SymVal dt, SymVal et) => HasInductionSchema (Forall nm Integer -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> Forall en et -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom "inductInteger5" ax
+     where pf i a b c d e = p (Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ax             = sAnd [ quantifiedBool (\           (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf 0 a b c d e)
+                                 , quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> (i .>= 0 .=> pf i a b c d e) .=> pf (i + 1) a b c d e)]
+                            .=>    quantifiedBool (\(Forall i) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf i a b c d e)
+
+-- | Induction schema for lists.
+instance SymVal x => HasInductionSchema (Forall nm [x] -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x])) ax
+     where pf = p . Forall
+           ax =   sAnd [pf [], quantifiedBool (\(Forall x) (Forall xs) -> pf xs .=> pf (x .: xs))]
+              .=> quantifiedBool (\(Forall xs) -> pf xs)
+
+-- | Induction schema for lists with one extra argument
+instance (SymVal x, SymVal at) => HasInductionSchema (Forall nm [x] -> Forall an at -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "1") ax
+     where pf xs a = p (Forall xs) (Forall a)
+           ax      = sAnd [ quantifiedBool (\                       (Forall a) -> pf [] a)
+                          , quantifiedBool (\(Forall x) (Forall xs) (Forall a) -> pf xs a .=> pf (x .: xs) a)]
+                     .=>    quantifiedBool (\(Forall xs) (Forall a) -> pf xs a)
+
+-- | Induction schema for lists with two extra arguments
+instance (SymVal x, SymVal at, SymVal bt) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "2") ax
+     where pf xs a b = p (Forall xs) (Forall a) (Forall b)
+           ax        = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) -> pf [] a b)
+                            , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) -> pf xs a b .=> pf (x .: xs) a b)]
+                       .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) -> pf xs a b)
+
+-- | Induction schema for lists with three extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "3") ax
+     where pf xs a b c = p (Forall xs) (Forall a) (Forall b) (Forall c)
+           ax          = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) -> pf [] a b c)
+                              , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) -> pf xs a b c .=> pf (x .: xs) a b c)]
+                         .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) -> pf xs a b c)
+
+-- | Induction schema for lists with four extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct, SymVal dt) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "4") ax
+     where pf xs a b c d = p (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d)
+           ax            = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) (Forall d) -> pf [] a b c d)
+                                , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) -> pf xs a b c d .=> pf (x .: xs) a b c d)]
+                           .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) -> pf xs a b c d)
+
+-- | Induction schema for lists with five extra arguments
+instance (SymVal x, SymVal at, SymVal bt, SymVal ct, SymVal dt, SymVal et) => HasInductionSchema (Forall nm [x] -> Forall an at -> Forall bn bt -> Forall cn ct -> Forall dn dt -> Forall en et -> SBool) where
+   inductionSchema p = proofOf $ internalAxiom ("induct" ++ show (typeRep @[x]) ++ "5") ax
+     where pf xs a b c d e = p (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ax              = sAnd [ quantifiedBool (\                       (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf [] a b c d e)
+                                  , quantifiedBool (\(Forall x) (Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf xs a b c d e .=> pf (x .: xs) a b c d e)]
+                             .=>    quantifiedBool (\(Forall xs) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) -> pf xs a b c d e)
+
+-- | Accept the given definition as a fact. Usually used to introduce definitional axioms,
+-- giving meaning to uninterpreted symbols. Note that we perform no checks on these propositions,
+-- if you assert nonsense, then you get nonsense back. So, calls to 'axiom' should be limited to
+-- definitions, or basic axioms (like commutativity, associativity) of uninterpreted function symbols.
+axiom :: Proposition a => String -> a -> TP (Proof a)
+axiom nm p = do cfg <- getTPConfig
+                u   <- tpGetNextUnique
+                _   <- liftIO $ startTP cfg True "Axiom" 0 (TPProofOneShot nm [])
+                let Proof iax = internalAxiom nm p
+                pure $ Proof (iax { isUserAxiom = True, uniqId = u })
+
+-- | Internal axiom generator; so we can keep truck of TP's trusted axioms, vs. user given axioms.
+internalAxiom :: Proposition a => String -> a -> Proof a
+internalAxiom nm p = Proof $ ProofObj { dependencies = []
+                                      , isUserAxiom  = False
+                                      , getObjProof  = label nm (quantifiedBool p)
+                                      , getProp      = toDyn p
+                                      , proofName    = nm
+                                      , uniqId       = TPInternal
+                                      , aliases      = []
+                                      , wasCached    = False
+                                      }
+
+-- | Propagate the settings for ribbon/timing from top to current. Because in any subsequent configuration
+-- in a lemmaWith, inductWith etc., we just want to change the solver, not the actual settings for TP.
+tpMergeCfg :: SMTConfig -> SMTConfig -> SMTConfig
+tpMergeCfg cur top = cur{verbose = verbose top, tpOptions = tpOptions top}
+
+-- | Prove a given statement, using auxiliaries as helpers. Using the default solver.
+lemma :: Proposition a => String -> a -> [ProofObj] -> TP (Proof a)
+lemma nm f by = do cfg <- getTPConfig
+                   lemmaWith cfg nm f by
+
+-- | Prove a lemma, using the given configuration.
+lemmaWith :: Proposition a => SMTConfig -> String -> a -> [ProofObj] -> TP (Proof a)
+lemmaWith cfgIn nm inputProp by = do
+                 cached <- lookupProofCache inputProp
+                 topCfg <- getTPConfig
+                 case cached of
+                   Just prf -> do let cfg = cfgIn `tpMergeCfg` topCfg
+                                  returnCachedProof cfg nm prf
+                   Nothing  -> do let cfg@SMTConfig{tpOptions = TPOptions{printStats}} = cfgIn `tpMergeCfg` topCfg
+                                  tpSt <- getTPState
+                                  u    <- tpGetNextUnique
+                                  result <- liftIO $ getTimeStampIf printStats >>= runSMTWith cfg . go tpSt cfg u
+                                  addToProofCache inputProp (proofOf result)
+                                  pure result
+  where go tpSt cfg u mbStartTime = do st <- symbolicEnv
+                                       -- Skip measure checks in the normal runWithQuery path; we handle them here
+                                       liftIO $ writeIORef (rSkipMeasureChecks st) True
+                                       qSaturateSavingObservables inputProp
+                                       mapM_ (constrain . getObjProof) by
+
+                                       -- Run measure checks for any newly encountered recursive functions
+                                       liftIO $ checkNewMeasures cfg st tpSt
+
+                                       -- Read no-term-check functions from this proof's State (not TPState, which accumulates)
+                                       noTermFns <- liftIO $ readIORef (rNoTermCheckFunctions st)
+
+                                       query $ smtProofStep cfg tpSt "Lemma" 0 (TPProofOneShot nm by) Nothing inputProp [] (good noTermFns cfg mbStartTime u)
+
+        -- What to do if all goes well
+        good noTermFns cfg mbStart u d = do
+                                       mbElapsed <- getElapsedTime mbStart
+                                       let ntcDeps = map noTermCheckProof (Set.toList noTermFns)
+                                           allBy   = by ++ ntcDeps
+                                       liftIO $ finishTP cfg ("Q.E.D." ++ concludeModulo allBy) d $ catMaybes [mbElapsed]
+                                       pure $ Proof $ ProofObj { dependencies = allBy
+                                                               , isUserAxiom  = False
+                                                               , getObjProof  = label nm (quantifiedBool inputProp)
+                                                               , getProp      = toDyn inputProp
+                                                               , proofName    = nm
+                                                               , uniqId       = u
+                                                               , aliases      = []
+                                                               , wasCached    = False
+                                                               }
+
+-- | Prove a given statement, using the induction schema for the proposition. Using the default solver.
+inductiveLemma :: Inductive a => String -> a -> [ProofObj] -> TP (Proof a)
+inductiveLemma nm f by = do cfg <- getTPConfig
+                            inductiveLemmaWith cfg nm f by
+
+-- | Prove a given statement, using the induction schema for the proposition. Using the default solver.
+inductiveLemmaWith :: Inductive a => SMTConfig -> String -> a -> [ProofObj] -> TP (Proof a)
+inductiveLemmaWith cfg nm f by = lemmaWith cfg nm f (inductionSchema f : by)
+
+-- | Check any newly encountered recursive function measures. This reads deferred checks
+-- from 'rMeasureChecks', runs those not yet verified, and records them as verified.
+-- Skips functions in 'measuresBeingVerified' to prevent infinite recursion when a
+-- measureLemma proof uses the function whose measure is currently being checked.
+checkNewMeasures :: SMTConfig -> State -> TPState -> IO ()
+checkNewMeasures cfg@SMTConfig{tpOptions = TPOptions{measuresBeingVerified}} st tpSt = do
+   isDry <- readIORef (dryRun tpSt)
+   unless isDry $ do
+     checks     <- readIORef (rMeasureChecks st)
+     verified   <- readIORef (measuresVerified tpSt)
+     productive <- readIORef (productiveVerified tpSt)
+     let allVerified = verified `Set.union` productive
+         allNames    = Set.fromList (map (\(n, _, _) -> n) checks)
+         new         = [(n, p, c) | (n, p, c) <- checks, n `Set.notMember` allVerified, n `Set.notMember` measuresBeingVerified]
+         skipped     = [n | (n, _, _) <- checks, n `Set.notMember` allVerified, n `Set.member` measuresBeingVerified]
+
+         msg s | not (verbose cfg)
+               = pure ()
+               | Just f <- redirectVerbose cfg
+               = appendFile f (s ++ "\n")
+               | True
+               = putStrLn s
+
+     unless (null new && null skipped) $
+        msg $ "[MEASURE] checkNewMeasures: " ++ show (length new) ++ " to verify"
+              ++ (if null skipped then "" else ", " ++ show (length skipped) ++ " skipped (being verified): " ++ show skipped)
+
+     modifyIORef' (measuresEncountered tpSt) (Set.union allNames)
+     let verify (n, isProductive, c) = do
+           msg $ "[MEASURE] checkNewMeasures: verifying " ++ n
+           () <- c cfg
+           msg $ "[MEASURE] checkNewMeasures: " ++ n ++ " verified"
+           if isProductive
+              then modifyIORef' (productiveVerified tpSt) (Set.insert n)
+              else modifyIORef' (measuresVerified   tpSt) (Set.insert n)
+     mapM_ verify new
+
+-- | Capture the general flow of a proof-step. Note that this is the only point where we call the backend solver
+-- in a TP proof.
+smtProofStep :: (SolverContext m, MonadIO m, MonadQuery m, MonadSymbolic m, Proposition a)
+   => SMTConfig                              -- ^ config
+   -> TPState                                -- ^ TPState
+   -> String                                 -- ^ tag
+   -> Int                                    -- ^ level
+   -> TPProofContext                         -- ^ the context in which we're doing the proof
+   -> Maybe SBool                            -- ^ Assumptions under which we do the check-sat. If there's one we'll push/pop
+   -> a                                      -- ^ what we want to prove
+   -> [(String, SVal)]                       -- ^ Values to display in case of failure
+   -> ((Int, Maybe NominalDiffTime) -> IO r) -- ^ what to do when unsat, with the tab amount and time elapsed (if asked)
+   -> m r
+smtProofStep cfg@SMTConfig{verbose, tpOptions = TPOptions{printStats}} tpState tag level ctx mbAssumptions prop disps unsat = do
+
+        isDry <- liftIO $ readIORef (dryRun tpState)
+        if isDry
+           then do -- Dry run: record width, skip solver, report success
+                   tab <- liftIO $ startTP cfg verbose tag level ctx
+                   liftIO $ modifyIORef' (maxRibbon tpState) (max tab)
+                   liftIO $ unsat (tab, Nothing)
+           else case mbAssumptions of
+                   Nothing  -> do queryDebug ["; smtProofStep: No context value to push."]
+                                  check
+                   Just asm -> do queryDebug ["; smtProofStep: Pushing in the context: " <> showText asm]
+                                  inNewAssertionStack $ do constrain asm
+                                                           check
+
+ where check = do
+           tab <- liftIO $ startTP cfg verbose tag level ctx
+
+           -- It's tempting to skolemize here.. But skolemization creates fresh constants
+           -- based on the name given, and they mess with all else. So, don't skolemize!
+           constrain $ sNot (quantifiedBool prop)
+
+           (mbT, r) <- timeIf printStats checkSat
+
+           updStats tpState (\s -> s{noOfCheckSats = noOfCheckSats s + 1})
+
+           case mbT of
+             Nothing -> pure ()
+             Just t  -> updStats tpState (\s -> s{solverElapsed = solverElapsed s + t})
+
+           case r of
+             Unk    -> unknown
+             Sat    -> cex
+             DSat{} -> cex
+             Unsat  -> liftIO $ unsat (tab, mbT)
+
+       die = error "Failed"
+
+       fullNm = case ctx of
+                  TPProofOneShot       s _    -> s
+                  TPProofStep    True  s _ ss -> "assumptions for " ++ intercalate "." (s : ss)
+                  TPProofStep    False s _ ss ->                       intercalate "." (s : ss)
+
+       unknown = do r <- getUnknownReason
+                    liftIO $ do message cfg $ "\n*** Failed to prove " ++ fullNm ++ ".\n"
+                                message cfg $ "\n*** Solver reported: " ++ show r ++ "\n"
+                                die
+
+       -- What to do if the proof fails
+       cex = do
+         liftIO $ message cfg $ "\n*** Failed to prove " ++ fullNm ++ ".\n"
+
+         res <- case ctx of
+                  TPProofStep{} -> do mapM_ (uncurry sObserve) disps
+                                      Satisfiable cfg <$> getModel
+                  TPProofOneShot _ by ->
+                     -- When trying to get a counter-example not in query mode, we
+                     -- do a skolemized sat call, which gets better counter-examples.
+                     -- We only include the those facts that are user-given axioms. This
+                     -- way our counter-example will be more likely to be relevant
+                     -- to the proposition we're currently proving. (Hopefully.)
+                     -- Remember that we first have to negate, and then skolemize!
+                     do SatResult res <- liftIO $ satWith cfg $ do
+                                           qSaturateSavingObservables prop
+                                           mapM_ constrain [getObjProof | ProofObj{isUserAxiom, getObjProof} <- by, isUserAxiom] :: Symbolic ()
+                                           mapM_ (uncurry sObserve) disps
+                                           pure $ skolemize (qNot prop)
+                        pure res
+
+         liftIO $ message cfg $ show (ThmResult res) ++ "\n"
+
+         die
diff --git a/Data/SBV/TP/TP.hs b/Data/SBV/TP/TP.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/TP/TP.hs
@@ -0,0 +1,1583 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.TP.TP
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds              #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE OverloadedLists        #-}
+{-# LANGUAGE OverloadedStrings      #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TupleSections          #-}
+{-# LANGUAGE TypeApplications       #-}
+{-# LANGUAGE TypeFamilyDependencies #-}
+{-# LANGUAGE TypeOperators          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.TP.TP (
+         Proposition, Proof, proofOf, assumptionFromProof, Instantiatable(..), Inst(..)
+       , rootOfTrust, RootOfTrust(..), ProofTree(..), showProofTree, showProofTreeHTML
+       ,   axiom
+       ,            lemma,          lemmaWith
+       ,   inductiveLemma, inductiveLemmaWith
+       ,             calc,           calcWith
+       ,           induct,         inductWith
+       ,          sInduct,        sInductWith
+       , sorry
+       , TP, runTP, runTPWith, tpQuiet, tpStats, tpAsms
+       , whenDryRun, unlessDryRun
+       , measureLemma, measureLemmaWith
+       , (|-), (|->), (⊢), (=:), (≡), (??), (∵), split, split2, cases, (==>), (⟹), qed, trivial, contradiction
+       , qc, qcWith
+       , disp
+       , recall, recallWith
+       ) where
+
+import Data.SBV
+import Data.SBV.Core.Model (qSaturateSavingObservables)
+import Data.SBV.Core.Data  (SBV(..), SVal(..))
+import qualified Data.SBV.Core.Symbolic as S (sObserve)
+
+import qualified Data.Text as T
+
+import Data.SBV.Core.Symbolic (rSkipMeasureChecks, rNoTermCheckFunctions)
+import Data.SBV.Core.Operations (svEqual)
+import Data.SBV.Control hiding (getProof, (|->))
+
+import Data.SBV.TP.Kernel
+import Data.SBV.TP.Utils
+
+import qualified Data.SBV.List as SL
+
+import Control.Exception (SomeException)
+import Control.Monad (when)
+import Control.Monad.Trans (liftIO)
+import Data.IORef (readIORef, writeIORef, modifyIORef')
+
+import qualified Data.Set as Set
+
+import Data.Char  (isSpace)
+import Data.List  (intercalate, isPrefixOf, isSuffixOf)
+import Data.Maybe (catMaybes, maybeToList)
+
+import Data.Proxy
+import Data.Kind    (Type)
+import GHC.TypeLits (KnownSymbol, symbolVal, Symbol)
+
+import Data.SBV.Utils.TDiff
+
+import Data.Dynamic
+
+import qualified Test.QuickCheck as QC
+import Test.QuickCheck (quickCheckWithResult)
+
+-- | Captures the steps for a calculational proof
+data CalcStrategy = CalcStrategy { calcIntros     :: SBool
+                                 , calcProofTree  :: TPProof
+                                 , calcQCInstance :: [Int] -> Symbolic SBool
+                                 }
+
+-- | Saturatable things in steps
+proofTreeSaturatables :: TPProof -> [SBool]
+proofTreeSaturatables = go
+  where go (ProofEnd    b           hs                ) = b : concatMap getH hs
+        go (ProofStep   a           hs               r) = a : concatMap getH hs ++ go r
+        go (ProofBranch (_ :: Bool) (_ :: [String]) ps) = concat [b : go p | (b, p) <- ps]
+
+        getH (HelperProof  p) = [getObjProof p]
+        getH (HelperAssum  b) = [b]
+        getH HelperQC{}       = []
+        getH HelperString{}   = []
+        getH (HelperDisp _ v) = [SBV (v `svEqual` v)]
+
+-- | Things that are inside calc-strategy that we have to saturate
+getCalcStrategySaturatables :: CalcStrategy -> [SBool]
+getCalcStrategySaturatables (CalcStrategy calcIntros calcProofTree _calcQCInstance) = calcIntros : proofTreeSaturatables calcProofTree
+
+-- | Use an injective type family to allow for curried use of calc and strong induction steps.
+type family StepArgs a t = result | result -> t where
+  StepArgs                                                                             SBool  t =                                               (SBool, TPProofRaw (SBV t))
+  StepArgs (Forall na a                                                             -> SBool) t = (SBV a                                     -> (SBool, TPProofRaw (SBV t)))
+  StepArgs (Forall na a -> Forall nb b                                              -> SBool) t = (SBV a -> SBV b                            -> (SBool, TPProofRaw (SBV t)))
+  StepArgs (Forall na a -> Forall nb b -> Forall nc c                               -> SBool) t = (SBV a -> SBV b -> SBV c                   -> (SBool, TPProofRaw (SBV t)))
+  StepArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d                -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d          -> (SBool, TPProofRaw (SBV t)))
+  StepArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> (SBool, TPProofRaw (SBV t)))
+
+-- | Use an injective type family to allow for curried use of measures in strong induction instances
+type family MeasureArgs a t = result | result -> t where
+  MeasureArgs                                                                             SBool  t = (                                             SBV t)
+  MeasureArgs (Forall na a                                                             -> SBool) t = (SBV a                                     -> SBV t)
+  MeasureArgs (Forall na a -> Forall nb b                                              -> SBool) t = (SBV a -> SBV b                            -> SBV t)
+  MeasureArgs (Forall na a -> Forall nb b -> Forall nc c                               -> SBool) t = (SBV a -> SBV b -> SBV c                   -> SBV t)
+  MeasureArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d                -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d          -> SBV t)
+  MeasureArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV t)
+
+-- | Use an injective type family to allow for curried use of regular induction steps. The first argument is the inductive arg that comes separately,
+-- and hence is not used in the right-hand side of the equation.
+type family IStepArgs a t = result | result -> t where
+  IStepArgs ( Forall nx x                                                                                          -> SBool) t =                                               (SBool, TPProofRaw (SBV t))
+  IStepArgs ( Forall nx x               -> Forall na a                                                             -> SBool) t = (SBV a ->                                     (SBool, TPProofRaw (SBV t)))
+  IStepArgs ( Forall nx x               -> Forall na a -> Forall nb b                                              -> SBool) t = (SBV a -> SBV b                            -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ( Forall nx x               -> Forall na a -> Forall nb b -> Forall nc c                               -> SBool) t = (SBV a -> SBV b -> SBV c                   -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ( Forall nx x               -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d                -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d          -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ( Forall nx x               -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ((Forall nx x, Forall ny y)                                                                            -> SBool) t =                                               (SBool, TPProofRaw (SBV t))
+  IStepArgs ((Forall nx x, Forall ny y) -> Forall na a                                                             -> SBool) t = (SBV a ->                                     (SBool, TPProofRaw (SBV t)))
+  IStepArgs ((Forall nx x, Forall ny y) -> Forall na a -> Forall nb b                                              -> SBool) t = (SBV a -> SBV b                            -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ((Forall nx x, Forall ny y) -> Forall na a -> Forall nb b -> Forall nc c                               -> SBool) t = (SBV a -> SBV b -> SBV c                   -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ((Forall nx x, Forall ny y) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d                -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d          -> (SBool, TPProofRaw (SBV t)))
+  IStepArgs ((Forall nx x, Forall ny y) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) t = (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> (SBool, TPProofRaw (SBV t)))
+
+-- | A class for doing equational reasoning style calculational proofs. Use 'calc' to prove a given theorem
+-- as a sequence of equalities, each step following from the previous.
+class Calc a where
+  -- | Prove a property via a series of equality steps, using the default solver.
+  -- Let @H@ be a list of already established lemmas. Let @P@ be a property we wanted to prove, named @name@.
+  -- Consider a call of the form @calc name P (cond, [A, B, C, D]) H@. Note that @H@ is
+  -- a list of already proven facts, ensured by the type signature. We proceed as follows:
+  --
+  --    * Prove: @(H && cond)                                   -> (A == B)@
+  --    * Prove: @(H && cond && A == B)                         -> (B == C)@
+  --    * Prove: @(H && cond && A == B && B == C)               -> (C == D)@
+  --    * Prove: @(H && (cond -> (A == B && B == C && C == D))) -> P@
+  --    * If all of the above steps succeed, conclude @P@.
+  --
+  -- cond acts as the context. Typically, if you are trying to prove @Y -> Z@, then you want cond to be Y.
+  -- (This is similar to @intros@ commands in theorem provers.)
+  --
+  -- So, calc-lemma is essentially modus-ponens, applied in a sequence of stepwise equality reasoning in the case of
+  -- non-boolean steps.
+  --
+  -- If there are no helpers given (i.e., if @H@ is empty), then this call is equivalent to 'lemmaWith'.
+  calc :: (Proposition a, SymVal t, EqSymbolic (SBV t)) => String -> a -> StepArgs a t -> TP (Proof a)
+
+  -- | Prove a property via a series of equality steps, using the given solver.
+  calcWith :: (Proposition a, SymVal t, EqSymbolic (SBV t)) => SMTConfig -> String -> a -> StepArgs a t -> TP (Proof a)
+
+  -- | Internal, shouldn't be needed outside the library
+  {-# MINIMAL calcSteps #-}
+  calcSteps :: (SymVal t, EqSymbolic (SBV t)) => a -> StepArgs a t -> Symbolic (SBool, CalcStrategy)
+
+  calc         nm p steps = getTPConfig >>= \cfg  -> calcWith    cfg                   nm p steps
+  calcWith cfg nm p steps = getTPConfig >>= \cfg' -> calcGeneric (tpMergeCfg cfg cfg') nm p steps
+
+  calcGeneric :: (SymVal t, EqSymbolic (SBV t), Proposition a) => SMTConfig -> String -> a -> StepArgs a t -> TP (Proof a)
+  calcGeneric cfg nm result steps = do
+      cached <- lookupProofCache result
+      case cached of
+        Just prf -> returnCachedProof cfg nm prf
+        Nothing  -> do
+          tpSt <- getTPState
+          u    <- tpGetNextUnique
+
+          (_, CalcStrategy {calcQCInstance}) <- liftIO $ runSMTWith cfg (calcSteps result steps)
+
+          proof <- liftIO $ runSMTWith cfg $ do
+
+             qSaturateSavingObservables result -- make sure we saturate the result, i.e., get all it's UI's, types etc. pop out
+
+             let header = "Lemma: " ++ nm
+             message cfg $ header ++ "\n"
+             liftIO $ do isDry <- readIORef (dryRun tpSt)
+                         when isDry $ modifyIORef' (maxRibbon tpSt) (max (length header))
+
+             (calcGoal, strategy@CalcStrategy {calcIntros, calcProofTree}) <- calcSteps result steps
+
+             -- Collect all subterms and saturate them
+             mapM_ qSaturateSavingObservables $ getCalcStrategySaturatables strategy
+
+             -- Run measure checks for any newly encountered recursive functions
+             st <- symbolicEnv
+             liftIO $ do writeIORef (rSkipMeasureChecks st) True
+                         checkNewMeasures cfg st tpSt
+
+             query $ proveProofTree cfg tpSt nm (result, calcGoal) calcIntros calcProofTree u calcQCInstance
+
+          addToProofCache result (proofOf proof)
+          pure proof
+
+-- | In the proof tree, what's the next node label?
+nextProofStep :: [Int] -> [Int]
+nextProofStep bs = case reverse bs of
+                     i : rs -> reverse $ i + 1 : rs
+                     []     -> [1]
+
+-- | Prove the proof tree. The arguments are:
+--
+--      result           : The ultimate goal we want to prove. Note that this is a general proposition, and we don't actually prove it. See the next param.
+--      resultBool       : The instance of result that, if we prove it, establishes the result itself
+--      initialHypotheses: Hypotheses (conjuncted)
+--      calcProofTree    : A tree of steps, which give rise to a bunch of equalities
+--
+-- Note that we do not check the resultBool is the result itself just "instantiated" appropriately. This is the contract with the caller who
+-- has to establish that by whatever means it chooses to do so.
+--
+-- The final proof we have has the following form:
+--
+--     - For each "link" in the proofTree, prove that intros .=> link
+--     - The above will give us a bunch of results, for each leaf node in the tree.
+--     - Then prove: (intros .=> sAnd results) .=> resultBool
+--     - Then conclude result, based on what assumption that proving resultBool establishes result
+--
+-- NB. This function needs to be in "sync" with qcRun below for obvious reasons. So, any changes there
+-- make it here too!
+proveProofTree :: Proposition a
+               => SMTConfig
+               -> TPState
+               -> String                    -- ^ the name of the top result
+               -> (a, SBool)                -- ^ goal: as a proposition and as a boolean
+               -> SBool                     -- ^ hypotheses
+               -> TPProof                   -- ^ proof tree
+               -> TPUnique                  -- ^ unique id
+               -> ([Int] -> Symbolic SBool) -- ^ quick-checker
+               -> Query (Proof a)
+proveProofTree cfg tpSt nm (result, resultBool) initialHypotheses calcProofTree uniq quickCheckInstance = do
+    results <- walk initialHypotheses 1 ([1], calcProofTree)
+
+    queryDebug [T.pack nm <> ": Proof end: proving the result:"]
+
+    mbStartTime <- getTimeStampIf printStats
+    st <- symbolicEnv
+    noTermFns <- liftIO $ readIORef (rNoTermCheckFunctions st)
+    let ntcDeps = map noTermCheckProof (Set.toList noTermFns)
+    smtProofStep cfg tpSt "Result" 1
+                 (TPProofStep False nm [] [""])
+                 (Just (initialHypotheses .=> sAnd results))
+                 resultBool [] $ \d ->
+                   do mbElapsed <- getElapsedTime mbStartTime
+                      let allDeps  = getDependencies calcProofTree ++ ntcDeps
+                          modulo   = concludeModulo (concatMap getHelperProofs (getAllHelpers calcProofTree) ++ ntcDeps)
+                      finishTP cfg ("Q.E.D." ++ modulo) d (catMaybes [mbElapsed])
+
+                      pure $ Proof $ ProofObj { dependencies = allDeps
+                                              , isUserAxiom  = False
+                                              , getObjProof  = label nm (quantifiedBool result)
+                                              , getProp      = toDyn result
+                                              , proofName    = nm
+                                              , uniqId       = uniq
+                                              , aliases      = []
+                                              , wasCached    = False
+                                              }
+
+  where SMTConfig{tpOptions = TPOptions{printStats, printAsms}} = cfg
+
+        isEnd ProofEnd{}    = True
+        isEnd ProofStep{}   = False
+        isEnd ProofBranch{} = False
+
+        -- trim the branch-name, if we're in a deeper level, and we're at the end
+        trimBN level bn | level > 1, 1 : _ <- reverse bn = init bn
+                        | True                           = bn
+
+        -- If the next step is ending and we're the 1st step; our number can be skipped
+        mkStepName level bn nextStep | isEnd nextStep = map show (trimBN level bn)
+                                     | True           = map show bn
+
+        walk :: SBool -> Int -> ([Int], TPProof) -> Query [SBool]
+
+        -- End of proof, return what it established. If there's a hint associated here, it was probably by mistake; so tell it to the user.
+        walk intros level (bn, ProofEnd calcResult hs)
+           | not (null hs)
+           = error $ unlines [ ""
+                             , "*** Incorrect calc/induct lemma calculations."
+                             , "***"
+                             , "***    The last step in the proof has a helper, which isn't used."
+                             , "***"
+                             , "*** Perhaps the hint is off-by-one in its placement?"
+                             ]
+           | True
+           =  do -- If we're not at the top-level and this is the only step, print it.
+                 -- Otherwise the noise isn't necessary.
+                 when (level > 1) $ case reverse bn of
+                                      1 : _ -> liftIO $ do tab <- startTP cfg False "Step" level (TPProofStep False nm [] (map show (init bn)))
+                                                           finishTP cfg "Q.E.D." (tab, Nothing) []
+                                      _     -> pure ()
+
+                 pure [intros .=> calcResult]
+
+        -- Do the branches separately and collect the results. If there's coverage needed, we do it too; which
+        -- is essentially the assumption here.
+        walk intros level (bnTop, ProofBranch checkCompleteness hintStrings ps) = do
+
+          let bn = trimBN level bnTop
+
+              addSuffix xs s = case reverse xs of
+                                  l : p -> reverse $ (l ++ s) : p
+                                  []    -> [s]
+
+              full | checkCompleteness = ""
+                   | True              = "full "
+
+              stepName = map show bn
+
+          _ <- io $ startTP cfg True "Step" level (TPProofStep False nm hintStrings (addSuffix stepName (" (" ++ show (length ps) ++ " way " ++ full ++ "case split)")))
+
+          results <- concat <$> sequence [walk (intros .&& branchCond) (level + 1) (bn ++ [i, 1], p) | (i, (branchCond, p)) <- zip [1..] ps]
+
+          when checkCompleteness $ smtProofStep cfg tpSt "Step" (level+1)
+                                                         (TPProofStep False nm [] (stepName ++ ["Completeness"]))
+                                                         (Just intros)
+                                                         (sOr (map fst ps))
+                                                         []
+                                                         (\d -> finishTP cfg "Q.E.D." d [])
+          pure results
+
+        -- Do a proof step
+        walk intros level (bn, ProofStep cur hs p) = do
+
+             let finish et helpers d = finishTP cfg ("Q.E.D." ++ concludeModulo helpers) d et
+                 stepName            = mkStepName level bn p
+                 disps               = [(n, v) | HelperDisp n v <- hs]
+
+                 -- First prove the assumptions, if there are any. We stay quiet, unless timing is asked for
+                 (quietCfg, finalizer)
+                   | printStats || printAsms = (cfg,                                             finish [] [])
+                   | True                    = (cfg{tpOptions = (tpOptions cfg) {quiet = True}}, const (pure ()))
+
+                 as = concatMap getHelperAssumes hs
+                 ss = getHelperText hs
+
+             case as of
+               [] -> pure ()
+               _  -> smtProofStep quietCfg tpSt "Asms" level
+                                           (TPProofStep True nm [] stepName)
+                                           (Just intros)
+                                           (sAnd as)
+                                           disps
+                                           finalizer
+
+             -- Are we asked to do quick-check?
+             case [qcArg | HelperQC qcArg <- hs] of
+               [] -> do -- No quickcheck. Just prove the step
+                        let by = concatMap getHelperProofs hs
+
+                        smtProofStep cfg tpSt "Step" level
+                                         (TPProofStep False nm ss stepName)
+                                         (Just (sAnd (intros : as ++ map getObjProof by)))
+                                         cur
+                                         disps
+                                         (finish [] by)
+
+               xs -> do let qcArg = last xs -- take the last one if multiple exists. Why not?
+
+                            hs' = concatMap xform hs ++ [HelperString ("qc: Running " ++ show (QC.maxSuccess qcArg) ++ " tests")]
+                            xform HelperProof{}    = []
+                            xform HelperAssum{}    = []
+                            xform h@HelperQC{}     = [h]
+                            xform h@HelperString{} = [h]
+                            xform HelperDisp{}     = []
+
+                        liftIO $ do
+
+                           tab <- startTP cfg (verbose cfg) "Step" level (TPProofStep False nm (getHelperText hs') stepName)
+                           isDry <- readIORef (dryRun tpSt)
+                           when isDry $ modifyIORef' (maxRibbon tpSt) (max tab)
+
+                           (mbT, r) <- timeIf printStats $ quickCheckWithResult qcArg{QC.chatty = verbose cfg} $ quickCheckInstance bn
+
+                           case mbT of
+                             Nothing -> pure ()
+                             Just t  -> updStats tpSt (\s -> s{qcElapsed = qcElapsed s + t})
+
+                           let err = case r of
+                                   QC.Success {}                -> Nothing
+                                   QC.Failure {QC.output = out} -> Just out
+                                   QC.GaveUp  {}                -> Just $ unlines [ "*** QuickCheck reported \"GaveUp\""
+                                                                                  , "***"
+                                                                                  , "*** This can happen if you have assumptions in the environment"
+                                                                                  , "*** that makes it hard for quick-check to generate valid test values."
+                                                                                  , "***"
+                                                                                  , "*** See if you can reduce assumptions. If not, please get in touch,"
+                                                                                  , "*** to see if we can handle the problem via custom Arbitrary instances."
+                                                                                  ]
+                                   QC.NoExpectedFailure {}      -> Just "Expected failure but test passed." -- can't happen
+
+                           case err of
+                             Just e  -> do putStrLn $ "\n*** QuickCheck failed for " ++ intercalate "." (nm : stepName)
+                                           putStrLn e
+                                           error "Failed"
+
+                             Nothing -> let extra = [' ' | printStats]  -- aligns better when printing stats
+                                        in finishTP cfg ("QC OK" ++ extra) (tab, mbT) []
+
+             -- Move to next
+             walk intros level (nextProofStep bn, p)
+
+-- | Helper data-type for calc-step below
+data CalcContext a = CalcStart     [Helper] -- Haven't started yet
+                   | CalcStep  a a [Helper] -- Intermediate step: first value, prev value
+
+
+-- | Turn a raw (i.e., as written by the user) proof tree to a tree where the successive equalities are made explicit.
+mkProofTree :: SymVal a => (SBV a -> SBV a -> c, SBV a -> SBV a -> SBool) -> TPProofRaw (SBV a) -> TPProofGen c [String] SBool
+mkProofTree (symTraceEq, symEq) = go (CalcStart [])
+  where -- End of the proof; tie the begin and end
+        go step (ProofEnd () hs) = case step of
+                                     -- It's tempting to error out if we're at the start and already reached the end
+                                     -- This means we're given a sequence of no-steps. While this is useless in the
+                                     -- general case, it's quite valid in a case-split; where one of the case-splits
+                                     -- might be easy enough for the solver to deduce so the user simply says "just derive it for me."
+                                     CalcStart hs'           -> ProofEnd sTrue (hs' ++ hs) -- Nothing proven!
+                                     CalcStep  begin end hs' -> ProofEnd (begin `symEq` end) (hs' ++ hs)
+
+        -- Branch: Just push it down. We use the hints from previous step, and pass the current ones down.
+        go step (ProofBranch c hs ps) = ProofBranch c (getHelperText hs) [(bc, go step' p) | (bc, p) <- ps]
+           where step' = case step of
+                           CalcStart hs'     -> CalcStart (hs' ++ hs)
+                           CalcStep  a b hs' -> CalcStep a b (hs' ++ hs)
+
+        -- Step:
+        go (CalcStart hs)           (ProofStep cur hs' p) = go (CalcStep cur cur (hs' ++ hs)) p
+        go (CalcStep first prev hs) (ProofStep cur hs' p) = ProofStep (prev `symTraceEq` cur) hs (go (CalcStep first cur hs') p)
+
+-- | Turn a sequence of steps into a chain of equalities
+mkCalcSteps :: SymVal a => (SBool, TPProofRaw (SBV a)) -> ([Int] -> Symbolic SBool) -> Symbolic CalcStrategy
+mkCalcSteps (intros, tpp) qcInstance = do
+        pure $ CalcStrategy { calcIntros     = intros
+                            , calcProofTree  = mkProofTree ((.===), (.===)) tpp
+                            , calcQCInstance = qcInstance
+                            }
+
+-- | Given initial hypothesis, and a raw proof tree, build the quick-check walk over this tree for the step that's marked as such.
+qcRun :: SymVal a => [Int] -> (SBool, TPProofRaw (SBV a)) -> Symbolic SBool
+qcRun checkedLabel (intros, tpp) = do
+        results <- runTree sTrue 1 ([1], mkProofTree (\a b -> (a, b, a .=== b), (.==)) tpp)
+        case [b | (l, b) <- results, l == checkedLabel] of
+          [(caseCond, b)] -> do constrain $ intros .&& caseCond
+                                pure b
+          []              -> notFound
+          _               -> die "Hit the label multiple times."
+
+ where die why =  error $ unlines [ ""
+                                  , "*** Data.SBV.patch: Impossible happened."
+                                  , "***"
+                                  , "*** " ++ why
+                                  , "***"
+                                  , "*** While trying to quickcheck at level " ++ show checkedLabel
+                                  , "*** Please report this as a bug!"
+                                  ]
+
+       -- It is possible that we may not find the node. Why? Because it might be under a case-split (ite essentially)
+       -- and the random choices we made before-hand may just not get us there. Sigh. So, the right thing to do is
+       -- to just say "we're good." But this can also indicate a bug in our code. Oh well, we'll ignore it.
+       notFound = pure sTrue
+
+       -- "run" the tree, and if we hit the correct label return the result.
+       -- This needs to be in "sync" with proveProofTree for obvious reasons. So, any changes there
+       -- make it here too!
+       runTree :: SymVal a => SBool -> Int -> ([Int], TPProofGen (SBV a, SBV a, SBool) [String] SBool) -> Symbolic [([Int], (SBool, SBool))]
+       runTree _        _     (_,  ProofEnd{})         = pure []
+       runTree caseCond level (bn, ProofBranch _ _ ps) = concat <$> sequence [runTree (caseCond .&& branchCond) (level + 1) (bn ++ [i, 1], p)
+                                                                             | (i, (branchCond, p)) <- zip [1..] ps
+                                                                             ]
+       runTree caseCond level (bn, ProofStep (lhs, rhs, cur) hs p) = do rest <- runTree caseCond level (nextProofStep bn, p)
+                                                                        when (bn == checkedLabel) $ do
+                                                                                sObserve "lhs" lhs
+                                                                                sObserve "rhs" rhs
+                                                                                mapM_ (uncurry S.sObserve) [(n, v) | HelperDisp n v <- hs]
+                                                                        pure $ (bn, (caseCond, cur)) : rest
+
+-- | Chaining lemmas that depend on no extra variables
+instance Calc SBool where
+   calcSteps result steps = (result,) <$> mkCalcSteps steps (`qcRun` steps)
+
+-- | Chaining lemmas that depend on a single extra variable.
+instance (KnownSymbol na, SymVal a) => Calc (Forall na a -> SBool) where
+   calcSteps result steps = do a  <- free (symbolVal (Proxy @na))
+                               let q checkedLabel = do aa <- free (symbolVal (Proxy @na))
+                                                       qcRun checkedLabel (steps aa)
+                               (result (Forall a),) <$> mkCalcSteps (steps a) q
+
+-- | Chaining lemmas that depend on two extra variables.
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => Calc (Forall na a -> Forall nb b -> SBool) where
+   calcSteps result steps = do (a, b) <- (,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb))
+                               let q checkedLabel = do (aa, ab) <- (,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb))
+                                                       qcRun checkedLabel (steps aa ab)
+                               (result (Forall a) (Forall b),) <$> mkCalcSteps (steps a b) q
+
+-- | Chaining lemmas that depend on three extra variables.
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => Calc (Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+   calcSteps result steps = do (a, b, c) <- (,,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc))
+                               let q checkedLabel = do (aa, ab, ac) <- (,,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc))
+                                                       qcRun checkedLabel (steps aa ab ac)
+                               (result (Forall a) (Forall b) (Forall c),) <$> mkCalcSteps (steps a b c) q
+
+-- | Chaining lemmas that depend on four extra variables.
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => Calc (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+   calcSteps result steps = do (a, b, c, d) <- (,,,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc)) <*> free (symbolVal (Proxy @nd))
+                               let q checkedLabel = do sb <- steps <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc)) <*> free (symbolVal (Proxy @nd))
+                                                       qcRun checkedLabel sb
+                               (result (Forall a) (Forall b) (Forall c) (Forall d),) <$> mkCalcSteps (steps a b c d) q
+
+-- | Chaining lemmas that depend on five extra variables.
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e)
+      => Calc (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+   calcSteps result steps = do (a, b, c, d, e) <- (,,,,) <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc)) <*> free (symbolVal (Proxy @nd)) <*> free (symbolVal (Proxy @ne))
+                               let q checkedLabel = do sb <- steps <$> free (symbolVal (Proxy @na)) <*> free (symbolVal (Proxy @nb)) <*> free (symbolVal (Proxy @nc)) <*> free (symbolVal (Proxy @nd)) <*> free (symbolVal (Proxy @ne))
+                                                       qcRun checkedLabel sb
+                               (result (Forall a) (Forall b) (Forall c) (Forall d) (Forall e),) <$> mkCalcSteps (steps a b c d e) q
+
+-- | Captures the schema for an inductive proof. Base case might be nothing, to cover strong induction.
+data InductionStrategy = InductionStrategy { inductionIntros     :: SBool
+                                           , inductionMeasure    :: Maybe (SBool, [ProofObj])
+                                           , inductionBaseCase   :: Maybe SBool
+                                           , inductionProofTree  :: TPProof
+                                           , inductiveStep       :: SBool
+                                           , inductiveQCInstance :: [Int] -> Symbolic SBool
+                                           }
+
+-- | Are we doing regular induction or measure based general induction?
+data InductionStyle = RegularInduction | GeneralInduction
+
+getInductionStrategySaturatables :: InductionStrategy -> [SBool]
+getInductionStrategySaturatables (InductionStrategy inductionIntros
+                                                    inductionMeasure
+                                                    inductionBaseCase
+                                                    inductionProofSteps
+                                                    inductiveStep
+                                                    _inductiveQCInstance)
+  = inductionIntros
+  : inductiveStep
+  : proofTreeSaturatables inductionProofSteps
+  ++ measureDs
+  ++ maybeToList inductionBaseCase
+  where objDeps p = getObjProof p : concatMap objDeps (dependencies p)
+        measureDs = case inductionMeasure of
+                      Nothing      -> []
+                      Just (a, ps) -> a : concatMap objDeps ps
+
+-- | A class for doing regular inductive proofs.
+class Inductive a where
+   type IHType a :: Type
+   type IHArg  a :: Type
+
+   -- | Inductively prove a lemma, using the default config.
+   -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
+   -- partial correctness is guaranteed if non-terminating functions are involved.
+   induct  :: (Proposition a, SymVal t, EqSymbolic (SBV t)) => String -> a -> (Proof (IHType a) -> IHArg a -> IStepArgs a t) -> TP (Proof a)
+
+   -- | Same as 'induct', but with the given solver configuration.
+   -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
+   -- partial correctness is guaranteed if non-terminating functions are involved.
+   inductWith :: (Proposition a, SymVal t, EqSymbolic (SBV t)) => SMTConfig -> String -> a -> (Proof (IHType a) -> IHArg a -> IStepArgs a t) -> TP (Proof a)
+
+   induct         nm p steps = getTPConfig >>= \cfg  -> inductWith                       cfg                   nm p steps
+   inductWith cfg nm p steps = getTPConfig >>= \cfg' -> inductionEngine RegularInduction (tpMergeCfg cfg cfg') nm p (inductionStrategy p steps)
+
+   -- | Internal, shouldn't be needed outside the library
+   {-# MINIMAL inductionStrategy #-}
+   inductionStrategy :: (Proposition a, SymVal t, EqSymbolic (SBV t)) => a -> (Proof (IHType a) -> IHArg a -> IStepArgs a t) -> Symbolic InductionStrategy
+
+-- | A class for doing generalized measure based strong inductive proofs.
+class SInductive a where
+   -- | Inductively prove a lemma, using measure based induction, using the default config.
+   -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
+   -- partial correctness is guaranteed if non-terminating functions are involved.
+   sInduct :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => String -> a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> TP (Proof a)
+
+   -- | Same as 'sInduct', but with the given solver configuration.
+   -- Inductive proofs over lists only hold for finite lists. We also assume that all functions involved are terminating. SBV does not prove termination, so only
+   -- partial correctness is guaranteed if non-terminating functions are involved.
+   sInductWith :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => SMTConfig -> String -> a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> TP (Proof a)
+
+   sInduct         nm p mhs steps = getTPConfig >>= \cfg  -> sInductWith                      cfg                   nm p mhs steps
+   sInductWith cfg nm p mhs steps = getTPConfig >>= \cfg' -> inductionEngine GeneralInduction (tpMergeCfg cfg cfg') nm p (sInductionStrategy p mhs steps)
+
+   -- | Internal, shouldn't be needed outside the library
+   {-# MINIMAL sInductionStrategy #-}
+   sInductionStrategy :: (Proposition a, Zero m, SymVal t, EqSymbolic (SBV t)) => a -> (MeasureArgs a m, [ProofObj]) -> (Proof a -> StepArgs a t) -> Symbolic InductionStrategy
+
+-- | Do an inductive proof, based on the given strategy
+inductionEngine :: Proposition a => InductionStyle -> SMTConfig -> String -> a -> Symbolic InductionStrategy -> TP (Proof a)
+inductionEngine style cfg nm result getStrategy = do
+   cached <- lookupProofCache result
+   case cached of
+     Just prf -> returnCachedProof cfg nm prf
+     Nothing -> do
+       tpSt <- getTPState
+       u    <- tpGetNextUnique
+
+       proof <- liftIO $ runSMTWith cfg $ do
+
+          qSaturateSavingObservables result -- make sure we saturate the result, i.e., get all it's UI's, types etc. pop out
+
+          let qual = case style of
+                       RegularInduction -> ""
+                       GeneralInduction  -> " (strong)"
+
+          let header = "Inductive lemma" ++ qual ++ ": " ++ nm
+          message cfg $ header ++ "\n"
+          liftIO $ do isDry <- readIORef (dryRun tpSt)
+                      when isDry $ modifyIORef' (maxRibbon tpSt) (max (length header))
+
+          strategy@InductionStrategy { inductionIntros
+                                     , inductionMeasure
+                                     , inductionBaseCase
+                                     , inductionProofTree
+                                     , inductiveStep
+                                     , inductiveQCInstance
+                                     } <- getStrategy
+
+          mapM_ qSaturateSavingObservables $ getInductionStrategySaturatables strategy
+
+          -- Run measure checks for any newly encountered recursive functions
+          st <- symbolicEnv
+          liftIO $ do writeIORef (rSkipMeasureChecks st) True
+                      checkNewMeasures cfg st tpSt
+
+          query $ do
+
+           case inductionMeasure of
+              Nothing      -> queryDebug [T.pack nm <> ": Induction" <> T.pack qual <> ", there is no custom measure to show non-negativeness."]
+              Just (m, hs) -> do queryDebug [T.pack nm <> ": Induction, proving measure is always non-negative:"]
+                                 smtProofStep cfg tpSt "Step" 1
+                                                       (TPProofStep False nm [] ["Measure is non-negative"])
+                                                       (Just (sAnd (inductionIntros : map getObjProof hs)))
+                                                       m
+                                                       []
+                                                       (\d -> finishTP cfg "Q.E.D." d [])
+           case inductionBaseCase of
+              Nothing -> queryDebug [T.pack nm <> ": Induction" <> T.pack qual <> ", there is no base case to prove."]
+              Just bc -> do queryDebug [T.pack nm <> ": Induction, proving base case:"]
+                            smtProofStep cfg tpSt "Step" 1
+                                                  (TPProofStep False nm [] ["Base"])
+                                                  (Just inductionIntros)
+                                                  bc
+                                                  []
+                                                  (\d -> finishTP cfg "Q.E.D." d [])
+
+           proveProofTree cfg tpSt nm (result, inductiveStep) inductionIntros inductionProofTree u inductiveQCInstance
+
+       addToProofCache result (proofOf proof)
+       pure proof
+
+-- Induction strategy helper
+mkIndStrategy :: (SymVal a, EqSymbolic (SBV a)) => Maybe (SBool, [ProofObj]) -> Maybe SBool -> (SBool, TPProofRaw (SBV a)) -> SBool -> ([Int] -> Symbolic SBool) -> Symbolic InductionStrategy
+mkIndStrategy mbMeasure mbBaseCase indSteps step indQCInstance = do
+        CalcStrategy { calcIntros, calcProofTree, calcQCInstance } <- mkCalcSteps indSteps indQCInstance
+        pure $ InductionStrategy { inductionIntros     = calcIntros
+                                 , inductionMeasure    = mbMeasure
+                                 , inductionBaseCase   = mbBaseCase
+                                 , inductionProofTree  = calcProofTree
+                                 , inductiveStep       = step
+                                 , inductiveQCInstance = calcQCInstance
+                                 }
+
+-- | Create a new variable with the given name, return both the variable and the name
+mkVar :: (KnownSymbol n, SymVal a) => proxy n -> Symbolic (SBV a, String)
+mkVar x = do let nn = symbolVal x
+             n <- free nn
+             pure (n, nn)
+
+-- | Create a new variable with the given name, return both the variable and the name. List version.
+mkLVar :: (KnownSymbol n, SymVal a) => proxy n -> Symbolic (SBV a, SList a, String, String, String)
+mkLVar x = do let nxs = symbolVal x
+                  nx  = singular nxs
+              e  <- free nx
+              es <- free nxs
+              pure (e, es, nx, nxs, nx ++ ":" ++ nxs)
+
+-- | Helper for induction result
+indResult :: [String] -> SBool -> SBool
+indResult nms = observeIf not ("P(" ++ intercalate ", " nms ++ ")")
+
+-- | Induction over 'SInteger'
+instance KnownSymbol nn => Inductive (Forall nn Integer -> SBool) where
+  type IHType (Forall nn Integer -> SBool) = SBool
+  type IHArg  (Forall nn Integer -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+
+       let bc = result (Forall 0)
+           ih = internalAxiom "IH" (n .>= zero .=> result (Forall n))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n)
+                     (indResult [nn ++ "+1"] (result (Forall (n+1))))
+                     (\checkedLabel -> free nn >>= qcRun checkedLabel . steps ih)
+
+-- | Induction over 'SInteger', taking an extra argument
+instance (KnownSymbol nn, KnownSymbol na, SymVal a) => Inductive (Forall nn Integer -> Forall na a -> SBool) where
+  type IHType (Forall nn Integer -> Forall na a -> SBool) = Forall na a -> SBool
+  type IHArg  (Forall nn Integer -> Forall na a -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+       (a, na) <- mkVar (Proxy @na)
+
+       let bc = result (Forall 0) (Forall a)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) -> n .>= zero .=> result (Forall n) (Forall a'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n a)
+                     (indResult [nn ++ "+1", na] (result (Forall (n+1)) (Forall a)))
+                     (\checkedLabel -> steps ih <$> free nn <*> free na >>= qcRun checkedLabel)
+
+-- | Induction over 'SInteger', taking two extra arguments
+instance (KnownSymbol nn, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => Inductive (Forall nn Integer -> Forall na a -> Forall nb b -> SBool) where
+  type IHType (Forall nn Integer -> Forall na a -> Forall nb b -> SBool) = Forall na a -> Forall nb b -> SBool
+  type IHArg  (Forall nn Integer -> Forall na a -> Forall nb b -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+       (a, na) <- mkVar (Proxy @na)
+       (b, nb) <- mkVar (Proxy @nb)
+
+       let bc = result (Forall 0) (Forall a) (Forall b)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) -> n .>= zero .=> result (Forall n) (Forall a') (Forall b'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n a b)
+                     (indResult [nn ++ "+1", na, nb] (result (Forall (n+1)) (Forall a) (Forall b)))
+                     (\checkedLabel -> steps ih <$> free nn <*> free na <*> free nb >>= qcRun checkedLabel)
+
+-- | Induction over 'SInteger', taking three extra arguments
+instance (KnownSymbol nn, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => Inductive (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+  type IHType (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> SBool
+  type IHArg  (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+       (a, na) <- mkVar (Proxy @na)
+       (b, nb) <- mkVar (Proxy @nb)
+       (c, nc) <- mkVar (Proxy @nc)
+
+       let bc = result (Forall 0) (Forall a) (Forall b) (Forall c)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) -> n .>= zero .=> result (Forall n) (Forall a') (Forall b') (Forall c'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n a b c)
+                     (indResult [nn ++ "+1", na, nb, nc] (result (Forall (n+1)) (Forall a) (Forall b) (Forall c)))
+                     (\checkedLabel -> steps ih <$> free nn <*> free na <*> free nb <*> free nc >>= qcRun checkedLabel)
+
+-- | Induction over 'SInteger', taking four extra arguments
+instance (KnownSymbol nn, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => Inductive (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+  type IHType (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool
+  type IHArg  (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+       (a, na) <- mkVar (Proxy @na)
+       (b, nb) <- mkVar (Proxy @nb)
+       (c, nc) <- mkVar (Proxy @nc)
+       (d, nd) <- mkVar (Proxy @nd)
+
+       let bc = result (Forall 0) (Forall a) (Forall b) (Forall c) (Forall d)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) -> n .>= zero .=> result (Forall n) (Forall a') (Forall b') (Forall c') (Forall d'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n a b c d)
+                     (indResult [nn ++ "+1", na, nb, nc, nd] (result (Forall (n+1)) (Forall a) (Forall b) (Forall c) (Forall d)))
+                     (\checkedLabel -> steps ih <$> free nn <*> free na <*> free nb <*> free nc <*> free nd >>= qcRun checkedLabel)
+
+-- | Induction over 'SInteger', taking five extra arguments
+instance (KnownSymbol nn, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e) => Inductive (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+  type IHType (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool
+  type IHArg  (Forall nn Integer -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = SInteger
+
+  inductionStrategy result steps = do
+       (n, nn) <- mkVar (Proxy @nn)
+       (a, na) <- mkVar (Proxy @na)
+       (b, nb) <- mkVar (Proxy @nb)
+       (c, nc) <- mkVar (Proxy @nc)
+       (d, nd) <- mkVar (Proxy @nd)
+       (e, ne) <- mkVar (Proxy @ne)
+
+       let bc = result (Forall 0) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) (Forall e' :: Forall ne e) -> n .>= zero .=> result (Forall n) (Forall a') (Forall b') (Forall c') (Forall d') (Forall e'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih n a b c d e)
+                     (indResult [nn ++ "+1", na, nb, nc, nd, ne] (result (Forall (n+1)) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)))
+                     (\checkedLabel -> steps ih <$> free nn <*> free na <*> free nb <*> free nc <*> free nd <*> free ne >>= qcRun checkedLabel)
+
+-- Given a user name for the list, get a name for the element, in the most suggestive way possible
+--   xs  -> x
+--   xss -> xs
+--   foo -> fooElt
+singular :: String -> String
+singular n = case reverse n of
+               's':_:_ -> init n
+               _       -> n ++ "Elt"
+
+-- | Induction over 'SList'
+instance (KnownSymbol nxs, SymVal x) => Inductive (Forall nxs [x] -> SBool) where
+  type IHType (Forall nxs [x] -> SBool) = SBool
+  type IHArg  (Forall nxs [x] -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+
+       let bc = result (Forall [])
+           ih = internalAxiom "IH" (result (Forall xs))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs))
+                     (indResult [nxxs] (result (Forall (x SL..: xs))))
+                     (\checkedLabel ->  ((,) <$> free nx <*> free nxs) >>= qcRun checkedLabel . steps ih)
+
+-- | Induction over 'SList', taking an extra argument
+instance (KnownSymbol nxs, SymVal x, KnownSymbol na, SymVal a) => Inductive (Forall nxs [x] -> Forall na a -> SBool) where
+  type IHType (Forall nxs [x] -> Forall na a -> SBool) = Forall na a -> SBool
+  type IHArg  (Forall nxs [x] -> Forall na a -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (a, na)                <- mkVar  (Proxy @na)
+
+       let bc = result (Forall []) (Forall a)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) -> result (Forall xs) (Forall a'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs) a)
+                     (indResult [nxxs, na] (result (Forall (x SL..: xs)) (Forall a)))
+                     (\checkedLabel -> steps ih <$> ((,) <$> free nx <*> free nxs) <*> free na >>= qcRun checkedLabel)
+
+-- | Induction over 'SList', taking two extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => Inductive (Forall nxs [x] -> Forall na a -> Forall nb b -> SBool) where
+  type IHType (Forall nxs [x] -> Forall na a -> Forall nb b -> SBool) = Forall na a -> Forall nb b -> SBool
+  type IHArg  (Forall nxs [x] -> Forall na a -> Forall nb b -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+
+       let bc = result (Forall []) (Forall a) (Forall b)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) -> result (Forall xs) (Forall a') (Forall b'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs) a b)
+                     (indResult [nxxs, na, nb] (result (Forall (x SL..: xs)) (Forall a) (Forall b)))
+                     (\checkedLabel -> steps ih <$> ((,) <$> free nx <*> free nxs) <*> free na <*> free nb >>= qcRun checkedLabel)
+
+-- | Induction over 'SList', taking three extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => Inductive (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+  type IHType (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> SBool
+  type IHArg  (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+
+       let bc = result (Forall []) (Forall a) (Forall b) (Forall c)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) -> result (Forall xs) (Forall a') (Forall b') (Forall c'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs) a b c)
+                     (indResult [nxxs, na, nb, nc] (result (Forall (x SL..: xs)) (Forall a) (Forall b) (Forall c)))
+                     (\checkedLabel -> steps ih <$> ((,) <$> free nx <*> free nxs) <*> free na <*> free nb <*> free nc >>= qcRun checkedLabel)
+
+-- | Induction over 'SList', taking four extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => Inductive (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+  type IHType (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool
+  type IHArg  (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+       (d, nd)                <- mkVar  (Proxy @nd)
+
+       let bc = result (Forall []) (Forall a) (Forall b) (Forall c) (Forall d)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) -> result (Forall xs) (Forall a') (Forall b') (Forall c') (Forall d'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs) a b c d)
+                     (indResult [nxxs, na, nb, nc, nd] (result (Forall (x SL..: xs)) (Forall a) (Forall b) (Forall c) (Forall d)))
+                     (\checkedLabel -> steps ih <$> ((,) <$> free nx <*> free nxs) <*> free na <*> free nb <*> free nc <*> free nd >>= qcRun checkedLabel)
+
+-- | Induction over 'SList', taking five extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e) => Inductive (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+  type IHType (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool
+  type IHArg  (Forall nxs [x] -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = (SBV x, SList x)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+       (d, nd)                <- mkVar  (Proxy @nd)
+       (e, ne)                <- mkVar  (Proxy @ne)
+
+       let bc = result (Forall []) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) (Forall e' :: Forall ne e) -> result (Forall xs) (Forall a') (Forall b') (Forall c') (Forall d') (Forall e'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs) a b c d e)
+                     (indResult [nxxs, na, nb, nc, nd, ne] (result (Forall (x SL..: xs)) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)))
+                     (\checkedLabel -> steps ih <$> ((,) <$> free nx <*> free nxs) <*> free na <*> free nb <*> free nc <*> free nd <*> free ne >>= qcRun checkedLabel)
+
+-- | Induction over two 'SList', simultaneously
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y) => Inductive ((Forall nxs [x], Forall nys [y]) -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> SBool) = SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+
+       let bc = result (Forall [], Forall []) .&& result (Forall [], Forall (y SL..: ys)) .&& result (Forall (x SL..: xs), Forall [])
+           ih = internalAxiom "IH" (result (Forall xs, Forall ys))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys))
+                     (indResult [nxxs, nyys] (result (Forall (x SL..: xs), Forall (y SL..: ys))))
+                     (\checkedLabel -> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) >>= qcRun checkedLabel . steps ih)
+
+-- | Induction over two 'SList', simultaneously, taking an extra argument
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y, KnownSymbol na, SymVal a) => Inductive ((Forall nxs [x], Forall nys [y]) -> Forall na a -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> Forall na a -> SBool) = Forall na a -> SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> Forall na a -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+       (a, na)                <- mkVar  (Proxy @na)
+
+       let bc = result (Forall [], Forall []) (Forall a) .&& result (Forall [], Forall (y SL..: ys)) (Forall a) .&& result (Forall (x SL..: xs), Forall []) (Forall a)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) -> result (Forall xs, Forall ys) (Forall a'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys) a)
+                     (indResult [nxxs, nyys, na] (result (Forall (x SL..: xs), Forall (y SL..: ys)) (Forall a)))
+                     (\checkedLabel -> steps ih <$> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) <*> free na >>= qcRun checkedLabel)
+
+-- | Induction over two 'SList', simultaneously, taking two extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => Inductive ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> SBool) = Forall na a -> Forall nb b -> SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+
+       let bc = result (Forall [], Forall []) (Forall a) (Forall b) .&& result (Forall [], Forall (y SL..: ys)) (Forall a) (Forall b) .&& result (Forall (x SL..: xs), Forall []) (Forall a) (Forall b)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) -> result (Forall xs, Forall ys) (Forall a') (Forall b'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys) a b)
+                     (indResult [nxxs, nyys, na, nb] (result (Forall (x SL..: xs), Forall (y SL..: ys)) (Forall a) (Forall b)))
+                     (\checkedLabel -> steps ih <$> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) <*> free na <*> free nb >>= qcRun checkedLabel)
+
+-- | Induction over two 'SList', simultaneously, taking three extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => Inductive ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+
+       let bc = result (Forall [], Forall []) (Forall a) (Forall b) (Forall c) .&& result (Forall [], Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c) .&& result (Forall (x SL..: xs), Forall []) (Forall a) (Forall b) (Forall c)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) -> result (Forall xs, Forall ys) (Forall a') (Forall b') (Forall c'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys) a b c)
+                     (indResult [nxxs, nyys, na, nb, nc] (result (Forall (x SL..: xs), Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c)))
+                     (\checkedLabel -> steps ih <$> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) <*> free na <*> free nb <*> free nc >>= qcRun checkedLabel)
+
+-- | Induction over two 'SList', simultaneously, taking four extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => Inductive ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+       (d, nd)                <- mkVar  (Proxy @nd)
+
+       let bc = result (Forall [], Forall []) (Forall a) (Forall b) (Forall c) (Forall d) .&& result (Forall [], Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c) (Forall d) .&& result (Forall (x SL..: xs), Forall []) (Forall a) (Forall b) (Forall c) (Forall d)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) -> result (Forall xs, Forall ys) (Forall a') (Forall b') (Forall c') (Forall d'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys) a b c d)
+                     (indResult [nxxs, nyys, na, nb, nc, nd] (result (Forall (x SL..: xs), Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c) (Forall d)))
+                     (\checkedLabel -> steps ih <$> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) <*> free na <*> free nb <*> free nc <*> free nd >>= qcRun checkedLabel)
+
+-- | Induction over two 'SList', simultaneously, taking five extra arguments
+instance (KnownSymbol nxs, SymVal x, KnownSymbol nys, SymVal y, KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e) => Inductive ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+  type IHType ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool
+  type IHArg  ((Forall nxs [x], Forall nys [y]) -> Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = (SBV x, SList x, SBV y, SList y)
+
+  inductionStrategy result steps = do
+       (x, xs, nx, nxs, nxxs) <- mkLVar (Proxy @nxs)
+       (y, ys, ny, nys, nyys) <- mkLVar (Proxy @nys)
+       (a, na)                <- mkVar  (Proxy @na)
+       (b, nb)                <- mkVar  (Proxy @nb)
+       (c, nc)                <- mkVar  (Proxy @nc)
+       (d, nd)                <- mkVar  (Proxy @nd)
+       (e, ne)                <- mkVar  (Proxy @ne)
+
+       let bc = result (Forall [], Forall []) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) .&& result (Forall [], Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e) .&& result (Forall (x SL..: xs), Forall []) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+           ih = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) (Forall e' :: Forall ne e) -> result (Forall xs, Forall ys) (Forall a') (Forall b') (Forall c') (Forall d') (Forall e'))
+
+       mkIndStrategy Nothing
+                     (Just bc)
+                     (steps ih (x, xs, y, ys) a b c d e)
+                     (indResult [nxxs, nyys, na, nb, nc, nd, ne] (result (Forall (x SL..: xs), Forall (y SL..: ys)) (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)))
+                     (\checkedLabel -> steps ih <$> ((,,,) <$> free nx <*> free nxs <*> free ny <*> free nys) <*> free na <*> free nb <*> free nc <*> free nd <*> free ne >>= qcRun checkedLabel)
+
+-- | Generalized induction with one parameter
+instance (KnownSymbol na, SymVal a) => SInductive (Forall na a -> SBool) where
+  sInductionStrategy result (measure, helpers) steps = do
+      (a, na) <- mkVar (Proxy @na)
+
+      let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) -> measure a' .< measure a .=> result (Forall a'))
+          conc = result (Forall a)
+
+      mkIndStrategy (Just (nonNeg (measure a), helpers))
+                    Nothing
+                    (steps ih a)
+                    (indResult [na] conc)
+                    (\checkedLabel -> free na >>= qcRun checkedLabel . steps ih)
+
+-- | Generalized induction with two parameters
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b) => SInductive (Forall na a -> Forall nb b -> SBool) where
+  sInductionStrategy result (measure, helpers) steps = do
+      (a, na) <- mkVar (Proxy @na)
+      (b, nb) <- mkVar (Proxy @nb)
+
+      let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) -> measure a' b' .< measure a b .=> result (Forall a') (Forall b'))
+          conc = result (Forall a) (Forall b)
+
+      mkIndStrategy (Just (nonNeg (measure a b), helpers))
+                    Nothing
+                    (steps ih a b)
+                    (indResult [na, nb] conc)
+                    (\checkedLabel -> steps ih <$> free na <*> free nb >>= qcRun checkedLabel)
+
+-- | Generalized induction with three parameters
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+  sInductionStrategy result (measure, helpers) steps = do
+      (a, na) <- mkVar (Proxy @na)
+      (b, nb) <- mkVar (Proxy @nb)
+      (c, nc) <- mkVar (Proxy @nc)
+
+      let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) -> measure a' b' c' .< measure a b c .=> result (Forall a') (Forall b') (Forall c'))
+          conc = result (Forall a) (Forall b) (Forall c)
+
+      mkIndStrategy (Just (nonNeg (measure a b c), helpers))
+                    Nothing
+                    (steps ih a b c)
+                    (indResult [na, nb, nc] conc)
+                    (\checkedLabel -> steps ih <$> free na <*> free nb <*> free nc >>= qcRun checkedLabel)
+
+-- | Generalized induction with four parameters
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+  sInductionStrategy result (measure, helpers) steps = do
+      (a, na) <- mkVar (Proxy @na)
+      (b, nb) <- mkVar (Proxy @nb)
+      (c, nc) <- mkVar (Proxy @nc)
+      (d, nd) <- mkVar (Proxy @nd)
+
+      let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) -> measure a' b' c' d' .< measure a b c d .=> result (Forall a') (Forall b') (Forall c') (Forall d'))
+          conc = result (Forall a) (Forall b) (Forall c) (Forall d)
+
+      mkIndStrategy (Just (nonNeg (measure a b c d), helpers))
+                    Nothing
+                    (steps ih a b c d)
+                    (indResult [na, nb, nc, nd] conc)
+                    (\checkedLabel -> steps ih <$> free na <*> free nb <*> free nc <*> free nd >>= qcRun checkedLabel)
+
+-- | Generalized induction with five parameters
+instance (KnownSymbol na, SymVal a, KnownSymbol nb, SymVal b, KnownSymbol nc, SymVal c, KnownSymbol nd, SymVal d, KnownSymbol ne, SymVal e) => SInductive (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+  sInductionStrategy result (measure, helpers) steps = do
+      (a, na) <- mkVar (Proxy @na)
+      (b, nb) <- mkVar (Proxy @nb)
+      (c, nc) <- mkVar (Proxy @nc)
+      (d, nd) <- mkVar (Proxy @nd)
+      (e, ne) <- mkVar (Proxy @ne)
+
+      let ih   = internalAxiom "IH" (\(Forall a' :: Forall na a) (Forall b' :: Forall nb b) (Forall c' :: Forall nc c) (Forall d' :: Forall nd d) (Forall e' :: Forall ne e) -> measure a' b' c' d' e' .< measure a b c d e .=> result (Forall a') (Forall b') (Forall c') (Forall d') (Forall e'))
+          conc = result (Forall a) (Forall b) (Forall c) (Forall d) (Forall e)
+
+      mkIndStrategy (Just (nonNeg (measure a b c d e), helpers))
+                    Nothing
+                    (steps ih a b c d e)
+                    (indResult [na, nb, nc, nd, ne] conc)
+                    (\checkedLabel -> steps ih <$> free na <*> free nb <*> free nc <*> free nd <*> free ne >>= qcRun checkedLabel)
+
+-- | Instantiation for a universally quantified variable
+newtype Inst (nm :: Symbol) a = Inst (SBV a)
+
+instance KnownSymbol nm => Show (Inst nm a) where
+   show (Inst a) = symbolVal (Proxy @nm) ++ " |-> " ++ show a
+
+-- | Instantiating a proof at a particular choice of arguments
+class Instantiatable a where
+  type IArgs a :: Type
+
+  -- | Apply a universal proof to some arguments, creating a boolean expression guaranteed to be true
+  at :: Proof a -> IArgs a -> Proof Bool
+
+-- | Instantiation a single parameter proof
+instance (KnownSymbol na, Typeable a) => Instantiatable (Forall na a -> SBool) where
+  type IArgs (Forall na a -> SBool) = Inst na a
+
+  at = instantiate $ \f (Inst a) -> f (Forall a :: Forall na a)
+
+-- | Two parameters
+instance ( KnownSymbol na, HasKind a, Typeable a
+         , KnownSymbol nb, HasKind b, Typeable b
+         ) => Instantiatable (Forall na a -> Forall nb b -> SBool) where
+  type IArgs (Forall na a -> Forall nb b -> SBool) = (Inst na a, Inst nb b)
+
+  at  = instantiate $ \f (Inst a, Inst b) -> f (Forall a :: Forall na a) (Forall b :: Forall nb b)
+
+-- | Three parameters
+instance ( KnownSymbol na, HasKind a, Typeable a
+         , KnownSymbol nb, HasKind b, Typeable b
+         , KnownSymbol nc, HasKind c, Typeable c
+         ) => Instantiatable (Forall na a -> Forall nb b -> Forall nc c -> SBool) where
+  type IArgs (Forall na a -> Forall nb b -> Forall nc c -> SBool) = (Inst na a, Inst nb b, Inst nc c)
+
+  at  = instantiate $ \f (Inst a, Inst b, Inst c) -> f (Forall a :: Forall na a) (Forall b :: Forall nb b) (Forall c :: Forall nc c)
+
+-- | Four parameters
+instance ( KnownSymbol na, HasKind a, Typeable a
+         , KnownSymbol nb, HasKind b, Typeable b
+         , KnownSymbol nc, HasKind c, Typeable c
+         , KnownSymbol nd, HasKind d, Typeable d
+         ) => Instantiatable (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) where
+  type IArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> SBool) = (Inst na a, Inst nb b, Inst nc c, Inst nd d)
+
+  at  = instantiate $ \f (Inst a, Inst b, Inst c, Inst d) -> f (Forall a :: Forall na a) (Forall b :: Forall nb b) (Forall c :: Forall nc c) (Forall d :: Forall nd d)
+
+-- | Five parameters
+instance ( KnownSymbol na, HasKind a, Typeable a
+         , KnownSymbol nb, HasKind b, Typeable b
+         , KnownSymbol nc, HasKind c, Typeable c
+         , KnownSymbol nd, HasKind d, Typeable d
+         , KnownSymbol ne, HasKind e, Typeable e
+         ) => Instantiatable (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) where
+  type IArgs (Forall na a -> Forall nb b -> Forall nc c -> Forall nd d -> Forall ne e -> SBool) = (Inst na a, Inst nb b, Inst nc c, Inst nd d, Inst ne e)
+
+  at  = instantiate $ \f (Inst a, Inst b, Inst c, Inst d, Inst e) -> f (Forall a :: Forall na a) (Forall b :: Forall nb b) (Forall c :: Forall nc c) (Forall d :: Forall nd d) (Forall e :: Forall ne e)
+
+-- | Instantiate a proof over an arg. This uses dynamic typing, kind of hacky, but works sufficiently well.
+instantiate :: (Typeable f, Show arg) => (f -> arg -> SBool) -> Proof a -> arg -> Proof Bool
+instantiate ap (Proof p@ProofObj{getProp, proofName}) a = case fromDynamic getProp of
+                                                            Nothing -> cantInstantiate
+                                                            Just f  -> let result = f `ap` a
+                                                                           nm     = proofName ++ " @ " ++ paren sha
+                                                                       in Proof $ p { getObjProof = label nm result
+                                                                                    , getProp     = toDyn result
+                                                                                    , proofName   = nm
+                                                                                    }
+ where sha = show a
+       cantInstantiate = error $ unlines [ "***"
+                                         , "Data.SBV.TP: Impossible happened: Cannot instantiate proof:"
+                                         , ""
+                                         , "   Name: " ++ proofName
+                                         , "   Type: " ++ trim (show getProp)
+                                         , "   At  : " ++ sha
+                                         , ""
+                                         , "Please report this as a bug!"
+                                         ]
+
+       -- dynamic puts funky <</>> at the beginning and end; trim it:
+       trim  ('<':'<':s) = reverse (trimE (reverse s))
+       trim  s           = s
+       trimE ('>':'>':s) = s
+       trimE s           = s
+
+       -- Add parens if necessary
+       paren s | "(" `isPrefixOf` s && ")" `isSuffixOf` s = s
+               | not (any isSpace s)                      = s
+               | True                                     = '(' : s ++ ")"
+
+-- | Helpers for a step
+data Helper = HelperProof  ProofObj     -- A previously proven theorem
+            | HelperAssum  SBool        -- A hypothesis
+            | HelperQC     QC.Args      -- Quickcheck with these args
+            | HelperString String       -- Just a text, only used for diagnostics
+            | HelperDisp   String SVal  -- Show the value of this expression in case of failure
+
+-- | Get all helpers used in a proof
+getAllHelpers :: TPProof -> [Helper]
+getAllHelpers (ProofStep   _           hs               p)  = hs ++ getAllHelpers p
+getAllHelpers (ProofBranch (_ :: Bool) (_ :: [String]) ps) = concatMap (getAllHelpers . snd) ps
+getAllHelpers (ProofEnd    _           hs                ) = hs
+
+-- | Get proofs from helpers
+getHelperProofs :: Helper -> [ProofObj]
+getHelperProofs (HelperProof p) = [p]
+getHelperProofs HelperAssum {}  = []
+getHelperProofs HelperQC    {}  = [quickCheckProof]
+getHelperProofs HelperString{}  = []
+getHelperProofs HelperDisp{}    = []
+
+-- | Get proofs from helpers
+getHelperAssumes :: Helper -> [SBool]
+getHelperAssumes HelperProof  {} = []
+getHelperAssumes (HelperAssum b) = [b]
+getHelperAssumes HelperQC     {} = []
+getHelperAssumes HelperString {} = []
+getHelperAssumes HelperDisp{}    = []
+
+-- | Get hint strings from helpers. If there's an explicit comment given, just pass that. If not, collect all the names
+getHelperText :: [Helper] -> [String]
+getHelperText hs = case [s | HelperString s <- hs] of
+                     [] -> concatMap collect hs
+                     ss -> ss
+  where collect :: Helper -> [String]
+        collect (HelperProof  p) = [proofName p | isUserAxiom p]  -- Don't put out internals (inductive hypotheses)
+        collect HelperAssum  {}  = []
+        collect (HelperQC     i) = ["qc: Running " ++ show (QC.maxSuccess i) ++ " tests"]
+        collect (HelperString s) = [s]
+        collect HelperDisp{}     = []
+
+-- | A proof is a sequence of steps, supporting branching
+data TPProofGen a bh b = ProofStep   a    [Helper] (TPProofGen a bh b)          -- ^ A single step
+                       | ProofBranch Bool bh       [(SBool, TPProofGen a bh b)] -- ^ A branching step. Bool indicates if completeness check is needed
+                       | ProofEnd    b    [Helper]                              -- ^ End of proof
+
+-- | A proof, as written by the user. No produced result, but helpers on branches
+type TPProofRaw a = TPProofGen a [Helper] ()
+
+-- | A proof, as processed by TP. Producing a boolean result and each step is a boolean. Helpers on branches dispersed down, only strings are left for printing
+type TPProof = TPProofGen SBool [String] SBool
+
+-- | Collect dependencies for a TPProof
+getDependencies :: TPProof -> [ProofObj]
+getDependencies = collect
+  where collect (ProofStep   _ hs next) = concatMap getHelperProofs hs ++ collect next
+        collect (ProofBranch _ _  bs)   = concatMap (collect . snd) bs
+        collect (ProofEnd    _    hs)   = concatMap getHelperProofs hs
+
+-- | Class capturing giving a proof-step helper
+type family Hinted a where
+  Hinted (TPProofRaw a) = TPProofRaw a
+  Hinted a              = TPProofRaw a
+
+-- | Attaching a hint
+(??) :: HintsTo a b => a -> b -> Hinted a
+(??) = addHint
+infixl 2 ??
+
+-- | Alternative unicode for `??`.
+(∵) :: HintsTo a b => a -> b -> Hinted a
+(∵) = (??)
+infixl 2 ∵
+
+-- | Class capturing hints
+class HintsTo a b where
+  addHint :: a -> b -> Hinted a
+
+-- | Giving just one proof as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a (Proof b) where
+  a `addHint` p = ProofStep a [HelperProof (proofOf p)] qed
+
+-- | Giving a bunch of proofs at the same type as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a [Proof b] where
+  a `addHint` ps = ProofStep a (map (HelperProof . proofOf) ps) qed
+
+-- | Giving just one proof-obj as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a ProofObj where
+  a `addHint` p = ProofStep a [HelperProof p] qed
+
+-- | Giving a bunch of proof-objs at the same type as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a [ProofObj] where
+  a `addHint` ps = ProofStep a (map HelperProof ps) qed
+
+-- | Giving just one boolean as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a SBool where
+  a `addHint` p = ProofStep a [HelperAssum p] qed
+
+-- | Giving a list of booleans as a helper.
+instance Hinted a ~ TPProofRaw a => HintsTo a [SBool] where
+  a `addHint` ps = ProofStep a (map HelperAssum ps) qed
+
+-- | Giving just one helper
+instance Hinted a ~ TPProofRaw a => HintsTo a Helper where
+  a `addHint` h = ProofStep a [h] qed
+
+-- | Giving a list of helper
+instance Hinted a ~ TPProofRaw a => HintsTo a [Helper] where
+  a `addHint` hs = ProofStep a hs qed
+
+-- | Giving user a hint as a string. This doesn't actually do anything for the solver, it just helps with readability
+instance Hinted a ~ TPProofRaw a => HintsTo a String where
+  a `addHint` s = ProofStep a [HelperString s] qed
+
+-- | Giving a bunch of strings
+instance Hinted a ~ TPProofRaw a => HintsTo a [String] where
+  a `addHint` ss = ProofStep a (map HelperString ss) qed
+
+-- | Giving just one proof as a helper, starting from a proof
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) (Proof b) where
+  ProofStep   a hs ps `addHint` h = ProofStep   a (hs ++ [HelperProof (proofOf h)]) ps
+  ProofBranch b hs bs `addHint` h = ProofBranch b (hs ++ [HelperProof (proofOf h)]) bs
+  ProofEnd    b hs    `addHint` h = ProofEnd    b (hs ++ [HelperProof (proofOf h)])
+
+-- | Giving just one proofobj as a helper, starting from a proof
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) ProofObj where
+  ProofStep   a hs ps `addHint` h = ProofStep   a (hs ++ [HelperProof h]) ps
+  ProofBranch b hs bs `addHint` h = ProofBranch b (hs ++ [HelperProof h]) bs
+  ProofEnd    b hs    `addHint` h = ProofEnd    b (hs ++ [HelperProof h])
+
+-- | Giving a bunch of proofs at the same type as a helper, starting from a proof
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) [Proof b] where
+  ProofStep   a hs ps `addHint` hs' = ProofStep   a (hs ++ map (HelperProof . proofOf) hs') ps
+  ProofBranch b hs bs `addHint` hs' = ProofBranch b (hs ++ map (HelperProof . proofOf) hs') bs
+  ProofEnd    b hs    `addHint` hs' = ProofEnd    b (hs ++ map (HelperProof . proofOf) hs')
+
+-- | Giving just one boolean as a helper.
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) SBool where
+  ProofStep   a hs ps `addHint` h = ProofStep   a (hs ++ [HelperAssum h]) ps
+  ProofBranch b hs bs `addHint` h = ProofBranch b (hs ++ [HelperAssum h]) bs
+  ProofEnd    b hs    `addHint` h = ProofEnd    b (hs ++ [HelperAssum h])
+
+-- | Giving a bunch of booleans as a helper.
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) [SBool] where
+  ProofStep   a hs ps `addHint` hs' = ProofStep   a (hs ++ map HelperAssum hs') ps
+  ProofBranch b hs bs `addHint` hs' = ProofBranch b (hs ++ map HelperAssum hs') bs
+  ProofEnd    b hs    `addHint` hs' = ProofEnd    b (hs ++ map HelperAssum hs')
+
+-- | Giving just one helper
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) Helper where
+  ProofStep   a hs ps `addHint` h = ProofStep   a (hs ++ [h]) ps
+  ProofBranch b hs bs `addHint` h = ProofBranch b (hs ++ [h]) bs
+  ProofEnd    b hs    `addHint` h = ProofEnd    b (hs ++ [h])
+
+-- | Giving a set of helpers
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) [Helper] where
+  ProofStep   a hs ps `addHint` hs' = ProofStep   a (hs ++ hs') ps
+  ProofBranch b hs bs `addHint` hs' = ProofBranch b (hs ++ hs') bs
+  ProofEnd    b hs    `addHint` hs' = ProofEnd    b (hs ++ hs')
+
+-- | Giving user a hint as a string. This doesn't actually do anything for the solver, it just helps with readability
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) String where
+  a `addHint` s = a `addHint` HelperString s
+
+-- | Giving a bunch of strings as hints. This doesn't actually do anything for the solver, it just helps with readability
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) [String] where
+  a `addHint` ss = a `addHint` map HelperString ss
+
+-- | Giving a set of proof objects as helpers. This is helpful since we occasionally put a bunch of proofs together.
+instance {-# OVERLAPPING #-} Hinted (TPProofRaw a) ~ TPProofRaw a => HintsTo (TPProofRaw a) [ProofObj] where
+  ProofStep   a hs ps `addHint` hs' = ProofStep   a (hs ++ map HelperProof hs') ps
+  ProofBranch b hs bs `addHint` hs' = ProofBranch b (hs ++ map HelperProof hs') bs
+  ProofEnd    b hs    `addHint` hs' = ProofEnd    b (hs ++ map HelperProof hs')
+
+-- | Capture what a given step can chain-to. This is a closed-type family, i.e.,
+-- we don't allow users to change this and write other chainable things. Probably it is not really necessary,
+-- but we'll cross that bridge if someone actually asks for it.
+type family ChainsTo a where
+  ChainsTo (TPProofRaw a) = TPProofRaw a
+  ChainsTo a              = TPProofRaw a
+
+-- | Chain steps in a calculational proof.
+(=:) :: ChainStep a (ChainsTo a) =>  a -> ChainsTo a -> ChainsTo a
+(=:) = chain
+infixr 1 =:
+
+-- | Unicode alternative for `=:`.
+(≡) :: ChainStep a (ChainsTo a) =>  a -> ChainsTo a -> ChainsTo a
+(≡) = (=:)
+infixr 1 ≡
+
+-- | Chaining two steps together
+class ChainStep a b where
+  chain :: a -> b -> b
+
+-- | Chaining from a value without any annotation
+instance ChainStep a (TPProofRaw a) where
+  chain x y = ProofStep x [] y
+
+-- | Chaining from another proof step
+instance ChainStep (TPProofRaw a) (TPProofRaw a) where
+  chain (ProofStep   a  hs  p)  y = ProofStep   a hs (chain p y)
+  chain (ProofBranch c  hs  ps) y = ProofBranch c hs [(branchCond, chain p y) | (branchCond, p) <- ps]
+  chain (ProofEnd    () hs)     y = case y of
+                                      ProofStep   a  hs' p  -> ProofStep   a  (hs' ++ hs) p
+                                      ProofBranch b  hs' bs -> ProofBranch b  (hs' ++ hs) bs
+                                      ProofEnd    () hs'    -> ProofEnd    () (hs' ++ hs)
+
+-- | Mark the end of a calculational proof.
+qed :: TPProofRaw a
+qed = ProofEnd () []
+
+-- | Mark a trivial proof. This is essentially the same as 'qed', but reads better in proof scripts.
+class Trivial a where
+  -- | Mark a proof as trivial, i.e., the solver should be able to deduce it without any help.
+  trivial :: a
+
+-- | Trivial proofs with no arguments
+instance Trivial (TPProofRaw a) where
+  trivial = qed
+
+-- | Trivial proofs with many arguments arguments
+instance Trivial a => Trivial (b -> a) where
+  trivial = const trivial
+
+-- | Mark a contradictory proof path. This is essentially the same as @sFalse := qed@, but reads better in proof scripts.
+class Contradiction a where
+  -- | Mark a proof as contradiction, i.e., the solver should be able to conclude it by reasoning that the current path is infeasible
+  contradiction :: a
+
+-- | Contradiction proofs with no arguments
+instance Contradiction (TPProofRaw SBool) where
+  contradiction = sFalse =: qed
+
+-- | Contradiction proofs with many arguments
+instance Contradiction a => Contradiction (b -> a) where
+  contradiction = const contradiction
+
+-- | Start a calculational proof, with the given hypothesis. Use @[]@ as the
+-- first argument if the calculation holds unconditionally. The first argument is
+-- typically used to introduce hypotheses in proofs of implications such as @A .=> B .=> C@, where
+-- we would put @[A, B]@ as the starting assumption. You can name these and later use in the derivation steps.
+(|-) :: [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
+bs |- p = (sAnd bs, p)
+infixl 0 |-
+
+-- | Start an implicational  proof, with the given hypothesis. Use @[]@ as the
+-- first argument if the calculation holds unconditionally. Each step will be a cascading
+-- chain of conjunctions of the previous, starting from @sTrue@.
+(|->) :: [SBool] -> TPProofRaw SBool -> (SBool, TPProofRaw SBool)
+bs |-> p = (sAnd bs, xform sTrue p)
+  where xform :: SBool -> TPProofGen SBool [Helper] () -> TPProofGen SBool [Helper] ()
+        xform conj (ProofStep   a hs r)  = let ca = conj .&& a in ProofStep ca hs (xform ca r)
+        xform conj (ProofBranch b bh ss) = ProofBranch b bh [(bc, xform conj r) | (bc, r) <- ss]
+        xform _    (ProofEnd    b hs )   = ProofEnd b hs
+infixl 0 |->
+
+-- | Alternative unicode for `|-`.
+(⊢) :: [SBool] -> TPProofRaw a -> (SBool, TPProofRaw a)
+(⊢) = (|-)
+infixl 0 ⊢
+
+-- | The boolean case-split
+cases :: [(SBool, TPProofRaw a)] -> TPProofRaw a
+cases = ProofBranch True []
+
+-- | Case splitting over a list; empty and full cases
+split :: SymVal a => SList a -> TPProofRaw r -> (SBV a -> SList a -> TPProofRaw r) -> TPProofRaw r
+split xs empty cons = ProofBranch False [] [(cnil, empty), (ccons, cons h t)]
+   where cnil   = SL.null   xs
+         (h, t) = SL.uncons xs
+         ccons  = sNot cnil .&& xs .=== h SL..: t
+
+-- | Case splitting over two lists; empty and full cases for each
+split2 :: (SymVal a, SymVal b)
+       => (SList a, SList b)
+       -> TPProofRaw r
+       -> ((SBV b, SList b)                     -> TPProofRaw r) -- empty first
+       -> ((SBV a, SList a)                     -> TPProofRaw r) -- empty second
+       -> ((SBV a, SList a) -> (SBV b, SList b) -> TPProofRaw r) -- neither empty
+       -> TPProofRaw r
+split2 (xs, ys) ee ec ce cc = ProofBranch False
+                                          []
+                                          [ (xnil  .&& ynil,  ee)
+                                          , (xnil  .&& ycons, ec (hy, ty))
+                                          , (xcons .&& ynil,  ce (hx, tx))
+                                          , (xcons .&& ycons, cc (hx, tx) (hy, ty))
+                                          ]
+  where xnil     = SL.null   xs
+        (hx, tx) = SL.uncons xs
+        xcons    = sNot xnil .&& xs .=== hx SL..: tx
+
+        ynil     = SL.null   ys
+        (hy, ty) = SL.uncons ys
+        ycons    = sNot ynil .&& ys .=== hy SL..: ty
+
+-- | A quick-check step, taking number of tests.
+qc :: Int -> Helper
+qc cnt = HelperQC QC.stdArgs{QC.maxSuccess = cnt}
+
+-- | A quick-check step, with specific quick-check args.
+qcWith :: QC.Args -> Helper
+qcWith = HelperQC
+
+-- | Observing values in case of failure.
+disp :: String -> SBV a -> Helper
+disp n v = HelperDisp n (unSBV v)
+
+-- | Specifying a case-split, helps with the boolean case.
+(==>) :: SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
+(==>) = (,)
+infix 0 ==>
+
+-- | Alternative unicode for `==>`
+(⟹) :: SBool -> TPProofRaw a -> (SBool, TPProofRaw a)
+(⟹) = (==>)
+infix 0 ⟹
+
+-- | Recalling a proof. If the proposition was previously proved and cached, the cached result
+-- is returned without re-proving. The output is kept brief: a single "Q.E.D." line.
+-- If stats mode is on, we show the full proof steps as the point of stats is to see detail.
+recall :: TP (Proof a) -> TP (Proof a)
+recall prf = getTPConfig >>= \cfg -> recallWith cfg prf
+
+-- | Recalling a proof, using a given config. Sets the recall context flag so that
+-- proof engines check the cache before proving.
+recallWith :: SMTConfig -> TP (Proof a) -> TP (Proof a)
+recallWith cfgIn prf = do
+  topCfg <- getTPConfig
+  tpSt   <- getTPState
+  let cfg@SMTConfig{tpOptions = TPOptions{printStats}} = cfgIn `tpMergeCfg` topCfg
+  -- Set recall context so proof engines check the cache
+  liftIO $ modifyIORef' (inRecallContext tpSt) (+1)
+  let cleanup = liftIO $ modifyIORef' (inRecallContext tpSt) (subtract 1)
+  if printStats
+     then restoring cfg topCfg $ do r <- prf
+                                    cleanup
+                                    pure r
+     else do let new = cfg{tpOptions = (tpOptions cfg) {quiet = True}}
+             restoring new topCfg $ do
+                 res <- tryTP prf
+                 cleanup
+                 case res of
+                   Left (_ :: SomeException) ->
+                     -- Re-run with original config so failure details are visible
+                     restoring cfg topCfg prf >> pure (error "unreachable")
+                   Right r@Proof{proofOf = po@ProofObj{dependencies, aliases = aka, wasCached = cached}} -> do
+                     let nm = proofName po
+                     liftIO $ printLemmaResult cfg (verbose cfg) nm dependencies cached aka
+                     pure r
+ where restoring new old act = do setTPConfig new
+                                  res <- act
+                                  setTPConfig old
+                                  pure res
+
+{- HLint ignore module "Eta reduce"         -}
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/TP/Utils.hs b/Data/SBV/TP/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/TP/Utils.hs
@@ -0,0 +1,707 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.TP.Utils
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Various theorem-proving machinery.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds                  #-}
+{-# LANGUAGE DeriveAnyClass             #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE DerivingStrategies         #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE NamedFieldPuns             #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+{-# LANGUAGE TupleSections              #-}
+{-# LANGUAGE TypeAbstractions           #-}
+{-# LANGUAGE TypeApplications           #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.TP.Utils (
+         TP, runTP, runTPWith, tryTP, whenDryRun, unlessDryRun, Proof(..), ProofObj(..), assumptionFromProof, sorry, quickCheckProof, noTermCheckProof
+       , startTP, finishTP, getTPState, getTPConfig, setTPConfig, tpGetNextUnique, TPState(..), TPStats(..), RootOfTrust(..)
+       , TPProofContext(..), message, updStats, rootOfTrust, concludeModulo, printLemmaResult
+       , ProofTree(..), TPUnique(..), showProofTree, showProofTreeHTML
+       , addToProofCache, lookupProofCache, returnCachedProof
+       , tpQuiet, tpAsms, tpStats
+       , measureLemma, measureLemmaWith
+       ) where
+
+import Control.Exception    (Exception, try)
+import Control.Monad        (unless, when)
+import Control.Monad.Reader (ReaderT(..), runReaderT, MonadReader, ask, liftIO)
+import Control.Monad.Trans  (MonadIO)
+
+import Data.Generics (everywhere, mkT)
+
+import Data.Time (NominalDiffTime)
+
+import Data.Tree
+import Data.Tree.View
+
+import Data.Proxy
+import Data.Typeable (typeOf, TypeRep)
+
+import Data.Char (isSpace)
+import Data.List (intercalate, isPrefixOf, isSuffixOf, isInfixOf, nub, sort, dropWhileEnd)
+import Data.Int  (Int64)
+
+import Data.SBV.Utils.Lib (unQuote)
+
+import System.IO     (hFlush, stdout)
+import System.Random (randomIO)
+
+import Data.SBV.Core.Data      (SBool, sTrue, Forall(..), QuantifiedBool, quantifiedBool, SBV(..), SV(..), NodeId(..), SBVExpr(..), SBVPgm(..), Op(..), CV(..))
+import Data.SBV.Core.Model     (label, MeasureHelper(..))
+import Data.SBV.Core.Symbolic  (SMTConfig, TPOptions(..), State(..), mkNewState, svToSV, SBVRunMode(..), globalSBVContext)
+import Data.SBV.Provers.Prover (defaultSMTCfg, SMTConfig(..))
+
+import Data.SBV.Utils.TDiff (showTDiff, timeIf)
+import Control.DeepSeq (NFData(rnf))
+
+import Data.Foldable (toList)
+import Data.IORef
+
+import GHC.Generics
+import Data.Dynamic
+
+import qualified Data.Map.Strict as Map
+
+import qualified Data.Set as Set
+import Data.Set (Set)
+
+-- | Various statistics we collect
+data TPStats = TPStats { noOfCheckSats :: !Int
+                       , solverElapsed :: !NominalDiffTime
+                       , qcElapsed     :: !NominalDiffTime
+                       }
+
+-- | Extra state we carry in a TP context
+data TPState = TPState { stats               :: IORef TPStats
+                       , proofCache          :: IORef (Map.Map (PropFingerprint, TypeRep) [ProofObj])
+                       , config              :: IORef SMTConfig
+                       , inRecallContext     :: IORef Int
+                       , measuresVerified    :: IORef (Set String)
+                       , productiveVerified  :: IORef (Set String)
+                       , measuresEncountered :: IORef (Set String)
+                       , dryRun              :: IORef Bool    -- ^ If True, collecting ribbon widths (no proving)
+                       , maxRibbon           :: IORef Int     -- ^ Session-wide maximum ribbon length
+                       }
+
+-- | Monad for running TP proofs in.
+newtype TP a = TP (ReaderT TPState IO a)
+            deriving newtype (Applicative, Functor, Monad, MonadIO, MonadReader TPState, MonadFail)
+
+-- | Run a TP action, catching exceptions.
+tryTP :: Exception e => TP a -> TP (Either e a)
+tryTP (TP act) = TP $ ReaderT $ \st -> try (runReaderT act st)
+
+-- | Run an action only during the dry-run pass.
+whenDryRun :: TP () -> TP ()
+whenDryRun act = do st <- ask
+                    isDry <- liftIO $ readIORef (dryRun st)
+                    when isDry act
+
+-- | Run an action only during the real (non-dry-run) pass. Useful for guarding user-facing output
+-- (e.g., proof tree printing) that should be suppressed during ribbon calculation.
+unlessDryRun :: TP () -> TP ()
+unlessDryRun act = do st <- ask
+                      isDry <- liftIO $ readIORef (dryRun st)
+                      unless isDry act
+
+-- | Extract the integer node ID from an SV.
+svIntId :: SV -> Int
+svIntId (SV _ (NodeId (_, _, i))) = i
+
+-- | Zero out the SBVContext in an SV, keeping only the kind and integer node ID.
+-- Used to normalize 'Op' values for fingerprinting.
+zeroSV :: SV -> SV
+zeroSV (SV k (NodeId (_, mb, i))) = SV k (NodeId (globalSBVContext, mb, i))
+
+-- | Zero out all embedded SBVContext values inside an 'Op' using SYB generic traversal.
+-- This automatically handles all current and future Op constructors that embed SV's.
+zeroContextInOp :: Op -> Op
+zeroContextInOp = everywhere (mkT zeroSV)
+
+-- | Fingerprint of a proposition's symbolic expression DAG.
+-- Computed by evaluating 'quantifiedBool' in a fresh State and extracting
+-- the expression program (with embedded SV contexts zeroed out via SYB),
+-- the constant map (mapping constant values to their SV int IDs), and the final result SV.
+-- Two identical propositions evaluated in identically-initialized States produce
+-- identical fingerprints. Different propositions diverge somewhere in variable creation,
+-- expression construction, or hash-consing, producing different fingerprints.
+newtype PropFingerprint = PropFingerprint ([(CV, Int)], [(Int, Op, [Int])], Int)
+  deriving (Eq, Ord)
+
+-- | Compute the fingerprint of a proposition by evaluating it in a fresh
+-- lightweight State (no solver connection needed). The State is created via
+-- 'mkNewState' with 'LambdaGen' mode, which initializes all counters identically
+-- without starting a solver process.
+propFingerprint :: QuantifiedBool a => a -> IO PropFingerprint
+propFingerprint prop = do
+  st  <- mkNewState defaultSMTCfg (LambdaGen Nothing)
+  sv  <- svToSV st (unSBV (quantifiedBool prop))
+  pgm <- readIORef (spgm st)
+  cm  <- readIORef (rconstMap st)
+  let entries = [ (svIntId target, zeroContextInOp op, map svIntId args)
+                | (target, SBVApp op args) <- toList (pgmAssignments pgm)
+                ]
+      consts  = [(c, svIntId s) | (c, s) <- Map.toAscList cm]
+  pure $ PropFingerprint (consts, entries, svIntId sv)
+
+-- | After proving a proposition, add the proof to the cache for future recall lookups.
+addToProofCache :: forall a. (Typeable a, QuantifiedBool a) => a -> ProofObj -> TP ()
+addToProofCache prop prf = do
+  TPState{proofCache} <- getTPState
+  fp <- liftIO $ propFingerprint prop
+  let key = (fp, typeOf (Proxy @a))
+  liftIO $ modifyIORef' proofCache $ Map.insertWith (\_ old -> prf : old) key [prf]
+
+-- | Look up a cached proof for the given proposition. Only succeeds when in recall context
+-- (i.e., called from within a recall wrapper). On cache hit, the returned ProofObj has
+-- its 'aliases' field populated with the names of other proofs of the same proposition.
+lookupProofCache :: forall a. (Typeable a, QuantifiedBool a) => a -> TP (Maybe ProofObj)
+lookupProofCache prop = do
+  TPState{proofCache, inRecallContext} <- getTPState
+  inRecall <- liftIO $ readIORef inRecallContext
+  if inRecall == 0
+     then pure Nothing
+     else do fp <- liftIO $ propFingerprint prop
+             let key = (fp, typeOf (Proxy @a))
+             cache <- liftIO $ readIORef proofCache
+             pure $ case reverse <$> Map.lookup key cache of
+               Nothing     -> Nothing
+               Just []     -> Nothing
+               Just (p:ps) -> Just p { aliases = [proofName q | q <- ps] }
+
+-- | Return a cached proof, printing a brief "Q.E.D." line with optional "a.k.a." annotation.
+returnCachedProof :: SMTConfig -> String -> ProofObj -> TP (Proof a)
+returnCachedProof cfg nm prf = do
+   let aka  = filter (/= nm) $ nub $ proofName prf : aliases prf
+       prf' = prf { proofName = nm, wasCached = True, aliases = aka }
+   liftIO $ printLemmaResult cfg False nm (dependencies prf) True aka
+   pure $ Proof prf'
+
+-- | The context in which we make a check-sat call
+data TPProofContext = TPProofOneShot String      -- ^ A one shot proof, with string containing its name
+                                     [ProofObj]  -- ^ Helpers used (latter only used for cex generation)
+                    | TPProofStep    Bool        -- ^ A proof step. If Bool is true, then these are the assumptions for that step
+                                     String      -- ^ Name of original goal
+                                     [String]    -- ^ The helper "strings" given by the user
+                                     [String]    -- ^ The step name, i.e., the name of the branch in the proof tree
+
+-- | Run a TP proof, using the default configuration.
+runTP :: TP a -> IO a
+runTP = runTPWith defaultSMTCfg
+
+-- | Run a TP proof, using the given configuration.
+runTPWith :: SMTConfig -> TP a -> IO a
+runTPWith cfg@SMTConfig{tpOptions = TPOptions{printStats}} (TP f) = do
+   rDryRun    <- newIORef True
+   rMaxRibbon <- newIORef 0
+
+   let runPass c = do
+         rStats       <- newIORef $ TPStats { noOfCheckSats = 0, solverElapsed = 0, qcElapsed = 0 }
+         rCache       <- newIORef Map.empty
+         rCfg         <- newIORef c
+         rRecall      <- newIORef (0 :: Int)
+         rMeasures    <- newIORef Set.empty
+         rProductive  <- newIORef Set.empty
+         rEncountered <- newIORef Set.empty
+         let st = TPState { config               = rCfg
+                           , stats               = rStats
+                           , proofCache          = rCache
+                           , inRecallContext     = rRecall
+                           , measuresVerified    = rMeasures
+                           , productiveVerified  = rProductive
+                           , measuresEncountered = rEncountered
+                           , dryRun              = rDryRun
+                           , maxRibbon           = rMaxRibbon
+                           }
+         a <- runReaderT f st
+         pure (a, st)
+
+   -- Pass 1: Dry run to collect ribbon widths
+   _ <- runPass ((tpQuiet True cfg){verbose = False})
+
+   -- Pass 2: Real run with computed ribbon
+   writeIORef rDryRun False
+   ribbon <- readIORef rMaxRibbon
+   let cfg' = cfg{tpOptions = (tpOptions cfg) { ribbonLength = max 20 (ribbon + 4) }}
+
+   (mbT, (r, TPState{stats = rStats, measuresVerified = rMeasures, productiveVerified = rProductive, measuresEncountered = rEncountered}))
+       <- timeIf printStats $ runPass cfg'
+
+   -- Print verified measures and productive functions
+   verified    <- readIORef rMeasures
+   productive  <- readIORef rProductive
+   encountered <- readIORef rEncountered
+
+   unless (Set.null verified)   $ printMeasures   cfg' (Set.toAscList verified)
+   unless (Set.null productive) $ printProductive cfg' (Set.toAscList productive)
+
+   -- Belt-and-suspenders: make sure all encountered measures have been verified.
+   -- Exclude functions in measuresBeingVerified: those are being verified by an outer caller
+   -- (e.g., when a measureLemma proof uses the function whose measure is being checked).
+   let beingVerified = measuresBeingVerified (tpOptions cfg)
+       missed = encountered `Set.difference` verified `Set.difference` productive `Set.difference` beingVerified
+
+   unless (Set.null missed) $
+     error $ "SBV.runTP: Internal error: The following functions have termination measures that were encountered but not verified: "
+           ++ intercalate ", " (Set.toAscList missed)
+
+   case mbT of
+     Nothing -> pure ()
+     Just t  -> do TPStats noOfCheckSats solverTime qcElapsed <- readIORef rStats
+
+                   let stats = [ ("SBV",       showTDiff (t - solverTime - qcElapsed))
+                               , ("Solver",    showTDiff solverTime)
+                               , ("QC",        showTDiff qcElapsed)
+                               , ("Total",     showTDiff t)
+                               , ("Decisions", show noOfCheckSats)
+                               ]
+
+                   message cfg' $ '[' : intercalate ", " [k ++ ": " ++ v | (k, v) <- stats] ++ "]\n"
+   pure r
+
+-- | get the state
+getTPState :: TP TPState
+getTPState = ask
+
+-- | Make a unique number in this TP run. We combine that context with the proof-count
+tpGetNextUnique :: TP TPUnique
+tpGetNextUnique = TPUser <$> liftIO randomIO
+
+-- | get the configuration
+getTPConfig :: TP SMTConfig
+getTPConfig = do rCfg <- config <$> getTPState
+                 liftIO (readIORef rCfg)
+
+-- | set the configuration
+setTPConfig :: SMTConfig -> TP ()
+setTPConfig cfg = do st <- getTPState
+                     liftIO (writeIORef (config st) cfg)
+
+-- | Update stats
+updStats :: MonadIO m => TPState -> (TPStats -> TPStats) -> m ()
+updStats TPState{stats} u = liftIO $ modifyIORef' stats u
+
+-- | Display the message if not quiet. Note that we don't print a newline; so the message must have it if needed.
+message :: MonadIO m => SMTConfig -> String -> m ()
+message SMTConfig{tpOptions = TPOptions{quiet}, redirectVerbose} s
+  | quiet
+  = pure ()
+  | Just f <- redirectVerbose
+  = liftIO $ appendFile f s
+  | True
+  = liftIO $ putStr s >> hFlush stdout
+
+-- | Print the list of functions whose termination measures have been verified.
+printMeasures :: SMTConfig -> [String] -> IO ()
+printMeasures = printFunctions "Functions proven terminating"
+
+-- | Print the list of functions whose productivity (guardedness) has been verified.
+printProductive :: SMTConfig -> [String] -> IO ()
+printProductive = printFunctions "Functions proven productive"
+
+-- | Print a list of function names under a header, wrapping lines to avoid excessively long output.
+-- If the list fits on one line, it follows the header directly. Otherwise, it starts on a new line.
+printFunctions :: String -> SMTConfig -> [String] -> IO ()
+printFunctions header cfg names
+  | length oneLine <= limit = message cfg $ header ++ ": " ++ oneLine ++ "\n"
+  | True                    = message cfg $ header ++ ":\n  " ++ wrapped ++ "\n"
+  where cleaned = nub (sort (map strip names))
+        strip   = dropWhileEnd (== ' ') . takeWhile (/= '@')
+
+        limit = 90
+
+        oneLine = intercalate ", " cleaned
+
+        wrapped = go limit cleaned
+
+        go _ []     = ""
+        go _ [n]    = n
+        go r (n:ns) = let len  = length n + 2  -- account for ", "
+                          rest = go (r - len) ns
+                      in if r - len < 0 && r /= limit
+                         then "\n  " ++ go limit (n:ns)
+                         else case rest of
+                                '\n':_ -> n ++ "," ++ rest
+                                _      -> n ++ ", " ++ rest
+
+-- | Start a proof. We return the number of characters we printed, so the finisher can align the result.
+startTP :: SMTConfig -> Bool -> String -> Int -> TPProofContext -> IO Int
+startTP cfg newLine what level ctx = do message cfg $ line ++ if newLine then "\n" else ""
+                                        hFlush stdout
+                                        pure (length line)
+  where nm = case ctx of
+               TPProofOneShot n _       -> n
+               TPProofStep    _ _ hs ss -> intercalate "." ss ++ userHints hs
+
+        tab = 2 * level
+
+        line = replicate tab ' ' ++ what ++ ": " ++ nm
+
+        userHints [] = ""
+        userHints ss = " (" ++ intercalate ", " ss ++ ")"
+
+-- | Finish a proof. First argument is what we got from the call of 'startTP' above.
+finishTP :: SMTConfig -> String -> (Int, Maybe NominalDiffTime) -> [NominalDiffTime] -> IO ()
+finishTP cfg@SMTConfig{tpOptions = TPOptions{ribbonLength}} what (skip, mbT) extraTiming =
+   message cfg $ replicate (ribbonLength - skip) ' ' ++ what ++ timing ++ extras ++ "\n"
+ where timing = maybe "" ((' ' :) . mkTiming) mbT
+       extras = concatMap mkTiming extraTiming
+
+       mkTiming t = '[' : showTDiff t ++ "]"
+
+-- | Unique identifier for each proof.
+data TPUnique = TPInternal        -- IH's
+              | TPSorry           -- sorry
+              | TPQC              -- qc (quick-check)
+              | TPNoTermCheck     -- no termination check (smtFunctionNoTermination)
+              | TPUser Int64      -- user given
+              deriving (NFData, Generic, Eq, Ord)
+
+-- | Proof for a property. This type is left abstract, i.e., the only way to create on is via a
+-- call to lemma/theorem etc., ensuring soundness. (Note that the trusted-code base here
+-- is still large: The underlying solver, SBV, and TP kernel itself. But this
+-- mechanism ensures we can't create proven things out of thin air, following the standard LCF
+-- methodology.)
+newtype Proof a = Proof { proofOf :: ProofObj -- ^ Get the underlying proof object
+                        }
+
+-- | Grab the underlying boolean in a proof. Useful in assumption contexts where we need a boolean
+assumptionFromProof :: Proof a -> SBool
+assumptionFromProof = getObjProof . proofOf
+
+-- | The actual proof container
+data ProofObj = ProofObj { dependencies :: [ProofObj]     -- ^ Immediate dependencies of this proof. (Not transitive)
+                         , isUserAxiom  :: Bool           -- ^ Was this an axiom given by the user?
+                         , getObjProof  :: SBool          -- ^ Get the underlying boolean
+                         , getProp      :: Dynamic        -- ^ The actual proposition
+                         , proofName    :: String         -- ^ User given name
+                         , uniqId       :: TPUnique       -- ^ Unique identifier
+                         , aliases      :: [String]       -- ^ Other names for proofs of the same proposition (populated on cache hit)
+                         , wasCached    :: Bool           -- ^ Was this proof retrieved from the cache?
+                         }
+
+-- | Drop the instantiation part
+shortProofName :: ProofObj -> String
+shortProofName p | " @ " `isInfixOf` s = reverse . dropWhile isSpace . reverse . takeWhile (/= '@') $ s
+                 | True                = s
+   where s = proofName p
+
+-- | Deduplicate proof objects by their unique id, keeping the first occurrence.
+-- Same result as @nubBy ((==) \`on\` uniqId)@, but O(n log n) instead of O(n^2).
+nubByUniqId :: [ProofObj] -> [ProofObj]
+nubByUniqId = go Set.empty
+  where go _    []     = []
+        go seen (p:ps)
+          | u `Set.member` seen =     go seen ps
+          | True                = p : go (Set.insert u seen) ps
+          where u = uniqId p
+
+-- | Nicely format a bunch of proof-names, shortened and uniquified. Note that if we get a dependency
+-- via multiple routes, they can get different uniqid's; so we do a bit of compression here.
+shortProofNames :: [ProofObj] -> String
+shortProofNames = intercalate ", " . map merge . compress . sort . map shortProofName . nubByUniqId
+ where compress []     = []
+       compress (a:as) = case span (a ==) as of
+                           (same, other) -> (a, length same + 1) : compress other
+       merge (n, 1) = n
+       merge (n, x) = n ++ " (x" ++ show x ++ ")"
+
+-- | Keeping track of where the sorry originates from. Used in displaying dependencies.
+newtype RootOfTrust = RootOfTrust (Maybe [ProofObj])
+
+-- | Show instance for t'RootOfTrust'
+instance Show RootOfTrust where
+  show (RootOfTrust mbp) = case mbp of
+                             Nothing -> "Nothing"
+                             Just ps -> "Just [" ++ shortProofNames ps ++ "]"
+
+-- | Trust forms a semigroup
+instance Semigroup RootOfTrust where
+   RootOfTrust as <> RootOfTrust bs = RootOfTrust $ nubByUniqId <$> (as <> bs)
+
+-- | Trust forms a monoid
+instance Monoid RootOfTrust where
+  mempty = RootOfTrust Nothing
+
+-- | NFData ignores the getProp field
+instance NFData ProofObj where
+  rnf (ProofObj dependencies isUserAxiom getObjProof _getProp proofName uniqId aliases wasCached) =     rnf dependencies
+                                                                                                 `seq` rnf isUserAxiom
+                                                                                                 `seq` rnf getObjProof
+                                                                                                 `seq` rnf proofName
+                                                                                                 `seq` rnf uniqId
+                                                                                                 `seq` rnf aliases
+                                                                                                 `seq` rnf wasCached
+
+-- | Dependencies of a proof, in a tree format.
+data ProofTree = ProofTree ProofObj [ProofTree]
+
+-- | Return all the proofs this particular proof depends on, transitively
+getProofTree :: ProofObj -> ProofTree
+getProofTree p = ProofTree p $ map getProofTree (dependencies p)
+
+-- | Turn dependencies to a container tree, for display purposes
+depsToTree :: Bool -> [TPUnique] -> (String -> Int -> Int -> a) -> (Int, ProofTree) -> ([TPUnique], Tree a)
+depsToTree shouldCompress visited xform (cnt, ProofTree top ds) = (nVisited, Node (xform nTop cnt (length chlds)) chlds)
+  where nTop = shortProofName top
+        uniq = uniqId top
+
+        (nVisited, chlds)
+           | shouldCompress && uniq `elem` visited = (visited, [])
+           | shouldCompress                        = walk (uniq : visited) (compress (filter interesting ds))
+           | True                                  = walk         visited  (map (1,) (filter interesting ds))
+
+        walk v []     = (v, [])
+        walk v (c:cs) = let (v',  t)  = depsToTree shouldCompress v xform c
+                            (v'', ts) = walk v' cs
+                        in (v'', t : ts)
+
+        -- Don't show internal axioms, not interesting
+        interesting (ProofTree p _) = case uniqId p of
+                                        TPInternal    -> False
+                                        TPSorry       -> True
+                                        TPQC          -> True
+                                        TPNoTermCheck -> True
+                                        TPUser{}      -> True
+
+        -- If a proof is used twice in the same proof, compress it
+        compress :: [ProofTree] -> [(Int, ProofTree)]
+        compress []       = []
+        compress (p : ps) = (1 + length [() | (_, True) <- filtered], p) : compress [d | (d, False) <- filtered]
+          where filtered = [(d, uniqId p' == curUniq) | d@(ProofTree p' _) <- ps]
+                curUniq  = case p of
+                             ProofTree curProof _ -> uniqId curProof
+
+-- | Display the proof tree as ASCII text. The first argument is if we should compress the tree, showing only the first
+-- use of any sublemma.
+showProofTree :: Bool -> Proof a -> String
+showProofTree compress d = showTree $ snd $ depsToTree compress [] sh (1, getProofTree (proofOf d))
+    where sh nm 1 _ = nm
+          sh nm x _= nm ++ " (x" ++ show x ++ ")"
+
+-- | Display the tree as an html doc for rendering purposes.
+-- The first argument is if we should compress the tree, showing only the first
+-- use of any sublemma. Second is the path (or URL) to external CSS file, if needed.
+showProofTreeHTML :: Bool -> Maybe FilePath -> Proof a -> String
+showProofTreeHTML compress mbCSS p = htmlTree mbCSS $ snd $ depsToTree compress [] nodify (1, getProofTree (proofOf p))
+  where nodify :: String -> Int -> Int -> NodeInfo
+        nodify nm cnt dc = NodeInfo { nodeBehavior = InitiallyExpanded
+                                    , nodeName     = nm
+                                    , nodeInfo     = spc (used cnt) ++ depCount dc
+                                    }
+        used 1 = ""
+        used n = "Used " ++ show n ++ " times."
+
+        spc "" = ""
+        spc s  = s ++ " "
+
+        depCount 0 = ""
+        depCount 1 = "Has one dependency."
+        depCount n = "Has " ++ show n ++ " dependencies."
+
+-- | Show instance for t'Proof'
+instance Typeable a => Show (Proof a) where
+  show p@(Proof ProofObj{proofName = nm}) = '[' : sh (rootOfTrust p) ++ "] " ++ nm ++ " :: " ++ pretty (show (typeOf p))
+    where sh (RootOfTrust Nothing)   = "Proven"
+          sh (RootOfTrust (Just ps)) = "Modulo: " ++ shortProofNames ps
+
+          -- More mathematical notation for types.
+          pretty :: String -> String
+          pretty = charToString . compress . unwords . walk . words . concatMap (\c -> if c == ',' then " , " else [c]) . clean
+            where fa v = ['Ɐ' : unQuote v, "∷"]
+                  ex v = ['∃' : unQuote v, "∷"]
+
+                  -- Remove spaces before commas: "foo , bar" -> "foo, bar"
+                  compress (' ' : ',' : rest) = compress (',' : rest)
+                  compress (c : rest)         = c : compress rest
+                  compress []                 = []
+
+                  -- Replace [Char] with String everywhere
+                  charToString ('[':'C':'h':'a':'r':']':rest) = "String" ++ charToString rest
+                  charToString (c:rest)                       = c : charToString rest
+                  charToString []                             = []
+
+                  walk ("SBV"    : "Bool" : rest) = walk $ "Bool" :  rest
+                  walk ("Forall" : xs     : rest) = walk $ fa xs  ++ rest
+                  walk ("Exists" : xs     : rest) = walk $ ex xs  ++ rest
+                  walk ("->"              : rest) = walk $ "→"    :  rest
+
+                  -- handle the double case. This isn't quite solid, but it does the trick.
+                  walk ("((Forall" : xs : t1 : "," : "(Forall" : ys : t2 : rest) = ap (fa xs) ++ [np t1 ++ ","] ++ fa ys ++ [np t2] ++ walk rest
+                     where -- remove a closing paren from the end if it's there
+                           np s | ")" `isSuffixOf` s = init s
+                                | True               = s
+                           -- add open paren to the first word
+                           ap (t : ts) = ('(':t) : ts
+                           ap []       = []
+
+                  -- Otherwise, pass along
+                  walk (c : cs) = c : walk cs
+                  walk []       = []
+
+          -- Strip of Proof (...)
+          clean :: String -> String
+          clean s | pre `isPrefixOf` s && suf `isSuffixOf` s
+                  = reverse . drop (length suf) . reverse . drop (length pre) $ s
+                  | True
+                  = s
+            where pre = "Proof ("
+                  suf = ")"
+
+-- | A manifestly false theorem. This is useful when we want to prove a theorem that the underlying solver
+-- cannot deal with, or if we want to postpone the proof for the time being. TP will keep
+-- track of the uses of 'sorry' and will print them appropriately while printing proofs.
+-- NB. We keep this as a t'ProofObj' as opposed to a t'Proof' as it is then easier to use it as a lemma helper.
+sorry :: ProofObj
+sorry = ProofObj { dependencies = []
+                 , isUserAxiom  = False
+                 , getObjProof  = label "sorry" (quantifiedBool p)
+                 , getProp      = toDyn p
+                 , proofName    = "sorry"
+                 , uniqId       = TPSorry
+                 , aliases      = []
+                 , wasCached    = False
+                 }
+  where -- ideally, I'd rather just use
+        --   p = sFalse
+        -- but then SBV constant folds the boolean, and the generated script
+        -- doesn't contain the actual contents, as SBV determines unsatisfiability
+        -- itself. By using the following proposition (which is easy for the backend
+        -- solver to determine as false, we avoid the constant folding.
+        p (Forall @"__sbvTP_sorry" (x :: SBool)) = label "SORRY: TP, proof uses \"sorry\"" x
+
+-- | Quick-check uses this proof. It's equivalent to sorry, really; except for its name
+quickCheckProof :: ProofObj
+quickCheckProof = ProofObj { dependencies = []
+                           , isUserAxiom  = False
+                           , getObjProof  = label "quickCheck" (quantifiedBool p)
+                           , getProp      = toDyn p
+                           , proofName    = "quickCheck"
+                           , uniqId       = TPQC
+                           , aliases      = []
+                           , wasCached    = False
+                           }
+  where -- ideally, I'd rather just use
+        --   p = sFalse
+        -- but then SBV constant folds the boolean, and the generated script
+        -- doesn't contain the actual contents, as SBV determines unsatisfiability
+        -- itself. By using the following proposition (which is easy for the backend
+        -- solver to determine as false, we avoid the constant folding.
+        p (Forall @"__sbvTP_quickCheck" (x :: SBool)) = label "QUICKCHECK: TP, proof uses \"qc\"" x
+
+-- | A proof object representing a function whose termination was not checked.
+-- When a function is defined with 'Data.SBV.smtFunctionNoTermination', its termination
+-- is assumed but not proven. Any proof that depends on such a function will be
+-- marked as modulo this assumption in its root of trust.
+noTermCheckProof :: String -> ProofObj
+noTermCheckProof nm = ProofObj { dependencies = []
+                               , isUserAxiom  = False
+                               , getObjProof  = sTrue
+                               , getProp      = toDyn True
+                               , proofName    = nm ++ " termination"
+                               , uniqId       = TPNoTermCheck
+                               , aliases      = []
+                               , wasCached    = False
+                               }
+
+-- | Calculate the root of trust. The returned list of proofs, if any, will need to be sorry and quickcheck free to
+-- have the given proof to be sorry-free.
+rootOfTrust :: Proof a -> RootOfTrust
+rootOfTrust = rot True . proofOf
+  where rot atTop p@ProofObj{uniqId = curUniq, dependencies} = compress res
+          where res = case curUniq of
+                        TPInternal    -> RootOfTrust Nothing
+                        TPQC          -> RootOfTrust $ Just [quickCheckProof]
+                        TPSorry       -> RootOfTrust $ Just [sorry]
+                        TPNoTermCheck -> RootOfTrust $ Just [p]
+                        TPUser {}     -> self <> foldMap (rot False) dependencies
+
+                -- if sorry or quickcheck is one of our direct dependencies, then we trust this proof.
+                -- Note that we skip this at the top. Why? at that level, we want to see the direct
+                -- dependency. But if we're down at a lower level, we just want to pick up
+                self | atTop                     = mempty
+                     | any isUnsafe dependencies = RootOfTrust $ Just [p]
+                     | True                      = mempty
+
+                isUnsafe ProofObj{uniqId = u} = u `elem` [TPSorry, TPQC]
+
+                -- If sorry is present, it dominates everything else. Otherwise keep all.
+                compress (RootOfTrust mbps) = RootOfTrust $ reduce <$> mbps
+                  where reduce ps
+                          | any (\o -> uniqId o == TPSorry) ps = [sorry]
+                          | True                               = ps
+
+-- | Print a one-line lemma result: @Lemma: name  Q.E.D. [Modulo: ...] [Cached] (a.k.a. ...)@
+printLemmaResult :: SMTConfig -> Bool -> String -> [ProofObj] -> Bool -> [String] -> IO ()
+printLemmaResult cfg verboseFlag nm deps cached aka = do
+   tab <- startTP cfg verboseFlag "Lemma" 0 (TPProofOneShot nm [])
+   finishTP cfg ("Q.E.D." ++ concludeModulo deps ++ cacheStr ++ akaStr) (tab, Nothing) []
+ where cacheStr | cached = " [Cached]"
+                | True   = ""
+       akaStr   | null aka = ""
+                | True     = " (a.k.a. " ++ intercalate ", " aka ++ ")"
+
+-- | Calculate the modulo string for dependencies
+concludeModulo :: [ProofObj] -> String
+concludeModulo by = case foldMap (rootOfTrust . Proof) by of
+                      RootOfTrust Nothing   -> ""
+                      RootOfTrust (Just ps) -> " [Modulo: " ++ shortProofNames ps ++ "]"
+
+-- | Make TP proofs quiet. Note that this setting will be effective with the
+-- call to 'runTP'\/'runTPWith', i.e., if you change the solver in a call to 'Data.SBV.TP.lemmaWith'\/'Data.SBV.TP.theoremWith', we
+-- will inherit the quiet settings from the surrounding environment.
+tpQuiet :: Bool -> SMTConfig -> SMTConfig
+tpQuiet b cfg = cfg{tpOptions = (tpOptions cfg) { quiet = b }}
+
+-- | Make TP proofs produce statistics. Note that this setting will be effective with the
+-- call to 'runTP'\/'runTPWith', i.e., if you change the solver in a call to 'Data.SBV.TP.lemmaWith'\/'Data.SBV.TP.theoremWith', we
+-- will inherit the statistics settings from the surrounding environment.
+tpStats :: SMTConfig -> SMTConfig
+tpStats cfg = cfg{tpOptions = (tpOptions cfg) { printStats = True }}
+
+
+-- | When proving assumptions for each step, print them as well. Normally, SBV doesn't
+-- print assumptions in each proof step, though it does prove them as they are typically trivial.
+-- But in certain cases seeing them would be helpful.
+tpAsms :: SMTConfig -> SMTConfig
+tpAsms cfg = cfg{tpOptions = (tpOptions cfg) { printAsms = True }}
+
+-- | Create a t'MeasureHelper' from a TP proof action. During measure verification,
+-- the proof is run to confirm the property holds, and the proven property is extracted
+-- and asserted as an axiom in the measure verification session. The solver configuration
+-- is inherited from the measure verification context, with output suppressed.
+--
+-- Example usage with 'Data.SBV.smtFunctionWithMeasure':
+--
+-- @
+-- normalize = smtFunctionWithMeasure "normalize"
+--               (\\f -> tuple (ifComplexity f, ifDepth f)
+--               , [measureLemma ifDepthNonNeg, measureLemma ifComplexityPos]
+--               )
+--             $ \\f -> ...
+-- @
+measureLemma :: forall a. (QuantifiedBool a, Typeable a) => TP (Proof a) -> MeasureHelper
+measureLemma tp = MeasureHelper $ \cfg -> do
+  proof <- runTPWith (tpQuiet True cfg) tp
+  case fromDynamic @a (getProp (proofOf proof)) of
+    Just prop -> pure (quantifiedBool prop)
+    Nothing   -> error "Data.SBV.measureLemma: impossible type mismatch in measure helper"
+
+-- | Like 'measureLemma', but using the given solver configuration, ignoring the
+-- one from the measure verification context.
+measureLemmaWith :: forall a. (QuantifiedBool a, Typeable a) => SMTConfig -> TP (Proof a) -> MeasureHelper
+measureLemmaWith userCfg tp = MeasureHelper $ \_cfg -> do
+  proof <- runTPWith (tpQuiet True userCfg) tp
+  case fromDynamic @a (getProp (proofOf proof)) of
+    Just prop -> pure (quantifiedBool prop)
+    Nothing   -> error "Data.SBV.measureLemmaWith: impossible type mismatch in measure helper"
diff --git a/Data/SBV/Tools/BMC.hs b/Data/SBV/Tools/BMC.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/BMC.hs
@@ -0,0 +1,119 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.BMC
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bounded model checking interface. See "Documentation.SBV.Examples.ProofTools.BMC"
+-- for an example use case.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.BMC (
+         bmcRefute, bmcRefuteWith, bmcCover, bmcCoverWith
+       ) where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Control.Monad (when)
+
+-- | Are we covering or refuting?
+data BMCKind = Refute
+             | Cover
+
+-- | Refutation using bounded model checking, using the default solver. This version tries to refute the goal
+-- in a depth-first fashion. Note that this method can find a refutation, but will never find a "proof."
+-- If it finds a refutation, it will be the shortest, though not necessarily unique.
+bmcRefute :: (Queriable IO st, res ~ QueryResult st)
+    => Maybe Int                            -- ^ Optional bound
+    -> Bool                                 -- ^ Verbose: prints iteration count
+    -> Symbolic ()                          -- ^ Setup code, if necessary. (Typically used for 'Data.SBV.setOption' calls. Pass @pure ()@ if not needed.)
+    -> (st -> SBool)                        -- ^ Initial condition
+    -> (st -> st -> SBool)                  -- ^ Transition relation
+    -> (st -> SBool)                        -- ^ Goal to cover, i.e., we find a set of transitions that satisfy this predicate.
+    -> IO (Either String (Int, [res]))      -- ^ Either a result, or a satisfying path of given length and intermediate observations.
+bmcRefute = bmcRefuteWith defaultSMTCfg
+
+-- | Refutation using a given solver.
+bmcRefuteWith :: (Queriable IO st, res ~ QueryResult st)
+    => SMTConfig                            -- ^ Solver to use
+    -> Maybe Int                            -- ^ Optional bound
+    -> Bool                                 -- ^ Verbose: prints iteration count
+    -> Symbolic ()                          -- ^ Setup code, if necessary. (Typically used for 'Data.SBV.setOption' calls. Pass @pure ()@ if not needed.)
+    -> (st -> SBool)                        -- ^ Initial condition
+    -> (st -> st -> SBool)                  -- ^ Transition relation
+    -> (st -> SBool)                        -- ^ Goal to cover, i.e., we find a set of transitions that satisfy this predicate.
+    -> IO (Either String (Int, [res]))      -- ^ Either a result, or a satisfying path of given length and intermediate observations.
+bmcRefuteWith = bmcWith Refute
+
+-- | Covers using bounded model checking, using the default solver. This version tries to cover the goal
+-- in a depth-first fashion. Note that this method can find a cover, but will never find determine that a goal is
+-- not coverable. If it finds a cover, it will be the shortest, though not necessarily unique.
+bmcCover :: (Queriable IO st, res ~ QueryResult st)
+    => Maybe Int                            -- ^ Optional bound
+    -> Bool                                 -- ^ Verbose: prints iteration count
+    -> Symbolic ()                          -- ^ Setup code, if necessary. (Typically used for 'Data.SBV.setOption' calls. Pass @pure ()@ if not needed.)
+    -> (st -> SBool)                        -- ^ Initial condition
+    -> (st -> st -> SBool)                  -- ^ Transition relation
+    -> (st -> SBool)                        -- ^ Goal to cover, i.e., we find a set of transitions that satisfy this predicate.
+    -> IO (Either String (Int, [res]))      -- ^ Either a result, or a satisfying path of given length and intermediate observations.
+bmcCover = bmcCoverWith defaultSMTCfg
+
+-- | Cover using a given solver.
+bmcCoverWith :: (Queriable IO st, res ~ QueryResult st)
+    => SMTConfig                            -- ^ Solver to use
+    -> Maybe Int                            -- ^ Optional bound
+    -> Bool                                 -- ^ Verbose: prints iteration count
+    -> Symbolic ()                          -- ^ Setup code, if necessary. (Typically used for 'Data.SBV.setOption' calls. Pass @pure ()@ if not needed.)
+    -> (st -> SBool)                        -- ^ Initial condition
+    -> (st -> st -> SBool)                  -- ^ Transition relation
+    -> (st -> SBool)                        -- ^ Goal to cover, i.e., we find a set of transitions that satisfy this predicate.
+    -> IO (Either String (Int, [res]))      -- ^ Either a result, or a satisfying path of given length and intermediate observations.
+bmcCoverWith = bmcWith Cover
+
+-- | Bounded model checking, configurable with the solver. Not exported; use 'bmcCover', 'bmcRefute' and their "with" variants.
+bmcWith :: (Queriable IO st, res ~ QueryResult st)
+        => BMCKind -> SMTConfig -> Maybe Int -> Bool -> Symbolic () -> (st -> SBool) -> (st -> st -> SBool) -> (st -> SBool)
+        -> IO (Either String (Int, [res]))
+bmcWith kind cfg mbLimit chatty setup initial trans goal
+  = runSMTWith cfg $ do setup
+                        query $ do state <- create
+                                   constrain $ initial state
+                                   go 0 state []
+   where (what, badResult, goodResult) = case kind of
+                                           Cover  -> ("BMC Cover",  "Cover can't be established.", "Satisfying")
+                                           Refute -> ("BMC Refute", "Cannot refute the claim.",    "Failing")
+
+         go i _ _
+          | Just l <- mbLimit, i >= l
+          = pure $ Left $ what ++ " limit of " ++ show l ++ " reached. " ++ badResult
+
+         go i curState sofar = do when chatty $ io $ putStrLn $ what ++ ": Iteration: " ++ show i
+
+                                  push 1
+
+                                  let g = goal curState
+                                  constrain $ case kind of
+                                                Cover  ->      g   -- Covering the goal
+                                                Refute -> sNot g   -- Trying to refute the goal, so satisfy the negation
+
+                                  cs <- checkSat
+
+                                  case cs of
+                                    DSat{} -> error $ what ++ ": Solver returned an unexpected delta-sat result."
+                                    Sat    -> do when chatty $ io $ putStrLn $ what ++ ": " ++ goodResult ++ " state found at iteration " ++ show i
+                                                 ms <- mapM project (curState : sofar)
+                                                 pure $ Right (i, reverse ms)
+                                    Unk    -> do when chatty $ io $ putStrLn $ what ++ ": Backend solver said unknown at iteration " ++ show  i
+                                                 pure $ Left $ what ++ ": Solver said unknown in iteration " ++ show i
+                                    Unsat  -> do pop 1
+                                                 nextState <- create
+                                                 constrain $ curState `trans` nextState
+                                                 go (i+1) nextState (curState : sofar)
diff --git a/Data/SBV/Tools/BVOptimize.hs b/Data/SBV/Tools/BVOptimize.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/BVOptimize.hs
@@ -0,0 +1,126 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.BVOptimize
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bit-vector optimization based on linear scan of the bits. The optimization
+-- engines are usually not incremental, and they perform poorly for optimizing
+-- bit-vector values in the presence of complicated constraints. We implement
+-- a simple optimizer by scanning the bits from top-to-bottom to minimize/maximize
+-- unsigned bit vector quantities, using the regular (i.e., incremental) solver.
+-- This can lead to better performance for this class of problems.
+--
+-- This implementation is based on an idea by Nikolaj Bjorner, see <https://github.com/Z3Prover/z3/issues/7156>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.BVOptimize (
+            -- ** Maximizing bit-vectors
+            -- $maxBVEx
+              maxBV, maxBVWith
+            -- ** Minimizing bit-vectors
+            -- $minBVEx
+            , minBV, minBVWith
+          ) where
+
+import Control.Monad
+
+import Data.SBV
+import Data.SBV.Control
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XDataKinds
+-- >>> import Data.SBV
+#endif
+
+{- $maxBVEx
+
+Here is a simple example of maximizing a bit-vector value:
+
+>>> :{
+runSMT $ do x :: SWord 32 <- free "x"
+            constrain $ x .> 5
+            constrain $ x .< 27
+            maxBV False x
+:}
+Satisfiable. Model:
+  x = 26 :: Word32
+-}
+
+-- | Maximize the value of an unsigned bit-vector value, using the default solver.
+maxBV :: SFiniteBits a
+      => Bool                -- ^ Do we want unsat-cores if unsatisfiable?
+      -> SBV a               -- ^ Value to maximize
+      -> Symbolic SatResult
+maxBV = maxBVWith defaultSMTCfg
+
+-- | Maximize the value of an unsigned bit-vector value, using the given solver.
+maxBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult
+maxBVWith = minMaxBV True
+
+{- $minBVEx
+
+Here is a simple example of minimizing a bit-vector value:
+
+>>> :{
+runSMT $ do x :: SWord 32 <- free "x"
+            constrain $ x .> 5
+            constrain $ x .< 27
+            minBV False x
+:}
+Satisfiable. Model:
+  x = 6 :: Word32
+-}
+
+-- | Minimize the value of an unsigned bit-vector value, using the default solver.
+minBV :: SFiniteBits a
+      => Bool                -- ^ Do we want unsat-cores if unsatisfiable?
+      -> SBV a               -- ^ Value to minimize
+      -> Symbolic SatResult
+minBV = minBVWith defaultSMTCfg
+
+-- | Minimize the value of an unsigned bit-vector value, using the given solver.
+minBVWith :: SFiniteBits a => SMTConfig -> Bool-> SBV a -> Symbolic SatResult
+minBVWith = minMaxBV False
+
+-- | min/max a given unsigned bit-vector. We walk down the bits in an incremental
+-- fashion. If we are maximizing, we try to make the bits set as we go down, otherwise
+-- we try to unset them. We keep adding the constraints so long as they are satisfiable,
+-- and at the end, get the optimal value produced.
+minMaxBV :: SFiniteBits a => Bool -> SMTConfig -> Bool -> SBV a -> Symbolic SatResult
+minMaxBV isMax cfg getUC v
+ | hasSign v
+ = error $ "minMaxBV works on unsigned bit-vectors, received: " ++ show (kindOf v)
+ | True
+ = do when getUC $ setOption $ ProduceUnsatCores True
+      query $ go (blastBE v)
+ where uc | getUC = Just <$> getUnsatCore
+          | True  = pure Nothing
+
+       rSat   = SatResult . Satisfiable   cfg <$> getModel
+       rUnk   = SatResult . Unknown       cfg <$> getUnknownReason
+       rUnsat = SatResult . Unsatisfiable cfg <$> uc
+
+       go :: [SBool] -> Query SatResult
+       go []     = do r <- checkSat
+                      case r of
+                        Sat     -> rSat
+                        Unsat   -> rUnsat
+                        Unk     -> rUnk
+                        DSat {} -> error "minMaxBV: Unexpected DSat result"
+       go (b:bs) = do push 1
+                      if isMax then constrain b
+                               else constrain $ sNot b
+                      r <- checkSat
+                      case r of
+                        Sat    -> go bs >>= \res -> pop 1 >> pure res
+                        Unsat  ->                   pop 1 >> go bs
+                        Unk    ->                   pop 1 >> rUnk
+                        DSat{} -> error "minMaxBV: Unexpected DSat result"
diff --git a/Data/SBV/Tools/CodeGen.hs b/Data/SBV/Tools/CodeGen.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/CodeGen.hs
@@ -0,0 +1,64 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.CodeGen
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Code-generation from SBV programs.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.CodeGen (
+
+        -- * Code generation from symbolic programs
+        -- $cCodeGeneration
+          SBVCodeGen, cgSym
+
+        -- ** Setting code-generation options
+        , cgPerformRTCs, cgSetDriverValues, cgGenerateDriver, cgGenerateMakefile, cgOverwriteFiles, cgShowU8UsingHex
+
+        -- ** Designating inputs
+        , cgInput, cgInputArr
+
+        -- ** Designating outputs
+        , cgOutput, cgOutputArr
+
+        -- ** Designating return values
+        , cgReturn, cgReturnArr
+
+        -- ** Code generation with uninterpreted functions
+        , cgAddPrototype, cgAddDecl, cgAddLDFlags, cgIgnoreSAssert
+
+        -- ** Code generation with 'Data.SBV.SInteger' and 'Data.SBV.SReal' types
+        -- $unboundedCGen
+        , cgIntegerSize, cgSRealType, CgSRealType(..)
+
+        -- ** Compilation to C
+        , compileToC, compileToCLib
+       ) where
+
+import Data.SBV.Compilers.C
+import Data.SBV.Compilers.CodeGen
+
+{- $cCodeGeneration
+The SBV library can generate straight-line executable code in C. (While other target languages are
+certainly possible, currently only C is supported.) The generated code will perform no run-time memory-allocations,
+(no calls to @malloc@), so its memory usage can be predicted ahead of time. Also, the functions will execute precisely the
+same instructions in all calls, so they have predictable timing properties as well. The generated code
+has no loops or jumps, and is typically quite fast. While the generated code can be large due to complete unrolling,
+these characteristics make them suitable for use in hard real-time systems, as well as in traditional computing.
+-}
+
+{- $unboundedCGen
+The types 'Data.SBV.SInteger' and 'Data.SBV.SReal' are unbounded quantities that have no direct counterparts in the C language. Therefore,
+it is not possible to generate standard C code for SBV programs using these types, unless custom libraries are available. To
+overcome this, SBV allows the user to explicitly set what the corresponding types should be for these two cases, using
+the functions below. Note that while these mappings will produce valid C code, the resulting code will be subject to
+overflow/underflows for 'Data.SBV.SInteger', and rounding for 'Data.SBV.SReal', so there is an implicit loss of precision.
+
+If the user does /not/ specify these mappings, then SBV will
+refuse to compile programs that involve these types.
+-}
diff --git a/Data/SBV/Tools/ExpectedValue.hs b/Data/SBV/Tools/ExpectedValue.hs
deleted file mode 100644
--- a/Data/SBV/Tools/ExpectedValue.hs
+++ /dev/null
@@ -1,86 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Tools.ExpectedValue
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computing the expected value of a symbolic variable
------------------------------------------------------------------------------
-
-{-# LANGUAGE PatternGuards #-}
-module Data.SBV.Tools.ExpectedValue (expectedValue, expectedValueWith) where
-
-import Control.DeepSeq (rnf)
-import System.Random   (newStdGen, StdGen)
-import Numeric
-
-import Data.SBV.BitVectors.Data
-
--- | Generalized version of 'expectedValue', allowing the user to specify the
--- warm-up count and the convergence factor. Maximum iteration count can also
--- be specified, at which point convergence won't be sought. The boolean controls verbosity.
-expectedValueWith :: Outputtable a => Bool -> Int -> Maybe Int -> Double -> Symbolic a -> IO [Double]
-expectedValueWith chatty warmupCount mbMaxIter epsilon m
-  | warmupCount < 0 || epsilon < 0
-  = error $ "SBV.expectedValue: warmup count and epsilon both must be non-negative, received: " ++ show (warmupCount, epsilon)
-  | True
-  = warmup warmupCount (repeat 0) >>= go warmupCount
-  where progress s | not chatty = return ()
-                   | True       = putStr $ "\r*** " ++ s
-        warmup :: Int -> [Integer] -> IO [Integer]
-        warmup 0 v = do progress $ "Warmup complete, performed " ++ show warmupCount ++ " rounds.\n"
-                        return v
-        warmup n v = do progress $ "Performing warmup, round: " ++ show (warmupCount - n)
-                        g <- newStdGen
-                        t <- runOnce g
-                        let v' = zipWith (+) v t
-                        rnf v' `seq` warmup (n-1) v'
-        runOnce :: StdGen -> IO [Integer]
-        runOnce g = do (_, Result _ _ _ _ cs _ _ _ _ _ cstrs _ os) <- runSymbolic' (Concrete g) (m >>= output)
-                       let cval o = case o `lookup` cs of
-                                      Nothing -> error "SBV.expectedValue: Cannot compute expected-values in the presence of uninterpreted constants!"
-                                      Just cw -> case (kindOf cw, cwVal cw) of
-                                                   (KBool, _)                -> if cwToBool cw then 1 else 0
-                                                   (KBounded{}, CWInteger v) -> v
-                                                   (KUnbounded, CWInteger v) -> v
-                                                   (KReal, _)                -> error "Cannot compute expected-values for real valued results."
-                                                   _                         -> error $ "SBV.expectedValueWith: Unexpected CW: " ++ show cw
-                       if all ((== 1) . cval) cstrs
-                          then return $ map cval os
-                          else runOnce g -- constraint not satisfied try again with the same set of constraints
-        go :: Int -> [Integer] -> IO [Double]
-        go cases curSums
-         | Just n <- mbMaxIter, n < curRound
-         = do progress "\n"
-              progress "Maximum iteration count reached, stopping.\n"
-              return curEVs
-         | True
-         = do g <- newStdGen
-              t <- runOnce g
-              let newSums  = zipWith (+) curSums t
-                  newEVs = map ev' newSums
-                  diffs  = zipWith (\x y -> abs (x - y)) newEVs curEVs
-              if all (< epsilon) diffs
-                 then do progress $ "Converges with epsilon " ++ show epsilon ++ " after " ++ show curRound ++ " rounds.\n"
-                         return newEVs
-                 else do progress $ "Tuning, round: " ++ show curRound ++ " (margin: " ++ showFFloat (Just 6) (maximum (0:diffs)) "" ++ ")"
-                         go newCases newSums
-         where curRound = cases - warmupCount
-               newCases = cases + 1
-               ev, ev' :: Integer -> Double
-               ev  x  = fromIntegral x / fromIntegral cases
-               ev' x  = fromIntegral x / fromIntegral newCases
-               curEVs = map ev curSums
-
--- | Given a symbolic computation that produces a value, compute the
--- expected value that value would take if this computation is run
--- with its free variables drawn from uniform distributions of its
--- respective values, satisfying the given constraints specified by
--- 'constrain' and 'pConstrain' calls. This is equivalent to calling
--- 'expectedValueWith' the following parameters: verbose, warm-up
--- round count of @10000@, no maximum iteration count, and with
--- convergence margin @0.0001@.
-expectedValue :: Outputtable a => Symbolic a -> IO [Double]
-expectedValue = expectedValueWith True 10000 Nothing 0.0001
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,53 +1,64 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Tools.GenTest
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Tools.GenTest
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Test generation from symbolic programs
 -----------------------------------------------------------------------------
 
-module Data.SBV.Tools.GenTest (genTest, TestVectors, getTestValues, renderTest, TestStyle(..)) where
+{-# OPTIONS_GHC -Wall -Werror #-}
 
+module Data.SBV.Tools.GenTest (
+        -- * Test case generation
+        genTest, TestVectors, getTestValues, renderTest, TestStyle(..)
+        ) where
+
+import Control.Monad (unless)
+
 import Data.Bits     (testBit)
 import Data.Char     (isAlpha, toUpper)
 import Data.Function (on)
 import Data.List     (intercalate, groupBy)
 import Data.Maybe    (fromMaybe)
-import System.Random
+import qualified Data.Text as T
 
-import Data.SBV.BitVectors.AlgReals
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Data
 
+import Data.SBV.Utils.PrettyNum
+import Data.SBV.Provers.Prover(defaultSMTCfg)
+
+import qualified Data.Foldable as F (toList)
+
 -- | Type of test vectors (abstract)
-newtype TestVectors = TV [([CW], [CW])]
+newtype TestVectors = TV [([CV], [CV])]
 
 -- | Retrieve the test vectors for further processing. This function
 -- is useful in cases where 'renderTest' is not sufficient and custom
 -- output (or further preprocessing) is needed.
-getTestValues :: TestVectors -> [([CW], [CW])]
+getTestValues :: TestVectors -> [([CV], [CV])]
 getTestValues (TV vs) = vs
 
 -- | Generate a set of concrete test values from a symbolic program. The output
 -- can be rendered as test vectors in different languages as necessary. Use the
 -- function 'output' call to indicate what fields should be in the test result.
--- (Also see 'constrain' and 'pConstrain' for filtering acceptable test values.)
+-- (Also see 'constrain' for filtering acceptable test values.)
 genTest :: Outputtable a => Int -> Symbolic a -> IO TestVectors
 genTest n m = gen 0 []
   where gen i sofar
-         | i == n = return $ TV $ reverse sofar
-         | True   = do g <- newStdGen
-                       t <- tc g
+         | i == n = pure $ TV $ reverse sofar
+         | True   = do t <- tc
                        gen (i+1) (t:sofar)
-        tc g = do (_, Result _ tvals _ _ cs _ _ _ _ _ cstrs _ os) <- runSymbolic' (Concrete g) (m >>= output)
-                  let cval = fromMaybe (error "Cannot generate tests in the presence of uninterpeted constants!") . (`lookup` cs)
-                      cond = all (cwToBool . cval) cstrs
-                  if cond
-                     then return (map snd tvals, map cval os)
-                     else tc g  -- try again, with the same set of constraints
+        tc = do (_, Result {resTraces=tvals, resConsts=(_, cs), resDefinitions=definitions, resConstraints=cstrs, resOutputs=os}) <- runSymbolic defaultSMTCfg (Concrete Nothing) (m >>= output)
+                let cval = fromMaybe (error "Cannot generate tests in the presence of uninterpreted constants!") . (`lookup` cs)
+                    cond = and [cvToBool (cval v) | (False, _, v) <- F.toList cstrs] -- Only pick-up "hard" constraints, as indicated by False in the fist component
+                unless (null definitions) $ error "Cannot generate tests in the presence of 'smtFunction' calls!"
+                if cond
+                   then pure (map snd tvals, map cval os)
+                   else tc   -- try again, with the same set of constraints
 
 -- | Test output style
 data TestStyle = Haskell String                     -- ^ As a Haskell value with given name
@@ -62,7 +73,7 @@
 renderTest (C n)          (TV vs) = c       n vs
 renderTest (Forte n b ss) (TV vs) = forte   n b ss vs
 
-haskell :: String -> [([CW], [CW])] -> String
+haskell :: String -> [([CV], [CV])] -> String
 haskell vname vs = intercalate "\n" $ [ "-- Automatically generated by SBV. Do not edit!"
                                       , ""
                                       , "module " ++ modName ++ "(" ++ n ++ ") where"
@@ -72,9 +83,11 @@
                                    ++ [ n ++ " :: " ++ getType vs
                                       , n ++ " = [ " ++ intercalate ("\n" ++ pad ++  ", ") (map mkLine vs), pad ++ "]"
                                       ]
-  where n | null vname                 = "testVectors"
-          | not (isAlpha (head vname)) = "tv" ++ vname
-          | True                       = vname
+  where n = case vname of
+              ""                    -> "testVectors"
+              f:_ | not (isAlpha f) -> "tv" ++ vname
+                  | True            -> vname
+
         imports
           | null vs               = []
           | needsInt && needsWord = ["import Data.Int", "import Data.Word", ""]
@@ -82,26 +95,27 @@
           | needsWord             = ["import Data.Word", ""]
           | needsRatio            = ["import Data.Ratio"]
           | True                  = []
-          where ((is, os):_) = vs
-                params       = is ++ os
+          where params       = case vs of { (is, os):_ -> is ++ os; _ -> error "SBV.renderTest: impossible, empty test vectors" }
                 needsInt     = any isSW params
                 needsWord    = any isUW params
                 needsRatio   = any isR params
-                isR cw       = case kindOf cw of
+                isR cv       = case kindOf cv of
                                  KReal -> True
                                  _     -> False
-                isSW cw      = case kindOf cw of
+                isSW cv      = case kindOf cv of
                                  KBounded True _ -> True
                                  _               -> False
-                isUW cw      = case kindOf cw of
+                isUW cv      = case kindOf cv of
                                  KBounded False sz -> sz > 1
                                  _                 -> False
-        modName = let (f:r) = n in toUpper f : r
+        modName = case n of
+                    f:r -> toUpper f : r
+                    _   -> error "SBV.renderTest: impossible, empty module name"
         pad = replicate (length n + 3) ' '
         getType []         = "[a]"
         getType ((i, o):_) = "[(" ++ mapType typeOf i ++ ", " ++ mapType typeOf o ++ ")]"
         mkLine  (i, o)     = "("  ++ mapType valOf  i ++ ", " ++ mapType valOf  o ++ ")"
-        mapType f cws = mkTuple $ map f $ groupBy ((==) `on` kindOf) cws
+        mapType f cvs = mkTuple $ map f $ groupBy ((==) `on` kindOf) cvs
         mkTuple [x] = x
         mkTuple xs  = "(" ++ intercalate ", " xs ++ ")"
         typeOf []    = "()"
@@ -110,7 +124,8 @@
         valOf  []    = "()"
         valOf  [x]   = s x
         valOf  xs    = "[" ++ intercalate ", " (map s xs) ++ "]"
-        t cw = case kindOf cw of
+
+        t cv = case kindOf cv of
                  KBool             -> "Bool"
                  KBounded False 8  -> "Word8"
                  KBounded False 16 -> "Word16"
@@ -123,19 +138,34 @@
                  KUnbounded        -> "Integer"
                  KFloat            -> "Float"
                  KDouble           -> "Double"
-                 KReal             -> error $ "SBV.renderTest: Unsupported real valued test value: " ++ show cw
-                 KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
-                 _                 -> error $ "SBV.renderTest: Unexpected CW: " ++ show cw
-        s cw = case kindOf cw of
-                  KBool             -> take 5 (show (cwToBool cw) ++ repeat ' ')
-                  KBounded sgn   sz -> let CWInteger w = cwVal cw in shex  False True (sgn, sz) w
-                  KUnbounded        -> let CWInteger w = cwVal cw in shexI False True           w
-                  KFloat            -> let CWFloat w   = cwVal cw in showHFloat w
-                  KDouble           -> let CWDouble w  = cwVal cw in showHDouble w
-                  KReal             -> let CWAlgReal w = cwVal cw in algRealToHaskell w
-                  KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
+                 KChar             -> error "SBV.renderTest: Unsupported char"
+                 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 ++ "}"
+                 _                 -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
 
-c :: String -> [([CW], [CW])] -> String
+        s cv = case kindOf cv of
+                  KVar{}            -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
+                  KBool             -> take 5 (show (cvToBool cv) ++ repeat ' ')
+                  KBounded sgn   sz -> case cvVal cv of { CInteger w -> T.unpack $ shex  False True (sgn, sz) w; r -> bad r }
+                  KUnbounded        -> case cvVal cv of { CInteger w -> T.unpack $ shexI False True           w; r -> bad r }
+                  KFloat            -> case cvVal cv of { CFloat   w -> showHFloat w;                            r -> bad r }
+                  KDouble           -> case cvVal cv of { CDouble  w -> showHDouble w;                           r -> bad r }
+                  KRational         -> error "SBV.renderTest: Unsupported rational number"
+                  KFP{}             -> error "SBV.renderTest: Unsupported arbitrary float"
+                  KChar             -> error "SBV.renderTest: Unsupported char"
+                  KString           -> error "SBV.renderTest: Unsupported string"
+                  KReal             -> case cvVal cv of { CAlgReal w -> algRealToHaskell w; r -> bad r }
+                  KList es          -> error $ "SBV.renderTest: Unsupported list valued sort: [" ++ show es ++ "]"
+                  KSet  es          -> error $ "SBV.renderTest: Unsupported set valued sort: {" ++ show es ++ "}"
+                  k@KApp{}          -> error $ "SBV.renderTest: Unsupported adt app: " ++ show k
+                  k@KADT{}          -> error $ "SBV.renderTest: Unsupported adt: "     ++ show k
+                  k@KTuple{}        -> error $ "SBV.renderTest: Unsupported tuple: "   ++ show k
+                  k@KArray{}        -> error $ "SBV.renderTest: Unsupported array: "   ++ show k
+               where bad _ = error $ "SBV.renderTest: Unexpected CVal for kind: " ++ show (kindOf cv)
+
+c :: String -> [([CV], [CV])] -> String
 c n vs = intercalate "\n" $
               [ "/* Automatically generated by SBV. Do not edit! */"
               , ""
@@ -156,13 +186,13 @@
               , "typedef double SDouble;"
               , ""
               , "/* Unsigned bit-vectors */"
-              , "typedef uint8_t  SWord8 ;"
+              , "typedef uint8_t  SWord8;"
               , "typedef uint16_t SWord16;"
               , "typedef uint32_t SWord32;"
               , "typedef uint64_t SWord64;"
               , ""
               , "/* Signed bit-vectors */"
-              , "typedef int8_t  SInt8 ;"
+              , "typedef int8_t  SInt8;"
               , "typedef int16_t SInt16;"
               , "typedef int32_t SInt32;"
               , "typedef int64_t SInt64;"
@@ -170,11 +200,15 @@
               , "typedef struct {"
               , "  struct {"
               ]
-           ++ (if null vs then [] else zipWith (mkField "i") (fst (head vs)) [(0::Int)..])
+           ++ (case vs of
+                 []       -> []
+                 (i, _):_ -> zipWith (mkField "i") i [(0::Int)..])
            ++ [ "  } input;"
               , "  struct {"
               ]
-           ++ (if null vs then [] else zipWith (mkField "o") (snd (head vs)) [(0::Int)..])
+           ++ (case vs of
+                 []       -> []
+                 (_, o):_ -> zipWith (mkField "o") o [(0::Int)..])
            ++ [ "  } output;"
               , "} " ++ n ++ "TestVector;"
               , ""
@@ -197,8 +231,9 @@
               , "  return 0;"
               , "}"
               ]
-  where mkField p cw i = "    " ++ t ++ " " ++ p ++ show i ++ ";"
-            where t = case kindOf cw of
+  where mkField p cv i = "    " ++ t ++ " " ++ p ++ show i ++ ";"
+            where t = case kindOf cv of
+                        KVar{}            -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
                         KBool             -> "SBool"
                         KBounded False 8  -> "SWord8"
                         KBounded False 16 -> "SWord16"
@@ -208,34 +243,61 @@
                         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"
+                        KRational         -> error "SBV.renderTest: Unsupported rational number"
+                        KFP{}             -> error "SBV.renderTest: Unsupported arbitrary float"
+                        KChar             -> error "SBV.renderTest: Unsupported char"
+                        KString           -> error "SBV.renderTest: Unsupported string"
                         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."
-                        KUserSort us _    -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
-                        _                 -> error $ "SBV.renderTest: Unexpected CW: " ++ show cw
+                        k@KApp{}          -> error $ "SBV.renderTest: Unsupported adt app: "     ++ show k
+                        k@KADT{}          -> error $ "SBV.renderTest: Unsupported adt: "         ++ show k
+                        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@KArray{}        -> error $ "SBV.renderTest: Unsupported array sort: "  ++ show k
+
         mkLine (is, os) = "{{" ++ intercalate ", " (map v is) ++ "}, {" ++ intercalate ", " (map v os) ++ "}}"
-        v cw = case kindOf cw of
-                  KBool           -> if cwToBool cw then "true " else "false"
-                  KBounded sgn sz -> let CWInteger w = cwVal cw in shex  False True (sgn, sz) w
-                  KUnbounded      -> let CWInteger w = cwVal cw in shexI False True           w
-                  KFloat          -> let CWFloat w   = cwVal cw in showCFloat w
-                  KDouble         -> let CWDouble w  = cwVal cw in showCDouble w
-                  KUserSort us _  -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
+
+        v cv = case kindOf cv of
+                  KVar{}          -> error $ "SBV.renderTest: Unexpected: " ++ show (kindOf cv)
+                  KBool           -> if cvToBool cv then "true " else "false"
+                  KBounded sgn sz -> case cvVal cv of { CInteger w -> T.unpack $ chex  False True (sgn, sz) w; r -> bad r }
+                  KUnbounded      -> case cvVal cv of { CInteger w -> T.unpack $ shexI False True           w; r -> bad r }
+                  KFloat          -> case cvVal cv of { CFloat w   -> showCFloat w;                            r -> bad r }
+                  KDouble         -> case cvVal cv of { CDouble w  -> showCDouble w;                           r -> bad r }
+                  KRational       -> error "SBV.renderTest: Unsupported rational number"
+                  KFP{}           -> error "SBV.renderTest: Unsupported arbitrary float"
+                  KChar           -> error "SBV.renderTest: Unsupported char"
+                  KString         -> error "SBV.renderTest: Unsupported string"
                   KReal           -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
+                  k@KList{}       -> error $ "SBV.renderTest: Unsupported list sort!"           ++ show k
+                  k@KSet{}        -> error $ "SBV.renderTest: Unsupported set sort!"            ++ show k
+                  k@KApp{}        -> error $ "SBV.renderTest: Unsupported adt app: "            ++ show k
+                  k@KADT{}        -> error $ "SBV.renderTest: Unsupported adt: "                ++ show k
+                  k@KTuple{}      -> error $ "SBV.renderTest: Unsupported tuple sort: "         ++ show k
+                  k@KArray{}      -> error $ "SBV.renderTest: Unsupported sum sort: "           ++ show k
+               where bad _ = error $ "SBV.renderTest: Unexpected CVal for kind: " ++ show (kindOf cv)
+
         outLine
           | null vs = "printf(\"\");"
           | True    = "printf(\"%*d. " ++ fmtString ++ "\\n\", " ++ show (length (show (length vs - 1))) ++ ", i"
                     ++ concatMap ("\n           , " ++ ) (zipWith inp is [(0::Int)..] ++ zipWith out os [(0::Int)..])
                     ++ ");"
-          where (is, os) = head vs
-                inp cw i = mkBool cw (n ++ "[i].input.i"  ++ show i)
-                out cw i = mkBool cw (n ++ "[i].output.o" ++ show i)
-                mkBool cw s = case kindOf cw of
+          where (is, os) = case vs of
+                             h:_ -> h
+                             _   -> error "outLine: Impossible hapepned, empty vs!"
+
+                inp cv i = mkBool cv (n ++ "[i].input.i"  ++ show i)
+                out cv i = mkBool cv (n ++ "[i].output.o" ++ show i)
+                mkBool cv s = case kindOf cv of
                                 KBool -> "(" ++ s ++ " == true) ? \"true \" : \"false\""
                                 _     -> s
                 fmtString = unwords (map fmt is) ++ " -> " ++ unwords (map fmt os)
-        fmt cw = case kindOf cw of
+
+        fmt cv = case kindOf cv of
                     KBool             -> "%s"
                     KBounded False  8 -> "0x%02\"PRIx8\""
                     KBounded False 16 -> "0x%04\"PRIx16\"U"
@@ -247,11 +309,13 @@
                     KBounded True  64 -> "%\"PRId64\"LL"
                     KFloat            -> "%f"
                     KDouble           -> "%f"
+                    KChar             -> error "SBV.renderTest: Unsupported char"
+                    KString           -> error "SBV.renderTest: Unsupported string"
                     KUnbounded        -> error "SBV.renderTest: Unsupported unbounded integers for C generation."
                     KReal             -> error "SBV.renderTest: Unsupported real valued values for C generation."
-                    _                 -> error $ "SBV.renderTest: Unexpected CW: " ++ show cw
+                    _                 -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
 
-forte :: String -> Bool -> ([Int], [Int]) -> [([CW], [CW])] -> String
+forte :: String -> Bool -> ([Int], [Int]) -> [([CV], [CV])] -> String
 forte vname bigEndian ss vs = intercalate "\n" $ [ "// Automatically generated by SBV. Do not edit!"
                                              , "let " ++ n ++ " ="
                                              , "   let c s = val [_, r] = str_split s \"'\" in " ++ blaster
@@ -259,34 +323,53 @@
                                           ++ [ "   in [ " ++ intercalate "\n      , " (map mkLine vs)
                                              , "      ];"
                                              ]
-  where n | null vname                 = "testVectors"
-          | not (isAlpha (head vname)) = "tv" ++ vname
-          | True                       = vname
+  where n = case vname of
+              ""                    -> "testVectors"
+              f:_ | not (isAlpha f) -> "tv" ++ vname
+                  | True            -> vname
+
         blaster
          | bigEndian = "map (\\s. s == \"1\") (explode (string_tl r))"
          | True      = "rev (map (\\s. s == \"1\") (explode (string_tl r)))"
+
         toF True  = '1'
         toF False = '0'
-        blast cw = case kindOf cw of
-                     KBool             -> [toF (cwToBool cw)]
-                     KBounded False 8  -> xlt  8 (cwVal cw)
-                     KBounded False 16 -> xlt 16 (cwVal cw)
-                     KBounded False 32 -> xlt 32 (cwVal cw)
-                     KBounded False 64 -> xlt 64 (cwVal cw)
-                     KBounded True 8   -> xlt  8 (cwVal cw)
-                     KBounded True 16  -> xlt 16 (cwVal cw)
-                     KBounded True 32  -> xlt 32 (cwVal cw)
-                     KBounded True 64  -> xlt 64 (cwVal cw)
-                     KFloat            -> error "SBV.renderTest: Float values are not supported when generating Forte test-cases."
-                     KDouble           -> error "SBV.renderTest: Double values are not supported when generating Forte test-cases."
-                     KReal             -> error "SBV.renderTest: Real values are not supported when generating Forte test-cases."
-                     KUnbounded        -> error "SBV.renderTest: Unbounded integers are not supported when generating Forte test-cases."
-                     _                 -> error $ "SBV.renderTest: Unexpected CW: " ++ show cw
-        xlt s (CWInteger v)   = [toF (testBit v i) | i <- [s-1, s-2 .. 0]]
-        xlt _ (CWFloat r)     = error $ "SBV.renderTest.Forte: Unexpected float value: " ++ show r
-        xlt _ (CWDouble r)    = error $ "SBV.renderTest.Forte: Unexpected double value: " ++ show r
-        xlt _ (CWAlgReal r)   = error $ "SBV.renderTest.Forte: Unexpected real value: " ++ show r
-        xlt _ (CWUserSort r)  = error $ "SBV.renderTest.Forte: Unexpected uninterpreted value: " ++ show r
+
+        blast cv = let noForte w = error "SBV.renderTest: " ++ w ++ " values are not supported when generating Forte test-cases."
+                   in case kindOf cv of
+                        KBool             -> [toF (cvToBool cv)]
+                        KBounded False 8  -> xlt  8 (cvVal cv)
+                        KBounded False 16 -> xlt 16 (cvVal cv)
+                        KBounded False 32 -> xlt 32 (cvVal cv)
+                        KBounded False 64 -> xlt 64 (cvVal cv)
+                        KBounded True 8   -> xlt  8 (cvVal cv)
+                        KBounded True 16  -> xlt 16 (cvVal cv)
+                        KBounded True 32  -> xlt 32 (cvVal cv)
+                        KBounded True 64  -> xlt 64 (cvVal cv)
+                        KFloat            -> noForte "Float"
+                        KDouble           -> noForte "Double"
+                        KChar             -> noForte "Char"
+                        KString           -> noForte "String"
+                        KReal             -> noForte "Real"
+                        KList ek          -> noForte $ "List of " ++ show ek
+                        KSet  ek          -> noForte $ "Set of " ++ show ek
+                        KUnbounded        -> noForte "Unbounded integers"
+                        _                 -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
+
+        xlt s (CInteger  v)  = [toF (testBit v i) | i <- [s-1, s-2 .. 0]]
+        xlt _ (CFloat    r)  = error $ "SBV.renderTest.Forte: Unexpected float value: "            ++ show r
+        xlt _ (CDouble   r)  = error $ "SBV.renderTest.Forte: Unexpected double value: "           ++ show r
+        xlt _ (CFP       r)  = error $ "SBV.renderTest.Forte: Unexpected arbitrary float value: "  ++ show r
+        xlt _ (CRational r)  = error $ "SBV.renderTest.Forte: Unexpected rational  value: "        ++ show r
+        xlt _ (CChar     r)  = error $ "SBV.renderTest.Forte: Unexpected char value: "             ++ show r
+        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 _ (CADT (k, _))  = error $ "SBV.renderTest.Forte: Unexpected ADT value: "              ++ show k
+        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 _ CArray{}       = error   "SBV.renderTest.Forte: Unexpected array value!"
+
         mkLine  (i, o) = "("  ++ mkTuple (form (fst ss) (concatMap blast i)) ++ ", " ++ mkTuple (form (snd ss) (concatMap blast o)) ++ ")"
         mkTuple []  = "()"
         mkTuple [x] = x
@@ -294,10 +377,10 @@
         form []     [] = []
         form []     bs = error $ "SBV.renderTest: Mismatched index in stream, extra " ++ show (length bs) ++ " bit(s) remain."
         form (i:is) bs
-          | length bs < i = error $ "SBV.renderTest: Mismatched index in stream, was looking for " ++ show i ++ " bit(s), but only " ++ show i ++ " remains."
-          | i == 1        = let b:r = bs
-                                v   = if b == '1' then "T" else "F"
-                            in v : form is r
+          | length bs < i = error $ "SBV.renderTest: Mismatched index in stream, was looking for " ++ show i ++ " bit(s), but only " ++ show bs ++ " remains."
+          | i == 1        = case bs of
+                              b:r -> (if b == '1' then "T" else "F") : form is r
+                              _   -> error "SBV.renderTest: impossible, empty bit stream"
           | True          = let (f, r) = splitAt i bs
                                 v      = "c \"" ++ show i ++ "'b" ++ f ++ "\""
                             in v : form is r
diff --git a/Data/SBV/Tools/Induction.hs b/Data/SBV/Tools/Induction.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/Induction.hs
@@ -0,0 +1,154 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.Induction
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Induction engine for state transition systems. See the following examples
+-- for details:
+--
+--   * "Documentation.SBV.Examples.ProofTools.Strengthen": Use of strengthening
+--     to establish inductive invariants.
+--
+--   * "Documentation.SBV.Examples.ProofTools.Sum": Proof for correctness of
+--     an algorithm to sum up numbers,
+--
+--   * "Documentation.SBV.Examples.ProofTools.Fibonacci": Proof for correctness of
+--     an algorithm to fast-compute fibonacci numbers, using axiomatization.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies     #-}
+{-# LANGUAGE TypeOperators    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.Induction (
+         InductionResult(..), InductionStep(..), induct, inductWith
+       ) where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.List     (intercalate)
+import Control.Monad (when)
+
+-- | A step in an inductive proof. If the tag is present (i.e., @Just nm@), then
+-- the step belongs to the subproof that establishes the strengthening named @nm@.
+data InductionStep = Initiation  (Maybe String)
+                   | Consecution (Maybe String)
+                   | PartialCorrectness
+
+-- | Show instance for 'InductionStep', diagnostic purposes only.
+instance Show InductionStep where
+   show (Initiation  Nothing)  = "initiation"
+   show (Initiation  (Just s)) = "initiation for strengthening " ++ show s
+   show (Consecution Nothing)  = "consecution"
+   show (Consecution (Just s)) = "consecution for strengthening " ++ show s
+   show PartialCorrectness     = "partial correctness"
+
+-- | Result of an inductive proof, with a counter-example in case of failure.
+--
+-- If a proof is found (indicated by a 'Proven' result), then the invariant holds
+-- and the goal is established once the termination condition holds. If it fails, then
+-- it can fail either in an initiation step or in a consecution step:
+--
+--    * A 'Failed' result in an 'Initiation' step means that the invariant does /not/ hold for
+--      the initial state, and thus indicates a true failure.
+--
+--    * A 'Failed' result in a 'Consecution' step will return a state /s/. This state is known as a
+--      CTI (counterexample to inductiveness): It will lead to a violation of the invariant
+--      in one step. However, this does not mean the property is invalid: It could be the
+--      case that it is simply not inductive. In this case, human intervention---or a smarter
+--      algorithm like IC3 for certain domains---is needed to see if one can strengthen the
+--      invariant so an inductive proof can be found. How this strengthening can be done remains
+--      an art, but the science is improving with algorithms like IC3.
+--
+--    * A 'Failed' result in a 'PartialCorrectness' step means that the invariant holds, but assuming the
+--      termination condition the goal still does not follow. That is, the partial correctness
+--      does not hold.
+data InductionResult a = Failed InductionStep (a, a)
+                       | Proven
+
+-- | Show instance for 'InductionResult', diagnostic purposes only.
+instance Show a => Show (InductionResult a) where
+  show Proven       = "Q.E.D."
+  show (Failed s e) = intercalate "\n" [ "Failed while establishing " ++ show s ++ "."
+                                       , "Counter-example to inductiveness:"
+                                       , intercalate "\n" ["  " ++ l | l <- lines (show e)]
+                                       ]
+
+-- | Induction engine, using the default solver. See "Documentation.SBV.Examples.ProofTools.Strengthen"
+-- and "Documentation.SBV.Examples.ProofTools.Sum" for examples.
+induct :: (Show res, Queriable IO st, res ~ QueryResult st)
+       => Bool                             -- ^ Verbose mode
+       -> Symbolic ()                      -- ^ Setup code, if necessary. (Typically used for 'Data.SBV.setOption' calls. Pass @pure ()@ if not needed.)
+       -> (st -> SBool)                    -- ^ Initial condition
+       -> (st -> st -> SBool)              -- ^ Transition relation
+       -> [(String, st -> SBool)]          -- ^ Strengthenings, if any. The @String@ is a simple tag.
+       -> (st -> SBool)                    -- ^ Invariant that ensures the goal upon termination
+       -> (st -> (SBool, SBool))           -- ^ Termination condition and the goal to establish
+       -> IO (InductionResult res)         -- ^ Either proven, or a concrete state value that, if reachable, fails the invariant.
+induct = inductWith defaultSMTCfg
+
+-- | Induction engine, configurable with the solver
+inductWith :: (Show res, Queriable IO st, res ~ QueryResult st)
+           => SMTConfig
+           -> Bool
+           -> Symbolic ()
+           -> (st -> SBool)
+           -> (st -> st -> SBool)
+           -> [(String, st -> SBool)]
+           -> (st -> SBool)
+           -> (st -> (SBool, SBool))
+           -> IO (InductionResult res)
+inductWith cfg chatty setup initial trans strengthenings inv goal =
+     try "Proving initiation"
+         (\s _ -> initial s .=> inv s)
+         (Failed (Initiation Nothing))
+         $ strengthen strengthenings
+         $ try "Proving consecution"
+               (\s s' -> sAnd (inv s : s `trans` s' : [st s | (_, st) <- strengthenings]) .=> inv s')
+               (Failed (Consecution Nothing))
+               $ try "Proving partial correctness"
+                     (\s _ -> let (term, result) = goal s in inv s .&& term .=> result)
+                     (Failed PartialCorrectness)
+                     (msg "Done" >> pure Proven)
+
+  where msg = when chatty . putStrLn
+
+        try m p wrap cont = do msg m
+                               res <- check p
+                               case res of
+                                 Just ex -> pure $ wrap ex
+                                 Nothing -> cont
+
+        check p = runSMTWith cfg $ do
+                        setup
+                        query $ do s  <- create
+                                   s' <- create
+                                   constrain $ sNot (p s s')
+
+                                   cs <- checkSat
+                                   case cs of
+                                     Unk    -> error "Solver said unknown"
+                                     DSat{} -> error "Solver returned a delta-sat result"
+                                     Unsat  -> pure Nothing
+                                     Sat    -> do io $ msg "Failed in state:"
+                                                  exS  <- project s
+                                                  io $ msg $ show exS
+                                                  io $ msg "Transitioning to:"
+                                                  exS' <- project s'
+                                                  io $ msg $ show exS'
+                                                  pure $ Just (exS, exS')
+
+        strengthen []             cont = cont
+        strengthen ((nm, st):sts) cont = try ("Proving strengthening initiation  : " ++ nm)
+                                             (\s _ -> initial s .=> st s)
+                                             (Failed (Initiation (Just nm)))
+                                             $ try ("Proving strengthening consecution: " ++ nm)
+                                                   (\s s' -> sAnd [st s, s `trans` s'] .=> st s')
+                                                   (Failed (Consecution (Just nm)))
+                                                   (strengthen sts cont)
diff --git a/Data/SBV/Tools/Optimize.hs b/Data/SBV/Tools/Optimize.hs
deleted file mode 100644
--- a/Data/SBV/Tools/Optimize.hs
+++ /dev/null
@@ -1,108 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Tools.Optimize
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- SMT based optimization
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
-module Data.SBV.Tools.Optimize (OptimizeOpts(..), optimize, optimizeWith, minimize, minimizeWith, maximize, maximizeWith) where
-
-import Data.Maybe (fromJust)
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model (OrdSymbolic(..), EqSymbolic(..))
-import Data.SBV.Provers.Prover   (satWith, defaultSMTCfg)
-import Data.SBV.SMT.SMT          (SatModel, getModel)
-import Data.SBV.Utils.Boolean
-
--- | Optimizer configuration. Note that iterative and quantified approaches are in general not interchangeable.
--- For instance, iterative solutions will loop infinitely when there is no optimal value, but quantified solutions
--- can handle such problems. Of course, quantified problems are harder for SMT solvers, naturally.
-data OptimizeOpts = Iterative  Bool   -- ^ Iteratively search. if True, it will be reporting progress
-                  | Quantified        -- ^ Use quantifiers
-
--- | Symbolic optimization. Generalization on 'minimize' and 'maximize' that allows arbitrary
--- cost functions and comparisons.
-optimizeWith :: (SatModel a, SymWord a, Show a, SymWord c, Show c)
-             => SMTConfig                         -- ^ SMT configuration
-             -> OptimizeOpts                      -- ^ Optimization options
-             -> (SBV c -> SBV c -> SBool)         -- ^ comparator
-             -> ([SBV a] -> SBV c)                -- ^ cost function
-             -> Int                               -- ^ how many elements?
-             -> ([SBV a] -> SBool)                -- ^ validity constraint
-             -> IO (Maybe [a])
-optimizeWith cfg (Iterative chatty) = iterOptimize chatty cfg
-optimizeWith cfg Quantified         = quantOptimize cfg
-
--- | Variant of 'optimizeWith' using the default solver. See 'optimizeWith' for parameter descriptions.
-optimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c) => OptimizeOpts -> (SBV c -> SBV c -> SBool) -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-optimize = optimizeWith defaultSMTCfg
-
--- | Variant of 'maximize' allowing the use of a user specified solver. See 'optimizeWith' for parameter descriptions.
-maximizeWith :: (SatModel a, SymWord a, Show a, SymWord c, Show c) => SMTConfig -> OptimizeOpts -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-maximizeWith cfg opts = optimizeWith cfg opts (.>=)
-
--- | Maximizes a cost function with respect to a constraint. Examples:
---
---   >>> maximize Quantified sum 3 (bAll (.< (10 :: SInteger)))
---   Just [9,9,9]
-maximize :: (SatModel a, SymWord a, Show a, SymWord c, Show c) => OptimizeOpts -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-maximize = maximizeWith defaultSMTCfg
-
--- | Variant of 'minimize' allowing the use of a user specified solver. See 'optimizeWith' for parameter descriptions.
-minimizeWith :: (SatModel a, SymWord a, Show a, SymWord c, Show c) => SMTConfig -> OptimizeOpts -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-minimizeWith cfg opts = optimizeWith cfg opts (.<=)
-
--- | Minimizes a cost function with respect to a constraint. Examples:
---
---   >>> minimize Quantified sum 3 (bAll (.> (10 :: SInteger)))
---   Just [11,11,11]
-minimize :: (SatModel a, SymWord a, Show a, SymWord c, Show c) => OptimizeOpts -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-minimize = minimizeWith defaultSMTCfg
-
--- | Optimization using quantifiers
-quantOptimize :: (SatModel a, SymWord a) => SMTConfig -> (SBV c -> SBV c -> SBool) -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-quantOptimize cfg cmp cost n valid = do
-           m <- satWith cfg $ do xs <- mkExistVars  n
-                                 ys <- mkForallVars n
-                                 return $ valid xs &&& (valid ys ==> cost xs `cmp` cost ys)
-           case getModel m of
-              Right (True, _)  -> error "SBV: Backend solver reported \"unknown\""
-              Right (False, a) -> return $ Just a
-              Left _           -> return Nothing
-
--- | Optimization using iteration
-iterOptimize :: (SatModel a, Show a, SymWord a, Show c, SymWord c) =>  Bool -> SMTConfig -> (SBV c -> SBV c -> SBool) -> ([SBV a] -> SBV c) -> Int -> ([SBV a] -> SBool) -> IO (Maybe [a])
-iterOptimize chatty cfg cmp cost n valid = do
-        msg "Trying to find a satisfying solution."
-        m <- satWith cfg $ valid `fmap` mkExistVars n
-        case getModel m of
-          Left _ -> do msg "No satisfying solutions found."
-                       return Nothing
-          Right (True, _)  -> error "SBV: Backend solver reported \"unknown\""
-          Right (False, a) -> do msg $ "First solution found: " ++ show a
-                                 let c = cost (map literal a)
-                                 msg $ "Initial value is    : " ++ show (fromJust (unliteral c))
-                                 msg "Starting iterative search."
-                                 go (1::Int) a c
-  where msg m | chatty = putStrLn $ "*** " ++ m
-              | True   = return ()
-        go i curSol curCost = do
-                msg $ "Round " ++ show i ++ " ****************************"
-                m <- satWith cfg $ do xs <- mkExistVars n
-                                      return $ let c = cost xs in valid xs &&& (c `cmp` curCost &&& c ./= curCost)
-                case getModel m of
-                  Left _ -> do msg "The current solution is optimal. Terminating search."
-                               return $ Just curSol
-                  Right (True, _)  -> error "SBV: Backend solver reported \"unknown\""
-                  Right (False, a) -> do msg $ "Solution: " ++ show a
-                                         let c = cost (map literal a)
-                                         msg $ "Value   : " ++ show (fromJust (unliteral c))
-                                         go (i+1) a c
diff --git a/Data/SBV/Tools/Overflow.hs b/Data/SBV/Tools/Overflow.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/Overflow.hs
@@ -0,0 +1,376 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.Overflow
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implementation of overflow detection functions.
+-- Based on: <http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/z3prefix.pdf>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                  #-}
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE ImplicitParams       #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeOperators        #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.Overflow (
+         -- * Arithmetic overflows
+         ArithOverflow(..), CheckedArithmetic(..)
+
+         -- * Fast-checking of signed-multiplication overflow
+         , signedMulOverflow
+
+         -- * Cast overflows
+         , sFromIntegralO, sFromIntegralChecked
+    ) where
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Model
+import Data.SBV.Core.Operations
+
+import GHC.TypeLits
+
+import GHC.Stack
+
+import Data.Int
+import Data.Word
+import Data.Proxy
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Detecting overflow. Each function here will return 'sTrue' if the result will not fit in the target
+-- type, i.e., if it overflows or underflows.
+class ArithOverflow a where
+  -- | Bit-vector addition. Unsigned addition can only overflow. Signed addition can underflow and overflow.
+  --
+  -- A tell tale sign of unsigned addition overflow is when the sum is less than minimum of the arguments.
+  --
+  -- >>> prove $ \x y -> bvAddO x (y::SWord16) .<=> x + y .< x `smin` y
+  -- Q.E.D.
+  bvAddO :: a -> a -> SBool
+
+  -- | Bit-vector subtraction. Unsigned subtraction can only underflow. Signed subtraction can underflow and overflow.
+  bvSubO :: a -> a -> SBool
+
+  -- | Bit-vector multiplication. Unsigned multiplication can only overflow. Signed multiplication can underflow and overflow.
+  bvMulO :: a -> a -> SBool
+
+  -- | Bit-vector division. Unsigned division neither underflows nor overflows. Signed division can only overflow. In fact, for each
+  -- signed bitvector type, there's precisely one pair that overflows, when @x@ is @minBound@ and @y@ is @-1@:
+  --
+  -- >>> allSat $ \x y -> x `bvDivO` (y::SInt8)
+  -- Solution #1:
+  --   s0 = -128 :: Int8
+  --   s1 =   -1 :: Int8
+  -- This is the only solution.
+  bvDivO :: a -> a -> SBool
+
+  -- | Bit-vector negation. Unsigned negation neither underflows nor overflows. Signed negation can only overflow, when the argument is
+  -- @minBound@:
+  --
+  -- >>> prove $ \x -> x .== minBound .<=> bvNegO (x::SInt16)
+  -- Q.E.D.
+  bvNegO :: a -> SBool
+
+instance ArithOverflow SWord8  where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SWord16 where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SWord32 where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SWord64 where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SInt8   where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SInt16  where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SInt32  where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance ArithOverflow SInt64  where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+
+instance (KnownNat n, BVIsNonZero n) => ArithOverflow (SWord n) where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+instance (KnownNat n, BVIsNonZero n) => ArithOverflow (SInt  n) where {bvAddO = l2 bvAddO; bvSubO = l2 bvSubO; bvMulO = l2 bvMulO; bvDivO = l2 bvDivO; bvNegO = l1 bvNegO}
+
+instance ArithOverflow SVal where
+  bvAddO = signPick2 (svMkOverflow2 (PlusOv False)) (svMkOverflow2 (PlusOv True))
+  bvSubO = signPick2 (svMkOverflow2 (SubOv  False)) (svMkOverflow2 (SubOv  True))
+  bvMulO = signPick2 (svMkOverflow2 (MulOv  False)) (svMkOverflow2 (MulOv  True))
+  bvDivO = signPick2 (const (const svFalse))        (svMkOverflow2 DivOv)           -- unsigned division doesn't overflow
+  bvNegO = signPick1 (const svFalse)                (svMkOverflow1 NegOv)           -- unsigned unary negation doesn't overflow
+
+-- | A class of checked-arithmetic operations. These follow the usual arithmetic,
+-- except make calls to 'Data.SBV.sAssert' to ensure no overflow/underflow can occur.
+-- Use them in conjunction with 'Data.SBV.safe' to ensure no overflow can happen.
+class (ArithOverflow (SBV a), Num a, SymVal a) => CheckedArithmetic a where
+  (+!)          :: (?loc :: CallStack) => SBV a -> SBV a -> SBV a
+  (-!)          :: (?loc :: CallStack) => SBV a -> SBV a -> SBV a
+  (*!)          :: (?loc :: CallStack) => SBV a -> SBV a -> SBV a
+  (/!)          :: (?loc :: CallStack) => SBV a -> SBV a -> SBV a
+  negateChecked :: (?loc :: CallStack) => SBV a          -> SBV a
+
+  infixl 6 +!, -!
+  infixl 7 *!, /!
+
+instance CheckedArithmetic Word8 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Word16 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Word32 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Word64 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Int8 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Int16 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Int32 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance CheckedArithmetic Int64 where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance (KnownNat n, BVIsNonZero n) => CheckedArithmetic (WordN n) where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+instance (KnownNat n, BVIsNonZero n) => CheckedArithmetic (IntN n) where
+  (+!)          = checkOp2 ?loc "addition"       (+)    bvAddO
+  (-!)          = checkOp2 ?loc "subtraction"    (-)    bvSubO
+  (*!)          = checkOp2 ?loc "multiplication" (*)    bvMulO
+  (/!)          = checkOp2 ?loc "division"       sDiv   bvDivO
+  negateChecked = checkOp1 ?loc "unary negation" negate bvNegO
+
+-- | Check all true
+svAll :: [SVal] -> SVal
+svAll = foldr svAnd svTrue
+
+-- | Are all the bits between a b (inclusive) zero?
+allZero :: Int -> Int -> SBV a -> SVal
+allZero m n (SBV x)
+  | m >= sz || n < 0 || m < n
+  = error $ "Data.SBV.Tools.Overflow.allZero: Received unexpected parameters: " ++ show (m, n, sz)
+  | True
+  = svAll [svTestBit x i `svEqual` svFalse | i <- [m, m-1 .. n]]
+  where sz = intSizeOf x
+
+-- | Are all the bits between a b (inclusive) one?
+allOne :: Int -> Int -> SBV a -> SVal
+allOne m n (SBV x)
+  | m >= sz || n < 0 || m < n
+  = error $ "Data.SBV.Tools.Overflow.allOne: Received unexpected parameters: " ++ show (m, n, sz)
+  | True
+  = svAll [svTestBit x i `svEqual` svTrue | i <- [m, m-1 .. n]]
+  where sz = intSizeOf x
+
+-- | Detecting underflow/overflow conditions for casting between bit-vectors. The first output is the result,
+-- the second component itself is a pair with the first boolean indicating underflow and the second indicating overflow.
+--
+-- >>> sFromIntegralO (256 :: SInt16) :: (SWord8, (SBool, SBool))
+-- (0 :: SWord8,(False,True))
+-- >>> sFromIntegralO (-2 :: SInt16) :: (SWord8, (SBool, SBool))
+-- (254 :: SWord8,(True,False))
+-- >>> sFromIntegralO (2 :: SInt16) :: (SWord8, (SBool, SBool))
+-- (2 :: SWord8,(False,False))
+-- >>> prove $ \x -> sFromIntegralO (x::SInt32) .== (sFromIntegral x :: SInteger, (sFalse, sFalse))
+-- Q.E.D.
+--
+-- As the last example shows, converting to `sInteger` never underflows or overflows for any value.
+sFromIntegralO :: forall a b. (Integral a, HasKind a, Num a, SymVal a, HasKind b, Num b, SymVal b) => SBV a -> (SBV b, (SBool, SBool))
+sFromIntegralO x = case (kindOf x, kindOf (Proxy @b)) of
+                     (KBounded False n, KBounded False m) -> (res, u2u n m)
+                     (KBounded False n, KBounded True  m) -> (res, u2s n m)
+                     (KBounded True n,  KBounded False m) -> (res, s2u n m)
+                     (KBounded True n,  KBounded True  m) -> (res, s2s n m)
+                     (KUnbounded,       KBounded s m)     -> (res, checkBounds s m)
+                     (KBounded{},       KUnbounded)       -> (res, (sFalse, sFalse))
+                     (KUnbounded,       KUnbounded)       -> (res, (sFalse, sFalse))
+                     (kFrom,            kTo)              -> error $ "sFromIntegralO: Expected bounded-BV types, received: " ++ show (kFrom, kTo)
+
+  where res :: SBV b
+        res = sFromIntegral x
+
+        checkBounds :: Bool -> Int -> (SBool, SBool)
+        checkBounds signed sz = (ix .< literal lb, ix .> literal ub)
+          where ix :: SInteger
+                ix = sFromIntegral x
+
+                s :: Integer
+                s = fromIntegral sz
+
+                ub :: Integer
+                ub | signed = 2^(s - 1) - 1
+                   | True   = 2^s       - 1
+
+                lb :: Integer
+                lb | signed = -ub-1
+                   | True   = 0
+
+        u2u :: Int -> Int -> (SBool, SBool)
+        u2u n m = (underflow, overflow)
+          where underflow  = sFalse
+                overflow
+                  | n <= m = sFalse
+                  | True   = SBV $ svNot $ allZero (n-1) m x
+
+        u2s :: Int -> Int -> (SBool, SBool)
+        u2s n m = (underflow, overflow)
+          where underflow = sFalse
+                overflow
+                  | m > n = sFalse
+                  | True  = SBV $ svNot $ allZero (n-1) (m-1) x
+
+        s2u :: Int -> Int -> (SBool, SBool)
+        s2u n m = (underflow, overflow)
+          where underflow = SBV $ (unSBV x `svTestBit` (n-1)) `svEqual` svTrue
+
+                overflow
+                  | m >= n - 1 = sFalse
+                  | True       = SBV $ svAll [(unSBV x `svTestBit` (n-1)) `svEqual` svFalse, svNot $ allZero (n-1) m x]
+
+        s2s :: Int -> Int -> (SBool, SBool)
+        s2s n m = (underflow, overflow)
+          where underflow
+                  | m > n = sFalse
+                  | True  = SBV $ svAll [(unSBV x `svTestBit` (n-1)) `svEqual` svTrue,  svNot $ allOne  (n-1) (m-1) x]
+
+                overflow
+                  | m > n = sFalse
+                  | True  = SBV $ svAll [(unSBV x `svTestBit` (n-1)) `svEqual` svFalse, svNot $ allZero (n-1) (m-1) x]
+
+-- | Version of 'sFromIntegral' that has calls to 'Data.SBV.sAssert' for checking no overflow/underflow can happen. Use it with a 'Data.SBV.safe' call.
+sFromIntegralChecked :: forall a b. (?loc :: CallStack, Integral a, HasKind a, HasKind b, Num a, SymVal a, HasKind b, Num b, SymVal b) => SBV a -> SBV b
+sFromIntegralChecked x = sAssert (Just ?loc) (msg "underflows") (sNot u)
+                       $ sAssert (Just ?loc) (msg "overflows")  (sNot o)
+                         r
+  where kFrom = show $ kindOf x
+        kTo   = show $ kindOf (Proxy @b)
+        msg c = "Casting from " ++ kFrom ++ " to " ++ kTo ++ " " ++ c
+
+        (r, (u, o)) = sFromIntegralO x
+
+-- | signedMulOverflow: Checking if a signed bitvector multiplication can overflow. In general you should simply use 'bvMulO' for checking
+-- signed multiplication overflow for bit-vectors. This is a function supported by SMTLib. Unfortunately, individual implementations have
+-- different performance characteristics. For instance, bitwuzla has a fairly performant implementation of this, but z3 does not. (At least
+-- not as of August 2024.) In cases where you can't use bitwuzla, you can use this implementation which has better performance.
+signedMulOverflow :: forall n. ( KnownNat n,          BVIsNonZero n
+                               , KnownNat (n+1),      BVIsNonZero (n+1)
+                               , KnownNat (2+Log2 n), BVIsNonZero (2+Log2 n))
+                               => SInt n -> SInt n -> SBool
+signedMulOverflow x y = sNot zeroOut .&& overflow
+  where zeroOut = x .== 0 .|| y .== 0
+
+        prod :: SInt (n+1)
+        prod = sFromIntegral x * sFromIntegral y
+
+        nv :: Int
+        nv = fromIntegral $ natVal (Proxy @n)
+
+        prodN, prodNm1 :: SBool
+        prodN   = prod `sTestBit` nv
+        prodNm1 = prod `sTestBit` (nv-1)
+
+        overflow =   nonSignBitPos x + nonSignBitPos y .> literal (fromIntegral (nv - 2))
+                 .|| prodN .<+> prodNm1
+
+        -- Find the position of the first non-sign bit. i.e., the first bit that differs from the msb.
+        -- Position is 0 indexed. Note that if there's no differing bit, then you also get back 0.
+        -- This is essentially an approximation of the logarithm of the magnitude of the number.
+        --
+        -- The result is at most N-2 for an N-bit word. Later we add two of these, so the maximum
+        -- value we need to represent is 2N-4. This will require 1 + lg(2N-4) = 2 + log(N-1) bits.
+        -- To support the case N=0, we return a (2 + log N) bit word.
+        --
+        -- Example for 3 bits:
+        --
+        --    000 -> 0  (no differing bit from 0; so we get 0)
+        --    001 -> 0
+        --    010 -> 1
+        --    011 -> 1
+        --    100 -> 1
+        --    101 -> 1
+        --    110 -> 0
+        --    111 -> 0  (no differing bit from 1; so we get 0)
+        nonSignBitPos :: ( KnownNat n,          BVIsNonZero n
+                         , KnownNat (2+Log2 n), BVIsNonZero (2+Log2 n))
+                         => SInt n -> SWord (2+Log2 n)
+        nonSignBitPos w = walk 0 rest
+          where (sign, rest) = case blastBE w of
+                                 []     -> error $ "Impossible happened, blastBE returned no bits for " ++ show w
+                                 (b:bs) -> (b, zip (map literal [0..]) (reverse bs))
+
+                walk sofar []          = sofar
+                walk sofar ((i, b):bs) = walk (ite (b ./= sign) i sofar) bs
+
+-- Helpers
+l2 :: (SVal -> SVal -> SBool) -> SBV a -> SBV a -> SBool
+l2 f (SBV a) (SBV b) = f a b
+
+l1 :: (SVal -> SBool) -> SBV a -> SBool
+l1 f (SBV a) = f a
+
+signPick2 :: (SVal -> SVal -> SVal) -> (SVal -> SVal -> SVal) -> (SVal -> SVal -> SBool)
+signPick2 fu fs a b
+ | hasSign a = SBV (fs a b)
+ | True      = SBV (fu a b)
+
+signPick1 :: (SVal -> SVal) -> (SVal -> SVal) -> (SVal -> SBool)
+signPick1 fu fs a
+ | hasSign a = SBV (fs a)
+ | True      = SBV (fu a)
+
+checkOp1 :: (HasKind a, HasKind b) => CallStack -> String -> (a -> SBV b) -> (a -> SBool) -> a -> SBV b
+checkOp1 loc w op cop a = sAssert (Just loc) (msg "overflows") (sNot (cop a)) $ op a
+  where k = show $ kindOf a
+        msg c = k ++ " " ++ w ++ " " ++ c
+
+checkOp2 :: (HasKind a, HasKind c) => CallStack -> String -> (a -> b -> SBV c) -> (a -> b -> SBool) -> a -> b -> SBV c
+checkOp2 loc w op cop a b = sAssert (Just loc) (msg "overflows")  (sNot (a `cop` b)) $ a `op` b
+  where k = show $ kindOf a
+        msg c = k ++ " " ++ w ++ " " ++ c
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,31 +1,40 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.BitVectors.Polynomials
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Tools.Polynomial
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Implementation of polynomial arithmetic
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE CPP                  #-}
 {-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE PatternGuards        #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
 
-module Data.SBV.Tools.Polynomial (Polynomial(..), crc, crcBV, ites, mdp, addPoly) where
+{-# OPTIONS_GHC -Wall -Werror #-}
 
+module Data.SBV.Tools.Polynomial (
+        -- * Polynomial arithmetic and CRCs
+        Polynomial(..), crc, crcBV, ites, mdp, addPoly
+        ) where
+
 import Data.Bits  (Bits(..))
-import Data.List  (genericTake)
+import Data.List  (genericTake
+#if !MIN_VERSION_base(4,20,0)
+                  , foldl'
+#endif
+                  )
 import Data.Maybe (fromJust, fromMaybe)
 import Data.Word  (Word8, Word16, Word32, Word64)
 
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model
-import Data.SBV.BitVectors.Splittable
-import Data.SBV.Utils.Boolean
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Model
 
+import GHC.TypeLits
+
 -- | Implements polynomial addition, multiplication, division, and modulus operations
 -- over GF(2^n).  NB. Similar to 'sQuotRem', division by @0@ is interpreted as follows:
 --
@@ -39,15 +48,15 @@
  -- For instance
  --
  --     @polynomial [0, 1, 3] :: SWord8@
- -- 
- -- will evaluate to @11@, since it sets the bits @0@, @1@, and @3@. Mathematicans would write this polynomial
+ --
+ -- will evaluate to @11@, since it sets the bits @0@, @1@, and @3@. Mathematicians would write this polynomial
  -- as @x^3 + x + 1@. And in fact, 'showPoly' will show it like that.
  polynomial :: [Int] -> a
  -- | Add two polynomials in GF(2^n).
  pAdd  :: a -> a -> a
  -- | Multiply two polynomials in GF(2^n), and reduce it by the irreducible specified by
  -- the polynomial as specified by coefficients of the third argument. Note that the third
- -- argument is specifically left in this form as it is usally in GF(2^(n+1)), which is not available in our
+ -- argument is specifically left in this form as it is usually in GF(2^(n+1)), which is not available in our
  -- formalism. (That is, we would need SWord9 for SWord8 multiplication, etc.) Also note that we do not
  -- support symbolic irreducibles, which is a minor shortcoming. (Most GF's will come with fixed irreducibles,
  -- so this should not be a problem in practice.)
@@ -67,14 +76,13 @@
  -- controls if the final type is shown as well.
  showPolynomial :: Bool -> a -> String
 
- -- defaults.. Minumum complete definition: pMult, pDivMod, showPolynomial
+ {-# MINIMAL pMult, pDivMod, showPolynomial #-}
  polynomial = foldr (flip setBit) 0
  pAdd       = xor
  pDiv x y   = fst (pDivMod x y)
  pMod x y   = snd (pDivMod x y)
  showPoly   = showPolynomial False
 
-
 instance Polynomial Word8   where {showPolynomial   = sp;           pMult = lift polyMult; pDivMod = liftC polyDivMod}
 instance Polynomial Word16  where {showPolynomial   = sp;           pMult = lift polyMult; pDivMod = liftC polyDivMod}
 instance Polynomial Word32  where {showPolynomial   = sp;           pMult = lift polyMult; pDivMod = liftC polyDivMod}
@@ -84,11 +92,13 @@
 instance Polynomial SWord32 where {showPolynomial b = liftS (sp b); pMult = polyMult;      pDivMod = polyDivMod}
 instance Polynomial SWord64 where {showPolynomial b = liftS (sp b); pMult = polyMult;      pDivMod = polyDivMod}
 
-lift :: SymWord a => ((SBV a, SBV a, [Int]) -> SBV a) -> (a, a, [Int]) -> a
+instance (KnownNat n, BVIsNonZero n) => Polynomial (SWord n) where {showPolynomial b = liftS (sp b); pMult = polyMult;      pDivMod = polyDivMod}
+
+lift :: SymVal a => ((SBV a, SBV a, [Int]) -> SBV a) -> (a, a, [Int]) -> a
 lift f (x, y, z) = fromJust $ unliteral $ f (literal x, literal y, z)
-liftC :: SymWord a => (SBV a -> SBV a -> (SBV a, SBV a)) -> a -> a -> (a, a)
+liftC :: SymVal a => (SBV a -> SBV a -> (SBV a, SBV a)) -> a -> a -> (a, a)
 liftC f x y = let (a, b) = f (literal x) (literal y) in (fromJust (unliteral a), fromJust (unliteral b))
-liftS :: SymWord a => (a -> String) -> SBV a -> String
+liftS :: SymVal a => (a -> String) -> SBV a -> String
 liftS f s
   | Just x <- unliteral s = f x
   | True                  = show s
@@ -111,11 +121,11 @@
 addPoly :: [SBool] -> [SBool] -> [SBool]
 addPoly xs    []      = xs
 addPoly []    ys      = ys
-addPoly (x:xs) (y:ys) = x <+> y : addPoly xs ys
+addPoly (x:xs) (y:ys) = x .<+> y : addPoly xs ys
 
 -- | Run down a boolean condition over two lists. Note that this is
 -- different than zipWith as shorter list is assumed to be filled with
--- false at the end (i.e., zero-bits); which nicely pads it when
+-- sFalse at the end (i.e., zero-bits); which nicely pads it when
 -- considered as an unsigned number in little-endian form.
 ites :: SBool -> [SBool] -> [SBool] -> [SBool]
 ites s xs ys
@@ -124,28 +134,28 @@
  | True
  = go xs ys
  where go []     []     = []
-       go []     (b:bs) = ite s false b : go [] bs
-       go (a:as) []     = ite s a false : go as []
+       go []     (b:bs) = ite s sFalse b : go [] bs
+       go (a:as) []     = ite s a sFalse : go as []
        go (a:as) (b:bs) = ite s a b : go as bs
 
 -- | Multiply two polynomials and reduce by the third (concrete) irreducible, given by its coefficients.
 -- See the remarks for the 'pMult' function for this design choice
-polyMult :: (Num a, Bits a, SymWord a, FromBits (SBV a)) => (SBV a, SBV a, [Int]) -> SBV a
+polyMult :: SFiniteBits a => (SBV a, SBV a, [Int]) -> SBV a
 polyMult (x, y, red)
   | isReal x
   = error $ "SBV.polyMult: Received a real value: " ++ show x
   | not (isBounded x)
   = error $ "SBV.polyMult: Received infinite precision value: " ++ show x
   | True
-  = fromBitsLE $ genericTake sz $ r ++ repeat false
+  = fromBitsLE $ genericTake sz $ r ++ repeat sFalse
   where (_, r) = mdp ms rs
-        ms = genericTake (2*sz) $ mul (blastLE x) (blastLE y) [] ++ repeat false
-        rs = genericTake (2*sz) $ [if i `elem` red then true else false |  i <- [0 .. foldr max 0 red] ] ++ repeat false
+        ms = genericTake (2*sz) $ mul (blastLE x) (blastLE y) [] ++ repeat sFalse
+        rs = genericTake (2*sz) $ [fromBool (i `elem` red) |  i <- [0 .. foldl' max 0 red] ] ++ repeat sFalse
         sz = intSizeOf x
         mul _  []     ps = ps
-        mul as (b:bs) ps = mul (false:as) bs (ites b (as `addPoly` ps) ps)
+        mul as (b:bs) ps = mul (sFalse:as) bs (ites b (as `addPoly` ps) ps)
 
-polyDivMod :: (Num a, Bits a, SymWord a, FromBits (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
+polyDivMod :: SFiniteBits a => SBV a -> SBV a -> (SBV a, SBV a)
 polyDivMod x y
    | isReal x
    = error $ "SBV.polyDivMod: Received a real value: " ++ show x
@@ -153,7 +163,7 @@
    = error $ "SBV.polyDivMod: Received infinite precision value: " ++ show x
    | True
    = ite (y .== 0) (0, x) (adjust d, adjust r)
-   where adjust xs = fromBitsLE $ genericTake sz $ xs ++ repeat false
+   where adjust xs = fromBitsLE $ genericTake sz $ xs ++ repeat sFalse
          sz        = intSizeOf x
          (d, r)    = mdp (blastLE x) (blastLE y)
 
@@ -177,13 +187,13 @@
          | True     = let (rqs, rrs) = go (n-1) bs
                       in (ites b (reverse qs) rqs, ites b rs rrs)
          where degQuot = degTop - n
-               ys' = replicate degQuot false ++ ys
+               ys' = replicate degQuot sFalse ++ ys
                (qs, rs) = divx (degQuot+1) degTop xs ys'
 
--- return the element at index i; if not enough elements, return false
--- N.B. equivalent to '(xs ++ repeat false) !! i', but more efficient
+-- return the element at index i; if not enough elements, return sFalse
+-- N.B. equivalent to '(xs ++ repeat sFalse) !! i', but more efficient
 idx :: [SBool] -> Int -> SBool
-idx []     _ = false
+idx []     _ = sFalse
 idx (x:_)  0 = x
 idx (_:xs) i = idx xs (i-1)
 
@@ -192,7 +202,7 @@
 divx n i xs ys'        = (q:qs, rs)
   where q        = xs `idx` i
         xs'      = ites q (xs `addPoly` ys') xs
-        (qs, rs) = divx (n-1) (i-1) xs' (tail ys')
+        (qs, rs) = divx (n-1) (i-1) xs' (drop 1 ys')
 
 -- | Compute CRCs over bit-vectors. The call @crcBV n m p@ computes
 -- the CRC of the message @m@ with respect to polynomial @p@. The
@@ -208,7 +218,7 @@
 -- polynomial division, but this routine is much faster in practice.)
 --
 -- NB. The @n@th bit of the polynomial @p@ /must/ be set for the CRC
--- to be computed correctly. Note that the polynomial argument 'p' will
+-- to be computed correctly. Note that the polynomial argument @p@ will
 -- not even have this bit present most of the time, as it will typically
 -- contain bits @0@ through @n-1@ as usual in the CRC literature. The higher
 -- order @n@th bit is simply assumed to be set, as it does not make
@@ -218,30 +228,33 @@
 -- NB. The literature on CRC's has many variants on how CRC's are computed.
 -- We follow the following simple procedure:
 --
---     * Extend the message 'm' by adding 'n' 0 bits on the right
+--     * Extend the message @m@ by adding @n@ 0 bits on the right
 --
---     * Divide the polynomial thus obtained by the 'p'
+--     * Divide the polynomial thus obtained by the @p@
 --
 --     * The remainder is the CRC value.
 --
 -- There are many variants on final XOR's, reversed polynomials etc., so
 -- it is essential to double check you use the correct /algorithm/.
 crcBV :: Int -> [SBool] -> [SBool] -> [SBool]
-crcBV n m p = take n $ go (replicate n false) (m ++ replicate n false)
+crcBV n m p = take n $ go (replicate n sFalse) (m ++ replicate n sFalse)
   where mask = drop (length p - n) p
         go c []     = c
         go c (b:bs) = go next bs
           where c' = drop 1 c ++ [b]
-                next = ite (head c) (zipWith (<+>) c' mask) c'
+                next = ite (hd c) (zipWith (.<+>) c' mask) c'
 
+                hd (f:_) = f
+                hd []    = error "crcBV: Impossible, prefix is empty"
+
 -- | Compute CRC's over polynomials, i.e., symbolic words. The first
 -- 'Int' argument plays the same role as the one in the 'crcBV' function.
-crc :: (FromBits (SBV a), FromBits (SBV b), Num a, Num b, Bits a, Bits b, SymWord a, SymWord b) => Int -> SBV a -> SBV b -> SBV b
+crc :: (SFiniteBits a, SFiniteBits b) => Int -> SBV a -> SBV b -> SBV b
 crc n m p
   | isReal m || isReal p
   = error $ "SBV.crc: Received a real value: " ++ show (m, p)
   | not (isBounded m) || not (isBounded p)
   = error $ "SBV.crc: Received an infinite precision value: " ++ show (m, p)
   | True
-  = fromBitsBE $ replicate (sz - n) false ++ crcBV n (blastBE m) (blastBE p)
+  = fromBitsBE $ replicate (sz - n) sFalse ++ crcBV n (blastBE m) (blastBE p)
   where sz = intSizeOf p
diff --git a/Data/SBV/Tools/Range.hs b/Data/SBV/Tools/Range.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/Range.hs
@@ -0,0 +1,218 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.Range
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Single variable valid range detection.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.Range (
+
+         -- * Boundaries and ranges
+         Boundary(..), Range(..)
+
+         -- * Computing valid ranges
+       , ranges, rangesWith
+
+       ) where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.Proxy
+
+import Data.SBV.Internals hiding (Range, free_)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> :set -XScopedTypeVariables -XDataKinds
+#endif
+
+-- | A boundary value
+data Boundary a = Unbounded -- ^ Unbounded
+                | Open   a  -- ^ Exclusive of the point
+                | Closed a  -- ^ Inclusive of the point
+
+-- | Is this a closed value?
+isClosed :: Boundary a -> Bool
+isClosed Unbounded  = False
+isClosed (Open   _) = False
+isClosed (Closed _) = True
+
+-- | A range is a pair of boundaries: Lower and upper bounds
+data Range a = Range (Boundary a) (Boundary a)
+
+-- | Show instance for t'Range'
+instance Show a => Show (Range a) where
+   show (Range l u) = sh True l ++ "," ++ sh False u
+     where sh onLeft b = case b of
+                           Unbounded | onLeft -> "(-oo"
+                                     | True   -> "oo)"
+                           Open   v  | onLeft -> "(" ++ show v
+                                     | True   -> show v ++ ")"
+                           Closed v  | onLeft -> "[" ++ show v
+                                     | True   -> show v ++ "]"
+
+-- | Given a single predicate over a single variable, find the contiguous ranges over which the predicate
+-- is satisfied. SBV will make one call to the optimizer, and then as many calls to the solver as there are
+-- disjoint ranges that the predicate is satisfied over. (Linear in the number of ranges.) Note that the
+-- number of ranges is large, this can take a long time!
+--
+-- Beware that, as of June 2021, z3 no longer supports optimization with 'SReal' in the presence of
+-- strict inequalities. See <https://github.com/Z3Prover/z3/issues/5314> for details. So, if you
+-- have 'SReal' variables, it is important that you do /not/ use a strict inequality, i.e., '.>', '.<', './=' etc.
+-- Inequalities of the form '.<=', '.>=' should be OK. Please report if you see any fishy
+-- behavior due to this change in z3's behavior.
+--
+-- Some examples:
+--
+-- >>> ranges (\(_ :: SInteger) -> sFalse)
+-- []
+-- >>> ranges (\(_ :: SInteger) -> sTrue)
+-- [(-oo,oo)]
+-- >>> ranges (\(x :: SInteger) -> sAnd [x .<= 120, x .>= -12, x ./= 3])
+-- [[-12,3),(3,120]]
+-- >>> ranges (\(x :: SInteger) -> sAnd [x .<= 75, x .>= 5, x ./= 6, x ./= 67])
+-- [[5,6),(6,67),(67,75]]
+-- >>> ranges (\(x :: SInteger) -> sAnd [x .<= 75, x ./= 3, x ./= 67])
+-- [(-oo,3),(3,67),(67,75]]
+-- >>> ranges (\(x :: SReal) -> sAnd [x .>= 3.2, x .<= 12.7])
+-- [[3.2,12.7]]
+-- >>> ranges (\(x :: SReal) -> sAnd [x .<= 12.7, x ./= 8])
+-- [(-oo,8.0),(8.0,12.7]]
+-- >>> ranges (\(x :: SReal) -> sAnd [x .>= 12.7, x ./= 15])
+-- [[12.7,15.0),(15.0,oo)]
+-- >>> ranges (\(x :: SInt8) -> sAnd [x .<= 7, x ./= 6])
+-- [[-128,6),(6,7]]
+-- >>> ranges $ \x -> x .>= (0::SReal)
+-- [[0.0,oo)]
+-- >>> ranges $ \x -> x .<= (0::SReal)
+-- [(-oo,0.0]]
+-- >>> ranges $ \(x :: SWord 4) -> 2*x .== 4
+-- [[2,3),(9,10]]
+ranges :: forall a. (OrdSymbolic (SBV a), Num a, SymVal 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. (OrdSymbolic (SBV a), Num a, SymVal 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 -> pure []
+                           Just r  -> search [r] []
+
+  where getInitialBounds :: IO (Maybe (Range a))
+        getInitialBounds = do
+            let getGenVal :: GeneralizedCV -> Boundary a
+                getGenVal (RegularCV  cv)  = Closed $ getRegVal cv
+                getGenVal (ExtendedCV ecv) = getExtVal ecv
+
+                getExtVal :: ExtCV -> Boundary a
+                getExtVal (Infinite _) = Unbounded
+                getExtVal (Epsilon  k) = Open $ getRegVal (mkConstCV k (0::Integer))
+                getExtVal i@Interval{} = error $ unlines [ "*** Data.SBV.ranges.getExtVal: Unexpected interval bounds!"
+                                                         , "***"
+                                                         , "*** Found bound: " ++ show i
+                                                         , "*** Please report this as a bug!"
+                                                         ]
+                getExtVal (BoundedCV cv) = Closed $ getRegVal cv
+                getExtVal (AddExtCV a b) = getExtVal a `addBound` getExtVal b
+                getExtVal (MulExtCV a b) = getExtVal a `mulBound` getExtVal b
+
+                opBound :: (a -> a -> a) -> Boundary a -> Boundary a -> Boundary a
+                opBound f x y = case (fromBound x, fromBound y, isClosed x && isClosed y) of
+                                  (Just a, Just b, True)  -> Closed $ a `f` b
+                                  (Just a, Just b, False) -> Open   $ a `f` b
+                                  _                       -> Unbounded
+                  where fromBound Unbounded  = Nothing
+                        fromBound (Open   a) = Just a
+                        fromBound (Closed a) = Just a
+
+                addBound, mulBound :: Boundary a -> Boundary a -> Boundary a
+                addBound = opBound (+)
+                mulBound = opBound (*)
+
+                getRegVal :: CV -> a
+                getRegVal cv = case parseCVs [cv] of
+                                 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
+
+
+                getBound cstr = do let objName = "boundValue"
+                                   res@(LexicographicResult m) <- optimizeWith cfg Lexicographic $ do x <- free_
+                                                                                                      constrain $ prop x
+                                                                                                      cstr objName x
+                                   case m of
+                                     Unsatisfiable{} -> pure Nothing
+                                     Unknown{}       -> error "Solver said Unknown!"
+                                     ProofError{}    -> error (show res)
+                                     _               -> pure $ getModelObjectiveValue (annotateForMS (Proxy @a) objName) m
+
+            mi <- getBound minimize
+            ma <- getBound maximize
+            case (mi, ma) of
+              (Just minV, Just maxV) -> pure $ Just $ Range (getGenVal minV) (getGenVal maxV)
+              _                      -> pure Nothing
+
+        -- Is this range satisfiable? Returns a witness to it.
+        witness :: Range a -> Symbolic (SBV a)
+        witness (Range lo hi) = do x :: SBV a <- free_
+
+                                   let restrict v open closed = case v of
+                                                                  Unbounded -> sTrue
+                                                                  Open   a  -> x `open`   literal a
+                                                                  Closed a  -> x `closed` literal a
+
+                                       lower = restrict lo (.>) (.>=)
+                                       upper = restrict hi (.<) (.<=)
+
+                                   constrain $ lower .&& upper
+
+                                   pure x
+
+        isFeasible :: Range a -> IO Bool
+        isFeasible r = runSMTWith cfg $ do _ <- witness r
+
+                                           query $ do cs <- checkSat
+                                                      case cs of
+                                                        Unsat  -> pure False
+                                                        DSat{} -> error "Data.SBV.interval.isFeasible: Solver returned a delta-satisfiable result!"
+                                                        Unk    -> error "Data.SBV.interval.isFeasible: Solver said unknown!"
+                                                        Sat    -> pure True
+
+        bisect :: Range a -> IO (Maybe [Range a])
+        bisect r@(Range lo hi) = runSMTWith cfg $ do x <- witness r
+
+                                                     constrain $ sNot (prop x)
+
+                                                     query $ do cs <- checkSat
+                                                                case cs of
+                                                                  Unsat  -> pure Nothing
+                                                                  DSat{} -> error "Data.SBV.interval.bisect: Solver returned a delta-satisfiable result!"
+                                                                  Unk    -> error "Data.SBV.interval.bisect: Solver said unknown!"
+                                                                  Sat    -> do midV <- Open <$> getValue x
+                                                                               pure $ Just [Range lo midV, Range midV hi]
+
+        search :: [Range a] -> [Range a] -> IO [Range a]
+        search []     sofar = pure $ reverse sofar
+        search (c:cs) sofar = do feasible <- isFeasible c
+                                 if feasible
+                                    then do mbCS <- bisect c
+                                            case mbCS of
+                                              Nothing  -> search cs          (c:sofar)
+                                              Just xss -> search (xss ++ cs) sofar
+                                    else search cs sofar
+
+{- HLint ignore rangesWith "Use fromMaybe" -}
diff --git a/Data/SBV/Tools/STree.hs b/Data/SBV/Tools/STree.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/STree.hs
@@ -0,0 +1,77 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.STree
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implementation of full-binary symbolic trees, providing logarithmic
+-- time access to elements. Both reads and writes are supported.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.STree (STree, readSTree, writeSTree, mkSTree) where
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model
+
+import Data.Proxy
+
+-- | A symbolic tree containing values of type e, indexed by
+-- elements of type i. Note that these are full-trees, and their
+-- their shapes remain constant. There is no API provided that
+-- can change the shape of the tree. These structures are useful
+-- when dealing with data-structures that are indexed with symbolic
+-- values where access time is important. 'STree' structures provide
+-- logarithmic time reads and writes.
+type STree i e = STreeInternal (SBV i) (SBV e)
+
+-- Internal representation, not exposed to the user
+data STreeInternal i e = SLeaf e                        -- NB. parameter 'i' is phantom
+                       | SBin  (STreeInternal i e) (STreeInternal i e)
+                       deriving Show
+
+instance SymVal e => Mergeable (STree i e) where
+  symbolicMerge f b (SLeaf i)  (SLeaf j)    = SLeaf (symbolicMerge f b i j)
+  symbolicMerge f b (SBin l r) (SBin l' r') = SBin  (symbolicMerge f b l l') (symbolicMerge f b r r')
+  symbolicMerge _ _ _          _            = error "SBV.STree.symbolicMerge: Impossible happened while merging states"
+
+-- | Reading a value. We bit-blast the index and descend down the full tree
+-- according to bit-values.
+readSTree :: (SFiniteBits i, SymVal e) => STree i e -> SBV i -> SBV e
+readSTree s i = walk (blastBE i) s
+  where walk []     (SLeaf v)  = v
+        walk (b:bs) (SBin l r) = ite b (walk bs r) (walk bs l)
+        walk _      _          = error $ "SBV.STree.readSTree: Impossible happened while reading: " ++ show i
+
+-- | Writing a value, similar to how reads are done. The important thing is that the tree
+-- representation keeps updates to a minimum.
+writeSTree :: (SFiniteBits i, SymVal e) => STree i e -> SBV i -> SBV e -> STree i e
+writeSTree s i j = walk (blastBE i) s
+  where walk []     _          = SLeaf j
+        walk (b:bs) (SBin l r) = SBin (ite b l (walk bs l)) (ite b (walk bs r) r)
+        walk _      _          = error $ "SBV.STree.writeSTree: Impossible happened while writing: " ++ show i
+
+-- | Construct the fully balanced initial tree using the given values.
+mkSTree :: forall i e. HasKind i => [SBV e] -> STree i e
+mkSTree ivals
+  | isReal (Proxy @i)
+  = error "SBV.STree.mkSTree: Cannot build a real-valued sized tree"
+  | not (isBounded (Proxy @i))
+  = error "SBV.STree.mkSTree: Cannot build an infinitely large tree"
+  | reqd /= given
+  = error $ "SBV.STree.mkSTree: Required " ++ show reqd ++ " elements, received: " ++ show given
+  | True
+  = go ivals
+  where reqd = 2 ^ intSizeOf (Proxy @i)
+        given = length ivals
+        go []  = error "SBV.STree.mkSTree: Impossible happened, ran out of elements"
+        go [l] = SLeaf l
+        go ns  = let (l, r) = splitAt (length ns `div` 2) ns in SBin (go l) (go r)
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,489 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Tools.WeakestPreconditions (
+        -- * Programs and statements
+          Program(..), Stmt(..), assert, stable
+
+        -- * Invariants, measures, and stability
+        , Invariant, WPMeasure, 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 @pure ()@.
+-- 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 WPMeasure 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 (WPMeasure 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 maintained 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 ~ QueryResult st) => 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."
+
+                              pure $ Proven t
+
+                 DSat{} -> pure $ Indeterminate "Unsupported: Solver returned a delta-satisfiable answer."
+
+                 Sat    -> do let checkVC :: (SBool, VC st SInteger) -> Query [VC res Integer]
+                                  checkVC (cond, vc) = do c <- getValue cond
+                                                          if c
+                                                             then pure []   -- 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
+                                                                                                                          pure $ 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
+                                                                                                                          pure $ MeasureDecrease l (r1, v1) (r2, v2)
+                                                                     pure [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
+
+                              pure $ 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 = pure 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) _ = pure $ \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 = pure $ \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
+                                        pure $ \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 = pure 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'
+                    zeroM     = 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 maintained 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 pure  (const [])
+                                      else wp st' Skip (const [(iterates .=> curM .>= zeroM, MeasureBound nm (st', curM))])
+
+                -- Condition 5: If we iterate, the measure must decrease
+                measureDecreases <- if noMeasure
+                                    then pure  (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:
+                pure $ \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 ~ QueryResult st) => 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{} -> pure 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
+                         pure $ Good st
+
+        stop :: Loc -> VC st Integer -> String -> IO (Status st)
+        stop l vc m = do putStrLn $ sLoc l m
+                         pure $ Stuck vc
+
+        giveUp :: st -> VC st Integer -> String -> IO (Status st)
+        giveUp st vc m = do r <- stop [] vc m
+                            printST st
+                            pure 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{}  = pure 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 = pure 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{}  = pure 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 < zeroM
+                           = 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
+                                 zeroM = map (const 0) mCur
+
+{- HLint ignore traceExecution "Use fromMaybe" -}
diff --git a/Data/SBV/Trans.hs b/Data/SBV/Trans.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Trans.hs
@@ -0,0 +1,181 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Trans
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- More generalized alternative to @Data.SBV@ for advanced client use
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Trans (
+  -- * Symbolic types
+
+  -- ** Booleans
+    SBool
+  -- *** Boolean values and functions
+  , sTrue, sFalse, sNot, (.&&), (.||), (.<+>), (.~&), (.~|), (.=>), (.<=>), fromBool, oneIf
+  -- *** Logical functions
+  , sAnd, sOr, sAny, sAll
+  -- ** Bit-vectors
+  -- *** Unsigned bit-vectors
+  , SWord8, SWord16, SWord32, SWord64, SWord, WordN
+  -- *** Signed bit-vectors
+  , SInt8, SInt16, SInt32, SInt64, SInt, IntN
+  -- *** Converting between fixed-size and arbitrary bit-vectors
+  , BVIsNonZero, FromSized, ToSized, fromSized, toSized
+  -- ** Unbounded integers
+  , SInteger
+  -- ** Floating point numbers
+  , SFloat, SDouble, SFloatingPoint
+  -- ** Algebraic reals
+  , SReal, AlgReal, sRealToSInteger
+  -- ** Characters, Strings and Regular Expressions
+  , SChar, SString
+  -- ** Symbolic lists
+  , SList
+  -- * Arrays of symbolic values
+  , readArray, writeArray, SArray
+
+  -- * Creating symbolic values
+  -- ** Single value
+  , sBool, sWord8, sWord16, sWord32, sWord64, sWord, sInt8, sInt16, sInt32, sInt64, sInt, sInteger, sReal, sFloat, sDouble, sChar, sString, sList, sArray
+
+  -- ** List of values
+  , sBools, sWord8s, sWord16s, sWord32s, sWord64s, sWords, sInt8s, sInt16s, sInt32s, sInt64s, sInts, sIntegers, sReals, sFloats, sDoubles, sChars, sStrings, sLists, sArrays
+
+  -- * Symbolic Equality and Comparisons
+  , EqSymbolic(..), OrdSymbolic(..), Zero(..), MeasureOf, Equality(..)
+  -- * Conditionals: Mergeable values
+  , Mergeable(..), ite, iteLazy
+
+  -- * Symbolic integral numbers
+  , SIntegral
+  -- * Division and Modulus
+  , SDivisible(..)
+  -- * Bit-vector operations
+  -- ** Conversions
+  , sFromIntegral
+  -- ** Shifts and rotates
+  , sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight
+  -- ** Finite bit-vector operations
+  , SFiniteBits(..)
+  -- ** Splitting, joining, and extending bit-vectors
+  , bvExtract, (#), zeroExtend, signExtend, bvDrop, bvTake
+  -- ** Exponentiation
+  , (.^)
+  -- * IEEE-floating point numbers
+  , IEEEFloating(..), RoundingMode(..), SRoundingMode, nan, infinity, sNaN, sInfinity
+  -- ** Rounding modes
+  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero, sRNE, sRNA, sRTP, sRTN, sRTZ
+  -- ** Conversion to/from floats
+  , IEEEFloatConvertible(..)
+
+  -- ** Bit-pattern conversions
+  , sFloatAsSWord32,       sWord32AsSFloat
+  , sDoubleAsSWord64,      sWord64AsSDouble
+  , sFloatingPointAsSWord, sWordAsSFloatingPoint
+
+  -- ** Extracting bit patterns from floats
+  , blastSFloat
+  , blastSDouble
+  , blastSFloatingPoint
+
+  -- * Symbolic types
+  , mkSymbolic, SMTDefinable(..), smtFunction, smtFunctionWithMeasure
+
+  -- * Properties, proofs, and satisfiability
+  , Predicate, ConstraintSet, ProvableM(..), Provable, SatisfiableM(..), Satisfiable
+  , generateSMTBenchmarkSat, generateSMTBenchmarkProof
+  , solve
+  -- * Constraints
+  -- ** General constraints
+  , constrain, softConstrain
+
+  -- ** Constraint Vacuity
+
+  -- ** Named constraints and attributes
+  , namedConstraint, constrainWithAttribute
+
+  -- ** Unsat cores
+
+  -- ** Cardinality constraints
+  , pbAtMost, pbAtLeast, pbExactly, pbLe, pbGe, pbEq, pbMutexed, pbStronglyMutexed
+
+  -- * Checking safety
+  , sAssert, isSafe, SExecutable(..)
+
+  -- * Quick-checking
+  , sbvQuickCheck
+
+  -- * Optimization
+
+  -- ** Multiple optimization goals
+  , OptimizeStyle(..)
+  -- ** Objectives
+  , Objective(..)
+  -- ** Soft assumptions
+  , assertWithPenalty , Penalty(..)
+  -- ** Field extensions
+  -- | If an optimization results in an infinity/epsilon value, the returned t'CV' value will be in the corresponding extension field.
+  , ExtCV(..), GeneralizedCV(..)
+
+  -- * Model extraction
+
+  -- ** Inspecting proof results
+  , ThmResult(..), SatResult(..), AllSatResult(..), SafeResult(..), OptimizeResult(..), SMTResult(..), SMTReasonUnknown(..)
+
+  -- ** Observing expressions
+  , observe, sObserve
+
+  -- ** Programmable model extraction
+  , SatModel(..), Modelable(..), displayModels, extractModels
+  , getModelDictionaries, getModelValues
+
+  -- * SMT Interface
+  , SMTConfig(..), Timing(..), SMTLibVersion(..), Solver(..), SMTSolver(..)
+  -- ** Controlling verbosity
+
+  -- ** Solvers
+  , boolector, bitwuzla, cvc4, cvc5, dReal, yices, z3, mathSAT, abc
+  -- ** Configurations
+  , defaultSolverConfig, defaultSMTCfg, sbvCheckSolverInstallation, getAvailableSolvers
+  , setLogic, Logic(..), setOption, setInfo, setTimeOut
+  -- ** SBV exceptions
+  , SBVException(..)
+
+  -- * Abstract SBV type
+  , SBV, HasKind(..), Kind(..), SymVal(..)
+  , MonadSymbolic(..), Symbolic, SymbolicT, label, output, runSMT, runSMTWith
+
+  -- * Module exports
+
+  , module Data.Bits
+  , module Data.Word
+  , module Data.Int
+  , module Data.Ratio
+  ) where
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind
+import Data.SBV.Core.Model
+import Data.SBV.Core.Floating
+import Data.SBV.Core.Symbolic
+
+import Data.SBV.Provers.Prover
+
+import Data.SBV.Client
+import Data.SBV.Utils.TDiff   (Timing(..))
+
+import Data.Bits
+import Data.Int
+import Data.Ratio
+import Data.Word
+
+import Data.SBV.SMT.Utils (SBVException(..))
+import Data.SBV.Control.Types (SMTReasonUnknown(..), Logic(..))
diff --git a/Data/SBV/Trans/Control.hs b/Data/SBV/Trans/Control.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Trans/Control.hs
@@ -0,0 +1,83 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Trans.Control
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- More generalized alternative to @Data.SBV.Control@ for advanced client use
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Trans.Control (
+
+     -- * User queries
+       ExtractIO(..), MonadQuery(..), QueryT, Query, query
+
+     -- * Checking satisfiability
+     , CheckSatResult(..), checkSat, ensureSat, checkSatUsing, checkSatAssuming, checkSatAssumingWithUnsatisfiableSet
+
+     -- * Querying the solver
+     -- ** Extracting values
+     , getValue, getFunction, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+
+     -- ** Extracting the unsat core
+     , getUnsatCore
+
+     -- ** Extracting a proof
+     , getProof
+
+     -- ** Extracting interpolants
+     , getInterpolantMathSAT, getInterpolantZ3
+
+     -- ** Getting abducts
+     , getAbduct, getAbductNext
+
+     -- ** Extracting assertions
+     , getAssertions
+
+     -- * Getting solver information
+     , SMTInfoFlag(..), SMTErrorBehavior(..), SMTInfoResponse(..)
+     , getInfo, getOption
+
+     -- * Entering and exiting assertion stack
+     , getAssertionStackDepth, push, pop, inNewAssertionStack
+
+     -- * Higher level tactics
+     , caseSplit
+
+     -- * Resetting the solver state
+     , resetAssertions
+
+     -- * Constructing assignments
+     , (|->)
+
+     -- * Terminating the query
+     , mkSMTResult
+     , exit
+
+     -- * Controlling the solver behavior
+     , ignoreExitCode, timeout
+
+     -- * Miscellaneous
+     , queryDebug
+     , echo
+     , io
+
+     -- * Solver options
+     , SMTOption(..)
+     ) where
+
+import Data.SBV.Core.Symbolic (MonadQuery(..), QueryT, Query, SymbolicT, QueryContext(..))
+
+import Data.SBV.Control.Query
+import Data.SBV.Control.Utils (queryDebug, executeQuery, getFunction, getValue)
+
+import Data.SBV.Utils.ExtractIO
+
+-- | Run a custom query.
+query :: ExtractIO m => QueryT m a -> SymbolicT m a
+query = executeQuery QueryExternal
diff --git a/Data/SBV/Tuple.hs b/Data/SBV/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tuple.hs
@@ -0,0 +1,487 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tuple
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Accessing symbolic tuple fields and deconstruction.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                    #-}
+{-# LANGUAGE DataKinds              #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE KindSignatures         #-}
+{-# LANGUAGE TypeApplications       #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module Data.SBV.Tuple (
+  -- * Symbolic field access
+    (^.), _1, _2, _3, _4, _5, _6, _7, _8
+  -- * Tupling and untupling
+  , tuple, untuple
+  -- * Swapping, only for 2-tuples
+  , swap
+  -- * Currying and uncurrying
+  , curry, uncurry, curry3, uncurry3
+  -- * Extractors for 2-tuple
+  , fst, snd
+  -- * Extractors for 3-tuple
+  , fst3, snd3, thd3
+  ) where
+
+import GHC.TypeLits
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Symbolic
+import Data.SBV.Core.Model
+
+import Prelude hiding (fst, snd, curry, uncurry)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV
+#endif
+
+-- | Field access, inspired by the lens library. This is merely reverse
+-- application, but allows us to write things like @(1, 2)^._1@ which is
+-- likely to be familiar to most Haskell programmers out there. Note that
+-- this is precisely equivalent to @_1 (1, 2)@, but perhaps it reads a little
+-- nicer.
+(^.) :: a -> (a -> b) -> b
+t ^. f = f t
+infixl 8 ^.
+
+-- | Swap the elements of a 2-tuple
+swap :: (SymVal a, SymVal b) => STuple a b -> STuple b a
+swap t = tuple (b, a)
+  where (a, b) = untuple t
+
+-- | Symbolic currying: turn a function that takes a symbolic 2-tuple into one
+-- that takes its two components separately. The inverse of 'uncurry'.
+curry :: (SymVal a, SymVal b) => (STuple a b -> r) -> SBV a -> SBV b -> r
+curry f a b = f (tuple (a, b))
+
+-- | Symbolic uncurrying: turn a function of two arguments into one that takes a
+-- symbolic 2-tuple. The inverse of 'curry'.
+uncurry :: (SymVal a, SymVal b) => (SBV a -> SBV b -> r) -> STuple a b -> r
+uncurry f t = f a b
+  where (a, b) = untuple t
+
+-- | Symbolic currying for 3-tuples: turn a function that takes a symbolic
+-- 3-tuple into one that takes its three components separately. The inverse of
+-- 'uncurry3'.
+curry3 :: (SymVal a, SymVal b, SymVal c) => (STuple3 a b c -> r) -> SBV a -> SBV b -> SBV c -> r
+curry3 f a b c = f (tuple (a, b, c))
+
+-- | Symbolic uncurrying for 3-tuples: turn a function of three arguments into
+-- one that takes a symbolic 3-tuple. The inverse of 'curry3'.
+uncurry3 :: (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b -> SBV c -> r) -> STuple3 a b c -> r
+uncurry3 f t = f a b c
+  where (a, b, c) = untuple t
+
+-- | First of a tuple
+fst :: (SymVal a, SymVal b) => STuple a b -> SBV a
+fst t = a where (a, _) = untuple t
+
+-- | Second of a tuple
+snd :: (SymVal a, SymVal b) => STuple a b -> SBV b
+snd t = b where (_, b) = untuple t
+
+-- | First of a 3-tuple
+fst3 :: (SymVal a, SymVal b, SymVal c) => STuple3 a b c -> SBV a
+fst3 t = a where (a, _, _) = untuple t
+
+-- | Second of a 3-tuple
+snd3 :: (SymVal a, SymVal b, SymVal c) => STuple3 a b c -> SBV b
+snd3 t = b where (_, b, _) = untuple t
+
+-- | Third of a 3-tuple
+thd3 :: (SymVal a, SymVal b, SymVal c) => STuple3 a b c -> SBV c
+thd3 t = c where (_, _, c) = untuple t
+
+-- | Dynamic interface to exporting tuples, this function is not
+-- exported on purpose; use it only via the field functions '_1', '_2', etc.
+symbolicFieldAccess :: (SymVal a, HasKind tup) => Int -> SBV tup -> SBV a
+symbolicFieldAccess i tup
+  | 1 > i || i > lks
+  = bad $ "Index is out of bounds, " ++ show i ++ " is outside [1," ++ show lks ++ "]"
+  | SBV (SVal kval (Left v)) <- tup
+  = case cvVal v of
+      CTuple vs | kval      /= ktup -> bad $ "Kind/value mismatch: "      ++ show kval
+                | length vs /= lks  -> bad $ "Value has fewer elements: " ++ show (CV kval (CTuple vs))
+                | True              -> literal $ fromCV $ CV kElem (vs !! (i-1))
+      _                             -> bad $ "Kind/value mismatch: " ++ show v
+  | True
+  = symAccess
+  where ktup = kindOf tup
+
+        (lks, eks) = case ktup of
+                       KTuple ks -> (length ks, ks)
+                       _         -> bad "Was expecting to receive a tuple!"
+
+        kElem = eks !! (i-1)
+
+        bad :: String -> a
+        bad problem = error $ unlines [ "*** Data.SBV.field: Impossible happened"
+                                      , "***   Accessing element: " ++ show i
+                                      , "***   Argument kind    : " ++ show ktup
+                                      , "***   Problem          : " ++ problem
+                                      , "*** Please report this as a bug!"
+                                      ]
+
+        symAccess :: SBV a
+        symAccess = SBV $ SVal kElem $ Right $ cache y
+          where y st = do sv <- svToSV st $ unSBV tup
+                          newExpr st kElem (SBVApp (TupleAccess i lks) [sv])
+
+-- | Field labels
+data Label (l :: Symbol) = Get
+
+-- | The class 'HasField' captures the notion that a type has a certain field
+class (SymVal elt, HasKind tup) => HasField l elt tup | l tup -> elt where
+  field :: Label l -> SBV tup -> SBV elt
+
+instance (HasKind a, HasKind b                                                                  , SymVal a) => HasField "_1" a (a, b)                   where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c                                                       , SymVal a) => HasField "_1" a (a, b, c)                where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c, HasKind d                                            , SymVal a) => HasField "_1" a (a, b, c, d)             where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e                                 , SymVal a) => HasField "_1" a (a, b, c, d, e)          where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal a) => HasField "_1" a (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal a) => HasField "_1" a (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 1
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal a) => HasField "_1" a (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 1
+
+instance (HasKind a, HasKind b                                                                  , SymVal b) => HasField "_2" b (a, b)                   where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c                                                       , SymVal b) => HasField "_2" b (a, b, c)                where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c, HasKind d                                            , SymVal b) => HasField "_2" b (a, b, c, d)             where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e                                 , SymVal b) => HasField "_2" b (a, b, c, d, e)          where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal b) => HasField "_2" b (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal b) => HasField "_2" b (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 2
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal b) => HasField "_2" b (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 2
+
+instance (HasKind a, HasKind b, HasKind c                                                       , SymVal c) => HasField "_3" c (a, b, c)                where field _ = symbolicFieldAccess 3
+instance (HasKind a, HasKind b, HasKind c, HasKind d                                            , SymVal c) => HasField "_3" c (a, b, c, d)             where field _ = symbolicFieldAccess 3
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e                                 , SymVal c) => HasField "_3" c (a, b, c, d, e)          where field _ = symbolicFieldAccess 3
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal c) => HasField "_3" c (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 3
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal c) => HasField "_3" c (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 3
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal c) => HasField "_3" c (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 3
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d                                            , SymVal d) => HasField "_4" d (a, b, c, d)             where field _ = symbolicFieldAccess 4
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e                                 , SymVal d) => HasField "_4" d (a, b, c, d, e)          where field _ = symbolicFieldAccess 4
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal d) => HasField "_4" d (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 4
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal d) => HasField "_4" d (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 4
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal d) => HasField "_4" d (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 4
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e                                 , SymVal e) => HasField "_5" e (a, b, c, d, e)          where field _ = symbolicFieldAccess 5
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal e) => HasField "_5" e (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 5
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal e) => HasField "_5" e (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 5
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal e) => HasField "_5" e (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 5
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f                      , SymVal f) => HasField "_6" f (a, b, c, d, e, f)       where field _ = symbolicFieldAccess 6
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal f) => HasField "_6" f (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 6
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal f) => HasField "_6" f (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 6
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g           , SymVal g) => HasField "_7" g (a, b, c, d, e, f, g)    where field _ = symbolicFieldAccess 7
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal g) => HasField "_7" g (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 7
+
+instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h, SymVal h) => HasField "_8" h (a, b, c, d, e, f, g, h) where field _ = symbolicFieldAccess 8
+
+-- | Access the 1st element of an @STupleN@, @2 <= N <= 8@. Also see '^.'.
+_1 :: HasField "_1" b a => SBV a -> SBV b
+_1 = field (Get @"_1")
+
+-- | Access the 2nd element of an @STupleN@, @2 <= N <= 8@. Also see '^.'.
+_2 :: HasField "_2" b a => SBV a -> SBV b
+_2 = field (Get @"_2")
+
+-- | Access the 3rd element of an @STupleN@, @3 <= N <= 8@. Also see '^.'.
+_3 :: HasField "_3" b a => SBV a -> SBV b
+_3 = field (Get @"_3")
+
+-- | Access the 4th element of an @STupleN@, @4 <= N <= 8@. Also see '^.'.
+_4 :: HasField "_4" b a => SBV a -> SBV b
+_4 = field (Get @"_4")
+
+-- | Access the 5th element of an @STupleN@, @5 <= N <= 8@. Also see '^.'.
+_5 :: HasField "_5" b a => SBV a -> SBV b
+_5 = field (Get @"_5")
+
+-- | Access the 6th element of an @STupleN@, @6 <= N <= 8@. Also see '^.'.
+_6 :: HasField "_6" b a => SBV a -> SBV b
+_6 = field (Get @"_6")
+
+-- | Access the 7th element of an @STupleN@, @7 <= N <= 8@. Also see '^.'.
+_7 :: HasField "_7" b a => SBV a -> SBV b
+_7 = field (Get @"_7")
+
+-- | Access the 8th element of an @STupleN@, @8 <= N <= 8@. Also see '^.'.
+_8 :: HasField "_8" b a => SBV a -> SBV b
+_8 = field (Get @"_8")
+
+-- | Constructing a tuple from its parts and deconstructing back.
+class Tuple tup a | a -> tup, tup -> a where
+  -- | Deconstruct a tuple, getting its constituent parts apart. Forms an
+  -- isomorphism pair with 'tuple':
+  --
+  -- >>> prove $ \p -> tuple @(Integer, Bool, (String, Char)) (untuple p) .== p
+  -- Q.E.D.
+  untuple :: SBV tup -> a
+
+  -- | Constructing a tuple from its parts. Forms an isomorphism pair with 'untuple':
+  --
+  -- >>> prove $ \p -> untuple @(Integer, Bool, (String, Char)) (tuple p) .== p
+  -- Q.E.D.
+  tuple   :: a -> SBV tup
+
+instance (SymVal a, SymVal b) => Tuple (a, b) (SBV a, SBV b) where
+  untuple p = (p^._1, p^._2)
+
+  tuple p@(sa, sb)
+    | Just a <- unliteral sa, Just b <- unliteral sb
+    = literal (a, b)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      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
+  untuple p = (p^._1, p^._2, p^._3)
+
+  tuple p@(sa, sb, sc)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc
+    = literal (a, b, c)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      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
+  untuple p = (p^._1, p^._2, p^._3, p^._4)
+
+  tuple p@(sa, sb, sc, sd)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc, Just d <- unliteral sd
+    = literal (a, b, c, d)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      csv <- sbvToSV st sc
+                      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
+  untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5)
+
+  tuple p@(sa, sb, sc, sd, se)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc, Just d <- unliteral sd, Just e <- unliteral se
+    = literal (a, b, c, d, e)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      csv <- sbvToSV st sc
+                      dsv <- sbvToSV st sd
+                      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
+  untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5, p^._6)
+
+  tuple p@(sa, sb, sc, sd, se, sf)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc, Just d <- unliteral sd, Just e <- unliteral se, Just f <- unliteral sf
+    = literal (a, b, c, d, e, f)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      csv <- sbvToSV st sc
+                      dsv <- sbvToSV st sd
+                      esv <- sbvToSV st se
+                      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
+  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)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc, Just d <- unliteral sd, Just e <- unliteral se, Just f <- unliteral sf, Just g <- unliteral sg
+    = literal (a, b, c, d, e, f, g)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      csv <- sbvToSV st sc
+                      dsv <- sbvToSV st sd
+                      esv <- sbvToSV st se
+                      fsv <- sbvToSV st sf
+                      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
+  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)
+    | Just a <- unliteral sa, Just b <- unliteral sb, Just c <- unliteral sc, Just d <- unliteral sd, Just e <- unliteral se, Just f <- unliteral sf, Just g <- unliteral sg, Just h <- unliteral sh
+    = literal (a, b, c, d, e, f, g, h)
+    | True
+    = SBV $ SVal k $ Right $ cache res
+    where k      = kindOf p
+          res st = do asv <- sbvToSV st sa
+                      bsv <- sbvToSV st sb
+                      csv <- sbvToSV st sc
+                      dsv <- sbvToSV st sd
+                      esv <- sbvToSV st se
+                      fsv <- sbvToSV st sf
+                      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)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Data/SBV/Utils/Boolean.hs b/Data/SBV/Utils/Boolean.hs
deleted file mode 100644
--- a/Data/SBV/Utils/Boolean.hs
+++ /dev/null
@@ -1,81 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Utils.Boolean
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Abstraction of booleans. Unfortunately, Haskell makes Bool's very hard to
--- work with, by making it a fixed-data type. This is our workaround
------------------------------------------------------------------------------
-
-module Data.SBV.Utils.Boolean(Boolean(..), bAnd, bOr, bAny, bAll)  where
-
-infixl 6 <+>       -- xor
-infixr 3 &&&, ~&   -- and, nand
-infixr 2 |||, ~|   -- or, nor
-infixr 1 ==>, <=>  -- implies, iff
-
--- | The 'Boolean' class: a generalization of Haskell's 'Bool' type
--- Haskell 'Bool' and SBV's 'SBool' are instances of this class, unifying the treatment of boolean values.
---
--- Minimal complete definition: 'true', 'bnot', '&&&'
--- However, it's advisable to define 'false', and '|||' as well (typically), for clarity.
-class Boolean b where
-  -- | logical true
-  true   :: b
-  -- | logical false
-  false  :: b
-  -- | complement
-  bnot   :: b -> b
-  -- | and
-  (&&&)  :: b -> b -> b
-  -- | or
-  (|||)  :: b -> b -> b
-  -- | nand
-  (~&)   :: b -> b -> b
-  -- | nor
-  (~|)   :: b -> b -> b
-  -- | xor
-  (<+>)  :: b -> b -> b
-  -- | implies
-  (==>)  :: b -> b -> b
-  -- | equivalence
-  (<=>)  :: b -> b -> b
-  -- | cast from Bool
-  fromBool :: Bool -> b
-
-  -- default definitions
-  false   = bnot true
-  a ||| b = bnot (bnot a &&& bnot b)
-  a ~& b  = bnot (a &&& b)
-  a ~| b  = bnot (a ||| b)
-  a <+> b = (a &&& bnot b) ||| (bnot a &&& b)
-  a <=> b = (a &&& b) ||| (bnot a &&& bnot b)
-  a ==> b = bnot a ||| b
-  fromBool True  = true
-  fromBool False = false
-
--- | Generalization of 'and'
-bAnd :: Boolean b => [b] -> b
-bAnd = foldr (&&&) true
-
--- | Generalization of 'or'
-bOr :: Boolean b => [b] -> b
-bOr  = foldr (|||) false
-
--- | Generalization of 'any'
-bAny :: Boolean b => (a -> b) -> [a] -> b
-bAny f = bOr  . map f
-
--- | Generalization of 'all'
-bAll :: Boolean b => (a -> b) -> [a] -> b
-bAll f = bAnd . map f
-
-instance Boolean Bool where
-  true   = True
-  false  = False
-  bnot   = not
-  (&&&)  = (&&)
-  (|||)  = (||)
diff --git a/Data/SBV/Utils/CrackNum.hs b/Data/SBV/Utils/CrackNum.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Utils/CrackNum.hs
@@ -0,0 +1,326 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Utils.CrackNum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Crack internal representation for numeric types
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE NamedFieldPuns #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Utils.CrackNum (
+        crackNum
+      ) where
+
+import Data.SBV.Core.Concrete
+import Data.SBV.Core.Kind
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Utils.Numeric
+import Data.SBV.Utils.PrettyNum (showFloatAtBase)
+
+import Data.Char (intToDigit, toUpper, isSpace)
+
+import Data.Bits
+import Data.List
+
+import LibBF hiding (Zero, bfToString)
+
+import Numeric
+
+-- | A class for cracking things deeper, if we know how.
+class CrackNum a where
+  -- | Convert an item to possibly bit-level description, if possible.
+  crackNum :: a -> Bool -> Maybe Integer -> Maybe String
+
+-- | CVs are easy to crack
+instance CrackNum CV where
+  crackNum cv verbose mbIV = case kindOf cv of
+                               -- Maybe one day we'll have a use for these, currently cracking them
+                               -- any further seems overkill
+                               KVar       {}  -> Nothing
+                               KBool      {}  -> Nothing
+                               KUnbounded {}  -> Nothing
+                               KReal      {}  -> Nothing
+                               KApp       {}  -> Nothing
+                               KADT       {}  -> Nothing
+                               KChar      {}  -> Nothing
+                               KString    {}  -> Nothing
+                               KList      {}  -> Nothing
+                               KSet       {}  -> Nothing
+                               KTuple     {}  -> Nothing
+                               KRational  {}  -> Nothing
+                               KArray     {}  -> Nothing
+
+                               -- Actual crackables
+                               KFloat{}       | CFloat   f <- cvVal cv -> Just $ float verbose mbIV f
+                                              | True                   -> Nothing   -- Can't really happen; but don't die
+
+                               KDouble{}      | CDouble  d <- cvVal cv -> Just $ float verbose mbIV d
+                                              | True                   -> Nothing   -- Can't really happen; but don't die
+
+                               KFP{}          | CFP      f <- cvVal cv -> Just $ float verbose mbIV f
+                                              | True                   -> Nothing   -- Can't really happen; but don't die
+
+                               KBounded sg sz | CInteger i <- cvVal cv -> Just $ int   sg sz i
+                                              | True                   -> Nothing   -- Can't really happen; but don't die
+
+-- How far off the screen we want displayed? Somewhat experimentally found.
+tab :: String
+tab = replicate 18 ' '
+
+-- Make splits of 4, top one has the remainder
+split4 :: Int -> [Int]
+split4 n
+  | m == 0 =     rest
+  | True   = m : rest
+  where (d, m) = n `divMod` 4
+        rest   = replicate d 4
+
+-- Convert bits to the corresponding integer.
+getVal :: [Bool] -> Integer
+getVal = foldl' (\s b -> 2 * s + if b then 1 else 0) 0
+
+-- Show in hex, but pay attention to how wide a field it should be in
+mkHex :: [Bool] -> String
+mkHex bin = map toUpper $ showHex (getVal bin) ""
+
+-- | Show a sized word/int in detail
+int :: Bool -> Int -> Integer -> String
+int signed sz v = intercalate "\n" $ ruler ++ info
+  where splits = split4 sz
+
+        ruler = map (tab ++) $ mkRuler sz splits
+
+        bitRep :: [[Bool]]
+        bitRep = split splits [v `testBit` i | i <- reverse [0 .. sz - 1]]
+
+        flatHex = concatMap mkHex bitRep
+        iprec
+          | signed = "Signed "   ++ show sz ++ "-bit 2's complement integer"
+          | True   = "Unsigned " ++ show sz ++ "-bit word"
+
+        signBit = v `testBit` (sz-1)
+        s | signed && signBit = "-"
+          | True              = ""
+
+        av = abs v
+
+        info = [ "   Binary layout: " ++ unwords [concatMap (\b -> if b then "1" else "0") is | is <- bitRep]
+               , "      Hex layout: " ++ unwords (split (split4 (length flatHex)) flatHex)
+               , "            Type: " ++ iprec
+               ]
+            ++ [ "            Sign: " ++ if signBit then "Negative" else "Positive" | signed]
+            ++ [ "          Binary: " ++ s ++ "0b" ++ showIntAtBase 2 intToDigit av ""
+               , "           Octal: " ++ s ++ "0o" ++ showOct av ""
+               , "         Decimal: " ++ show v
+               , "             Hex: " ++ s ++ "0x" ++ showHex av ""
+               ]
+
+-- | What kind of Float is this?
+data FPKind = Zero       Bool  -- with sign
+            | Infty      Bool  -- with sign
+            | NaN
+            | Subnormal
+            | Normal
+            deriving Eq
+
+-- | Show instance for Kind, not for reading back!
+instance Show FPKind where
+  show Zero{}    = "FP_ZERO"
+  show Infty{}   = "FP_INFINITE"
+  show NaN       = "FP_NAN"
+  show Subnormal = "FP_SUBNORMAL"
+  show Normal    = "FP_NORMAL"
+
+-- | Find out what kind this float is. We specifically ask
+-- the caller to provide if the number is zero, neg-inf, and pos-inf. Why?
+-- Because the FP type doesn't have those recognizers that also work with Float/Double.
+getKind :: RealFloat a => a -> FPKind
+getKind fp
+ | fp == 0           = Zero  (isNegativeZero fp)
+ | isInfinite fp     = Infty (fp < 0)
+ | isNaN fp          = NaN
+ | isDenormalized fp = Subnormal
+ | True              = Normal
+
+-- Show the value in different bases
+showAtBases :: FPKind -> (String, String, String, String) -> Either String (String, String, String, String)
+showAtBases k bvs = case k of
+                     Zero False  -> Right ("0b0.0",  "0o0.0",  "0.0",  "0x0")
+                     Zero True   -> Right ("-0b0.0", "-0o0.0", "-0.0", "-0o0")
+                     Infty False -> Left  "Infinity"
+                     Infty True  -> Left  "-Infinity"
+                     NaN         -> Left  "NaN"
+                     Subnormal   -> Right (dropSuffixes bvs)
+                     Normal      -> Right (dropSuffixes bvs)
+  where dropSuffixes (a, b, c, d) = (bfRemoveRedundantExp a, bfRemoveRedundantExp b, bfRemoveRedundantExp c, bfRemoveRedundantExp d)
+
+-- | Float data for display purposes
+data FloatData = FloatData { prec   :: String
+                           , eb     :: Int
+                           , sb     :: Int
+                           , bits   :: Integer
+                           , fpKind :: FPKind
+                           , fpVals :: Either String (String, String, String, String)
+                           }
+
+-- | A simple means to organize different bits and pieces of float data
+-- for display purposes
+class HasFloatData a where
+  getFloatData :: a -> FloatData
+
+-- | Float instance
+instance HasFloatData Float where
+  getFloatData f = FloatData {
+      prec   = "Single"
+    , eb     =  8
+    , sb     = 24
+    , bits   = fromIntegral (floatToWord f)
+    , fpKind = k
+    , fpVals = showAtBases k (showFloatAtBase 2 f "", showFloatAtBase 8 f "", show f, showFloatAtBase 16 f "")
+    }
+    where k = getKind f
+
+-- | Double instance
+instance HasFloatData Double where
+  getFloatData d  = FloatData {
+      prec   = "Double"
+    , eb     = 11
+    , sb     = 53
+    , bits   = fromIntegral (doubleToWord d)
+    , fpKind = k
+    , fpVals = showAtBases k (showFloatAtBase 2 d "", showFloatAtBase 8 d "", show d, showFloatAtBase 16 d "")
+    }
+    where k = getKind d
+
+-- | Find the exponent values, (exponent value, exponent as stored, bias)
+getExponentData :: FloatData -> (Integer, Integer, Integer)
+getExponentData FloatData{eb, sb, bits, fpKind} = (expValue, expStored, bias)
+  where -- | Bias is 2^(eb-1) - 1
+        bias :: Integer
+        bias = (2 :: Integer) ^ ((fromIntegral eb :: Integer) - 1) - 1
+
+        -- | Exponent as stored is simply bit extraction
+        expStored = getVal [bits `testBit` i | i <- reverse [sb-1 .. sb+eb-2]]
+
+        -- | Exponent value is stored exponent - bias, unless the number is subnormal. In that case it is 1 - bias
+        expValue = case fpKind of
+                     Subnormal -> 1 - bias
+                     _         -> expStored - bias
+
+-- | FP instance
+instance HasFloatData FP where
+  getFloatData v@(FP eb sb f) = FloatData {
+      prec   = case (eb, sb) of
+                 ( 5,  11) -> "Half (5 exponent bits, 10 significand bits.)"
+                 ( 8,  24) -> "Single (8 exponent bits, 23 significand bits.)"
+                 (11,  53) -> "Double (11 exponent bits, 52 significand bits.)"
+                 (15, 113) -> "Quad (15 exponent bits, 112 significand bits.)"
+                 ( _,   _) -> show eb ++ " exponent bits, " ++ show (sb-1) ++ " significand bit" ++ if sb > 2 then "s" else ""
+    , eb     = eb
+    , sb     = sb
+    , bits   = bfToBits (mkBFOpts eb sb NearEven) f
+    , fpKind = k
+    , fpVals = showAtBases k (bfToString 2 True True v, bfToString 8 True True v, bfToString 10 True False v, bfToString 16 True True v)
+    }
+    where opts = mkBFOpts eb sb NearEven
+          k | bfIsZero f           = Zero  (bfIsNeg f)
+            | bfIsInf f            = Infty (bfIsNeg f)
+            | bfIsNaN f            = NaN
+            | bfIsSubnormal opts f = Subnormal
+            | True                 = Normal
+
+-- | Show a float in detail. mbSurface is the integer equivalent if this is a NaN; so we
+-- can represent it faithfully to the original given. Used by crackNum executable.
+float :: HasFloatData a => Bool -> Maybe Integer -> a -> String
+float verbose mbSurface f = intercalate "\n" $ ruler ++ legend : info
+   where fd@FloatData{prec, eb, sb, bits = bitsAsStored, fpKind, fpVals} = getFloatData f
+
+         nanKind = case fpKind of
+                     Zero{}    -> False
+                     Infty{}   -> False
+                     NaN       -> True
+                     Subnormal -> False
+                     Normal    -> False
+
+         (nanClassifier, bits, nanChanged)
+           | nanKind, Just i <- mbSurface = (extraClassifier i,  i,            i /= bitsAsStored)
+           | True                         = ("",                 bitsAsStored, False)
+
+         -- Is this surface representation a signaling NaN or a quiet nan?
+         -- The test is that the tip bit of the significand is high: If so, quiet. If top bit is low, then signaling.
+         extraClassifier :: Integer -> String
+         extraClassifier i
+           | sb < 2               = ""      -- I don't think this can happen, but just in case
+           | i `testBit` (sb - 2) = " (Quiet)"
+           | True                 = " (Signaling)"
+
+         splits = [1, eb, sb]
+         ruler  = map (tab ++) $ mkRuler (eb + sb) splits
+
+         legend = tab ++ "S " ++ mkTag ('E' : show eb) eb ++ " " ++ mkTag ('S' : show (sb-1)) (sb-1)
+
+         mkTag t len = take len $ replicate ((len - length t) `div` 2) '-' ++ t ++ repeat '-'
+
+         allBits :: [Bool]
+         allBits = [bits `testBit` i | i <- reverse [0 .. eb + sb - 1]]
+
+         storedBits :: [Bool]
+         storedBits = [bitsAsStored `testBit` i | i <- reverse [0 .. eb + sb - 1]]
+
+         flatHex = concatMap mkHex (split (split4 (eb + sb)) allBits)
+         sign    = bits `testBit` (eb+sb-1)
+
+         (exponentVal, storedExponent, bias) = getExponentData fd
+
+         esInfo = "Stored: " ++ show storedExponent ++ ", Bias: " ++ show bias
+
+         chunks bs = unwords [concatMap (\b -> if b then "1" else "0") is | is <- split splits bs]
+
+         isSubNormal = case fpKind of
+                         Subnormal -> True
+                         _         -> False
+
+         info =   [ "   Binary layout: " ++ chunks allBits]
+               ++ [ " Calculated bits: " ++ chunks storedBits ++ " (Surface NaN value differs from calculated)" | verbose && nanChanged]
+               ++ [ "      Hex layout: " ++ unwords (split (split4 (length flatHex)) flatHex)
+                  , "       Precision: " ++ prec
+                  , "            Sign: " ++ if sign then "Negative" else "Positive"
+                  ]
+               ++ [ "        Exponent: " ++ show exponentVal ++ " (Subnormal, with fixed exponent value. " ++ esInfo ++ ")" | isSubNormal    ]
+               ++ [ "        Exponent: " ++ show exponentVal ++ " ("                                       ++ esInfo ++ ")" | not isSubNormal]
+               ++ [ "  Classification: " ++ show fpKind ++ nanClassifier]
+               ++ (case fpVals of
+                     Left val                       -> [ "           Value: " ++ val]
+                     Right (bval, oval, dval, hval) -> [ "          Binary: " ++ bval
+                                                       , "           Octal: " ++ oval
+                                                       , "         Decimal: " ++ dval
+                                                       , "             Hex: " ++ hval
+                                                       ])
+               ++ [ "            Note: Representation for NaN's is not unique" | fpKind == NaN]
+
+
+-- | Build a ruler with given split points
+mkRuler :: Int -> [Int] -> [String]
+mkRuler n splits = map (trimRight . unwords . split splits . trim Nothing) $ transpose $ map pad $ reverse [0 .. n-1]
+  where len = length (show (n-1))
+        pad i = reverse $ take len $ reverse (show i) ++ repeat '0'
+
+        trim _      "" = ""
+        trim mbPrev (c:cs)
+          | mbPrev == Just c = ' ' : trim mbPrev   cs
+          | True             =  c  : trim (Just c) cs
+
+        trimRight = reverse . dropWhile isSpace . reverse
+
+split :: [Int] -> [a] -> [[a]]
+split _      [] = []
+split []     xs = [xs]
+split (i:is) xs = case splitAt i xs of
+                   (pre, [])   -> [pre]
+                   (pre, post) -> pre : split is post
diff --git a/Data/SBV/Utils/ExtractIO.hs b/Data/SBV/Utils/ExtractIO.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Utils/ExtractIO.hs
@@ -0,0 +1,51 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Utils.ExtractIO
+-- Copyright : (c) Brian Schroeder
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Helper typeclass for interoperation with APIs which take IO actions in
+-- negative position.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Utils.ExtractIO where
+
+import Control.Monad.Except      (ExceptT(ExceptT), runExceptT)
+import Control.Monad.IO.Class    (MonadIO)
+import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT)
+
+import qualified Control.Monad.Writer.Lazy   as LW
+import qualified Control.Monad.Writer.Strict as SW
+
+-- | Monads which support 'IO' operations and can extract all 'IO' behavior for
+-- interoperation with functions like 'Control.Concurrent.catches', which takes
+-- an 'IO' action in negative position. This function can not be implemented
+-- for transformers like @ReaderT r@ or @StateT s@, whose resultant 'IO'
+-- actions are a function of some environment or state.
+class MonadIO m => ExtractIO m where
+    -- | Law: the @m a@ yielded by 'IO' is pure with respect to 'IO'.
+    extractIO :: m a -> IO (m a)
+
+-- | Trivial IO extraction for 'IO'.
+instance ExtractIO IO where
+    extractIO = fmap pure
+
+-- | IO extraction for t'MaybeT'.
+instance ExtractIO m => ExtractIO (MaybeT m) where
+    extractIO = fmap MaybeT . extractIO . runMaybeT
+
+-- | IO extraction for t'ExceptT'.
+instance ExtractIO m => ExtractIO (ExceptT e m) where
+    extractIO = fmap ExceptT . extractIO . runExceptT
+
+-- | IO extraction for lazy t'LW.WriterT'.
+instance (Monoid w, ExtractIO m) => ExtractIO (LW.WriterT w m) where
+    extractIO = fmap LW.WriterT . extractIO . LW.runWriterT
+
+-- | IO extraction for strict t'SW.WriterT'.
+instance (Monoid w, ExtractIO m) => ExtractIO (SW.WriterT w m) where
+    extractIO = fmap SW.WriterT . extractIO . SW.runWriterT
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,49 +1,87 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Utils.Lib
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Utils.Lib
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Misc helpers
 -----------------------------------------------------------------------------
 
-module Data.SBV.Utils.Lib (mlift2, mlift3, mlift4, mlift5, mlift6, mlift7, mlift8, joinArgs, splitArgs) where
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
-import Data.Char (isSpace)
-import Data.Maybe (fromJust, isNothing)
+{-# OPTIONS_GHC -Wall -Werror #-}
 
+module Data.SBV.Utils.Lib ( mlift2, mlift3, mlift4, mlift5, mlift6, mlift7, mlift8
+                          , joinArgs, splitArgs
+                          , stringToQFS, qfsToString
+                          , showText
+                          , isKString
+                          , checkObservableName
+                          , needsBars, barify
+                          , unQuote, unBar, nameSupply
+                          , atProxy
+                          , mapToSortedList
+                          ,   curry2,   curry3,   curry4,   curry5,   curry6,   curry7,   curry8,   curry9,   curry10,   curry11,   curry12
+                          , uncurry2, uncurry3, uncurry4, uncurry5, uncurry6, uncurry7, uncurry8, uncurry9, uncurry10, uncurry11, uncurry12
+                          )
+                          where
+
+import Data.Char    (isSpace, chr, ord, isDigit, isAscii, isAlphaNum)
+import Data.List    (isPrefixOf, isSuffixOf, sortBy)
+import Data.Ord     (comparing)
+import Data.Dynamic (fromDynamic, toDyn, Typeable)
+import Data.Maybe   (fromJust, isJust, isNothing)
+import Data.Proxy
+import Data.Text    (Text)
+
+import qualified Data.Text as T
+
+import qualified Data.Map.Strict as Map
+
+import Type.Reflection (typeRep)
+
+import Numeric (readHex, showHex)
+
+import Data.SBV.SMT.SMTLibNames (isReserved)
+
+-- | We have a nasty issue with the usual String/List confusion in Haskell. However, we can
+-- do a simple dynamic trick to determine where we are. The ice is thin here, but it seems to work.
+isKString :: forall a. Typeable a => a -> Bool
+isKString _ = isJust (fromDynamic (toDyn (undefined :: a)) :: Maybe String)
+
 -- | Monadic lift over 2-tuples
 mlift2 :: Monad m => (a' -> b' -> r) -> (a -> m a') -> (b -> m b') -> (a, b) -> m r
-mlift2 k f g (a, b) = f a >>= \a' -> g b >>= \b' -> return $ k a' b'
+mlift2 k f g (a, b) = f a >>= \a' -> g b >>= \b' -> pure $ k a' b'
 
 -- | Monadic lift over 3-tuples
 mlift3 :: Monad m => (a' -> b' -> c' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (a, b, c) -> m r
-mlift3 k f g h (a, b, c) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> return $ k a' b' c'
+mlift3 k f g h (a, b, c) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> pure $ k a' b' c'
 
 -- | Monadic lift over 4-tuples
 mlift4 :: Monad m => (a' -> b' -> c' -> d' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (a, b, c, d) -> m r
-mlift4 k f g h i (a, b, c, d) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> return $ k a' b' c' d'
+mlift4 k f g h i (a, b, c, d) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> pure $ k a' b' c' d'
 
 -- | Monadic lift over 5-tuples
 mlift5 :: Monad m => (a' -> b' -> c' -> d' -> e' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (a, b, c, d, e) -> m r
-mlift5 k f g h i j (a, b, c, d, e) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> return $ k a' b' c' d' e'
+mlift5 k f g h i j (a, b, c, d, e) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> pure $ k a' b' c' d' e'
 
 -- | Monadic lift over 6-tuples
 mlift6 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (a, b, c, d, e, f) -> m r
-mlift6 k f g h i j l (a, b, c, d, e, y) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> return $ k a' b' c' d' e' y'
+mlift6 k f g h i j l (a, b, c, d, e, y) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> pure $ k a' b' c' d' e' y'
 
 -- | Monadic lift over 7-tuples
 mlift7 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> g' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (g -> m g') -> (a, b, c, d, e, f, g) -> m r
-mlift7 k f g h i j l m (a, b, c, d, e, y, z) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> return $ k a' b' c' d' e' y' z'
+mlift7 k f g h i j l m (a, b, c, d, e, y, z) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> pure $ k a' b' c' d' e' y' z'
 
 -- | Monadic lift over 8-tuples
 mlift8 :: Monad m => (a' -> b' -> c' -> d' -> e' -> f' -> g' -> h' -> r) -> (a -> m a') -> (b -> m b') -> (c -> m c') -> (d -> m d') -> (e -> m e') -> (f -> m f') -> (g -> m g') -> (h -> m h') -> (a, b, c, d, e, f, g, h) -> m r
-mlift8 k f g h i j l m n (a, b, c, d, e, y, z, w) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> n w >>= \w' -> return $ k a' b' c' d' e' y' z' w'
+mlift8 k f g h i j l m n (a, b, c, d, e, y, z, w) = f a >>= \a' -> g b >>= \b' -> h c >>= \c' -> i d >>= \d' -> j e >>= \e' -> l y >>= \y' -> m z >>= \z' -> n w >>= \w' -> pure $ k a' b' c' d' e' y' z' w'
 
 -- Command line argument parsing code courtesy of Neil Mitchell's cmdargs package: see
--- <https://github.com/ndmitchell/cmdargs/blob/master/System/Console/CmdArgs/Explicit/SplitJoin.hs>
+-- <http://github.com/ndmitchell/cmdargs/blob/master/System/Console/CmdArgs/Explicit/SplitJoin.hs>
 
 -- | Given a sequence of arguments, join them together in a manner that could be used on
 --   the command line, giving preference to the Windows @cmd@ shell quoting conventions.
@@ -88,3 +126,167 @@
           f Norm (x:xs) | isSpace x = Nothing : f Init xs
           f m (x:xs)                = Just x : f m xs
           f _ []                    = []
+
+-- | Given an SMTLib string (i.e., one that works in the string theory), convert it to a Haskell equivalent
+qfsToString :: String -> String
+qfsToString = go
+  where go "" = ""
+
+        go ('\\':'u':'{':d4:d3:d2:d1:d0:'}' : rest) | [(v, "")] <- readHex [d4, d3, d2, d1, d0] = chr v : go rest
+        go ('\\':'u':       d3:d2:d1:d0     : rest) | [(v, "")] <- readHex [    d3, d2, d1, d0] = chr v : go rest
+        go ('\\':'u':'{':   d3:d2:d1:d0:'}' : rest) | [(v, "")] <- readHex [    d3, d2, d1, d0] = chr v : go rest
+        go ('\\':'u':'{':      d2:d1:d0:'}' : rest) | [(v, "")] <- readHex [        d2, d1, d0] = chr v : go rest
+        go ('\\':'u':'{':         d1:d0:'}' : rest) | [(v, "")] <- readHex [            d1, d0] = chr v : go rest
+        go ('\\':'u':'{':            d0:'}' : rest) | [(v, "")] <- readHex [                d0] = chr v : go rest
+
+        -- Otherwise, just proceed; hopefully we covered everything above
+        go (c : rest) = c : go rest
+
+-- | Show a value as 'Text'.
+showText :: Show a => a -> Text
+showText = T.pack . show
+
+-- | Given a Haskell string, convert it to SMTLib. if ord is 0x00020 to 0x0007E, then we print it as is
+-- to cover the printable ASCII range.
+stringToQFS :: String -> String
+stringToQFS = concatMap cvt
+  where cvt c
+         | c == '"'                 = "\"\""
+         | oc >= 0x20 && oc <= 0x7E = [c]
+         | True                     = "\\u{" ++ showHex oc "" ++ "}"
+         where oc = ord c
+
+-- | Check if an observable name is good.
+checkObservableName :: String -> Maybe String
+checkObservableName lbl
+  | null lbl
+  = Just "SBV.observe: Bad empty name!"
+  | isReserved lbl
+  = Just $ "SBV.observe: The name chosen is reserved, please change it!: " ++ show lbl
+  | "s" `isPrefixOf` lbl && all isDigit (drop 1 lbl)
+  = Just $ "SBV.observe: Names of the form sXXX are internal to SBV, please use a different name: " ++ show lbl
+  | True
+  = Nothing
+
+-- Remove one pair of surrounding 'c's, if present
+noSurrounding :: Char -> String -> String
+noSurrounding c (c':cs@(_:_)) | c == c' && c == last cs  = init cs
+noSurrounding _ s                                        = s
+
+-- Remove a pair of surrounding quotes
+unQuote :: String -> String
+unQuote = noSurrounding '"'
+
+-- Remove a pair of surrounding bars
+unBar :: String -> String
+unBar = noSurrounding '|'
+
+-- | Add bars if needed
+barify :: String -> String
+barify s | needsBars s = '|' : s ++ "|"
+         | True        = s
+
+-- Is this string surrounded by bars? NB. There shouldn't be any other bars or backslash anywhere
+isEnclosedInBars :: String -> Bool
+isEnclosedInBars nm =  "|" `isPrefixOf` nm
+                    && "|" `isSuffixOf` nm
+                    && length nm > 2
+                    && not (any (`elem` ("|\\" :: String)) (drop 1 (init nm)))
+
+-- Does this name need bar in SMTLib2?
+needsBars :: String -> Bool
+needsBars ""        = error "Impossible happened: needsBars received an empty name!"
+needsBars nm@(h:tl) = not (isEnclosedInBars nm || (isAscii h && all validChar tl))
+ where  validChar x = isAscii x && (isAlphaNum x || x `elem` ("_" :: String))
+
+-- | Converts a proxy to a readable result. This is useful when you want to write a polymorphic
+-- proof, so that the name contains the instantiated version properly.
+atProxy :: forall a. Typeable a => Proxy a -> String -> String
+atProxy _ nm = nm ++ " @" ++ par (show (typeRep @a))
+ where par s | any isSpace s = '(' : s ++ ")"
+             | True          = s
+
+-- An infinite supply of names, starting with a given set
+nameSupply :: [String] -> [String]
+nameSupply preSupply = preSupply ++ map mkUnique extras
+  where extras =  ["x", "y", "z"]                           -- x y z
+               ++ [[c] | c <- ['a' .. 'w']]                 -- a b c ... w
+               ++ ['x' : show i | i <- [(1::Int) ..]]       -- x1 x2 x3 ...
+
+        -- make sure extras are different than preSupply. Note that extras
+        -- themselves are unique, so we only have to check the preSupply
+        mkUnique x | x `elem` preSupply = mkUnique $ x ++ "'"
+                   | True               = x
+
+-- Different arities of curry/uncurry
+curry2 :: ((a, b) -> z) -> a -> b -> z
+curry2 fn a b = fn (a, b)
+
+curry3 :: ((a, b, c) -> z) -> a -> b -> c -> z
+curry3 fn a b c = fn (a, b, c)
+
+curry4 :: ((a, b, c, d) -> z) -> a -> b -> c -> d -> z
+curry4 fn a b c d = fn (a, b, c, d)
+
+curry5 :: ((a, b, c, d, e) -> z) -> a -> b -> c -> d -> e -> z
+curry5 fn a b c d e = fn (a, b, c, d, e)
+
+curry6 :: ((a, b, c, d, e, f) -> z) -> a -> b -> c -> d -> e -> f -> z
+curry6 fn a b c d e f = fn (a, b, c, d, e, f)
+
+curry7 :: ((a, b, c, d, e, f, g) -> z) -> a -> b -> c -> d -> e -> f -> g -> z
+curry7 fn a b c d e f g = fn (a, b, c, d, e, f, g)
+
+curry8 :: ((a, b, c, d, e, f, g, h) -> z) -> a -> b -> c -> d -> e -> f -> g -> h -> z
+curry8 fn a b c d e f g h = fn (a, b, c, d, e, f, g, h)
+
+curry9 :: ((a, b, c, d, e, f, g, h, i) -> z) -> a -> b -> c -> d -> e -> f -> g -> h -> i -> z
+curry9 fn a b c d e f g h i = fn (a, b, c, d, e, f, g, h, i)
+
+curry10 :: ((a, b, c, d, e, f, g, h, i, j) -> z) -> a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> z
+curry10 fn a b c d e f g h i j = fn (a, b, c, d, e, f, g, h, i, j)
+
+curry11 :: ((a, b, c, d, e, f, g, h, i, j, k) -> z) -> a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> z
+curry11 fn a b c d e f g h i j k = fn (a, b, c, d, e, f, g, h, i, j, k)
+
+curry12 :: ((a, b, c, d, e, f, g, h, i, j, k, l) -> z) -> a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> z
+curry12 fn a b c d e f g h i j k l = fn (a, b, c, d, e, f, g, h, i, j, k, l)
+
+uncurry2 :: (a -> b -> z) -> (a, b) -> z
+uncurry2 fn (a, b) = fn a b
+
+uncurry3 :: (a -> b -> c -> z) -> (a, b, c) -> z
+uncurry3 fn (a, b, c) = fn a b c
+
+uncurry4 :: (a -> b -> c -> d -> z) -> (a, b, c, d) -> z
+uncurry4 fn (a, b, c, d) = fn a b c d
+
+uncurry5 :: (a -> b -> c -> d -> e -> z) -> (a, b, c, d, e) -> z
+uncurry5 fn (a, b, c, d, e) = fn a b c d e
+
+uncurry6 :: (a -> b -> c -> d -> e -> f -> z) -> (a, b, c, d, e, f) -> z
+uncurry6 fn (a, b, c, d, e, f) = fn a b c d e f
+
+uncurry7 :: (a -> b -> c -> d -> e -> f -> g -> z) -> (a, b, c, d, e, f, g) -> z
+uncurry7 fn (a, b, c, d, e, f, g) = fn a b c d e f g
+
+uncurry8 :: (a -> b -> c -> d -> e -> f -> g -> h -> z) -> (a, b, c, d, e, f, g, h) -> z
+uncurry8 fn (a, b, c, d, e, f, g, h) = fn a b c d e f g h
+
+uncurry9 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> z) -> (a, b, c, d, e, f, g, h, i) -> z
+uncurry9 fn (a, b, c, d, e, f, g, h, i) = fn a b c d e f g h i
+
+uncurry10 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> z) -> (a, b, c, d, e, f, g, h, i, j) -> z
+uncurry10 fn (a, b, c, d, e, f, g, h, i, j) = fn a b c d e f g h i j
+
+uncurry11 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> z) -> (a, b, c, d, e, f, g, h, i, j, k) -> z
+uncurry11 fn (a, b, c, d, e, f, g, h, i, j, k) = fn a b c d e f g h i j k
+
+uncurry12 :: (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k -> l -> z) -> (a, b, c, d, e, f, g, h, i, j, k, l) -> z
+uncurry12 fn (a, b, c, d, e, f, g, h, i, j, k, l) = fn a b c d e f g h i j k l
+
+-- | Convert a map to a list of @(value, key)@ pairs, sorted by value.
+-- Useful when the map is keyed by a descriptor but indexed by an integer
+-- that determines output order.
+mapToSortedList :: Ord v => Map.Map k v -> [(v, k)]
+mapToSortedList = sortBy (comparing fst) . map (\(a, b) -> (b, a)) . Map.toList
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,32 +1,37 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Utils.Numeric
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Utils.Numeric
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Various number related utilities
 -----------------------------------------------------------------------------
 
-module Data.SBV.Utils.Numeric where
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
 
--- | 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
+{-# OPTIONS_GHC -Wall -Werror #-}
 
--- | 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
+module Data.SBV.Utils.Numeric (
+           fpMaxH, fpMinH, fp2fp, fpRemH, fpRoundToIntegralH, fpIsEqualObjectH, fpCompareObjectH, fpIsNormalizedH
+         , floatToWord, wordToFloat, doubleToWord, wordToDouble
+         , RoundingMode(..), smtRoundingMode
+         ) where
 
+import Data.Word
+import Data.Text         (Text)
+import Data.Array.ST     (newArray, readArray, MArray, STUArray)
+import Data.Array.Unsafe (castSTUArray)
+import GHC.ST            (runST, ST)
+
+import Test.QuickCheck  (Arbitrary(..), elements)
+
 -- | 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:
---      <https://ghc.haskell.org/trac/ghc/ticket/10378>
---      <https://github.com/Z3Prover/z3/issues/68>
+--      <https://gitlab.haskell.org/ghc/ghc/-/issues/10378>
+--      <http://github.com/Z3Prover/z3/issues/68>
 -- So, we codify here what the Z3 (SMTLib) is implementing for fpMax.
 -- The discrepancy with Haskell is that the NaN propagation doesn't work in Haskell
 -- The discrepancy with x86 is that given +0/-0, x86 returns the second argument; SMTLib is non-deterministic
@@ -40,7 +45,7 @@
    where isN0   = isNegativeZero
          isP0 a = a == 0 && not (isN0 a)
 
--- | SMTLib compliant definition for 'fpMin'. See the comments for 'fpMax'.
+-- | SMTLib compliant definition for 'Data.SBV.fpMin'. See the comments for 'Data.SBV.fpMax'.
 fpMinH :: RealFloat a => a -> a -> a
 fpMinH x y
    | isNaN x                                  = y
@@ -55,22 +60,21 @@
 -- except careful on NaN, Infinities, and -0.
 fp2fp :: (RealFloat a, RealFloat b) => a -> b
 fp2fp x
- | isNaN x               =  0 / 0
- | isInfinite x && x < 0 = -1 / 0
- | isInfinite x          =  1 / 0
+ | isNaN x               =   0 / 0
+ | isInfinite x && x < 0 = -(1 / 0)
+ | isInfinite x          =   1 / 0
  | isNegativeZero x      = negate 0
  | True                  = fromRational (toRational x)
 
 -- | Compute the "floating-point" remainder function, the float/double value that
 -- remains from the division of @x@ and @y@. There are strict rules around 0's, Infinities,
--- and NaN's as coded below, See <http://smt-lib.org/papers/BTRW14.pdf>, towards the
--- end of section 4.c.
+-- and NaN's as coded below.
 fpRemH :: RealFloat a => a -> a -> a
 fpRemH x y
   | isInfinite x || isNaN x = 0 / 0
   | y == 0       || isNaN y = 0 / 0
   | isInfinite y            = x
-  | True                    = pSign (x - fromRational (fromInteger d * ry))
+  | True                    = pSign (fromRational (rx - fromInteger d * ry))
   where rx, ry, rd :: Rational
         rx = toRational x
         ry = toRational y
@@ -88,7 +92,7 @@
   | isNaN x      = x
   | x == 0       = x
   | isInfinite x = x
-  | i == 0       = if x < 0 || isNegativeZero x then -0.0 else 0.0
+  | i == 0       = if x < 0 then -0.0 else 0.0
   | True         = fromInteger i
   where i :: Integer
         i = round x
@@ -102,7 +106,81 @@
   | isNegativeZero b = isNegativeZero a
   | True             = a == b
 
+-- | Ordering for floats, avoiding the +0/-0/NaN issues. Note that this is
+-- essentially used for indexing into a map, so we need to be total. Thus,
+-- the order we pick is:
+--    NaN -oo -0 +0 +oo
+-- The placement of NaN here is questionable, but immaterial.
+fpCompareObjectH :: RealFloat a => a -> a -> Ordering
+fpCompareObjectH a b
+  | a `fpIsEqualObjectH` b   = EQ
+  | isNaN a                  = LT
+  | isNaN b                  = GT
+  | isNegativeZero a, b == 0 = LT
+  | isNegativeZero b, a == 0 = GT
+  | True                     = a `compare` b
+
 -- | Check if a number is "normal." Note that +0/-0 is not considered a normal-number
 -- and also this is not simply the negation of isDenormalized!
 fpIsNormalizedH :: RealFloat a => a -> Bool
 fpIsNormalizedH x = not (isDenormalized x || isInfinite x || isNaN x || x == 0)
+
+-------------------------------------------------------------------------
+-- Reinterpreting float/double as word32/64 and back. Here, we use the
+-- definitions from the reinterpret-cast package:
+--
+--     http://hackage.haskell.org/package/reinterpret-cast
+--
+-- The reason we steal these definitions is to make sure we keep minimal
+-- dependencies and no FFI requirements anywhere.
+-------------------------------------------------------------------------
+-- | Reinterpret-casts a `Float` to a `Word32`.
+floatToWord :: Float -> Word32
+floatToWord x = runST (cast x)
+{-# INLINEABLE floatToWord #-}
+
+-- | Reinterpret-casts a `Word32` to a `Float`.
+wordToFloat :: Word32 -> Float
+wordToFloat x = runST (cast x)
+{-# INLINEABLE wordToFloat #-}
+
+-- | Reinterpret-casts a `Double` to a `Word64`.
+doubleToWord :: Double -> Word64
+doubleToWord x = runST (cast x)
+{-# INLINEABLE doubleToWord #-}
+
+-- | Reinterpret-casts a `Word64` to a `Double`.
+wordToDouble :: Word64 -> Double
+wordToDouble x = runST (cast x)
+{-# INLINEABLE wordToDouble #-}
+
+{-# INLINE cast #-}
+cast :: (MArray (STUArray s) a (ST s), MArray (STUArray s) b (ST s)) => a -> ST s b
+cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0
+
+-- | Rounding mode to be used for the IEEE floating-point operations.
+-- Note that Haskell's default is 'RoundNearestTiesToEven'. If you use
+-- a different rounding mode, then the counter-examples you get may not
+-- match what you observe in Haskell.
+data RoundingMode = RoundNearestTiesToEven  -- ^ Round to nearest representable floating point value.
+                                            -- If precisely at half-way, pick the even number.
+                                            -- (In this context, /even/ means the lowest-order bit is zero.)
+                  | RoundNearestTiesToAway  -- ^ Round to nearest representable floating point value.
+                                            -- If precisely at half-way, pick the number further away from 0.
+                                            -- (That is, for positive values, pick the greater; for negative values, pick the smaller.)
+                  | RoundTowardPositive     -- ^ Round towards positive infinity. (Also known as rounding-up or ceiling.)
+                  | RoundTowardNegative     -- ^ Round towards negative infinity. (Also known as rounding-down or floor.)
+                  | RoundTowardZero         -- ^ Round towards zero. (Also known as truncation.)
+                  deriving (Show, Enum, Bounded)
+
+-- | Arbitrary instance for 'RoundingMode'
+instance Arbitrary RoundingMode where
+  arbitrary = elements [minBound .. maxBound]
+
+-- | Convert a rounding mode to the format SMT-Lib2 understands.
+smtRoundingMode :: RoundingMode -> Text
+smtRoundingMode RoundNearestTiesToEven = "roundNearestTiesToEven"
+smtRoundingMode RoundNearestTiesToAway = "roundNearestTiesToAway"
+smtRoundingMode RoundTowardPositive    = "roundTowardPositive"
+smtRoundingMode RoundTowardNegative    = "roundTowardNegative"
+smtRoundingMode RoundTowardZero        = "roundTowardZero"
diff --git a/Data/SBV/Utils/PrettyNum.hs b/Data/SBV/Utils/PrettyNum.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Utils/PrettyNum.hs
@@ -0,0 +1,547 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Utils.PrettyNum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Number representations in hex/bin
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Utils.PrettyNum (
+        PrettyNum(..), readBin, shex, chex, shexI, sbin, sbinI
+      , showCFloat, showCDouble, showHFloat, showHDouble, showBFloat, showFloatAtBase
+      , showSMTFloat, showSMTDouble, smtRoundingMode, cvToSMTLib
+      , showNegativeNumber
+      ) where
+
+import Data.Bits  ((.&.), countTrailingZeros, testBit)
+import Data.Char  (intToDigit, ord, chr)
+import Data.Int   (Int8, Int16, Int32, Int64)
+import Data.List  (isPrefixOf)
+import Data.Maybe (fromMaybe, listToMaybe)
+import Data.Ratio (numerator, denominator)
+import Data.Word  (Word8, Word16, Word32, Word64)
+import Data.Text  (Text)
+import qualified Data.Text as T
+
+import qualified Data.Set as Set
+
+import Numeric (showIntAtBase, showHex, readInt, floatToDigits)
+import qualified Numeric as N (showHFloat)
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Kind (smtType, showBaseKind)
+
+import Data.SBV.Core.AlgReals    (algRealToSMTLib2)
+import Data.SBV.Core.SizedFloats (fprToSMTLib2, bfToString)
+
+import Data.SBV.Utils.Lib     (stringToQFS, showText)
+import Data.SBV.Utils.Numeric (smtRoundingMode, floatToWord, doubleToWord)
+
+-- | 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.
+  hexS :: a -> Text
+  -- | Show a number in binary, starting with @0b@ and type.
+  binS :: a -> Text
+  -- | Show a number in hexadecimal, starting with @0x@ but no type.
+  hexP :: a -> Text
+  -- | Show a number in binary, starting with @0b@ but no type.
+  binP :: a -> Text
+  -- | Show a number in hex, without prefix, or types.
+  hex :: a -> Text
+  -- | Show a number in bin, without prefix, or types.
+  bin :: a -> Text
+
+-- Why not default methods? Because defaults need "Integral a" but Bool is not..
+instance PrettyNum Bool where
+  hexS = showText
+  binS = showText
+  hexP = showText
+  binP = showText
+  hex  = showText
+  bin  = showText
+
+instance PrettyNum String where
+  hexS = showText
+  binS = showText
+  hexP = showText
+  binP = showText
+  hex  = showText
+  bin  = showText
+
+instance PrettyNum Word8 where
+  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)
+
+  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)
+
+  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)
+
+  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)
+
+  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
+
+  hexP = shexI False True
+  binP = sbinI False True
+
+  hex  = shexI False False
+  bin  = sbinI False False
+
+shBKind :: HasKind a => a -> Text
+shBKind a = " :: " <> showBaseKind (kindOf a)
+
+instance PrettyNum CV where
+  hexS = cvPretty True  True  True  True  (\f -> T.pack (N.showHFloat f "")) (\d -> T.pack (N.showHFloat d ""))
+  binS = cvPretty False True  True  True  (\f -> T.pack (showBFloat f ""))   (\d -> T.pack (showBFloat d ""))
+  hexP = cvPretty True  False True  False showText                           showText
+  binP = cvPretty False False True  False showText                           showText
+  hex  = cvPretty True  False False False showText                           showText
+  bin  = cvPretty False False False False showText                           showText
+
+-- | Factor out the common structure of PrettyNum CV methods
+cvPretty :: Bool              -- ^ isHex (True) or isBin (False)
+         -> Bool              -- ^ Show type suffix on integers
+         -> Bool              -- ^ Show prefix (0x/0b) on integers
+         -> Bool              -- ^ Show kind suffix on non-integer cases
+         -> (Float -> Text)   -- ^ Float formatter
+         -> (Double -> Text)  -- ^ Double formatter
+         -> CV -> Text
+cvPretty isHex shType shPre shKind fmtF fmtD cv
+  | isADT           cv                         = showText cv <> knd
+  | isBoolean       cv                         = (if isHex then hexS else binS) (cvToBool cv) <> knd
+  | isFloat         cv, CFloat   f <- cvVal cv = fmtF f <> knd
+  | isDouble        cv, CDouble  d <- cvVal cv = fmtD d <> knd
+  | isFP            cv, CFP      f <- cvVal cv = T.pack (bfToString base shPre True f) <> knd
+  | isReal          cv, CAlgReal r <- cvVal cv = showText r <> knd
+  | isString        cv, CString  s <- cvVal cv = showText s <> knd
+  | not (isBounded cv), CInteger i <- cvVal cv = intI i
+  | CInteger i <- cvVal cv                     = intB (hasSign cv, intSizeOf cv) i
+  | True                                       = error $ "PrettyNum: Received CV that can't be displayed: " ++ show cv
+  where knd  = if shKind then shBKind cv else ""
+        base = if isHex then 16 else 2
+        intI = (if isHex then shexI else sbinI) shType shPre
+        intB = (if isHex then shex  else sbin)  shType shPre
+
+instance (SymVal a, PrettyNum a) => PrettyNum (SBV a) where
+  hexS s = maybe (showText s) (hexS :: a -> Text) $ unliteral s
+  binS s = maybe (showText s) (binS :: a -> Text) $ unliteral s
+
+  hexP s = maybe (showText s) (hexP :: a -> Text) $ unliteral s
+  binP s = maybe (showText s) (binP :: a -> Text) $ unliteral s
+
+  hex  s = maybe (showText s) (hex  :: a -> Text) $ unliteral s
+  bin  s = maybe (showText s) (bin  :: a -> Text) $ unliteral s
+
+-- | Show as a hexadecimal value. First bool controls whether type info is printed
+-- while the second boolean controls whether 0x prefix is printed. The tuple is
+-- the signedness and the bit-length of the input. The length of the string
+-- will /not/ depend on the value, but rather the bit-length.
+shex :: (Show a, Integral a) => Bool -> Bool -> (Bool, Int) -> a -> Text
+shex shType shPre (signed, size) a
+ | a < 0
+ = "-" <> pre <> T.pack (pad l (s16 (abs (fromIntegral a :: Integer)))) <> t
+ | True
+ = pre <> T.pack (pad l (s16 a)) <> t
+ where t | shType = " :: " <> (if signed then "Int" else "Word") <> showText size
+         | True   = T.empty
+       pre | shPre = "0x"
+           | True  = T.empty
+       l = (size + 3) `div` 4
+
+-- | Show as hexadecimal, but for C programs. We have to be careful about
+-- printing min-bounds, since C does some funky casting, possibly losing
+-- the sign bit. In those cases, we use the defined constants in <stdint.h>.
+-- We also properly append the necessary suffixes as needed.
+chex :: (Show a, Integral a) => Bool -> Bool -> (Bool, Int) -> a -> Text
+chex shType shPre (signed, size) a
+   | Just s <- (signed, size, fromIntegral a) `lookup` specials
+   = T.pack s
+   | True
+   = shex shType shPre (signed, size) a <> T.pack suffix
+  where specials :: [((Bool, Int, Integer), String)]
+        specials = [ ((True,  8, fromIntegral (minBound :: Int8)),  "INT8_MIN" )
+                   , ((True, 16, fromIntegral (minBound :: Int16)), "INT16_MIN")
+                   , ((True, 32, fromIntegral (minBound :: Int32)), "INT32_MIN")
+                   , ((True, 64, fromIntegral (minBound :: Int64)), "INT64_MIN")
+                   ]
+        suffix = case (signed, size) of
+                   (False, 16) -> "U"
+
+                   (False, 32) -> "UL"
+                   (True,  32) -> "L"
+
+                   (False, 64) -> "ULL"
+                   (True,  64) -> "LL"
+
+                   _           -> ""
+
+-- | Show as a hexadecimal value, integer version. Almost the same as shex above
+-- except we don't have a bit-length so the length of the string will depend
+-- on the actual value.
+shexI :: Bool -> Bool -> Integer -> Text
+shexI shType shPre a
+ | a < 0
+ = "-" <> pre <> T.pack (s16 (abs a)) <> t
+ | True
+ = pre <> T.pack (s16 a) <> t
+ where t | shType = " :: Integer"
+         | True   = T.empty
+       pre | shPre = "0x"
+           | True  = T.empty
+
+-- | Similar to 'shex'; except in binary.
+sbin :: (Show a, Integral a) => Bool -> Bool -> (Bool, Int) -> a -> Text
+sbin shType shPre (signed,size) a
+ | a < 0
+ = "-" <> pre <> T.pack (pad size (s2 (abs (fromIntegral a :: Integer)))) <> t
+ | True
+ = pre <> T.pack (pad size (s2 a)) <> t
+ where t | shType = " :: " <> (if signed then "Int" else "Word") <> showText size
+         | True   = T.empty
+       pre | shPre = "0b"
+           | True  = T.empty
+
+-- | Similar to 'shexI'; except in binary.
+sbinI :: Bool -> Bool -> Integer -> Text
+sbinI shType shPre a
+ | a < 0
+ = "-" <> pre <> T.pack (s2 (abs a)) <> t
+ | True
+ = pre <> T.pack (s2 a) <> t
+ where t | shType = " :: Integer"
+         | True   = T.empty
+       pre | shPre = "0b"
+           | True  = T.empty
+
+-- | Pad a string to a given length. If the string is longer, then we don't drop anything.
+pad :: Int -> String -> String
+pad l s = replicate (l - length s) '0' ++ s
+
+-- | Binary printer
+s2 :: (Show a, Integral a) => a -> String
+s2  v = showIntAtBase 2 intToDigit v ""
+
+-- | Hex printer
+s16 :: (Show a, Integral a) => a -> String
+s16 v = showHex v ""
+
+-- | A more convenient interface for reading binary numbers, also supports negative numbers
+readBin :: Num a => String -> a
+readBin ('-':s) = -(readBin s)
+readBin s = case readInt 2 isDigit cvt s' of
+              [(a, "")] -> a
+              _         -> error $ "SBV.readBin: Cannot read a binary number from: " ++ show s
+  where cvt c = ord c - ord '0'
+        isDigit = (`elem` ("01" :: String))
+        s' | "0b" `isPrefixOf` s = drop 2 s
+           | True                = s
+
+-- | A version of show for floats that generates correct C literals for nan/infinite. NB. Requires "math.h" to be included.
+showCFloat :: Float -> String
+showCFloat f
+   | isNaN f             = "((float) NAN)"
+   | isInfinite f, f < 0 = "((float) (-INFINITY))"
+   | isInfinite f        = "((float) INFINITY)"
+   | True                = N.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 d
+   | isNaN d             = "((double) NAN)"
+   | isInfinite d, d < 0 = "((double) (-INFINITY))"
+   | isInfinite d        = "((double) INFINITY)"
+   | True                = N.showHFloat d " /* " ++ show d ++ " */"
+
+-- | A version of show for floats that generates correct Haskell literals for nan/infinite
+showHFloat :: Float -> String
+showHFloat f
+   | isNaN f             = "((0/0) :: Float)"
+   | isInfinite f, f < 0 = "((-1/0) :: Float)"
+   | isInfinite f        = "((1/0) :: Float)"
+   | True                = show f
+
+-- | A version of show for doubles that generates correct Haskell literals for nan/infinite
+showHDouble :: Double -> String
+showHDouble d
+   | isNaN d             = "((0/0) :: Double)"
+   | isInfinite d, d < 0 = "((-1/0) :: Double)"
+   | isInfinite d        = "((1/0) :: Double)"
+   | True                = show d
+
+-- | A version of show for floats that generates correct SMTLib literals using the rounding mode
+showSMTFloat :: Float -> Text
+showSMTFloat f
+   | isNaN f             = as "NaN"
+   | isInfinite f, f < 0 = as "-oo"
+   | isInfinite f        = as "+oo"
+   | isNegativeZero f    = as "-zero"
+   | f == 0              = as "+zero"
+   | True                = let w   = floatToWord f
+                               b i = if w `testBit` i then '1' else '0'
+                               s   = T.pack [b 31]
+                               e   = T.pack [b i | i <- [30, 29 .. 23]]
+                               m   = T.pack [b i | i <- [22, 21 ..  0]]
+                           in "(fp #b" <> s <> " #b" <> e <> " #b" <> m <> ")"
+   where as s = "(_ " <> s <> " 8 24)"
+
+-- | A version of show for doubles that generates correct SMTLib literals using the rounding mode
+showSMTDouble :: Double -> Text
+showSMTDouble d
+   | isNaN d             = as "NaN"
+   | isInfinite d, d < 0 = as "-oo"
+   | isInfinite d        = as "+oo"
+   | isNegativeZero d    = as "-zero"
+   | d == 0              = as "+zero"
+   | True                = let w   = doubleToWord d
+                               b i = if w `testBit` i then '1' else '0'
+                               s   = T.pack [b 63]
+                               e   = T.pack [b i | i <- [62, 61 .. 52]]
+                               m   = T.pack [b i | i <- [51, 50 ..  0]]
+                           in "(fp #b" <> s <> " #b" <> e <> " #b" <> m <> ")"
+   where as s = "(_ " <> s <> " 11 53)"
+
+-- | Show an SBV rational as an SMTLib value. This is used for faithful rationals.
+showSMTRational :: Rational -> Text
+showSMTRational r = "(SBV.Rational " <> showNegativeNumber (numerator r) <> " " <> showNegativeNumber (denominator r) <> ")"
+
+-- | Convert a CV to an SMTLib2 compliant value
+cvToSMTLib :: CV -> Text
+cvToSMTLib x
+  | isBoolean       x, CInteger  w      <- cvVal x = if w == 0 then "false" else "true"
+  | isRoundingMode  x, CADT (s, [])     <- cvVal x = roundModeConvert s
+  | isReal          x, CAlgReal  r      <- cvVal x = T.pack (algRealToSMTLib2 r)
+  | isRational      x, CRational r      <- cvVal x = showSMTRational r
+  | isFloat         x, CFloat    f      <- cvVal x = showSMTFloat  f
+  | isDouble        x, CDouble   d      <- cvVal x = showSMTDouble d
+  | isFP            x, CFP       f      <- cvVal x = T.pack (fprToSMTLib2 f)
+  | not (isBounded x), CInteger  w      <- cvVal x = if w >= 0 then showText w else "(- " <> showText (abs w) <> ")"
+  | not (hasSign x)  , CInteger  w      <- cvVal x = smtLibHex (intSizeOf x) w
+  -- signed numbers (with 2's complement representation) is problematic
+  -- since there's no way to put a bvneg over a positive number to get minBound..
+  -- Hence, we punt and use binary notation in that particular case
+  | hasSign x        , CInteger  w      <- cvVal x = if w == negate (2 ^ intSizeOf x)
+                                                     then mkMinBound (intSizeOf x)
+                                                     else negIf (w < 0) $ smtLibHex (intSizeOf x) (abs w)
+  | isChar x         , CChar c          <- cvVal x = "(_ char " <> smtLibHex 8 (fromIntegral (ord c)) <> ")"
+  | isString x       , CString s        <- cvVal x = "\"" <> T.pack (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
+
+  -- Arrays become sequence of stores
+  | isArray x        , CArray ac       <- cvVal x  = smtLibArray (kindOf x) ac
+
+  -- ADTs
+  | isADT x          , CADT c          <- cvVal x = smtLibADT (cvKind x) c
+
+  | True = error $ "SBV.cvtCV: Impossible happened: Kind/Value disagreement on: " ++ show (kindOf x, x)
+  where roundModeConvert s = fromMaybe (T.pack s) (listToMaybe [smtRoundingMode m | m <- [minBound .. maxBound] :: [RoundingMode], show m == s])
+        -- Carefully code hex numbers, SMTLib is picky about lengths of hex constants. For the time
+        -- being, SBV only supports sizes that are multiples of 4, but the below code is more robust
+        -- in case of future extensions to support arbitrary sizes.
+        smtLibHex :: Int -> Integer -> Text
+        smtLibHex 1  v = "#b" <> showText v
+        smtLibHex sz v
+          | sz `mod` 4 == 0 = "#x" <> T.pack (pad (sz `div` 4) (showHex v ""))
+          | True            = "#b" <> T.pack (pad sz (showBin v ""))
+           where showBin = showIntAtBase 2 intToDigit
+        negIf :: Bool -> Text -> Text
+        negIf True  a = "(bvneg " <> a <> ")"
+        negIf False a = a
+
+        smtLibSeq :: Kind -> [CVal] -> Text
+        smtLibSeq k          [] = "(as seq.empty " <> smtType k <> ")"
+        smtLibSeq (KList ek) xs = let mkSeq  [e]   = e
+                                      mkSeq  es    = "(seq.++ " <> T.unwords es <> ")"
+                                      mkUnit inner = "(seq.unit " <> inner <> ")"
+                                  in mkSeq (mkUnit . cvToSMTLib . CV ek <$> xs)
+        smtLibSeq k _ = error $ "SBV.cvToSMTLib: Impossible case (smtLibSeq), received kind: " ++ show k
+
+        smtLibSet :: Kind -> RCSet CVal -> Text
+        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 (CV ke e) <> " " <> how <> ")"
+
+        smtLibTup :: Kind -> [CVal] -> Text
+        smtLibTup (KTuple []) _  = "mkSBVTuple0"
+        smtLibTup (KTuple ks) xs = "(mkSBVTuple" <> showText (length ks) <> " " <> T.unwords (zipWith (\ek e -> cvToSMTLib (CV ek e)) ks xs) <> ")"
+        smtLibTup k           _  = error $ "SBV.cvToSMTLib: Impossible case (smtLibTup), received kind: " ++ show k
+
+        -- Remember that in an ArrayModel we keep a history; i.e., the earlier elements are written later. So, we reverse the assocs
+        smtLibArray :: Kind -> ArrayModel CVal CVal -> Text
+        smtLibArray k@(KArray k1 k2) (ArrayModel assocs def) = mkStoreChain k k1 k2 (reverse assocs) def
+        smtLibArray k              _                         = error $ "SBV.cvToSMTLib: Impossible case (smtLibArray), received non-matching kind: " ++ show k
+
+        mkStoreChain k k1 k2 writes def = walk writes base
+          where base = "((as const " <> smtType k <> ") " <> cvToSMTLib (CV k2 def) <> ")"
+
+                walk []                  sofar = sofar
+                walk ((key, val) : rest) sofar = walk rest (store key val sofar)
+
+                store key val sofar = "(store " <> sofar <> " " <> cvToSMTLib (CV k1 key) <> " " <> cvToSMTLib (CV k2 val) <> ")"
+
+        -- 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)
+        mkMinBound :: Int -> Text
+        mkMinBound i = "#b1" <> T.replicate (i-1) "0"
+
+        -- ADTs
+        smtLibADT :: Kind -> (String,  [(Kind, CVal)]) -> Text
+        smtLibADT knd (c, [])  = ascribe c knd
+        smtLibADT knd (c, kvs) = "(" <> ascribe c knd <> " " <> T.unwords (map (\(k, v) -> cvToSMTLib (CV  k v)) kvs) <> ")"
+        ascribe nm k = "(as " <> T.pack nm <> " " <> smtType k <> ")"
+
+-- | Show a float as a binary
+showBFloat :: (Show a, RealFloat a) => a -> ShowS
+showBFloat = showFloatAtBase 2
+
+-- | Like Haskell's showHFloat, but uses arbitrary base instead.
+-- Note that the exponent is always written in decimal. Let the exponent value be d:
+--    If base=10, then we use @e@ to denote the exponent; meaning 10^d
+--    If base is a power of 2, then we use @p@ to denote the exponent; meaning 2^d
+--    Otherwise, we use @ to denote the exponent, and it means base^d
+showFloatAtBase :: (Show a, RealFloat a) => Int -> a -> ShowS
+showFloatAtBase base input
+  | base < 2 = error $ "showFloatAtBase: Received invalid base (must be >= 2): " ++ show base
+  | True     = showString $ fmt input
+  where fmt x
+         | isNaN x                   = "NaN"
+         | isInfinite x              = (if x < 0 then "-" else "") ++ "Infinity"
+         | x < 0 || isNegativeZero x = '-' : cvt (-x)
+         | True                      = cvt x
+
+        basePow2 = base .&. (base-1) == 0
+        lg2Base  = countTrailingZeros base  -- only used when basePow2 is true
+
+        prefix = case base of
+                   2  -> "0b"
+                   8  -> "0o"
+                   10 -> ""
+                   16 -> "0x"
+                   x  -> "0<" ++ show x ++ ">"
+
+        powChar
+          | base == 10 = 'e'
+          | basePow2   = 'p'
+          | True       = '@'
+
+        -- why r-1? Because we're shifting the fraction by 1 digit; does reducing the exponent by 1
+        f2d x = case floatToDigits (fromIntegral base) x of
+                  ([],   e) -> (0, [], e - 1)
+                  (d:ds, e) -> (d, ds, e - 1)
+
+        cvt x
+         | x == 0 = prefix ++ '0' : powChar : "+0"
+         | True   = prefix ++ toDigit d ++ frac ds ++ pow
+         where (d, ds, e)  = f2d x
+               pow
+                | base == 10 = powChar : shSigned e
+                | basePow2   = powChar : shSigned (e * lg2Base)
+                | True       = powChar : shSigned e
+
+               shSigned v
+                | v < 0      =       show v
+                | True       = '+' : show v
+
+        -- Given digits, show them except if they're all 0 then drop
+        frac digits
+         | all (== 0) digits = ""
+         | True              = "." ++ concatMap toDigit digits
+
+        toDigit v | v <= 15 = [intToDigit v]
+                  | v <  36 = [chr (ord 'a' + v - 10)]
+                  | True    = '<' : show v ++ ">"
+
+-- | When we show a negative number in SMTLib, we must properly parenthesize.
+showNegativeNumber :: (Show a, Num a, Ord a) => a -> Text
+showNegativeNumber i
+  | i < 0 = "(- " <> showText (-i) <> ")"
+  | True  = showText i
diff --git a/Data/SBV/Utils/SExpr.hs b/Data/SBV/Utils/SExpr.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Utils/SExpr.hs
@@ -0,0 +1,700 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Utils.SExpr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Parsing of S-expressions (mainly used for parsing SMT-Lib get-value output)
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE BangPatterns #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Data.SBV.Utils.SExpr ( SExpr(..), parenDeficit, parseSExpr
+                            , parseSExprFunction, makeHaskellFunction
+                            , unQuote, simplifyECon
+                            , nameSupply
+                            ) where
+
+import Data.Bits   (setBit, testBit)
+import Data.Char   (isDigit, ord, isSpace)
+import Data.Either (partitionEithers)
+import Data.List   (isPrefixOf, nubBy, intercalate)
+import Data.Maybe  (fromMaybe, listToMaybe)
+import Data.Word   (Word32, Word64)
+
+import Control.Monad (foldM)
+
+import Numeric    (readInt, readSigned, readDec, readHex, fromRat)
+
+import Data.SBV.Core.AlgReals
+import Data.SBV.Core.SizedFloats
+import Data.SBV.Core.Data (nan, infinity, RoundingMode(..))
+
+import Data.SBV.Utils.Lib (unBar, unQuote, nameSupply)
+
+import Data.SBV.Utils.Numeric (fpIsEqualObjectH, wordToFloat, wordToDouble)
+
+-- | ADT S-Expression format, suitable for representing get-model output of SMT-Lib
+data SExpr = ECon           String
+           | ENum           (Integer, Maybe Int, Bool)  -- Second argument is how wide the field was in bits, if known. Useful in FP parsing.
+                                                        -- Third argument is true, if this was a boolean constant
+           | EReal          AlgReal
+           | EFloat         Float
+           | EFloatingPoint FP
+           | EDouble        Double
+           | EApp           [SExpr]
+           deriving Show
+
+-- | Extremely simple minded tokenizer, good for our use model.
+tokenize :: String -> [String]
+tokenize inp = go inp []
+ where go "" sofar = reverse sofar
+
+       go (c:cs) sofar
+          | isSpace c = go (dropWhile isSpace cs) sofar
+
+       go ('(':cs) sofar = go cs ("(" : sofar)
+       go (')':cs) sofar = go cs (")" : sofar)
+
+       go (':':':':cs) sofar = go cs ("::" : sofar)
+
+       go (':':cs) sofar = case break (`elem` stopper) cs of
+                            (pre, rest) -> go rest ((':':pre) : sofar)
+
+       go ('|':r) sofar = let wrap s = '|' : s ++ "|"
+                          in case span (/= '|') r of
+                               (pre, '|':rest) -> go rest (wrap pre : sofar)
+                               (pre, rest)     -> go rest (wrap pre : sofar)
+
+       go (';':r) sofar = go (drop 1 (dropWhile (/= '\n') r)) sofar
+
+       go ('"':r) sofar = go rest (finalStr : sofar)
+           where grabString []             acc = (reverse acc, [])         -- Strictly speaking, this is the unterminated string case; but let's ignore
+                 grabString ('"' :'"':cs)  acc = grabString cs ('"' :acc)
+                 grabString ('"':cs)       acc = (reverse acc, cs)
+                 grabString (c:cs)         acc = grabString cs (c:acc)
+
+                 (str, rest) = grabString r []
+                 finalStr    = '"' : str ++ "\""
+
+       go cs sofar = case span (`notElem` stopper) cs of
+                       (pre, post) -> go post (pre : sofar)
+
+       -- characters that can stop the current token
+       -- it is *crucial* that this list contains every character
+       -- we can match in one of the previous cases!
+       stopper = " \t\n():|\";"
+
+-- | The balance of parens in this string. If 0, this means it's a legit line!
+parenDeficit :: String -> Int
+parenDeficit = go 0 . tokenize
+  where go :: Int -> [String] -> Int
+        go !balance []           = balance
+        go !balance ("(" : rest) = go (balance+1) rest
+        go !balance (")" : rest) = go (balance-1) rest
+        go !balance (_   : rest) = go balance     rest
+
+-- | Parse a string into an SExpr, potentially failing with an error message
+parseSExpr :: String -> Either String SExpr
+parseSExpr inp = do (sexp, extras) <- parse inpToks
+                    if null extras
+                       then case sexp of
+                              EApp [ECon "error", ECon er] -> Left $ "Solver returned an error: " ++ er
+                              _                            -> pure sexp
+
+                       else die "Extra tokens after valid input"
+  where inpToks = tokenize inp
+
+        die w = Left $  "SBV.Provers.SExpr: Failed to parse S-Expr: " ++ w
+                     ++ "\n*** Input : <" ++ inp ++ ">"
+
+        parse []         = die "ran out of tokens"
+        parse ("(":toks) = do (f, r) <- parseApp toks []
+                              f' <- cvt (EApp f)
+                              pure (f', r)
+        parse (")":_)    = die "extra tokens after close paren"
+        parse [tok]      = do t <- pTok tok
+                              pure (t, [])
+        parse _          = die "ill-formed s-expr"
+
+        parseApp []         _     = die "failed to grab s-expr application"
+        parseApp (")":toks) sofar = pure (reverse sofar, toks)
+        parseApp ("(":toks) sofar = do (f, r) <- parse ("(":toks)
+                                       parseApp r (f : sofar)
+        parseApp (tok:toks) sofar = do t <- pTok tok
+                                       parseApp toks (t : sofar)
+
+        pTok "false" = pure $ ENum (0, Nothing, True)
+        pTok "true"  = pure $ ENum (1, Nothing, True)
+
+        pTok ('0':'b':r)                                 = mkNum (Just (length r))     $ readInt 2 (`elem` "01") (\c -> ord c - ord '0') r
+        pTok ('b':'v':r) | not (null r) && all isDigit r = mkNum Nothing               $ readDec (takeWhile (/= '[') r)
+        pTok ('#':'b':r)                                 = mkNum (Just (length r))     $ readInt 2 (`elem` "01") (\c -> ord c - ord '0') r
+        pTok ('#':'x':r)                                 = mkNum (Just (4 * length r)) $ readHex r
+
+        pTok n | possiblyNum n = if all intChar n then mkNum Nothing $ readSigned readDec n else getReal n
+        pTok n                 = pure $ ECon (constantMap n)
+
+        -- crude, but effective!
+        possiblyNum s = case s of
+                          ""        -> False
+                          ('-':c:_) -> isDigit c
+                          (c:_)     -> isDigit c
+
+        intChar c = c == '-' || isDigit c
+
+        mkNum l [(n, "")] = pure $ ENum (n, l, False)
+        mkNum _ _         = die "cannot read number"
+
+        getReal n = pure $ EReal $ mkPolyReal (Left (exact, n'))
+          where exact = not ("?" `isPrefixOf` reverse n)
+                n' | exact = n
+                   | True  = init n
+
+        fst3 (a, _, _) = a
+        snd3 (_, b, _) = b
+        thd3 (_, _, c) = c
+
+        -- simplify numbers and root-obj values
+        cvt (EApp [ECon "to_int",  EReal a])                       = pure $ EReal a   -- ignore the "casting"
+        cvt (EApp [ECon "to_real", EReal a])                       = pure $ EReal a   -- ignore the "casting"
+        cvt (EApp [ECon "/", EReal a, EReal b])                    = pure $ EReal (a / b)
+        cvt (EApp [ECon "/", EReal a, ENum  b])                    = pure $ EReal (a                    / fromInteger (fst3 b))
+        cvt (EApp [ECon "/", ENum  a, EReal b])                    = pure $ EReal (fromInteger (fst3 a) /             b      )
+        cvt (EApp [ECon "/", ENum  a, ENum  b])                    = pure $ EReal (fromInteger (fst3 a) / fromInteger (fst3 b))
+        cvt (EApp [ECon "-", EReal a])                             = pure $ EReal (-a)
+        cvt (EApp [ECon "-", ENum a])                              = pure $ ENum  (-(fst3 a), snd3 a, thd3 a)
+
+        -- bit-vector value as CVC4 prints: (_ bv0 16) for instance
+        cvt (EApp [ECon "_", ENum a, ENum _b])                     = pure $ ENum a
+        cvt (EApp [ECon "root-obj", EApp (ECon "+":trms), ENum k]) = do ts <- mapM getCoeff trms
+                                                                        pure $ EReal $ mkPolyReal (Right (fst3 k, ts))
+        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum (11, _, _), ENum (53, _, _)]]) = getDouble n
+        cvt (EApp [ECon "as", n, EApp [ECon "_", ECon "FloatingPoint", ENum ( 8, _, _), ENum (24, _, _)]]) = getFloat  n
+        cvt (EApp [ECon "as", n, ECon "Float64"])                                                          = getDouble n
+        cvt (EApp [ECon "as", n, ECon "Float32"])                                                          = getFloat  n
+
+        -- Deal with CVC4's approximate reals
+        cvt x@(EApp [ECon "witness", EApp [EApp [ECon v, ECon "Real"]]
+                                   , EApp [ECon "or", EApp [ECon "=", ECon v', val], _]]) | v == v'   = do
+                                                approx <- cvt val
+                                                case approx of
+                                                  ENum (s, _, _) -> pure $ EReal $ mkPolyReal (Left (False, show s))
+                                                  EReal aval     -> case aval of
+                                                                      AlgRational _ r -> pure $ EReal $ AlgRational False r
+                                                                      _               -> pure $ EReal aval
+                                                  _              -> die $ "Cannot parse a CVC4 approximate value from: " ++ show x
+
+        -- Deal with CVC5's algebraic reals. This is very crude!
+        cvt x@(EApp (ECon "_" : ECon "real_algebraic_number" : rest)) =
+            let isComma (ECon ",") = True
+                isComma _          = False
+
+                get (ENum    (n, _, _))            = pure $ fromIntegral n
+                get (EReal   (AlgRational True r)) = pure r
+                get (EFloat  f)                    = pure $ toRational f
+                get (EDouble d)                    = pure $ toRational d
+                get t                              = die $ "Cannot get a CVC5 real-algebraic bound from: " ++ show t
+
+            in case drop 1 (dropWhile (not . isComma) rest) of
+                [EApp [n1, n2], _] -> do low  <- get n1
+                                         high <- get n2
+                                         pure $ EReal $ AlgInterval (OpenPoint low) (OpenPoint high)
+                _                  -> die $ "Cannot parse a CVC5 real-algebraic number from: " ++ show x
+
+        -- NB. Note the lengths on the mantissa for the following two are 23/52; not 24/53!
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just  8, _), ENum (m, Just 23, _)]) = pure $ EFloat         $ getTripleFloat  s e m
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just 11, _), ENum (m, Just 52, _)]) = pure $ EDouble        $ getTripleDouble s e m
+        cvt (EApp [ECon "fp",    ENum (s, Just 1, _), ENum ( e, Just eb, _), ENum (m, Just sb, _)]) = pure $ EFloatingPoint $ fpFromRawRep (s == 1) (e, eb) (m, sb+1)
+
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum ( 8, _, _),       ENum (24, _, _)])         = pure $ EFloat           nan
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum (11, _, _),       ENum (53, _, _)])         = pure $ EDouble          nan
+        cvt (EApp [ECon "_",     ECon "NaN",       ENum (eb, _, _),       ENum (sb, _, _)])         = pure $ EFloatingPoint $ fpNaN (fromIntegral eb) (fromIntegral sb)
+
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum ( 8, _, _),       ENum (24, _, _)])         = pure $ EFloat           infinity
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum (11, _, _),       ENum (53, _, _)])         = pure $ EDouble          infinity
+        cvt (EApp [ECon "_",     ECon "+oo",       ENum (eb, _, _),       ENum (sb, _, _)])         = pure $ EFloatingPoint $ fpInf False (fromIntegral eb) (fromIntegral sb)
+
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum ( 8, _, _),       ENum (24, _, _)])         = pure $ EFloat         $ -infinity
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum (11, _, _),       ENum (53, _, _)])         = pure $ EDouble        $ -infinity
+        cvt (EApp [ECon "_",     ECon "-oo",       ENum (eb, _, _),       ENum (sb, _, _)])         = pure $ EFloatingPoint $ fpInf True (fromIntegral eb) (fromIntegral sb)
+
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum ( 8, _, _),       ENum (24, _, _)])         = pure $ EFloat  0
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum (11, _, _),       ENum (53, _, _)])         = pure $ EDouble 0
+        cvt (EApp [ECon "_",     ECon "+zero",     ENum (eb, _, _),       ENum (sb, _, _)])         = pure $ EFloatingPoint $ fpZero False (fromIntegral eb) (fromIntegral sb)
+
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum ( 8, _, _),       ENum (24, _, _)])         = pure $ EFloat         $ -0
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum (11, _, _),       ENum (53, _, _)])         = pure $ EDouble        $ -0
+        cvt (EApp [ECon "_",     ECon "-zero",     ENum (eb, _, _),       ENum (sb, _, _)])         = pure $ EFloatingPoint $ fpZero True (fromIntegral eb) (fromIntegral sb)
+
+        cvt x                                                                                       = pure x
+
+        getCoeff (EApp [ECon "*", ENum k, EApp [ECon "^", ECon "x", ENum p]]) = pure (fst3 k, fst3 p)  -- kx^p
+        getCoeff (EApp [ECon "*", ENum k,                 ECon "x"        ] ) = pure (fst3 k,      1)  -- kx
+        getCoeff (                        EApp [ECon "^", ECon "x", ENum p] ) = pure (     1, fst3 p)  --  x^p
+        getCoeff (                                        ECon "x"          ) = pure (     1,      1)  --  x
+        getCoeff (                ENum k                                    ) = pure (fst3 k,      0)  -- k
+        getCoeff x = die $ "Cannot parse a root-obj,\nProcessing term: " ++ show x
+        getDouble (ECon s)  = case (s, rdFP (dropWhile (== '+') s)) of
+                                ("plusInfinity",  _     ) -> pure $ EDouble infinity
+                                ("minusInfinity", _     ) -> pure $ EDouble (-infinity)
+                                ("oo",            _     ) -> pure $ EDouble infinity
+                                ("-oo",           _     ) -> pure $ EDouble (-infinity)
+                                ("zero",          _     ) -> pure $ EDouble 0
+                                ("-zero",         _     ) -> pure $ EDouble (-0)
+                                ("NaN",           _     ) -> pure $ EDouble nan
+                                (_,               Just v) -> pure $ EDouble v
+                                _               -> die $ "Cannot parse a double value from: " ++ s
+        getDouble (EApp [_, s, _, _]) = getDouble s
+        getDouble (EReal r) = pure $ EDouble $ fromRat $ toRational r
+        getDouble x         = die $ "Cannot parse a double value from: " ++ show x
+        getFloat (ECon s)   = case (s, rdFP (dropWhile (== '+') s)) of
+                                ("plusInfinity",  _     ) -> pure $ EFloat infinity
+                                ("minusInfinity", _     ) -> pure $ EFloat (-infinity)
+                                ("oo",            _     ) -> pure $ EFloat infinity
+                                ("-oo",           _     ) -> pure $ EFloat (-infinity)
+                                ("zero",          _     ) -> pure $ EFloat 0
+                                ("-zero",         _     ) -> pure $ EFloat (-0)
+                                ("NaN",           _     ) -> pure $ EFloat nan
+                                (_,               Just v) -> pure $ EFloat v
+                                _               -> die $ "Cannot parse a float value from: " ++ s
+        getFloat (EReal r)  = pure $ EFloat $ fromRat $ toRational r
+        getFloat (EApp [_, s, _, _]) = getFloat s
+        getFloat x          = die $ "Cannot parse a float value from: " ++ show x
+
+-- | Parses the Z3 floating point formatted numbers like so: 1.321p5/1.2123e9 etc.
+rdFP :: (Read a, RealFloat a) => String -> Maybe a
+rdFP s = case break (`elem` "pe") s of
+           (m, 'p':e) -> rd m >>= \m' -> rd e >>= \e' -> pure $ m' * ( 2 ** e')
+           (m, 'e':e) -> rd m >>= \m' -> rd e >>= \e' -> pure $ m' * (10 ** e')
+           (m, "")    -> rd m
+           _          -> Nothing
+ where rd v = case reads v of
+                [(n, "")] -> Just n
+                _         -> Nothing
+
+-- | Convert an (s, e, m) triple to a float value
+getTripleFloat :: Integer -> Integer -> Integer -> Float
+getTripleFloat s e m = wordToFloat w32
+  where sign      = [s == 1]
+        expt      = [e `testBit` i | i <- [ 7,  6 .. 0]]
+        mantissa  = [m `testBit` i | i <- [22, 21 .. 0]]
+        positions = [i | (i, b) <- zip [31, 30 .. 0] (sign ++ expt ++ mantissa), b]
+        w32       = foldr (flip setBit) (0::Word32) positions
+
+-- | Convert an (s, e, m) triple to a float value
+getTripleDouble :: Integer -> Integer -> Integer -> Double
+getTripleDouble s e m = wordToDouble w64
+  where sign      = [s == 1]
+        expt      = [e `testBit` i | i <- [10,  9 .. 0]]
+        mantissa  = [m `testBit` i | i <- [51, 50 .. 0]]
+        positions = [i | (i, b) <- zip [63, 62 .. 0] (sign ++ expt ++ mantissa), b]
+        w64       = foldr (flip setBit) (0::Word64) positions
+
+-- | Special constants of SMTLib2 and their internal translation. Mainly
+-- rounding modes for now.
+constantMap :: String -> String
+constantMap n = fromMaybe n (listToMaybe [to | (from, to) <- special, n `elem` from])
+ where special = [ (["RNE", "roundNearestTiesToEven"], show RoundNearestTiesToEven)
+                 , (["RNA", "roundNearestTiesToAway"], show RoundNearestTiesToAway)
+                 , (["RTP", "roundTowardPositive"],    show RoundTowardPositive)
+                 , (["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 <- parseSetLambda         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 set-lambda expression, which is literally a lambda function, that might look like this:
+--        (lambda ((x!1 String))
+--          (or (not (or (= x!1 "o") (= x!1 "l") (= x!1 "e") (= x!1 "h")))
+--              (= x!1 "o")
+--              (= x!1 "l")
+--              (= x!1 "e")
+--              (= x!1 "h")))
+--   For this, we do a little bit of an interpretative dance to see if we can "construct" the necessary expression.
+--
+--   In parsed form:
+--      EApp [ECon "lambda",EApp [EApp [ECon "x!1",ECon "String"]],EApp [ECon "not",EApp [ECon "or",EApp [ECon "=",ECon "x!1",ECon "\"e\""],EApp [ECon "=",ECon "x!1",ECon "\"l\""]]]]
+--
+--   This is by no means comprehensive, and is quite crude, but hopefully covers the cases we see in practice.
+parseSetLambda :: SExpr -> Maybe ([([SExpr], SExpr)], SExpr)
+parseSetLambda funExpr = case funExpr of
+                               EApp [l@(ECon "lambda"), bv@(EApp [EApp [ECon _, _]]), body] -> go (\bd -> EApp [l, bv, bd]) body
+                               _                                                            -> Nothing
+  where go mkLambda = build
+         where build (EApp [ECon "not",  rest      ]) =         neg =<<      build rest
+               build (EApp (ECon "or"  : rest@(_:_))) = foldM1 disj =<< mapM build rest
+               build (EApp (ECon "and" : rest@(_:_))) = foldM1 conj =<< mapM build rest
+               build other                            = parseLambdaExpression (mkLambda other)
+
+        -- We're guaranteed by above construction that foldM1 will never take an empty list (due to rest@(_:_) pattern match.)
+        foldM1 _ []     = error "Data.SBV.parseSetLambda: Impossible happened; empty arg to foldM1"
+        foldM1 f (x:xs) = foldM f x xs
+
+        checkBool (ENum (1, Nothing, True)) = True
+        checkBool (ENum (0, Nothing, True)) = True
+        checkBool _                         = False
+
+        negBool (ENum (1, Nothing, _)) = ENum (0, Nothing, True)
+        negBool _                      = ENum (1, Nothing, True)
+
+        orBool t@(ENum (1, Nothing, _)) _                        = t
+        orBool _                        t@(ENum (1, Nothing, _)) = t
+        orBool _ _                                               = ENum (0, Nothing, True)
+
+        andBool f@(ENum (0, Nothing, _)) _                        = f
+        andBool _                        f@(ENum (0, Nothing, _)) = f
+        andBool _ _                                               = ENum (1, Nothing, True)
+
+        neg :: ([([SExpr], SExpr)], SExpr) -> Maybe ([([SExpr], SExpr)], SExpr)
+        neg (rows, dflt)
+         | all checkBool (dflt : map snd rows) = Just ([(e, negBool r) | (e, r) <- rows], negBool dflt)
+         | True                                = Nothing
+
+        disj, conj :: ([([SExpr], SExpr)], SExpr) -> ([([SExpr], SExpr)], SExpr) -> Maybe ([([SExpr], SExpr)], SExpr)
+        disj = bin orBool
+        conj = bin andBool
+
+        bin f rd1@(rows1, dflt1) rd2@(rows2, dflt2)
+          | all checkBool (dflt1 : dflt2 : map snd rows1 ++ map snd rows2) = Just (combine f rd1 rd2)
+          | True                                                           = Nothing
+
+        -- Since we don't have equality over SExprs (can of worms!), we use "show" equality here. The ice is thin, but it works!
+        combine f (rows1, dflt1) (rows2, dflt2) = (rows, f dflt1 dflt2)
+          where rows = map calc $ nubBy (\x y -> show x == show y) (map fst rows1 ++ map fst rows2)
+
+                calc :: [SExpr] -> ([SExpr], SExpr)
+                calc args = (args, f (find rows1 dflt1 args) (find rows2 dflt2 args))
+
+                find rs d a = case [r | (v, r) <- rs, show v == show a] of
+                               []  -> d
+                               [x] -> x
+                               x   -> error $ unlines [ "Data.SBV.parseSetLambda: Impossible happened while combining rows."
+                                                      , "   First row  :"   ++ show rows1
+                                                      , "   First dflt :"  ++ show dflt1
+                                                      , "   Second row :"  ++ show rows2
+                                                      , "   Second dflt:" ++ show dflt2
+                                                      , "   Looking for: " ++ show a
+                                                      , "Multiple matches found: " ++ show x
+                                                      ]
+
+-- | 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 squashLambdas funExpr of
+                                  EApp [ECon "lambda", EApp params, body] -> mapM getParam params >>= flip lambda body >>= chainAssigns
+                                  _                                       -> Nothing
+  where -- convert (lambda p1 (lambda p2 body)) to (lambda (p1 ++ p2) body)
+        squashLambdas (EApp  [ECon "lambda", EApp p1
+                                           , EApp [ECon "lambda", EApp p2, body]])
+                            = squashLambdas $ EApp [ECon "lambda", EApp (p1 ++ p2), body]
+        squashLambdas other = other
+
+        getParam (EApp [ECon v, ECon ty]) = Just (v, ty == "Bool")
+        getParam (EApp [ECon v, _      ]) = Just (v, False)
+        getParam _                        = Nothing
+
+        lambda :: [(String, Bool)]  -- Bool is True if this is a boolean variable. Otherwise we don't keep track of the type
+               -> SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
+        lambda params body = reverse <$> go [] body
+          where true  = ENum (1, Nothing, True)
+                false = ENum (0, Nothing, True)
+
+                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
+
+                -- Catch cases like: x = a)
+                go sofar inner@(EApp [ECon "=", _, _])
+                  = go sofar (EApp [ECon "ite", inner, true, false])
+
+                -- Catch cases like: not x
+                go sofar (EApp [ECon "not", inner])
+                  = go sofar (EApp [ECon "ite", inner, false, true])
+
+                -- Catch (or x y z..)
+                go sofar (EApp (ECon "or" : elts))
+                  = let xform []     = false
+                        xform [x]    = x
+                        xform (x:xs) = EApp [ECon "ite", x, true, xform xs]
+                    in go sofar $ xform elts
+
+                -- Catch (and x y z..)
+                go sofar (EApp (ECon "and" : elts))
+                  = let xform []     = true
+                        xform [x]    = x
+                        xform (x:xs) = EApp [ECon "ite", x, xform xs, false]
+                    in go sofar $ xform elts
+
+                -- 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 enough.
+                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) paramNames
+                   | True                    = Nothing
+                  where paramNames = map fst params
+
+                        -- 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` paramNames = 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)                     = case v `lookup` params of
+                                                               Just True -> Just (v, true)  -- boolean identity, require it to be true
+                                                               _         -> Nothing
+
+                        -- 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]) = pure [Right defVal]
+          vals (EApp [EApp [ECon "as", ECon "const", EApp (ECon "Array" : _)], defVal]) = pure [Right defVal]
+          vals (EApp (ECon "store" : prev : argsVal)) | length argsVal >= 2             = do rest <- vals prev
+                                                                                             pure $ Left (init argsVal, last argsVal) : rest
+          vals _                                                                        = Nothing
+
+-- | Turn a sequence of left-right chain assignments (condition + free) into a single chain
+-- NB. We make sure the results here are unique, i.e., there's only one assignment to each unique entry
+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.
+        -- NB. I'm not sure if solvers actually would return duplicate assignments, but just being safe here. (i.e.,
+        -- this duplication may actually never happen in practice.)
+        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
+                     (EFloatingPoint a1, EFloatingPoint a2) -> fpIsEqualObjectH a1 a2
+                     (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 EFloatingPoint{} = 4
+        eRank EDouble{}        = 5
+        eRank EApp{}           = 6
+
+-- Turn
+--  "((F (lambda ((x!1 Int)) (+ 3 (* 2 x!1)))))"
+---  into
+--  "F x = 3 + 2 * x"
+-- if we can. We try but don't push too hard! This is only used for display purposes.
+--
+-- This isn't very fool-proof; can be confused if there are binding constructs etc.
+-- Also, the generated text isn't necessarily fully Haskell acceptable.
+-- But it seems to do an OK job for most common use cases.
+makeHaskellFunction :: String -> String -> Bool -> Maybe [String] -> Maybe String
+makeHaskellFunction resp nm isCurried mbArgs
+   = case parseSExpr resp of
+       Right (EApp [EApp [ECon o, e]]) | o == nm -> do (args, bd) <- lambda e
+                                                       let params | isCurried = unwords args
+                                                                  | True      = '(' : intercalate ", " args ++ ")"
+                                                       pure $ unBar nm ++ " " ++ params ++ " = " ++ bd
+       _                                         -> Nothing
+
+  where -- infinite supply of names; starting with the ones we're given
+        preSupply = fromMaybe [] mbArgs
+
+        lambda :: SExpr -> Maybe ([String], String)
+        lambda (EApp [ECon "lambda", EApp args, bd]) = do as <- mapM getArg args
+                                                          let env = zip as (nameSupply preSupply)
+                                                          pure (map snd env, hprint env bd)
+        lambda _                                     = Nothing
+
+        getArg (EApp [ECon argName, _]) = Just argName
+        getArg _                        = Nothing
+
+-- | z3 prints uninterpreted values like this: T!val!4 or T_val_4. Turn that into T_4
+simplifyECon :: String -> String
+simplifyECon "" = ""
+simplifyECon ('!':'v':'a':'l':'!':rest) = '_' : simplifyECon rest
+simplifyECon ('_':'v':'a':'l':'_':rest) = '_' : simplifyECon rest
+simplifyECon (c:cs) = c : simplifyECon cs
+
+-- Print as a Haskell expression, with minimal parens.
+-- This isn't fool-proof; but it does an OK job
+hprint :: [(String, String)] -> SExpr -> String
+hprint env = go (0 :: Int)
+  where go p e = case e of
+                   ECon n | Just a <- n `lookup` env -> a
+                          | True                     -> simplifyECon n
+                   ENum (1, _, True) -> "True"
+                   ENum (0, _, True) -> "False"
+                   ENum (i, _, _)    -> cnst i
+                   EReal  a          -> cnst a
+                   EFloat f          -> cnst f
+                   EFloatingPoint f  -> cnst f
+                   EDouble f         -> cnst f
+
+                   -- Handle lets
+                   EApp [ECon "let", EApp binders, rhs] ->
+                       let getBind (EApp [ECon nm, def]) = simplifyECon nm ++ " = " ++  go 0 def
+                           getBind bnd                   = go 0 bnd
+
+                           binds = '{' : intercalate "; " (map getBind binders) ++ "}"
+                       in parenIf (p >= 1) $ "let " ++ binds ++ " in " ++ go 0 rhs
+
+                   -- few simps
+                   EApp [ECon "not", EApp [ECon ">=", a, b]] -> go p $ EApp [ECon "<",  a, b]
+                   EApp [ECon "not", EApp [ECon "<=", a, b]] -> go p $ EApp [ECon ">",  a, b]
+                   EApp [ECon "not", EApp [ECon "<",  a, b]] -> go p $ EApp [ECon ">=", a, b]
+                   EApp [ECon "not", EApp [ECon ">",  a, b]] -> go p $ EApp [ECon "<=", a, b]
+
+                   -- Handle x + -y that z3 is fond of producing
+                   EApp [ECon a, x, EApp [ECon m, ENum (-1, _, _), y]] | isPlus a && isTimes m -> go p $ EApp [ECon "-", x, y]
+
+                   -- Handle x + -NUM that z3 is also fond of producing
+                   EApp [ECon a, x, ENum (i, mw, bool)] | isPlus a && i < 0 -> go p $ EApp [ECon "-", x, ENum (-i, mw, bool)]
+
+                   -- Handle -1 * x
+                   EApp [ECon o, ENum (-1, _, _), b] | isTimes o -> parenIf (p >= 8) (neg (go 8 b))
+
+                   -- Move additive constants to the right, multiplicative constants to the left
+                   EApp [ECon o, x, y] | isPlus  o && isConst x && not (isConst y) -> go p $ EApp [ECon o, y, x]
+                   EApp [ECon o, x, y] | isTimes o && isConst y && not (isConst x) -> go p $ EApp [ECon o, y, x]
+
+                   -- Simp arithmetic
+                   EApp (ECon o : xs) | isPlus  o -> recurse 6 (Just "+")  xs
+                   EApp (ECon o : xs) | isMinus o -> recurse 6 (Just "-")  xs
+                   EApp (ECon o : xs) | isTimes o -> recurse 7 (Just "*")  xs
+                   EApp (ECon o : xs) | isDiv   o -> recurse 7 (Just "/")  xs
+
+                   -- Booleans
+                   EApp (ECon o : xs) | isLT    o -> recurse 4 (Just "<")  xs
+                   EApp (ECon o : xs) | isLTE   o -> recurse 4 (Just "<=") xs
+                   EApp (ECon o : xs) | isGT    o -> recurse 4 (Just ">")  xs
+                   EApp (ECon o : xs) | isGTE   o -> recurse 4 (Just ">=") xs
+                   EApp (ECon o : xs) | isAND   o -> recurse 3 (Just "&&") xs
+                   EApp (ECon o : xs) | isOR    o -> recurse 2 (Just "||") xs
+                   EApp (ECon o : xs) | isEQ    o -> recurse 4 (Just "==") xs
+
+                   -- Otherwise, just do prefix
+                   EApp xs                        -> recurse 9 Nothing xs
+
+           where recurse p' (Just op) xs = parenIf (p >= p') $ intercalate (' ' : op ++ " ") (map (parenNeg . go p') xs)
+                 recurse p' Nothing   xs = parenIf (p >= p') $ unwords                       (map (parenNeg . go p') xs)
+
+        isConst ECon          {} = False
+        isConst ENum          {} = True
+        isConst EReal         {} = True
+        isConst EFloat        {} = True
+        isConst EFloatingPoint{} = True
+        isConst EDouble       {} = True
+        isConst EApp          {} = False
+
+        parenNeg x@('-':_) = paren x
+        parenNeg x         = x
+
+        neg ('-':x) = x
+        neg x       = '-' : parenIf (any isSpace x) x
+
+        cnst x = case show x of
+                  sx@('-' : _) -> paren sx
+                  sx           -> sx
+
+        paren r@('(':_) = r
+        paren r         = '(' : r ++ ")"
+
+        parenIf False r = r
+        parenIf True  r = paren r
+
+        isPlus  = (`elem` ["+",  "bvadd"])
+        isTimes = (`elem` ["*",  "bvmul"])
+        isMinus = (`elem` ["-",  "bvsub"])
+        isDiv   = (`elem` ["/",  "bvdiv"])
+        isLT    = (`elem` ["<",  "bvult", "bvslt", "fp.lt" ])
+        isLTE   = (`elem` ["<=", "bvule", "bvsle", "fp.leq"])
+        isGT    = (`elem` [">",  "bvugt", "bvsgt", "fp.gt" ])
+        isGTE   = (`elem` [">=", "bvuge", "bvsge", "fp.gte"])
+        isEQ    = (`elem` ["=",  "fp.eq"])
+        isAND   = (== "and")
+        isOR    = (== "or")
+
+{- HLint ignore chainAssigns "Redundant if" -}
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,77 +1,94 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Data.SBV.Utils.TDiff
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Data.SBV.Utils.TDiff
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Runs an IO computation printing the time it took to run it
 -----------------------------------------------------------------------------
 
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Data.SBV.Utils.TDiff
-  ( timeIf
-  , Timing(..)
-  , TimedStep(..)
-  , TimingInfo
+  ( Timing(..)
+  , timeIf
+  , timeIfRNF
   , showTDiff
+  , getTimeStampIf
+  , getElapsedTime
   )
   where
 
-import Control.DeepSeq (rnf, NFData(..))
-import System.Time     (TimeDiff(..), normalizeTimeDiff, diffClockTimes, getClockTime)
-import Numeric         (showFFloat)
+import Data.Time (getCurrentTime, diffUTCTime, NominalDiffTime, UTCTime)
+import Data.IORef (IORef)
 
-import           Data.Map (Map)
-import qualified Data.Map as Map
-import           Data.IORef(IORef, modifyIORef')
+import Data.List (intercalate)
 
+import Data.Ratio
+import GHC.Real   (Ratio((:%)))
+
+import Numeric (showFFloat)
+
+import Control.Monad.Trans (liftIO, MonadIO)
+import Control.DeepSeq (NFData(rnf))
+
+
 -- | Specify how to save timing information, if at all.
-data Timing     = NoTiming | PrintTiming | SaveTiming (IORef TimingInfo)
+data Timing = NoTiming | PrintTiming | SaveTiming (IORef NominalDiffTime)
 
--- | Specify what is being timed.
-data TimedStep  = ProblemConstruction | Translation | WorkByProver String
-                  deriving (Eq, Ord, Show)
+-- | Show 'NominalDiffTime' in human readable form. 'NominalDiffTime' is
+-- essentially picoseconds (10^-12 seconds). We show it so that
+-- it's represented at the day:hour:minute:second.XXX granularity.
+showTDiff :: NominalDiffTime -> String
+showTDiff diff
+   | denom /= 1    -- Should never happen! But just in case.
+   = show diff
+   | True
+   = intercalate ":" fields
+   where total, denom :: Integer
+         total :% denom = (picoFactor % 1) * toRational diff
 
--- | A collection of timed stepd.
-type TimingInfo = Map TimedStep TimeDiff
+         -- there are 10^12 pico-seconds in a second
+         picoFactor :: Integer
+         picoFactor = (10 :: Integer) ^ (12 :: Integer)
 
--- | A more helpful show instance for steps
-timedStepLabel :: TimedStep -> String
-timedStepLabel lbl =
-  case lbl of
-    ProblemConstruction -> "problem construction"
-    Translation         -> "translation"
-    WorkByProver x      -> x
+         (s2p, m2s, h2m, d2h) = case drop 1 $ scanl (*) 1 [picoFactor, 60, 60, 24] of
+                                  (s2pv : m2sv : h2mv : d2hv : _) -> (s2pv, m2sv, h2mv, d2hv)
+                                  _                               -> (0, 0, 0, 0)  -- won't ever happen
 
--- | Show the time difference in a user-friendly format.
-showTDiff :: TimeDiff -> String
-showTDiff itd = et
-  where td = normalizeTimeDiff itd
-        vals = dropWhile (\(v, _) -> v == 0) (zip [tdYear td, tdMonth td, tdDay td, tdHour td, tdMin td] "YMDhm")
-        sec = ' ' : show (tdSec td) ++ dropWhile (/= '.') pico
-        pico = showFFloat (Just 3) (((10**(-12))::Double) * fromIntegral (tdPicosec td)) "s"
-        et = concatMap (\(v, c) -> ' ':show v ++ [c]) vals ++ sec
+         (days,    days')    = total    `divMod` d2h
+         (hours,   hours')   = days'    `divMod` h2m
+         (minutes, seconds') = hours'   `divMod` m2s
+         (seconds, picos)    = seconds' `divMod` s2p
+         secondsPicos        =  show seconds
+                             ++ dropWhile (/= '.') (showFFloat (Just 3) (fromIntegral picos * (10**(-12) :: Double)) "s")
 
--- | If selected, runs the computation @m@, and prints the time it took
--- to run it. The return type should be an instance of 'NFData' to ensure
--- the correct elapsed time is printed.
-timeIf :: NFData a => Timing -> TimedStep -> IO a -> IO a
-timeIf how what m =
-  case how of
-    NoTiming -> m
-    PrintTiming ->
-      do (elapsed,a) <- doTime m
-         putStrLn $ "** Elapsed " ++ timedStepLabel what ++ " time:" ++ showTDiff elapsed
-         return a
-    SaveTiming here ->
-      do (elapsed,a) <- doTime m
-         modifyIORef' here (Map.insert what elapsed)
-         return a
+         aboveSeconds = map (\(t, v) -> show v ++ [t]) $ dropWhile (\p -> snd p == 0) [('d', days), ('h', hours), ('m', minutes)]
+         fields       = aboveSeconds ++ [secondsPicos]
 
-doTime :: NFData a => IO a -> IO (TimeDiff,a)
-doTime m = do start <- getClockTime
-              r <- m
-              end <- rnf r `seq` getClockTime
-              let elapsed = diffClockTimes end start
-              elapsed `seq` return (elapsed, r)
+-- | Run an action and measure how long it took. We reduce the result to weak-head-normal-form,
+-- so beware of the cases if the result is lazily computed; in which case we'll stop soon as the
+-- result is in WHNF, and not necessarily fully calculated.
+timeIf :: MonadIO m => Bool -> m a -> m (Maybe NominalDiffTime, a)
+timeIf measureTime act = do mbStart <- getTimeStampIf measureTime
+                            r     <- act
+                            r `seq` do mbElapsed <- getElapsedTime mbStart
+                                       pure (mbElapsed, r)
+
+-- | Same as 'timeIf', except we fully evaluate the result, via its NFData instance.
+timeIfRNF :: (NFData a, MonadIO m) => Bool -> m a -> m (Maybe NominalDiffTime, a)
+timeIfRNF measureTime act = timeIf measureTime (act >>= \r -> rnf r `seq` pure r)
+
+-- | Get a time-stamp if we're asked to do so
+getTimeStampIf  :: MonadIO m => Bool -> m (Maybe UTCTime)
+getTimeStampIf measureTime
+  | not measureTime = pure Nothing
+  | True            = liftIO $ Just <$> getCurrentTime
+
+-- | Get elapsed time from the given beginning time, if any.
+getElapsedTime :: MonadIO m => Maybe UTCTime -> m (Maybe NominalDiffTime)
+getElapsedTime Nothing      = pure Nothing
+getElapsedTime (Just start) = liftIO $ do e <- getCurrentTime
+                                          pure $ Just (diffUTCTime e start)
diff --git a/Documentation/SBV/Examples/ADT/Expr.hs b/Documentation/SBV/Examples/ADT/Expr.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Expr.hs
@@ -0,0 +1,172 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Expr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A basic expression ADT example.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ADT.Expr where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import qualified Data.SBV.List as SL
+
+-- | A basic arithmetic expression type.
+data Expr = Val Integer
+          | Var String
+          | Add Expr Expr
+          | Mul Expr Expr
+          | Let String Expr Expr
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
+
+-- | Show instance for 'Expr'.
+instance Show Expr where
+  show (Val i)     = show i
+  show (Var a)     = a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Num instance, simplifies construction of values
+instance Num Expr where
+  fromInteger = Val
+  (+)         = Add
+  (*)         = Mul
+  abs         = error "Num Expr: undefined abs"
+  signum      = error "Num Expr: undefined signum"
+  negate      = error "Num Expr: undefined negate"
+
+-- | Num instance for the symbolic version
+instance Num SExpr where
+  fromInteger = sVal . literal
+  (+)         = sAdd
+  (*)         = sMul
+  abs         = error "Num SExpr: undefined abs"
+  signum      = error "Num SExpr: undefined signum"
+  negate      = error "Num SExpr: undefined negate"
+
+-- | Validity: We require each variable appearing to be an identifier (lowercase letter followed by
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is introduced by an enclosing let expression.
+isValid :: SExpr -> SBool
+isValid = go []
+  where isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+        go :: SList String -> SExpr -> SBool
+        go = smtFunction "valid"
+           $ \env expr -> [sCase| expr of
+                              Var s     -> isId s .&& s `SL.elem` env
+                              Val _     -> sTrue
+                              Add l r   -> go env l .&& go env r
+                              Mul l r   -> go env l .&& go env r
+                              Let s a b -> isId s .&& go env a .&& go (s SL..: env) b
+                           |]
+
+-- | Evaluate an expression.
+eval :: SExpr -> SInteger
+eval = go []
+ where go :: SList (String, Integer) -> SExpr -> SInteger
+       go = smtFunction "eval"
+          $ \env expr -> [sCase| expr of
+                            Val i     -> i
+                            Var s     -> get env s
+                            Add l r   -> go env l + go env r
+                            Mul l r   -> go env l * go env r
+                            Let s e r -> go (tuple (s, go env e) SL..: env) r
+                         |]
+
+       get :: SList (String, Integer) -> SString -> SInteger
+       get = smtFunction "get"
+           $ \env s -> [sCase| env of
+                          []                    -> 0
+                          (k, v) : es | s .== k -> v
+                                      | True    -> get es s
+                       |]
+
+-- | A basic theorem about 'eval'.
+-- >>> evalPlus5
+-- Q.E.D.
+evalPlus5 :: IO ThmResult
+evalPlus5 = prove $ do e :: SExpr <- free "e"
+                       pure $ eval (e + 5) .== 5 + eval e
+
+-- | A simple sat result example.
+--
+-- >>> evalSat
+-- Satisfiable. Model:
+--   e = Let "h" (Val 1) (Var "h") :: Expr
+--   a =                         9 :: Integer
+--   b =                        10 :: Integer
+evalSat :: IO SatResult
+evalSat = sat $ do e :: SExpr    <- free "e"
+                   constrain $ isValid e
+                   constrain $ isLet   e
+
+                   a :: SInteger <- free "a"
+                   b :: SInteger <- free "b"
+                   constrain $ a .>= 4
+                   constrain $ b .>= 10
+
+                   pure $ eval (e + sVal a) .== b * eval e
+
+-- | Another test, generating some (mildly) interesting examples.
+--
+-- >>> genE
+-- Satisfiable. Model:
+--   e1 = Let "k" (Mul (Val 1) (Mul (Val (-3)) (Val (-1)))) (Var "k") :: Expr
+--   e2 =                                                    Val (-2) :: Expr
+genE :: IO SatResult
+genE = sat $ do e1 :: SExpr <- free "e1"
+                e2 :: SExpr <- free "e2"
+
+                constrain $ isValid e1
+                constrain $ isValid e2
+
+                constrain $ e1 ./== e2
+                constrain $ isLet e1
+                constrain $ eval e1 .== 3
+                constrain $ eval e1 .== eval e2 + 5
+
+-- | Query mode example.
+--
+-- >>> queryE
+-- e1: (let k = (1 * (-3 * -1)) in k)
+-- e2: -2
+queryE :: IO ()
+queryE = runSMT $ do
+           e1 :: SExpr <- free "e1"
+           e2 :: SExpr <- free "e2"
+
+           constrain $ isValid e1
+           constrain $ isValid e2
+
+           constrain $ e1 ./== e2
+           constrain $ isLet e1
+           constrain $ eval e1 .== 3
+           constrain $ eval e1 .== eval e2 + 5
+
+           query $ do cs <- checkSat
+                      case cs of
+                        Sat -> do e1v <- getValue e1
+                                  e2v <- getValue e2
+                                  io $ putStrLn $ "e1: " ++ show e1v
+                                  io $ putStrLn $ "e2: " ++ show e2v
+                        _   -> error $ "Unexpected result: " ++ show cs
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/ADT/Param.hs b/Documentation/SBV/Examples/ADT/Param.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Param.hs
@@ -0,0 +1,191 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Param
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A basic parameterized expression ADT example.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ADT.Param where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import qualified Data.SBV.List as SL
+
+-- | A basic arithmetic expression type.
+data Expr nm val = Val val
+                 | Var nm
+                 | Add (Expr nm val) (Expr nm val)
+                 | Mul (Expr nm val) (Expr nm val)
+                 | Let nm (Expr nm val) (Expr nm val)
+
+-- | Create a symbolic version of expressions.
+mkSymbolic [''Expr]
+
+-- | Show instance for 'Expr'.
+instance (Show nm, Show val) => Show (Expr nm val) where
+  show (Val i)     = show i
+  show (Var a)     = show a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ show s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Show instance for 'Expr', specialized when name is string.
+instance {-# OVERLAPPING #-} Show val => Show (Expr String val) where
+  show (Val i)     = show i
+  show (Var a)     = a
+  show (Add l r)   = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r)   = "(" ++ show l ++ " * " ++ show r ++ ")"
+  show (Let s a b) = "(let " ++ s ++ " = " ++ show a ++ " in " ++ show b ++ ")"
+
+-- | Num instance, simplifies construction of values
+instance Integral val => Num (Expr nm val) where
+  fromInteger = Val . fromIntegral
+  (+)         = Add
+  (*)         = Mul
+  abs         = error "Num Expr: undefined abs"
+  signum      = error "Num Expr: undefined signum"
+  negate      = error "Num Expr: undefined negate"
+
+-- | Num instance for the symbolic version
+instance (SymVal nm, SymVal val, Integral val) => Num (SExpr nm val) where
+  fromInteger = sVal . literal . fromIntegral
+  (+)         = sAdd
+  (*)         = sMul
+  abs         = error "Num SExpr: undefined abs"
+  signum      = error "Num SExpr: undefined signum"
+  negate      = error "Num SExpr: undefined negate"
+
+-- | Validity: We require each variable appearing to be an identifier to satisfy the predicate given.
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is introduced by an enclosing let expression.
+isValid :: (SymVal nm, Eq nm, SymVal val) => (SBV nm -> SBool) -> SExpr nm val -> SBool
+isValid nmChk = go []
+  where go = smtFunction "valid"
+           $ \env expr -> [sCase| expr of
+                              Var s     -> nmChk s  .&& s `SL.elem` env
+                              Val _     -> sTrue
+                              Add l r   -> go env l .&& go env r
+                              Mul l r   -> go env l .&& go env r
+                              Let s a b -> nmChk s  .&& go env a .&& go (s SL..: env) b
+                           |]
+
+-- | Evaluate an expression.
+eval :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+eval = go []
+ where go = smtFunction "eval"
+          $ \env expr -> [sCase| expr of
+                            Val i     -> i
+                            Var s     -> get env s
+                            Add l r   -> go env l + go env r
+                            Mul l r   -> go env l * go env r
+                            Let s e r -> go (tuple (s, go env e) SL..: env) r
+                         |]
+
+       get = smtFunction "get"
+           $ \env s -> [sCase| env of
+                           []                    -> 0
+                           (k, v) : es | s .== k -> v
+                                       | True    -> get es s
+                        |]
+
+-- | A basic theorem about 'eval'.
+-- >>> evalPlus5
+-- Q.E.D.
+evalPlus5 :: IO ThmResult
+evalPlus5 = prove $ do e :: SExpr String Integer <- free "e"
+                       pure $ eval (e + 5) .== 5 + eval e
+
+-- | Is this a string identifier? Lowercase letter followed by any number of upper-lower case letters and digits.
+isId :: SString -> SBool
+isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+
+-- | A simple sat result example.
+--
+-- >>> evalSat
+-- Satisfiable. Model:
+--   e = Let "h" (Val 1) (Var "h") :: Expr String Integer
+--   a =                         9 :: Integer
+--   b =                        10 :: Integer
+evalSat :: IO SatResult
+evalSat = sat $ do e :: SExpr String Integer  <- free "e"
+                   constrain $ isValid isId e
+                   constrain $ isLet   e
+
+                   a :: SInteger <- free "a"
+                   b :: SInteger <- free "b"
+                   constrain $ a .>= 4
+                   constrain $ b .>= 10
+
+                   pure $ eval (e + sVal a) .== b * eval e
+
+-- | Another test, generating some (mildly) interesting examples.
+--
+-- >>> genE
+-- Satisfiable. Model:
+--   e1 = Let "h" (Val 5) (Val 3) :: Expr String Integer
+--   e2 =                Val (-2) :: Expr String Integer
+genE :: IO SatResult
+genE = sat $ do e1 :: SExpr String Integer <- free "e1"
+                e2 :: SExpr String Integer <- free "e2"
+
+                constrain $ isValid isId e1
+                constrain $ isValid isId e2
+
+                constrain $ e1 ./== e2
+                constrain $ isLet e1
+                constrain $ eval e1 .== 3
+                constrain $ eval e1 .== eval e2 + 5
+
+-- | Query mode example.
+--
+-- >>> queryE
+-- e1: (let a = ((let x = 20 in 4) * -5) in (-1 * -3))
+-- e2: -2
+-- e3: (let h = 79 % 80 in h)
+queryE :: IO ()
+queryE = runSMT $ do
+           e1 :: SExpr String Integer <- free "e1"
+           e2 :: SExpr String Integer <- free "e2"
+
+           e3 :: SExpr String Rational <- free "e3"
+
+           constrain $ isValid isId e1
+           constrain $ isValid isId e2
+           constrain $ isValid isId e3
+
+           constrain $ e1 ./== e2
+           constrain $ isLet e1
+           constrain $ eval e1 .== 3
+           constrain $ eval e1 .== eval e2 + 5
+
+           constrain $ isLet e3
+           constrain $ isMul (getLet_2 e1)
+           constrain $ isMul (getLet_3 e1)
+
+           query $ do cs <- checkSat
+                      case cs of
+                        Sat -> do e1v <- getValue e1
+                                  e2v <- getValue e2
+                                  e3v <- getValue e3
+                                  io $ putStrLn $ "e1: " ++ show e1v
+                                  io $ putStrLn $ "e2: " ++ show e2v
+                                  io $ putStrLn $ "e3: " ++ show e3v
+                        _   -> error $ "Unexpected result: " ++ show cs
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/ADT/Types.hs b/Documentation/SBV/Examples/ADT/Types.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ADT/Types.hs
@@ -0,0 +1,131 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ADT.Types
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An encoding of the simple type-checking via constraints, following
+-- <https://microsoft.github.io/z3guide/docs/theories/Datatypes/#using-datatypes-for-solving-type-constraints>
+-----------------------------------------------------------------------------
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+module Documentation.SBV.Examples.ADT.Types where
+
+import Data.SBV
+
+-- | Simple encoding of untyped lambda terms
+data M = Var { var   :: String }     -- ^ Variables: @x@
+       | Lam { bound :: String       -- ^ Abstraction: @\x. M@
+             , body :: M
+             }
+       | App { fn  :: M              -- ^ Application: @M M@
+             , arg :: M
+             }
+
+-- | Types.
+data T = TInt                        -- ^ Integers
+       | TStr                        -- ^ Strings
+       | TArr { dom :: T, rng :: T } -- ^ Functions: @t -> t@
+
+-- | Make terms and types symbolic
+mkSymbolic [''M]
+mkSymbolic [''T]
+
+-- | Instead of modeling environments for mapping variables to their
+-- types, we'll simply use an uninterpreted function. Note that
+-- this also implies we consider all terms to be given so that variables
+-- do not shadow each other; i.e., all variables are unique. This is
+-- a simplification, but it is not without justification: One can
+-- always alpha-rename bound variables so all bound variables are unique.
+env :: SString -> ST
+env = uninterpret "env"
+
+-- | Use an uninterpreted function to also magically find the type of a term.
+typeOf :: SM -> ST
+typeOf = uninterpret "typeOf"
+
+-- | Given a term and a type, check that the term has that type.
+tc :: SM -> ST -> SBool
+tc = smtFunction "constraints" $ \m t ->
+        [sCase| m of
+
+          -- Var case. The environment must match the type we expect.
+          Var s -> env s .== t
+
+          -- Abstraction case. Type must be a function, whose domain matches the variable.
+          -- And body must match the range.
+          Lam v b
+            | isTArr t .&& env v .== sdom t
+            -> tc b (srng t)
+
+          -- Application case. In this case, we ask the solver to give us the type of the
+          -- function, and then ensure the whole thing is well-formed
+          App f a -> let tf = typeOf f
+                     in   isTArr tf      -- f must have an arrow type
+                      .&& tc f tf        -- The function must type-check with that type
+                      .&& tc a (sdom tf) -- Argument must have the type of this function
+                      .&& t .== srng tf  -- Final result must match the type we're looking for
+
+          -- Otherwise, ill-typed.
+          _ -> sFalse
+        |]
+
+-- | Well typedness: If what the 'typeOf' function returns type-checks the term,
+-- then a term is well-typed.
+wellTyped :: SM -> SBool
+wellTyped m = tc m (typeOf m)
+
+-- | Make sure the identity function can be typed.
+--
+-- >>> idWF
+-- Satisfiable. Model:
+--   env :: String -> T
+--   env _ = TInt
+-- <BLANKLINE>
+--   typeOf :: M -> T
+--   typeOf _ = TArr TInt TInt
+--
+-- The model is rather uninteresting, but it shows that identity can have the type Integer to Integer, where
+-- all variables are mapped to Integers.
+idWF :: IO SatResult
+idWF = sat $ wellTyped $ sLam x vx
+  where x  = literal "x"
+        vx = sVar x
+
+-- | Check that if we apply a function that takes n integer to a string is not well-typed.
+--
+-- >>> intFuncAppString
+-- Unsatisfiable
+--
+-- As expected, the solver says that there's no way to type-check such an expression.
+intFuncAppString :: IO SatResult
+intFuncAppString = sat $ do
+        -- Introduce the constant @plus1 :: Int -> Int@
+        plus1 <- free "plus1"
+        constrain $ tc plus1 (literal (TInt `TArr` TInt))
+
+        -- Introduce the constant @str :: String@
+        str <- free "str"
+        constrain $ tc str sTStr
+
+        -- Check if the application of plus1 to str can be well-typed
+        pure $ wellTyped $ sApp plus1 str
+
+-- | Make sure self-application cannot be typed.
+--
+-- >>> selfAppNotWellTyped
+-- Unsatisfiable
+--
+-- We get unsatisfiable, indicating there's no way to come up with an environment that will
+-- successfully assign a type to the term @\x -> x x@.
+selfAppNotWellTyped :: IO SatResult
+selfAppNotWellTyped = sat $ wellTyped $ sLam x (sApp vx vx)
+  where x  = literal "x"
+        vx = sVar x
diff --git a/Documentation/SBV/Examples/BitPrecise/Adders.hs b/Documentation/SBV/Examples/BitPrecise/Adders.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/Adders.hs
@@ -0,0 +1,185 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.Adders
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Build two textbook binary adders out of logic gates and prove them correct,
+-- fully automatically, by bit-blasting.
+--
+-- We model each adder as a Haskell function over a statically-known list of
+-- symbolic bits, producing a fixed Boolean circuit. We then prove---for a
+-- chosen word size---that the circuit computes the same result as SBV's native
+-- bit-vector addition @(+)@:
+--
+--   * A /ripple-carry/ adder, which threads a carry sequentially through a
+--     chain of full adders.
+--
+--   * A /carry-lookahead/ adder, which computes every carry directly from the
+--     generate\/propagate signals of all lower bits, with no sequential
+--     dependency.
+--
+-- Besides proving each adder equal to @(+)@, we also prove the two adders equal
+-- to /each other/: the fast, parallel carry-lookahead circuit computes exactly
+-- the same result as the simple ripple-carry reference.
+--
+-- All proofs here are discharged by a single decidable bit-vector query at a
+-- fixed width. See "Documentation.SBV.Examples.TP.Adder" for the companion
+-- development that instead proves a ripple-carry adder correct for /all/ widths
+-- at once, by induction.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.Adders where
+
+import Data.SBV hiding (fullAdder)
+import GHC.TypeLits (KnownNat)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> :set -XDataKinds -XTypeApplications -XScopedTypeVariables
+#endif
+
+-- | A symbolic bit is just a symbolic boolean.
+type Bit = SBool
+
+-- * Logic gates
+
+-- | A half adder takes two bits and produces their sum bit and carry bit:
+-- @sum = a xor b@, @carry = a and b@.
+halfAdder :: Bit -> Bit -> (Bit, Bit)
+halfAdder a b = (a .<+> b, a .&& b)
+
+-- | A full adder takes two bits and an incoming carry, and produces the sum bit
+-- together with the outgoing carry. We build it out of two half adders, in the
+-- usual way.
+fullAdder :: Bit -> Bit -> Bit -> (Bit, Bit)
+fullAdder a b cin = (s, c0 .|| c1)
+  where (s0, c0) = halfAdder a b
+        (s,  c1) = halfAdder s0 cin
+
+-- * Ripple-carry adder
+
+-- | The ripple-carry adder. Given an incoming carry and a little-endian list of
+-- bit pairs (one pair per bit position, least-significant first), it threads the
+-- carry through a chain of full adders, returning the list of sum bits together
+-- with the final carry-out.
+rippleAdd :: Bit -> [(Bit, Bit)] -> ([Bit], Bit)
+rippleAdd cin []            = ([], cin)
+rippleAdd cin ((a, b) : ps) = (s : ss, cout)
+  where (s,  c)    = fullAdder a b cin
+        (ss, cout) = rippleAdd c ps
+
+-- * Carry-lookahead adder
+
+-- | Generate and propagate signals for a bit position: a position /generates/ a
+-- carry when both inputs are set, and /propagates/ an incoming carry when
+-- exactly one input is set.
+generatePropagate :: Bit -> Bit -> (Bit, Bit)
+generatePropagate a b = (a .&& b, a .<+> b)
+
+-- | The carry-lookahead adder. Rather than rippling the carry through the chain,
+-- it computes the carry /into/ each position directly from the
+-- generate\/propagate signals of all lower positions, using the textbook
+-- expansion
+--
+-- @
+--   c(i) = g(i-1) + p(i-1).g(i-2) + ... + p(i-1)...p(1).g(0) + p(i-1)...p(0).cin
+-- @
+--
+-- so that every carry is an independent flat formula with no sequential
+-- dependency. The sum bit at position @i@ is then @p(i) xor c(i)@, and the
+-- carry-out is the carry into the (nonexistent) position just past the top.
+lookaheadAdd :: Bit -> [(Bit, Bit)] -> ([Bit], Bit)
+lookaheadAdd cin ps = (sums, carryInto n)
+  where n   = length ps
+        gps = [ generatePropagate a b | (a, b) <- ps ]
+
+        g k = fst (gps !! k)
+        p k = snd (gps !! k)
+
+        -- product of the propagate signals over positions [lo .. hi-1]
+        prodP lo hi = sAnd [ p k | k <- [lo .. hi - 1] ]
+
+        -- carry into position i, expanded over all lower positions
+        carryInto i = sOr $ (cin .&& prodP 0 i)
+                          : [ g j .&& prodP (j + 1) i | j <- [0 .. i - 1] ]
+
+        sums = [ p i .<+> carryInto i | i <- [0 .. n - 1] ]
+
+-- * Lifting to words
+
+-- | Run an adder over the bits of two words. We blast both operands into
+-- little-endian bit lists, feed them to the adder with no incoming carry, and
+-- reassemble the sum bits into a word. The carry-out is dropped, matching the
+-- wrap-around semantics of bit-vector @(+)@.
+addWith :: forall n. (KnownNat n, BVIsNonZero n) => (Bit -> [(Bit, Bit)] -> ([Bit], Bit)) -> SWord n -> SWord n -> SWord n
+addWith adder x y = fromBitsLE ss
+  where (ss, _) = adder sFalse (zip (blastLE x) (blastLE y))
+
+-- | The ripple-carry adder, lifted to words.
+rippleAddWord :: (KnownNat n, BVIsNonZero n) => SWord n -> SWord n -> SWord n
+rippleAddWord = addWith rippleAdd
+
+-- | The carry-lookahead adder, lifted to words.
+lookaheadAddWord :: (KnownNat n, BVIsNonZero n) => SWord n -> SWord n -> SWord n
+lookaheadAddWord = addWith lookaheadAdd
+
+-- * Correctness
+
+-- | The ripple-carry adder computes bit-vector addition. We prove it here at
+-- width 8, but the same call proves it at any width you instantiate:
+--
+-- >>> rippleCorrect @8
+-- Q.E.D.
+--
+-- Adder-versus-@(+)@ equivalence is one of the easy cases for bit-blasting (the
+-- carry chain is linear), so this stays fast even at large widths---it is the
+-- cheap baseline to compare the lookahead proofs against.
+rippleCorrect :: forall n. (KnownNat n, BVIsNonZero n) => IO ThmResult
+rippleCorrect = prove $ \(x :: SWord n) (y :: SWord n) -> rippleAddWord x y .== x + y
+
+-- | The carry-lookahead adder computes bit-vector addition:
+--
+-- >>> lookaheadCorrect @8
+-- Q.E.D.
+--
+-- Note that, unlike 'rippleCorrect', this proof slows down noticeably as the
+-- width grows. The lookahead carry is the flat \(O(n^2)\) generate\/propagate
+-- expansion, so the formula handed to the solver grows quadratically in the
+-- width---try @lookaheadCorrect \@64@, @\@128@, @\@256@ to watch it climb.
+lookaheadCorrect :: forall n. (KnownNat n, BVIsNonZero n) => IO ThmResult
+lookaheadCorrect = prove $ \(x :: SWord n) (y :: SWord n) -> lookaheadAddWord x y .== x + y
+
+-- | The fast carry-lookahead adder agrees with the simple ripple-carry adder on
+-- every input---the parallel carry computation refines the sequential one:
+--
+-- >>> rippleEqLookahead @8
+-- Q.E.D.
+--
+-- This proof drags in the same \(O(n^2)\) lookahead carry expansion as
+-- 'lookaheadCorrect', so it scales the same way: comfortable at small widths,
+-- visibly slower as the width grows.
+rippleEqLookahead :: forall n. (KnownNat n, BVIsNonZero n) => IO ThmResult
+rippleEqLookahead = prove $ \(x :: SWord n) (y :: SWord n) -> rippleAddWord x y .== lookaheadAddWord x y
+
+-- | The carry-out of the ripple-carry adder is exactly the unsigned overflow
+-- flag: it is set precisely when the true sum does not fit in @n@ bits, which
+-- for an addition with no incoming carry is detectable as the result wrapping
+-- below either operand:
+--
+-- >>> rippleOverflow @8
+-- Q.E.D.
+rippleOverflow :: forall n. (KnownNat n, BVIsNonZero n) => IO ThmResult
+rippleOverflow = prove $ \(x :: SWord n) (y :: SWord n) ->
+                   let (_, cout) = rippleAdd sFalse (zip (blastLE x) (blastLE y))
+                   in cout .== ((x + y) .< x)
diff --git a/Documentation/SBV/Examples/BitPrecise/BitTricks.hs b/Documentation/SBV/Examples/BitPrecise/BitTricks.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/BitTricks.hs
@@ -0,0 +1,62 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.BitTricks
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Checks the correctness of a few tricks from the large collection found in:
+--      <http://graphics.stanford.edu/~seander/bithacks.html>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.BitTricks where
+
+import Data.SBV
+
+-- | Formalizes <http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax>
+fastMinCorrect :: SInt32 -> SInt32 -> SBool
+fastMinCorrect x y = m .== fm
+  where m  = ite (x .< y) x y
+        fm = y `xor` ((x `xor` y) .&. (-(oneIf (x .< y))));
+
+-- | Formalizes <http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax>
+fastMaxCorrect :: SInt32 -> SInt32 -> SBool
+fastMaxCorrect x y = m .== fm
+  where m  = ite (x .< y) y x
+        fm = x `xor` ((x `xor` y) .&. (-(oneIf (x .< y))));
+
+-- | Formalizes <http://graphics.stanford.edu/~seander/bithacks.html#DetectOppositeSigns>
+oppositeSignsCorrect :: SInt32 -> SInt32 -> SBool
+oppositeSignsCorrect x y = r .== os
+  where r  = (x .< 0 .&& y .>= 0) .|| (x .>= 0 .&& y .< 0)
+        os = (x `xor` y) .< 0
+
+-- | Formalizes <http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching>
+conditionalSetClearCorrect :: SBool -> SWord32 -> SWord32 -> SBool
+conditionalSetClearCorrect f m w = r .== r'
+  where r  = ite f (w .|. m) (w .&. complement m)
+        r' = w `xor` ((-(oneIf f) `xor` w) .&. m);
+
+-- | Formalizes <http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2>
+powerOfTwoCorrect :: SWord32 -> SBool
+powerOfTwoCorrect v = f .== s
+  where f = (v ./= 0) .&& ((v .&. (v-1)) .== 0);
+        powers :: [Word32]
+        powers = map ((2::Word32)^) [(0::Word32) .. 31]
+        s = sAny (v .==) $ map literal powers
+
+-- | Collection of queries
+queries :: IO ()
+queries =
+  let check w t = do putStr $ "Proving " ++ show w ++ ": "
+                     print =<< prove t
+  in do check "Fast min             " fastMinCorrect
+        check "Fast max             " fastMaxCorrect
+        check "Opposite signs       " oppositeSignsCorrect
+        check "Conditional set/clear" conditionalSetClearCorrect
+        check "PowerOfTwo           " powerOfTwoCorrect
diff --git a/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs b/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs
@@ -0,0 +1,115 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.BrokenSearch
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The classic "binary-searches are broken" example:
+--     <http://ai.googleblog.com/2006/06/extra-extra-read-all-about-it-nearly.html>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.BrokenSearch where
+
+import Data.SBV
+import Data.SBV.Tools.Overflow
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.Int
+#endif
+
+-- | Model the mid-point computation of the binary search, which is broken due to arithmetic overflow.
+-- Note how we use the overflow checking variants of the arithmetic operators. We have:
+--
+-- >>> checkArithOverflow midPointBroken
+-- ./Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs:43:32:+!: SInt32 addition overflows: Violated. Model:
+--   low  = 1073741832 :: Int32
+--   high = 1107296257 :: Int32
+--
+-- Indeed:
+--
+-- >>> (1073741832 + 1107296257) `div` (2::Int32)
+-- -1056964604
+--
+-- giving us quite a large negative mid-point value!
+midPointBroken :: SInt32 -> SInt32 -> SInt32
+midPointBroken low high = (low +! high) /! 2
+
+-- | The correct version of how to compute the mid-point. As expected, this version doesn't have any
+-- underflow or overflow issues:
+--
+-- >>> checkArithOverflow midPointFixed
+-- No violations detected.
+--
+-- As expected, the value is computed correctly too:
+--
+-- >>> checkCorrectMidValue midPointFixed
+-- Q.E.D.
+midPointFixed :: SInt32 -> SInt32 -> SInt32
+midPointFixed low high = low +! ((high -! low) /! 2)
+
+-- | Show that the variant suggested by the blog post is good as well:
+--
+--       @mid = ((unsigned int)low + (unsigned int)high) >> 1;@
+--
+-- In this case the overflow is eliminated by doing the computation at a wider
+-- range:
+--
+-- >>> checkArithOverflow midPointAlternative
+-- No violations detected.
+--
+-- And the value computed is indeed correct:
+--
+-- >>> checkCorrectMidValue midPointAlternative
+-- Q.E.D.
+midPointAlternative :: SInt32 -> SInt32 -> SInt32
+midPointAlternative low high = sFromIntegral ((low' +! high') `shiftR` 1)
+  where low', high' :: SWord32
+        low'  = sFromIntegralChecked low
+        high' = sFromIntegralChecked high
+
+-------------------------------------------------------------------------------------
+-- * Helpers
+-------------------------------------------------------------------------------------
+
+-- | A helper predicate to check safety under the conditions that @low@ is at least 0
+-- and @high@ is at least @low@.
+checkArithOverflow :: (SInt32 -> SInt32 -> SInt32) -> IO ()
+checkArithOverflow f = do sr <- safe $ do low   <- sInt32 "low"
+                                          high <- sInt32 "high"
+
+                                          constrain $ low .>= 0
+                                          constrain $ low .<= high
+
+                                          output $ f low high
+
+                          case filter (not . isSafe) sr of
+                                 [] -> putStrLn "No violations detected."
+                                 xs -> mapM_ print xs
+
+-- | Another helper to show that the result is actually the correct value, if it was done over
+-- 64-bit integers, which is sufficiently large enough.
+checkCorrectMidValue :: (SInt32 -> SInt32 -> SInt32) -> IO ThmResult
+checkCorrectMidValue f = prove $ do low  <- sInt32 "low"
+                                    high <- sInt32 "high"
+
+                                    constrain $ low .>= 0
+                                    constrain $ low .<= high
+
+                                    let low', high' :: SInt64
+                                        low'  = sFromIntegral low
+                                        high' = sFromIntegral high
+                                        mid'  = (low' + high') `sDiv` 2
+
+                                        mid   = f low high
+
+                                    pure $ sFromIntegral mid .== mid'
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/BitPrecise/Legato.hs b/Documentation/SBV/Examples/BitPrecise/Legato.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/Legato.hs
@@ -0,0 +1,313 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.Legato
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An encoding and correctness proof of Legato's multiplier in Haskell. Bill Legato came
+-- up with an interesting way to multiply two 8-bit numbers on Mostek, as described here:
+--   <http://www.cs.utexas.edu/~moore/acl2/workshop-2004/contrib/legato/Weakest-Preconditions-Report.pdf>
+--
+-- Here's Legato's algorithm, as coded in Mostek assembly:
+--
+-- @
+--    step1 :       LDX #8         ; load X immediate with the integer 8
+--    step2 :       LDA #0         ; load A immediate with the integer 0
+--    step3 : LOOP  ROR F1         ; rotate F1 right circular through C
+--    step4 :       BCC ZCOEF      ; branch to ZCOEF if C = 0
+--    step5 :       CLC            ; set C to 0
+--    step6 :       ADC F2         ; set A to A+F2+C and C to the carry
+--    step7 : ZCOEF ROR A          ; rotate A right circular through C
+--    step8 :       ROR LOW        ; rotate LOW right circular through C
+--    step9 :       DEX            ; set X to X-1
+--    step10:       BNE LOOP       ; branch to LOOP if Z = 0
+-- @
+--
+-- This program came to be known as the Legato's challenge in the community, where
+-- the challenge was to prove that it indeed does perform multiplication. This file
+-- formalizes the Mostek architecture in Haskell and proves that Legato's algorithm
+-- is indeed correct.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds      #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.Legato where
+
+import Data.Array (Array, Ix(..), (!), (//), array)
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+import GHC.Generics (Generic)
+
+------------------------------------------------------------------
+-- * Mostek architecture
+------------------------------------------------------------------
+
+-- | We model only two registers of Mostek that is used in the above algorithm, can add more.
+data Register = RegX  | RegA  deriving (Eq, Ord, Ix, Bounded)
+
+-- | The carry flag ('FlagC') and the zero flag ('FlagZ')
+data Flag = FlagC | FlagZ deriving (Eq, Ord, Ix, Bounded)
+
+-- | Mostek was an 8-bit machine.
+type Value = SWord 8
+
+-- | Convenient synonym for symbolic machine bits.
+type Bit = SBool
+
+-- | Register bank
+type Registers = Array Register Value
+
+-- | Flag bank
+type Flags = Array Flag Bit
+
+-- | We have three memory locations, sufficient to model our problem
+data Location = F1   -- ^ multiplicand
+              | F2   -- ^ multiplier
+              | LO   -- ^ low byte of the result gets stored here
+              deriving (Eq, Ord, Ix, Bounded)
+
+-- | Memory is simply an array from locations to values
+type Memory = Array Location Value
+
+-- | Abstraction of the machine: The CPU consists of memory, registers, and flags.
+-- Unlike traditional hardware, we assume the program is stored in some other memory area that
+-- we need not model. (No self modifying programs!)
+--
+-- t'Mostek' is equipped with an automatically derived 'Mergeable' instance
+-- because each field is 'Mergeable'.
+data Mostek = Mostek { memory    :: Memory
+                     , registers :: Registers
+                     , flags     :: Flags
+                     } deriving (Generic, Mergeable)
+
+-- | Given a machine state, compute a value out of it
+type Extract a = Mostek -> a
+
+-- | Programs are essentially state transformers (on the machine state)
+type Program = Mostek -> Mostek
+
+------------------------------------------------------------------
+-- * Low-level operations
+------------------------------------------------------------------
+
+-- | Get the value of a given register
+getReg :: Register -> Extract Value
+getReg r m = registers m ! r
+
+-- | Set the value of a given register
+setReg :: Register -> Value -> Program
+setReg r v m = m {registers = registers m // [(r, v)]}
+
+-- | Get the value of a flag
+getFlag :: Flag -> Extract Bit
+getFlag f m = flags m ! f
+
+-- | Set the value of a flag
+setFlag :: Flag -> Bit -> Program
+setFlag f b m = m {flags = flags m // [(f, b)]}
+
+-- | Read memory
+peek :: Location -> Extract Value
+peek a m = memory m ! a
+
+-- | Write to memory
+poke :: Location -> Value -> Program
+poke a v m = m {memory = memory m // [(a, v)]}
+
+-- | Checking overflow. In Legato's multiplier the @ADC@ instruction
+-- needs to see if the expression x + y + c overflowed, as checked
+-- by this function. Note that we verify the correctness of this check
+-- separately below in `checkOverflowCorrect`.
+checkOverflow :: SWord 8 -> SWord 8 -> SBool -> SBool
+checkOverflow x y c = s .< x .|| s .< y .|| s' .< s
+  where s  = x + y
+        s' = s + ite c 1 0
+
+-- | Correctness theorem for our `checkOverflow` implementation.
+--
+--   We have:
+--
+--   >>> checkOverflowCorrect
+--   Q.E.D.
+checkOverflowCorrect :: IO ThmResult
+checkOverflowCorrect = checkOverflow === overflow
+  where -- Reference spec for overflow. We do the addition
+        -- using 16 bits and check that it's larger than 255
+        overflow :: SWord 8 -> SWord 8 -> SBool -> SBool
+        overflow x y c = (0 # x) + (0 # y) + ite c 1 0 .> (255 :: SWord 16)
+------------------------------------------------------------------
+-- * Instruction set
+------------------------------------------------------------------
+
+-- | An instruction is modeled as a 'Program' transformer. We model
+-- mostek programs in direct continuation passing style.
+type Instruction = Program -> Program
+
+-- | LDX: Set register @X@ to value @v@
+ldx :: Value -> Instruction
+ldx v k = k . setReg RegX v
+
+-- | LDA: Set register @A@ to value @v@
+lda :: Value -> Instruction
+lda v k = k . setReg RegA v
+
+-- | CLC: Clear the carry flag
+clc :: Instruction
+clc k = k . setFlag FlagC sFalse
+
+-- | ROR, memory version: Rotate the value at memory location @a@
+-- to the right by 1 bit, using the carry flag as a transfer position.
+-- That is, the final bit of the memory location becomes the new carry
+-- and the carry moves over to the first bit. This very instruction
+-- is one of the reasons why Legato's multiplier is quite hard to understand
+-- and is typically presented as a verification challenge.
+rorM :: Location -> Instruction
+rorM a k m = k . setFlag FlagC c' . poke a v' $ m
+  where v  = peek a m
+        c  = getFlag FlagC m
+        v' = setBitTo (v `rotateR` 1) 7 c
+        c' = sTestBit v 0
+
+-- | ROR, register version: Same as 'rorM', except through register @r@.
+rorR :: Register -> Instruction
+rorR r k m = k . setFlag FlagC c' . setReg r v' $ m
+  where v  = getReg r m
+        c  = getFlag FlagC m
+        v' = setBitTo (v `rotateR` 1) 7 c
+        c' = sTestBit v 0
+
+-- | BCC: branch to label @l@ if the carry flag is sFalse
+bcc :: Program -> Instruction
+bcc l k m = ite (c .== sFalse) (l m) (k m)
+  where c = getFlag FlagC m
+
+-- | ADC: Increment the value of register @A@ by the value of memory contents
+-- at location @a@, using the carry-bit as the carry-in for the addition.
+adc :: Location -> Instruction
+adc a k m = k . setFlag FlagZ (v' .== 0) . setFlag FlagC c' . setReg RegA v' $ m
+  where v  = peek a m
+        ra = getReg RegA m
+        c  = getFlag FlagC m
+        v' = v + ra + ite c 1 0
+        c' = checkOverflow v ra c
+
+-- | DEX: Decrement the value of register @X@
+dex :: Instruction
+dex k m = k . setFlag FlagZ (x .== 0) . setReg RegX x $ m
+  where x = getReg RegX m - 1
+
+-- | BNE: Branch if the zero-flag is sFalse
+bne :: Program -> Instruction
+bne l k m = ite (z .== sFalse) (l m) (k m)
+  where z = getFlag FlagZ m
+
+-- | The 'end' combinator "stops" our program, providing the final continuation
+-- that does nothing.
+end :: Program
+end = id
+
+------------------------------------------------------------------
+-- * Legato's algorithm in Haskell/SBV
+------------------------------------------------------------------
+
+-- | Multiplies the contents of @F1@ and @F2@, storing the low byte of the result
+-- in @LO@ and the high byte of it in register @A@. The implementation is a direct
+-- transliteration of Legato's algorithm given at the top, using our notation.
+legato :: Program
+legato = start
+  where start   =    ldx 8
+                   $ lda 0
+                   $ loop
+        loop    =    rorM F1
+                   $ bcc zeroCoef
+                   $ clc
+                   $ adc F2
+                   $ zeroCoef
+        zeroCoef =   rorR RegA
+                   $ rorM LO
+                   $ dex
+                   $ bne loop
+                   $ end
+
+------------------------------------------------------------------
+-- * Verification interface
+------------------------------------------------------------------
+-- | Given values for  F1 and F2, @runLegato@ takes an arbitrary machine state @m@ and
+-- returns the high and low bytes of the multiplication.
+runLegato :: Mostek -> (Value, Value)
+runLegato m = (getReg RegA m', peek LO m')
+  where m' = legato m
+
+-- | Helper synonym for capturing relevant bits of Mostek
+type InitVals = ( Value      -- Contents of mem location F1
+                , Value      -- Contents of mem location F2
+                , Value      -- Contents of mem location LO
+                , Value      -- Content of Register X
+                , Value      -- Content of Register A
+                , Bit        -- Value of FlagC
+                , Bit        -- Value of FlagZ
+                )
+
+-- | Create an instance of the Mostek machine, initialized by the memory and the relevant
+-- values of the registers and the flags
+initMachine :: InitVals -> Mostek
+initMachine (f1, f2, lo, rx, ra, fc, fz) = Mostek { memory    = array (minBound, maxBound) [(F1, f1), (F2, f2), (LO, lo)]
+                                                  , registers = array (minBound, maxBound) [(RegX, rx),  (RegA, ra)]
+                                                  , flags     = array (minBound, maxBound) [(FlagC, fc), (FlagZ, fz)]
+                                                  }
+
+-- | The correctness theorem. For all possible memory configurations, the factors (@x@ and @y@ below), the location
+-- of the low-byte result and the initial-values of registers and the flags, this function will return True only if
+-- running Legato's algorithm does indeed compute the product of @x@ and @y@ correctly.
+legatoIsCorrect :: InitVals -> SBool
+legatoIsCorrect initVals@(x, y, _, _, _, _, _) = result .== expected
+    where (hi, lo) = runLegato (initMachine initVals)
+          -- NB. perform the comparison over 16 bit values to avoid overflow!
+          -- If Value changes to be something else, modify this accordingly.
+          result, expected :: SWord 16
+          result   = 256 * (0 # hi) + (0 # lo)
+          expected = (0 # x) * (0 # y)
+
+------------------------------------------------------------------
+-- * Verification
+------------------------------------------------------------------
+
+-- | The correctness theorem.
+correctnessTheorem :: IO ThmResult
+correctnessTheorem = proveWith defaultSMTCfg{timing = PrintTiming} $ do
+        lo <- sWord "lo"
+
+        x <- sWord  "x"
+        y <- sWord  "y"
+
+        regX  <- sWord "regX"
+        regA  <- sWord "regA"
+
+        flagC <- sBool "flagC"
+        flagZ <- sBool "flagZ"
+
+        pure $ legatoIsCorrect (x, y, lo, regX, regA, flagC, flagZ)
+
+------------------------------------------------------------------
+-- * C Code generation
+------------------------------------------------------------------
+
+-- | Generate a C program that implements Legato's algorithm automatically.
+legatoInC :: IO ()
+legatoInC = compileToC Nothing "runLegato" $ do
+                x <- cgInput "x"
+                y <- cgInput "y"
+                let (hi, lo) = runLegato (initMachine (x, y, 0, 0, 0, sFalse, sFalse))
+                cgOutput "hi" hi
+                cgOutput "lo" lo
+
+{- HLint ignore legato "Redundant $"        -}
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/BitPrecise/MergeSort.hs b/Documentation/SBV/Examples/BitPrecise/MergeSort.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/MergeSort.hs
@@ -0,0 +1,104 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.MergeSort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Symbolic implementation of merge-sort and its correctness. Note that this
+-- version, while fully push-button, proves merge-sort correct for fixed number
+-- of elements, i.e., not in its generality. A general proof would require
+-- non-trivial applications of induction and more manual guiding. We do
+-- such a proof in "Documentation.SBV.Examples.TP.MergeSort", which
+-- shows the full-power of the theorem-proving like aspects of SBV.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TupleSections #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.MergeSort where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+-----------------------------------------------------------------------------
+-- * Implementing Merge-Sort
+-----------------------------------------------------------------------------
+-- | Element type of lists we'd like to sort. For simplicity, we'll just
+-- use 'SWord8' here, but we can pick any symbolic type.
+type E = SWord8
+
+-- | Merging two given sorted lists, preserving the order.
+merge :: [E] -> [E] -> [E]
+merge []     ys           = ys
+merge xs     []           = xs
+merge xs@(x:xr) ys@(y:yr) = ite (x .< y) (x : merge xr ys) (y : merge xs yr)
+
+-- | Simple merge-sort implementation. We simply divide the input list
+-- in two halves so long as it has at least two elements, sort
+-- each half on its own, and then merge.
+mergeSort :: [E] -> [E]
+mergeSort []  = []
+mergeSort [x] = [x]
+mergeSort xs  = merge (mergeSort th) (mergeSort bh)
+   where (th, bh) = splitAt (length xs `div` 2) xs
+
+-----------------------------------------------------------------------------
+-- * Proving correctness
+-- ${props}
+-----------------------------------------------------------------------------
+{- $props
+There are two main parts to proving that a sorting algorithm is correct:
+
+       * Prove that the output is non-decreasing
+
+       * Prove that the output is a permutation of the input
+-}
+
+-- | Check whether a given sequence is non-decreasing.
+nonDecreasing :: [E] -> SBool
+nonDecreasing []       = sTrue
+nonDecreasing [_]      = sTrue
+nonDecreasing (a:b:xs) = a .<= b .&& nonDecreasing (b:xs)
+
+-- | Check whether two given sequences are permutations. We simply check that each sequence
+-- is a subset of the other, when considered as a set. The check is slightly complicated
+-- for the need to account for possibly duplicated elements.
+isPermutationOf :: [E] -> [E] -> SBool
+isPermutationOf as bs = go as (map (, sTrue) bs) .&& go bs (map (, sTrue) as)
+  where go []     _  = sTrue
+        go (x:xs) ys = let (found, ys') = mark x ys in found .&& go xs ys'
+        -- Go and mark off an instance of 'x' in the list, if possible. We keep track
+        -- of unmarked elements by associating a boolean bit. Note that we have to
+        -- keep the lists equal size for the recursive result to merge properly.
+        mark _ []         = (sFalse, [])
+        mark x ((y,v):ys) = ite (v .&& x .== y)
+                                (sTrue, (y, sNot v):ys)
+                                (let (r, ys') = mark x ys in (r, (y,v):ys'))
+
+-- | Asserting correctness of merge-sort for a list of the given size. Note that we can
+-- only check correctness for fixed-size lists. Also, the proof will get more and more
+-- complicated for the backend SMT solver as the list size increases. A value around
+-- 5 or 6 should be fairly easy to prove. For instance, we have:
+--
+-- >>> correctness 5
+-- Q.E.D.
+correctness :: Int -> IO ThmResult
+correctness n = prove $ do xs <- mkFreeVars n
+                           let ys = mergeSort xs
+                           pure $ nonDecreasing ys .&& isPermutationOf xs ys
+
+-----------------------------------------------------------------------------
+-- * Generating C code
+-----------------------------------------------------------------------------
+
+-- | Generate C code for merge-sorting an array of size @n@. Again, we're restricted
+-- to fixed size inputs. While the output is not how one would code merge sort in C
+-- by hand, it's a faithful rendering of all the operations merge-sort would do as
+-- described by its Haskell counterpart.
+codeGen :: Int -> IO ()
+codeGen n = compileToC (Just ("mergeSort" ++ show n)) "mergeSort" $ do
+                xs <- cgInputArr n "xs"
+                cgOutputArr "ys" (mergeSort xs)
diff --git a/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs b/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/PEXT_PDEP.hs
@@ -0,0 +1,163 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.PEXT_PDEP
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+--
+-- Models the x86 [PEXT](https://www.felixcloutier.com/x86/pext) and [PDEP](https://www.felixcloutier.com/x86/pdep) instructions.
+--
+-- The pseudo-code implementation given by Intel for PEXT (parallel extract) is:
+--
+-- @
+--    TEMP := SRC1;
+--    MASK := SRC2;
+--    DEST := 0 ;
+--    m := 0, k := 0;
+--    DO WHILE m < OperandSize
+--        IF MASK[m] = 1 THEN
+--            DEST[k] := TEMP[m];
+--            k := k+ 1;
+--        FI
+--        m := m+ 1;
+--    OD
+-- @
+--
+-- PDEP (parallel deposit) is similar, except the assignment is:
+--
+-- @
+--    DEST[m] := TEMP[k]
+-- @
+--
+-- In PEXT, we grab the values of the source corresponding to the mask, and pile them into the destination from the bottom. In PDEP, we
+-- do the reverse: We distribute the bits from the bottom of the source to the destination according to the mask.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.PEXT_PDEP where
+
+import Data.SBV
+import GHC.TypeLits (KnownNat)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> :set -XDataKinds -XTypeApplications
+#endif
+
+--------------------------------------------------------------------------------------------------
+-- * Parallel extraction
+--------------------------------------------------------------------------------------------------
+
+-- | Parallel extraction: Given a source value and a mask, extract the bits in the source that are
+-- pointed to by the mask, and put it in the destination starting from the bottom.
+--
+-- >>> satWith z3{printBase = 16} $ \r -> r .== pext (0xAA :: SWord 8) 0xAA
+-- Satisfiable. Model:
+--   s0 = 0x0f :: Word8
+-- >>> prove $ \x -> pext @8 x 0 .== 0
+-- Q.E.D.
+-- >>> prove $ \x -> pext @8 x (complement 0) .== x
+-- Q.E.D.
+pext :: forall n. (KnownNat n, BVIsNonZero n) => SWord n -> SWord n -> SWord n
+pext src mask = walk 0 src 0 (blastLE mask)
+  where walk dest _ _   []     = dest
+        walk dest x idx (m:ms) = walk (ite m (sSetBitTo dest idx (lsb x)) dest)
+                                      (x `shiftR` 1)
+                                      (ite m (idx + 1) idx)
+                                      ms
+
+--------------------------------------------------------------------------------------------------
+-- * Parallel deposit
+--------------------------------------------------------------------------------------------------
+
+-- | Parallel deposit: Given a source value and a mask, write into the destination that are
+-- allowed by the mask, grabbing the bits from the source starting from the bottom.
+--
+-- >>> satWith z3{printBase = 16} $ \r -> r .== pdep (0xFF :: SWord 8) 0xAA
+-- Satisfiable. Model:
+--   s0 = 0xaa :: Word8
+-- >>> prove $ \x -> pdep @8 x 0 .== 0
+-- Q.E.D.
+-- >>> prove $ \x -> pdep @8 x (complement 0) .== x
+-- Q.E.D.
+pdep :: forall n. (KnownNat n, BVIsNonZero n) => SWord n -> SWord n -> SWord n
+pdep src mask = walk 0 src 0 (blastLE mask)
+  where walk dest _ _   []     = dest
+        walk dest x idx (m:ms) = walk (ite m (sSetBitTo dest idx (lsb x)) dest)
+                                      (ite m (x `shiftR` 1) x)
+                                      (idx + 1)
+                                      ms
+--------------------------------------------------------------------------------------------------
+-- * Round-trip property
+--------------------------------------------------------------------------------------------------
+
+-- | Prove that extraction and depositing with the same mask restore the source in all masked positions:
+--
+-- >>> extractThenDeposit
+-- Q.E.D.
+extractThenDeposit :: IO ThmResult
+extractThenDeposit = prove $ do x :: SWord 8 <- sWord "x"
+                                m :: SWord 8 <- sWord "m"
+                                pure $ (x .&. m) .== pdep (pext x m) m
+
+-- | Prove that depositing and extracting with the same mask will push preserve the bottom
+-- n-bits of the source, where n is the number of bits set in the mask.
+--
+-- >>> depositThenExtract
+-- Q.E.D.
+depositThenExtract :: IO ThmResult
+depositThenExtract = prove $ do x :: SWord 8 <- sWord "x"
+                                m :: SWord 8 <- sWord "m"
+                                let preserved = 2 .^ sPopCount m - 1
+                                pure $ (x .&. preserved) .== pext (pdep x m) m
+
+--------------------------------------------------------------------------------------------------
+-- * Code generation
+--------------------------------------------------------------------------------------------------
+
+-- | We can generate the code for these functions if they need to be used in SMTLib. Below
+-- is an example at 2-bits, which can be adjusted to produce any bit-size.
+--
+-- >>> putStrLn =<< sbv2smt pext_2
+-- ; Automatically generated by SBV. Do not modify!
+-- ; |pext_2 @(SBV (WordN 2) -> SBV (WordN 2) -> SBV (WordN 2))| :: SWord 2 -> SWord 2 -> SWord 2
+-- (define-fun |pext_2 @(SBV (WordN 2) -> SBV (WordN 2) -> SBV (WordN 2))| ((l1_s0 (_ BitVec 2)) (l1_s1 (_ BitVec 2))) (_ BitVec 2)
+--                           (let ((l1_s3 #b0))
+--                           (let ((l1_s7 #b01))
+--                           (let ((l1_s8 #b00))
+--                           (let ((l1_s20 #b10))
+--                           (let ((l1_s2 ((_ extract 1 1) l1_s1)))
+--                           (let ((l1_s4 (distinct l1_s2 l1_s3)))
+--                           (let ((l1_s5 ((_ extract 0 0) l1_s1)))
+--                           (let ((l1_s6 (distinct l1_s3 l1_s5)))
+--                           (let ((l1_s9 (ite l1_s6 l1_s7 l1_s8)))
+--                           (let ((l1_s10 (= l1_s7 l1_s9)))
+--                           (let ((l1_s11 (bvlshr l1_s0 l1_s7)))
+--                           (let ((l1_s12 ((_ extract 0 0) l1_s11)))
+--                           (let ((l1_s13 (distinct l1_s3 l1_s12)))
+--                           (let ((l1_s14 (= l1_s8 l1_s9)))
+--                           (let ((l1_s15 ((_ extract 0 0) l1_s0)))
+--                           (let ((l1_s16 (distinct l1_s3 l1_s15)))
+--                           (let ((l1_s17 (ite l1_s16 l1_s7 l1_s8)))
+--                           (let ((l1_s18 (ite l1_s6 l1_s17 l1_s8)))
+--                           (let ((l1_s19 (bvor l1_s7 l1_s18)))
+--                           (let ((l1_s21 (bvand l1_s18 l1_s20)))
+--                           (let ((l1_s22 (ite l1_s13 l1_s19 l1_s21)))
+--                           (let ((l1_s23 (ite l1_s14 l1_s22 l1_s18)))
+--                           (let ((l1_s24 (bvor l1_s20 l1_s23)))
+--                           (let ((l1_s25 (bvand l1_s7 l1_s23)))
+--                           (let ((l1_s26 (ite l1_s13 l1_s24 l1_s25)))
+--                           (let ((l1_s27 (ite l1_s10 l1_s26 l1_s23)))
+--                           (let ((l1_s28 (ite l1_s4 l1_s27 l1_s18)))
+--                           l1_s28))))))))))))))))))))))))))))
+pext_2 :: SWord 2 -> SWord 2 -> SWord 2
+pext_2 = smtFunction "pext_2" (pext @2)
diff --git a/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs b/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs
@@ -0,0 +1,104 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.BitPrecise.PrefixSum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The PrefixSum algorithm over power-lists and proof of
+-- the Ladner-Fischer implementation.
+-- See <https://www.cs.utexas.edu/~misra/psp.dir/powerlist.pdf>
+-- and <http://www.cs.utexas.edu/~plaxton/c/337/05f/slides/ParallelRecursion-4.pdf>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.BitPrecise.PrefixSum where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+----------------------------------------------------------------------
+-- * Formalizing power-lists
+----------------------------------------------------------------------
+
+-- | A poor man's representation of powerlists and
+-- basic operations on them: <https://www.cs.utexas.edu/~misra/psp.dir/powerlist.pdf>.
+-- We merely represent power-lists by ordinary lists.
+type PowerList a = [a]
+
+-- | The tie operator, concatenation.
+tiePL :: PowerList a -> PowerList a -> PowerList a
+tiePL = (++)
+
+-- | The zip operator, zips the power-lists of the same size, returns
+-- a powerlist of double the size.
+zipPL :: PowerList a -> PowerList a -> PowerList a
+zipPL []     []     = []
+zipPL (x:xs) (y:ys) = x : y : zipPL xs ys
+zipPL _      _      = error "zipPL: nonsimilar powerlists received"
+
+-- | Inverse of zipping.
+unzipPL :: PowerList a -> (PowerList a, PowerList a)
+unzipPL = unzip . chunk2
+  where chunk2 []       = []
+        chunk2 (x:y:xs) = (x,y) : chunk2 xs
+        chunk2 _        = error "unzipPL: malformed powerlist"
+
+----------------------------------------------------------------------
+-- * Reference prefix-sum implementation
+----------------------------------------------------------------------
+
+-- | Reference prefix sum (@ps@) is simply Haskell's @scanl1@ function.
+ps :: (a, a -> a -> a) -> PowerList a -> PowerList a
+ps (_, f) = scanl1 f
+
+----------------------------------------------------------------------
+-- * The Ladner-Fischer parallel version
+----------------------------------------------------------------------
+
+-- | The Ladner-Fischer (@lf@) implementation of prefix-sum.
+lf :: (a, a -> a -> a) -> PowerList a -> PowerList a
+lf _            []  = error "lf: malformed (empty) powerlist"
+lf _            [x] = [x]
+lf (zeroE, f)   pl  = zipPL (zipWith f (rsh lfpq) p) lfpq
+   where (p, q) = unzipPL pl
+         pq     = zipWith f p q
+         lfpq   = lf (zeroE, f) pq
+         rsh xs = zeroE : init xs
+
+
+----------------------------------------------------------------------
+-- * Sample proofs for concrete operators
+----------------------------------------------------------------------
+
+-- | Correctness theorem, for a powerlist of given size, an associative operator, and its left-unit element.
+flIsCorrect :: Int -> (forall a. (OrdSymbolic a, Num a, Bits a) => (a, a -> a -> a)) -> Symbolic SBool
+flIsCorrect n zf = do
+        args :: PowerList SWord32 <- mkFreeVars n
+        pure $ ps zf args .== lf zf args
+
+-- | Proves Ladner-Fischer is equivalent to reference specification for addition.
+-- @0@ is the left-unit element, and we use a power-list of size @8@. We have:
+--
+-- >>> thm1
+-- Q.E.D.
+thm1 :: IO ThmResult
+thm1 = prove $ flIsCorrect  8 (0, (+))
+
+-- | Proves Ladner-Fischer is equivalent to reference specification for the function @max@.
+-- @0@ is the left-unit element, and we use a power-list of size @16@. We have:
+--
+-- >>> thm2
+-- Q.E.D.
+thm2 :: IO ThmResult
+thm2 = prove $ flIsCorrect 16 (0, smax)
diff --git a/Documentation/SBV/Examples/CodeGeneration/AddSub.hs b/Documentation/SBV/Examples/CodeGeneration/AddSub.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/AddSub.hs
@@ -0,0 +1,143 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.AddSub
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Simple code generation example.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.AddSub where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+-- | Simple function that returns add/sum of args
+addSub :: SWord8 -> SWord8 -> (SWord8, SWord8)
+addSub x y = (x+y, x-y)
+
+-- | Generate C code for addSub. Here's the output showing the generated C code:
+--
+-- >>> genAddSub
+-- == BEGIN: "Makefile" ================
+-- # Makefile for addSub. Automatically generated by SBV. Do not edit!
+-- <BLANKLINE>
+-- # include any user-defined .mk file in the current directory.
+-- -include *.mk
+-- <BLANKLINE>
+-- CC?=gcc
+-- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+-- <BLANKLINE>
+-- all: addSub_driver
+-- <BLANKLINE>
+-- addSub.o: addSub.c addSub.h
+-- 	${CC} ${CCFLAGS} -c $< -o $@
+-- <BLANKLINE>
+-- addSub_driver.o: addSub_driver.c
+-- 	${CC} ${CCFLAGS} -c $< -o $@
+-- <BLANKLINE>
+-- addSub_driver: addSub.o addSub_driver.o
+-- 	${CC} ${CCFLAGS} $^ -o $@
+-- <BLANKLINE>
+-- clean:
+-- 	rm -f *.o
+-- <BLANKLINE>
+-- veryclean: clean
+-- 	rm -f addSub_driver
+-- == END: "Makefile" ==================
+-- == BEGIN: "addSub.h" ================
+-- /* Header file for addSub. Automatically generated by SBV. Do not edit! */
+-- <BLANKLINE>
+-- #ifndef __addSub__HEADER_INCLUDED__
+-- #define __addSub__HEADER_INCLUDED__
+-- <BLANKLINE>
+-- #include <stdio.h>
+-- #include <stdlib.h>
+-- #include <inttypes.h>
+-- #include <stdint.h>
+-- #include <stdbool.h>
+-- #include <string.h>
+-- #include <math.h>
+-- <BLANKLINE>
+-- /* The boolean type */
+-- typedef bool SBool;
+-- <BLANKLINE>
+-- /* The float type */
+-- typedef float SFloat;
+-- <BLANKLINE>
+-- /* The double type */
+-- typedef double SDouble;
+-- <BLANKLINE>
+-- /* Unsigned bit-vectors */
+-- typedef uint8_t  SWord8;
+-- typedef uint16_t SWord16;
+-- typedef uint32_t SWord32;
+-- typedef uint64_t SWord64;
+-- <BLANKLINE>
+-- /* Signed bit-vectors */
+-- typedef int8_t  SInt8;
+-- typedef int16_t SInt16;
+-- typedef int32_t SInt32;
+-- typedef int64_t SInt64;
+-- <BLANKLINE>
+-- /* Entry point prototype: */
+-- void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
+--             SWord8 *dif);
+-- <BLANKLINE>
+-- #endif /* __addSub__HEADER_INCLUDED__ */
+-- == END: "addSub.h" ==================
+-- == BEGIN: "addSub_driver.c" ================
+-- /* Example driver program for addSub. */
+-- /* Automatically generated by SBV. Edit as you see fit! */
+-- <BLANKLINE>
+-- #include <stdio.h>
+-- #include "addSub.h"
+-- <BLANKLINE>
+-- int main(void)
+-- {
+--   SWord8 sum;
+--   SWord8 dif;
+-- <BLANKLINE>
+--   addSub(132, 241, &sum, &dif);
+-- <BLANKLINE>
+--   printf("addSub(132, 241, &sum, &dif) ->\n");
+--   printf("  sum = %"PRIu8"\n", sum);
+--   printf("  dif = %"PRIu8"\n", dif);
+-- <BLANKLINE>
+--   return 0;
+-- }
+-- == END: "addSub_driver.c" ==================
+-- == BEGIN: "addSub.c" ================
+-- /* File: "addSub.c". Automatically generated by SBV. Do not edit! */
+-- <BLANKLINE>
+-- #include "addSub.h"
+-- <BLANKLINE>
+-- void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
+--             SWord8 *dif)
+-- {
+--   const SWord8 s0 = x;
+--   const SWord8 s1 = y;
+--   const SWord8 s2 = s0 + s1;
+--   const SWord8 s3 = s0 - s1;
+-- <BLANKLINE>
+--   *sum = s2;
+--   *dif = s3;
+-- }
+-- == END: "addSub.c" ==================
+--
+genAddSub :: IO ()
+genAddSub = compileToC outDir "addSub" $ do
+        x <- cgInput "x"
+        y <- cgInput "y"
+        -- leave the cgDriverVals call out for generating a driver with random values
+        cgSetDriverValues [132, 241]
+        let (s, d) = addSub x y
+        cgOutput "sum" s
+        cgOutput "dif" d
+ where -- use Just "dirName" for putting the output to the named directory
+       -- otherwise, it'll go to standard output
+       outDir = Nothing
diff --git a/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs b/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs
@@ -0,0 +1,89 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Computing the CRC symbolically, using the USB polynomial. We also
+-- generating C code for it as well. This example demonstrates the
+-- use of the 'crcBV' function, along with how CRC's can be computed
+-- mathematically using polynomial division. While the results are the
+-- same (i.e., proven equivalent, see 'crcGood' below), the internal
+-- CRC implementation generates much better code, compare 'cg1' vs 'cg2' below.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.CRC_USB5 where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+import Data.SBV.Tools.Polynomial
+
+-----------------------------------------------------------------------------
+-- * The USB polynomial
+-----------------------------------------------------------------------------
+
+-- | The USB CRC polynomial: @x^5 + x^2 + 1@.
+-- Although this polynomial needs just 6 bits to represent (5 if higher
+-- order bit is implicitly assumed to be set), we'll simply use a 16 bit
+-- number for its representation to keep things simple for code generation
+-- purposes.
+usb5 :: SWord16
+usb5 = polynomial [5, 2, 0]
+
+-----------------------------------------------------------------------------
+-- * Computing CRCs
+-----------------------------------------------------------------------------
+
+-- | Given an 11 bit message, compute the CRC of it using the USB polynomial,
+-- which is 5 bits, and then append it to the msg to get a 16-bit word. Again,
+-- the incoming 11-bits is represented as a 16-bit word, with 5 highest bits
+-- essentially ignored for input purposes.
+crcUSB :: SWord16 -> SWord16
+crcUSB i = fromBitsBE (ib ++ cb)
+  where ib = drop 5  (blastBE i)    -- only the last 11 bits needed
+        pb = drop 11 (blastBE usb5) -- only the last  5 bits needed
+        cb = crcBV 5 ib pb
+
+-- | Alternate method for computing the CRC, /mathematically/. We shift
+-- the number to the left by 5, and then compute the remainder from the
+-- polynomial division by the USB polynomial. The result is then appended
+-- to the end of the message.
+crcUSB' :: SWord16 -> SWord16
+crcUSB' i' = i .|. pMod i usb5
+  where i = i' `shiftL` 5
+
+-----------------------------------------------------------------------------
+-- * Correctness
+-----------------------------------------------------------------------------
+
+-- | Prove that the custom 'crcBV' function is equivalent to the mathematical
+-- definition of CRC's for 11 bit messages. We have:
+--
+-- >>> crcGood
+-- Q.E.D.
+crcGood :: IO ThmResult
+crcGood = prove $ \i -> crcUSB i .== crcUSB' i
+
+-----------------------------------------------------------------------------
+-- * Code generation
+-----------------------------------------------------------------------------
+
+-- | Generate a C function to compute the USB CRC, using the internal CRC
+-- function.
+cg1 :: IO ()
+cg1 = compileToC (Just "crcUSB1") "crcUSB1" $ do
+        msg <- cgInput "msg"
+        cgOutput "crc" (crcUSB msg)
+
+-- | Generate a C function to compute the USB CRC, using the mathematical
+-- definition of the CRCs. While this version generates functionally equivalent
+-- C code, it's less efficient; it has about 30% more code. So, the above
+-- version is preferable for code generation purposes.
+cg2 :: IO ()
+cg2 = compileToC (Just "crcUSB2") "crcUSB2" $ do
+        msg <- cgInput "msg"
+        cgOutput "crc" (crcUSB' msg)
diff --git a/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs b/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs
@@ -0,0 +1,186 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.Fibonacci
+-- Copyright : (c) Lee Pike
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Computing Fibonacci numbers and generating C code. Inspired by Lee Pike's
+-- original implementation, modified for inclusion in the package. It illustrates
+-- symbolic termination issues one can have when working with recursive algorithms
+-- and how to deal with such, eventually generating good C code.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.Fibonacci where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-----------------------------------------------------------------------------
+-- * A naive implementation
+-----------------------------------------------------------------------------
+
+-- | This is a naive implementation of fibonacci, and will work fine (albeit slow)
+-- for concrete inputs:
+--
+-- >>> map (fib0 . literal) [0..6]
+-- [0 :: SWord64,1 :: SWord64,1 :: SWord64,2 :: SWord64,3 :: SWord64,5 :: SWord64,8 :: SWord64]
+--
+-- However, it is not suitable for doing proofs or generating code, as it is not
+-- symbolically terminating when it is called with a symbolic value @n@. When we
+-- recursively call @fib0@ on @n-1@ (or @n-2@), the test against @0@ will always
+-- explore both branches since the result will be symbolic, hence will not
+-- terminate. (An integrated theorem prover can establish termination
+-- after a certain number of unrollings, but this would be quite expensive to
+-- implement, and would be impractical.)
+fib0 :: SWord64 -> SWord64
+fib0 n = ite (n .== 0 .|| n .== 1)
+             n
+             (fib0 (n-1) + fib0 (n-2))
+
+-----------------------------------------------------------------------------
+-- * Using a recursion depth, and accumulating parameters
+-----------------------------------------------------------------------------
+
+{- $genLookup
+One way to deal with symbolic termination is to limit the number of recursive
+calls. In this version, we impose a limit on the index to the function, working
+correctly upto that limit. If we use a compile-time constant, then SBV's code generator
+can produce code as the unrolling will eventually stop.
+-}
+
+-- | The recursion-depth limited version of fibonacci. Limiting the maximum number to be 20, we can say:
+--
+-- >>> map (fib1 20 . literal) [0..6]
+-- [0 :: SWord64,1 :: SWord64,1 :: SWord64,2 :: SWord64,3 :: SWord64,5 :: SWord64,8 :: SWord64]
+--
+-- The function will work correctly, so long as the index we query is at most @top@, and otherwise
+-- will return the value at @top@. Note that we also use accumulating parameters here for efficiency,
+-- although this is orthogonal to the termination concern.
+--
+-- A note on modular arithmetic: The 64-bit word we use to represent the values will of course
+-- eventually overflow, beware! Fibonacci is a fast growing function..
+fib1 :: SWord64 -> SWord64 -> SWord64
+fib1 top n = fib' 0 1 0
+  where fib' :: SWord64 -> SWord64 -> SWord64 -> SWord64
+        fib' prev' prev m = ite (m .== top .|| m .== n)          -- did we reach recursion depth, or the index we're looking for
+                                prev'                            -- stop and return the result
+                                (fib' prev (prev' + prev) (m+1)) -- otherwise recurse
+
+-- | We can generate code for 'fib1' using the 'genFib1' action. Note that the
+-- generated code will grow larger as we pick larger values of @top@, but only linearly,
+-- thanks to the accumulating parameter trick used by 'fib1'. The following is an excerpt
+-- from the code generated for the call @genFib1 10@, where the code will work correctly
+-- for indexes up to 10:
+--
+-- > SWord64 fib1(const SWord64 x)
+-- > {
+-- >   const SWord64 s0 = x;
+-- >   const SBool   s2 = s0 == 0x0000000000000000ULL;
+-- >   const SBool   s4 = s0 == 0x0000000000000001ULL;
+-- >   const SBool   s6 = s0 == 0x0000000000000002ULL;
+-- >   const SBool   s8 = s0 == 0x0000000000000003ULL;
+-- >   const SBool   s10 = s0 == 0x0000000000000004ULL;
+-- >   const SBool   s12 = s0 == 0x0000000000000005ULL;
+-- >   const SBool   s14 = s0 == 0x0000000000000006ULL;
+-- >   const SBool   s17 = s0 == 0x0000000000000007ULL;
+-- >   const SBool   s19 = s0 == 0x0000000000000008ULL;
+-- >   const SBool   s22 = s0 == 0x0000000000000009ULL;
+-- >   const SWord64 s25 = s22 ? 0x0000000000000022ULL : 0x0000000000000037ULL;
+-- >   const SWord64 s26 = s19 ? 0x0000000000000015ULL : s25;
+-- >   const SWord64 s27 = s17 ? 0x000000000000000dULL : s26;
+-- >   const SWord64 s28 = s14 ? 0x0000000000000008ULL : s27;
+-- >   const SWord64 s29 = s12 ? 0x0000000000000005ULL : s28;
+-- >   const SWord64 s30 = s10 ? 0x0000000000000003ULL : s29;
+-- >   const SWord64 s31 = s8 ? 0x0000000000000002ULL : s30;
+-- >   const SWord64 s32 = s6 ? 0x0000000000000001ULL : s31;
+-- >   const SWord64 s33 = s4 ? 0x0000000000000001ULL : s32;
+-- >   const SWord64 s34 = s2 ? 0x0000000000000000ULL : s33;
+-- >
+-- >   return s34;
+-- > }
+genFib1 :: SWord64 -> IO ()
+genFib1 top = compileToC Nothing "fib1" $ do
+        x <- cgInput "x"
+        cgReturn $ fib1 top x
+
+-----------------------------------------------------------------------------
+-- * Generating a look-up table
+-----------------------------------------------------------------------------
+
+{- $genLookup
+While 'fib1' generates good C code, we can do much better by taking
+advantage of the inherent partial-evaluation capabilities of SBV to generate
+a look-up table, as follows.
+-}
+
+-- | Compute the fibonacci numbers statically at /code-generation/ time and
+-- put them in a table, accessed by the 'select' call.
+fib2 :: Word64 -> SWord64 -> SWord64
+fib2 top = select table 0
+  where table = map (fib1 (literal top) . literal) [0 .. top]
+
+-- | Once we have 'fib2', we can generate the C code straightforwardly. Below
+-- is an excerpt from the code that SBV generates for the call @genFib2 64@. Note
+-- that this code is a constant-time look-up table implementation of fibonacci,
+-- with no run-time overhead. The index can be made arbitrarily large,
+-- naturally. (Note that this function returns @0@ if the index is larger
+-- than 64, as specified by the call to 'select' with default @0@.)
+--
+-- > SWord64 fibLookup(const SWord64 x)
+-- > {
+-- >   const SWord64 s0 = x;
+-- >   static const SWord64 table0[] = {
+-- >       0x0000000000000000ULL, 0x0000000000000001ULL,
+-- >       0x0000000000000001ULL, 0x0000000000000002ULL,
+-- >       0x0000000000000003ULL, 0x0000000000000005ULL,
+-- >       0x0000000000000008ULL, 0x000000000000000dULL,
+-- >       0x0000000000000015ULL, 0x0000000000000022ULL,
+-- >       0x0000000000000037ULL, 0x0000000000000059ULL,
+-- >       0x0000000000000090ULL, 0x00000000000000e9ULL,
+-- >       0x0000000000000179ULL, 0x0000000000000262ULL,
+-- >       0x00000000000003dbULL, 0x000000000000063dULL,
+-- >       0x0000000000000a18ULL, 0x0000000000001055ULL,
+-- >       0x0000000000001a6dULL, 0x0000000000002ac2ULL,
+-- >       0x000000000000452fULL, 0x0000000000006ff1ULL,
+-- >       0x000000000000b520ULL, 0x0000000000012511ULL,
+-- >       0x000000000001da31ULL, 0x000000000002ff42ULL,
+-- >       0x000000000004d973ULL, 0x000000000007d8b5ULL,
+-- >       0x00000000000cb228ULL, 0x0000000000148addULL,
+-- >       0x0000000000213d05ULL, 0x000000000035c7e2ULL,
+-- >       0x00000000005704e7ULL, 0x00000000008cccc9ULL,
+-- >       0x0000000000e3d1b0ULL, 0x0000000001709e79ULL,
+-- >       0x0000000002547029ULL, 0x0000000003c50ea2ULL,
+-- >       0x0000000006197ecbULL, 0x0000000009de8d6dULL,
+-- >       0x000000000ff80c38ULL, 0x0000000019d699a5ULL,
+-- >       0x0000000029cea5ddULL, 0x0000000043a53f82ULL,
+-- >       0x000000006d73e55fULL, 0x00000000b11924e1ULL,
+-- >       0x000000011e8d0a40ULL, 0x00000001cfa62f21ULL,
+-- >       0x00000002ee333961ULL, 0x00000004bdd96882ULL,
+-- >       0x00000007ac0ca1e3ULL, 0x0000000c69e60a65ULL,
+-- >       0x0000001415f2ac48ULL, 0x000000207fd8b6adULL,
+-- >       0x0000003495cb62f5ULL, 0x0000005515a419a2ULL,
+-- >       0x00000089ab6f7c97ULL, 0x000000dec1139639ULL,
+-- >       0x000001686c8312d0ULL, 0x000002472d96a909ULL,
+-- >       0x000003af9a19bbd9ULL, 0x000005f6c7b064e2ULL, 0x000009a661ca20bbULL
+-- >   };
+-- >   const SWord64 s65 = s0 >= 65 ? 0x0000000000000000ULL : table0[s0];
+-- >
+-- >   return s65;
+-- > }
+genFib2 :: Word64 -> IO ()
+genFib2 top = compileToC Nothing "fibLookup" $ do
+        cgPerformRTCs True       -- protect against potential overflow, our table is not big enough
+        x <- cgInput "x"
+        cgReturn $ fib2 top x
diff --git a/Documentation/SBV/Examples/CodeGeneration/GCD.hs b/Documentation/SBV/Examples/CodeGeneration/GCD.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/GCD.hs
@@ -0,0 +1,156 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.GCD
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Computing GCD symbolically, and generating C code for it. This example
+-- illustrates symbolic termination related issues when programming with
+-- SBV, when the termination of a recursive algorithm crucially depends
+-- on the value of a symbolic variable. The technique we use is to statically
+-- enforce termination by using a recursion depth counter.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.GCD where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Tools.CodeGen
+#endif
+
+-----------------------------------------------------------------------------
+-- * Computing GCD
+-----------------------------------------------------------------------------
+
+-- | The symbolic GCD algorithm, over two 8-bit numbers. We define @sgcd a 0@ to
+-- be @a@ for all @a@, which implies @sgcd 0 0 = 0@. Note that this is essentially
+-- Euclid's algorithm, except with a recursion depth counter. We need the depth
+-- counter since the algorithm is not /symbolically terminating/, as we don't have
+-- a means of determining that the second argument (@b@) will eventually reach 0 in a symbolic
+-- context. Hence we stop after 12 iterations. Why 12? We've empirically determined that this
+-- algorithm will recurse at most 12 times for arbitrary 8-bit numbers. Of course, this is
+-- a claim that we shall prove below.
+sgcd :: SWord8 -> SWord8 -> SWord8
+sgcd a b = go a b 12
+  where go :: SWord8 -> SWord8 -> SWord8 -> SWord8
+        go x y c = ite (c .== 0 .|| y .== 0)   -- stop if y is 0, or if we reach the recursion depth
+                       x
+                       (go y y' (c-1))
+          where (_, y') = x `sQuotRem` y
+
+-----------------------------------------------------------------------------
+-- * Verification
+-----------------------------------------------------------------------------
+
+{- $VerificationIntro
+We prove that 'sgcd' does indeed compute the common divisor of the given numbers.
+Our predicate takes @x@, @y@, and @k@. We show that what 'sgcd' returns is indeed a common divisor,
+and it is at least as large as any given @k@, provided @k@ is a common divisor as well.
+-}
+
+-- | We have:
+--
+-- >>> prove sgcdIsCorrect
+-- Q.E.D.
+sgcdIsCorrect :: SWord8 -> SWord8 -> SWord8 -> SBool
+sgcdIsCorrect x y k = ite (y  .== 0)                        -- if y is 0
+                          (k' .== x)                        -- then k' must be x, nothing else to prove by definition
+                          (isCommonDivisor k'  .&&          -- otherwise, k' is a common divisor and
+                          (isCommonDivisor k .=> k' .>= k)) -- if k is a common divisor as well, then k' is at least as large as k
+  where k' = sgcd x y
+        isCommonDivisor a = z1 .== 0 .&& z2 .== 0
+           where (_, z1) = x `sQuotRem` a
+                 (_, z2) = y `sQuotRem` a
+
+-----------------------------------------------------------------------------
+-- * Code generation
+-----------------------------------------------------------------------------
+
+{- $VerificationIntro
+Now that we have proof our 'sgcd' implementation is correct, we can go ahead
+and generate C code for it.
+-}
+
+-- | This call will generate the required C files. The following is the function
+-- body generated for 'sgcd'. (We are not showing the generated header, @Makefile@,
+-- and the driver programs for brevity.) Note that the generated function is
+-- a constant time algorithm for GCD. It is not necessarily fastest, but it will take
+-- precisely the same amount of time for all values of @x@ and @y@.
+--
+-- > /* File: "sgcd.c". Automatically generated by SBV. Do not edit! */
+-- >
+-- > #include <stdio.h>
+-- > #include <stdlib.h>
+-- > #include <inttypes.h>
+-- > #include <stdint.h>
+-- > #include <stdbool.h>
+-- > #include "sgcd.h"
+-- >
+-- > SWord8 sgcd(const SWord8 x, const SWord8 y)
+-- > {
+-- >   const SWord8 s0 = x;
+-- >   const SWord8 s1 = y;
+-- >   const SBool  s3 = s1 == 0;
+-- >   const SWord8 s4 = (s1 == 0) ? s0 : (s0 % s1);
+-- >   const SWord8 s5 = s3 ? s0 : s4;
+-- >   const SBool  s6 = 0 == s5;
+-- >   const SWord8 s7 = (s5 == 0) ? s1 : (s1 % s5);
+-- >   const SWord8 s8 = s6 ? s1 : s7;
+-- >   const SBool  s9 = 0 == s8;
+-- >   const SWord8 s10 = (s8 == 0) ? s5 : (s5 % s8);
+-- >   const SWord8 s11 = s9 ? s5 : s10;
+-- >   const SBool  s12 = 0 == s11;
+-- >   const SWord8 s13 = (s11 == 0) ? s8 : (s8 % s11);
+-- >   const SWord8 s14 = s12 ? s8 : s13;
+-- >   const SBool  s15 = 0 == s14;
+-- >   const SWord8 s16 = (s14 == 0) ? s11 : (s11 % s14);
+-- >   const SWord8 s17 = s15 ? s11 : s16;
+-- >   const SBool  s18 = 0 == s17;
+-- >   const SWord8 s19 = (s17 == 0) ? s14 : (s14 % s17);
+-- >   const SWord8 s20 = s18 ? s14 : s19;
+-- >   const SBool  s21 = 0 == s20;
+-- >   const SWord8 s22 = (s20 == 0) ? s17 : (s17 % s20);
+-- >   const SWord8 s23 = s21 ? s17 : s22;
+-- >   const SBool  s24 = 0 == s23;
+-- >   const SWord8 s25 = (s23 == 0) ? s20 : (s20 % s23);
+-- >   const SWord8 s26 = s24 ? s20 : s25;
+-- >   const SBool  s27 = 0 == s26;
+-- >   const SWord8 s28 = (s26 == 0) ? s23 : (s23 % s26);
+-- >   const SWord8 s29 = s27 ? s23 : s28;
+-- >   const SBool  s30 = 0 == s29;
+-- >   const SWord8 s31 = (s29 == 0) ? s26 : (s26 % s29);
+-- >   const SWord8 s32 = s30 ? s26 : s31;
+-- >   const SBool  s33 = 0 == s32;
+-- >   const SWord8 s34 = (s32 == 0) ? s29 : (s29 % s32);
+-- >   const SWord8 s35 = s33 ? s29 : s34;
+-- >   const SBool  s36 = 0 == s35;
+-- >   const SWord8 s37 = s36 ? s32 : s35;
+-- >   const SWord8 s38 = s33 ? s29 : s37;
+-- >   const SWord8 s39 = s30 ? s26 : s38;
+-- >   const SWord8 s40 = s27 ? s23 : s39;
+-- >   const SWord8 s41 = s24 ? s20 : s40;
+-- >   const SWord8 s42 = s21 ? s17 : s41;
+-- >   const SWord8 s43 = s18 ? s14 : s42;
+-- >   const SWord8 s44 = s15 ? s11 : s43;
+-- >   const SWord8 s45 = s12 ? s8 : s44;
+-- >   const SWord8 s46 = s9 ? s5 : s45;
+-- >   const SWord8 s47 = s6 ? s1 : s46;
+-- >   const SWord8 s48 = s3 ? s0 : s47;
+-- >
+-- >   return s48;
+-- > }
+genGCDInC :: IO ()
+genGCDInC = compileToC Nothing "sgcd" $ do
+                x <- cgInput "x"
+                y <- cgInput "y"
+                cgReturn $ sgcd x y
diff --git a/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs b/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs
@@ -0,0 +1,239 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.PopulationCount
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Computing population-counts (number of set bits) and automatically
+-- generating C code.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.PopulationCount where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-----------------------------------------------------------------------------
+-- * Reference: Slow but /obviously/ correct
+-----------------------------------------------------------------------------
+
+-- | Given a 64-bit quantity, the simplest (and obvious) way to count the
+-- number of bits that are set in it is to simply walk through all the bits
+-- and add 1 to a running count. This is slow, as it requires 64 iterations,
+-- but is simple and easy to convince yourself that it is correct. For instance:
+--
+-- >>> popCountSlow 0x0123456789ABCDEF
+-- 32 :: SWord8
+popCountSlow :: SWord64 -> SWord8
+popCountSlow inp = go inp 0 0
+  where go :: SWord64 -> Int -> SWord8 -> SWord8
+        go _ 64 c = c
+        go x i  c = go (x `shiftR` 1) (i+1) (ite (x .&. 1 .== 1) (c+1) c)
+
+-----------------------------------------------------------------------------
+-- * Faster: Using a look-up table
+-----------------------------------------------------------------------------
+
+-- | Faster version. This is essentially the same algorithm, except we
+-- go 8 bits at a time instead of one by one, by using a precomputed table
+-- of population-count values for each byte. This algorithm /loops/ only
+-- 8 times, and hence is at least 8 times more efficient.
+popCountFast :: SWord64 -> SWord8
+popCountFast inp = go inp 0 0
+  where go :: SWord64 -> Int -> SWord8 -> SWord8
+        go _ 8 c = c
+        go x i c = go (x `shiftR` 8) (i+1) (c + select pop8 0 (x .&. 0xff))
+
+-- | Look-up table, containing population counts for all possible 8-bit
+-- value, from 0 to 255. Note that we do not \"hard-code\" the values, but
+-- merely use the slow version to compute them.
+pop8 :: [SWord8]
+pop8 = map (popCountSlow . literal) [0 .. 255]
+
+-----------------------------------------------------------------------------
+-- * Verification
+-----------------------------------------------------------------------------
+
+{- $VerificationIntro
+We prove that `popCountFast` and `popCountSlow` are functionally equivalent.
+This is essential as we will automatically generate C code from `popCountFast`,
+and we would like to make sure that the fast version is correct with
+respect to the slower reference version.
+-}
+
+-- | States the correctness of faster population-count algorithm, with respect
+-- to the reference slow version. Turns out Z3's default solver is rather slow
+-- for this one, but there's a magic incantation to make it go fast.
+-- See <http://github.com/Z3Prover/z3/issues/1150> for details.
+--
+-- >>> let cmd = "(check-sat-using (then (using-params ackermannize_bv :div0_ackermann_limit 1000000) simplify bit-blast sat))"
+-- >>> proveWith z3{satCmd = cmd} fastPopCountIsCorrect
+-- Q.E.D.
+fastPopCountIsCorrect :: SWord64 -> SBool
+fastPopCountIsCorrect x = popCountFast x .== popCountSlow x
+
+-----------------------------------------------------------------------------
+-- * Code generation
+-----------------------------------------------------------------------------
+
+-- | Not only we can prove that faster version is correct, but we can also automatically
+-- generate C code to compute population-counts for us. This action will generate all the
+-- C files that you will need, including a driver program for test purposes.
+--
+-- Below is the generated header file for `popCountFast`:
+--
+-- >>> genPopCountInC
+-- == BEGIN: "Makefile" ================
+-- # Makefile for popCount. Automatically generated by SBV. Do not edit!
+-- <BLANKLINE>
+-- # include any user-defined .mk file in the current directory.
+-- -include *.mk
+-- <BLANKLINE>
+-- CC?=gcc
+-- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+-- <BLANKLINE>
+-- all: popCount_driver
+-- <BLANKLINE>
+-- popCount.o: popCount.c popCount.h
+-- 	${CC} ${CCFLAGS} -c $< -o $@
+-- <BLANKLINE>
+-- popCount_driver.o: popCount_driver.c
+-- 	${CC} ${CCFLAGS} -c $< -o $@
+-- <BLANKLINE>
+-- popCount_driver: popCount.o popCount_driver.o
+-- 	${CC} ${CCFLAGS} $^ -o $@
+-- <BLANKLINE>
+-- clean:
+-- 	rm -f *.o
+-- <BLANKLINE>
+-- veryclean: clean
+-- 	rm -f popCount_driver
+-- == END: "Makefile" ==================
+-- == BEGIN: "popCount.h" ================
+-- /* Header file for popCount. Automatically generated by SBV. Do not edit! */
+-- <BLANKLINE>
+-- #ifndef __popCount__HEADER_INCLUDED__
+-- #define __popCount__HEADER_INCLUDED__
+-- <BLANKLINE>
+-- #include <stdio.h>
+-- #include <stdlib.h>
+-- #include <inttypes.h>
+-- #include <stdint.h>
+-- #include <stdbool.h>
+-- #include <string.h>
+-- #include <math.h>
+-- <BLANKLINE>
+-- /* The boolean type */
+-- typedef bool SBool;
+-- <BLANKLINE>
+-- /* The float type */
+-- typedef float SFloat;
+-- <BLANKLINE>
+-- /* The double type */
+-- typedef double SDouble;
+-- <BLANKLINE>
+-- /* Unsigned bit-vectors */
+-- typedef uint8_t  SWord8;
+-- typedef uint16_t SWord16;
+-- typedef uint32_t SWord32;
+-- typedef uint64_t SWord64;
+-- <BLANKLINE>
+-- /* Signed bit-vectors */
+-- typedef int8_t  SInt8;
+-- typedef int16_t SInt16;
+-- typedef int32_t SInt32;
+-- typedef int64_t SInt64;
+-- <BLANKLINE>
+-- /* Entry point prototype: */
+-- SWord8 popCount(const SWord64 x);
+-- <BLANKLINE>
+-- #endif /* __popCount__HEADER_INCLUDED__ */
+-- == END: "popCount.h" ==================
+-- == BEGIN: "popCount_driver.c" ================
+-- /* Example driver program for popCount. */
+-- /* Automatically generated by SBV. Edit as you see fit! */
+-- <BLANKLINE>
+-- #include <stdio.h>
+-- #include "popCount.h"
+-- <BLANKLINE>
+-- int main(void)
+-- {
+--   const SWord8 __result = popCount(0x1b02e143e4f0e0e5ULL);
+-- <BLANKLINE>
+--   printf("popCount(0x1b02e143e4f0e0e5ULL) = %"PRIu8"\n", __result);
+-- <BLANKLINE>
+--   return 0;
+-- }
+-- == END: "popCount_driver.c" ==================
+-- == BEGIN: "popCount.c" ================
+-- /* File: "popCount.c". Automatically generated by SBV. Do not edit! */
+-- <BLANKLINE>
+-- #include "popCount.h"
+-- <BLANKLINE>
+-- SWord8 popCount(const SWord64 x)
+-- {
+--   const SWord64 s0 = x;
+--   static const SWord8 table0[] = {
+--       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
+--       3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
+--       3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
+--       2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
+--       3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
+--       5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
+--       2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
+--       4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+--       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
+--       4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
+--       5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
+--       5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+--   };
+--   const SWord64 s11 = s0 & 0x00000000000000ffULL;
+--   const SWord8  s12 = table0[s11];
+--   const SWord64 s14 = s0 >> 8;
+--   const SWord64 s15 = 0x00000000000000ffULL & s14;
+--   const SWord8  s16 = table0[s15];
+--   const SWord8  s17 = s12 + s16;
+--   const SWord64 s18 = s14 >> 8;
+--   const SWord64 s19 = 0x00000000000000ffULL & s18;
+--   const SWord8  s20 = table0[s19];
+--   const SWord8  s21 = s17 + s20;
+--   const SWord64 s22 = s18 >> 8;
+--   const SWord64 s23 = 0x00000000000000ffULL & s22;
+--   const SWord8  s24 = table0[s23];
+--   const SWord8  s25 = s21 + s24;
+--   const SWord64 s26 = s22 >> 8;
+--   const SWord64 s27 = 0x00000000000000ffULL & s26;
+--   const SWord8  s28 = table0[s27];
+--   const SWord8  s29 = s25 + s28;
+--   const SWord64 s30 = s26 >> 8;
+--   const SWord64 s31 = 0x00000000000000ffULL & s30;
+--   const SWord8  s32 = table0[s31];
+--   const SWord8  s33 = s29 + s32;
+--   const SWord64 s34 = s30 >> 8;
+--   const SWord64 s35 = 0x00000000000000ffULL & s34;
+--   const SWord8  s36 = table0[s35];
+--   const SWord8  s37 = s33 + s36;
+--   const SWord64 s38 = s34 >> 8;
+--   const SWord64 s39 = 0x00000000000000ffULL & s38;
+--   const SWord8  s40 = table0[s39];
+--   const SWord8  s41 = s37 + s40;
+-- <BLANKLINE>
+--   return s41;
+-- }
+-- == END: "popCount.c" ==================
+genPopCountInC :: IO ()
+genPopCountInC = compileToC Nothing "popCount" $ do
+        cgSetDriverValues [0x1b02e143e4f0e0e5]  -- remove this line to get a random test value
+        x <- cgInput "x"
+        cgReturn $ popCountFast x
diff --git a/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs b/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs
@@ -0,0 +1,71 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates the use of uninterpreted functions for the purposes of
+-- code generation. This facility is important when we want to take
+-- advantage of native libraries in the target platform, or when we'd
+-- like to hand-generate code for certain functions for various
+-- purposes, such as efficiency, or reliability.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.CodeGeneration.Uninterpreted where
+
+import Data.Maybe (fromMaybe)
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | A definition of shiftLeft that can deal with variable length shifts.
+-- (Note that the ``shiftL`` method from the 'Bits' class requires an 'Int' shift
+-- amount.) Unfortunately, this'll generate rather clumsy C code due to the
+-- use of tables etc., so we uninterpret it for code generation purposes
+-- using the 'cgUninterpret' function.
+shiftLeft :: SWord32 -> SWord32 -> SWord32
+shiftLeft = cgUninterpret "SBV_SHIFTLEFT" cCode hCode
+  where -- the C code we'd like SBV to spit out when generating code. Note that this is
+        -- arbitrary C code. In this case we just used a macro, but it could be a function,
+        -- text that includes files etc. It should essentially bring the name SBV_SHIFTLEFT
+        -- used above into scope when compiled. If no code is needed, one can also just
+        -- provide the empty list for the same effect. Also see 'cgAddDecl', 'cgAddLDFlags',
+        -- and 'cgAddPrototype' functions for further variations.
+        cCode = ["#define SBV_SHIFTLEFT(x, y) ((x) << (y))"]
+        -- the Haskell code we'd like SBV to use when running inside Haskell or when
+        -- translated to SMTLib for verification purposes. This is good old Haskell
+        -- code, as one would typically write.
+        hCode x = select [x * literal (bit b) | b <- [0.. bs x - 1]] (literal 0)
+        bs x = fromMaybe (error "SBV.Example.CodeGeneration.Uninterpreted.shiftLeft: Unexpected non-finite usage!") (bitSizeMaybe x)
+
+-- | Test function that uses shiftLeft defined above. When used as a normal Haskell function
+-- or in verification the definition is fully used, i.e., no uninterpretation happens. To wit,
+-- we have:
+--
+--  >>> tstShiftLeft 3 4 5
+--  224 :: SWord32
+--
+--  >>> prove $ \x y -> tstShiftLeft x y 0 .== x + y
+--  Q.E.D.
+tstShiftLeft ::  SWord32 -> SWord32 -> SWord32 -> SWord32
+tstShiftLeft x y z = x `shiftLeft` z + y `shiftLeft` z
+
+-- | Generate C code for "tstShiftLeft". In this case, SBV will *use* the user given definition
+-- verbatim, instead of generating code for it. (Also see the functions 'cgAddDecl', 'cgAddLDFlags',
+-- and 'cgAddPrototype'.)
+genCCode :: IO ()
+genCCode = compileToC Nothing "tst" $ do
+                [x, y, z] <- cgInputArr 3 "vs"
+                cgReturn $ tstShiftLeft x y z
diff --git a/Documentation/SBV/Examples/Crypto/AES.hs b/Documentation/SBV/Examples/Crypto/AES.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Crypto/AES.hs
@@ -0,0 +1,910 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Crypto.AES
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An implementation of AES (Advanced Encryption Standard), using SBV.
+-- For details on AES, see <http://en.wikipedia.org/wiki/Advanced_Encryption_Standard>.
+--
+-- We do a T-box implementation, which leads to good C code as we can take
+-- advantage of look-up tables. Note that we make virtually no attempt to
+-- optimize our Haskell code. The concern here is not with getting Haskell running
+-- fast at all. The idea is to program the T-Box implementation as naturally and clearly
+-- as possible in Haskell, and have SBV's code-generator generate fast C code automatically.
+-- Therefore, we merely use ordinary Haskell lists as our data-structures, and do not
+-- bother with any unboxing or strictness annotations. Thus, we achieve the separation
+-- of concerns: Correctness via clarity and simplicity and proofs on the Haskell side,
+-- performance by relying on SBV's code generator. If necessary, the generated code
+-- can be FFI'd back into Haskell to complete the loop.
+--
+-- All 3 valid key sizes (128, 192, and 256) as required by the FIPS-197 standard
+-- are supported.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE ParallelListComp #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
+
+module Documentation.SBV.Examples.Crypto.AES where
+
+import Control.Monad (void, when)
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+import Data.SBV.Tools.Polynomial
+
+import Data.List (transpose)
+import Data.Maybe (fromJust)
+
+import Data.Proxy
+
+import Numeric (showHex)
+
+import Test.QuickCheck hiding (verbose)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-----------------------------------------------------------------------------
+-- * Formalizing GF(2^8)
+-----------------------------------------------------------------------------
+
+-- | An element of the Galois Field 2^8, which are essentially polynomials with
+-- maximum degree 7. They are conveniently represented as values between 0 and 255.
+type GF28 = SWord 8
+
+-- | Multiplication in GF(2^8). This is simple polynomial multiplication, followed
+-- by the irreducible polynomial @x^8+x^4+x^3+x^1+1@. We simply use the 'pMult'
+-- function exported by SBV to do the operation.
+gf28Mult :: GF28 -> GF28 -> GF28
+gf28Mult x y = pMult (x, y, [8, 4, 3, 1, 0])
+
+-- | Exponentiation by a constant in GF(2^8). The implementation uses the usual
+-- square-and-multiply trick to speed up the computation.
+gf28Pow :: GF28 -> Int -> GF28
+gf28Pow n = pow
+  where sq x  = x `gf28Mult` x
+        pow 0    = 1
+        pow i
+         | odd i = n `gf28Mult` sq (pow (i `shiftR` 1))
+         | True  = sq (pow (i `shiftR` 1))
+
+-- | Computing inverses in GF(2^8). By the mathematical properties of GF(2^8)
+-- and the particular irreducible polynomial used @x^8+x^5+x^3+x^1+1@, it
+-- turns out that raising to the 254 power gives us the multiplicative inverse.
+-- Of course, we can prove this using SBV:
+--
+-- >>> prove $ \x -> x ./= 0 .=> x `gf28Mult` gf28Inverse x .== 1
+-- Q.E.D.
+--
+-- Note that we exclude @0@ in our theorem, as it does not have a
+-- multiplicative inverse.
+gf28Inverse :: GF28 -> GF28
+gf28Inverse x = x `gf28Pow` 254
+
+-----------------------------------------------------------------------------
+-- * Implementing AES
+-----------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+-- ** Types and basic operations
+-----------------------------------------------------------------------------
+-- | AES state. The state consists of four 32-bit words, each of which is in turn treated
+-- as four GF28's, i.e., 4 bytes. The T-Box implementation keeps the four-bytes together
+-- for efficient representation.
+type State = [SWord 32]
+
+-- | The key, which can be 128, 192, or 256 bits. Represented as a sequence of 32-bit words.
+type Key = [SWord 32]
+
+-- | The key schedule. AES executes in rounds, and it treats first and last round keys slightly
+-- differently than the middle ones. We reflect that choice by being explicit about it in our type.
+-- The length of the middle list of keys depends on the key-size, which in turn determines
+-- the number of rounds.
+type KS = (Key, [Key], Key)
+
+-- | Rotating a state row by a fixed amount to the right.
+rotR :: [GF28] -> Int -> [GF28]
+rotR [a, b, c, d] 1 = [d, a, b, c]
+rotR [a, b, c, d] 2 = [c, d, a, b]
+rotR [a, b, c, d] 3 = [b, c, d, a]
+rotR xs           i = error $ "rotR: Unexpected input: " ++ show (xs, i)
+
+-----------------------------------------------------------------------------
+-- ** The key schedule
+-----------------------------------------------------------------------------
+
+-- | Definition of round-constants, as specified in Section 5.2 of the AES standard.
+roundConstants :: [GF28]
+roundConstants = 0 : [ gf28Pow 2 (k-1) | k <- [1 .. ] ]
+
+-- | The @InvMixColumns@ transformation, as described in Section 5.3.3 of the standard. Note
+-- that this transformation is only used explicitly during key-expansion in the T-Box implementation
+-- of AES.
+invMixColumns :: State -> State
+invMixColumns state = map fromBytes $ transpose $ mmult (map toBytes state)
+ where dot f   = foldr1 xor . zipWith ($) f
+       mmult n = [map (dot r) n | r <- [ [mE, mB, mD, m9]
+                                       , [m9, mE, mB, mD]
+                                       , [mD, m9, mE, mB]
+                                       , [mB, mD, m9, mE]
+                                       ]]
+       -- table-lookup versions of gf28Mult with the constants used in invMixColumns
+       mE = select mETable 0
+       mB = select mBTable 0
+       mD = select mDTable 0
+       m9 = select m9Table 0
+       mETable = map (gf28Mult 0xE . literal) [0..255]
+       mBTable = map (gf28Mult 0xB . literal) [0..255]
+       mDTable = map (gf28Mult 0xD . literal) [0..255]
+       m9Table = map (gf28Mult 0x9 . literal) [0..255]
+
+-- | Key expansion. Starting with the given key, returns an infinite sequence of
+-- words, as described by the AES standard, Section 5.2, Figure 11.
+keyExpansion :: Int -> Key -> [Key]
+keyExpansion nk key = chop4 keys
+   where keys :: [SWord 32]
+         keys = key ++ [nextWord i prev old | i <- [nk ..] | prev <- drop (nk-1) keys | old <- keys]
+
+         nextWord :: Int -> SWord 32 -> SWord 32 -> SWord 32
+         nextWord i prev old
+           | i `mod` nk == 0           = old `xor` subWordRcon (prev `rotateL` 8) (roundConstants !! (i `div` nk))
+           | i `mod` nk == 4 && nk > 6 = old `xor` subWordRcon prev 0
+           | True                      = old `xor` prev
+
+         subWordRcon :: SWord 32 -> GF28 -> SWord 32
+         subWordRcon w rc = fromBytes [a `xor` rc, b, c, d]
+            where [a, b, c, d] = map sbox $ toBytes w
+
+-----------------------------------------------------------------------------
+-- ** The S-box transformation
+-----------------------------------------------------------------------------
+
+-- | The values of the AES S-box table. Note that we describe the S-box programmatically
+-- using the mathematical construction given in Section 5.1.1 of the standard. However,
+-- the code-generation will turn this into a mere look-up table, as it is just a
+-- constant table, all computation being done at \"compile-time\".
+sboxTable :: [GF28]
+sboxTable = [xformByte (gf28Inverse (literal b)) | b <- [0 .. 255]]
+  where xformByte :: GF28 -> GF28
+        xformByte b = foldr xor 0x63 [b `rotateR` i | i <- [0, 4, 5, 6, 7]]
+
+-- | The sbox transformation. We simply select from the sbox table. Note that we
+-- are obliged to give a default value (here @0@) to be used if the index is out-of-bounds
+-- as required by SBV's 'select' function. However, that will never happen since
+-- the table has all 256 elements in it.
+sbox :: GF28 -> GF28
+sbox = select sboxTable 0
+
+-----------------------------------------------------------------------------
+-- ** The inverse S-box transformation
+-----------------------------------------------------------------------------
+
+-- | The values of the inverse S-box table. Again, the construction is programmatic.
+unSBoxTable :: [GF28]
+unSBoxTable = [gf28Inverse (xformByte (literal b)) | b <- [0 .. 255]]
+  where xformByte :: GF28 -> GF28
+        xformByte b = foldr xor 0x05 [b `rotateR` i | i <- [2, 5, 7]]
+
+-- | The inverse s-box transformation.
+unSBox :: GF28 -> GF28
+unSBox = select unSBoxTable 0
+
+-- | Prove that the 'sbox' and 'unSBox' are inverses. We have:
+--
+-- >>> prove sboxInverseCorrect
+-- Q.E.D.
+--
+sboxInverseCorrect :: GF28 -> SBool
+sboxInverseCorrect x = unSBox (sbox x) .== x .&& sbox (unSBox x) .== x
+
+-----------------------------------------------------------------------------
+-- ** AddRoundKey transformation
+-----------------------------------------------------------------------------
+
+-- | Adding the round-key to the current state. We simply exploit the fact
+-- that addition is just xor in implementing this transformation.
+addRoundKey :: Key -> State -> State
+addRoundKey = zipWith xor
+
+-----------------------------------------------------------------------------
+-- ** Tables for T-Box encryption
+-----------------------------------------------------------------------------
+
+-- | T-box table generation function for encryption
+t0Func :: GF28 -> [GF28]
+t0Func a = [s `gf28Mult` 2, s, s, s `gf28Mult` 3] where s = sbox a
+
+-- | First look-up table used in encryption
+t0 :: GF28 -> SWord 32
+t0 = select t0Table 0 where t0Table = [fromBytes (t0Func a)          | a <- map literal [0..255]]
+
+-- | Second look-up table used in encryption
+t1 :: GF28 -> SWord 32
+t1 = select t1Table 0 where t1Table = [fromBytes (t0Func a `rotR` 1) | a <- map literal [0..255]]
+
+-- | Third look-up table used in encryption
+t2 :: GF28 -> SWord 32
+t2 = select t2Table 0 where t2Table = [fromBytes (t0Func a `rotR` 2) | a <- map literal [0..255]]
+
+-- | Fourth look-up table used in encryption
+t3 :: GF28 -> SWord 32
+t3 = select t3Table 0 where t3Table = [fromBytes (t0Func a `rotR` 3) | a <- map literal [0..255]]
+
+-----------------------------------------------------------------------------
+-- ** Tables for T-Box decryption
+-----------------------------------------------------------------------------
+
+-- | T-box table generating function for decryption
+u0Func :: GF28 -> [GF28]
+u0Func a = [s `gf28Mult` 0xE, s `gf28Mult` 0x9, s `gf28Mult` 0xD, s `gf28Mult` 0xB] where s = unSBox a
+
+-- | First look-up table used in decryption
+u0 :: GF28 -> SWord 32
+u0 = select t0Table 0 where t0Table = [fromBytes (u0Func a)          | a <- map literal [0..255]]
+
+-- | Second look-up table used in decryption
+u1 :: GF28 -> SWord 32
+u1 = select t1Table 0 where t1Table = [fromBytes (u0Func a `rotR` 1) | a <- map literal [0..255]]
+
+-- | Third look-up table used in decryption
+u2 :: GF28 -> SWord 32
+u2 = select t2Table 0 where t2Table = [fromBytes (u0Func a `rotR` 2) | a <- map literal [0..255]]
+
+-- | Fourth look-up table used in decryption
+u3 :: GF28 -> SWord 32
+u3 = select t3Table 0 where t3Table = [fromBytes (u0Func a `rotR` 3) | a <- map literal [0..255]]
+
+-----------------------------------------------------------------------------
+-- ** AES rounds
+-----------------------------------------------------------------------------
+
+-- | Generic round function. Given the function to perform one round, a key-schedule,
+-- and a starting state, it performs the AES rounds.
+doRounds :: (Bool -> State -> Key -> State) -> KS -> State -> State
+doRounds rnd (ikey, rkeys, fkey) sIn = rnd True (last rs) fkey
+  where s0 = ikey `addRoundKey` sIn
+        rs = s0 : [rnd False s k | s <- rs | k <- rkeys ]
+
+-- | One encryption round. The first argument indicates whether this is the final round
+-- or not, in which case the construction is slightly different.
+aesRound :: Bool -> State -> Key -> State
+aesRound isFinal s key = d `addRoundKey` key
+  where d = map (f isFinal) [0..3]
+        a = map toBytes s
+        f True j = fromBytes [ sbox (a !! ((j+0) `mod` 4) !! 0)
+                             , sbox (a !! ((j+1) `mod` 4) !! 1)
+                             , sbox (a !! ((j+2) `mod` 4) !! 2)
+                             , sbox (a !! ((j+3) `mod` 4) !! 3)
+                             ]
+        f False j = e0 `xor` e1 `xor` e2 `xor` e3
+              where e0 = t0 (a !! ((j+0) `mod` 4) !! 0)
+                    e1 = t1 (a !! ((j+1) `mod` 4) !! 1)
+                    e2 = t2 (a !! ((j+2) `mod` 4) !! 2)
+                    e3 = t3 (a !! ((j+3) `mod` 4) !! 3)
+
+-- | One decryption round. Similar to the encryption round, the first argument
+-- indicates whether this is the final round or not.
+aesInvRound :: Bool -> State -> Key -> State
+aesInvRound isFinal s key = d `addRoundKey` key
+  where d = map (f isFinal) [0..3]
+        a = map toBytes s
+        f True j = fromBytes [ unSBox (a !! ((j+0) `mod` 4) !! 0)
+                             , unSBox (a !! ((j+3) `mod` 4) !! 1)
+                             , unSBox (a !! ((j+2) `mod` 4) !! 2)
+                             , unSBox (a !! ((j+1) `mod` 4) !! 3)
+                             ]
+        f False j = e0 `xor` e1 `xor` e2 `xor` e3
+              where e0 = u0 (a !! ((j+0) `mod` 4) !! 0)
+                    e1 = u1 (a !! ((j+3) `mod` 4) !! 1)
+                    e2 = u2 (a !! ((j+2) `mod` 4) !! 2)
+                    e3 = u3 (a !! ((j+1) `mod` 4) !! 3)
+
+-----------------------------------------------------------------------------
+-- * AES API
+-----------------------------------------------------------------------------
+
+-- | Key schedule. Given a 128, 192, or 256 bit key, expand it to get key-schedules
+-- for encryption and decryption. The key is given as a sequence of 32-bit words.
+-- (4 elements for 128-bits, 6 for 192, and 8 for 256.) Compare this function to 'aesInvKeySchedule'
+-- which can calculate the key-expansion for decryption on the fly, as opposed to calculating
+-- the forward key-expansion first.
+aesKeySchedule :: Key -> (KS, KS)
+aesKeySchedule key
+  | nk `elem` [4, 6, 8]
+  = (encKS, decKS)
+  | True
+  = error "aesKeySchedule: Invalid key size"
+  where nk = length key
+        nr = nk + 6
+        encKS@(f, m, l) = (head rKeys, take (nr-1) (tail rKeys), rKeys !! nr)
+        decKS = (l, map invMixColumns (reverse m), f)
+        rKeys = keyExpansion nk key
+
+-- | Block encryption. The first argument is the plain-text, which must have
+-- precisely 4 elements, for a total of 128-bits of input. The second
+-- argument is the key-schedule to be used, obtained by a call to 'aesKeySchedule'.
+-- The output will always have 4 32-bit words, which is the cipher-text.
+aesEncrypt :: [SWord 32] -> KS -> [SWord 32]
+aesEncrypt pt encKS
+  | length pt == 4
+  = doRounds aesRound encKS pt
+  | True
+  = error "aesEncrypt: Invalid plain-text size"
+
+-- | Block decryption. The arguments are the same as in 'aesEncrypt', except
+-- the first argument is the cipher-text and the output is the corresponding
+-- plain-text.
+aesDecrypt :: [SWord 32] -> KS -> [SWord 32]
+aesDecrypt ct decKS
+  | length ct == 4
+  = doRounds aesInvRound decKS ct
+  | True
+  = error "aesDecrypt: Invalid cipher-text size"
+
+-----------------------------------------------------------------------------
+-- * On-the-fly decryption
+-- ${ontheflyintro}
+-----------------------------------------------------------------------------
+{- $ontheflyintro
+   While regular encryption can be fused with key-generation, the standard method of AES
+   decryption has to perform the key-expansion before decryption starts. This can be undesirable
+   as it necessarily serializes the action of key-expansion before decryption. An
+   alternative is to do on-the-fly decryption: We can expand the key in reverse, and thus
+   need not save the key-schedule. One downside of this approach, however, is that we need
+   to keep the "unwound" key: That is, instead of the common key used for encryption and
+   decryption, we need to hold on to the final value of key-expansion, so it can be run
+   in reverse. In this section, we implement on-the-fly decryption using this idea.
+-}
+
+-- | Inverse key expansion. Starting from the final round key, unwinds key generation operation
+-- to construct keys for the previous rounds. Used in on-the-fly decryption.
+invKeyExpansion :: Int -> Key -> [Key]
+invKeyExpansion nk rkey = map reverse (chop4 keys)
+   where keys :: [SWord 32]
+         keys = rkey ++ [invNextWord i prev old | i <- reverse [0 .. remaining - 1] | prev <- drop 1 keys | old <- keys]
+
+         totalWords = 4 * (nk + 6 + 1)
+         remaining  = totalWords - nk
+
+         invNextWord :: Int -> SWord 32 -> SWord 32 -> SWord 32
+         invNextWord i prev old
+           | i `mod` nk == 0           = old `xor` subWordRcon (prev `rotateL` 8) (roundConstants !! (1 + i `div` nk))
+           | i `mod` nk == 4 && nk > 6 = old `xor` subWordRcon prev 0
+           | True                      = old `xor` prev
+
+         subWordRcon :: SWord 32 -> GF28 -> SWord 32
+         subWordRcon w rc = fromBytes [a `xor` rc, b, c, d]
+            where [a, b, c, d] = map sbox $ toBytes w
+
+-- | AES inverse key schedule. Starting from the last-round key, construct the sequence of keys
+-- that can be used for doing on-the-fly decryption. Compare this function to 'aesKeySchedule' which
+-- returns both encryption and decryption schedules: In this case, we don't calculate the encryption
+-- sequence, hence we can fuse this function with the decryption operation.
+aesInvKeySchedule :: Key -> KS
+aesInvKeySchedule key
+  | nk `elem` [4, 6, 8]
+  = decKS
+  | True
+  = error "aesInvKeySchedule: Invalid key size"
+  where nk = length key
+        nr = nk + 6
+        decKS = (head rKeys, take (nr-1) (tail rKeys), rKeys !! nr)
+        rKeys = invKeyExpansion nk key
+
+-- | Block decryption, starting from the unwound key. That is, start from the final key.
+-- Also; we don't use the T-box implementation. Just pure AES inverse cipher.
+aesDecryptUnwoundKey :: [SWord 32] -> KS -> [SWord 32]
+aesDecryptUnwoundKey ct decKS
+  | length ct == 4
+  = doRounds aesInvRoundRegular decKS ct
+  | True
+  = error "aesDecrypt: Invalid cipher-text size"
+  where aesInvRoundRegular isFinal s key = u
+          where u :: State
+                u = map (f isFinal) [0 .. 3]
+                  where a   = map toBytes s
+                        kbs = map toBytes key
+                        f True j = fromBytes [ unSBox (a !! ((j+0) `mod` 4) !! 0)
+                                             , unSBox (a !! ((j+3) `mod` 4) !! 1)
+                                             , unSBox (a !! ((j+2) `mod` 4) !! 2)
+                                             , unSBox (a !! ((j+1) `mod` 4) !! 3)
+                                             ] `xor` (key !! j)
+                        f False j = e0 `xor` e1 `xor` e2 `xor` e3
+                              where e0 = otfU0 $ unSBox (a !! ((j+0) `mod` 4) !! 0) `xor` (kbs !! j !! 0)
+                                    e1 = otfU1 $ unSBox (a !! ((j+3) `mod` 4) !! 1) `xor` (kbs !! j !! 1)
+                                    e2 = otfU2 $ unSBox (a !! ((j+2) `mod` 4) !! 2) `xor` (kbs !! j !! 2)
+                                    e3 = otfU3 $ unSBox (a !! ((j+1) `mod` 4) !! 3) `xor` (kbs !! j !! 3)
+
+                otfU0Func b = [b `gf28Mult` 0xE, b `gf28Mult` 0x9, b `gf28Mult` 0xD, b `gf28Mult` 0xB]
+                otfU0 = select t0Table 0 where t0Table = [fromBytes (otfU0Func a)          | a <- map literal [0..255]]
+                otfU1 = select t1Table 0 where t1Table = [fromBytes (otfU0Func a `rotR` 1) | a <- map literal [0..255]]
+                otfU2 = select t2Table 0 where t2Table = [fromBytes (otfU0Func a `rotR` 2) | a <- map literal [0..255]]
+                otfU3 = select t3Table 0 where t3Table = [fromBytes (otfU0Func a `rotR` 3) | a <- map literal [0..255]]
+
+-----------------------------------------------------------------------------
+-- * Test vectors
+-----------------------------------------------------------------------------
+
+-- | Common plain text for test vectors
+commonPT :: [SWord 32]
+commonPT = [0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff]
+
+-- | Key for 128-bit encryption test
+aes128Key :: Key
+aes128Key = [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]
+
+-- | Key for 192-bit encryption test
+aes192Key :: Key
+aes192Key = aes128Key ++ [0x10111213, 0x14151617]
+
+-- | Key for 256-bit encryption test
+aes256Key :: Key
+aes256Key = aes192Key ++ [0x18191a1b, 0x1c1d1e1f]
+
+-- | Expected cipher-text for 128-bit encryption
+aes128CT :: [SWord 32]
+aes128CT = [0x69c4e0d8, 0x6a7b0430, 0xd8cdb780, 0x70b4c55a]
+
+-- | Expected cipher-text for 192-bit encryption
+aes192CT :: [SWord 32]
+aes192CT = [0xdda97ca4, 0x864cdfe0, 0x6eaf70a0, 0xec0d7191]
+
+-- | Expected cipher-text for 256-bit encryption
+aes256CT :: [SWord 32]
+aes256CT = [0x8ea2b7ca, 0x516745bf, 0xeafc4990, 0x4b496089]
+
+-- | Calculate the 128-bit final-round key from on-the-fly decryption key schedule
+aes128InvKey :: Key
+aes128InvKey = extractFinalKey aes128Key
+
+-- | Calculate the 192-bit final-round key from on-the-fly decryption key schedule
+aes192InvKey :: Key
+aes192InvKey = extractFinalKey aes192Key
+
+-- | Calculate the 192-bit final-round key from on-the-fly decryption key schedule. Compare this
+-- to 'aes192InvKey': Typically we just need the final 6-blocks, but it is advantageous to have
+-- the entire last 8-blocks even for 192-bit keys. That is,  e store the final 256-bits of key-expansion
+-- for speed purposes for both 192 and 256 bit versions. (But only the final 128 bits for the 128-bit version.)
+aes192InvKeyExtended :: Key
+aes192InvKeyExtended = extractFinalKeyExtended aes192Key
+
+-- | Calculate the 256-bit final-round key from on-the-fly decryption key schedule
+aes256InvKey :: Key
+aes256InvKey = extractFinalKey aes256Key
+
+-- | Extract the final key for on-the-fly decryption. This will extract exactly the number of blocks we need.
+extractFinalKey :: [SWord 32] -> [SWord 32]
+extractFinalKey initKey = take nk (extractFinalKeyExtended initKey)
+  where nk = length initKey
+
+-- | Extract the extended key for on-the-fly decryption. This will extract 4-blocks for 128-bit decryption,
+-- but 256 bit for both 192 and 256-bit variants
+extractFinalKeyExtended :: [SWord 32] -> [SWord 32]
+extractFinalKeyExtended initKey = take feed (concatMap reverse (chop4 (take feed roundKeys)))
+  where nk             = length initKey
+        feed | nk == 4 = 4
+             | True    = 8
+
+        ((f, m, l), _) = aesKeySchedule initKey
+        roundKeys      = l ++ concat (reverse m) ++ f
+
+-----------------------------------------------------------------------------
+-- ** 128-bit enc/dec test
+-----------------------------------------------------------------------------
+
+-- | 128-bit encryption test, from Appendix C.1 of the AES standard:
+--
+-- >>> map hex8 t128Enc
+-- ["69c4e0d8","6a7b0430","d8cdb780","70b4c55a"]
+t128Enc :: [SWord 32]
+t128Enc = aesEncrypt commonPT ks
+  where (ks, _) = aesKeySchedule aes128Key
+
+-- | 128-bit decryption test, from Appendix C.1 of the AES standard:
+--
+-- >>> map hex8 t128Dec
+-- ["00112233","44556677","8899aabb","ccddeeff"]
+t128Dec :: [SWord 32]
+t128Dec = aesDecrypt aes128CT ks
+  where (_, ks) = aesKeySchedule aes128Key
+
+-----------------------------------------------------------------------------
+-- ** 192-bit enc/dec test
+-----------------------------------------------------------------------------
+
+-- | 192-bit encryption test, from Appendix C.2 of the AES standard:
+--
+-- >>> map hex8 t192Enc
+-- ["dda97ca4","864cdfe0","6eaf70a0","ec0d7191"]
+t192Enc :: [SWord 32]
+t192Enc = aesEncrypt commonPT ks
+  where (ks, _) = aesKeySchedule aes192Key
+
+-- | 192-bit decryption test, from Appendix C.2 of the AES standard:
+--
+-- >>> map hex8 t192Dec
+-- ["00112233","44556677","8899aabb","ccddeeff"]
+--
+t192Dec :: [SWord 32]
+t192Dec = aesDecrypt aes192CT ks
+  where (_, ks) = aesKeySchedule aes192Key
+
+-----------------------------------------------------------------------------
+-- ** 256-bit enc/dec test
+-----------------------------------------------------------------------------
+
+-- | 256-bit encryption, from Appendix C.3 of the AES standard:
+--
+-- >>> map hex8 t256Enc
+-- ["8ea2b7ca","516745bf","eafc4990","4b496089"]
+t256Enc :: [SWord 32]
+t256Enc = aesEncrypt commonPT ks
+  where (ks, _) = aesKeySchedule aes256Key
+
+-- | 256-bit decryption, from Appendix C.3 of the AES standard:
+--
+-- >>> map hex8 t256Dec
+-- ["00112233","44556677","8899aabb","ccddeeff"]
+t256Dec :: [SWord 32]
+t256Dec = aesDecrypt aes256CT ks
+  where (_, ks) = aesKeySchedule aes256Key
+
+-- | Various tests for round-trip properties. We have:
+--
+-- >>> runAESTests False
+-- GOOD: Key generation AES128
+-- GOOD: Key generation AES192
+-- GOOD: Key generation AES256
+-- GOOD: Encryption     AES128
+-- GOOD: Decryption     AES128
+-- GOOD: Decryption-OTF AES128
+-- GOOD: Encryption     AES192
+-- GOOD: Decryption     AES192
+-- GOOD: Decryption-OTF AES192
+-- GOOD: Encryption     AES256
+-- GOOD: Decryption     AES256
+-- GOOD: Decryption-OTF AES256
+runAESTests :: Bool -> IO ()
+runAESTests runQC = do
+                 testInvKeyExpansion
+
+                 check "AES128" aes128Key aes128InvKey aes128CT
+                 check "AES192" aes192Key aes192InvKey aes192CT
+                 check "AES256" aes256Key aes256InvKey aes256CT
+
+                 -- Quick-check tests are rather slow. So only run when requested.
+                 when runQC $ do
+                   putStrLn "Quick-check AES128 roundtrip" >> quickCheck roundTrip128
+                   putStrLn "Quick-check AES192 roundtrip" >> quickCheck roundTrip192
+                   putStrLn "Quick-check AES256 roundtrip" >> quickCheck roundTrip256
+
+  where check :: String -> Key -> Key -> [SWord 32] -> IO ()
+        check what key invKey ctExpected = do eq ("Encryption     " ++ what) ctExpected ctGot
+                                              eq ("Decryption     " ++ what) commonPT   ptGot
+                                              eq ("Decryption-OTF " ++ what) commonPT   ptGotInv
+           where (encKS, decKS) = aesKeySchedule key
+                 ctGot          = aesEncrypt           commonPT   encKS
+                 ptGot          = aesDecrypt           ctExpected decKS
+                 ptGotInv       = aesDecryptUnwoundKey ctExpected (aesInvKeySchedule invKey)
+
+                 eq tag expected got
+                   | length expected /= length got
+                   = error $ unlines [ "BAD!: " ++ tag
+                                     , "Comparing different sized lists:"
+                                     , "Expected: " ++ show expected
+                                     , "Got     : " ++ show got
+                                     ]
+                   | map extract expected == map extract got
+                   = putStrLn $ "GOOD: " ++ tag
+                   | True
+                   = error $ unlines [ "BAD!: " ++ tag
+                                     , "Expected: " ++ unwords (map hex8 expected)
+                                     , "Got     : " ++ unwords (map hex8 got)
+                                     ]
+                  where extract :: SWord 32 -> Integer
+                        extract = fromIntegral . fromJust . unliteral
+
+        testInvKeyExpansion :: IO ()
+        testInvKeyExpansion = do goTestInvKey "128" aes128Key
+                                 goTestInvKey "192" aes192Key
+                                 goTestInvKey "256" aes256Key
+        goTestInvKey what k = do
+          let nk = length k
+              nr = nk + 6
+
+              feed = case nk of
+                       4 -> 4
+                       _ -> 8
+
+              ((f, m, l), _) = aesKeySchedule k
+              required       = l ++ concat (reverse m) ++ f
+              invKeySchedule = take (nr+1) $ invKeyExpansion nk (take nk (concatMap reverse (chop4 (take feed required))))
+              obtained       = concat invKeySchedule
+
+              expected = map (fromJust . unliteral) required
+              result   = map (fromJust . unliteral) obtained
+
+              sh i a b
+               | a == b = pad ++ show i ++ " " ++ disp a
+               | True   = pad ++ show i ++ " " ++ disp a ++ " |vs| " ++ disp b
+               where pad = if i < 10 then " " else ""
+
+              disp = unwords . map (hex8 . literal)
+
+              lexpected = length expected
+              lresult   = length result
+
+          when (lexpected /= lresult) $
+             error $ what ++ ": BAD! Mismatching lengths: " ++ show (lexpected, lresult)
+
+          let debugging = False
+
+          if expected == result
+             then if debugging
+                     then putStrLn $ unlines $ ("Size " ++ what ++ ": Good") : zipWith3 sh [(0::Int)..] (chop4 expected) (chop4 result)
+                     else putStrLn $ "GOOD: Key generation AES" ++ what
+             else error    $ unlines $ ("Size " ++ what ++ ": BAD!") : zipWith3 sh [(0::Int)..] (chop4 expected) (chop4 result)
+
+        roundTrip128 (i0, i1, i2, i3) (k0, k1, k2, k3)                 = roundTrip [i0, i1, i2, i3] [k0, k1, k2, k3]
+        roundTrip192 (i0, i1, i2, i3) (k0, k1, k2, k3, k4, k5)         = roundTrip [i0, i1, i2, i3] [k0, k1, k2, k3, k4, k5]
+        roundTrip256 (i0, i1, i2, i3) (k0, k1, k2, k3, k4, k5, k6, k7) = roundTrip [i0, i1, i2, i3] [k0, k1, k2, k3, k4, k5, k6, k7]
+
+        roundTrip :: [SWord32] -> [SWord32] -> SBool
+        roundTrip ptIn keyIn = pt .== pt' .&& pt .== pt''
+           where pt  = map toSized ptIn
+                 key = map toSized keyIn
+
+                 (encKS, decKS) = aesKeySchedule key
+                 ct   = aesEncrypt pt encKS
+                 pt'  = aesDecrypt ct decKS
+                 pt'' = aesDecryptUnwoundKey ct (aesInvKeySchedule (extractFinalKey key))
+
+-----------------------------------------------------------------------------
+-- * Verification
+-- ${verifIntro}
+-----------------------------------------------------------------------------
+{- $verifIntro
+  While SMT based technologies can prove correct many small properties fairly quickly, it would
+  be naive for them to automatically verify that our AES implementation is correct. (By correct,
+  we mean decryption followed by encryption yielding the same result.) However, we can state
+  this property precisely using SBV, and use quick-check to gain some confidence.
+-}
+
+-- | Correctness theorem for 128-bit AES. Ideally, we would run:
+--
+-- @
+--   prove aes128IsCorrect
+-- @
+--
+-- to get a proof automatically. Unfortunately, while SBV will successfully generate the proof
+-- obligation for this theorem and ship it to the SMT solver, it would be naive to expect the SMT-solver
+-- to finish that proof in any reasonable time with the currently available SMT solving technologies.
+-- Instead, we can issue:
+--
+-- @
+--   quickCheck aes128IsCorrect
+-- @
+--
+-- and get some degree of confidence in our code. Similar predicates can be easily constructed for 192, and
+-- 256 bit cases as well.
+aes128IsCorrect :: (SWord 32, SWord 32, SWord 32, SWord 32)  -- ^ plain-text words
+                -> (SWord 32, SWord 32, SWord 32, SWord 32)  -- ^ key-words
+                -> SBool                                     -- ^ True if round-trip gives us plain-text back
+aes128IsCorrect (i0, i1, i2, i3) (k0, k1, k2, k3) = pt .== pt'
+   where pt  = [i0, i1, i2, i3]
+         key = [k0, k1, k2, k3]
+         (encKS, decKS) = aesKeySchedule key
+         ct  = aesEncrypt pt encKS
+         pt' = aesDecrypt ct decKS
+
+-----------------------------------------------------------------------------
+-- * Block encryption at full size
+-----------------------------------------------------------------------------
+
+-- | 128-bit encryption, that takes 128-bit values, instead of chunks. We have:
+--
+-- >>> hex8 $ aes128Enc 0x000102030405060708090a0b0c0d0e0f 0x00112233445566778899aabbccddeeff
+-- "69c4e0d86a7b0430d8cdb78070b4c55a"
+--
+-- You can also render this function as a stand-alone function using:
+--
+-- @
+--   sbv2smt (smtFunction "aes128Enc" aes128Enc)
+-- @
+aes128Enc :: SWord 128 -> SWord 128 -> SWord 128
+aes128Enc key pt = from32 $ aesEncrypt (to32 pt) ks
+  where to32 :: SWord 128 -> [SWord 32]
+        to32 x = [ bvExtract (Proxy @127) (Proxy @96) x
+                 , bvExtract (Proxy  @95) (Proxy @64) x
+                 , bvExtract (Proxy  @63) (Proxy @32) x
+                 , bvExtract (Proxy  @31) (Proxy  @0) x
+                 ]
+
+        from32 :: [SWord 32] -> SWord 128
+        from32 [a, b, c, d] = a # b # c # d
+        from32 _ = error "nope"
+
+        (ks, _)  = aesKeySchedule (to32 key)
+
+-----------------------------------------------------------------------------
+-- * Code generation
+-- ${codeGenIntro}
+-----------------------------------------------------------------------------
+{- $codeGenIntro
+   We have emphasized that our T-Box implementation in Haskell was guided by clarity and correctness, not
+   performance. Indeed, our implementation is hardly the fastest AES implementation in Haskell. However,
+   we can use it to automatically generate straight-line C-code that can run fairly fast.
+
+   For the purposes of illustration, we only show here how to generate code for a 128-bit AES block-encrypt
+   function, that takes 8 32-bit words as an argument. The first 4 are the 128-bit input, and the final
+   four are the 128-bit key. The impact of this is that the generated function would expand the key for
+   each block of encryption, a needless task unless we change the key in every block. In a more serious application,
+   we would instead generate code for both the 'aesKeySchedule' and the 'aesEncrypt' functions, thus reusing the
+   key-schedule over many applications of the encryption call. (Unfortunately doing this is rather cumbersome right
+   now, since Haskell does not support fixed-size lists.)
+-}
+
+-- | Code generation for 128-bit AES encryption.
+--
+-- The following sample from the generated code-lines show how T-Boxes are rendered as C arrays:
+--
+-- @
+--   static const SWord32 table1[] = {
+--       0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+--       0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+--       0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+--       0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+--       ...
+--       }
+-- @
+--
+-- The generated program has 5 tables (one sbox table, and 4-Tboxes), all converted to fast C arrays. Here
+-- is a sample of the generated straightline C-code:
+--
+-- @
+--   const SWord8  s1915 = (SWord8) s1912;
+--   const SWord8  s1916 = table0[s1915];
+--   const SWord16 s1917 = (((SWord16) s1914) << 8) | ((SWord16) s1916);
+--   const SWord32 s1918 = (((SWord32) s1911) << 16) | ((SWord32) s1917);
+--   const SWord32 s1919 = s1844 ^ s1918;
+--   const SWord32 s1920 = s1903 ^ s1919;
+-- @
+--
+-- The GNU C-compiler does a fine job of optimizing this straightline code to generate a fairly efficient C implementation.
+cgAES128BlockEncrypt :: IO ()
+cgAES128BlockEncrypt = compileToC Nothing "aes128BlockEncrypt" $ do
+        pt  <- cgInputArr 4 "pt"        -- plain-text as an array of 4 Word32's
+        key <- cgInputArr 4 "key"       -- key as an array of 4 Word32s
+
+        -- Use the test values from Appendix C.1 of the AES standard as the driver values
+        cgSetDriverValues $ map (fromIntegral . fromJust . unliteral) $ commonPT ++ aes128Key
+
+        let (encKs, _) = aesKeySchedule key
+        cgOutputArr "ct" $ aesEncrypt pt encKs
+
+-----------------------------------------------------------------------------
+-- * C-library generation
+-- ${libraryIntro}
+-----------------------------------------------------------------------------
+{- $libraryIntro
+   The 'cgAES128BlockEncrypt' example shows how to generate code for 128-bit AES encryption. As the generated
+   function performs encryption on a given block, it performs key expansion as necessary. However, this is
+   not quite practical: We would like to expand the key only once, and encrypt the stream of plain-text blocks using
+   the same expanded key (potentially using some crypto-mode), until we decide to change the key. In this
+   section, we show how to use SBV to instead generate a library of functions that can be used in such a scenario.
+   The generated library is a typical @.a@ archive, that can be linked using the C-compiler as usual.
+-}
+
+-- | Components of the AES implementation that the library is generated from. For each case, we provide
+-- the driver values from the AES test-vectors.
+aesLibComponents :: Int -> [(String, [Integer], SBVCodeGen ())]
+aesLibComponents sz = [ ("aes" ++ show sz ++ "KeySchedule",    keyDriverVals,    keySchedule)
+                      , ("aes" ++ show sz ++ "BlockEncrypt",   encDriverVals,    enc)
+                      , ("aes" ++ show sz ++ "BlockDecrypt",   decDriverVals,    dec)
+                      , ("aes" ++ show sz ++ "InvKeySchedule", invKeyDriverVals, invKeySchedule)
+                      , ("aes" ++ show sz ++ "OTFDecrypt",     invDecDriverVals, otfDec)
+                      ]
+  where badSize = error $ "aesLibComponents: Size must be one of 128, 192, or 256; received: " ++ show sz
+
+        -- key-schedule
+        nk
+         | sz == 128 = 4
+         | sz == 192 = 6
+         | sz == 256 = 8
+         | True      = badSize
+
+        -- We get 4*(nr+1) keys, where nr = nk + 6
+        nr = nk + 6
+        xk = 4 * (nr + 1)
+
+        (keyDriverVals, invKeyDriverVals, encDriverVals, decDriverVals, invDecDriverVals)
+           | sz == 128 = (keyDriver aes128Key, keyDriver aes128InvKey, encDriver commonPT aes128Key, decDriver aes128CT aes128Key, invDecDriver aes128CT aes128InvKey)
+           | sz == 192 = (keyDriver aes192Key, keyDriver aes192InvKey, encDriver commonPT aes192Key, decDriver aes192CT aes192Key, invDecDriver aes192CT aes192InvKey)
+           | sz == 256 = (keyDriver aes256Key, keyDriver aes256InvKey, encDriver commonPT aes256Key, decDriver aes256CT aes256Key, invDecDriver aes256CT aes256InvKey)
+           | True      = badSize
+           where keyDriver       key = map cvt $ concatMap reverse (chop4 key)
+                 encDriver    pt key = map cvt $ pt ++ flatten (fst (aesKeySchedule    key))
+                 decDriver    ct key = map cvt $ ct ++ flatten (snd (aesKeySchedule    key))
+                 invDecDriver ct key = map cvt $ ct ++ flatten      (aesInvKeySchedule key)
+
+                 flatten (f, mid, l) = f ++ concat mid ++ l
+                 cvt = fromIntegral . fromJust . unliteral
+
+        keySchedule = do key <- cgInputArr nk "key"     -- key
+                         let (encKS, decKS) = aesKeySchedule key
+                         cgOutputArr "encKS" (ksToXKey encKS)
+                         cgOutputArr "decKS" (ksToXKey decKS)
+
+        invKeySchedule = do key <- cgInputArr nk "key"     -- key
+                            let decKS = aesInvKeySchedule (concatMap reverse (chop4 key))
+                            cgOutputArr "decKS" (ksToXKey decKS)
+
+        -- encryption
+        enc = do pt   <- cgInputArr 4  "pt"    -- plain-text
+                 xkey <- cgInputArr xk "xkey"  -- expanded key
+                 cgOutputArr "ct" $ aesEncrypt pt (xkeyToKS xkey)
+
+        -- decryption
+        dec = do pt   <- cgInputArr 4  "ct"    -- cipher-text
+                 xkey <- cgInputArr xk "xkey"  -- expanded key
+                 cgOutputArr "pt" $ aesDecrypt pt (xkeyToKS xkey)
+
+        -- on-the-fly decryption
+        otfDec = do ct   <- cgInputArr 4  "ct"    -- cipher-text
+                    xkey <- cgInputArr xk "xkey"  -- expanded key
+                    cgOutputArr "pt" $ aesDecryptUnwoundKey ct (xkeyToKS xkey)
+
+        -- Transforming back and forth from our KS type to a flat array used by the generated C code
+        -- Turn a series of expanded keys to our internal KS type
+        xkeyToKS :: [SWord 32] -> KS
+        xkeyToKS xs = (f, m, l)
+           where f  = take 4 xs                             -- first round key
+                 m  = chop4 (take (xk - 8) (drop 4 xs))     -- middle rounds
+                 l  = drop (xk - 4) xs                      -- last round key
+
+        -- Turn a KS to a series of expanded key words
+        ksToXKey :: KS -> [SWord 32]
+        ksToXKey (f, m, l) = f ++ concat m ++ l
+
+-- | Generate code for AES functionality; given the key size.
+cgAESLibrary :: Int -> Maybe FilePath -> IO ()
+cgAESLibrary sz mbd
+  | sz `elem` [128, 192, 256] = void $ compileToCLib mbd nm [(fnm, configure dvals f) | (fnm, dvals, f) <- aesLibComponents sz]
+  | True                      = error $ "cgAESLibrary: Size must be one of 128, 192, or 256, received: " ++ show sz
+  where nm = "aes" ++ show sz ++ "Lib"
+
+        configure dvals code = cgSetDriverValues dvals >> code
+
+-- | Generate a C library, containing functions for performing 128-bit enc/dec/key-expansion.
+-- A note on performance: In a very rough speed test, the generated code was able to do
+-- 6.3 million block encryptions per second on a decent MacBook Pro. On the same machine, OpenSSL
+-- reports 8.2 million block encryptions per second. So, the generated code is about 25% slower
+-- as compared to the highly optimized OpenSSL implementation. (Note that the speed test was done
+-- somewhat simplistically, so these numbers should be considered very rough estimates.)
+cgAES128Library :: IO ()
+cgAES128Library = cgAESLibrary 128 Nothing
+
+--------------------------------------------------------------------------------------------
+-- | For doctest purposes only
+hex8 :: (SymVal a, Show a, Integral a) => SBV a -> String
+hex8 v = replicate (8 - length s) '0' ++ s
+  where s = flip showHex "" . fromJust . unliteral $ v
+
+-- | Chunk in groups of 4. (This function must be in some standard library, where?)
+chop4 :: [a] -> [[a]]
+chop4 [] = []
+chop4 xs = let (f, r) = splitAt 4 xs in f : chop4 r
+
+{- HLint ignore aesRound             "Use head"           -}
+{- HLint ignore aesInvRound          "Use head"           -}
+{- HLint ignore aesDecryptUnwoundKey "Use head"           -}
+{- HLint ignore module               "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Crypto/Prince.hs b/Documentation/SBV/Examples/Crypto/Prince.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Crypto/Prince.hs
@@ -0,0 +1,267 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Crypto.Prince
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implementation of Prince encryption and decryption.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE ParallelListComp #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
+
+module Documentation.SBV.Examples.Crypto.Prince where
+
+import Prelude hiding(round)
+import Numeric
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- * Types
+-- | Section 2: Prince is essentially a 64-bit cipher, with 128-bit key, coming in two parts.
+type Block = SWord 64
+
+-- | Plantext is simply a block.
+type PT = Block
+
+-- | Key is again a 64-bit block.
+type Key = Block
+
+-- | Cypher text is another 64-bit block.
+type CT = Block
+
+-- | A nibble is 4-bits. Ideally, we would like to represent a nibble by @SWord 4@; and indeed SBV can do that for
+-- verification purposes just fine. Unfortunately, the SBV's C compiler doesn't support 4-bit bit-vectors, as
+-- there's nothing meaningful in the C-land that we can map it to. Thus, we represent a nibble with 8-bits. The
+-- top 4 bits will always be 0.
+type Nibble = SWord 8
+
+-- * Key expansion
+
+-- | Expanding a key, from Section 3.4 of the spec.
+expandKey :: Key -> Key
+expandKey k = (k `rotateR` 1) `xor` (k `shiftR` 63)
+
+-- | expandKey(x) = x has a unique solution. We have:
+--
+-- >>> prop_ExpandKey
+-- Q.E.D.
+prop_ExpandKey :: IO ()
+prop_ExpandKey = do let lim = 10
+                    ms <- extractModels <$> allSatWith z3{allSatMaxModelCount = Just lim}
+                                                       (\x -> x .== expandKey x)
+                    case length ms of
+                      0 -> putStrLn "No solutions to equation `x == expandKey x`!"
+                      1 -> putStrLn "Q.E.D."
+                      n -> do let qual = if n == lim then "at least " else ""
+                              putStrLn $ "Failed. There are " ++ qual ++ show n ++ " solutions to `x == expandKey x`!"
+                              mapM_ (\i -> putStrLn ("    " ++ show i)) (ms :: [WordN 64])
+
+
+-- | Section 2: Encryption
+encrypt :: PT -> Key -> Key -> CT
+encrypt pt k0 k1 = prince k0 k0' k1 pt
+   where k0' = expandKey k0
+
+-- | Decryption
+decrypt :: CT -> Key -> Key -> PT
+decrypt ct k0 k1 = prince k0' k0 (k1 `xor` alpha) ct
+  where k0'   = expandKey k0
+        alpha = 0xc0ac29b7c97c50dd
+
+-- * Main algorithm
+
+-- | Basic prince algorithm
+prince :: Block -> Key -> Key -> Key -> Block
+prince k0 k0' k1 inp = out
+   where start = inp `xor` k0
+         end   = princeCore k1 start
+         out   = end `xor` k0'
+
+-- | Core prince. It's essentially folding of 12 rounds stitched together:
+princeCore :: Key -> Block -> Block
+princeCore k1 inp = end
+   where start    = inp `xor` k1 `xor` rConstants 0
+         front5   = foldl (round k1) start    [1 .. 5]
+         midPoint = sBoxInv . m' . sBox $ front5
+         back5    = foldl (invRound k1) midPoint [6..10]
+         end      = back5 `xor` rConstants 11 `xor` k1
+
+-- | Forward round.
+round :: Key -> Block -> Int -> Block
+round k1 b i = k1 `xor` rConstants i `xor` m (sBox b)
+
+-- | Backend round.
+invRound :: Key -> Block -> Int -> Block
+invRound k1 b i = sBoxInv (mInv (rConstants i `xor` (b `xor` k1)))
+
+-- | M transformation.
+m :: Block -> Block
+m = sr . m'
+
+-- | Inverse of M.
+mInv :: Block -> Block
+mInv = m' . srInv
+
+-- | SR.
+sr :: Block -> Block
+sr b = fromNibbles [n0, n5, n10, n15, n4, n9, n14, n3, n8, n13, n2, n7, n12, n1, n6, n11]
+  where [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15] = toNibbles b
+
+-- | Inverse of SR:
+srInv :: Block -> Block
+srInv b = fromNibbles [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15]
+  where [n0, n5, n10, n15, n4, n9, n14, n3, n8, n13, n2, n7, n12, n1, n6, n11] = toNibbles b
+
+-- | Prove sr and srInv are inverses: We have:
+--
+-- >>> prove prop_sr
+-- Q.E.D.
+prop_sr :: Predicate
+prop_sr = do b <- free "block"
+             pure $   b .== sr (srInv b)
+                  .&& b .== srInv (sr b)
+
+-- | M' transformation
+m' :: Block -> Block
+m' = mMult
+
+-- | The matrix as described in Section 3.3
+mat :: [[Int]]
+mat = res
+  where m0 = [[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
+        m1 = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
+        m2 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]
+        m3 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]
+
+        rows as bs cs ds = [a ++ b ++ c ++ d | a <- as | b <- bs | c <- cs | d <- ds ]
+
+        m0' = concat [rows m0 m1 m2 m3, rows m1 m2 m3 m0, rows m2 m3 m0 m1, rows m3 m0 m1 m2]
+        m1' = concat [rows m1 m2 m3 m0, rows m2 m3 m0 m1, rows m3 m0 m1 m2, rows m0 m1 m2 m3]
+
+        zs  = replicate 16 (replicate 16 0)
+        res = concat [rows m0' zs  zs  zs, rows zs  m1' zs  zs, rows zs  zs  m1' zs, rows zs  zs  zs  m0']
+
+-- | Multiplication.
+mMult :: Block -> Block
+mMult b | length mat /= 64           = error $ "mMult: Expected 64 rows, got       : " ++ show (length mat)
+        | any ((/= 64) . length) mat = error $ "mMult: Expected 64 on each row, got: " ++ show [p | p@(_, l) <- zip [(1::Int)..] (map length mat), l /= 64]
+        | True                       = fromBitsBE $ map mult mat
+  where bits = blastBE b
+
+        mult :: [Int] -> SBool
+        mult row = foldr (.<+>) sFalse $ zipWith mul row bits
+
+        mul :: Int -> SBool -> SBool
+        mul 0 _ = sFalse
+        mul 1 v = v
+        mul i _ = error $ "mMult: Unexpected constant: " ++ show i
+
+-- | Non-linear transformation of a block
+nonLinear :: [Nibble] -> Nibble -> Block -> Block
+nonLinear box def = fromNibbles . map s . toNibbles
+  where s :: Nibble -> Nibble
+        s = select box def
+
+-- | SBox transformation.
+sBox :: Block -> Block
+sBox = nonLinear [0xB, 0xF, 0x3, 0x2, 0xA, 0xC, 0x9, 0x1, 0x6, 0x7, 0x8, 0x0, 0xE, 0x5, 0xD, 0x4] 0x0
+
+-- | Inverse SBox transformation.
+sBoxInv :: Block -> Block
+sBoxInv = nonLinear [0xB, 0x7, 0x3, 0x2, 0xF, 0xD, 0x8, 0x9, 0xA, 0x6, 0x4, 0x0, 0x5, 0xE, 0xC, 0x1] 0x0
+
+-- | Prove that sbox and sBoxInv are inverses: We have:
+--
+-- >>> prove prop_SBox
+-- Q.E.D.
+prop_SBox :: Predicate
+prop_SBox = do b <- free "block"
+               pure $   b .== sBoxInv (sBox b)
+                    .&& b .== sBox (sBoxInv b)
+
+-- * Round constants
+
+-- | Round constants
+rConstants :: Int -> SWord 64
+rConstants  0 = 0x0000000000000000
+rConstants  1 = 0x13198a2e03707344
+rConstants  2 = 0xa4093822299f31d0
+rConstants  3 = 0x082efa98ec4e6c89
+rConstants  4 = 0x452821e638d01377
+rConstants  5 = 0xbe5466cf34e90c6c
+rConstants  6 = 0x7ef84f78fd955cb1
+rConstants  7 = 0x85840851f1ac43aa
+rConstants  8 = 0xc882d32f25323c54
+rConstants  9 = 0x64a51195e0e3610d
+rConstants 10 = 0xd3b5a399ca0c2399
+rConstants 11 = 0xc0ac29b7c97c50dd
+rConstants n  = error $ "rConstants called with invalid round number: " ++ show n
+
+-- | Round-constants property: rc_i `xor` rc_{11-i} is constant. We have:
+--
+-- >>> prop_RoundKeys
+-- True
+prop_RoundKeys :: SBool
+prop_RoundKeys = sAnd [magic .== rConstants i `xor` rConstants (11-i) | i <- [0 .. 11]]
+  where magic = rConstants 11
+
+-- | Convert a 64 bit word to nibbles
+toNibbles :: SWord 64 -> [Nibble]
+toNibbles = concatMap nibbles . toBytes
+  where nibbles :: SWord 8 -> [Nibble]
+        nibbles b = [b `shiftR` 4, b .&. 0xF]
+
+-- | Convert from nibbles to a 64 bit word
+fromNibbles :: [Nibble] -> SWord 64
+fromNibbles xs
+  | length xs /= 16 = error $ "fromNibbles: Incorrect number of nibbles, expected 16, got: " ++ show (length xs)
+  | True            = fromBytes $ cvt xs
+  where cvt (n1 : n2 : ns) = (n1 `shiftL` 4 .|. n2) : cvt ns
+        cvt _              = []
+
+-- * Test vectors
+
+-- | From Appendix A of the spec. We have:
+--
+-- >>> testVectors
+-- True
+testVectors :: SBool
+testVectors = sAnd $  [encrypt pt k0 k1 .== ct | (pt, k0, k1, ct) <- tvs]
+                   ++ [decrypt ct k0 k1 .== pt | (pt, k0, k1, ct) <- tvs]
+   where tvs :: [(SWord 64, SWord 64, SWord 64, SWord 64)]
+         tvs = [ (0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x818665aa0d02dfda)
+               , (0xffffffffffffffff, 0x0000000000000000, 0x0000000000000000, 0x604ae6ca03c20ada)
+               , (0x0000000000000000, 0xffffffffffffffff, 0x0000000000000000, 0x9fb51935fc3df524)
+               , (0x0000000000000000, 0x0000000000000000, 0xffffffffffffffff, 0x78a54cbe737bb7ef)
+               , (0x0123456789abcdef, 0x0000000000000000, 0xfedcba9876543210, 0xae25ad3ca8fa9ccf)
+               ]
+
+-- | Nicely show a concrete block.
+showBlock :: Block -> String
+showBlock b =  case unliteral b of
+                 Just v  -> "0x" ++ pad (showHex v "")
+                 Nothing -> error "showBlock: Symbolic input!"
+  where pad s = reverse $ take 16 $ reverse s ++ repeat '0'
+
+-- * Code generation
+
+-- | Generating C code for the encryption block.
+codeGen :: IO ()
+codeGen = compileToC Nothing "enc" $ do
+               input <- cgInput "inp"
+               k0    <- cgInput "k0"
+               k1    <- cgInput "k1"
+               cgOverwriteFiles True
+               cgOutput "ct"  $ encrypt input k0 k1
diff --git a/Documentation/SBV/Examples/Crypto/RC4.hs b/Documentation/SBV/Examples/Crypto/RC4.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Crypto/RC4.hs
@@ -0,0 +1,153 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Crypto.RC4
+-- Copyright : (c) Austin Seipp
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An implementation of RC4 (AKA Rivest Cipher 4 or Alleged RC4/ARC4),
+-- using SBV. For information on RC4, see: <http://en.wikipedia.org/wiki/RC4>.
+--
+-- We make no effort to optimize the code, and instead focus on a clear
+-- implementation. In fact, the RC4 algorithm relies on in-place update of
+-- its state heavily for efficiency, and is therefore unsuitable for a purely
+-- functional implementation.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Crypto.RC4 where
+
+import Data.Char  (ord, chr)
+import Data.List  (genericIndex)
+import Data.Maybe (fromJust)
+import Data.SBV
+
+import Data.SBV.Tools.STree
+
+import Numeric (showHex)
+
+-----------------------------------------------------------------------------
+-- * Types
+-----------------------------------------------------------------------------
+
+-- | RC4 State contains 256 8-bit values. We use the symbolically accessible
+-- full-binary type 'STree' to represent the state, since RC4 needs
+-- access to the array via a symbolic index and it's important to minimize access time.
+type S = STree Word8 Word8
+
+-- | Construct the fully balanced initial tree, where the leaves are simply the numbers @0@ through @255@.
+initS :: S
+initS = mkSTree (map literal [0 .. 255])
+
+-- | The key is a stream of 'Word8' values.
+type Key = [SWord8]
+
+-- | Represents the current state of the RC4 stream: it is the @S@ array
+-- along with the @i@ and @j@ index values used by the PRGA.
+type RC4 = (S, SWord8, SWord8)
+
+-----------------------------------------------------------------------------
+-- * The PRGA
+-----------------------------------------------------------------------------
+
+-- | Swaps two elements in the RC4 array.
+swap :: SWord8 -> SWord8 -> S -> S
+swap i j st = writeSTree (writeSTree st i stj) j sti
+  where sti = readSTree st i
+        stj = readSTree st j
+
+-- | Implements the PRGA used in RC4. We return the new state and the next key value generated.
+prga :: RC4 -> (SWord8, RC4)
+prga (st', i', j') = (readSTree st kInd, (st, i, j))
+  where i    = i' + 1
+        j    = j' + readSTree st' i
+        st   = swap i j st'
+        kInd = readSTree st i + readSTree st j
+
+-----------------------------------------------------------------------------
+-- * Key schedule
+-----------------------------------------------------------------------------
+
+-- | Constructs the state to be used by the PRGA using the given key.
+initRC4 :: Key -> S
+initRC4 key
+ | keyLength < 1 || keyLength > 256
+ = error $ "RC4 requires a key of length between 1 and 256, received: " ++ show keyLength
+ | True
+ = snd $ foldl mix (0, initS) (map literal [0..255])
+ where keyLength = length key
+       mix :: (SWord8, S) -> SWord8 -> (SWord8, S)
+       mix (j', s) i = let j = j' + readSTree s i + genericIndex key (fromJust (unliteral i) `mod` fromIntegral keyLength)
+                       in (j, swap i j s)
+
+-- | The key-schedule. Note that this function returns an infinite list.
+keySchedule :: Key -> [SWord8]
+keySchedule key = genKeys (initRC4 key, 0, 0)
+  where genKeys :: RC4 -> [SWord8]
+        genKeys st = let (k, st') = prga st in k : genKeys st'
+
+-- | Generate a key-schedule from a given key-string.
+keyScheduleString :: String -> [SWord8]
+keyScheduleString = keySchedule . map (literal . fromIntegral . ord)
+
+-----------------------------------------------------------------------------
+-- * Encryption and Decryption
+-----------------------------------------------------------------------------
+
+-- | RC4 encryption. We generate key-words and xor it with the input. The
+-- following test-vectors are from Wikipedia <http://en.wikipedia.org/wiki/RC4>:
+--
+-- >>> concatMap hex2 $ encrypt "Key" "Plaintext"
+-- "bbf316e8d940af0ad3"
+--
+-- >>> concatMap hex2 $ encrypt "Wiki" "pedia"
+-- "1021bf0420"
+--
+-- >>> concatMap hex2 $ encrypt "Secret" "Attack at dawn"
+-- "45a01f645fc35b383552544b9bf5"
+encrypt :: String -> String -> [SWord8]
+encrypt key pt = zipWith xor (keyScheduleString key) (map cvt pt)
+  where cvt = literal . fromIntegral . ord
+
+-- | RC4 decryption. Essentially the same as decryption. For the above test vectors we have:
+--
+-- >>> decrypt "Key" [0xbb, 0xf3, 0x16, 0xe8, 0xd9, 0x40, 0xaf, 0x0a, 0xd3]
+-- "Plaintext"
+--
+-- >>> decrypt "Wiki" [0x10, 0x21, 0xbf, 0x04, 0x20]
+-- "pedia"
+--
+-- >>> decrypt "Secret" [0x45, 0xa0, 0x1f, 0x64, 0x5f, 0xc3, 0x5b, 0x38, 0x35, 0x52, 0x54, 0x4b, 0x9b, 0xf5]
+-- "Attack at dawn"
+decrypt :: String -> [SWord8] -> String
+decrypt key ct = map cvt $ zipWith xor (keyScheduleString key) ct
+  where cvt = chr . fromIntegral . fromJust . unliteral
+
+-----------------------------------------------------------------------------
+-- * Verification
+-----------------------------------------------------------------------------
+
+-- | Prove that round-trip encryption/decryption leaves the plain-text unchanged.
+-- The theorem is stated parametrically over key and plain-text sizes. The expression
+-- performs the proof for a 40-bit key (5 bytes) and 40-bit plaintext (again 5 bytes).
+--
+-- Note that this theorem is trivial to prove, since it is essentially establishing
+-- xor'in the same value twice leaves a word unchanged (i.e., @x `xor` y `xor` y = x@).
+-- However, the proof takes quite a while to complete, as it gives rise to a fairly
+-- large symbolic trace.
+rc4IsCorrect :: IO ThmResult
+rc4IsCorrect = prove $ do
+        key <- mkFreeVars 5
+        pt  <- mkFreeVars 5
+        let ks  = keySchedule key
+            ct  = zipWith xor ks pt
+            pt' = zipWith xor ks ct
+        pure $ pt .== pt'
+
+--------------------------------------------------------------------------------------------
+-- | For doctest purposes only
+hex2 :: (SymVal a, Show a, Integral a) => SBV a -> String
+hex2 v = replicate (2 - length s) '0' ++ s
+  where s = flip showHex "" . fromJust . unliteral $ v
diff --git a/Documentation/SBV/Examples/Crypto/SHA.hs b/Documentation/SBV/Examples/Crypto/SHA.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Crypto/SHA.hs
@@ -0,0 +1,415 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Crypto.SHA
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implementation of SHA2 class of algorithms, closely following the spec
+-- <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf>.
+--
+-- We support all variants of SHA in the spec, except for SHA1. Note that
+-- this implementation is really useful for code-generation purposes from
+-- SBV, as it is hard to state (or prove!) any particular properties of
+-- these algorithms that is suitable for SMT solving.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
+
+module Documentation.SBV.Examples.Crypto.SHA where
+
+import Data.SBV
+import Data.SBV.Tools.CodeGen
+
+import Prelude hiding (Foldable(..))
+import Data.Char (ord, toLower)
+import Data.List (genericLength, length, foldl')
+import Numeric   (showHex)
+
+import Data.Proxy (Proxy(..))
+
+-----------------------------------------------------------------------------
+-- * Parameterizing SHA
+-----------------------------------------------------------------------------
+
+-- | Parameterized SHA representation, that captures all the differences
+-- between variants of the algorithm. @w@ is the word-size type.
+data SHA w = SHA { wordSize           :: Int              -- ^ Section 1           : Word size we operate with
+                 , blockSize          :: Int              -- ^ Section 1           : Block size for messages
+                 , sum0Coefficients   :: (Int, Int, Int)  -- ^ Section 4.1.2-3     : Coefficients of the Sum0 function
+                 , sum1Coefficients   :: (Int, Int, Int)  -- ^ Section 4.1.2-3     : Coefficients of the Sum1 function
+                 , sigma0Coefficients :: (Int, Int, Int)  -- ^ Section 4.1.2-3     : Coefficients of the sigma0 function
+                 , sigma1Coefficients :: (Int, Int, Int)  -- ^ Section 4.1.2-3     : Coefficients of the sigma1 function
+                 , shaConstants       :: [w]              -- ^ Section 4.2.2-3     : Magic SHA constants
+                 , h0                 :: [w]              -- ^ Section 5.3.2-6     : Initial hash value
+                 , shaLoopCount       :: Int              -- ^ Section 6.2.2, 6.4.2: How many iterations are there in the inner loop
+                 }
+
+-----------------------------------------------------------------------------
+-- * Section 4.1.2, SHA functions
+-----------------------------------------------------------------------------
+
+-- | The choose function.
+ch :: Bits a => a -> a -> a -> a
+ch x y z = (x .&. y) `xor` (complement x .&. z)
+
+-- | The majority function.
+maj :: Bits a => a -> a -> a -> a
+maj x y z = (x .&. y) `xor` (x .&. z) `xor` (y .&. z)
+
+-- | The sum-0 function. We parameterize over the rotation amounts as different
+-- variants of SHA use different rotation amounts.
+sum0 :: Bits a => SHA w -> a -> a
+sum0 SHA{sum0Coefficients = (a, b, c)} x = (x `rotateR` a) `xor` (x `rotateR` b) `xor` (x `rotateR` c)
+
+-- | The sum-1 function. Again, parameterized.
+sum1 :: Bits a => SHA w -> a -> a
+sum1 SHA{sum1Coefficients = (a, b, c)} x = (x `rotateR` a) `xor` (x `rotateR` b) `xor` (x `rotateR` c)
+
+-- | The sigma0 function. Parameterized.
+sigma0 :: Bits a => SHA w -> a -> a
+sigma0 SHA{sigma0Coefficients = (a, b, c)} x = (x `rotateR` a) `xor` (x `rotateR` b) `xor` (x `shiftR` c)
+
+-- | The sigma1 function. Parameterized.
+sigma1 :: Bits a => SHA w -> a -> a
+sigma1 SHA{sigma1Coefficients = (a, b, c)} x = (x `rotateR` a) `xor` (x `rotateR` b) `xor` (x `shiftR` c)
+
+-----------------------------------------------------------------------------
+-- * SHA variants
+-----------------------------------------------------------------------------
+
+-- | Parameterization for SHA224.
+sha224P :: SHA (SWord 32)
+sha224P = SHA { wordSize           = 32
+              , blockSize          = 512
+              , sum0Coefficients   = ( 2, 13, 22)
+              , sum1Coefficients   = ( 6, 11, 25)
+              , sigma0Coefficients = ( 7, 18,  3)
+              , sigma1Coefficients = (17, 19, 10)
+              , shaConstants       = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
+                                     , 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
+                                     , 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
+                                     , 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
+                                     , 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
+                                     , 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
+                                     , 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
+                                     , 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+                                     ]
+              , h0                 = [ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939
+                                     , 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
+                                     ]
+              , shaLoopCount       = 64
+              }
+
+-- | Parameterization for SHA256. Inherits mostly from SHA224.
+sha256P :: SHA (SWord 32)
+sha256P = sha224P { h0 = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a
+                         , 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+                         ]
+                  }
+
+-- | Parameterization for SHA384.
+sha384P :: SHA (SWord 64)
+sha384P = SHA { wordSize           = 64
+              , blockSize          = 1024
+              , sum0Coefficients   = (28, 34, 39)
+              , sum1Coefficients   = (14, 18, 41)
+              , sigma0Coefficients = ( 1,  8,  7)
+              , sigma1Coefficients = (19, 61,  6)
+              , shaConstants       = [ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc
+                                     , 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118
+                                     , 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2
+                                     , 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694
+                                     , 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65
+                                     , 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5
+                                     , 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4
+                                     , 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70
+                                     , 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df
+                                     , 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b
+                                     , 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30
+                                     , 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8
+                                     , 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8
+                                     , 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3
+                                     , 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec
+                                     , 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b
+                                     , 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178
+                                     , 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b
+                                     , 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c
+                                     , 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+                                     ]
+              , h0                 = [ 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939
+                                     , 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4
+                                     ]
+              , shaLoopCount       = 80
+              }
+
+-- | Parameterization for SHA512. Inherits mostly from SHA384.
+sha512P :: SHA (SWord 64)
+sha512P = sha384P { h0 = [ 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1
+                         , 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
+                         ]
+                  }
+
+-- | Parameterization for SHA512_224. Inherits mostly from SHA512
+sha512_224P :: SHA (SWord 64)
+sha512_224P = sha512P { h0 = [ 0x8C3D37C819544DA2, 0x73E1996689DCD4D6, 0x1DFAB7AE32FF9C82, 0x679DD514582F9FCF
+                             , 0x0F6D2B697BD44DA8, 0x77E36F7304C48942, 0x3F9D85A86A1D36C8, 0x1112E6AD91D692A1
+                             ]
+                      }
+
+-- | Parameterization for SHA512_256. Inherits mostly from SHA512
+sha512_256P :: SHA (SWord 64)
+sha512_256P = sha512P { h0 = [ 0x22312194FC2BF72C, 0x9F555FA3C84C64C2, 0x2393B86B6F53B151, 0x963877195940EABD
+                             , 0x96283EE2A88EFFE3, 0xBE5E1E2553863992, 0x2B0199FC2C85B8AA, 0x0EB72DDC81C52CA2
+                             ]
+                      }
+
+-----------------------------------------------------------------------------
+-- * Section 5, Preprocessing
+-----------------------------------------------------------------------------
+
+-- | t'Block' is a  synonym for lists, but makes the intent clear.
+newtype Block a = Block [a]
+
+-- | Prepare the message by turning it into blocks. We also check for the message
+-- size requirement here. Note that this won't actually happen in practice as the input
+-- length would be > 2^64 (or 2^128), and you'd run out of memory first!
+prepareMessage :: forall w. (Num w, ByteConverter w) => SHA w -> String -> [Block w]
+prepareMessage SHA{wordSize, blockSize} s
+  | msgLen >= maxLen
+  = error $ "Message is too big! Size: " ++ show msgLen ++ " Max: " ++ show maxLen
+  | True
+  = parse $ chunkBy (wordSize `div` 8) fromBytes padded
+  where -- Maximum message size supported by the algorithm
+        maxLen :: Integer
+        maxLen = 2^(2 * fromIntegral wordSize :: Integer)
+
+        -- Size of the input in bits
+        msgLen :: Integer
+        msgLen = 8 * genericLength s
+
+        -- In all variants, we have 16-element blocks:
+        --    SHA 224, 256                  :  512-bit block size with 32-bit word size: Total 16 words to a block
+        --    SHA 384, 512, 512_224, 512_256: 1024-bit block size with 64-bit word size: Total 16 words to a block
+        parse = chunkBy 16 Block
+
+        msgSizeAsBytes :: [SWord 8]
+        msgSizeAsBytes
+          | wordSize == 32 = toBytes (fromIntegral msgLen :: SWord  64)
+          | wordSize == 64 = toBytes (fromIntegral msgLen :: SWord 128)
+          | True           = error $ "prepareMessage: Unexpected word size: " ++ show wordSize
+
+        -- kLen is how many bits extra we need in the padding
+        kLen :: Int
+        kLen = blockSize - fromIntegral ((msgLen + fromIntegral (2 * wordSize)) `mod` fromIntegral blockSize)
+
+        -- Since message is always a multiple of 8, we need to pad it with the byte 0x80 for the first byte
+        -- after it (1000 0000), and then enough bytes to fill to make it a multiple of the block size.
+        padded :: [SWord 8]
+        padded = map (fromIntegral . ord) s ++ [0x80] ++ replicate ((kLen `div` 8) - 1) 0 ++ msgSizeAsBytes
+
+-----------------------------------------------------------------------------
+-- * Section 6.2.2 and 6.4.2, Hash computation
+-----------------------------------------------------------------------------
+
+-- | Hash one block of message, starting from a previous hash. This function
+-- corresponds to body of the for-loop in the spec. This function always
+-- produces a list of length 8, corresponding to the final 8 values of the @H@.
+hashBlock :: (Num w, Bits w) => SHA w -> [w] -> Block w -> [w]
+hashBlock p@SHA{shaLoopCount, shaConstants} hPrev (Block m) = step4
+   where lim = shaLoopCount - 1
+
+         -- Step 1: Prepare the message schedule:
+         w t
+          | 0  <= t && t <= 15  = m !! t
+          | 16 <= t && t <= lim = sigma1 p (w (t-2)) + w (t-7) + sigma0 p (w (t-15)) + w (t-16)
+          | True                = error $ "hashBlock, unexpected t: " ++ show t
+
+         -- Step 2: Initialize working variables
+         -- No code needed!
+
+         -- Step 3 Body:
+         step3Body [a, b, c, d, e, f, g, h] t = [t1 + t2, a, b, c, d + t1, e, f, g]
+           where t1   = h + sum1 p e + ch e f g + shaConstants !! t + w t
+                 t2   = sum0 p a + maj a b c
+         step3Body xs t = error $ "Impossible! step3Body received a list of length " ++ show (length xs) ++ ", iteration: " ++ show t
+
+         -- Step 3 simply folds the body for the required loop-count
+         step3 = foldl' step3Body hPrev [0 .. lim]
+
+         -- Step 4
+         step4 = zipWith (+) step3 hPrev
+
+-- | Compute the hash of a given string using the specified parameterized hash algorithm.
+shaP :: (Num w, Bits w, ByteConverter w) => SHA w -> String -> [w]
+shaP p@SHA{h0} = foldl' (hashBlock p) h0 . prepareMessage p
+
+-----------------------------------------------------------------------------
+-- * Computing the digest
+-----------------------------------------------------------------------------
+
+-- | SHA224 digest.
+sha224 :: String -> SWord 224
+sha224 s = h0 # h1 # h2 # h3 # h4 # h5 # h6
+  where [h0, h1, h2, h3, h4, h5, h6, _] = shaP sha224P s
+
+-- | SHA256 digest.
+sha256 :: String -> SWord 256
+sha256 s = h0 # h1 # h2 # h3 # h4 # h5 # h6 # h7
+  where [h0, h1, h2, h3, h4, h5, h6, h7] = shaP sha256P s
+
+-- | SHA384 digest.
+sha384 :: String -> SWord 384
+sha384 s = h0 # h1 # h2 # h3 # h4 # h5
+  where [h0, h1, h2, h3, h4, h5, _, _] = shaP sha384P s
+
+-- | SHA512 digest.
+sha512 :: String -> SWord 512
+sha512 s = h0 # h1 # h2 # h3 # h4 # h5 # h6 # h7
+  where [h0, h1, h2, h3, h4, h5, h6, h7] = shaP sha512P s
+
+-- | SHA512_224 digest.
+sha512_224 :: String -> SWord 224
+sha512_224 s = h0 # h1 # h2 # h3Top
+  where [h0, h1, h2, h3, _, _, _, _] = shaP sha512_224P s
+        h3Top                        = bvExtract (Proxy @63) (Proxy @32) h3
+
+-- | SHA512_256 digest.
+sha512_256 :: String -> SWord 256
+sha512_256 s = h0 # h1 # h2 # h3
+  where [h0, h1, h2, h3, _, _, _, _] = shaP sha512_256P s
+
+-----------------------------------------------------------------------------
+-- * Testing
+-----------------------------------------------------------------------------
+
+-- | Collection of known answer tests for SHA. Since these tests take too long during regular
+-- regression runs, we pass as an argument how many to run. Increase the below number to 24 to run all tests.
+-- We have:
+--
+-- >>> knownAnswerTests 1
+-- True
+knownAnswerTests :: Int -> Bool
+knownAnswerTests nTest = and $  take nTest $  [showHash (sha224     t) == map toLower r | (t, r) <- sha224Kats    ]
+                                           ++ [showHash (sha256     t) == map toLower r | (t, r) <- sha256Kats    ]
+                                           ++ [showHash (sha384     t) == map toLower r | (t, r) <- sha384Kats    ]
+                                           ++ [showHash (sha512     t) == map toLower r | (t, r) <- sha512Kats    ]
+                                           ++ [showHash (sha512_224 t) == map toLower r | (t, r) <- sha512_224Kats]
+                                           ++ [showHash (sha512_256 t) == map toLower r | (t, r) <- sha512_256Kats]
+
+  where -- | From <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA224DigestTest.java>
+        sha224Kats :: [(String, String)]
+        sha224Kats = [ (""                                                        , "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")
+                     , ("a"                                                       , "abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5")
+                     , ("abc"                                                     , "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7")
+                     , ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525")
+                     ]
+
+        -- | From: <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA256DigestTest.java>
+        sha256Kats :: [(String, String)]
+        sha256Kats = [ (""                                                        , "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
+                     , ("a"                                                       , "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb")
+                     , ("abc"                                                     , "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+                     , ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1")
+                     ]
+
+        -- | From: <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA384DigestTest.java>
+        sha384Kats :: [(String, String)]
+        sha384Kats = [ (""                                                                                                                , "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b")
+                     , ("a"                                                                                                               , "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31")
+                     , ("abc"                                                                                                             , "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7")
+                     , ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039")
+                     ]
+
+        -- | From: <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA512DigestTest.java>
+        sha512Kats :: [(String, String)]
+        sha512Kats = [ (""                                                                                                                , "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
+                     , ("a"                                                                                                               , "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75")
+                     , ("abc"                                                                                                             , "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
+                     , ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909")
+                     ]
+
+        -- | From: <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA512t224DigestTest.java>
+        sha512_224Kats :: [(String, String)]
+        sha512_224Kats = [ (""                                                                                                                , "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4")
+                         , ("a"                                                                                                               , "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327")
+                         , ("abc"                                                                                                             , "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA")
+                         , ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9")
+                         ]
+
+        -- | From: <http://github.com/bcgit/bc-java/blob/master/core/src/test/java/org/bouncycastle/crypto/test/SHA512t256DigestTest.java>
+        sha512_256Kats :: [(String, String)]
+        sha512_256Kats = [ (""                                                                                                                , "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a")
+                         , ("a"                                                                                                               , "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8")
+                         , ("abc"                                                                                                             , "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23")
+                         , ("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A")
+                         ]
+
+-----------------------------------------------------------------------------
+-- * Code generation
+-- ${codeGenIntro}
+-----------------------------------------------------------------------------
+{- $codeGenIntro
+   It is not practical to generate SBV code for hashing an entire string, as it would
+   require handling of a fixed size string. Instead we show how to generate code
+   for hashing one block, which can then be incorporated into a larger program
+   by providing the appropriate loop.
+-}
+
+-- | Generate code for one block of SHA256 in action, starting from an arbitrary hash value.
+cgSHA256 :: IO ()
+cgSHA256 = compileToC Nothing "sha256" $ do
+
+        let algorithm = sha256P
+
+        hInBytes   <- cgInputArr 32 "hIn"
+        blockBytes <- cgInputArr 64 "block"
+
+        let hIn   = chunkBy 4 fromBytes hInBytes
+            block = chunkBy 4 fromBytes blockBytes
+
+            result = hashBlock algorithm hIn (Block block)
+
+        cgOutputArr "hash" $ concatMap toBytes result
+
+-- | Generate code for one block of SHA512 in action, starting from an arbitrary hash value.
+cgSHA512 :: IO ()
+cgSHA512 = compileToC Nothing "sha512" $ do
+
+        let algorithm = sha512P
+
+        hInBytes   <- cgInputArr  64 "hIn"
+        blockBytes <- cgInputArr 128 "block"
+
+        let hIn   = chunkBy 8 fromBytes hInBytes
+            block = chunkBy 8 fromBytes blockBytes
+
+            result = hashBlock algorithm hIn (Block block)
+
+        cgOutputArr "hash" $ concatMap toBytes result
+
+-----------------------------------------------------------------------------
+-- * Helpers
+-----------------------------------------------------------------------------
+
+-- | Helper for chunking a list by given lengths and combining each chunk with a function
+chunkBy :: Int -> ([a] -> b) -> [a] -> [b]
+chunkBy i f = go
+  where go [] = []
+        go xs
+         | length first /= i = error $ "chunkBy: Not a multiple of " ++ show i ++ ", got: " ++ show (length first)
+         | True              = f first : go rest
+         where (first, rest) = splitAt i xs
+
+-- | Nicely lay out a hash value as a string
+showHash :: (Show a, Integral a, SymVal a) => SBV a -> String
+showHash x = case (kindOf x, unliteral x) of
+               (KBounded False n, Just v)  -> pad (n `div` 4) $ showHex v ""
+               _                           -> error $ "Impossible happened: Unexpected hash value: " ++ show x
+  where pad l s = reverse $ take l $ reverse s ++ repeat '0'
diff --git a/Documentation/SBV/Examples/DeltaSat/DeltaSat.hs b/Documentation/SBV/Examples/DeltaSat/DeltaSat.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/DeltaSat/DeltaSat.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.DeltaSat.DeltaSat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The encoding of the Flyspec example from the dReal web page
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.DeltaSat.DeltaSat where
+
+import Data.SBV
+
+-- | Encode the delta-sat problem as given in <http://dreal.github.io/>
+-- We have:
+--
+-- >>> flyspeck
+-- Unsatisfiable
+flyspeck :: IO SatResult
+flyspeck = dsat $ do
+        x1 <- sReal "x1"
+        x2 <- sReal "x2"
+
+        constrain $ x1 `inRange` ( 3, 3.14)
+        constrain $ x2 `inRange` (-7, 5)
+
+        let pi' = 3.14159265
+            lhs = 2 * pi' - 2 * x1 * asin (cos 0.979 * sin (pi' / x1))
+            rhs = -0.591 - 0.0331 * x2 + 0.506 + 1
+
+        pure $ lhs .<= rhs
diff --git a/Documentation/SBV/Examples/Existentials/Diophantine.hs b/Documentation/SBV/Examples/Existentials/Diophantine.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Existentials/Diophantine.hs
@@ -0,0 +1,174 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Existentials.Diophantine
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Finding minimal natural number solutions to linear Diophantine equations,
+-- using explicit quantification.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections       #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Existentials.Diophantine where
+
+import Data.List (intercalate, transpose)
+
+import Data.SBV
+import Data.Proxy
+
+import GHC.TypeLits
+
+--------------------------------------------------------------------------------------------------
+-- * Representing solutions
+--------------------------------------------------------------------------------------------------
+-- | For a homogeneous problem, the solution is any linear combination of the resulting vectors.
+-- For a non-homogeneous problem, the solution is any linear combination of the vectors in the
+-- second component plus one of the vectors in the first component.
+data Solution = Homogeneous    [[Integer]]
+              | NonHomogeneous [[Integer]] [[Integer]]
+
+instance Show Solution where
+  show s = case s of
+             Homogeneous        xss -> comb supplyH (map (False,) xss)
+             NonHomogeneous css xss -> intercalate "\n" [comb supplyNH ((True, cs) : map (False,) xss) | cs <- css]
+    where supplyH  = ['k' : replicate i '\'' | i <- [0 ..]]
+          supplyNH = "" : supplyH
+
+          comb supply xss = vec $ map add (transpose (zipWith muls supply xss))
+            where muls x (isConst, cs) = map mul cs
+                    where mul 0 = "0"
+                          mul 1 | isConst = "1"
+                                | True    = x
+                          mul k | isConst = show k
+                                | True    = show k ++ x
+
+                  add [] = "0"
+                  add xs = foldr1 plus xs
+
+                  plus "0" y   = y
+                  plus x   "0" = x
+                  plus x   y   = x ++ "+" ++ y
+
+          vec xs = "(" ++ intercalate ", " xs ++ ")"
+
+--------------------------------------------------------------------------------------------------
+-- * Solving diophantine equations
+--------------------------------------------------------------------------------------------------
+-- | ldn: Solve a (L)inear (D)iophantine equation, returning minimal solutions over (N)aturals.
+-- The input is given as a rows of equations, with rhs values separated into a tuple. The first
+-- argument must be a proxy of a natural, must be total number of columns in the system. (i.e.,
+-- #of variables + 1). The second parameter limits the search to bound: In case there are
+-- too many solutions, you might want to limit your search space.
+ldn :: forall proxy n. KnownNat n => proxy n -> Maybe Int -> [([Integer], Integer)] -> IO Solution
+ldn pn mbLim problem = do solution <- basis pn mbLim (map (map literal) m)
+                          if homogeneous
+                              then pure $ Homogeneous solution
+                              else do let ones  = [xs | (1:xs) <- solution]
+                                          zeros = [xs | (0:xs) <- solution]
+                                      pure $ NonHomogeneous ones zeros
+  where rhs = map snd problem
+        lhs = map fst problem
+        homogeneous = all (== 0) rhs
+        m | homogeneous = lhs
+          | True        = zipWith (\x y -> -x : y) rhs lhs
+
+-- | Find the basis solution. By definition, the basis has all non-trivial (i.e., non-0) solutions
+-- that cannot be written as the sum of two other solutions. We use the mathematically equivalent
+-- statement that a solution is in the basis if it's least according to the natural partial
+-- order using the ordinary less-than relation.
+basis :: forall proxy n. KnownNat n => proxy n -> Maybe Int -> [[SInteger]] -> IO [[Integer]]
+basis _ mbLim m = extractModels `fmap` allSatWith z3{allSatMaxModelCount = mbLim} cond
+ where cond = do as <- mkFreeVars  n
+
+                 constrain $ \(ForallN bs :: ForallN n nm Integer) ->
+                        ok as .&& (ok bs .=> as .== bs .|| sNot (bs `less` as))
+
+       n = case m of
+            []  -> 0
+            f:_ -> length f
+
+       ok xs = sAny (.> 0) xs .&& sAll (.>= 0) xs .&& sAnd [sum (zipWith (*) r xs) .== 0 | r <- m]
+
+       as `less` bs = sAnd (zipWith (.<=) as bs) .&& sOr (zipWith (.<) as bs)
+
+--------------------------------------------------------------------------------------------------
+-- * Examples
+--------------------------------------------------------------------------------------------------
+
+-- | Solve the equation:
+--
+--    @2x + y - z = 2@
+--
+-- We have:
+--
+-- >>> test
+-- (1+k, k', 2k+k')
+-- (k, 2+k', 2k+k')
+--
+-- That is, for arbitrary @k@ and @k'@, we have two different solutions. (An infinite family.)
+-- You can verify these solutions by substituting the values for @x@, @y@ and @z@ in the above, for each choice.
+-- It's harder to see that they cover all possibilities, but a moments thought reveals that is indeed the case.
+test :: IO Solution
+test = ldn (Proxy @4) Nothing [([2,1,-1], 2)]
+
+-- | A puzzle: Five sailors and a monkey escape from a naufrage and reach an island with
+-- coconuts. Before dawn, they gather a few of them and decide to sleep first and share
+-- the next day. At night, however, one of them awakes, counts the nuts, makes five parts,
+-- gives the remaining nut to the monkey, saves his share away, and sleeps. All other
+-- sailors do the same, one by one. When they all wake up in the morning, they again make 5 shares,
+-- and give the last remaining nut to the monkey. How many nuts were there at the beginning?
+--
+-- We can model this as a series of diophantine equations:
+--
+-- @
+--       x_0 = 5 x_1 + 1
+--     4 x_1 = 5 x_2 + 1
+--     4 x_2 = 5 x_3 + 1
+--     4 x_3 = 5 x_4 + 1
+--     4 x_4 = 5 x_5 + 1
+--     4 x_5 = 5 x_6 + 1
+-- @
+--
+-- We need to solve for x_0, over the naturals. If you run this program, z3 takes its time (quite long!)
+-- but, it eventually computes: [15621,3124,2499,1999,1599,1279,1023] as the answer.
+--
+-- That is:
+--
+-- @
+--   * There was a total of 15621 coconuts
+--   * 1st sailor: 15621 = 3124*5+1, leaving 15621-3124-1 = 12496
+--   * 2nd sailor: 12496 = 2499*5+1, leaving 12496-2499-1 =  9996
+--   * 3rd sailor:  9996 = 1999*5+1, leaving  9996-1999-1 =  7996
+--   * 4th sailor:  7996 = 1599*5+1, leaving  7996-1599-1 =  6396
+--   * 5th sailor:  6396 = 1279*5+1, leaving  6396-1279-1 =  5116
+--   * In the morning, they had: 5116 = 1023*5+1.
+-- @
+--
+-- Note that this is the minimum solution, that is, we are guaranteed that there's
+-- no solution with less number of coconuts. In fact, any member of @[15625*k-4 | k <- [1..]]@
+-- is a solution, i.e., so are @31246@, @46871@, @62496@, @78121@, etc.
+--
+-- Note that we iteratively deepen our search by requesting increasing number of
+-- solutions to avoid the all-sat pitfall.
+sailors :: IO [Integer]
+sailors = search 1
+  where search i = do soln <- ldn (Proxy @8)
+                                  (Just i)
+                                  [ ([1, -5,  0,  0,  0,  0,  0], 1)
+                                  , ([0,  4, -5 , 0,  0,  0,  0], 1)
+                                  , ([0,  0,  4, -5 , 0,  0,  0], 1)
+                                  , ([0,  0,  0,  4, -5,  0,  0], 1)
+                                  , ([0,  0,  0,  0,  4, -5,  0], 1)
+                                  , ([0,  0,  0,  0,  0,  4, -5], 1)
+                                  ]
+                      case soln of
+                        NonHomogeneous (xs:_) _ -> pure xs
+                        _                       -> search (i+1)
diff --git a/Documentation/SBV/Examples/Lists/BoundedMutex.hs b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
@@ -0,0 +1,154 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Lists.BoundedMutex
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves a simple mutex algorithm correct up to a given bound.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Lists.BoundedMutex where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Each agent can be in one of the three states
+data State = Idle     -- ^ Regular work
+           | Ready    -- ^ Intention to enter critical state
+           | Critical -- ^ In the critical state
+           deriving Show
+
+-- | Make 'State' a symbolic enumeration
+mkSymbolic [''State]
+
+-- | The mutex property holds for two sequences of state transitions, if they are not in
+-- their critical section at the same time.
+mutex :: [SState] -> [SState] -> SBool
+mutex p1s p2s = sAnd $ zipWith (\p1 p2 -> p1 ./= sCritical .|| p2 ./= sCritical) p1s p2s
+
+-- | A sequence is valid upto a bound if it starts at 'Idle', and follows the mutex rules. That is:
+--
+--    * From 'Idle' it can switch to 'Ready' or stay 'Idle'
+--    * From 'Ready' it can switch to 'Critical' if it's its turn
+--    * From 'Critical' it can either stay in 'Critical' or go back to 'Idle'
+--
+-- The variable @me@ identifies the agent id.
+validSequence :: Integer -> [SInteger] -> [SState] -> SBool
+validSequence _  []     _           = sTrue
+validSequence _  _      []          = sTrue
+validSequence me pturns procs@(p:_) = sAnd [ sIdle .== p
+                                           , check pturns procs sIdle
+                                           ]
+   where check []           _          _    = sTrue
+         check _            []         _    = sTrue
+         check (turn:turns) (cur:rest) prev = ok .&& check turns rest cur
+           where ok = ite (prev .== sIdle)                          (cur `sElem` [sIdle, sReady])
+                    $ ite (prev .== sReady .&& turn .== literal me) (cur `sElem` [sCritical])
+                    $ ite (prev .== sCritical)                      (cur `sElem` [sCritical, sIdle])
+                                                                    (cur `sElem` [prev])
+
+-- | The mutex algorithm, coded implicitly as an assignment to turns. Turns start at @1@, and at each stage is either
+-- @1@ or @2@; giving preference to that process. The only condition is that if either process is in its critical
+-- section, then the turn value stays the same. Note that this is sufficient to satisfy safety (i.e., mutual
+-- exclusion), though it does not guarantee liveness.
+validTurns :: [SInteger] -> [SState] -> [SState] -> SBool
+validTurns []                    _        _        = sTrue
+validTurns turns@(firstTurn : _) process1 process2 = firstTurn .== 1 .&& check (zip3 turns process1 process2) 1
+  where check []                     _    = sTrue
+        check ((cur, p1, p2) : rest) prev =   cur `sElem` map literal [1, 2]
+                                          .&& (p1 .== sCritical .|| p2 .== sCritical .=> cur .== prev)
+                                          .&& check rest cur
+
+-- | Check that we have the mutex property so long as 'validSequence' and 'validTurns' holds; i.e.,
+-- so long as both the agents and the arbiter act according to the rules. The check is bounded up-to-the
+-- given concrete bound; so this is an example of a bounded-model-checking style proof. We have:
+--
+-- >>> checkMutex 20
+-- All is good!
+checkMutex :: Int -> IO ()
+checkMutex b = runSMT $ do
+                  p1    :: [SState]   <- mapM (\i -> free ("p1_" ++ show i)) [1 .. b]
+                  p2    :: [SState]   <- mapM (\i -> free ("p2_" ++ show i)) [1 .. b]
+                  turns :: [SInteger] <- mapM (\i -> free ("t_"  ++ show i)) [1 .. b]
+
+                  -- Ensure that both sequences and the turns are valid
+                  constrain $ validSequence 1 turns p1
+                  constrain $ validSequence 2 turns p2
+                  constrain $ validTurns      turns p1 p2
+
+                  -- Try to assert that mutex does not hold. If we get a
+                  -- counter example, we would've found a violation!
+                  constrain $ sNot $ mutex p1 p2
+
+                  query $ do cs <- checkSat
+                             case cs of
+                               Unk    -> error "Solver said Unknown!"
+                               DSat{} -> error "Solver said delta-satisfiable!"
+                               Unsat  -> io . putStrLn $ "All is good!"
+                               Sat    -> do io . putStrLn $ "Violation detected!"
+                                            do p1V <- mapM getValue p1
+                                               p2V <- mapM getValue p2
+                                               ts  <- mapM getValue turns
+
+                                               io . putStrLn $ "P1: " ++ show p1V
+                                               io . putStrLn $ "P2: " ++ show p2V
+                                               io . putStrLn $ "Ts: " ++ show ts
+
+-- | Our algorithm is correct, but it is not fair. It does not guarantee that a process that
+-- wants to enter its critical-section will always do so eventually. Demonstrate this by
+-- trying to show a bounded trace of length 10, such that the second process is ready but
+-- never transitions to critical. We have:
+--
+-- >>> notFair 10
+-- Fairness is violated at bound: 10
+-- P1: [Idle,Idle,Idle,Idle,Ready,Critical,Idle,Ready,Critical,Critical]
+-- P2: [Idle,Ready,Ready,Ready,Ready,Ready,Ready,Ready,Ready,Ready]
+-- Ts: [1,1,1,1,1,1,1,1,1,1]
+--
+-- As expected, P2 gets ready but never goes critical since the arbiter keeps picking
+-- P1 unfairly. (You might get a different trace depending on what z3 happens to produce!)
+--
+-- Exercise for the reader: Change the 'validTurns' function so that it alternates the turns
+-- from the previous value if neither process is in critical. Show that this makes the 'notFair'
+-- function below no longer exhibits the issue. Is this sufficient? Concurrent programming is tricky!
+notFair :: Int -> IO ()
+notFair b = runSMT $ do p1    :: [SState]   <- mapM (\i -> free ("p1_" ++ show i)) [1 .. b]
+                        p2    :: [SState]   <- mapM (\i -> free ("p2_" ++ show i)) [1 .. b]
+                        turns :: [SInteger] <- mapM (\i -> free ("t_"  ++ show i)) [1 .. b]
+
+                        -- Ensure that both sequences and the turns are valid
+                        constrain $ validSequence 1 turns p1
+                        constrain $ validSequence 2 turns p2
+                        constrain $ validTurns    turns p1 p2
+
+                        -- Ensure that the second process becomes ready in the second cycle:
+                        constrain $ p2 !! 1 .== sReady
+
+                        -- Find a trace where p2 never goes critical
+                        -- counter example, we would've found a violation!
+                        constrain $ sNot $ sCritical `sElem` p2
+
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unk    -> error "Solver said Unknown!"
+                                     DSat{} -> error "Solver said delta-satisfiable!"
+                                     Unsat  -> error "Solver couldn't find a violating trace!"
+                                     Sat    -> do io . putStrLn $ "Fairness is violated at bound: " ++ show b
+                                                  do p1V <- mapM getValue p1
+                                                     p2V <- mapM getValue p2
+                                                     ts  <- mapM getValue turns
+
+                                                     io . putStrLn $ "P1: " ++ show p1V
+                                                     io . putStrLn $ "P2: " ++ show p2V
+                                                     io . putStrLn $ "Ts: " ++ show ts
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Lists/CountOutAndTransfer.hs b/Documentation/SBV/Examples/Lists/CountOutAndTransfer.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Lists/CountOutAndTransfer.hs
@@ -0,0 +1,65 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Lists.CountOutAndTransfer
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Shows that COAT (Count-out-and-transfer) trick preserves order of cards.
+-- From pg. 35 of <http://graphics8.nytimes.com/packages/pdf/crossword/Mulcahy_Mathematical_Card_Magic-Sample2.pdf>:
+--
+-- /Given a packet of n cards, COATing k cards refers to counting out that many from the top into a pile, thus reversing their order, and transferring those as a unit to the bottom./
+--
+-- We show that if you COAT 4 times where @k@ is at least @n/2@ for a deck of size @n@, then the deck remains in the same order.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Lists.CountOutAndTransfer where
+
+import Prelude hiding (length, take, drop, reverse, (++))
+
+import Data.SBV
+import Data.SBV.List
+
+-- | Count-out-and-transfer (COAT): Take @k@ cards from top, reverse it,
+-- and put it at the bottom of a deck.
+coat :: SymVal a => SInteger -> SList a -> SList a
+coat k cards = drop k cards ++ reverse (take k cards)
+
+-- | COAT 4 times.
+fourCoat :: SymVal a => SInteger -> SList a -> SList a
+fourCoat k = coat k . coat k . coat k . coat k
+
+-- | A deck is simply a list of integers. Note that a regular deck will have
+-- distinct cards, we do not impose this in our proof. That is, the
+-- proof works regardless whether we put duplicates into the deck, which
+-- generalizes the theorem.
+type Deck = SList Integer
+
+-- | Key property of COATing. If you take a deck of size @n@, and
+-- COAT it 4 times, then the deck remains in the same order. The COAT
+-- factor, @k@, must be greater than half the size of the deck size.
+--
+-- Note that the proof time increases significantly with @n@.
+-- Here's a proof for deck size of 6, for all @k@ >= @3@.
+--
+-- >>> coatCheck 6
+-- Q.E.D.
+--
+-- It's interesting to note that one can also express this theorem
+-- by making @n@ symbolic as well. However, doing so definitely requires
+-- an inductive proof, and the SMT-solver doesn't handle this case
+-- out-of-the-box, running forever.
+coatCheck :: Integer -> IO ThmResult
+coatCheck n = prove $ do
+     deck :: Deck <- free "deck"
+     k            <- free "k"
+
+     constrain $ length deck .== literal n
+     constrain $ 2*k .>= literal n
+
+     pure $ deck .== fourCoat k deck
diff --git a/Documentation/SBV/Examples/Lists/Fibonacci.hs b/Documentation/SBV/Examples/Lists/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Lists/Fibonacci.hs
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Lists.Fibonacci
+-- Copyright : (c) Joel Burget
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Define the fibonacci sequence as an SBV symbolic list.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Lists.Fibonacci where
+
+import Data.SBV
+
+import Prelude hiding ((!!))
+
+import           Data.SBV.List ((!!))
+import qualified Data.SBV.List as L
+
+import Data.SBV.Control
+
+-- | Compute a prefix of the fibonacci numbers. We have:
+--
+-- >>> mkFibs 10
+-- [1,1,2,3,5,8,13,21,34,55]
+mkFibs :: Int -> IO [Integer]
+mkFibs n = take n <$> runSMT genFibs
+
+-- | Generate fibonacci numbers as a sequence. Note that we constrain only
+-- the first 200 entries.
+genFibs :: Symbolic [Integer]
+genFibs = do fibs <- sList "fibs"
+
+             -- constrain the length
+             constrain $ L.length fibs .== 200
+
+             -- Constrain first two elements
+             constrain $ fibs !! 0 .== 1
+             constrain $ fibs !! 1 .== 1
+
+             -- Constrain an arbitrary element at index `i`
+             let constr i = constrain $ fibs !! i + fibs !! (i+1) .== fibs !! (i+2)
+
+             -- Constrain the remaining elts
+             mapM_ (constr . fromIntegral) [(0::Int) .. 197]
+
+             query $ do cs <- checkSat
+                        case cs of
+                          Unk    -> error "Solver returned unknown!"
+                          DSat{} -> error "Unexpected dsat result!"
+                          Unsat  -> error "Solver couldn't generate the fibonacci sequence!"
+                          Sat    -> getValue fibs
diff --git a/Documentation/SBV/Examples/Misc/Auxiliary.hs b/Documentation/SBV/Examples/Misc/Auxiliary.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Auxiliary.hs
@@ -0,0 +1,65 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Auxiliary
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates model construction with auxiliary variables. Sometimes we
+-- need to introduce a variable in our problem as an existential variable,
+-- but it's "internal" to the problem and we do not consider it as part of
+-- the solution. Also, in an `allSat` scenario, we may not care for models
+-- that only differ in these auxiliaries. SBV allows designating such variables
+-- as `isNonModelVar` so we can still use them like any other variable, but without
+-- considering them explicitly in model construction.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Auxiliary where
+
+import Data.SBV
+
+-- | A simple predicate, based on two variables @x@ and @y@, true when
+-- @0 <= x <= 1@ and @x - abs y@ is @0@.
+problem :: Predicate
+problem = do x <- free "x"
+             y <- free "y"
+             constrain $ x .>= 0
+             constrain $ x .<= 1
+             pure $ x - abs y .== (0 :: SInteger)
+
+-- | Generate all satisfying assignments for our problem. We have:
+--
+-- >>> allModels
+-- Solution #1:
+--   x =  1 :: Integer
+--   y = -1 :: Integer
+-- Solution #2:
+--   x = 1 :: Integer
+--   y = 1 :: Integer
+-- Solution #3:
+--   x = 0 :: Integer
+--   y = 0 :: Integer
+-- Found 3 different solutions.
+--
+-- Note that solutions @2@ and @3@ share the value @x = 1@, since there are
+-- multiple values of @y@ that make this particular choice of @x@ satisfy our constraint.
+allModels :: IO AllSatResult
+allModels = allSat problem
+
+-- | Generate all satisfying assignments, but we first tell SBV that @y@ should not be considered
+-- as a model problem, i.e., it's auxiliary. We have:
+--
+-- >>> modelsWithYAux
+-- Solution #1:
+--   x = 1 :: Integer
+-- Solution #2:
+--   x = 0 :: Integer
+-- Found 2 different solutions.
+--
+-- Note that we now have only two solutions, one for each unique value of @x@ that satisfy our
+-- constraint.
+modelsWithYAux :: IO AllSatResult
+modelsWithYAux = allSatWith z3{isNonModelVar = (`elem` ["y"])} problem
diff --git a/Documentation/SBV/Examples/Misc/Definitions.hs b/Documentation/SBV/Examples/Misc/Definitions.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Definitions.hs
@@ -0,0 +1,190 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Definitions
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how we can add actual SMT-definitions for functions
+-- that cannot otherwise be defined in SBV. Typically, these are used
+-- for recursive definitions.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE QuasiQuotes     #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Definitions where
+
+import Data.SBV
+import Data.SBV.Tuple
+
+-------------------------------------------------------------------------
+-- * Simple functions
+-------------------------------------------------------------------------
+
+-- | Add one to an argument
+add1 :: SInteger -> SInteger
+add1 = smtFunction "add1" (+1)
+
+-- | Reverse run the add1 function. Note that the generated SMTLib will have the function
+-- add1 itself defined. You can verify this by running the below in verbose mode.
+--
+-- >>> add1Example
+-- Satisfiable. Model:
+--   x = 4 :: Integer
+add1Example :: IO SatResult
+add1Example = sat $ do
+        x <- sInteger "x"
+        pure $ 5 .== add1 x
+
+-------------------------------------------------------------------------
+-- * Basic recursive functions
+-------------------------------------------------------------------------
+
+-- | Sum of numbers from 0 to the given number. Since this is a recursive
+-- definition, we cannot simply symbolically simulate it as it wouldn't
+-- terminate. So, we use the function generation facilities to define it
+-- directly in SMTLib.
+sumToN :: SInteger -> SInteger
+sumToN = smtFunction "sumToN" $ \x -> [sCase| x of
+                                         _ | x .<= 0 -> 0
+                                         _           -> x + sumToN (x - 1)
+                                      |]
+
+-- | Prove that sumToN works as expected.
+--
+-- We have:
+--
+-- >>> sumToNExample
+-- Satisfiable. Model:
+--   s0 =  5 :: Integer
+--   s1 = 15 :: Integer
+sumToNExample :: IO SatResult
+sumToNExample = sat $ \a r -> a .== 5 .&& r .== sumToN a
+
+-- | Coding list-length recursively. Again, we map directly to an SMTLib function.
+len :: SList Integer -> SInteger
+len = smtFunction "list_length" $ \xs -> [sCase| xs of
+                                            []   -> 0
+                                            _:ts -> 1 + len ts
+                                         |]
+
+-- | Calculate the length of a list, using recursive functions.
+--
+-- We have:
+--
+-- >>> lenExample
+-- Satisfiable. Model:
+--   s0 = [1,2,3] :: [Integer]
+--   s1 =       3 :: Integer
+lenExample :: IO SatResult
+lenExample = sat $ \a r -> a .== [1,2,3] .&& r .== len a
+
+-------------------------------------------------------------------------
+-- * Mutual recursion
+-------------------------------------------------------------------------
+
+-- | A simple mutual-recursion example, from the z3 documentation. We have:
+--
+-- >>> pingPong
+-- Satisfiable. Model:
+--   s0 = 1 :: Integer
+pingPong :: IO SatResult
+pingPong = sat $ \x -> x .> 0 .&& ping x sTrue .> x
+  where ping :: SInteger -> SBool -> SInteger
+        ping = smtFunctionWithMeasure "ping" (\_ y -> ite y 1 (0 :: SInteger), [])
+             $ \x y -> [sCase| y of
+                           True  -> pong (x+1) (sNot y)
+                           False -> x - 1
+                        |]
+
+        pong :: SInteger -> SBool -> SInteger
+        pong = smtFunctionWithMeasure "pong" (\_ b -> ite b 1 (0 :: SInteger), [])
+             $ \a b -> [sCase| b of
+                           True  -> ping (a-1) (sNot b)
+                           False -> a
+                        |]
+
+-- | Usual way to define even-odd mutually recursively. While the termination measure
+-- is verified, current SMT solvers do not terminate when evaluating mutually recursive
+-- @define-funs-rec@ definitions. See 'isEvenOdd' for a single-function alternative
+-- that is more solver-friendly.
+--
+-- >>> evenOdd
+-- Unknown.
+--   Reason: timeout
+evenOdd :: IO SatResult
+evenOdd = sat $ do setTimeOut 5000
+                   a <- sInteger "a"
+                   r <- sBool "r"
+                   constrain $ a .== 20 .&& r .== isE a
+  where isE, isO :: SInteger -> SBool
+        isE = smtFunctionWithMeasure "isE" (\x -> tuple (abs x, ite (x .< 0) (1 :: SInteger) 0), [])
+            $ \x -> [sCase| x of
+                       _ | x .< 0 -> isE (-x)
+                       _          -> x .== 0 .|| isO (x - 1)
+                    |]
+        isO = smtFunctionWithMeasure "isO" (\x -> tuple (abs x, ite (x .< 0) (1 :: SInteger) 0), [])
+            $ \x -> [sCase| x of
+                       _ | x .< 0 -> isO (-x)
+                       _          -> x .== 0 .|| isE (x - 1)
+                    |]
+
+-- | Another technique to handle mutually definitions is to define the functions together, and pull the results out individually.
+--
+-- The measure @(abs x, ite (x < 0) 1 0)@ ensures termination: when @x < 0@, the call @isEvenOdd(-x)@
+-- keeps @abs x@ the same but drops the second component from 1 to 0. When @x > 0@, the call
+-- @isEvenOdd(x-1)@ decreases @abs x@.
+isEvenOdd :: SInteger -> STuple Bool Bool
+isEvenOdd = smtFunctionWithMeasure "isEvenOdd" (\x -> tuple (abs x, ite (x .< 0) (1 :: SInteger) 0), [])
+          $ \x -> [sCase| x of
+                     _ | x .<  0 -> isEvenOdd (-x)
+                     _ | x .== 0 -> tuple (sTrue, sFalse)
+                     _           -> swap (isEvenOdd (x - 1))
+                  |]
+
+-- | Extract the isEven function for easier use.
+isEven :: SInteger -> SBool
+isEven x = isEvenOdd x ^._1
+
+-- | Extract the isOdd function for easier use.
+isOdd :: SInteger -> SBool
+isOdd x = isEvenOdd x ^._2
+
+-- | We can prove 20 is even and definitely not odd, thusly:
+--
+-- >>> evenOdd2
+-- Satisfiable. Model:
+--   s0 =    20 :: Integer
+--   s1 =  True :: Bool
+--   s2 = False :: Bool
+evenOdd2 :: IO SatResult
+evenOdd2 = sat $ \a r1 r2 -> a .== 20 .&& r1 .== isEven a .&& r2 .== isOdd a
+
+-------------------------------------------------------------------------
+-- * Nested recursion
+-------------------------------------------------------------------------
+
+-- | Ackermann function, demonstrating nested recursion.
+ack :: SInteger -> SInteger -> SInteger
+ack = smtFunction "ack"
+    $ \x y -> [sCase| x of
+                 _ | x .<= 0 -> y + 1
+                 _ | y .<= 0 -> ack (x - 1) 1
+                 _           -> ack (x - 1) (ack x (y - 1))
+              |]
+
+-- | We can prove constant-folding instances of the equality @ack 1 y == y + 2@:
+--
+-- >>> ack1y
+-- Satisfiable. Model:
+--   s0 = 5 :: Integer
+--   s1 = 7 :: Integer
+--
+-- Expecting the prover to handle the general case for arbitrary @y@ is beyond the current
+-- scope of what SMT solvers do out-of-the-box for the time being.
+ack1y :: IO SatResult
+ack1y = sat $ \y r -> y .== 5 .&& r .== ack 1 y
diff --git a/Documentation/SBV/Examples/Misc/Enumerate.hs b/Documentation/SBV/Examples/Misc/Enumerate.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Enumerate.hs
@@ -0,0 +1,72 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Enumerate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how enumerations can be translated to their SMT-Lib
+-- counterparts, without losing any information content. Also see
+-- "Documentation.SBV.Examples.Puzzles.U2Bridge" for a more detailed
+-- example involving enumerations.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Enumerate where
+
+import Data.SBV
+
+-- | A simple enumerated type, that we'd like to translate to SMT-Lib intact;
+-- i.e., this type will not be uninterpreted but rather preserved and will
+-- be just like any other symbolic type SBV provides.
+data E = A | B | C
+
+-- | Make 'E' a symbolic value.
+mkSymbolic [''E]
+
+-- | Have the SMT solver enumerate the elements of the domain. We have:
+--
+-- >>> elts
+-- Solution #1:
+--   s0 = B :: E
+-- Solution #2:
+--   s0 = A :: E
+-- Solution #3:
+--   s0 = C :: E
+-- Found 3 different solutions.
+elts :: IO AllSatResult
+elts = allSat $ \(x::SE) -> x .== x
+
+-- | Shows that if we require 4 distinct elements of the type 'E', we shall fail; as
+-- the domain only has three elements. We have:
+--
+-- >>> four
+-- Unsatisfiable
+four :: IO SatResult
+four = sat $ \a b c (d::SE) -> distinct [a, b, c, d]
+
+-- | Enumerations are automatically ordered, so we can ask for the maximum
+-- element. Note the use of quantification. We have:
+--
+-- >>> maxE
+-- Satisfiable. Model:
+--   maxE = C :: E
+maxE :: IO SatResult
+maxE = sat $ do mx :: SE <- free "maxE"
+                constrain $ \(Forall e) -> mx .>= e
+
+-- | Similarly, we get the minimum element. We have:
+--
+-- >>> minE
+-- Satisfiable. Model:
+--   minE = A :: E
+minE :: IO SatResult
+minE = sat $ do mn :: SE <- free "minE"
+                constrain $ \(Forall e) -> mn .<= e
diff --git a/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs b/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/FirstOrderLogic.hs
@@ -0,0 +1,470 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.FirstOrderLogic
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves various first-order logic properties using SBV. The properties we
+-- prove all come from <https://en.wikipedia.org/wiki/First-order_logic>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.FirstOrderLogic where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> :set -XDataKinds -XScopedTypeVariables
+#endif
+
+-- | An uninterpreted sort for demo purposes, named 'U'
+data U
+mkSymbolic [''U]
+
+-- | An uninterpreted sort for demo purposes, named 'V'
+data V
+mkSymbolic [''V]
+
+-- | An enumerated type for demo purposes, named 'E'
+data E = A | B | C
+
+mkSymbolic [''E]
+
+-- | Helper to turn quantified formula to a regular boolean. We
+-- can think of this as quantifier elimination, hence the name 'qe'.
+qe :: QuantifiedBool a => a -> SBool
+qe = quantifiedBool
+
+-- * Pushing negation over quantifiers
+{- $negUniv
+\(\lnot \forall x\,P(x)\Leftrightarrow \exists x\,\lnot P(x)\)
+
+>>> let p = uninterpret "P" :: SU -> SBool
+>>> prove $ sNot (qe (\(Forall x) -> p x)) .<=> qe (\(Exists x) -> sNot (p x))
+Q.E.D.
+
+\(\lnot \exists x\,P(x)\Leftrightarrow \forall x\,\lnot P(x)\)
+
+>>> let p = uninterpret "P" :: SU -> SBool
+>>> prove $ sNot (qe (\(Exists x) -> p x)) .<=> qe (\(Forall x) -> sNot (p x))
+Q.E.D.
+-}
+
+-- * Interchanging quantifiers
+{- $interchange
+\(\forall x\,\forall y\,P(x,y)\Leftrightarrow \forall y\,\forall x\,P(x,y)\)
+
+>>> let p = uninterpret "P" :: (SU, SV) -> SBool
+>>> prove $ qe (\(Forall x) (Forall y) -> p (x, y)) .<=> qe (\(Forall y) (Forall x) -> p (x, y))
+Q.E.D.
+
+\(\exists x\,\exists y\,P(x,y)\Leftrightarrow \exists y\,\exists x\,P(x,y)\)
+
+>>> let p = uninterpret "P" :: (SU, SV) -> SBool
+>>> prove $ qe (\(Exists x) (Exists y) -> p (x, y)) .<=> qe (\(Exists y) (Exists x) -> p (x, y))
+Q.E.D.
+-}
+
+-- * Merging quantifiers
+{- $mergeQuants
+\(\forall x\,P(x)\land \forall x\,Q(x)\Leftrightarrow \forall x\,(P(x)\land Q(x))\)
+
+>>> let p = uninterpret "P" :: SU -> SBool
+>>> let q = uninterpret "Q" :: SU -> SBool
+>>> prove $ (qe (\(Forall x) -> p x) .&& qe (\(Forall x) -> q x)) .<=> qe (\(Forall x) -> p x .&& q x)
+Q.E.D.
+
+\(\exists x\,P(x)\lor \exists x\,Q(x)\Leftrightarrow \exists x\,(P(x)\lor Q(x))\)
+
+>>> let p = uninterpret "P" :: SU -> SBool
+>>> let q = uninterpret "Q" :: SU -> SBool
+>>> prove $ (qe (\(Exists x) -> p x) .|| qe (\(Exists x) -> q x)) .<=> qe (\(Exists x) -> p x .|| q x)
+Q.E.D.
+-}
+
+-- * Scoping over quantifiers
+{- $scopeOverQuants
+Provided \(x\) is not free in \(P\): \(P\land \exists x\,Q(x)\Leftrightarrow \exists x\,(P\land Q(x))\)
+
+>>> let p = uninterpret "P" :: SBool
+>>> let q = uninterpret "Q" :: SU -> SBool
+>>> prove $ (p .&& qe (\(Exists x) -> q x)) .<=> qe (\(Exists x) -> p .&& q x)
+Q.E.D.
+
+Provided \(x\) is not free in \(P\): \(P\lor \forall x\,Q(x)\Leftrightarrow \forall x\,(P\lor Q(x))\)
+
+>>> let p = uninterpret "P" :: SBool
+>>> let q = uninterpret "Q" :: SU -> SBool
+>>> prove $ (p .|| qe (\(Forall x) -> q x)) .<=> qe (\(Forall x) -> p .|| q x)
+Q.E.D.
+-}
+
+-- * A non-identity
+{- $nonIdentity
+It's instructive to look at an example where the proof actually fails. Consider, for instance, an
+example of a merging quantifiers like we did above, except when the equality doesn't hold. That
+is, we try to prove the "correct" sounding, but incorrect conjecture:
+
+\(\forall x\,P(x)\lor \forall x\,Q(x)\Leftrightarrow \forall x\,(P(x)\lor Q(x))\)
+
+We have:
+
+>>> let p = uninterpret "P" :: SU -> SBool
+>>> let q = uninterpret "Q" :: SU -> SBool
+>>> prove $ (qe (\(Forall x) -> p x) .|| qe (\(Forall x) -> q x)) .<=> qe (\(Forall x) -> p x .|| q x)
+Falsifiable. Counter-example:
+  P :: U -> Bool
+  P U_2 = True
+  P U_0 = True
+  P _   = False
+<BLANKLINE>
+  Q :: U -> Bool
+  Q U_2 = False
+  Q U_0 = False
+  Q _   = True
+
+The solver found us a falsifying instance: Pick a domain with at least three elements. We'll call
+the first element @U_2@, and the second element @U_0@, without naming the others. (Unfortunately the solver picks nonintuitive names, but you can substitute better names if you like. They're just names of two distinct
+objects that belong to the domain \(U\) with no other meaning.)
+
+Arrange so that \(P\) is true on @U_2@ and @U_0@, but false for everything else.
+Also arrange so that \(Q\) is false on these two elements, but true for everything else.
+
+With this
+assignment, the right hand side of our conjecture
+is true no matter which element you pick, because either \(P\) or \(Q\) is true on any
+given element. (Actually, only one will be true on any element, but that is tangential.)
+But left-hand-side is not a tautology: Clearly neither \(P\) nor \(Q\) are true for all elements, and
+hence both disjuncts are false. Thus, the alleged conjecture is not an equivalence in first order logic.
+-}
+
+-- * Exists unique
+{- $existsUnique
+We can use the t'ExistsUnique' constructor to indicate a value must exists uniquely. For instance,
+we can prove that there is an element in 'E' that's less than 'C', but it's not unique. However,
+there's a unique element that's less than all the elements in 'E':
+
+>>> prove $ \(Exists       (me :: SE)) -> me .<= sC
+Q.E.D.
+>>> prove $ \(ExistsUnique (me :: SE)) -> me .<= sC
+Falsifiable
+>>> prove $ \(ExistsUnique (me :: SE)) (Forall e) -> me .<= e
+Q.E.D.
+-}
+
+-- * Skolemization
+{- $skolemization
+Given a formula, skolemization produces an equisatisfiable formula that has no existential quantifiers. Instead,
+the existentials are replaced by uninterpreted functions.
+Skolemization is useful when we want to see the instantiation of nested existential variables. Interpretation for such variables will be
+functions of the enclosing universals.
+-}
+
+-- | Consider the formula \(\forall x\,\exists y\, x \ge y\), over bit-vectors of size 8. We can ask SBV to satisfy it:
+--
+-- >>> sat skolemEx1
+-- Satisfiable
+--
+-- But this isn't really illuminating. We can first skolemize, and then ask to satisfy:
+--
+-- >>> sat $ skolemize skolemEx1
+-- Satisfiable. Model:
+--   y :: Word8 -> Word8
+--   y x = x
+--
+-- which is much better We are told that we can have the witness as the value given for each choice of @x@.
+skolemEx1 :: Forall "x" Word8 -> Exists "y" Word8 -> SBool
+skolemEx1 (Forall x) (Exists y) = x .>= y
+
+-- | Consider the formula \(\forall a\,\exists b\,\forall c\,\exists d\, a + b >= c + d\), over bit-vectors of size 8. We can ask SBV to satisfy it:
+--
+-- >>> sat skolemEx2
+-- Satisfiable
+--
+-- Again, we're left in the dark as to why this is satisfiable. Let's skolemize first, and then call 'sat' on it:
+--
+-- >>> sat $ skolemize skolemEx2
+-- Satisfiable. Model:
+--   b :: Word8 -> Word8
+--   b _ = 0
+-- <BLANKLINE>
+--   d :: Word8 -> Word8 -> Word8
+--   d a c = a + 255 * c
+--
+-- Let's see what the solver said. It suggested we should use the value of @0@ for @b@, regardless of the
+-- choice of @a@. (Note how @b@ is a function of one variable, i.e., of @a@)
+-- And it suggested using @a + (255 * c)@ for @d@,
+-- for whatever we choose for @a@ and @c@. Why does this work? Well, given
+-- arbitrary @a@ and @c@, we end up with:
+--
+-- @
+--     a + b >= c + d
+--     --> substitute b = 0 and d = a + 255c as suggested by the solver
+--     a + 0 >= c + a + 255c
+--     a >= 256c + a
+--     a >= a
+-- @
+--
+-- showing the formula is satisfiable for whatever values you pick for @a@ and @c@. Note that @256@ is simply
+-- @0@ when interpreted modulo @2^8@. Clever!
+skolemEx2 :: Forall "a" Word8 -> Exists "b" Word8 -> Forall "c" Word8 -> Exists "d" Word8 -> SBool
+skolemEx2 (Forall a) (Exists b) (Forall c) (Exists d) = a + b .>= c + d
+
+-- | A common proof technique to show validity is to show that the negation is unsatisfiable. Note
+-- that if you want to skolemize during this process, you should first /negate/ and then skolemize!
+--
+-- This example demonstrates the possible pitfall. The 'skolemEx3' function
+-- encodes \(\exists x\, \forall y\, y \ge x\) for 8-bit bitvectors; which is a valid statement since
+-- @x = 0@ acts as the witness. We can directly prove this in SBV:
+--
+-- >>> prove skolemEx3
+-- Q.E.D.
+--
+-- Or, we can ask if the negation is unsatisfiable:
+--
+-- >>> sat (qNot skolemEx3)
+-- Unsatisfiable
+--
+-- If we want, we can skolemize after the negation step:
+--
+-- >>> sat (skolemize (qNot skolemEx3))
+-- Unsatisfiable
+--
+-- and get the same result. However, it would be __unsound__ to skolemize first and then negate:
+--
+-- >>> sat (qNot (skolemize skolemEx3))
+-- Satisfiable. Model:
+--   x = 1 :: Word8
+--
+-- And that would be the incorrect conclusion that our formula is invalid with a counter-example! You
+-- can see the same by doing:
+--
+-- >>> prove (skolemize skolemEx3)
+-- Falsifiable. Counter-example:
+--   x = 1 :: Word8
+--
+-- So, if you want to check validity and want to also perform skolemization; you should negate your
+-- formula first and then skolemize, not the other way around!
+skolemEx3 :: Exists "x" Word8 -> Forall "y" Word8 -> SBool
+skolemEx3 (Exists x) (Forall y) = y .>= x
+
+-- | If you skolemize different formulas that share the same name for their existentials, then SBV will
+-- get confused and will think those represent the same skolem function. This is unfortunate, but it follows
+-- the requirement that uninterpreted function names should be unique. In this particular case, however, since
+-- SBV creates these functions, it is harder to control the internal names. In such cases, use the function
+-- 'taggedSkolemize' to provide a name to prefix the skolem functions. As demonstrated by 'skolemEx4'. We get:
+--
+-- >>> skolemEx4
+-- Satisfiable. Model:
+--   c1_y :: Integer -> Integer
+--   c1_y x = x
+-- <BLANKLINE>
+--   c2_y :: Integer -> Integer
+--   c2_y x = x + 1
+--
+-- Note how the internal skolem functions are named according to the tag given. If you use regular 'skolemize'
+-- this program will essentially do the wrong thing by assuming the skolem functions for both predicates are
+-- the same, and will return unsat. Beware!
+-- All skolem functions should be named differently in your program for your deductions to be sound.
+skolemEx4 :: IO SatResult
+skolemEx4 = sat cs
+  where cs :: ConstraintSet
+        cs = do constrain $ taggedSkolemize "c1" $ \(Forall @"x" x) (Exists @"y" y) -> x .== (y   :: SInteger)
+                constrain $ taggedSkolemize "c2" $ \(Forall @"x" x) (Exists @"y" y) -> x .== (y-1 :: SInteger)
+
+-- * Special relations
+
+-- ** Partial orders
+{- $partialOrder
+A partial order is a reflexive, antisymmetic, and a transitive relation. We can prove these properties
+for relations that are checked by the 'isPartialOrder' predicate in SBV:
+
+\(\forall x\,R(x,x)\)
+
+\(\forall x\,\forall y\, R(x, y) \land R(y, x) \Rightarrow x = y\)
+
+\(\forall x\,\forall y\, \forall z\, R(x, y) \land R(y, z) \Rightarrow R(x, z)\)
+
+>>> let r         = uninterpret "R" :: Relation U
+>>> let isPartial = isPartialOrder "poR" r
+>>> prove $ \(Forall x) -> isPartial .=> r (x, x)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) -> isPartial .=> (r (x, y) .&& r (y, x) .=> x .== y)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isPartial .=> (r (x, y) .&& r (y, z) .=> r (x, z))
+Q.E.D.
+-}
+
+-- | Demonstrates creating a partial order. We have:
+--
+-- >>> poExample
+-- Q.E.D.
+poExample :: IO ThmResult
+poExample = prove $ do
+  let r = uninterpret "R" :: Relation E
+  constrain $ isPartialOrder "poR" r
+
+  pure $ qe (\(Forall x) -> r (x, x)) :: Predicate
+
+-- ** Linear orders
+{- $linearOrder
+A linear order, ensured by the predicate 'isLinearOrder', satisfies the following axioms:
+
+\(\forall x\,R(x,x)\)
+
+\(\forall x\,\forall y\, R(x, y) \land R(y, x) \Rightarrow x = y\)
+
+\(\forall x\,\forall y\, \forall z\, R(x, y) \land R(y, z) \Rightarrow R(x, z)\)
+
+\(\forall x\,\forall y\, R(x, y) \lor R(y, x)\)
+
+>>> let r        = uninterpret "R" :: Relation U
+>>> let isLinear = isLinearOrder "loR" r
+>>> prove $ \(Forall x) -> isLinear .=> r (x, x)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) -> isLinear .=> (r (x, y) .&& r (y, x) .=> x .== y)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isLinear .=> (r (x, y) .&& r (y, z) .=> r (x, z))
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) -> isLinear .=> (r (x, y) .|| r (y, x))
+Q.E.D.
+-}
+
+-- ** Tree orders
+{- $treeOrder
+A tree order, ensured by the predicate 'isTreeOrder', satisfies the following axioms:
+
+\(\forall x\,R(x,x)\)
+
+\(\forall x\,\forall y\, R(x, y) \land R(y, x) \Rightarrow x = y\)
+
+\(\forall x\,\forall y\, \forall z\, R(x, y) \land R(y, z) \Rightarrow R(x, z)\)
+
+\(\forall x\,\forall y\,\forall z\, (R(y, x) \land R(z, z)) \Rightarrow (R (y, z) \lor R (z, y))\)
+
+>>> let r      = uninterpret "R" :: Relation U
+>>> let isTree = isTreeOrder "toR" r
+>>> prove $ \(Forall x) -> isTree .=> r (x, x)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) -> isTree .=> (r (x, y) .&& r (y, x) .=> x .== y)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isTree .=> (r (x, y) .&& r (y, z) .=> r (x, z))
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isTree .=> ((r (y, x) .&& r (z, x)) .=> (r (y, z) .|| r (z, y)))
+Q.E.D.
+-}
+
+-- ** Piecewise linear orders
+{- $piecewiseLinear
+A piecewise linear order, ensured by the predicate 'isPiecewiseLinearOrder', satisfies the following axioms:
+
+\(\forall x\,R(x,x)\)
+
+\(\forall x\,\forall y\, R(x, y) \land R(y, x) \Rightarrow x = y\)
+
+\(\forall x\,\forall y\, \forall z\, R(x, y) \land R(y, z) \Rightarrow R(x, z)\)
+
+\(\forall x\,\forall y\,\forall z\, (R(x, y) \land R(x, z)) \Rightarrow (R (y, z) \lor R (z, y))\)
+
+\(\forall x\,\forall y\,\forall z\, (R(y, x) \land R(z, x)) \Rightarrow (R (y, z) \lor R (z, y))\)
+
+>>> let r           = uninterpret "R" :: Relation U
+>>> let isPiecewise = isPiecewiseLinearOrder "plR" r
+>>> prove $ \(Forall x) -> isPiecewise .=> r (x, x)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) -> isPiecewise .=> (r (x, y) .&& r (y, x) .=> x .== y)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isPiecewise .=> (r (x, y) .&& r (y, z) .=> r (x, z))
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isPiecewise .=> ((r (x, y) .&& r (x, z)) .=> (r (y, z) .|| r (z, y)))
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> isPiecewise .=> ((r (y, x) .&& r (z, x)) .=> (r (y, z) .|| r (z, y)))
+Q.E.D.
+-}
+
+-- ** Transitive closures
+{- $transitiveClosures
+The transitive closure of a relation can be created using 'mkTransitiveClosure'. Transitive closures
+are not first-order axiomatizable. That is, we cannot write first-order formulas to uniquely
+describe them. However, we can check some of the expected properties:
+
+>>> let r   = uninterpret "R" :: Relation U
+>>> let tcR = mkTransitiveClosure "tcR" r
+>>> prove $ \(Forall x) (Forall y) -> r (x, y) .=> tcR (x, y)
+Q.E.D.
+>>> prove $ \(Forall x) (Forall y) (Forall z) -> r (x, y) .&& r (y, z) .=> tcR (x, z)
+Q.E.D.
+
+What's missing here is the check that if the transitive closure relates two elements, then they are
+connected transitively in the original relation. This requirement is not axiomatizable in first order logic.
+-}
+
+-- | Create a transitive relation of a simple relation and show that transitive connections are respected.
+-- We have:
+--
+-- >>> tcExample1
+-- Q.E.D.
+tcExample1 :: IO ThmResult
+tcExample1 = prove $ do
+  a :: SU <- free "a"
+  b :: SU <- free "b"
+  c :: SU <- free "c"
+
+  let r   = uninterpret "R"
+      tcR = mkTransitiveClosure "tcR" r
+
+  -- Add R(a, b), R(b, c), but explicitly state ~R(a, c)
+  constrain $ r (a, b)
+  constrain $ r (b, c)
+  constrain $ sNot $ r (a, c)
+
+  -- Show that in tcR, a and c are connected
+  pure $ tcR (a, c)
+
+-- | Another transitive-closure example, this time we show the transitive closure is the smallest
+-- relation, i.e., doesn't have extra connections. We have:
+--
+-- >>> tcExample2
+-- Q.E.D.
+tcExample2 :: IO ThmResult
+tcExample2 = prove $ do
+  let r   = uninterpret "r"
+      tcR = mkTransitiveClosure "tcR" r
+
+  -- Add R(A, B), ~R(A, C), ~R(B, C) then it shouldn't be the case that R(a, c)
+  constrain $ r (sA, sB)
+  constrain $ sNot $ r (sA, sC)
+  constrain $ sNot $ r (sB, sC)
+
+  -- Show that in tcR, a and c cannot be connected
+  pure $ sNot $ tcR (sA, sC) :: Predicate
+
+-- | Demonstrates computing the transitive closure of existing relations. We have:
+--
+-- >>> tcExample3
+-- Q.E.D.
+tcExample3 :: IO ThmResult
+tcExample3 = prove $ do
+
+        -- Define a relation over the type 'E', which only relates 'A' to 'B'.
+        let rel :: Relation E
+            rel xy = xy .== (sA, sB)
+
+        -- Create a relation and its transitive closure, and associate it with our function:
+        let tcR = mkTransitiveClosure "R" rel
+
+        -- Show that in tcR, a and c cannot be connected
+        pure $ sNot $ tcR (sA, sC) :: Predicate
diff --git a/Documentation/SBV/Examples/Misc/Floating.hs b/Documentation/SBV/Examples/Misc/Floating.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Floating.hs
@@ -0,0 +1,229 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Floating
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Several examples involving IEEE-754 floating point numbers, i.e., single
+-- precision 'Float' ('SFloat'), double precision 'Double' ('SDouble'), and
+-- the generic 'SFloatingPoint' @eb@ @sb@ type where the user can specify the
+-- exponent and significand bit-widths. (Note that there is always an extra
+-- sign-bit, and the value of @sb@ includes the hidden bit.)
+--
+-- Arithmetic with floating point is full of surprises; due to precision
+-- issues associativity of arithmetic operations typically do not hold. Also,
+-- the presence of @NaN@ is always something to look out for.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Floating where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-----------------------------------------------------------------------------
+-- * FP addition is not associative
+-----------------------------------------------------------------------------
+
+-- | Prove that floating point addition is not associative. For illustration purposes,
+-- we will require one of the inputs to be a @NaN@. We have:
+--
+-- >>> prove $ assocPlus (0/0)
+-- Falsifiable. Counter-example:
+--   s0 = 0.0 :: Float
+--   s1 = 0.0 :: Float
+--
+-- Indeed:
+--
+-- >>> let i = 0/0 :: Float
+-- >>> i + (0.0 + 0.0)
+-- NaN
+-- >>> ((i + 0.0) + 0.0)
+-- NaN
+--
+-- But keep in mind that @NaN@ does not equal itself in the floating point world! We have:
+--
+-- >>> let nan = 0/0 :: Float in nan == nan
+-- False
+assocPlus :: SFloat -> SFloat -> SFloat -> SBool
+assocPlus x y z = x + (y + z) .== (x + y) + z
+
+-- | Prove that addition is not associative, even if we ignore @NaN@/@Infinity@ values.
+-- To do this, we use the predicate 'fpIsPoint', which is true of a floating point
+-- number ('SFloat' or 'SDouble') if it is neither @NaN@ nor @Infinity@. (That is, it's a
+-- representable point in the real-number line.)
+--
+-- We have:
+--
+-- >>> assocPlusRegular
+-- Falsifiable. Counter-example:
+--   x =  2.5291315e20 :: Float
+--   y = -2.9558926e20 :: Float
+--   z =  1.1256507e20 :: Float
+--
+-- Indeed, we have:
+--
+-- >>> let x =  2.5291315e20 :: Float
+-- >>> let y = -2.9558926e20 :: Float
+-- >>> let z =  1.1256507e20 :: Float
+-- >>> x + (y + z)
+-- 6.988897e19
+-- >>> (x + y) + z
+-- 6.988896e19
+--
+-- Note the significant difference in the results!
+assocPlusRegular :: IO ThmResult
+assocPlusRegular = prove $ do [x, y, z] <- sFloats ["x", "y", "z"]
+                              let lhs = x+(y+z)
+                                  rhs = (x+y)+z
+                              -- make sure we do not overflow at the intermediate points
+                              constrain $ fpIsPoint lhs
+                              constrain $ fpIsPoint rhs
+                              pure $ lhs .== rhs
+
+-----------------------------------------------------------------------------
+-- * FP addition by non-zero can result in no change
+-----------------------------------------------------------------------------
+
+-- | Demonstrate that @a+b = a@ does not necessarily mean @b@ is @0@ in the floating point world,
+-- even when we disallow the obvious solution when @a@ and @b@ are @Infinity.@
+-- We have:
+--
+-- >>> nonZeroAddition
+-- Falsifiable. Counter-example:
+--   a = 2.9670994e34 :: Float
+--   b = -7.208359e-5 :: Float
+--
+-- Indeed, we have:
+--
+-- >>> let a = 2.9670994e34 :: Float
+-- >>> let b = -7.208359e-5 :: Float
+-- >>> a + b == a
+-- True
+-- >>> b == 0
+-- False
+nonZeroAddition :: IO ThmResult
+nonZeroAddition = prove $ do [a, b] <- sFloats ["a", "b"]
+                             constrain $ fpIsPoint a
+                             constrain $ fpIsPoint b
+                             constrain $ a + b .== a
+                             pure $ b .== 0
+
+-----------------------------------------------------------------------------
+-- * FP multiplicative inverses may not exist
+-----------------------------------------------------------------------------
+
+-- | This example illustrates that @a * (1/a)@ does not necessarily equal @1@. Again,
+-- we protect against division by @0@ and @NaN@/@Infinity@.
+--
+-- We have:
+--
+-- >>> multInverse
+-- Falsifiable. Counter-example:
+--   a = -2.372672e38 :: Float
+--
+-- Indeed, we have:
+--
+-- >>> let a = -2.372672e38 :: Float
+-- >>> a * (1/a)
+-- 0.99999994
+multInverse :: IO ThmResult
+multInverse = prove $ do a <- sFloat "a"
+                         constrain $ fpIsPoint a
+                         constrain $ fpIsPoint (1/a)
+                         pure $ a * (1/a) .== 1
+
+-----------------------------------------------------------------------------
+-- * Effect of rounding modes
+-----------------------------------------------------------------------------
+
+-- | One interesting aspect of floating-point is that the chosen rounding-mode
+-- can effect the results of a computation if the exact result cannot be precisely
+-- represented. SBV exports the functions 'fpAdd', 'fpSub', 'fpMul', 'fpDiv', 'fpFMA'
+-- and 'fpSqrt' which allows users to specify the IEEE supported 'RoundingMode' for
+-- the operation. This example illustrates how SBV can be used to find rounding-modes
+-- where, for instance, addition can produce different results. We have:
+--
+-- >>> roundingAdd
+-- Satisfiable. Model:
+--   rm = RoundTowardPositive :: RoundingMode
+--   x  =          -4.0039067 :: Float
+--   y  =            131076.0 :: Float
+--
+-- (Note that depending on your version of Z3, you might get a different result.)
+-- Unfortunately Haskell floats do not allow computation with arbitrary rounding modes, but SBV's
+-- 'SFloatingPoint' type does. We have:
+--
+-- >>> sat $ \x -> x .== (fpAdd sRoundTowardPositive (-4.0039067) 131076.0 :: SFloat)
+-- Satisfiable. Model:
+--   s0 = 131072.0 :: Float
+-- >>> (-4.0039067) + 131076.0 :: Float
+-- 131071.99
+--
+-- We can see why these two results are indeed different: The 'RoundTowardPositive
+-- (which rounds towards positive infinity) produces a larger result.
+--
+-- >>> (-4.0039067) + 131076.0 :: Double
+-- 131071.9960933
+--
+-- we see that the "more precise" result is larger than what the 'Float' value is, justifying the
+-- larger value with 'RoundTowardPositive. A more detailed study is beyond our current scope, so we'll
+-- merely note that floating point representation and semantics is indeed a thorny subject.
+roundingAdd :: IO SatResult
+roundingAdd = sat $ do m :: SRoundingMode <- free "rm"
+                       constrain $ m ./= literal RoundNearestTiesToEven
+                       x <- sFloat "x"
+                       y <- sFloat "y"
+                       let lhs = fpAdd m x y
+                       let rhs = x + y
+                       constrain $ fpIsPoint lhs
+                       constrain $ fpIsPoint rhs
+                       pure $ lhs ./= rhs
+
+-- | Arbitrary precision floating-point numbers. SBV can talk about floating point numbers with arbitrary
+-- exponent and significand sizes as well. Here is a simple example demonstrating the minimum non-zero positive
+-- and maximum floating point values with exponent width 5 and significand width 4, which is actually 3
+-- bits for the significand explicitly stored, includes the hidden bit. We have:
+--
+-- >>> fp54Bounds
+-- Objective "toMetricSpace(max)": Optimal model:
+--   x = 61440 :: FloatingPoint 5 4
+-- Objective "toMetricSpace(min)": Optimal model:
+--   x = 0.000007629 :: FloatingPoint 5 4
+--
+-- An important note is in order. When printing floats in decimal, one can get correct yet surprising results.
+-- There's a large body of publications in how to render floats in decimal, or in bases that are not powers of
+-- two in general. So, when looking at such values in decimal, keep in mind that what you see might be
+-- a representative value: That is, it preserves the value when translated back to the format. For instance,
+-- the more precise answer for the min value would be 2^-17, which is 0.00000762939453125. But we see
+-- it truncated here. In fact, any number between 2^-16 and 2^-17 would be correct as they all map to the same
+-- underlying representation in this format. Moral of the story is that when reading floating-point numbers in
+-- decimal notation one should be very careful about the printed representation and the numeric value; while
+-- they will match in value (if there are no bugs!), they can print quite differently! (Also keep in
+-- mind the rounding modes that impact how the conversion is done.)
+--
+-- One final note: When printing the models, we skip optimization variables that are not named @x@. See the
+-- call to `Data.SBV.Core.Symbolic.isNonModelVal`. When we optimize floating-point values, the underlying engine actually optimizes
+-- with bit-vector values, producing intermediate results. We skip those here to simplify the presentation.
+fp54Bounds :: IO OptimizeResult
+fp54Bounds = optimizeWith z3{isNonModelVar = (/= "x")}
+                          Independent $ do x :: SFloatingPoint 5 4 <- sFloatingPoint "x"
+
+                                           constrain $ fpIsPoint x
+                                           constrain $ x .> 0
+
+                                           maximize "max" x
+                                           minimize "min" x
+
+                                           pure sTrue
diff --git a/Documentation/SBV/Examples/Misc/LambdaArray.hs b/Documentation/SBV/Examples/Misc/LambdaArray.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/LambdaArray.hs
@@ -0,0 +1,70 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.LambdaArray
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how lambda-abstractions can be used to model arrays.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.LambdaArray where
+
+import Data.SBV
+
+-- | Given an array, and bounds on it, initialize it within the bounds to the element given.
+-- Otherwise, leave it untouched.
+memset :: SArray Integer Integer -> SInteger -> SInteger -> SInteger -> SArray Integer Integer
+memset mem lo hi newVal = lambdaArray update
+  where update :: SInteger -> SInteger
+        update idx = let oldVal = readArray mem idx
+                     in ite (lo .<= idx .&& idx .<= hi) newVal oldVal
+
+-- | Prove a simple property: If we read from the initialized region, we get the initial value. We have:
+--
+-- >>> memsetExample
+-- Q.E.D.
+memsetExample :: IO ThmResult
+memsetExample = prove $ do
+   mem   <- sArray   "mem"
+   lo    <- sInteger "lo"
+   hi    <- sInteger "hi"
+   zeroV <- sInteger "zero"
+
+   -- Get an index within lo/hi
+   idx  <- sInteger "idx"
+   constrain $ idx .>= lo .&& idx .<= hi
+
+   -- It must be the case that we get zero back after mem-setting
+   pure $ readArray (memset mem lo hi zeroV) idx .== zeroV
+
+-- | Get an example of reading a value out of range. The value returned should be out-of-range for lo/hi
+--
+-- >>> outOfInit
+-- Satisfiable. Model:
+--   mem  = ([], 1) :: Array Integer Integer
+--   lo   =       0 :: Integer
+--   hi   =       0 :: Integer
+--   zero =       0 :: Integer
+--   idx  =       1 :: Integer
+--   Read =       1 :: Integer
+outOfInit :: IO SatResult
+outOfInit = sat $ do
+   mem   <- sArray "mem"
+   lo    <- sInteger "lo"
+   hi    <- sInteger "hi"
+   zeroV <- sInteger "zero"
+
+   -- Get a meaningful range:
+   constrain $ lo .<= hi
+
+   -- Get an index
+   idx  <- sInteger "idx"
+
+   -- Let read produce non-zero
+   constrain $ observe "Read" (readArray (memset mem lo hi zeroV) idx) ./= zeroV
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Misc/ModelExtract.hs b/Documentation/SBV/Examples/Misc/ModelExtract.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/ModelExtract.hs
@@ -0,0 +1,48 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.ModelExtract
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates use of programmatic model extraction. When programming with
+-- SBV, we typically use `sat`/`allSat` calls to compute models automatically.
+-- In more advanced uses, however, the user might want to use programmable
+-- extraction features to do fancier programming. We demonstrate some of
+-- these utilities here.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.ModelExtract where
+
+import Data.SBV
+
+-- | A simple function to generate a new integer value, that is not in the
+-- given set of values. We also require the value to be non-negative
+outside :: [Integer] -> IO SatResult
+outside disallow = sat $ do x <- sInteger "x"
+                            let notEq i = constrain $ x ./= literal i
+                            mapM_ notEq disallow
+                            pure $ x .>= 0
+
+-- | We now use "outside" repeatedly to generate 10 integers, such that we not only disallow
+-- previously generated elements, but also any value that differs from previous solutions
+-- by less than 5.  Here, we use the `getModelValue` function. We could have also extracted the dictionary
+-- via `getModelDictionary` and did fancier programming as well, as necessary. We have:
+--
+-- >>> genVals
+-- [45,40,35,30,25,20,15,10,5,0]
+genVals :: IO [Integer]
+genVals = go [] []
+  where go _ model
+         | length model >= 10 = pure model
+        go disallow model
+          = do res <- outside disallow
+               -- Look up the value of "x" in the generated model
+               -- Note that we simply get an integer here; but any
+               -- SBV known type would be OK as well.
+               case "x" `getModelValue` res of
+                 Just c -> go ([c-4 .. c+4] ++ disallow) (c : model)
+                 _      -> pure model
diff --git a/Documentation/SBV/Examples/Misc/NestedArray.hs b/Documentation/SBV/Examples/Misc/NestedArray.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/NestedArray.hs
@@ -0,0 +1,42 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.NestedArray
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how to model nested-arrays, i.e., arrays of arrays in SBV.
+-- Instead of SMTLib's nested model, in SBV we use a tuple as an index,
+-- which is isomorphic to nested arrays.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.NestedArray where
+
+import Data.SBV
+import Data.SBV.Tuple
+import Data.SBV.Control
+
+-- | Model a nested array that is indexed by integers, and we store
+-- another integer to integer array in each index. We have:
+--
+-- >>> nestedArray
+-- (0,10)
+nestedArray :: IO (Integer, Integer)
+nestedArray = runSMT $ do
+  idx <- sInteger "idx"
+  arr <- sArray_ :: Symbolic (SArray (Integer, Integer) Integer)
+
+  -- we'll assert that arr[idx][idx] = 10
+  let val = readArray arr (tuple (idx, idx))
+  constrain $ val .== literal 10
+
+  query $ do
+    cs <- checkSat
+    case cs of
+      Sat -> do idxVal <- getValue idx
+                elt    <- getValue (readArray arr (tuple (idx, idx)))
+                pure (idxVal, elt)
+      _   -> error $ "Solver said: " ++ show cs
diff --git a/Documentation/SBV/Examples/Misc/Newtypes.hs b/Documentation/SBV/Examples/Misc/Newtypes.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Newtypes.hs
@@ -0,0 +1,97 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Newtypes
+-- Copyright : (c) Curran McConnell
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how to create symbolic newtypes with the same behaviour as
+-- their wrapped type.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                        #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE ScopedTypeVariables        #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Newtypes where
+
+import Prelude hiding (ceiling)
+import Data.SBV
+import qualified Data.SBV.Internals as SI
+import Test.QuickCheck(Arbitrary)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | A t'Metres' is a newtype wrapper around 'Integer'.
+newtype Metres = Metres Integer deriving (Real, Integral, Num, Enum, Eq, Ord, Arbitrary)
+
+-- | Symbolic version of t'Metres'.
+type SMetres = SBV Metres
+
+-- | To use t'Metres' symbolically, we associate it with the underlying symbolic
+-- type's kind.
+instance HasKind Metres where
+   kindOf _ = KUnbounded
+
+-- | The 'SymVal' instance simply uses stock definitions. This is always
+-- possible for newtypes that simply wrap over an existing symbolic type.
+instance SymVal Metres where
+   mkSymVal    = SI.genMkSymVar KUnbounded
+   literal     = SI.genLiteral  KUnbounded
+   fromCV      = SI.genFromCV
+   minMaxBound = Nothing
+
+-- | Similarly, we can create another newtype, this time wrapping over 'Word16'. As an example,
+-- consider measuring the human height in centimetres? The tallest person in history,
+-- Robert Wadlow, was 272 cm. We don't need negative values, so 'Word16' is the smallest type that
+-- suits our needs.
+newtype HumanHeightInCm = HumanHeightInCm Word16 deriving (Real, Integral, Num, Enum, Eq, Ord, Bounded, Arbitrary)
+
+-- | Symbolic version of t'HumanHeightInCm'.
+type SHumanHeightInCm = SBV HumanHeightInCm
+
+-- | Symbolic instance simply follows the underlying type, just like t'Metres'.
+instance HasKind HumanHeightInCm where
+    kindOf _ = KBounded False 16
+
+-- | Similarly here, for the 'SymVal' instance.
+instance SymVal HumanHeightInCm where
+    mkSymVal = SI.genMkSymVar $ KBounded False 16
+    literal  = SI.genLiteral  $ KBounded False 16
+    fromCV   = SI.genFromCV
+
+-- | The tallest human ever was 272 cm. We can simply use 'literal' to lift it
+-- to the symbolic space.
+tallestHumanEver :: SHumanHeightInCm
+tallestHumanEver = literal 272
+
+-- | Given a distance between a floor and a ceiling, we can see whether
+-- the human can stand in that room. Comparison is expressed using 'sFromIntegral'.
+ceilingHighEnoughForHuman :: SMetres -> SHumanHeightInCm -> SBool
+ceilingHighEnoughForHuman ceiling humanHeight = humanHeight' .< ceiling'
+    where -- In a real codebase, the code for comparing these newtypes
+          -- should be reusable, perhaps through a typeclass.
+        ceiling'     = literal 100 * sFromIntegral ceiling :: SInteger
+        humanHeight' = sFromIntegral humanHeight :: SInteger
+
+-- | Now, suppose we want to see whether we could design a room with a ceiling
+-- high enough that any human could stand in it. We have:
+--
+-- >>> sat problem
+-- Satisfiable. Model:
+--   floorToCeiling =   3 :: Integer
+--   humanheight    = 272 :: Word16
+problem :: Predicate
+problem = do
+    ceiling     :: SMetres          <- free "floorToCeiling"
+    humanHeight :: SHumanHeightInCm <- free "humanheight"
+    constrain $ humanHeight .== tallestHumanEver
+
+    pure $ ceilingHighEnoughForHuman ceiling humanHeight
diff --git a/Documentation/SBV/Examples/Misc/NoDiv0.hs b/Documentation/SBV/Examples/Misc/NoDiv0.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/NoDiv0.hs
@@ -0,0 +1,46 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.NoDiv0
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates SBV's assertion checking facilities
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ImplicitParams #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.NoDiv0 where
+
+import Data.SBV
+import GHC.Stack
+
+-- | A simple variant of division, where we explicitly require the
+-- caller to make sure the divisor is not 0.
+checkedDiv :: (?loc :: CallStack) => SInt32 -> SInt32 -> SInt32
+checkedDiv x y = sAssert (Just ?loc)
+                         "Divisor should not be 0"
+                         (y ./= 0)
+                         (x `sDiv` y)
+
+-- | Check whether an arbitrary call to 'checkedDiv' is safe. Clearly, we do not expect
+-- this to be safe:
+--
+-- >>> test1
+-- [./Documentation/SBV/Examples/Misc/NoDiv0.hs:38:14:checkedDiv: Divisor should not be 0: Violated. Model:
+--   s0 = 0 :: Int32
+--   s1 = 0 :: Int32]
+--
+test1 :: IO [SafeResult]
+test1 = safe checkedDiv
+
+-- | Repeat the test, except this time we explicitly protect against the bad case. We have:
+--
+-- >>> test2
+-- [./Documentation/SBV/Examples/Misc/NoDiv0.hs:46:41:checkedDiv: Divisor should not be 0: No violations detected]
+--
+test2 :: IO [SafeResult]
+test2 = safe $ \x y -> ite (y .== 0) 3 (checkedDiv x y)
diff --git a/Documentation/SBV/Examples/Misc/Polynomials.hs b/Documentation/SBV/Examples/Misc/Polynomials.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Polynomials.hs
@@ -0,0 +1,80 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Polynomials
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Simple usage of polynomials over GF(2^n), using Rijndael's
+-- finite field: <http://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field>
+--
+-- The functions available are:
+--
+--  [/pMult/] GF(2^n) Multiplication
+--
+--  [/pDiv/] GF(2^n) Division
+--
+--  [/pMod/] GF(2^n) Modulus
+--
+--  [/pDivMod/] GF(2^n) Division/Modulus, packed together
+--
+-- Note that addition in GF(2^n) is simply `xor`, so no custom function is provided.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Polynomials where
+
+import Data.SBV
+import Data.SBV.Tools.Polynomial
+
+-- | Helper synonym for representing GF(2^8); which are merely 8-bit unsigned words. Largest
+-- term in such a polynomial has degree 7.
+type GF28 = SWord8
+
+-- | Multiplication in Rijndael's field; usual polynomial multiplication followed by reduction
+-- by the irreducible polynomial.  The irreducible used by Rijndael's field is the polynomial
+-- @x^8 + x^4 + x^3 + x + 1@, which we write by giving it's /exponents/ in SBV.
+-- See: <http://en.wikipedia.org/wiki/Finite_field_arithmetic#Rijndael.27s_finite_field>.
+-- Note that the irreducible itself is not in GF28! It has a degree of 8.
+--
+-- NB. You can use the 'showPoly' function to print polynomials nicely, as a mathematician would write.
+gfMult :: GF28 -> GF28 -> GF28
+a `gfMult` b = pMult (a, b, [8, 4, 3, 1, 0])
+
+-- | States that the unit polynomial @1@, is the unit element
+multUnit :: GF28 -> SBool
+multUnit x = (x `gfMult` unit) .== x
+  where unit = polynomial [0]   -- x@0
+
+-- | States that multiplication is commutative
+multComm :: GF28 -> GF28 -> SBool
+multComm x y = (x `gfMult` y) .== (y `gfMult` x)
+
+-- | States that multiplication is associative, note that associativity
+-- proofs are notoriously hard for SAT/SMT solvers
+multAssoc :: GF28 -> GF28 -> GF28 -> SBool
+multAssoc x y z = ((x `gfMult` y) `gfMult` z) .== (x `gfMult` (y `gfMult` z))
+
+-- | States that the usual multiplication rule holds over GF(2^n) polynomials
+-- Checks:
+--
+-- @
+--    if (a, b) = x `pDivMod` y then x = y `pMult` a + b
+-- @
+--
+-- being careful about @y = 0@. When divisor is 0, then quotient is
+-- defined to be 0 and the remainder is the numerator.
+-- (Note that addition is simply `xor` in GF(2^8).)
+polyDivMod :: GF28 -> GF28 -> SBool
+polyDivMod x y = ite (y .== 0) ((0, x) .== (a, b)) (x .== (y `gfMult` a) `xor` b)
+  where (a, b) = x `pDivMod` y
+
+-- | Queries
+testGF28 :: IO ()
+testGF28 = do
+  print =<< prove multUnit
+  print =<< prove multComm
+  -- print =<< prove multAssoc -- takes too long; see above note..
+  print =<< prove polyDivMod
diff --git a/Documentation/SBV/Examples/Misc/ProgramPaths.hs b/Documentation/SBV/Examples/Misc/ProgramPaths.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/ProgramPaths.hs
@@ -0,0 +1,83 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.ProgramPaths
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A simple example of showing how to compute program paths. Consider the simple
+-- program:
+--
+-- @
+--   d1 x y = if y < x - 2  then   7 else   2
+--   d2   y = if y > 3      then  10 else  50
+--   d3 x y = if y < -x + 3 then 100 else 200
+--   d4 x y = d1 x y + d2 y + d3 x y
+-- @
+--
+-- What are all the possible values @d4 x y@ can take, and what are the values of
+-- @x@ and @y@ to obtain these values?
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.ProgramPaths where
+
+import Data.SBV
+
+-- | Symbolic version of @d1 x y = if y < x - 2 then 7 else 2@
+d1 :: SInteger -> SInteger -> SInteger
+d1 x y = ite (y .< x - 2) 7 2
+
+-- | Symbolic version of @d2 y = if y > 3 then  10 else  50@
+d2 :: SInteger -> SInteger
+d2 y = ite (y .> 3) 10 50
+
+-- | Symbolic version of @d3 x y = if y < -x + 3 then 100 else 200@
+d3 :: SInteger -> SInteger -> SInteger
+d3 x y = ite (y .< -x + 3) 100 200
+
+-- | Symbolic version of @d4 x y = d1 x y + d2 x y + d3 x y@
+d4 :: SInteger -> SInteger -> SInteger
+d4 x y = d1 x y + d2 y + d3 x y
+
+-- | Compute all possible program paths. Note the call to `allSatPartition`, which
+-- causes `allSat` to find models that generate differing values for the given
+-- expression. We have:
+--
+-- >>> paths
+-- Solution #1:
+--   x =  -2 :: Integer
+--   y =   4 :: Integer
+--   r = 112 :: Integer
+-- Solution #2:
+--   x =   0 :: Integer
+--   y =   3 :: Integer
+--   r = 252 :: Integer
+-- Solution #3:
+--   x =  -1 :: Integer
+--   y =   4 :: Integer
+--   r = 212 :: Integer
+-- Solution #4:
+--   x =   3 :: Integer
+--   y =   0 :: Integer
+--   r = 257 :: Integer
+-- Solution #5:
+--   x =   2 :: Integer
+--   y =  -1 :: Integer
+--   r = 157 :: Integer
+-- Solution #6:
+--   x =   7 :: Integer
+--   y =   4 :: Integer
+--   r = 217 :: Integer
+-- Solution #7:
+--   x =   0 :: Integer
+--   y =   0 :: Integer
+--   r = 152 :: Integer
+-- Found 7 different solutions.
+paths :: IO AllSatResult
+paths = allSat $ do
+  x <- sInteger "x"
+  y <- sInteger "y"
+  allSatPartition "r" $ d4 x y
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,364 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.SetAlgebra where
+
+import Data.SBV hiding (complement)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV hiding (complement)
+-- >>> import Data.SBV.Set
+-- >>> :set -XScopedTypeVariables
+#endif
+
+-- | Abbreviation for set of integers. For convenience only in monomorphising the properties.
+type SI = SSet Integer
+
+-- * 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
+
+\((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
+\(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
+
+\(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
+
+\( 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
+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
+
+\( 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
+
+\( 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
+
+\( 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
+
+\( 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
+
+\( (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
+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
+
+\( 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
+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
+
+\( 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
+
+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 =     {2} :: {Integer}
+  s1 =       U :: {Integer}
+  s2 = U - {2} :: {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 = U - {2} :: {Integer}
+  s1 = U - {2} :: {Integer}
+  s2 =     {2} :: {Integer}
+-}
diff --git a/Documentation/SBV/Examples/Misc/SoftConstrain.hs b/Documentation/SBV/Examples/Misc/SoftConstrain.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/SoftConstrain.hs
@@ -0,0 +1,47 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.SoftConstrain
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates soft-constraints, i.e., those that the solver
+-- is free to leave unsatisfied. Solvers will try to satisfy
+-- this constraint, unless it is impossible to do so to get
+-- a model. Can be good in modeling default values, for instance.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.SoftConstrain where
+
+import Data.SBV
+
+-- | Create two strings, requiring one to be a particular value, constraining the other
+-- to be different than another constant string. But also add soft constraints to
+-- indicate our preferences for each of these variables. We get:
+--
+-- >>> example
+-- Satisfiable. Model:
+--   x = "x-must-really-be-hello" :: String
+--   y =        "default-y-value" :: String
+--
+-- Note how the value of @x@ is constrained properly and thus the default value
+-- doesn't kick in, but @y@ takes the default value since it is acceptable by
+-- all the other hard constraints.
+example :: IO SatResult
+example = sat $ do x <- sString "x"
+                   y <- sString "y"
+
+                   constrain $ x .== "x-must-really-be-hello"
+                   constrain $ y ./= "y-can-be-anything-but-hello"
+
+                   -- Now add soft-constraints to indicate our preference
+                   -- for what these variables should be:
+                   softConstrain $ x .== "default-x-value"
+                   softConstrain $ y .== "default-y-value"
+
+                   pure sTrue
diff --git a/Documentation/SBV/Examples/Misc/Tuple.hs b/Documentation/SBV/Examples/Misc/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/Tuple.hs
@@ -0,0 +1,79 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.Tuple
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A basic tuple use case, also demonstrating regular expressions,
+-- strings, etc. This is a basic template for getting SBV to produce
+-- valid data for applications that require inputs that satisfy
+-- arbitrary criteria.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Misc.Tuple where
+
+import Data.SBV
+import Data.SBV.Tuple
+import Data.SBV.Control
+
+import Prelude hiding ((!!))
+import Data.SBV.List   ((!!))
+import Data.SBV.RegExp
+
+import qualified Data.SBV.List as L
+
+-- | A dictionary is a list of lookup values. Note that we
+-- store the type @[(a, b)]@ as a symbolic value here, mixing
+-- sequences and tuples.
+type Dict a b = SBV [(a, b)]
+
+-- | Create a dictionary of length 5, such that each element
+-- has an string key and each value is the length of the key.
+-- We impose a few more constraints to make the output interesting.
+-- For instance, you might get:
+--
+-- @ ghci> example
+-- [("nt_",3),("dHAk",4),("kzkk0",5),("mZxs9s",6),("c32'dPM",7)]
+-- @
+--
+-- Depending on your version of z3, a different answer might be provided.
+-- Here, we check that it satisfies our length conditions:
+--
+-- >>> import Data.List (genericLength)
+-- >>> example >>= \ex -> return (length ex == 5 && all (\(l, i) -> genericLength l == i) ex)
+-- True
+example :: IO [(String, Integer)]
+example = runSMT $ do dict :: Dict String Integer <- free "dict"
+
+                      -- require precisely 5 elements
+                      let len   = 5 :: Int
+                          range = [0 .. len - 1]
+
+                      constrain $ L.length dict .== fromIntegral len
+
+                      -- require each key to be at of length 3 more than the index it occupies
+                      -- and look like an identifier
+                      let goodKey i s = let l = L.length s
+                                            r = asciiLower * KStar (asciiLetter + digit + "_" + "'")
+                                      in l .== fromIntegral i+3 .&& s `match` r
+
+                          restrict i = case untuple (dict !! fromIntegral i) of
+                                         (k, v) -> constrain $ goodKey i k .&& v .== L.length k
+
+                      mapM_ restrict range
+
+                      -- require distinct keys:
+                      let keys = [(dict !! fromIntegral i)^._1 | i <- range]
+                      constrain $ distinct keys
+
+                      query $ do ensureSat
+                                 getValue dict
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,99 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+{-# LANGUAGE TypeFamilies      #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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.
+mkSymbolic [''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 .== sMon) 0
+                    $ ite (x .== sTue) 1
+                    $ ite (x .== sWed) 2
+                    $ ite (x .== sThu) 3
+                    $ ite (x .== sFri) 4
+                    $ ite (x .== sSat) 5
+                                       6
+
+  fromMetricSpace x = ite (x .== 0) sMon
+                    $ ite (x .== 1) sTue
+                    $ ite (x .== 2) sWed
+                    $ ite (x .== 3) sThu
+                    $ ite (x .== 4) sFri
+                    $ ite (x .== 5) sSat
+                                    sSun
+
+  annotateForMS _ s = "DayAsWord8(" ++ s ++ ")"
+
+-- | Identify weekend days
+isWeekend :: SDay -> SBool
+isWeekend = (`sElem` weekend)
+  where weekend = [sSat, sSun]
+
+-- | Using optimization, find the latest day that is not a weekend.
+-- We have:
+--
+-- >>> almostWeekend
+-- Optimal model:
+--   almostWeekend        = Fri :: Day
+--   DayAsWord8(last-day) =   4 :: Word8
+--   last-day             = Fri :: Day
+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
+--   DayAsWord8(first-day) =   0 :: Word8
+--   first-day             = Mon :: Day
+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
+--   DayAsWord8(first-weekend) =   5 :: Word8
+--   first-weekend             = Sat :: Day
+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
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Optimization/ExtField.hs
@@ -0,0 +1,54 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Optimization.ExtField
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates the extension field (@oo@/@epsilon@) optimization results.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Optimization.ExtField where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Optimization goals where min/max values might require assignments
+-- to values that are infinite (integer case), or infinite/epsilon (real case).
+-- This simple example demonstrates how SBV can be used to extract such values.
+--
+-- We have:
+--
+-- >>> optimize Independent problem
+-- Objective "one-x": Optimal in an extension field:
+--   one-x =  oo :: Integer
+--   min_y = 7.0 :: Real
+--   min_z = 5.0 :: Real
+-- Objective "min_y": Optimal in an extension field:
+--   one-x =  oo :: Integer
+--   min_y = 7.0 :: Real
+--   min_z = 5.0 :: Real
+-- Objective "min_z": Optimal in an extension field:
+--   one-x =  oo :: Integer
+--   min_y = 7.0 :: Real
+--   min_z = 5.0 :: Real
+problem :: ConstraintSet
+problem = do x <- sInteger "x"
+             y <- sReal "y"
+             z <- sReal "z"
+
+             maximize "one-x" $ 1 - x
+
+             constrain $ y .>= 0 .&& z .>= 5
+             minimize "min_y" $ 2+y+z
+
+             minimize "min_z" z
diff --git a/Documentation/SBV/Examples/Optimization/LinearOpt.hs b/Documentation/SBV/Examples/Optimization/LinearOpt.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Optimization/LinearOpt.hs
@@ -0,0 +1,50 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Optimization.LinearOpt
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Simple linear optimization example, as found in operations research texts.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Optimization.LinearOpt where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Taken from <http://people.brunel.ac.uk/~mastjjb/jeb/or/morelp.html>
+--
+--    *  maximize 5x1 + 6x2
+--       - subject to
+--
+--          1. x1 + x2 <= 10
+--          2. x1 - x2 >= 3
+--          3. 5x1 + 4x2 <= 35
+--          4. x1 >= 0
+--          5. x2 >= 0
+--
+-- >>> optimize Lexicographic problem
+-- Optimal model:
+--   x1   =  47 % 9 :: Real
+--   x2   =  20 % 9 :: Real
+--   goal = 355 % 9 :: Real
+problem :: ConstraintSet
+problem = do [x1, x2] <- mapM sReal ["x1", "x2"]
+
+             constrain $ x1 + x2 .<= 10
+             constrain $ x1 - x2 .>= 3
+             constrain $ 5*x1 + 4*x2 .<= 35
+             constrain $ x1 .>= 0
+             constrain $ x2 .>= 0
+
+             maximize "goal" $ 5 * x1 + 6 * x2
diff --git a/Documentation/SBV/Examples/Optimization/Production.hs b/Documentation/SBV/Examples/Optimization/Production.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Optimization/Production.hs
@@ -0,0 +1,76 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Optimization.Production
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves a simple linear optimization problem
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Optimization.Production where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Taken from <http://people.brunel.ac.uk/~mastjjb/jeb/or/morelp.html>
+--
+-- A company makes two products (X and Y) using two machines (A and B).
+--
+--   - Each unit of X that is produced requires 50 minutes processing time on machine
+--     A and 30 minutes processing time on machine B.
+--
+--   - Each unit of Y that is produced requires 24 minutes processing time on machine
+--     A and 33 minutes processing time on machine B.
+--
+--   - At the start of the current week there are 30 units of X and 90 units of Y in stock.
+--     Available processing time on machine A is forecast to be 40 hours and on machine B is
+--     forecast to be 35 hours.
+--
+--   - The demand for X in the current week is forecast to be 75 units and for Y is forecast
+--     to be 95 units.
+--
+--   - Company policy is to maximise the combined sum of the units of X and the units of Y
+--     in stock at the end of the week.
+--
+-- How much of each product should we make in the current week?
+--
+-- We have:
+--
+-- >>> optimize Lexicographic production
+-- Optimal model:
+--   X     = 45 :: Integer
+--   Y     =  6 :: Integer
+--   stock =  1 :: Integer
+--
+-- That is, we should produce 45 X's and 6 Y's, with the final maximum stock of just 1 expected!
+production :: ConstraintSet
+production = do x <- sInteger "X" -- Units of X produced
+                y <- sInteger "Y" -- Units of X produced
+
+                -- Amount of time on machine A and B
+                let timeA = 50 * x + 24 * y
+                    timeB = 30 * x + 33 * y
+
+                constrain $ timeA .<= 40 * 60
+                constrain $ timeB .<= 35 * 60
+
+                -- Amount of product we'll end up with
+                let finalX = x + 30
+                    finalY = y + 90
+
+                -- Make sure the demands are met:
+                constrain $ finalX .>= 75
+                constrain $ finalY .>= 95
+
+                -- Policy: Maximize the final stock
+                maximize "stock" $ (finalX - 75) + (finalY - 95)
diff --git a/Documentation/SBV/Examples/Optimization/VM.hs b/Documentation/SBV/Examples/Optimization/VM.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Optimization/VM.hs
@@ -0,0 +1,96 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Optimization.VM
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves a VM allocation problem using optimization features
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Optimization.VM where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Computer allocation problem:
+--
+--   - We have three virtual machines (VMs) which require 100, 50 and 15 GB hard disk respectively.
+--
+--   - There are three servers with capabilities 100, 75 and 200 GB in that order.
+--
+--   - Find out a way to place VMs into servers in order to
+--
+--        - Minimize the number of servers used
+--
+--        - Minimize the operation cost (the servers have fixed daily costs 10, 5 and 20 USD respectively.)
+--
+-- We have:
+--
+-- >>> optimize Lexicographic allocate
+-- Optimal model:
+--   x11         = False :: Bool
+--   x12         = False :: Bool
+--   x13         =  True :: Bool
+--   x21         = False :: Bool
+--   x22         = False :: Bool
+--   x23         =  True :: Bool
+--   x31         = False :: Bool
+--   x32         = False :: Bool
+--   x33         =  True :: Bool
+--   noOfServers =     1 :: Integer
+--   cost        =    20 :: Integer
+--
+-- That is, we should put all the jobs on the third server, for a total cost of 20.
+allocate :: ConstraintSet
+allocate = do
+    -- xij means VM i is running on server j
+    x1@[x11, x12, x13] <- sBools ["x11", "x12", "x13"]
+    x2@[x21, x22, x23] <- sBools ["x21", "x22", "x23"]
+    x3@[x31, x32, x33] <- sBools ["x31", "x32", "x33"]
+
+    -- Each job runs on exactly one server
+    constrain $ pbStronglyMutexed x1
+    constrain $ pbStronglyMutexed x2
+    constrain $ pbStronglyMutexed x3
+
+    let need :: [SBool] -> SInteger
+        need rs = sum $ zipWith (\r c -> ite r c 0) rs [100, 50, 15]
+
+    -- The capacity on each server is respected
+    let capacity1 = need [x11, x21, x31]
+        capacity2 = need [x12, x22, x32]
+        capacity3 = need [x13, x23, x33]
+
+    constrain $ capacity1 .<= 100
+    constrain $ capacity2 .<=  75
+    constrain $ capacity3 .<= 200
+
+    -- compute #of servers running:
+    let y1 = sOr [x11, x21, x31]
+        y2 = sOr [x12, x22, x32]
+        y3 = sOr [x13, x23, x33]
+
+        b2n b = ite b 1 0
+
+    let noOfServers = sum $ map b2n [y1, y2, y3]
+
+    -- minimize # of servers
+    minimize "noOfServers" (noOfServers :: SInteger)
+
+    -- cost on each server
+    let cost1 = ite y1 10 0
+        cost2 = ite y2  5 0
+        cost3 = ite y3 20 0
+
+    -- minimize the total cost
+    minimize "cost" (cost1 + cost2 + cost3 :: SInteger)
diff --git a/Documentation/SBV/Examples/ProofTools/AddHorn.hs b/Documentation/SBV/Examples/ProofTools/AddHorn.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ProofTools/AddHorn.hs
@@ -0,0 +1,108 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ProofTools.AddHorn
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Example of invariant generation for a simple addition algorithm:
+--
+-- @
+--    z = x
+--    i = 0
+--    assume y > 0
+--
+--    while (i < y)
+--       z = z + 1
+--       i = i + 1
+--
+--   assert z == x + y
+-- @
+--
+-- We use the Horn solver to calculate the invariant and then show that it
+-- indeed is a sufficient invariant to establish correctness.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP       #-}
+{-# LANGUAGE DataKinds #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ProofTools.AddHorn where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Helper type synonym for the invariant.
+type Inv = (SInteger, SInteger, SInteger, SInteger) -> SBool
+
+-- | Helper type synonym for verification conditions.
+type VC = Forall "x" Integer -> Forall "y" Integer -> Forall "z" Integer -> Forall "i" Integer -> SBool
+
+-- | Helper for turning an invariant predicate to a boolean.
+quantify :: Inv -> VC
+quantify f = \(Forall x) (Forall y) (Forall z) (Forall i) -> f (x, y, z, i)
+
+-- | First verification condition: Before the loop starts, invariant must hold:
+--
+-- \(z = x \land i = 0 \land y > 0 \Rightarrow inv (x, y, z, i)\)
+vc1 :: Inv -> VC
+vc1 inv = quantify $ \(x, y, z, i) -> z .== x .&& i .== 0 .&& y .> 0 .=> inv (x, y, z, i)
+
+-- | Second verification condition: If the loop body executes, invariant must still hold at the end:
+--
+-- \(inv (x, y, z, i) \land i < y \Rightarrow inv (x, y, z+1, i+1)\)
+vc2 :: Inv -> VC
+vc2 inv = quantify $ \(x, y, z, i) -> inv (x, y, z, i) .&& i .< y .=> inv (x, y, z+1, i+1)
+
+-- | Third verification condition: Once the loop exits, invariant and the negation of the loop condition
+-- must establish the final assertion:
+--
+-- \(inv (x, y, z, i) \land i \geq y \Rightarrow z == x + y\)
+vc3 :: Inv -> VC
+vc3 inv = quantify $ \(x, y, z, i) -> inv (x, y, z, i) .&& i .>= y .=> z .== x + y
+
+-- | Synthesize the invariant. We use an uninterpreted function for the SMT solver to synthesize. We get:
+--
+-- >>> synthesize
+-- Satisfiable. Model:
+--   invariant :: (Integer, Integer, Integer, Integer) -> Bool
+--   invariant (x, y, z, i) = x + (-z) + i > (-1) && x + (-z) + i < 1 && x + y + (-z) > (-1)
+--
+-- This is a bit hard to read, but you can convince yourself it is equivalent to @x + i .== z .&& x + y .>= z@:
+--
+-- >>> let f (x, y, z, i) = x + (-z) + i .> (-1) .&& x + (-z) + i .< 1 .&& x + y + (-z) .> (-1)
+-- >>> let g (x, y, z, i) = x + i .== z .&& x + y .>= z
+-- >>> f === (g :: Inv)
+-- Q.E.D.
+synthesize :: IO SatResult
+synthesize = sat vcs
+  where invariant :: Inv
+        invariant = uninterpretWithArgs "invariant" ["x", "y", "z", "i"]
+
+        vcs :: ConstraintSet
+        vcs = do setLogic $ CustomLogic "HORN"
+                 constrain $ vc1 invariant
+                 constrain $ vc2 invariant
+                 constrain $ vc3 invariant
+
+-- | Verify that the synthesized function does indeed work. To do so, we simply prove that the invariant found satisfies all the vcs:
+--
+-- >>> verify
+-- Q.E.D.
+verify :: IO ThmResult
+verify = prove vcs
+  where invariant :: Inv
+        invariant (x, y, z, i) = x + (-z) + i .> (-1) .&& x + (-z) + i .< 1 .&& x + y + (-z) .> (-1)
+
+        vcs :: SBool
+        vcs =   quantifiedBool (vc1 invariant)
+            .&& quantifiedBool (vc3 invariant)
+            .&& quantifiedBool (vc3 invariant)
+
+{- HLint ignore quantify "Redundant lambda" -}
diff --git a/Documentation/SBV/Examples/ProofTools/BMC.hs b/Documentation/SBV/Examples/ProofTools/BMC.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ProofTools/BMC.hs
@@ -0,0 +1,121 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ProofTools.BMC
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A BMC example, showing how traditional state-transition reachability
+-- problems can be coded using SBV, using bounded model checking.
+--
+-- We imagine a system with two integer variables, @x@ and @y@. At each
+-- iteration, we can either increment @x@ by @2@, or decrement @y@ by @4@.
+--
+-- Can we reach a state where @x@ and @y@ are the same starting from @x=0@
+-- and @y=10@?
+--
+-- What if @y@ starts at @11@?
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ProofTools.BMC where
+
+import Data.SBV
+import Data.SBV.Tools.BMC
+
+-- * System state
+
+-- | System state, containing the two integers.
+data S a = S { x :: a, y :: a } deriving (Traversable, Functor, Foldable)
+
+-- | Show the state as a pair
+instance Show a => Show (S a) where
+  show S{x, y} = show (x, y)
+
+-- | Symbolic equality for @S@.
+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) where
+  type QueryResult (S SInteger) = S Integer
+  create = S <$> freshVar_ <*> freshVar_
+
+-- * Encoding the problem
+
+-- | We parameterize over the initial state for different variations.
+problem :: Int -> (S SInteger -> SBool) -> IO (Either String (Int, [S Integer]))
+problem lim initial = bmcCover (Just lim) True setup initial trans goal
+  where
+        -- This is where we would put solver options, typically via
+        -- calls to 'Data.SBV.setOption'. We do not need any for this problem,
+        -- so we simply do nothing.
+        setup :: Symbolic ()
+        setup = pure ()
+
+        -- Transition relation: At each step we either
+        -- get to increase @x@ by 2, or decrement @y@ by 4:
+        trans :: S SInteger -> S SInteger -> SBool
+        trans S{x, y} next = next `sElem` [ S { x = x + 2, y = y     }
+                                          , S { x = x,     y = y - 4 }
+                                          ]
+
+        -- Goal state is when @x@ equals @y@:
+        goal :: S SInteger -> SBool
+        goal S{x, y} = x .== y
+
+-- * Examples
+
+-- | Example 1: We start from @x=0@, @y=10@, and search up to depth @10@. We have:
+--
+-- >>> ex1
+-- BMC Cover: Iteration: 0
+-- BMC Cover: Iteration: 1
+-- BMC Cover: Iteration: 2
+-- BMC Cover: Iteration: 3
+-- BMC Cover: Satisfying state found at iteration 3
+-- Right (3,[(0,10),(0,6),(2,6),(2,2)])
+--
+-- As expected, there's a solution in this case. Furthermore, since the BMC engine
+-- found a solution at depth @3@, we also know that there is no solution at
+-- depths @0@, @1@, or @2@; i.e., this is "a" shortest solution. (That is,
+-- it may not be unique, but there isn't a shorter sequence to get us to
+-- our goal.)
+ex1 :: IO (Either String (Int, [S Integer]))
+ex1 = problem 10 isInitial
+  where isInitial :: S SInteger -> SBool
+        isInitial S{x, y} = x .== 0 .&& y .== 10
+
+-- | Example 2: We start from @x=0@, @y=11@, and search up to depth @10@. We have:
+--
+-- >>> ex2
+-- BMC Cover: Iteration: 0
+-- BMC Cover: Iteration: 1
+-- BMC Cover: Iteration: 2
+-- BMC Cover: Iteration: 3
+-- BMC Cover: Iteration: 4
+-- BMC Cover: Iteration: 5
+-- BMC Cover: Iteration: 6
+-- BMC Cover: Iteration: 7
+-- BMC Cover: Iteration: 8
+-- BMC Cover: Iteration: 9
+-- Left "BMC Cover limit of 10 reached. Cover can't be established."
+--
+-- As expected, there's no solution in this case. While SBV (and BMC) cannot establish
+-- that there is no solution at a larger depth, you can see that this will never be the
+-- case: In each step we do not change the parity of either variable. That is, @x@
+-- will remain even, and @y@ will remain odd. So, there will never be a solution at
+-- any depth. This isn't the only way to see this result of course, but the point
+-- remains that BMC is just not capable of establishing inductive facts.
+ex2 :: IO (Either String (Int, [S Integer]))
+ex2 = problem 10 isInitial
+  where isInitial :: S SInteger -> SBool
+        isInitial S{x, y} = x .== 0 .&& y .== 11
diff --git a/Documentation/SBV/Examples/ProofTools/Fibonacci.hs b/Documentation/SBV/Examples/ProofTools/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ProofTools/Fibonacci.hs
@@ -0,0 +1,101 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ProofTools.Fibonacci
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Example inductive proof to show partial correctness of the for-loop
+-- based fibonacci algorithm:
+--
+-- @
+--     i = 0
+--     k = 1
+--     m = 0
+--     while i < n:
+--        m, k = k, m + k
+--        i++
+-- @
+--
+-- We do the proof against an axiomatized fibonacci implementation using an
+-- uninterpreted function.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ProofTools.Fibonacci where
+
+import Data.SBV
+import Data.SBV.Tools.Induction
+
+-- * System state
+
+-- | 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, Traversable, Functor, Foldable)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (S SInteger) where
+  type QueryResult (S SInteger) = S Integer
+  create = S <$> freshVar_ <*> freshVar_ <*> freshVar_ <*> freshVar_
+
+-- | Encoding partial correctness of the sum algorithm. We have:
+--
+-- >>> fibCorrect
+-- Q.E.D.
+--
+-- NB. In my experiments, I found that this proof is quite fragile due
+-- to the use of quantifiers: If you make a mistake in your algorithm
+-- or the coding, z3 pretty much spins forever without finding a counter-example.
+-- However, with the correct coding, the proof is almost instantaneous!
+fibCorrect :: IO (InductionResult (S Integer))
+fibCorrect = induct chatty setup initial trans strengthenings inv goal
+  where -- Set this to True for SBV to print steps as it proceeds
+        -- through the inductive proof
+        chatty :: Bool
+        chatty = False
+
+        -- Declare fib as un uninterpreted function:
+        fib :: SInteger -> SInteger
+        fib = uninterpret "fib"
+
+        -- We setup to axiomatize the textbook definition of fib in SMT-Lib
+        setup :: Symbolic ()
+        setup = do constrain $ fib 0 .== 0
+                   constrain $ fib 1 .== 1
+                   constrain $ \(Forall x) -> fib (x+2) .== fib (x+1) + fib x
+
+        -- Initialize variables
+        initial :: S SInteger -> SBool
+        initial S{i, k, m, n} = i .== 0 .&& k .== 1 .&& m .== 0 .&& n .>= 0
+
+        -- We code the algorithm almost literally in SBV notation:
+        trans :: S SInteger -> S SInteger -> SBool
+        trans S{i, k, m, n} S{i = i', k = k', m = m', n = n'} = (i', k', m', n') .== ite (i .< n)
+                                                                                         (i+1, m+k, k, n)
+                                                                                         (i,   k,   m, n)
+
+        -- No strengthenings needed for this problem!
+        strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = []
+
+        -- Loop invariant: @i@ remains at most @n@, @k@ is @fib (i+1)@
+        -- and @m@ is fib(i)@:
+        inv :: S SInteger -> SBool
+        inv S{i, k, m, n} =    i .<= n
+                           .&& k .== fib (i+1)
+                           .&& m .== fib i
+
+        -- Final goal. When the termination condition holds, the value @m@
+        -- holds the @n@th fibonacci number. Note that SBV does not prove the
+        -- termination condition; it simply is the indication that the loop
+        -- has ended as specified by the user.
+        goal :: S SInteger -> (SBool, SBool)
+        goal S{i, m, n} = (i .== n, m .== fib n)
diff --git a/Documentation/SBV/Examples/ProofTools/Strengthen.hs b/Documentation/SBV/Examples/ProofTools/Strengthen.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ProofTools/Strengthen.hs
@@ -0,0 +1,164 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ProofTools.Strengthen
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- An example showing how traditional state-transition invariance problems
+-- can be coded using SBV, using induction. We also demonstrate the use of
+-- invariant strengthening.
+--
+-- This example comes from Bradley's [Understanding IC3](http://theory.stanford.edu/~arbrad/papers/Understanding_IC3.pdf) paper,
+-- which considers the following two programs:
+--
+-- @
+--      x, y := 1, 1                    x, y := 1, 1
+--      while *:                        while *:
+--        x, y := x+1, y+x                x, y := x+y, y+x
+-- @
+--
+-- Where @*@ stands for non-deterministic choice. For each program we try to prove that @y >= 1@ is an invariant.
+--
+-- It turns out that the property @y >= 1@ is indeed an invariant, but is
+-- not inductive for either program. We proceed to strengthen the invariant
+-- and establish it for the first case. We then note that the same strengthening
+-- doesn't work for the second program, and find a further strengthening to
+-- establish that case as well. This example follows the introductory example
+-- in Bradley's paper quite closely.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ProofTools.Strengthen where
+
+import Data.SBV
+import Data.SBV.Tools.Induction
+
+-- * System state
+
+-- | 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, Traversable, Functor, Foldable)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (S SInteger) where
+  type QueryResult (S SInteger) = S Integer
+  create = S <$> freshVar_ <*> freshVar_
+
+-- * Encoding the problem
+
+-- | We parameterize over the transition relation and the strengthenings to
+-- investigate various combinations.
+problem :: (S SInteger -> S SInteger -> SBool) -> [(String, S SInteger -> SBool)] -> IO (InductionResult (S Integer))
+problem trans strengthenings = induct chatty setup initial trans strengthenings inv goal
+  where -- Set this to True for SBV to print steps as it proceeds
+        -- through the inductive proof
+        chatty :: Bool
+        chatty = False
+
+        -- This is where we would put solver options, typically via
+        -- calls to 'Data.SBV.setOption'. We do not need any for this problem,
+        -- so we simply do nothing.
+        setup :: Symbolic ()
+        setup = pure ()
+
+        -- Initially, @x@ and @y@ are both @1@
+        initial :: S SInteger -> SBool
+        initial S{x, y} = x .== 1 .&& y .== 1
+
+        -- Invariant to prove:
+        inv :: S SInteger -> SBool
+        inv S{y} = y .>= 1
+
+        -- We're not interested in termination/goal for this problem, so just pass trivial values
+        goal :: S SInteger -> (SBool, SBool)
+        goal _ = (sTrue, sTrue)
+
+-- | The first program, coded as a transition relation:
+pgm1 :: S SInteger -> S SInteger -> SBool
+pgm1 S{x, y} S{x = x', y = y'} = x' .== x+1 .&& y' .== y+x
+
+-- | The second program, coded as a transition relation:
+pgm2 :: S SInteger -> S SInteger -> SBool
+pgm2 S{x, y} S{x = x', y = y'} = x' .== x+y .&& y' .== y+x
+
+-- * Examples
+
+-- | Example 1: First program, with no strengthenings. We have:
+--
+-- >>> ex1
+-- Failed while establishing consecution.
+-- Counter-example to inductiveness:
+--   (S {x = -1, y = 1},S {x = 0, y = 0})
+ex1 :: IO (InductionResult (S Integer))
+ex1 = problem pgm1 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = []
+
+-- | Example 2: First program, strengthened with @x >= 0@. We have:
+--
+-- >>> ex2
+-- Q.E.D.
+ex2 :: IO (InductionResult (S Integer))
+ex2 = problem pgm1 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = [("x >= 0", \S{x} -> x .>= 0)]
+
+-- | Example 3: Second program, with no strengthenings. We have:
+--
+-- >>> ex3
+-- Failed while establishing consecution.
+-- Counter-example to inductiveness:
+--   (S {x = -1, y = 1},S {x = 0, y = 0})
+ex3 :: IO (InductionResult (S Integer))
+ex3 = problem pgm2 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = []
+
+-- | Example 4: Second program, strengthened with @x >= 0@. We have:
+--
+-- >>> ex4
+-- Failed while establishing consecution for strengthening "x >= 0".
+-- Counter-example to inductiveness:
+--   (S {x = 0, y = -1},S {x = -1, y = -1})
+ex4 :: IO (InductionResult (S Integer))
+ex4 = problem pgm2 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = [("x >= 0", \S{x} -> x .>= 0)]
+
+-- | Example 5: Second program, strengthened with @x >= 0@ and @y >= 1@ separately. We have:
+--
+-- >>> ex5
+-- Failed while establishing consecution for strengthening "x >= 0".
+-- Counter-example to inductiveness:
+--   (S {x = 0, y = -1},S {x = -1, y = -1})
+--
+-- Note how this was sufficient in 'ex2' to establish the invariant for the first
+-- program, but fails for the second.
+ex5 :: IO (InductionResult (S Integer))
+ex5 = problem pgm2 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = [ ("x >= 0", \S{x} -> x .>= 0)
+                         , ("y >= 1", \S{y} -> y .>= 1)
+                         ]
+
+-- | Example 6: Second program, strengthened with @x >= 0 \/\\ y >= 1@ simultaneously. We have:
+--
+-- >>> ex6
+-- Q.E.D.
+--
+-- Compare this to 'ex5'. As pointed out by Bradley, this shows that
+-- /a conjunction of assertions can be inductive when none of its components, on its own, is inductive./
+-- It remains an art to find proper loop invariants, though the science is improving!
+ex6 :: IO (InductionResult (S Integer))
+ex6 = problem pgm2 strengthenings
+  where strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = [("x >= 0 /\\ y >= 1", \S{x, y} -> x .>= 0 .&& y .>= 1)]
diff --git a/Documentation/SBV/Examples/ProofTools/Sum.hs b/Documentation/SBV/Examples/ProofTools/Sum.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/ProofTools/Sum.hs
@@ -0,0 +1,90 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.ProofTools.Sum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Example inductive proof to show partial correctness of the traditional
+-- for-loop sum algorithm:
+--
+-- @
+--     s = 0
+--     i = 0
+--     while i <= n:
+--        s += i
+--        i++
+-- @
+--
+-- We prove the loop invariant and establish partial correctness that
+-- @s@ is the sum of all numbers up to and including @n@ upon termination.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.ProofTools.Sum where
+
+import Data.SBV
+import Data.SBV.Tools.Induction
+
+-- * System state
+
+-- | 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, Traversable, Functor, Foldable)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (S SInteger) where
+  type QueryResult (S SInteger) = S Integer
+  create = S <$> freshVar_ <*> freshVar_ <*> freshVar_
+
+-- | Encoding partial correctness of the sum algorithm. We have:
+--
+-- >>> sumCorrect
+-- Q.E.D.
+sumCorrect :: IO (InductionResult (S Integer))
+sumCorrect = induct chatty setup initial trans strengthenings inv goal
+  where -- Set this to True for SBV to print steps as it proceeds
+        -- through the inductive proof
+        chatty :: Bool
+        chatty = False
+
+        -- This is where we would put solver options, typically via
+        -- calls to 'Data.SBV.setOption'. We do not need any for this problem,
+        -- so we simply do nothing.
+        setup :: Symbolic ()
+        setup = pure ()
+
+        -- Initially, @s@ and @i@ are both @0@. We also require @n@ to be at least @0@.
+        initial :: S SInteger -> SBool
+        initial S{s, i, n} = s .== 0 .&& i .== 0 .&& n .>= 0
+
+        -- We code the algorithm almost literally in SBV notation:
+        trans :: S SInteger -> S SInteger -> SBool
+        trans S{s, i, n} S{s = s', i = i', n = n'} = (s', i', n') .== ite (i .<= n)
+                                                                          (s+i, i+1, n)
+                                                                          (s  , i  , n)
+
+        -- No strengthenings needed for this problem!
+        strengthenings :: [(String, S SInteger -> SBool)]
+        strengthenings = []
+
+        -- Loop invariant: @i@ remains at most @n+1@ and @s@ the sum of
+        -- all the numbers up-to @i-1@.
+        inv :: S SInteger -> SBool
+        inv S{s, i, n} =    i .<= n+1
+                        .&& s .== (i * (i - 1)) `sDiv` 2
+
+        -- Final goal. When the termination condition holds, the sum is
+        -- equal to all the numbers up to and including @n@. Note that
+        -- SBV does not prove the termination condition; it simply is
+        -- the indication that the loop has ended as specified by the user.
+        goal :: S SInteger -> (SBool, SBool)
+        goal S{s, i, n} = (i .== n+1, s .== (n * (n+1)) `sDiv` 2)
diff --git a/Documentation/SBV/Examples/Puzzles/AOC_2021_24.hs b/Documentation/SBV/Examples/Puzzles/AOC_2021_24.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/AOC_2021_24.hs
@@ -0,0 +1,451 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.AOC_2021_24
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A solution to the advent-of-code problem, 2021, day 24: <http://adventofcode.com/2021/day/24>.
+--
+-- Here is a high-level summary: We are essentially modeling the ALU of a fictional
+-- computer with 4 integer registers (w, x, y, z), and 6 instructions (inp, add, mul, div, mod, eql).
+-- You are given a program (hilariously called "monad"), and your goal is to figure out what
+-- the maximum and minimum inputs you can provide to this program such that when it runs
+-- register z ends up with the value 0. Please refer to the above link for the full description.
+--
+-- While there are multiple ways to solve this problem in SBV, the solution here demonstrates
+-- how to turn programs in this fictional language into actual Haskell/SBV programs, i.e.,
+-- developing a little EDSL (embedded domain-specific language) for it. Hopefully this
+-- should provide a template for other similar programs.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE NamedFieldPuns   #-}
+{-# LANGUAGE NegativeLiterals #-}
+
+#if __GLASGOW_HASKELL__ >= 913
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-record-selectors #-}
+#else
+{-# OPTIONS_GHC -Wall -Werror #-}
+#endif
+
+module Documentation.SBV.Examples.Puzzles.AOC_2021_24 where
+
+import Prelude hiding (read, mod, div)
+
+import Control.Monad (forM_)
+import Data.Maybe
+
+import qualified Data.Map.Strict          as M
+import qualified Control.Monad.State.Lazy as ST
+
+import Data.SBV
+
+-----------------------------------------------------------------------------------------------
+-- * Registers, values, and the ALU
+-----------------------------------------------------------------------------------------------
+
+-- | A Register in the machine, identified by its name.
+type Register = String
+
+-- | We operate on 64-bit signed integers. It is also possible to use the unbounded integers here
+-- as the problem description doesn't mention any size limitations. But performance isn't as good
+-- with unbounded integers, and 64-bit signed bit-vectors seem to fit the bill just fine, much
+-- like any other modern processor these days.
+type Value = SInt64
+
+-- | An item of data to be processed. We can either be referring to a named register, or an immediate value.
+data Data = Reg {register :: Register}
+          | Imm Int64
+
+-- | 'Num' instance for 'Data'. This is merely there for us to be able to represent programs in a
+-- natural way, i.e, lifting integers (positive and negative). Other methods are neither implemented
+-- nor needed.
+instance Num Data where
+  fromInteger    = Imm . fromIntegral
+  (+)            = error "+     : unimplemented"
+  (*)            = error "*     : unimplemented"
+  negate (Imm i) = Imm (-i)
+  negate Reg{}   = error "negate: unimplemented"
+  abs            = error "abs   : unimplemented"
+  signum         = error "signum: unimplemented"
+
+-- | Shorthand for the @w@ register.
+w :: Data
+w = Reg "w"
+
+-- | Shorthand for the @x@ register.
+x :: Data
+x = Reg "x"
+
+-- | Shorthand for the @y@ register.
+y :: Data
+y = Reg "y"
+
+-- | Shorthand for the @z@ register.
+z :: Data
+z = Reg "z"
+
+-- | The state of the machine. We keep track of the data values, along with the input parameters.
+data State = State { env    :: M.Map Register Value  -- ^ Values of registers
+                   , inputs :: [Value]               -- ^ Input parameters, stored in reverse.
+                   }
+
+-- | The ALU is simply a state transformer, manipulating the state, wrapped around SBV's 'Symbolic' monad.
+type ALU = ST.StateT State Symbolic
+
+-----------------------------------------------------------------------------------------------
+-- * Operations
+-----------------------------------------------------------------------------------------------
+
+-- | Reading a value. For a register, we simply look it up in the environment.
+-- For an immediate, we simply return it.
+read :: Data -> ALU Value
+read (Reg r) = ST.get >>= \st -> pure $ fromJust (r `M.lookup` env st)
+read (Imm i) = pure $ literal i
+
+-- | Writing a value. We update the registers.
+write :: Data -> Value -> ALU ()
+write d v = ST.modify' $ \st -> st{env = M.insert (register d) v (env st)}
+
+-- | Reading an input value. In this version, we simply write a free symbolic value
+-- to the specified register, and keep track of the inputs explicitly.
+inp :: Data -> ALU ()
+inp a = do v <- ST.lift free_
+           write a v
+           ST.modify' $ \st -> st{inputs = v : inputs st}
+
+-- | Addition.
+add :: Data -> Data -> ALU ()
+add a b = write a =<< (+) <$> read a <*> read b
+
+-- | Multiplication.
+mul :: Data -> Data -> ALU ()
+mul a b = write a =<< (*) <$> read a <*> read b
+
+-- | Division.
+div :: Data -> Data -> ALU ()
+div a b = write a =<< sDiv <$> read a <*> read b
+
+-- | Modulus.
+mod :: Data -> Data -> ALU ()
+mod a b = write a =<< sMod <$> read a <*> read b
+
+-- | Equality.
+eql :: Data -> Data -> ALU ()
+eql a b = write a . oneIf =<< (.==) <$> read a <*> read b
+
+-----------------------------------------------------------------------------------------------
+-- * Running a program
+-----------------------------------------------------------------------------------------------
+
+-- | Run a given program, returning the final state. We simply start with the initial
+-- environment mapping all registers to zero, as specified in the problem specification.
+run :: ALU () -> Symbolic State
+run pgm = ST.execStateT pgm initState
+ where initState = State { env    = M.fromList [(register r, 0) | r <- [w, x, y, z]]
+                         , inputs = []
+                         }
+
+-----------------------------------------------------------------------------------------------
+-- * Solving the puzzle
+--
+-----------------------------------------------------------------------------------------------
+
+-- | We simply run the 'monad' program, and specify the constraints at the end. We take a boolean
+-- as a parameter, choosing whether we want to minimize or maximize the model-number. Note that this
+-- test takes rather long to run. We get:
+--
+-- @
+-- ghci> puzzle True
+-- Optimal model:
+--   Maximum model number = 96918996924991 :: Int64
+-- ghci> puzzle False
+-- Optimal model:
+--   Minimum model number = 91811241911641 :: Int64
+-- @
+puzzle :: Bool -> IO ()
+puzzle shouldMaximize = print =<< optimizeWith z3{isNonModelVar = (/= finalVar)}  Lexicographic problem
+  where finalVar | shouldMaximize = "Maximum model number"
+                 | True           = "Minimum model number"
+        problem = do State{env, inputs} <- run monad
+
+                     -- The final z value should be 0
+                     constrain $ fromJust (register z `M.lookup` env) .== 0
+
+                     -- Digits of the model number, stored in reverse
+                     let digits = reverse inputs
+
+                     -- Each digit is between 1-9
+                     forM_ digits $ \d -> constrain $ d `inRange` (1, 9)
+
+                     -- Digits spell out the model number. We minimize/maximize this value as requested:
+                     let modelNum = foldl (\sofar d -> 10 * sofar + d) 0 digits
+
+                     -- maximize/minimize the digits as requested
+                     if shouldMaximize
+                        then maximize "goal" modelNum
+                        else minimize "goal" modelNum
+
+                     -- For display purposes, create a variable to assign to modelNum
+                     modelNumV <- free finalVar
+                     constrain $ modelNumV .== modelNum
+
+-- | The program we need to crack. Note that different users get different programs on the Advent-Of-Code site, so this is simply one example.
+-- You can simply cut-and-paste your version instead. (Don't forget the pragma @NegativeLiterals@ to GHC so @add x -1@ parses correctly as @add x (-1)@.)
+monad :: ALU ()
+monad = do inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 11
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 5
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 13
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 5
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 12
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 1
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 15
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 15
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 10
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 2
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -1
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 2
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 14
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 5
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -8
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 8
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -7
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 14
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -8
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 12
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 1
+           add x 11
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 7
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -2
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 14
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -2
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 13
+           mul y x
+           add z y
+           inp w
+           mul x 0
+           add x z
+           mod x 26
+           div z 26
+           add x -13
+           eql x w
+           eql x 0
+           mul y 0
+           add y 25
+           mul y x
+           add y 1
+           mul z y
+           mul y 0
+           add y w
+           add y 6
+           mul y x
+           add z y
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Puzzles/Birthday.hs b/Documentation/SBV/Examples/Puzzles/Birthday.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Birthday.hs
@@ -0,0 +1,129 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Birthday
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- This is a formalization of the Cheryl's birthday problem, which went viral in April 2015.
+--
+-- Here's the puzzle:
+--
+-- @
+-- Albert and Bernard just met Cheryl. "When’s your birthday?" Albert asked Cheryl.
+--
+-- Cheryl thought a second and said, "I’m not going to tell you, but I’ll give you some clues." She wrote down a list of 10 dates:
+--
+--   May 15, May 16, May 19
+--   June 17, June 18
+--   July 14, July 16
+--   August 14, August 15, August 17
+--
+-- "My birthday is one of these," she said.
+--
+-- Then Cheryl whispered in Albert’s ear the month — and only the month — of her birthday. To Bernard, she whispered the day, and only the day.
+-- “Can you figure it out now?” she asked Albert.
+--
+-- Albert: I don’t know when your birthday is, but I know Bernard doesn’t know, either.
+-- Bernard: I didn’t know originally, but now I do.
+-- Albert: Well, now I know, too!
+--
+-- When is Cheryl’s birthday?
+-- @
+--
+-- NB. Thanks to Amit Goel for suggesting the formalization strategy used in here.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Birthday where
+
+import Data.SBV
+
+-----------------------------------------------------------------------------------------------
+-- * Types and values
+-----------------------------------------------------------------------------------------------
+
+-- | Months. We only put in the months involved in the puzzle for simplicity
+data Month = May | Jun | Jul | Aug
+
+-- | Days. Again, only the ones mentioned in the puzzle.
+data Day = D14 | D15 | D16 | D17 | D18 | D19
+
+mkSymbolic [''Month]
+mkSymbolic [''Day]
+
+-- | Represent the birthday as a record
+data Birthday = BD SMonth SDay
+
+-- | Make a valid symbolic birthday
+mkBirthday :: Symbolic Birthday
+mkBirthday = do b <- BD <$> free "birthMonth" <*> free "birthDay"
+                constrain $ valid b
+                pure b
+
+-- | Is this a valid birthday? i.e., one that was declared by Cheryl to be a possibility.
+valid :: Birthday -> SBool
+valid (BD m d) =   (m .== sMay .=> d `sElem` [sD15, sD16, sD19])
+               .&& (m .== sJun .=> d `sElem` [sD17, sD18])
+               .&& (m .== sJul .=> d `sElem` [sD14, sD16])
+               .&& (m .== sAug .=> d `sElem` [sD14, sD15, sD17])
+
+-----------------------------------------------------------------------------------------------
+-- * The puzzle
+-----------------------------------------------------------------------------------------------
+
+-- | Encode the conversation as given in the puzzle.
+--
+-- NB. Lee Pike pointed out that not all the constraints are actually necessary! (Private
+-- communication.) The puzzle still has a unique solution if the statements @a1@ and @b1@
+-- (i.e., Albert and Bernard saying they themselves do not know the answer) are removed.
+-- To experiment you can simply comment out those statements and observe that there still
+-- is a unique solution. Thanks to Lee for pointing this out! In fact, it is instructive to
+-- assert the conversation line-by-line, and see how the search-space gets reduced in each
+-- step.
+puzzle :: ConstraintSet
+puzzle = do BD birthMonth birthDay <- mkBirthday
+
+            let ok    = sAll valid
+                qe qb = quantifiedBool qb
+
+            -- Albert: I do not know
+            let a1 m = qe $ \(Exists d1) (Exists d2) -> ok [BD m d1, BD m d2] .&& d1 ./= d2
+            constrain $ a1 birthMonth
+
+            -- Albert: I know that Bernard doesn't know
+            let a2 m = qe $ \(Forall d) -> ok [BD m d] .=> qe (\(Exists m1) (Exists m2) -> ok [BD m1 d, BD m2 d] .&& m1 ./= m2)
+            constrain $ a2 birthMonth
+
+            -- Bernard: I did not know
+            let b1 d = qe $ \(Exists m1) (Exists m2) -> ok [BD m1 d, BD m2 d] .&& m1 ./= m2
+            constrain $ b1 birthDay
+
+            -- Bernard: But now I know
+            let b2p m d = ok [BD m d] .&& a1 m .&& a2 m
+                b2  d   = qe $ \(Forall m1) (Forall m2) -> (b2p m1 d .&& b2p m2 d) .=> m1 .== m2
+            constrain $ b2 birthDay
+
+            -- Albert: Now I know too
+            let a3p m d = ok [BD m d] .&& a1 m .&& a2 m .&& b1 d .&& b2 d
+                a3  m   = \(Forall d1) (Forall d2) -> (a3p m d1 .&& a3p m d2) .=> d1 .== d2
+            constrain $ a3 birthMonth
+
+-- | Find all solutions to the birthday problem. We have:
+--
+-- >>> cheryl
+-- Solution #1:
+--   birthMonth = Jul :: Month
+--   birthDay   = D16 :: Day
+-- This is the only solution.
+cheryl :: IO ()
+cheryl = print =<< allSat puzzle
+
+{- HLint ignore puzzle "Redundant lambda" -}
+{- HLint ignore puzzle "Eta reduce"       -}
diff --git a/Documentation/SBV/Examples/Puzzles/Coins.hs b/Documentation/SBV/Examples/Puzzles/Coins.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Coins.hs
@@ -0,0 +1,108 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Coins
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the following puzzle:
+--
+-- @
+-- You and a friend pass by a standard coin operated vending machine and you decide to get a candy bar.
+-- The price is US $0.95, but after checking your pockets you only have a dollar (US $1) and the machine
+-- only takes coins. You turn to your friend and have this conversation:
+--   you: Hey, do you have change for a dollar?
+--   friend: Let's see. I have 6 US coins but, although they add up to a US $1.15, I can't break a dollar.
+--   you: Huh? Can you make change for half a dollar?
+--   friend: No.
+--   you: How about a quarter?
+--   friend: Nope, and before you ask I cant make change for a dime or nickel either.
+--   you: Really? and these six coins are all US government coins currently in production?
+--   friend: Yes.
+--   you: Well can you just put your coins into the vending machine and buy me a candy bar, and I'll pay you back?
+--   friend: Sorry, I would like to but I can't with the coins I have.
+-- What coins are your friend holding?
+-- @
+--
+-- To be fair, the problem has no solution /mathematically/. But there is a solution when one takes into account that
+-- vending machines typically do not take the 50 cent coins!
+--
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Coins where
+
+import Data.SBV
+
+-- | We will represent coins with 16-bit words (more than enough precision for coins).
+type Coin = SWord16
+
+-- | Create a coin. The argument Int argument just used for naming the coin. Note that
+-- we constrain the value to be one of the valid U.S. coin values as we create it.
+mkCoin :: Int -> Symbolic Coin
+mkCoin i = do c <- free $ 'c' : show i
+              constrain $ sAny (.== c) [1, 5, 10, 25, 50, 100]
+              pure c
+
+-- | Return all combinations of a sequence of values.
+combinations :: [a] -> [[a]]
+combinations coins = concat [combs i coins | i <- [1 .. length coins]]
+  where combs 0 _      = [[]]
+        combs _ []     = []
+        combs k (x:xs) = map (x:) (combs (k-1) xs) ++ combs k xs
+
+-- | Constraint 1: Cannot make change for a dollar.
+c1 :: [Coin] -> SBool
+c1 xs = sum xs ./= 100
+
+-- | Constraint 2: Cannot make change for half a dollar.
+c2 :: [Coin] -> SBool
+c2 xs = sum xs ./= 50
+
+-- | Constraint 3: Cannot make change for a quarter.
+c3 :: [Coin] -> SBool
+c3 xs = sum xs ./= 25
+
+-- | Constraint 4: Cannot make change for a dime.
+c4 :: [Coin] -> SBool
+c4 xs = sum xs ./= 10
+
+-- | Constraint 5: Cannot make change for a nickel
+c5 :: [Coin] -> SBool
+c5 xs = sum xs ./= 5
+
+-- | Constraint 6: Cannot buy the candy either. Here's where we need to have the extra knowledge
+-- that the vending machines do not take 50 cent coins.
+c6 :: [Coin] -> SBool
+c6 xs = sum (map val xs) ./= 95
+   where val x = ite (x .== 50) 0 x
+
+-- | Solve the puzzle. We have:
+--
+-- >>> puzzle
+-- Satisfiable. Model:
+--   c1 = 50 :: Word16
+--   c2 = 25 :: Word16
+--   c3 = 10 :: Word16
+--   c4 = 10 :: Word16
+--   c5 = 10 :: Word16
+--   c6 = 10 :: Word16
+--
+-- i.e., your friend has 4 dimes, a quarter, and a half dollar.
+puzzle :: IO SatResult
+puzzle = sat $ do
+        cs <- mapM mkCoin [1..6]
+
+        -- Assert each of the constraints for all combinations that has
+        -- at least two coins (to make change)
+        mapM_ constrain [c s | s <- combinations cs, length s >= 2, c <- [c1, c2, c3, c4, c5, c6]]
+
+        -- the following constraint is not necessary for solving the puzzle
+        -- however, it makes sure that the solution comes in decreasing value of coins,
+        -- thus allowing the above test to succeed regardless of the solver used.
+        constrain $ sAnd $ zipWith (.>=) cs (drop 1 cs)
+
+        -- assert that the sum must be 115 cents.
+        pure $ sum cs .== 115
diff --git a/Documentation/SBV/Examples/Puzzles/Counts.hs b/Documentation/SBV/Examples/Puzzles/Counts.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Counts.hs
@@ -0,0 +1,86 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Counts
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Consider the sentence:
+--
+-- @
+--    In this sentence, the number of occurrences of 0 is _, of 1 is _, of 2 is _,
+--    of 3 is _, of 4 is _, of 5 is _, of 6 is _, of 7 is _, of 8 is _, and of 9 is _.
+-- @
+--
+-- The puzzle is to fill the blanks with numbers, such that the sentence
+-- will be correct. There are precisely two solutions to this puzzle, both of
+-- which are found by SBV successfully.
+--
+--  References:
+--
+--    * Douglas Hofstadter, Metamagical Themes, pg. 27.
+--
+--    * <http://mathcentral.uregina.ca/mp/archives/previous2002/dec02sol.html>
+--
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Counts where
+
+import Data.SBV
+import Data.List (sortOn)
+
+-- | We will assume each number can be represented by an 8-bit word, i.e., can be at most 128.
+type Count = SWord8
+
+-- | Given a number, increment the count array depending on the digits of the number
+count :: Count -> [Count] -> [Count]
+count n cnts = ite (n .< 10)
+                   (upd n cnts)                           -- only one digit
+                   (ite (n .< 100)
+                        (upd d1 (upd d2 cnts))            -- two digits
+                        (upd d1 (upd d2 (upd d3 cnts))))  -- three digits
+  where (r1, d1)   = n  `sQuotRem` 10
+        (d3, d2)   = r1 `sQuotRem` 10
+        upd d = zipWith inc (map literal [0..])
+          where inc i c = ite (i .== d) (c+1) c
+
+-- | Encoding of the puzzle. The solution is a sequence of 10 numbers
+-- for the occurrences of the digits such that if we count each digit,
+-- we find these numbers.
+puzzle :: [Count] -> SBool
+puzzle cnt = cnt .== last css
+  where ones = replicate 10 1  -- all digits occur once to start with
+        css  = ones : zipWith count cnt css
+
+-- | Finds all two known solutions to this puzzle. We have:
+--
+-- >>> counts
+-- Solution #1
+-- 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` mkFreeVars 10
+            cnt <- displayModels (sortOn show) disp res
+            putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
+  where disp n (_, s) = do putStrLn $ "Solution #" ++ show n
+                           dispSolution s
+        dispSolution :: [Word8] -> IO ()
+        dispSolution ns = putStrLn soln
+          where soln =  "In this sentence, the number of occurrences"
+                     ++  " of 0 is " ++ show (ns !! 0)
+                     ++ ", of 1 is " ++ show (ns !! 1)
+                     ++ ", of 2 is " ++ show (ns !! 2)
+                     ++ ", of 3 is " ++ show (ns !! 3)
+                     ++ ", of 4 is " ++ show (ns !! 4)
+                     ++ ", of 5 is " ++ show (ns !! 5)
+                     ++ ", of 6 is " ++ show (ns !! 6)
+                     ++ ", of 7 is " ++ show (ns !! 7)
+                     ++ ", of 8 is " ++ show (ns !! 8)
+                     ++ ", of 9 is " ++ show (ns !! 9)
+                     ++ "."
+{- HLint ignore counts "Use head" -}
diff --git a/Documentation/SBV/Examples/Puzzles/DieHard.hs b/Documentation/SBV/Examples/Puzzles/DieHard.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/DieHard.hs
@@ -0,0 +1,113 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.DieHard
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the die-hard riddle: In the movie Die Hard 3, the heroes must obtain
+-- exactly 4 gallons of water using a 5 gallon jug, a 3 gallon jug, and a water faucet.
+-- We use a bounded-model-checking style search to find a solution.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedRecordDot   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeApplications      #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.DieHard where
+
+import Data.SBV
+import Data.SBV.Tools.BMC
+
+-- | Possible actions
+data Action = Initial | FillBig | FillSmall | EmptyBig | EmptySmall | BigToSmall | SmallToBig
+             deriving Show
+
+mkSymbolic [''Action]
+
+-- | We represent the state with two quantities, the amount of water in each jug. The
+-- action is how we got into this state.
+data State a b = State { big    :: a
+                       , small  :: a
+                       , action :: b
+                       }
+
+-- | Show instance
+instance (Show a, Show b) => Show (State a b) where
+  show s = "Big: " ++ show s.big ++ ", Small: " ++ show s.small ++ " (" ++ show s.action ++ ")"
+
+-- | Fully symbolic state
+type SState = State SInteger SAction
+
+-- | Fully concrete state
+type CState = State Integer Action
+
+-- | 'Queriable' instance needed for running bmc
+instance Queriable IO SState where
+  type QueryResult SState = CState
+
+  create                = State <$> freshVar_ <*> freshVar_ <*> freshVar_
+  project (State b s a) = State <$> project b <*> project s <*> project a
+  embed   (State b s a) = State <$> embed   b <*> embed   s <*> embed   a
+
+-- | Solve the problem using a BMC search. We have:
+--
+-- >>> dieHard
+-- BMC Cover: Iteration: 0
+-- BMC Cover: Iteration: 1
+-- BMC Cover: Iteration: 2
+-- BMC Cover: Iteration: 3
+-- BMC Cover: Iteration: 4
+-- BMC Cover: Iteration: 5
+-- BMC Cover: Iteration: 6
+-- BMC Cover: Satisfying state found at iteration 6
+-- Big: 0, Small: 0 (Initial)
+-- Big: 5, Small: 0 (FillBig)
+-- Big: 2, Small: 3 (BigToSmall)
+-- Big: 2, Small: 0 (EmptySmall)
+-- Big: 0, Small: 2 (BigToSmall)
+-- Big: 5, Small: 2 (FillBig)
+-- Big: 4, Small: 3 (BigToSmall)
+dieHard :: IO ()
+dieHard = display =<< bmcCover Nothing True (pure ()) initial trans goal
+  where -- we start from empty jugs, and try to reach a state where big has 4 gallons
+        initial State{big, small, action} = (big, small, action) .== (0, 0, sInitial)
+        goal    State{big}                = big .== 4
+
+        -- Valid actions as a transition relation:
+        trans :: SState -> SState -> SBool
+        trans fromState toState = go actions
+          where go []                = sFalse
+                go ((act, f) : rest) = ite (toState.action .== act) (f fromState `matches` toState) (go rest)
+
+                matches :: SState -> SState -> SBool
+                p `matches` q = p.big .== q.big .&& p.small .== q.small
+
+                infix 1 |=>
+                a |=> f = (a, f)
+
+                actions = [ sFillBig    |=> \st -> st{big   = 5}
+                          , sFillSmall  |=> \st -> st{small = 3}
+
+                          , sEmptyBig   |=> \st -> st{big   = 0}
+                          , sEmptySmall |=> \st -> st{small = 0}
+
+                          , sBigToSmall |=> \st -> let space = 3 - st.small
+                                                       xfer  = space `smin` st.big
+                                                   in st{big = st.big - xfer, small = st.small + xfer}
+
+                          , sSmallToBig |=> \st -> let space = 5 - st.big
+                                                       xfer  = space `smin` st.small
+                                                   in st{big = st.big + xfer, small = st.small - xfer}
+                          ]
+
+        display :: Either String (Int, [CState]) -> IO ()
+        display (Left e)        = error e
+        display (Right (_, as)) = mapM_ print as
diff --git a/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs b/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs
@@ -0,0 +1,39 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.DogCatMouse
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Puzzle:
+--   Spend exactly 100 dollars and buy exactly 100 animals.
+--   Dogs cost 15 dollars, cats cost 1 dollar, and mice cost 25 cents each.
+--   You have to buy at least one of each.
+--   How many of each should you buy?
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.DogCatMouse where
+
+import Data.SBV
+
+-- | Prints the only solution:
+--
+-- >>> puzzle
+-- Solution #1:
+--   dog   =  3 :: Integer
+--   cat   = 41 :: Integer
+--   mouse = 56 :: Integer
+-- This is the only solution.
+puzzle :: IO AllSatResult
+puzzle = allSat $ do
+           [dog, cat, mouse] <- sIntegers ["dog", "cat", "mouse"]
+           solve [ dog   .>= 1                                           -- at least one dog
+                 , cat   .>= 1                                           -- at least one cat
+                 , mouse .>= 1                                           -- at least one mouse
+                 , dog + cat + mouse .== 100                             -- buy precisely 100 animals
+                 , 15 `per` dog + 1 `per` cat + 0.25 `per` mouse .== 100 -- spend exactly 100 dollars
+                 ]
+  where p `per` q = p * (sFromIntegral q :: SReal)
diff --git a/Documentation/SBV/Examples/Puzzles/Drinker.hs b/Documentation/SBV/Examples/Puzzles/Drinker.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Drinker.hs
@@ -0,0 +1,44 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Drinker
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- SBV proof of the drinker paradox: <http://en.wikipedia.org/wiki/Drinker_paradox>
+--
+-- Let P be the non-empty set of people in a bar. The theorem says if there is somebody drinking in the bar,
+-- then everybody is drinking in the bar. The general formulation is:
+--
+-- @
+--     ∃x : P. D(x) -> ∀y : P. D(y)
+-- @
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Drinker where
+
+import Data.SBV
+
+-- | Declare a carrier data-type in Haskell named P, representing all the people in a bar.
+data P
+
+-- | Make 'P' an uninterpreted sort, introducing the type 'SP' for its symbolic version
+mkSymbolic [''P]
+
+-- | Declare the uninterpret function 'd', standing for drinking. For each person, this function
+-- assigns whether they are drinking; but is otherwise completely uninterpreted. (i.e., our theorem
+-- will be true for all such functions.)
+d :: SP -> SBool
+d = uninterpret "D"
+
+-- | Formulate the drinkers paradox, if some one is drinking, then everyone is!
+--
+-- >>> drinker
+-- Q.E.D.
+drinker :: IO ThmResult
+drinker = prove $ \(Exists x) (Forall y) -> d x .=> d y
diff --git a/Documentation/SBV/Examples/Puzzles/Euler185.hs b/Documentation/SBV/Examples/Puzzles/Euler185.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Euler185.hs
@@ -0,0 +1,51 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Euler185
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A solution to Project Euler problem #185: <http://projecteuler.net/index.php?section=problems&id=185>
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Euler185 where
+
+import Data.Char (ord)
+import Data.SBV
+
+-- | The given guesses and the correct digit counts, encoded as a simple list.
+guesses :: [(String, SWord8)]
+guesses = [ ("5616185650518293", 2), ("3847439647293047", 1), ("5855462940810587", 3)
+          , ("9742855507068353", 3), ("4296849643607543", 3), ("3174248439465858", 1)
+          , ("4513559094146117", 2), ("7890971548908067", 3), ("8157356344118483", 1)
+          , ("2615250744386899", 2), ("8690095851526254", 3), ("6375711915077050", 1)
+          , ("6913859173121360", 1), ("6442889055042768", 2), ("2321386104303845", 0)
+          , ("2326509471271448", 2), ("5251583379644322", 2), ("1748270476758276", 3)
+          , ("4895722652190306", 1), ("3041631117224635", 3), ("1841236454324589", 3)
+          , ("2659862637316867", 2)
+          ]
+
+-- | Encode the problem, note that we check digits are within 0-9 as
+-- we use 8-bit words to represent them. Otherwise, the constraints are simply
+-- generated by zipping the alleged solution with each guess, and making sure the
+-- number of matching digits match what's given in the problem statement.
+euler185 :: Symbolic SBool
+euler185 = do soln <- mkFreeVars 16
+              pure $ sAll digit soln .&& sAnd (map (genConstr soln) guesses)
+  where genConstr a (b, c) = sum (zipWith eq a b) .== (c :: SWord8)
+        digit x = (x :: SWord8) .>= 0 .&& x .<= 9
+        eq x y =  ite (x .== fromIntegral (ord y - ord '0')) 1 0
+
+-- | Print out the solution nicely. We have:
+--
+-- >>> solveEuler185
+-- 4640261571849533
+-- Number of solutions: 1
+solveEuler185 :: IO ()
+solveEuler185 = do res <- allSat euler185
+                   cnt <- displayModels id disp res
+                   putStrLn $ "Number of solutions: " ++ show cnt
+   where disp _ (_, ss) = putStrLn $ concatMap show (ss :: [Word8])
diff --git a/Documentation/SBV/Examples/Puzzles/Fish.hs b/Documentation/SBV/Examples/Puzzles/Fish.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Fish.hs
@@ -0,0 +1,126 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Fish
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the following logic puzzle, attributed to Albert Einstein:
+--
+--   - The Briton lives in the red house.
+--   - The Swede keeps dogs as pets.
+--   - The Dane drinks tea.
+--   - The green house is left to the white house.
+--   - The owner of the green house drinks coffee.
+--   - The person who plays football rears birds.
+--   - The owner of the yellow house plays baseball.
+--   - The man living in the center house drinks milk.
+--   - The Norwegian lives in the first house.
+--   - The man who plays volleyball lives next to the one who keeps cats.
+--   - The man who keeps the horse lives next to the one who plays baseball.
+--   - The owner who plays tennis drinks beer.
+--   - The German plays hockey.
+--   - The Norwegian lives next to the blue house.
+--   - The man who plays volleyball has a neighbor who drinks water.
+--
+-- Who owns the fish?
+------------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Fish where
+
+import Data.SBV
+
+-- | Colors of houses
+data Color = Red | Green | White | Yellow | Blue
+
+-- | Make 'Color' a symbolic value.
+mkSymbolic [''Color]
+
+-- | Nationalities of the occupants
+data Nationality = Briton | Dane | Swede | Norwegian | German
+                 deriving Show
+
+-- | Make 'Nationality' a symbolic value.
+mkSymbolic [''Nationality]
+
+-- | Beverage choices
+data Beverage = Tea | Coffee | Milk | Beer | Water
+
+-- | Make 'Beverage' a symbolic value.
+mkSymbolic [''Beverage]
+
+-- | Pets they keep
+data Pet = Dog | Horse | Cat | Bird | Fish
+
+-- | Make 'Pet' a symbolic value.
+mkSymbolic [''Pet]
+
+-- | Sports they engage in
+data Sport = Football | Baseball | Volleyball | Hockey | Tennis
+
+-- | Make 'Sport' a symbolic value.
+mkSymbolic [''Sport]
+
+-- | We have:
+--
+-- >>> fishOwner
+-- German
+--
+-- 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 'allSatTrackUFs' 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` allSatWith z3{allSatTrackUFs = False} puzzle
+               case vs of
+                 [Just (v::Nationality)] -> print v
+                 []                      -> error "no solution"
+                 _                       -> error "no unique solution"
+ where puzzle = do
+
+          let c = uninterpret "color"
+              n = uninterpret "nationality"
+              b = uninterpret "beverage"
+              p = uninterpret "pet"
+              s = uninterpret "sport"
+
+          let i `neighbor` j = i .== j+1 .|| j .== i+1
+              a `is`       v = a .== literal v
+
+          let fact0   = constrain
+              fact1 f = do i <- free_
+                           constrain $ 1 .<= i .&& i .<= (5 :: SInteger)
+                           constrain $ f i
+              fact2 f = do i <- free_
+                           j <- free_
+                           constrain $ 1 .<= i .&& i .<= (5 :: SInteger)
+                           constrain $ 1 .<= j .&& j .<= 5
+                           constrain $ i ./= j
+                           constrain $ f i j
+
+          fact1 $ \i   -> n i `is` Briton     .&& c i `is` Red
+          fact1 $ \i   -> n i `is` Swede      .&& p i `is` Dog
+          fact1 $ \i   -> n i `is` Dane       .&& b i `is` Tea
+          fact2 $ \i j -> c i `is` Green      .&& c j `is` White    .&& i .== j-1
+          fact1 $ \i   -> c i `is` Green      .&& b i `is` Coffee
+          fact1 $ \i   -> s i `is` Football   .&& p i `is` Bird
+          fact1 $ \i   -> c i `is` Yellow     .&& s i `is` Baseball
+          fact0 $         b 3 `is` Milk
+          fact0 $         n 1 `is` Norwegian
+          fact2 $ \i j -> s i `is` Volleyball .&& p j `is` Cat      .&& i `neighbor` j
+          fact2 $ \i j -> p i `is` Horse      .&& s j `is` Baseball .&& i `neighbor` j
+          fact1 $ \i   -> s i `is` Tennis     .&& b i `is` Beer
+          fact1 $ \i   -> n i `is` German     .&& s i `is` Hockey
+          fact2 $ \i j -> n i `is` Norwegian  .&& c j `is` Blue     .&& i `neighbor` j
+          fact2 $ \i j -> s i `is` Volleyball .&& b j `is` Water    .&& i `neighbor` j
+
+          ownsFish <- free "fishOwner"
+          fact1 $ \i -> n i .== ownsFish .&& p i `is` Fish
diff --git a/Documentation/SBV/Examples/Puzzles/Garden.hs b/Documentation/SBV/Examples/Puzzles/Garden.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Garden.hs
@@ -0,0 +1,91 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Garden
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The origin of this puzzle is Raymond Smullyan's "The Flower Garden" riddle:
+--
+--     In a certain flower garden, each flower was either red, yellow,
+--     or blue, and all three colors were represented. A statistician
+--     once visited the garden and made the observation that whatever
+--     three flowers you picked, at least one of them was bound to be red.
+--     A second statistician visited the garden and made the observation
+--     that whatever three flowers you picked, at least one was bound to
+--     be yellow.
+--
+--     Two logic students heard about this and got into an argument.
+--     The first student said: “It therefore follows that whatever
+--     three flowers you pick, at least one is bound to be blue, doesn’t
+--     it?” The second student said: “Of course not!”
+--
+--     Which student was right, and why?
+--
+-- We slightly modify the puzzle. Assuming the first student is right, we use
+-- SBV to show that the garden must contain exactly 3 flowers. In any other
+-- case, the second student would be right.
+------------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances  #-}
+{-# LANGUAGE TemplateHaskell    #-}
+{-# LANGUAGE TypeApplications   #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Garden where
+
+import Data.SBV
+
+-- | Colors of the flowers
+data Color = Red | Yellow | Blue
+
+-- | Make 'Color' a symbolic value.
+mkSymbolic [''Color]
+
+-- | Represent flowers by symbolic integers
+type Flower = SInteger
+
+-- | The uninterpreted function 'col' assigns a color to each flower.
+col :: Flower -> SBV Color
+col = uninterpret "col"
+
+-- | Describe a valid pick of three flowers @i@, @j@, @k@, assuming
+-- we have @n@ flowers to start with. Essentially the numbers should
+-- be within bounds and distinct.
+validPick :: SInteger -> Flower -> Flower -> Flower -> SBool
+validPick n i j k = distinct [i, j, k] .&& sAll ok [i, j, k]
+  where ok x = inRange x (1, n)
+
+-- | Count the number of flowers that occur in a given set of flowers.
+count :: Color -> [Flower] -> SInteger
+count c fs = sum [ite (col f .== literal c) 1 0 | f <- fs]
+
+-- | Smullyan's puzzle.
+puzzle :: ConstraintSet
+puzzle = do n <- sInteger "N"
+
+            let valid = validPick n
+
+            -- Each color is represented:
+            constrain $ \(Exists ef1) (Exists ef2) (Exists ef3) ->
+               valid ef1 ef2 ef3 .&& map col [ef1, ef2, ef3] .== [sRed, sYellow, sBlue]
+
+            -- Pick any three, at least one is Red, one is Yellow, one is Blue
+            constrain $ \(Forall af1) (Forall af2) (Forall af3) ->
+                let atLeastOne c = count c [af1, af2, af3] .>= 1
+                in valid af1 af2 af3 .=> atLeastOne Red .&& atLeastOne Yellow .&& atLeastOne Blue
+
+-- | Solve the puzzle. We have:
+--
+-- >>> flowerCount
+-- Solution #1:
+--   N = 3 :: Integer
+-- This is the only solution.
+--
+-- So, a garden with 3 flowers is the only solution. (Note that we simply skip
+-- 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{allSatTrackUFs=False} puzzle
diff --git a/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
@@ -0,0 +1,140 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.HexPuzzle
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- We're given a board, with 19 hexagon cells. The cells are arranged as follows:
+--
+-- @
+--                     01  02  03
+--                   04  05  06  07
+--                 08  09  10  11  12
+--                   13  14  15  16
+--                     17  18  19
+-- @
+--
+--   - Each cell has a color, one of @BLACK@, @BLUE@, @GREEN@, or @RED@.
+--
+--   - At each step, you get to press one of the center buttons. That is,
+--     one of 5, 6, 9, 10, 11, 14, or 15.
+--
+--   - Pressing a button that is currently colored @BLACK@ has no effect.
+--
+--   - Otherwise (i.e., if the pressed button is not @BLACK@), then colors
+--     rotate clockwise around that button. For instance if you press 15
+--     when it is not colored @BLACK@, then 11 moves to 16, 16 moves to 19,
+--     19 moves to 18, 18 moves to 14, 14 moves to 10, and 10 moves to 11.
+--
+--   - Note that by "move," we mean the colors move: We still refer to the buttons
+--     with the same number after a move.
+--
+-- You are given an initial board coloring, and a final one. Your goal is
+-- to find a minimal sequence of button presses that will turn the original board
+-- to the final one.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.HexPuzzle where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.Proxy
+
+-- | Colors we're allowed
+data Color = Black | Blue | Green | Red
+
+-- | Make 'Color' a symbolic value.
+mkSymbolic [''Color]
+
+-- | Use 8-bit words for button numbers, even though we only have 1 to 19.
+type Button  = Word8
+
+-- | Symbolic version of button.
+type SButton = SBV Button
+
+-- | The grid is an array mapping each button to its color.
+type Grid = SArray Button Color
+
+-- | Given a button press, and the current grid, compute the next grid.
+-- If the button is "unpressable", i.e., if it is not one of the center
+-- buttons or it is currently colored black, we return the grid unchanged.
+next :: SButton -> Grid -> Grid
+next b g = ite (readArray g b .== sBlack) g
+         $ ite (b .==  5)                        (rot [ 1,  2,  6, 10,  9,  4])
+         $ ite (b .==  6)                        (rot [ 2,  3,  7, 11, 10,  5])
+         $ ite (b .==  9)                        (rot [ 4,  5, 10, 14, 13,  8])
+         $ ite (b .== 10)                        (rot [ 5,  6, 11, 15, 14,  9])
+         $ ite (b .== 11)                        (rot [ 6,  7, 12, 16, 15, 10])
+         $ ite (b .== 14)                        (rot [ 9, 10, 15, 18, 17, 13])
+         $ ite (b .== 15)                        (rot [10, 11, 16, 19, 18, 14]) g
+  where rot xs = foldr (\(i, c) a -> writeArray a (literal i) c) g (zip new cur)
+          where cur = map (readArray g . literal) xs
+                new = drop 1 xs ++ take 1 xs
+
+-- | Iteratively search at increasing depths of button-presses to see if we can
+-- transform from the initial board position to a final board position.
+search :: [Color] -> [Color] -> IO ()
+search initial final = runSMT $ do registerType (Proxy @SColor)
+                                   let emptyGrid = constArray sBlack
+                                       initGrid  = foldr (\(i, c) a -> writeArray a (literal i) (literal c)) emptyGrid (zip [1..] initial)
+                                   query $ loop (0 :: Int) initGrid []
+
+  where loop i g sofar = do io $ putStrLn $ "Searching at depth: " ++ show i
+
+                            -- Go into a new context, and see if we've reached a solution:
+                            push 1
+                            constrain $ map (readArray g . literal) [1..19] .== map literal final
+                            cs <- checkSat
+
+                            case cs of
+                              Unk    -> error $ "Solver said Unknown, depth: " ++ show i
+
+                              DSat{} -> error $ "Solver returned a delta-satisfiable result, depth: " ++ show i
+
+                              Unsat  -> do -- It didn't work out. Pop and try again with one more move:
+                                           pop 1
+                                           b <- freshVar ("press_" ++ show i)
+                                           constrain $ b `sElem` map literal [5, 6, 9, 10, 11, 14, 15]
+                                           loop (i+1) (next b g) (sofar ++ [b])
+
+                              Sat    -> do vs <- mapM getValue sofar
+                                           io $ putStrLn $ "Found: " ++ show vs
+                                           findOthers sofar vs
+
+        findOthers vs = go
+                where go curVals = do constrain $ sOr $ zipWith (\v c -> v ./= literal c) vs curVals
+                                      cs <- checkSat
+                                      case cs of
+                                       Unk    -> error "Unknown!"
+                                       DSat{} -> error "Delta-sat!"
+                                       Unsat  -> io $ putStrLn "There are no more solutions."
+                                       Sat    -> do newVals <- mapM getValue vs
+                                                    io $ putStrLn $ "Found: " ++ show newVals
+                                                    go newVals
+
+-- | A particular example run. We have:
+--
+-- >>> example
+-- Searching at depth: 0
+-- Searching at depth: 1
+-- Searching at depth: 2
+-- Searching at depth: 3
+-- Searching at depth: 4
+-- Searching at depth: 5
+-- Searching at depth: 6
+-- Found: [10,10,9,11,14,6]
+-- Found: [10,10,11,9,14,6]
+-- There are no more solutions.
+example :: IO ()
+example = search initBoard finalBoard
+   where initBoard  = [Black, Black, Black, Red, Blue, Green, Red, Black, Green, Green, Green, Black, Red, Green, Green, Red, Black, Black, Black]
+         finalBoard = [Black, Red, Black, Black, Green, Green, Black, Red, Green, Blue, Green, Red, Black, Green, Green, Black, Black, Red, Black]
diff --git a/Documentation/SBV/Examples/Puzzles/Jugs.hs b/Documentation/SBV/Examples/Puzzles/Jugs.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Jugs.hs
@@ -0,0 +1,115 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Jugs
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the classic water jug puzzle: We have 3 jugs. The capacity of the jugs are 8, 5,
+-- and 3 gallons. We begin with the 8 gallon jug full, the other two empty. We can transfer
+-- from any jug to any other, completely topping off the latter. We want to end with
+-- 4 gallons of water in the first and second jugs, and with an empty third jug. What
+-- moves should we execute in order to do so?
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Jugs where
+
+import Data.SBV
+import Data.SBV.Control
+
+import GHC.Generics(Generic)
+
+-- | A Jug has a capacity (i.e., maximum amount of water it can hold), and content, showing how much
+-- it currently has. The invariant is that content is always non-negative and is at most the capacity.
+data Jug = Jug { capacity :: Integer
+               , content  :: SInteger
+               } deriving (Generic, Mergeable)
+
+-- | Transfer from one jug to another. By definition,
+-- we transfer to fill the second jug, which may end up
+-- filling it fully, or leaving some in the first jug.
+transfer :: Jug -> Jug -> (Jug, Jug)
+transfer j1 j2 = (j1', j2')
+  where empty         = literal (capacity j2) - content j2
+        transferrable = empty `smin` content j1
+        j1'           = j1 { content = content j1 - transferrable }
+        j2'           = j2 { content = content j2 + transferrable }
+
+-- | At the beginning, we have an full 8-gallon jug, and two empty jugs, 5 and 3 gallons each.
+initJugs :: (Jug, Jug, Jug)
+initJugs = (j1, j2, j3)
+  where j1 = Jug 8 8
+        j2 = Jug 5 0
+        j3 = Jug 3 0
+
+-- | We've solved the puzzle if 8 and 5 gallon jugs have 4 gallons each, and the third one is empty.
+solved :: (Jug, Jug, Jug) -> SBool
+solved (j1, j2, j3) = content j1 .== 4 .&& content j2 .== 4 .&& content j3 .== 0
+
+-- | Execute a bunch of moves.
+moves :: [(SInteger, SInteger)] -> (Jug, Jug, Jug)
+moves = foldl move initJugs
+  where move :: (Jug, Jug, Jug) -> (SInteger, SInteger) -> (Jug, Jug, Jug)
+        move (j0, j1, j2) (from, to) =
+              ite ((from, to) .== (1, 2)) (let (j0', j1') = transfer j0 j1 in (j0', j1', j2))
+            $ ite ((from, to) .== (2, 1)) (let (j1', j0') = transfer j1 j0 in (j0', j1', j2))
+            $ ite ((from, to) .== (1, 3)) (let (j0', j2') = transfer j0 j2 in (j0', j1,  j2'))
+            $ ite ((from, to) .== (3, 1)) (let (j2', j0') = transfer j2 j0 in (j0', j1,  j2'))
+            $ ite ((from, to) .== (2, 3)) (let (j1', j2') = transfer j1 j2 in (j0,  j1', j2'))
+            $ ite ((from, to) .== (3, 2)) (let (j2', j1') = transfer j2 j1 in (j0,  j1', j2'))
+                                          (j0, j1, j2)
+
+-- | Solve the puzzle. We have:
+--
+-- >>> puzzle
+-- # of moves: 0
+-- # of moves: 1
+-- # of moves: 2
+-- # of moves: 3
+-- # of moves: 4
+-- # of moves: 5
+-- # of moves: 6
+-- # of moves: 7
+-- 1 --> 2
+-- 2 --> 3
+-- 3 --> 1
+-- 2 --> 3
+-- 1 --> 2
+-- 2 --> 3
+-- 3 --> 1
+--
+-- Here's the contents in terms of gallons after each move:
+-- (8, 0, 0)
+-- (3, 5, 0)
+-- (3, 2, 3)
+-- (6, 2, 0)
+-- (6, 0, 2)
+-- (1, 5, 2)
+-- (1, 4, 3)
+-- (4, 4, 0)
+--
+-- Note that by construction this is the minimum length solution. (Though our construction
+-- does not guarantee that it is unique.)
+puzzle :: IO ()
+puzzle = runSMT $ do
+            let run i = do io $ putStrLn $ "# of moves: " ++ show (i :: Int)
+                           push 1
+                           ms <- mapM (const genMove) [1..i]
+                           constrain $ solved $ moves ms
+                           cs <- checkSat
+                           case cs of
+                             Unsat -> do pop 1
+                                         run (i+1)
+                             Sat   -> mapM_ sh ms
+                             _     -> error $ "Unexpected result: " ++ show cs
+            query $ run 0
+  where genMove = (,) <$> freshVar_ <*> freshVar_
+        sh (f, t) = do from <- getValue f
+                       to   <- getValue t
+                       io $ putStrLn $ show from ++ " --> " ++ show to
diff --git a/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs b/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/KnightsAndKnaves.hs
@@ -0,0 +1,134 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.KnightsAndKnaves
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- From Raymond Smullyan: On a fictional island, all inhabitants are either knights,
+-- who always tell the truth, or knaves, who always lie. John and Bill are residents
+-- of the island of knights and knaves. John and Bill make several utterances.
+-- Determine which one is a knave or a knight, depending on their answers.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+module Documentation.SBV.Examples.Puzzles.KnightsAndKnaves where
+
+import Prelude hiding (and, not)
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Inhabitants of the island, as an uninterpreted sort
+data Inhabitant
+mkSymbolic [''Inhabitant]
+
+-- | Each inhabitant is either a knave or a knight
+data Identity = Knave | Knight
+
+mkSymbolic [''Identity]
+
+-- | Statements are utterances which are either true or false
+data Statement = Truth | Falsity
+
+mkSymbolic [''Statement]
+
+-- | John is an inhabitant of the island.
+john :: SInhabitant
+john = uninterpret "John"
+
+-- | Bill is an inhabitant of the island.
+bill :: SInhabitant
+bill = uninterpret "Bill"
+
+-- | The connective 'is' makes a statement about an inhabitant regarding his/her identity.
+is :: SInhabitant -> SIdentity -> SStatement
+is = uninterpret "is"
+
+-- | The connective 'says' makes a predicate from what an inhabitant states
+says :: SInhabitant -> SStatement -> SBool
+says = uninterpret "says"
+
+-- | The connective 'holds' is will be true if the statement is true
+holds :: SStatement -> SBool
+holds = uninterpret "holds"
+
+-- | The connective 'and' creates the conjunction of two statements
+and :: SStatement -> SStatement -> SStatement
+and = uninterpret "AND"
+
+-- | The connective 'not' negates a statement
+not :: SStatement -> SStatement
+not = uninterpret "NOT"
+
+-- | The connective 'iff' creates a statement that equates the truth values of its argument statements
+iff :: SStatement -> SStatement -> SStatement
+iff = uninterpret "IFF"
+
+-- | Encode Smullyan's puzzle. We have:
+--
+-- >>> puzzle
+-- Question 1.
+--   John says, We are both knaves
+--     Then, John is: Knave
+--     And,  Bill is: Knight
+-- Question 2.
+--   John says If (and only if) Bill is a knave, then I am a knave.
+--   Bill says We are of different kinds.
+--     Then, John is: Knave
+--     And,  Bill is: Knight
+puzzle :: IO ()
+puzzle = runSMT $ do
+
+    -- truth holds, falsity doesn't
+    constrain $ holds sTruth
+    constrain $ sNot $ holds sFalsity
+
+    -- Each inhabitant is either a knave or a knight
+    constrain $ \(Forall x) -> holds (is x sKnave) .<+> holds (is x sKnight)
+
+    -- If x is a knave and he says something, then that statement is false
+    constrain $ \(Forall x) (Forall y) -> holds (is x sKnave)  .=> (says x y .=> sNot (holds y))
+
+    -- If x is a knight and he says something, then that statement is true
+    constrain $ \(Forall x) (Forall y) -> holds (is x sKnight) .=> (says x y .=> holds y)
+
+    -- The meaning of conjunction: It holds whenever both statements hold
+    constrain $ \(Forall x) (Forall y) -> holds (and x y) .== (holds x .&& holds y)
+
+    -- The meaning of negation: It holds when the original doesn't
+    constrain $ \(Forall x) -> holds (not x) .== sNot (holds x)
+
+    -- The meaning of iff: both statements hold or don't hold at the same time
+    constrain $ \(Forall x) (Forall y) -> holds (iff x y) .== (holds x .== holds y)
+
+    query $ do
+
+      -- helper to get the responses out
+      let checkStatus = do cs <- checkSat
+                           case cs of
+                             Sat -> do jk <- getValue (holds (is john sKnight))
+                                       bk <- getValue (holds (is bill sKnight))
+                                       io $ putStrLn $ "    Then, John is: " ++ if jk then "Knight" else "Knave"
+                                       io $ putStrLn $ "    And,  Bill is: " ++ if bk then "Knight" else "Knave"
+                             _   -> error $ "Solver said: " ++ show cs
+
+          question w q = inNewAssertionStack $ do
+                io $ putStrLn w
+                q >> checkStatus
+
+      -- Question 1
+      question "Question 1." $ do
+         io $ putStrLn "  John says, We are both knaves"
+         constrain $ says john (and (is john sKnave) (is bill sKnave))
+
+      -- Question 2
+      question "Question 2." $ do
+         io $ putStrLn "  John says If (and only if) Bill is a knave, then I am a knave."
+         io $ putStrLn "  Bill says We are of different kinds."
+         constrain $ says john (iff (is bill sKnave) (is john sKnave))
+         constrain $ says bill (not (iff (is bill sKnave) (is john sKnave)))
diff --git a/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs b/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs
@@ -0,0 +1,65 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.LadyAndTigers
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Puzzle:
+--
+--    You are standing in front of three rooms and must choose one. In one room is a Lady
+--    (whom you could and wish to marry), in the other two rooms are tigers (that if you
+--    choose either of these rooms, the tiger invites you to breakfast – the problem is
+--    that you are the main course). Your job is to choose the room with the Lady.
+--    The signs on the doors are:
+--
+--         * A Tiger is in this room
+--         * A Lady is in this room
+--         * A Tiger is in room two
+--
+--    At most only 1 statement is true. Where’s the Lady?
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.LadyAndTigers where
+
+import Data.SBV
+
+-- | Prints the only solution:
+--
+-- >>> ladyAndTigers
+-- Solution #1:
+--   sign1  = False :: Bool
+--   sign2  = False :: Bool
+--   sign3  =  True :: Bool
+--   tiger1 = False :: Bool
+--   tiger2 =  True :: Bool
+--   tiger3 =  True :: Bool
+-- This is the only solution.
+--
+-- That is, the lady is in room 1, and only the third room's sign is true.
+ladyAndTigers :: IO AllSatResult
+ladyAndTigers = allSat $ do
+
+    -- One boolean for each of the correctness of the signs
+    [sign1, sign2, sign3] <- mapM sBool ["sign1", "sign2", "sign3"]
+
+    -- One boolean for each of the presence of the tigers
+    [tiger1, tiger2, tiger3] <- mapM sBool ["tiger1", "tiger2", "tiger3"]
+
+    -- Room 1 sign: A Tiger is in this room
+    constrain $ sign1 .<=> tiger1
+
+    -- Room 2 sign: A Lady is in this room
+    constrain $ sign2 .<=> sNot tiger2
+
+    -- Room 3 sign: A Tiger is in room 2
+    constrain $ sign3 .<=> tiger2
+
+    -- At most one sign is true
+    constrain $ [sign1, sign2, sign3] `pbAtMost` 1
+
+    -- There are precisely two tigers
+    constrain $ [tiger1, tiger2, tiger3] `pbExactly` 2
diff --git a/Documentation/SBV/Examples/Puzzles/MagicSquare.hs b/Documentation/SBV/Examples/Puzzles/MagicSquare.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/MagicSquare.hs
@@ -0,0 +1,77 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.MagicSquare
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the magic-square puzzle. An NxN magic square is one where all entries
+-- are filled with numbers from 1 to NxN such that sums of all rows, columns
+-- and diagonals is the same.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.MagicSquare where
+
+import Data.List (genericLength, transpose)
+
+import Data.SBV
+
+-- | Use 32-bit words for elements.
+type Elem  = SWord32
+
+-- | A row is a list of elements
+type Row   = [Elem]
+
+-- | The puzzle board is a list of rows
+type Board = [Row]
+
+-- | Checks that all elements in a list are within bounds
+check :: Elem -> Elem -> [Elem] -> SBool
+check low high = sAll $ \x -> x .>= low .&& x .<= high
+
+-- | Get the diagonal of a square matrix
+diag :: [[a]] -> [a]
+diag ((a:_):rs) = a : diag (map (drop 1) rs)
+diag _          = []
+
+-- | Test if a given board is a magic square
+isMagic :: Board -> SBool
+isMagic rows = sAnd $ fromBool isSquare : allEqual (map sum items) : distinct (concat rows) : map chk items
+  where items = d1 : d2 : rows ++ columns
+        n = genericLength rows
+        isSquare = all (\r -> genericLength r == n) rows
+        columns = transpose rows
+        d1 = diag rows
+        d2 = diag (map reverse rows)
+        chk = check (literal 1) (literal (n*n))
+
+-- | Group a list of elements in the sublists of length @i@
+chunk :: Int -> [a] -> [[a]]
+chunk _ [] = []
+chunk i xs = let (f, r) = splitAt i xs in f : chunk i r
+
+-- | Given @n@, magic @n@ prints all solutions to the @nxn@ magic square problem
+magic :: Int -> IO ()
+magic n
+ | n < 0 = putStrLn $ "n must be non-negative, received: " ++ show n
+ | True  = do putStrLn $ "Finding all " ++ show n ++ "-magic squares.."
+              res <- allSat $ (isMagic . chunk n) `fmap` mkFreeVars n2
+              cnt <- displayModels id disp res
+              putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
+   where n2 = n * n
+         disp i (_, model)
+          | lmod /= n2
+          = error $ "Impossible! Backend solver returned " ++ show n ++ " values, was expecting: " ++ show lmod
+          | True
+          = do putStrLn $ "Solution #" ++ show i
+               mapM_ printRow board
+               putStrLn $ "Valid Check: " ++ show (isMagic sboard)
+               putStrLn "Done."
+          where lmod  = length model
+                board = chunk n model
+                sboard = map (map literal) board
+                sh2 z = let s = show z in if length s < 2 then ' ':s else s
+                printRow r = putStr "   " >> mapM_ (\x -> putStr (sh2 x ++ " ")) r >> putStrLn ""
diff --git a/Documentation/SBV/Examples/Puzzles/Murder.hs b/Documentation/SBV/Examples/Puzzles/Murder.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Murder.hs
@@ -0,0 +1,182 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Murder
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solution to "Malice and Alice," from George J. Summers' Logical Deduction Puzzles:
+--
+-- @
+-- A man and a woman were together in a bar at the time of the murder.
+-- The victim and the killer were together on a beach at the time of the murder.
+-- One of Alice’s two children was alone at the time of the murder.
+-- Alice and her husband were not together at the time of the murder.
+-- The victim's twin was not the killer.
+-- The killer was younger than the victim.
+--
+-- Who killed who?
+-- @
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror   #-}
+
+module Documentation.SBV.Examples.Puzzles.Murder where
+
+import Data.Char
+import Data.List
+
+import Data.SBV hiding (some)
+import Data.SBV.Control
+
+-- | Locations
+data Location = Bar | Beach | Alone
+              deriving Show
+
+-- | Sexes
+data Sex = Male | Female
+         deriving Show
+
+-- | Roles
+data Role = Victim | Killer | Bystander
+          deriving Show
+
+mkSymbolic [''Location]
+mkSymbolic [''Sex]
+mkSymbolic [''Role]
+
+-- | A person has a name, age, together with location and sex.
+-- We parameterize over a function so we can use this struct
+-- both in a concrete context and a symbolic context. Note
+-- that the name is always concrete.
+data Person f = Person { nm       :: String
+                       , age      :: f Integer
+                       , location :: f Location
+                       , sex      :: f Sex
+                       , role     :: f Role
+                       }
+
+-- | Helper functor
+newtype Const a = Const { getConst :: a }
+
+-- | Show a person
+instance Show (Person Const) where
+  show (Person n a l s r) = unwords [n, show (getConst a), show (getConst l), show (getConst s), show (getConst r)]
+
+-- | Create a new symbolic person
+newPerson :: String -> Symbolic (Person SBV)
+newPerson n = do
+        p <- Person n <$> free_ <*> free_ <*> free_ <*> free_
+        constrain $ age p .>= 20
+        constrain $ age p .<= 50
+        pure p
+
+-- | Get the concrete value of the person in the model
+getPerson :: Person SBV -> Query (Person Const)
+getPerson Person{nm, age, location, sex, role} = Person nm <$> (Const <$> getValue age)
+                                                           <*> (Const <$> getValue location)
+                                                           <*> (Const <$> getValue sex)
+                                                           <*> (Const <$> getValue role)
+
+-- | Solve the puzzle. We have:
+--
+-- >>> killer
+-- Alice     48  Bar    Female  Bystander
+-- Husband   47  Beach  Male    Killer
+-- Brother   48  Beach  Male    Victim
+-- Daughter  21  Alone  Female  Bystander
+-- Son       20  Bar    Male    Bystander
+--
+-- That is, Alice's brother was the victim and Alice's husband was the killer.
+killer :: IO ()
+killer = do
+   persons <- puzzle
+   let wps      = map (words . show) persons
+       cwidths  = map ((+2) . maximum . map length) (transpose wps)
+       align xs = concat $ zipWith (\i f -> take i (f ++ repeat ' ')) cwidths xs
+       trim     = reverse . dropWhile isSpace . reverse
+   mapM_ (putStrLn . trim . align) wps
+
+-- | Constraints of the puzzle, coded following the English description.
+puzzle :: IO [Person Const]
+puzzle = runSMT $ do
+  alice    <- newPerson "Alice"
+  husband  <- newPerson "Husband"
+  brother  <- newPerson "Brother"
+  daughter <- newPerson "Daughter"
+  son      <- newPerson "Son"
+
+  -- Sex of each character
+  constrain $ sex alice    .== sFemale
+  constrain $ sex husband  .== sMale
+  constrain $ sex brother  .== sMale
+  constrain $ sex daughter .== sFemale
+  constrain $ sex son      .== sMale
+
+  let chars = [alice, husband, brother, daughter, son]
+
+  -- Age relationships. To come up with "reasonable" numbers,
+  -- we make the kids at least 25 years younger than the parents
+  constrain $ age son      .<  age alice    - 25
+  constrain $ age son      .<  age husband  - 25
+  constrain $ age daughter .<  age alice    - 25
+  constrain $ age daughter .<  age husband  - 25
+
+  -- Ensure that there's a twin. Looking at the characters, the
+  -- only possibilities are either Alice's kids, or Alice and her brother
+  constrain $ age son .== age daughter .|| age alice .== age brother
+
+  -- One victim, one killer
+  constrain $ sum (map (\c -> oneIf (role c .== sVictim)) chars) .== (1 :: SInteger)
+  constrain $ sum (map (\c -> oneIf (role c .== sKiller)) chars) .== (1 :: SInteger)
+
+  let ifVictim p = role p .== sVictim
+      ifKiller p = role p .== sKiller
+
+      every f = sAll f chars
+      some  f = sAny f chars
+
+  -- A man and a woman were together in a bar at the time of the murder.
+  constrain $ some $ \c -> sex c .== sFemale .&& location c .== sBar
+  constrain $ some $ \c -> sex c .== sMale   .&& location c .== sBar
+
+  -- The victim and the killer were together on a beach at the time of the murder.
+  constrain $ every $ \c -> ifVictim c .=> location c .== sBeach
+  constrain $ every $ \c -> ifKiller c .=> location c .== sBeach
+
+  -- One of Alice’s two children was alone at the time of the murder.
+  constrain $ location daughter .== sAlone .|| location son .== sAlone
+
+  -- Alice and her husband were not together at the time of the murder.
+  constrain $ location alice ./= location husband
+
+  -- The victim has a twin
+  constrain $ every $ \c -> ifVictim c .=> some (\d -> literal (nm c /= nm d) .&& age c .== age d)
+
+  -- The victim's twin was not the killer.
+  constrain $ every $ \c -> ifVictim c .=> every (\d -> age c .== age d .=> role d ./= sKiller)
+
+  -- The killer was younger than the victim.
+  constrain $ every $ \c -> ifKiller c .=> every (\d -> ifVictim d .=> age c .< age d)
+
+  -- Ensure certain pairs can't be twins
+  constrain $ age husband ./= age brother
+  constrain $ age husband ./= age alice
+
+  query $ do cs <- checkSat
+             case cs of
+               Sat -> do a <- getPerson alice
+                         h <- getPerson husband
+                         b <- getPerson brother
+                         d <- getPerson daughter
+                         s <- getPerson son
+                         pure [a, h, b, d, s]
+               _   -> error $ "Solver said: " ++ show cs
+
+{- HLint ignore getPerson "Functor law" -}
diff --git a/Documentation/SBV/Examples/Puzzles/NQueens.hs b/Documentation/SBV/Examples/Puzzles/NQueens.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/NQueens.hs
@@ -0,0 +1,48 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.NQueens
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the NQueens puzzle: <http://en.wikipedia.org/wiki/Eight_queens_puzzle>
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.NQueens where
+
+import Data.SBV
+
+-- | A solution is a sequence of row-numbers where queens should be placed
+type Solution = [SWord8]
+
+-- | Checks that a given solution of @n@-queens is valid, i.e., no queen
+-- captures any other.
+isValid :: Int -> Solution -> SBool
+isValid n s = sAll rangeFine s .&& distinct s .&& sAll checkDiag ijs
+  where rangeFine x = x .>= 1 .&& x .<= fromIntegral n
+        ijs = [(i, j) | i <- [1..n], j <- [i+1..n]]
+        checkDiag (i, j) = diffR ./= diffC
+           where qi = s !! (i-1)
+                 qj = s !! (j-1)
+                 diffR = ite (qi .>= qj) (qi-qj) (qj-qi)
+                 diffC = fromIntegral (j-i)
+
+-- | Given @n@, it solves the @n-queens@ puzzle, printing all possible solutions.
+nQueens :: Int -> IO ()
+nQueens n
+ | n < 0 = putStrLn $ "n must be non-negative, received: " ++ show n
+ | True  = do putStrLn $ "Finding all " ++ show n ++ "-queens solutions.."
+              res <- allSat $ isValid n `fmap` mkFreeVars n
+              cnt <- displayModels id disp res
+              putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
+   where disp i (_, s) = do putStr $ "Solution #" ++ show i ++ ": "
+                            dispSolution s
+         dispSolution :: [Word8] -> IO ()
+         dispSolution model
+           | lmod /= n = error $ "Impossible! Backend solver returned " ++ show lmod ++ " values, was expecting: " ++ show n
+           | True      = do putStr $ show model
+                            putStrLn $ " (Valid: " ++ show (isValid n (map literal model)) ++ ")"
+           where lmod  = length model
diff --git a/Documentation/SBV/Examples/Puzzles/Newspaper.hs b/Documentation/SBV/Examples/Puzzles/Newspaper.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Newspaper.hs
@@ -0,0 +1,104 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Newspaper
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solution to the following puzzle (found at <http://hugopeters.me/posts/15>)
+-- which contains 10 questions:
+--
+-- @
+-- a. What is sum of all integer answers?
+-- b. How many boolean answers are true?
+-- c. Is a the largest number?
+-- d. How many integers are equal to me?
+-- e. Are all integers positive?
+-- f. What is the average of all integers?
+-- g. Is d strictly larger than b?
+-- h. What is a / h?
+-- i. Is f equal to d - b - h * d?
+-- j. What is the answer to this question?
+-- @
+--
+-- Note that @j@ is ambiguous: It can be a boolean or an integer. We use
+-- the solver to decide what its type should be, so that all the other
+-- answers are consistent with that decision.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Newspaper where
+
+import Data.SBV
+import Data.SBV.Either
+
+-- | Encoding of the constraints.
+puzzle :: Symbolic ()
+puzzle = do
+    a <- sInteger "a"
+    b <- sInteger "b"
+    c <- sBool    "c"
+    d <- sInteger "d"
+    e <- sBool    "e"
+    f <- sInteger "f"
+    g <- sBool    "g"
+    h <- sInteger "h"
+    i <- sBool    "i"
+    j <- sEither  "j"
+
+    jIsInt <- sBool "jIsInt"
+
+    let ints  intj = [a, b, d, f, h] ++ [fromRight j |     intj]
+        bools intj = [c, e, g, i]    ++ [fromLeft  j | not intj]
+
+        choice fn = ite jIsInt (fn True) (fn False)
+
+    -- a. What is sum of all integer answers?
+    constrain $ a .== choice (sum . ints)
+
+    -- b. How many boolean answers are true?
+    constrain $ b .== choice (sum . map oneIf . bools)
+
+    -- c. Is a the largest number?
+    constrain $ c .== (a .== choice (foldr1 smax . ints))
+
+    -- d. How many integers are equal to me?
+    constrain $ d .== choice (sum . map (oneIf . (d .==)) . ints)
+
+    -- e. Are all integers positive?
+    constrain $ e .== choice (sAll (.> 0) . ints)
+
+    -- f. What is the average of all integers?
+    constrain $ f * choice (literal . toInteger . length . ints) .== choice (sum . ints)
+
+    -- g. is d strictly larger than b?
+    constrain $ g .== (d .> b)
+
+    -- h. what is a / h?
+    constrain $ h * h .== a
+
+    -- i. is f equal to d - b - h * d?
+    constrain $ i .== (f .== d - b - h * d)
+
+    -- j. what is the answer to this question?
+    constrain $ ite jIsInt (isRight j) (isLeft j)
+
+-- | Print all solutions to the problem. We have:
+--
+-- >>> solvePuzzle
+-- Solution #1:
+--   a =         144 :: Integer
+--   b =           2 :: Integer
+--   c =        True :: Bool
+--   d =           2 :: Integer
+--   e =       False :: Bool
+--   f =          24 :: Integer
+--   g =       False :: Bool
+--   h =         -12 :: Integer
+--   i =        True :: Bool
+--   j = Right (-16) :: Either Bool Integer
+-- This is the only solution.
+solvePuzzle :: IO ()
+solvePuzzle = print =<< allSatWith z3{isNonModelVar = (== "jIsInt")} puzzle
diff --git a/Documentation/SBV/Examples/Puzzles/Orangutans.hs b/Documentation/SBV/Examples/Puzzles/Orangutans.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Orangutans.hs
@@ -0,0 +1,117 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Orangutans
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Based on <http://github.com/goldfirere/video-resources/blob/main/2022-08-12-java/Haskell.hs>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DeriveAnyClass      #-}
+{-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Orangutans where
+
+import Data.SBV
+import GHC.Generics (Generic)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Orangutans in the puzzle.
+data Orangutan = Merah | Ofallo | Quirrel | Shamir
+               deriving (Show, Enum, Bounded)
+
+-- | Handlers for each orangutan.
+data Handler = Dolly | Eva | Francine | Gracie
+
+-- | Location for each orangutan.
+data Location = Ambalat | Basahan | Kendisi | Tarakan
+
+mkSymbolic [''Orangutan]
+mkSymbolic [''Handler]
+mkSymbolic [''Location]
+
+-- | An assignment is solution to the puzzle
+data Assignment = MkAssignment { orangutan :: SOrangutan
+                               , handler   :: SHandler
+                               , location  :: SLocation
+                               , age       :: SInteger
+                               }
+                               deriving (Generic, Mergeable)
+
+-- | Create a symbolic assignment, using symbolic fields.
+mkSym :: Orangutan -> Symbolic Assignment
+mkSym o = do let h = show o ++ ".handler"
+                 l = show o ++ ".location"
+                 a = show o ++ ".age"
+             s <- MkAssignment (literal o) <$> free h <*> free l <*> free a
+             constrain $ s.age `sElem` [4, 7, 10, 13]
+             pure s
+
+-- | We get:
+--
+-- >>> allSat puzzle
+-- Solution #1:
+--   Merah.handler    =   Gracie :: Handler
+--   Merah.location   =  Tarakan :: Location
+--   Merah.age        =       10 :: Integer
+--   Ofallo.handler   =      Eva :: Handler
+--   Ofallo.location  =  Kendisi :: Location
+--   Ofallo.age       =       13 :: Integer
+--   Quirrel.handler  =    Dolly :: Handler
+--   Quirrel.location =  Basahan :: Location
+--   Quirrel.age      =        4 :: Integer
+--   Shamir.handler   = Francine :: Handler
+--   Shamir.location  =  Ambalat :: Location
+--   Shamir.age       =        7 :: Integer
+-- This is the only solution.
+puzzle :: ConstraintSet
+puzzle = do
+   solution@[_merah, ofallo, quirrel, shamir] <- mapM mkSym [minBound .. maxBound]
+
+   let find f = foldr1 (\a1 a2 -> ite (f a1) a1 a2) solution
+
+   -- 0. All are different in terms of handlers, locations, and ages
+   constrain $ distinct (map (.handler)  solution)
+   constrain $ distinct (map (.location) solution)
+   constrain $ distinct (map (.age)      solution)
+
+   -- 1. Shamir is 7 years old.
+   constrain $ shamir.age .== 7
+
+   -- 2. Shamir came from Ambalat.
+   constrain $ shamir.location .== sAmbalat
+
+   -- 3. Quirrel is younger than the ape that was found in Tarakan.
+   let tarakan = find (\a -> a.location .== sTarakan)
+   constrain $ quirrel.age .< tarakan.age
+
+   -- 4. Of Ofallo and the ape that was found in Tarakan, one is cared for by Gracie and the other is 13 years old.
+   let clue4 a1 a2 = a1.handler .== sGracie .&& a2.age .== 13
+   constrain $ clue4 ofallo tarakan .|| clue4 tarakan ofallo
+   constrain $ sOfallo ./= tarakan.orangutan
+
+   -- 5. The animal that was found in Ambalat is either the 10-year-old or the animal Francine works with.
+   let ambalat = find (\a -> a.location .== sAmbalat)
+   constrain $ ambalat.age .== 10 .|| ambalat.handler .== sFrancine
+
+   -- 6. Ofallo isn't 10 years old.
+   constrain $ ofallo.age ./= 10
+
+   -- 7. The ape that was found in Kendisi is older than the ape Dolly works with.
+   let kendisi = find (\a -> a.location .== sKendisi)
+   let dolly   = find (\a -> a.handler  .== sDolly)
+   constrain $ kendisi.age .> dolly.age
diff --git a/Documentation/SBV/Examples/Puzzles/Rabbits.hs b/Documentation/SBV/Examples/Puzzles/Rabbits.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Rabbits.hs
@@ -0,0 +1,64 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Rabbits
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A puzzle, attributed to Lewis Caroll:
+--
+--   - All rabbits, that are not greedy, are black
+--   - No old rabbits are free from greediness
+--   - Therefore: Some black rabbits are not old
+--
+-- What's implicit here is that there is a rabbit that must be not-greedy;
+-- which we add to our constraints.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Rabbits where
+
+import Data.SBV
+
+-- | A universe of rabbits
+data Rabbit
+
+-- | Make rabbits symbolically available.
+mkSymbolic [''Rabbit]
+
+-- | Identify those rabbits that are greedy. Note that we leave the predicate uninterpreted.
+greedy :: SRabbit -> SBool
+greedy = uninterpret "greedy"
+
+-- | Identify those rabbits that are black. Note that we leave the predicate uninterpreted.
+black :: SRabbit -> SBool
+black = uninterpret "black"
+
+-- | Identify those rabbits that are old. Note that we leave the predicate uninterpreted.
+old :: SRabbit -> SBool
+old = uninterpret "old"
+
+-- | Express the puzzle.
+rabbits :: Predicate
+rabbits = do -- All rabbits that are not greedy are black
+             constrain $ \(Forall x) -> sNot (greedy x) .=> black  x
+
+             -- No old rabbits are free from greediness
+             constrain $ \(Forall x) -> old x .=> greedy x
+
+             -- There is at least one non-greedy rabbit
+             constrain $ \(Exists x) -> sNot (greedy x)
+
+             -- Therefore, there must be a black rabbit that's not old:
+             pure $ quantifiedBool $ \(Exists x) -> black x .&& sNot (old x)
+
+-- | Prove the claim. We have:
+--
+-- >>> rabbitsAreOK
+-- Q.E.D.
+rabbitsAreOK :: IO ThmResult
+rabbitsAreOK = prove rabbits
diff --git a/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs b/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs
@@ -0,0 +1,47 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.SendMoreMoney
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the classic @send + more = money@ puzzle.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.SendMoreMoney where
+
+import Data.SBV
+
+-- | Solve the puzzle. We have:
+--
+-- >>> sendMoreMoney
+-- Solution #1:
+--   s = 9 :: Integer
+--   e = 5 :: Integer
+--   n = 6 :: Integer
+--   d = 7 :: Integer
+--   m = 1 :: Integer
+--   o = 0 :: Integer
+--   r = 8 :: Integer
+--   y = 2 :: Integer
+-- This is the only solution.
+--
+-- That is:
+--
+-- >>> 9567 + 1085 == 10652
+-- True
+sendMoreMoney :: IO AllSatResult
+sendMoreMoney = allSat $ do
+        ds@[s,e,n,d,m,o,r,y] <- mapM sInteger ["s", "e", "n", "d", "m", "o", "r", "y"]
+        let isDigit x = x .>= 0 .&& x .<= 9
+            val xs    = sum $ zipWith (*) (reverse xs) (iterate (*10) 1)
+            send      = val [s,e,n,d]
+            more      = val [m,o,r,e]
+            money     = val [m,o,n,e,y]
+        constrain $ sAll isDigit ds
+        constrain $ distinct ds
+        constrain $ s ./= 0 .&& m ./= 0
+        solve [send + more .== money]
diff --git a/Documentation/SBV/Examples/Puzzles/SquareBirthday.hs b/Documentation/SBV/Examples/Puzzles/SquareBirthday.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/SquareBirthday.hs
@@ -0,0 +1,202 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.SquareBirthday
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- As of January 2026, to access the careers link at <http://math.inc>, you need to solve the following
+-- puzzle:
+--
+-- @
+-- Suppose that today is June 1, 2025. We call a date "square" if all of its components (day, month, and year) are
+-- perfect squares. I was born in the last millennium, and my next birthday (relative to that date) will be the last
+-- square date in my life. If you sum the square roots of the components of that upcoming square birthday
+-- (day, month, year), you obtain my age on June 1, 2025. My mother would have been born on a square date if the month
+-- were a square number; in reality it is not a square date, but both the month and day are perfect cubes. When was
+-- I born, and when was my mother born?
+-- @
+--
+-- So, let's solve it using SBV.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE TypeFamilies        #-}
+{-# LANGUAGE OverloadedRecordDot #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.SquareBirthday where
+
+import Prelude hiding (fromEnum, toEnum)
+
+import Data.SBV
+import Data.SBV.Control
+
+import qualified Data.SBV.List  as SL
+import qualified Data.SBV.Tuple as ST
+
+-- | Months in a year.
+data Month = Jan | Feb | Mar | Apr | May | Jun
+           | Jul | Aug | Sep | Oct | Nov | Dec
+           deriving Show
+
+-- | A date. We use unbounded integers for day and year, which simplifies coding,
+-- though one can also enumerate the possible values from the problem itself.
+data Date = MkDate { day   :: Integer
+                   , month :: Month
+                   , year  :: Integer
+                   }
+
+-- | Make 'Month' and 'Date' usable in symbolic contexts.
+mkSymbolic [''Month, ''Date]
+
+-- | Show instance for date, for pretty-printing.
+instance Show Date where
+  show (MkDate d m y) = show m ++ " " ++ pad ++ show d ++ ", " ++ show y
+   where pad | d < 10 = " "
+             | True   = ""
+
+-- | Get a symbolic date with the given name. Since we used
+-- integers for the day and year fields, we constrain them
+-- appropriately. Note that one can further constrain days
+-- based on the year and month; but that level detail isn't
+-- necessary for the current problem.
+symDate :: String -> Symbolic SDate
+symDate nm = do dt <- free nm
+
+                constrain [sCase| dt of
+                              MkDate d _ y -> sAnd [ 1 .<= d, d .<= 31
+                                                   , 0 .<= y
+                                                   ]
+                          |]
+
+                pure dt
+
+-- | Encode today as a symbolic value. The puzzle says today is June 1st, 2025.
+today :: SDate
+today = literal $ MkDate { day   =    1
+                         , month =  Jun
+                         , year  = 2025
+                         }
+
+-- | A date is on or after another, if the month-day combo is
+-- lexicographically later. Note that we ignore the year for this
+-- comparison, as we're interested if the anniversary of a date is after or not.
+onOrAfter :: SDate -> SDate -> SBool
+d1 `onOrAfter` d2 = (smonth d1, sday d1) .>= (smonth d2, sday d2)
+
+-- | Similar to 'onOrAfter', except we require strictly later.
+after :: SDate -> SDate -> SBool
+d1 `after` d2 = (smonth d1, sday d1) .>  (smonth d2, sday d2)
+
+-- | The age based on a given date is the difference between years less than one.
+-- We have to adjust by 1 if today happens to be after the given date.
+age :: SDate -> SInteger
+age d = syear today - syear d - 1 + oneIf (today `after` d)
+
+-- | We can let years to range over arbitrary integers. But that complicates the
+-- job of the solver. So, based on what we know from the problem, we restrict
+-- our attention to years between 1900 and 2100. Note that there are only
+-- two years that satisfy this in that range: 1936 and 2025. (Any other square
+-- year makes no sense for the setting of the problem.) To simplify the square-root
+-- computation, we also store the square root in this list as the second component:
+--
+-- >>> squareYears
+-- [(1936,44),(2025,45)]
+squareYears :: [(Integer, Integer)]
+squareYears = takeWhile (\(y, _) -> y < 2100)
+            $ dropWhile (\(y, _) -> y < 1900)
+            $ [(i * i, i) | i <- [1::Integer ..]]
+
+-- | A date is square if all its components are.
+squareDate :: SDate -> SBool
+squareDate dt = [sCase| dt of
+                   MkDate d m y -> squareDay d .&& squareMonth m .&& squareYear y
+                |]
+  where squareDay   d = d `sElem` [1, 4, 9, 16, 25]
+        squareMonth m = m `sElem` [sJan, sApr, sSep]
+        squareYear  y = y `sElem` map (literal . fst) squareYears
+
+
+-- | Summing the square-roots of the components of a date.
+sqrSum :: SDate -> SInteger
+sqrSum dt = [sCase| dt of
+               MkDate d m y -> r d + mr m + r y
+            |]
+ where r v  = v `SL.lookup` literal ([(i * i, i) | i <- [1, 2, 3, 4, 5]] ++ squareYears)
+
+       mr :: SMonth -> SInteger
+       mr m = [sCase| m of
+                  Jan -> 1
+                  Apr -> 2
+                  Sep -> 3
+                  _   -> some "Non-Square Month" (const sTrue)
+              |]
+
+-- | Formalizing the puzzle. We literally write down the description in
+-- SBV notation. As with any formalization, this step is subjective; there
+-- could be many different ways to express the same problem. The description
+-- below is quite faithful to the problem description given. We have:
+--
+-- >>> puzzle
+-- Me : Sep 25, 1971
+-- Mom: Aug  1, 1936
+puzzle :: IO ()
+puzzle = runSMT $ do
+
+    -----------------------------------
+    -- Constraints about my birthday
+    -----------------------------------
+    myBirthday <- symDate "My Birthday"
+
+    -- I was born in the last millennium
+    constrain $ syear myBirthday .< 2000 .&& syear myBirthday .>= 1900
+
+    -- My next birthday will be a square
+    let next = [sCase| myBirthday of
+                  MkDate d m _ -> sMkDate d m (syear today + oneIf (today `onOrAfter` myBirthday))
+               |]
+
+    constrain $ squareDate next
+
+    -- And it'll be the last square day of my life, so we maximize the metric corresponding to the
+    -- date. We turn it into a 3-tuple of year, month, date over integers, which preserves the
+    -- order of the dates.
+    maximize "Next Birthday Latest" $ ST.tuple (syear next, fromEnum (smonth next), sday next)
+
+    -- If you square the components of my next birthday, it gives me my current age on Jun 1, 2025
+    constrain $ sqrSum next .== age myBirthday
+
+    -----------------------------------
+    -- Constraints about mom's birthday
+    -----------------------------------
+    momBirthday <- symDate "Mom's Birthday"
+
+    -- Mom has a square birth-date, except for the month:
+    constrain [sCase| momBirthday of
+                 MkDate d _ y -> squareDate (sMkDate d sJan y)
+              |]
+
+    -- Mom's day and month are perfect cubes
+    constrain [sCase| momBirthday of
+                 MkDate d m _ -> sAnd [ d `sElem` [1, 8, 27]
+                                      , m `sElem` [sJan, sAug]
+                                      ]
+              |]
+
+    -- Extract the results:
+    query $ do cs <- checkSat
+               case cs of
+                 Sat -> do me  <- getValue myBirthday
+                           mom <- getValue momBirthday
+
+                           io $ do putStrLn $ "Me : " ++ show me
+                                   putStrLn $ "Mom: " ++ show mom
+
+                 _   -> error $ "Unexpected result: " ++ show cs
diff --git a/Documentation/SBV/Examples/Puzzles/Sudoku.hs b/Documentation/SBV/Examples/Puzzles/Sudoku.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Sudoku.hs
@@ -0,0 +1,191 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Sudoku
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The Sudoku solver, quintessential SMT solver example!
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Sudoku where
+
+import Control.Monad (when, zipWithM_)
+
+import Control.Monad.State.Lazy
+
+import Data.List     (transpose)
+
+import Data.SBV
+import Data.SBV.Control
+
+-------------------------------------------------------------------
+-- * Modeling Sudoku
+-------------------------------------------------------------------
+-- | A row is a sequence of digits that we represent symbolic integers
+type Row = [SInteger]
+
+-- | A Sudoku board is a sequence of 9 rows
+type Board = [Row]
+
+-- | Given a series of elements, make sure they are all different
+-- and they all are numbers between 1 and 9
+check :: [SInteger] -> SBool
+check grp = sAnd $ distinct grp : map rangeFine grp
+  where rangeFine x = x `inRange` (1, 9)
+
+-- | Given a full Sudoku board, check that it is valid
+valid :: Board -> SBool
+valid rows = sAnd $ literal sizesOK : map check (rows ++ columns ++ squares)
+  where sizesOK = length rows == 9 && all (\r -> length r == 9) rows
+
+        columns = transpose rows
+        regions = transpose [chunk 3 row | row <- rows]
+        squares = [concat sq | sq <- chunk 3 (concat regions)]
+
+        chunk :: Int -> [a] -> [[a]]
+        chunk _ [] = []
+        chunk i xs = let (f, r) = splitAt i xs in f : chunk i r
+
+-- | A puzzle is simply a list of rows. Put 0 to indicate blanks.
+type Puzzle = [[Integer]]
+
+-------------------------------------------------------------------
+-- * Solving Sudoku puzzles
+-------------------------------------------------------------------
+
+-- | Fill a given board, replacing 0's with appropriate elements to solve the puzzle
+fillBoard :: Puzzle -> IO Puzzle
+fillBoard board = runSMT $ do
+     let emptyCellCount = length $ concatMap (filter (== 0)) board
+     subst <- mkFreeVars emptyCellCount
+     constrain $ valid (fill literal subst)
+
+     query $ do cs <- checkSat
+                case cs of
+                  Sat   -> do vals <- mapM getValue subst
+                              pure $ fill id vals
+                  Unsat -> error "Unsolvable puzzle!"
+                  _     -> error $ "Solver said: " ++ show cs
+
+ where fill xform = evalState (mapM (mapM replace) board)
+         where replace 0 = do supply <- get
+                              case supply of
+                                []     -> error "Run out of supplies while filling in the board!"
+                                (s:ss) -> put ss >> pure s
+               replace n = pure $ xform n
+
+-- | Solve a given puzzle and print the results
+sudoku :: Puzzle -> IO ()
+sudoku board = fillBoard board >>= displayBoard
+ where displayBoard :: Puzzle -> IO ()
+       displayBoard puzzle = do
+            let sh       i r = show r ++ if i `elem` [3, 6] then " " else ""
+                printRow i r = do putStrLn $ "    " ++ unwords (zipWith sh [(1::Int)..] r)
+                                  when (i `elem` [3, 6]) $ putStrLn ""
+            zipWithM_ printRow [(1::Int)..] puzzle
+
+            let isValid = valid (map (map literal) puzzle)
+            case unliteral isValid of
+               Just True  -> pure ()
+               Just False -> error "Invalid solution generated!"
+               Nothing    -> error "Impossible happened, got a symbolic result for valid."
+
+-------------------------------------------------------------------
+-- * Example boards
+-------------------------------------------------------------------
+
+-- | A random puzzle, found on the internet..
+puzzle1 :: Puzzle
+puzzle1 = [ [0, 6, 0,   0, 0, 0,   0, 1, 0]
+          , [0, 0, 0,   6, 5, 1,   0, 0, 0]
+          , [1, 0, 7,   0, 0, 0,   6, 0, 2]
+
+          , [6, 2, 0,   3, 0, 5,   0, 9, 4]
+          , [0, 0, 3,   0, 0, 0,   2, 0, 0]
+          , [4, 8, 0,   9, 0, 7,   0, 3, 6]
+
+          , [9, 0, 6,   0, 0, 0,   4, 0, 8]
+          , [0, 0, 0,   7, 9, 4,   0, 0, 0]
+          , [0, 5, 0,   0, 0, 0,   0, 7, 0] ]
+
+-- | Another random puzzle, found on the internet..
+puzzle2 :: Puzzle
+puzzle2 = [ [1, 0, 3,   0, 0, 0,   0, 8, 0]
+          , [0, 0, 6,   0, 4, 8,   0, 0, 0]
+          , [0, 4, 0,   0, 0, 0,   0, 0, 0]
+
+          , [2, 0, 0,   0, 9, 6,   1, 0, 0]
+          , [0, 9, 0,   8, 0, 1,   0, 4, 0]
+          , [0, 0, 4,   3, 2, 0,   0, 0, 8]
+
+          , [0, 0, 0,   0, 0, 0,   0, 7, 0]
+          , [0, 0, 0,   1, 5, 0,   4, 0, 0]
+          , [0, 6, 0,   0, 0, 0,   2, 0, 3] ]
+
+-- | Another random puzzle, found on the internet..
+puzzle3 :: Puzzle
+puzzle3 = [ [6, 0, 0,   0, 1, 0,   5, 0, 0]
+          , [8, 0, 3,   0, 0, 0,   0, 0, 0]
+          , [0, 0, 0,   0, 6, 0,   0, 2, 0]
+
+          , [0, 3, 0,   1, 0, 8,   0, 9, 0]
+          , [1, 0, 0,   0, 9, 0,   0, 0, 4]
+          , [0, 5, 0,   2, 0, 3,   0, 1, 0]
+
+          , [0, 7, 0,   0, 3, 0,   0, 0, 0]
+          , [0, 0, 0,   0, 0, 0,   3, 0, 6]
+          , [0, 0, 4,   0, 5, 0,   0, 0, 9] ]
+
+-- | According to the web, this is the toughest.
+-- sudoku puzzle ever.. It even has a name: Al Escargot:
+-- <http://zonkedyak.blogspot.com/2006/11/worlds-hardest-sudoku-puzzle-al.html>
+puzzle4 :: Puzzle
+puzzle4 = [ [1, 0, 0,   0, 0, 7,   0, 9, 0]
+          , [0, 3, 0,   0, 2, 0,   0, 0, 8]
+          , [0, 0, 9,   6, 0, 0,   5, 0, 0]
+
+          , [0, 0, 5,   3, 0, 0,   9, 0, 0]
+          , [0, 1, 0,   0, 8, 0,   0, 0, 2]
+          , [6, 0, 0,   0, 0, 4,   0, 0, 0]
+
+          , [3, 0, 0,   0, 0, 0,   0, 1, 0]
+          , [0, 4, 0,   0, 0, 0,   0, 0, 7]
+          , [0, 0, 7,   0, 0, 0,   3, 0, 0] ]
+
+-- | This one has been called diabolical, apparently
+puzzle5 :: Puzzle
+puzzle5 = [ [ 0, 9, 0,   7, 0, 0,   8, 6, 0]
+          , [ 0, 3, 1,   0, 0, 5,   0, 2, 0]
+          , [ 8, 0, 6,   0, 0, 0,   0, 0, 0]
+
+          , [ 0, 0, 7,   0, 5, 0,   0, 0, 6]
+          , [ 0, 0, 0,   3, 0, 7,   0, 0, 0]
+          , [ 5, 0, 0,   0, 1, 0,   7, 0, 0]
+
+          , [ 0, 0, 0,   0, 0, 0,   1, 0, 9]
+          , [ 0, 2, 0,   6, 0, 0,   3, 5, 0]
+          , [ 0, 5, 4,   0, 0, 8,   0, 7, 0] ]
+
+-- | Another example
+puzzle6 :: Puzzle
+puzzle6 = [ [0, 0, 0,   0, 6, 0,   0, 8, 0]
+          , [0, 2, 0,   0, 0, 0,   0, 0, 0]
+          , [0, 0, 1,   0, 0, 0,   0, 0, 0]
+
+          , [0, 7, 0,   0, 0, 0,   1, 0, 2]
+          , [5, 0, 0,   0, 3, 0,   0, 0, 0]
+          , [0, 0, 0,   0, 0, 0,   4, 0, 0]
+
+          , [0, 0, 4,   2, 0, 1,   0, 0, 0]
+          , [3, 0, 0,   7, 0, 0,   6, 0, 0]
+          , [0, 0, 0,   0, 0, 0,   0, 5, 0] ]
+
+-- | Solve them all, this takes a fraction of a second to run for each case
+allPuzzles :: IO ()
+allPuzzles = mapM_ sudoku [puzzle1, puzzle2, puzzle3, puzzle4, puzzle5, puzzle6]
diff --git a/Documentation/SBV/Examples/Puzzles/Tower.hs b/Documentation/SBV/Examples/Puzzles/Tower.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/Tower.hs
@@ -0,0 +1,153 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.Tower
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Solves the tower puzzle, <http://www.chiark.greenend.org.uk/%7Esgtatham/puzzles/js/towers.html>.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.Tower where
+
+import Control.Monad
+import Data.Array hiding (inRange)
+import Data.SBV
+import Data.SBV.Control
+
+-------------------------------------------------------------------
+-- * Modeling Towers
+-------------------------------------------------------------------
+
+-- | Count of visible towers as an array.
+type Count a = Array Integer a
+
+-- | The grid itself. The indexes are tuples, first coordinate increases as you go from
+-- left to right, and the second increases as you go from top to bottom.
+type Grid a = Array (Integer, Integer) a
+
+-- | The problem has 4 counts, from top, left, bottom, and right. And the grid itself.
+type Problem a = (Count a, Count a, Count a, Count a, Grid a)
+
+-- | Example problem. Encodes:
+--
+-- @
+--     - - 3 - - 4
+--   -     2       5
+--   -   2         -
+--   4             -
+--   2             -
+--   -             2
+--   3             -
+--     - - 3 4 - -
+-- @
+problem :: Problem (Maybe Integer)
+problem = (top, left, bot, right, grid)
+  where build ix es = accumArray (\_ a -> a) Nothing ix [(i, Just v) | (i, v) <- es]
+
+        top   = build  (1, 6)          [(3, 3), (6, 4)]
+        left  = build  (1, 6)          [(3, 4), (4, 2), (6, 3)]
+        bot   = build  (1, 6)          [(3, 3), (4, 4)]
+        right = build  (1, 6)          [(1, 5), (5, 2)]
+        grid  = build ((1, 1), (6, 6)) [((3, 1), 2), ((2, 2), 2)]
+
+-- | Given a concrete partial board, turn it into a symbolic board, by filling in the
+-- empty cells with symbolic variables.
+symProblem :: Problem (Maybe Integer) -> Symbolic (Problem SInteger)
+symProblem (t, l, b, r, g) = (,,,,) <$> fill t <*> fill l <*> fill b <*> fill r <*> fill g
+ where fill :: Traversable f => f (Maybe Integer) -> Symbolic (f SInteger)
+       fill = mapM (maybe free_ (pure . literal))
+
+-------------------------------------------------------------------
+-- * Counting visible towers
+-------------------------------------------------------------------
+
+-- | Given a list of tower heights, count the number of visible ones in the given order.
+-- We simply keep track of the tallest we have seen so far, and increment the count for
+-- each tower we see if it's taller than the tallest seen so far.
+visible :: [SInteger] -> SInteger
+visible = go 0 0
+ where go _            visibleSofar []     = visibleSofar
+       go tallestSofar visibleSofar (x:xs) = go (tallestSofar `smax` x)
+                                                (ite (x .> tallestSofar) (1 + visibleSofar) visibleSofar)
+                                                xs
+
+-------------------------------------------------------------------
+-- * Building constraints
+-------------------------------------------------------------------
+
+-- | Build the constraints for a given problem. We scan the elements and add the required
+-- visibility counts for each row and column, viewed both in the correct order and in the backwards order.
+tower :: Problem SInteger -> Symbolic ()
+tower (top, left, bot, right, grid) = do
+  let (minX, maxX) = bounds top
+      (minY, maxY) = bounds left
+
+  -- Constraints from top and bottom
+  forM_ [minX .. maxX] $ \x -> do
+      let reqT = top ! x
+          reqB = bot ! x
+          elts = [grid ! (x, y) | y <- [minY .. maxY]]
+      mapM_ (\e -> constrain (inRange e (literal 1, literal maxY))) elts
+      constrain $ distinct elts
+      constrain $ reqT .== visible elts
+      constrain $ reqB .== visible (reverse elts)
+
+  -- Constraints from left and right
+  forM_ [minY .. maxY] $ \y -> do
+      let reqL = left  ! y
+          reqR = right ! y
+          elts = [grid ! (x, y) | x <- [minX .. maxX]]
+      mapM_ (\e -> constrain (inRange e (literal 1, literal maxX))) elts
+      constrain $ distinct elts
+      constrain $ reqL .== visible elts
+      constrain $ reqR .== visible (reverse elts)
+
+-------------------------------------------------------------------
+-- * Example run
+-------------------------------------------------------------------
+
+-- | Solve the puzzle described above. We get:
+--
+-- >>> example
+--   1 2 3 2 2 4
+-- 1 6 5 2 4 3 1 5
+-- 3 3 2 5 6 1 4 2
+-- 4 2 4 1 5 6 3 2
+-- 2 5 3 6 1 4 2 3
+-- 2 1 6 4 3 2 5 2
+-- 3 4 1 3 2 5 6 1
+--   3 2 3 4 2 1
+example :: IO ()
+example = runSMT $ do
+        sp <- symProblem problem
+        tower sp
+        query $ do cs <- checkSat
+                   case cs of
+                     Unsat -> io $ putStrLn "Unsolvable"
+                     Sat   -> display sp
+                     _     -> error $ "Unexpected result: " ++ show cs
+ where display :: Problem SInteger -> Query ()
+       display (top, left, bot, right, grid) = do
+          let (minX, maxX) = bounds top
+              (minY, maxY) = bounds left
+
+          -- Display top row
+          io $ putStr "  "
+          topVals <- forM [minX .. maxX] $ \x -> getValue (top ! x)
+          io $ putStrLn $ unwords (map show topVals)
+
+          -- Display each row, sandwiched between left/right
+          forM_ [minY .. maxY] $ \y -> do
+             lv <- getValue (left  ! y)
+             rv <- getValue (right ! y)
+             row <- forM [minX .. maxX] $ \x -> getValue (grid ! (x, y))
+             io $ putStrLn $ unwords (map show (lv : row ++ [rv]))
+
+          -- Finish with bottom row
+          io $ putStr "  "
+          botVals <- forM [minX .. maxX] $ \x -> getValue (bot ! x)
+          io $ putStrLn $ unwords (map show botVals)
diff --git a/Documentation/SBV/Examples/Puzzles/U2Bridge.hs b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
@@ -0,0 +1,273 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Puzzles.U2Bridge
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The famous U2 bridge crossing puzzle: <http://www.braingle.com/brainteasers/515/u2.html>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass    #-}
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Puzzles.U2Bridge where
+
+import Control.Monad       (unless)
+import Control.Monad.State (State, runState, put, get, gets, modify, evalState)
+
+import Data.List(sortOn)
+
+import GHC.Generics (Generic)
+
+import Data.SBV
+
+-------------------------------------------------------------
+-- * Modeling the puzzle
+-------------------------------------------------------------
+
+-- | U2 band members.
+data U2Member = Bono | Edge | Adam | Larry
+              deriving Show
+
+-- | Make 'U2Member' a symbolic value.
+mkSymbolic [''U2Member]
+
+-- | Model time using 32 bits
+type Time  = Word32
+
+-- | Symbolic variant for time
+type STime = SBV Time
+
+-- | Crossing times for each member of the band
+crossTime :: U2Member -> Time
+crossTime Bono  = 1
+crossTime Edge  = 2
+crossTime Adam  = 5
+crossTime Larry = 10
+
+-- | The symbolic variant.. The duplication is unfortunate.
+sCrossTime :: SU2Member -> STime
+sCrossTime m =   ite (m .== sBono) (literal (crossTime Bono))
+               $ ite (m .== sEdge) (literal (crossTime Edge))
+               $ ite (m .== sAdam) (literal (crossTime Adam))
+                                   (literal (crossTime Larry)) -- Must be Larry
+
+-- | Location of the flash
+data Location = Here | There
+              deriving (Eq, Show, Enum, Bounded)
+
+-- | Make 'Location' a symbolic value.
+mkSymbolic [''Location]
+
+-- | The status of the puzzle after each move
+--
+-- This type is equipped with an automatically derived 'Mergeable' instance
+-- because each field is 'Mergeable'. A 'Generic' instance must also be derived
+-- for this to work, and the @DeriveAnyClass@ language extension must be
+-- enabled. The derived 'Mergeable' instance simply walks down the structure
+-- field by field and merges each one. An equivalent hand-written 'Mergeable'
+-- instance is provided in a comment below.
+data Status = Status { time   :: STime       -- ^ elapsed time
+                     , flash  :: SLocation   -- ^ location of the flash
+                     , lBono  :: SLocation   -- ^ location of Bono
+                     , lEdge  :: SLocation   -- ^ location of Edge
+                     , lAdam  :: SLocation   -- ^ location of Adam
+                     , lLarry :: SLocation   -- ^ location of Larry
+                     } deriving (Generic, Mergeable)
+
+-- The derived Mergeable instance is equivalent to the following:
+--
+-- instance Mergeable Status where
+--   symbolicMerge f t s1 s2 = Status { time   = symbolicMerge f t (time   s1) (time   s2)
+--                                    , flash  = symbolicMerge f t (flash  s1) (flash  s2)
+--                                    , lBono  = symbolicMerge f t (lBono  s1) (lBono  s2)
+--                                    , lEdge  = symbolicMerge f t (lEdge  s1) (lEdge  s2)
+--                                    , lAdam  = symbolicMerge f t (lAdam  s1) (lAdam  s2)
+--                                    , lLarry = symbolicMerge f t (lLarry s1) (lLarry s2)
+--                                    }
+
+-- | Start configuration, time elapsed is 0 and everybody is here
+start :: Status
+start = Status { time   = 0
+               , flash  = sHere
+               , lBono  = sHere
+               , lEdge  = sHere
+               , lAdam  = sHere
+               , lLarry = sHere
+               }
+
+-- | A puzzle move is modeled as a state-transformer
+type Move a = State Status a
+
+-- | Mergeable instance for 'Move' simply pushes the merging the data after run of each branch
+-- starting from the same state.
+instance Mergeable a => Mergeable (Move a) where
+  symbolicMerge f t a b
+    = do s <- get
+         let (ar, s1) = runState a s
+             (br, s2) = runState b s
+         put $ symbolicMerge f t s1 s2
+         pure $ symbolicMerge f t ar br
+
+-- | Read the state via an accessor function
+peek :: (Status -> a) -> Move a
+peek = gets
+
+-- | Given an arbitrary member, return his location
+whereIs :: SU2Member -> Move SLocation
+whereIs p =  ite (p .== sBono) (peek lBono)
+           $ ite (p .== sEdge) (peek lEdge)
+           $ ite (p .== sAdam) (peek lAdam)
+                               (peek lLarry)
+
+-- | Transferring the flash to the other side
+xferFlash :: Move ()
+xferFlash = modify $ \s -> s{flash = ite (flash s .== sHere) sThere sHere}
+
+-- | Transferring a person to the other side
+xferPerson :: SU2Member -> Move ()
+xferPerson p =  do lb <- peek lBono
+                   le <- peek lEdge
+                   la <- peek lAdam
+                   ll <- peek lLarry
+                   let move l = ite (l .== sHere) sThere sHere
+                       lb' = ite (p .== sBono)  (move lb) lb
+                       le' = ite (p .== sEdge)  (move le) le
+                       la' = ite (p .== sAdam)  (move la) la
+                       ll' = ite (p .== sLarry) (move ll) ll
+                   modify $ \s -> s{lBono = lb', lEdge = le', lAdam = la', lLarry = ll'}
+
+-- | Increment the time, when only one person crosses
+bumpTime1 :: SU2Member -> Move ()
+bumpTime1 p = modify $ \s -> s{time = time s + sCrossTime p}
+
+-- | Increment the time, when two people cross together
+bumpTime2 :: SU2Member -> SU2Member -> Move ()
+bumpTime2 p1 p2 = modify $ \s -> s{time = time s + sCrossTime p1 `smax` sCrossTime p2}
+
+-- | Symbolic version of 'Control.Monad.when'
+whenS :: SBool -> Move () -> Move ()
+whenS t a = ite t a (pure ())
+
+-- | Move one member, remembering to take the flash
+move1 :: SU2Member -> Move ()
+move1 p = do f <- peek flash
+             l <- whereIs p
+             -- only do the move if the person and the flash are at the same side
+             whenS (f .== l) $ do bumpTime1 p
+                                  xferFlash
+                                  xferPerson p
+
+-- | Move two members, again with the flash
+move2 :: SU2Member -> SU2Member -> Move ()
+move2 p1 p2 = do f  <- peek flash
+                 l1 <- whereIs p1
+                 l2 <- whereIs p2
+                 -- only do the move if both people and the flash are at the same side
+                 whenS (f .== l1 .&& f .== l2) $ do bumpTime2 p1 p2
+                                                    xferFlash
+                                                    xferPerson p1
+                                                    xferPerson p2
+
+-------------------------------------------------------------
+-- * Actions
+-------------------------------------------------------------
+
+-- | A move action is a sequence of triples. The first component is symbolically
+-- True if only one member crosses. (In this case the third element of the triple
+-- is irrelevant.) If the first component is (symbolically) False, then both members
+-- move together
+type Actions = [(SBool, SU2Member, SU2Member)]
+
+-- | Run a sequence of given actions.
+run :: Actions -> Move [Status]
+run = mapM step
+ where step (b, p1, p2) = ite b (move1 p1) (move2 p1 p2) >> get
+
+-------------------------------------------------------------
+-- * Recognizing valid solutions
+-------------------------------------------------------------
+
+-- | Check if a given sequence of actions is valid, i.e., they must all
+-- cross the bridge according to the rules and in less than 17 seconds
+isValid :: Actions -> SBool
+isValid as =   time end .<= 17
+           .&& sAll check as
+           .&& zigZag (cycle [sThere, sHere]) (map flash states)
+           .&& sAll (.== sThere) [lBono end, lEdge end, lAdam end, lLarry end]
+  where check (s, p1, p2) =   (sNot s .=> p1 .>  p2)    -- for two person moves, ensure first person is "larger"
+                          .&& (s      .=> p2 .== sBono) -- for one person moves, ensure second person is always "bono"
+        states = evalState (run as) start
+        end = last states
+        zigZag reqs locs = sAnd $ zipWith (.==) locs reqs
+
+-------------------------------------------------------------
+-- * Solving the puzzle
+-------------------------------------------------------------
+
+-- | See if there is a solution that has precisely @n@ steps
+solveN :: Int -> IO Bool
+solveN n = do putStrLn $ "Checking for solutions with " ++ show n ++ " move" ++ plu n ++ "."
+              let genAct = do b  <- free_
+                              p1 <- free_
+                              p2 <- free_
+                              pure (b, p1, p2)
+              res <- allSat $ isValid `fmap` mapM (const genAct) [1..n]
+              cnt <- displayModels (sortOn show) disp res
+              if cnt == 0 then pure False
+                          else do putStrLn $ "Found: " ++ show cnt ++ " solution" ++ plu cnt ++ " with " ++ show n ++ " move" ++ plu n ++ "."
+                                  pure True
+  where plu v = if v == 1 then "" else "s"
+        disp :: Int -> (Bool, [(Bool, U2Member, U2Member)]) -> IO ()
+        disp i (_, ss)
+         | lss /= n = error $ "Expected " ++ show n ++ " results; got: " ++ show lss
+         | True     = do putStrLn $ "Solution #" ++ show i ++ ":"
+                         go False 0 ss
+                         pure ()
+         where lss  = length ss
+               go _ t []                   = putStrLn $ "Total time: " ++ show t
+               go l t ((True,  a, _):rest) = do putStrLn $ sh2 t ++ shL l ++ show a
+                                                go (not l) (t + crossTime a) rest
+               go l t ((False, a, b):rest) = do putStrLn $ sh2 t ++ shL l ++ show a ++ ", " ++ show b
+                                                go (not l) (t + crossTime a `max` crossTime b) rest
+               sh2 t = let s = show t in if length s < 2 then ' ' : s else s
+               shL False = " --> "
+               shL True  = " <-- "
+
+-- | Solve the U2-bridge crossing puzzle, starting by testing solutions with
+-- increasing number of steps, until we find one. We have:
+--
+-- >>> solveU2
+-- Checking for solutions with 1 move.
+-- Checking for solutions with 2 moves.
+-- Checking for solutions with 3 moves.
+-- Checking for solutions with 4 moves.
+-- Checking for solutions with 5 moves.
+-- Solution #1:
+--  0 --> Edge, Bono
+--  2 <-- Bono
+--  3 --> Larry, Adam
+-- 13 <-- Edge
+-- 15 --> Edge, Bono
+-- Total time: 17
+-- Solution #2:
+--  0 --> Edge, Bono
+--  2 <-- Edge
+--  4 --> Larry, Adam
+-- 14 <-- Bono
+-- 15 --> Edge, Bono
+-- Total time: 17
+-- Found: 2 solutions with 5 moves.
+--
+-- Finding all possible solutions to the puzzle.
+solveU2 :: IO ()
+solveU2 = go 1
+ where go i = do p <- solveN i
+                 unless p $ go (i+1)
diff --git a/Documentation/SBV/Examples/Queries/Abducts.hs b/Documentation/SBV/Examples/Queries/Abducts.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/Abducts.hs
@@ -0,0 +1,50 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.Abducts
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates extraction of abducts via queries.
+--
+-- N.B. Interpolants are only supported by CVC5 currently.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.Abducts where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Abduct extraction example. We have the constraint @x >= 0@
+-- and we want to make @x + y >= 2@. We have:
+--
+-- >>> example
+-- Got: (define-fun abd () Bool (= s1 2))
+-- Got: (define-fun abd () Bool (and (= s1 1) (= s1 s0)))
+-- Got: (define-fun abd () Bool (and (= s0 2) (= s1 1)))
+-- Got: (define-fun abd () Bool (and (<= 1 s0) (= s1 1)))
+--
+-- Note that @s0@ refers to @x@ and @s1@ refers to @y@ above. You can verify
+-- that adding any of these will ensure @x + y >= 2@.
+example :: IO ()
+example = runSMTWith cvc5 $ do
+
+       setOption $ ProduceAbducts True
+
+       x <- sInteger "x"
+       y <- sInteger "y"
+
+       constrain $ x .>= 0
+
+       query $ do abd <- getAbduct Nothing "abd" $ x + y .>= 2
+                  io $ putStrLn $ "Got: " ++ abd
+
+                  let next = getAbductNext >>= io . putStrLn . ("Got: " ++)
+
+                  -- Get and display a couple of abducts
+                  next
+                  next
+                  next
diff --git a/Documentation/SBV/Examples/Queries/AllSat.hs b/Documentation/SBV/Examples/Queries/AllSat.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/AllSat.hs
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.AllSat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- When we would like to find all solutions to a problem, we can query the
+-- solver repeatedly, telling it to give us a new model each time. SBV already
+-- provides 'Data.SBV.allSat' that precisely does this. However, this example demonstrates
+-- how the query mode can be used to achieve the same, and can also incorporate
+-- extra conditions with ease as we walk through solutions.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.AllSat where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Find all solutions to @x + y .== 10@ for positive @x@ and @y@.
+-- This is rather silly to do in the query mode as `allSat` can do
+-- this automatically, but it demonstrates how we can dynamically
+-- query the result and put in new constraints based on those.
+goodSum :: Symbolic [(Integer, Integer)]
+goodSum = do x <- sInteger "x"
+             y <- sInteger "y"
+
+             -- constrain positive and sum:
+             constrain $ x .>= 0
+             constrain $ y .>= 0
+             constrain $ x + y .== 10
+
+             -- Capture the "next" solution function:
+             let next i sofar = do
+                    io $ putStrLn $ "Iteration: " ++ show (i :: Integer)
+
+                    -- Using a check-sat assuming, we force the solver to walk through
+                    -- the entire range of x's
+                    cs <- checkSatAssuming [x .== literal (i-1)]
+
+                    case cs of
+                      Unk    -> error "Too bad, solver said unknown.." -- Won't happen
+                      DSat{} -> error "Unexpected dsat result.."       -- Won't happen
+                      Unsat  -> do io $ putStrLn "No other solution!"
+                                   pure $ reverse sofar
+
+                      Sat    -> do xv <- getValue x
+                                   yv <- getValue y
+
+                                   io $ putStrLn $ "Current solution is: " ++ show (xv, yv)
+
+                                   -- For next iteration: Put in constraints outlawing the current one:
+                                   -- Note that we do *not* put these separately, as we do want
+                                   -- to allow repetition on one value if the other is different!
+                                   constrain $   x ./= literal xv
+                                             .|| y ./= literal yv
+
+                                   -- loop around!
+                                   next (i+1) ((xv, yv) : sofar)
+
+             -- Go into query mode and execute the loop:
+             query $ do io $ putStrLn "Starting the all-sat engine!"
+                        next 1 []
+
+-- | Run the query. We have:
+--
+-- >>> demo
+-- Starting the all-sat engine!
+-- Iteration: 1
+-- Current solution is: (0,10)
+-- Iteration: 2
+-- Current solution is: (1,9)
+-- Iteration: 3
+-- Current solution is: (2,8)
+-- Iteration: 4
+-- Current solution is: (3,7)
+-- Iteration: 5
+-- Current solution is: (4,6)
+-- Iteration: 6
+-- Current solution is: (5,5)
+-- Iteration: 7
+-- Current solution is: (6,4)
+-- Iteration: 8
+-- Current solution is: (7,3)
+-- Iteration: 9
+-- Current solution is: (8,2)
+-- Iteration: 10
+-- Current solution is: (9,1)
+-- Iteration: 11
+-- Current solution is: (10,0)
+-- Iteration: 12
+-- No other solution!
+-- [(0,10),(1,9),(2,8),(3,7),(4,6),(5,5),(6,4),(7,3),(8,2),(9,1),(10,0)]
+demo :: IO ()
+demo = print =<< runSMT goodSum
diff --git a/Documentation/SBV/Examples/Queries/CaseSplit.hs b/Documentation/SBV/Examples/Queries/CaseSplit.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/CaseSplit.hs
@@ -0,0 +1,85 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.CaseSplit
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A couple of demonstrations for the 'caseSplit' function.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.CaseSplit where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | A simple floating-point problem, but we do the sat-analysis via a case-split.
+-- Due to the nature of floating-point numbers, a case-split on the characteristics
+-- of the number (such as NaN, negative-zero, etc. is most suitable.)
+--
+-- We have:
+--
+-- >>> csDemo1
+-- Case fpIsNegativeZero: Starting
+-- Case fpIsNegativeZero: Unsatisfiable
+-- Case fpIsPositiveZero: Starting
+-- Case fpIsPositiveZero: Unsatisfiable
+-- Case fpIsNormal: Starting
+-- Case fpIsNormal: Unsatisfiable
+-- Case fpIsSubnormal: Starting
+-- Case fpIsSubnormal: Unsatisfiable
+-- Case fpIsPoint: Starting
+-- Case fpIsPoint: Unsatisfiable
+-- Case fpIsNaN: Starting
+-- Case fpIsNaN: Satisfiable
+-- ("fpIsNaN",NaN)
+csDemo1 :: IO (String, Float)
+csDemo1 = runSMT $ do
+
+       x <- sFloat "x"
+
+       constrain $ x ./= x -- yes, in the FP land, this is satisfiable by NaN
+
+       query $ do mbR <- caseSplit True [ ("fpIsNegativeZero", fpIsNegativeZero x)
+                                        , ("fpIsPositiveZero", fpIsPositiveZero x)
+                                        , ("fpIsNormal",       fpIsNormal       x)
+                                        , ("fpIsSubnormal",    fpIsSubnormal    x)
+                                        , ("fpIsPoint",        fpIsPoint        x)
+                                        , ("fpIsNaN",          fpIsNaN          x)
+                                        ]
+
+                  case mbR of
+                    Nothing     -> error "Cannot find a FP number x such that x /= x"  -- Won't happen!
+                    Just (s, _) -> do xv <- getValue x
+                                      pure (s, xv)
+
+-- | Demonstrates the "coverage" case.
+--
+-- We have:
+--
+-- >>> csDemo2
+-- Case negative: Starting
+-- Case negative: Unsatisfiable
+-- Case less than 8: Starting
+-- Case less than 8: Unsatisfiable
+-- Case Coverage: Starting
+-- Case Coverage: Satisfiable
+-- ("Coverage",10)
+csDemo2 :: IO (String, Integer)
+csDemo2 = runSMT $ do
+
+       x <- sInteger "x"
+
+       constrain $ x .== 10
+
+       query $ do mbR <- caseSplit True [ ("negative"   , x .< 0)
+                                        , ("less than 8", x .< 8)
+                                        ]
+
+                  case mbR of
+                    Nothing     -> error "Cannot find a solution!" -- Won't happen!
+                    Just (s, _) -> do xv <- getValue x
+                                      pure (s, xv)
diff --git a/Documentation/SBV/Examples/Queries/Concurrency.hs b/Documentation/SBV/Examples/Queries/Concurrency.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/Concurrency.hs
@@ -0,0 +1,176 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.Concurrency
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- When we would like to solve a set of related problems we can use query mode
+-- to perform push's and pop's. However performing a push and a pop is still
+-- single threaded and so each solution will need to wait for the previous
+-- solution to be found. In this example we show a class of functions
+-- 'Data.SBV.satConcurrentWithAll' and 'Data.SBV.satConcurrentWithAny' which spin up
+-- independent solver instances and runs query computations concurrently. The
+-- children query computations are allowed to communicate with one another as
+-- demonstrated in the second demo.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.Concurrency where
+
+import Data.SBV
+import Data.SBV.Control
+import Control.Concurrent
+import Control.Monad.IO.Class (liftIO)
+
+-- | Find all solutions to @x + y .== 10@ for positive @x@ and @y@, but at each
+-- iteration we would like to ensure that the value of @x@ we get is at least
+-- twice as large as the previous one. This is rather silly, but demonstrates
+-- how we can dynamically query the result and put in new constraints based on
+-- those.
+shared :: MVar (SInteger, SInteger) -> Symbolic ()
+shared v = do
+  x <- sInteger "x"
+  y <- sInteger "y"
+  constrain $ y .<= 10
+  constrain $ x .<= 10
+  constrain $ x + y .== 10
+  liftIO $ putMVar v (x,y)
+
+-- | In our first query we'll define a constraint that will not be known to the
+-- shared or second query and then solve for an answer that will differ from the
+-- first query. Note that we need to pass an MVar in so that we can operate on
+-- the shared variables. In general, the variables you want to operate on should
+-- be defined in the shared part of the query and then passed to the children
+-- queries via channels, MVars, or TVars. In this query we constrain x to be
+-- less than y and then return the sum of the values. We add a threadDelay just
+-- for demonstration purposes
+queryOne :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
+queryOne v = do
+  io $ putStrLn "[One]: Waiting"
+  liftIO $ threadDelay 5000000
+  io $ putStrLn "[One]: Done"
+  (x,y) <- liftIO $ takeMVar v
+  constrain $ x .< y
+
+  cs <- checkSat
+  case cs of
+    Unk    -> error "Too bad, solver said unknown.." -- Won't happen
+    DSat{} -> error "Unexpected dsat result.."       -- Won't happen
+    Unsat  -> do io $ putStrLn "No other solution!"
+                 pure Nothing
+
+    Sat    -> do xv <- getValue x
+                 yv <- getValue y
+                 io $ putStrLn $ "[One]: Current solution is: " ++ show (xv, yv)
+                 pure $ Just (xv + yv)
+
+-- | In the second query we constrain for an answer where y is smaller than x,
+-- and then return the product of the found values.
+queryTwo :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
+queryTwo v = do
+  (x,y) <- liftIO $ takeMVar v
+  io $ putStrLn $ "[Two]: got values" ++ show (x,y)
+  constrain $ y .< x
+
+  cs <- checkSat
+  case cs of
+    Unk    -> error "Too bad, solver said unknown.." -- Won't happen
+    DSat{} -> error "Unexpected dsat result.."       -- Won't happen
+    Unsat  -> do io $ putStrLn "No other solution!"
+                 pure Nothing
+
+    Sat    -> do yv <- getValue y
+                 xv <- getValue x
+                 io $ putStrLn $ "[Two]: Current solution is: " ++ show (xv, yv)
+                 pure $ Just (xv * yv)
+
+-- | Run the demo several times to see that the children threads will change ordering.
+demo :: IO ()
+demo = do
+  v <- newEmptyMVar
+  putStrLn "[Main]: Hello from main, kicking off children: "
+  results <- satConcurrentWithAll z3 [queryOne v, queryTwo v] (shared v)
+  putStrLn "[Main]: Children spawned, waiting for results"
+  putStrLn "[Main]: Here they are: "
+  print results
+
+-- | Example computation.
+sharedDependent :: MVar (SInteger, SInteger) -> Symbolic ()
+sharedDependent v = do -- constrain positive and sum:
+  x <- sInteger "x"
+  y <- sInteger "y"
+  constrain $ y .<= 10
+  constrain $ x .<= 10
+  constrain $ x + y .== 10
+  liftIO $ putMVar v (x,y)
+
+-- | In our first query we will make a constrain, solve the constraint and
+-- return the values for our variables, then we'll mutate the MVar sending
+-- information to the second query. Note that you could use channels, or TVars,
+-- or TMVars, whatever you need here, we just use MVars for demonstration
+-- purposes. Also note that this effectively creates an ordering between the
+-- children queries
+firstQuery :: MVar (SInteger, SInteger) -> MVar (SInteger , SInteger) -> Query (Maybe Integer)
+firstQuery v1 v2 = do
+  (x,y) <- liftIO $ takeMVar v1
+  io $ putStrLn "[One]: got vars...working..."
+  constrain $ x .< y
+
+  cs <- checkSat
+  case cs of
+    Unk    -> error "Too bad, solver said unknown.." -- Won't happen
+    DSat{} -> error "Unexpected dsat result.."       -- Won't happen
+    Unsat  -> do io $ putStrLn "No other solution!"
+                 pure Nothing
+
+    Sat    -> do xv <- getValue x
+                 yv <- getValue y
+                 io $ putStrLn $ "[One]: Current solution is: " ++ show (xv, yv)
+                 io $ putStrLn   "[One]: Place vars for [Two]"
+                 liftIO $ putMVar v2 (literal (xv + yv), literal (xv * yv))
+                 pure $ Just (xv + yv)
+
+-- | In the second query we create a new variable z, and then a symbolic query
+-- using information from the first query and return a solution that uses the
+-- new variable and the old variables. Each child query is run in a separate
+-- instance of z3 so you can think of this query as driving to a point in the
+-- search space, then waiting for more information, once it gets that
+-- information it will run a completely separate computation from the first one
+-- and return its results.
+secondQuery :: MVar (SInteger, SInteger) -> Query (Maybe Integer)
+secondQuery v2 = do
+  (x,y) <- liftIO $ takeMVar v2
+  io $ putStrLn $ "[Two]: got values" ++ show (x,y)
+  z <- freshVar "z"
+  constrain $ z .> x + y
+
+  cs <- checkSat
+  case cs of
+    Unk    -> error "Too bad, solver said unknown.." -- Won't happen
+    DSat{} -> error "Unexpected dsat result.."       -- Won't happen
+    Unsat  -> do io $ putStrLn "No other solution!"
+                 pure Nothing
+
+    Sat    -> do yv <- getValue y
+                 xv <- getValue x
+                 zv <- getValue z
+                 io $ putStrLn $ "[Two]: My solution is: " ++ show (zv + xv, zv + yv)
+                 pure $ Just (zv * xv * yv)
+
+-- | In our second demonstration we show how through the use of concurrency
+-- constructs the user can have children queries communicate with one another.
+-- Note that the children queries are independent and so anything side-effectual
+-- like a push or a pop will be isolated to that child thread, unless of course
+-- it happens in shared.
+demoDependent :: IO ()
+demoDependent = do
+  v1 <- newEmptyMVar
+  v2 <- newEmptyMVar
+  results <- satConcurrentWithAll z3 [firstQuery v1 v2, secondQuery v2] (sharedDependent v1)
+  print results
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Queries/Enums.hs b/Documentation/SBV/Examples/Queries/Enums.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/Enums.hs
@@ -0,0 +1,65 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.Enums
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates the use of enumeration values during queries.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.Enums where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Days of the week. We make it symbolic using the 'mkSymbolic' splice.
+data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
+         deriving Show
+
+-- | Make 'Day' a symbolic value.
+mkSymbolic [''Day]
+
+-- | A trivial query to find three consecutive days that's all before 'Thursday'. The point
+-- here is that we can perform queries on such enumerated values and use 'getValue' on them
+-- and return their values from queries just like any other value. We have:
+--
+-- >>> findDays
+-- [Monday,Tuesday,Wednesday]
+findDays :: IO [Day]
+findDays = runSMT $ do (d1 :: SDay) <- free "d1"
+                       (d2 :: SDay) <- free "d2"
+                       (d3 :: SDay) <- free "d3"
+
+                       -- Assert that they are ordered
+                       constrain $ d1 .<= d2
+                       constrain $ d2 .<= d3
+
+                       -- Assert that last day is before 'Thursday'
+                       constrain $ d3 .< sThursday
+
+                       -- Constraints can be given before or after
+                       -- the query mode starts. We will assert that
+                       -- they are different after we start interacting
+                       -- with the solver. Note that we can query the
+                       -- values based on other values obtained too,
+                       -- if we want to guide the search.
+
+                       query $ do constrain $ distinct [d1, d2, d3]
+
+                                  cs <- checkSat
+                                  case cs of
+                                    Sat -> do a <- getValue d1
+                                              b <- getValue d2
+                                              c <- getValue d3
+                                              pure [a, b, c]
+
+                                    _   -> error "Impossible, can't find days!"
diff --git a/Documentation/SBV/Examples/Queries/FourFours.hs b/Documentation/SBV/Examples/Queries/FourFours.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/FourFours.hs
@@ -0,0 +1,213 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.FourFours
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A query based solution to the four-fours puzzle.
+-- Inspired by <http://www.gigamonkeys.com/trees/>
+--
+-- @
+-- Try to make every number between 0 and 20 using only four 4s and any
+-- mathematical operation, with all four 4s being used each time.
+-- @
+--
+-- We pretty much follow the structure of <http://www.gigamonkeys.com/trees/>,
+-- with the exception that we generate the trees filled with symbolic operators
+-- and ask the SMT solver to find the appropriate fillings.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.FourFours where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.List (inits, tails)
+import Data.Maybe
+
+-- | Supported binary operators. To keep the search-space small, we will only allow division by @2@ or @4@,
+-- and exponentiation will only be to the power @0@. This does restrict the search space, but is sufficient to
+-- solve all the instances.
+data BinOp = Plus | Minus | Times | Divide | Expt
+           deriving (Eq, Show)
+
+-- | Make 'BinOp' a symbolic value.
+mkSymbolic [''BinOp]
+
+-- | Supported unary operators. Similar to 'BinOp' case, we will restrict square-root and factorial to
+-- be only applied to the value @4.
+data UnOp  = Negate | Sqrt | Factorial
+           deriving Eq
+
+-- | Make 'UnOp' a symbolic value.
+mkSymbolic [''UnOp]
+
+-- | The shape of a tree, either a binary node, or a unary node, or the number @4@, represented here by
+-- the constructor @F@. We parameterize by the operator type: When doing symbolic computations, we'll fill
+-- those with 'SBinOp' and 'SUnOp'. When finding the shapes, we will simply put unit values, i.e., holes.
+data T b u = B b (T b u) (T b u)
+           | U u (T b u)
+           | F
+
+-- | A rudimentary 'Show' instance for trees, nothing fancy.
+instance Show (T BinOp UnOp) where
+   show F       = "4"
+   show (U u t) = case u of
+                    Negate    -> "-" ++ show t
+                    Sqrt      -> "sqrt(" ++ show t ++ ")"
+                    Factorial -> show t ++ "!"
+   show (B o l r) = "(" ++ show l ++ " " ++ so ++ " " ++ show r ++ ")"
+     where so = fromMaybe (error $ "Unexpected operator: " ++ show o)
+                        $ o `lookup` [(Plus, "+"), (Minus, "-"), (Times, "*"), (Divide, "/"), (Expt, "^")]
+
+-- | Construct all possible tree shapes. The argument here follows the logic in <http://www.gigamonkeys.com/trees/>:
+-- We simply construct all possible shapes and extend with the operators. The number of such trees is:
+--
+-- >>> length allPossibleTrees
+-- 640
+--
+-- Note that this is a /lot/ smaller than what is generated by <http://www.gigamonkeys.com/trees/>. (There, the
+-- number of trees is 10240000: 16000 times more than what we have to consider!)
+allPossibleTrees :: [T () ()]
+allPossibleTrees = trees $ replicate 4 F
+  where trees :: [T () ()] -> [T () ()]
+        trees [x] = [x, U () x]
+        trees xs  = do (left, right) <- splits
+                       t1            <- trees left
+                       t2            <- trees right
+                       trees [B () t1 t2]
+          where splits = init $ drop 1 $ zip (inits xs) (tails xs)
+
+-- | Given a tree with hols, fill it with symbolic operators. This is the /trick/ that allows
+-- us to consider only 640 trees as opposed to over 10 million.
+fill :: T () () -> Symbolic (T SBinOp SUnOp)
+fill (B _ l r) = B <$> free_ <*> fill l <*> fill r
+fill (U _ t)   = U <$> free_ <*> fill t
+fill F         = pure F
+
+-- | Minor helper for writing "symbolic" case statements. Simply walks down a list
+-- of values to match against a symbolic version of the key.
+cases :: (Eq a, SymVal a, Mergeable v) => SBV a -> [(a, v)] -> v
+cases k = walk
+  where walk []              = error "cases: Expected a non-empty list of cases!"
+        walk [(_, v)]        = v
+        walk ((k1, v1):rest) = ite (k .== literal k1) v1 (walk rest)
+
+-- | Evaluate a symbolic tree, obtaining a symbolic value. Note how we structure
+-- this evaluation so we impose extra constraints on what values square-root, divide
+-- etc. can take. This is the power of the symbolic approach: We can put arbitrary
+-- symbolic constraints as we evaluate the tree.
+eval :: T SBinOp SUnOp -> Symbolic SInteger
+eval tree = case tree of
+              B b l r -> eval l >>= \l' -> eval r >>= \r' -> binOp b l' r'
+              U u t   -> eval t >>= uOp u
+              F       -> pure 4
+
+  where binOp :: SBinOp -> SInteger -> SInteger -> Symbolic SInteger
+        binOp o l r = do constrain $ o .== sDivide .=> r .== 4 .|| r .== 2
+                         constrain $ o .== sExpt   .=> r .== 0
+                         pure $ cases o
+                                  [ (Plus,    l+r)
+                                  , (Minus,   l-r)
+                                  , (Times,   l*r)
+                                  , (Divide,  l `sDiv` r)
+                                  , (Expt,    1)   -- exponent is restricted to 0, so the value is 1
+                                  ]
+
+        uOp :: SUnOp -> SInteger -> Symbolic SInteger
+        uOp o v = do constrain $ o .== sSqrt      .=> v .== 4
+                     constrain $ o .== sFactorial .=> v .== 4
+                     pure $ cases o
+                              [ (Negate,    -v)
+                              , (Sqrt,       2)  -- argument is restricted to 4, so the value is 2
+                              , (Factorial, 24)  -- argument is restricted to 4, so the value is 24
+                              ]
+
+-- | In the query mode, find a filling of a given tree shape /t/, such that it evaluates to the
+-- requested number /i/. Note that we return back a concrete tree.
+generate :: Integer -> T () () -> IO (Maybe (T BinOp UnOp))
+generate i t = runSMT $ do symT <- fill t
+                           val  <- eval symT
+                           constrain $ val .== literal i
+                           query $ do cs <- checkSat
+                                      case cs of
+                                        Sat -> Just <$> construct symT
+                                        _   -> pure Nothing
+    where -- Walk through the tree, ask the solver for
+          -- the assignment to symbolic operators and fill back.
+          construct F           = pure F
+          construct (U o s')    = do uo <- getValue o
+                                     U uo <$> construct s'
+          construct (B b l' r') = do bo <- getValue b
+                                     B bo <$> construct l' <*> construct r'
+
+-- | Given an integer, walk through all possible tree shapes (at most 640 of them), and find a
+-- filling that solves the puzzle.
+find :: Integer -> IO ()
+find target = go allPossibleTrees
+  where go []     = putStrLn $ show target ++ ": No solution found."
+        go (t:ts) = do chk <- generate target t
+                       case chk of
+                         Nothing -> go ts
+                         Just r  -> do let ok  = concEval r == target
+                                           tag = if ok then " [OK]: " else " [BAD]: "
+                                           sh i | i < 10 = ' ' : show i
+                                                | True   =       show i
+
+                                       putStrLn $ sh target ++ tag ++ show r
+
+        -- Make sure the result is correct!
+        concEval :: T BinOp UnOp -> Integer
+        concEval F         = 4
+        concEval (U u t)   = uEval u (concEval t)
+        concEval (B b l r) = bEval b (concEval l) (concEval r)
+
+        uEval :: UnOp -> Integer -> Integer
+        uEval Negate    i = -i
+        uEval Sqrt      i = if i == 4 then  2 else error $ "uEval: Found sqrt applied to value: " ++ show i
+        uEval Factorial i = if i == 4 then 24 else error $ "uEval: Found factorial applied to value: " ++ show i
+
+        bEval :: BinOp -> Integer -> Integer -> Integer
+        bEval Plus   i j = i + j
+        bEval Minus  i j = i - j
+        bEval Times  i j = i * j
+        bEval Divide i j = i `div` j
+        bEval Expt   i j = i ^ j
+
+-- | Solution to the puzzle. When you run this puzzle, the solver can produce different results
+-- than what's shown here, but the expressions should still be all valid!
+--
+-- @
+-- ghci> puzzle
+--  0 [OK]: (4 - (4 + (4 - 4)))
+--  1 [OK]: (4 / (4 + (4 - 4)))
+--  2 [OK]: sqrt((4 + (4 * (4 - 4))))
+--  3 [OK]: (4 - (4 ^ (4 - 4)))
+--  4 [OK]: (4 + (4 * (4 - 4)))
+--  5 [OK]: (4 + (4 ^ (4 - 4)))
+--  6 [OK]: (4 + sqrt((4 * (4 / 4))))
+--  7 [OK]: (4 + (4 - (4 / 4)))
+--  8 [OK]: (4 - (4 - (4 + 4)))
+--  9 [OK]: (4 + (4 + (4 / 4)))
+-- 10 [OK]: (4 + (4 + (4 - sqrt(4))))
+-- 11 [OK]: (4 + ((4 + 4!) / 4))
+-- 12 [OK]: (4 * (4 - (4 / 4)))
+-- 13 [OK]: (4! + ((sqrt(4) - 4!) / sqrt(4)))
+-- 14 [OK]: (4 + (4 + (4 + sqrt(4))))
+-- 15 [OK]: (4 + ((4! - sqrt(4)) / sqrt(4)))
+-- 16 [OK]: (4 * (4 * (4 / 4)))
+-- 17 [OK]: (4 + ((sqrt(4) + 4!) / sqrt(4)))
+-- 18 [OK]: -(4 + (4 - (sqrt(4) + 4!)))
+-- 19 [OK]: -(4 - (4! - (4 / 4)))
+-- 20 [OK]: (4 * (4 + (4 / 4)))
+-- @
+puzzle :: IO ()
+puzzle = mapM_ find [0 .. 20]
diff --git a/Documentation/SBV/Examples/Queries/GuessNumber.hs b/Documentation/SBV/Examples/Queries/GuessNumber.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/GuessNumber.hs
@@ -0,0 +1,80 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.GuessNumber
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A simple number-guessing game implementation via queries. Clearly an
+-- SMT solver is hardly needed for this problem, but it is a nice demo
+-- for the interactive-query programming.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.GuessNumber where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | Use the backend solver to guess the number given as argument.
+-- The number is assumed to be between @0@ and @1000@, and we use a simple
+-- binary search. Returns the sequence of guesses we performed during
+-- the search process.
+guess :: Integer -> Symbolic [Integer]
+guess input = do g <- sInteger "guess"
+
+                 -- A simple loop to find the value in a query. lb and up
+                 -- correspond to the current lower/upper bound we operate in.
+                 let loop lb ub sofar = do
+
+                          io $ putStrLn $ "Current bounds: " ++ show (lb, ub)
+
+                          -- Assert the current bound:
+                          constrain $ g .>= literal lb
+                          constrain $ g .<= literal ub
+
+                          -- Issue a check-sat
+                          cs <- checkSat
+                          case cs of
+                            Unk    -> error "Too bad, solver said Unknown.." -- Won't really happen
+                            DSat{} -> error "Unexpected delta-sat result.."  -- Won't really happen
+                            Unsat  ->
+                                   -- This cannot happen! If it does, the input was
+                                   -- not properly constrained. Note that we found this
+                                   -- by getting an Unsat, not by checking the value!
+                                   error $ unlines [ "There's no solution!"
+                                                   , "Guess sequence: " ++ show (reverse sofar)
+                                                   ]
+                            Sat    -> do gv <- getValue g
+                                         case gv `compare` input of
+                                           EQ -> -- Got it, return:
+                                                 pure (reverse (gv : sofar))
+                                           LT -> -- Solver guess is too small, increase the lower bound:
+                                                 loop ((lb+1) `max` (lb + (input - lb) `div` 2)) ub (gv : sofar)
+                                           GT -> -- Solver guess is too big, decrease the upper bound:
+                                                 loop lb ((ub-1) `min` (ub - (ub - input) `div` 2)) (gv : sofar)
+
+                 -- Start the search
+                 query $ loop 0 1000 []
+
+-- | Play a round of the game, making the solver guess the secret number 42.
+-- Note that you can generate a random-number and make the solver guess it too!
+-- We have:
+--
+-- >>> play
+-- Current bounds: (0,1000)
+-- Current bounds: (21,1000)
+-- Current bounds: (31,1000)
+-- Current bounds: (36,1000)
+-- Current bounds: (39,1000)
+-- Current bounds: (40,1000)
+-- Current bounds: (41,1000)
+-- Current bounds: (42,1000)
+-- Solved in: 8 guesses:
+--   8 21 31 36 39 40 41 42
+play :: IO ()
+play = do gs <- runSMT (guess 42)
+          putStrLn $ "Solved in: " ++ show (length gs) ++ " guesses:"
+          putStrLn $ "  " ++ unwords (map show gs)
diff --git a/Documentation/SBV/Examples/Queries/Interpolants.hs b/Documentation/SBV/Examples/Queries/Interpolants.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/Interpolants.hs
@@ -0,0 +1,132 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.Interpolants
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates extraction of interpolants via queries.
+--
+-- N.B. Interpolants are supported by MathSAT and Z3. Unfortunately
+-- the extraction of interpolants is not standardized, and are slightly
+-- different for these two solvers. So, we have two separate examples
+-- to demonstrate the usage.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.Interpolants where
+
+import Data.SBV
+import Data.SBV.Control
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Control
+#endif
+
+-- | MathSAT example. Compute the interpolant for the following sets of formulas:
+--
+--     @{x - 3y >= -1, x + y >= 0}@
+--
+-- AND
+--
+--     @{z - 2x >= 3, 2z <= 1}@
+--
+-- where the variables are integers.  Note that these sets of
+-- formulas are themselves satisfiable, but not taken all together.
+-- The pair @(x, y) = (0, 0)@ satisfies the first set. The pair @(x, z) = (-2, 0)@
+-- satisfies the second. However, there's no triple @(x, y, z)@ that satisfies all
+-- these four formulas together. We can use SBV to check this fact:
+--
+-- >>> sat $ \x y z -> sAnd [x - 3*y .>= -1, x + y .>= 0, z - 2*x .>= 3, 2 * z .<= (1::SInteger)]
+-- Unsatisfiable
+--
+-- An interpolant for these sets would only talk about the variable @x@ that is common
+-- to both. We have:
+--
+-- >>> runSMTWith mathSAT exampleMathSAT
+-- "(<= 0 s0)"
+--
+-- Notice that we get a string back, not a term; so there's some back-translation we need to do. We
+-- know that @s0@ is @x@ through our translation mechanism, so the interpolant is saying that @x >= 0@
+-- is entailed by the first set of formulas, and is inconsistent with the second. Let's use SBV
+-- to indeed show that this is the case:
+--
+-- >>> prove $ \x y -> (x - 3*y .>= -1 .&& x + y .>= 0) .=> (x .>= (0::SInteger))
+-- Q.E.D.
+--
+-- And:
+--
+-- >>> prove $ \x z -> (z - 2*x .>= 3 .&& 2 * z .<= 1) .=> sNot (x .>= (0::SInteger))
+-- Q.E.D.
+--
+-- This establishes that we indeed have an interpolant!
+exampleMathSAT :: Symbolic String
+exampleMathSAT = do
+       x <- sInteger "x"
+       y <- sInteger "y"
+       z <- sInteger "z"
+
+       -- tell the solver we want interpolants
+       -- NB. Only MathSAT needs this. Z3 doesn't need or like this setting!
+       setOption $ ProduceInterpolants True
+
+       -- create interpolation constraints. MathSAT requires the relevant formulas
+       -- to be marked with the attribute :interpolation-group
+       constrainWithAttribute [(":interpolation-group", "A")] $ x - 3*y .>= -1
+       constrainWithAttribute [(":interpolation-group", "A")] $ x + y   .>=  0
+       constrainWithAttribute [(":interpolation-group", "B")] $ z - 2*x .>=  3
+       constrainWithAttribute [(":interpolation-group", "B")] $ 2*z     .<=  1
+
+       -- To obtain the interpolant, we run a query
+       query $ do cs <- checkSat
+                  case cs of
+                    Unsat  -> getInterpolantMathSAT ["A"]
+                    DSat{} -> error "Unexpected delta-sat result!"
+                    Sat    -> error "Unexpected sat result!"
+                    Unk    -> error "Unexpected unknown result!"
+
+-- | Z3 example. Compute the interpolant for formulas @y = 2x@ and @y = 2z+1@.
+--
+-- These formulas are not satisfiable together since it would mean
+-- @y@ is both even and odd at the same time. An interpolant for
+-- this pair of formulas is a formula that's expressed only in terms
+-- of @y@, which is the only common symbol among them. We have:
+--
+-- >>> runSMT evenOdd
+-- "(let (a!1 (= (mod (+ (* (- 1) s1) 0) 2) 0)) (or (= s1 0) a!1))"
+--
+-- This is a bit hard to read unfortunately, due to translation artifacts and use of strings. To analyze,
+-- we need to know that @s1@ is @y@ through SBV's translation. Let's express it in
+-- regular infix notation with @y@ for @s1@, and substitute the let-bound variable:
+--
+-- @(y == 0) || ((-y) `mod` 2 == 0)@
+--
+-- Notice that the only symbol is @y@, as required. To establish that this is
+-- indeed an interpolant, we should establish that when @y@ is even, this formula
+-- is @True@; and if @y@ is odd, then it should be @False@. You can argue
+-- mathematically that this indeed the case, but let's just use SBV to prove the required relationships:
+--
+-- >>> prove $ \(y :: SInteger) -> (y `sMod` 2 .== 0) .=> ((y .== 0) .|| ((-y) `sMod` 2 .== 0))
+-- Q.E.D.
+--
+-- And:
+--
+-- >>> prove $ \(y :: SInteger) -> (y `sMod` 2 .== 1) .=> sNot ((y .== 0) .|| ((-y) `sMod` 2 .== 0))
+-- Q.E.D.
+--
+-- This establishes that we indeed have an interpolant!
+evenOdd :: Symbolic String
+evenOdd = do
+       x <- sInteger "x"
+       y <- sInteger "y"
+       z <- sInteger "z"
+
+       query $ getInterpolantZ3 [y .== 2*x, y .== 2*z+1]
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/Queries/UnsatCore.hs b/Documentation/SBV/Examples/Queries/UnsatCore.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Queries/UnsatCore.hs
@@ -0,0 +1,52 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Queries.UnsatCore
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates extraction of unsat-cores via queries.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Queries.UnsatCore where
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | A simple goal with three constraints, two of which are
+-- conflicting with each other. The third is irrelevant, in the sense
+-- that it does not contribute to the fact that the goal is unsatisfiable.
+p :: Symbolic (Maybe [String])
+p = do a <- sInteger "a"
+       b <- sInteger "b"
+
+       -- tell the solver we want unsat-cores
+       setOption $ ProduceUnsatCores True
+
+       -- create named constraints, which will allow
+       -- unsat-core extraction with the given names
+       namedConstraint "less than 5"  $ a .< 5
+       namedConstraint "more than 10" $ a .> 10
+       namedConstraint "irrelevant"   $ a .> b
+
+       -- To obtain the unsat-core, we run a query
+       query $ do cs <- checkSat
+                  case cs of
+                    Unsat -> Just <$> getUnsatCore
+                    _     -> pure Nothing
+
+
+-- | Extract the unsat-core of 'p'. We have:
+--
+-- >>> ucCore
+-- Unsat core is: ["less than 5","more than 10"]
+--
+-- Demonstrating that the constraint @a .> b@ is /not/ needed for unsatisfiability in this case.
+ucCore :: IO ()
+ucCore = do mbCore <- runSMT p
+            case mbCore of
+              Nothing   -> putStrLn "Problem is satisfiable."
+              Just core -> putStrLn $ "Unsat core is: " ++ show core
diff --git a/Documentation/SBV/Examples/Strings/RegexCrossword.hs b/Documentation/SBV/Examples/Strings/RegexCrossword.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Strings/RegexCrossword.hs
@@ -0,0 +1,109 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Strings.RegexCrossword
+-- Copyright : (c) Joel Burget
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- This example solves regex crosswords from <http://regexcrossword.com>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Strings.RegexCrossword where
+
+import Data.List (genericLength, transpose)
+
+import Data.SBV
+import Data.SBV.Control
+
+import qualified Data.SBV.List   as L
+import qualified Data.SBV.RegExp as R
+
+-- | Solve a given crossword, returning the corresponding rows
+solveCrossword :: [R.RegExp] -> [R.RegExp] -> IO [String]
+solveCrossword rowRegExps colRegExps = runSMT $ do
+        let numRows = genericLength rowRegExps
+            numCols = genericLength colRegExps
+
+        -- constrain rows
+        let mkRow rowRegExp = do row :: SString <- free_
+                                 constrain $ row `R.match` rowRegExp
+                                 constrain $ L.length row .== literal numCols
+                                 pure row
+
+        rows <- mapM mkRow rowRegExps
+
+        -- constrain columns
+        let mkCol colRegExp = do col :: SString <- free_
+                                 constrain $ col `R.match` colRegExp
+                                 constrain $ L.length col .== literal numRows
+                                 pure col
+
+        cols <- mapM mkCol colRegExps
+
+        -- constrain each "cell" as they rows/columns intersect:
+        let rowss =           [[r L.!! literal i | i <- [0..numCols-1]] | r <- rows]
+        let colss = transpose [[c L.!! literal i | i <- [0..numRows-1]] | c <- cols]
+
+        constrain $ sAnd $ zipWith (.==) (concat rowss) (concat colss)
+
+        -- Now query to extract the solution
+        query $ do cs <- checkSat
+                   case cs of
+                     Unk    -> error "Solver returned unknown!"
+                     DSat{} -> error "Solver returned delta-sat!"
+                     Unsat  -> error "There are no solutions to this puzzle!"
+                     Sat    -> mapM getValue rows
+
+-- | Solve <http://regexcrossword.com/challenges/intermediate/puzzles/1>
+--
+-- >>> puzzle1
+-- ["ATO","WEL"]
+puzzle1 :: IO [String]
+puzzle1 = solveCrossword rs cs
+  where rs = [ R.KStar (R.oneOf "NOTAD")  -- [NOTAD]*
+             , "WEL" + "BAL" + "EAR"      -- WEL|BAL|EAR
+             ]
+
+        cs = [ "UB" + "IE" + "AW"         -- UB|IE|AW
+             , R.KStar (R.oneOf "TUBE")   -- [TUBE]*
+             , R.oneOf "BORF" * R.All     -- [BORF].
+             ]
+
+-- | Solve <http://regexcrossword.com/challenges/intermediate/puzzles/2>
+--
+-- >>> puzzle2
+-- ["WA","LK","ER"]
+puzzle2 :: IO [String]
+puzzle2 = solveCrossword rs cs
+  where rs = [ R.KPlus (R.oneOf "AWE")       -- [AWE]+
+             , R.KPlus (R.oneOf "ALP") * "K" -- [ALP]+K
+             , "PR" + "ER" + "EP"            -- (PR|ER|EP)
+             ]
+
+        cs = [ R.oneOf "BQW" * ("PR" + "LE") -- [BQW](PR|LE)
+             , R.KPlus (R.oneOf "RANK")      -- [RANK]+
+             ]
+
+-- | Solve <http://regexcrossword.com/challenges/palindromeda/puzzles/3>
+--
+-- >>> puzzle3
+-- ["RATS","ABUT","TUBA","STAR"]
+puzzle3 :: IO [String]
+puzzle3 = solveCrossword rs cs
+ where rs = [ R.KStar (R.oneOf "TRASH")                -- [TRASH]*
+            , ("FA" + "AB") * R.KStar (R.oneOf "TUP")  -- (FA|AB)[TUP]*
+            , R.KStar ("BA" + "TH" + "TU")             -- (BA|TH|TU)*
+            , R.KStar R.All * "A" * R.KStar R.All      -- .*A.*
+            ]
+
+       cs = [ R.KStar ("TS" + "RA" + "QA")                     -- (TS|RA|QA)*
+            , R.KStar ("AB" + "UT" + "AR")                     -- (AB|UT|AR)*
+            , ("K" + "T") * "U" * R.KStar R.All * ("A" + "R")  -- (K|T)U.*(A|R)
+            , R.KPlus ("AR" + "FS" + "ST")                     -- (AR|FS|ST)+
+            ]
diff --git a/Documentation/SBV/Examples/Strings/SQLInjection.hs b/Documentation/SBV/Examples/Strings/SQLInjection.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Strings/SQLInjection.hs
@@ -0,0 +1,155 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Strings.SQLInjection
+-- Copyright : (c) Joel Burget
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Implement the symbolic evaluation of a language which operates on
+-- strings in a way similar to bash. It's possible to do different analyses,
+-- but this example finds program inputs which result in a query containing a
+-- SQL injection.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Strings.SQLInjection where
+
+import Control.Monad.State
+import Control.Monad.Writer
+import Data.String
+
+import Data.SBV
+import Data.SBV.Control
+
+import Prelude hiding ((++))
+import Data.SBV.List ((++))
+import qualified Data.SBV.RegExp as R
+
+-- | Simple expression language
+data SQLExpr = Query   SQLExpr
+             | Const   String
+             | Concat  SQLExpr SQLExpr
+             | ReadVar SQLExpr
+
+-- | Literals strings can be lifted to be constant programs
+instance IsString SQLExpr where
+  fromString = Const
+
+-- | Evaluation monad. The state argument is the environment to store
+-- variables as we evaluate.
+type M = StateT (SArray String String) (WriterT [SString] Symbolic)
+
+-- | Given an expression, symbolically evaluate it
+eval :: SQLExpr -> M SString
+eval (Query q)         = do q' <- eval q
+                            tell [q']
+                            lift $ lift free_
+eval (Const str)       = pure $ literal str
+eval (Concat e1 e2)    = (++) <$> eval e1 <*> eval e2
+eval (ReadVar nm)      = do n   <- eval nm
+                            arr <- get
+                            pure $ readArray arr n
+
+-- | A simple program to query all messages with a given topic id. In SQL like notation:
+--
+-- @
+--   query ("SELECT msg FROM msgs where topicid='" ++ my_topicid ++ "'")
+-- @
+exampleProgram :: SQLExpr
+exampleProgram = Query $ foldr1 Concat [ "SELECT msg FROM msgs WHERE topicid='"
+                                       , ReadVar "my_topicid"
+                                       , "'"
+                                       ]
+
+-- | Limit names to be at most 7 chars long, with simple letters.
+nameRe :: R.RegExp
+nameRe = R.Loop 1 7 (R.Range 'a' 'z')
+
+-- | Strings: Again, at most of length 5, surrounded by quotes.
+strRe :: R.RegExp
+strRe = "'" * R.Loop 1 5 (R.Range 'a' 'z' + " ") * "'"
+
+-- | A "select" command:
+selectRe :: R.RegExp
+selectRe = "SELECT "
+         * (nameRe + "*")
+         * " FROM "
+         * nameRe
+         * R.Opt (  " WHERE "
+                  * nameRe
+                  * "="
+                  * (nameRe + strRe)
+                  )
+
+-- | A "drop" instruction, which can be exploited!
+dropRe :: R.RegExp
+dropRe = "DROP TABLE " * (nameRe + strRe)
+
+-- | We'll greatly simplify here and say a statement is either a select or a drop:
+statementRe :: R.RegExp
+statementRe = selectRe + dropRe
+
+-- | The exploit: We're looking for a DROP TABLE after at least one legitimate command.
+exploitRe :: R.RegExp
+exploitRe = R.KPlus (statementRe * "; ")
+          * "DROP TABLE 'users'"
+
+-- | Analyze the program for inputs which result in a SQL injection. There are
+-- other possible injections, but in this example we're only looking for a
+-- @DROP TABLE@ command.
+--
+-- Remember that our example program (in pseudo-code) is:
+--
+-- @
+--   query ("SELECT msg FROM msgs WHERE topicid='" ++ my_topicid ++ "'")
+-- @
+--
+-- Depending on your z3 version, you might see an output of the form:
+--
+-- @
+--   ghci> findInjection exampleProgram
+--   "kg'; DROP TABLE 'users"
+-- @
+--
+-- though the topic might change obviously. Indeed, if we substitute the suggested string, we get the program:
+--
+-- > query ("SELECT msg FROM msgs WHERE topicid='kg'; DROP TABLE 'users'")
+--
+-- which would query for topic @kg@ and then delete the users table!
+--
+-- Here, we make sure that the injection ends with the malicious string:
+--
+-- >>> ("'; DROP TABLE 'users" `Data.List.isSuffixOf`) <$> findInjection exampleProgram
+-- True
+findInjection :: SQLExpr -> IO String
+findInjection expr = runSMT $ do
+
+    -- This example generates different outputs on different platforms (Mac vs Linux).
+    -- So, we explicitly set the random-seed to get a consistent doctest output
+    -- Otherwise the following line isn't needed.
+    setOption $ OptionKeyword ":smt.random_seed" ["1"]
+
+    badTopic <- sString "badTopic"
+
+    -- Create an initial environment that returns the symbolic
+    -- value my_topicid only, and unspecified for all other variables
+    emptyEnv :: SArray String String <- sArray "emptyEnv"
+
+    let env = writeArray emptyEnv "my_topicid" badTopic
+
+    (_, queries) <- runWriterT (evalStateT (eval expr) env)
+
+    -- For all the queries thus generated, ask that one of them be "exploitable"
+    constrain $ sAny (`R.match` exploitRe) queries
+
+    query $ do cs <- checkSat
+               case cs of
+                 Unk    -> error "Solver returned unknown!"
+                 DSat{} -> error "Solver returned delta-satisfiable!"
+                 Unsat  -> error "No exploits are found"
+                 Sat    -> getValue badTopic
diff --git a/Documentation/SBV/Examples/TP/Ackermann.hs b/Documentation/SBV/Examples/TP/Ackermann.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Ackermann.hs
@@ -0,0 +1,279 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Ackermann
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving the relationship between Ackermann's original 3-argument function (1928)
+-- and the Ackermann-Péter function (1935).
+--
+-- Ackermann's original function was a 3-argument function designed to demonstrate
+-- a total computable function that is not primitive recursive. The third argument
+-- generalizes the operation: @ack 0 n a = n + a@ (addition), and higher levels
+-- correspond to multiplication, exponentiation, etc.
+--
+-- Rózsa Péter simplified this to a 2-argument function in 1935, which is what
+-- most people today call "the Ackermann function."
+--
+-- This example is inspired by: <https://github.com/imandra-ai/imandrax-examples/blob/main/src/ackermann.iml>
+--
+-- Note: This proof was developed by Claude (Anthropic's AI assistant) with
+-- minimal user prompting and guidance.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Ackermann where
+
+import Data.SBV
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Ackermann's original 3-argument function (1928)
+
+-- | Ackermann's original 3-argument function (1928). This is the lesser-known
+-- original version, not the commonly referenced Ackermann-Péter function.
+-- The third argument @a@ generalizes the operation at each level.
+ack :: SInteger -> SInteger -> SInteger -> SInteger
+ack = smtFunction "ack"
+  $ \m n a -> [sCase| m of
+                 _ | m .<= 0 -> n + a
+                 _ | n .<= 0 -> 0
+                 _ | n .== 1 -> a
+                 _           -> ack (m - 1) (ack m (n - 1) a) a
+              |]
+
+-- * Ackermann-Péter function (1935)
+
+-- | The Ackermann-Péter function (1935), commonly known as "the Ackermann function."
+-- This is Rózsa Péter's simplified 2-argument version of Ackermann's original function.
+pet :: SInteger -> SInteger -> SInteger
+pet = smtFunction "pet"
+  $ \m n -> [sCase| m of
+               _ | m .<= 0 -> n + 1
+               _ | n .<= 0 -> pet (m - 1) 1
+               _           -> pet (m - 1) (pet m (n - 1))
+            |]
+
+-- * Correctness
+
+-- | Prove that @ack m 2 2 = 4@ for all m >= 0.
+--
+-- >>> runTP ack_2_2_4
+-- Inductive lemma (strong): ack_2_2_4
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2.1                        Q.E.D.
+--     Step: 1.2.2                        Q.E.D.
+--     Step: 1.2.3                        Q.E.D.
+--     Step: 1.2.4                        Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Functions proven terminating: ack
+-- [Proven] ack_2_2_4 :: Ɐm ∷ Integer → Bool
+ack_2_2_4 :: TP (Proof (Forall "m" Integer -> SBool))
+ack_2_2_4 = sInduct "ack_2_2_4"
+                    (\(Forall m) -> m .>= 0 .=> ack m 2 2 .== 4)
+                    (id, []) $
+                    \ih m -> [m .>= 0]
+                          |- ack m 2 2
+                          =: cases [ m .== 0 ==> trivial
+                                   , m .> 0  ==> ack m 2 2
+                                              =: ack (m - 1) (ack m 1 2) 2
+                                              =: ack (m - 1) 2 2
+                                              ?? ih `at` Inst @"m" (m - 1)
+                                              =: (4 :: SInteger)
+                                              =: qed
+                                   ]
+
+-- | Prove that @ack@ is non-negative when all arguments are non-negative.
+-- We use strong induction on the lexicographic measure (m, n).
+--
+-- >>> runTP ack_psd
+-- Inductive lemma (strong): ack_psd
+--   Step: Measure is non-negative      Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2                        Q.E.D.
+--     Step: 1.3                        Q.E.D.
+--     Step: 1.4.1                      Q.E.D.
+--     Step: 1.4.2                      Q.E.D.
+--     Step: 1.4.3                      Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: ack
+-- [Proven] ack_psd :: Ɐm ∷ Integer → Ɐn ∷ Integer → Ɐa ∷ Integer → Bool
+ack_psd :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> Forall "a" Integer -> SBool))
+ack_psd = sInduct "ack_psd"
+                  (\(Forall m) (Forall n) (Forall a) ->
+                      m .>= 0 .&& n .>= 0 .&& a .>= 0 .=> ack m n a .>= 0)
+                  (\m n _a -> tuple (m, n), []) $
+                  \ih m n a -> [m .>= 0, n .>= 0, a .>= 0]
+                            |- ack m n a .>= 0
+                            =: cases [ m .<= 0 ==> trivial   -- n + a >= 0
+                                     , n .<= 0 ==> trivial   -- 0 >= 0
+                                     , n .== 1 ==> trivial   -- a >= 0
+                                     , m .> 0 .&& n .> 1
+                                         ==> ack m n a .>= 0
+                                          =: ack (m - 1) (ack m (n - 1) a) a .>= 0
+                                          ?? ih `at` (Inst @"m" m, Inst @"n" (n - 1), Inst @"a" a)
+                                          ?? ih `at` (Inst @"m" (m - 1), Inst @"n" (ack m (n - 1) a), Inst @"a" a)
+                                          =: sTrue
+                                          =: qed
+                                     ]
+
+-- | Prove that @pet@ is non-negative when both arguments are non-negative.
+-- We use strong induction on the lexicographic measure (m, n).
+--
+-- >>> runTPWith cvc5 pet_psd
+-- Inductive lemma (strong): pet_psd
+--   Step: Measure is non-negative      Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2.1                      Q.E.D.
+--     Step: 1.2.2                      Q.E.D.
+--     Step: 1.2.3                      Q.E.D.
+--     Step: 1.3.1                      Q.E.D.
+--     Step: 1.3.2                      Q.E.D.
+--     Step: 1.3.3                      Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: pet
+-- [Proven] pet_psd :: Ɐm ∷ Integer → Ɐn ∷ Integer → Bool
+pet_psd :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
+pet_psd = do
+    sInduct "pet_psd"
+                  (\(Forall m) (Forall n) -> m .>= 0 .&& n .>= 0 .=> pet m n .>= 0)
+                  (\m n -> tuple (m, n), []) $
+                  \ih m n -> [m .>= 0, n .>= 0]
+                          |- pet m n .>= 0
+                          =: cases [ m .<= 0 ==> trivial   -- n + 1 >= 0
+                                   , m .> 0 .&& n .<= 0
+                                       ==> pet m n .>= 0
+                                        =: pet (m - 1) 1 .>= 0
+                                        ?? ih `at` (Inst @"m" (m - 1), Inst @"n" (1 :: SInteger))
+                                        =: sTrue
+                                        =: qed
+                                   , m .> 0 .&& n .> 0
+                                       ==> pet m n .>= 0
+                                        =: pet (m - 1) (pet m (n - 1)) .>= 0
+                                        ?? ih `at` (Inst @"m" m, Inst @"n" (n - 1))
+                                        ?? ih `at` (Inst @"m" (m - 1), Inst @"n" (pet m (n - 1)))
+                                        =: sTrue
+                                        =: qed
+                                   ]
+
+-- | The main theorem, relating @pet@ and @ack@: @pet m n + 3 = ack (m-1) (n+3) 2@ for @m > 0@ and @n >= 0@.
+--
+-- >>> runTPWith cvc5 petAck
+-- Inductive lemma (strong): ack_2_2_4
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2.1                        Q.E.D.
+--     Step: 1.2.2                        Q.E.D.
+--     Step: 1.2.3                        Q.E.D.
+--     Step: 1.2.4                        Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Inductive lemma (strong): pet_psd
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2.1                        Q.E.D.
+--     Step: 1.2.2                        Q.E.D.
+--     Step: 1.2.3                        Q.E.D.
+--     Step: 1.3.1                        Q.E.D.
+--     Step: 1.3.2                        Q.E.D.
+--     Step: 1.3.3                        Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Inductive lemma (strong): petAck
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2.1                        Q.E.D.
+--     Step: 1.2.2                        Q.E.D.
+--     Step: 1.2.3                        Q.E.D.
+--     Step: 1.3.1                        Q.E.D.
+--     Step: 1.3.2                        Q.E.D.
+--     Step: 1.3.3                        Q.E.D.
+--     Step: 1.3.4                        Q.E.D.
+--     Step: 1.3.5                        Q.E.D.
+--     Step: 1.4.1                        Q.E.D.
+--     Step: 1.4.2                        Q.E.D.
+--     Step: 1.4.3                        Q.E.D.
+--     Step: 1.4.4                        Q.E.D.
+--     Step: 1.4.5                        Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Functions proven terminating: ack, pet
+-- [Proven] petAck :: Ɐm ∷ Integer → Ɐn ∷ Integer → Bool
+petAck :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
+petAck = do
+    ack224 <- ack_2_2_4
+    psd    <- pet_psd
+    sInduct "petAck"
+               (\(Forall m) (Forall n) ->
+                   m .> 0 .&& n .>= 0 .=> pet m n + 3 .== ack (m - 1) (n + 3) 2)
+               (\m n -> tuple (m, n), []) $
+               \ih m n -> [m .> 0, n .>= 0]
+                       |- pet m n + 3 .== ack (m - 1) (n + 3) 2
+                       =: cases [ m .== 1 .&& n .== 0
+                                    ==> trivial
+                                , m .== 1 .&& n .> 0
+                                    ==> pet 1 n + 3 .== ack 0 (n + 3) 2
+                                     =: pet 0 (pet 1 (n - 1)) + 3 .== (n + 3) + 2
+                                     ?? ih `at` (Inst @"m" (1 :: SInteger), Inst @"n" (n - 1))
+                                     =: sTrue
+                                     =: qed
+                                , m .> 1 .&& n .<= 0
+                                    -- n <= 0 with n >= 0 means n == 0
+                                    ==> pet m n + 3 .== ack (m - 1) (n + 3) 2
+                                     -- First unfold pet: since n <= 0, pet m n = pet (m-1) 1
+                                     =: pet (m - 1) 1 + 3 .== ack (m - 1) (n + 3) 2
+                                     -- Unfold ack: ack (m-1) (n+3) 2 = ack (m-2) (ack (m-1) (n+2) 2) 2
+                                     =: pet (m - 1) 1 + 3 .== ack (m - 2) (ack (m - 1) (n + 2) 2) 2
+                                     -- Apply IH at (m-1, 1): pet (m-1) 1 + 3 = ack (m-2) 4 2
+                                     ?? ih `at` (Inst @"m" (m - 1), Inst @"n" (1 :: SInteger))
+                                     =: ack (m - 2) 4 2 .== ack (m - 2) (ack (m - 1) (n + 2) 2) 2
+                                     -- Since n = 0, n+2 = 2, and ack (m-1) 2 2 = 4 by ack_2_2_4
+                                     ?? ack224 `at` Inst @"m" (m - 1)
+                                     =: sTrue
+                                     =: qed
+                                , m .> 1 .&& n .> 0
+                                    ==> pet m n + 3 .== ack (m - 1) (n + 3) 2
+                                     -- Unfold pet: pet m n = pet (m-1) (pet m (n-1))
+                                     =: pet (m - 1) (pet m (n - 1)) + 3 .== ack (m - 1) (n + 3) 2
+                                     -- Unfold ack on RHS: ack (m-1) (n+3) 2 = ack (m-2) (ack (m-1) (n+2) 2) 2
+                                     =: pet (m - 1) (pet m (n - 1)) + 3 .== ack (m - 2) (ack (m - 1) (n + 2) 2) 2
+                                     -- Use pet_psd to establish pet m (n-1) >= 0
+                                     ?? psd `at` (Inst @"m" m, Inst @"n" (n - 1))
+                                     -- Apply IH at (m-1, pet m (n-1)) to transform LHS
+                                     ?? ih `at` (Inst @"m" (m - 1), Inst @"n" (pet m (n - 1)))
+                                     =: ack (m - 2) (pet m (n - 1) + 3) 2 .== ack (m - 2) (ack (m - 1) (n + 2) 2) 2
+                                     -- Apply IH at (m, n-1): pet m (n-1) + 3 = ack (m-1) (n+2) 2
+                                     ?? ih `at` (Inst @"m" m, Inst @"n" (n - 1))
+                                     =: sTrue
+                                     =: qed
+                                ]
+
+{- HLint ignore module    "Use curry"     -}
+{- HLint ignore ack_psd   "Use camelCase" -}
+{- HLint ignore pet_psd   "Use camelCase" -}
+{- HLint ignore ack_2_2_4 "Use camelCase" -}
diff --git a/Documentation/SBV/Examples/TP/Adder.hs b/Documentation/SBV/Examples/TP/Adder.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Adder.hs
@@ -0,0 +1,395 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Adder
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Prove binary adders correct by induction, for /all/ widths at once.
+--
+-- This is the inductive companion to
+-- "Documentation.SBV.Examples.BitPrecise.Adders", which proves fixed-width
+-- adders correct automatically by bit-blasting. Here, instead, we model the
+-- operands as arbitrary-length, little-endian symbolic bit lists and prove---by
+-- induction on the list---properties that hold with no bound on the width:
+--
+--   * a ripple-carry adder agrees with the mathematical value of the bits
+--     (@correctness@);
+--
+--   * a parallel-prefix (carry-lookahead) tree computes the same carry as the
+--     ripple, because the generate\/propagate carry operator is associative
+--     (@lookaheadCorrect@); and
+--
+--   * that lookahead carry is exactly the carry the ripple adder threads
+--     (@lookaheadMatchesAdder@).
+--
+-- A number is represented by a little-endian list of bit pairs: one
+-- @(a, b)@ per position, least-significant first, where @a@ is a bit of the
+-- first operand and @b@ the corresponding bit of the second. The integer value
+-- of such a list is @sum_i bit_i * 2^i@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Adder where
+
+import Prelude hiding (fst, snd, foldl, map, curry, uncurry, (++))
+
+import Data.SBV hiding (fullAdder)
+import Data.SBV.List (foldl, map, (++))
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+import Documentation.SBV.Examples.TP.Lists (foldlOverAppend)
+
+-- We reuse the very same combinational gates that the fixed-width, bit-blasted
+-- companion proves correct---only the adder driver differs (a symbolic,
+-- inductive recursion here versus a metalevel one there). The 'Data.SBV.fullAdder'
+-- word-level operation is hidden above so 'fullAdder' refers to that gate.
+import Documentation.SBV.Examples.BitPrecise.Adders (Bit, fullAdder, generatePropagate)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XOverloadedLists
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Bits, values, and the adder
+
+-- | The integer value of a single bit: @1@ if set, @0@ otherwise.
+bitVal :: Bit -> SInteger
+bitVal b = ite b 1 0
+
+-- | The integer value of a little-endian bit list: @sum_i bit_i * 2^i@.
+val :: SList Bool -> SInteger
+val = smtFunction "val"
+    $ \bs -> [sCase| bs of
+                []     -> 0
+                x : xs -> bitVal x + 2 * val xs
+             |]
+
+-- | The value of the first operand, read off the first components of the pairs.
+valA :: SList (Bool, Bool) -> SInteger
+valA = smtFunction "valA"
+     $ \ps -> [sCase| ps of
+                 []          -> 0
+                 (a, _) : qs -> bitVal a + 2 * valA qs
+              |]
+
+-- | The value of the second operand, read off the second components of the pairs.
+valB :: SList (Bool, Bool) -> SInteger
+valB = smtFunction "valB"
+     $ \ps -> [sCase| ps of
+                 []          -> 0
+                 (_, b) : qs -> bitVal b + 2 * valB qs
+              |]
+
+-- | The ripple-carry adder. Given an incoming carry and a little-endian list of
+-- bit pairs, thread the carry through a chain of full adders (the same
+-- 'fullAdder' gate the bit-blasted companion verifies), emitting each sum bit
+-- and, at the end, the final carry-out as the most-significant bit. The result
+-- is therefore one bit longer than the input, so its value is exactly the full
+-- sum---no truncation.
+rca :: Bit -> SList (Bool, Bool) -> SList Bool
+rca = smtFunction "rca"
+    $ \c ps -> [sCase| ps of
+                  []     -> [c]
+                  p : qs -> let (s, co) = uncurry fullAdder p c
+                            in s .: rca co qs
+               |]
+
+-- * Correctness
+
+-- | The ripple-carry adder computes the sum of its operands, for any width:
+--
+-- @val (rca 0 ps) == valA ps + valB ps@
+--
+-- We prove it via a more general lemma that tracks the incoming carry, since the
+-- recursive calls feed each stage's carry-out into the next.
+--
+-- >>> runTP correctness
+-- Lemma: fullAdderCorrect        Q.E.D.
+-- Inductive lemma: rcaCorrect
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Lemma: adderCorrect            Q.E.D.
+-- Functions proven terminating: rca, val, valA, valB
+-- [Proven] adderCorrect :: Ɐps ∷ [(Bool, Bool)] → Bool
+correctness :: TP (Proof (Forall "ps" [(Bool, Bool)] -> SBool))
+correctness = do
+
+  -- A single full adder is arithmetically correct: the sum bit plus twice the
+  -- carry-out equals the sum of the three input bits. This is a finite boolean
+  -- fact, discharged directly.
+  faC <- lemma "fullAdderCorrect"
+               (\(Forall @"a" a) (Forall @"b" b) (Forall @"c" c) ->
+                    let (s, co) = fullAdder a b c
+                    in bitVal s + 2 * bitVal co .== bitVal a + bitVal b + bitVal c)
+               []
+
+  -- The general statement, tracking the incoming carry. Induct on the list of
+  -- bit pairs; the carry is universally quantified so the induction hypothesis
+  -- applies at the carry-out fed to the recursive call.
+  rcaC <- induct "rcaCorrect"
+                 (\(Forall @"ps" ps) (Forall @"c" c) ->
+                      val (rca c ps) .== valA ps + valB ps + bitVal c) $
+                 \ih (p, ps) c ->
+                     let a       = fst p
+                         b       = snd p
+                         (s, co) = fullAdder a b c
+                     in [] |- val (rca c (p .: ps))
+                           =: val (s .: rca co ps)
+                           =: bitVal s + 2 * val (rca co ps)
+                           ?? ih `at` Inst @"c" co
+                           =: bitVal s + 2 * (valA ps + valB ps + bitVal co)
+                           ?? faC `at` (Inst @"a" a, Inst @"b" b, Inst @"c" c)
+                           =: (bitVal a + 2 * valA ps) + (bitVal b + 2 * valB ps) + bitVal c
+                           =: valA (p .: ps) + valB (p .: ps) + bitVal c
+                           =: qed
+
+  -- The headline corollary: with no incoming carry, the adder computes the sum.
+  lemma "adderCorrect"
+        (\(Forall ps) -> val (rca sFalse ps) .== valA ps + valB ps)
+        [proofOf rcaC]
+
+-- * Carry-lookahead, via a parallel-prefix tree
+--
+-- $lookahead
+-- A ripple-carry adder is slow because each stage waits for the carry from the
+-- one below it. A /carry-lookahead/ adder breaks that chain by computing the
+-- carries in parallel. The key is to summarize a contiguous block of positions
+-- by a @(generate, propagate)@ /section/: whether the block produces a carry on
+-- its own (@generate@), and whether it would pass an incoming carry straight
+-- through (@propagate@). Adjacent sections combine with the associative operator
+-- 'dot', so the carries can be gathered by a balanced /tree/ of 'dot's rather
+-- than a linear ripple.
+--
+-- We prove that tree correct against the ripple as follows. 'dot' is an
+-- associative monoid with identity 'idSec', and applying a section to an
+-- incoming carry ('applyC') is its action. The ripple carry is the /linear/
+-- fold of 'dot' over the sections (@carryIsFold@), and a balanced tree of 'dot's
+-- computes that /same/ fold by associativity (@treeIsFold@). Hence the parallel
+-- tree and the sequential ripple agree.
+
+-- | Combine two adjacent @(generate, propagate)@ sections, lower-order first.
+-- The combined block generates a carry if the high part does, or if it
+-- propagates one generated by the low part; it propagates only if both do.
+dot :: SBV (Bool, Bool) -> SBV (Bool, Bool) -> SBV (Bool, Bool)
+dot lo hi = tuple (fst hi .|| (snd hi .&& fst lo), snd hi .&& snd lo)
+
+-- | The identity section: generates nothing, propagates everything.
+idSec :: SBV (Bool, Bool)
+idSec = tuple (sFalse, sTrue)
+
+-- | Apply a section to an incoming carry, giving the carry out of that section.
+applyC :: SBV (Bool, Bool) -> Bit -> Bit
+applyC sec c = fst sec .|| (snd sec .&& c)
+
+-- | The sequential ripple carry-out: thread the incoming carry through the
+-- sections, left to right.
+carry :: Bit -> SList (Bool, Bool) -> Bit
+carry = smtFunction "carry"
+      $ \c gps -> [sCase| gps of
+                     []       -> c
+                     b : rest -> carry (applyC b c) rest
+                  |]
+
+-- | The @(generate, propagate)@ section of a single operand bit-pair @(a, b)@,
+-- using the very same 'generatePropagate' gate as the bit-blasted companion.
+gpOf :: SBV (Bool, Bool) -> SBV (Bool, Bool)
+gpOf p = tuple (uncurry generatePropagate p)
+
+-- | The carry-out actually threaded by the ripple adder 'rca': fold the
+-- incoming carry through the full-adder carry of each position. (This is 'rca'
+-- with the sum bits dropped---it threads the identical carry, via the same
+-- 'fullAdder'.)
+rcaCarry :: Bit -> SList (Bool, Bool) -> Bit
+rcaCarry = smtFunction "rcaCarry"
+         $ \c ps -> [sCase| ps of
+                       []     -> c
+                       p : qs -> let (_, co) = uncurry fullAdder p c
+                                 in rcaCarry co qs
+                    |]
+
+-- | The headline lookahead result, in textbook parallel-prefix form: the ripple
+-- carry over a concatenation equals combining the two halves' sections
+-- /independently/ and then applying the result to the incoming carry. Since
+-- 'dot' is associative, the halves can be split the same way recursively---so
+-- the carries can be gathered by a balanced /tree/ of 'dot's instead of a linear
+-- ripple, and this says every such tree computes the same carry.
+--
+-- The proof rests on two pieces: @carryIsFold@ (the ripple carry /is/ the linear
+-- fold of 'dot'), kept as its own reusable lemma, and @foldlDotSplit@ (the fold
+-- distributes over append---the associativity law that licenses any tree).
+--
+-- >>> runTP lookaheadCorrect
+-- Lemma: dotAssoc                     Q.E.D.
+-- Lemma: dotLeftUnit                  Q.E.D.
+-- Lemma: applyCDot                    Q.E.D.
+-- Inductive lemma: foldlDotShift
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Step: 5                           Q.E.D.
+--   Step: 6                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma: carryIsFold
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Step: 5                           Q.E.D.
+--   Step: 6                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma: foldlOverAppend
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: foldlDotSplit
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: treeCarry
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: carry, sbv.foldl
+-- [Proven] treeCarry :: Ɐc ∷ Bool → Ɐxs ∷ [(Bool, Bool)] → Ɐys ∷ [(Bool, Bool)] → Bool
+lookaheadCorrect :: TP (Proof (Forall "c" Bool -> Forall "xs" [(Bool, Bool)] -> Forall "ys" [(Bool, Bool)] -> SBool))
+lookaheadCorrect = do
+
+  -- 'dot' is an associative monoid with identity 'idSec'; 'applyC' is its
+  -- action. All finite boolean facts.
+  assoc <- lemma "dotAssoc"    (\(Forall @"x" x) (Forall @"y" y) (Forall @"z" z) -> dot x (dot y z) .== dot (dot x y) z)                  []
+  lunit <- lemma "dotLeftUnit" (\(Forall @"x" x) -> dot idSec x .== x)                                                                    []
+  act   <- lemma "applyCDot"   (\(Forall @"lo" lo) (Forall @"hi" hi) (Forall @"c" c) -> applyC (dot lo hi) c .== applyC hi (applyC lo c)) []
+
+  -- Folding with an initial section @s@ equals @s@ combined with the fold from
+  -- the identity. (Accumulator reassociation, à la Lists.foldrFoldl.)
+  fldShift <- induct "foldlDotShift"
+                  (\(Forall @"xs" xs) (Forall @"s" s) ->
+                       foldl dot s xs .== dot s (foldl dot idSec xs)) $
+                  \ih (x, xs) s -> [] |- foldl dot s (x .: xs)
+                                      =: foldl dot (dot s x) xs
+                                      ?? ih `at` Inst @"s" (dot s x)
+                                      =: dot (dot s x) (foldl dot idSec xs)
+                                      ?? assoc
+                                      =: dot s (dot x (foldl dot idSec xs))
+                                      ?? ih `at` Inst @"s" x
+                                      =: dot s (foldl dot x xs)
+                                      ?? lunit
+                                      =: dot s (foldl dot (dot idSec x) xs)
+                                      =: dot s (foldl dot idSec (x .: xs))
+                                      =: qed
+
+  -- The reusable link: the sequential ripple carry is the left fold of 'dot'
+  -- over the sections, applied to the incoming carry. Induct on the sections;
+  -- the carry is the threaded argument, so the hypothesis applies at the next
+  -- carry-in.
+  cif <- induct "carryIsFold"
+                (\(Forall @"gps" gps) (Forall @"c" c) ->
+                     carry c gps .== applyC (foldl dot idSec gps) c) $
+                \ih (b, gps) c -> [] |- carry c (b .: gps)
+                                     =: carry (applyC b c) gps
+                                     ?? ih `at` Inst @"c" (applyC b c)
+                                     =: applyC (foldl dot idSec gps) (applyC b c)
+                                     ?? act `at` (Inst @"lo" b, Inst @"hi" (foldl dot idSec gps), Inst @"c" c)
+                                     =: applyC (dot b (foldl dot idSec gps)) c
+                                     ?? fldShift `at` (Inst @"xs" gps, Inst @"s" b)
+                                     =: applyC (foldl dot b gps) c
+                                     ?? lunit
+                                     =: applyC (foldl dot (dot idSec b) gps) c
+                                     =: applyC (foldl dot idSec (b .: gps)) c
+                                     =: qed
+
+  -- foldl of 'dot' distributes over append (imported from the Lists examples).
+  foa <- foldlOverAppend dot
+
+  -- The split/homomorphism law: reducing a concatenation equals reducing the
+  -- halves independently and combining them with 'dot'. This is what licenses
+  -- any balanced (tree) grouping of the sections.
+  splitLaw <- calc "foldlDotSplit"
+                (\(Forall @"xs" xs) (Forall @"ys" ys) ->
+                     foldl dot idSec (xs ++ ys) .== dot (foldl dot idSec xs) (foldl dot idSec ys)) $
+                \xs ys -> [] |- foldl dot idSec (xs ++ ys)
+                             ?? foa `at` (Inst @"xs" xs, Inst @"ys" ys, Inst @"e" idSec)
+                             =: foldl dot (foldl dot idSec xs) ys
+                             ?? fldShift `at` (Inst @"xs" ys, Inst @"s" (foldl dot idSec xs))
+                             =: dot (foldl dot idSec xs) (foldl dot idSec ys)
+                             =: qed
+
+  -- Headline: the ripple carry of a concatenation equals applying the
+  -- independently-combined half-sections to the incoming carry.
+  calc "treeCarry"
+       (\(Forall @"c" c) (Forall @"xs" xs) (Forall @"ys" ys) ->
+            carry c (xs ++ ys) .== applyC (dot (foldl dot idSec xs) (foldl dot idSec ys)) c) $
+       \c xs ys -> [] |- carry c (xs ++ ys)
+                    ?? cif `at` (Inst @"gps" (xs ++ ys), Inst @"c" c)
+                    =: applyC (foldl dot idSec (xs ++ ys)) c
+                    ?? splitLaw `at` (Inst @"xs" xs, Inst @"ys" ys)
+                    =: applyC (dot (foldl dot idSec xs) (foldl dot idSec ys)) c
+                    =: qed
+
+-- | The capstone, tying the lookahead machinery back to the actual adder:
+-- running the (foldable, tree-groupable) section 'carry' over the operands'
+-- generate\/propagate signals reproduces exactly the carry that the ripple adder
+-- 'rca' threads. Combined with @treeCarry@, this says the adder's own carry can
+-- be computed by any balanced prefix tree.
+--
+-- >>> runTP lookaheadMatchesAdder
+-- Lemma: applyCgpOf                         Q.E.D.
+-- Inductive lemma: lookaheadMatchesAdder
+--   Step: Base                              Q.E.D.
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Step: 3                                 Q.E.D.
+--   Step: 4                                 Q.E.D.
+--   Step: 5                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Functions proven terminating: carry, rcaCarry, sbv.map
+-- [Proven] lookaheadMatchesAdder :: Ɐps ∷ [(Bool, Bool)] → Ɐc ∷ Bool → Bool
+lookaheadMatchesAdder :: TP (Proof (Forall "ps" [(Bool, Bool)] -> Forall "c" Bool -> SBool))
+lookaheadMatchesAdder = do
+
+  -- Applying a position's generate/propagate section to a carry is exactly the
+  -- full-adder carry-out. A finite boolean fact.
+  applyGP <- lemma "applyCgpOf"
+                   (\(Forall @"p" p) (Forall @"c" c) ->
+                        let (_, co) = uncurry fullAdder p c
+                        in applyC (gpOf p) c .== co)
+                   []
+
+  -- Induct on the operands; the carry is threaded, so the hypothesis applies at
+  -- the next carry-in.
+  induct "lookaheadMatchesAdder"
+         (\(Forall @"ps" ps) (Forall @"c" c) -> carry c (map gpOf ps) .== rcaCarry c ps) $
+         \ih (p, ps) c -> let (_, co) = uncurry fullAdder p c
+                          in [] |- carry c (map gpOf (p .: ps))
+                                =: carry c (gpOf p .: map gpOf ps)
+                                =: carry (applyC (gpOf p) c) (map gpOf ps)
+                                ?? applyGP `at` (Inst @"p" p, Inst @"c" c)
+                                =: carry co (map gpOf ps)
+                                ?? ih `at` Inst @"c" co
+                                =: rcaCarry co ps
+                                =: rcaCarry c (p .: ps)
+                                =: qed
diff --git a/Documentation/SBV/Examples/TP/Basics.hs b/Documentation/SBV/Examples/TP/Basics.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Basics.hs
@@ -0,0 +1,427 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Basics
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Some basic TP usage.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Basics where
+
+import Prelude hiding(reverse, length, elem)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+import Control.Monad (void)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XScopedTypeVariables
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+-- >>> import Control.Exception
+#endif
+
+-- * Truth and falsity
+
+-- | @sTrue@ is provable.
+--
+-- We have:
+--
+-- >>> trueIsProvable
+-- Lemma: true         Q.E.D.
+-- [Proven] true :: Bool
+trueIsProvable :: IO (Proof SBool)
+trueIsProvable = runTP $ lemma "true" sTrue []
+
+-- | @sFalse@ isn't provable.
+--
+-- We have:
+--
+-- >>> falseIsn'tProvable `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: sFalse
+-- *** Failed to prove sFalse.
+-- Falsifiable
+falseIsn'tProvable :: IO ()
+falseIsn'tProvable = runTP $ do
+        _won'tGoThrough <- lemma "sFalse" sFalse []
+        pure ()
+
+-- * Quantification
+
+-- | Basic quantification example: For every integer, there's a larger integer.
+--
+-- We have:
+-- >>> largerIntegerExists
+-- Lemma: largerIntegerExists    Q.E.D.
+-- [Proven] largerIntegerExists :: Ɐx ∷ Integer → ∃y ∷ Integer → Bool
+largerIntegerExists :: IO (Proof (Forall "x" Integer -> Exists "y" Integer -> SBool))
+largerIntegerExists = runTP $ lemma "largerIntegerExists"
+                                    (\(Forall x) (Exists y) -> x .< y)
+                                    []
+
+-- * Basic connectives
+
+-- | Pushing a universal through conjunction. We have:
+--
+-- >>> forallConjunction @Integer (uninterpret "p") (uninterpret "q")
+-- Lemma: forallConjunction    Q.E.D.
+-- [Proven] forallConjunction :: Bool
+forallConjunction :: forall a. SymVal a => (SBV a -> SBool) -> (SBV a -> SBool) -> IO (Proof SBool)
+forallConjunction p q = runTP $ do
+    let qb = quantifiedBool
+
+    lemma "forallConjunction"
+           (      (qb (\(Forall x) -> p x) .&& qb (\(Forall x) -> q x))
+            .<=> -------------------------------------------------------
+                          qb (\(Forall x) -> p x .&& q x)
+           )
+           []
+
+-- | Pushing an existential through disjunction. We have:
+--
+-- >>> existsDisjunction @Integer (uninterpret "p") (uninterpret "q")
+-- Lemma: existsDisjunction    Q.E.D.
+-- [Proven] existsDisjunction :: Bool
+existsDisjunction :: forall a. SymVal a => (SBV a -> SBool) -> (SBV a -> SBool) -> IO (Proof SBool)
+existsDisjunction p q = runTP $ do
+    let qb = quantifiedBool
+
+    lemma "existsDisjunction"
+           (      (qb (\(Exists x) -> p x) .|| qb (\(Exists x) -> q x))
+            .<=> -------------------------------------------------------
+                          qb (\(Exists x) -> p x .|| q x)
+           )
+           []
+
+-- | We cannot push a universal through a disjunction. We have:
+--
+-- >>> forallDisjunctionNot @Integer (uninterpret "p") (uninterpret "q") `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: forallConjunctionNot
+-- *** Failed to prove forallConjunctionNot.
+-- Falsifiable. Counter-example:
+--   p :: Integer -> Bool
+--   p 4 = True
+--   p 3 = False
+--   p _ = True
+-- <BLANKLINE>
+--   q :: Integer -> Bool
+--   q 4 = False
+--   q 3 = True
+--   q _ = True
+--
+-- Note how @p@ and @q@ differ in their treatment of the inputs 3 and 4, but agree everywhere else. So, for each
+-- input, at least one of @p@ or @q@ is @True@, making the disjunction @True@ for all inputs. But the predicates
+-- @p@ and @q@ are not universally true themselves, constituting a counter-example.
+forallDisjunctionNot :: forall a. SymVal a => (SBV a -> SBool) -> (SBV a -> SBool) -> IO ()
+forallDisjunctionNot p q = runTP $ do
+    let qb = quantifiedBool
+
+    -- This won't prove!
+    _won'tGoThrough <- lemma "forallConjunctionNot"
+                             (      (qb (\(Forall x) -> p x) .|| qb (\(Forall x) -> q x))
+                              .<=> -------------------------------------------------------
+                                              qb (\(Forall x) -> p x .|| q x)
+                             )
+                             []
+
+    pure ()
+
+-- | We cannot push an existential through conjunction. We have:
+--
+-- >>> existsConjunctionNot @Integer (uninterpret "p") (uninterpret "q") `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: existsConjunctionNot
+-- *** Failed to prove existsConjunctionNot.
+-- Falsifiable. Counter-example:
+--   p :: Integer -> Bool
+--   p 3 = False
+--   p _ = True
+-- <BLANKLINE>
+--   q :: Integer -> Bool
+--   q 3 = True
+--   q _ = False
+--
+-- In this case, both @p@ and @q@ have a satisfying input (for @p@ everything but 3, for @q@, only 3), but
+-- there is no single value that satisfies both, thus giving us our counter-example.
+existsConjunctionNot :: forall a. SymVal a => (SBV a -> SBool) -> (SBV a -> SBool) -> IO ()
+existsConjunctionNot p q = runTP $ do
+    let qb = quantifiedBool
+
+    _wont'GoThrough <- lemma "existsConjunctionNot"
+                             (      (qb (\(Exists x) -> p x) .&& qb (\(Exists x) -> q x))
+                              .<=> -------------------------------------------------------
+                                              qb (\(Exists x) -> p x .&& q x)
+                             )
+                            []
+
+    pure ()
+
+-- * QuickCheck
+
+-- | Using quick-check as a step. This can come in handy if a proof step isn't converging,
+-- or if you want to quickly see if there are any obvious counterexamples. This example prints:
+--
+-- @
+-- Lemma: qcExample
+--   Step: 1 (passed 1000 tests)           Q.E.D. [Modulo: quickCheck]
+--   Step: 2 (Failed during quickTest)
+--
+-- *** QuickCheck failed for qcExample.2
+-- *** Failed! Assertion failed (after 1 test):
+--   n   = 175 :: Word8
+--   lhs =  94 :: Word8
+--   rhs =  95 :: Word8
+--   val =  94 :: Word8
+--
+-- *** Exception: Failed
+-- @
+--
+-- Of course, the counterexample you get might differ depending on the quickcheck outcome.
+qcExample :: TP (Proof (Forall "n" Word8 -> SBool))
+qcExample = calc "qcExample"
+                 (\(Forall n) -> n + n .== 2 * n) $
+                 \n -> [] |- n + n
+                          ?? qc 1000
+                          =: 2 * n
+                          ?? qc 1000
+                          ?? disp "val" (2 * n)
+                          =: 2 * n + 1
+                          =: qed
+
+-- | We can't really prove Fermat's last theorem. But we can quick-check instances of it.
+--
+-- >>> runTP (qcFermat 3)
+-- Lemma: qcFermat 3
+--   Step: 1 (qc: Running 1000 tests)    QC OK
+--   Result:                             Q.E.D. [Modulo: quickCheck]
+-- [Modulo: quickCheck] qcFermat 3 :: Ɐx ∷ Integer → Ɐy ∷ Integer → Ɐz ∷ Integer → Bool
+qcFermat :: Integer -> TP (Proof (Forall "x" Integer -> Forall "y" Integer -> Forall "z" Integer -> SBool))
+qcFermat e = calc ("qcFermat " <> show e)
+                  (\(Forall x) (Forall y) (Forall z) -> n .> 2 .=> x.^n + y.^n ./= z.^n) $
+                  \x y z -> [n .> 2]
+                         |- x .^ n + y .^ n ./= z .^ n
+                         ?? qc 1000
+                         =: sTrue
+                         =: qed
+  where n = literal e
+
+-- * Termination checking
+
+-- | When a recursive function is defined via 'smtFunction', SBV automatically checks that it terminates
+-- by guessing and verifying a termination measure. Here we define a simple recursive @sumToN@ and prove
+-- a property about it. Note the @Functions proven terminating@ line in the output, confirming that SBV
+-- verified the termination of @sumToN@ before proceeding with the proof.
+--
+-- >>> terminationDemo
+-- Lemma: sumToN_at_5    Q.E.D.
+-- Functions proven terminating: sumToN
+-- [Proven] sumToN_at_5 :: Ɐn ∷ Integer → Bool
+terminationDemo :: IO (Proof (Forall "n" Integer -> SBool))
+terminationDemo = runTP $ do
+    let sumToN :: SInteger -> SInteger
+        sumToN = smtFunction "sumToN" $ \x -> [sCase| x of
+                                                 _ | x .<= 0 -> 0
+                                                 _           -> x + sumToN (x - 1)
+                                              |]
+
+    lemma "sumToN_at_5"
+          (\(Forall n) -> n .== 5 .=> sumToN n .== 15)
+          []
+
+-- | If SBV cannot determine a termination measure, it will report an error. Here, we define
+-- a function that recurses without decreasing any argument, and SBV rightfully rejects it:
+--
+-- >>> badTermination `catch` (\(e :: SomeException) -> mapM_ putStrLn . filter (\l -> take 3 l == "***") . lines $ show e)
+-- *** Data.SBV: Cannot determine a termination measure.
+-- ***
+-- ***   Function: bad :: SBV Integer -> SBV Integer
+-- ***
+-- ***   Measures tried:
+-- ***     abs arg1
+-- ***     smax 0 arg1
+-- ***     abs arg1 + smax 0 arg1
+-- ***     (abs arg1, smax 0 arg1)
+-- ***     (smax 0 arg1, abs arg1)
+-- ***
+-- *** Please use 'smtFunctionWithMeasure' to provide an explicit measure.
+badTermination :: IO ()
+badTermination = do
+    let bad :: SInteger -> SInteger
+        bad = smtFunction "bad" $ \x -> [sCase| x of
+                                           _ | x .== 0 -> 0
+                                           _           -> bad x
+                                        |]
+    r <- prove $ \x -> bad x .== bad x
+    print r
+
+-- | If the user provides an explicit but incorrect termination measure via 'smtFunctionWithMeasure',
+-- SBV will detect this and report an error. Here, we use @const 0@ as a measure, which clearly
+-- does not decrease at recursive calls:
+--
+-- >>> badMeasure `catch` (\(e :: SomeException) -> mapM_ putStrLn . filter (\l -> take 3 l == "***") . lines $ show e)
+-- *** Data.SBV: Termination measure does not strictly decrease at a recursive call site.
+-- ***
+-- ***   Function: badM :: SBV Integer -> SBV Integer
+-- ***
+-- ***   Falsifiable. Counter-example:
+-- ***     arg    = 1 :: Integer
+-- ***     before = 0 :: Integer
+-- ***     then   = 0 :: Integer
+-- ***
+-- *** The measure must strictly decrease at every recursive call.
+badMeasure :: IO ()
+badMeasure = do
+    let badM :: SInteger -> SInteger
+        badM = smtFunctionWithMeasure "badM" (const (0 :: SInteger), [])
+             $ \x -> [sCase| x of
+                        _ | x .<= 0 -> 0
+                        _           -> x + badM (x - 1)
+                     |]
+    r <- prove $ \x -> badM x .== badM x
+    print r
+
+-- | A termination measure is only a valid argument for termination if it takes values in a
+-- /well-founded/ order: one with no infinite descending chains. Being non-negative and strictly
+-- decreasing then forces the recursion to stop. The integers (bounded below by @0@) are well-founded,
+-- but the reals are /not/: the chain @1, 1\/2, 1\/4, ...@ descends forever without ever reaching a
+-- minimum. So a real-valued measure proves nothing.
+--
+-- Consider this Zeno-style non-terminating recursion: for any @x > 0@, the argument @x \/ 2@ is
+-- again positive, so it never reaches the base case. Yet the measure @0 `smax` x@ is non-negative
+-- and strictly decreases at the recursive call (@x \/ 2 < x@). Accepting it would mean certifying a
+-- non-terminating function as terminating, which can be used to derive falsehoods.
+--
+-- @
+-- zeno :: SReal -> SReal
+-- zeno = smtFunctionWithMeasure \"zeno\" (\\x -> 0 \`smax\` x, [])
+--      $ \\x -> ite (x .<= 0) 0 (zeno (x \/ 2))
+-- @
+--
+-- SBV rules this out /at compile time/: the 'Data.SBV.Zero' class gates which types may be used as
+-- measures, and there is deliberately no instance for algebraic reals. So the definition above does
+-- not type-check, reporting:
+--
+-- @
+--     • A termination measure may not have a real-valued result.
+--
+--       The reals are not well-ordered: an infinite descending chain such as
+--       1, 1\/2, 1\/4, ... has no least element, so a non-negative and strictly
+--       decreasing real measure does not imply termination.
+--
+--       Use an integer-valued measure instead (e.g. a count of remaining steps).
+-- @
+
+-- * Axioms and consistency
+
+-- | SBV checks that recursive functions defined via 'smtFunction' terminate, verifying a termination measure, which
+-- can be auto-guessed or specified by the user. However, axioms are taken on faith: they are not checked for consistency.
+-- If an axiom introduces a non-terminating or contradictory definition, the logic becomes inconsistent, i.e.,
+-- we can prove arbitrary results.
+--
+-- Here is a simple example where we assert an axiom equivalent to a non-terminating definition @f n == 1 + f n@.
+-- Using this, we can deduce @False@:
+--
+-- >>> axiomsAreDangerous
+-- Axiom: bad
+-- Lemma: axiomsCanBeInconsistent
+--   Step: 1 (bad @ (n |-> 0 :: SInteger))    Q.E.D.
+--   Result:                                  Q.E.D.
+-- [Proven] axiomsCanBeInconsistent :: Bool
+axiomsAreDangerous :: IO (Proof SBool)
+axiomsAreDangerous = runTP $ do
+
+   let f :: SInteger -> SInteger
+       f = uninterpret "f"
+
+   badAxiom <- axiom "bad" (\(Forall n) -> f n .== 1 + f n)
+
+   calc "axiomsCanBeInconsistent"
+        sFalse
+        ([] |- f 0
+            ?? badAxiom `at` Inst @"n" (0 :: SInteger)
+            =: 1 + f 0
+            =: qed)
+
+-- * Trying to prove non-theorems
+
+-- | An example where we attempt to prove a non-theorem. Notice the counter-example
+-- generated for:
+--
+-- @length xs == ite (length xs .== 3) 5 (length xs)@
+--
+-- >>> badRevLen `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: badRevLen
+-- *** Failed to prove badRevLen.
+-- Falsifiable. Counter-example:
+--   xs = [17,17,17] :: [Integer]
+badRevLen :: IO ()
+badRevLen = runTP $
+   void $ lemma "badRevLen"
+                (\(Forall @"xs" (xs :: SList Integer)) -> length (reverse xs) .== ite (length xs .== 3) 5 (length xs))
+                []
+
+-- | It is instructive to see what kind of counter-example we get if a lemma fails to prove.
+-- Below, we do a variant of the 'lengthTail, but with a bad implementation over integers,
+-- and see the counter-example. Our implementation returns an incorrect answer if the given list is longer
+-- than 5 elements and have 42 in it:
+--
+-- >>> badLengthProof `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: badLengthProof
+-- *** Failed to prove badLengthProof.
+-- Falsifiable. Counter-example:
+--   xs   = [12,15,19,25,32,42] :: [Integer]
+--   imp  =                  42 :: Integer
+--   spec =                   6 :: Integer
+badLengthProof :: IO ()
+badLengthProof = runTP $ do
+   let badLength :: SList Integer -> SInteger
+       badLength xs = ite (length xs .> 5 .&& 42 `elem` xs) 42 (length xs)
+
+   void $ lemma "badLengthProof" (\(Forall @"xs" xs) -> observe "imp" (badLength xs) .== observe "spec" (length xs)) []
+
+-- * Caching
+
+-- | It is not unusual that TP proofs rely on other proofs. Typically, all the helpers are used together and proven in
+-- one go. It is, however, useful to be able to write these proofs as top-level entries, and reuse them multiple times
+-- in several proofs. (See "Documentation/SBV/Examples/TP/PowerMod.hs" for an example.) To avoid re-proving such
+-- lemmas, SBV caches proof results keyed by symbolic fingerprint. Use 'recall' to invoke a proof action that
+-- benefits from the cache: if the proposition has already been proved, the cached result is returned immediately.
+-- Note that 'lemma', 'calc', and 'induct' always prove from scratch and then store the result in the cache;
+-- only 'recall' performs a cache lookup.
+--
+-- Lemma names do not need to be unique. If you prove the same proposition under different names, 'recall' will
+-- show the aliases. If you prove different propositions under the same name, each is proved independently.
+-- To demonstrate, note that reusing the name @"evil"@ does not cause any confusion: the second call to
+-- 'lemma' proves from scratch and correctly fails:
+--
+-- >>> runTP duplicateNames `catch` (\(_ :: SomeException) -> pure ())
+-- Lemma: evil         Q.E.D.
+-- Lemma: evil
+-- *** Failed to prove evil.
+-- Falsifiable
+--
+-- (Incidentally, if you really want to be evil, you can just use 'axiom' and assert false, but that's another story.)
+duplicateNames :: TP ()
+duplicateNames = do
+   -- Prove true
+   _ <- lemma "evil" sTrue []
+
+   -- Attempt to prove false, reusing the same name. Will be caught!
+   _ <- lemma "evil" sFalse []
+
+   pure ()
diff --git a/Documentation/SBV/Examples/TP/BinarySearch.hs b/Documentation/SBV/Examples/TP/BinarySearch.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/BinarySearch.hs
@@ -0,0 +1,269 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.BinarySearch
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving binary search correct.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.BinarySearch where
+
+import Prelude hiding (null, length, (!!), drop, take, tail, elem, notElem)
+
+import Data.SBV
+import Data.SBV.Maybe
+import Data.SBV.TP
+
+-- * Binary search
+
+-- | We will work with arrays containing integers, indexed by integers. Note that since SMTLib arrays
+-- are indexed by their entire domain, we explicitly take a lower/upper bounds as parameters, which fits well
+-- with the binary search algorithm.
+type Arr = SArray Integer Integer
+
+-- | Bounds: This is the focus into the array; both indexes are inclusive.
+type Idx = (SInteger, SInteger)
+
+-- | Encode binary search in a functional style.
+bsearch :: Arr -> Idx -> SInteger -> SMaybe Integer
+bsearch array (low, high) = f array low high
+  where f = smtFunctionWithMeasure "bsearch" (\_arr lo hi _x -> (hi - lo + 1) `smax` 0, [])
+          $ \arr lo hi x ->
+               let mid  = (lo + hi) `sEDiv` 2
+                   xmid = arr `readArray` mid
+               in [sCase| lo of
+                     _ | lo .> hi   -> sNothing
+                     _ | xmid .== x -> sJust mid
+                     _ | xmid .< x  -> bsearch arr (mid+1, hi)    x
+                     _              -> bsearch arr (lo,    mid-1) x
+                  |]
+
+-- * Correctness proof
+
+-- | A predicate testing whether a given array is non-decreasing in the given range
+nonDecreasing :: Arr -> Idx -> SBool
+nonDecreasing arr (low, high) = quantifiedBool $
+    \(Forall i) (Forall j) -> low .<= i .&& i .<= j .&& j .<= high .=> arr `readArray` i .<= arr `readArray` j
+
+-- | A predicate testing whether an element is in the array within the given bounds
+inArray :: Arr -> Idx -> SInteger -> SBool
+inArray arr (low, high) elt = quantifiedBool $ \(Exists i) -> low .<= i .&& i .<= high .&& arr `readArray` i .== elt
+
+-- | Correctness of binary search.
+--
+-- We have:
+--
+-- >>> correctness
+-- Lemma: notInRange                            Q.E.D.
+-- Lemma: inRangeHigh                           Q.E.D.
+-- Lemma: inRangeLow                            Q.E.D.
+-- Lemma: nonDecreasing                         Q.E.D.
+-- Inductive lemma (strong): bsearchAbsent
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (unfold bsearch)                   Q.E.D.
+--   Step: 2 (push isNothing down, simplify)    Q.E.D.
+--   Step: 3 (2 way case split)
+--     Step: 3.1                                Q.E.D.
+--     Step: 3.2.1                              Q.E.D.
+--     Step: 3.2.2                              Q.E.D.
+--     Step: 3.2.3                              Q.E.D.
+--     Step: 3.2.4                              Q.E.D.
+--     Step: 3.2.5 (simplify)                   Q.E.D.
+--     Step: 3.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Inductive lemma (strong): bsearchPresent
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (unfold bsearch)                   Q.E.D.
+--   Step: 2 (simplify)                         Q.E.D.
+--   Step: 3 (3 way case split)
+--     Step: 3.1                                Q.E.D.
+--     Step: 3.2                                Q.E.D.
+--     Step: 3.3.1                              Q.E.D.
+--     Step: 3.3.2 (3 way case split)
+--       Step: 3.3.2.1                          Q.E.D.
+--       Step: 3.3.2.2.1                        Q.E.D.
+--       Step: 3.3.2.2.2                        Q.E.D.
+--       Step: 3.3.2.3.1                        Q.E.D.
+--       Step: 3.3.2.3.2                        Q.E.D.
+--       Step: 3.3.2.Completeness               Q.E.D.
+--     Step: 3.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Lemma: bsearchCorrect
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                              Q.E.D.
+--     Step: 1.1.2                              Q.E.D.
+--     Step: 1.2.1                              Q.E.D.
+--     Step: 1.2.2                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: bsearch
+-- [Proven] bsearchCorrect :: Ɐarr ∷ (ArrayModel Integer Integer) → Ɐlo ∷ Integer → Ɐhi ∷ Integer → Ɐx ∷ Integer → Bool
+correctness :: IO (Proof (Forall "arr" (ArrayModel Integer Integer) -> Forall "lo" Integer -> Forall "hi" Integer -> Forall "x" Integer -> SBool))
+correctness = runTPWith cvc5 $ do
+
+  -- Helper: if a value is not in a range, then it isn't in any subrange of it:
+  notInRange <- lemma "notInRange"
+                           (\(Forall arr) (Forall lo) (Forall hi) (Forall md) (Forall x)
+                               ->  sNot (inArray arr (lo, hi) x) .&& lo .<= md .&& md .<= hi
+                               .=> sNot (inArray arr (lo, md) x) .&& sNot (inArray arr (md, hi) x))
+                           []
+
+  -- Helper: if a value is in a range of a nonDecreasing array, and if its value is larger than a given mid point, then it's in the higher part
+  inRangeHigh <- lemma "inRangeHigh"
+                       (\(Forall arr) (Forall lo) (Forall hi) (Forall md) (Forall x)
+                           ->  nonDecreasing arr (lo, hi) .&& inArray arr (lo, hi) x .&& lo .<= md .&& md .<= hi .&& x .> arr `readArray` md
+                           .=> inArray arr (md+1, hi) x)
+                       []
+
+  -- Helper: if a value is in a range of a nonDecreasing array, and if its value is lower than a given mid point, then it's in the lowr part
+  inRangeLow  <- lemma "inRangeLow"
+                       (\(Forall arr) (Forall lo) (Forall hi) (Forall md) (Forall x)
+                           ->  nonDecreasing arr (lo, hi) .&& inArray arr (lo, hi) x .&& lo .<= md .&& md .<= hi .&& x .< arr `readArray` md
+                           .=> inArray arr (lo, md-1) x)
+                       []
+
+  -- Helper: if an array is nonDecreasing, then its parts are also non-decreasing when cut in any middle point
+  nonDecreasingInRange <- lemma "nonDecreasing"
+                                (\(Forall arr) (Forall lo) (Forall hi) (Forall md)
+                                    ->  nonDecreasing arr (lo, hi) .&& lo .<= md .&& md .<= hi
+                                    .=> nonDecreasing arr (lo, md) .&& nonDecreasing arr (md, hi))
+                                []
+
+  -- Prove the case when the target is not in the array
+  bsearchAbsent <- sInduct "bsearchAbsent"
+        (\(Forall arr) (Forall lo) (Forall hi) (Forall x) ->
+            nonDecreasing arr (lo, hi) .&& sNot (inArray arr (lo, hi) x) .=> isNothing (bsearch arr (lo, hi) x))
+        (\_arr lo hi _x -> abs (hi - lo + 1), []) $
+        \ih arr lo hi x ->
+              [nonDecreasing arr (lo, hi), sNot (inArray arr (lo, hi) x)]
+           |- isNothing (bsearch arr (lo, hi) x)
+           ?? "unfold bsearch"
+           =: let mid  = (lo + hi) `sEDiv` 2
+                  xmid = arr `readArray` mid
+           in isNothing (ite (lo .> hi)
+                             sNothing
+                             (ite (xmid .== x)
+                                  (sJust mid)
+                                  (ite (xmid .< x)
+                                       (bsearch arr (mid+1, hi)    x)
+                                       (bsearch arr (lo,    mid-1) x))))
+           ?? "push isNothing down, simplify"
+           =: ite (lo .> hi)
+                  sTrue
+                  (ite (xmid .== x)
+                       sFalse
+                       (ite (xmid .< x)
+                            (isNothing (bsearch arr (mid+1, hi)    x))
+                            (isNothing (bsearch arr (lo,    mid-1) x))))
+           =: cases [ lo .> hi  ==> trivial
+                    , lo .<= hi ==> ite (xmid .== x)
+                                        sFalse
+                                        (ite (xmid .< x)
+                                             (isNothing (bsearch arr (mid+1, hi)    x))
+                                             (isNothing (bsearch arr (lo,    mid-1) x)))
+                                 =: let inst1 l h m = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h, Inst @"m" m, Inst @"x" x)
+                                        inst2 l h m = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h, Inst @"m" m             )
+                                        inst3 l h   = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h,              Inst @"x" x)
+                                 in ite (xmid .< x)
+                                        (isNothing (bsearch arr (mid+1, hi)    x))
+                                        (isNothing (bsearch arr (lo,    mid-1) x))
+                                 ?? notInRange           `at` inst1 lo      hi (mid+1)
+                                 ?? nonDecreasingInRange `at` inst2 lo      hi (mid+1)
+                                 ?? ih                   `at` inst3 (mid+1) hi
+                                 =: ite (xmid .< x)
+                                        sTrue
+                                        (isNothing (bsearch arr (lo,    mid-1) x))
+                                 ?? notInRange           `at` inst1 lo hi      (mid-1)
+                                 ?? nonDecreasingInRange `at` inst2 lo hi      (mid-1)
+                                 ?? ih                   `at` inst3 lo (mid-1)
+                                 =: ite (xmid .< x) sTrue sTrue
+                                 ?? "simplify"
+                                 =: sTrue
+                                 =: qed
+                    ]
+
+  -- Prove the case when the target is in the array
+  bsearchPresent <- sInduct "bsearchPresent"
+        (\(Forall arr) (Forall lo) (Forall hi) (Forall x) ->
+            nonDecreasing arr (lo, hi) .&& inArray arr (lo, hi) x .=> arr `readArray` fromJust (bsearch arr (lo, hi) x) .== x)
+        (\_arr lo hi _x -> abs (hi - lo + 1), []) $
+        \ih arr lo hi x ->
+             [nonDecreasing arr (lo, hi), inArray arr (lo, hi) x]
+          |- x .== arr `readArray` fromJust (bsearch arr (lo, hi) x)
+          ?? "unfold bsearch"
+          =: let mid  = (lo + hi) `sEDiv` 2
+                 xmid = arr `readArray` mid
+          in x .== arr `readArray` fromJust (ite (lo .> hi)
+                                                 sNothing
+                                                 (ite (xmid .== x)
+                                                      (sJust mid)
+                                                      (ite (xmid .< x)
+                                                           (bsearch arr (mid+1, hi)    x)
+                                                           (bsearch arr (lo,    mid-1) x))))
+          ?? "simplify"
+          =: ite (lo .> hi)
+                 (x .== arr `readArray` fromJust sNothing)
+                 (ite (xmid .== x)
+                      (x .== arr `readArray` mid)
+                      (ite (xmid .< x)
+                           (x .== arr `readArray` fromJust (bsearch arr (mid+1, hi)    x))
+                           (x .== arr `readArray` fromJust (bsearch arr (lo,    mid-1) x))))
+          =: cases [ lo .>  hi ==> trivial
+                   , lo .== hi ==> trivial
+                   , lo .<  hi ==> ite (xmid .== x)
+                                       (x .== arr `readArray` mid)
+                                       (ite (xmid .< x)
+                                            (x .== arr `readArray` fromJust (bsearch arr (mid+1, hi)    x))
+                                            (x .== arr `readArray` fromJust (bsearch arr (lo,    mid-1) x)))
+                                =: let inst1 l h m = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h, Inst @"m" m, Inst @"x" x)
+                                       inst2 l h m = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h, Inst @"m" m             )
+                                       inst3 l h   = (Inst @"arr" arr, Inst @"lo" l, Inst @"hi" h,              Inst @"x" x)
+                                in cases [ xmid .== x ==> trivial
+                                         , xmid .< x  ==> x .== arr `readArray` fromJust (bsearch arr (mid+1, hi)    x)
+                                                       ?? inRangeHigh          `at` inst1 lo      hi mid
+                                                       ?? nonDecreasingInRange `at` inst2 lo      hi (mid+1)
+                                                       ?? ih                   `at` inst3 (mid+1) hi
+                                                       =: sTrue
+                                                       =: qed
+                                         , xmid .> x  ==> x .== arr `readArray` fromJust (bsearch arr (lo, mid-1) x)
+                                                       ?? inRangeLow           `at` inst1 lo hi      mid
+                                                       ?? nonDecreasingInRange `at` inst2 lo hi      (mid-1)
+                                                       ?? ih                   `at` inst3 lo (mid-1)
+                                                       =: sTrue
+                                                       =: qed
+                                         ]
+                   ]
+
+  calc "bsearchCorrect"
+        (\(Forall arr) (Forall lo) (Forall hi) (Forall x) ->
+            nonDecreasing arr (lo, hi) .=> let res = bsearch arr (lo, hi) x
+                                           in ite (inArray arr (lo, hi) x)
+                                                  (arr `readArray` fromJust res .== x)
+                                                  (isNothing res)) $
+        \arr lo hi x -> [nonDecreasing arr (lo, hi)]
+                     |- let res = bsearch arr (lo, hi) x
+                        in ite (inArray arr (lo, hi) x)
+                               (arr `readArray` fromJust res .== x)
+                               (isNothing res)
+                     =: cases [ inArray arr (lo, hi) x
+                                  ==> arr `readArray` fromJust (bsearch arr (lo, hi) x) .== x
+                                   ?? bsearchPresent `at` (Inst @"arr" arr, Inst @"lo" lo, Inst @"hi" hi, Inst @"x" x)
+                                   =: sTrue
+                                   =: qed
+                              , sNot (inArray arr (lo, hi) x)
+                                  ==> isNothing (bsearch arr (lo, hi) x)
+                                   ?? bsearchAbsent `at` (Inst @"arr" arr, Inst @"lo" lo, Inst @"hi" hi, Inst @"x" x)
+                                   =: sTrue
+                                   =: qed
+                              ]
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/Documentation/SBV/Examples/TP/CaseSplit.hs b/Documentation/SBV/Examples/TP/CaseSplit.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/CaseSplit.hs
@@ -0,0 +1,48 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.CaseSplit
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Use TP to prove @2n^2 + n + 1@ is never divisible by @3@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.CaseSplit where
+
+import Data.SBV
+import Data.SBV.TP
+
+-- | Prove that @2n^2 + n + 1@ is not divisible by @3@.
+--
+-- We have:
+--
+-- >>> notDiv3
+-- Lemma: notDiv3
+--   Step: 1 (3 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2               Q.E.D.
+--     Step: 1.3               Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] notDiv3 :: Ɐn ∷ Integer → Bool
+notDiv3 :: IO (Proof (Forall "n" Integer -> SBool))
+notDiv3 = runTP $ do
+
+   let s n = 2 * n * n + n + 1
+
+   -- Do a case-split for each possible outcome of @s n `sEMod` 3@. In each case
+   -- we get the witness that is guaranteed to exist by the case condition, and rewrite
+   -- @s n@ accordingly. Once this is done, z3 can figure out the rest by itself.
+   calc "notDiv3"
+        (\(Forall n) -> s n `sEMod` 3 ./= 0) $
+        \n -> [] |- s n
+                 =: cases [ n `sEMod` 3 .== 0 ==> s (0 + 3 * some "k" (\k -> n .== 0 + 3 * k)) =: qed
+                          , n `sEMod` 3 .== 1 ==> s (1 + 3 * some "k" (\k -> n .== 1 + 3 * k)) =: qed
+                          , n `sEMod` 3 .== 2 ==> s (2 + 3 * some "k" (\k -> n .== 2 + 3 * k)) =: qed
+                          ]
diff --git a/Documentation/SBV/Examples/TP/Coins.hs b/Documentation/SBV/Examples/TP/Coins.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Coins.hs
@@ -0,0 +1,114 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Coins
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving the classic coin change theorem: For any amount @n >= 8@, you can make
+-- exact change using only 3-cent and 5-cent coins.
+--
+-- This example is inspired by: <https://github.com/imandra-ai/imandrax-examples/blob/main/src/coins.iml>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Coins where
+
+import Data.SBV
+import Data.SBV.Maybe hiding (maybe)
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Types
+
+-- | A pocket contains a count of 3-cent and 5-cent coins.
+data Pocket = Pocket { num3s :: Integer
+                     , num5s :: Integer
+                     }
+
+-- | Create a symbolic version of Pocket.
+mkSymbolic [''Pocket]
+
+-- * Making change
+
+-- | Make change for a given amount. Returns 'Nothing' if the amount is less than 8.
+-- Base cases:
+--
+--   *  8 = 3 + 5
+--   *  9 = 3 + 3 + 3
+--   * 10 = 5 + 5
+--
+-- For @n > 10@, we use change for @n-3@ and add one more 3-cent coin.
+mkChange :: SInteger -> SMaybe Pocket
+mkChange = smtFunction "mkChange" $ \n ->
+    [sCase| n of
+       _ | n .<   8 -> sNothing
+       _ | n .==  8 -> sJust (sPocket 1 1)
+       _ | n .==  9 -> sJust (sPocket 3 0)
+       _ | n .== 10 -> sJust (sPocket 0 2)
+       _            -> case mkChange (n - 3) of
+                         Nothing             -> sNothing
+                         Just (Pocket n3 n5) -> sJust (sPocket (n3 + 1) n5)
+   |]
+
+-- | Evaluate the value of a pocket (total cents).
+evalPocket :: SMaybe Pocket -> SInteger
+evalPocket mp = [sCase| mp of
+                   Nothing             -> 0
+                   Just (Pocket n3 n5) -> 3 * n3 + 5 * n5
+                |]
+
+-- * Correctness
+
+-- | Prove that for any @n >= 8@, @mkChange@ produces a pocket that evaluates to @n@.
+--
+-- We have:
+--
+-- >>> runTP correctness
+-- Inductive lemma (strong): mkChangeCorrect
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (5 way case split)
+--     Step: 1.1                                Q.E.D.
+--     Step: 1.2                                Q.E.D.
+--     Step: 1.3                                Q.E.D.
+--     Step: 1.4                                Q.E.D.
+--     Step: 1.5.1                              Q.E.D.
+--     Step: 1.5.2                              Q.E.D.
+--     Step: 1.5.3                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: mkChange
+-- [Proven] mkChangeCorrect :: Ɐn ∷ Integer → Bool
+correctness :: TP (Proof (Forall "n" Integer -> SBool))
+correctness =
+    sInduct "mkChangeCorrect"
+            (\(Forall n) -> n .>= 8 .=> evalPocket (mkChange n) .== n)
+            (id, []) $
+            \ih n -> [n .>= 8]
+                  |- evalPocket (mkChange n) .== n
+                  =: cases [ n .== 8  ==> trivial
+                           , n .== 9  ==> trivial
+                           , n .== 10 ==> trivial
+                           , n .< 8   ==> trivial   -- Vacuously true: contradicts n >= 8
+                           , n .> 10  ==> evalPocket (mkChange n) .== n
+                                       =: [sCase| mkChange (n - 3) of
+                                            Nothing             -> evalPocket sNothing .== n
+                                            Just (Pocket n3 n5) -> evalPocket (sJust (sPocket (n3 + 1) n5)) .== n
+                                         |]
+                                       ?? ih `at` Inst @"n" (n - 3)
+                                       =: sTrue
+                                       =: qed
+                           ]
diff --git a/Documentation/SBV/Examples/TP/Collatz.hs b/Documentation/SBV/Examples/TP/Collatz.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Collatz.hs
@@ -0,0 +1,119 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Collatz
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- The Collatz function: starting from a positive integer, if it is 1 we stop;
+-- if it is even we halve it; if it is odd we triple and add one.  Whether this
+-- process terminates for every positive integer is the famous Collatz conjecture,
+-- an open problem in mathematics. Because no termination measure is known, we
+-- define 'collatz' with 'smtFunctionNoTermination', which emits the recursive
+-- definition without any termination check.
+--
+-- We then prove that 'collatz' reaches 1 for every power of two.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Collatz where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Definitions
+
+-- | The Collatz function. Termination for all positive integers is the famous
+-- Collatz conjecture, an open problem in mathematics. We use 'smtFunctionNoTermination'
+-- since no termination measure is known.
+collatz :: SInteger -> SInteger
+collatz = smtFunctionNoTermination "collatz"
+        $ \n -> [sCase| n of
+                   1                  -> 1
+                   _ | 2 `sDivides` n -> collatz (n `sDiv` 2)
+                     | True           -> collatz (3 * n + 1)
+                |]
+
+-- | Power of two: @pow2 k = 2^k@ for @k >= 0@.
+pow2 :: SInteger -> SInteger
+pow2 = smtFunction "pow2"
+     $ \k -> [sCase| k of
+                _ | k .<= 0 -> 1
+                  | True    -> 2 * pow2 (k - 1)
+             |]
+
+-- * Helper lemmas
+
+-- | Doubling doesn't change the Collatz result.
+--
+-- >>> runTP doubling
+-- Lemma: doubling     Q.E.D. [Modulo: collatz termination]
+-- [Modulo: collatz termination] doubling :: Ɐn ∷ Integer → Bool
+doubling :: TP (Proof (Forall "n" Integer -> SBool))
+doubling = lemma "doubling" (\(Forall @"n" n) -> n .>= 1 .=> collatz (2 * n) .== collatz n) []
+
+-- | Powers of two are positive.
+--
+-- >>> runTP pow2pos
+-- Inductive lemma: pow2pos
+--   Step: Base                Q.E.D.
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven terminating: pow2
+-- [Proven] pow2pos :: Ɐk ∷ Integer → Bool
+pow2pos :: TP (Proof (Forall "k" Integer -> SBool))
+pow2pos = induct "pow2pos"
+                 (\(Forall @"k" k) -> pow2 k .>= 1) $
+                 \ih k -> []
+                       |- pow2 (k + 1) .>= 1
+                       =: 2 * pow2 k .>= 1
+                       ?? ih
+                       =: sTrue
+                       =: qed
+
+-- * Correctness
+
+-- | All powers of two reach 1 under the Collatz function.
+--
+-- >>> runTP collatzPow2
+-- Lemma: doubling                 Q.E.D. [Modulo: collatz termination]
+-- Lemma: pow2pos                  Q.E.D.
+-- Inductive lemma: collatzPow2
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D. [Modulo: collatz termination]
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D. [Modulo: collatz termination]
+-- Functions proven terminating: pow2
+-- [Modulo: collatz termination] collatzPow2 :: Ɐk ∷ Integer → Bool
+collatzPow2 :: TP (Proof (Forall "k" Integer -> SBool))
+collatzPow2 = do
+   dbl <- recall doubling
+   p2p <- recall pow2pos
+
+   induct "collatzPow2"
+          (\(Forall @"k" k) -> k .>= 0 .=> collatz (pow2 k) .== 1) $
+          \ih k -> [k .>= 0]
+                |- collatz (pow2 (k + 1))
+                =: collatz (2 * pow2 k)
+                ?? dbl
+                ?? p2p
+                =: collatz (pow2 k)
+                ?? ih
+                =: (1 :: SInteger)
+                =: qed
diff --git a/Documentation/SBV/Examples/TP/ConstFold.hs b/Documentation/SBV/Examples/TP/ConstFold.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/ConstFold.hs
@@ -0,0 +1,1523 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.ConstFold
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Correctness of constant folding for a simple expression language.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.ConstFold where
+
+import Prelude hiding ((++), snd)
+
+import Data.SBV
+import Data.SBV.List  as SL
+import Data.SBV.Tuple as ST
+import Data.SBV.TP
+
+-- Get the expression language definitions
+import Documentation.SBV.Examples.TP.VM
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+-- >>> :set -XTypeApplications
+#endif
+
+-- | Base expression type (used in quantifiers).
+type Exp = Expr String Integer
+
+-- | Base environment-list type (used in quantifiers).
+type EL = [(String, Integer)]
+
+-- | Symbolic expression over strings and integers.
+type SE = SExpr String Integer
+
+-- | Symbolic environment over strings and integers.
+type E = Env String Integer
+
+-- * Simplification
+
+-- | Simplify an expression at the top level, assuming sub-expressions are already folded.
+-- The rules are:
+--
+--   * @Sqr (Con v)         → Con (v*v)@
+--   * @Inc (Con v)         → Con (v+1)@
+--   * @Add (Con 0) x       → x@
+--   * @Add x (Con 0)       → x@
+--   * @Add (Con a) (Con b) → Con (a+b)@
+--   * @Mul (Con 0) x       → Con 0@
+--   * @Mul x (Con 0)       → Con 0@
+--   * @Mul (Con 1) x       → x@
+--   * @Mul x (Con 1)       → x@
+--   * @Mul (Con a) (Con b) → Con (a*b)@
+--   * @Let nm (Con v) b    → subst nm v b@
+simplify :: SE -> SE
+simplify = smtFunction "simplify" $ \expr ->
+  [sCase| expr of
+    Sqr (Con v)         -> sCon (v * v)
+
+    Inc (Con v)         -> sCon (v + 1)
+
+    Add (Con 0) r       -> r
+    Add l       (Con 0) -> l
+    Add (Con a) (Con b) -> sCon (a + b)
+
+    Mul (Con 0) _       -> sCon 0
+    Mul _       (Con 0) -> sCon 0
+    Mul (Con 1) r       -> r
+    Mul l       (Con 1) -> l
+    Mul (Con a) (Con b) -> sCon (a * b)
+
+    Let nm (Con v) b    -> subst nm v b
+
+    -- fall-thru
+    _                   -> expr
+  |]
+
+-- * Substitution
+
+-- | Substitute a variable with a value in an expression. Capture-avoiding:
+-- if a @Let@-bound variable shadows the target, we do not substitute in the body.
+--
+--   * @Var x         → if x == nm then Con v else Var x@
+--   * @Con c         → Con c@
+--   * @Sqr a         → Sqr (subst nm v a)@
+--   * @Inc a         → Inc (subst nm v a)@
+--   * @Add a b       → Add (subst nm v a) (subst nm v b)@
+--   * @Mul a b       → Mul (subst nm v a) (subst nm v b)@
+--   * @Let x a b     → Let x (subst nm v a) (if x == nm then b else subst nm v b)@
+subst :: SString -> SInteger -> SE -> SE
+subst = smtFunction "subst" $ \nm v expr ->
+  [sCase| expr of
+
+    -- Substitute for vars if name matches
+    Var x | x .== nm -> sCon v
+          | True     -> sVar x
+
+    -- pass thru
+    Con c   -> sCon c
+    Sqr a   -> sSqr (subst nm v a)
+    Inc a   -> sInc (subst nm v a)
+    Add a b -> sAdd (subst nm v a) (subst nm v b)
+    Mul a b -> sMul (subst nm v a) (subst nm v b)
+
+    -- substitute in the definition, but only substitute in the body if the name is not shadowing
+    Let x a b | x .== nm -> sLet x (subst nm v a) b
+              | True     -> sLet x (subst nm v a) (subst nm v b)
+  |]
+
+-- * Constant folding
+
+-- | Constant fold an expression bottom-up: first fold sub-expressions, then simplify.
+cfold :: SE -> SE
+cfold = smtFunction "cfold" $ \expr ->
+  [sCase| expr of
+    Var nm     -> sVar nm
+    Con v      -> sCon v
+    Sqr a      -> simplify (sSqr (cfold a))
+    Inc a      -> simplify (sInc (cfold a))
+    Add a b    -> simplify (sAdd (cfold a) (cfold b))
+    Mul a b    -> simplify (sMul (cfold a) (cfold b))
+    Let nm a b -> simplify (sLet nm (cfold a) (cfold b))
+  |]
+
+-- * Correctness
+
+-- | The size measure is always non-negative.
+--
+-- >>> runTP measureNonNeg
+-- Lemma: measureNonNeg    Q.E.D.
+-- Functions proven terminating: exprSize
+-- [Proven] measureNonNeg :: Ɐe ∷ (Expr String Integer) → Bool
+measureNonNeg :: TP (Proof (Forall "e" Exp -> SBool))
+measureNonNeg = inductiveLemma "measureNonNeg"
+                               (\(Forall @"e" (e :: SE)) -> size e .>= 0)
+                               []
+
+-- | Congruence for squaring: if @a == b@ then @a*a == b*b@.
+--
+-- >>> runTP sqrCong
+-- Lemma: sqrCong      Q.E.D.
+-- [Proven] sqrCong :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+sqrCong :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+sqrCong = lemma "sqrCong"
+                (\(Forall @"a" (a :: SInteger)) (Forall @"b" b) ->
+                      a .== b .=> a * a .== b * b) []
+
+-- | Congruence for addition on the left: if @a == b@ then @a+c == b+c@.
+--
+-- >>> runTP addCongL
+-- Lemma: addCongL     Q.E.D.
+-- [Proven] addCongL :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐc ∷ Integer → Bool
+addCongL :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "c" Integer -> SBool))
+addCongL = lemma "addCongL"
+                 (\(Forall @"a" (a :: SInteger)) (Forall @"b" b) (Forall @"c" c) ->
+                       a .== b .=> a + c .== b + c) []
+
+-- | Congruence for addition on the right: if @b == c@ then @a+b == a+c@.
+--
+-- >>> runTP addCongR
+-- Lemma: addCongR     Q.E.D.
+-- [Proven] addCongR :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐc ∷ Integer → Bool
+addCongR :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "c" Integer -> SBool))
+addCongR = lemma "addCongR"
+                 (\(Forall @"a" (a :: SInteger)) (Forall @"b" b) (Forall @"c" c) ->
+                       b .== c .=> a + b .== a + c) []
+
+-- | Congruence for multiplication on the left: if @a == b@ then @a*c == b*c@.
+--
+-- >>> runTP mulCongL
+-- Lemma: mulCongL     Q.E.D.
+-- [Proven] mulCongL :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐc ∷ Integer → Bool
+mulCongL :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "c" Integer -> SBool))
+mulCongL = lemma "mulCongL"
+                 (\(Forall @"a" (a :: SInteger)) (Forall @"b" b) (Forall @"c" c) ->
+                       a .== b .=> a * c .== b * c) []
+
+-- | Congruence for multiplication on the right: if @b == c@ then @a*b == a*c@.
+--
+-- >>> runTP mulCongR
+-- Lemma: mulCongR     Q.E.D.
+-- [Proven] mulCongR :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐc ∷ Integer → Bool
+mulCongR :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "c" Integer -> SBool))
+mulCongR = lemma "mulCongR"
+                 (\(Forall @"a" (a :: SInteger)) (Forall @"b" b) (Forall @"c" c) ->
+                       b .== c .=> a * b .== a * c) []
+
+-- | Unfolding @interpInEnv@ over @Sqr@.
+--
+-- >>> runTP sqrHelper
+-- Lemma: sqrHelper    Q.E.D.
+-- Functions proven terminating: interpInEnv, sbv.lookup
+-- [Proven] sqrHelper :: Ɐenv ∷ [(String, Integer)] → Ɐa ∷ (Expr String Integer) → Bool
+sqrHelper :: TP (Proof (Forall "env" EL -> Forall "a" Exp -> SBool))
+sqrHelper = lemma "sqrHelper"
+                  (\(Forall @"env" (env :: E)) (Forall @"a" a) ->
+                        interpInEnv env (sSqr a) .== interpInEnv env a * interpInEnv env a) []
+
+-- | Unfolding @interpInEnv@ over @Add@.
+--
+-- >>> runTP addHelper
+-- Lemma: addHelper    Q.E.D.
+-- Functions proven terminating: interpInEnv, sbv.lookup
+-- [Proven] addHelper :: Ɐenv ∷ [(String, Integer)] → Ɐa ∷ (Expr String Integer) → Ɐb ∷ (Expr String Integer) → Bool
+addHelper :: TP (Proof (Forall "env" EL -> Forall "a" Exp -> Forall "b" Exp -> SBool))
+addHelper = lemma "addHelper"
+                  (\(Forall @"env" (env :: E)) (Forall @"a" a) (Forall @"b" b) ->
+                        interpInEnv env (sAdd a b) .== interpInEnv env a + interpInEnv env b) []
+
+-- | Unfolding @interpInEnv@ over @Mul@.
+--
+-- >>> runTP mulHelper
+-- Lemma: mulHelper    Q.E.D.
+-- Functions proven terminating: interpInEnv, sbv.lookup
+-- [Proven] mulHelper :: Ɐenv ∷ [(String, Integer)] → Ɐa ∷ (Expr String Integer) → Ɐb ∷ (Expr String Integer) → Bool
+mulHelper :: TP (Proof (Forall "env" EL -> Forall "a" Exp -> Forall "b" Exp -> SBool))
+mulHelper = lemma "mulHelper"
+                  (\(Forall @"env" (env :: E)) (Forall @"a" a) (Forall @"b" b) ->
+                        interpInEnv env (sMul a b) .== interpInEnv env a * interpInEnv env b) []
+
+-- | Unfolding @interpInEnv@ over @Let@.
+--
+-- >>> runTP letHelper
+-- Lemma: letHelper    Q.E.D.
+-- Functions proven terminating: interpInEnv, sbv.lookup
+-- [Proven] letHelper :: Ɐenv ∷ [(String, Integer)] → Ɐnm ∷ String → Ɐa ∷ (Expr String Integer) → Ɐb ∷ (Expr String Integer) → Bool
+letHelper :: TP (Proof (Forall "env" EL -> Forall "nm" String -> Forall "a" Exp -> Forall "b" Exp -> SBool))
+letHelper = lemma "letHelper"
+                  (\(Forall @"env" (env :: E)) (Forall @"nm" nm) (Forall @"a" a) (Forall @"b" b) ->
+                        interpInEnv env (sLet nm a b) .== interpInEnv (ST.tuple (nm, interpInEnv env a) .: env) b) []
+
+-- * Environment lemmas
+
+-- | Swapping two adjacent bindings with distinct keys does not affect lookup.
+--
+-- >>> runTP lookupSwap
+-- Lemma: lookupSwap
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven terminating: sbv.lookup
+-- [Proven] lookupSwap :: Ɐk ∷ String → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+lookupSwap :: TP (Proof (Forall "k" String -> Forall "b1" (String, Integer)
+                      -> Forall "b2" (String, Integer) -> Forall "env" EL -> SBool))
+lookupSwap = calc "lookupSwap"
+                  (\(Forall @"k" (k :: SString)) (Forall @"b1" (b1 :: STuple String Integer))
+                    (Forall @"b2" (b2 :: STuple String Integer)) (Forall @"env" (env :: E)) ->
+                      let (x, _) = ST.untuple b1
+                          (y, _) = ST.untuple b2
+                      in  x ./= y .=> SL.lookup k (b1 .: b2 .: env) .== SL.lookup k (b2 .: b1 .: env)) $
+                  \k b1 b2 env ->
+                      let (x, _) = ST.untuple b1
+                          (y, _) = ST.untuple b2
+                      in [x ./= y]
+                      |- cases [ k .== x
+                                 ==> SL.lookup k (b1 .: b2 .: env)
+                                  =: SL.lookup k (b2 .: b1 .: env)
+                                  =: qed
+                               , k ./= x
+                                 ==> SL.lookup k (b1 .: b2 .: env)
+                                  =: SL.lookup k (b2 .: env)
+                                  =: SL.lookup k (b2 .: b1 .: env)
+                                  =: qed
+                               ]
+
+-- | One-step unfolding of 'SL.lookup' on a cons cell. The solver can expand the
+-- @define-fun-rec@ but struggles to fold it back, so we provide this as a reusable hint.
+--
+-- >>> runTP lookupCons
+-- Lemma: lookupCons    Q.E.D.
+-- Functions proven terminating: sbv.lookup
+-- [Proven] lookupCons :: Ɐk ∷ String → Ɐb ∷ (String, Integer) → Ɐrest ∷ [(String, Integer)] → Bool
+lookupCons :: TP (Proof (Forall "k" String -> Forall "b" (String, Integer) -> Forall "rest" EL -> SBool))
+lookupCons = lemma "lookupCons"
+   (\(Forall @"k" (k :: SString)) (Forall @"b" (b :: STuple String Integer)) (Forall @"rest" (rest :: E)) ->
+      let (bk, bv) = ST.untuple b
+      in SL.lookup k (b .: rest) .== ite (k .== bk) bv (SL.lookup k rest))
+   []
+
+-- | Generalized swap: swapping two adjacent distinct-keyed bindings behind
+-- a prefix does not affect lookup.
+--
+-- >>> runTP lookupSwapPfx
+-- Lemma: lookupSwap                          Q.E.D.
+-- Lemma: lookupCons                          Q.E.D.
+-- Inductive lemma (strong): lookupSwapPfx
+--   Step: Measure is non-negative            Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1 (base)                       Q.E.D.
+--     Step: 1.2.1 (cons)                     Q.E.D.
+--     Step: 1.2.2                            Q.E.D.
+--     Step: 1.2.3                            Q.E.D.
+--     Step: 1.2.4                            Q.E.D.
+--     Step: 1.2.5                            Q.E.D.
+--     Step: 1.Completeness                   Q.E.D.
+--   Result:                                  Q.E.D.
+-- Functions proven terminating: sbv.lookup
+-- [Proven] lookupSwapPfx :: Ɐpfx ∷ [(String, Integer)] → Ɐk ∷ String → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+lookupSwapPfx :: TP (Proof (Forall "pfx" EL -> Forall "k" String -> Forall "b1" (String, Integer)
+                         -> Forall "b2" (String, Integer) -> Forall "env" EL -> SBool))
+lookupSwapPfx = do
+   lkS <- recall lookupSwap
+   lkC <- recall lookupCons
+
+   sInduct "lookupSwapPfx"
+     (\(Forall @"pfx" (pfx :: E)) (Forall @"k" (k :: SString)) (Forall @"b1" (b1 :: STuple String Integer))
+       (Forall @"b2" (b2 :: STuple String Integer)) (Forall @"env" (env :: E)) ->
+         let (x, _) = ST.untuple b1
+             (y, _) = ST.untuple b2
+         in  x ./= y .=>    SL.lookup k (pfx ++ b1 .: b2 .: env)
+                         .== SL.lookup k (pfx ++ b2 .: b1 .: env))
+     (\pfx _ _ _ _ -> SL.length pfx :: SInteger, []) $
+     \ih pfx k b1 b2 env ->
+       let (x, _) = ST.untuple b1
+           (y, _) = ST.untuple b2
+       in [x ./= y]
+       |- cases [ SL.null pfx
+                  ==> SL.lookup k (pfx ++ b1 .: b2 .: env)
+                   ?? "base"
+                   ?? lkS `at` (Inst @"k" k, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                   =: SL.lookup k (pfx ++ b2 .: b1 .: env)
+                   =: qed
+                , sNot (SL.null pfx)
+                  ==> let h      = SL.head pfx
+                          t      = SL.tail pfx
+                          (hk, hv) = ST.untuple h
+                       in SL.lookup k (pfx ++ b1 .: b2 .: env)
+                       ?? "cons"
+                       ?? pfx .== h .: t
+                       =: SL.lookup k (h .: (t ++ b1 .: b2 .: env))
+                       =: ite (k .== hk) hv (SL.lookup k (t ++ b1 .: b2 .: env))
+                       ?? ih `at` (Inst @"pfx" t, Inst @"k" k, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                       =: ite (k .== hk) hv (SL.lookup k (t ++ b2 .: b1 .: env))
+                       ?? lkC `at` (Inst @"k" k, Inst @"b" h, Inst @"rest" (t ++ b2 .: b1 .: env))
+                       =: SL.lookup k (h .: (t ++ b2 .: b1 .: env))
+                       =: SL.lookup k (pfx ++ b2 .: b1 .: env)
+                       =: qed
+                ]
+
+-- | A shadowed binding does not affect lookup: if the same key appears first, the second is irrelevant.
+--
+-- >>> runTP lookupShadow
+-- Lemma: lookupShadow    Q.E.D.
+-- Functions proven terminating: sbv.lookup
+-- [Proven] lookupShadow :: Ɐk ∷ String → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+lookupShadow :: TP (Proof (Forall "k" String -> Forall "b1" (String, Integer)
+                        -> Forall "b2" (String, Integer) -> Forall "env" EL -> SBool))
+lookupShadow = lemma "lookupShadow"
+                     (\(Forall @"k" (k :: SString)) (Forall @"b1" (b1 :: STuple String Integer))
+                       (Forall @"b2" (b2 :: STuple String Integer)) (Forall @"env" (env :: E)) ->
+                         let (x, _) = ST.untuple b1
+                             (y, _) = ST.untuple b2
+                         in  x .== y .=>    SL.lookup k (b1 .: b2 .: env)
+                                        .== SL.lookup k (b1 .: env))
+                     []
+
+-- | Generalized shadow: a shadowed binding behind a prefix does not affect lookup.
+--
+-- >>> runTP lookupShadowPfx
+-- Lemma: lookupShadow                          Q.E.D.
+-- Lemma: lookupCons                            Q.E.D.
+-- Inductive lemma (strong): lookupShadowPfx
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1 (base)                         Q.E.D.
+--     Step: 1.2.1 (cons)                       Q.E.D.
+--     Step: 1.2.2                              Q.E.D.
+--     Step: 1.2.3                              Q.E.D.
+--     Step: 1.2.4                              Q.E.D.
+--     Step: 1.2.5                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: sbv.lookup
+-- [Proven] lookupShadowPfx :: Ɐpfx ∷ [(String, Integer)] → Ɐk ∷ String → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+lookupShadowPfx :: TP (Proof (Forall "pfx" EL -> Forall "k" String -> Forall "b1" (String, Integer)
+                           -> Forall "b2" (String, Integer) -> Forall "env" EL -> SBool))
+lookupShadowPfx = do
+   lkSh <- recall lookupShadow
+   lkC  <- recall lookupCons
+   sInduct "lookupShadowPfx"
+     (\(Forall @"pfx" (pfx :: E)) (Forall @"k" (k :: SString)) (Forall @"b1" (b1 :: STuple String Integer))
+       (Forall @"b2" (b2 :: STuple String Integer)) (Forall @"env" (env :: E)) ->
+         let (x, _) = ST.untuple b1
+             (y, _) = ST.untuple b2
+         in  x .== y .=>    SL.lookup k (pfx ++ b1 .: b2 .: env)
+                         .== SL.lookup k (pfx ++ b1 .: env))
+     (\pfx _ _ _ _ -> SL.length pfx :: SInteger, []) $
+     \ih pfx k b1 b2 env ->
+       let (x, _) = ST.untuple b1
+           (y, _) = ST.untuple b2
+       in [x .== y]
+       |- cases [ SL.null pfx
+                  ==> SL.lookup k (pfx ++ b1 .: b2 .: env)
+                   ?? "base"
+                   ?? lkSh `at` (Inst @"k" k, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                   =: SL.lookup k (pfx ++ b1 .: env)
+                   =: qed
+                , sNot (SL.null pfx)
+                  ==> let h  = SL.head pfx
+                          t  = SL.tail pfx
+                          (hk, hv) = ST.untuple h
+                       in SL.lookup k (pfx ++ b1 .: b2 .: env)
+                       ?? "cons"
+                       ?? pfx .== h .: t
+                       =: SL.lookup k (h .: (t ++ b1 .: b2 .: env))
+                       =: ite (k .== hk) hv (SL.lookup k (t ++ b1 .: b2 .: env))
+                       ?? ih `at` (Inst @"pfx" t, Inst @"k" k, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                       =: ite (k .== hk) hv (SL.lookup k (t ++ b1 .: env))
+                       ?? lkC `at` (Inst @"k" k, Inst @"b" h, Inst @"rest" (t ++ b1 .: env))
+                       =: SL.lookup k (h .: (t ++ b1 .: env))
+                       =: SL.lookup k (pfx ++ b1 .: env)
+                       =: qed
+                ]
+
+-- | Swapping two adjacent distinct-keyed bindings in the environment
+-- does not affect interpretation. The @pfx@ parameter allows the swap
+-- to happen at any depth in the environment.
+--
+-- >>> runTPWith cvc5 envSwap
+-- Lemma: measureNonNeg                       Q.E.D.
+-- Lemma: lookupSwapPfx                       Q.E.D.
+-- Lemma: sqrCong                             Q.E.D.
+-- Lemma: sqrHelper                           Q.E.D.
+-- Lemma: addCongL                            Q.E.D.
+-- Lemma: addCongR                            Q.E.D.
+-- Lemma: addHelper                           Q.E.D.
+-- Lemma: mulCongL                            Q.E.D.
+-- Lemma: mulCongR                            Q.E.D.
+-- Lemma: mulHelper                           Q.E.D.
+-- Lemma: letHelper                           Q.E.D.
+-- Inductive lemma (strong): envSwap
+--   Step: Measure is non-negative            Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1 (Var)                        Q.E.D.
+--     Step: 1.2 (Con)                        Q.E.D.
+--     Step: 1.3.1 (Sqr)                      Q.E.D.
+--     Step: 1.3.2                            Q.E.D.
+--     Step: 1.3.3                            Q.E.D.
+--     Step: 1.4 (Inc)                        Q.E.D.
+--     Step: 1.5.1 (Add)                      Q.E.D.
+--     Step: 1.5.2                            Q.E.D.
+--     Step: 1.5.3                            Q.E.D.
+--     Step: 1.5.4                            Q.E.D.
+--     Step: 1.6.1 (Mul)                      Q.E.D.
+--     Step: 1.6.2                            Q.E.D.
+--     Step: 1.6.3                            Q.E.D.
+--     Step: 1.6.4                            Q.E.D.
+--     Step: 1.7.1 (Let)                      Q.E.D.
+--     Step: 1.7.2                            Q.E.D.
+--     Step: 1.7.3                            Q.E.D.
+--     Step: 1.7.4                            Q.E.D.
+--     Step: 1.Completeness                   Q.E.D.
+--   Result:                                  Q.E.D.
+-- Functions proven terminating: exprSize, interpInEnv, sbv.lookup
+-- [Proven] envSwap :: Ɐe ∷ (Expr String Integer) → Ɐpfx ∷ [(String, Integer)] → Ɐenv ∷ [(String, Integer)] → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Bool
+envSwap :: TP (Proof (Forall "e" Exp -> Forall "pfx" EL -> Forall "env" EL
+                   -> Forall "b1" (String, Integer) -> Forall "b2" (String, Integer) -> SBool))
+envSwap = do
+   mnn   <- recall measureNonNeg
+   lkSP  <- recall lookupSwapPfx
+   sqrC  <- recall sqrCong
+   sqrH  <- recall sqrHelper
+   addCL <- recall addCongL
+   addCR <- recall addCongR
+   addH  <- recall addHelper
+   mulCL <- recall mulCongL
+   mulCR <- recall mulCongR
+   mulH  <- recall mulHelper
+   letH  <- recall letHelper
+
+   sInduct "envSwap"
+     (\(Forall @"e" (e :: SE)) (Forall @"pfx" (pfx :: E)) (Forall @"env" (env :: E))
+       (Forall @"b1" (b1 :: STuple String Integer)) (Forall @"b2" (b2 :: STuple String Integer)) ->
+       let (x, _)  = ST.untuple b1
+           (y, _)  = ST.untuple b2
+       in x ./= y .=> interpInEnv (pfx ++ b1 .: b2 .: env) e .== interpInEnv (pfx ++ b2 .: b1 .: env) e)
+     (\e _ _ _ _ -> size e :: SInteger, [proofOf mnn]) $
+     \ih e pfx env b1 b2 ->
+       let (x, _) = ST.untuple b1
+           (y, _) = ST.untuple b2
+           env1 = pfx ++ b1 .: b2 .: env
+           env2 = pfx ++ b2 .: b1 .: env
+       in [x ./= y]
+       |- cases [ isVar e
+                  ==> let nm = svar e
+                    in interpInEnv env1 (sVar nm)
+                    ?? "Var"
+                    ?? lkSP `at` (Inst @"pfx" pfx, Inst @"k" nm, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                    =: interpInEnv env2 (sVar nm)
+                    =: qed
+
+                , isCon e
+                  ==> let v = scon e
+                    in interpInEnv env1 (sCon v)
+                    ?? "Con"
+                    =: interpInEnv env2 (sCon v)
+                    =: qed
+
+                , isSqr e
+                  ==> let a = ssqrVal e
+                    in interpInEnv env1 (sSqr a)
+                    ?? "Sqr"
+                    ?? sqrH `at` (Inst @"env" env1, Inst @"a" a)
+                    =: interpInEnv env1 a * interpInEnv env1 a
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? sqrC `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a))
+                    =: interpInEnv env2 a * interpInEnv env2 a
+                    ?? sqrH `at` (Inst @"env" env2, Inst @"a" a)
+                    =: interpInEnv env2 (sSqr a)
+                    =: qed
+
+                , isInc e
+                  ==> let a = sincVal e
+                    in interpInEnv env1 (sInc a)
+                    ?? "Inc"
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv env2 (sInc a)
+                    =: qed
+
+                , isAdd e
+                  ==> let a = sadd1 e
+                          b = sadd2 e
+                    in interpInEnv env1 (sAdd a b)
+                    ?? "Add"
+                    ?? addH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a + interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? addCL `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a), Inst @"c" (interpInEnv env1 b))
+                    =: interpInEnv env2 a + interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? addCR `at` (Inst @"a" (interpInEnv env2 a), Inst @"b" (interpInEnv env1 b), Inst @"c" (interpInEnv env2 b))
+                    =: interpInEnv env2 a + interpInEnv env2 b
+                    ?? addH `at` (Inst @"env" env2, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sAdd a b)
+                    =: qed
+
+                , isMul e
+                  ==> let a = smul1 e
+                          b = smul2 e
+                    in interpInEnv env1 (sMul a b)
+                    ?? "Mul"
+                    ?? mulH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? mulCL `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a), Inst @"c" (interpInEnv env1 b))
+                    =: interpInEnv env2 a * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? mulCR `at` (Inst @"a" (interpInEnv env2 a), Inst @"b" (interpInEnv env1 b), Inst @"c" (interpInEnv env2 b))
+                    =: interpInEnv env2 a * interpInEnv env2 b
+                    ?? mulH `at` (Inst @"env" env2, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sMul a b)
+                    =: qed
+
+                , isLet e
+                  ==> let nm = slvar  e
+                          a  = slval  e
+                          b  = slbody e
+                          val1 = interpInEnv env1 a
+                          val2 = interpInEnv env2 a
+                    in interpInEnv env1 (sLet nm a b)
+                    ?? "Let"
+                    ?? letH `at` (Inst @"env" env1, Inst @"nm" nm, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv (ST.tuple (nm, val1) .: env1) b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv (ST.tuple (nm, val2) .: env1) b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" (ST.tuple (nm, val2) .: pfx), Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv (ST.tuple (nm, val2) .: env2) b
+                    ?? letH `at` (Inst @"env" env2, Inst @"nm" nm, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sLet nm a b)
+                    =: qed
+                ]
+
+-- | A shadowed binding in the environment does not affect interpretation.
+-- The @pfx@ parameter allows the shadow to occur at any depth.
+--
+-- >>> runTPWith cvc5 envShadow
+-- Lemma: measureNonNeg                         Q.E.D.
+-- Lemma: lookupShadowPfx                       Q.E.D.
+-- Lemma: sqrCong                               Q.E.D.
+-- Lemma: sqrHelper                             Q.E.D.
+-- Lemma: addCongL                              Q.E.D.
+-- Lemma: addCongR                              Q.E.D.
+-- Lemma: addHelper                             Q.E.D.
+-- Lemma: mulCongL                              Q.E.D.
+-- Lemma: mulCongR                              Q.E.D.
+-- Lemma: mulHelper                             Q.E.D.
+-- Lemma: letHelper                             Q.E.D.
+-- Inductive lemma (strong): envShadow
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1 (Var)                          Q.E.D.
+--     Step: 1.2 (Con)                          Q.E.D.
+--     Step: 1.3.1 (Sqr)                        Q.E.D.
+--     Step: 1.3.2                              Q.E.D.
+--     Step: 1.3.3                              Q.E.D.
+--     Step: 1.4 (Inc)                          Q.E.D.
+--     Step: 1.5.1 (Add)                        Q.E.D.
+--     Step: 1.5.2                              Q.E.D.
+--     Step: 1.5.3                              Q.E.D.
+--     Step: 1.5.4                              Q.E.D.
+--     Step: 1.6.1 (Mul)                        Q.E.D.
+--     Step: 1.6.2                              Q.E.D.
+--     Step: 1.6.3                              Q.E.D.
+--     Step: 1.6.4                              Q.E.D.
+--     Step: 1.7.1 (Let)                        Q.E.D.
+--     Step: 1.7.2                              Q.E.D.
+--     Step: 1.7.3                              Q.E.D.
+--     Step: 1.7.4                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: exprSize, interpInEnv, sbv.lookup
+-- [Proven] envShadow :: Ɐe ∷ (Expr String Integer) → Ɐpfx ∷ [(String, Integer)] → Ɐenv ∷ [(String, Integer)] → Ɐb1 ∷ (String, Integer) → Ɐb2 ∷ (String, Integer) → Bool
+envShadow :: TP (Proof (Forall "e" Exp -> Forall "pfx" EL -> Forall "env" EL
+                     -> Forall "b1" (String, Integer) -> Forall "b2" (String, Integer) -> SBool))
+envShadow = do
+   mnn   <- recall measureNonNeg
+   lkShP <- recall lookupShadowPfx
+   sqrC  <- recall sqrCong
+   sqrH  <- recall sqrHelper
+   addCL <- recall addCongL
+   addCR <- recall addCongR
+   addH  <- recall addHelper
+   mulCL <- recall mulCongL
+   mulCR <- recall mulCongR
+   mulH  <- recall mulHelper
+   letH  <- recall letHelper
+
+   sInduct "envShadow"
+     (\(Forall @"e" (e :: SE)) (Forall @"pfx" (pfx :: E)) (Forall @"env" (env :: E))
+       (Forall @"b1" (b1 :: STuple String Integer)) (Forall @"b2" (b2 :: STuple String Integer)) ->
+       let (x, _)  = ST.untuple b1
+           (y, _)  = ST.untuple b2
+       in x .== y .=> interpInEnv (pfx ++ b1 .: b2 .: env) e .== interpInEnv (pfx ++ b1 .: env) e)
+     (\e _ _ _ _ -> size e :: SInteger, [proofOf mnn]) $
+     \ih e pfx env b1 b2 ->
+       let (x, _) = ST.untuple b1
+           (y, _) = ST.untuple b2
+           env1 = pfx ++ b1 .: b2 .: env
+           env2 = pfx ++ b1 .: env
+       in [x .== y]
+       |- cases [ isVar e
+                  ==> let nm = svar e
+                    in interpInEnv env1 (sVar nm)
+                    ?? "Var"
+                    ?? lkShP `at` (Inst @"pfx" pfx, Inst @"k" nm, Inst @"b1" b1, Inst @"b2" b2, Inst @"env" env)
+                    =: interpInEnv env2 (sVar nm)
+                    =: qed
+
+                , isCon e
+                  ==> let v = scon e
+                    in interpInEnv env1 (sCon v)
+                    ?? "Con"
+                    =: interpInEnv env2 (sCon v)
+                    =: qed
+
+                , isSqr e
+                  ==> let a = ssqrVal e
+                    in interpInEnv env1 (sSqr a)
+                    ?? "Sqr"
+                    ?? sqrH `at` (Inst @"env" env1, Inst @"a" a)
+                    =: interpInEnv env1 a * interpInEnv env1 a
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? sqrC `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a))
+                    =: interpInEnv env2 a * interpInEnv env2 a
+                    ?? sqrH `at` (Inst @"env" env2, Inst @"a" a)
+                    =: interpInEnv env2 (sSqr a)
+                    =: qed
+
+                , isInc e
+                  ==> let a = sincVal e
+                    in interpInEnv env1 (sInc a)
+                    ?? "Inc"
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv env2 (sInc a)
+                    =: qed
+
+                , isAdd e
+                  ==> let a = sadd1 e
+                          b = sadd2 e
+                    in interpInEnv env1 (sAdd a b)
+                    ?? "Add"
+                    ?? addH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a + interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? addCL `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a), Inst @"c" (interpInEnv env1 b))
+                    =: interpInEnv env2 a + interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? addCR `at` (Inst @"a" (interpInEnv env2 a), Inst @"b" (interpInEnv env1 b), Inst @"c" (interpInEnv env2 b))
+                    =: interpInEnv env2 a + interpInEnv env2 b
+                    ?? addH `at` (Inst @"env" env2, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sAdd a b)
+                    =: qed
+
+                , isMul e
+                  ==> let a = smul1 e
+                          b = smul2 e
+                    in interpInEnv env1 (sMul a b)
+                    ?? "Mul"
+                    ?? mulH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? mulCL `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env2 a), Inst @"c" (interpInEnv env1 b))
+                    =: interpInEnv env2 a * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    ?? mulCR `at` (Inst @"a" (interpInEnv env2 a), Inst @"b" (interpInEnv env1 b), Inst @"c" (interpInEnv env2 b))
+                    =: interpInEnv env2 a * interpInEnv env2 b
+                    ?? mulH `at` (Inst @"env" env2, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sMul a b)
+                    =: qed
+
+                , isLet e
+                  ==> let nm = slvar  e
+                          a  = slval  e
+                          b  = slbody e
+                          val1 = interpInEnv env1 a
+                          val2 = interpInEnv env2 a
+                    in interpInEnv env1 (sLet nm a b)
+                    ?? "Let"
+                    ?? letH `at` (Inst @"env" env1, Inst @"nm" nm, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv (ST.tuple (nm, val1) .: env1) b
+                    ?? ih `at` (Inst @"e" a, Inst @"pfx" pfx, Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv (ST.tuple (nm, val2) .: env1) b
+                    ?? ih `at` (Inst @"e" b, Inst @"pfx" (ST.tuple (nm, val2) .: pfx), Inst @"env" env, Inst @"b1" b1, Inst @"b2" b2)
+                    =: interpInEnv (ST.tuple (nm, val2) .: env2) b
+                    ?? letH `at` (Inst @"env" env2, Inst @"nm" nm, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env2 (sLet nm a b)
+                    =: qed
+                ]
+
+-- * Substitution correctness
+
+-- | Unfolding @interpInEnv@ over @Var@.
+--
+-- >>> runTP varHelper
+-- Lemma: varHelper    Q.E.D.
+-- Functions proven terminating: interpInEnv, sbv.lookup
+-- [Proven] varHelper :: Ɐenv ∷ [(String, Integer)] → Ɐnm ∷ String → Bool
+varHelper :: TP (Proof (Forall "env" EL -> Forall "nm" String -> SBool))
+varHelper = lemma "varHelper"
+                  (\(Forall @"env" (env :: E)) (Forall @"nm" nm) ->
+                        interpInEnv env (sVar nm) .== SL.lookup nm env) []
+
+-- | Substitution preserves semantics: interpreting in an extended environment
+-- is the same as substituting and interpreting in the original environment.
+--
+-- >>> runTPWith cvc5 substCorrect
+-- Lemma: measureNonNeg                         Q.E.D.
+-- Lemma: sqrCong                               Q.E.D.
+-- Lemma: sqrHelper                             Q.E.D.
+-- Lemma: addHelper                             Q.E.D.
+-- Lemma: mulCongL                              Q.E.D.
+-- Lemma: mulCongR                              Q.E.D.
+-- Lemma: mulHelper                             Q.E.D.
+-- Lemma: letHelper                             Q.E.D.
+-- Lemma: varHelper                             Q.E.D.
+-- Lemma: envSwap                               Q.E.D.
+-- Lemma: envShadow                             Q.E.D.
+-- Inductive lemma (strong): substCorrect
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1 (2 way case split)
+--       Step: 1.1.1.1 (Var)                    Q.E.D.
+--       Step: 1.1.1.2                          Q.E.D.
+--       Step: 1.1.1.3                          Q.E.D.
+--       Step: 1.1.1.4                          Q.E.D.
+--       Step: 1.1.1.5                          Q.E.D.
+--       Step: 1.1.2.1 (Var)                    Q.E.D.
+--       Step: 1.1.2.2                          Q.E.D.
+--       Step: 1.1.2.3                          Q.E.D.
+--       Step: 1.1.2.4                          Q.E.D.
+--       Step: 1.1.2.5                          Q.E.D.
+--       Step: 1.1.Completeness                 Q.E.D.
+--     Step: 1.2 (Con)                          Q.E.D.
+--     Step: 1.3.1 (Sqr)                        Q.E.D.
+--     Step: 1.3.2                              Q.E.D.
+--     Step: 1.3.3                              Q.E.D.
+--     Step: 1.3.4                              Q.E.D.
+--     Step: 1.4 (Inc)                          Q.E.D.
+--     Step: 1.5.1 (Add)                        Q.E.D.
+--     Step: 1.5.2                              Q.E.D.
+--     Step: 1.5.3                              Q.E.D.
+--     Step: 1.5.4                              Q.E.D.
+--     Step: 1.6.1 (Mul)                        Q.E.D.
+--     Step: 1.6.2                              Q.E.D.
+--     Step: 1.6.3                              Q.E.D.
+--     Step: 1.6.4                              Q.E.D.
+--     Step: 1.6.5                              Q.E.D.
+--     Step: 1.7.1 (Let)                        Q.E.D.
+--     Step: 1.7.2 (2 way case split)
+--       Step: 1.7.2.1.1                        Q.E.D.
+--       Step: 1.7.2.1.2 (shadow)               Q.E.D.
+--       Step: 1.7.2.1.3                        Q.E.D.
+--       Step: 1.7.2.1.4                        Q.E.D.
+--       Step: 1.7.2.1.5                        Q.E.D.
+--       Step: 1.7.2.2.1                        Q.E.D.
+--       Step: 1.7.2.2.2 (swap)                 Q.E.D.
+--       Step: 1.7.2.2.3                        Q.E.D.
+--       Step: 1.7.2.2.4                        Q.E.D.
+--       Step: 1.7.2.2.5                        Q.E.D.
+--       Step: 1.7.2.2.6                        Q.E.D.
+--       Step: 1.7.2.Completeness               Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: exprSize, interpInEnv, sbv.lookup, subst
+-- [Proven] substCorrect :: Ɐe ∷ (Expr String Integer) → Ɐnm ∷ String → Ɐv ∷ Integer → Ɐenv ∷ [(String, Integer)] → Bool
+substCorrect :: TP (Proof (Forall "e" Exp -> Forall "nm" String -> Forall "v" Integer -> Forall "env" EL -> SBool))
+substCorrect = do
+   mnn   <- recall measureNonNeg
+   sqrC  <- recall sqrCong
+   sqrH  <- recall sqrHelper
+   addH  <- recall addHelper
+   mulCL <- recall mulCongL
+   mulCR <- recall mulCongR
+   mulH  <- recall mulHelper
+   letH  <- recall letHelper
+   varH  <- recall varHelper
+   eSwp  <- recall envSwap
+   eShd  <- recall envShadow
+
+   sInduct "substCorrect"
+     (\(Forall @"e" (e :: SE)) (Forall @"nm" (nm :: SString)) (Forall @"v" (v :: SInteger)) (Forall @"env" (env :: E)) ->
+         interpInEnv (ST.tuple (nm, v) .: env) e .== interpInEnv env (subst nm v e))
+     (\e _ _ _ -> size e :: SInteger, [proofOf mnn]) $
+     \ih e nm v env ->
+       let nmv  = ST.tuple (nm, v)
+           env1 = nmv .: env
+       in []
+       |- cases [ isVar e
+                  ==> let x = svar e
+                    in interpInEnv env1 (sVar x)
+                    ?? "Var"
+                    =: cases [ x .== nm
+                               ==> interpInEnv env1 (sVar nm)
+                                ?? varH `at` (Inst @"env" env1, Inst @"nm" nm)
+                                =: SL.lookup nm env1
+                                =: v
+                                =: interpInEnv env (sCon v)
+                                =: interpInEnv env (subst nm v (sVar nm))
+                                =: qed
+                             , x ./= nm
+                               ==> interpInEnv env1 (sVar x)
+                                ?? varH `at` (Inst @"env" env1, Inst @"nm" x)
+                                =: SL.lookup x env1
+                                =: SL.lookup x env
+                                ?? varH `at` (Inst @"env" env, Inst @"nm" x)
+                                =: interpInEnv env (sVar x)
+                                =: interpInEnv env (subst nm v (sVar x))
+                                =: qed
+                             ]
+
+                , isCon e
+                  ==> let c = scon e
+                    in interpInEnv env1 (sCon c)
+                    ?? "Con"
+                    =: interpInEnv env (subst nm v (sCon c))
+                    =: qed
+
+                , isSqr e
+                  ==> let a = ssqrVal e
+                    in interpInEnv env1 (sSqr a)
+                    ?? "Sqr"
+                    ?? sqrH `at` (Inst @"env" env1, Inst @"a" a)
+                    =: interpInEnv env1 a * interpInEnv env1 a
+                    ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    ?? sqrC `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env (subst nm v a)))
+                    =: interpInEnv env (subst nm v a) * interpInEnv env (subst nm v a)
+                    ?? sqrH `at` (Inst @"env" env, Inst @"a" (subst nm v a))
+                    =: interpInEnv env (sSqr (subst nm v a))
+                    =: interpInEnv env (subst nm v (sSqr a))
+                    =: qed
+
+                , isInc e
+                  ==> let a = sincVal e
+                    in interpInEnv env1 (sInc a)
+                    ?? "Inc"
+                    ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    =: interpInEnv env (subst nm v (sInc a))
+                    =: qed
+
+                , isAdd e
+                  ==> let a = sadd1 e
+                          b = sadd2 e
+                    in interpInEnv env1 (sAdd a b)
+                    ?? "Add"
+                    ?? addH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a + interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    ?? ih `at` (Inst @"e" b, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    =: interpInEnv env (subst nm v a) + interpInEnv env (subst nm v b)
+                    ?? addH `at` (Inst @"env" env, Inst @"a" (subst nm v a), Inst @"b" (subst nm v b))
+                    =: interpInEnv env (sAdd (subst nm v a) (subst nm v b))
+                    =: interpInEnv env (subst nm v (sAdd a b))
+                    =: qed
+
+                , isMul e
+                  ==> let a = smul1 e
+                          b = smul2 e
+                    in interpInEnv env1 (sMul a b)
+                    ?? "Mul"
+                    ?? mulH `at` (Inst @"env" env1, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv env1 a * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    ?? mulCL `at` (Inst @"a" (interpInEnv env1 a), Inst @"b" (interpInEnv env (subst nm v a)), Inst @"c" (interpInEnv env1 b))
+                    =: interpInEnv env (subst nm v a) * interpInEnv env1 b
+                    ?? ih `at` (Inst @"e" b, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                    ?? mulCR `at` (Inst @"a" (interpInEnv env (subst nm v a)), Inst @"b" (interpInEnv env1 b), Inst @"c" (interpInEnv env (subst nm v b)))
+                    =: interpInEnv env (subst nm v a) * interpInEnv env (subst nm v b)
+                    ?? mulH `at` (Inst @"env" env, Inst @"a" (subst nm v a), Inst @"b" (subst nm v b))
+                    =: interpInEnv env (sMul (subst nm v a) (subst nm v b))
+                    =: interpInEnv env (subst nm v (sMul a b))
+                    =: qed
+
+                , isLet e
+                  ==> let x   = slvar  e
+                          a   = slval  e
+                          b   = slbody e
+                          val = interpInEnv env1 a
+                    in interpInEnv env1 (sLet x a b)
+                    ?? "Let"
+                    ?? letH `at` (Inst @"env" env1, Inst @"nm" x, Inst @"a" a, Inst @"b" b)
+                    =: interpInEnv (ST.tuple (x, val) .: env1) b
+                    =: cases [ x .== nm
+                               ==> let xv = ST.tuple (x, val)
+                                 in interpInEnv (xv .: nmv .: env) b
+                                 ?? "shadow"
+                                 ?? eShd `at` (Inst @"e" b, Inst @"pfx" (SL.nil :: E), Inst @"env" env, Inst @"b1" xv, Inst @"b2" nmv)
+                                 =: interpInEnv (xv .: env) b
+                                 ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                                 =: interpInEnv (ST.tuple (x, interpInEnv env (subst nm v a)) .: env) b
+                                 ?? letH `at` (Inst @"env" env, Inst @"nm" x, Inst @"a" (subst nm v a), Inst @"b" b)
+                                 =: interpInEnv env (sLet x (subst nm v a) b)
+                                 =: interpInEnv env (subst nm v (sLet x a b))
+                                 =: qed
+                             , x ./= nm
+                               ==> let xv = ST.tuple (x, val)
+                                 in interpInEnv (xv .: nmv .: env) b
+                                 ?? "swap"
+                                 ?? eSwp `at` (Inst @"e" b, Inst @"pfx" (SL.nil :: E), Inst @"env" env, Inst @"b1" xv, Inst @"b2" nmv)
+                                 =: interpInEnv (nmv .: xv .: env) b
+                                 ?? ih `at` (Inst @"e" b, Inst @"nm" nm, Inst @"v" v, Inst @"env" (xv .: env))
+                                 =: interpInEnv (xv .: env) (subst nm v b)
+                                 ?? ih `at` (Inst @"e" a, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                                 =: interpInEnv (ST.tuple (x, interpInEnv env (subst nm v a)) .: env) (subst nm v b)
+                                 ?? letH `at` (Inst @"env" env, Inst @"nm" x, Inst @"a" (subst nm v a), Inst @"b" (subst nm v b))
+                                 =: interpInEnv env (sLet x (subst nm v a) (subst nm v b))
+                                 =: interpInEnv env (subst nm v (sLet x a b))
+                                 =: qed
+                             ]
+                ]
+
+-- | Simplification preserves semantics.
+--
+-- >>> runTPWith cvc5 simpCorrect
+-- Lemma: sqrCong                               Q.E.D.
+-- Lemma: sqrHelper                             Q.E.D.
+-- Lemma: addHelper                             Q.E.D.
+-- Lemma: mulCongL                              Q.E.D.
+-- Lemma: mulCongR                              Q.E.D.
+-- Lemma: mulHelper                             Q.E.D.
+-- Lemma: letHelper                             Q.E.D.
+-- Lemma: substCorrect                          Q.E.D.
+-- Lemma: simpCorrect
+--   Step: 1 (7 way case split)
+--     Step: 1.1.1 (Var)                        Q.E.D.
+--     Step: 1.1.2                              Q.E.D.
+--     Step: 1.1.3                              Q.E.D.
+--     Step: 1.2.1 (Con)                        Q.E.D.
+--     Step: 1.2.2                              Q.E.D.
+--     Step: 1.2.3                              Q.E.D.
+--     Step: 1.3.1 (Sqr)                        Q.E.D.
+--     Step: 1.3.2 (2 way case split)
+--       Step: 1.3.2.1.1                        Q.E.D.
+--       Step: 1.3.2.1.2 (Sqr Con)              Q.E.D.
+--       Step: 1.3.2.1.3                        Q.E.D.
+--       Step: 1.3.2.1.4                        Q.E.D.
+--       Step: 1.3.2.1.5                        Q.E.D.
+--       Step: 1.3.2.2.1                        Q.E.D.
+--       Step: 1.3.2.2.2 (Sqr _)                Q.E.D.
+--       Step: 1.3.2.Completeness               Q.E.D.
+--     Step: 1.4.1 (Inc)                        Q.E.D.
+--     Step: 1.4.2 (2 way case split)
+--       Step: 1.4.2.1.1                        Q.E.D.
+--       Step: 1.4.2.1.2 (Inc Con)              Q.E.D.
+--       Step: 1.4.2.1.3                        Q.E.D.
+--       Step: 1.4.2.2.1                        Q.E.D.
+--       Step: 1.4.2.2.2 (Inc _)                Q.E.D.
+--       Step: 1.4.2.Completeness               Q.E.D.
+--     Step: 1.5.1 (Add)                        Q.E.D.
+--     Step: 1.5.2 (6 way case split)
+--       Step: 1.5.2.1.1                        Q.E.D.
+--       Step: 1.5.2.1.2 (Add 0+b)              Q.E.D.
+--       Step: 1.5.2.1.3                        Q.E.D.
+--       Step: 1.5.2.2.1                        Q.E.D.
+--       Step: 1.5.2.2.2 (Add a+0)              Q.E.D.
+--       Step: 1.5.2.2.3                        Q.E.D.
+--       Step: 1.5.2.3.1                        Q.E.D.
+--       Step: 1.5.2.3.2 (Add Con)              Q.E.D.
+--       Step: 1.5.2.3.3                        Q.E.D.
+--       Step: 1.5.2.4 (2 way case split)
+--         Step: 1.5.2.4.1.1                    Q.E.D.
+--         Step: 1.5.2.4.1.2 (Add 0,_)          Q.E.D.
+--         Step: 1.5.2.4.1.3                    Q.E.D.
+--         Step: 1.5.2.4.2.1                    Q.E.D.
+--         Step: 1.5.2.4.2.2 (Add C,_)          Q.E.D.
+--         Step: 1.5.2.4.Completeness           Q.E.D.
+--       Step: 1.5.2.5 (2 way case split)
+--         Step: 1.5.2.5.1.1                    Q.E.D.
+--         Step: 1.5.2.5.1.2 (Add _,0)          Q.E.D.
+--         Step: 1.5.2.5.1.3                    Q.E.D.
+--         Step: 1.5.2.5.2.1                    Q.E.D.
+--         Step: 1.5.2.5.2.2 (Add _,C)          Q.E.D.
+--         Step: 1.5.2.5.Completeness           Q.E.D.
+--       Step: 1.5.2.6.1                        Q.E.D.
+--       Step: 1.5.2.6.2 (Add _,_)              Q.E.D.
+--       Step: 1.5.2.Completeness               Q.E.D.
+--     Step: 1.6.1 (Mul)                        Q.E.D.
+--     Step: 1.6.2 (8 way case split)
+--       Step: 1.6.2.1.1                        Q.E.D.
+--       Step: 1.6.2.1.2 (Mul 0*b)              Q.E.D.
+--       Step: 1.6.2.1.3                        Q.E.D.
+--       Step: 1.6.2.2.1                        Q.E.D.
+--       Step: 1.6.2.2.2 (Mul a*0)              Q.E.D.
+--       Step: 1.6.2.2.3                        Q.E.D.
+--       Step: 1.6.2.3.1                        Q.E.D.
+--       Step: 1.6.2.3.2 (Mul 1*b)              Q.E.D.
+--       Step: 1.6.2.3.3                        Q.E.D.
+--       Step: 1.6.2.3.4                        Q.E.D.
+--       Step: 1.6.2.3.5                        Q.E.D.
+--       Step: 1.6.2.4.1                        Q.E.D.
+--       Step: 1.6.2.4.2 (Mul a*1)              Q.E.D.
+--       Step: 1.6.2.4.3                        Q.E.D.
+--       Step: 1.6.2.4.4                        Q.E.D.
+--       Step: 1.6.2.4.5                        Q.E.D.
+--       Step: 1.6.2.5.1                        Q.E.D.
+--       Step: 1.6.2.5.2 (Mul Con)              Q.E.D.
+--       Step: 1.6.2.5.3                        Q.E.D.
+--       Step: 1.6.2.5.4                        Q.E.D.
+--       Step: 1.6.2.5.5                        Q.E.D.
+--       Step: 1.6.2.5.6                        Q.E.D.
+--       Step: 1.6.2.6 (3 way case split)
+--         Step: 1.6.2.6.1.1                    Q.E.D.
+--         Step: 1.6.2.6.1.2 (Mul 0,_)          Q.E.D.
+--         Step: 1.6.2.6.1.3                    Q.E.D.
+--         Step: 1.6.2.6.2.1                    Q.E.D.
+--         Step: 1.6.2.6.2.2 (Mul 1,_)          Q.E.D.
+--         Step: 1.6.2.6.2.3                    Q.E.D.
+--         Step: 1.6.2.6.2.4                    Q.E.D.
+--         Step: 1.6.2.6.2.5                    Q.E.D.
+--         Step: 1.6.2.6.3.1                    Q.E.D.
+--         Step: 1.6.2.6.3.2 (Mul C,_)          Q.E.D.
+--         Step: 1.6.2.6.Completeness           Q.E.D.
+--       Step: 1.6.2.7 (3 way case split)
+--         Step: 1.6.2.7.1.1                    Q.E.D.
+--         Step: 1.6.2.7.1.2 (Mul _,0)          Q.E.D.
+--         Step: 1.6.2.7.1.3                    Q.E.D.
+--         Step: 1.6.2.7.2.1                    Q.E.D.
+--         Step: 1.6.2.7.2.2 (Mul _,1)          Q.E.D.
+--         Step: 1.6.2.7.2.3                    Q.E.D.
+--         Step: 1.6.2.7.2.4                    Q.E.D.
+--         Step: 1.6.2.7.2.5                    Q.E.D.
+--         Step: 1.6.2.7.3.1                    Q.E.D.
+--         Step: 1.6.2.7.3.2 (Mul _,C)          Q.E.D.
+--         Step: 1.6.2.7.Completeness           Q.E.D.
+--       Step: 1.6.2.8.1                        Q.E.D.
+--       Step: 1.6.2.8.2 (Mul _,_)              Q.E.D.
+--       Step: 1.6.2.Completeness               Q.E.D.
+--     Step: 1.7.1 (Let)                        Q.E.D.
+--     Step: 1.7.2 (2 way case split)
+--       Step: 1.7.2.1.1                        Q.E.D.
+--       Step: 1.7.2.1.2 (Let Con)              Q.E.D.
+--       Step: 1.7.2.1.3                        Q.E.D.
+--       Step: 1.7.2.1.4                        Q.E.D.
+--       Step: 1.7.2.2.1                        Q.E.D.
+--       Step: 1.7.2.2.2 (Let _)                Q.E.D.
+--       Step: 1.7.2.Completeness               Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: exprSize, interpInEnv, sbv.lookup, simplify, subst
+-- [Proven] simpCorrect :: Ɐe ∷ (Expr String Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+simpCorrect :: TP (Proof (Forall "e" Exp -> Forall "env" EL -> SBool))
+simpCorrect = do
+   sqrC  <- recall sqrCong
+   sqrH  <- recall sqrHelper
+   addH  <- recall addHelper
+   mulCL <- recall mulCongL
+   mulCR <- recall mulCongR
+   mulH  <- recall mulHelper
+   letH  <- recall letHelper
+   subC  <- recall substCorrect
+
+   calc "simpCorrect"
+     (\(Forall @"e" (e :: SE)) (Forall @"env" (env :: E)) -> interpInEnv env (simplify e) .== interpInEnv env e) $
+     \e env -> []
+     |- [pCase| e of
+          Var nm     -> interpInEnv env (simplify e)
+                     ?? "Var"
+                     =: interpInEnv env (simplify (sVar nm))
+                     =: interpInEnv env (sVar nm)
+                     =: interpInEnv env e
+                     =: qed
+
+          Con c      -> interpInEnv env (simplify e)
+                     ?? "Con"
+                     =: interpInEnv env (simplify (sCon c))
+                     =: interpInEnv env (sCon c)
+                     =: interpInEnv env e
+                     =: qed
+
+          Sqr a      -> interpInEnv env (simplify e)
+                     ?? "Sqr"
+                     =: interpInEnv env (simplify (sSqr a))
+                     =: cases [ isCon a
+                                 ==> let v = scon a
+                                   in interpInEnv env (simplify (sSqr (sCon v)))
+                                   ?? "Sqr Con"
+                                   =: interpInEnv env (sCon (v * v))
+                                   ?? interpInEnv env (sCon (v * v)) .== v * v
+                                   =: v * v
+                                   ?? sqrC `at` (Inst @"a" (interpInEnv env (sCon v)), Inst @"b" v)
+                                   =: interpInEnv env (sCon v) * interpInEnv env (sCon v)
+                                   ?? sqrH `at` (Inst @"env" env, Inst @"a" (sCon v))
+                                   =: interpInEnv env (sSqr (sCon v))
+                                   =: qed
+                               , sNot (isCon a)
+                                 ==> interpInEnv env (simplify (sSqr a))
+                                   ?? "Sqr _"
+                                   =: interpInEnv env (sSqr a)
+                                   =: qed
+                               ]
+
+          Inc a      -> interpInEnv env (simplify e)
+                     ?? "Inc"
+                     =: interpInEnv env (simplify (sInc a))
+                     =: cases [ isCon a
+                                 ==> let v = scon a
+                                   in interpInEnv env (simplify (sInc (sCon v)))
+                                   ?? "Inc Con"
+                                   =: interpInEnv env (sCon (v + 1))
+                                   =: interpInEnv env (sInc (sCon v))
+                                   =: qed
+                               , sNot (isCon a)
+                                 ==> interpInEnv env (simplify (sInc a))
+                                   ?? "Inc _"
+                                   =: interpInEnv env (sInc a)
+                                   =: qed
+                               ]
+
+          Add a b    -> interpInEnv env (simplify e)
+                     ?? "Add"
+                     =: interpInEnv env (simplify (sAdd a b))
+                     =: cases [ isCon a .&& scon a .== 0
+                                 ==> interpInEnv env (simplify (sAdd (sCon 0) b))
+                                   ?? "Add 0+b"
+                                   =: interpInEnv env b
+                                   ?? addH `at` (Inst @"env" env, Inst @"a" (sCon 0), Inst @"b" b)
+                                   =: interpInEnv env (sAdd (sCon 0) b)
+                                   =: qed
+
+                               , isCon b .&& scon b .== 0
+                                 ==> interpInEnv env (simplify (sAdd a (sCon 0)))
+                                   ?? "Add a+0"
+                                   =: interpInEnv env a
+                                   ?? addH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 0))
+                                   =: interpInEnv env (sAdd a (sCon 0))
+                                   =: qed
+
+                               , isCon a .&& isCon b
+                                 ==> let va = scon a; vb = scon b
+                                   in interpInEnv env (simplify (sAdd (sCon va) (sCon vb)))
+                                   ?? "Add Con"
+                                   =: interpInEnv env (sCon (va + vb))
+                                   ?? addH `at` (Inst @"env" env, Inst @"a" (sCon va), Inst @"b" (sCon vb))
+                                   =: interpInEnv env (sAdd (sCon va) (sCon vb))
+                                   =: qed
+
+                               , isCon a .&& sNot (isCon b)
+                                 ==> let va = scon a
+                                   in cases [ va .== 0
+                                              ==> interpInEnv env (simplify (sAdd (sCon 0) b))
+                                                ?? "Add 0,_"
+                                                =: interpInEnv env b
+                                                ?? addH `at` (Inst @"env" env, Inst @"a" (sCon 0), Inst @"b" b)
+                                                =: interpInEnv env (sAdd (sCon 0) b)
+                                                =: qed
+                                            , va ./= 0
+                                              ==> interpInEnv env (simplify (sAdd (sCon va) b))
+                                                ?? "Add C,_"
+                                                =: interpInEnv env (sAdd (sCon va) b)
+                                                =: qed
+                                            ]
+
+                               , sNot (isCon a) .&& isCon b
+                                 ==> let vb = scon b
+                                   in cases [ vb .== 0
+                                              ==> interpInEnv env (simplify (sAdd a (sCon 0)))
+                                                ?? "Add _,0"
+                                                =: interpInEnv env a
+                                                ?? addH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 0))
+                                                =: interpInEnv env (sAdd a (sCon 0))
+                                                =: qed
+                                            , vb ./= 0
+                                              ==> interpInEnv env (simplify (sAdd a (sCon vb)))
+                                                ?? "Add _,C"
+                                                =: interpInEnv env (sAdd a (sCon vb))
+                                                =: qed
+                                            ]
+
+                               , sNot (isCon a) .&& sNot (isCon b)
+                                 ==> interpInEnv env (simplify (sAdd a b))
+                                   ?? "Add _,_"
+                                   =: interpInEnv env (sAdd a b)
+                                   =: qed
+                               ]
+
+          Mul a b    -> interpInEnv env (simplify e)
+                     ?? "Mul"
+                     =: interpInEnv env (simplify (sMul a b))
+                     =: cases [ isCon a .&& scon a .== 0
+                                 ==> interpInEnv env (simplify (sMul (sCon 0) b))
+                                   ?? "Mul 0*b"
+                                   =: interpInEnv env (sCon 0)
+                                   ?? mulH `at` (Inst @"env" env, Inst @"a" (sCon 0), Inst @"b" b)
+                                   =: interpInEnv env (sMul (sCon 0) b)
+                                   =: qed
+
+                               , isCon b .&& scon b .== 0
+                                 ==> interpInEnv env (simplify (sMul a (sCon 0)))
+                                   ?? "Mul a*0"
+                                   =: interpInEnv env (sCon 0)
+                                   ?? mulH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 0))
+                                   =: interpInEnv env (sMul a (sCon 0))
+                                   =: qed
+
+                               , isCon a .&& scon a .== 1
+                                 ==> interpInEnv env (simplify (sMul (sCon 1) b))
+                                   ?? "Mul 1*b"
+                                   =: interpInEnv env b
+                                   =: 1 * interpInEnv env b
+                                   ?? interpInEnv env (sCon 1) .== 1
+                                   =: interpInEnv env (sCon 1) * interpInEnv env b
+                                   ?? mulH `at` (Inst @"env" env, Inst @"a" (sCon 1), Inst @"b" b)
+                                   =: interpInEnv env (sMul (sCon 1) b)
+                                   =: qed
+
+                               , isCon b .&& scon b .== 1
+                                 ==> interpInEnv env (simplify (sMul a (sCon 1)))
+                                   ?? "Mul a*1"
+                                   =: interpInEnv env a
+                                   =: interpInEnv env a * 1
+                                   ?? interpInEnv env (sCon 1) .== 1
+                                   =: interpInEnv env a * interpInEnv env (sCon 1)
+                                   ?? mulH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 1))
+                                   =: interpInEnv env (sMul a (sCon 1))
+                                   =: qed
+
+                               , isCon a .&& isCon b
+                                 ==> let va = scon a; vb = scon b
+                                   in interpInEnv env (simplify (sMul (sCon va) (sCon vb)))
+                                   ?? "Mul Con"
+                                   ?? simplify (sMul (sCon va) (sCon vb)) .== sCon (va * vb)
+                                   =: interpInEnv env (sCon (va * vb))
+                                   ?? interpInEnv env (sCon (va * vb)) .== va * vb
+                                   =: va * vb
+                                   ?? mulCL `at` (Inst @"a" (interpInEnv env (sCon va)), Inst @"b" va, Inst @"c" vb)
+                                   =: interpInEnv env (sCon va) * vb
+                                   ?? mulCR `at` (Inst @"a" (interpInEnv env (sCon va)), Inst @"b" (interpInEnv env (sCon vb)), Inst @"c" vb)
+                                   =: interpInEnv env (sCon va) * interpInEnv env (sCon vb)
+                                   ?? mulH `at` (Inst @"env" env, Inst @"a" (sCon va), Inst @"b" (sCon vb))
+                                   =: interpInEnv env (sMul (sCon va) (sCon vb))
+                                   =: qed
+
+                               , isCon a .&& sNot (isCon b)
+                                 ==> let va = scon a
+                                   in cases [ va .== 0
+                                              ==> interpInEnv env (simplify (sMul (sCon 0) b))
+                                                ?? "Mul 0,_"
+                                                =: interpInEnv env (sCon 0)
+                                                ?? mulH `at` (Inst @"env" env, Inst @"a" (sCon 0), Inst @"b" b)
+                                                =: interpInEnv env (sMul (sCon 0) b)
+                                                =: qed
+                                            , va .== 1
+                                              ==> interpInEnv env (simplify (sMul (sCon 1) b))
+                                                ?? "Mul 1,_"
+                                                =: interpInEnv env b
+                                                =: 1 * interpInEnv env b
+                                                ?? interpInEnv env (sCon 1) .== 1
+                                                =: interpInEnv env (sCon 1) * interpInEnv env b
+                                                ?? mulH `at` (Inst @"env" env, Inst @"a" (sCon 1), Inst @"b" b)
+                                                =: interpInEnv env (sMul (sCon 1) b)
+                                                =: qed
+                                            , va ./= 0 .&& va ./= 1
+                                              ==> interpInEnv env (simplify (sMul (sCon va) b))
+                                                ?? "Mul C,_"
+                                                =: interpInEnv env (sMul (sCon va) b)
+                                                =: qed
+                                            ]
+
+                               , sNot (isCon a) .&& isCon b
+                                 ==> let vb = scon b
+                                   in cases [ vb .== 0
+                                              ==> interpInEnv env (simplify (sMul a (sCon 0)))
+                                                ?? "Mul _,0"
+                                                =: interpInEnv env (sCon 0)
+                                                ?? mulH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 0))
+                                                =: interpInEnv env (sMul a (sCon 0))
+                                                =: qed
+                                            , vb .== 1
+                                              ==> interpInEnv env (simplify (sMul a (sCon 1)))
+                                                ?? "Mul _,1"
+                                                =: interpInEnv env a
+                                                =: interpInEnv env a * 1
+                                                ?? interpInEnv env (sCon 1) .== 1
+                                                =: interpInEnv env a * interpInEnv env (sCon 1)
+                                                ?? mulH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" (sCon 1))
+                                                =: interpInEnv env (sMul a (sCon 1))
+                                                =: qed
+                                            , vb ./= 0 .&& vb ./= 1
+                                              ==> interpInEnv env (simplify (sMul a (sCon vb)))
+                                                ?? "Mul _,C"
+                                                =: interpInEnv env (sMul a (sCon vb))
+                                                =: qed
+                                            ]
+
+                               , sNot (isCon a) .&& sNot (isCon b)
+                                 ==> interpInEnv env (simplify (sMul a b))
+                                   ?? "Mul _,_"
+                                   =: interpInEnv env (sMul a b)
+                                   =: qed
+                               ]
+
+          Let nm a b -> interpInEnv env (simplify e)
+                     ?? "Let"
+                     =: interpInEnv env (simplify (sLet nm a b))
+                     =: cases [ isCon a
+                                 ==> let v = scon a
+                                   in interpInEnv env (simplify (sLet nm (sCon v) b))
+                                   ?? "Let Con"
+                                   =: interpInEnv env (subst nm v b)
+                                   ?? subC `at` (Inst @"e" b, Inst @"nm" nm, Inst @"v" v, Inst @"env" env)
+                                   =: interpInEnv (ST.tuple (nm, v) .: env) b
+                                   ?? letH `at` (Inst @"env" env, Inst @"nm" nm, Inst @"a" (sCon v), Inst @"b" b)
+                                   =: interpInEnv env (sLet nm (sCon v) b)
+                                   =: qed
+                               , sNot (isCon a)
+                                 ==> interpInEnv env (simplify (sLet nm a b))
+                                   ?? "Let _"
+                                   =: interpInEnv env (sLet nm a b)
+                                   =: qed
+                               ]
+        |]
+
+-- | Constant folding preserves the semantics: interpreting an expression
+-- is the same as constant-folding it first and then interpreting the result.
+--
+-- >>> runTPWith cvc5 cfoldCorrect
+-- Lemma: measureNonNeg                         Q.E.D.
+-- Lemma: simpCorrect                           Q.E.D.
+-- Lemma: sqrCong                               Q.E.D. [Cached]
+-- Lemma: sqrHelper                             Q.E.D. [Cached]
+-- Lemma: mulCongL                              Q.E.D. [Cached]
+-- Lemma: mulCongR                              Q.E.D. [Cached]
+-- Lemma: mulHelper                             Q.E.D. [Cached]
+-- Inductive lemma (strong): cfoldCorrect
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1.1 (case Var)                   Q.E.D.
+--     Step: 1.1.2                              Q.E.D.
+--     Step: 1.1.3                              Q.E.D.
+--     Step: 1.2.1 (case Con)                   Q.E.D.
+--     Step: 1.2.2                              Q.E.D.
+--     Step: 1.2.3                              Q.E.D.
+--     Step: 1.3.1 (case Sqr)                   Q.E.D.
+--     Step: 1.3.2                              Q.E.D.
+--     Step: 1.3.3                              Q.E.D.
+--     Step: 1.3.4                              Q.E.D.
+--     Step: 1.3.5                              Q.E.D.
+--     Step: 1.3.6                              Q.E.D.
+--     Step: 1.3.7                              Q.E.D.
+--     Step: 1.4.1 (case Inc)                   Q.E.D.
+--     Step: 1.4.2                              Q.E.D.
+--     Step: 1.4.3                              Q.E.D.
+--     Step: 1.4.4                              Q.E.D.
+--     Step: 1.4.5                              Q.E.D.
+--     Step: 1.5.1 (case Add)                   Q.E.D.
+--     Step: 1.5.2                              Q.E.D.
+--     Step: 1.5.3                              Q.E.D.
+--     Step: 1.5.4                              Q.E.D.
+--     Step: 1.5.5                              Q.E.D.
+--     Step: 1.6.1 (case Mul)                   Q.E.D.
+--     Step: 1.6.2                              Q.E.D.
+--     Step: 1.6.3                              Q.E.D.
+--     Step: 1.6.4                              Q.E.D.
+--     Step: 1.6.5                              Q.E.D.
+--     Step: 1.6.6                              Q.E.D.
+--     Step: 1.6.7                              Q.E.D.
+--     Step: 1.6.8                              Q.E.D.
+--     Step: 1.7.1 (case Let)                   Q.E.D.
+--     Step: 1.7.2                              Q.E.D.
+--     Step: 1.7.3                              Q.E.D.
+--     Step: 1.7.4                              Q.E.D.
+--     Step: 1.7.5                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: cfold, exprSize, interpInEnv, sbv.lookup, simplify, subst
+-- [Proven] cfoldCorrect :: Ɐe ∷ (Expr String Integer) → Ɐenv ∷ [(String, Integer)] → Bool
+cfoldCorrect :: TP (Proof (Forall "e" Exp -> Forall "env" EL -> SBool))
+cfoldCorrect = do
+   mnn   <- recall measureNonNeg
+   sc    <- recall simpCorrect
+   sqrC  <- recall sqrCong
+   sqrH  <- recall sqrHelper
+   mulCL <- recall mulCongL
+   mulCR <- recall mulCongR
+   mulH  <- recall mulHelper
+
+   sInduct "cfoldCorrect"
+     (\(Forall @"e" (e :: SE)) (Forall @"env" (env :: E)) -> interpInEnv env (cfold e) .== interpInEnv env e)
+     (\e _ -> size e, [proofOf mnn]) $
+     \ih e env -> []
+       |- [pCase| e of
+            Var nm     -> interpInEnv env (cfold e)
+                       ?? "case Var"
+                       =: interpInEnv env (cfold (sVar nm))
+                       =: interpInEnv env (sVar nm)
+                       =: interpInEnv env e
+                       =: qed
+
+            Con v      -> interpInEnv env (cfold e)
+                       ?? "case Con"
+                       =: interpInEnv env (cfold (sCon v))
+                       =: interpInEnv env (sCon v)
+                       =: interpInEnv env e
+                       =: qed
+
+            Sqr a      -> interpInEnv env (cfold e)
+                       ?? "case Sqr"
+                       =: interpInEnv env (cfold (sSqr a))
+                       =: interpInEnv env (simplify (sSqr (cfold a)))
+                       ?? sc `at` (Inst @"e" (sSqr (cfold a)), Inst @"env" env)
+                       =: interpInEnv env (sSqr (cfold a))
+                       ?? sqrH `at` (Inst @"env" env, Inst @"a" (cfold a))
+                       =: interpInEnv env (cfold a) * interpInEnv env (cfold a)
+                       ?? ih `at` (Inst @"e" a, Inst @"env" env)
+                       ?? sqrC `at` (Inst @"a" (interpInEnv env (cfold a)), Inst @"b" (interpInEnv env a))
+                       =: interpInEnv env a * interpInEnv env a
+                       ?? sqrH `at` (Inst @"env" env, Inst @"a" a)
+                       =: interpInEnv env (sSqr a)
+                       =: interpInEnv env e
+                       =: qed
+
+            Inc a      -> interpInEnv env (cfold e)
+                       ?? "case Inc"
+                       =: interpInEnv env (cfold (sInc a))
+                       =: interpInEnv env (simplify (sInc (cfold a)))
+                       ?? sc `at` (Inst @"e" (sInc (cfold a)), Inst @"env" env)
+                       =: interpInEnv env (sInc (cfold a))
+                       ?? ih `at` (Inst @"e" a, Inst @"env" env)
+                       =: interpInEnv env (sInc a)
+                       =: interpInEnv env e
+                       =: qed
+
+            Add a b    -> interpInEnv env (cfold e)
+                       ?? "case Add"
+                       =: interpInEnv env (cfold (sAdd a b))
+                       =: interpInEnv env (simplify (sAdd (cfold a) (cfold b)))
+                       ?? sc `at` (Inst @"e" (sAdd (cfold a) (cfold b)), Inst @"env" env)
+                       =: interpInEnv env (sAdd (cfold a) (cfold b))
+                       ?? ih `at` (Inst @"e" a, Inst @"env" env)
+                       ?? ih `at` (Inst @"e" b, Inst @"env" env)
+                       =: interpInEnv env (sAdd a b)
+                       =: interpInEnv env e
+                       =: qed
+
+            Mul a b    -> interpInEnv env (cfold e)
+                       ?? "case Mul"
+                       =: interpInEnv env (cfold (sMul a b))
+                       =: interpInEnv env (simplify (sMul (cfold a) (cfold b)))
+                       ?? sc `at` (Inst @"e" (sMul (cfold a) (cfold b)), Inst @"env" env)
+                       =: interpInEnv env (sMul (cfold a) (cfold b))
+                       ?? mulH `at` (Inst @"env" env, Inst @"a" (cfold a), Inst @"b" (cfold b))
+                       =: interpInEnv env (cfold a) * interpInEnv env (cfold b)
+                       ?? ih `at` (Inst @"e" a, Inst @"env" env)
+                       ?? mulCL `at` (Inst @"a" (interpInEnv env (cfold a)), Inst @"b" (interpInEnv env a), Inst @"c" (interpInEnv env (cfold b)))
+                       =: interpInEnv env a * interpInEnv env (cfold b)
+                       ?? ih `at` (Inst @"e" b, Inst @"env" env)
+                       ?? mulCR `at` (Inst @"a" (interpInEnv env a), Inst @"b" (interpInEnv env (cfold b)), Inst @"c" (interpInEnv env b))
+                       =: interpInEnv env a * interpInEnv env b
+                       ?? mulH `at` (Inst @"env" env, Inst @"a" a, Inst @"b" b)
+                       =: interpInEnv env (sMul a b)
+                       =: interpInEnv env e
+                       =: qed
+
+            Let nm a b -> interpInEnv env (cfold e)
+                       ?? "case Let"
+                       =: interpInEnv env (cfold (sLet nm a b))
+                       =: interpInEnv env (simplify (sLet nm (cfold a) (cfold b)))
+                       ?? sc `at` (Inst @"e" (sLet nm (cfold a) (cfold b)), Inst @"env" env)
+                       =: interpInEnv env (sLet nm (cfold a) (cfold b))
+                       ?? ih `at` (Inst @"e" a, Inst @"env" env)
+                       ?? ih `at` (Inst @"e" b, Inst @"env" (ST.tuple (nm, interpInEnv env a) .: env))
+                       =: interpInEnv env (sLet nm a b)
+                       =: interpInEnv env e
+                       =: qed
+          |]
+
+{-# ANN simpCorrect  ("HLint: ignore Evaluate" :: String) #-}
+{-# ANN cfoldCorrect ("HLint: ignore Evaluate" :: String) #-}
diff --git a/Documentation/SBV/Examples/TP/Countdown.hs b/Documentation/SBV/Examples/TP/Countdown.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Countdown.hs
@@ -0,0 +1,135 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Countdown
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving properties of a countdown function that builds a list
+-- from @n@ down to @0@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Countdown where
+
+import Prelude hiding (head, length, (!!))
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Definitions
+
+-- | A function that counts down from @n@ to @0@, building a list.
+countdown :: SInteger -> SList Integer
+countdown = smtFunction "countdown"
+          $ \n -> [sCase| n of
+                     v | v .<= 0 -> singleton 0
+                       | True    -> v .: countdown (v - 1)
+                  |]
+
+-- * Correctness
+
+-- | Prove that @countdown n@ always starts with @n@, for positive @n@.
+--
+-- >>> runTP countdownHead
+-- Lemma: countdownHead    Q.E.D.
+-- Functions proven terminating: countdown
+-- [Proven] countdownHead :: Ɐn ∷ Integer → Bool
+countdownHead :: TP (Proof (Forall "n" Integer -> SBool))
+countdownHead = lemma "countdownHead" (\(Forall @"n" n) -> n .> 0 .=> head (countdown n) .== n) []
+
+-- | Prove by induction that @countdown n@ is never empty.
+--
+-- >>> runTP countdownNonEmpty
+-- Inductive lemma: countdownNonEmpty
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: countdown
+-- [Proven] countdownNonEmpty :: Ɐn ∷ Integer → Bool
+countdownNonEmpty :: TP (Proof (Forall "n" Integer -> SBool))
+countdownNonEmpty =
+   induct "countdownNonEmpty"
+          (\(Forall @"n" n) -> n .>= 0 .=> length (countdown n) .> 0) $
+          \ih n -> [n .>= 0] |- length (countdown (n + 1))
+                             =: length ((n + 1) .: countdown n)
+                             ?? ih
+                             =: 1 + length (countdown n)
+                             =: qed
+
+-- | Prove by induction that @countdown n@ has length @n + 1@.
+--
+-- >>> runTP countdownLen
+-- Inductive lemma: countdownLen
+--   Step: Base                     Q.E.D.
+--   Step: 1                        Q.E.D.
+--   Step: 2                        Q.E.D.
+--   Step: 3                        Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: countdown
+-- [Proven] countdownLen :: Ɐn ∷ Integer → Bool
+countdownLen :: TP (Proof (Forall "n" Integer -> SBool))
+countdownLen =
+   induct "countdownLen"
+          (\(Forall @"n" n) -> n .>= 0 .=> length (countdown n) .== n + 1) $
+          \ih n -> [n .>= 0] |- length (countdown (n + 1))
+                             =: length ((n + 1) .: countdown n)
+                             =: 1 + length (countdown n)
+                             ?? ih
+                             =: n + 2
+                             =: qed
+
+-- | Prove by induction that the @k@-th element of @countdown n@ is @n - k@.
+--
+-- The key subtlety is that the 'induct' Result step only has access to the calc chain
+-- equalities, not to the helper proofs (which live inside each step's assertion stack).
+-- The Result step must prove @P(n+1, k)@ for all valid @k@, i.e., @0 <= k <= n+1@.
+-- If the intros only cover @k <= n@, the Result step has no information for @k = n+1@
+-- and hangs. The fix is to use intros @[n >= 0, 0 <= k, k <= n+1]@ so the calc chain
+-- covers the entire domain of the goal.
+--
+-- >>> runTP countdownElem
+-- Lemma: countdownLen               Q.E.D.
+-- Lemma: elemOne                    Q.E.D.
+-- Inductive lemma: countdownElem
+--   Step: Base                      Q.E.D.
+--   Step: 1                         Q.E.D.
+--   Step: 2                         Q.E.D.
+--   Result:                         Q.E.D.
+-- Functions proven terminating: countdown
+-- [Proven] countdownElem :: Ɐn ∷ Integer → Ɐk ∷ Integer → Bool
+countdownElem :: TP (Proof (Forall "n" Integer -> Forall "k" Integer -> SBool))
+countdownElem = do
+   cLen <- recall countdownLen
+
+   -- NB. The precondition uses (<=) not (<): this is important so the lemma covers
+   -- k = length y (the last valid index of x .: y), not just k < length y.
+   elemOne <- lemma "elemOne" (\(Forall @"x" (x :: SInteger)) (Forall @"y" y) (Forall @"k" k) ->
+                                   k .> 0 .&& k .<= length y .=> (x .: y) !! k .== y !! (k - 1)) []
+
+   induct "countdownElem"
+          (\(Forall @"n" n) (Forall @"k" k) -> 0 .<= k .&& k .<= n .=> countdown n !! k .== n - k) $
+          \ih n k -> [n .>= 0, 0 .<= k, k .<= n + 1]
+                  |- countdown (n + 1) !! k
+                  =: ((n + 1) .: countdown n) !! k
+                  ?? elemOne
+                  ?? cLen
+                  ?? ih `at` Inst @"k" (k - 1)
+                  =: n + 1 - k
+                  =: qed
diff --git a/Documentation/SBV/Examples/TP/Fibonacci.hs b/Documentation/SBV/Examples/TP/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Fibonacci.hs
@@ -0,0 +1,86 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Fibonacci
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving that the naive version of fibonacci and the faster tail-recursive
+-- version are equivalent.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Fibonacci(correctness) where
+
+import Data.SBV
+import Data.SBV.TP
+
+-- * Naive fibonacci
+
+-- | Calculate fibonacci using the textbook definition.
+fibonacci :: SInteger -> SInteger
+fibonacci = smtFunction "fibonacci" $ \n -> [sCase| n of
+                                               _ | n .<= 1 -> 1
+                                               _           -> fibonacci (n-1) + fibonacci (n-2)
+                                            |]
+
+-- * Tail recursive version
+
+-- | Tail recursive version
+fib :: SInteger -> SInteger -> SInteger -> SInteger
+fib = smtFunction "fib" $ \a b n -> [sCase| n of
+                                       _ | n .<= 0 -> a
+                                       _           -> fib b (a+b) (n-1)
+                                    |]
+
+-- | Faster version of fibonacci, using the tail-recursive version.
+fibTail :: SInteger -> SInteger
+fibTail = fib 1 1
+
+-- * Correctness
+
+-- | Proving the tail recursive version of fibonacci is equivalent to the textbook version.
+--
+-- We have:
+--
+-- >>> correctness
+-- Inductive lemma: helper
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2 (unfold fibonacci)    Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: fibCorrect
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: fib, fibonacci
+-- [Proven] fibCorrect :: Ɐn ∷ Integer → Bool
+correctness :: IO (Proof (Forall "n" Integer -> SBool))
+correctness = runTP $ do
+
+  helper <- induct "helper"
+                   (\(Forall n) (Forall k) ->
+                       n .>= 0 .&& k .>= 0 .=> fib (fibonacci k) (fibonacci (k+1)) n .== fibonacci (k+n)) $
+                   \ih n k -> [n .>= 0, k .>= 0]
+                           |- fib (fibonacci k) (fibonacci (k+1)) (n+1)
+                           =: fib (fibonacci (k+1)) (fibonacci k + fibonacci (k+1)) n
+                           ?? "unfold fibonacci"
+                           =: fib (fibonacci (k+1)) (fibonacci (k+2)) n
+                           ?? ih `at` Inst @"k" (k+1)
+                           =: fibonacci (k+1+n)
+                           =: qed
+
+  calc "fibCorrect"
+       (\(Forall n) -> n .>= 0 .=> fibonacci n .== fibTail n) $
+       \n -> [n .>= 0] |- fibTail n
+                       =: fib 1 1 n
+                       ?? helper `at` (Inst @"n" n, Inst @"k" 0)
+                       =: fibonacci n
+                       =: qed
diff --git a/Documentation/SBV/Examples/TP/GCD.hs b/Documentation/SBV/Examples/TP/GCD.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/GCD.hs
@@ -0,0 +1,1063 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.GCD
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- We define three different versions of the GCD algorithm: (1) Regular
+-- version using the modulus operator, (2) the more basic version using
+-- subtraction, and (3) the so called binary GCD. We prove that the modulus
+-- based algorithm correct, i.e., that it calculates the greatest-common-divisor
+-- of its arguments. We then prove that the other two variants are equivalent
+-- to this version, thus establishing their correctness as well.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.GCD where
+
+import Prelude hiding (gcd)
+
+import Data.SBV
+import Data.SBV.TP
+import Data.SBV.Tuple
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Calculating GCD
+
+-- | @nGCD@ is the version of GCD that works on non-negative integers.
+--
+-- Ideally, we should make this function local to @gcd@, but then we can't refer to it explicitly in our proofs.
+--
+-- Note on maximality: Note that, by definition @gcd 0 0 = 0@. Since any number divides @0@,
+-- there is no greatest common divisor for the pair @(0, 0)@. So, maximality here is meant
+-- to be in terms of divisibility. That is, any divisor of @a@ and @b@ will also divide their @gcd@.
+nGCD :: SInteger -> SInteger -> SInteger
+nGCD = smtFunction "nGCD" $ \a b -> [sCase| b of
+                                       _ | b .== 0 -> a
+                                       _           -> nGCD b (a `sEMod` b)
+                                    |]
+
+-- | Generalized GCD, working for all integers. We simply call @nGCD@ with the absolute value of the arguments.
+gcd :: SInteger -> SInteger -> SInteger
+gcd a b = nGCD (abs a) (abs b)
+
+-- * Basic properties
+
+-- | \(\gcd\, a\ b \geq 0\)
+--
+-- ==== __Proof__
+-- >>> runTP gcdNonNegative
+-- Inductive lemma (strong): nonNegativeNGCD
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                Q.E.D.
+--     Step: 1.2.1                              Q.E.D.
+--     Step: 1.2.2                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Lemma: nonNegative                           Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] nonNegative :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdNonNegative :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdNonNegative = do
+     -- We first prove over nGCD, using strong induction with the measure @a+b@.
+     nn <- sInduct "nonNegativeNGCD"
+                   (\(Forall a) (Forall b) -> a .>= 0 .&& b .>= 0 .=> nGCD a b .>= 0)
+                   (\_a b -> b, []) $
+                   \ih a b -> [a .>= 0, b .>= 0]
+                           |- cases [ b .== 0 ==> trivial
+                                    , b ./= 0 ==> nGCD a b .>= 0
+                                               =: nGCD b (a `sEMod` b) .>= 0
+                                               ?? ih `at` (Inst @"a" b, Inst @"b" (a `sEMod` b))
+                                               =: sTrue
+                                               =: qed
+                                    ]
+
+     lemma "nonNegative"
+           (\(Forall a) (Forall b) -> gcd a b .>= 0)
+           [proofOf nn]
+
+-- | \(\gcd\, a\ b=0\implies a=0\land b=0\)
+--
+-- ==== __Proof__
+-- >>> runTP gcdZero
+-- Inductive lemma (strong): nGCDZero
+--   Step: Measure is non-negative       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2.1                       Q.E.D.
+--     Step: 1.2.2                       Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: gcdZero                        Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdZero :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdZero :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdZero = do
+
+  -- First prove over nGCD:
+  nGCDZero <-
+    sInduct "nGCDZero"
+            (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .&& nGCD a b .== 0 .=> a .== 0 .&& b .== 0)
+            (\_a b -> b, []) $
+            \ih a b -> [a .>= 0, b .>= 0]
+                    |- (nGCD a b .== 0 .=> a .== 0 .&& b .== 0)
+                    =: cases [ b .== 0 ==> trivial
+                             , b .>  0 ==> (nGCD b (a `sEMod` b) .== 0 .=> a .== 0 .&& b .== 0)
+                                        ?? ih `at` (Inst @"a" b, Inst @"b" (a `sEMod` b))
+                                        =: sTrue
+                                        =: qed
+                             ]
+
+  lemma "gcdZero"
+        (\(Forall @"a" a) (Forall @"b" b) -> gcd a b .== 0 .=> a .== 0 .&& b .== 0)
+        [proofOf nGCDZero]
+
+-- | \(\gcd\, a\ b=\gcd\, b\ a\)
+--
+-- ==== __Proof__
+-- >>> runTP commutative
+-- Lemma: nGCDCommutative
+--   Step: 1                 Q.E.D.
+--   Result:                 Q.E.D.
+-- Lemma: commutative
+--   Step: 1                 Q.E.D.
+--   Step: 2                 Q.E.D.
+--   Result:                 Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] commutative :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+commutative :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+commutative = do
+    -- First prove over nGCD. Simple enough proof, but quantifiers and recursive functions
+    -- cause z3 to diverge. So, we have to explicitly write it out.
+    nGCDComm <-
+        calc "nGCDCommutative"
+             (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCD a b .== nGCD b a) $
+             \a b -> [a .>= 0, b .>= 0]
+                  |- nGCD a b
+                  =: nGCD b a
+                  =: qed
+
+    -- It's unfortunate we have to spell this out explicitly, a simple lemma call
+    -- that uses the above proof doesn't converge.
+    calc "commutative"
+          (\(Forall a) (Forall b) -> gcd a b .== gcd b a) $
+          \a b -> [] |- gcd a b
+                     =: nGCD (abs a) (abs b)
+                     ?? nGCDComm `at` (Inst @"a" (abs a), Inst @"b" (abs b))
+                     =: gcd b a
+                     =: qed
+
+-- | \(\gcd\,(-a)\,b = \gcd\,a\,b = \gcd\,a\,(-b)\)
+--
+-- ==== __Proof__
+-- >>> runTP negGCD
+-- Lemma: negGCD       Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] negGCD :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+negGCD :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+negGCD = lemma "negGCD" (\(Forall a) (Forall b) -> let g = gcd a b in gcd (-a) b .== g .&& g .== gcd a (-b)) []
+
+-- | \( \gcd\,a\,0 = \gcd\,0\,a = |a| \land \gcd\,0\,0 = 0\)
+--
+-- ==== __Proof__
+-- >>> runTP zeroGCD
+-- Lemma: zeroGCD      Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] zeroGCD :: Ɐa ∷ Integer → Bool
+zeroGCD :: TP (Proof (Forall "a" Integer -> SBool))
+zeroGCD = lemma "zeroGCD" (\(Forall a) -> gcd a 0 .== gcd 0 a .&& gcd 0 a .== abs a .&& gcd 0 0 .== 0) []
+
+-- * Even and odd
+
+-- | Is the given integer even?
+isEven :: SInteger -> SBool
+isEven = (2 `sDivides`)
+
+-- | Is the given integer odd?
+isOdd :: SInteger -> SBool
+isOdd  = sNot . isEven
+
+-- * Divisibility
+
+-- | Divides relation. By definition @0@ only divides @0@. (But every number divides @0@).
+dvd :: SInteger -> SInteger -> SBool
+a `dvd` b = ite (a .== 0) (b .== 0) (b `sEMod` a .== 0)
+
+-- | \(d \mid a \implies d \mid ka\)
+--
+-- ==== __Proof__
+-- >>> runTP dvdMul
+-- Lemma: dvdMul
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dvdMul :: Ɐd ∷ Integer → Ɐa ∷ Integer → Ɐk ∷ Integer → Bool
+dvdMul :: TP (Proof (Forall "d" Integer -> Forall "a" Integer -> Forall "k" Integer -> SBool))
+dvdMul = calc "dvdMul"
+              (\(Forall d) (Forall a) (Forall k) -> d `dvd` a .=> d `dvd` (k*a)) $
+              \d a k -> [d `dvd` a]
+                     |- cases [ d .== 0 ==> d `dvd` (k*a)
+                                         ?? a .== 0
+                                         =: sTrue
+                                         =: qed
+                              , d ./= 0 ==> d `dvd` (k*a)
+                                         =: (k*a) `sEMod` d .== 0
+                                         ?? a .== d * a `sEDiv` d
+                                         ?? k * a .== d * (k * a `sEDiv` d)
+                                         ?? (d * (k * a `sEDiv` d)) `sEMod` d .== 0
+                                         =: sTrue
+                                         =: qed
+                              ]
+
+-- | \(a \mid |b| \iff a \mid b\)
+--
+-- A number divides another exactly when it also divides its absolute value. This follows
+-- from 'dvdMul', as both directions are an instance of multiplying by @-1@.
+--
+-- ==== __Proof__
+-- >>> runTP dvdAbs
+-- Lemma: dvdMul               Q.E.D.
+-- Lemma: dvdAbs_l2r
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2               Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- Lemma: dvdAbs_r2l
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2               Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- Lemma: dvdAbs               Q.E.D.
+-- [Proven] dvdAbs :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+dvdAbs :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+dvdAbs = do
+   dM <- recall dvdMul
+
+   l2r <- calc "dvdAbs_l2r"
+               (\(Forall @"a" a) (Forall @"b" b) -> a `dvd` abs b .=> a `dvd` b) $
+               \a b -> [a `dvd` abs b]
+                    |- cases [ b .>= 0 ==> a `dvd` b
+                                        =: sTrue
+                                        =: qed
+                             , b .<  0 ==> a `dvd` b
+                                        ?? dM `at` (Inst @"d" a, Inst @"a" (abs b), Inst @"k" (-1))
+                                        =: sTrue
+                                        =: qed
+                             ]
+
+   r2l <- calc "dvdAbs_r2l"
+               (\(Forall @"a" a) (Forall @"b" b) -> a `dvd` b .=> a `dvd` abs b) $
+               \a b -> [a `dvd` b]
+                    |- cases [ b .>= 0 ==> a `dvd` abs b
+                                        =: sTrue
+                                        =: qed
+                             , b .<  0 ==> a `dvd` abs b
+                                        ?? dM `at` (Inst @"d" a, Inst @"a" b, Inst @"k" (-1))
+                                        =: sTrue
+                                        =: qed
+                             ]
+
+   lemma "dvdAbs"
+         (\(Forall @"a" a) (Forall @"b" b) -> a `dvd` b .== a `dvd` abs b)
+         [proofOf l2r, proofOf r2l]
+
+-- | \(d \mid (2a + 1) \implies \mathrm{isOdd}(d)\)
+--
+-- ==== __Proof__
+-- >>> runTP dvdOddThenOdd
+-- Lemma: dvdOddThenOdd
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dvdOddThenOdd :: Ɐd ∷ Integer → Ɐa ∷ Integer → Bool
+dvdOddThenOdd :: TP (Proof (Forall "d" Integer -> Forall "a" Integer -> SBool))
+dvdOddThenOdd = calc "dvdOddThenOdd"
+                     (\(Forall d) (Forall a) -> d `dvd` (2*a+1) .=> isOdd d) $
+                     \d a -> [d `dvd` (2*a+1)]
+                          |- cases [ isOdd  d ==> trivial
+                                   , isEven d ==> (2 * (d `sEDiv` 2)) `dvd` (2*a+1)
+                                               =: 2 `dvd` (2*a+1)
+                                               =: contradiction
+                                   ]
+
+-- | \(\mathrm{isOdd}(d) \land d \mid 2a \implies d \mid a\)
+--
+-- ==== __Proof__
+-- >>> runTP dvdEvenWhenOdd
+-- Lemma: dvdEvenWhenOdd
+--   Step: 1                Q.E.D.
+--   Step: 2                Q.E.D.
+--   Step: 3                Q.E.D.
+--   Step: 4                Q.E.D.
+--   Step: 5                Q.E.D.
+--   Step: 6                Q.E.D.
+--   Step: 7                Q.E.D.
+--   Result:                Q.E.D.
+-- [Proven] dvdEvenWhenOdd :: Ɐd ∷ Integer → Ɐa ∷ Integer → Bool
+dvdEvenWhenOdd :: TP (Proof (Forall "d" Integer -> Forall "a" Integer -> SBool))
+dvdEvenWhenOdd = calc "dvdEvenWhenOdd"
+                      (\(Forall d) (Forall a) -> isOdd d .&& d `dvd` (2*a) .=> d `dvd` a) $
+                      \d a ->  [isOdd d, d `dvd` (2*a)]
+                           |-  let t = (d - 1) `sEDiv` 2
+                                   m = (2*a)   `sEDiv` d
+                            in sTrue
+
+                            -- Observe that d = 2t+1 and 2a = dm
+                            =: d .== 2*t + 1 .&& 2*a .== d*m
+
+                            -- So, 2a == (2t+1)m holds
+                            =: 2*a .== (2*t+1) * m
+
+                            -- Arithmetic gives us
+                            =: 2*a .== 2*t*m + m .&& 2*(a-t*m) .== m
+
+                            -- So m = 2*(a-t*m), i.e., m is even
+                            =: m .== 2 * (a - t*m)
+
+                            -- Let n = a - t*m, so m = 2n. It follows that 2a = d(2n) = 2(dn)
+                            =: let n = a - t*m
+                            in 2*a .== d * (2 * n) .&& 2 * a .== 2 * (d * n)
+
+                            -- From which we can conclude a = dn
+                            =: a .== d * n
+
+                            -- Thus we can deduce d must divide a
+                            ?? d `dvd` (d * n)
+                            =: d `dvd` a
+
+                            -- Done!
+                            =: qed
+
+-- | \(d \mid a \land d \mid b \implies d \mid (a + b)\)
+--
+-- ==== __Proof__
+-- >>> runTP dvdSum1
+-- Lemma: dvdSum1
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.2.3             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dvdSum1 :: Ɐd ∷ Integer → Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+dvdSum1 :: TP (Proof (Forall "d" Integer -> Forall "a" Integer -> Forall "b" Integer -> SBool))
+dvdSum1 =
+  calc "dvdSum1"
+       (\(Forall d) (Forall a) (Forall b) -> d `dvd` a .&& d `dvd` b .=> d `dvd` (a + b)) $
+       \d a b -> [d `dvd` a .&& d `dvd` b]
+              |- cases [ a .== 0 .|| b .== 0 ==> trivial
+                       , a ./= 0 .&& b ./= 0 ==> d `dvd` (a + b)
+                                              =: d `dvd` (a `sEDiv` d * d + b `sEDiv` d * d)
+                                              =: d `dvd` (d * (a `sEDiv` d + b `sEDiv` d))
+                                              =: sTrue
+                                              =: qed
+                       ]
+
+-- | \(d \mid (a + b) \land d \mid b \implies d \mid a \)
+--
+-- ==== __Proof__
+-- >>> runTP dvdSum2
+-- Lemma: dvdSum2
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.2.3             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dvdSum2 :: Ɐd ∷ Integer → Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+dvdSum2 :: TP (Proof (Forall "d" Integer -> Forall "a" Integer -> Forall "b" Integer -> SBool))
+dvdSum2 =
+  calc "dvdSum2"
+       (\(Forall d) (Forall a) (Forall b) -> d `dvd` (a + b) .&& d `dvd` b .=> d `dvd` a) $
+       \d a b -> [d `dvd` (a + b) .&& d `dvd` b]
+              |- cases [ d .== 0 ==> trivial
+                       , d ./= 0 ==> let k1 = (a + b) `sEDiv` d
+                                         k2 =      b  `sEDiv` d
+                                     in a `sEDiv` d
+                                     =: (a + b - b) `sEDiv` d
+                                     =: (k1 * d - k2 * d) `sEDiv` d
+                                     =: (k1 - k2) * d `sEDiv` d
+                                     =: qed
+                       ]
+
+-- * Correctness of GCD
+
+-- | \(\gcd\,a\,b \mid a \land \gcd\,a\,b \mid b\)
+--
+-- GCD of two numbers divide these numbers. This is part one of the proof, where we are
+-- not concerned with maximality. Our goal is to show that the calculated gcd divides both inputs.
+--
+-- ==== __Proof__
+-- >>> runTP gcdDivides
+-- Lemma: dvdAbs                        Q.E.D.
+-- Lemma: helper
+--   Step: 1                            Q.E.D.
+--   Result:                            Q.E.D.
+-- Inductive lemma (strong): dvdNGCD
+--   Step: Measure is non-negative      Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2.1                      Q.E.D.
+--     Step: 1.2.2                      Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Lemma: gcdDivides                    Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdDivides :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdDivides :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdDivides = do
+
+   dAbs <- recall dvdAbs
+
+   -- Helper about divisibility. If x|b and x| a%b, then x|a.
+   helper <- calc "helper"
+                  (\(Forall @"a" a) (Forall @"b" b) (Forall @"x" x) ->
+                           b ./= 0 .&& x `dvd` b .&& x `dvd` (a `sEMod` b)
+                       .=> -----------------------------------------------
+                                       x `dvd` a
+                  ) $
+                  \a b x -> [b ./= 0, x `dvd` b, x `dvd` (a `sEMod` b)]
+                         |- x `dvd` a
+                         ?? a `sEDiv` x .== (a `sEDiv` b) * (b `sEDiv` x) + (a `sEMod` b) `sEDiv` x
+                         =: sTrue
+                         =: qed
+
+   -- Use strong induction to prove divisibility over non-negative numbers.
+   dNGCD <- sInduct "dvdNGCD"
+                     (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCD a b `dvd` a .&& nGCD a b `dvd` b)
+                     (\_a b -> b, []) $
+                     \ih a b -> [a .>= 0, b .>= 0]
+                             |- let g = nGCD a b
+                             in g `dvd` a .&& g `dvd` b
+                             =: cases [ b .== 0 ==> trivial
+                                      , b .>  0 ==> let g' = nGCD b (a `sEMod` b)
+                                                 in g' `dvd` a .&& g' `dvd` b
+                                                 ?? ih `at` (Inst @"a" b, Inst @"b" (a `sEMod` b))
+                                                 ?? helper
+                                                 =: sTrue
+                                                 =: qed
+                                      ]
+
+   -- Now generalize to arbitrary integers.
+   lemma"gcdDivides"
+        (\(Forall a) (Forall b) -> gcd a b `dvd` a .&& gcd a b `dvd` b)
+        [proofOf dAbs, proofOf dNGCD]
+
+-- | \(x \mid a \land x \mid b \implies x \mid \gcd\,a\,b\)
+--
+-- Maximality. Any divisor of the inputs divides the GCD.
+--
+-- ==== __Proof__
+-- >>> runTP gcdMaximal
+-- Lemma: dvdAbs                         Q.E.D.
+-- Lemma: commutative                    Q.E.D.
+-- Lemma: eDiv                           Q.E.D.
+-- Lemma: helper
+--   Step: 1 (x `dvd` a && x `dvd` b)    Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Inductive lemma (strong): mNGCD
+--   Step: Measure is non-negative       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2.1                       Q.E.D.
+--     Step: 1.2.2                       Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: gcdMaximal
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                       Q.E.D.
+--     Step: 1.1.2                       Q.E.D.
+--     Step: 1.2.1                       Q.E.D.
+--     Step: 1.2.2                       Q.E.D.
+--     Step: 1.2.3                       Q.E.D.
+--     Step: 1.2.4                       Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdMaximal :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐx ∷ Integer → Bool
+gcdMaximal :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "x" Integer -> SBool))
+gcdMaximal = do
+
+   dAbs <- recall dvdAbs
+   comm <- recall commutative
+
+   eDiv <- lemma "eDiv"
+                 (\(Forall @"x" x) (Forall @"y" y) -> y ./= 0 .=> x .== (x `sEDiv` y) * y + x `sEMod` y)
+                 []
+
+   -- Helper: If x|a, x|b then x|a%b.
+   helper <- calc "helper"
+                  (\(Forall @"a" a) (Forall @"b" b) (Forall @"x" x) ->
+                           x ./= 0 .&& b ./= 0 .&& x `dvd` a .&& x `dvd` b
+                       .=> -----------------------------------------------
+                                     x `dvd` (a `sEMod` b)
+                  ) $
+                  \a b x -> [x ./= 0, b ./= 0, x `dvd` a, x `dvd` b]
+                         |- x `dvd` (a `sEMod` b)
+                         ?? "x `dvd` a && x `dvd` b"
+                         =: let k1 = a `sDiv` x
+                                k2 = b `sDiv` x
+                         in x `dvd` ((k1*x) `sEMod` (k2*x))
+                         ?? eDiv `at` (Inst @"x" (k1*x), Inst @"y" (k2*x))
+                         =: x `dvd` ((k1*x) - ((k1*x) `sEDiv` (k2*x)) * (k2*x))
+                         =: sTrue
+                         =: qed
+
+   -- Now prove maximality for non-negative integers:
+   mNGCD <- sInduct "mNGCD"
+                    (\(Forall @"a" a) (Forall @"b" b) (Forall @"x" x) ->
+                          a .>= 0 .&& b .>= 0 .&& x `dvd` a .&& x `dvd` b .=> x `dvd` nGCD a b)
+                    (\_a b _x -> b, []) $
+                    \ih a b x -> let g = nGCD a b
+                              in [a .>= 0, b .>= 0, x `dvd` a .&& x `dvd` b]
+                              |- x `dvd` g
+                              =: cases [ b .== 0 ==> trivial
+                                       , b .>  0 ==> x `dvd` nGCD b (a `sEMod` b)
+                                                  ?? ih `at` (Inst @"a" b, Inst @"b" (a `sEMod` b), Inst @"x" x)
+                                                  ?? helper
+                                                  =: sTrue
+                                                  =: qed
+                                                  ]
+
+   -- Generalize to arbitrary integers:
+   calc "gcdMaximal"
+        (\(Forall @"a" a) (Forall @"b" b) (Forall @"x" x) -> x `dvd` a .&& x `dvd` b .=> x `dvd` gcd a b) $
+        \a b x -> [x `dvd` a, x `dvd` b]
+               |- x `dvd` gcd a b
+               =: cases [ abs a .>= abs b ==> x `dvd` nGCD (abs a) (abs b)
+                                           ?? mNGCD    `at` (Inst @"a" (abs a), Inst @"b" (abs b), Inst @"x" x)
+                                           ?? dAbs     `at` (Inst @"a" x, Inst @"b" a)
+                                           ?? dAbs     `at` (Inst @"a" x, Inst @"b" b)
+                                           =: sTrue
+                                           =: qed
+                        , abs a .<  abs b ==> x `dvd` gcd a b
+                                           ?? comm `at` (Inst @"a" a, Inst @"b" b)
+                                           =: x `dvd` gcd b a
+                                           =: x `dvd` nGCD (abs b) (abs a)
+                                           ?? mNGCD    `at` (Inst @"a" (abs b), Inst @"b" (abs a), Inst @"x" x)
+                                           ?? dAbs     `at` (Inst @"a" x, Inst @"b" a)
+                                           ?? dAbs     `at` (Inst @"a" x, Inst @"b" b)
+                                           =: sTrue
+                                           =: qed
+                        ]
+
+-- | \(\gcd\,a\,b \mid a \land \gcd\,a\,b \mid b \land (x \mid a \land x \mid b \implies x \mid \gcd\,a\,b)\)
+--
+-- Putting it all together: GCD divides both arguments, and its maximal.
+--
+-- ==== __Proof__
+-- >>> runTP gcdCorrect
+-- Lemma: gcdDivides                     Q.E.D.
+-- Lemma: gcdMaximal                     Q.E.D.
+-- Lemma: gcdCorrect
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdCorrect :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdCorrect :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdCorrect = do
+  divides <- recall gcdDivides
+  maximal <- recall gcdMaximal
+
+  calc "gcdCorrect"
+       (\(Forall a) (Forall b) ->
+             let g = gcd a b
+          in  g `dvd` a
+          .&& g `dvd` b
+          .&& quantifiedBool (\(Forall x) -> x `dvd` a .&& x `dvd` b .=> x `dvd` g)
+       ) $
+       \a b -> []
+            |- let g = gcd a b
+                   m = quantifiedBool (\(Forall x) -> x `dvd` a .&& x `dvd` b .=> x `dvd` g)
+            in g `dvd` a .&& g `dvd` b .&& m
+            ?? divides `at` (Inst @"a" a, Inst @"b" b)
+            =: m
+            ?? maximal
+            =: sTrue
+            =: qed
+
+-- | \(\bigl((a \neq 0 \lor b \neq 0) \land x \mid a \land x \mid b \bigr) \implies x \leq \gcd\,a\,b\)
+--
+-- Additionally prove that GCD is really maximum, i.e., it is the largest in the regular sense. Note
+-- that we have to make an exception for @gcd 0 0@ since by definition the GCD is @0@, which is clearly
+-- not the largest divisor of @0@ and @0@. (Since any number is a GCD for the pair @(0, 0)@, there is
+-- no maximum.)
+--
+-- ==== __Proof__
+-- >>> runTP gcdLargest
+-- Lemma: gcdMaximal                            Q.E.D.
+-- Lemma: gcdZero                               Q.E.D.
+-- Lemma: nonNegative                           Q.E.D.
+-- Lemma: gcdLargest
+--   Step: 1                                    Q.E.D.
+--   Step: 2                                    Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdLargest :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐx ∷ Integer → Bool
+gcdLargest :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "x" Integer -> SBool))
+gcdLargest = do
+   maximal <- recall gcdMaximal
+   gcdZ    <- recall gcdZero
+   nn      <- recall gcdNonNegative
+
+   calc "gcdLargest"
+        (\(Forall a) (Forall b) (Forall x) -> (a ./= 0 .|| b ./= 0) .&& x `dvd` a .&& x `dvd` b .=> x .<= gcd a b) $
+        \a b x -> [(a ./= 0 .|| b ./= 0) .&& x `dvd` a, x `dvd` b]
+               |- x .<= gcd a b
+               ?? maximal `at` (Inst @"a" a, Inst @"b" b, Inst @"x" x)
+               =: (x `dvd` gcd a b .=> x .<= gcd a b)
+               ?? gcdZ  `at` (Inst @"a" a, Inst @"b" b)
+               ?? nn    `at` (Inst @"a" a, Inst @"b" b)
+               =: sTrue
+               =: qed
+
+-- * Other GCD Facts
+
+-- | \(\gcd\, a\, b = \gcd\, (a + b)\, b\)
+--
+-- ==== __Proof__
+-- >>> runTP gcdAdd
+-- Lemma: dvdSum1                               Q.E.D.
+-- Lemma: dvdSum2                               Q.E.D.
+-- Lemma: gcdDivides                            Q.E.D.
+-- Lemma: gcdLargest                            Q.E.D.
+-- Lemma: gcdAdd
+--   Step: 1                                    Q.E.D.
+--   Step: 2                                    Q.E.D.
+--   Step: 3                                    Q.E.D.
+--   Step: 4                                    Q.E.D.
+--   Step: 5                                    Q.E.D.
+--   Step: 6                                    Q.E.D.
+--   Step: 7                                    Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdAdd :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdAdd :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdAdd = do
+
+   dSum1   <- recall dvdSum1
+   dSum2   <- recall dvdSum2
+   divides <- recall gcdDivides
+   largest <- recall gcdLargest
+
+   calc "gcdAdd"
+        (\(Forall @"a" a) (Forall @"b" b) -> gcd a b .== gcd (a + b) b) $
+        \a b -> [] |-> let g1 = gcd a       b
+                           g2 = gcd (a + b) b
+                    in sTrue
+
+                    -- First use the divides property to conclude that g1 divides a and b
+                    ?? divides `at` (Inst @"a" a, Inst @"b" b)
+                    =: g1 `dvd` a .&& g1 `dvd` b
+
+                    -- Same for g2 for a+b and b
+                    ?? divides `at` (Inst @"a" (a + b), Inst @"b" b)
+                    =: g2 `dvd` (a+b) .&& g2 `dvd` b
+
+                    -- Use dSum1 to show g1 divides a+b
+                    ?? dSum1 `at` (Inst @"d" g1, Inst @"a" a, Inst @"b" b)
+                    =: g1 `dvd` (a+b)
+
+                    -- Similarly, use dSum2 to show g2 divides a
+                    ?? dSum2 `at` (Inst @"d" g2, Inst @"a" a, Inst @"b" b)
+                    =:  g2 `dvd` a
+
+                    -- Now use largest to show g1 >= g2
+                    ?? largest `at` (Inst @"a" a,     Inst @"b" b, Inst @"x" g2)
+                    =: g1 .>= g2
+
+                    -- But again via largest, we can show g2 >= g1
+                    ?? largest `at` (Inst @"a" (a+b), Inst @"b" b, Inst @"x" g1)
+                    =: g2 .>= g1
+
+                    -- Finally conclude g1 = g2, since both are greater-than-equal to each other:
+                    =: g1 .== g2
+                    =: qed
+
+-- | \(\gcd\, (2a)\, (2b) = 2 (\gcd\,a\, b)\)
+--
+-- ==== __Proof__
+-- >>> runTP gcdEvenEven
+-- Lemma: red2                               Q.E.D.
+-- Lemma: modEE
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Step: 3                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Inductive lemma (strong): nGCDEvenEven
+--   Step: Measure is non-negative           Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                             Q.E.D.
+--     Step: 1.2.1                           Q.E.D.
+--     Step: 1.2.2                           Q.E.D.
+--     Step: 1.2.3                           Q.E.D.
+--     Step: 1.2.4                           Q.E.D.
+--     Step: 1.Completeness                  Q.E.D.
+--   Result:                                 Q.E.D.
+-- Lemma: gcdEvenEven
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Step: 3                                 Q.E.D.
+--   Step: 4                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdEvenEven :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdEvenEven :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdEvenEven = do
+
+   red2  <- lemmaWith z3 "red2"
+                  (\(Forall @"a" a) (Forall @"b" b) -> b ./= 0 .=> (2*a) `sEDiv` (2*b) .== a `sEDiv` b)
+                  []
+
+   modEE <- calcWith cvc5 "modEE"
+                 (\(Forall @"a" a) (Forall @"b" b) -> b ./= 0 .=> (2*a) `sEMod` (2*b) .== 2 * (a `sEMod` b)) $
+                 \a b -> [b ./= 0]
+                      |- (2*a) `sEMod` (2*b)
+                      ?? red2 `at` (Inst @"a" a, Inst @"b" b)
+                      =: 2*a - 2*b * (a `sEDiv` b)
+                      =: 2 * (a - b * (a `sEDiv` b))
+                      =: 2 * (a `sEMod` b)
+                      =: qed
+
+   nGCDEvenEven <- sInduct "nGCDEvenEven"
+                           (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCD (2*a) (2*b) .== 2 * nGCD a b)
+                           (\_a b -> b, []) $
+                           \ih a b -> [a .>= 0, b .>= 0]
+                                   |- nGCD (2*a) (2*b)
+                                   =: cases [ b .== 0 ==> trivial
+                                            , b ./= 0 ==> nGCD (2 * a) (2 * b)
+                                                       =: nGCD (2 * b) ((2 * a) `sEMod` (2 * b))
+                                                       ?? modEE `at` (Inst @"a" a, Inst @"b" b)
+                                                       =: nGCD (2 * b) (2 * (a `sEMod` b))
+                                                       ?? ih
+                                                       =: 2 * nGCD a b
+                                                       =: qed
+                                         ]
+
+   calc "gcdEvenEven"
+        (\(Forall a) (Forall b) -> gcd (2*a) (2*b) .== 2 * gcd a b) $
+        \a b -> [] |- gcd (2*a) (2*b)
+                   =: nGCD (abs (2*a)) (abs (2*b))
+                   =: nGCD (2 * abs a) (2 * abs b)
+                   ?? nGCDEvenEven `at` (Inst @"a" (abs a), Inst @"b" (abs b))
+                   =: 2 * nGCD (abs a) (abs b)
+                   =: 2 * gcd a b
+                   =: qed
+
+-- | \(\gcd\, (2a+1)\, (2b) = \gcd\,(2a+1)\, b\)
+--
+-- ==== __Proof__
+-- >>> runTP gcdOddEven
+-- Lemma: gcdDivides                            Q.E.D.
+-- Lemma: gcdLargest                            Q.E.D.
+-- Lemma: dvdMul                                Q.E.D. [Cached]
+-- Lemma: dvdOddThenOdd                         Q.E.D.
+-- Lemma: dvdEvenWhenOdd                        Q.E.D.
+-- Lemma: gcdOddEven
+--   Step: 1                                    Q.E.D.
+--   Step: 2                                    Q.E.D.
+--   Step: 3                                    Q.E.D.
+--   Step: 4                                    Q.E.D.
+--   Step: 5                                    Q.E.D.
+--   Step: 6                                    Q.E.D.
+--   Step: 7                                    Q.E.D.
+--   Step: 8                                    Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: nGCD
+-- [Proven] gcdOddEven :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdOddEven :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdOddEven = do
+
+   divides      <- recall gcdDivides
+   largest      <- recall gcdLargest
+   dMul         <- recall dvdMul
+   dOddThenOdd  <- recall dvdOddThenOdd
+   dEvenWhenOdd <- recall dvdEvenWhenOdd
+
+   calc "gcdOddEven"
+        (\(Forall a) (Forall b) -> gcd (2*a+1) (2*b) .== gcd (2*a+1) b) $
+        \a b -> [] |-> let g1 = gcd (2*a+1) (2*b)
+                           g2 = gcd (2*a+1) b
+                   in sTrue
+
+                   -- First use the divides property to conclude that g1 divides both 2*a+1 and 2*b
+                   ?? divides `at` (Inst @"a" (2*a+1), Inst @"b" (2*b))
+                   =: g1 `dvd` (2*a+1) .&& g1 `dvd` (2*b)
+
+                   -- Same for g2, for 2*a+1 and b
+                   ?? divides `at` (Inst @"a" (2*a+1), Inst @"b" b)
+                   =: g2 `dvd` (2*a+1) .&& g2 `dvd` b
+
+                   -- By arithmetic, g2 divides 2*b
+                   ?? dMul `at` (Inst @"d" g2, Inst @"a" b, Inst @"k" 2)
+                   =: g2 `dvd` (2*b)
+
+                   -- Observe that g1 must be odd
+                   ?? dOddThenOdd `at` (Inst @"d" g1, Inst @"a" a)
+                   =: isOdd g1
+
+                   -- Conclude that g1 must divide b
+                   ?? dEvenWhenOdd `at` (Inst @"d" g1, Inst @"a" b)
+                   =: g1 `dvd` b
+
+                   -- Now use largest to show g1 >= g2
+                   ?? largest `at` (Inst @"a" (2*a+1),  Inst @"b" (2*b), Inst @"x" g2)
+                   =: g1 .>= g2
+
+                   -- But again via largest, we can show g2 >= g1
+                   ?? largest `at` (Inst @"a" (2*a+1), Inst @"b" b, Inst @"x" g1)
+                   =: g2 .>= g1
+
+                   -- Finally conclude g1 = g2 since both are greater-than-equal to each other:
+                   =: g1 .== g2
+                   =: qed
+
+-- * GCD via subtraction
+
+-- | @nGCDSub@ is the original version of Euclid, which uses subtraction instead of modulus. This is the version that
+-- works on non-negative numbers. It has the precondition that @a >= b >= 0@, and maintains this invariant in each
+-- recursive call.
+nGCDSub :: SInteger -> SInteger -> SInteger
+nGCDSub = smtFunction "nGCDSub"
+        $ \a b -> [sCase| a of
+                     _ | a .== b -> a
+                     _ | a .<= 0 -> b
+                     _ | b .<= 0 -> a
+                     _ | a .> b  -> nGCDSub (a - b) b
+                     _           -> nGCDSub a (b - a)
+                  |]
+
+-- | Generalized version of subtraction based GCD, working over all integers.
+gcdSub :: SInteger -> SInteger -> SInteger
+gcdSub a b = nGCDSub (abs a) (abs b)
+
+-- | \(\mathrm{gcdSub}\, a\, b = \gcd\, a\, b\)
+--
+-- Instead of proving @gcdSub@ correct, we'll simply show that it is equivalent to @gcd@, hence it has
+-- all the properties we already established.
+--
+-- ==== __Proof__
+-- >>> runTP gcdSubEquiv
+-- Lemma: commutative                           Q.E.D.
+-- Lemma: gcdAdd                                Q.E.D.
+-- Inductive lemma (strong): nGCDSubEquiv
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (5 way case split)
+--     Step: 1.1                                Q.E.D.
+--     Step: 1.2                                Q.E.D.
+--     Step: 1.3                                Q.E.D.
+--     Step: 1.4.1                              Q.E.D.
+--     Step: 1.4.2                              Q.E.D.
+--     Step: 1.4.3                              Q.E.D.
+--     Step: 1.5.1                              Q.E.D.
+--     Step: 1.5.2                              Q.E.D.
+--     Step: 1.5.3                              Q.E.D.
+--     Step: 1.5.4                              Q.E.D.
+--     Step: 1.5.5                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Lemma: gcdSubEquiv
+--   Step: 1                                    Q.E.D.
+--   Step: 2                                    Q.E.D.
+--   Step: 3                                    Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: nGCD, nGCDSub
+-- [Proven] gcdSubEquiv :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdSubEquiv :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdSubEquiv = do
+
+   -- We'll be using the commutativity of GCD and the gcdAdd property
+   comm <- recall commutative
+   addG <- recall gcdAdd
+
+   -- First prove over the non-negative numbers:
+   nEq <- sInduct "nGCDSubEquiv"
+                  (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCDSub a b .== nGCD a b)
+                  (\a b -> a + b, []) $
+                  \ih a b -> [a .>= 0, b .>= 0]
+                          |- nGCDSub a b
+                          =: cases [ a .== b             ==> nGCD a b =: qed
+                                   , a .== 0             ==> nGCD a b =: qed
+                                   , b .== 0             ==> nGCD a b =: qed
+                                   , a .> b  .&& b ./= 0 ==> nGCDSub (a - b) b
+                                                          ?? ih
+                                                          =: nGCD (a - b) b
+                                                          ?? addG `at` (Inst @"a" (a - b), Inst @"b" b)
+                                                          =: nGCD a b
+                                                          =: qed
+                                   , a .< b  .&& a ./= 0 ==> nGCDSub a (b - a)
+                                                          ?? ih
+                                                          =: nGCD a (b - a)
+                                                          ?? comm
+                                                          =: nGCD (b - a) a
+                                                          ?? addG `at` (Inst @"a" (b - a), Inst @"b" a)
+                                                          =: nGCD b a
+                                                          ?? comm
+                                                          =: nGCD a b
+                                                          =: qed
+                                   ]
+
+   -- Now prove over all integers
+   calcWith cvc5 "gcdSubEquiv"
+         (\(Forall a) (Forall b) -> gcd a b .== gcdSub a b) $
+         \a b -> [] |- gcd a b
+                    =: nGCD (abs a) (abs b)
+                    ?? nEq `at` (Inst @"a" (abs a), Inst @"b" (abs b))
+                    =: nGCDSub (abs a) (abs b)
+                    =: gcdSub a b
+                    =: qed
+
+-- * Binary GCD
+
+-- | @nGCDBin@ is the binary GCD algorithm that works on non-negative numbers.
+nGCDBin :: SInteger -> SInteger -> SInteger
+nGCDBin = smtFunction "nGCDBin"
+        $ \a b -> [sCase| a of
+                     _ | a .<= 0               -> b
+                     _ | b .<= 0               -> a
+                     _ | isEven a .&& isEven b -> 2 * nGCDBin (a `sEDiv` 2) (b `sEDiv` 2)
+                     _ | isOdd  a .&& isEven b -> nGCDBin a (b `sEDiv` 2)
+                     _ | a .<= b               -> nGCDBin a (b - a)
+                     _                         -> nGCDBin (a - b) b
+                  |]
+-- | Generalized version that works on arbitrary integers.
+gcdBin :: SInteger -> SInteger -> SInteger
+gcdBin a b = nGCDBin (abs a) (abs b)
+
+-- | \(\mathrm{gcdBin}\, a\, b = \gcd\, a\, b\)
+--
+-- Instead of proving @gcdBin@ correct, we'll simply show that it is equivalent to @gcd@, hence it has
+-- all the properties we already established.
+--
+-- ==== __Proof__
+-- >>> runTP gcdBinEquiv
+-- Lemma: gcdEvenEven                           Q.E.D.
+-- Lemma: gcdOddEven                            Q.E.D.
+-- Lemma: gcdAdd                                Q.E.D.
+-- Lemma: commutative                           Q.E.D. [Cached]
+-- Inductive lemma (strong): nGCDBinEquiv
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (5 way case split)
+--     Step: 1.1                                Q.E.D.
+--     Step: 1.2                                Q.E.D.
+--     Step: 1.3.1                              Q.E.D.
+--     Step: 1.3.2                              Q.E.D.
+--     Step: 1.3.3                              Q.E.D.
+--     Step: 1.4.1                              Q.E.D.
+--     Step: 1.4.2                              Q.E.D.
+--     Step: 1.4.3                              Q.E.D.
+--     Step: 1.5 (3 way case split)
+--       Step: 1.5.1                            Q.E.D.
+--       Step: 1.5.2.1                          Q.E.D.
+--       Step: 1.5.2.2                          Q.E.D.
+--       Step: 1.5.2.3                          Q.E.D.
+--       Step: 1.5.2.4                          Q.E.D.
+--       Step: 1.5.2.5                          Q.E.D.
+--       Step: 1.5.2.6                          Q.E.D.
+--       Step: 1.5.3.1                          Q.E.D.
+--       Step: 1.5.3.2                          Q.E.D.
+--       Step: 1.5.3.3                          Q.E.D.
+--       Step: 1.5.3.4                          Q.E.D.
+--       Step: 1.5.Completeness                 Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Lemma: gcdBinEquiv
+--   Step: 1                                    Q.E.D.
+--   Step: 2                                    Q.E.D.
+--   Step: 3                                    Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: nGCD, nGCDBin
+-- [Proven] gcdBinEquiv :: Ɐa ∷ Integer → Ɐb ∷ Integer → Bool
+gcdBinEquiv :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> SBool))
+gcdBinEquiv = do
+   gEvenEven <- recallWith cvc5 gcdEvenEven
+   gOddEven  <- recall gcdOddEven
+   gAdd      <- recall gcdAdd
+   comm      <- recall commutative
+
+   -- First prove over the non-negative numbers:
+   nEq <- sInduct "nGCDBinEquiv"
+                  (\(Forall @"a" a) (Forall @"b" b) -> a .>= 0 .&& b .>= 0 .=> nGCDBin a b .== nGCD a b)
+                  (\a b -> tuple (a, b), []) $
+                  \ih a b -> [a .>= 0, b .>= 0]
+                          |- nGCDBin a b
+                          =: cases [ a .== 0               ==> trivial
+                                   , b .== 0               ==> trivial
+                                   , isEven a .&& isEven b ==> 2 * nGCDBin (a `sEDiv` 2) (b `sEDiv` 2)
+                                                            ?? ih `at` (Inst @"a" (a `sEDiv` 2), Inst @"b" (b `sEDiv` 2))
+                                                            =: 2 * nGCD (a `sEDiv` 2) (b `sEDiv` 2)
+                                                            ?? a .== 2 * a `sEDiv` 2
+                                                            ?? b .== 2 * b `sEDiv` 2
+                                                            ?? gEvenEven `at` (Inst @"a" (a `sEDiv` 2), Inst @"b" (b `sEDiv` 2))
+                                                            =: nGCD a b
+                                                            =: qed
+                                   , isOdd a  .&& isEven b ==> nGCDBin a (b `sEDiv` 2)
+                                                            ?? ih `at` (Inst @"a" a, Inst @"b" (b `sEDiv` 2))
+                                                            =: nGCD a (b `sEDiv` 2)
+                                                            ?? a .== 2 * ((a-1) `sEDiv` 2) + 1
+                                                            ?? b .== 2 * b `sEDiv` 2
+                                                            ?? gOddEven `at` (Inst @"a" ((a-1) `sEDiv` 2), Inst @"b" (b `sEDiv` 2))
+                                                            =: nGCD a b
+                                                            =: qed
+                                   , isOdd b               ==> cases [ a .== 0             ==> trivial
+                                                                     , a ./= 0 .&& a .<= b ==> nGCDBin a b
+                                                                                            =: nGCDBin a (b - a)
+                                                                                            ?? ih `at` (Inst @"a" a, Inst @"b" (b - a))
+                                                                                            =: nGCD a (b - a)
+                                                                                            ?? comm `at` (Inst @"a" a, Inst @"b" (b - a))
+                                                                                            =: nGCD (b - a) a
+                                                                                            ?? gAdd `at` (Inst @"a" (b - a), Inst @"b" a)
+                                                                                            =: nGCD b a
+                                                                                            ?? comm `at` (Inst @"a" b, Inst @"b" a)
+                                                                                            =: nGCD a b
+                                                                                            =: qed
+                                                                     , a .>  b             ==> nGCDBin a b
+                                                                                            =: nGCDBin (a - b) b
+                                                                                            ?? ih `at` (Inst @"a" (a - b), Inst @"b" b)
+                                                                                            =: nGCD (a - b) b
+                                                                                            ?? gAdd `at` (Inst @"a" a, Inst @"b" (-b))
+                                                                                            =: nGCD a b
+                                                                                            =: qed
+                                                                     ]
+                                   ]
+
+   -- Now prove over all integers
+   calcWith cvc5 "gcdBinEquiv"
+         (\(Forall a) (Forall b) -> gcd a b .== gcdBin a b) $
+         \a b -> [] |- gcd a b
+                    =: nGCD (abs a) (abs b)
+                    ?? nEq `at` (Inst @"a" (abs a), Inst @"b" (abs b))
+                    =: nGCDBin (abs a) (abs b)
+                    =: gcdBin a b
+                    =: qed
+
+{- HLint ignore gcdSubEquiv "Avoid lambda" -}
+{- HLint ignore gcdBinEquiv "Use curry"    -}
diff --git a/Documentation/SBV/Examples/TP/InsertionSort.hs b/Documentation/SBV/Examples/TP/InsertionSort.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/InsertionSort.hs
@@ -0,0 +1,225 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.InsertionSort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving insertion sort correct.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.InsertionSort where
+
+import Prelude hiding (null, length, head, tail, elem)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+import qualified Documentation.SBV.Examples.TP.SortHelpers as SH
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+#endif
+
+-- * Insertion sort
+
+-- | Insert an element into an already sorted list in the correct place.
+insert :: (OrdSymbolic (SBV a), SymVal a) => SBV a -> SList a -> SList a
+insert = smtFunction "insert"
+       $ \e l -> [sCase| l of
+                     []               -> [e]
+                     x : xs | e .<= x -> e .: x .: xs
+                            | True    -> x .: insert e xs
+                 |]
+
+-- | Insertion sort, using 'insert' above to successively insert the elements.
+insertionSort :: (OrdSymbolic (SBV a), SymVal a) => SList a -> SList a
+insertionSort = smtFunction "insertionSort"
+              $ \l -> [sCase| l of
+                          []     -> []
+                          x : xs -> insert x (insertionSort xs)
+                      |]
+
+
+-- | Remove the first occurrence of an number from a list, if any.
+removeFirst :: (Eq a, SymVal a) => SBV a -> SList a -> SList a
+removeFirst = smtFunction "removeFirst"
+            $ \e l -> [sCase| l of
+                          []               -> []
+                          x : xs | e .== x -> xs
+                                 | True    -> x .: removeFirst e xs
+                      |]
+
+-- | Are two lists permutations of each other? Note that we diverge from the counting
+-- based definition of permutation here, since this variant works better with insertion sort.
+isPermutation :: (Eq a, SymVal a) => SList a -> SList a -> SBool
+isPermutation = smtFunction "isPermutation"
+              $ \l r -> [sCase| l of
+                            []     -> null r
+                            x : xs -> x `elem` r .&& isPermutation xs (removeFirst x r)
+                        |]
+
+-- * Correctness proof
+
+-- | Correctness of insertion-sort. z3 struggles with this, but CVC5 proves it just fine.
+--
+-- We have:
+--
+-- >>> correctness @Integer
+-- Lemma: nonDecrTail                          Q.E.D.
+-- Inductive lemma: insertNonDecreasing
+--   Step: Base                                Q.E.D.
+--   Step: 1 (unfold insert)                   Q.E.D.
+--   Step: 2 (push nonDecreasing down)         Q.E.D.
+--   Step: 3 (unfold simplify)                 Q.E.D.
+--   Step: 4                                   Q.E.D.
+--   Step: 5                                   Q.E.D.
+--   Result:                                   Q.E.D.
+-- Inductive lemma: sortNonDecreasing
+--   Step: Base                                Q.E.D.
+--   Step: 1 (unfold insertionSort)            Q.E.D.
+--   Step: 2                                   Q.E.D.
+--   Result:                                   Q.E.D.
+-- Inductive lemma: insertIsElem
+--   Step: Base                                Q.E.D.
+--   Step: 1                                   Q.E.D.
+--   Step: 2                                   Q.E.D.
+--   Step: 3                                   Q.E.D.
+--   Step: 4                                   Q.E.D.
+--   Result:                                   Q.E.D.
+-- Inductive lemma: removeAfterInsert
+--   Step: Base                                Q.E.D.
+--   Step: 1 (expand insert)                   Q.E.D.
+--   Step: 2 (push removeFirst down ite)       Q.E.D.
+--   Step: 3 (unfold removeFirst on 'then')    Q.E.D.
+--   Step: 4 (unfold removeFirst on 'else')    Q.E.D.
+--   Step: 5                                   Q.E.D.
+--   Step: 6 (simplify)                        Q.E.D.
+--   Result:                                   Q.E.D.
+-- Inductive lemma: sortIsPermutation
+--   Step: Base                                Q.E.D.
+--   Step: 1                                   Q.E.D.
+--   Step: 2                                   Q.E.D.
+--   Step: 3                                   Q.E.D.
+--   Step: 4                                   Q.E.D.
+--   Step: 5                                   Q.E.D.
+--   Result:                                   Q.E.D.
+-- Lemma: insertionSortIsCorrect               Q.E.D.
+-- Functions proven terminating: insert, insertionSort, isPermutation, nonDecreasing, removeFirst
+-- [Proven] insertionSortIsCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. (OrdSymbolic (SBV a), Eq a, SymVal a) => IO (Proof (Forall "xs" [a] -> SBool))
+correctness = runTPWith cvc5 $ do
+
+    --------------------------------------------------------------------------------------------
+    -- Part I. Import helper lemmas, definitions
+    --------------------------------------------------------------------------------------------
+    let nonDecreasing = SH.nonDecreasing @a
+
+    nonDecrTail <- SH.nonDecrTail @a
+
+    --------------------------------------------------------------------------------------------
+    -- Part II. Prove that the output of insertion sort is non-decreasing.
+    --------------------------------------------------------------------------------------------
+
+    insertNonDecreasing <-
+        induct "insertNonDecreasing"
+               (\(Forall xs) (Forall e) -> nonDecreasing xs .=> nonDecreasing (insert e xs)) $
+               \ih (x, xs) e -> [nonDecreasing (x .: xs)]
+                             |- nonDecreasing (insert e (x .: xs))
+                             ?? "unfold insert"
+                             =: nonDecreasing (ite (e .<= x) (e .: x .: xs) (x .: insert e xs))
+                             ?? "push nonDecreasing down"
+                             =: ite (e .<= x) (nonDecreasing (e .: x .: xs))
+                                              (nonDecreasing (x .: insert e xs))
+                             ?? "unfold simplify"
+                             =: ite (e .<= x)
+                                    (nonDecreasing (x .: xs))
+                                    (nonDecreasing (x .: insert e xs))
+                             ?? nonDecreasing (x .: xs)
+                             =: (e .> x .=> nonDecreasing (x .: insert e xs))
+                             ?? nonDecrTail `at` (Inst @"x" x, Inst @"xs" (insert e xs))
+                             ?? ih
+                             =: sTrue
+                             =: qed
+
+    sortNonDecreasing <-
+        induct "sortNonDecreasing"
+               (\(Forall @"xs" xs) -> nonDecreasing (insertionSort xs)) $
+               \ih (x, xs) -> [] |- nonDecreasing (insertionSort (x .: xs))
+                                 ?? "unfold insertionSort"
+                                 =: nonDecreasing (insert x (insertionSort xs))
+                                 ?? insertNonDecreasing `at` (Inst @"xs" (insertionSort xs), Inst @"e" x)
+                                 ?? ih
+                                 =: sTrue
+                                 =: qed
+
+    --------------------------------------------------------------------------------------------
+    -- Part III. Prove that the output of insertion sort is a permutation of its input
+    --------------------------------------------------------------------------------------------
+
+    insertIsElem <-
+        induct "insertIsElem"
+               (\(Forall @"xs" xs) (Forall @"e" (e :: SBV a)) -> e `elem` insert e xs) $
+               \ih (x, xs) e -> [] |- e `elem` insert e (x .: xs)
+                                   =: e `elem` ite (e .<= x) (e .: x .: xs) (x .: insert e xs)
+                                   =: ite (e .<= x) (e `elem` (e .: x .: xs)) (e `elem` (x .: insert e xs))
+                                   =: ite (e .<= x) sTrue (e `elem` insert e xs)
+                                   ?? ih
+                                   =: sTrue
+                                   =: qed
+
+    removeAfterInsert <-
+        induct "removeAfterInsert"
+               (\(Forall @"xs" xs) (Forall @"e" (e :: SBV a)) -> removeFirst e (insert e xs) .== xs) $
+               \ih (x, xs) e ->
+                   [] |- removeFirst e (insert e (x .: xs))
+                      ?? "expand insert"
+                      =: removeFirst e (ite (e .<= x) (e .: x .: xs) (x .: insert e xs))
+                      ?? "push removeFirst down ite"
+                      =: ite (e .<= x) (removeFirst e (e .: x .: xs)) (removeFirst e (x .: insert e xs))
+                      ?? "unfold removeFirst on 'then'"
+                      =: ite (e .<= x) (x .: xs) (removeFirst e (x .: insert e xs))
+                      ?? "unfold removeFirst on 'else'"
+                      =: ite (e .<= x) (x .: xs) (x .: removeFirst e (insert e xs))
+                      ?? ih
+                      =: ite (e .<= x) (x .: xs) (x .: xs)
+                      ?? "simplify"
+                      =: x .: xs
+                      =: qed
+
+    sortIsPermutation <-
+        induct "sortIsPermutation"
+               (\(Forall @"xs" (xs :: SList a)) -> isPermutation xs (insertionSort xs)) $
+               \ih (x, xs) ->
+                   [] |- isPermutation (x .: xs) (insertionSort (x .: xs))
+                      =: isPermutation (x .: xs) (insert x (insertionSort xs))
+                      =:     x `elem` insert x (insertionSort xs)
+                         .&& isPermutation xs (removeFirst x (insert x (insertionSort xs)))
+                      ?? insertIsElem
+                      =: isPermutation xs (removeFirst x (insert x (insertionSort xs)))
+                      ?? removeAfterInsert
+                      =: isPermutation xs (insertionSort xs)
+                      ?? ih
+                      =: sTrue
+                      =: qed
+
+    --------------------------------------------------------------------------------------------
+    -- Put the two parts together for the final proof
+    --------------------------------------------------------------------------------------------
+    lemma "insertionSortIsCorrect"
+          (\(Forall xs) -> let out = insertionSort xs in nonDecreasing out .&& isPermutation xs out)
+          [proofOf sortNonDecreasing, proofOf sortIsPermutation]
diff --git a/Documentation/SBV/Examples/TP/Kadane.hs b/Documentation/SBV/Examples/TP/Kadane.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Kadane.hs
@@ -0,0 +1,175 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Kadane
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving the correctness of Kadane's algorithm for computing the maximum
+-- sum of any contiguous list (maximum segment sum problem).
+--
+-- Kadane's algorithm is a classic dynamic programming algorithm that solves
+-- the maximum segment sum problem in O(n) time. Given a list of integers,
+-- it finds the maximum sum of any contiguous list, where the empty
+-- list has sum 0.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Kadane where
+
+import Prelude hiding (length, maximum, null, head, tail, (++))
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+-- >>> :set -XOverloadedLists
+#endif
+
+-- * Problem specification
+
+-- | The maximum segment sum problem: Find the maximum sum of any contiguous
+-- subarray. We include the empty subarray (with sum 0) as a valid segment.
+-- This is the obvious definition: Empty list maps to 0. Otherwise, we take the
+-- value of the segment starting at the current position, and take the maximum
+-- of that value with the recursive result of the tail. This is obviously
+-- correct, but has the runtime of O(n^2).
+--
+-- We have:
+--
+-- >>> mss [1, -2, 3, 4, -1, 2]  -- the segment: [3, 4, -1, 2]
+-- 8 :: SInteger
+-- >>> mss [-2, -3, -1]          -- empty segment
+-- 0 :: SInteger
+-- >>> mss [1, 2, 3]             -- the whole list
+-- 6 :: SInteger
+mss :: SList Integer -> SInteger
+mss = smtFunction "mss"
+    $ \xs -> [sCase| xs of
+                 []    -> 0
+                 _ : t -> mssBegin xs `smax` mss t
+             |]
+
+-- | Maximum sum of segments starting at the beginning of the given list.
+-- This is 0 if the empty segment is best, or positive if a non-empty prefix exists.
+--
+-- We have:
+--
+-- >>> mssBegin [1, -2, 3, 4, -1, 2]  -- the segment: [1, -2, 3, 4, -1, 2]
+-- 7 :: SInteger
+-- >>> mssBegin [-2, -3, -1]          -- empty segment
+-- 0 :: SInteger
+-- >>> mssBegin [1, 2, 3]             -- the whole list
+-- 6 :: SInteger
+mssBegin :: SList Integer -> SInteger
+mssBegin = smtFunction "mssBegin"
+         $ \xs -> [sCase| xs of
+                      []    -> 0
+                      h : t -> 0 `smax` (h `smax` (h + mssBegin t))
+                  |]
+
+-- * Kadane's algorithm implementation
+
+-- | Kadane algorithm: We call the helper with the values of maximum value ending
+-- at the beginning and the list, and recurse.
+--
+-- >>> kadane [1, -2, 3, 4, -1, 2]  -- the segment: [3, 4, -1, 2]
+-- 8 :: SInteger
+-- >>> kadane [-2, -3, -1]          -- empty segment
+-- 0 :: SInteger
+-- >>> kadane [1, 2, 3]             -- the whole list
+-- 6 :: SInteger
+kadane :: SList Integer -> SInteger
+kadane xs = kadaneHelper xs 0 0
+
+-- | Helper for Kadane's algorithm. Along with the list, we keep track of the maximum-value
+-- ending at the beginning of the list argument, and the maximum value sofar.
+kadaneHelper :: SList Integer -> SInteger -> SInteger -> SInteger
+kadaneHelper = smtFunction "kadaneHelper"
+             $ \xs maxEndingHere maxSoFar ->
+                  [sCase| xs of
+                      []    -> maxSoFar
+                      h : t -> let newMaxEndingHere = 0 `smax` (h + maxEndingHere)
+                                   newMaxSofar      = maxSoFar `smax` newMaxEndingHere
+                               in kadaneHelper t newMaxEndingHere newMaxSofar
+                  |]
+
+-- * Correctness proof
+
+-- | The key insight is that we need a generalized invariant that characterizes
+-- @kadaneHelper@ for arbitrary accumulator values, not just the initial @(0, 0)@.
+--
+-- The invariant states: for @kadaneHelper xs meh msf@ where:
+--
+--   * @meh@ (max-ending-here) is the maximum sum of a segment ending at the boundary
+--   * @msf@ (max-so-far) is the best segment sum seen in the already-processed prefix
+--   * Preconditions: @meh >= 0@ and @msf >= meh@
+--
+-- @
+--   kadaneHelper xs meh msf == msf `smax` mss xs `smax` (meh + mssBegin xs)
+-- @
+--
+-- This captures that the result is the maximum of:
+--
+--   * @msf@ - the best segment entirely in the already-processed prefix
+--   * @mss xs@ - the best segment entirely in the remaining suffix
+--   * @meh + mssBegin xs@ - the best segment crossing the boundary
+--
+-- >>> runTPWith cvc5 correctness
+-- Inductive lemma: kadaneHelperInvariant
+--   Step: Base                              Q.E.D.
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Lemma: correctness
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Step: 3                                 Q.E.D.
+--   Step: 4                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Functions proven terminating: kadaneHelper, mss, mssBegin
+-- [Proven] correctness :: Ɐxs ∷ [Integer] → Bool
+correctness :: TP (Proof (Forall "xs" [Integer] -> SBool))
+correctness = do
+
+  -- First, prove the generalized invariant. This is the heart of the proof: it relates kadaneHelper with arbitrary
+  -- accumulators to the specification functions mss and mssBegin.
+  invariant <- induct "kadaneHelperInvariant"
+      (\(Forall xs) (Forall meh) (Forall msf) ->
+         (meh .>= 0 .&& msf .>= meh) .=> kadaneHelper xs meh msf .== (msf `smax` mss xs `smax` (meh + mssBegin xs))) $
+      \ih (a, as) meh msf ->
+         [meh .>= 0, msf .>= meh] |- let newMeh = 0 `smax` (a + meh)
+                                         newMsf = msf `smax` newMeh
+                                     in kadaneHelper (a .: as) meh msf
+                                     =: kadaneHelper as newMeh newMsf
+                                     ?? ih `at` (Inst @"meh" newMeh, Inst @"msf" newMsf)
+                                     =: newMsf `smax` mss as `smax` (newMeh + mssBegin as)
+                                     =: qed
+
+  -- Now the main theorem follows easily: kadane xs = kadaneHelper xs 0 0
+  -- and with meh=0, msf=0, the invariant gives us:
+  --   kadaneHelper xs 0 0 = 0 `smax` mss xs `smax` (0 + mssBegin xs)
+  --                       = mss xs `smax` mssBegin xs
+  --                       = mss xs  (since mss xs >= mssBegin xs by definition)
+  calc "correctness"
+       (\(Forall xs) -> mss xs .== kadane xs) $
+       \xs -> [] |- kadane xs
+                 =: kadaneHelper xs 0 0
+                 ?? invariant `at` (Inst @"xs" xs, Inst @"meh" (0 :: SInteger), Inst @"msf" (0 :: SInteger))
+                 =: 0 `smax` mss xs `smax` (0 + mssBegin xs)
+                 =: mss xs `smax` mssBegin xs
+                 -- mss xs >= mssBegin xs by definition (mss considers all segments)
+                 =: mss xs
+                 =: qed
diff --git a/Documentation/SBV/Examples/TP/Kleene.hs b/Documentation/SBV/Examples/TP/Kleene.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Kleene.hs
@@ -0,0 +1,140 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Kleene
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Example use of the TP layer, proving some Kleene algebra theorems.
+--
+-- Based on <http://www.philipzucker.com/bryzzowski_kat/>
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-unused-matches #-}
+
+module Documentation.SBV.Examples.TP.Kleene where
+
+import Prelude hiding((<=))
+
+import Data.SBV
+import Data.SBV.TP
+
+-- | An uninterpreted sort, corresponding to the type of Kleene algebra strings.
+data Kleene
+mkSymbolic [''Kleene]
+
+-- | Star operator over kleene algebras. We're leaving this uninterpreted.
+star :: SKleene -> SKleene
+star = uninterpret "STAR"
+
+-- | The 'Num' instance for Kleene makes it easy to write regular expressions
+-- in the more familiar form.
+instance Num SKleene where
+  (+) = uninterpret "PAR"
+  (*) = uninterpret "SEQ"
+
+  abs    = error "SKleene: not defined: abs"
+  signum = error "SKleene: not defined: signum"
+  negate = error "SKleene: not defined: signum"
+
+  fromInteger 0 = uninterpret "zero"
+  fromInteger 1 = uninterpret "one"
+  fromInteger n = error $ "SKleene: not defined: fromInteger " ++ show n
+
+-- | The set of strings matched by one regular expression is a subset of the second,
+-- if adding it to the second doesn't change the second set.
+(<=) :: SKleene -> SKleene -> SBool
+x <= y = x + y .== y
+
+-- | A sequence of Kleene algebra proofs. See <http://www.cs.cornell.edu/~kozen/Papers/ka.pdf>
+--
+-- We have:
+--
+-- >>> kleeneProofs
+-- Axiom: par_assoc
+-- Axiom: par_comm
+-- Axiom: par_idem
+-- Axiom: par_zero
+-- Axiom: seq_assoc
+-- Axiom: seq_zero
+-- Axiom: seq_one
+-- Axiom: rdistrib
+-- Axiom: ldistrib
+-- Axiom: unfold
+-- Axiom: least_fix
+-- Lemma: par_lzero                     Q.E.D.
+-- Lemma: par_monotone                  Q.E.D.
+-- Lemma: seq_monotone                  Q.E.D.
+-- Lemma: star_star_1
+--   Step: 1 (unfold)                   Q.E.D.
+--   Step: 2 (factor out x * star x)    Q.E.D.
+--   Step: 3 (par_idem)                 Q.E.D.
+--   Step: 4 (unfold)                   Q.E.D.
+--   Result:                            Q.E.D.
+-- Lemma: subset_eq                     Q.E.D.
+-- Lemma: star_star_2_2                 Q.E.D.
+-- Lemma: star_star_2_3                 Q.E.D.
+-- Lemma: star_star_2_1                 Q.E.D.
+-- Lemma: star_star_2                   Q.E.D.
+kleeneProofs :: IO ()
+kleeneProofs = runTP $ do
+
+  -- Kozen axioms
+  par_assoc <- axiom "par_assoc" $ \(Forall @"x" (x :: SKleene)) (Forall @"y" y) (Forall @"z" z) -> x + (y + z) .== (x + y) + z
+  par_comm  <- axiom "par_comm"  $ \(Forall @"x" (x :: SKleene)) (Forall @"y" y)                 -> x + y       .== y + x
+  par_idem  <- axiom "par_idem"  $ \(Forall @"x" (x :: SKleene))                                 -> x + x       .== x
+  par_zero  <- axiom "par_zero"  $ \(Forall @"x" (x :: SKleene))                                 -> x + 0       .== x
+
+  seq_assoc <- axiom "seq_assoc" $ \(Forall @"x" (x :: SKleene)) (Forall @"y" y) (Forall @"z" z) -> x * (y * z) .== (x * y) * z
+  seq_zero  <- axiom "seq_zero"  $ \(Forall @"x" (x :: SKleene))                                 -> x * 0       .== 0
+  seq_one   <- axiom "seq_one"   $ \(Forall @"x" (x :: SKleene))                                 -> x * 1       .== x
+
+  rdistrib  <- axiom "rdistrib"  $ \(Forall @"x" (x :: SKleene)) (Forall @"y" y) (Forall @"z" z) -> x * (y + z) .== x * y + x * z
+  ldistrib  <- axiom "ldistrib"  $ \(Forall @"x" (x :: SKleene)) (Forall @"y" y) (Forall @"z" z) -> (y + z) * x .== y * x + z * x
+
+  unfold    <- axiom "unfold"    $ \(Forall @"e" e) -> star e .== 1 + e * star e
+
+  least_fix <- axiom "least_fix" $ \(Forall @"x" x) (Forall @"e" e) (Forall @"f" f) -> ((f + e * x) <= x) .=> ((star e * f) <= x)
+
+  -- Collect the basic axioms in a list for easy reference
+  let kleene = [ proofOf par_assoc,  proofOf par_comm, proofOf par_idem, proofOf par_zero
+               , proofOf seq_assoc,  proofOf seq_zero, proofOf seq_one
+               , proofOf ldistrib,   proofOf rdistrib
+               , proofOf unfold
+               , proofOf least_fix
+               ]
+
+  -- Various proofs:
+  par_lzero    <- lemma "par_lzero"    (\(Forall @"x" x) -> (0 :: SKleene) + x .== x)                                        kleene
+  par_monotone <- lemma "par_monotone" (\(Forall @"x" x) (Forall @"y" y) (Forall @"z" z) -> x <= y .=> ((x + z) <= (y + z))) kleene
+  seq_monotone <- lemma "seq_monotone" (\(Forall @"x" x) (Forall @"y" y) (Forall @"z" z) -> x <= y .=> ((x * z) <= (y * z))) kleene
+
+  -- This one requires a chain of reasoning: x* x* == x*
+  star_star_1  <- calc "star_star_1"
+                       (\(Forall @"x" x) -> star x * star x .== star x) $
+                       \x -> [] |- star x * star x                     ?? unfold
+                                =: (1 + x * star x) * (1 + x * star x)
+                                ?? "factor out x * star x"
+                                ?? kleene
+                                =: (1 + 1) + (x * star x + x * star x) ?? par_idem
+                                =: 1 + x * star x                      ?? unfold
+                                =: star x
+                                =: qed
+
+  subset_eq   <- lemma "subset_eq" (\(Forall @"x" x) (Forall @"y" y) -> (x .== y) .== (x <= y .&& y <= x)) kleene
+
+  -- Prove: x** = x*
+  star_star_2 <- do _1 <- lemma "star_star_2_2" (\(Forall @"x" x) -> ((star x * star x + 1) <= star x) .=> star (star x) <= star x) kleene
+                    _2 <- lemma "star_star_2_3" (\(Forall @"x" x) -> star (star x) <= star x)                                       (kleene ++ [proofOf _1])
+                    _3 <- lemma "star_star_2_1" (\(Forall @"x" x) -> star x        <= star (star x))                                kleene
+
+                    lemma "star_star_2" (\(Forall @"x" x) -> star (star x) .== star x) [proofOf subset_eq, proofOf _2, proofOf _3]
+
+  pure ()
diff --git a/Documentation/SBV/Examples/TP/Lists.hs b/Documentation/SBV/Examples/TP/Lists.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Lists.hs
@@ -0,0 +1,2064 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Lists
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A variety of TP proofs on list processing functions. Note that
+-- these proofs only hold for finite lists. SMT-solvers do not model infinite
+-- lists, and hence all claims are for finite (but arbitrary-length) lists.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Lists (
+     -- * Append
+     appendNull, consApp, appendAssoc, initsLength, tailsLength, tailsAppend
+
+     -- * Reverse
+   , revLen, revApp, revCons, revSnoc, revRev, enumLen, revNM
+
+     -- * Length
+   , lengthTail, lenAppend, lenAppend2
+
+     -- * Replicate
+   , replicateLength
+
+     -- * All and any
+   , allAny
+
+     -- * Map
+   , mapEquiv, mapAppend, mapReverse, mapCompose, mapConcat
+
+     -- * Foldr and foldl
+   , foldrMapFusion, foldrFusion, foldrOverAppend, foldlOverAppend, foldrFoldlDuality, foldrFoldlDualityGeneralized, foldrFoldl
+   , bookKeeping
+
+     -- * Filter
+   , filterAppend, filterConcat, takeDropWhile
+
+     -- * Stutter removal
+   , destutter, destutterIdempotent
+
+     -- * Difference
+   , appendDiff, diffAppend, diffDiff
+
+     -- * Partition
+   , partition1, partition2
+
+    -- * Take and drop
+   , take_take, drop_drop, take_drop, take_cons, take_map, drop_cons, drop_map, length_take, length_drop, take_all, drop_all
+   , take_append, drop_append
+
+   -- * Zip
+   , map_fst_zip
+   , map_snd_zip
+   , map_fst_zip_take
+   , map_snd_zip_take
+
+   -- * Counting elements
+   , count, countOneStep, countAppend, takeDropCount, countNonNeg, countElem, elemCount
+
+   -- * Disjointness
+   , disjoint, disjointDiff
+
+   -- * Interleaving
+   , interleave, uninterleave, interleaveLen, interleaveRoundTrip
+ ) where
+
+import Prelude (Integer, Bool, Eq, ($), Num(..), id, (.), flip)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XScopedTypeVariables
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+-- >>> import Control.Exception
+#endif
+
+-- | @xs ++ [] == xs@
+--
+-- >>> runTP $ appendNull @Integer
+-- Lemma: appendNull    Q.E.D.
+-- [Proven] appendNull :: Ɐxs ∷ [Integer] → Bool
+appendNull :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+appendNull = lemma "appendNull"
+                   (\(Forall xs) -> xs ++ [] .== xs)
+                   []
+
+-- | @(x : xs) ++ ys == x : (xs ++ ys)@
+--
+-- >>> runTP $ consApp @Integer
+-- Lemma: consApp      Q.E.D.
+-- [Proven] consApp :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+consApp :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+consApp = lemma "consApp"
+                (\(Forall x) (Forall xs) (Forall ys) -> (x .: xs) ++ ys .== x .: (xs ++ ys))
+                []
+
+-- | @(xs ++ ys) ++ zs == xs ++ (ys ++ zs)@
+--
+-- >>> runTP $ appendAssoc @Integer
+-- Lemma: appendAssoc    Q.E.D.
+-- [Proven] appendAssoc :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐzs ∷ [Integer] → Bool
+--
+-- Surprisingly, z3 can prove this without any induction. (Since SBV's append translates directly to
+-- the concatenation of sequences in SMTLib, it must trigger an internal heuristic in z3
+-- that proves it right out-of-the-box!)
+appendAssoc :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "zs" [a] -> SBool))
+appendAssoc =
+   lemma "appendAssoc"
+         (\(Forall xs) (Forall ys) (Forall zs) -> xs ++ (ys ++ zs) .== (xs ++ ys) ++ zs)
+         []
+
+-- | @length (inits xs) == 1 + length xs@
+--
+-- >>> runTP $ initsLength @Integer
+-- Inductive lemma (strong): initsLength
+--   Step: Measure is non-negative          Q.E.D.
+--   Step: 1                                Q.E.D.
+--   Result:                                Q.E.D.
+-- Functions proven terminating: sbv.inits
+-- [Proven] initsLength :: Ɐxs ∷ [Integer] → Bool
+initsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+initsLength =
+   sInduct "initsLength"
+           (\(Forall xs) -> length (inits xs) .== 1 + length xs)
+           (length @a, []) $
+           \ih xs -> [] |- length (inits xs)
+                        ?? ih
+                        =: 1 + length xs
+                        =: qed
+
+-- | @length (tails xs) == 1 + length xs@
+--
+-- >>> runTP $ tailsLength @Integer
+-- Inductive lemma: tailsLength
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: sbv.tails
+-- [Proven] tailsLength :: Ɐxs ∷ [Integer] → Bool
+tailsLength :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+tailsLength =
+   induct "tailsLength"
+          (\(Forall xs) -> length (tails xs) .== 1 + length xs) $
+          \ih (x, xs) -> [] |- length (tails (x .: xs))
+                            =: length (tails xs ++ [x .: xs])
+                            =: length (tails xs) + 1
+                            ?? ih
+                            =: 1 + length xs + 1
+                            =: 1 + length (x .: xs)
+                            =: qed
+
+-- | @tails (xs ++ ys) == map (++ ys) (tails xs) ++ tail (tails ys)@
+--
+-- This property comes from Richard Bird's "Pearls of functional Algorithm Design" book, chapter 2.
+-- Note that it is not exactly as stated there, as the definition of @tails@ Bird uses is different
+-- than the standard Haskell function @tails@: Bird's version does not return the empty list as the
+-- tail. So, we slightly modify it to fit the standard definition. (NB. z3 is finicky on this
+-- problem, while cvc5 works much better.)
+--
+-- >>> runTPWith cvc5 $ tailsAppend @Integer
+-- Inductive lemma: base case
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: helper
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: tailsAppend
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: sbv.closureMap, sbv.tails
+-- [Proven] tailsAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+tailsAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+tailsAppend = do
+
+   let -- Ideally, we would like to define appendEach like this:
+       --
+       --       appendEach xs ys = map (++ ys) xs
+       --
+       -- But capture of ys is not allowed when we use the higher-order
+       -- function map in SBV. So, we create a closure instead.
+       appendEach :: SList a -> SList [a] -> SList [a]
+       appendEach ys = map $ Closure { closureEnv = ys
+                                     , closureFun = \env xs -> xs ++ env
+                                     }
+
+   -- Even proving the base case of induction is hard due to recursive definition. So we first prove the base case by induction.
+   bc <- induct "base case"
+                (\(Forall @"ys" (ys :: SList a)) -> tails ys .== [ys] ++ tail (tails ys)) $
+                \ih (y, ys) -> [] |- tails (y .: ys)
+                                  =: [y .: ys] ++ tails ys
+                                  ?? ih
+                                  =: [y .: ys] ++ [ys] ++ tail (tails ys)
+                                  =: [y .: ys] ++ tail (tails (y .: ys))
+                                  =: qed
+
+   -- Also need a helper to relate how appendEach and tails work together
+   helper <- calc "helper"
+                   (\(Forall @"xs" xs) (Forall @"ys" ys) (Forall @"x" x) ->
+                        appendEach ys (tails (x .: xs)) .== [(x .: xs) ++ ys] ++ appendEach ys (tails xs)) $
+                   \xs ys x -> [] |- appendEach ys (tails (x .: xs))
+                                  =: appendEach ys ([x .: xs] ++ tails xs)
+                                  =: [(x .: xs) ++ ys] ++ appendEach ys (tails xs)
+                                  =: qed
+
+   induct "tailsAppend"
+          (\(Forall xs) (Forall ys) -> tails (xs ++ ys) .== appendEach ys (tails xs) ++ tail (tails ys)) $
+          \ih (x, xs) ys -> [assumptionFromProof bc]
+                         |- tails ((x .: xs) ++ ys)
+                         =: tails (x .: (xs ++ ys))
+                         =: [x .: (xs ++ ys)] ++ tails (xs ++ ys)
+                         ?? ih
+                         =: [(x .: xs) ++ ys] ++ appendEach ys (tails xs) ++ tail (tails ys)
+                         ?? helper
+                         =: appendEach ys (tails (x .: xs)) ++ tail (tails ys)
+                         =: qed
+
+-- | @length xs == length (reverse xs)@
+--
+-- >>> runTP $ revLen @Integer
+-- Inductive lemma: revLen
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] revLen :: Ɐxs ∷ [Integer] → Bool
+revLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+revLen = induct "revLen"
+                (\(Forall xs) -> length (reverse xs) .== length xs) $
+                \ih (x, xs) -> [] |- length (reverse (x .: xs))
+                                  =: length (reverse xs ++ [x])
+                                  =: length (reverse xs) + length [x]
+                                  ?? ih
+                                  =: length xs + 1
+                                  =: length (x .: xs)
+                                  =: qed
+
+-- | @reverse (xs ++ ys) .== reverse ys ++ reverse xs@
+--
+-- >>> runTP $ revApp @Integer
+-- Inductive lemma: revApp
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Step: 5                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] revApp :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+revApp :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+revApp = induct "revApp"
+                 (\(Forall xs) (Forall ys) -> reverse (xs ++ ys) .== reverse ys ++ reverse xs) $
+                 \ih (x, xs) ys -> [] |- reverse ((x .: xs) ++ ys)
+                                      =: reverse (x .: (xs ++ ys))
+                                      =: reverse (xs ++ ys) ++ [x]
+                                      ?? ih
+                                      =: (reverse ys ++ reverse xs) ++ [x]
+                                      =: reverse ys ++ (reverse xs ++ [x])
+                                      =: reverse ys ++ reverse (x .: xs)
+                                      =: qed
+
+-- | @reverse (x:xs) == reverse xs ++ [x]@
+--
+-- >>> runTP $ revCons @Integer
+-- Lemma: revCons      Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] revCons :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+revCons :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
+revCons = lemma "revCons"
+                (\(Forall x) (Forall xs) -> reverse (x .: xs) .== reverse xs ++ [x])
+                []
+
+-- | @reverse (xs ++ [x]) == x : reverse xs@
+--
+-- >>> runTP $ revSnoc @Integer
+-- Inductive lemma: revApp
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Step: 5                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Lemma: revSnoc             Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] revSnoc :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+revSnoc :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
+revSnoc = do
+   ra <- revApp @a
+
+   lemma "revSnoc"
+         (\(Forall x) (Forall xs) -> reverse (xs ++ [x]) .== x .: reverse xs)
+         [proofOf ra]
+
+-- | @reverse (reverse xs) == xs@
+--
+-- >>> runTP $ revRev @Integer
+-- Inductive lemma: revApp
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Step: 5                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Inductive lemma: revRev
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] revRev :: Ɐxs ∷ [Integer] → Bool
+revRev :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+revRev = do
+
+   ra <- revApp @a
+
+   induct "revRev"
+          (\(Forall xs) -> reverse (reverse xs) .== xs) $
+          \ih (x, xs) -> [] |- reverse (reverse (x .: xs))
+                            =: reverse (reverse xs ++ [x])
+                            ?? ra
+                            =: reverse [x] ++ reverse (reverse xs)
+                            ?? ih
+                            =: [x] ++ xs
+                            =: x .: xs
+                            =: qed
+
+-- | \(\mathit{length } [n \dots m] = \max(0,\; m - n + 1)\)
+--
+-- The proof uses the metric @|m-n|@.
+--
+-- >>> runTP enumLen
+-- Inductive lemma (strong): enumLen
+--   Step: Measure is non-negative      Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2.1                      Q.E.D.
+--     Step: 1.2.2                      Q.E.D.
+--     Step: 1.2.3                      Q.E.D.
+--     Step: 1.2.4                      Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: EnumSymbolic.Integer.enumFromThenTo.up
+-- [Proven] enumLen :: Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
+enumLen :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
+enumLen =
+  sInduct "enumLen"
+          (\(Forall n) (Forall m) -> length [sEnum|n .. m|] .== 0 `smax` (m - n + 1))
+          (\n m -> abs (m - n), []) $
+          \ih n m -> [] |- length [sEnum|n+1 .. m|]
+                        =: cases [ n+1 .>  m ==> trivial
+                                 , n+1 .<= m ==> length (n+1 .: [sEnum|n+2 .. m|])
+                                              =: 1 + length [sEnum|n+2 .. m|]
+                                              ?? ih
+                                              =: 1 + (0 `smax` (m - (n+2) + 1))
+                                              =: 0 `smax` (m - (n+1) + 1)
+                                              =: qed
+                                 ]
+
+-- | @reverse [n .. m] == [m, m-1 .. n]@
+--
+-- The proof uses the metric @|m-n|@.
+--
+-- >>> runTP revNM
+-- Inductive lemma (strong): helper
+--   Step: Measure is non-negative     Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma (strong): revNM
+--   Step: Measure is non-negative     Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                       Q.E.D.
+--     Step: 1.2.1                     Q.E.D.
+--     Step: 1.2.2                     Q.E.D.
+--     Step: 1.2.3                     Q.E.D.
+--     Step: 1.2.4                     Q.E.D.
+--     Step: 1.Completeness            Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating:
+--   EnumSymbolic.Integer.enumFromThenTo.down, EnumSymbolic.Integer.enumFromThenTo.up, sbv.reverse
+-- [Proven] revNM :: Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
+revNM :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
+revNM = do
+
+  helper <- sInduct "helper"
+                    (\(Forall @"m" (m :: SInteger)) (Forall @"n" n) ->
+                          n .< m .=> [sEnum|m, m-1 .. n+1|] ++ [n] .== [sEnum|m, m-1 .. n|])
+                    (\m n -> abs (m - n), []) $
+                    \ih m n -> [n .< m] |- [sEnum|m, m-1 .. n+1|] ++ [n]
+                                        =: m .: [sEnum|m-1, m-2 .. n+1|] ++ [n]
+                                        ?? ih
+                                        =: m .: [sEnum|m-1, m-2 .. n|]
+                                        =: [sEnum|m, m-1 .. n|]
+                                        =: qed
+
+  sInduct "revNM"
+          (\(Forall n) (Forall m) -> reverse [sEnum|n .. m|] .== [sEnum|m, m-1 .. n|])
+          (\n m -> abs (m - n), []) $
+          \ih n m -> [] |- reverse [sEnum|n .. m|]
+                        =: cases [ n .>  m ==> trivial
+                                 , n .<= m ==> reverse (n .: [sEnum|(n+1) .. m|])
+                                            =: reverse [sEnum|(n+1) .. m|] ++ [n]
+                                            ?? ih
+                                            =: [sEnum|m, m-1 .. n+1|] ++ [n]
+                                            ?? helper
+                                            =: [sEnum|m, m-1 .. n|]
+                                            =: qed
+                                 ]
+
+-- | @length (x : xs) == 1 + length xs@
+--
+-- >>> runTP $ lengthTail @Integer
+-- Lemma: lengthTail    Q.E.D.
+-- [Proven] lengthTail :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+lengthTail :: forall a. SymVal a => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
+lengthTail = lemma "lengthTail"
+                   (\(Forall x) (Forall xs) -> length (x .: xs) .== 1 + length xs)
+                   []
+
+-- | @length (xs ++ ys) == length xs + length ys@
+--
+-- >>> runTP $ lenAppend @Integer
+-- Lemma: lenAppend    Q.E.D.
+-- [Proven] lenAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+lenAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+lenAppend = lemma "lenAppend"
+                  (\(Forall xs) (Forall ys) -> length (xs ++ ys) .== length xs + length ys)
+                  []
+
+-- | @length xs == length ys -> length (xs ++ ys) == 2 * length xs@
+--
+-- >>> runTP $ lenAppend2 @Integer
+-- Lemma: lenAppend2    Q.E.D.
+-- [Proven] lenAppend2 :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+lenAppend2 :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+lenAppend2 = lemma "lenAppend2"
+                   (\(Forall xs) (Forall ys) -> length xs .== length ys .=> length (xs ++ ys) .== 2 * length xs)
+                   []
+
+-- | @length (replicate k x) == max (0, k)@
+--
+-- >>> runTP $ replicateLength @Integer
+-- Inductive lemma: replicateLength
+--   Step: Base                        Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                       Q.E.D.
+--     Step: 1.2.1                     Q.E.D.
+--     Step: 1.2.2                     Q.E.D.
+--     Step: 1.2.3                     Q.E.D.
+--     Step: 1.2.4                     Q.E.D.
+--     Step: 1.Completeness            Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: sbv.replicate
+-- [Proven] replicateLength :: Ɐk ∷ Integer → Ɐx ∷ Integer → Bool
+replicateLength :: forall a. SymVal a => TP (Proof (Forall "k" Integer -> Forall "x" a -> SBool))
+replicateLength = induct "replicateLength"
+                         (\(Forall k) (Forall x) -> length (replicate k x) .== 0 `smax` k) $
+                         \ih k x -> [] |- length (replicate (k+1) x)
+                                       =: cases [ k .< 0  ==> trivial
+                                                , k .>= 0 ==> length (x .: replicate k x)
+                                                           =: 1 + length (replicate k x)
+                                                           ?? ih
+                                                           =: 1 + 0 `smax` k
+                                                           =: 0 `smax` (k+1)
+                                                           =: qed
+                                                ]
+
+-- | @not (all id xs) == any not xs@
+--
+-- A list of booleans is not all true, if any of them is false.
+--
+-- >>> runTP allAny
+-- Inductive lemma: allAny
+--   Step: Base               Q.E.D.
+--   Step: 1                  Q.E.D.
+--   Step: 2                  Q.E.D.
+--   Step: 3                  Q.E.D.
+--   Step: 4                  Q.E.D.
+--   Result:                  Q.E.D.
+-- Functions proven terminating: sbv.foldr
+-- [Proven] allAny :: Ɐxs ∷ [Bool] → Bool
+allAny :: TP (Proof (Forall "xs" [Bool] -> SBool))
+allAny = induct "allAny"
+                (\(Forall xs) -> sNot (all id xs) .== any sNot xs) $
+                \ih (x, xs) -> [] |- sNot (all id (x .: xs))
+                                  =: sNot (x .&& all id xs)
+                                  =: (sNot x .|| sNot (all id xs))
+                                  ?? ih
+                                  =: sNot x .|| any sNot xs
+                                  =: any sNot (x .: xs)
+                                  =: qed
+
+-- | @f == g ==> map f xs == map g xs@
+--
+-- >>> runTP $ mapEquiv @Integer @Integer (uninterpret "f") (uninterpret "g")
+-- Inductive lemma: mapEquiv
+--   Step: Base                 Q.E.D.
+--   Step: 1                    Q.E.D.
+--   Step: 2                    Q.E.D.
+--   Step: 3                    Q.E.D.
+--   Step: 4                    Q.E.D.
+--   Result:                    Q.E.D.
+-- Functions proven terminating: sbv.map
+-- [Proven] mapEquiv :: Ɐxs ∷ [Integer] → Bool
+mapEquiv :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
+mapEquiv f g = do
+   let f'eq'g :: SBool
+       f'eq'g = quantifiedBool $ \(Forall x) -> f x .== g x
+
+   induct "mapEquiv"
+          (\(Forall xs) -> f'eq'g .=> map f xs .== map g xs) $
+          \ih (x, xs) -> [f'eq'g] |- map f (x .: xs) .== map g (x .: xs)
+                                  =: f x .: map f xs .== g x .: map g xs
+                                  =: f x .: map f xs .== f x .: map g xs
+                                  ?? ih
+                                  =: f x .: map f xs .== f x .: map f xs
+                                  =: map f (x .: xs) .== map f (x .: xs)
+                                  =: qed
+
+-- | @map f (xs ++ ys) == map f xs ++ map f ys@
+--
+-- >>> runTP $ mapAppend @Integer @Integer (uninterpret "f")
+-- Inductive lemma: mapAppend
+--   Step: Base                  Q.E.D.
+--   Step: 1                     Q.E.D.
+--   Step: 2                     Q.E.D.
+--   Step: 3                     Q.E.D.
+--   Step: 4                     Q.E.D.
+--   Step: 5                     Q.E.D.
+--   Result:                     Q.E.D.
+-- Functions proven terminating: sbv.map
+-- [Proven] mapAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+mapAppend :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+mapAppend f =
+   induct "mapAppend"
+          (\(Forall xs) (Forall ys) -> map f (xs ++ ys) .== map f xs ++ map f ys) $
+          \ih (x, xs) ys -> [] |- map f ((x .: xs) ++ ys)
+                               =: map f (x .: (xs ++ ys))
+                             =: f x .: map f (xs ++ ys)
+                             ?? ih
+                             =: f x .: (map f xs  ++ map f ys)
+                             =: (f x .: map f xs) ++ map f ys
+                             =: map f (x .: xs) ++ map f ys
+                             =: qed
+
+-- | @map f . reverse == reverse . map f@
+--
+-- >>> runTP $ mapReverse @Integer @String (uninterpret "f")
+-- Inductive lemma: mapAppend
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Inductive lemma: mapReverse
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Step: 6                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.map, sbv.reverse
+-- [Proven] mapReverse :: Ɐxs ∷ [Integer] → Bool
+mapReverse :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
+mapReverse f = do
+     mApp <- mapAppend f
+
+     induct "mapReverse"
+            (\(Forall xs) -> reverse (map f xs) .== map f (reverse xs)) $
+            \ih (x, xs) -> [] |- reverse (map f (x .: xs))
+                              =: reverse (f x .: map f xs)
+                              =: reverse (map f xs) ++ [f x]
+                              ?? ih
+                              =: map f (reverse xs) ++ [f x]
+                              =: map f (reverse xs) ++ map f [x]
+                              ?? mApp
+                              =: map f (reverse xs ++ [x])
+                              =: map f (reverse (x .: xs))
+                              =: qed
+
+-- | @map f . map g == map (f . g)@
+--
+-- >>> runTP $ mapCompose @Integer @Bool @String (uninterpret "f") (uninterpret "g")
+-- Inductive lemma: mapCompose
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.map
+-- [Proven] mapCompose :: Ɐxs ∷ [Integer] → Bool
+mapCompose :: forall a b c. (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b) -> (SBV b -> SBV c) -> TP (Proof (Forall "xs" [a] -> SBool))
+mapCompose f g =
+  induct "mapCompose"
+         (\(Forall xs) -> map g (map f xs) .== map (g . f) xs) $
+         \ih (x, xs) -> [] |- map g (map f (x .: xs))
+                           =: map g (f x .: map f xs)
+                           =: g (f x) .: map g (map f xs)
+                           ?? ih
+                           =: g (f x) .: map (g . f) xs
+                           =: (g . f) x .: map (g . f) xs
+                           =: map (g . f) (x .: xs)
+                           =: qed
+
+-- | @map f . concat = concat . map (map f)@
+--
+-- >>> runTP $ mapConcat @Integer @Bool (uninterpret "f")
+-- Lemma: mapAppend              Q.E.D.
+-- Inductive lemma: mapConcat
+--   Step: Base                  Q.E.D.
+--   Step: 1                     Q.E.D.
+--   Step: 2                     Q.E.D.
+--   Step: 3                     Q.E.D.
+--   Step: 4                     Q.E.D.
+--   Step: 5                     Q.E.D.
+--   Result:                     Q.E.D.
+-- Functions proven terminating: sbv.foldr, sbv.map
+-- [Proven] mapConcat :: Ɐxs ∷ [[Integer]] → Bool
+mapConcat :: (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "xs" [[a]] -> SBool))
+mapConcat f = do
+   ma <- recall (mapAppend f)
+
+   induct "mapConcat"
+          (\(Forall xs) -> map f (concat xs) .== concat (map (map f) xs)) $
+          \ih (x, xs) -> [] |- map f (concat (x .: xs))
+                            =: map f (x ++ concat xs)
+                            ?? ma
+                            =: map f x ++ map f (concat xs)
+                            ?? ih
+                            =: map f x ++ concat (map (map f) xs)
+                            =: concat (map f x .: map (map f) xs)
+                            =: concat (map (map f) (x .: xs))
+                            =: qed
+
+-- | @foldr f a . map g == foldr (f . g) a@
+--
+-- >>> runTP $ foldrMapFusion @String @Bool @Integer (uninterpret "a") (uninterpret "b") (uninterpret "c")
+-- Inductive lemma: foldrMapFusion
+--   Step: Base                       Q.E.D.
+--   Step: 1                          Q.E.D.
+--   Step: 2                          Q.E.D.
+--   Step: 3                          Q.E.D.
+--   Step: 4                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Functions proven terminating: sbv.foldr, sbv.map
+-- [Proven] foldrMapFusion :: Ɐxs ∷ [String] → Bool
+foldrMapFusion :: forall a b c. (SymVal a, SymVal b, SymVal c) => SBV c -> (SBV a -> SBV b) -> (SBV b -> SBV c -> SBV c) -> TP (Proof (Forall "xs" [a] -> SBool))
+foldrMapFusion a g f =
+  induct "foldrMapFusion"
+         (\(Forall xs) -> foldr f a (map g xs) .== foldr (f . g) a xs) $
+         \ih (x, xs) -> [] |- foldr f a (map g (x .: xs))
+                           =: foldr f a (g x .: map g xs)
+                           =: g x `f` foldr f a (map g xs)
+                           ?? ih
+                           =: g x `f` foldr (f . g) a xs
+                           =: foldr (f . g) a (x .: xs)
+                           =: qed
+
+-- |
+--
+-- @
+--   f . foldr g a == foldr h b
+--   provided, f a = b and for all x and y, f (g x y) == h x (f y).
+-- @
+--
+-- >>> runTP $ foldrFusion @String @Bool @Integer (uninterpret "a") (uninterpret "b") (uninterpret "f") (uninterpret "g") (uninterpret "h")
+-- Inductive lemma: foldrFusion
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: sbv.foldr
+-- [Proven] foldrFusion :: Ɐxs ∷ [String] → Bool
+foldrFusion :: forall a b c. (SymVal a, SymVal b, SymVal c) => SBV c -> SBV b -> (SBV c -> SBV b) -> (SBV a -> SBV c -> SBV c) -> (SBV a -> SBV b -> SBV b) -> TP (Proof (Forall "xs" [a] -> SBool))
+foldrFusion a b f g h = do
+   let -- Assumptions under which the equality holds
+       h1 = f a .== b
+       h2 = quantifiedBool $ \(Forall x) (Forall y) -> f (g x y) .== h x (f y)
+
+   induct "foldrFusion"
+          (\(Forall xs) -> h1 .&& h2 .=> f (foldr g a xs) .== foldr h b xs) $
+          \ih (x, xs) -> [h1, h2] |- f (foldr g a (x .: xs))
+                                  =: f (g x (foldr g a xs))
+                                  =: h x (f (foldr g a xs))
+                                  ?? ih
+                                  =: h x (foldr h b xs)
+                                  =: foldr h b (x .: xs)
+                                  =: qed
+
+-- | @foldr f a (xs ++ ys) == foldr f (foldr f a ys) xs@
+--
+-- >>> runTP $ foldrOverAppend @Integer (uninterpret "a") (uninterpret "f")
+-- Inductive lemma: foldrOverAppend
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: sbv.foldr
+-- [Proven] foldrOverAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+foldrOverAppend :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+foldrOverAppend a f =
+   induct "foldrOverAppend"
+          (\(Forall xs) (Forall ys) -> foldr f a (xs ++ ys) .== foldr f (foldr f a ys) xs) $
+          \ih (x, xs) ys -> [] |- foldr f a ((x .: xs) ++ ys)
+                               =: foldr f a (x .: (xs ++ ys))
+                               =: x `f` foldr f a (xs ++ ys)
+                               ?? ih
+                               =: x `f` foldr f (foldr f a ys) xs
+                               =: foldr f (foldr f a ys) (x .: xs)
+                               =: qed
+
+-- | @foldl f e (xs ++ ys) == foldl f (foldl f e xs) ys@
+--
+-- >>> runTP $ foldlOverAppend @Integer @Bool (uninterpret "f")
+-- Inductive lemma: foldlOverAppend
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: sbv.foldl
+-- [Proven] foldlOverAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐe ∷ Bool → Bool
+foldlOverAppend :: forall a b. (SymVal a, SymVal b) => (SBV b -> SBV a -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" b -> SBool))
+foldlOverAppend f =
+   induct "foldlOverAppend"
+          (\(Forall xs) (Forall ys) (Forall a) -> foldl f a (xs ++ ys) .== foldl f (foldl f a xs) ys) $
+          \ih (x, xs) ys a -> [] |- foldl f a ((x .: xs) ++ ys)
+                                 =: foldl f a (x .: (xs ++ ys))
+                                 =: foldl f (a `f` x) (xs ++ ys)
+                                 -- z3 is smart enough to instantiate the IH correctly below, but we're
+                                 -- using an explicit instantiation to be clear about the use of @a@ at a different value
+                                 ?? ih `at` (Inst @"ys" ys, Inst @"e" (a `f` x))
+                                 =: foldl f (foldl f (a `f` x) xs) ys
+                                 =: qed
+
+-- | @foldr f e xs == foldl (flip f) e (reverse xs)@
+--
+-- >>> runTP $ foldrFoldlDuality @Integer @String (uninterpret "f")
+-- Inductive lemma: foldlOverAppend
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Inductive lemma: foldrFoldlDuality
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: sbv.foldl, sbv.foldr, sbv.reverse
+-- [Proven] foldrFoldlDuality :: Ɐxs ∷ [Integer] → Ɐe ∷ String → Bool
+foldrFoldlDuality :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV b) -> TP (Proof (Forall "xs" [a] -> Forall "e" b -> SBool))
+foldrFoldlDuality f = do
+   foa <- foldlOverAppend (flip f)
+
+   induct "foldrFoldlDuality"
+          (\(Forall xs) (Forall e) -> foldr f e xs .== foldl (flip f) e (reverse xs)) $
+          \ih (x, xs) e -> [] |- let ff  = flip f
+                                     rxs = reverse xs
+                                 in foldr f e (x .: xs)
+                                 =: x `f` foldr f e xs
+                                 ?? ih
+                                 =: x `f` foldl ff e rxs
+                                 =: foldl ff e rxs `ff` x
+                                 =: foldl ff (foldl ff e rxs) [x]
+                                 ?? foa
+                                 =: foldl ff e (rxs ++ [x])
+                                 =: foldl ff e (reverse (x .: xs))
+                                 =: qed
+
+-- | Given:
+--
+-- @
+--     x \@ (y \@ z) = (x \@ y) \@ z     (associativity of @)
+-- and e \@ x = x                     (left unit)
+-- and x \@ e = x                     (right unit)
+-- @
+--
+-- Proves:
+--
+-- @
+--     foldr (\@) e xs == foldl (\@) e xs
+-- @
+--
+-- >>> runTP $ foldrFoldlDualityGeneralized @Integer (uninterpret "e") (uninterpret "|@|")
+-- Inductive lemma: helper
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Inductive lemma: foldrFoldlDuality
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: sbv.foldl, sbv.foldr
+-- [Proven] foldrFoldlDuality :: Ɐxs ∷ [Integer] → Bool
+foldrFoldlDualityGeneralized :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xs" [a] -> SBool))
+foldrFoldlDualityGeneralized e (@) = do
+   -- Assumptions under which the equality holds
+   let assoc = quantifiedBool $ \(Forall x) (Forall y) (Forall z) -> x @ (y @ z) .== (x @ y) @ z
+       lunit = quantifiedBool $ \(Forall x) -> e @ x .== x
+       runit = quantifiedBool $ \(Forall x) -> x @ e .== x
+
+   -- Helper: foldl (@) (y @ z) xs = y @ foldl (@) z xs
+   -- Note the instantiation of the IH at a different value for z. It turns out
+   -- we don't have to actually specify this since z3 can figure it out by itself, but we're being explicit.
+   helper <- induct "helper"
+                    (\(Forall @"xs" xs) (Forall @"y" y) (Forall @"z" z) -> assoc .=> foldl (@) (y @ z) xs .== y @ foldl (@) z xs) $
+                    \ih (x, xs) y z -> [assoc] |- foldl (@) (y @ z) (x .: xs)
+                                               =: foldl (@) ((y @ z) @ x) xs
+                                               ?? assoc
+                                               =: foldl (@) (y @ (z @ x)) xs
+                                               ?? ih `at` (Inst @"y" y, Inst @"z" (z @ x))
+                                               =: y @ foldl (@) (z @ x) xs
+                                               =: y @ foldl (@) z (x .: xs)
+                                               =: qed
+
+   induct "foldrFoldlDuality"
+          (\(Forall xs) -> assoc .&& lunit .&& runit .=> foldr (@) e xs .== foldl (@) e xs) $
+          \ih (x, xs) -> [assoc, lunit, runit] |- foldr (@) e (x .: xs)
+                                               =: x @ foldr (@) e xs
+                                               ?? ih
+                                               =: x @ foldl (@) e xs
+                                               ?? helper
+                                               =: foldl (@) (x @ e) xs
+                                               ?? runit
+                                               =: foldl (@) x xs
+                                               ?? lunit
+                                               =: foldl (@) (e @ x) xs
+                                               =: foldl (@) e (x .: xs)
+                                               =: qed
+
+-- | Given:
+--
+-- @
+--        (x \<+> y) \<*> z = x \<+> (y \<*> z)
+--   and  x \<+> e = e \<*> x
+-- @
+--
+-- Proves:
+--
+-- @
+--    foldr (\<+>) e xs = foldl (\<*>) e xs
+-- @
+--
+-- In Bird's Introduction to Functional Programming book (2nd edition) this is called the second duality theorem:
+--
+-- >>> runTP $ foldrFoldl @Integer @String (uninterpret "<+>") (uninterpret "<*>") (uninterpret "e")
+-- Inductive lemma: foldl over <*>/<+>
+--   Step: Base                           Q.E.D.
+--   Step: 1                              Q.E.D.
+--   Step: 2                              Q.E.D.
+--   Step: 3                              Q.E.D.
+--   Step: 4                              Q.E.D.
+--   Result:                              Q.E.D.
+-- Inductive lemma: foldrFoldl
+--   Step: Base                           Q.E.D.
+--   Step: 1                              Q.E.D.
+--   Step: 2                              Q.E.D.
+--   Step: 3                              Q.E.D.
+--   Step: 4                              Q.E.D.
+--   Step: 5                              Q.E.D.
+--   Result:                              Q.E.D.
+-- Functions proven terminating: sbv.foldl, sbv.foldr
+-- [Proven] foldrFoldl :: Ɐxs ∷ [Integer] → Bool
+foldrFoldl :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV b) -> (SBV b -> SBV a -> SBV b) -> SBV b -> TP (Proof (Forall "xs" [a] -> SBool))
+foldrFoldl (<+>) (<*>) e = do
+   -- Assumptions about the operators
+   let -- (x <+> y) <*> z == x <+> (y <*> z)
+       assoc = quantifiedBool $ \(Forall x) (Forall y) (Forall z) -> (x <+> y) <*> z .== x <+> (y <*> z)
+
+       -- x <+> e == e <*> x
+       unit  = quantifiedBool $ \(Forall x) -> x <+> e .== e <*> x
+
+   -- Helper: x <+> foldl (<*>) y xs == foldl (<*>) (x <+> y) xs
+   helper <-
+      induct "foldl over <*>/<+>"
+             (\(Forall @"xs" xs) (Forall @"x" x) (Forall @"y" y) -> assoc .=> x <+> foldl (<*>) y xs .== foldl (<*>) (x <+> y) xs) $
+
+             -- Using z to avoid confusion with the variable x already present, following Bird.
+             -- z3 can figure out the proper instantiation of ih so the at call is unnecessary, but being explicit is helpful.
+             \ih (z, xs) x y -> [assoc] |- x <+> foldl (<*>) y (z .: xs)
+                                        =: x <+> foldl (<*>) (y <*> z) xs
+                                        ?? ih `at` (Inst @"x" x, Inst @"y" (y <*> z))
+                                        =: foldl (<*>) (x <+> (y <*> z)) xs
+                                        ?? assoc
+                                        =: foldl (<*>) ((x <+> y) <*> z) xs
+                                        =: foldl (<*>) (x <+> y) (z .: xs)
+                                        =: qed
+
+   -- Final proof:
+   induct "foldrFoldl"
+          (\(Forall xs) -> assoc .&& unit .=> foldr (<+>) e xs .== foldl (<*>) e xs) $
+          \ih (x, xs) -> [assoc, unit] |- foldr (<+>) e (x .: xs)
+                                       =: x <+> foldr (<+>) e xs
+                                       ?? ih
+                                       =: x <+> foldl (<*>) e xs
+                                       ?? helper
+                                       =: foldl (<*>) (x <+> e) xs
+                                       =: foldl (<*>) (e <*> x) xs
+                                       =: foldl (<*>) e (x .: xs)
+                                       =: qed
+
+-- | Provided @f@ is associative and @a@ is its both left and right-unit:
+--
+-- @foldr f a . concat == foldr f a . map (foldr f a)@
+--
+-- >>> runTP $ bookKeeping @Integer (uninterpret "a") (uninterpret "f")
+-- Inductive lemma: foldBase
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma: foldrOverAppend
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma: bookKeeping
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Step: 5                           Q.E.D.
+--   Step: 6                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: sbv.foldr, sbv.map
+-- [Proven] bookKeeping :: Ɐxss ∷ [[Integer]] → Bool
+--
+-- NB. This theorem does not hold if @f@ does not have a left-unit! Consider the input @[[], [x]]@. Left hand side reduces to
+-- @x@, while the right hand side reduces to: @f a x@. And unless @f@ is commutative or @a@ is not also a left-unit,
+-- then one can find a counter-example. (Aside: if both left and right units exist for a binary operator, then they
+-- are necessarily the same element, since @l = f l r = r@. So, an equivalent statement could simply say @f@ has
+-- both left and right units.) A concrete counter-example is:
+--
+-- @
+--   data T = A | B | C
+--
+--   f :: T -> T -> T
+--   f C A = A
+--   f C B = A
+--   f x _ = x
+-- @
+--
+-- You can verify @f@ is associative. Also note that @C@ is the right-unit for @f@, but it isn't the left-unit.
+-- In fact, @f@ has no-left unit by the above argument. In this case, the bookkeeping law produces @B@ for
+-- the left-hand-side, and @A@ for the right-hand-side for the input @[[], [B]]@.
+bookKeeping :: forall a. SymVal a => SBV a -> (SBV a -> SBV a -> SBV a) -> TP (Proof (Forall "xss" [[a]] -> SBool))
+bookKeeping a f = do
+
+   -- Assumptions about f
+   let assoc = quantifiedBool $ \(Forall x) (Forall y) (Forall z) -> x `f` (y `f` z) .== (x `f` y) `f` z
+       rUnit = quantifiedBool $ \(Forall x) -> x `f` a .== x
+       lUnit = quantifiedBool $ \(Forall x) -> a `f` x .== x
+
+   -- Helper: @foldr f y xs = foldr f a xs `f` y@
+   helper <- induct "foldBase"
+                    (\(Forall xs) (Forall y) -> lUnit .&& assoc .=> foldr f y xs .== foldr f a xs `f` y) $
+                    \ih (x, xs) y -> [lUnit, assoc] |- foldr f y (x .: xs)
+                                                    =: x `f` foldr f y xs
+                                                    ?? ih
+                                                    =: x `f` (foldr f a xs `f` y)
+                                                    =: (x `f` foldr f a xs) `f` y
+                                                    =: foldr f a (x .: xs) `f` y
+                                                    =: qed
+
+   foa <- foldrOverAppend a f
+
+   induct "bookKeeping"
+          (\(Forall xss) -> assoc .&& rUnit .&& lUnit .=> foldr f a (concat xss) .== foldr f a (map (foldr f a) xss)) $
+          \ih (xs, xss) -> [assoc, rUnit, lUnit] |- foldr f a (concat (xs .: xss))
+                                                 =: foldr f a (xs ++ concat xss)
+                                                 ?? foa
+                                                 =: foldr f (foldr f a (concat xss)) xs
+                                                 ?? ih
+                                                 =: foldr f (foldr f a (map (foldr f a) xss)) xs
+                                                 ?? helper `at` (Inst @"xs" xs, Inst @"y" (foldr f a (map (foldr f a) xss)))
+                                                 =: foldr f a xs `f` foldr f a (map (foldr f a) xss)
+                                                 =: foldr f a (foldr f a xs .: map (foldr f a) xss)
+                                                 =: foldr f a (map (foldr f a) (xs .: xss))
+                                                 =: qed
+
+-- | @filter p (xs ++ ys) == filter p xs ++ filter p ys@
+--
+-- >>> runTP $ filterAppend @Integer (uninterpret "p")
+-- Inductive lemma: filterAppend
+--   Step: Base                     Q.E.D.
+--   Step: 1                        Q.E.D.
+--   Step: 2                        Q.E.D.
+--   Step: 3                        Q.E.D.
+--   Step: 4                        Q.E.D.
+--   Step: 5                        Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: sbv.filter
+-- [Proven] filterAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+filterAppend :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+filterAppend p =
+   induct "filterAppend"
+          (\(Forall xs) (Forall ys) -> filter p xs ++ filter p ys .== filter p (xs ++ ys)) $
+          \ih (x, xs) ys -> [] |- filter p (x .: xs) ++ filter p ys
+                               =: ite (p x) (x .: filter p xs) (filter p xs) ++ filter p ys
+                               =: ite (p x) (x .: filter p xs ++ filter p ys) (filter p xs ++ filter p ys)
+                               ?? ih
+                               =: ite (p x) (x .: filter p (xs ++ ys)) (filter p (xs ++ ys))
+                               =: filter p (x .: (xs ++ ys))
+                               =: filter p ((x .: xs) ++ ys)
+                               =: qed
+
+-- | @filter p (concat xss) == concatMap (filter p xss)@
+--
+-- >>> runTP $ filterConcat @Integer (uninterpret "f")
+-- Inductive lemma: filterAppend
+--   Step: Base                     Q.E.D.
+--   Step: 1                        Q.E.D.
+--   Step: 2                        Q.E.D.
+--   Step: 3                        Q.E.D.
+--   Step: 4                        Q.E.D.
+--   Step: 5                        Q.E.D.
+--   Result:                        Q.E.D.
+-- Inductive lemma: filterConcat
+--   Step: Base                     Q.E.D.
+--   Step: 1                        Q.E.D.
+--   Step: 2                        Q.E.D.
+--   Step: 3                        Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: sbv.filter, sbv.foldr, sbv.map
+-- [Proven] filterConcat :: Ɐxss ∷ [[Integer]] → Bool
+filterConcat :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xss" [[a]] -> SBool))
+filterConcat p = do
+  fa <- filterAppend p
+
+  inductWith cvc5 "filterConcat"
+         (\(Forall xss) -> filter p (concat xss) .== concatMap (filter p) xss) $
+         \ih (xs, xss) -> [] |- filter p (concat (xs .: xss))
+                             =: filter p (xs ++ concat xss)
+                             ?? fa
+                             =: filter p xs ++ filter p (concat xss)
+                             ?? ih
+                             =: concatMap (filter p) (xs .: xss)
+                             =: qed
+
+-- | @takeWhile f xs ++ dropWhile f xs == xs@
+--
+-- >>> runTP $ takeDropWhile @Integer (uninterpret "f")
+-- Inductive lemma: takeDropWhile
+--   Step: Base                      Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                   Q.E.D.
+--     Step: 1.1.2                   Q.E.D.
+--     Step: 1.2.1                   Q.E.D.
+--     Step: 1.2.2                   Q.E.D.
+--     Step: 1.Completeness          Q.E.D.
+--   Result:                         Q.E.D.
+-- Functions proven terminating: sbv.dropWhile, sbv.takeWhile
+-- [Proven] takeDropWhile :: Ɐxs ∷ [Integer] → Bool
+takeDropWhile :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
+takeDropWhile f =
+   induct "takeDropWhile"
+          (\(Forall xs) -> takeWhile f xs ++ dropWhile f xs .== xs) $
+          \ih (x, xs) -> [] |- takeWhile f (x .: xs) ++ dropWhile f (x .: xs)
+                            =: cases [ f x        ==> x .: takeWhile f xs ++ dropWhile f xs
+                                                   ?? ih
+                                                   =: x .: xs
+                                                   =: qed
+                                     , sNot (f x) ==> [] ++ x .: xs
+                                                   =: x .: xs
+                                                   =: qed
+                                     ]
+-- | Remove adjacent duplicates.
+destutter :: SymVal a => SList a -> SList a
+destutter = smtFunction "destutter"
+          $ \xs -> [sCase| xs of
+                      []   -> xs
+                      [_]  -> xs
+                      a : rest@(b : _) | a .== b ->      destutter rest
+                                       | True    -> a .: destutter rest
+                   |]
+
+-- | @destutter (destutter xs) == destutter xs@
+--
+-- >>> runTP $ destutterIdempotent @Integer
+-- Inductive lemma: helper1
+--   Step: Base                         Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2.1                      Q.E.D.
+--     Step: 1.2.2                      Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Inductive lemma: helper2
+--   Step: Base                         Q.E.D.
+--   Step: 1                            Q.E.D.
+--   Result:                            Q.E.D.
+-- Inductive lemma (strong): helper3
+--   Step: Measure is non-negative      Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                        Q.E.D.
+--     Step: 1.2                        Q.E.D.
+--     Step: 1.3.1                      Q.E.D.
+--     Step: 1.3.2 (2 way case split)
+--       Step: 1.3.2.1.1                Q.E.D.
+--       Step: 1.3.2.1.2                Q.E.D.
+--       Step: 1.3.2.2.1                Q.E.D.
+--       Step: 1.3.2.2.2                Q.E.D.
+--       Step: 1.3.2.Completeness       Q.E.D.
+--     Step: 1.Completeness             Q.E.D.
+--   Result:                            Q.E.D.
+-- Lemma: destutterIdempotent           Q.E.D.
+-- Functions proven terminating: destutter, noAdd
+-- [Proven] destutterIdempotent :: Ɐxs ∷ [Integer] → Bool
+destutterIdempotent :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+destutterIdempotent = do
+
+   -- No adjacent duplicates
+   let noAdd = smtFunction "noAdd"
+             $ \xs -> [sCase| xs of
+                         []  -> sTrue
+                         [_] -> sTrue
+                         a : rest@(b : _) | a .== b -> sFalse
+                                          | True    -> noAdd rest
+                      |]
+
+   -- Helper: The head of a destuttered non-empty list does not change
+   helper1 <- induct "helper1"
+                     (\(Forall @"xs" (xs :: SList a)) (Forall @"h" h) -> head (destutter (h .: xs)) .== h) $
+                     \ih (x, xs) h -> []
+                                   |- head (destutter (h .: x .: xs))
+                                   =: cases [ h ./= x ==> trivial
+                                            , h .== x ==> head (destutter (x .: xs))
+                                                       ?? ih
+                                                       =: x
+                                                       =: qed
+                                            ]
+
+   -- Helper: show that if a list has no adjacent duplicates, then destutter leaves it unchanged:
+   helper2 <- induct "helper2"
+                     (\(Forall @"xs" (xs :: SList a)) -> noAdd xs .=> destutter xs .== xs) $
+                     \ih (x, xs) -> [noAdd (x .: xs)]
+                                 |- destutter (x .: xs)
+                                 ?? ih
+                                 =: x .: xs
+                                 =: qed
+
+   -- Helper: prove that noAdd is true for the result of destutter
+   helper3 <- sInductWith cvc5 "helper3"
+                  (\(Forall @"xs" (xs :: SList a)) -> noAdd (destutter xs))
+                  (length, []) $
+                  \ih xs -> []
+                         |- noAdd (destutter xs)
+                         =: [pCase| xs of
+                              []  -> trivial
+                              [_] -> trivial
+                              whole@(a : rest@(b : bs))
+                                 -> noAdd (destutter whole)
+                                 =: cases [a .== b  ==> noAdd (destutter rest)
+                                                     ?? ih
+                                                     =: sTrue
+                                                     =: qed
+                                          , a ./= b ==> noAdd (a .: destutter rest)
+                                                     ?? helper1 `at` (Inst @"xs" bs, Inst @"h" b)
+                                                     ?? ih
+                                                     =: sTrue
+                                                     =: qed
+                                          ]
+                            |]
+
+   -- Now we can prove idempotency easily:
+   lemma "destutterIdempotent"
+          (\(Forall xs) -> destutter (destutter xs) .== destutter xs)
+          [proofOf helper2, proofOf helper3]
+
+-- | @(as ++ bs) \\ cs == (as \\ cs) ++ (bs \\ cs)@
+--
+-- >>> runTP $ appendDiff @Integer
+-- Inductive lemma: appendDiff
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.diff
+-- [Proven] appendDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
+appendDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
+appendDiff = induct "appendDiff"
+                    (\(Forall as) (Forall bs) (Forall cs) -> (as ++ bs) \\ cs .== (as \\ cs) ++ (bs \\ cs)) $
+                    \ih (a, as) bs cs -> [] |- (a .: as ++ bs) \\ cs
+                                            =: (a .: (as ++ bs)) \\ cs
+                                            =: ite (a `elem` cs) ((as ++ bs) \\ cs) (a .: ((as ++ bs) \\ cs))
+                                            ?? ih
+                                            =: ((a .: as) \\ cs) ++ (bs \\ cs)
+                                            =: qed
+
+-- | @as \\ (bs ++ cs) == (as \\ bs) \\ cs@
+--
+-- >>> runTP $ diffAppend @Integer
+-- Inductive lemma: diffAppend
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.diff
+-- [Proven] diffAppend :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
+diffAppend :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
+diffAppend = induct "diffAppend"
+                    (\(Forall as) (Forall bs) (Forall cs) -> as \\ (bs ++ cs) .== (as \\ bs) \\ cs) $
+                    \ih (a, as) bs cs -> [] |- (a .: as) \\ (bs ++ cs)
+                                            =: ite (a `elem` (bs ++ cs)) (as \\ (bs ++ cs)) (a .: (as \\ (bs ++ cs)))
+                                            ?? ih `at` (Inst @"bs" bs, Inst @"cs" cs)
+                                            =: ite (a `elem` (bs ++ cs)) ((as \\ bs) \\ cs) (a .: (as \\ (bs ++ cs)))
+                                            ?? ih `at` (Inst @"bs" bs, Inst @"cs" cs)
+                                            =: ite (a `elem` (bs ++ cs)) ((as \\ bs) \\ cs) (a .: ((as \\ bs) \\ cs))
+                                            =: ((a .: as) \\ bs) \\ cs
+                                            =: qed
+
+-- | @(as \\ bs) \\ cs == (as \\ cs) \\ bs@
+--
+-- >>> runTP $ diffDiff @Integer
+-- Inductive lemma: diffDiff
+--   Step: Base                      Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                   Q.E.D.
+--     Step: 1.1.2                   Q.E.D.
+--     Step: 1.1.3 (2 way case split)
+--       Step: 1.1.3.1               Q.E.D.
+--       Step: 1.1.3.2.1             Q.E.D.
+--       Step: 1.1.3.2.2 (a ∉ cs)    Q.E.D.
+--       Step: 1.1.3.Completeness    Q.E.D.
+--     Step: 1.2.1                   Q.E.D.
+--     Step: 1.2.2 (2 way case split)
+--       Step: 1.2.2.1.1             Q.E.D.
+--       Step: 1.2.2.1.2             Q.E.D.
+--       Step: 1.2.2.1.3 (a ∈ cs)    Q.E.D.
+--       Step: 1.2.2.2.1             Q.E.D.
+--       Step: 1.2.2.2.2             Q.E.D.
+--       Step: 1.2.2.2.3 (a ∉ bs)    Q.E.D.
+--       Step: 1.2.2.2.4 (a ∉ cs)    Q.E.D.
+--       Step: 1.2.2.Completeness    Q.E.D.
+--     Step: 1.Completeness          Q.E.D.
+--   Result:                         Q.E.D.
+-- Functions proven terminating: sbv.diff
+-- [Proven] diffDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Ɐcs ∷ [Integer] → Bool
+diffDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> Forall "cs" [a] -> SBool))
+diffDiff = induct "diffDiff"
+                  (\(Forall as) (Forall bs) (Forall cs) -> (as \\ bs) \\ cs .== (as \\ cs) \\ bs) $
+                  \ih (a, as) bs cs ->
+                      [] |- ((a .: as) \\ bs) \\ cs
+                         =: cases [ a `elem`    bs ==> (as \\ bs) \\ cs
+                                                    ?? ih
+                                                    =: (as \\ cs) \\ bs
+                                                    =: cases [ a `elem`    cs ==> ((a .: as) \\ cs) \\ bs
+                                                                               =: qed
+                                                             , a `notElem` cs ==> (a .: (as \\ cs)) \\ bs
+                                                                               ?? "a ∉ cs"
+                                                                               =: ((a .: as) \\ cs) \\ bs
+                                                                               =: qed
+                                                             ]
+                                  , a `notElem` bs ==> (a .: (as \\ bs)) \\ cs
+                                                    =: cases [ a `elem`    cs ==> (as \\ bs) \\ cs
+                                                                               ?? ih
+                                                                               =: (as \\ cs) \\ bs
+                                                                               ?? "a ∈ cs"
+                                                                               =: ((a .: as) \\ cs) \\ bs
+                                                                               =: qed
+                                                             , a `notElem` cs ==> a .: ((as \\ bs) \\ cs)
+                                                                               ?? ih
+                                                                               =: a .: ((as \\ cs) \\ bs)
+                                                                               ?? "a ∉ bs"
+                                                                               =: (a .: (as \\ cs)) \\ bs
+                                                                               ?? "a ∉ cs"
+                                                                               =: ((a .: as) \\ cs) \\ bs
+                                                                               =: qed
+                                                             ]
+                                  ]
+
+-- | Are the two lists disjoint?
+disjoint :: (Eq a, SymVal a) => SList a -> SList a -> SBool
+disjoint = smtFunction "disjoint"
+         $ \xs ys -> [sCase| xs of
+                        []     -> sTrue
+                        a : as -> a `notElem` ys .&& disjoint as ys
+                     |]
+
+-- | @disjoint as bs .=> as \\ bs == as@
+--
+-- >>> runTP $ disjointDiff @Integer
+-- Inductive lemma: disjointDiff
+--   Step: Base                     Q.E.D.
+--   Step: 1                        Q.E.D.
+--   Step: 2                        Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: disjoint, sbv.diff
+-- [Proven] disjointDiff :: Ɐas ∷ [Integer] → Ɐbs ∷ [Integer] → Bool
+disjointDiff :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "as" [a] -> Forall "bs" [a] -> SBool))
+disjointDiff = induct "disjointDiff"
+                      (\(Forall as) (Forall bs) -> disjoint as bs .=> as \\ bs .== as) $
+                      \ih (a, as) bs -> [disjoint (a .: as) bs]
+                                     |- (a .: as) \\ bs
+                                     =: a .: (as \\ bs)
+                                     ?? ih
+                                     =: a .: as
+                                     =: qed
+
+-- | @fst (partition f xs) == filter f xs@
+--
+-- >>> runTP $ partition1 @Integer (uninterpret "f")
+-- Inductive lemma: partition1
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.filter, sbv.partition
+-- [Proven] partition1 :: Ɐxs ∷ [Integer] → Bool
+partition1 :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
+partition1 f =
+   induct "partition1"
+          (\(Forall xs) -> fst (partition f xs) .== filter f xs) $
+          \ih (x, xs) -> [] |- fst (partition f (x .: xs))
+                            =: fst (let res = partition f xs
+                                    in ite (f x)
+                                           (tuple (x .: fst res, snd res))
+                                           (tuple (fst res, x .: snd res)))
+                            =: ite (f x) (x .: fst (partition f xs)) (fst (partition f xs))
+                            ?? ih
+                            =: ite (f x) (x .: filter f xs) (filter f xs)
+                            =: filter f (x .: xs)
+                            =: qed
+
+-- | @snd (partition f xs) == filter (not . f) xs@
+--
+-- >>> runTP $ partition2 @Integer (uninterpret "f")
+-- Inductive lemma: partition2
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.filter, sbv.partition
+-- [Proven] partition2 :: Ɐxs ∷ [Integer] → Bool
+partition2 :: forall a. SymVal a => (SBV a -> SBool) -> TP (Proof (Forall "xs" [a] -> SBool))
+partition2 f =
+   induct "partition2"
+          (\(Forall xs) -> snd (partition f xs) .== filter (sNot . f) xs) $
+          \ih (x, xs) -> [] |- snd (partition f (x .: xs))
+                            =: snd (let res = partition f xs
+                                    in ite (f x)
+                                           (tuple (x .: fst res, snd res))
+                                           (tuple (fst res, x .: snd res)))
+                            =: ite (f x) (snd (partition f xs)) (x .: snd (partition f xs))
+                            ?? ih
+                            =: ite (f x) (filter (sNot . f) xs) (x .: filter (sNot . f) xs)
+                            =: filter (sNot . f) (x .: xs)
+                            =: qed
+
+-- | @take n (take m xs) == take (n `smin` m) xs@
+--
+-- >>> runTP $ take_take @Integer
+-- Lemma: take_take    Q.E.D.
+-- [Proven] take_take :: Ɐm ∷ Integer → Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+take_take :: forall a. SymVal a => TP (Proof (Forall "m" Integer -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
+take_take = lemma "take_take"
+                  (\(Forall m) (Forall n) (Forall xs) -> take n (take m xs) .== take (n `smin` m) xs)
+                  []
+
+-- | @n >= 0 && m >= 0 ==> drop n (drop m xs) == drop (n + m) xs@
+--
+-- >>> runTP $ drop_drop @Integer
+-- Lemma: drop_drop    Q.E.D.
+-- [Proven] drop_drop :: Ɐm ∷ Integer → Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+drop_drop :: forall a. SymVal a => TP (Proof (Forall "m" Integer -> Forall "n" Integer -> Forall "xs" [a] -> SBool))
+drop_drop = lemma "drop_drop"
+                  (\(Forall m) (Forall n) (Forall xs) -> n .>= 0 .&& m .>= 0 .=> drop n (drop m xs) .== drop (n + m) xs)
+                  []
+
+-- | @take n xs ++ drop n xs == xs@
+--
+-- >>> runTP $ take_drop @Integer
+-- Lemma: take_drop    Q.E.D.
+-- [Proven] take_drop :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+take_drop :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+take_drop = lemma "take_drop"
+                  (\(Forall n) (Forall xs) -> take n xs ++ drop n xs .== xs)
+                  []
+
+-- | @n .> 0 ==> take n (x .: xs) == x .: take (n - 1) xs@
+--
+-- >>> runTP $ take_cons @Integer
+-- Lemma: take_cons    Q.E.D.
+-- [Proven] take_cons :: Ɐn ∷ Integer → Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+take_cons :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
+take_cons = lemma "take_cons"
+                  (\(Forall n) (Forall x) (Forall xs) -> n .> 0 .=> take n (x .: xs) .== x .: take (n - 1) xs)
+                  []
+
+-- | @take n (map f xs) == map f (take n xs)@
+--
+-- >>> runTP $ take_map @Integer @Integer (uninterpret "f")
+-- Lemma: take_cons                   Q.E.D.
+-- Lemma: map1                        Q.E.D.
+-- Lemma: take_map.n <= 0             Q.E.D.
+-- Inductive lemma: take_map.n > 0
+--   Step: Base                       Q.E.D.
+--   Step: 1                          Q.E.D.
+--   Step: 2                          Q.E.D.
+--   Step: 3                          Q.E.D.
+--   Step: 4                          Q.E.D.
+--   Step: 5                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Lemma: take_map
+--   Step: 1                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Functions proven terminating: sbv.map
+-- [Proven] take_map :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+take_map :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+take_map f = do
+    tc   <- take_cons @a
+
+    map1 <- lemma "map1"
+                  (\(Forall x) (Forall xs) -> map f (x .: xs) .== f x .: map f xs)
+                  []
+
+    h1 <- lemma "take_map.n <= 0"
+                 (\(Forall @"xs" xs) (Forall @"n" n) -> n .<= 0 .=> take n (map f xs) .== map f (take n xs))
+                 []
+
+    h2 <- inductWith cvc5 "take_map.n > 0"
+                 (\(Forall @"xs" xs) (Forall @"n" n) -> n .> 0 .=> take n (map f xs) .== map f (take n xs)) $
+                 \ih (x, xs) n -> [n .> 0] |- take n (map f (x .: xs))
+                                           =: take n (f x .: map f xs)
+                                           =: f x .: take (n - 1) (map f xs)
+                                           ?? ih `at` Inst @"n" (n-1)
+                                           =: f x .: map f (take (n - 1) xs)
+                                           ?? map1 `at` (Inst @"x" x, Inst @"xs" (take (n - 1) xs))
+                                           =: map f (x .: take (n - 1) xs)
+                                           ?? tc
+                                           =: map f (take n (x .: xs))
+                                           =: qed
+
+    calc "take_map"
+         (\(Forall n) (Forall xs) -> take n (map f xs) .== map f (take n xs)) $
+         \n xs -> [] |- take n (map f xs)
+                     ?? h1
+                     ?? h2
+                     =: map f (take n xs)
+                     =: qed
+
+-- | @n .> 0 ==> drop n (x .: xs) == drop (n - 1) xs@
+--
+-- >>> runTP $ drop_cons @Integer
+-- Lemma: drop_cons    Q.E.D.
+-- [Proven] drop_cons :: Ɐn ∷ Integer → Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+drop_cons :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "x" a -> Forall "xs" [a] -> SBool))
+drop_cons = lemma "drop_cons"
+                  (\(Forall n) (Forall x) (Forall xs) -> n .> 0 .=> drop n (x .: xs) .== drop (n - 1) xs)
+                  []
+
+-- | @drop n (map f xs) == map f (drop n xs)@
+--
+-- >>> runTP $ drop_map @Integer @String (uninterpret "f")
+-- Lemma: drop_cons                   Q.E.D.
+-- Lemma: drop_cons                   Q.E.D.
+-- Lemma: drop_map.n <= 0             Q.E.D.
+-- Inductive lemma: drop_map.n > 0
+--   Step: Base                       Q.E.D.
+--   Step: 1                          Q.E.D.
+--   Step: 2                          Q.E.D.
+--   Step: 3                          Q.E.D.
+--   Step: 4                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Lemma: drop_map
+--   Step: 1                          Q.E.D.
+--   Step: 2                          Q.E.D.
+--   Step: 3                          Q.E.D.
+--   Step: 4                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Functions proven terminating: sbv.map
+-- [Proven] drop_map :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+drop_map :: forall a b. (SymVal a, SymVal b) => (SBV a -> SBV b) -> TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+drop_map f = do
+   dcA <- drop_cons @a
+   dcB <- drop_cons @b
+
+   h1 <- lemma "drop_map.n <= 0"
+               (\(Forall @"xs" xs) (Forall @"n" n) -> n .<= 0 .=> drop n (map f xs) .== map f (drop n xs))
+               []
+
+   h2 <- induct "drop_map.n > 0"
+                (\(Forall @"xs" xs) (Forall @"n" n) -> n .> 0 .=> drop n (map f xs) .== map f (drop n xs)) $
+                \ih (x, xs) n -> [n .> 0] |- drop n (map f (x .: xs))
+                                          =: drop n (f x .: map f xs)
+                                          ?? dcB `at` (Inst @"n" n, Inst @"x" (f x), Inst @"xs" (map f xs))
+                                          =: drop (n - 1) (map f xs)
+                                          ?? ih `at` Inst @"n" (n-1)
+                                          =: map f (drop (n - 1) xs)
+                                          ?? dcA `at` (Inst @"n" n, Inst @"x" x, Inst @"xs" xs)
+                                          =: map f (drop n (x .: xs))
+                                          =: qed
+
+   -- I'm a bit surprised that z3 can't deduce the following with a simple-lemma, which is essentially a simple case-split.
+   -- But the good thing about calc is that it lets us direct the tool in precise ways that we'd like.
+   calc "drop_map"
+        (\(Forall n) (Forall xs) -> drop n (map f xs) .== map f (drop n xs)) $
+        \n xs -> [] |- let result = drop n (map f xs) .== map f (drop n xs)
+                       in result
+                       =: ite (n .<= 0) (n .<= 0 .=> result) (n .> 0 .=> result)
+                       ?? h1
+                       =: ite (n .<= 0) sTrue (n .> 0 .=> result)
+                       ?? h2
+                       =: ite (n .<= 0) sTrue sTrue
+                       =: sTrue
+                       =: qed
+
+-- | @n >= 0 ==> length (take n xs) == length xs \`min\` n@
+--
+-- >>> runTP $ length_take @Integer
+-- Lemma: length_take    Q.E.D.
+-- [Proven] length_take :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+length_take :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+length_take = lemma "length_take"
+                    (\(Forall n) (Forall xs) -> n .>= 0 .=> length (take n xs) .== length xs `smin` n)
+                    []
+
+-- | @n >= 0 ==> length (drop n xs) == (length xs - n) \`max\` 0@
+--
+-- >>> runTP $ length_drop @Integer
+-- Lemma: length_drop    Q.E.D.
+-- [Proven] length_drop :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+length_drop :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+length_drop = lemma "length_drop"
+                    (\(Forall n) (Forall xs) -> n .>= 0 .=> length (drop n xs) .== (length xs - n) `smax` 0)
+                    []
+
+-- | @length xs \<= n ==\> take n xs == xs@
+--
+-- >>> runTP $ take_all @Integer
+-- Lemma: take_all     Q.E.D.
+-- [Proven] take_all :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+take_all :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+take_all = lemma "take_all"
+                 (\(Forall n) (Forall xs) -> length xs .<= n .=> take n xs .== xs)
+                 []
+
+-- | @length xs \<= n ==\> drop n xs == []@
+--
+-- >>> runTP $ drop_all @Integer
+-- Lemma: drop_all     Q.E.D.
+-- [Proven] drop_all :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Bool
+drop_all :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> SBool))
+drop_all = lemma "drop_all"
+                 (\(Forall n) (Forall xs) -> length xs .<= n .=> drop n xs .== [])
+                 []
+
+-- | @take n (xs ++ ys) == (take n xs ++ take (n - length xs) ys)@
+--
+-- >>> runTP $ take_append @Integer
+-- Lemma: take_append    Q.E.D.
+-- [Proven] take_append :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+take_append :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+take_append = lemmaWith cvc5 "take_append"
+                        (\(Forall n) (Forall xs) (Forall ys) -> take n (xs ++ ys) .== take n xs ++ take (n - length xs) ys)
+                        []
+
+-- | @drop n (xs ++ ys) == drop n xs ++ drop (n - length xs) ys@
+--
+-- NB. As of Feb 2025, z3 struggles to prove this, but cvc5 gets it out-of-the-box.
+--
+-- >>> runTP $ drop_append @Integer
+-- Lemma: drop_append    Q.E.D.
+-- [Proven] drop_append :: Ɐn ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+drop_append :: forall a. SymVal a => TP (Proof (Forall "n" Integer -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+drop_append = lemmaWith cvc5 "drop_append"
+                        (\(Forall n) (Forall xs) (Forall ys) -> drop n (xs ++ ys) .== drop n xs ++ drop (n - length xs) ys)
+                        []
+
+-- | @length xs == length ys ==> map fst (zip xs ys) = xs@
+--
+-- >>> runTP $ map_fst_zip @Integer @Integer
+-- Inductive lemma: map_fst_zip
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: sbv.map, sbv.zip
+-- [Proven] map_fst_zip :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
+map_fst_zip :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
+map_fst_zip = induct "map_fst_zip"
+                     (\(Forall xs, Forall ys) -> length xs .== length ys .=> map fst (zip xs ys) .== xs) $
+                     \ih (x, xs, y, ys) -> [length (x .: xs) .== length (y .: ys)]
+                                        |- map fst (zip (x .: xs) (y .: ys))
+                                        =: map fst (tuple (x, y) .: zip xs ys)
+                                        =: fst (tuple (x, y)) .: map fst (zip xs ys)
+                                        =: x .: map fst (zip xs ys)
+                                        ?? ih
+                                        =: x .: xs
+                                        =: qed
+
+-- | @length xs == length ys ==> map snd (zip xs ys) = xs@
+--
+-- >>> runTP $ map_snd_zip @Integer @Integer
+-- Inductive lemma: map_snd_zip
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: sbv.map, sbv.zip
+-- [Proven] map_snd_zip :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
+map_snd_zip :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
+map_snd_zip = induct "map_snd_zip"
+                     (\(Forall xs, Forall ys) -> length xs .== length ys .=> map snd (zip xs ys) .== ys) $
+                     \ih (x, xs, y, ys) -> [length (x .: xs) .== length (y .: ys)]
+                                        |- map snd (zip (x .: xs) (y .: ys))
+                                        =: map snd (tuple (x, y) .: zip xs ys)
+                                        =: snd (tuple (x, y)) .: map snd (zip xs ys)
+                                        =: y .: map snd (zip xs ys)
+                                        ?? ih
+                                        =: y .: ys
+                                        =: qed
+
+-- | @map fst (zip xs ys) == take (min (length xs) (length ys)) xs@
+--
+-- >>> runTP $ map_fst_zip_take @Integer @Integer
+-- Lemma: take_cons                     Q.E.D.
+-- Inductive lemma: map_fst_zip_take
+--   Step: Base                         Q.E.D.
+--   Step: 1                            Q.E.D.
+--   Step: 2                            Q.E.D.
+--   Step: 3                            Q.E.D.
+--   Step: 4                            Q.E.D.
+--   Step: 5                            Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: sbv.map, sbv.zip
+-- [Proven] map_fst_zip_take :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
+map_fst_zip_take :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
+map_fst_zip_take = do
+   tc <- take_cons @a
+
+   induct "map_fst_zip_take"
+          (\(Forall xs, Forall ys) -> map fst (zip xs ys) .== take (length xs `smin` length ys) xs) $
+          \ih (x, xs, y, ys) -> [] |- map fst (zip (x .: xs) (y .: ys))
+                                   =: map fst (tuple (x, y) .: zip xs ys)
+                                   =: x .: map fst (zip xs ys)
+                                   ?? ih
+                                   =: x .: take (length xs `smin` length ys) xs
+                                   ?? tc
+                                   =: take (1 + (length xs `smin` length ys)) (x .: xs)
+                                   =: take (length (x .: xs) `smin` length (y .: ys)) (x .: xs)
+                                   =: qed
+
+-- | @map snd (zip xs ys) == take (min (length xs) (length ys)) xs@
+--
+-- >>> runTP $ map_snd_zip_take @Integer @Integer
+-- Lemma: take_cons                     Q.E.D.
+-- Inductive lemma: map_snd_zip_take
+--   Step: Base                         Q.E.D.
+--   Step: 1                            Q.E.D.
+--   Step: 2                            Q.E.D.
+--   Step: 3                            Q.E.D.
+--   Step: 4                            Q.E.D.
+--   Step: 5                            Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: sbv.map, sbv.zip
+-- [Proven] map_snd_zip_take :: (Ɐxs ∷ [Integer], Ɐys ∷ [Integer]) → Bool
+map_snd_zip_take :: forall a b. (SymVal a, SymVal b) => TP (Proof ((Forall "xs" [a], Forall "ys" [b]) -> SBool))
+map_snd_zip_take = do
+   tc <- take_cons @a
+
+   induct "map_snd_zip_take"
+          (\(Forall xs, Forall ys) -> map snd (zip xs ys) .== take (length xs `smin` length ys) ys) $
+          \ih (x, xs, y, ys) -> [] |- map snd (zip (x .: xs) (y .: ys))
+                                   =: map snd (tuple (x, y) .: zip xs ys)
+                                   =: y .: map snd (zip xs ys)
+                                   ?? ih
+                                   =: y .: take (length xs `smin` length ys) ys
+                                   ?? tc
+                                   =: take (1 + (length xs `smin` length ys)) (y .: ys)
+                                   =: take (length (x .: xs) `smin` length (y .: ys)) (y .: ys)
+                                   =: qed
+
+-- | Count the number of occurrences of an element in a list
+count :: SymVal a => SBV a -> SList a -> SInteger
+count = smtFunction "count"
+      $ \e l -> [sCase| l of
+                   []               -> 0
+                   x : xs | e .== x -> 1 + count e xs
+                          | True    -> count e xs
+                |]
+
+-- | One-step unfolding of 'count' on a cons cell. The solver can expand the
+-- @define-fun-rec@ but struggles to fold it back, so we provide this as a reusable hint.
+--
+-- >>> runTP $ countOneStep @Integer
+-- Lemma: countOneStep    Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] countOneStep :: Ɐe ∷ Integer → Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+countOneStep :: forall a. SymVal a => TP (Proof (Forall "e" a -> Forall "x" a -> Forall "xs" [a] -> SBool))
+countOneStep = lemma "countOneStep"
+   (\(Forall @"e" e) (Forall @"x" x) (Forall @"xs" (xs :: SList a)) ->
+      count e (x .: xs) .== ite (e .== x) (1 + count e xs) (count e xs))
+   []
+
+-- | Interleave the elements of two lists. If one ends, we take the rest from the other.
+interleave :: SymVal a => SList a -> SList a -> SList a
+interleave = smtFunction "interleave"
+           $ \xs ys -> [sCase| xs of
+                           []     -> ys
+                           a : as -> a .: interleave ys as
+                        |]
+
+-- | Prove that interleave preserves total length.
+--
+-- The induction here is on the total length of the lists, and hence
+-- we use the generalized induction principle. We have:
+--
+-- >>> runTP $ interleaveLen @Integer
+-- Inductive lemma (strong): interleaveLen
+--   Step: Measure is non-negative            Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                              Q.E.D.
+--     Step: 1.2.1                            Q.E.D.
+--     Step: 1.2.2                            Q.E.D.
+--     Step: 1.2.3                            Q.E.D.
+--     Step: 1.Completeness                   Q.E.D.
+--   Result:                                  Q.E.D.
+-- Functions proven terminating: interleave
+-- [Proven] interleaveLen :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+interleaveLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+interleaveLen = sInduct "interleaveLen"
+                        (\(Forall xs) (Forall ys) -> length xs + length ys .== length (interleave xs ys))
+                        (\xs ys -> length xs + length ys, []) $
+                        \ih xs ys -> [] |- length xs + length ys .== length (interleave xs ys)
+                                        =: [pCase| xs of
+                                              []             -> trivial
+                                              whole@(_ : as) ->
+                                                   length whole + length ys .== length (interleave whole ys)
+                                                =: 1 + length as + length ys .== 1 + length (interleave ys as)
+                                                ?? ih `at` (Inst @"xs" ys, Inst @"ys" as)
+                                                =: sTrue
+                                                =: qed
+                                           |]
+
+-- | Uninterleave the elements of two lists. We roughly split it into two, of alternating elements.
+uninterleave :: SymVal a => SList a -> STuple [a] [a]
+uninterleave lst = uninterleaveGen lst (tuple ([], []))
+
+-- | Generalized form of uninterleave with the auxiliary lists made explicit.
+uninterleaveGen :: SymVal a => SList a -> STuple [a] [a] -> STuple [a] [a]
+uninterleaveGen = smtFunction "uninterleave"
+                $ \xs alts -> let (es, os) = untuple alts
+                              in [sCase| xs of
+                                    []     -> tuple (reverse es, reverse os)
+                                    x : ys -> uninterleaveGen ys (tuple (os, x .: es))
+                                 |]
+
+-- | The functions 'uninterleave' and 'interleave' are inverses so long as the inputs are of the same length. (The equality
+-- would even hold if the first argument has one extra element, but we keep things simple here.)
+--
+-- We have:
+--
+-- >>> runTP $ interleaveRoundTrip @Integer
+-- Lemma: revCons                            Q.E.D.
+-- Inductive lemma (strong): roundTripGen
+--   Step: Measure is non-negative           Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                             Q.E.D.
+--     Step: 1.2                             Q.E.D.
+--     Step: 1.3.1                           Q.E.D.
+--     Step: 1.3.2                           Q.E.D.
+--     Step: 1.3.3                           Q.E.D.
+--     Step: 1.3.4                           Q.E.D.
+--     Step: 1.3.5                           Q.E.D.
+--     Step: 1.3.6                           Q.E.D.
+--     Step: 1.3.7                           Q.E.D.
+--     Step: 1.3.8                           Q.E.D.
+--     Step: 1.Completeness                  Q.E.D.
+--   Result:                                 Q.E.D.
+-- Lemma: interleaveRoundTrip
+--   Step: 1                                 Q.E.D.
+--   Step: 2                                 Q.E.D.
+--   Result:                                 Q.E.D.
+-- Functions proven terminating: interleave, sbv.reverse, uninterleave
+-- [Proven] interleaveRoundTrip :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+interleaveRoundTrip :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+interleaveRoundTrip = do
+
+   revHelper <- lemma "revCons" (\(Forall a) (Forall as) (Forall bs) -> reverse @a (a .: as) ++ bs .== reverse as ++ (a .: bs)) []
+
+   -- Generalize the theorem first to take the helper lists explicitly
+   roundTripGen <- sInductWith cvc5
+         "roundTripGen"
+         (\(Forall @"xs" xs) (Forall @"ys" ys) (Forall @"alts" alts) ->
+               length xs .== length ys .=> let (es, os) = untuple alts
+                                           in uninterleaveGen (interleave xs ys) alts .== tuple (reverse es ++ xs, reverse os ++ ys))
+         (\xs ys _alts -> length xs + length ys, []) $
+         \ih xs ys alts -> [length xs .== length ys]
+                        |- let (es, os) = untuple alts
+                        in uninterleaveGen (interleave xs ys) alts
+                        =: [pCase| tuple (xs, ys) of
+                              ([], _) -> trivial
+                              (_, []) -> trivial
+                              (ll@(a : as), rr@(b : bs)) ->
+                                   uninterleaveGen (interleave ll rr) alts
+                                =: uninterleaveGen (a .: interleave rr as) alts
+                                =: uninterleaveGen (a .: b .: interleave as bs) alts
+                                =: uninterleaveGen (interleave as bs) (tuple (a .: es, b .: os))
+                                ?? ih `at` (Inst @"xs" as, Inst @"ys" bs, Inst @"alts" (tuple (a .: es, b .: os)))
+                                =: tuple (reverse (a .: es) ++ as, reverse (b .: os) ++ bs)
+                                ?? revHelper `at` (Inst @"a" a, Inst @"as" es, Inst @"bs" as)
+                                =: tuple (reverse es ++ ll, reverse (b .: os) ++ bs)
+                                ?? revHelper `at` (Inst @"a" b, Inst @"as" os, Inst @"bs" bs)
+                                =: tuple (reverse es ++ ll, reverse os ++ rr)
+                                =: tuple (reverse es ++ xs, reverse os ++ ys)
+                                =: qed
+                           |]
+
+   -- Round-trip theorem:
+   calc "interleaveRoundTrip"
+           (\(Forall xs) (Forall ys) -> length xs .== length ys .=> uninterleave (interleave xs ys) .== tuple (xs, ys)) $
+           \xs ys -> [length xs .== length ys]
+                  |- uninterleave (interleave xs ys)
+                  =: uninterleaveGen (interleave xs ys) (tuple ([], []))
+                  ?? roundTripGen `at` (Inst @"xs" xs, Inst @"ys" ys, Inst @"alts" (tuple ([], [])))
+                  =: tuple (reverse [] ++ xs, reverse [] ++ ys)
+                  =: qed
+
+-- | @count e (xs ++ ys) == count e xs + count e ys@
+--
+-- >>> runTP $ countAppend @Integer
+-- Inductive lemma: countAppend
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2 (unfold count)        Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4 (simplify)            Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] countAppend :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐe ∷ Integer → Bool
+countAppend :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "e" a -> SBool))
+countAppend =
+   induct "countAppend"
+          (\(Forall xs) (Forall ys) (Forall e) -> count e (xs ++ ys) .== count e xs + count e ys) $
+          \ih (x, xs) ys e -> [] |- count e ((x .: xs) ++ ys)
+                                 =: count e (x .: (xs ++ ys))
+                                 ?? "unfold count"
+                                 =: (let r = count e (xs ++ ys) in ite (e .== x) (1+r) r)
+                                 ?? ih `at` (Inst @"ys" ys, Inst @"e" e)
+                                 =: (let r = count e xs + count e ys in ite (e .== x) (1+r) r)
+                                 ?? "simplify"
+                                 =: count e (x .: xs) + count e ys
+                                 =: qed
+
+-- | @count e (take n xs) + count e (drop n xs) == count e xs@
+--
+-- >>> runTP $ takeDropCount @Integer
+-- Inductive lemma: countAppend
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2 (unfold count)        Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Step: 4 (simplify)            Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: take_drop                Q.E.D.
+-- Lemma: takeDropCount
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] takeDropCount :: Ɐxs ∷ [Integer] → Ɐn ∷ Integer → Ɐe ∷ Integer → Bool
+takeDropCount :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "n" Integer -> Forall "e" a -> SBool))
+takeDropCount = do
+       capp     <- countAppend @a
+       takeDrop <- take_drop   @a
+
+       calc "takeDropCount"
+            (\(Forall xs) (Forall n) (Forall e) -> count e (take n xs) + count e (drop n xs) .== count e xs) $
+            \xs n e -> [] |- count e (take n xs) + count e (drop n xs)
+                          ?? capp `at` (Inst @"xs" (take n xs), Inst @"ys" (drop n xs), Inst @"e" e)
+                          =: count e (take n xs ++ drop n xs)
+                          ?? takeDrop
+                          =: count e xs
+                          =: qed
+
+-- | @count e xs >= 0@
+--
+-- >>> runTP $ countNonNeg @Integer
+-- Inductive lemma: countNonNeg
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] countNonNeg :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
+countNonNeg :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
+countNonNeg =
+   induct "countNonNeg"
+          (\(Forall xs) (Forall e) -> count e xs .>= 0) $
+          \ih (x, xs) e -> [] |- count e (x .: xs) .>= 0
+                              =: cases [ e .== x ==> 1 + count e xs .>= 0
+                                                  ?? ih
+                                                  =: sTrue
+                                                  =: qed
+                                       , e ./= x ==> count e xs .>= 0
+                                                  ?? ih
+                                                  =: sTrue
+                                                  =: qed
+                                       ]
+
+-- | @e \`elem\` xs ==> count e xs .> 0@
+--
+-- >>> runTP $ countElem @Integer
+-- Inductive lemma: countNonNeg
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: countElem
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] countElem :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
+countElem :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
+countElem = do
+
+    cnn <- countNonNeg @a
+
+    induct "countElem"
+           (\(Forall xs) (Forall e) -> e `elem` xs .=> count e xs .> 0) $
+           \ih (x, xs) e -> [e `elem` (x .: xs)]
+                         |- count e (x .: xs) .> 0
+                         =: cases [ e .== x ==> 1 + count e xs .> 0
+                                             ?? cnn
+                                             =: sTrue
+                                             =: qed
+                                  , e ./= x ==> count e xs .> 0
+                                             ?? ih
+                                             =: sTrue
+                                             =: qed
+                                  ]
+
+-- | @count e xs .> 0 .=> e \`elem\` xs@
+--
+-- >>> runTP $ elemCount @Integer
+-- Inductive lemma: elemCount
+--   Step: Base                  Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                 Q.E.D.
+--     Step: 1.2.1               Q.E.D.
+--     Step: 1.2.2               Q.E.D.
+--     Step: 1.Completeness      Q.E.D.
+--   Result:                     Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] elemCount :: Ɐxs ∷ [Integer] → Ɐe ∷ Integer → Bool
+elemCount :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "e" a -> SBool))
+elemCount =
+    induct "elemCount"
+           (\(Forall xs) (Forall e) -> count e xs .> 0 .=> e `elem` xs) $
+           \ih (x, xs) e -> [count e xs .> 0]
+                         |- e `elem` (x .: xs)
+                         =: cases [ e .== x ==> trivial
+                                  , e ./= x ==> e `elem` xs
+                                             ?? ih
+                                             =: sTrue
+                                             =: qed
+                                  ]
+
+{- HLint ignore revRev         "Redundant reverse" -}
+{- HLint ignore allAny         "Use and"           -}
+{- HLint ignore bookKeeping    "Fuse foldr/map"    -}
+{- HLint ignore foldrMapFusion "Fuse foldr/map"    -}
+{- HLint ignore filterConcat   "Move filter"       -}
+{- HLint ignore module         "Use camelCase"     -}
+{- HLint ignore module         "Use first"         -}
+{- HLint ignore module         "Use second"        -}
+{- HLint ignore module         "Use zipWith"       -}
+{- HLint ignore mapCompose     "Use map once"      -}
+{- HLint ignore tailsAppend    "Avoid lambda"      -}
+{- HLint ignore tailsAppend    "Use :"             -}
+{- HLint ignore mapReverse     "Evaluate"          -}
+{- HLint ignore mapConcat      "Use concatMap"     -}
+{- HLint ignore takeDropWhile  "Evaluate"          -}
diff --git a/Documentation/SBV/Examples/TP/Majority.hs b/Documentation/SBV/Examples/TP/Majority.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Majority.hs
@@ -0,0 +1,157 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Majority
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving Boyer-Moore's majority algorithm correct. We follow the ACL2 proof
+-- closely, which you can find at <https://github.com/acl2/acl2/blob/master/books/demos/majority-vote.lisp>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Majority where
+
+import Prelude hiding (null, length)
+
+import Data.SBV
+import Data.SBV.List
+
+import Data.SBV.TP
+import qualified Documentation.SBV.Examples.TP.Lists as TP
+
+-- * Calculating majority
+
+-- | Given a list, calculate the majority element using Boyer-Moore's algorithm.
+-- Note that the algorithm returns the majority if it exists. If there is no
+-- majority element, then the result is irrelevant.
+majority :: SymVal a => SBV a -> SInteger -> SList a -> SBV a
+majority = smtFunction "majority"
+                    $ \c i lst -> [sCase| lst of
+                                     []               -> c
+                                     x : xs | i .== 0 -> majority x 1 xs
+                                            | True    -> majority c (i + ite (c .== x) 1 (-1)) xs
+                                  |]
+
+-- | We can now define mjrty, which simply feeds the majority function with an arbitrary element of the domain.
+-- By the definition of 'majority' above, this arbitrary element will be returned if the given list is empty.
+-- Otherwise, majority will be returned if it exists, and an element of the list otherwise.
+mjrty :: SymVal a => SList a -> SBV a
+mjrty = majority (some "arb" (const sTrue)) 0
+
+-- | The function @how-many@ in the paper is already defined in SBV as 'TP.count'. Let's give it a name:
+howMany :: SymVal a => SBV a -> SList a -> SInteger
+howMany = TP.count
+
+-- * Correctness
+
+-- | The generalized majority theorem. This comment is taken more or less
+-- directly from J's proof, cast in SBV terms:
+--
+-- This is the generalized theorem that explains how majority works on any @c@ and
+-- @i@ instead of just on the initial @c@ and @i=0@.
+--
+-- The way to imagine @majority c i xs@ is that we started with
+-- a bigger @xs'@ that contains @i@ occurrences of c followed by @xs@. That is,
+-- @xs' = replicate i c ++ xs@.  We know that @majority c 0 xs'@ finds
+-- the majority in @xs'@ if there is one.
+--
+-- So the generalized theorem supposes that @e@ occurs a majority of times in @xs'@.
+-- We can say that in terms of @c@, @i@, and @xs@: the number of times @e@ occurs in @xs@
+-- plus @i@ (if @e@ is @c@) is greater than half of the length of @xs@ plus @i@.
+--
+-- The conclusion states that @majority c i x@ is @e@. We have:
+--
+-- >>> correctness @Integer
+-- Inductive lemma: majorityGeneral
+--   Step: Base                        Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                     Q.E.D.
+--     Step: 1.1.2                     Q.E.D.
+--     Step: 1.2.1                     Q.E.D.
+--     Step: 1.2.2 (2 way case split)
+--       Step: 1.2.2.1.1               Q.E.D.
+--       Step: 1.2.2.1.2               Q.E.D.
+--       Step: 1.2.2.2.1               Q.E.D.
+--       Step: 1.2.2.2.2               Q.E.D.
+--       Step: 1.2.2.Completeness      Q.E.D.
+--     Step: 1.Completeness            Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: majority                     Q.E.D.
+-- Lemma: ifExistsFound                Q.E.D.
+-- Lemma: ifNoMajority                 Q.E.D.
+-- Lemma: uniqueness
+--   Step: 1                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: count, majority
+-- ([Proven] majority :: Ɐc ∷ Integer → Ɐxs ∷ [Integer] → Bool,[Proven] ifExistsFound :: Ɐc ∷ Integer → Ɐxs ∷ [Integer] → Bool,[Proven] ifNoMajority :: Ɐc ∷ Integer → Ɐxs ∷ [Integer] → Bool,[Proven] uniqueness :: Ɐm1 ∷ Integer → Ɐm2 ∷ Integer → Ɐxs ∷ [Integer] → Bool)
+correctness :: forall a. SymVal a
+            => IO ( Proof (Forall "c" a -> Forall "xs" [a] -> SBool)                    -- If majority exists, the calculated value is majority
+                  , Proof (Forall "c" a -> Forall "xs" [a] -> SBool)                    -- If majority exists, it is found
+                  , Proof (Forall "c" a -> Forall "xs" [a] -> SBool)                    -- If returned value isn't majority, then no majority exists
+                  , Proof (Forall "m1" a -> Forall "m2" a  -> Forall "xs" [a] -> SBool) -- Uniqueness: If there are two majorities, they're the same
+                  )
+correctness = runTP $ do
+
+  -- Helper definition
+  let isMajority :: SBV a -> SList a -> SBool
+      isMajority e xs = length xs `sEDiv` 2 .< howMany e xs
+
+  -- First prove the generalized majority theorem
+  majorityGeneral <-
+     induct "majorityGeneral"
+            (\(Forall @"xs" xs) (Forall @"i" i) (Forall @"e" (e :: SBV a)) (Forall @"c" c)
+                  -> i .>= 0 .&& (length xs + i) `sEDiv` 2 .< ite (e .== c) i 0 + howMany e xs .=> majority c i xs .== e) $
+            \ih (x, xs) i e c ->
+                   [i .>= 0, (length (x .: xs) + i) `sEDiv` 2 .< ite (e .== c) i 0 + howMany e (x .: xs)]
+                |- majority c i (x .: xs)
+                =: cases [ i .== 0 ==> majority x 1 xs
+                                    ?? ih `at` (Inst @"i" 1, Inst @"e" e, Inst @"c" x)
+                                    =: e
+                                    =: qed
+                         , i .>  0 ==> majority c (i + ite (c .== x) 1 (-1)) xs
+                                    =: cases [ c .== x ==> majority c (i + 1) xs
+                                                        ?? ih `at` (Inst @"i" (i+1), Inst @"e" e, Inst @"c" c)
+                                                        =: e
+                                                        =: qed
+                                             , c ./= x ==> majority c (i - 1) xs
+                                                        ?? ih `at` (Inst @"i" (i-1), Inst @"e" e, Inst @"c" c)
+                                                        =: e
+                                                        =: qed
+                                             ]
+                         ]
+
+  -- We can now prove the main theorem, by instantiating the general version.
+  correct <- lemma "majority"
+                   (\(Forall c) (Forall xs) -> isMajority c xs .=> mjrty xs .== c)
+                   [proofOf majorityGeneral]
+
+  -- Corollary: If there is a majority element, then what we return is a majority element:
+  ifExistsFound <- lemma "ifExistsFound"
+                        (\(Forall c) (Forall xs) -> isMajority c xs .=> isMajority (mjrty xs) xs)
+                        [proofOf correct]
+
+  -- Contrapositive to the above: If the returned value is not majority, then there is no majority:
+  ifNoMajority <- lemma "ifNoMajority"
+                        (\(Forall c) (Forall xs) -> sNot (isMajority (mjrty xs) xs) .=> sNot (isMajority c xs))
+                        [proofOf ifExistsFound]
+
+  -- Let's also prove majority is unique, while we're at it, even though it is not essential for our main argument.
+  unique <- calc "uniqueness"
+                 (\(Forall m1) (Forall m2) (Forall xs) -> isMajority m1 xs .&& isMajority m2 xs .=> m1 .== m2) $
+                 \m1 m2 xs -> [isMajority m1 xs, isMajority m2 xs]
+                           |- m1
+                           ?? correct `at` (Inst @"c" m1, Inst @"xs" xs)
+                           ?? correct `at` (Inst @"c" m2, Inst @"xs" xs)
+                           =: m2
+                           =: qed
+
+  pure (correct, ifExistsFound, ifNoMajority, unique)
diff --git a/Documentation/SBV/Examples/TP/McCarthy91.hs b/Documentation/SBV/Examples/TP/McCarthy91.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/McCarthy91.hs
@@ -0,0 +1,94 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.McCarthy91
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving McCarthy's 91 function correct.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.McCarthy91 where
+
+import Data.SBV
+import Data.SBV.TP
+
+-- * Definitions
+
+-- | Nested recursive definition of McCarthy's function. We use 'smtFunctionWithContract' because
+-- the nested recursion @mcCarthy91 (mcCarthy91 (n + 11))@ requires knowing what the inner call returns
+-- in order to verify that the outer call's measure decreases. The contract states that for inputs @≤ 100@,
+-- the result is @91@. Note that the contract itself is verified as part of the measure check: SBV proves
+-- both measure decrease and the contract simultaneously via well-founded induction.
+mcCarthy91 :: SInteger -> SInteger
+mcCarthy91 = smtFunctionWithContract "mcCarthy91"
+               ( \n -> 0 `smax` (101 - n)
+               , \n r -> n .<= 100 .=> r .== 91
+               , []
+               )
+           $ \n -> [sCase| n of
+                      _ | n .> 100 -> n - 10
+                      _            -> mcCarthy91 (mcCarthy91 (n + 11))
+                   |]
+
+-- | Specification for McCarthy's function.
+spec91 :: SInteger -> SInteger
+spec91 n = ite (n .> 100) (n - 10) 91
+
+-- * Correctness
+
+-- | We prove the equivalence of the nested recursive definition against the spec with a case analysis
+-- and strong induction. We have:
+--
+-- >>> correctness
+-- Lemma: case1                       Q.E.D.
+-- Lemma: case2                       Q.E.D.
+-- Inductive lemma (strong): case3
+--   Step: Measure is non-negative    Q.E.D.
+--   Step: 1 (unfold)                 Q.E.D.
+--   Step: 2                          Q.E.D.
+--   Result:                          Q.E.D.
+-- Lemma: mcCarthy91
+--   Step: 1 (3 way case split)
+--     Step: 1.1                      Q.E.D.
+--     Step: 1.2                      Q.E.D.
+--     Step: 1.3                      Q.E.D.
+--     Step: 1.Completeness           Q.E.D.
+--   Result:                          Q.E.D.
+-- Functions proven terminating: mcCarthy91
+-- [Proven] mcCarthy91 :: Ɐn ∷ Integer → Bool
+correctness :: IO (Proof (Forall "n" Integer -> SBool))
+correctness = runTP $ do
+
+   -- Case 1. When @n > 100@
+   case1 <- lemma "case1" (\(Forall @"n" n) -> n .>= 100 .=> mcCarthy91 n .== spec91 n) []
+
+   -- Case 2. When @90 <= n <= 100@
+   case2 <- lemma "case2" (\(Forall @"n" n) -> 90 .<= n .&& n .<= 100 .=> mcCarthy91 n .== spec91 n) []
+
+   -- Case 3. When @n < 90@. The crucial point here is the measure, which makes sure 101 < 100 < 99 < ...
+   case3 <- sInduct "case3"
+                    (\(Forall n) -> n .< 90 .=> mcCarthy91 n .== spec91 n)
+                    (\n -> abs (101 - n), []) $
+                    \ih n -> [n .< 90] |- mcCarthy91 n
+                                       ?? "unfold"
+                                       =: mcCarthy91 (mcCarthy91 (n + 11))
+                                       ?? ih `at` Inst @"n" (n + 11)
+                                       =: mcCarthy91 91
+                                       =: qed
+
+   -- Putting it all together
+   calc "mcCarthy91"
+        (\(Forall n) -> mcCarthy91 n .== spec91 n) $
+        \n -> [] |- cases [ n .> 100               ==> mcCarthy91 n ?? case1 =: spec91 n =: qed
+                          , 90 .<= n .&& n .<= 100 ==> mcCarthy91 n ?? case2 =: spec91 n =: qed
+                          , n .< 90                ==> mcCarthy91 n ?? case3 =: spec91 n =: qed
+                          ]
diff --git a/Documentation/SBV/Examples/TP/MergeSort.hs b/Documentation/SBV/Examples/TP/MergeSort.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/MergeSort.hs
@@ -0,0 +1,314 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.MergeSort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving merge sort correct.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.MergeSort where
+
+import Prelude hiding (null, length, head, tail, elem, splitAt, (++), take, drop)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+import qualified Documentation.SBV.Examples.TP.Lists       as TP
+import qualified Documentation.SBV.Examples.TP.SortHelpers as SH
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+#endif
+
+-- * Merge sort
+
+-- | Merge two already sorted lists into another
+merge :: (OrdSymbolic (SBV a), SymVal a) => SList a -> SList a -> SList a
+merge = smtFunction "merge"
+      $ \l r -> [sCase| tuple (l, r) of
+                   ([], _) -> r
+                   (_, []) -> l
+
+                   (ll@(a : as), rr@(b : bs)) | a .<= b -> a .: merge as rr
+                                              | True    -> b .: merge ll bs
+                |]
+
+-- | Merge sort, using 'merge' above to successively sort halved input
+mergeSort :: (OrdSymbolic (SBV a), SymVal a) => SList a -> SList a
+mergeSort = smtFunction "mergeSort"
+          $ \l -> [sCase| l of
+                     []  -> l
+                     [_] -> l
+                     _   -> let (h1, h2) = splitAt (length l `sEDiv` 2) l
+                            in merge (mergeSort h1) (mergeSort h2)
+                  |]
+
+-- * Correctness proof
+
+-- | Correctness of merge-sort.
+--
+-- We have:
+--
+-- >>> correctness @Integer
+-- Lemma: nonDecrInsert                                      Q.E.D.
+-- Inductive lemma: countAppend
+--   Step: Base                                              Q.E.D.
+--   Step: 1                                                 Q.E.D.
+--   Step: 2 (unfold count)                                  Q.E.D.
+--   Step: 3                                                 Q.E.D.
+--   Step: 4 (simplify)                                      Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Lemma: take_drop                                          Q.E.D.
+-- Lemma: takeDropCount
+--   Step: 1                                                 Q.E.D.
+--   Step: 2                                                 Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Lemma: countOneStep                                       Q.E.D.
+-- Lemma: mergeHead                                          Q.E.D.
+-- Lemma: mergeUnfold                                        Q.E.D.
+-- Inductive lemma (strong): mergeKeepsSort
+--   Step: Measure is non-negative                           Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                                             Q.E.D.
+--     Step: 1.2                                             Q.E.D.
+--     Step: 1.3 (2 way case split)
+--       Step: 1.3.1.1 (2 way case split)                    Q.E.D.
+--       Step: 1.3.1.2                                       Q.E.D.
+--       Step: 1.3.1.3                                       Q.E.D.
+--       Step: 1.3.2.1 (2 way case split)                    Q.E.D.
+--       Step: 1.3.2.2                                       Q.E.D.
+--       Step: 1.3.2.3                                       Q.E.D.
+--       Step: 1.3.Completeness                              Q.E.D.
+--     Step: 1.Completeness                                  Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Inductive lemma (strong): sortNonDecreasing
+--   Step: Measure is non-negative                           Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                             Q.E.D.
+--     Step: 1.2.1 (unfold)                                  Q.E.D.
+--     Step: 1.2.2 (push nonDecreasing down)                 Q.E.D.
+--     Step: 1.2.3                                           Q.E.D.
+--     Step: 1.2.4                                           Q.E.D.
+--     Step: 1.Completeness                                  Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Inductive lemma (strong): mergeCount
+--   Step: Measure is non-negative                           Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                                             Q.E.D.
+--     Step: 1.2                                             Q.E.D.
+--     Step: 1.3.1 (unfold merge)                            Q.E.D.
+--     Step: 1.3.2 (push count inside)                       Q.E.D.
+--     Step: 1.3.3 (unfold count, twice)                     Q.E.D.
+--     Step: 1.3.4                                           Q.E.D.
+--     Step: 1.3.5                                           Q.E.D.
+--     Step: 1.3.6 (unfold count in reverse, twice)          Q.E.D.
+--     Step: 1.3.7 (simplify)                                Q.E.D.
+--     Step: 1.Completeness                                  Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Inductive lemma (strong): sortIsPermutation
+--   Step: Measure is non-negative                           Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                             Q.E.D.
+--     Step: 1.2.1 (unfold mergeSort)                        Q.E.D.
+--     Step: 1.2.2 (push count down, simplify, rearrange)    Q.E.D.
+--     Step: 1.2.3                                           Q.E.D.
+--     Step: 1.2.4                                           Q.E.D.
+--     Step: 1.2.5                                           Q.E.D.
+--     Step: 1.2.6                                           Q.E.D.
+--     Step: 1.Completeness                                  Q.E.D.
+--   Result:                                                 Q.E.D.
+-- Lemma: mergeSortIsCorrect                                 Q.E.D.
+-- Functions proven terminating: count, merge, mergeSort, nonDecreasing
+-- [Proven] mergeSortIsCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. (OrdSymbolic (SBV a), SymVal a) => IO (Proof (Forall "xs" [a] -> SBool))
+correctness = runTP $ do
+
+    --------------------------------------------------------------------------------------------
+    -- Part I. Import helper lemmas, definitions
+    --------------------------------------------------------------------------------------------
+    let nonDecreasing = SH.nonDecreasing @a
+        isPermutation = SH.isPermutation @a
+        count         = TP.count         @a
+
+    nonDecrIns    <- SH.nonDecrIns    @a
+    takeDropCount <- TP.takeDropCount @a
+    cntStep       <- TP.countOneStep  @a
+
+    -- Head of merge: one unfold of merge suffices for the solver
+    mergeHead <- lemma "mergeHead"
+                    (\(Forall xs) (Forall ys) -> sNot (null ys) .=>
+                        head (merge xs ys) .== ite (null xs) (head ys) (ite (head xs .<= head ys) (head xs) (head ys)))
+                    []
+
+    -- Unfold lemma for merge's recursive case
+    mergeUnfold <- lemma "mergeUnfold"
+                    (\(Forall x) (Forall xs) (Forall y) (Forall ys) ->
+                        merge (x .: xs) (y .: ys) .== ite (x .<= y) (x .: merge xs (y .: ys)) (y .: merge (x .: xs) ys))
+                    []
+
+    --------------------------------------------------------------------------------------------
+    -- Part II. Prove that the output of merge sort is non-decreasing.
+    --------------------------------------------------------------------------------------------
+
+    mergeKeepsSort <-
+        sInductWith cvc5 "mergeKeepsSort"
+           (\(Forall xs) (Forall ys) -> nonDecreasing xs .&& nonDecreasing ys .=> nonDecreasing (merge xs ys))
+           (\xs ys -> tuple (length xs, length ys), []) $
+           \ih xs ys -> [nonDecreasing xs, nonDecreasing ys]
+                     |- [pCase| tuple (xs, ys) of
+                          ([], _)          -> trivial
+                          (_, [])          -> trivial
+                          (ll@(a : as), rr@(b : bs)) ->
+                                nonDecreasing (merge ll rr)
+                             ?? "2 way case split"
+                             =: cases [ a .<= b ==> nonDecreasing (merge ll rr)
+                                                 ?? mergeUnfold `at` (Inst @"x" a, Inst @"xs" as, Inst @"y" b, Inst @"ys" bs)
+                                                 =: nonDecreasing (a .: merge as rr)
+                                                 ?? ih         `at` (Inst @"xs" as, Inst @"ys" rr)
+                                                 ?? nonDecrIns `at` (Inst @"x" a, Inst @"xs" (merge as rr))
+                                                 ?? mergeHead  `at` (Inst @"xs" as, Inst @"ys" rr)
+                                                 =: sTrue
+                                                 =: qed
+                                      , a .> b  ==> nonDecreasing (merge ll rr)
+                                                 ?? mergeUnfold `at` (Inst @"x" a, Inst @"xs" as, Inst @"y" b, Inst @"ys" bs)
+                                                 =: nonDecreasing (b .: merge ll bs)
+                                                 ?? ih         `at` (Inst @"xs" ll, Inst @"ys" bs)
+                                                 ?? nonDecrIns `at` (Inst @"x" b, Inst @"xs" (merge ll bs))
+                                                 ?? mergeHead  `at` (Inst @"xs" ll, Inst @"ys" bs)
+                                                 =: sTrue
+                                                 =: qed
+                                      ]
+                        |]
+
+    sortNonDecreasing <-
+        sInduct "sortNonDecreasing"
+                (\(Forall xs) -> nonDecreasing (mergeSort xs))
+                (length, []) $
+                \ih xs -> [] |- [pCase| xs of
+                                  []             -> qed
+                                  whole@(_ : es) ->
+                                        nonDecreasing (mergeSort whole)
+                                     ?? "unfold"
+                                     =: let (h1, h2) = splitAt (length whole `sEDiv` 2) whole
+                                        in nonDecreasing (ite (length whole .<= 1)
+                                                              whole
+                                                              (merge (mergeSort h1) (mergeSort h2)))
+                                     ?? "push nonDecreasing down"
+                                     =: ite (length whole .<= 1)
+                                            (nonDecreasing whole)
+                                            (nonDecreasing (merge (mergeSort h1) (mergeSort h2)))
+                                     ?? ih `at` Inst @"xs" es
+                                     =: ite (length whole .<= 1)
+                                            sTrue
+                                            (nonDecreasing (merge (mergeSort h1) (mergeSort h2)))
+                                     ?? ih `at` Inst @"xs" h1
+                                     ?? ih `at` Inst @"xs" h2
+                                     ?? mergeKeepsSort `at` (Inst @"xs" (mergeSort h1), Inst @"ys" (mergeSort h2))
+                                     =: sTrue
+                                     =: qed
+                                |]
+
+    --------------------------------------------------------------------------------------------
+    -- Part III. Prove that the output of merge sort is a permutation of its input
+    --------------------------------------------------------------------------------------------
+    mergeCount <-
+        sInduct "mergeCount"
+                (\(Forall xs) (Forall ys) (Forall e) -> count e (merge xs ys) .== count e xs + count e ys)
+                (\xs ys _e -> tuple (length xs, length ys), []) $
+                \ih as bs e -> [] |- [pCase| tuple (as, bs) of
+                                      ([], _) -> trivial
+                                      (_, []) -> trivial
+
+                                      (ll@(x : xs), rr@(y : ys)) ->
+                                              count e (merge ll rr)
+                                           ?? "unfold merge"
+                                           =: count e (ite (x .<= y)
+                                                           (x .: merge xs rr)
+                                                           (y .: merge ll ys))
+                                           ?? "push count inside"
+                                           =: ite (x .<= y)
+                                                  (count e (x .: merge xs rr))
+                                                  (count e (y .: merge ll ys))
+                                           ?? "unfold count, twice"
+                                           ?? cntStep `at` (Inst @"e" e, Inst @"x" x, Inst @"xs" (merge xs rr))
+                                           ?? cntStep `at` (Inst @"e" e, Inst @"x" y, Inst @"xs" (merge ll ys))
+                                           =: ite (x .<= y)
+                                                  (let r = count e (merge xs rr) in ite (e .== x) (1+r) r)
+                                                  (let r = count e (merge ll ys) in ite (e .== y) (1+r) r)
+                                           ?? ih `at` (Inst @"xs" xs, Inst @"ys" rr, Inst @"e" e)
+                                           =: ite (x .<= y)
+                                                  (let r = count e xs + count e rr in ite (e .== x) (1+r) r)
+                                                  (let r = count e (merge ll ys) in ite (e .== y) (1+r) r)
+                                           ?? ih `at` (Inst @"xs" ll, Inst @"ys" ys, Inst @"e" e)
+                                           =: ite (x .<= y)
+                                                  (let r = count e xs + count e rr in ite (e .== x) (1+r) r)
+                                                  (let r = count e ll + count e ys in ite (e .== y) (1+r) r)
+                                           ?? "unfold count in reverse, twice"
+                                           ?? cntStep `at` (Inst @"e" e, Inst @"x" x, Inst @"xs" xs)
+                                           ?? cntStep `at` (Inst @"e" e, Inst @"x" y, Inst @"xs" ys)
+                                           =: ite (x .<= y)
+                                                  (count e ll + count e rr)
+                                                  (count e ll + count e rr)
+                                           ?? "simplify"
+                                           =: count e ll + count e rr
+                                           =: qed
+                                    |]
+
+    sortIsPermutation <-
+        sInductWith cvc5 "sortIsPermutation"
+                (\(Forall xs) (Forall e) -> count e xs .== count e (mergeSort xs))
+                (\xs _e -> length xs, []) $
+                \ih as e -> [] |- [pCase| as of
+                                    []     -> trivial
+                                    whole@(x : xs) -> count e (mergeSort whole)
+                                           ?? "unfold mergeSort"
+                                           =: count e (ite (length whole .<= 1)
+                                                           whole
+                                                           (let (h1, h2) = splitAt (length whole `sEDiv` 2) whole
+                                                            in merge (mergeSort h1) (mergeSort h2)))
+                                           ?? "push count down, simplify, rearrange"
+                                           =: let (h1, h2) = splitAt (length whole `sEDiv` 2) whole
+                                           in ite (null xs)
+                                                  (count e [x])
+                                                  (count e (merge (mergeSort h1) (mergeSort h2)))
+                                           ?? mergeCount `at` (Inst @"xs" (mergeSort h1), Inst @"ys" (mergeSort h2), Inst @"e" e)
+                                           =: ite (null xs)
+                                                  (count e [x])
+                                                  (count e (mergeSort h1) + count e (mergeSort h2))
+                                           ?? ih `at` (Inst @"xs" h1, Inst @"e" e)
+                                           =: ite (null xs)
+                                                  (count e [x])
+                                                  (count e h1 + count e (mergeSort h2))
+                                           ?? ih `at` (Inst @"xs" h2, Inst @"e" e)
+                                           =: ite (null xs)
+                                                  (count e [x])
+                                                  (count e h1 + count e h2)
+                                           ?? takeDropCount `at` (Inst @"xs" whole, Inst @"n" (length whole `sEDiv` 2), Inst @"e" e)
+                                           =: ite (null xs)
+                                                  (count e [x])
+                                                  (count e whole)
+                                           =: qed
+                                  |]
+
+    --------------------------------------------------------------------------------------------
+    -- Put the two parts together for the final proof
+    --------------------------------------------------------------------------------------------
+    lemma "mergeSortIsCorrect"
+          (\(Forall xs) -> let out = mergeSort xs in nonDecreasing out .&& isPermutation xs out)
+          [proofOf sortNonDecreasing, proofOf sortIsPermutation]
diff --git a/Documentation/SBV/Examples/TP/MutualCorecursion.hs b/Documentation/SBV/Examples/TP/MutualCorecursion.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/MutualCorecursion.hs
@@ -0,0 +1,187 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.MutualCorecursion
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrating mutually corecursive (productive) functions. Two functions
+-- @ping@ and @pong@ take turns producing elements of a stream: each emits
+-- its argument and then calls the other with the next value:
+--
+-- @
+--   ping n = n .: pong (n + 1)
+--   pong n = n .: ping (n + 1)
+-- @
+--
+-- Together they produce the natural number stream starting from @n@:
+-- @ping 0 = [0, 1, 2, 3, ...]@. We prove that the @k@-th element
+-- of @ping n@ is @n + k@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.MutualCorecursion where
+
+import Prelude hiding (head, length, (!!))
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Definitions
+
+-- | @ping n@ emits @n@ and hands off to 'pong'. Note the use of 'smtProductiveFunction':
+-- since @ping@ and @pong@ are corecursive (no base case, always producing output), we
+-- declare them productive instead of terminating.
+ping :: SInteger -> SList Integer
+ping = smtProductiveFunction "ping"
+     $ \n -> n .: pong (n + 1)
+
+-- | @pong n@ emits @n@ and hands off to 'ping'. See 'ping' for why we use 'smtProductiveFunction'.
+pong :: SInteger -> SList Integer
+pong = smtProductiveFunction "pong"
+     $ \n -> n .: ping (n + 1)
+
+-- * Helper lemmas
+
+-- | @ping@ produces unboundedly long lists.
+--
+-- >>> runTP pingLen
+-- Inductive lemma: pingLen
+--   Step: Base                Q.E.D.
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven productive: ping, pong
+-- [Proven] pingLen :: Ɐm ∷ Integer → Ɐn ∷ Integer → Bool
+pingLen :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
+pingLen = inductWith cvc5 "pingLen"
+                     (\(Forall @"m" (m :: SInteger)) (Forall @"n" n) -> length (ping n) .>= m) $
+                     \ih m n -> []
+                             |- length (ping n) .>= m + 1
+                             =: length (n .: pong (n + 1)) .>= m + 1
+                             ?? ih `at` Inst @"n" (n + 2)
+                             =: sTrue
+                             =: qed
+
+-- | @pong@ produces unboundedly long lists.
+--
+-- >>> runTP pongLen
+-- Inductive lemma: pongLen
+--   Step: Base                Q.E.D.
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven productive: ping, pong
+-- [Proven] pongLen :: Ɐm ∷ Integer → Ɐn ∷ Integer → Bool
+pongLen :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
+pongLen = inductWith cvc5 "pongLen"
+                     (\(Forall @"m" (m :: SInteger)) (Forall @"n" n) -> length (pong n) .>= m) $
+                     \ih m n -> []
+                             |- length (pong n) .>= m + 1
+                             =: length (n .: ping (n + 1)) .>= m + 1
+                             ?? ih `at` Inst @"n" (n + 2)
+                             =: sTrue
+                             =: qed
+
+-- | Indexing past a cons: @(x .: y) !! k == y !! (k - 1)@ when @k > 0@ and in bounds.
+--
+-- >>> runTP consIndex
+-- Lemma: consIndex    Q.E.D.
+-- [Proven] consIndex :: Ɐx ∷ Integer → Ɐy ∷ [Integer] → Ɐk ∷ Integer → Bool
+consIndex :: TP (Proof (Forall "x" Integer -> Forall "y" [Integer] -> Forall "k" Integer -> SBool))
+consIndex = lemma "consIndex"
+                  (\(Forall @"x" (x :: SInteger)) (Forall @"y" y) (Forall @"k" k) ->
+                        k .> 0 .&& k .<= length y .=> (x .: y) !! k .== y !! (k - 1))
+                  []
+
+-- * Correctness
+
+-- | Proving @ping n@ and @pong n@ produce the same elements. We prove that the @k@-th
+-- elements are the same, by induction on @k@.
+--
+-- >>> runTP pingEqPong
+-- Lemma: pingLen                 Q.E.D.
+-- Lemma: pongLen                 Q.E.D.
+-- Lemma: consIndex               Q.E.D.
+-- Inductive lemma: pingEqPong
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven productive: ping, pong
+-- [Proven] pingEqPong :: Ɐk ∷ Integer → Ɐn ∷ Integer → Bool
+pingEqPong :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> SBool))
+pingEqPong = do
+   piLen <- recall pingLen
+   poLen <- recall pongLen
+   ci    <- recall consIndex
+
+   inductWith cvc5 "pingEqPong"
+          (\(Forall @"k" k) (Forall @"n" n) -> k .>= 0 .=> ping n !! k .== pong n !! k) $
+          \ih k n -> [k .>= 0]
+                  |- ping n !! (k + 1)
+                  =: (n .: pong (n + 1)) !! (k + 1)
+                  ?? ci `at` (Inst @"x" n, Inst @"y" (pong (n + 1)), Inst @"k" (k + 1))
+                  ?? poLen
+                  =: pong (n + 1) !! k
+                  ?? ih `at` Inst @"n" (n + 1)
+                  =: ping (n + 1) !! k
+                  ?? ci `at` (Inst @"x" n, Inst @"y" (ping (n + 1)), Inst @"k" (k + 1))
+                  ?? piLen
+                  =: (n .: ping (n + 1)) !! (k + 1)
+                  =: pong n !! (k + 1)
+                  =: qed
+
+-- | The @k@-th element of @ping n@ is @n + k@.
+--
+-- >>> runTP pingElem
+-- Lemma: pingEqPong              Q.E.D.
+-- Lemma: consIndex               Q.E.D. [Cached]
+-- Lemma: pongLen                 Q.E.D. [Cached]
+-- Inductive lemma: pingElem
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4                      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven productive: ping, pong
+-- [Proven] pingElem :: Ɐk ∷ Integer → Ɐn ∷ Integer → Bool
+pingElem :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> SBool))
+pingElem = do
+   eq    <- recall pingEqPong
+   ci    <- recall consIndex
+   poLen <- recall pongLen
+
+   inductWith cvc5 "pingElem"
+          (\(Forall @"k" k) (Forall @"n" n) -> k .>= 0 .=> ping n !! k .== n + k) $
+          \ih k n -> [k .>= 0]
+                  |- ping n !! (k + 1)
+                  =: (n .: pong (n + 1)) !! (k + 1)
+                  ?? ci `at` (Inst @"x" n, Inst @"y" (pong (n + 1)), Inst @"k" (k + 1))
+                  ?? poLen
+                  =: pong (n + 1) !! k
+                  ?? eq `at` (Inst @"k" k, Inst @"n" (n + 1))
+                  =: ping (n + 1) !! k
+                  ?? ih `at` Inst @"n" (n + 1)
+                  =: (n + 1) + k
+                  =: n + (k + 1)
+                  =: qed
diff --git a/Documentation/SBV/Examples/TP/NatStream.hs b/Documentation/SBV/Examples/TP/NatStream.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/NatStream.hs
@@ -0,0 +1,121 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.NatStream
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrating productive (corecursive) functions. A productive function
+-- is one where every recursive call is guarded by a data constructor, so
+-- the function always makes progress by producing output. Unlike terminating
+-- functions, productive functions need not have a base case and may produce
+-- infinite output.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.NatStream where
+
+import Prelude hiding (head, length, (!!))
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Definitions
+
+-- | The infinite stream of integers starting from @n@: @[n, n+1, n+2, ...]@.
+-- There is no base case; every recursive call is guarded by the list
+-- constructor @.:@, making this a productive (corecursive) definition.
+nats :: SInteger -> SList Integer
+nats = smtProductiveFunction "nats"
+     $ \n -> n .: nats (n + 1)
+
+-- * Correctness
+
+-- | Prove that @nats n@ always starts with @n@.
+--
+-- NB. As of Mar 2026, z3 can't handle this but cvc5 can.
+--
+-- >>> runTP natsHead
+-- Lemma: natsHead     Q.E.D.
+-- Functions proven productive: nats
+-- [Proven] natsHead :: Ɐn ∷ Integer → Bool
+natsHead :: TP (Proof (Forall "n" Integer -> SBool))
+natsHead = lemmaWith cvc5 "natsHead"
+                 (\(Forall @"n" n) -> head (nats n) .== n)
+                 []
+
+-- | Prove by induction that @nats n@ has at least @m@ elements, for any @m@.
+-- This captures the idea that @nats@ produces an unboundedly long list.
+--
+-- NB. As of Mar 2026, z3 can't handle this but cvc5 can.
+--
+-- >>> runTP natsLen
+-- Inductive lemma: natsLen
+--   Step: Base                Q.E.D.
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven productive: nats
+-- [Proven] natsLen :: Ɐm ∷ Integer → Ɐn ∷ Integer → Bool
+natsLen :: TP (Proof (Forall "m" Integer -> Forall "n" Integer -> SBool))
+natsLen =
+   inductWith cvc5 "natsLen"
+          (\(Forall @"m" m) (Forall @"n" n) -> length (nats n) .>= m) $
+          \ih m n -> []
+                  |- length (nats n) .>= m + 1
+                  =: length (n .: nats (n + 1)) .>= m + 1
+                  ?? ih `at` Inst @"n" (n + 1)
+                  =: sTrue
+                  =: qed
+
+-- | Prove by induction that the @k@-th element of @nats n@ is @n + k@.
+--
+-- NB. As of Mar 2026, z3 can't handle this but cvc5 can.
+--
+-- >>> runTP natsElem
+-- Lemma: natsLen               Q.E.D.
+-- Lemma: elemOne               Q.E.D.
+-- Inductive lemma: natsElem
+--   Step: Base                 Q.E.D.
+--   Step: 1                    Q.E.D.
+--   Step: 2                    Q.E.D.
+--   Step: 3                    Q.E.D.
+--   Step: 4                    Q.E.D.
+--   Result:                    Q.E.D.
+-- Functions proven productive: nats
+-- [Proven] natsElem :: Ɐk ∷ Integer → Ɐn ∷ Integer → Bool
+natsElem :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> SBool))
+natsElem = do
+   nLen <- recall natsLen
+
+   elemOne <- lemma "elemOne"
+                    (\(Forall @"x" (x :: SInteger)) (Forall @"y" y) (Forall @"k" k) ->
+                          k .> 0 .&& k .<= length y .=> (x .: y) !! k .== y !! (k - 1))
+                    []
+
+   inductWith cvc5 "natsElem"
+          (\(Forall @"k" k) (Forall @"n" n) -> k .>= 0 .=> nats n !! k .== n + k) $
+          \ih k n -> [k .>= 0]
+                  |- nats n !! (k + 1)
+                  =: (n .: nats (n + 1)) !! (k + 1)
+                  ?? elemOne
+                  ?? nLen
+                  =: nats (n + 1) !! k
+                  ?? ih `at` Inst @"n" (n + 1)
+                  =: (n + 1) + k
+                  =: n + (k + 1)
+                  =: qed
diff --git a/Documentation/SBV/Examples/TP/Numeric.hs b/Documentation/SBV/Examples/TP/Numeric.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Numeric.hs
@@ -0,0 +1,370 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Numeric
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Example use of inductive TP proofs, over integers.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Numeric where
+
+import Prelude hiding (sum, map, product, length, (^), replicate, elem)
+
+import Data.SBV
+import Data.SBV.TP
+import Data.SBV.List
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XScopedTypeVariables
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+-- >>> import Control.Exception
+#endif
+
+-- * Sum of constants
+
+-- | \(\sum_{i=1}^{n} c = c \cdot n\)
+--
+-- >>> runTP $ sumConstProof (uninterpret "c")
+-- Inductive lemma: sumConst_correct
+--   Step: Base                         Q.E.D.
+--   Step: 1                            Q.E.D.
+--   Step: 2                            Q.E.D.
+--   Step: 3                            Q.E.D.
+--   Step: 4                            Q.E.D.
+--   Result:                            Q.E.D.
+-- Functions proven terminating: sbv.foldr, sbv.replicate
+-- [Proven] sumConst_correct :: Ɐn ∷ Integer → Bool
+sumConstProof :: SInteger -> TP (Proof (Forall "n" Integer -> SBool))
+sumConstProof c = induct "sumConst_correct"
+                         (\(Forall n) -> n .>= 0 .=> sum (replicate n c) .== c * n) $
+                         \ih n -> [n .>= 0] |- sum (replicate (n+1) c)
+                                            =: sum (c .: replicate n c)
+                                            =: c + sum (replicate n c)
+                                            ?? ih
+                                            =: c + c*n
+                                            =: c*(n+1)
+                                            =: qed
+
+-- * Sum of numbers
+
+-- | \(\sum_{i=0}^{n} i = \frac{n(n+1)}{2}\)
+--
+-- NB. We define the sum of numbers from @0@ to @n@ as @sum [sEnum|n, n-1 .. 0|]@, i.e., we
+-- construct the list starting from @n@ going down to @0@. Contrast this to the perhaps more natural
+-- definition of @sum [sEnum|0 .. n]@, i.e., going up. While the latter is equivalent functionality, the former
+-- works much better with the proof-structure: Since we induct on @n@, in each step we strip of one
+-- layer, and the recursion in the down-to construction matches the inductive schema.
+--
+-- >>> runTP sumProof
+-- Inductive lemma: sum_correct
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: EnumSymbolic.Integer.enumFromThenTo.down, sbv.foldr
+-- [Proven] sum_correct :: Ɐn ∷ Integer → Bool
+sumProof :: TP (Proof (Forall "n" Integer -> SBool))
+sumProof = induct "sum_correct"
+                  (\(Forall n) -> n .>= 0 .=> sum [sEnum|n, n-1 .. 0|] .== (n * (n+1)) `sEDiv` 2) $
+                  \ih n -> [n .>= 0] |- sum [sEnum|n+1, n .. 0|]
+                                     =: n+1 + sum [sEnum|n, n-1 .. 0|]
+                                     ?? ih
+                                     =: n+1 + (n * (n+1)) `sEDiv` 2
+                                     =: ((n+1) * (n+2)) `sEDiv` 2
+                                     =: qed
+
+-- * Sum of squares of numbers
+--
+-- | \(\sum_{i=0}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}\)
+--
+-- >>> runTP sumSquareProof
+-- Inductive lemma: sumSquare_correct
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: EnumSymbolic.Integer.enumFromThenTo.down, sbv.foldr, sbv.map
+-- [Proven] sumSquare_correct :: Ɐn ∷ Integer → Bool
+sumSquareProof :: TP (Proof (Forall "n" Integer -> SBool))
+sumSquareProof = do
+   let sq :: SInteger -> SInteger
+       sq k = k * k
+
+       sumSquare n = sum $ map sq [sEnum|n, n-1 .. 0|]
+
+   induct "sumSquare_correct"
+          (\(Forall n) -> n .>= 0 .=> sumSquare n .== (n*(n+1)*(2*n+1)) `sEDiv` 6) $
+          \ih n -> [n .>= 0] |- sumSquare (n+1)
+                             =: sum (map sq [sEnum|n+1, n .. 0|])
+                             =: sum (map sq (n+1 .: [sEnum|n, n-1 .. 0|]))
+                             =: sum ((n+1)*(n+1) .: map sq [sEnum|n, n-1 .. 0|])
+                             =: (n+1)*(n+1) + sum (map sq [sEnum|n, n-1 .. 0|])
+                             ?? ih
+                             =: (n+1)*(n+1) + (n*(n+1)*(2*n+1)) `sEDiv` 6
+                             =: ((n+1)*(n+2)*(2*n+3)) `sEDiv` 6
+                             =: qed
+
+-- * Sum of cubes of numbers
+
+-- | \(\sum_{i=0}^{n} i^3 = \left( \sum_{i=0}^{n} i \right)^2 = \left( \frac{n(n+1)}{2} \right)^2\)
+--
+-- This is attributed to Nicomachus, hence the name.
+--
+-- >>> runTP nicomachus
+-- Inductive lemma: sum_correct
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: evenHalfSquared          Q.E.D.
+-- Inductive lemma: nn1IsEven
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: sum_squared
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: nicomachus
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: EnumSymbolic.Integer.enumFromThenTo.down, sbv.foldr, sumCubed
+-- [Proven] nicomachus :: Ɐn ∷ Integer → Bool
+nicomachus :: TP (Proof (Forall "n" Integer -> SBool))
+nicomachus = do
+   let (^) :: SInteger -> Integer -> SInteger
+       _ ^ 0 = 1
+       b ^ n = b * b ^ (n-1)
+       infixr 8 ^
+
+       sumCubed :: SInteger -> SInteger
+       sumCubed = smtFunction "sumCubed" $ \n -> [sCase| n of
+                                                    _ | n .<= 0 -> 0
+                                                    _           -> n^3 + sumCubed (n - 1)
+                                                 |]
+
+   -- Grab the proof of regular summation formula
+   sp <- sumProof
+
+   -- Square of the summation result. This is a trivial lemma for humans, but there are lots
+   -- of multiplications involved making the problem non-linear and we need to spell it out.
+   ssp <- do
+        -- Squaring half of an even number? You can square the number and divide by 4 instead:
+        -- z3 can prove this out of the box, but without it being explicitly expressed, the
+        -- following proof doesn't go through.
+        evenHalfSquared <- lemma "evenHalfSquared"
+                                 (\(Forall n) -> 2 `sDivides` n .=> (n `sEDiv` 2) ^ 2 .== (n ^ 2) `sEDiv` 4)
+                                 []
+
+        -- The multiplication @n * (n+1)@ is always even. It's surprising that I had to use induction here
+        -- but neither z3 nor cvc5 can converge on this out-of-the-box.
+        nn1IsEven <- induct "nn1IsEven"
+                            (\(Forall n) -> n .>= 0 .=> 2 `sDivides` (n * (n+1))) $
+                            \ih n -> [n .>= 0] |- 2 `sDivides` ((n+1) * (n+2))
+                                               =: 2 `sDivides` (n*(n+1) + 2*(n+1))
+                                               =: 2 `sDivides` (n*(n+1))
+                                               ?? ih
+                                               =: sTrue
+                                               =: qed
+
+        calc "sum_squared"
+               (\(Forall @"n" n) -> n .>= 0 .=> sum [sEnum|n, n-1 .. 0|] ^ 2 .== (n^2 * (n+1)^2) `sEDiv` 4) $
+               \n -> [n .>= 0] |- sum [sEnum|n, n-1 .. 0|] ^ 2
+                               ?? sp `at` Inst @"n" n
+                               =: ((n * (n+1)) `sEDiv` 2)^2
+                               ?? nn1IsEven `at` Inst @"n" n
+                               ?? evenHalfSquared `at` Inst @"n" (n * (n+1))
+                               =: ((n * (n+1))^2) `sEDiv` 4
+                               =: qed
+
+   -- We can finally put it together:
+   induct "nicomachus"
+          (\(Forall n) -> n .>= 0 .=> sumCubed n .== sum [sEnum|n, n-1 .. 0|] ^ 2) $
+          \ih n -> [n .>= 0]
+                |- sumCubed (n+1)
+                =: (n+1)^3 + sumCubed n
+                ?? ih
+                ?? ssp
+                =: sum [sEnum|n+1, n .. 0|] ^ 2
+                =: qed
+
+-- * Exponents and divisibility by 7
+
+-- | \(7 \mid \left(11^n - 4^n\right)\)
+--
+-- NB. As of Feb 2025, z3 struggles with the inductive step in this proof, but cvc5 performs just fine.
+--
+-- >>> runTP elevenMinusFour
+-- Lemma: powN                         Q.E.D.
+-- Inductive lemma: elevenMinusFour
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Step: 5                           Q.E.D.
+--   Step: 6                           Q.E.D.
+--   Step: 7                           Q.E.D.
+--   Step: 8                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: pow
+-- [Proven] elevenMinusFour :: Ɐn ∷ Integer → Bool
+elevenMinusFour :: TP (Proof (Forall "n" Integer -> SBool))
+elevenMinusFour = do
+   let pow :: SInteger -> SInteger -> SInteger
+       pow = smtFunction "pow" $ \x y -> [sCase| y of
+                                            _ | y .<= 0 -> 1
+                                            _           -> x * pow x (y - 1)
+                                         |]
+
+       emf :: SInteger -> SBool
+       emf n = 7 `sDivides` (11 `pow` n - 4 `pow` n)
+
+   -- helper
+   powN <- lemma "powN" (\(Forall x) (Forall n) -> n .>= 0 .=> x `pow` (n+1) .== x * x `pow` n) []
+
+   inductWith cvc5 "elevenMinusFour"
+          (\(Forall n) -> n .>= 0 .=> emf n) $
+          \ih n -> [n .>= 0]
+                |- emf (n+1)
+                =: 7 `sDivides` (11 `pow` (n+1) - 4 `pow` (n+1))
+                ?? powN `at` (Inst @"x" 11, Inst @"n" n)
+                =: 7 `sDivides` (11 * 11 `pow` n - 4 `pow` (n+1))
+                ?? powN `at` (Inst @"x" 4, Inst @"n" n)
+                =: 7 `sDivides` (11 * 11 `pow` n - 4 * 4 `pow` n)
+                =: 7 `sDivides` (7 * 11 `pow` n + 4 * 11 `pow` n - 4 * 4 `pow` n)
+                =: 7 `sDivides` (7 * 11 `pow` n + 4 * (11 `pow` n - 4 `pow` n))
+                ?? ih
+                =: let x = some "x" (\v -> 7*v .== 11 `pow` n - 4 `pow` n)   -- Apply the IH and grab the witness for it
+                in 7 `sDivides` (7 * 11 `pow` n + 4 * 7 * x)
+                =: 7 `sDivides` (7 * (11 `pow` n + 4 * x))
+                =: sTrue
+                =: qed
+
+-- * A proof about factorials
+
+-- | \(\sum_{k=0}^{n} k \cdot k! = (n+1)! - 1\)
+--
+-- >>> runTP sumMulFactorial
+-- Lemma: fact (n+1)
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Inductive lemma: sumMulFactorial
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Step: 5                           Q.E.D.
+--   Step: 6                           Q.E.D.
+--   Step: 7                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: EnumSymbolic.Integer.enumFromThenTo.down, sbv.foldr, sbv.map
+-- [Proven] sumMulFactorial :: Ɐn ∷ Integer → Bool
+sumMulFactorial :: TP (Proof (Forall "n" Integer -> SBool))
+sumMulFactorial = do
+  let fact :: SInteger -> SInteger
+      fact n = product [sEnum|n, n-1 .. 1|]
+
+  -- This is pure expansion, but without it z3 struggles in the next lemma.
+  helper <- calc "fact (n+1)"
+                 (\(Forall n) -> n .>= 0 .=> fact (n+1) .== (n+1) * fact n) $
+                 \n -> [n .>= 0] |- fact (n+1)
+                                 =: product [sEnum|n+1, n .. 1|]
+                                 =: product (n+1 .: [sEnum|n, n-1 .. 1|])
+                                 =: (n+1) * product [sEnum|n, n-1 .. 1|]
+                                 =: (n+1) * fact n
+                                 =: qed
+
+  induct "sumMulFactorial"
+         (\(Forall n) -> n .>= 0 .=> sum (map (\k -> k * fact k) [sEnum|n, n-1 .. 0|]) .== fact (n+1) - 1) $
+         \ih n -> [n .>= 0] |- sum (map (\k -> k * fact k) [sEnum|n+1, n .. 0|])
+                            =: sum (map (\k -> k * fact k) (n+1 .: [sEnum|n, n-1 .. 0|]))
+                            =: sum ((n+1) * fact (n+1) .: map (\k -> k * fact k) [sEnum|n, n-1 .. 0|])
+                            =: (n+1) * fact (n+1) + sum (map (\k -> k * fact k) [sEnum|n, n-1 .. 0|])
+                            ?? ih
+                            =: (n+1) * fact (n+1) + fact (n+1) - 1
+                            =: ((n+1) + 1) * fact (n+1) - 1
+                            =: (n+2) * fact (n+1) - 1
+                            ?? helper `at` Inst @"n" (n+1)
+                            =: fact (n+2) - 1
+                            =: qed
+
+-- * Product with 0
+
+-- | \(\prod_{x \in xs} x = 0 \iff 0 \in xs\)
+--
+-- >>> runTP product0
+-- Inductive lemma: product0
+--   Step: Base                 Q.E.D.
+--   Step: 1                    Q.E.D.
+--   Step: 2 (2 way case split)
+--     Step: 2.1                Q.E.D.
+--     Step: 2.2.1              Q.E.D.
+--     Step: 2.2.2              Q.E.D.
+--     Step: 2.Completeness     Q.E.D.
+--   Result:                    Q.E.D.
+-- Functions proven terminating: sbv.foldr
+-- [Proven] product0 :: Ɐxs ∷ [Integer] → Bool
+product0 :: TP (Proof (Forall "xs" [Integer] -> SBool))
+product0 =
+  induct "product0"
+         (\(Forall @"xs" (xs :: SList Integer)) -> product xs .== 0 .<=> 0 `elem` xs) $
+         \ih (x, xs) -> [] |- (product (x .: xs) .== 0 .<=> 0 `elem` (x .: xs))
+                           =: (x * product xs .== 0 .<=> x .== 0 .|| 0 `elem` xs)
+                           =: cases [ x .== 0 ==> trivial
+                                    , x ./= 0 ==> (x * product xs .== 0 .<=> 0 `elem` xs)
+                                               ?? ih
+                                               =: sTrue
+                                               =: qed
+                                    ]
+
+-- * A negative example
+
+-- | The regular inductive proof on integers (i.e., proving at @0@, assuming at @n@ and proving at
+-- @n+1@ will not allow you to conclude things when @n < 0@. The following example demonstrates this with the most
+-- obvious example:
+--
+-- >>> badNonNegative `catch` (\(_ :: SomeException) -> pure ())
+-- Inductive lemma: badNonNegative
+--   Step: Base                       Q.E.D.
+--   Step: 1
+-- *** Failed to prove badNonNegative.1.
+-- Falsifiable. Counter-example:
+--   n = -2 :: Integer
+badNonNegative :: IO ()
+badNonNegative = runTP $ do
+    _ <- induct "badNonNegative"
+                (\(Forall @"n" (n :: SInteger)) -> n .>= 0) $
+                \ih n -> [] |- n + 1 .>= 0
+                            ?? ih
+                            =: sTrue
+                            =: qed
+    pure ()
diff --git a/Documentation/SBV/Examples/TP/Peano.hs b/Documentation/SBV/Examples/TP/Peano.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Peano.hs
@@ -0,0 +1,926 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Peano
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Modeling Peano arithmetic in SBV and proving various properties using TP.
+-- Most of the properties we prove come from <https://en.wikipedia.org/wiki/Peano_axioms>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Peano where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- | Natural numbers. (If you are looking at the haddock documents, note the plethora of definitions
+-- the call to 'mkSymbolic' generates. You can mostly ignore these, except for the case analyzer,
+-- the testers and accessors.)
+data Nat = Zero
+         | Succ { prev :: Nat }
+
+-- | Create a symbolic version of naturals.
+mkSymbolic [''Nat]
+
+-- | Numeric instance. Choices: We clamp everything at Zero. Negation is identity.
+instance Num Nat where
+  fromInteger i | i <= 0 = Zero
+                | True   = Succ (fromInteger (i - 1))
+
+  a + Zero   = a
+  a + Succ b = Succ (a + b)
+
+  (-) = error "Nat: No support for subtraction"
+
+  _ * Zero   = Zero
+  a * Succ b = a + a * b
+
+  abs = id
+
+  signum Zero = 0
+  signum _    = 1
+
+  negate = id
+
+-- Symbolic numeric instance, mirroring the above
+instance Num SNat where
+  fromInteger = literal . fromInteger
+
+  (+) = plus
+      where plus = smtFunction "sNatPlus" $
+                     \m n -> [sCase| m of
+                               Zero   -> n
+                               Succ p -> sSucc (p + n)
+                             |]
+
+  (-) = error "SNat: No support for subtraction"
+
+  (*) = times
+      where times = smtFunction "sNatTimes" $
+                      \m n -> [sCase| m of
+                                Zero   -> 0
+                                Succ p -> n + p * n
+                              |]
+
+  abs = id
+
+  signum m = [sCase| m of
+               Zero -> 0
+               _    -> 1
+             |]
+
+-- | Symbolic ordering. We only define less-than, other methods use the defaults.
+instance OrdSymbolic SNat where
+   m .< n = quantifiedBool (\(Exists k) -> n .== m + sSucc k)
+
+-- * Conversion to and from integers
+
+-- | Convert from 'Nat' to 'Integer'.
+--
+-- NB. When writing the properties below, we use the notation \(\overline{n}\) to mean @n2i n@.
+n2i :: SNat -> SInteger
+n2i = smtFunction "n2i" $ \n -> [sCase| n of
+                                   Zero   -> 0
+                                   Succ p -> 1 + n2i p
+                                |]
+
+-- | Convert Non-negative integers to 'Nat'. Negative numbers become Zero.
+--
+-- NB. When writing the properties below, we use the notation \(\underline{i}\) to mean @i2n i@.
+i2n :: SInteger -> SNat
+i2n = smtFunction "i2n" $ \i -> [sCase| i of
+                                   _ | i .<= 0 -> 0
+                                   _           -> sSucc (i2n (i - 1))
+                                |]
+
+-- | \(\overline{n} \geq 0\)
+--
+-- >>> runTP n2iNonNeg
+-- Lemma: n2iNonNeg    Q.E.D.
+-- Functions proven terminating: n2i
+-- [Proven] n2iNonNeg :: Ɐn ∷ Nat → Bool
+n2iNonNeg  :: TP (Proof (Forall "n" Nat -> SBool))
+n2iNonNeg = inductiveLemma "n2iNonNeg" (\(Forall n) -> n2i n .>= 0) []
+
+-- | \(\overline{\underline{i}} = \max(i, 0)\).
+--
+-- >>> runTP i2n2i
+-- Lemma: i2n2i        Q.E.D.
+-- Functions proven terminating: i2n, n2i
+-- [Proven] i2n2i :: Ɐi ∷ Integer → Bool
+i2n2i :: TP (Proof (Forall "i" Integer -> SBool))
+i2n2i = inductiveLemma "i2n2i" (\(Forall i) -> n2i (i2n i) .== i `smax` 0) []
+
+-- | \(\underline{\overline{n}} = n\)
+--
+-- >>> runTP n2i2n
+-- Lemma: n2i2n        Q.E.D.
+-- Functions proven terminating: i2n, n2i
+-- [Proven] n2i2n :: Ɐn ∷ Nat → Bool
+n2i2n :: TP (Proof (Forall "n" Nat -> SBool))
+n2i2n = inductiveLemma "n2i2n" (\(Forall n) -> i2n (n2i n) .== n) []
+
+-- | \(\overline{m + n} = \overline{m} + \overline{n}\)
+--
+-- >>> runTP n2iAdd
+-- Lemma: n2iAdd       Q.E.D.
+-- Functions proven terminating: n2i, sNatPlus
+-- [Proven] n2iAdd :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+n2iAdd :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+n2iAdd = inductiveLemma "n2iAdd" (\(Forall m) (Forall n) -> n2i (m + n) .== n2i m + n2i n) []
+
+-- * Addition
+
+-- ** Correctness
+
+-- | \(\overline{m + n} = \overline{m} + \overline{n}\)
+--
+-- >>> runTP addCorrect
+-- Lemma: addCorrect    Q.E.D.
+-- Functions proven terminating: n2i, sNatPlus
+-- [Proven] addCorrect :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addCorrect :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addCorrect = inductiveLemma
+               "addCorrect"
+               (\(Forall m) (Forall n) -> n2i (m + n) .== n2i m + n2i n)
+               []
+
+-- ** Left and right unit
+
+-- | \(0 + m = m\)
+--
+-- >>> runTP addLeftUnit
+-- Lemma: addLeftUnit    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addLeftUnit :: Ɐm ∷ Nat → Bool
+addLeftUnit :: TP (Proof (Forall "m" Nat -> SBool))
+addLeftUnit = lemma "addLeftUnit" (\(Forall m) -> 0 + m .== m) []
+
+-- | \(m + 0 = m\)
+--
+-- >>> runTP addRightUnit
+-- Lemma: addRightUnit    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addRightUnit :: Ɐm ∷ Nat → Bool
+addRightUnit :: TP (Proof (Forall "m" Nat -> SBool))
+addRightUnit = inductiveLemma "addRightUnit" (\(Forall m) -> m + 0 .== m) []
+
+-- ** Addition with non-zero values
+
+-- | \(m + \mathrm{Succ}\,n = \mathrm{Succ}\,(m + n)\)
+--
+-- >>> runTP addSucc
+-- Lemma: caseZero     Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1           Q.E.D.
+--   Step: 2           Q.E.D.
+--   Step: 3           Q.E.D.
+--   Result:           Q.E.D.
+-- Lemma: addSucc      Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addSucc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addSucc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addSucc = do
+   caseZero <- lemma "caseZero"
+                      (\(Forall @"n" n) -> 0 + sSucc n .== sSucc (0 + n))
+                      []
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) ->
+                        m + sSucc n .== sSucc (m + n) .=> sSucc m + sSucc n .== sSucc (sSucc m + n)) $
+                    \m n -> let ih = m + sSucc n .== sSucc (m + n)
+                         in [ih] |- sSucc m + sSucc n
+                                 =: sSucc (m + sSucc n)
+                                 ?? ih
+                                 =: sSucc (sSucc (m + n))
+                                 =: sSucc (sSucc m + n)
+                                 =: qed
+
+   inductiveLemma
+      "addSucc"
+      (\(Forall @"m" m) (Forall @"n" n) -> m + sSucc n .== sSucc (m + n))
+      [proofOf caseZero, proofOf caseSucc]
+
+-- ** Associativity
+
+-- | \(m + (n + o) = (m + n) + o\)
+--
+-- >>> runTP addAssoc
+-- Lemma: addAssoc     Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addAssoc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+addAssoc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+addAssoc = inductiveLemma
+             "addAssoc"
+             (\(Forall m) (Forall n) (Forall o) -> m + (n + o) .== (m + n) + o)
+             []
+
+-- ** Commutativity
+
+-- | \(m + n = n + m\)
+--
+-- >>> runTP addComm
+-- Lemma: addLeftUnit     Q.E.D.
+-- Lemma: addRightUnit    Q.E.D.
+-- Lemma: caseZero        Q.E.D.
+-- Lemma: addSucc         Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Result:              Q.E.D.
+-- Lemma: addComm         Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addComm :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+addComm :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+addComm = do
+    alu <- recall addLeftUnit
+    aru <- recall addRightUnit
+
+    caseZero <- lemma "caseZero"
+                      (\(Forall @"n" (n :: SNat)) -> 0 + n .== n + 0)
+                      [proofOf alu, proofOf aru]
+
+    as <- recall addSucc
+
+    caseSucc <- calc "caseSucc"
+                     (\(Forall @"m" m) (Forall @"n" n) -> m + n .== n + m .=> sSucc m + n .== n + sSucc m) $
+                     \m n -> let ih = m + n .== n + m
+                          in [ih] |- sSucc m + n
+                                  =: sSucc (m + n)
+                                  ?? ih
+                                  =: sSucc (n + m)
+                                  ?? as `at` (Inst @"m" n, Inst @"n" m)
+                                  =: n + sSucc m
+                                  =: qed
+
+    inductiveLemma "addComm"
+                   (\(Forall m) (Forall n) -> m + n .== n + m)
+                   [proofOf caseZero, proofOf caseSucc]
+
+-- * Multiplication
+
+-- ** Correctness
+
+-- | \(\overline{m * n} = \overline{m} * \overline{n}\)
+--
+-- >>> runTP mulCorrect
+-- Lemma: caseZero       Q.E.D.
+-- Lemma: addCorrect     Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1             Q.E.D.
+--   Step: 2             Q.E.D.
+--   Step: 3             Q.E.D.
+--   Step: 4             Q.E.D.
+--   Step: 5             Q.E.D.
+--   Result:             Q.E.D.
+-- Lemma: mullCorrect    Q.E.D.
+-- Functions proven terminating: n2i, sNatPlus, sNatTimes
+-- [Proven] mullCorrect :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulCorrect :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulCorrect = do
+   caseZero <- lemma "caseZero"
+                     (\(Forall @"n" n) -> n2i (0 * n) .== n2i 0 * n2i n)
+                     []
+
+   addC <- recall addCorrect
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) ->
+                          n2i (m * n) .== n2i m * n2i n .=> n2i (sSucc m * n) .== n2i (sSucc m) * n2i n) $
+                    \m n -> let ih = n2i (m * n) .== n2i m * n2i n
+                         in [ih] |- n2i (sSucc m * n)
+                                 =: n2i (n + m * n)
+                                 ?? addC `at` (Inst @"m" n, Inst @"n" (m * n))
+                                 =: n2i n + n2i (m * n)
+                                 ?? ih
+                                 =: n2i n + n2i m * n2i n
+                                 =: n2i n * (1 + n2i m)
+                                 =: n2i n * n2i (sSucc m)
+                                 =: qed
+
+   inductiveLemma
+       "mullCorrect"
+       (\(Forall @"m" m) (Forall @"n" n) -> n2i (m * n) .== n2i m * n2i n)
+       [proofOf caseZero, proofOf caseSucc]
+
+-- ** Left and right absorption
+
+-- | \(0 * m = 0\)
+--
+-- >>> runTP mulLeftAbsorb
+-- Lemma: mulLeftAbsorb    Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulLeftAbsorb :: Ɐm ∷ Nat → Bool
+mulLeftAbsorb :: TP (Proof (Forall "m" Nat -> SBool))
+mulLeftAbsorb = lemma "mulLeftAbsorb" (\(Forall m) -> 0 * m .== 0) []
+
+-- | \(m * 0 = 0\)
+--
+-- >>> runTP mulRightAbsorb
+-- Lemma: mulRightAbsorb    Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulRightAbsorb :: Ɐm ∷ Nat → Bool
+mulRightAbsorb :: TP (Proof (Forall "m" Nat -> SBool))
+mulRightAbsorb = inductiveLemma "mulRightAbsorb" (\(Forall m) -> m * 0 .== 0) []
+
+-- ** Left and right unit
+
+-- | \(\mathrm{Succ\,0} * m = m\)
+--
+-- >>> runTP mulLeftUnit
+-- Lemma: mulLeftUnit    Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulLeftUnit :: Ɐm ∷ Nat → Bool
+mulLeftUnit :: TP (Proof (Forall "m" Nat -> SBool))
+mulLeftUnit = inductiveLemma "mulLeftUnit" (\(Forall m) -> sSucc 0 * m .== m) []
+
+-- | \(m * \mathrm{Succ\,0} = m\)
+--
+-- >>> runTP mulRightUnit
+-- Lemma: mulRightUnit    Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulRightUnit :: Ɐm ∷ Nat → Bool
+mulRightUnit :: TP (Proof (Forall "m" Nat -> SBool))
+mulRightUnit = inductiveLemma "mulRightUnit" (\(Forall m) -> m * sSucc 0 .== m) []
+
+-- ** Distribution over addition
+
+-- | \(m * (n + o) = m * n + m * o\)
+--
+-- >>> runTP distribLeft
+-- Lemma: caseZero        Q.E.D.
+-- Lemma: addAssoc        Q.E.D.
+-- Lemma: addComm         Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Step: 4              Q.E.D.
+--   Step: 5              Q.E.D.
+--   Step: 6              Q.E.D.
+--   Step: 7              Q.E.D.
+--   Step: 8              Q.E.D.
+--   Step: 9              Q.E.D.
+--   Result:              Q.E.D.
+-- Lemma: distribLeft     Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] distribLeft :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+distribLeft :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+distribLeft = do
+   caseZero <- lemma "caseZero" (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> 0 * (n + o) .== 0 * n + 0 * o) []
+
+   addAsc <- recall addAssoc
+   addCom <- recall addComm
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                        m * (n + o) .== m * n + m * o .=> sSucc m * (n + o) .== sSucc m * n + sSucc m * o) $
+               \m n o -> let ih = m * (n + o) .== m * n + m * o
+                      in [ih] |- sSucc m * (n + o)
+                              =: (n + o) + m * (n + o)
+                              ?? ih
+                              =: (n + o) + (m * n + m * o)
+                              ?? addAsc `at` (Inst @"m" n, Inst @"n" o, Inst @"o" (m * n + m * o))
+                              =: n + (o + (m * n + m * o))
+                              ?? addCom `at` (Inst @"m" (m * n), Inst @"n" (m * o))
+                              =: n + (o + (m * o + m * n))
+                              ?? addAsc `at` (Inst @"m" o, Inst @"n" (m * o), Inst @"o" (m * n))
+                              =: n + ((o + m * o) + m * n)
+                              =: n + (sSucc m * o + m * n)
+                              ?? addCom `at` (Inst @"m" (sSucc m * o), Inst @"n" (m * n))
+                              =: n + (m * n + sSucc m * o)
+                              ?? addAsc `at` (Inst @"m" n, Inst @"n" (m * n), Inst @"o" (sSucc m * o))
+                              =: (n + m * n) + sSucc m * o
+                              =: sSucc m * n + sSucc m * o
+                              =: qed
+
+   inductiveLemma
+     "distribLeft"
+     (\(Forall m) (Forall n) (Forall o) -> m * (n + o) .== m * n + m * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- | \((m + n) * o = m * o + n * o\)
+--
+-- >>> runTP distribRight
+-- Lemma: caseZero        Q.E.D.
+-- Lemma: addAssoc        Q.E.D.
+-- Lemma: addComm         Q.E.D.
+-- Lemma: addSucc         Q.E.D. [Cached]
+-- Lemma: caseSucc
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Step: 4              Q.E.D.
+--   Step: 5              Q.E.D.
+--   Step: 6              Q.E.D.
+--   Step: 7              Q.E.D.
+--   Result:              Q.E.D.
+-- Lemma: distribRight    Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] distribRight :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+distribRight :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+distribRight = do
+   caseZero <- lemma "caseZero" (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> (0 + n) * o .== 0 * o + n * o) []
+
+   pAddAssoc <- recall addAssoc
+   pAddCom   <- recall addComm
+   pAddSucc  <- recall addSucc
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                        (m + n) * o .== m * o + n * o .=> (sSucc m + n) * o .== sSucc m * o + n * o) $
+               \m n o -> let ih = (m + n) * o .== m * o + n * o
+                      in [ih] |- (sSucc m + n) * o
+                              ?? pAddCom `at` (Inst @"m" (sSucc m), Inst @"n" n)
+                              =: (n + sSucc m) * o
+                              ?? pAddSucc `at` (Inst @"m" n, Inst @"n" m)
+                              =: sSucc (n + m) * o
+                              ?? pAddCom `at` (Inst @"m" n, Inst @"n" m)
+                              =: sSucc (m + n) * o
+                              =: o + (m + n) * o
+                              ?? ih
+                              =: o + (m * o + n *o)
+                              ?? pAddAssoc `at` (Inst @"m" o, Inst @"n" (m * o), Inst @"o" (n * o))
+                              =: (o + m * o) + n * o
+                              =: sSucc m * o + n * o
+                              =: qed
+
+   inductiveLemma
+     "distribRight"
+     (\(Forall m) (Forall n) (Forall o) -> (m + n) * o .== m * o + n * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- ** Multiplication with non-zero values
+
+-- | \(m * \mathrm{Succ}\,n = m * n + m\)
+--
+-- >>> runTP mulSucc
+-- Lemma: addLeftUnit       Q.E.D.
+-- Lemma: distribLeft       Q.E.D.
+-- Lemma: mulRightUnit      Q.E.D.
+-- Lemma: addComm           Q.E.D. [Cached]
+-- Lemma: mulSucc
+--   Step: 1                Q.E.D.
+--   Step: 2 (defn of +)    Q.E.D.
+--   Step: 3                Q.E.D.
+--   Step: 4                Q.E.D.
+--   Step: 5                Q.E.D.
+--   Result:                Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulSucc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulSucc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulSucc = do
+   alu <- recall addLeftUnit
+   dL  <- recall distribLeft
+   mru <- recall mulRightUnit
+   ac  <- recall addComm
+
+   calc "mulSucc"
+        (\(Forall @"m" m) (Forall @"n" n) -> m * sSucc n .== m * n + m) $
+        \m n -> [] |- m * sSucc n
+                   ?? alu
+                   =: m * sSucc (0 + n)
+                   ?? "defn of +"
+                   =: m * (sSucc 0 + n)
+                   ?? dL `at` (Inst @"m" m, Inst @"n" (sSucc 0), Inst @"o" n)
+                   =: m * sSucc 0 + m * n
+                   ?? mru
+                   =: m + m * n
+                   ?? ac `at` (Inst @"m" m, Inst @"n" (m * n))
+                   =: m * n + m
+                   =: qed
+
+-- ** Associativity
+
+-- | \(m * (n * o) = (m * n) * o\)
+--
+-- >>> runTP mulAssoc
+-- Lemma: caseZero        Q.E.D.
+-- Lemma: distribRight    Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Step: 4              Q.E.D.
+--   Result:              Q.E.D.
+-- Lemma: mulAssoc        Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulAssoc :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+mulAssoc :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+mulAssoc = do
+   caseZero <- lemma "caseZero"
+                     (\(Forall @"n" n) (Forall @"o" (o :: SNat)) -> 0 * (n * o) .== (0 * n) * o)
+                     []
+
+   distR <- recall distribRight
+
+   caseSucc <- calc "caseSucc"
+                    (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) ->
+                       m * (n * o) .== (m * n) * o .=> sSucc m * (n * o) .== (sSucc m * n) * o) $
+                    \m n o -> let ih = m * (n * o) .== (m * n) * o
+                              in [ih] |- sSucc m * (n * o)
+                                      =: (n * o) + m * (n * o)
+                                      ?? ih
+                                      =: (n * o) + (m * n) * o
+                                      ?? distR `at` (Inst @"m" n, Inst @"n" (m * n), Inst @"o" o)
+                                      =: (n + m * n) * o
+                                      =: (sSucc m * n) * o
+                                      =: qed
+
+   inductiveLemma
+     "mulAssoc"
+     (\(Forall m) (Forall n) (Forall o) -> m * (n * o) .== (m * n) * o)
+     [proofOf caseZero, proofOf caseSucc]
+
+-- ** Commutativity
+
+-- | \(m * n = n * m\)
+--
+-- >>> runTP mulComm
+-- Lemma: mulRightAbsorb    Q.E.D.
+-- Lemma: caseZero          Q.E.D.
+-- Lemma: mulRightUnit      Q.E.D.
+-- Lemma: distribLeft       Q.E.D.
+-- Lemma: caseSucc
+--   Step: 1                Q.E.D.
+--   Step: 2                Q.E.D.
+--   Step: 3                Q.E.D.
+--   Step: 4                Q.E.D.
+--   Step: 5                Q.E.D.
+--   Step: 6                Q.E.D.
+--   Result:                Q.E.D.
+-- Lemma: mulComm           Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulComm :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+mulComm :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+mulComm = do
+  mra <- recall mulRightAbsorb
+
+  caseZero <- lemma "caseZero"
+                    (\(Forall @"m" (m :: SNat)) -> 0 * m .== m * 0)
+                    [proofOf mra]
+
+  mru <- recall mulRightUnit
+  dL  <- recall distribLeft
+
+  caseSucc <- calc "caseSucc"
+                   (\(Forall @"m" m) (Forall @"n" n) -> m * n .== n * m .=> sSucc m * n .== n * sSucc m) $
+                   \m n -> let ih = m * n .== n * m
+                        in [ih] |- sSucc m * n
+                                =: n + m * n
+                                ?? ih
+                                =: n + n * m
+                                ?? mru
+                                =: n * sSucc 0 + n * m
+                                ?? dL `at` (Inst @"m" n, Inst @"n" (sSucc 0), Inst @"o" m)
+                                =: n * (sSucc 0 + m)
+                                =: n * sSucc (0 + m)
+                                =: n * sSucc m
+                                =: qed
+
+  inductiveLemma
+    "mulComm"
+    (\(Forall @"m" m) (Forall @"n" n) -> m * n .== n * m)
+    [proofOf caseZero, proofOf caseSucc]
+
+-- * Ordering
+
+-- ** Transitivity of @<@
+
+-- | \(m < n \;\wedge\; n < o \;\rightarrow\; m < o\)
+--
+-- >>> runTP ltTrans
+-- Lemma: addAssoc     Q.E.D.
+-- Lemma: ltTrans
+--   Step: 1           Q.E.D.
+--   Step: 2           Q.E.D.
+--   Step: 3           Q.E.D.
+--   Step: 4           Q.E.D.
+--   Step: 5           Q.E.D.
+--   Step: 6           Q.E.D.
+--   Result:           Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] ltTrans :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+ltTrans :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+ltTrans = do
+  aa <- recall addAssoc
+
+  calc "ltTrans"
+       (\(Forall @"m" m) (Forall @"n" n) (Forall @"o" o) -> m .< n .&& n .< o .=> m .< o) $
+       \m n o ->  [m .< n, n .< o]
+              |-> let k1 = some "k1" (\k -> n .== m + sSucc k)
+                      k2 = some "k2" (\k -> o .== n + sSucc k)
+               in n .== m + sSucc k1
+               =: o .== n + sSucc k2
+               =: o .== (m + sSucc k1) + sSucc k2
+               ?? aa `at` (Inst @"m" m, Inst @"n" (sSucc k1), Inst @"o" (sSucc k2))
+               =: o .== m + (sSucc k1 + sSucc k2)
+               =: o .== m + sSucc (k1 + sSucc k2)
+               =: m .< o
+               =: sTrue
+               =: qed
+
+-- ** Irreflexivity of @<@
+
+-- | \(\neg(m < m)\)
+--
+-- >>> runTP ltIrreflexive
+-- Lemma: cancel           Q.E.D.
+-- Lemma: ltIrreflexive
+--   Step: 1               Q.E.D.
+--   Step: 2               Q.E.D.
+--   Result:               Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] ltIrreflexive :: Ɐm ∷ Nat → Bool
+ltIrreflexive :: TP (Proof (Forall "m" Nat -> SBool))
+ltIrreflexive = do
+  cancel <- inductiveLemma
+              "cancel"
+              (\(Forall @"m" m) (Forall @"n" n) -> m + n .== m .=> n .== 0)
+              []
+
+  calc "ltIrreflexive"
+       (\(Forall @"m" m) -> sNot (m .< m)) $
+       \m -> [m .< m] |-> let k = some "k" (\d -> m .== m + sSucc d)
+                      in m .== m + sSucc k
+                      ?? cancel `at` (Inst @"m" m, Inst @"n" (sSucc k))
+                      =: sSucc k .== 0
+                      =: contradiction
+
+-- ** Trichotomy
+
+-- | \(m \geq n = \overline{m} \geq \overline{n}\)
+--
+-- >>> runTP lteEquiv
+-- Lemma: n2iAdd               Q.E.D.
+-- Lemma: n2iNonNeg            Q.E.D.
+-- Lemma: n2i2n                Q.E.D.
+-- Lemma: i2n2i                Q.E.D.
+-- Lemma: addRightUnit         Q.E.D.
+-- Lemma: lteEquiv_ltr
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.2.3             Q.E.D.
+--     Step: 1.2.4             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- Lemma: lteEquiv_rtl
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Step: 3                   Q.E.D.
+--   Step: 4                   Q.E.D.
+--   Step: 5                   Q.E.D.
+--   Step: 6                   Q.E.D.
+--   Step: 7 (2 way case split)
+--     Step: 7.1               Q.E.D.
+--     Step: 7.2.1             Q.E.D.
+--     Step: 7.2.2             Q.E.D.
+--     Step: 7.2.3             Q.E.D.
+--     Step: 7.2.4             Q.E.D.
+--     Step: 7.2.5             Q.E.D.
+--     Step: 7.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- Lemma: lteEquiv             Q.E.D.
+-- Functions proven terminating: i2n, n2i, sNatPlus
+-- [Proven] lteEquiv :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+lteEquiv :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+lteEquiv = do
+    n2ia    <- recall n2iAdd
+    nn      <- recall n2iNonNeg
+    n2i2nId <- recall n2i2n
+    i2n2iId <- recall i2n2i
+    aru     <- recall addRightUnit
+
+    ltr <- calcWith cvc5 "lteEquiv_ltr"
+              (\(Forall @"m" m) (Forall @"n" n) -> (m .>= n) .=> (n2i m .>= n2i n)) $
+              \m n -> [m .>= n]
+                   |- n2i m .>= n2i n
+                    =: cases [ m .== n ==> trivial
+                             , m .>  n ==> let k = some "k" (\d -> m .== n + sSucc d)
+                                        in n2i m .>= n2i n
+                                        ?? m .> n
+                                        =: n2i (n + sSucc k) .>= n2i n
+                                        ?? n2ia `at` (Inst @"m" n, Inst @"n" (sSucc k))
+                                        =: n2i n + n2i (sSucc k) .>= n2i n
+                                        ?? nn `at` Inst @"n" (sSucc k)
+                                        =: sTrue
+                                        =: qed
+                             ]
+
+    rtl <- calc "lteEquiv_rtl"
+                (\(Forall @"m" m) (Forall @"n" n) -> (n2i m .>= n2i n) .=> (m .>= n)) $
+                \m n -> [n2i m .>= n2i n]
+                     |-> let k = n2i m - n2i n
+                     in k .>= 0
+                     =: n2i m .== n2i n + k
+                     ?? i2n2iId `at` Inst @"i" k
+                     =: n2i m .== n2i n + n2i (i2n k)
+                     ?? n2ia `at` (Inst @"m" n, Inst @"n" (i2n k))
+                     =: n2i m .== n2i (n + i2n k)
+                     =: i2n (n2i m) .== i2n (n2i (n + i2n k))
+                     ?? n2i2nId `at` Inst @"n" m
+                     =: m .== i2n (n2i (n + i2n k))
+                     ?? n2i2nId `at` Inst @"n" (n + i2n k)
+                     =: m .== n + i2n k
+                     =: cases [ k .>  0 ==> trivial
+                              , k .<= 0 ==> m .== n + i2n k
+                                         ?? i2n k .== 0
+                                         =: m .== n + 0
+                                         ?? aru
+                                         =: m .== n
+                                         =: m .== n .|| m .> n
+                                         =: m .>= n
+                                         =: qed
+                              ]
+
+    lemma "lteEquiv"
+          (\(Forall m) (Forall n) -> (n2i m .>= n2i n) .== (m .>= n))
+          [proofOf ltr, proofOf rtl]
+
+-- | \(m \geq n \;\lor\; n \geq m\)
+--
+-- >>> runTP ordered
+-- Lemma: lteEquiv             Q.E.D.
+-- Lemma: ordered
+--   Step: 1                   Q.E.D.
+--   Step: 2                   Q.E.D.
+--   Result:                   Q.E.D.
+-- Functions proven terminating: i2n, n2i, sNatPlus
+-- [Proven] ordered :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+ordered :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+ordered = do
+   lteEq <- recall lteEquiv
+
+   calcWith cvc5 "ordered"
+        (\(Forall m) (Forall n) -> m .>= n .|| n .>= m) $
+        \m n -> [] |- (m .>= n .|| n .>= m)
+                   ?? lteEq `at` (Inst @"m" m, Inst @"n" n)
+                   =: (n2i m .>= n2i n .|| n .>= m)
+                   ?? lteEq `at` (Inst @"m" n, Inst @"n" m)
+                   =: (n2i m .>= n2i n .|| n2i n .>= n2i m)
+                   =: qed
+
+-- | \(m < n \;\lor\; m = n \;\lor\; n < m\)
+--
+-- >>> runTP trichotomy
+-- Lemma: ordered              Q.E.D.
+-- Lemma: trichotomy           Q.E.D.
+-- Functions proven terminating: i2n, n2i, sNatPlus
+-- [Proven] trichotomy :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+trichotomy :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+trichotomy = do
+   pOrdered <- recall ordered
+
+   lemma "trichotomy"
+         (\(Forall m) (Forall n) -> m .< n .|| m .== n .|| n .< m)
+         [proofOf pOrdered]
+
+-- ** Addition and ordering
+
+-- | \(m < n \;\rightarrow\; m + o < n + o\)
+--
+-- >>> runTP addOrder
+-- Lemma: addAssoc        Q.E.D.
+-- Lemma: addComm         Q.E.D.
+-- Lemma: addOrder
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Step: 4              Q.E.D.
+--   Step: 5              Q.E.D.
+--   Result:              Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] addOrder :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+addOrder :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+addOrder = do
+  pAddAssoc <- recall addAssoc
+  pAddComm  <- recall addComm
+
+  calc "addOrder"
+       (\(Forall m) (Forall n) (Forall o) -> m .< n .=> m + o .< n + o) $
+       \m n o -> [m .< n]
+              |-> let k = some "k" (\d -> n .== m + sSucc d)
+               in n .== m + sSucc k
+               =: n + o .== (m + sSucc k) + o
+               ?? pAddAssoc `at` (Inst @"m" m, Inst @"n" (sSucc k), Inst @"o" o)
+               =: n + o .== m + (sSucc k + o)
+               ?? pAddComm `at` (Inst @"m" (sSucc k), Inst @"n" o)
+               =: n + o .== m + (o + sSucc k)
+               ?? pAddAssoc `at` (Inst @"m" m, Inst @"n" o, Inst @"o" (sSucc k))
+               =: n + o .== (m + o) + sSucc k
+               =: m + o .<= n + o
+               =: qed
+
+-- ** Multiplication and ordering
+
+-- | \(o > 0 \;\wedge\; m < n \;\rightarrow\; m * o < n * o\)
+--
+-- >>> runTP mulOrder
+-- Lemma: distribRight    Q.E.D.
+-- Lemma: mulOrder
+--   Step: 1              Q.E.D.
+--   Step: 2              Q.E.D.
+--   Step: 3              Q.E.D.
+--   Step: 4              Q.E.D.
+--   Step: 5              Q.E.D.
+--   Step: 6              Q.E.D.
+--   Result:              Q.E.D.
+-- Functions proven terminating: sNatPlus, sNatTimes
+-- [Proven] mulOrder :: Ɐm ∷ Nat → Ɐn ∷ Nat → Ɐo ∷ Nat → Bool
+mulOrder :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> Forall "o" Nat -> SBool))
+mulOrder = do
+  pDistribRight <- recall distribRight
+
+  calc "mulOrder"
+       (\(Forall m) (Forall n) (Forall o) -> 0 .< o .&& m .< n .=> m * o .< n * o) $
+       \m n o -> [0 .< o, m .< n]
+              |-> let k = some "k" (\d -> n .== m + sSucc d)
+               in n .== m + sSucc k
+               =: n * o .== (m + sSucc k) * o
+               ?? pDistribRight `at` (Inst @"m" m, Inst @"n" (sSucc k), Inst @"o" o)
+               =: n * o .== m * o + sSucc k * o
+               ?? 0 .< o
+               =: n * o .== m * o + sSucc k * sSucc (sprev o)
+               =: n * o .== m * o + (sSucc (sprev o) + k * sSucc (sprev o))
+               =: n * o .== m * o + sSucc (sprev o + k * sSucc (sprev o))
+               =: m * o .< n * o
+               =: qed
+
+-- ** Order and sum
+
+-- | \(m < n \;\rightarrow\; \exists o.\; m + o = n\)
+--
+-- >>> runTP orderSum
+-- Lemma: orderSum     Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] orderSum :: Ɐm ∷ Nat → Ɐn ∷ Nat → Bool
+orderSum :: TP (Proof (Forall "m" Nat -> Forall "n" Nat -> SBool))
+orderSum = lemma "orderSum"
+                 (\(Forall m) (Forall n) -> m .< n .=> quantifiedBool (\(Exists o) -> m + o .== n))
+                 []
+
+-- ** 0 and 1 relationship
+
+-- | \(0 < 1\)
+--
+-- >>> runTP zeroLtOne
+-- Lemma: zeroLtOne    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] zeroLtOne :: Bool
+zeroLtOne :: TP (Proof SBool)
+zeroLtOne = lemma "zeroLtOne" (0 .< (1 :: SNat)) []
+
+-- | \(m > 0 \;\rightarrow\; m \geq 1\)
+--
+-- >>> runTP nothingBetweenZeroAndOne
+-- Lemma: nothingBetweenZeroAndOne    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] nothingBetweenZeroAndOne :: Ɐm ∷ Nat → Bool
+nothingBetweenZeroAndOne :: TP (Proof (Forall "m" Nat -> SBool))
+nothingBetweenZeroAndOne = lemma "nothingBetweenZeroAndOne"
+                                 (\(Forall m) -> m .> 0 .=> m .>= 1)
+                                 []
+
+-- ** 0 is the minimum
+
+-- | \(m \geq 0\)
+--
+-- >>> runTP minimumElt
+-- Lemma: minimumElt    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] minimumElt :: Ɐm ∷ Nat → Bool
+minimumElt :: TP (Proof (Forall "m" Nat -> SBool))
+minimumElt = lemma "minimumElt" (\(Forall m) -> m .>= 0) []
+
+-- ** There is no maximum element
+
+-- | \(\forall m \;\exists n \;.\; m < n\)
+--
+-- >>> runTP noMaximumElt
+-- Lemma: noMaximumElt    Q.E.D.
+-- Functions proven terminating: sNatPlus
+-- [Proven] noMaximumElt :: Ɐm ∷ Nat → ∃n ∷ Nat → Bool
+noMaximumElt :: TP (Proof (Forall "m" Nat -> Exists "n" Nat -> SBool))
+noMaximumElt = lemma "noMaximumElt" (\(Forall m) (Exists n) -> m .< n) []
diff --git a/Documentation/SBV/Examples/TP/PigeonHole.hs b/Documentation/SBV/Examples/TP/PigeonHole.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/PigeonHole.hs
@@ -0,0 +1,53 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.PigeonHole
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves the pigeon-hole principle. If a list of integers sum to more than the length
+-- of the list itself, then some cell must contain a value larger than @1@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP       #-}
+{-# LANGUAGE DataKinds #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.PigeonHole where
+
+import Prelude hiding (sum, length, elem, null, any)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- | Overflow: Some value is greater than 1.
+overflow :: SList Integer -> SBool
+overflow = any (.> 1)
+
+-- | \(\sum xs > \lvert xs \rvert \Rightarrow \textrm{overflow}\, xs\)
+--
+-- >>> runTP pigeonHole
+-- Inductive lemma: pigeonHole
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.foldr
+--[Proven] pigeonHole :: Ɐxs ∷ [Integer] → Bool
+pigeonHole :: TP (Proof (Forall "xs" [Integer] -> SBool))
+pigeonHole = induct "pigeonHole"
+                   (\(Forall xs) -> sum xs .> length xs .=> overflow xs) $
+                   \ih (x, xs) -> [sum xs .> length xs]
+                               |- overflow (x .: xs)
+                               =: (x .> 1 .|| overflow xs)
+                               ?? ih
+                               =: sTrue
+                               =: qed
diff --git a/Documentation/SBV/Examples/TP/PowerMod.hs b/Documentation/SBV/Examples/TP/PowerMod.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/PowerMod.hs
@@ -0,0 +1,507 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.PowerMod
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proofs about power and modulus. Adapted from an example by amigalemming,
+-- see <http://github.com/LeventErkok/sbv/issues/744>.
+--
+-- We also demonstrate the use of recall for reusing previously established proofs.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.PowerMod where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- | Power function over integers.
+power :: SInteger -> SInteger -> SInteger
+power = smtFunction "power" $ \b n -> [sCase| n of
+                                         _ | n .<= 0 -> 1
+                                         _           -> b * power b (n-1)
+                                      |]
+
+-- | \(m > 1 \Rightarrow n + mk \equiv n \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modAddMultiple
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modAddMultiple :: Ɐk ∷ Integer → Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
+modAddMultiple :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> Forall "m" Integer -> SBool))
+modAddMultiple = do
+   -- First prove for k >= 0 by induction. We need this restriction since
+   -- the inductive hypothesis for integers is guarded by k >= 0.
+   pos <- induct "modAddMultiplePos"
+             (\(Forall k) (Forall n) (Forall m) -> k .>= 0 .&& m .> 1 .=> (n + m*k) `sEMod` m .== n `sEMod` m) $
+             \ih k n m -> [k .>= 0, m .> 1] |- (n + m*(k+1)) `sEMod` m
+                                             =: (n + m*k + m) `sEMod` m
+                                             ?? m `sEMod` m .== 0
+                                             ?? (n + m*k + m) `sEDiv` m .== (n + m*k) `sEDiv` m + 1
+                                             =: (n + m*k) `sEMod` m
+                                             ?? ih `at` (Inst @"n" n, Inst @"m" m)
+                                             =: n `sEMod` m
+                                             =: qed
+
+   -- Extend to all k by case-splitting. For k < 0, use the positive case with
+   -- k' = -k > 0 and n' = n+m*k: pos gives (n'+m*k') mod m = n' mod m,
+   -- i.e., n mod m = (n+m*k) mod m.
+   calc "modAddMultiple"
+      (\(Forall k) (Forall n) (Forall m) -> m .> 1 .=> (n + m*k) `sEMod` m .== n `sEMod` m) $
+      \k n m -> [m .> 1] |- cases [ k .>= 0 ==> (n + m*k) `sEMod` m
+                                             ?? pos `at` (Inst @"k" k, Inst @"n" n, Inst @"m" m)
+                                             =: n `sEMod` m
+                                             =: qed
+                                  , k .< 0  ==> (n + m*k) `sEMod` m
+                                             ?? pos `at` (Inst @"k" (-k), Inst @"n" (n + m*k), Inst @"m" m)
+                                             =: n `sEMod` m
+                                             =: qed
+                                  ]
+
+-- | \(m > 0 \Rightarrow a + b \equiv a + (b \bmod m) \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modAddRight
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modAddRight :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modAddRight :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modAddRight = do
+   mAddMul <- modAddMultiple
+   calc "modAddRight"
+      (\(Forall a) (Forall b) (Forall m) -> m .> 0  .=>  (a+b) `sEMod` m .== (a + b `sEMod` m) `sEMod` m) $
+      \a b m -> [m .> 0] |- (a+b) `sEMod` m
+                         =: (a + b `sEMod` m + m * b `sEDiv` m) `sEMod` m
+                         ?? mAddMul `at` (Inst @"k" (b `sEDiv` m), Inst @"n" (a + b `sEMod` m), Inst @"m" m)
+                         =: (a + b `sEMod` m) `sEMod` m
+                         =: qed
+
+-- | \(m > 0 \Rightarrow a + b \equiv (a \bmod m) + b \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modAddLeft
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddLeft
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modAddLeft :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modAddLeft :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modAddLeft = do
+   mAddR <- modAddRight
+   calc "modAddLeft"
+      (\(Forall a) (Forall b) (Forall m) -> m .> 0 .=>  (a+b) `sEMod` m .== (a `sEMod` m + b) `sEMod` m) $
+      \a b m -> [m .> 0] |- (a+b) `sEMod` m
+                         =: (b+a) `sEMod` m
+                         ?? mAddR
+                         =: (b + a `sEMod` m) `sEMod` m
+                         =: (a `sEMod` m + b) `sEMod` m
+                         =: qed
+
+-- | \(m > 0 \Rightarrow a - b \equiv a - (b \bmod m) \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modSubRight
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modSubRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modSubRight :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modSubRight :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modSubRight = do
+   mAddMul <- modAddMultiple
+   calc "modSubRight"
+      (\(Forall a) (Forall b) (Forall m) -> m .> 0 .=>  (a-b) `sEMod` m .== (a - b `sEMod` m) `sEMod` m) $
+      \a b m -> [m .> 0] |- (a - b) `sEMod` m
+                         ?? b .== b `sEMod` m + m * b `sEDiv` m
+                         =: (a - (b `sEMod` m + m * b `sEDiv` m)) `sEMod` m
+                         =: ((a - b `sEMod` m) + m * (- (b `sEDiv` m))) `sEMod` m
+                         ?? mAddMul `at` (Inst @"k" (- (b `sEDiv` m)), Inst @"n" (a - b `sEMod` m), Inst @"m" m)
+                         =: (a - b `sEMod` m) `sEMod` m
+                         =: qed
+
+-- | \(a \geq 0 \land m > 0 \Rightarrow ab \equiv a \cdot (b \bmod m) \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modMulRightNonneg
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddLeft
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight                    Q.E.D. [Cached]
+-- Inductive lemma: modMulRightNonneg
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modMulRightNonneg :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modMulRightNonneg :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modMulRightNonneg = do
+   mAddL <- modAddLeft
+   mAddR <- recall modAddRight
+
+   induct "modMulRightNonneg"
+      (\(Forall a) (Forall b) (Forall m) -> a .>= 0 .&& m .> 0 .=> (a*b) `sEMod` m .== (a * b `sEMod` m) `sEMod` m) $
+      \ih a b m -> [a .>= 0, m .> 0] |- ((a+1)*b) `sEMod` m
+                                     =: (a*b+b) `sEMod` m
+                                     ?? mAddR `at` (Inst @"a" (a*b), Inst @"b" b, Inst @"m" m)
+                                     =: (a*b + b `sEMod` m) `sEMod` m
+                                     ?? mAddL `at` (Inst @"a" (a*b), Inst @"b" (b `sEMod` m), Inst @"m" m)
+                                     =: ((a*b) `sEMod` m + b `sEMod` m) `sEMod` m
+                                     ?? ih `at` (Inst @"b" b, Inst @"m" m)
+                                     =: ((a * b `sEMod` m) `sEMod` m + b `sEMod` m) `sEMod` m
+                                     ?? mAddL
+                                     =: (a * b `sEMod` m + b `sEMod` m) `sEMod` m
+                                     =: ((a+1) * b `sEMod` m) `sEMod` m
+                                     =: qed
+
+-- | \(a \geq 0 \land m > 0 \Rightarrow -ab \equiv -\left(a \cdot (b \bmod m)\right) \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modMulRightNeg
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddLeft
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modSubRight                    Q.E.D.
+-- Inductive lemma: modMulRightNeg
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modMulRightNeg :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modMulRightNeg :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modMulRightNeg = do
+   mAddL <- modAddLeft
+   mSubR <- recall modSubRight
+
+   induct "modMulRightNeg"
+      (\(Forall a) (Forall b) (Forall m) -> a .>= 0 .&& m .> 0 .=> (-(a*b)) `sEMod` m .== (-(a * b `sEMod` m)) `sEMod` m) $
+      \ih a b m -> [a .>= 0, m .> 0] |- (-((a+1)*b)) `sEMod` m
+                                     =: (-(a*b)-b) `sEMod` m
+                                     ?? mSubR `at` (Inst @"a" (-(a*b)), Inst @"b" b, Inst @"m" m)
+                                     =: (-(a*b) - b `sEMod` m) `sEMod` m
+                                     ?? mAddL `at` (Inst @"a" (-(a*b)), Inst @"b" (- (b `sEMod` m)), Inst @"m" m)
+                                     =: ((-(a*b)) `sEMod` m - b `sEMod` m) `sEMod` m
+                                     ?? ih `at` (Inst @"b" b, Inst @"m" m)
+                                     =: ((-(a * b `sEMod` m)) `sEMod` m - b `sEMod` m) `sEMod` m
+                                     ?? mAddL
+                                     =: (-(a * b `sEMod` m) - b `sEMod` m) `sEMod` m
+                                     =: (-((a+1) * b `sEMod` m)) `sEMod` m
+                                     =: qed
+
+-- | \(m > 0 \Rightarrow ab \equiv a \cdot (b \bmod m) \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modMulRight
+-- Inductive lemma: modAddMultiplePos
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddMultiple
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2                         Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddLeft
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modAddRight                    Q.E.D. [Cached]
+-- Inductive lemma: modMulRightNonneg
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: modMulRightNeg                 Q.E.D.
+-- Lemma: modMulRight
+--   Step: 1 (2 way case split)
+--     Step: 1.1                         Q.E.D.
+--     Step: 1.2.1                       Q.E.D.
+--     Step: 1.2.2                       Q.E.D.
+--     Step: 1.2.3                       Q.E.D.
+--     Step: 1.Completeness              Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modMulRight :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modMulRight :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modMulRight = do
+   mMulNonneg <- modMulRightNonneg
+   mMulNeg    <- recall modMulRightNeg
+
+   calc "modMulRight"
+        (\(Forall a) (Forall b) (Forall m) -> m .> 0 .=> (a*b) `sEMod` m .== (a * b `sEMod` m) `sEMod` m) $
+        \a b m -> [m .> 0] |- cases [ a .>= 0 ==> (a*b) `sEMod` m
+                                               ?? mMulNonneg `at` (Inst @"a" a, Inst @"b" b, Inst @"m" m)
+                                               =: (a * b `sEMod` m) `sEMod` m
+                                               =: qed
+                                    , a .<  0 ==> (a*b) `sEMod` m
+                                               =: (-((-a)*b)) `sEMod` m
+                                               ?? mMulNeg `at` (Inst @"a" (-a), Inst @"b" b, Inst @"m" m)
+                                               =: (-((-a) * b `sEMod` m)) `sEMod` m
+                                               =: (a * b `sEMod` m) `sEMod` m
+                                               =: qed
+                                    ]
+
+-- | \(m > 0 \Rightarrow ab \equiv (a \bmod m) \cdot b \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP modMulLeft
+-- Lemma: modMulRight                    Q.E.D.
+-- Lemma: modMulLeft
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- [Proven] modMulLeft :: Ɐa ∷ Integer → Ɐb ∷ Integer → Ɐm ∷ Integer → Bool
+modMulLeft :: TP (Proof (Forall "a" Integer -> Forall "b" Integer -> Forall "m" Integer -> SBool))
+modMulLeft = do
+   mMulR <- recall modMulRight
+
+   calc "modMulLeft"
+        (\(Forall a) (Forall b) (Forall m) -> m .> 0 .=> (a*b) `sEMod` m .== (a `sEMod` m * b) `sEMod` m) $
+        \a b m -> [m .> 0] |- (a*b) `sEMod` m
+                           =: (b*a) `sEMod` m
+                           ?? mMulR
+                           =: (b * a `sEMod` m) `sEMod` m
+                           =: (a `sEMod` m * b) `sEMod` m
+                           =: qed
+
+-- | \(n \geq 0 \land m > 0 \Rightarrow b^n \equiv (b \bmod m)^n \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP powerMod
+-- Lemma: modMulLeft                     Q.E.D.
+-- Lemma: modMulRight                    Q.E.D. [Cached]
+-- Inductive lemma: powerModInduct
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Step: 5                             Q.E.D.
+--   Step: 6                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Lemma: powerMod                       Q.E.D.
+-- Functions proven terminating: power
+-- [Proven] powerMod :: Ɐb ∷ Integer → Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
+powerMod :: TP (Proof (Forall "b" Integer -> Forall "n" Integer -> Forall "m" Integer -> SBool))
+powerMod = do
+   mMulL <- recall modMulLeft
+   mMulR <- recall modMulRight
+
+   -- We want to write the b parameter first, but need to induct on n. So, this helper rearranges the parameters only.
+   pMod <- induct "powerModInduct"
+      (\(Forall @"n" n) (Forall @"m" m) (Forall @"b" b) -> n .>= 0 .&& m .> 0 .=> power b n `sEMod` m .== power (b `sEMod` m) n `sEMod` m) $
+      \ih n m b -> [n .>= 0, m .> 0] |- power b (n+1) `sEMod` m
+                                     =: (power b n * b) `sEMod` m
+                                     ?? mMulL `at` (Inst @"a" (power b n), Inst @"b" b, Inst @"m" m)
+                                     =: (power b n `sEMod` m * b) `sEMod` m
+                                     ?? ih `at` (Inst @"m" m, Inst @"b" b)
+                                     =: (power (b `sEMod` m) n `sEMod` m * b) `sEMod` m
+                                     ?? mMulL `at` (Inst @"a" (power (b `sEMod` m) n), Inst @"b" b, Inst @"m" m)
+                                     =: (power (b `sEMod` m) n * b) `sEMod` m
+                                     ?? mMulR `at` (Inst @"a" (power (b `sEMod` m) n), Inst @"b" b, Inst @"m" m)
+                                     =: (power (b `sEMod` m) n * b `sEMod` m) `sEMod` m
+                                     =: power (b `sEMod` m) (n+1) `sEMod` m
+                                     =: qed
+
+   -- Same as above, just a more natural selection of variable order.
+   lemma "powerMod"
+         (\(Forall b) (Forall n) (Forall m) -> n .>= 0 .&& m .> 0 .=> power b n `sEMod` m .== power (b `sEMod` m) n `sEMod` m)
+         [proofOf pMod]
+
+-- | \(n \geq 0 \Rightarrow 1^n = 1\)
+--
+-- ==== __Proof__
+-- >>> runTP onePower
+-- Inductive lemma: onePower
+--   Step: Base                 Q.E.D.
+--   Step: 1 (unfold power)     Q.E.D.
+--   Step: 2                    Q.E.D.
+--   Result:                    Q.E.D.
+-- Functions proven terminating: power
+-- [Proven] onePower :: Ɐn ∷ Integer → Bool
+onePower :: TP (Proof (Forall "n" Integer -> SBool))
+onePower = induct "onePower"
+                  (\(Forall n) -> n .>= 0 .=> power 1 n .== 1) $
+                  \ih n -> [] |- power 1 (n+1)
+                               ?? "unfold power"
+                               =: 1 * power 1 n
+                               ?? ih
+                               =: (1 :: SInteger)
+                               =: qed
+
+-- | \(n \geq 0 \Rightarrow (27^n \bmod 13) = 1\)
+--
+-- ==== __Proof__
+-- >>> runTP powerOf27
+-- Lemma: onePower                       Q.E.D.
+-- Lemma: powerMod                       Q.E.D.
+-- Lemma: powerOf27
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Step: 4                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: power
+-- [Proven] powerOf27 :: Ɐn ∷ Integer → Bool
+powerOf27 :: TP (Proof (Forall "n" Integer -> SBool))
+powerOf27 = do
+   pOne <- recall onePower
+   pMod <- recall powerMod
+   calc "powerOf27" (\(Forall n) -> n .>= 0 .=> power 27 n `sEMod` 13 .== 1) $
+                    \n -> [n .>= 0]
+                       |- power 27 n `sEMod` 13
+                       ?? pMod `at` (Inst @"b" 27, Inst @"n" n, Inst @"m" 13)
+                       =: power (27 `sEMod` 13) n `sEMod` 13
+                       =: power 1 n `sEMod` 13
+                       ?? pOne
+                       =: 1 `sEMod` 13
+                       =: (1 :: SInteger)
+                       =: qed
+
+-- | \(n \geq 0 \wedge m > 0 \implies (27^{\frac{n}{3}} \bmod 13) \cdot 3^{n \bmod 3} \equiv 3^{n \bmod 3} \pmod{m}\)
+--
+-- ==== __Proof__
+-- >>> runTP powerOfThreeMod13VarDivisor
+-- Lemma: powerOf27                      Q.E.D.
+-- Lemma: powerOfThreeMod13VarDivisor
+--   Step: 1                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: power
+-- [Proven] powerOfThreeMod13VarDivisor :: Ɐn ∷ Integer → Ɐm ∷ Integer → Bool
+powerOfThreeMod13VarDivisor :: TP (Proof (Forall "n" Integer -> Forall "m" Integer -> SBool))
+powerOfThreeMod13VarDivisor = do
+   p27 <- recall powerOf27
+   calc "powerOfThreeMod13VarDivisor"
+        (\(Forall n) (Forall m) ->
+            n .>= 0 .&& m .> 0 .=>     power 27 (n `sEDiv` 3) `sEMod` 13 * power 3 (n `sEMod` 3) `sEMod` m
+                                   .== power  3 (n `sEMod` 3) `sEMod` m) $
+        \n m -> [n .>= 0, m .> 0]
+             |- power 27 (n `sEDiv` 3) `sEMod` 13 * power 3 (n `sEMod` 3) `sEMod` m
+             ?? p27 `at` Inst @"n" (sEDiv n 3)
+             =: power 3 (n `sEMod` 3) `sEMod` m
+             =: qed
diff --git a/Documentation/SBV/Examples/TP/Primes.hs b/Documentation/SBV/Examples/TP/Primes.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Primes.hs
@@ -0,0 +1,522 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Primes
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Prove that there are an infinite number of primes. Along the way we formalize
+-- and prove a number of properties about divisibility as well. Our proof is inspired by
+-- the ACL2 proof in <https://github.com/acl2/acl2/blob/master/books/projects/numbers/euclid.lisp>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Primes where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Divisibility
+
+-- | Divides relation. By definition @0@ only divides @0@. (But every number divides @0@).
+dvd :: SInteger -> SInteger -> SBool
+x `dvd` y = ite (x .== 0) (y .== 0) (y `sEMod` x .== 0)
+
+-- | \(x \mid y \implies x \mid y * z\)
+--
+-- === __Proof__
+-- >>> runTP dividesProduct
+-- Lemma: dividesProduct
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.2.3             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dividesProduct :: Ɐx ∷ Integer → Ɐy ∷ Integer → Ɐz ∷ Integer → Bool
+dividesProduct :: TP (Proof (Forall "x" Integer -> Forall "y" Integer -> Forall "z" Integer -> SBool))
+dividesProduct = calc "dividesProduct"
+                      (\(Forall x) (Forall y) (Forall z) -> x `dvd` y .=> x `dvd` (y*z)) $
+                      \x y z -> [x `dvd` y]
+                             |- cases [ x .== 0 ==> x `dvd` (y*z)
+                                                 ?? y .== 0
+                                                 =: sTrue
+                                                 =: qed
+                                      , x ./= 0 ==> x `dvd` (y*z)
+                                                 ?? y .== x * y `sEDiv` x
+                                                 =: x `dvd` ((x * y `sEDiv` x) * z)
+                                                 =: x `dvd` (x * ((y `sEDiv` x) * z))
+                                                 =: sTrue
+                                                 =: qed
+                                      ]
+-- | \(x \mid y \land y \mid z \implies x \mid z\)
+--
+-- === __Proof__
+-- >>> runTP dividesTransitive
+-- Lemma: dividesProduct       Q.E.D.
+-- Lemma: dividesTransitive
+--   Step: 1 (2 way case split)
+--     Step: 1.1               Q.E.D.
+--     Step: 1.2.1             Q.E.D.
+--     Step: 1.2.2             Q.E.D.
+--     Step: 1.2.3             Q.E.D.
+--     Step: 1.2.4             Q.E.D.
+--     Step: 1.Completeness    Q.E.D.
+--   Result:                   Q.E.D.
+-- [Proven] dividesTransitive :: Ɐx ∷ Integer → Ɐy ∷ Integer → Ɐz ∷ Integer → Bool
+dividesTransitive :: TP (Proof (Forall "x" Integer -> Forall "y" Integer -> Forall "z" Integer -> SBool))
+dividesTransitive = do
+    dp <- recall dividesProduct
+
+    calc "dividesTransitive"
+         (\(Forall x) (Forall y) (Forall z) -> x `dvd` y .&& y `dvd` z .=> x `dvd` z) $
+         \x y z -> [x `dvd` y, y `dvd` z]
+                |- cases [ x .== 0 .|| y .== 0 .|| z .== 0 ==> trivial
+                         , x ./= 0 .&& y ./= 0 .&& z ./= 0
+                            ==> x `dvd` z
+                             ?? z .== z `sEDiv` y * y
+                             =: x `dvd` (z `sEDiv` y * y)
+                             ?? y .== y `sEDiv` x * x
+                             ?? x `dvd` y
+                             =: x `dvd` ((z `sEDiv` y) * (y `sEDiv` x * x))
+                             =: x `dvd` (x * ((z `sEDiv` y) * (y `sEDiv` x)))
+                             ?? dp `at` (Inst @"x" x, Inst @"y" x, Inst @"z" ((z `sEDiv` y) * (y `sEDiv` x)))
+                             =: sTrue
+                             =: qed
+                         ]
+
+-- * The least divisor
+
+-- | The definition of primality will depend on the notion of least divisor. Given @k@ and @n@, the least-divisor of
+-- @n@ that is at least @k@ is the number that is at least @k@ and divides @n@ evenly. The idea is that a number is
+-- prime if the least divisor starting from @2@ is itself.
+ld :: SInteger -> SInteger -> SInteger
+ld = smtFunctionWithMeasure "ld" (\k n -> (n - k) `smax` 0, [])
+   $ \k n -> [sCase| tuple (k .<= 0 .|| k .> n, n `sEMod` k) of
+                (True, _) -> 0
+                (_,    0) -> k
+                _         -> ld (k+1) n
+             |]
+
+-- | \(1 < k \leq n \implies \mathit{ld}\,k\,n \mid n \land k \leq \mathit{ld}\,k\,n \leq n\)
+--
+-- === __Proof__
+-- >>> runTP leastDivisorDivides
+-- Inductive lemma (strong): leastDivisorDivides
+--   Step: Measure is non-negative                  Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                    Q.E.D.
+--     Step: 1.2                                    Q.E.D.
+--     Step: 1.Completeness                         Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: ld
+-- [Proven] leastDivisorDivides :: Ɐk ∷ Integer → Ɐn ∷ Integer → Bool
+leastDivisorDivides :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> SBool))
+leastDivisorDivides =
+   sInduct "leastDivisorDivides"
+           (\(Forall k) (Forall n) -> 1 .< k .&& k .<= n .=> let d = ld k n in d `dvd` n .&& k .<= d .&& d .<= n)
+           (\k n -> n - k, []) $
+           \ih k n -> [1 .< k, k .<= n]
+                  |- let d = ld k n
+                  in cases [ n `sEMod` k .== 0 ==> d `dvd` n .&& k .<= d .&& d .<= n
+                                                ?? d .== k
+                                                =: sTrue
+                                                =: qed
+                           , n `sEMod` k ./= 0 ==> d `dvd` n .&& k .<= d .&& d .<= n
+                                                ?? d .== ld (k+1) n
+                                                ?? ih `at` (Inst @"k" (k+1), Inst @"n" n)
+                                                =: sTrue
+                                                =: qed
+                           ]
+
+-- | \(1 < k \leq n \land d \mid n \land k \leq d \implies \mathit{ld}\,k\,n \leq d\)
+--
+-- === __Proof__
+-- >>> runTP leastDivisorIsLeast
+-- Inductive lemma (strong): leastDivisorisLeast
+--   Step: Measure is non-negative                  Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                    Q.E.D.
+--     Step: 1.2                                    Q.E.D.
+--     Step: 1.Completeness                         Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: ld
+-- [Proven] leastDivisorisLeast :: Ɐk ∷ Integer → Ɐn ∷ Integer → Ɐd ∷ Integer → Bool
+leastDivisorIsLeast :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> Forall "d" Integer -> SBool))
+leastDivisorIsLeast =
+  sInduct "leastDivisorisLeast"
+          (\(Forall k) (Forall n) (Forall d) -> 1 .< k .&& k .<= n .&& d `dvd` n .&& k .<= d .=> ld k n .<= d)
+          (\k n _d -> n - k, []) $
+          \ih k n d -> [1 .< k, k .<= n, d `dvd` n, k .<= d]
+                    |- cases [ n `sEMod` k .== 0 ==> ld k n .<= d
+                                                  =: k .<= d
+                                                  =: qed
+                             , n `sEMod` k ./= 0 ==> ld k n .<= d
+                                                  ?? ih
+                                                  =: sTrue
+                                                  =: qed
+                             ]
+
+-- | \(n \geq k \geq 2 \implies \mathit{ld}\,k\,(\mathit{ld}\,k\,n) = \mathit{ld}\,k\,n\)
+--
+-- === __Proof__
+-- >>> runTP leastDivisorTwice
+-- Lemma: dividesTransitive                         Q.E.D.
+-- Lemma: leastDivisorDivides                       Q.E.D.
+-- Lemma: leastDivisorisLeast                       Q.E.D.
+-- Lemma: helper1                                   Q.E.D.
+-- Lemma: helper2                                   Q.E.D.
+-- Lemma: helper3
+--   Step: 1                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Lemma: helper4                                   Q.E.D.
+-- Lemma: helper5
+--   Step: 1                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Lemma: leastDivisorTwice                         Q.E.D.
+-- Functions proven terminating: ld
+-- [Proven] leastDivisorTwice :: Ɐk ∷ Integer → Ɐn ∷ Integer → Bool
+leastDivisorTwice :: TP (Proof (Forall "k" Integer -> Forall "n" Integer -> SBool))
+leastDivisorTwice = do
+  dt  <- recall dividesTransitive
+  ldd <- recall leastDivisorDivides
+  ldl <- recall leastDivisorIsLeast
+
+  h1 <- lemmaWith cvc5
+              "helper1"
+              (\(Forall @"k" k) (Forall @"n" n) -> n .>= k .&& k .>= 2 .=> ld k (ld k n) `dvd` ld k n .&& ld k (ld k n) .<= ld k n)
+              [proofOf ldd]
+
+  h2 <- lemma "helper2"
+              (\(Forall @"k" k) (Forall @"n" n) -> n .>= k .&& k .>= 2 .=> ld k n `dvd` n)
+              [proofOf ldd]
+
+  h3 <- calc "helper3"
+             (\(Forall @"k" k) (Forall @"n" n) -> n .>= k .&& k .>= 2 .=> ld k (ld k n) `dvd` n) $
+             \k n -> [n .>= k, k .>= 2]
+                  |- ld k (ld k n) `dvd` n
+                  ?? h1
+                  ?? h2
+                  ?? dt `at` (Inst @"x" (ld k (ld k n)), Inst @"y" (ld k n), Inst @"z" n)
+                  =: sTrue
+                  =: qed
+
+  h4 <- lemma "helper4"
+              (\(Forall @"k" k) (Forall @"n" n) -> n .>= k .&& k .>= 2 .=> k .<= ld k (ld k n))
+              [proofOf ldd]
+
+  h5 <- calc "helper5"
+              (\(Forall @"k" k) (Forall @"n" n) -> n .>= k .&& k .>= 2 .=> ld k n .<= ld k (ld k n)) $
+              \k n -> [n .>= k, k .>= 2]
+                   |- ld k n .<= ld k (ld k n)
+                   ?? h3  `at` (Inst @"k" k, Inst @"n" n)
+                   ?? h4  `at` (Inst @"k" k, Inst @"n" n)
+                   ?? ldl `at` (Inst @"k" k, Inst @"n" n, Inst @"d" (ld k (ld k n)))
+                   =: sTrue
+                   =: qed
+
+  lemma "leastDivisorTwice"
+        (\(Forall k) (Forall n) -> n .>= k .&& k .>= 2 .=> ld k (ld k n) .== ld k n)
+        [proofOf h1, proofOf h5]
+
+-- * Primality
+
+-- | A number is prime if its least divisor greater than or equal to @2@ is itself.
+isPrime :: SInteger -> SBool
+isPrime n = n .>= 2 .&& ld 2 n .== n
+
+-- | \(\mathit{isPrime}\,p \implies p \geq 2\)
+--
+-- === __Proof__
+-- >>> runTP primeAtLeast2
+-- Lemma: primeAtLeast2    Q.E.D.
+-- Functions proven terminating: ld
+-- [Proven] primeAtLeast2 :: Ɐp ∷ Integer → Bool
+primeAtLeast2 :: TP (Proof (Forall "p" Integer -> SBool))
+primeAtLeast2 = lemma "primeAtLeast2" (\(Forall p) -> isPrime p .=> p .>= 2) []
+
+-- | \(n \geq 2 \implies \mathit{isPrime}\,(\mathit{ld}\,2\,n)\)
+--
+-- === __Proof__
+-- >>> runTP leastDivisorIsPrime
+-- Lemma: leastDivisorTwice                         Q.E.D.
+-- Lemma: leastDivisorDivides                       Q.E.D. [Cached]
+-- Lemma: leastDivisorIsPrime
+--   Step: 1                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: ld
+-- [Proven] leastDivisorIsPrime :: Ɐn ∷ Integer → Bool
+leastDivisorIsPrime :: TP (Proof (Forall "n" Integer -> SBool))
+leastDivisorIsPrime = do
+   ldt <- recall leastDivisorTwice
+   ldd <- recall leastDivisorDivides
+
+   calc "leastDivisorIsPrime"
+        (\(Forall n) -> n .>= 2 .=> isPrime (ld 2 n)) $
+        \n -> [n .>= 2] |- isPrime (ld 2 n)
+                        ?? ldt `at` (Inst @"k" 2, Inst @"n" n)
+                        ?? ldd `at` (Inst @"k" 2, Inst @"n" n)
+                        =: sTrue
+                        =: qed
+
+-- | The least prime divisor is the least divisor of it starting from @2@. By 'leastDivisorIsPrime', this number
+-- is guaranteed to be prime.
+leastPrimeDivisor :: SInteger -> SInteger
+leastPrimeDivisor n = ld 2 n
+
+-- * Formalizing factorial
+
+-- | The factorial function.
+fact :: SInteger -> SInteger
+fact = smtFunction "fact" $ \n -> [sCase| n of
+                                     _ | n .<= 0 -> 1
+                                     _           -> n * fact (n - 1)
+                                  |]
+
+-- | \(n! \geq 1\)
+--
+-- === __Proof__
+-- >>> runTP factAtLeast1
+-- Inductive lemma: factAtLeast1
+--   Step: Base                     Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                    Q.E.D.
+--     Step: 1.2.1                  Q.E.D.
+--     Step: 1.2.2                  Q.E.D.
+--     Step: 1.Completeness         Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: fact
+-- [Proven] factAtLeast1 :: Ɐn ∷ Integer → Bool
+factAtLeast1 :: TP (Proof (Forall "n" Integer -> SBool))
+factAtLeast1 = inductWith cvc5 "factAtLeast1"
+                      (\(Forall n) -> fact n .>= 1) $
+                      \ih n -> [] |- fact (n+1) .>= 1
+                                  =: cases [ n+1 .<= 0 ==> trivial
+                                           , n+1 .>  0 ==> (n+1) * fact n .>= 1
+                                                        ?? ih
+                                                        =: sTrue
+                                                        =: qed
+                                           ]
+
+-- | \(1 \leq k \land k \leq n \implies k \mid n!\)
+--
+-- === __Proof__
+-- >>> runTP dividesFact
+-- Lemma: dividesProduct           Q.E.D.
+-- Inductive lemma: dividesFact
+--   Step: Base                    Q.E.D.
+--   Step: 1                       Q.E.D.
+--   Step: 2 (2 way case split)
+--     Step: 2.1.1                 Q.E.D.
+--     Step: 2.1.2                 Q.E.D.
+--     Step: 2.2.1                 Q.E.D.
+--     Step: 2.2.2                 Q.E.D.
+--     Step: 2.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: fact
+-- [Proven] dividesFact :: Ɐn ∷ Integer → Ɐk ∷ Integer → Bool
+dividesFact :: TP (Proof (Forall "n" Integer -> Forall "k" Integer -> SBool))
+dividesFact = do
+   dvp <- recall dividesProduct
+
+   induct "dividesFact"
+          (\(Forall n) (Forall k) -> 1 .<= k .&& k .<= n .=> k `dvd` fact n) $
+          \ih n k -> [1 .<= k, k .<= n + 1]
+                  |- k `dvd` fact (n + 1)
+                  =: k `dvd` ((n + 1) * fact n)
+                  =: cases [ k .== n + 1 ==> k `dvd` ((n + 1) * fact n)
+                                          ?? dvp `at` (Inst @"x" k, Inst @"y" (n+1), Inst @"z" (fact n))
+                                          =: sTrue
+                                          =: qed
+                           , k ./= n + 1 ==> k `dvd` ((n + 1) * fact n)
+                                          ?? ih
+                                          ?? dvp `at` (Inst @"x" k, Inst @"y" (fact n), Inst @"z" (n+1))
+                                          =: sTrue
+                                          =: qed
+                           ]
+
+-- | \(1 \leq k \land k \leq n \implies \neg (k \mid n! + 1)\)
+--
+-- === __Proof__
+-- >>> runTP notDividesFactP1
+-- Lemma: dividesFact              Q.E.D.
+-- Lemma: notDividesFactP1
+--   Step: 1                       Q.E.D.
+--   Step: 2                       Q.E.D.
+--   Step: 3                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: fact
+-- [Proven] notDividesFactP1 :: Ɐn ∷ Integer → Ɐk ∷ Integer → Bool
+notDividesFactP1 :: TP (Proof (Forall "n" Integer -> Forall "k" Integer -> SBool))
+notDividesFactP1 = do
+   df    <- recall dividesFact
+
+   calc "notDividesFactP1"
+         (\(Forall n) (Forall k) -> 1 .< k .&& k .<= n .=> sNot (k `dvd` (fact n + 1))) $
+         \n k -> [1 .< k, k .<= n]
+              |- k `dvd` (fact n + 1)
+              ?? df `at` (Inst @"n" n, Inst @"k" k)
+              =: k `dvd` (k * fact n `sEDiv` k + 1)
+              =: k `dvd` 1
+              =: contradiction
+
+-- * Finding a greater prime
+
+-- | Given a number, return another number which is both prime and is larger than the input. Note that
+-- we don't claim to return the closest prime to the input. Just some prime that is larger, as we shall prove.
+greaterPrime :: SInteger -> SInteger
+greaterPrime n = leastPrimeDivisor (1 + fact n)
+
+-- | \(\mathit{greaterPrime}\, n \mid n! + 1\)
+--
+-- === __Proof__
+-- >>> runTP greaterPrimeDivides
+-- Lemma: leastDivisorDivides                       Q.E.D.
+-- Lemma: factAtLeast1                              Q.E.D.
+-- Lemma: greaterPrimeDivides
+--   Step: 1                                        Q.E.D.
+--   Step: 2                                        Q.E.D.
+--   Step: 3                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: fact, ld
+-- [Proven] greaterPrimeDivides :: Ɐn ∷ Integer → Bool
+greaterPrimeDivides :: TP (Proof (Forall "n" Integer -> SBool))
+greaterPrimeDivides = do
+   ldd  <- recall leastDivisorDivides
+   fal1 <- recall factAtLeast1
+
+   calc "greaterPrimeDivides"
+        (\(Forall n) -> greaterPrime n `dvd` (1 + fact n)) $
+        \n -> [] |- greaterPrime n `dvd` (1 + fact n)
+                 =: leastPrimeDivisor (1 + fact n) `dvd` (1 + fact n)
+                 =: ld 2 (1 + fact n) `dvd` (1 + fact n)
+                 ?? ldd  `at` (Inst @"k" 2, Inst @"n" (1 + fact n))
+                 ?? fal1 `at` Inst @"n" n
+                 =: sTrue
+                 =: qed
+
+-- | \(\mathit{greaterPrime}\, n > n\)
+--
+-- === __Proof__
+-- >>> runTP greaterPrimeGreater
+-- Lemma: notDividesFactP1                          Q.E.D.
+-- Lemma: greaterPrimeDivides                       Q.E.D.
+-- Lemma: leastDivisorIsPrime                       Q.E.D.
+-- Lemma: factAtLeast1                              Q.E.D. [Cached]
+-- Lemma: primeAtLeast2                             Q.E.D.
+-- Lemma: greaterPrimeGreater
+--   Step: 1                                        Q.E.D.
+--   Step: 2                                        Q.E.D.
+--   Step: 3                                        Q.E.D.
+--   Step: 4                                        Q.E.D.
+--   Step: 5                                        Q.E.D.
+--   Step: 6                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: fact, ld
+-- [Proven] greaterPrimeGreater :: Ɐn ∷ Integer → Bool
+greaterPrimeGreater :: TP (Proof (Forall "n" Integer -> SBool))
+greaterPrimeGreater = do
+   ndfp1 <- recall notDividesFactP1
+   gpd   <- recall greaterPrimeDivides
+   ldp   <- recall leastDivisorIsPrime
+   fal1  <- recall factAtLeast1
+   pal2  <- recall primeAtLeast2
+
+   calc "greaterPrimeGreater"
+         (\(Forall n) -> greaterPrime n .> n) $
+         \n -> [] |-> sTrue
+                   ?? ndfp1 `at` (Inst @"n" n, Inst @"k" (greaterPrime n))
+                   ?? gpd   `at` Inst @"n" n
+                   =: sNot (1 .< greaterPrime n .&& greaterPrime n .<= n)
+                   =: (1 .>= greaterPrime n .|| greaterPrime n .> n)
+                   =: (1 .>= leastPrimeDivisor (1 + fact n) .|| greaterPrime n .> n)
+                   =: (1 .>= leastPrimeDivisor (1 + fact n) .|| greaterPrime n .> n)
+                   =: (1 .>= ld 2 (1 + fact n) .|| greaterPrime n .> n)
+                   ?? ldp  `at` Inst @"n" (1 + fact n)
+                   ?? pal2 `at` Inst @"p" (ld 2 (1 + fact n))
+                   ?? fal1 `at` Inst @"n" n
+                   =: greaterPrime n .> n
+                   =: qed
+
+-- * Infinitude of primes
+
+-- | \(\mathit{isPrime}\,(\mathit{greaterPrime}\,n) \land \mathit{greaterPrime}\,n > n\)
+--
+-- We can finally prove our goal: For each given number, there is a larger number that is prime. This
+-- establishes that we have an infinite number of primes.
+--
+-- === __Proof__
+-- >>> runTP infinitudeOfPrimes
+-- Lemma: leastDivisorIsPrime                       Q.E.D.
+-- Lemma: factAtLeast1                              Q.E.D.
+-- Lemma: greaterPrimeGreater                       Q.E.D.
+-- Lemma: infinitudeOfPrimes
+--   Step: 1                                        Q.E.D.
+--   Step: 2                                        Q.E.D.
+--   Step: 3                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Functions proven terminating: fact, ld
+-- [Proven] infinitudeOfPrimes :: Ɐn ∷ Integer → Bool
+infinitudeOfPrimes :: TP (Proof (Forall "n" Integer -> SBool))
+infinitudeOfPrimes = do
+   ldp <- recall leastDivisorIsPrime
+   fa1 <- recall factAtLeast1
+   gpg <- recall greaterPrimeGreater
+
+   calc "infinitudeOfPrimes"
+         (\(Forall n) -> let p = greaterPrime n in p .> n .&& isPrime p) $
+         \n -> [] |- let p = greaterPrime n
+                  in p .> n .&& isPrime (greaterPrime n)
+                  =: p .> n .&& isPrime (leastPrimeDivisor (1 + fact n))
+                  =: p .> n .&& isPrime (ld 2 (1 + fact n))
+                  ?? ldp `at` Inst @"n" (1 + fact n)
+                  ?? fa1 `at` Inst @"n" n
+                  ?? gpg `at` Inst @"n" n
+                  =: sTrue
+                  =: qed
+
+-- | \(\forall n. \exists p. \mathit{isPrime}\,p \land p > n\)
+--
+-- Another expression of the fact that there are infinitely many primes. One might prefer this
+-- version as it only refers to the 'isPrime' predicate only.
+--
+-- === __Proof__
+-- >>> runTP noLargestPrime
+-- Lemma: infinitudeOfPrimes                        Q.E.D.
+-- Lemma: helper
+--   Step: 1                                        Q.E.D.
+--   Result:                                        Q.E.D.
+-- Lemma: noLargestPrime                            Q.E.D.
+-- Functions proven terminating: fact, ld
+-- [Proven] noLargestPrime :: Ɐn ∷ Integer → ∃p ∷ Integer → Bool
+noLargestPrime :: TP (Proof (Forall "n" Integer -> Exists "p" Integer -> SBool))
+noLargestPrime = do
+   iop <- recall infinitudeOfPrimes
+
+   h <- calc "helper"
+             (\(Forall @"n" n) -> quantifiedBool (\(Exists p) -> isPrime p .&& p .> n)) $
+             \n -> [] |- quantifiedBool (\(Exists p) -> isPrime p .&& p .> n)
+                      ?? iop `at` Inst @"n" n
+                      =: sTrue
+                      =: qed
+
+   lemmaWith cvc5 "noLargestPrime"
+       (\(Forall n) (Exists p) -> isPrime p .&& p .> n)
+       [proofOf h]
+
+{- HLint ignore module "Avoid lambda" -}
+{- HLint ignore module "Eta reduce"   -}
diff --git a/Documentation/SBV/Examples/TP/Queue.hs b/Documentation/SBV/Examples/TP/Queue.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Queue.hs
@@ -0,0 +1,197 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Queue
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A classic functional queue implemented with two stacks (lists). The front
+-- list holds elements ready for dequeue; the back list accumulates new
+-- elements in reverse. We prove that this representation faithfully
+-- implements a FIFO queue by showing:
+--
+--   (1) Enqueue appends to the abstract queue.
+--   (2) Enqueuing a sequence of elements and reading out the abstraction
+--       gives back the original sequence.
+--   (3) Dequeue retrieves the front of the abstract queue.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Queue where
+
+import Prelude hiding (length, head, tail, null, reverse, (++), fst, snd)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XOverloadedLists
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Tuple
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Queue representation
+
+-- | A queue is a pair @(front, back)@ representing the abstract list
+-- @front ++ reverse back@.
+type Queue a = STuple [a] [a]
+
+-- | Abstraction function: the list a queue represents.
+--
+-- >>> toList (tuple ([1,2,3], [6,5,4])) :: SList Integer
+-- [1,2,3,4,5,6] :: [SInteger]
+toList :: SymVal a => Queue a -> SList a
+toList q = [sCase| q of
+               (f, b) -> f ++ reverse b
+           |]
+
+-- | The empty queue.
+--
+-- >>> toList (emptyQ @Integer)
+-- [] :: [SInteger]
+emptyQ :: SymVal a => Queue a
+emptyQ = tuple ([], [])
+
+-- | Enqueue: add an element to the back.
+--
+-- >>> toList (enqueue (tuple ([1,2], [4,3])) 5) :: SList Integer
+-- [1,2,3,4,5] :: [SInteger]
+enqueue :: SymVal a => Queue a -> SBV a -> Queue a
+enqueue q x = [sCase| q of
+                  (f, b) -> tuple (f, x .: b)
+              |]
+
+-- | Enqueue all elements of a list, left to right.
+--
+-- >>> toList (enqueueAll (emptyQ @Integer) [1,2,3])
+-- [1,2,3] :: [SInteger]
+enqueueAll :: SymVal a => Queue a -> SList a -> Queue a
+enqueueAll = smtFunction "enqueueAll"
+           $ \q xs -> [sCase| xs of
+                         []       -> q
+                         x : rest -> enqueueAll (enqueue q x) rest
+                      |]
+
+-- | Dequeue: remove and return the front element. When the front list
+-- is empty, we reverse the back list into the front first.
+-- Precondition: the queue is non-empty.
+--
+-- >>> let (v, q') = untuple (dequeue (tuple ([1,2,3], [6,5,4]) :: Queue Integer)) in (v, toList q')
+-- (1 :: SInteger,[2,3,4,5,6] :: [SInteger])
+-- >>> let (v, q') = untuple (dequeue (tuple ([], [3,2,1]) :: Queue Integer)) in (v, toList q')
+-- (1 :: SInteger,[2,3] :: [SInteger])
+dequeue :: forall a. SymVal a => Queue a -> STuple a ([a], [a])
+dequeue q = [sCase| q of
+               (x : xs, t) -> tuple (x, tuple (xs, t))
+               ([],     t) -> case reverse t of
+                                y : ys -> tuple (y, tuple (ys, []))
+                                -- unreachable: both front and back are empty
+                                _      -> tuple (some "dead" (const sTrue), tuple ([], []))
+            |]
+
+-- * Correctness
+
+-- | @toList (enqueue q x) == toList q ++ [x]@
+--
+-- Enqueue appends to the abstract list.
+--
+-- >>> runTP $ enqueueCorrect @Integer
+-- Lemma: enqueueCorrect    Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] enqueueCorrect :: Ɐf ∷ [Integer] → Ɐb ∷ [Integer] → Ɐx ∷ Integer → Bool
+enqueueCorrect :: forall a. SymVal a => TP (Proof (Forall "f" [a] -> Forall "b" [a] -> Forall "x" a -> SBool))
+enqueueCorrect =
+   lemma "enqueueCorrect"
+         (\(Forall @"f" f) (Forall @"b" b) (Forall @"x" x) ->
+              toList (enqueue (tuple (f, b)) x) .== toList (tuple (f, b)) ++ [x])
+         []
+
+-- | @toList (enqueueAll q xs) == toList q ++ xs@
+--
+-- Enqueuing a sequence of elements appends the whole sequence to the
+-- abstract list. This is the key invariant of the two-stack representation.
+--
+-- >>> runTP $ enqueueAllCorrect @Integer
+-- Lemma: enqueueCorrect                 Q.E.D.
+-- Inductive lemma: enqueueAllCorrect
+--   Step: Base                          Q.E.D.
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Step: 3                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: enqueueAll, sbv.reverse
+-- [Proven] enqueueAllCorrect :: Ɐxs ∷ [Integer] → Ɐf ∷ [Integer] → Ɐb ∷ [Integer] → Bool
+enqueueAllCorrect :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "f" [a] -> Forall "b" [a] -> SBool))
+enqueueAllCorrect = do
+
+   eqC <- enqueueCorrect @a
+
+   induct "enqueueAllCorrect"
+          (\(Forall @"xs" xs) (Forall @"f" f) (Forall @"b" b) ->
+               toList (enqueueAll (tuple (f, b)) xs) .== (f ++ reverse b) ++ xs) $
+          \ih (x, xs) f b -> []
+                          |- toList (enqueueAll (tuple (f, b)) (x .: xs))
+                          =: toList (enqueueAll (tuple (f, x .: b)) xs)
+                          ?? ih `at` (Inst @"f" f, Inst @"b" (x .: b))
+                          =: (f ++ reverse (x .: b)) ++ xs
+                          ?? eqC
+                          =: (f ++ reverse b) ++ (x .: xs)
+                          =: qed
+
+-- | @toList (enqueueAll emptyQ xs) == xs@
+--
+-- Starting from an empty queue, enqueuing a list of elements produces
+-- a queue whose abstract contents is that same list. This demonstrates
+-- the fundamental FIFO property: elements come out in the order they went in.
+--
+-- >>> runTP $ fifo @Integer
+-- Lemma: enqueueAllCorrect              Q.E.D.
+-- Lemma: fifo
+--   Step: 1                             Q.E.D.
+--   Step: 2                             Q.E.D.
+--   Result:                             Q.E.D.
+-- Functions proven terminating: enqueueAll, sbv.reverse
+-- [Proven] fifo :: Ɐxs ∷ [Integer] → Bool
+fifo :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+fifo = do
+   eaC <- recall (enqueueAllCorrect @a)
+
+   calc "fifo"
+        (\(Forall xs) -> toList (enqueueAll emptyQ xs) .== xs) $
+        \xs -> [] |- toList (enqueueAll emptyQ xs)
+                  ?? eaC `at` (Inst @"xs" xs, Inst @"f" ([] :: SList a), Inst @"b" ([] :: SList a))
+                  =: reverse [] ++ xs
+                  =: xs
+                  =: qed
+
+-- | Dequeue from a non-empty queue gives the head of the abstract list,
+-- and the remaining queue represents the tail.
+--
+-- >>> runTP $ dequeueCorrect @Integer
+-- Lemma: dequeueCorrect    Q.E.D.
+-- Functions proven terminating: sbv.reverse
+-- [Proven] dequeueCorrect :: Ɐf ∷ [Integer] → Ɐb ∷ [Integer] → Bool
+dequeueCorrect :: forall a. SymVal a => TP (Proof (Forall "f" [a] -> Forall "b" [a] -> SBool))
+dequeueCorrect =
+   lemma "dequeueCorrect"
+         (\(Forall @"f" f) (Forall @"b" b) ->
+              sNot (null (toList (tuple (f, b))))
+              .=> let (v, q) = untuple (dequeue (tuple (f, b)))
+                      l      = toList (tuple (f, b))
+                  in v .== head l .&& toList q .== tail l)
+         []
diff --git a/Documentation/SBV/Examples/TP/QuickSort.hs b/Documentation/SBV/Examples/TP/QuickSort.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/QuickSort.hs
@@ -0,0 +1,698 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.QuickSort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving quick sort correct. The proof here closely follows the development
+-- given by Tobias Nipkow, in his paper  "Term Rewriting and Beyond -- Theorem
+-- Proving in Isabelle," published in Formal Aspects of Computing 1: 320-338
+-- back in 1989.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.QuickSort where
+
+import Prelude hiding (null, length, (++), tail, all, fst, snd, elem)
+import Control.Monad.Trans (liftIO)
+
+import Data.SBV
+import Data.SBV.List hiding (partition)
+import Data.SBV.Tuple
+import Data.SBV.TP
+import qualified Documentation.SBV.Examples.TP.Lists as TP
+
+import qualified Documentation.SBV.Examples.TP.SortHelpers as SH
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Quick sort
+
+-- | Quick-sort, using the first element as pivot.
+quickSort :: forall a. (OrdSymbolic (SBV a), SymVal a) => SList a -> SList a
+quickSort = smtFunctionWithMeasure "quickSort"
+              ( length @a
+              , [ measureLemma (partitionFstBound @a)
+                , measureLemma (partitionSndBound @a)
+                ]
+              )
+          $ \l -> [sCase| l of
+                     []     -> []
+                     x : xs -> case partition x xs of
+                                 (lo, hi) -> quickSort lo ++ [x] ++ quickSort hi
+                  |]
+
+-- | We define @partition@ as an explicit function. Unfortunately, we can't just replace this
+-- with @\pivot xs -> Data.List.SBV.partition (.< pivot) xs@ because that would create a firstified version of partition
+-- with a free-variable captured, which isn't supported due to higher-order limitations in SMTLib.
+partition :: (OrdSymbolic (SBV a), SymVal a) => SBV a -> SList a -> STuple [a] [a]
+partition = smtFunction "partition"
+          $ \pivot xs -> [sCase| xs of
+                            []     -> tuple ([], [])
+                            a : as -> case partition pivot as of
+                                        (lo, hi) | a .< pivot -> tuple (a .: lo, hi)
+                                                 | True       -> tuple (lo, a .: hi)
+                         |]
+
+-- | The first component of partition is no longer than the input.
+--
+-- >>> runTP $ partitionFstBound @Integer
+-- Inductive lemma (strong): partitionNotLongerFst
+--   Step: Measure is non-negative                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2 (simplify)                         Q.E.D.
+--     Step: 1.2.3                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Functions proven terminating: partition
+-- [Proven] partitionNotLongerFst :: Ɐl ∷ [Integer] → Ɐpivot ∷ Integer → Bool
+partitionFstBound :: forall a. (OrdSymbolic (SBV a), SymVal a) => TP (Proof (Forall "l" [a] -> Forall "pivot" a -> SBool))
+partitionFstBound = sInduct "partitionNotLongerFst"
+   (\(Forall l) (Forall pivot) -> length (fst (partition @a pivot l)) .<= length l)
+   (\l _ -> length l, []) $
+   \ih l pivot -> [] |- length (fst (partition @a pivot l)) .<= length l
+                     =: [pCase| l of
+                          []             -> trivial
+                          whole@(a : as) ->
+                             let lo = fst (partition pivot as)
+                             in ite (a .< pivot)
+                                    (length (a .: lo) .<= length whole)
+                                    (length       lo  .<= length whole)
+                             ?? "simplify"
+                             =: ite (a .< pivot)
+                                    (length lo .<=     length as)
+                                    (length lo .<= 1 + length as)
+                             ?? ih `at` (Inst @"l" as, Inst @"pivot" pivot)
+                             =: sTrue
+                             =: qed
+                        |]
+
+-- | The second component of partition is no longer than the input.
+--
+-- >>> runTP $ partitionSndBound @Integer
+-- Inductive lemma (strong): partitionNotLongerSnd
+--   Step: Measure is non-negative                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2 (simplify)                         Q.E.D.
+--     Step: 1.2.3                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Functions proven terminating: partition
+-- [Proven] partitionNotLongerSnd :: Ɐl ∷ [Integer] → Ɐpivot ∷ Integer → Bool
+partitionSndBound :: forall a. (OrdSymbolic (SBV a), SymVal a) => TP (Proof (Forall "l" [a] -> Forall "pivot" a -> SBool))
+partitionSndBound = sInduct "partitionNotLongerSnd"
+   (\(Forall l) (Forall pivot) -> length (snd (partition @a pivot l)) .<= length l)
+   (\l _ -> length l, []) $
+   \ih l pivot -> [] |- length (snd (partition @a pivot l)) .<= length l
+                     =: [pCase| l of
+                          []     -> trivial
+                          whole@(a : as) -> let hi = snd (partition pivot as)
+                                 in ite (a .< pivot)
+                                        (length       hi  .<= length whole)
+                                        (length (a .: hi) .<= length whole)
+                                 ?? "simplify"
+                                 =: ite (a .< pivot)
+                                        (length hi .<= 1 + length as)
+                                        (length hi .<=     length as)
+                                 ?? ih `at` (Inst @"l" as, Inst @"pivot" pivot)
+                                 =: sTrue
+                                 =: qed
+                        |]
+
+-- * Correctness proof
+
+-- | Correctness of quick-sort.
+--
+-- We have:
+--
+-- >>> correctness @Integer
+-- Inductive lemma: countAppend
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2 (unfold count)                           Q.E.D.
+--   Step: 3                                          Q.E.D.
+--   Step: 4 (simplify)                               Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: countNonNeg
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                                    Q.E.D.
+--     Step: 1.1.2                                    Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: countElem
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                                    Q.E.D.
+--     Step: 1.1.2                                    Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: elemCount
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: sublistCorrect
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: sublistElem
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: sublistTail                                 Q.E.D.
+-- Lemma: sublistIfPerm                               Q.E.D.
+-- Inductive lemma: lltCorrect
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: lgeCorrect
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: lltSublist
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: lltPermutation
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: lgeSublist
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: lgePermutation
+--   Step: 1                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: partitionFstLT
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (unroll partition)                       Q.E.D.
+--   Step: 2 (push fst down, simplify)                Q.E.D.
+--   Step: 3 (push llt down)                          Q.E.D.
+--   Step: 4                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: partitionSndGE
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2 (push lge down)                          Q.E.D.
+--   Step: 3                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: partitionNotLongerFst                       Q.E.D.
+-- Lemma: partitionNotLongerSnd                       Q.E.D.
+-- Inductive lemma: countPartition
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (expand partition)                       Q.E.D.
+--   Step: 2 (push countTuple down)                   Q.E.D.
+--   Step: 3 (2 way case split)
+--     Step: 3.1.1                                    Q.E.D.
+--     Step: 3.1.2 (simplify)                         Q.E.D.
+--     Step: 3.1.3                                    Q.E.D.
+--     Step: 3.2.1                                    Q.E.D.
+--     Step: 3.2.2 (simplify)                         Q.E.D.
+--     Step: 3.2.3                                    Q.E.D.
+--     Step: 3.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma (strong): sortCountsMatch
+--   Step: Measure is non-negative                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2 (expand quickSort)                 Q.E.D.
+--     Step: 1.2.3 (push count down)                  Q.E.D.
+--     Step: 1.2.4                                    Q.E.D.
+--     Step: 1.2.5                                    Q.E.D.
+--     Step: 1.2.6 (IH on lo)                         Q.E.D.
+--     Step: 1.2.7 (IH on hi)                         Q.E.D.
+--     Step: 1.2.8                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: sortIsPermutation                           Q.E.D.
+-- Inductive lemma: nonDecreasingMerge
+--   Step: Base                                       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2                                    Q.E.D.
+--     Step: 1.2.3                                    Q.E.D.
+--     Step: 1.2.4                                    Q.E.D.
+--     Step: 1.2.5                                    Q.E.D.
+--     Step: 1.2.6                                    Q.E.D.
+--     Step: 1.2.7                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma (strong): sortIsNonDecreasing
+--   Step: Measure is non-negative                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                                      Q.E.D.
+--     Step: 1.2.1                                    Q.E.D.
+--     Step: 1.2.2 (expand quickSort)                 Q.E.D.
+--     Step: 1.2.3                                    Q.E.D.
+--     Step: 1.Completeness                           Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: quickSortIsCorrect                          Q.E.D.
+-- Inductive lemma: partitionSortedLeft
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: partitionSortedRight
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Inductive lemma: unchangedIfNondecreasing
+--   Step: Base                                       Q.E.D.
+--   Step: 1                                          Q.E.D.
+--   Step: 2                                          Q.E.D.
+--   Step: 3                                          Q.E.D.
+--   Step: 4                                          Q.E.D.
+--   Result:                                          Q.E.D.
+-- Lemma: ifChangedThenUnsorted                       Q.E.D.
+-- == Proof tree:
+-- quickSortIsCorrect
+--  ├╴sortIsPermutation
+--  │  └╴sortCountsMatch
+--  │     ├╴countAppend (x2)
+--  │     ├╴partitionNotLongerFst
+--  │     ├╴partitionNotLongerSnd
+--  │     └╴countPartition
+--  └╴sortIsNonDecreasing
+--     ├╴partitionNotLongerFst
+--     ├╴partitionNotLongerSnd
+--     ├╴partitionFstLT
+--     ├╴partitionSndGE
+--     ├╴sortIsPermutation (x2)
+--     ├╴lltPermutation
+--     │  ├╴lltSublist
+--     │  │  ├╴sublistElem
+--     │  │  │  └╴sublistCorrect
+--     │  │  │     ├╴countElem
+--     │  │  │     │  └╴countNonNeg
+--     │  │  │     └╴elemCount
+--     │  │  ├╴lltCorrect
+--     │  │  └╴sublistTail
+--     │  └╴sublistIfPerm
+--     ├╴lgePermutation
+--     │  ├╴lgeSublist
+--     │  │  ├╴sublistElem
+--     │  │  ├╴lgeCorrect
+--     │  │  └╴sublistTail
+--     │  └╴sublistIfPerm
+--     └╴nonDecreasingMerge
+-- Functions proven terminating: count, lge, llt, nonDecreasing, partition, quickSort
+-- [Proven] quickSortIsCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. (Eq a, OrdSymbolic (SBV a), SymVal a) => IO (Proof (Forall "xs" [a] -> SBool))
+correctness = runTP $ do
+
+  --------------------------------------------------------------------------------------------
+  -- Part I. Import helper lemmas, definitions
+  --------------------------------------------------------------------------------------------
+  let count         = TP.count         @a
+      isPermutation = SH.isPermutation @a
+      nonDecreasing = SH.nonDecreasing @a
+      sublist       = SH.sublist       @a
+
+  countAppend   <- TP.countAppend   @a
+  sublistElem   <- SH.sublistElem   @a
+  sublistTail   <- SH.sublistTail   @a
+  sublistIfPerm <- SH.sublistIfPerm @a
+
+  ---------------------------------------------------------------------------------------------------
+  -- Part II. Formalizing less-than/greater-than-or-equal over lists and relationship to permutations
+  ---------------------------------------------------------------------------------------------------
+  -- llt: list less-than:     all the elements are <  pivot
+  -- lge: list greater-equal: all the elements are >= pivot
+  let llt, lge :: SBV a -> SList a -> SBool
+      llt = smtFunction "llt"
+          $ \pivot l -> [sCase| l of
+                           []     -> sTrue
+                           x : xs -> x .<  pivot .&& llt pivot xs
+                        |]
+      lge = smtFunction "lge"
+          $ \pivot l -> [sCase| l of
+                           []     -> sTrue
+                           x : xs -> x .>= pivot .&& lge pivot xs
+                        |]
+
+  -- llt correctness
+  lltCorrect <-
+     induct "lltCorrect"
+            (\(Forall xs) (Forall e) (Forall pivot) -> llt pivot xs .&& e `elem` xs .=> e .< pivot) $
+            \ih (x, xs) e pivot -> [llt pivot (x .: xs), e `elem` (x .: xs)]
+                                |- e .< pivot
+                                ?? ih
+                                =: sTrue
+                                =: qed
+
+  -- lge correctness
+  lgeCorrect <-
+     induct "lgeCorrect"
+            (\(Forall xs) (Forall e) (Forall pivot) -> lge pivot xs .&& e `elem` xs .=> e .>= pivot) $
+            \ih (x, xs) e pivot -> [lge pivot (x .: xs), e `elem` (x .: xs)]
+                                |- e .>= pivot
+                                ?? ih
+                                =: sTrue
+                                =: qed
+
+  -- If a value is less than all the elements in a list, then it is also less than all the elements of any sublist of it
+  lltSublist <-
+     inductWith cvc5 "lltSublist"
+            (\(Forall xs) (Forall pivot) (Forall ys) -> llt pivot ys .&& xs `sublist` ys .=> llt pivot xs) $
+            \ih (x, xs) pivot ys -> [llt pivot ys, (x .: xs) `sublist` ys]
+                                 |- llt pivot (x .: xs)
+                                 =: x .< pivot .&& llt pivot xs
+                                 -- To establish x .< pivot, observe that x is in ys, and together
+                                 -- with llt pivot ys, we get that x is less than pivot
+                                 ?? sublistElem `at` (Inst @"x" x,   Inst @"xs" xs, Inst @"ys" ys)
+                                 ?? lltCorrect  `at` (Inst @"xs" ys, Inst @"e"  x,  Inst @"pivot" pivot)
+
+                                 -- Use induction hypothesis to get rid of the second conjunct. We need to tell
+                                 -- the prover that xs is a sublist of ys too so it can satisfy its precondition
+                                 ?? sublistTail `at` (Inst @"x" x, Inst @"xs" xs, Inst @"ys" ys)
+                                 ?? ih          `at` (Inst @"pivot" pivot, Inst @"ys" ys)
+                                 =: sTrue
+                                 =: qed
+
+  -- Variant of the above for the permutation case
+  lltPermutation <-
+     calc "lltPermutation"
+           (\(Forall xs) (Forall pivot) (Forall ys) -> llt pivot ys .&& isPermutation xs ys .=> llt pivot xs) $
+           \xs pivot ys -> [llt pivot ys, isPermutation xs ys]
+                        |- llt pivot xs
+                        ?? lltSublist    `at` (Inst @"xs" xs, Inst @"pivot" pivot, Inst @"ys" ys)
+                        ?? sublistIfPerm `at` (Inst @"xs" xs, Inst @"ys" ys)
+                        =: sTrue
+                        =: qed
+
+  -- If a value is greater than or equal to all the elements in a list, then it is also less than all the elements of any sublist of it
+  lgeSublist <-
+     inductWith cvc5 "lgeSublist"
+            (\(Forall xs) (Forall pivot) (Forall ys) -> lge pivot ys .&& xs `sublist` ys .=> lge pivot xs) $
+            \ih (x, xs) pivot ys -> [lge pivot ys, (x .: xs) `sublist` ys]
+                                 |- lge pivot (x .: xs)
+                                 =: x .>= pivot .&& lge pivot xs
+                                 -- To establish x .>= pivot, observe that x is in ys, and together
+                                 -- with lge pivot ys, we get that x is greater than equal to the pivot
+                                 ?? sublistElem `at` (Inst @"x" x,   Inst @"xs" xs, Inst @"ys" ys)
+                                 ?? lgeCorrect  `at` (Inst @"xs" ys, Inst @"e"  x,  Inst @"pivot" pivot)
+
+                                 -- Use induction hypothesis to get rid of the second conjunct. We need to tell
+                                 -- the prover that xs is a sublist of ys too so it can satisfy its precondition
+                                 ?? sublistTail `at` (Inst @"x" x, Inst @"xs" xs, Inst @"ys" ys)
+                                 ?? ih          `at` (Inst @"pivot" pivot, Inst @"ys" ys)
+                                 =: sTrue
+                                 =: qed
+
+  -- Variant of the above for the permutation case
+  lgePermutation <-
+     calc "lgePermutation"
+           (\(Forall xs) (Forall pivot) (Forall ys) -> lge pivot ys .&& isPermutation xs ys .=> lge pivot xs) $
+           \xs pivot ys -> [lge pivot ys, isPermutation xs ys]
+                        |- lge pivot xs
+                        ?? lgeSublist    `at` (Inst @"xs" xs, Inst @"pivot" pivot, Inst @"ys" ys)
+                        ?? sublistIfPerm `at` (Inst @"xs" xs, Inst @"ys" ys)
+                        =: sTrue
+                        =: qed
+
+  --------------------------------------------------------------------------------------------
+  -- Part III. Helper lemmas for partition
+  --------------------------------------------------------------------------------------------
+
+  -- The first element of the partition produces all smaller elements
+  partitionFstLT <- inductWith cvc5 "partitionFstLT"
+     (\(Forall l) (Forall pivot) -> llt pivot (fst (partition pivot l))) $
+     \ih (a, as) pivot -> [] |- llt pivot (fst (partition pivot (a .: as)))
+                             ?? "unroll partition"
+                             =: let (lo, hi) = untuple (partition pivot as)
+                             in llt pivot (fst (ite (a .< pivot)
+                                                    (tuple (a .: lo, hi))
+                                                    (tuple (lo, a .: hi))))
+                             ?? "push fst down, simplify"
+                             =: llt pivot (ite (a .< pivot) (a .: lo) lo)
+                             ?? "push llt down"
+                             =: ite (a .< pivot) (llt pivot (a .: lo)) (llt pivot lo)
+                             ?? ih
+                             =: sTrue
+                             =: qed
+
+  -- The second element of the partition produces all greater-than-or-equal to elements
+  partitionSndGE <- inductWith cvc5 "partitionSndGE"
+     (\(Forall l) (Forall pivot) -> lge pivot (snd (partition pivot l))) $
+     \ih (a, as) pivot -> [] |- lge pivot (snd (partition pivot (a .: as)))
+                             =: lge pivot (ite (a .< pivot)
+                                               (     snd (partition pivot as))
+                                               (a .: snd (partition pivot as)))
+                             ?? "push lge down"
+                             =: ite (a .< pivot)
+                                    (a .< pivot .&& lge pivot (snd (partition pivot as)))
+                                    (               lge pivot (snd (partition pivot as)))
+                             ?? ih
+                             =: sTrue
+                             =: qed
+
+  -- The first element of partition does not increase in size
+  partitionNotLongerFst <- recall (partitionFstBound @a)
+
+  -- The second element of partition does not increase in size
+  partitionNotLongerSnd <- recall (partitionSndBound @a)
+
+  --------------------------------------------------------------------------------------------
+  -- Part IV. Helper lemmas for count
+  --------------------------------------------------------------------------------------------
+
+  -- Count is preserved over partition
+  let countTuple :: SBV a -> STuple [a] [a] -> SInteger
+      countTuple e xsys = count e xs + count e ys
+        where (xs, ys) = untuple xsys
+
+  countPartition <-
+     induct "countPartition"
+            (\(Forall xs) (Forall pivot) (Forall e) -> countTuple e (partition pivot xs) .== count e xs) $
+            \ih (a, as) pivot e ->
+                [] |- countTuple e (partition pivot (a .: as))
+                   ?? "expand partition"
+                   =: countTuple e (let (lo, hi) = untuple (partition pivot as)
+                                    in ite (a .< pivot)
+                                           (tuple (a .: lo, hi))
+                                           (tuple (lo, a .: hi)))
+                   ?? "push countTuple down"
+                   =: let (lo, hi) = untuple (partition pivot as)
+                   in ite (a .< pivot)
+                          (count e (a .: lo) + count e hi)
+                          (count e lo + count e (a .: hi))
+                   =: cases [e .== a  ==> ite (a .< pivot)
+                                              (1 + count e lo + count e hi)
+                                              (count e lo + 1 + count e hi)
+                                       ?? "simplify"
+                                       =: 1 + count e lo + count e hi
+                                       ?? ih
+                                       =: 1 + count e as
+                                       =: qed
+                            , e ./= a ==> ite (a .< pivot)
+                                              (count e lo + count e hi)
+                                              (count e lo + count e hi)
+                                       ?? "simplify"
+                                       =: count e lo + count e hi
+                                       ?? ih
+                                       =: count e as
+                                       =: qed
+                            ]
+  --------------------------------------------------------------------------------------------
+  -- Part V. Prove that the output of quick sort is a permutation of its input
+  --------------------------------------------------------------------------------------------
+
+  sortCountsMatch <-
+     sInduct "sortCountsMatch"
+             (\(Forall xs) (Forall e) -> count e xs .== count e (quickSort xs))
+             (\xs _ -> length xs, []) $
+             \ih xs e ->
+                [] |- count e (quickSort xs)
+                   =: [pCase| xs of
+                        []             -> trivial
+                        whole@(a : as) ->
+                              let (lo, hi) = untuple (partition a as)
+                              in count e (quickSort whole)
+                              ?? "expand quickSort"
+                              =: count e (quickSort lo ++ [a] ++ quickSort hi)
+                              ?? "push count down"
+                              =: count e (quickSort lo ++ [a] ++ quickSort hi)
+                              ?? countAppend `at` (Inst @"xs" (quickSort lo), Inst @"ys" ([a] ++ quickSort hi), Inst @"e" e)
+                              =: count e (quickSort lo) + count e ([a] ++ quickSort hi)
+                              ?? countAppend `at` (Inst @"xs" [a], Inst @"ys" (quickSort hi), Inst @"e" e)
+                              =: count e (quickSort lo) + count e [a] + count e (quickSort hi)
+                              ?? ih                    `at` (Inst @"xs" lo, Inst @"e" e)
+                              ?? partitionNotLongerFst `at` (Inst @"l"  as, Inst @"pivot" a)
+                              ?? "IH on lo"
+                              =: count e lo + count e [a] + count e (quickSort hi)
+                              ?? ih                    `at` (Inst @"xs" hi, Inst @"e" e)
+                              ?? partitionNotLongerSnd `at` (Inst @"l"  as, Inst @"pivot" a)
+                              ?? "IH on hi"
+                              =: count e lo + count e [a] + count e hi
+                              ?? countPartition `at` (Inst @"xs" as, Inst @"pivot" a, Inst @"e" e)
+                              =: count e xs
+                              =: qed
+                      |]
+
+  sortIsPermutation <- lemma "sortIsPermutation" (\(Forall xs) -> isPermutation xs (quickSort xs)) [proofOf sortCountsMatch]
+
+  --------------------------------------------------------------------------------------------
+  -- Part VI. Helper lemmas for nonDecreasing
+  --------------------------------------------------------------------------------------------
+  nonDecreasingMerge <-
+      inductWith cvc5 "nonDecreasingMerge"
+          (\(Forall xs) (Forall pivot) (Forall ys) ->
+                     nonDecreasing xs .&& llt pivot xs
+                 .&& nonDecreasing ys .&& lge pivot ys .=> nonDecreasing (xs ++ [pivot] ++ ys)) $
+          \ih (x, xs) pivot ys ->
+                [nonDecreasing (x .: xs), llt pivot xs, nonDecreasing ys, lge pivot ys]
+             |- nonDecreasing (x .: xs ++ [pivot] ++ ys)
+             =: [pCase| xs of
+                  [] -> trivial
+                  whole@(a : as) ->
+                         nonDecreasing (x .: whole ++ [pivot] ++ ys)
+                      =: nonDecreasing (x .: a .: (as ++ [pivot] ++ ys))
+                      =: x .<= a .&& nonDecreasing (a .: (as ++ [pivot] ++ ys))
+                      =: nonDecreasing (a .: (as ++ [pivot] ++ ys))
+                      =: nonDecreasing (whole ++ [pivot] ++ ys)
+                      =: nonDecreasing (xs ++ [pivot] ++ ys)
+                      -- This hint shouldn't be necessary, but it makes the proof go faster!
+                      ?? nonDecreasing xs
+                      ?? ih
+                      =: sTrue
+                      =: qed
+                |]
+
+  --------------------------------------------------------------------------------------------
+  -- Part VII. Prove that the output of quick sort is non-decreasing
+  --------------------------------------------------------------------------------------------
+  sortIsNonDecreasing <-
+     sInductWith cvc5 "sortIsNonDecreasing"
+             (\(Forall xs) -> nonDecreasing (quickSort xs))
+             (length @a, []) $
+             \ih xs ->
+                [] |- nonDecreasing (quickSort xs)
+                   =: [pCase| xs of
+                        [] -> trivial
+                        whole@(a : as) ->
+                             let (lo, hi) = untuple (partition a as)
+                             in nonDecreasing (quickSort whole)
+                          ?? "expand quickSort"
+                          =: nonDecreasing (quickSort lo ++ [a] ++ quickSort hi)
+                          -- Deduce that lo/hi is not longer than as, and hence, shorter than xs
+                          ?? partitionNotLongerFst `at` (Inst @"l" as, Inst @"pivot" a)
+                          ?? partitionNotLongerSnd `at` (Inst @"l" as, Inst @"pivot" a)
+
+                          -- Use the inductive hypothesis twice to deduce quickSort of lo and hi are nonDecreasing
+                          ?? ih `at` Inst @"xs" lo  -- nonDecreasing (quickSort lo)
+                          ?? ih `at` Inst @"xs" hi  -- nonDecreasing (quickSort hi)
+
+                          -- Deduce that lo is all less than a, and hi is all greater than or equal to a
+                          ?? partitionFstLT `at` (Inst @"l" as, Inst @"pivot" a)
+                          ?? partitionSndGE `at` (Inst @"l" as, Inst @"pivot" a)
+
+                          -- Deduce that quickSort lo is all less than a
+                          ?? sortIsPermutation `at`  Inst @"xs" lo
+                          ?? lltPermutation    `at` (Inst @"xs" (quickSort lo), Inst @"pivot" a, Inst @"ys" lo)
+
+                          -- Deduce that quickSort hi is all greater than or equal to a
+                          ?? sortIsPermutation `at`  Inst @"xs" hi
+                          ?? lgePermutation    `at` (Inst @"xs" (quickSort hi), Inst @"pivot" a, Inst @"ys" hi)
+
+                          -- Finally conclude that the whole reconstruction is non-decreasing
+                          ?? nonDecreasingMerge `at` (Inst @"xs" (quickSort lo), Inst @"pivot" a, Inst @"ys" (quickSort hi))
+                          =: sTrue
+                          =: qed
+                      |]
+
+  --------------------------------------------------------------------------------------------
+  -- Part VIII. Putting it together
+  --------------------------------------------------------------------------------------------
+
+  qs <- lemma "quickSortIsCorrect"
+              (\(Forall xs) -> let out = quickSort xs in isPermutation xs out .&& nonDecreasing out)
+              [proofOf sortIsPermutation, proofOf sortIsNonDecreasing]
+
+  --------------------------------------------------------------------------------------------
+  -- Part IX. Bonus: This property isn't really needed for correctness, but let's also prove
+  -- that if a list is sorted, then quick-sort returns it unchanged.
+  --------------------------------------------------------------------------------------------
+  partitionSortedLeft <-
+     inductWith cvc5 "partitionSortedLeft"
+            (\(Forall @"as" as) (Forall @"pivot" pivot) -> nonDecreasing (pivot .: as) .=> null (fst (partition pivot as))) $
+            \ih (a, as) pivot -> [nonDecreasing (pivot .: a .: as)]
+                              |- fst (partition pivot (a .: as))
+                              =: let (lo, _) = untuple (partition pivot as)
+                              in lo
+                              ?? ih
+                              =: nil
+                              =: qed
+
+  partitionSortedRight <-
+     inductWith cvc5 "partitionSortedRight"
+           (\(Forall @"xs" xs) (Forall @"pivot" pivot) -> nonDecreasing (pivot .: xs) .=> xs .== snd (partition pivot xs)) $
+           \ih (a, as) pivot -> [nonDecreasing (pivot .: a .: as)]
+                             |- snd (partition pivot (a .: as))
+                             =: let (_, hi) = untuple (partition pivot as)
+                             in a .: hi
+                             ?? ih
+                             =: a .: as
+                             =: qed
+
+  unchangedIfNondecreasing <-
+       induct "unchangedIfNondecreasing"
+              (\(Forall @"xs" xs) -> nonDecreasing xs .=> quickSort xs .== xs) $
+              \ih (x, xs) -> [nonDecreasing (x .: xs)]
+                          |- quickSort (x .: xs)
+                          =: let (lo, hi) = untuple (partition x xs)
+                          in quickSort lo ++ [x] ++ quickSort hi
+                          ?? partitionSortedLeft
+                          =: [x] ++ quickSort hi
+                          ?? partitionSortedRight
+                          =: [x] ++ quickSort xs
+                          ?? ih
+                          =: x .: xs
+                          =: qed
+
+  -- A nice corollary to the above is that if quicksort changes its input, that implies the input was not non-decreasing:
+  _ <- lemma "ifChangedThenUnsorted"
+             (\(Forall @"xs" xs) -> quickSort xs ./= xs .=> sNot (nonDecreasing xs))
+             [proofOf unchangedIfNondecreasing]
+
+  --------------------------------------------------------------------------------------------
+  -- We can display the dependencies in a proof.
+  -- Note that we do avoid doing this during the
+  -- dry-run of the proof to avoid duplicate output.
+  --------------------------------------------------------------------------------------------
+  unlessDryRun $ liftIO $ do putStrLn "== Proof tree:"
+                             putStr $ showProofTree True qs
+
+  pure qs
+
+{- HLint ignore correctness "Use :" -}
diff --git a/Documentation/SBV/Examples/TP/RevAcc.hs b/Documentation/SBV/Examples/TP/RevAcc.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/RevAcc.hs
@@ -0,0 +1,81 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.RevAcc
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves that the accumulating version of reverse is equivalent to the
+-- standard definition.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.RevAcc where
+
+import Prelude hiding (head, tail, null, reverse, (++))
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+#endif
+
+-- * Reversing with an accumulator.
+
+-- | Accumulating reverse.
+revAcc :: SymVal a => SList a -> SList a -> SList a
+revAcc = smtFunction "revAcc"
+       $ \acc xs -> [sCase| xs of
+                       []     -> acc
+                       a : as -> revAcc (a .: acc) as
+                    |]
+
+-- | Given 'revAcc', we can reverse a list by providing the empty list as the initial accumulator.
+rev :: SymVal a => SList a -> SList a
+rev = revAcc []
+
+-- * Correctness proof
+
+-- | Correctness the function 'rev'. We have:
+--
+-- >>> correctness @Integer
+-- Inductive lemma: revAccCorrect
+--   Step: Base                      Q.E.D.
+--   Step: 1                         Q.E.D.
+--   Step: 2                         Q.E.D.
+--   Step: 3                         Q.E.D.
+--   Step: 4                         Q.E.D.
+--   Result:                         Q.E.D.
+-- Lemma: revCorrect                 Q.E.D.
+-- Functions proven terminating: revAcc, sbv.reverse
+-- [Proven] revCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. SymVal a => IO (Proof (Forall "xs" [a] -> SBool))
+correctness = runTP $ do
+
+  -- Helper lemma regarding 'revAcc'
+  helper <- induct "revAccCorrect"
+                   (\(Forall @"xs" (xs :: SList a)) (Forall @"acc" acc) -> revAcc acc xs .== reverse xs ++ acc) $
+                   \ih (x, xs) acc -> [] |- revAcc acc (x .: xs)
+                                         =: revAcc (x .: acc) xs
+                                         ?? ih
+                                         =: reverse xs ++ x .: acc
+                                         =: (reverse xs ++ [x]) ++ acc
+                                         =: reverse (x .: xs) ++ acc
+                                         =: qed
+
+  -- The main theorem simply follows from the helper:
+  lemma "revCorrect"
+        (\(Forall xs) -> rev xs .== reverse xs)
+        [proofOf helper]
diff --git a/Documentation/SBV/Examples/TP/Reverse.hs b/Documentation/SBV/Examples/TP/Reverse.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Reverse.hs
@@ -0,0 +1,176 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Reverse
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Can we define the reverse function using no auxiliary functions, i.e., only
+-- in terms of cons, head, tail, and itself (recursively)? This example
+-- shows such a definition and proves that it is correct.
+--
+-- See Zohar Manna's 1974 "Mathematical Theory of Computation" book, where this
+-- definition and its proof is presented as Example 5.36.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Reverse where
+
+import Prelude hiding (head, tail, null, reverse, length, init, last, (++))
+
+import Data.SBV
+import Data.SBV.List hiding (partition)
+import Data.SBV.TP
+
+import qualified Documentation.SBV.Examples.TP.Lists as TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Reversing with no auxiliaries
+
+-- | This definition of reverse uses no helper functions, other than the usual
+-- head, tail, and cons to reverse a given list. Note that efficiency
+-- is not our concern here, we call 'rev' itself three times in the body.
+rev :: forall a. SymVal a => SList a -> SList a
+rev = smtFunctionWithMeasure "rev"
+        ( length @a
+        , [measureLemma (revPreservesLen @a)]
+        )
+    $ \xs -> [sCase| xs of
+                []     -> xs
+                x : as -> case rev as of
+                            []         -> [x]
+                            hras : tas -> hras .: rev (x .: rev tas)
+             |]
+
+-- | Reversing preserves length. Needed as a measure helper for 'rev'.
+--
+-- >>> runTP $ revPreservesLen @Integer
+-- Inductive lemma (strong): revPreservesLen
+--   Step: Measure is non-negative              Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                                Q.E.D.
+--     Step: 1.2                                Q.E.D.
+--     Step: 1.3.1                              Q.E.D.
+--     Step: 1.3.2                              Q.E.D.
+--     Step: 1.3.3                              Q.E.D.
+--     Step: 1.Completeness                     Q.E.D.
+--   Result:                                    Q.E.D.
+-- Functions proven terminating: rev
+-- [Proven] revPreservesLen :: Ɐxs ∷ [Integer] → Bool
+revPreservesLen :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+revPreservesLen = sInductWith cvc5 "revPreservesLen"
+   (\(Forall xs) -> length (rev @a xs) .== length xs)
+   (length, []) $
+   \ih xs -> [] |- length (rev @a xs) .== length xs
+               =: [pCase| xs of
+                    []     -> trivial
+                    [_]    -> trivial
+                    whole@(a : as) -> length (head (rev as) .: rev (a .: rev (tail (rev as)))) .== length whole
+                           -- Simplify: length (h .: e) = 1 + length e
+                           =: (1 + length (rev (a .: rev (tail (rev as))))) .== (1 + length as)
+                           -- Now apply the IH instances in order: each precondition depends on previous conclusions
+                           ?? ih `at` Inst @"xs" as
+                           ?? ih `at` Inst @"xs" (tail (rev as))
+                           ?? ih `at` Inst @"xs" (a .: rev (tail (rev as)))
+                           =: sTrue
+                           =: qed
+                  |]
+
+-- * Correctness proof
+
+-- | Correctness the function 'rev'. We have:
+--
+-- >>> runTP $ correctness @Integer
+-- Lemma: revLen                           Q.E.D.
+-- Lemma: revApp                           Q.E.D.
+-- Lemma: revSnoc                          Q.E.D.
+-- Lemma: revRev                           Q.E.D.
+-- Inductive lemma (strong): revCorrect
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2                           Q.E.D.
+--     Step: 1.3.1                         Q.E.D.
+--     Step: 1.3.2                         Q.E.D.
+--     Step: 1.3.3                         Q.E.D.
+--     Step: 1.3.4                         Q.E.D.
+--     Step: 1.3.5                         Q.E.D.
+--     Step: 1.3.6 (simplify head)         Q.E.D.
+--     Step: 1.3.7                         Q.E.D.
+--     Step: 1.3.8 (simplify tail)         Q.E.D.
+--     Step: 1.3.9                         Q.E.D.
+--     Step: 1.3.10                        Q.E.D.
+--     Step: 1.3.11                        Q.E.D.
+--     Step: 1.3.12 (substitute)           Q.E.D.
+--     Step: 1.3.13                        Q.E.D.
+--     Step: 1.3.14                        Q.E.D.
+--     Step: 1.3.15                        Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Functions proven terminating: rev, sbv.reverse
+-- [Proven] revCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+correctness = do
+
+  -- Quietly import a few helpers from "Data.SBV.TP.List"
+  revLen  <- recall $ TP.revLen  @a
+  revApp  <- recall $ TP.revApp  @a
+  revSnoc <- recall $ TP.revSnoc @a
+  revRev  <- recall $ TP.revRev  @a
+
+  sInductWith cvc5 "revCorrect"
+    (\(Forall xs) -> rev xs .== reverse xs)
+    (length, []) $
+    \ih xs -> [] |- rev xs
+                 =: [pCase| xs of
+                      []     -> trivial
+                      [_]    -> trivial
+                      a : as -> head (rev as) .: rev (a .: rev (tail (rev as)))
+                             ?? ih `at` Inst @"xs" as
+                             =: head (reverse as) .: rev (a .: rev (tail (rev as)))
+                             ?? ih `at` Inst @"xs" as
+                             =: head (reverse as) .: rev (a .: rev (tail (reverse as)))
+                             ?? ih `at` Inst @"xs" (tail (rev as))
+                             =: head (reverse as) .: rev (a .: rev (tail (reverse as)))
+                             ?? revSnoc `at` (Inst @"x" (last as), Inst @"xs" (init as))
+                             =: let w = init as
+                                    b = last as
+                             in head (b .: reverse w) .: rev (a .: rev (tail (reverse as)))
+                             ?? "simplify head"
+                             =: b .: rev (a .: rev (tail (reverse as)))
+                             ?? revSnoc `at` (Inst @"x" (last xs), Inst @"xs" (init as))
+                             =: b .: rev (a .: rev (tail (b .: reverse w)))
+                             ?? "simplify tail"
+                             =: b .: rev (a .: rev (reverse w))
+                             ?? ih     `at` Inst @"xs" (reverse w)
+                             ?? revLen `at` Inst @"xs" w
+                             =: b .: rev (a .: reverse (reverse w))
+                             ?? revRev `at` Inst @"xs" w
+                             =: b .: rev (a .: w)
+                             ?? ih
+                             =: b .: reverse (a .: w)
+                             ?? "substitute"
+                             =: last as .: reverse (a .: init as)
+                             ?? revApp `at` (Inst @"xs" (a .: init as), Inst @"ys" [last as])
+                             =: reverse (a .: init as ++ [last as])
+                             =: reverse (a .: as)
+                             =: reverse xs
+                             =: qed
+                    |]
+
+{- HLint ignore correctness "Use last"          -}
+{- HLint ignore correctness "Redundant reverse" -}
diff --git a/Documentation/SBV/Examples/TP/RunLength.hs b/Documentation/SBV/Examples/TP/RunLength.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/RunLength.hs
@@ -0,0 +1,198 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.RunLength
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proving that run-length decoding inverts encoding. We define:
+--
+--   * @encode@: groups consecutive equal elements into (value, count) pairs
+--   * @decode@: expands each pair back into a run of elements
+--
+-- and prove @decode (encode xs) == xs@ for all finite lists @xs@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.RunLength where
+
+import Prelude hiding (length, head, tail, null, reverse, (++), replicate, fst, snd)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.Tuple
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XOverloadedLists
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Tuple
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Definitions
+
+-- | Run-length decode: expand each (value, count) pair into a run of that element.
+--
+-- >>> decode (tuple (1,3) .: tuple (2,2) .: tuple (3,1) .: []) :: SList Integer
+-- [1,1,1,2,2,3] :: [SInteger]
+-- >>> decode ([] :: SList (Integer, Integer))
+-- [] :: [SInteger]
+decode :: forall a. SymVal a => SList (a, Integer) -> SList a
+decode = smtFunction "decode"
+       $ \ps -> [sCase| ps of
+                   []            -> []
+                   (e, c) : rest -> replicate c e ++ decode rest
+                |]
+
+-- | Prepend an element to a run-length encoded list. If the head run has the
+-- same value, we increment its count; otherwise we create a new singleton run.
+--
+-- >>> encodeCons 1 (encode [1,1,2,2]) :: SList (Integer, Integer)
+-- [(1,3),(2,2)] :: [(SInteger, SInteger)]
+-- >>> encodeCons 5 (encode [1,1,2,2]) :: SList (Integer, Integer)
+-- [(5,1),(1,2),(2,2)] :: [(SInteger, SInteger)]
+encodeCons :: forall a. SymVal a => SBV a -> SList (a, Integer) -> SList (a, Integer)
+encodeCons = smtFunction "encodeCons"
+           $ \x ps -> [sCase| ps of
+                         []                      -> [tuple (x, 1)]
+                         (e, c) : rest | x .== e -> tuple (x, c + 1) .: rest
+                                       | True    -> tuple (x,     1) .: ps
+                      |]
+
+-- | Run-length encode: fold from the right, using 'encodeCons' to merge
+-- each element into the growing encoding.
+--
+-- >>> encode [1,1,1,2,2,3] :: SList (Integer, Integer)
+-- [(1,3),(2,2),(3,1)] :: [(SInteger, SInteger)]
+-- >>> encode ([] :: SList Integer)
+-- [] :: [(SInteger, SInteger)]
+-- >>> encode [4] :: SList (Integer, Integer)
+-- [(4,1)] :: [(SInteger, SInteger)]
+encode :: forall a. SymVal a => SList a -> SList (a, Integer)
+encode = smtFunction "encode"
+       $ \xs -> [sCase| xs of
+                   []       -> []
+                   x : rest -> encodeCons x (encode rest)
+                |]
+
+-- * Correctness
+
+-- | @decode (encode xs) == xs@
+--
+-- The proof proceeds by induction on @xs@. The key helper shows that
+-- decoding after 'encodeCons' is the same as consing the element,
+-- provided the head count in the encoded list is positive (which
+-- 'encode' always guarantees).
+--
+-- >>> runTPWith cvc5 $ correctness @Integer
+-- Lemma: decodeEncodeCons
+--   Step: 1 (3 way case split)
+--     Step: 1.1.1                         Q.E.D.
+--     Step: 1.1.2                         Q.E.D.
+--     Step: 1.1.3                         Q.E.D.
+--     Step: 1.1.4                         Q.E.D.
+--     Step: 1.2.1                         Q.E.D.
+--     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.2.4                         Q.E.D.
+--     Step: 1.3.1                         Q.E.D.
+--     Step: 1.3.2                         Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Inductive lemma: encodeHeadPos
+--   Step: Base                            Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2.1                         Q.E.D.
+--     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.3                           Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Inductive lemma (strong): rleCorrect
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2.1                         Q.E.D.
+--     Step: 1.2.2                         Q.E.D.
+--     Step: 1.2.3                         Q.E.D.
+--     Step: 1.2.4                         Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Functions proven terminating: decode, encode, sbv.replicate
+-- [Proven] rleCorrect :: Ɐxs ∷ [Integer] → Bool
+correctness :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> SBool))
+correctness = do
+
+  -- Key helper: encodeCons followed by decode is the same as consing.
+  -- The condition ensures the head count is positive so that
+  -- replicate (n+1) unfolds correctly.
+  helper <- calc "decodeEncodeCons"
+                 (\(Forall @"x" (x :: SBV a)) (Forall @"ps" ps) ->
+                      (null ps .|| snd (head ps) .>= 1)
+                      .=> decode (encodeCons x ps) .== x .: decode ps) $
+                 \x ps -> [null ps .|| snd (head ps) .>= 1]
+                       |- decode (encodeCons x ps)
+                       =: [pCase| ps of
+                             []                       -> decode [tuple (x, 1)]
+                                                      =: replicate 1 x ++ decode []
+                                                      =: [x] ++ decode []
+                                                      =: x .: decode []
+                                                      =: qed
+                             ((e, c) : ecs) | x .== e -> decode (tuple (x, c + 1) .: ecs)
+                                                      =: replicate (c + 1) x ++ decode ecs
+                                                      =: x .: replicate c x ++ decode ecs
+                                                      =: x .: decode (tuple (e, c) .: ecs)
+                                                      =: qed
+                                            | True    -> decode (tuple (x, 1) .: ps)
+                                                      =: x .: decode ps
+                                                      =: qed
+                          |]
+
+  -- encode always produces a list whose head (if any) has count >= 1
+  -- (This is needed as a precondition for helper above.)
+  encPos <- induct "encodeHeadPos"
+                   (\(Forall @"xs" (xs :: SList a)) ->
+                        null (encode xs) .|| snd (head (encode xs)) .>= 1) $
+                   \ih (x, xs) -> []
+                               |- (null (encodeCons x (encode xs)) .|| snd (head (encodeCons x (encode xs))) .>= 1)
+                               =: cases [ null (encode xs)        ==> trivial
+                                        , sNot (null (encode xs)) .&& x .== fst (head (encode xs))
+                                           ==> snd (head (encodeCons x (encode xs))) .>= 1
+                                            =: snd (head (encode xs)) + 1 .>= 1
+                                            ?? ih
+                                            =: sTrue
+                                            =: qed
+                                        , sNot (null (encode xs)) .&& x ./= fst (head (encode xs))
+                                           ==> trivial
+                                        ]
+
+  -- Main theorem: decode . encode == id
+  sInduct "rleCorrect"
+          (\(Forall xs) -> decode @a (encode xs) .== xs)
+          (length @a, []) $
+          \ih xs -> [] |- decode (encode xs)
+                      =: [pCase| xs of
+                            []             -> trivial
+                            whole@(x : ys) -> decode (encode whole)
+                                           =: decode (encodeCons x (encode ys))
+                                           ?? helper `at` (Inst @"x" x, Inst @"ps" (encode ys))
+                                           ?? encPos `at` Inst @"xs" ys
+                                           =: x .: decode (encode ys)
+                                           ?? ih `at` Inst @"xs" ys
+                                           =: x .: ys
+                                           =: qed
+                         |]
diff --git a/Documentation/SBV/Examples/TP/ShefferStroke.hs b/Documentation/SBV/Examples/TP/ShefferStroke.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/ShefferStroke.hs
@@ -0,0 +1,689 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.ShefferStroke
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Inspired by https://www.philipzucker.com/cody_sheffer/, proving
+-- that the axioms of sheffer stroke (i.e., nand in traditional boolean
+-- logic), imply it is a boolean algebra.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.ShefferStroke where
+
+import Prelude hiding ((<))
+import Data.List (intercalate)
+
+import Data.SBV
+import Data.SBV.TP
+
+-- * Generalized Boolean Algebras
+
+-- | Capture what it means to be a boolean algebra. We follow Lean's
+-- definition, as much as we can: <https://leanprover-community.github.io/mathlib_docs/order/boolean_algebra.html>.
+-- Since there's no way in Haskell to capture properties together with a class, we'll represent the properties
+-- separately.
+class BooleanAlgebra α where
+  ﬧ    :: α -> α
+  (⨆)  :: α -> α -> α
+  (⨅)  :: α -> α -> α
+  (≤)  :: α -> α -> SBool
+  (<)  :: α -> α -> SBool
+  (\\) :: α -> α -> α
+  (⇨)  :: α -> α -> α
+  ⲳ    :: α
+  т    :: α
+
+  infix  4 ≤
+  infixl 6 ⨆
+  infixl 7 ⨅
+
+-- | Proofs needed for a boolean-algebra. Again, we follow Lean's definition here. Since we cannot
+-- put these in the class definition above, we will keep them in a simple data-structure.
+data BooleanAlgebraProof = BooleanAlgebraProof {
+    le_refl          {- ∀ (a : α), a ≤ a                             -} :: Proof (Forall "a" Stroke -> SBool)
+  , le_trans         {- ∀ (a b c : α), a ≤ b → b ≤ c → a ≤ c         -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> Forall "c" Stroke -> SBool)
+  , lt_iff_le_not_le {- (∀ (a b : α), a < b ↔ a ≤ b ∧ ¬b ≤ a)        -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , le_antisymm      {- ∀ (a b : α), a ≤ b → b ≤ a → a = b           -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , le_sup_left      {- ∀ (a b : α), a ≤ a ⊔ b                       -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , le_sup_right     {- ∀ (a b : α), b ≤ a ⊔ b                       -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , sup_le           {- ∀ (a b c : α), a ≤ c → b ≤ c → a ⊔ b ≤ c     -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> Forall "c" Stroke -> SBool)
+  , inf_le_left      {- ∀ (a b : α), a ⊓ b ≤ a                       -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , inf_le_right     {- ∀ (a b : α), a ⊓ b ≤ b                       -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool)
+  , le_inf           {- ∀ (a b c : α), a ≤ b → a ≤ c → a ≤ b ⊓ c     -} :: Proof (Forall "a" Stroke -> Forall "b" Stroke -> Forall "c" Stroke -> SBool)
+  , le_sup_inf       {- ∀ (x y z : α), (x ⊔ y) ⊓ (x ⊔ z) ≤ x ⊔ y ⊓ z -} :: Proof (Forall "x" Stroke -> Forall "y" Stroke -> Forall "z" Stroke -> SBool)
+  , inf_compl_le_bot {- ∀ (x : α), x ⊓ xᶜ ≤ ⊥                        -} :: Proof (Forall "x" Stroke -> SBool)
+  , top_le_sup_compl {- ∀ (x : α), ⊤ ≤ x ⊔ xᶜ                        -} :: Proof (Forall "x" Stroke -> SBool)
+  , le_top           {- ∀ (a : α), a ≤ ⊤                             -} :: Proof (Forall "a" Stroke -> SBool)
+  , bot_le           {- ∀ (a : α), ⊥ ≤ a                             -} :: Proof (Forall "a" Stroke -> SBool)
+  , sdiff_eq         {- (∀ (x y : α), x \ y = x ⊓ yᶜ)                -} :: Proof (Forall "x" Stroke -> Forall "y" Stroke -> SBool)
+  , himp_eq          {- (∀ (x y : α), x ⇨ y = y ⊔ xᶜ)                -} :: Proof (Forall "x" Stroke -> Forall "y" Stroke -> SBool)
+  }
+
+-- | A somewhat prettier printer for a BooleanAlgebra proof
+instance Show BooleanAlgebraProof where
+  show p = intercalate "\n" [ "BooleanAlgebraProof {"
+                            , "  le_refl         : " ++ show (le_refl          p)
+                            , "  le_trans        : " ++ show (le_trans         p)
+                            , "  lt_iff_le_not_le: " ++ show (lt_iff_le_not_le p)
+                            , "  le_antisymm     : " ++ show (le_antisymm      p)
+                            , "  le_sup_left     : " ++ show (le_sup_left      p)
+                            , "  le_sup_right    : " ++ show (le_sup_right     p)
+                            , "  sup_le          : " ++ show (sup_le           p)
+                            , "  inf_le_left     : " ++ show (inf_le_left      p)
+                            , "  inf_le_right    : " ++ show (inf_le_right     p)
+                            , "  le_inf          : " ++ show (le_inf           p)
+                            , "  le_sup_inf      : " ++ show (le_sup_inf       p)
+                            , "  inf_compl_le_bot: " ++ show (inf_compl_le_bot p)
+                            , "  top_le_sup_compl: " ++ show (top_le_sup_compl p)
+                            , "  le_top          : " ++ show (le_top           p)
+                            , "  bot_le          : " ++ show (bot_le           p)
+                            , "  sdiff_eq        : " ++ show (sdiff_eq         p)
+                            , "  himp_eq         : " ++ show (himp_eq          p)
+                            , "}"
+                            ]
+
+-- * The sheffer stroke
+
+-- | The abstract type for the domain.
+data Stroke
+mkSymbolic [''Stroke]
+
+-- | The sheffer stroke operator.
+(⏐) :: SStroke -> SStroke -> SStroke
+(⏐) = uninterpret "⏐"
+infixl 7 ⏐
+
+-- | The boolean algebra of the sheffer stroke.
+instance BooleanAlgebra SStroke where
+  ﬧ x    = x ⏐ x
+  a ⨆ b  = ﬧ(a ⏐ b)
+  a ⨅ b  = ﬧ a ⏐ ﬧ b
+  a ≤ b  = a .== b ⨅ a
+  a < b  = a ≤ b .&& a ./= b
+  a \\ b = a ⨅ ﬧ b
+  a ⇨ b  = b ⨆ ﬧ a
+  ⲳ      = arb ⏐ ﬧ arb where arb = some "ⲳ" (const sTrue)
+  т      = ﬧ ⲳ
+
+-- | Double-negation
+ﬧﬧ :: BooleanAlgebra a => a -> a
+ﬧﬧ = ﬧ . ﬧ
+
+-- | First Sheffer axiom: @ﬧﬧa == a@
+sheffer1 :: TP (Proof (Forall "a" Stroke -> SBool))
+sheffer1 = axiom "ﬧﬧa == a" $ \(Forall a) -> ﬧﬧ a .== a
+
+-- | Second Sheffer axiom: @a ⏐ (b ⏐ ﬧb) == ﬧa@
+sheffer2 :: TP (Proof (Forall "a" Stroke -> Forall "b" Stroke -> SBool))
+sheffer2 = axiom "a ⏐ (b ⏐ ﬧb) == ﬧa" $ \(Forall a) (Forall b) -> a ⏐ (b ⏐ ﬧ b) .== ﬧ a
+
+-- | Third Sheffer axiom: @ﬧ(a ⏐ (b ⏐ c)) == (ﬧb ⏐ a) ⏐ (ﬧc ⏐ a)@
+sheffer3 :: TP (Proof (Forall "a" Stroke -> Forall "b" Stroke -> Forall "c" Stroke -> SBool))
+sheffer3 = axiom "ﬧ(a ⏐ (b ⏐ c)) == (ﬧb ⏐ a) ⏐ (ﬧc ⏐ a)" $ \(Forall a) (Forall b) (Forall c) -> ﬧ(a ⏐ (b ⏐ c)) .== (ﬧ b ⏐ a) ⏐ (ﬧ c ⏐ a)
+
+-- * Sheffer's stroke defines a boolean algebra
+
+-- | Prove that Sheffer stroke axioms imply it is a boolean algebra. We have:
+--
+-- >>> shefferBooleanAlgebra
+-- Axiom: ﬧﬧa == a
+-- Axiom: a ⏐ (b ⏐ ﬧb) == ﬧa
+-- Axiom: ﬧ(a ⏐ (b ⏐ c)) == (ﬧb ⏐ a) ⏐ (ﬧc ⏐ a)
+-- Lemma: a | b = b | a
+--   Step: 1 (ﬧﬧa == a)                                 Q.E.D.
+--   Step: 2 (ﬧﬧa == a)                                 Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4 (ﬧ(a ⏐ (b ⏐ c)) == (ﬧb ⏐ a) ⏐ (ﬧc ⏐ a))    Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6 (ﬧﬧa == a)                                 Q.E.D.
+--   Step: 7 (ﬧﬧa == a)                                 Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a | a′ = b | b′
+--   Step: 1 (ﬧﬧa == a)                                 Q.E.D.
+--   Step: 2 (a ⏐ (b ⏐ ﬧb) == ﬧa)                       Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4 (a ⏐ (b ⏐ ﬧb) == ﬧa)                       Q.E.D.
+--   Step: 5 (ﬧﬧa == a)                                 Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊔ b = b ⊔ a                                 Q.E.D.
+-- Lemma: a ⊓ b = b ⊓ a                                 Q.E.D.
+-- Lemma: a ⊔ ⲳ = a                                     Q.E.D.
+-- Lemma: a ⊓ т = a                                     Q.E.D.
+-- Lemma: a ⊔ (b ⊓ c) = (a ⊔ b) ⊓ (a ⊔ c)               Q.E.D.
+-- Lemma: a ⊓ (b ⊔ c) = (a ⊓ b) ⊔ (a ⊓ c)               Q.E.D.
+-- Lemma: a ⊔ aᶜ = т                                    Q.E.D.
+-- Lemma: a ⊓ aᶜ = ⲳ                                    Q.E.D.
+-- Lemma: a ⊔ т = т
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊓ ⲳ = ⲳ
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊔ (a ⊓ b) = a
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊓ (a ⊔ b) = a
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊓ a = a
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊔ a' = т → a ⊓ a' = ⲳ → a' = aᶜ
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Step: 7                                            Q.E.D.
+--   Step: 8                                            Q.E.D.
+--   Step: 9                                            Q.E.D.
+--   Step: 10                                           Q.E.D.
+--   Step: 11                                           Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: aᶜᶜ = a                                       Q.E.D.
+-- Lemma: aᶜ = bᶜ → a = b                               Q.E.D.
+-- Lemma: a ⊔ bᶜ = т → a ⊓ bᶜ = ⲳ → a = b               Q.E.D.
+-- Lemma: a ⊔ (aᶜ ⊔ b) = т
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊓ (aᶜ ⊓ b) = ⲳ
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: (a ⊔ b)ᶜ = aᶜ ⊓ bᶜ                            Q.E.D.
+-- Lemma: (a ⨅ b)ᶜ = aᶜ ⨆ bᶜ                            Q.E.D.
+-- Lemma: (a ⊔ (b ⊔ c)) ⊔ aᶜ = т                        Q.E.D.
+-- Lemma: b ⊓ (a ⊔ (b ⊔ c)) = b                         Q.E.D.
+-- Lemma: b ⊔ (a ⊓ (b ⊓ c)) = b                         Q.E.D.
+-- Lemma: (a ⊔ (b ⊔ c)) ⊔ bᶜ = т
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Step: 7                                            Q.E.D.
+--   Step: 8                                            Q.E.D.
+--   Step: 9                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: (a ⊔ (b ⊔ c)) ⊔ cᶜ = т                        Q.E.D.
+-- Lemma: (a ⊔ b ⊔ c)ᶜ ⊓ a = ⲳ
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Step: 7                                            Q.E.D.
+--   Step: 8                                            Q.E.D.
+--   Step: 9                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: (a ⊔ b ⊔ c)ᶜ ⊓ b = ⲳ                          Q.E.D.
+-- Lemma: (a ⊔ b ⊔ c)ᶜ ⊓ c = ⲳ                          Q.E.D.
+-- Lemma: (a ⊔ (b ⊔ c)) ⊔ ((a ⊔ b) ⊔ c)ᶜ = т
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Step: 7                                            Q.E.D.
+--   Step: 8                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: (a ⊔ (b ⊔ c)) ⊓ ((a ⊔ b) ⊔ c)ᶜ = ⲳ
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Step: 5                                            Q.E.D.
+--   Step: 6                                            Q.E.D.
+--   Step: 7                                            Q.E.D.
+--   Step: 8                                            Q.E.D.
+--   Step: 9                                            Q.E.D.
+--   Step: 10                                           Q.E.D.
+--   Step: 11                                           Q.E.D.
+--   Step: 12                                           Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊔ (b ⊔ c) = (a ⊔ b) ⊔ c                     Q.E.D.
+-- Lemma: a ⊓ (b ⊓ c) = (a ⊓ b) ⊓ c
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ≤ b → b ≤ a → a = b
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ≤ a                                         Q.E.D.
+-- Lemma: a ≤ b → b ≤ c → a ≤ c
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Step: 4                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a < b ↔ a ≤ b ∧ ¬b ≤ a                        Q.E.D.
+-- Lemma: a ≤ a ⊔ b                                     Q.E.D.
+-- Lemma: b ≤ a ⊔ b                                     Q.E.D.
+-- Lemma: a ≤ c → b ≤ c → a ⊔ b ≤ c
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: a ⊓ b ≤ a                                     Q.E.D.
+-- Lemma: a ⊓ b ≤ b                                     Q.E.D.
+-- Lemma: a ≤ b → a ≤ c → a ≤ b ⊓ c
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: (x ⊔ y) ⊓ (x ⊔ z) ≤ x ⊔ y ⊓ z                 Q.E.D.
+-- Lemma: x ⊓ xᶜ ≤ ⊥                                    Q.E.D.
+-- Lemma: ⊤ ≤ x ⊔ xᶜ                                    Q.E.D.
+-- Lemma: a ≤ ⊤
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Step: 3                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: ⊥ ≤ a
+--   Step: 1                                            Q.E.D.
+--   Step: 2                                            Q.E.D.
+--   Result:                                            Q.E.D.
+-- Lemma: x \ y = x ⊓ yᶜ                                Q.E.D.
+-- Lemma: x ⇨ y = y ⊔ xᶜ                                Q.E.D.
+-- BooleanAlgebraProof {
+--   le_refl         : [Proven] a ≤ a :: Ɐa ∷ Stroke → Bool
+--   le_trans        : [Proven] a ≤ b → b ≤ c → a ≤ c :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Ɐc ∷ Stroke → Bool
+--   lt_iff_le_not_le: [Proven] a < b ↔ a ≤ b ∧ ¬b ≤ a :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   le_antisymm     : [Proven] a ≤ b → b ≤ a → a = b :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   le_sup_left     : [Proven] a ≤ a ⊔ b :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   le_sup_right    : [Proven] b ≤ a ⊔ b :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   sup_le          : [Proven] a ≤ c → b ≤ c → a ⊔ b ≤ c :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Ɐc ∷ Stroke → Bool
+--   inf_le_left     : [Proven] a ⊓ b ≤ a :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   inf_le_right    : [Proven] a ⊓ b ≤ b :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Bool
+--   le_inf          : [Proven] a ≤ b → a ≤ c → a ≤ b ⊓ c :: Ɐa ∷ Stroke → Ɐb ∷ Stroke → Ɐc ∷ Stroke → Bool
+--   le_sup_inf      : [Proven] (x ⊔ y) ⊓ (x ⊔ z) ≤ x ⊔ y ⊓ z :: Ɐx ∷ Stroke → Ɐy ∷ Stroke → Ɐz ∷ Stroke → Bool
+--   inf_compl_le_bot: [Proven] x ⊓ xᶜ ≤ ⊥ :: Ɐx ∷ Stroke → Bool
+--   top_le_sup_compl: [Proven] ⊤ ≤ x ⊔ xᶜ :: Ɐx ∷ Stroke → Bool
+--   le_top          : [Proven] a ≤ ⊤ :: Ɐa ∷ Stroke → Bool
+--   bot_le          : [Proven] ⊥ ≤ a :: Ɐa ∷ Stroke → Bool
+--   sdiff_eq        : [Proven] x \ y = x ⊓ yᶜ :: Ɐx ∷ Stroke → Ɐy ∷ Stroke → Bool
+--   himp_eq         : [Proven] x ⇨ y = y ⊔ xᶜ :: Ɐx ∷ Stroke → Ɐy ∷ Stroke → Bool
+-- }
+shefferBooleanAlgebra :: IO BooleanAlgebraProof
+shefferBooleanAlgebra = runTP $ do
+
+  -- shorthand
+  let p = proofOf
+
+  -- Get the axioms
+  sh1 <- sheffer1
+  sh2 <- sheffer2
+  sh3 <- sheffer3
+
+  commut <- calc "a | b = b | a" (\(Forall @"a" a) (Forall @"b" b) -> a ⏐ b .== b ⏐ a) $
+                 \a b -> [] ⊢ a ⏐ b                       ∵ sh1
+                            ≡ ﬧﬧ(a ⏐ b)                   ∵ sh1
+                            ≡ ﬧﬧ(a ⏐ ﬧﬧ b)
+                            ≡ ﬧﬧ(a ⏐ (ﬧ b ⏐ ﬧ b))         ∵ sh3
+                            ≡ ﬧ ((ﬧﬧ b ⏐ a) ⏐ (ﬧﬧ b ⏐ a))
+                            ≡ ﬧﬧ(ﬧﬧ b ⏐ a)                ∵ sh1
+                            ≡ ﬧﬧ b ⏐ a                    ∵ sh1
+                            ≡ b ⏐ a
+                            ≡ qed
+
+  all_bot <- calc "a | a′ = b | b′" (\(Forall @"a" a) (Forall @"b" b) -> a ⏐ ﬧ a .== b ⏐ ﬧ b) $
+                  \a b -> [] ⊢ a ⏐ ﬧ a                  ∵ sh1
+                             ≡ ﬧﬧ(a ⏐ ﬧ a)              ∵ sh2
+                             ≡ ﬧ((a ⏐ ﬧ a) ⏐ (b ⏐ ﬧ b)) ∵ commut
+                             ≡ ﬧ((b ⏐ ﬧ b) ⏐ (a ⏐ ﬧ a)) ∵ sh2
+                             ≡ ﬧﬧ (b ⏐ ﬧ b)             ∵ sh1
+                             ≡ b ⏐ ﬧ b
+                             ≡ qed
+
+  commut1  <- lemma "a ⊔ b = b ⊔ a" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨆ b .== b ⨆ a) [p commut]
+  commut2  <- lemma "a ⊓ b = b ⊓ a" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨅ b .== b ⨅ a) [p commut]
+
+  ident1   <- lemma "a ⊔ ⲳ = a" (\(Forall @"a" (a :: SStroke)) -> a ⨆ ⲳ .== a) [p sh1, p sh2]
+  ident2   <- lemma "a ⊓ т = a" (\(Forall @"a" (a :: SStroke)) -> a ⨅ т .== a) [p sh1, p sh2]
+
+  distrib1 <- lemma "a ⊔ (b ⊓ c) = (a ⊔ b) ⊓ (a ⊔ c)"
+                    (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> a ⨆ (b ⨅ c) .== (a ⨆ b) ⨅ (a ⨆ c))
+                    [p sh1, p sh3, p commut]
+
+  distrib2 <- lemma "a ⊓ (b ⊔ c) = (a ⊓ b) ⊔ (a ⊓ c)"
+                    (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> a ⨅ (b ⨆ c) .== (a ⨅ b) ⨆ (a ⨅ c))
+                    [p sh1, p sh3, p commut]
+
+  compl1 <- lemma "a ⊔ aᶜ = т" (\(Forall @"a" (a :: SStroke)) -> a ⨆ ﬧ a .== т) [p sh1, p sh2, p sh3, p all_bot]
+  compl2 <- lemma "a ⊓ aᶜ = ⲳ" (\(Forall @"a" (a :: SStroke)) -> a ⨅ ﬧ a .== ⲳ) [p sh1, p commut, p all_bot]
+
+  bound1 <- calc "a ⊔ т = т" (\(Forall @"a"  a) -> a ⨆ т .== т) $
+                 \a -> [] ⊢ a ⨆ т               ∵ ident2
+                           ≡ (a ⨆ т) ⨅ т         ∵ commut2
+                           ≡ т ⨅ (a ⨆ т)         ∵ compl1
+                           ≡ (a ⨆ ﬧ a) ⨅ (a ⨆ т) ∵ distrib1
+                           ≡ a ⨆ (ﬧ a ⨅ т)       ∵ ident2
+                           ≡ a ⨆ ﬧ a             ∵ compl1
+                           ≡ (т :: SStroke)
+                           ≡ qed
+
+  bound2 <- calc "a ⊓ ⲳ = ⲳ" (\(Forall @"a" a) -> a ⨅ ⲳ .== ⲳ) $
+                 \a -> [] ⊢ a ⨅ ⲳ               ∵ ident1
+                           ≡ (a ⨅ ⲳ) ⨆ ⲳ         ∵ commut1
+                           ≡ ⲳ ⨆ (a ⨅ ⲳ)         ∵ compl2
+                           ≡ (a ⨅ ﬧ a) ⨆ (a ⨅ ⲳ) ∵ distrib2
+                           ≡ a ⨅ (ﬧ a ⨆ ⲳ)       ∵ ident1
+                           ≡ a ⨅ ﬧ a             ∵ compl2
+                           ≡ (ⲳ :: SStroke)
+                           ≡ qed
+
+  absorb1 <- calc "a ⊔ (a ⊓ b) = a" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨆ (a ⨅ b) .== a) $
+                  \a b -> [] ⊢ a ⨆ (a ⨅ b)       ∵ ident2
+                             ≡ (a ⨅ т) ⨆ (a ⨅ b) ∵ distrib2
+                             ≡ a ⨅ (т ⨆ b)       ∵ commut1
+                             ≡ a ⨅ (b ⨆ т)       ∵ bound1
+                             ≡ a ⨅ т             ∵ ident2
+                             ≡ a
+                             ≡ qed
+
+  absorb2 <- calc "a ⊓ (a ⊔ b) = a" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨅ (a ⨆ b) .== a) $
+                  \a b -> [] ⊢ a ⨅ (a ⨆ b)       ∵ ident1
+                             ≡ (a ⨆ ⲳ) ⨅ (a ⨆ b) ∵ distrib1
+                             ≡ a ⨆ (ⲳ ⨅ b)       ∵ commut2
+                             ≡ a ⨆ (b ⨅ ⲳ)       ∵ bound2
+                             ≡ a ⨆ ⲳ             ∵ ident1
+                             ≡ a
+                             ≡ qed
+
+  idemp2 <- calc "a ⊓ a = a" (\(Forall @"a" (a :: SStroke)) -> a ⨅ a .== a) $
+                 \a -> [] ⊢ a ⨅ a       ∵ ident1
+                          ≡ a ⨅ (a ⨆ ⲳ) ∵ absorb2
+                          ≡ a
+                          ≡ qed
+
+  inv <- calc "a ⊔ a' = т → a ⊓ a' = ⲳ → a' = aᶜ"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"a'" a') -> a ⨆ a' .== т .=> a ⨅ a' .== ⲳ .=> a' .== ﬧ a) $
+              \a a' -> [a ⨆ a' .== т, a ⨅ a' .== ⲳ] ⊢ a'                     ∵ ident2
+                                                    ≡ a' ⨅ т                 ∵ compl1
+                                                    ≡ a' ⨅ (a ⨆ ﬧ a)         ∵ distrib2
+                                                    ≡ (a' ⨅ a) ⨆ (a' ⨅ ﬧ a)  ∵ commut2
+                                                    ≡ (a' ⨅ a) ⨆ (ﬧ a ⨅ a')  ∵ commut2
+                                                    ≡ (a ⨅ a') ⨆ (ﬧ a ⨅ a')  ∵ a ⨅ a' .== ⲳ
+                                                    ≡ ⲳ ⨆ (ﬧ a ⨅ a')         ∵ compl2
+                                                    ≡ (a ⨅ ﬧ a) ⨆ (ﬧ a ⨅ a') ∵ commut2
+                                                    ≡ (ﬧ a ⨅ a) ⨆ (ﬧ a ⨅ a') ∵ distrib2
+                                                    ≡ ﬧ a ⨅ (a ⨆ a')         ∵ a ⨆ a' .== т
+                                                    ≡ ﬧ a ⨅ т                ∵ ident2
+                                                    ≡ ﬧ a
+                                                    ≡ qed
+
+  dne      <- lemma "aᶜᶜ = a"
+                    (\(Forall @"a" (a :: SStroke)) -> ﬧﬧ a .== a)
+                    [p inv, p compl1, p compl2, p commut1, p commut2]
+
+  inv_elim <- lemma "aᶜ = bᶜ → a = b"
+                    (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> ﬧ a .== ﬧ b .=> a .== b)
+                    [p dne]
+
+  cancel <- lemma "a ⊔ bᶜ = т → a ⊓ bᶜ = ⲳ → a = b"
+                  (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨆ ﬧ b .== т .=> a ⨅ ﬧ b .== ⲳ .=> a .== b)
+                  [p inv, p inv_elim]
+
+  a1 <- calc "a ⊔ (aᶜ ⊔ b) = т" (\(Forall @"a" a) (Forall @"b" b)  -> a ⨆ (ﬧ a ⨆ b) .== т) $
+             \a b -> [] ⊢ a ⨆ (ﬧ a ⨆ b)               ∵ ident2
+                        ≡ (a ⨆ (ﬧ a ⨆ b)) ⨅ т         ∵ commut2
+                        ≡ т ⨅ (a ⨆ (ﬧ a ⨆ b))         ∵ compl1
+                        ≡ (a ⨆ ﬧ a) ⨅ (a ⨆ (ﬧ a ⨆ b)) ∵ distrib1
+                        ≡ a ⨆ (ﬧ a ⨅ (ﬧ a ⨆ b))       ∵ absorb2
+                        ≡ a ⨆ ﬧ a                     ∵ compl1
+                        ≡ (т :: SStroke)
+                        ≡ qed
+
+  a2 <- calc "a ⊓ (aᶜ ⊓ b) = ⲳ" (\(Forall @"a" a) (Forall @"b" b)  -> a ⨅ (ﬧ a ⨅ b) .== ⲳ) $
+             \a b -> [] ⊢ a ⨅ (ﬧ a ⨅ b)               ∵ ident1
+                        ≡ (a ⨅ (ﬧ a ⨅ b)) ⨆ ⲳ         ∵ commut1
+                        ≡ ⲳ ⨆ (a ⨅ (ﬧ a ⨅ b))         ∵ compl2
+                        ≡ (a ⨅ ﬧ a) ⨆ (a ⨅ (ﬧ a ⨅ b)) ∵ distrib2
+                        ≡ a ⨅ (ﬧ a ⨆ (ﬧ a ⨅ b))       ∵ absorb1
+                        ≡ a ⨅ ﬧ a                     ∵ compl2
+                        ≡ (ⲳ :: SStroke)
+                        ≡ qed
+
+  dm1 <- lemma "(a ⊔ b)ᶜ = aᶜ ⊓ bᶜ"
+               (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> ﬧ(a ⨆ b) .== ﬧ a ⨅ ﬧ b)
+               [p a1, p a2, p dne, p commut1, p commut2, p ident1, p ident2, p distrib1, p distrib2]
+
+  dm2 <- lemma "(a ⨅ b)ᶜ = aᶜ ⨆ bᶜ"
+               (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> ﬧ(a ⨅ b) .== ﬧ a ⨆ ﬧ b)
+               [p a1, p a2, p dne, p commut1, p commut2, p ident1, p ident2, p distrib1, p distrib2]
+
+
+  d1 <- lemma "(a ⊔ (b ⊔ c)) ⊔ aᶜ = т"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> (a ⨆ (b ⨆ c)) ⨆ ﬧ a .== т)
+              [p a1, p a2, p commut1, p ident1, p ident2, p distrib1, p compl1, p compl2, p dm1, p dm2, p idemp2]
+
+  e1 <- lemma "b ⊓ (a ⊔ (b ⊔ c)) = b"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> b ⨅ (a ⨆ (b ⨆ c)) .== b)
+              [p distrib2, p absorb1, p absorb2, p commut1]
+
+  e2 <- lemma "b ⊔ (a ⊓ (b ⊓ c)) = b" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> b ⨆ (a ⨅ (b ⨅ c)) .== b) [p distrib1, p absorb1, p absorb2, p commut2]
+
+  f1 <- calc "(a ⊔ (b ⊔ c)) ⊔ bᶜ = т" (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> (a ⨆ (b ⨆ c)) ⨆ ﬧ b .== т) $
+             \a b c -> [] ⊢ (a ⨆ (b ⨆ c)) ⨆ ﬧ b               ∵ commut1
+                          ≡ ﬧ b ⨆ (a ⨆ (b ⨆ c))               ∵ ident2
+                          ≡ (ﬧ b ⨆ (a ⨆ (b ⨆ c))) ⨅ т         ∵ commut2
+                          ≡ т ⨅ (ﬧ b ⨆ (a ⨆ (b ⨆ c)))         ∵ compl1
+                          ≡ (b ⨆ ﬧ b) ⨅ (ﬧ b ⨆ (a ⨆ (b ⨆ c))) ∵ commut1
+                          ≡ (ﬧ b ⨆ b) ⨅ (ﬧ b ⨆ (a ⨆ (b ⨆ c))) ∵ distrib1
+                          ≡ ﬧ b ⨆ (b ⨅ (a ⨆ (b ⨆ c)))         ∵ e1
+                          ≡ ﬧ b ⨆ b                           ∵ commut1
+                          ≡ b ⨆ ﬧ b                           ∵ compl1
+                          ≡ (т :: SStroke)
+                          ≡ qed
+
+  g1 <- lemma "(a ⊔ (b ⊔ c)) ⊔ cᶜ = т"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> (a ⨆ (b ⨆ c)) ⨆ ﬧ c .== т)
+              [p commut1, p f1]
+
+  h1 <- calc "(a ⊔ b ⊔ c)ᶜ ⊓ a = ⲳ"
+             (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> ﬧ(a ⨆ b ⨆ c) ⨅ a .== ⲳ) $
+             \a b c -> [] ⊢ ﬧ(a ⨆ b ⨆ c) ⨅ a                    ∵ commut2
+                          ≡ a ⨅ ﬧ (a ⨆ b ⨆ c)                   ∵ dm1
+                          ≡ a ⨅ (ﬧ a ⨅ ﬧ b ⨅ ﬧ c)               ∵ ident1
+                          ≡ (a ⨅  (ﬧ a ⨅ ﬧ b ⨅ ﬧ c)) ⨆ ⲳ        ∵ commut1
+                          ≡ ⲳ ⨆ (a ⨅ (ﬧ a ⨅ ﬧ b ⨅ ﬧ c))         ∵ compl2
+                          ≡ (a ⨅ ﬧ a) ⨆ (a ⨅ (ﬧ a ⨅ ﬧ b ⨅ ﬧ c)) ∵ distrib2
+                          ≡ a ⨅ (ﬧ a ⨆ (ﬧ a ⨅ ﬧ b ⨅ ﬧ c))       ∵ commut2
+                          ≡ a ⨅ (ﬧ a ⨆ (ﬧ c ⨅ (ﬧ a ⨅ ﬧ b)))     ∵ e2
+                          ≡ a ⨅ ﬧ a                             ∵ compl2
+                          ≡ (ⲳ :: SStroke)
+                          ≡ qed
+
+  i1 <- lemma "(a ⊔ b ⊔ c)ᶜ ⊓ b = ⲳ"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> ﬧ(a ⨆ b ⨆ c) ⨅ b .== ⲳ)
+              [p commut1, p h1]
+
+  j1 <- lemma "(a ⊔ b ⊔ c)ᶜ ⊓ c = ⲳ"
+              (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> ﬧ(a ⨆ b ⨆ c) ⨅ c .== ⲳ)
+              [p a2, p dne, p commut2]
+
+
+  assoc1 <- do
+    c1 <- calc "(a ⊔ (b ⊔ c)) ⊔ ((a ⊔ b) ⊔ c)ᶜ = т"
+               (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> (a ⨆ (b ⨆ c)) ⨆ ﬧ((a ⨆ b) ⨆ c) .== т) $
+               \a b c -> [] ⊢ (a ⨆ (b ⨆ c)) ⨆ ﬧ((a ⨆ b) ⨆ c)                        ∵ dm1
+                            ≡ (a ⨆ (b ⨆ c)) ⨆ (ﬧ a ⨅ ﬧ b ⨅ ﬧ c)                     ∵ distrib1
+                            ≡ ((a ⨆ (b ⨆ c)) ⨆ (ﬧ a ⨅ ﬧ b)) ⨅ ((a ⨆ (b ⨆ c)) ⨆ ﬧ c) ∵ g1
+                            ≡ ((a ⨆ (b ⨆ c)) ⨆ (ﬧ a ⨅ ﬧ b)) ⨅ т                     ∵ ident2
+                            ≡ (a ⨆ (b ⨆ c)) ⨆ (ﬧ a ⨅ ﬧ b)                           ∵ distrib1
+                            ≡ ((a ⨆ (b ⨆ c)) ⨆ ﬧ a) ⨅ ((a ⨆ (b ⨆ c)) ⨆ ﬧ b)         ∵ d1
+                            ≡ т ⨅ ((a ⨆ (b ⨆ c)) ⨆ ﬧ b)                             ∵ f1
+                            ≡ (т ⨅ т :: SStroke)                                    ∵ idemp2
+                            ≡ (т :: SStroke)
+                            ≡ qed
+
+    c2 <- calc "(a ⊔ (b ⊔ c)) ⊓ ((a ⊔ b) ⊔ c)ᶜ = ⲳ"
+               (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> (a ⨆ (b ⨆ c)) ⨅ ﬧ((a ⨆ b) ⨆ c) .== ⲳ) $
+               \a b c -> [] ⊢ (a ⨆ (b ⨆ c)) ⨅ ﬧ((a ⨆ b) ⨆ c)                    ∵ commut2
+                            ≡ ﬧ((a ⨆ b) ⨆ c) ⨅ (a ⨆ (b ⨆ c))                    ∵ distrib2
+                            ≡ (ﬧ((a ⨆ b) ⨆ c) ⨅ a) ⨆ (ﬧ((a ⨆ b) ⨆ c) ⨅ (b ⨆ c)) ∵ commut2
+                            ≡ (a ⨅ ﬧ((a ⨆ b) ⨆ c)) ⨆ ((b ⨆ c) ⨅ ﬧ((a ⨆ b) ⨆ c)) ∵ commut2
+                            ≡ (ﬧ((a ⨆ b) ⨆ c) ⨅ a) ⨆ ((b ⨆ c) ⨅ ﬧ((a ⨆ b) ⨆ c)) ∵ h1
+                            ≡ ⲳ ⨆ ((b ⨆ c) ⨅ ﬧ((a ⨆ b) ⨆ c))                    ∵ commut1
+                            ≡ ((b ⨆ c) ⨅ ﬧ((a ⨆ b) ⨆ c)) ⨆ ⲳ                    ∵ ident1
+                            ≡ (b ⨆ c) ⨅ ﬧ((a ⨆ b) ⨆ c)                          ∵ commut2
+                            ≡ ﬧ((a ⨆ b) ⨆ c) ⨅ (b ⨆ c)                          ∵ distrib2
+                            ≡ (ﬧ((a ⨆ b) ⨆ c) ⨅ b) ⨆ (ﬧ((a ⨆ b) ⨆ c) ⨅ c)       ∵ j1
+                            ≡ (ﬧ((a ⨆ b) ⨆ c) ⨅ b) ⨆ ⲳ                          ∵ i1
+                            ≡ (ⲳ ⨆ ⲳ :: SStroke)                                ∵ ident1
+                            ≡ (ⲳ :: SStroke)
+                            ≡ qed
+
+    lemma "a ⊔ (b ⊔ c) = (a ⊔ b) ⊔ c"
+          (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> a ⨆ (b ⨆ c) .== (a ⨆ b) ⨆ c)
+          [p c1, p c2, p cancel]
+
+  assoc2 <- calc "a ⊓ (b ⊓ c) = (a ⊓ b) ⊓ c"
+                 (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) (Forall @"c" c) -> a ⨅ (b ⨅ c) .== (a ⨅ b) ⨅ c) $
+                 \a b c -> [] ⊢ a ⨅ (b ⨅ c)     ∵ dne
+                              ≡ ﬧﬧ(a ⨅ (b ⨅ c)) ∵ assoc1
+                              ≡ ﬧﬧ((a ⨅ b) ⨅ c) ∵ dne
+                              ≡   ((a ⨅ b) ⨅ c)
+                              ≡ qed
+
+  le_antisymm <- calc "a ≤ b → b ≤ a → a = b"
+                      (\(Forall @"a" a) (Forall @"b" b) -> a ≤ b .=> b ≤ a .=> a .== b) $
+                      \a b -> [a ≤ b, b ≤ a] ⊢ a     ∵ a ≤ b
+                                             ≡ b ⨅ a ∵ commut2
+                                             ≡ a ⨅ b ∵ b ≤ a
+                                             ≡ b
+                                             ≡ qed
+
+  le_refl <- lemma "a ≤ a" (\(Forall @"a" a) -> a ≤ a) [p idemp2]
+
+  le_trans <- calc "a ≤ b → b ≤ c → a ≤ c" (\(Forall a) (Forall b) (Forall c) -> a ≤ b .=> b ≤ c .=> a ≤ c) $
+                   \a b c -> [a ≤ b, b ≤ c] ⊢ a            ∵ a ≤ b
+                                            ≡ b ⨅ a        ∵ b ≤ c
+                                            ≡ (c ⨅ b) ⨅ a  ∵ assoc2
+                                            ≡ c ⨅ (b ⨅ a)  ∵ a ≤ b
+                                            ≡ (c ⨅ a)
+                                            ≡ qed
+
+  lt_iff_le_not_le <- lemma "a < b ↔ a ≤ b ∧ ¬b ≤ a"
+                            (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> (a < b) .<=> a ≤ b .&& sNot (b ≤ a))
+                            [p sh3]
+
+  le_sup_left  <- lemma "a ≤ a ⊔ b"
+                  (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ≤ a ⨆ b)
+                  [p commut1, p commut2, p absorb2]
+
+  le_sup_right <- lemma "b ≤ a ⊔ b"
+                  (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ≤ a ⨆ b)
+                  [p commut1, p commut2, p absorb2]
+
+  sup_le <- calc "a ≤ c → b ≤ c → a ⊔ b ≤ c"
+                 (\(Forall a) (Forall b) (Forall c) -> a ≤ c .=> b ≤ c .=> a ⨆ b ≤ c) $
+                 \a b c -> [a ≤ c, b ≤ c] ⊢ a ⨆ b             ∵ [a ≤ c, b ≤ c]
+                                          ≡ (c ⨅ a) ⨆ (c ⨅ b) ∵ distrib2
+                                          ≡ c ⨅ (a ⨆ b)
+                                          ≡ qed
+
+  inf_le_left  <- lemma "a ⊓ b ≤ a"
+                        (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨅ b ≤ a)
+                        [p assoc2,  p idemp2]
+
+  inf_le_right <- lemma "a ⊓ b ≤ b"
+                        (\(Forall @"a" (a :: SStroke)) (Forall @"b" b) -> a ⨅ b ≤ b)
+                        [p commut2, p inf_le_left]
+
+  le_inf <- calc "a ≤ b → a ≤ c → a ≤ b ⊓ c"
+                 (\(Forall a) (Forall b) (Forall c) -> a ≤ b .=> a ≤ c .=> a ≤ b ⨅ c) $
+                 \a b c -> [a ≤ b, a ≤ c] ⊢ a           ∵ a ≤ b
+                                          ≡ b ⨅ a       ∵ a ≤ c
+                                          ≡ b ⨅ (c ⨅ a) ∵ assoc2
+                                          ≡ (b ⨅ c ⨅ a)
+                                          ≡ qed
+
+  le_sup_inf <- lemma "(x ⊔ y) ⊓ (x ⊔ z) ≤ x ⊔ y ⊓ z"
+                      (\(Forall x) (Forall y) (Forall z) -> (x ⨆ y) ⨅ (x ⨆ z) ≤ x ⨆ y ⨅ z)
+                      [p distrib1, p le_refl]
+
+  inf_compl_le_bot <- lemma "x ⊓ xᶜ ≤ ⊥" (\(Forall x) -> x ⨅ ﬧ x ≤ ⲳ) [p compl2, p le_refl]
+  top_le_sup_compl <- lemma "⊤ ≤ x ⊔ xᶜ" (\(Forall x) -> т ≤ x ⨆ ﬧ x) [p compl1, p le_refl]
+
+  le_top <- calc "a ≤ ⊤" (\(Forall @"a" a) -> a ≤ т) $
+                 \a -> [] ⊢ a ≤ т
+                          ≡ a .== т ⨅ a ∵ commut2
+                          ≡ a .== a ⨅ т ∵ ident2
+                          ≡ a .== a
+                          ≡ qed
+
+  bot_le <- calc "⊥ ≤ a" (\(Forall @"a" a) -> ⲳ ≤ a) $
+                 \a -> [] ⊢ ⲳ ≤ a
+                          ≡ ⲳ .== a ⨅ ⲳ            ∵ bound2
+                          ≡ ⲳ .== (ⲳ :: SStroke)
+                          ≡ qed
+
+  sdiff_eq <- lemma "x \\ y = x ⊓ yᶜ" (\(Forall x) (Forall y) -> x \\ y .== x ⨅ ﬧ y) []
+  himp_eq  <- lemma "x ⇨ y = y ⊔ xᶜ"  (\(Forall x) (Forall y) -> x ⇨ y .== y ⨆ ﬧ x)  []
+
+  pure BooleanAlgebraProof {
+            le_refl          {- ∀ (a : α), a ≤ a                             -} = le_refl
+          , le_trans         {- ∀ (a b c : α), a ≤ b → b ≤ c → a ≤ c         -} = le_trans
+          , lt_iff_le_not_le {- (∀ (a b : α), a < b ↔ a ≤ b ∧ ¬b ≤ a)        -} = lt_iff_le_not_le
+          , le_antisymm      {- ∀ (a b : α), a ≤ b → b ≤ a → a = b           -} = le_antisymm
+          , le_sup_left      {- ∀ (a b : α), a ≤ a ⊔ b                       -} = le_sup_left
+          , le_sup_right     {- ∀ (a b : α), b ≤ a ⊔ b                       -} = le_sup_right
+          , sup_le           {- ∀ (a b c : α), a ≤ c → b ≤ c → a ⊔ b ≤ c     -} = sup_le
+          , inf_le_left      {- ∀ (a b : α), a ⊓ b ≤ a                       -} = inf_le_left
+          , inf_le_right     {- ∀ (a b : α), a ⊓ b ≤ b                       -} = inf_le_right
+          , le_inf           {- ∀ (a b c : α), a ≤ b → a ≤ c → a ≤ b ⊓ c     -} = le_inf
+          , le_sup_inf       {- ∀ (x y z : α), (x ⊔ y) ⊓ (x ⊔ z) ≤ x ⊔ y ⊓ z -} = le_sup_inf
+          , inf_compl_le_bot {- ∀ (x : α), x ⊓ xᶜ ≤ ⊥                        -} = inf_compl_le_bot
+          , top_le_sup_compl {- ∀ (x : α), ⊤ ≤ x ⊔ xᶜ                        -} = top_le_sup_compl
+          , le_top           {- ∀ (a : α), a ≤ ⊤                             -} = le_top
+          , bot_le           {- ∀ (a : α), ⊥ ≤ a                             -} = bot_le
+          , sdiff_eq         {- (∀ (x y : α), x \ y = x ⊓ yᶜ)                -} = sdiff_eq
+          , himp_eq          {- (∀ (x y : α), x ⇨ y = y ⊔ xᶜ)                -} = himp_eq
+       }
diff --git a/Documentation/SBV/Examples/TP/SortHelpers.hs b/Documentation/SBV/Examples/TP/SortHelpers.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/SortHelpers.hs
@@ -0,0 +1,195 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.SortHelpers
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Various definitions and lemmas that are useful for sorting related proofs.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.SortHelpers where
+
+import Prelude hiding (null, length, tail, elem, head, (++), take, drop)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+import Documentation.SBV.Examples.TP.Lists
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import Data.SBV.TP
+#endif
+
+-- | A predicate testing whether a given list is non-decreasing.
+nonDecreasing :: (OrdSymbolic (SBV a), SymVal a) => SList a -> SBool
+nonDecreasing = smtFunction "nonDecreasing"
+              $ \l -> [sCase| l of
+                         []  -> sTrue
+                         [_] -> sTrue
+                         x : rest@(y : _) -> x .<= y .&& nonDecreasing rest
+                      |]
+
+-- | Are two lists permutations of each other?
+isPermutation :: SymVal a => SList a -> SList a -> SBool
+isPermutation xs ys = quantifiedBool (\(Forall @"x" x) -> count x xs .== count x ys)
+
+-- | The tail of a non-decreasing list is non-decreasing. We have:
+--
+-- >>> runTP $ nonDecrTail @Integer
+-- Lemma: nonDecrTail    Q.E.D.
+-- Functions proven terminating: nonDecreasing
+-- [Proven] nonDecrTail :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+nonDecrTail :: forall a. (OrdSymbolic (SBV a), SymVal a) => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
+nonDecrTail = lemma "nonDecrTail"
+                    (\(Forall x) (Forall xs) -> nonDecreasing (x .: xs) .=> nonDecreasing xs)
+                    []
+
+-- | If we insert an element that is less than the head of a nonDecreasing list, it remains nondecreasing. We have:
+--
+-- >>> runTP $ nonDecrIns @Integer
+-- Lemma: nonDecrInsert    Q.E.D.
+-- Functions proven terminating: nonDecreasing
+-- [Proven] nonDecrInsert :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Bool
+nonDecrIns :: forall a. (OrdSymbolic (SBV a), SymVal a) => TP (Proof (Forall "x" a -> Forall "xs" [a] -> SBool))
+nonDecrIns = lemma "nonDecrInsert"
+                   (\(Forall x) (Forall xs) -> nonDecreasing xs .&& sNot (null xs) .&& x .<= head xs .=> nonDecreasing (x .: xs))
+                   []
+
+-- | Sublist relationship
+sublist :: SymVal a => SList a -> SList a -> SBool
+sublist xs ys = quantifiedBool (\(Forall @"e" e) -> count e xs .> 0 .=> count e ys .> 0)
+
+-- | 'sublist' correctness. We have:
+--
+-- >>> runTP $ sublistCorrect @Integer
+-- Inductive lemma: countNonNeg
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: countElem
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: elemCount
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                   Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: sublistCorrect
+--   Step: 1                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] sublistCorrect :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Ɐx ∷ Integer → Bool
+sublistCorrect :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> Forall "x" a -> SBool))
+sublistCorrect = do
+
+    cElem  <- countElem @a
+    eCount <- elemCount @a
+
+    calc "sublistCorrect"
+         (\(Forall xs) (Forall ys) (Forall x) -> xs `sublist` ys .&& x `elem` xs .=> x `elem` ys) $
+         \xs ys x -> [xs `sublist` ys, x `elem` xs]
+                  |- x `elem` ys
+                  ?? cElem  `at` (Inst @"xs" xs, Inst @"e" x)
+                  ?? eCount `at` (Inst @"xs" ys, Inst @"e" x)
+                  =: sTrue
+                  =: qed
+
+-- | If one list is a sublist of another, then its head is an elem. We have:
+--
+-- >>> runTP $ sublistElem @Integer
+-- Inductive lemma: countNonNeg
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: countElem
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                 Q.E.D.
+--     Step: 1.1.2                 Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Inductive lemma: elemCount
+--   Step: Base                    Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                   Q.E.D.
+--     Step: 1.2.1                 Q.E.D.
+--     Step: 1.2.2                 Q.E.D.
+--     Step: 1.Completeness        Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: sublistCorrect
+--   Step: 1                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: sublistElem
+--   Step: 1                       Q.E.D.
+--   Result:                       Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] sublistElem :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+sublistElem :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+sublistElem = do
+   slc <- sublistCorrect @a
+
+   calc "sublistElem"
+        (\(Forall x) (Forall xs) (Forall ys) -> (x .: xs) `sublist` ys .=> x `elem` ys) $
+        \x xs ys -> [(x .: xs) `sublist` ys]
+                 |- x `elem` ys
+                 ?? slc `at` (Inst @"xs" (x .: xs), Inst @"ys" ys, Inst @"x" x)
+                 =: sTrue
+                 =: qed
+
+-- | If one list is a sublist of another so is its tail. We have:
+--
+-- >>> runTP $ sublistTail @Integer
+-- Lemma: sublistTail    Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] sublistTail :: Ɐx ∷ Integer → Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+sublistTail :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "x" a -> Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+sublistTail =
+  lemma "sublistTail"
+        (\(Forall x) (Forall xs) (Forall ys) -> (x .: xs) `sublist` ys .=> xs `sublist` ys)
+        []
+
+-- | Permutation implies sublist. We have:
+--
+-- >>> runTP $ sublistIfPerm @Integer
+-- Lemma: sublistIfPerm    Q.E.D.
+-- Functions proven terminating: count
+-- [Proven] sublistIfPerm :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+sublistIfPerm :: forall a. (Eq a, SymVal a) => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+sublistIfPerm = lemma "sublistIfPerm"
+                      (\(Forall xs) (Forall ys) -> isPermutation xs ys .=> xs `sublist` ys)
+                      []
diff --git a/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs b/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Sqrt2IsIrrational.hs
@@ -0,0 +1,111 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Sqrt2IsIrrational
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Prove that square-root of 2 is irrational.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeAbstractions #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Sqrt2IsIrrational where
+
+import Prelude hiding (even, odd)
+
+import Data.SBV
+import Data.SBV.TP
+
+-- | Prove that square-root of @2@ is irrational. That is, we can never find @a@ and @b@ such that
+-- @sqrt 2 == a / b@ and @a@ and @b@ are co-prime.
+--
+-- In order not to deal with reals and square-roots, we prove the integer-only alternative:
+-- If @a^2 = 2b^2@, then @a@ and @b@ cannot be co-prime. We proceed by establishing the
+-- following helpers first:
+--
+--   (1) An odd number squared is odd: @odd x -> odd x^2@
+--   (2) An even number that is a perfect square must be the square of an even number: @even x^2 -> even x@.
+--   (3) If a number is even, then its square must be a multiple of 4: @even x .=> x*x % 4 == 0@.
+--
+--  Using these helpers, we can argue:
+--
+--   (4)  Start with the premise @a^2 = 2b^2@.
+--   (5)  Thus, @a^2@ must be even. (Since it equals @2b^2@ by (4).)
+--   (6)  Thus, @a@ must be even. (Using (2) and (5).)
+--   (7)  Thus, @a^2@ must be divisible by @4@. (Using (3) and (6). That is, @2b^2 == 4K@ for some @K@.)
+--   (8)  Thus, @b^2@ must be even. (Using (7), and @b^2 = 2K@.)
+--   (9)  Thus, @b@ must be even. (Using (2) and (8).)
+--   (10) Since @a@ and @b@ are both even, they cannot be co-prime. (Using (6) and (9).)
+--
+-- Note that our proof is mostly about the first 3 facts above, then z3 and TP fills in the rest.
+--
+-- We have:
+--
+-- >>> sqrt2IsIrrational
+-- Lemma: oddSquaredIsOdd
+--   Step: 1                       Q.E.D.
+--   Step: 2 (expand square)       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: squareEvenImpliesEven    Q.E.D.
+-- Lemma: evenSquaredIsMult4
+--   Step: 1                       Q.E.D.
+--   Step: 2 (expand square)       Q.E.D.
+--   Result:                       Q.E.D.
+-- Lemma: sqrt2IsIrrational        Q.E.D.
+-- [Proven] sqrt2IsIrrational :: Bool
+sqrt2IsIrrational :: IO (Proof SBool)
+sqrt2IsIrrational = runTP $ do
+    let even, odd :: SInteger -> SBool
+        even = (2 `sDivides`)
+        odd  = sNot . even
+
+        sq :: SInteger -> SInteger
+        sq x = x * x
+
+    -- Prove that an odd number squared gives you an odd number.
+    -- We need to help the solver by guiding it through how it can
+    -- be decomposed as @2k+1@.
+    --
+    -- Interestingly, the solver doesn't need the analogous theorem that even number
+    -- squared is even, possibly because the even/odd definition above is enough for
+    -- it to deduce that fact automatically.
+    oddSquaredIsOdd <- calc "oddSquaredIsOdd"
+                             (\(Forall @"a" a) -> odd a .=> odd (sq a)) $
+                             \a -> [odd a] |- sq a
+                                           =: let k = some "k" $ \_k -> a .== 2*_k + 1  -- Grab the witness that a is odd
+                                           in sq (2 * k + 1)
+                                           ?? "expand square"
+                                           =: 4*k*k + 4*k + 1
+                                           =: qed
+
+    -- Prove that if a perfect square is even, then it has to be the square of an even number. For z3, the above proof
+    -- is enough to establish this.
+    squareEvenImpliesEven <- lemma "squareEvenImpliesEven"
+                                   (\(Forall @"a" a) -> even (sq a) .=> even a)
+                                   [proofOf oddSquaredIsOdd]
+
+    -- Prove that if @a@ is an even number, then its square is four times the square of another.
+    evenSquaredIsMult4 <- calc "evenSquaredIsMult4"
+                               (\(Forall @"a" a) -> even a .=> 4 `sDivides` sq a) $
+                               \a -> [even a] |- sq a
+                                              =: let k = some "k" $ \_k -> a .== 2*_k -- Grab the witness that a is even
+                                              in sq (2 * k)
+                                              ?? "expand square"
+                                              =: 4*(k*k)
+                                              =: qed
+
+    -- Define what it means to be co-prime. Note that we use euclidian notion of modulus here
+    -- as z3 deals with that much better. Two numbers are co-prime if 1 is their only common divisor.
+    let coPrime :: SInteger -> SInteger -> SBool
+        coPrime x y = quantifiedBool (\(Forall z) -> (x `sEMod` z .== 0 .&& y `sEMod` z .== 0) .=> z .== 1)
+
+    -- Prove that square-root of 2 is irrational. We do this by showing for all pairs of integers @a@ and @b@
+    -- such that @a*a == 2*b*b@, it must be the case that @a@ and @b@ can not be co-prime:
+    lemma "sqrt2IsIrrational"
+          (quantifiedBool (\(Forall a) (Forall b) -> sq a .== 2 * sq b .=> sNot (coPrime a b)))
+          [proofOf squareEvenImpliesEven, proofOf evenSquaredIsMult4]
diff --git a/Documentation/SBV/Examples/TP/StrongInduction.hs b/Documentation/SBV/Examples/TP/StrongInduction.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/StrongInduction.hs
@@ -0,0 +1,336 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.StrongInduction
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Examples of strong induction.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.StrongInduction where
+
+import Prelude hiding (length, null, head, tail, reverse, (++), splitAt, sum)
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XScopedTypeVariables
+-- >>> import Control.Exception
+#endif
+
+-- * Numeric examples
+
+-- | Prove that the sequence @1@, @3@, @S_{k-2} + 2 S_{k-1}@ is always odd.
+--
+-- We have:
+--
+-- >>> oddSequence1
+-- Inductive lemma (strong): oddSequence1
+--   Step: Measure is non-negative           Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                             Q.E.D.
+--     Step: 1.2                             Q.E.D.
+--     Step: 1.3.1                           Q.E.D.
+--     Step: 1.3.2                           Q.E.D.
+--     Step: 1.3.3                           Q.E.D.
+--     Step: 1.Completeness                  Q.E.D.
+--   Result:                                 Q.E.D.
+-- Functions proven terminating: seq
+-- [Proven] oddSequence1 :: Ɐn ∷ Integer → Bool
+oddSequence1 :: IO (Proof (Forall "n" Integer -> SBool))
+oddSequence1 = runTP $ do
+  let s :: SInteger -> SInteger
+      s = smtFunction "seq"
+        $ \n -> [sCase| n of
+                   _ | n .<= 0 -> 1
+                   _ | n .== 1 -> 3
+                   _           -> s (n-2) + 2 * s (n-1)
+                |]
+
+  -- z3 can't handle this, but CVC5 is proves it just fine.
+  -- Note also that we do a "proof-by-contradiction," by deriving that
+  -- the negation of the goal leads to falsehood.
+  sInductWith cvc5 "oddSequence1"
+          (\(Forall n) -> n .>= 0 .=> sNot (2 `sDivides` s n))
+          (abs, []) $
+          \ih n -> [n .>= 0] |- 2 `sDivides` s n
+                             =: cases [ n .== 0 ==> contradiction
+                                      , n .== 1 ==> contradiction
+                                      , n .>= 2 ==> 2 `sDivides` (s (n-2) + 2 * s (n-1))
+                                                 =: 2 `sDivides` s (n-2)
+                                                 ?? ih `at` Inst @"n" (n - 2)
+                                                 =: contradiction
+                                      ]
+
+-- | Prove that the sequence @1@, @3@, @2 S_{k-1} - S_{k-2}@ generates sequence of odd numbers.
+--
+-- We have:
+--
+-- >>> oddSequence2
+-- Lemma: oddSequence_0                          Q.E.D.
+-- Lemma: oddSequence_1                          Q.E.D.
+-- Inductive lemma (strong): oddSequence_sNp2
+--   Step: Measure is non-negative               Q.E.D.
+--   Step: 1                                     Q.E.D.
+--   Step: 2                                     Q.E.D.
+--   Step: 3 (simplify)                          Q.E.D.
+--   Step: 4                                     Q.E.D.
+--   Step: 5 (simplify)                          Q.E.D.
+--   Step: 6                                     Q.E.D.
+--   Result:                                     Q.E.D.
+-- Lemma: oddSequence2
+--   Step: 1 (3 way case split)
+--     Step: 1.1                                 Q.E.D.
+--     Step: 1.2                                 Q.E.D.
+--     Step: 1.3.1                               Q.E.D.
+--     Step: 1.3.2                               Q.E.D.
+--     Step: 1.Completeness                      Q.E.D.
+--   Result:                                     Q.E.D.
+-- Functions proven terminating: seq
+-- [Proven] oddSequence2 :: Ɐn ∷ Integer → Bool
+oddSequence2 :: IO (Proof (Forall "n" Integer -> SBool))
+oddSequence2 = runTP $ do
+  let s :: SInteger -> SInteger
+      s = smtFunction "seq"
+        $ \n -> [sCase| n of
+                   _ | n .<= 0 -> 1
+                   _ | n .== 1 -> 3
+                   _           -> 2 * s (n-1) - s (n-2)
+                |]
+
+  s0 <- lemma "oddSequence_0" (s 0 .== 1) []
+  s1 <- lemma "oddSequence_1" (s 1 .== 3) []
+
+  sNp2 <- sInduct "oddSequence_sNp2"
+                  (\(Forall n) -> n .>= 2 .=> s n .== 2 * n + 1)
+                  (abs, []) $
+                  \ih n -> [n .>= 2] |- s n
+                                     =: 2 * s (n-1) - s (n-2)
+                                     ?? ih `at` Inst @"n" (n-1)
+                                     =: 2 * (2 * (n-1) + 1) - s (n-2)
+                                     ?? "simplify"
+                                     =: 4*n - 4 + 2 - s (n-2)
+                                     ?? ih `at` Inst @"n" (n-2)
+                                     =: 4*n - 2 - (2 * (n-2) + 1)
+                                     ?? "simplify"
+                                     =: 4*n - 2 - 2*n + 4 - 1
+                                     =: 2*n + 1
+                                     =: qed
+
+  calc "oddSequence2" (\(Forall n) -> n .>= 0 .=> s n .== 2 * n + 1) $
+                      \n -> [n .>= 0] |- s n
+                                      =: cases [ n .== 0 ==> trivial
+                                               , n .== 1 ==> trivial
+                                               , n .>= 2 ==> s n
+                                                          ?? s0
+                                                          ?? s1
+                                                          ?? sNp2 `at` Inst @"n" n
+                                                          =: 2 * n + 1
+                                                          =: qed
+                                               ]
+
+-- * Strong induction checks
+
+-- | For strong induction to work, We have to instantiate the proof at a "smaller" value. This
+-- example demonstrates what happens if we don't. We have:
+--
+-- >>> won'tProve1 `catch` (\(_ :: SomeException) -> pure ())
+-- Inductive lemma (strong): lengthGood
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1
+-- *** Failed to prove lengthGood.1.
+-- <BLANKLINE>
+-- *** Solver reported: canceled
+won'tProve1 :: IO ()
+won'tProve1 = runTP $ do
+   let len :: SList Integer -> SInteger
+       len = smtFunction "len"
+           $ \xs -> [sCase| xs of
+                       []     -> 0
+                       _ : as -> 1 + len as
+                    |]
+
+   -- Run it for 5 seconds, as otherwise z3 will hang as it can't prove make the inductive step
+   _ <- sInductWith z3{extraArgs = ["-t:5000"]} "lengthGood"
+                (\(Forall xs) -> len xs .== length xs)
+                (length, []) $
+                \ih xs -> [] |- len xs
+                             -- incorrectly instantiate the IH at xs!
+                             ?? ih `at` Inst @"xs" xs
+                             =: length xs
+                             =: qed
+   pure ()
+
+-- | Note that strong induction does not need an explicit base case, as the base-cases is folded into the
+-- inductive step. Here's an example demonstrating what happens when the failure is only at the base case.
+--
+-- >>> won'tProve2 `catch` (\(_ :: SomeException) -> pure ())
+-- Inductive lemma (strong): badLength
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1
+-- *** Failed to prove badLength.1.
+-- Falsifiable. Counter-example:
+--   xs = [] :: [Integer]
+won'tProve2 :: IO ()
+won'tProve2 = runTP $ do
+   let len :: SList Integer -> SInteger
+       len = smtFunction "badLength"
+           $ \xs -> [sCase| xs of
+                       []     -> 123
+                       _ : as -> 1 + len as
+                    |]
+
+   _ <- sInduct "badLength"
+                (\(Forall xs) -> len xs .== length xs)
+                (length, []) $
+                \ih xs -> [] |- len xs
+                             ?? ih `at` Inst @"xs" xs
+                             =: length xs
+                             =: qed
+   pure ()
+
+-- | The measure for strong induction should always produce a non-negative measure. The measure, in general, is an integer, or
+-- a tuple of integers, for tuples upto size 5. The ordering is lexicographic. This allows us to do proofs over 5-different arguments
+-- where their total measure goes down. If the measure can be negative, then we flag that as a failure, as demonstrated here. We have:
+--
+-- >>> won'tProve3 `catch` (\(_ :: SomeException) -> pure ())
+-- Inductive lemma (strong): badMeasure
+--   Step: Measure is non-negative
+-- *** Failed to prove badMeasure.Measure is non-negative.
+-- Falsifiable. Counter-example:
+--   x = -1 :: Integer
+won'tProve3 :: IO ()
+won'tProve3 = runTP $ do
+   _ <- sInduct "badMeasure"
+                (\(Forall @"x" (x :: SInteger)) -> x .== x)
+                (id, []) $
+                \_ih x -> [] |- x
+                             =: x
+                             =: qed
+
+
+   pure ()
+
+-- | The measure must always go down using lexicographic ordering. If not, SBV will flag this as a failure. We have:
+--
+-- >>> won'tProve4 `catch` (\(_ :: SomeException) -> pure ())
+-- Inductive lemma (strong): badMeasure
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2.1                         Q.E.D.
+--     Step: 1.2.2
+-- *** Failed to prove badMeasure.1.2.2.
+-- <BLANKLINE>
+-- *** Solver reported: canceled
+won'tProve4 :: IO ()
+won'tProve4 = runTP $ do
+
+   let -- a bizarre (but valid!) way to sum two integers
+       weirdSum :: SInteger -> SInteger -> SInteger
+       weirdSum = smtFunction "weirdSum"
+                $ \x y -> [sCase| x of
+                              _ | x .<= 0 -> y
+                              _           -> weirdSum (x - 1) (y + 1)
+                           |]
+
+   _ <- sInductWith z3{extraArgs = ["-t:5000"]} "badMeasure"
+                (\(Forall x) (Forall y) -> x .>= 0 .=> weirdSum x y .== x + y)
+                -- This measure is not good, since it remains the same. Note that we do not get a
+                -- failure, but the proof will never converge either; so we put a time bound
+                (\x y -> abs x + abs y, []) $
+                \ih x y -> [x .>= 0] |- ite (x .<= 0) y (weirdSum (x - 1) (y + 1))
+                                     =: cases [ x .<= 0 ==> trivial
+                                              , x .>  0 ==> weirdSum (x - 1) (y + 1)
+                                                         ?? ih `at` (Inst @"x" (x - 1), Inst @"y" (y + 1))
+                                                         =: x - 1 + y + 1
+                                                         =: x + y
+                                                         =: qed
+                                              ]
+
+   pure ()
+
+-- * Summing via halving
+
+-- | We prove that summing a list can be done by halving the list, summing parts, and adding the results. The proof uses
+-- strong induction. We have:
+--
+-- >>> sumHalves
+-- Inductive lemma: sumAppend
+--   Step: Base                           Q.E.D.
+--   Step: 1                              Q.E.D.
+--   Step: 2                              Q.E.D.
+--   Step: 3                              Q.E.D.
+--   Result:                              Q.E.D.
+-- Inductive lemma (strong): sumHalves
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (3 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2                          Q.E.D.
+--     Step: 1.3.1                        Q.E.D.
+--     Step: 1.3.2                        Q.E.D.
+--     Step: 1.3.3                        Q.E.D.
+--     Step: 1.3.4                        Q.E.D.
+--     Step: 1.3.5                        Q.E.D.
+--     Step: 1.3.6 (simplify)             Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Functions proven terminating: halvingSum, sbv.foldr
+-- [Proven] sumHalves :: Ɐxs ∷ [Integer] → Bool
+sumHalves :: IO (Proof (Forall "xs" [Integer] -> SBool))
+sumHalves = runTP $ do
+
+    let halvingSum :: SList Integer -> SInteger
+        halvingSum = smtFunction "halvingSum"
+                   $ \xs -> [sCase| xs of
+                                []  -> sum xs
+                                [_] -> sum xs
+                                _   -> let (f, s) = splitAt (length xs `sDiv` 2) xs
+                                       in halvingSum f + halvingSum s
+                            |]
+
+    helper <- induct "sumAppend"
+                     (\(Forall xs) (Forall ys) -> sum (xs ++ ys) .== sum xs + sum ys) $
+                     \ih (x, xs) ys -> [] |- sum (x .: xs ++ ys)
+                                          =: x + sum (xs ++ ys)
+                                          ?? ih
+                                          =: x + sum xs + sum ys
+                                          =: sum (x .: xs) + sum ys
+                                          =: qed
+
+    -- Use strong induction to prove the theorem. CVC5 solves this with ease, but z3 struggles.
+    sInductWith cvc5 "sumHalves"
+      (\(Forall xs) -> halvingSum xs .== sum xs)
+      (length, []) $
+      \ih xs -> [] |- halvingSum xs
+                   =: [pCase| xs of
+                        []                -> qed
+                        [_]               -> qed
+                        whole@(_ : _ : _) ->
+                             halvingSum whole
+                          =: let (f, s) = splitAt (length whole `sDiv` 2) whole
+                          in halvingSum f + halvingSum s
+                          ?? ih `at` Inst @"xs" f
+                          =: sum f + halvingSum s
+                          ?? ih `at` Inst @"xs" s
+                          =: sum f + sum s
+                          ?? helper `at` (Inst @"xs" f, Inst @"ys" s)
+                          =: sum (f ++ s)
+                          ?? "simplify"
+                          =: sum whole
+                          =: qed
+                      |]
diff --git a/Documentation/SBV/Examples/TP/SumReverse.hs b/Documentation/SBV/Examples/TP/SumReverse.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/SumReverse.hs
@@ -0,0 +1,85 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.SumReverse
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves @sum (reverse xs) == sum xs@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE OverloadedLists     #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.SumReverse where
+
+import Prelude hiding ((++), foldr, sum, reverse)
+
+import Data.SBV
+import Data.SBV.TP
+import Data.SBV.List
+
+
+#ifdef DOCTEST
+-- $setup
+-- >>> :set -XFlexibleContexts
+-- >>> :set -XTypeApplications
+#endif
+
+-- | @sum (reverse xs) = sum xs@
+--
+-- >>> revSum @Integer
+-- Inductive lemma: sumAppend
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4 (associativity)      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Inductive lemma: sumReverse
+--   Step: Base                   Q.E.D.
+--   Step: 1                      Q.E.D.
+--   Step: 2                      Q.E.D.
+--   Step: 3                      Q.E.D.
+--   Step: 4 (commutativity)      Q.E.D.
+--   Step: 5                      Q.E.D.
+--   Result:                      Q.E.D.
+-- Functions proven terminating: sbv.foldr, sbv.reverse
+-- [Proven] sumReverse :: Ɐxs ∷ [Integer] → Bool
+revSum :: forall a. (SymVal a, Num (SBV a)) => IO (Proof (Forall "xs" [a] -> SBool))
+revSum = runTP $ do
+
+  -- helper: sum distributes over append.
+  sumAppend <- induct "sumAppend"
+                      (\(Forall xs) (Forall ys) -> sum (xs ++ ys) .== sum xs + sum ys) $
+                      \ih (x, xs) ys -> [] |- sum ((x .: xs) ++ ys)
+                                           =: sum (x .: (xs ++ ys))
+                                           =: x + sum (xs ++ ys)
+                                           ?? ih
+                                           =: x + (sum xs + sum ys)
+                                           ?? "associativity"
+                                           =: (x + sum xs) + sum ys
+                                           =: sum (x .: xs) + sum ys
+                                           =: qed
+
+  -- Now prove the original theorem by induction
+  induct "sumReverse"
+         (\(Forall xs) -> sum (reverse xs) .== sum xs) $
+         \ih (x, xs) -> [] |- sum (reverse (x .: xs))
+                           =: sum (reverse xs ++ [x])
+                           ?? sumAppend `at` (Inst @"xs" (reverse xs), Inst @"ys" [x])
+                           =: sum (reverse xs) + sum [x]
+                           ?? ih
+                           =: sum xs + x
+                           ?? "commutativity"
+                           =: x + sum xs
+                           =: sum (x .: xs)
+                           =: qed
diff --git a/Documentation/SBV/Examples/TP/Tao.hs b/Documentation/SBV/Examples/TP/Tao.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/Tao.hs
@@ -0,0 +1,58 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.Tao
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A question posed by Terrence Tao: <https://mathstodon.xyz/@tao/110736805384878353>.
+-- Essentially, for an arbitrary binary operation op, we prove that
+--
+-- @
+--    (x op x) op y == y op x
+-- @
+--
+-- Implies @op@ must be commutative.
+-----------------------------------------------------------------------------
+
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.Tao where
+
+import Data.SBV
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> :set -XTypeApplications
+#endif
+
+-- | Create an uninterpreted type to do the proofs over.
+data T
+mkSymbolic [''T]
+
+-- | Prove that:
+--
+--  @
+--    (x op x) op y == y op x
+--  @
+--
+--  means that @op@ is commutative.
+--
+-- We have:
+--
+-- >>> tao @T (uninterpret "op")
+-- Lemma: tao          Q.E.D.
+-- [Proven] tao :: Bool
+tao :: forall a. SymVal a => (SBV a -> SBV a -> SBV a) -> IO (Proof SBool)
+tao op = runTP $
+   lemma "tao" (    quantifiedBool (\(Forall x) (Forall y) -> ((x `op` x) `op` y) .== y `op` x)
+                .=> quantifiedBool (\(Forall x) (Forall y) -> (x `op` y) .== (y `op` x)))
+               []
diff --git a/Documentation/SBV/Examples/TP/TautologyChecker.hs b/Documentation/SBV/Examples/TP/TautologyChecker.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/TautologyChecker.hs
@@ -0,0 +1,1124 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.TautologyChecker
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A verified tautology checker (unordered BDD-style SAT solver) in SBV.
+-- This is a port of the Imandra proof by Grant Passmore, originally
+-- inspired by Boyer-Moore '79.
+-- See <https://raw.githubusercontent.com/imandra-ai/imandrax-examples/refs/heads/main/src/tautology.iml>
+--
+-- We define a simple formula type with If-then-else, normalize formulas into a canonical form, and prove
+-- both soundness and completeness of the tautology checker. The canonical form is essentially an
+-- unordered-BDD, making it easy to evaluate it.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE OverloadedLists   #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.TautologyChecker where
+
+import Prelude hiding (null, tail, head, (++))
+
+import Data.SBV
+import Data.SBV.List
+import Data.SBV.TP
+import Data.SBV.Tuple
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.TP
+#endif
+
+-- * Formula representation
+
+-- | A propositional formula with variables and if-then-else.
+data Formula = FTrue
+             | FFalse
+             | Var { fVar   :: Integer }
+             | If  { ifCond :: Formula
+                   , ifThen :: Formula
+                   , ifElse :: Formula
+                   }
+
+-- | Make formulas symbolic.
+mkSymbolic [''Formula]
+
+-- * Measuring formulas
+
+-- | Depth of nested If constructors in the condition position.
+ifDepth :: SFormula -> SInteger
+ifDepth = smtFunction "ifDepth"
+        $ \f -> [sCase| f of
+                   If c _ _ -> 1 + ifDepth c
+                   _        -> 0
+                |]
+
+-- | \(\mathit{ifDepth}(f) \geq 0\)
+--
+-- >>> runTP ifDepthNonNeg
+-- Lemma: ifDepthNonNeg    Q.E.D.
+-- Functions proven terminating: ifDepth
+-- [Proven] ifDepthNonNeg :: Ɐf ∷ Formula → Bool
+ifDepthNonNeg :: TP (Proof (Forall "f" Formula -> SBool))
+ifDepthNonNeg = inductiveLemma "ifDepthNonNeg" (\(Forall f) -> ifDepth f .>= 0) []
+
+-- | Complexity of a formula (for termination measure).
+ifComplexity :: SFormula -> SInteger
+ifComplexity = smtFunction "ifComplexity"
+             $ \f -> [sCase| f of
+                        If c l r -> ifComplexity c * (ifComplexity l + ifComplexity r)
+                        _        -> 1
+                     |]
+
+-- | \(\mathit{ifComplexity}(f) > 0\)
+--
+-- >>> runTP ifComplexityPos
+-- Lemma: ifComplexityPos    Q.E.D.
+-- Functions proven terminating: ifComplexity
+-- [Proven] ifComplexityPos :: Ɐf ∷ Formula → Bool
+ifComplexityPos :: TP (Proof (Forall "f" Formula -> SBool))
+ifComplexityPos = inductiveLemma "ifComplexityPos" (\(Forall f) -> ifComplexity f .> 0) []
+
+-- | The branches of an If have smaller complexity than the whole.
+--
+-- \(\mathit{ifComplexity}(c) < \mathit{ifComplexity}(\mathit{If}(c, l, r)) \land \mathit{ifComplexity}(l) < \mathit{ifComplexity}(\mathit{If}(c, l, r)) \land \mathit{ifComplexity}(r) < \mathit{ifComplexity}(\mathit{If}(c, l, r))\)
+--
+-- >>> runTP ifComplexitySmaller
+-- Lemma: ifComplexityPos        Q.E.D.
+-- Lemma: ifComplexitySmaller
+--   Step: 1                     Q.E.D.
+--   Result:                     Q.E.D.
+-- Functions proven terminating: ifComplexity
+-- [Proven] ifComplexitySmaller :: Ɐc ∷ Formula → Ɐl ∷ Formula → Ɐr ∷ Formula → Bool
+ifComplexitySmaller :: TP (Proof (Forall "c" Formula -> Forall "l" Formula -> Forall "r" Formula -> SBool))
+ifComplexitySmaller = do
+  icp <- recall ifComplexityPos
+
+  calc "ifComplexitySmaller"
+       (\(Forall c) (Forall l) (Forall r) ->
+          let ic = ifComplexity (sIf c l r)
+          in ifComplexity c .< ic .&& ifComplexity l .< ic .&& ifComplexity r .< ic) $
+       \c l r ->
+         let ic = ifComplexity (sIf c l r)
+             cc = ifComplexity c
+             cl = ifComplexity l
+             cr = ifComplexity r
+         in [] |- cc .< ic .&& cl .< ic .&& cr .< ic
+               ?? icp `at` Inst @"f" c
+               ?? icp `at` Inst @"f" l
+               ?? icp `at` Inst @"f" r
+               =: sTrue
+               =: qed
+
+-- * Normalization
+
+-- | Check if a formula is in normal form (no nested If in condition position).
+isNormal :: SFormula -> SBool
+isNormal = smtFunction "isNormal"
+         $ \f -> [sCase| f of
+                    If c p q  -> sNot (isIf c) .&& isNormal p .&& isNormal q
+                    _         -> sTrue
+                 |]
+
+-- | Normalize a formula by eliminating nested Ifs in condition position.
+--
+-- The key transformation is:
+--
+-- @
+--   If (If (p, q, r), left, right)
+--     =
+--   If (p, If (q, left, right), If (r, left, right))
+-- @
+--
+-- Note that this transformation increases the size of the formula, but reduces its complexity.
+normalize :: SFormula -> SFormula
+normalize = smtFunctionWithMeasure "normalize"
+                                   ( \f -> tuple (ifComplexity f, ifDepth f)
+                                   , [ measureLemma        ifDepthNonNeg
+                                     , measureLemma        ifComplexityPos
+                                     , measureLemmaWith z3 ifComplexitySmaller
+                                     , measureLemmaWith z3 normalizePreservesComplexity
+                                     ]
+                                   )
+          $ \f -> [sCase| f of
+                     If (If p q r) left right -> normalize (sIf p (sIf q left right) (sIf r left right))
+                     If c          left right -> sIf c (normalize left) (normalize right)
+                     _                        -> f
+                  |]
+
+-- | The normalization transformation preserves complexity.
+--
+-- \(\mathit{ifComplexity}(\mathit{If}(p, \mathit{If}(q, l, r), \mathit{If}(s, l, r))) = \mathit{ifComplexity}(\mathit{If}(\mathit{If}(p, q, s), l, r))\)
+--
+-- >>> runTP normalizePreservesComplexity
+-- Lemma: helper                          Q.E.D.
+-- Lemma: normalizePreservesComplexity
+--   Step: 1                              Q.E.D.
+--   Step: 2                              Q.E.D.
+--   Step: 3                              Q.E.D.
+--   Step: 4                              Q.E.D.
+--   Step: 5                              Q.E.D.
+--   Step: 6                              Q.E.D.
+--   Step: 7                              Q.E.D.
+--   Result:                              Q.E.D.
+-- Functions proven terminating: ifComplexity
+-- [Proven] normalizePreservesComplexity :: Ɐp ∷ Formula → Ɐq ∷ Formula → Ɐs ∷ Formula → Ɐl ∷ Formula → Ɐr ∷ Formula → Bool
+normalizePreservesComplexity :: TP (Proof (Forall "p" Formula -> Forall "q" Formula -> Forall "s" Formula -> Forall "l" Formula -> Forall "r" Formula -> SBool))
+normalizePreservesComplexity = do
+
+  -- The following is a trivial lemma, but without it the solver don't seem to be able to make progress since
+  -- it needs to instantiate it properly. So we help the solver out explicitly.
+  helper <- lemma "helper"
+                  (\(Forall @"a" a) (Forall @"b" b) (Forall @"c" c) -> a .== b .=> a * c .== b * (c :: SInteger))
+                  []
+
+  calc "normalizePreservesComplexity"
+       (\(Forall p) (Forall q) (Forall s) (Forall l) (Forall r) ->
+          ifComplexity (sIf p (sIf q l r) (sIf s l r)) .== ifComplexity (sIf (sIf p q s) l r)) $
+       \p q s l r ->
+         let cp = ifComplexity p
+             cq = ifComplexity q
+             cs = ifComplexity s
+             cl = ifComplexity l
+             cr = ifComplexity r
+         in [] |- ifComplexity (sIf p (sIf q l r) (sIf s l r))
+               =: cp * (ifComplexity (sIf q l r) + ifComplexity (sIf s l r))
+               =: cp * (cq * (cl + cr) + cs * (cl + cr))
+               =: cp * ((cq + cs) * (cl + cr))
+               =: (cp * (cq + cs)) * (cl + cr)
+               ?? helper `at` (Inst @"a" (ifComplexity (sIf p q s)), Inst @"b" (cp * (cq + cs)), Inst @"c" (cl + cr))
+               =: ifComplexity (sIf p q s) * (cl + cr)
+               =: ifComplexity (sIf p q s) * (ifComplexity l + ifComplexity r)
+               =: ifComplexity (sIf (sIf p q s) l r)
+               =: qed
+
+-- * Variable bindings
+
+-- | A binding associates a variable ID with a boolean value.
+data Binding = Binding { varId :: Integer
+                       , value :: Bool
+                       }
+
+-- | Make bindings symbolic.
+mkSymbolic [''Binding]
+
+-- | Look up a variable in the binding list. If it's not in the list, then it's false.
+lookUp :: SInteger -> SList Binding -> SBool
+lookUp = smtFunction "lookUp"
+       $ \vid bs -> [sCase| bs of
+                       []                                    -> sFalse
+                       Binding bId bVal : rest | vid .== bId -> bVal
+                                               | True        -> lookUp vid rest
+                    |]
+
+-- | Check if a variable is assigned in the bindings.
+isAssigned :: SInteger -> SList Binding -> SBool
+isAssigned = smtFunction "isAssigned"
+           $ \vid bs -> [sCase| bs of
+                           []                                -> sFalse
+                           Binding bId _ : rst | bId .== vid -> sTrue
+                                               | True        -> isAssigned vid rst
+                        |]
+
+-- | Add a binding assuming the variable is true.
+assumeTrue :: SInteger -> SList Binding -> SList Binding
+assumeTrue vid bs = sBinding vid sTrue .: bs
+
+-- | Add a binding assuming the variable is false.
+assumeFalse :: SInteger -> SList Binding -> SList Binding
+assumeFalse vid bs = sBinding vid sFalse .: bs
+
+-- | Adding a binding preserves existing assignments.
+--
+-- >>> runTP isAssignedExtends
+-- Lemma: isAssignedExtends    Q.E.D.
+-- Functions proven terminating: isAssigned
+-- [Proven] isAssignedExtends :: Ɐi ∷ Integer → Ɐn ∷ Integer → Ɐv ∷ Bool → Ɐbs ∷ [Binding] → Bool
+isAssignedExtends :: TP (Proof (Forall "i" Integer -> Forall "n" Integer -> Forall "v" Bool -> Forall "bs" [Binding] -> SBool))
+isAssignedExtends = lemma "isAssignedExtends"
+                          (\(Forall i) (Forall n) (Forall v) (Forall bs) -> isAssigned i bs .=> isAssigned i (sBinding n v .: bs))
+                          []
+
+-- | Looking up a variable in extended bindings: if already assigned, value is preserved.
+--
+-- >>> runTP lookUpExtends
+-- Lemma: lookUpExtends    Q.E.D.
+-- Functions proven terminating: isAssigned, lookUp
+-- [Proven] lookUpExtends :: Ɐi ∷ Integer → Ɐn ∷ Integer → Ɐv ∷ Bool → Ɐbs ∷ [Binding] → Bool
+lookUpExtends :: TP (Proof (Forall "i" Integer -> Forall "n" Integer -> Forall "v" Bool -> Forall "bs" [Binding] -> SBool))
+lookUpExtends = lemma "lookUpExtends"
+                      (\(Forall i) (Forall n) (Forall v) (Forall bs) ->
+                                isAssigned i bs .&& i ./= n .=> lookUp i (sBinding n v .: bs) .== lookUp i bs)
+                      []
+
+-- | Looking up a variable that was just added returns the added value.
+--
+-- >>> runTP lookUpSame
+-- Lemma: lookUpSame    Q.E.D.
+-- Functions proven terminating: lookUp
+-- [Proven] lookUpSame :: Ɐn ∷ Integer → Ɐv ∷ Bool → Ɐbs ∷ [Binding] → Bool
+lookUpSame :: TP (Proof (Forall "n" Integer -> Forall "v" Bool -> Forall "bs" [Binding] -> SBool))
+lookUpSame = lemma "lookUpSame" (\(Forall n) (Forall v) (Forall bs) -> lookUp n (sBinding n v .: bs) .== v) []
+
+-- | Adding a binding for a variable makes it assigned.
+--
+-- >>> runTP isAssignedSame
+-- Lemma: isAssignedSame    Q.E.D.
+-- Functions proven terminating: isAssigned
+-- [Proven] isAssignedSame :: Ɐn ∷ Integer → Ɐv ∷ Bool → Ɐbs ∷ [Binding] → Bool
+isAssignedSame :: TP (Proof (Forall "n" Integer -> Forall "v" Bool -> Forall "bs" [Binding] -> SBool))
+isAssignedSame = lemma "isAssignedSame" (\(Forall n) (Forall v) (Forall bs) -> isAssigned n (sBinding n v .: bs)) []
+
+-- * Formula evaluation
+
+-- | Evaluate a formula under a binding environment.
+eval :: SFormula -> SList Binding -> SBool
+eval = smtFunction "eval"
+     $ \f bs -> [sCase| f of
+                   Var n    -> lookUp n bs
+                   If c l r | eval c bs -> eval l bs
+                            | True      -> eval r bs
+                   FTrue    -> sTrue
+                   FFalse   -> sFalse
+                |]
+
+-- * Tautology checking
+
+-- | Check if a normalized formula is a tautology.
+isTautology' :: SFormula -> SList Binding -> SBool
+isTautology' = smtFunction "isTautology'" $ \f bs ->
+  [sCase| f of
+    -- Trivial cases
+    FTrue          -> sTrue
+    FFalse         -> sFalse
+
+    -- Variable
+    Var _          -> eval f bs
+
+    -- Constant branches
+    If FTrue  l _  -> isTautology' l bs
+    If FFalse _ r  -> isTautology' r bs
+
+    -- Branching on a variable
+    If (Var n) l r
+      -- We have already this variable, so evaluate based on the current choice
+      | isAssigned n bs, eval (sVar n) bs -> isTautology' l bs
+      | isAssigned n bs                   -> isTautology' r bs
+
+      -- We haven't yet assigned this variable. Both branches should work out:
+      | True             ->     isTautology' l (assumeTrue  n bs)
+                            .&& isTautology' r (assumeFalse n bs)
+
+    If _ _ _ -> sFalse  -- Contradicts isNormal assumption
+  |]
+
+-- | Main tautology checker.
+isTautology :: SFormula -> SBool
+isTautology f = isTautology' (normalize f) []
+
+-- * Soundness
+
+-- | \(\mathit{lookUp}(x, a \mathbin{+\!\!+} b) = \mathit{if } \mathit{isAssigned}(x, a) \mathit{ then } \mathit{lookUp}(x, a) \mathit{ else } \mathit{lookUp}(x, b)\)
+--
+-- If we look up a variable in a concatenated binding list, we first check
+-- the first list, and only if not found there, check the second.
+--
+-- >>> runTP lookUpStable
+-- Inductive lemma: lookUpStable
+--   Step: Base                     Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1.1                  Q.E.D.
+--     Step: 1.1.2                  Q.E.D.
+--     Step: 1.2.1                  Q.E.D.
+--     Step: 1.2.2                  Q.E.D.
+--     Step: 1.Completeness         Q.E.D.
+--   Result:                        Q.E.D.
+-- Functions proven terminating: isAssigned, lookUp
+-- [Proven] lookUpStable :: Ɐa ∷ [Binding] → Ɐx ∷ Integer → Ɐb ∷ [Binding] → Bool
+lookUpStable :: TP (Proof (Forall "a" [Binding] -> Forall "x" Integer -> Forall "b" [Binding] -> SBool))
+lookUpStable =
+  induct "lookUpStable"
+         (\(Forall a) (Forall x) (Forall b) -> lookUp x (a ++ b) .== ite (isAssigned x a) (lookUp x a) (lookUp x b)) $
+         \ih (binding, a) x b ->
+           let vid = svarId binding
+               val = svalue binding
+           in [] |- lookUp x ((binding .: a) ++ b)
+                 =: cases [ vid .== x ==> ite (isAssigned x (binding .: a)) (lookUp x (binding .: a)) (lookUp x b)
+                                       =: val
+                                       =: qed
+                          , vid ./= x ==> lookUp x (a ++ b)
+                                       ?? ih
+                                       =: ite (isAssigned x a) (lookUp x a) (lookUp x b)
+                                       =: qed
+                          ]
+
+-- | \(\mathit{lookUp}(x, a) \implies \mathit{isAssigned}(x, a)\)
+--
+-- >>> runTP trueIsAssigned
+-- Inductive lemma: trueIsAssigned
+--   Step: Base                       Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                      Q.E.D.
+--     Step: 1.2.1                    Q.E.D.
+--     Step: 1.2.2                    Q.E.D.
+--     Step: 1.Completeness           Q.E.D.
+--   Result:                          Q.E.D.
+-- Functions proven terminating: isAssigned, lookUp
+-- [Proven] trueIsAssigned :: Ɐa ∷ [Binding] → Ɐx ∷ Integer → Bool
+trueIsAssigned :: TP (Proof (Forall "a" [Binding] -> Forall "x" Integer -> SBool))
+trueIsAssigned =
+  induct "trueIsAssigned"
+         (\(Forall a) (Forall x) -> lookUp x a .=> isAssigned x a) $
+         \ih (binding, a) x ->
+           let vid = [sCase| binding of Binding v _ -> v|]
+           in [lookUp x (binding .: a)]
+           |- isAssigned x (binding .: a)
+           =: cases [ vid .== x ==> trivial
+                    , vid ./= x ==> isAssigned x a
+                                 ?? ih
+                                 =: sTrue
+                                 =: qed
+                    ]
+
+-- | \(\mathit{value} = \mathit{lookUp}(x, bs) \implies \mathit{eval}(f, \{x \mapsto \mathit{value}\} :: bs) = \mathit{eval}(f, bs)\)
+--
+-- If we add a redundant binding (same id and value) to the front, evaluation doesn't change.
+--
+-- >>> runTPWith cvc5 evalStable
+-- Lemma: ifComplexityPos                  Q.E.D.
+-- Lemma: ifComplexitySmaller              Q.E.D.
+-- Inductive lemma (strong): evalStable
+--   Step: Measure is non-negative         Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                           Q.E.D.
+--     Step: 1.2                           Q.E.D.
+--     Step: 1.3                           Q.E.D.
+--     Step: 1.4.1                         Q.E.D.
+--     Step: 1.4.2                         Q.E.D.
+--     Step: 1.4.3                         Q.E.D.
+--     Step: 1.4.4                         Q.E.D.
+--     Step: 1.4.5                         Q.E.D.
+--     Step: 1.4.6                         Q.E.D.
+--     Step: 1.Completeness                Q.E.D.
+--   Result:                               Q.E.D.
+-- Functions proven terminating: eval, ifComplexity, lookUp
+-- [Proven] evalStable :: Ɐf ∷ Formula → Ɐx ∷ Integer → Ɐv ∷ Bool → Ɐbs ∷ [Binding] → Bool
+evalStable :: TP (Proof (Forall "f" Formula -> Forall "x" Integer -> Forall "v" Bool -> Forall "bs" [Binding] -> SBool))
+evalStable = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+
+  sInduct "evalStable"
+          (\(Forall f) (Forall x) (Forall v) (Forall bs) -> v .== lookUp x bs .=> eval f (sBinding x v .: bs) .== eval f bs)
+          (\f _ _ _ -> ifComplexity f, [proofOf icp]) $
+          \ih f x v bs ->
+               let b = sBinding x v
+               in [v .== lookUp x bs]
+               |- cases [ isFTrue  f ==> trivial
+                        , isFFalse f ==> trivial
+                        , isVar    f ==> trivial
+                        , isIf     f ==>
+                            let c = sifCond f
+                                l = sifThen f
+                                r = sifElse f
+                            in eval f (b .: bs)
+                            =: eval (sIf c l r) (b .: bs)
+                            =: ite (eval c (b .: bs)) (eval l (b .: bs)) (eval r (b .: bs))
+                            ?? ih  `at` (Inst @"f" c, Inst @"x" x, Inst @"v" v, Inst @"bs" bs)
+                            ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                            =: ite (eval c bs) (eval l (b .: bs)) (eval r (b .: bs))
+                            ?? ih  `at` (Inst @"f" l, Inst @"x" x, Inst @"v" v, Inst @"bs" bs)
+                            ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                            =: ite (eval c bs) (eval l bs) (eval r (b .: bs))
+                            ?? ih  `at` (Inst @"f" r, Inst @"x" x, Inst @"v" v, Inst @"bs" bs)
+                            ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                            =: ite (eval c bs) (eval l bs) (eval r bs)
+                            =: eval (sIf c l r) bs
+                            =: qed
+                        ]
+
+-- | Key soundness lemma: If a normalized formula is a tautology under bindings @b@,
+-- then it evaluates to true under @b ++ a@ for any @a@.
+--
+-- >>> runTPWith cvc5 tautologyImpliesEval
+-- Lemma: ifComplexityPos                            Q.E.D.
+-- Lemma: ifComplexitySmaller                        Q.E.D.
+-- Lemma: lookUpStable                               Q.E.D.
+-- Lemma: trueIsAssigned                             Q.E.D.
+-- Lemma: evalStable                                 Q.E.D.
+-- Inductive lemma (strong): tautologyImpliesEval
+--   Step: Measure is non-negative                   Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                                     Q.E.D.
+--     Step: 1.2                                     Q.E.D.
+--     Step: 1.3.1                                   Q.E.D.
+--     Step: 1.3.2                                   Q.E.D.
+--     Step: 1.3.3                                   Q.E.D.
+--     Step: 1.3.4                                   Q.E.D.
+--     Step: 1.3.5                                   Q.E.D.
+--     Step: 1.4 (4 way case split)
+--       Step: 1.4.1.1                               Q.E.D.
+--       Step: 1.4.1.2                               Q.E.D.
+--       Step: 1.4.2.1                               Q.E.D.
+--       Step: 1.4.2.2                               Q.E.D.
+--       Step: 1.4.2.3                               Q.E.D.
+--       Step: 1.4.3 (2 way case split)
+--         Step: 1.4.3.1.1                           Q.E.D.
+--         Step: 1.4.3.1.2                           Q.E.D.
+--         Step: 1.4.3.1.3                           Q.E.D.
+--         Step: 1.4.3.1.4                           Q.E.D.
+--         Step: 1.4.3.2 (2 way case split)
+--           Step: 1.4.3.2.1.1                       Q.E.D.
+--           Step: 1.4.3.2.1.2                       Q.E.D.
+--           Step: 1.4.3.2.1.3                       Q.E.D.
+--           Step: 1.4.3.2.1.4                       Q.E.D.
+--           Step: 1.4.3.2.1.5                       Q.E.D.
+--           Step: 1.4.3.2.1.6                       Q.E.D.
+--           Step: 1.4.3.2.1.7                       Q.E.D.
+--           Step: 1.4.3.2.1.8                       Q.E.D.
+--           Step: 1.4.3.2.2.1                       Q.E.D.
+--           Step: 1.4.3.2.2.2                       Q.E.D.
+--           Step: 1.4.3.2.2.3                       Q.E.D.
+--           Step: 1.4.3.2.2.4                       Q.E.D.
+--           Step: 1.4.3.2.2.5                       Q.E.D.
+--           Step: 1.4.3.2.2.6                       Q.E.D.
+--           Step: 1.4.3.2.2.7                       Q.E.D.
+--           Step: 1.4.3.2.2.8                       Q.E.D.
+--           Step: 1.4.3.2.Completeness              Q.E.D.
+--         Step: 1.4.3.Completeness                  Q.E.D.
+--       Step: 1.4.4                                 Q.E.D.
+--       Step: 1.4.Completeness                      Q.E.D.
+--     Step: 1.Completeness                          Q.E.D.
+--   Result:                                         Q.E.D.
+-- Functions proven terminating: eval, ifComplexity, isAssigned, isNormal, isTautology', lookUp
+-- [Proven] tautologyImpliesEval :: Ɐf ∷ Formula → Ɐa ∷ [Binding] → Ɐb ∷ [Binding] → Bool
+tautologyImpliesEval :: TP (Proof (Forall "f" Formula -> Forall "a" [Binding] -> Forall "b" [Binding] -> SBool))
+tautologyImpliesEval = do
+
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+  lus <- recall lookUpStable
+  tia <- recall trueIsAssigned
+  evs <- recall evalStable
+
+  sInduct "tautologyImpliesEval"
+          (\(Forall f) (Forall a) (Forall b) -> isNormal f .&& isTautology' f b .=> eval f (b ++ a))
+          (\f _ _ -> ifComplexity f, [proofOf icp]) $
+          \ih f a b ->
+                [isNormal f, isTautology' f b]
+             |- cases [ isFTrue  f ==> trivial
+                      , isFFalse f ==> trivial
+                      , isVar    f ==> let n = sfVar f
+                                       in eval f (b ++ a)
+                                       =: eval (sVar n) (b ++ a)
+                                       =: lookUp n (b ++ a)
+                                       ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                       =: ite (isAssigned n b) (lookUp n b) (lookUp n a)
+                                       ?? tia `at` (Inst @"a" b, Inst @"x" n)
+                                       =: lookUp n b
+                                       =: sTrue
+                                       =: qed
+                      , isIf f     ==>
+                          let c = sifCond f
+                              l = sifThen f
+                              r = sifElse f
+                          in cases [ isFTrue  c ==> eval (sIf c l r) (b ++ a)
+                                                 =: ite (eval c (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                 ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                 ?? ih  `at` (Inst @"f" l, Inst @"a" a, Inst @"b" b)
+                                                 =: sTrue
+                                                 =: qed
+                                   , isFFalse c ==> eval (sIf c l r) (b ++ a)
+                                                 =: ite (eval c (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                 =: eval r (b ++ a)
+                                                 ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                 ?? ih  `at` (Inst @"f" r, Inst @"a" a, Inst @"b" b)
+                                                 =: sTrue
+                                                 =: qed
+                                   , isVar    c ==> let n = sfVar c
+                                                    in cases [ isAssigned n b ==>
+                                                                    eval (sIf (sVar n) l r) (b ++ a)
+                                                                 =: ite (eval (sVar n) (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                 =: ite (lookUp n (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                 ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                                                 =: ite (lookUp n b) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                 ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                 ?? ih  `at` (Inst @"f" l, Inst @"a" a, Inst @"b" b)
+                                                                 ?? ih  `at` (Inst @"f" r, Inst @"a" a, Inst @"b" b)
+                                                                 =: sTrue
+                                                                 =: qed
+                                                             , sNot (isAssigned n b) ==>
+                                                                 cases [ lookUp n a ==>
+                                                                             eval (sIf (sVar n) l r) (b ++ a)
+                                                                          =: ite (eval (sVar n) (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          =: ite (lookUp n (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                                                          =: ite (lookUp n a) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          =: eval l (b ++ a)
+                                                                          ?? evs `at` (Inst @"f" l, Inst @"x" n, Inst @"v" (lookUp n a), Inst @"bs" (b ++ a))
+                                                                          ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                                                          =: eval l (sBinding n (lookUp n a) .: (b ++ a))
+                                                                          =: eval l (sBinding n sTrue .: (b ++ a))
+                                                                          =: eval l (assumeTrue n b ++ a)
+                                                                          ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                          ?? ih  `at` (Inst @"f" l, Inst @"a" a, Inst @"b" (assumeTrue n b))
+                                                                          =: sTrue
+                                                                          =: qed
+                                                                       , sNot (lookUp n a) ==>
+                                                                             eval (sIf (sVar n) l r) (b ++ a)
+                                                                          =: ite (eval (sVar n) (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          =: ite (lookUp n (b ++ a)) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                                                          =: ite (lookUp n a) (eval l (b ++ a)) (eval r (b ++ a))
+                                                                          =: eval r (b ++ a)
+                                                                          ?? evs `at` (Inst @"f" r, Inst @"x" n, Inst @"v" (lookUp n a), Inst @"bs" (b ++ a))
+                                                                          ?? lus `at` (Inst @"a" b, Inst @"x" n, Inst @"b" a)
+                                                                          =: eval r (sBinding n (lookUp n a) .: (b ++ a))
+                                                                          =: eval r (sBinding n sFalse .: (b ++ a))
+                                                                          =: eval r (assumeFalse n b ++ a)
+                                                                          ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                          ?? ih  `at` (Inst @"f" r, Inst @"a" a, Inst @"b" (assumeFalse n b))
+                                                                          =: sTrue
+                                                                          =: qed
+                                                                       ]
+                                                             ]
+                                   , isIf c     ==> trivial  -- Contradicts isNormal
+                                   ]
+                      ]
+
+-- * Normalization correctness
+
+-- | \(\mathit{isNormal}(\mathit{normalize}(f))\)
+--
+-- Normalization produces normalized formulas.
+--
+-- >>> runTP normalizeCorrect
+-- Lemma: ifComplexityPos                        Q.E.D.
+-- Lemma: ifComplexitySmaller                    Q.E.D.
+-- Lemma: normalizePreservesComplexity           Q.E.D.
+-- Lemma: ifDepthNonNeg                          Q.E.D.
+-- Inductive lemma (strong): normalizeCorrect
+--   Step: Measure is non-negative               Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                                 Q.E.D.
+--     Step: 1.2                                 Q.E.D.
+--     Step: 1.3                                 Q.E.D.
+--     Step: 1.4 (2 way case split)
+--       Step: 1.4.1.1                           Q.E.D.
+--       Step: 1.4.1.2                           Q.E.D.
+--       Step: 1.4.2.1                           Q.E.D.
+--       Step: 1.4.2.2                           Q.E.D.
+--       Step: 1.4.2.3                           Q.E.D.
+--       Step: 1.4.2.4                           Q.E.D.
+--       Step: 1.4.2.5                           Q.E.D.
+--       Step: 1.4.Completeness                  Q.E.D.
+--     Step: 1.Completeness                      Q.E.D.
+--   Result:                                     Q.E.D.
+-- Functions proven terminating: ifComplexity, ifDepth, isNormal, normalize
+-- [Proven] normalizeCorrect :: Ɐf ∷ Formula → Bool
+normalizeCorrect :: TP (Proof (Forall "f" Formula -> SBool))
+normalizeCorrect = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+  npc <- recall normalizePreservesComplexity
+  idn <- recall ifDepthNonNeg
+
+  sInductWith cvc5 "normalizeCorrect"
+              (\(Forall f) -> isNormal (normalize f))
+              (\f -> tuple (ifComplexity f, ifDepth f), [proofOf icp, proofOf idn]) $
+              \ih f -> []
+                    |- isNormal (normalize f)
+                    =: cases [ isFTrue  f ==> trivial
+                             , isFFalse f ==> trivial
+                             , isVar    f ==> trivial
+                             , isIf     f ==> let c = sifCond f
+                                                  l = sifThen f
+                                                  r = sifElse f
+                                              in cases [ isIf c ==>
+                                                           let p  = sifCond c
+                                                               q  = sifThen c
+                                                               rc = sifElse c
+                                                               transformed = sIf p (sIf q l r) (sIf rc l r)
+                                                           in isNormal (normalize transformed)
+                                                           ?? npc `at` (Inst @"p" p, Inst @"q" q, Inst @"s" rc, Inst @"l" l, Inst @"r" r)
+                                                           ?? ih `at` Inst @"f" transformed
+                                                           =: sTrue
+                                                           =: qed
+                                                       , sNot (isIf c) ==>
+                                                              isNormal (sIf c (normalize l) (normalize r))
+                                                           =: sNot (isIf c) .&& isNormal (normalize l) .&& isNormal (normalize r)
+                                                           =: isNormal (normalize l) .&& isNormal (normalize r)
+                                                           ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                           ?? ih  `at` Inst @"f" l
+                                                           =: isNormal (normalize r)
+                                                           ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                           ?? ih  `at` Inst @"f" r
+                                                           =: sTrue
+                                                           =: qed
+                                                       ]
+                             ]
+
+-- | \(\mathit{isNormal}(f) \implies \mathit{normalize}(f) = f\)
+--
+-- Normalizing a normalized formula is the identity.
+--
+-- >>> runTP normalizeSame
+-- Lemma: ifComplexityPos                     Q.E.D.
+-- Lemma: ifComplexitySmaller                 Q.E.D.
+-- Inductive lemma (strong): normalizeSame
+--   Step: Measure is non-negative            Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                              Q.E.D.
+--     Step: 1.2                              Q.E.D.
+--     Step: 1.3                              Q.E.D.
+--     Step: 1.4.1                            Q.E.D.
+--     Step: 1.4.2                            Q.E.D.
+--     Step: 1.Completeness                   Q.E.D.
+--   Result:                                  Q.E.D.
+-- Functions proven terminating: ifComplexity, isNormal, normalize
+-- [Proven] normalizeSame :: Ɐf ∷ Formula → Bool
+normalizeSame :: TP (Proof (Forall "f" Formula -> SBool))
+normalizeSame = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+
+  sInduct "normalizeSame"
+          (\(Forall f) -> isNormal f .=> normalize f .== f)
+          (ifComplexity, [proofOf icp]) $
+          \ih f -> [isNormal f]
+                |- cases [ isFTrue  f ==> trivial
+                         , isFFalse f ==> trivial
+                         , isVar    f ==> trivial
+                         , isIf     f ==> let c = sifCond f
+                                              l = sifThen f
+                                              r = sifElse f
+                                          in sIf c (normalize l) (normalize r)
+                                          ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                          ?? ih `at` Inst @"f" l
+                                          =: sIf c l (normalize r)
+                                          ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                          ?? ih `at` Inst @"f" r
+                                          =: sIf c l r
+                                          =: qed
+                         ]
+
+-- | \(\mathit{eval}(\mathit{normalize}(f), bs) = \mathit{eval}(f, bs)\)
+--
+-- Normalization preserves semantics.
+--
+-- >>> runTP normalizeRespectsTruth
+-- Lemma: ifComplexityPos                              Q.E.D.
+-- Lemma: ifComplexitySmaller                          Q.E.D.
+-- Lemma: normalizePreservesComplexity                 Q.E.D.
+-- Lemma: ifDepthNonNeg                                Q.E.D.
+-- Inductive lemma (strong): normalizeRespectsTruth
+--   Step: Measure is non-negative                     Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                                       Q.E.D.
+--     Step: 1.2                                       Q.E.D.
+--     Step: 1.3                                       Q.E.D.
+--     Step: 1.4 (2 way case split)
+--       Step: 1.4.1                                   Q.E.D.
+--       Step: 1.4.2.1                                 Q.E.D.
+--       Step: 1.4.2.2                                 Q.E.D.
+--       Step: 1.4.2.3                                 Q.E.D.
+--       Step: 1.4.Completeness                        Q.E.D.
+--     Step: 1.Completeness                            Q.E.D.
+--   Result:                                           Q.E.D.
+-- Functions proven terminating: eval, ifComplexity, ifDepth, lookUp, normalize
+-- [Proven] normalizeRespectsTruth :: Ɐf ∷ Formula → Ɐbs ∷ [Binding] → Bool
+normalizeRespectsTruth :: TP (Proof (Forall "f" Formula -> Forall "bs" [Binding] -> SBool))
+normalizeRespectsTruth = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+  npc <- recall normalizePreservesComplexity
+  idn <- recall ifDepthNonNeg
+
+  sInductWith cvc5 "normalizeRespectsTruth"
+              (\(Forall f) (Forall bs) -> eval (normalize f) bs .== eval f bs)
+              (\f _ -> tuple (ifComplexity f, ifDepth f), [proofOf icp, proofOf idn]) $
+              \ih f bs -> []
+                       |- cases [ isFTrue  f ==> trivial
+                                , isFFalse f ==> trivial
+                                , isVar    f ==> trivial
+                                , isIf     f ==> let c = sifCond f
+                                                     l = sifThen f
+                                                     r = sifElse f
+                                                 in cases [ isIf c ==>
+                                                              let p  = sifCond c
+                                                                  q  = sifThen c
+                                                                  rc = sifElse c
+                                                                  transformed = sIf p (sIf q l r) (sIf rc l r)
+                                                              in eval (normalize (sIf c l r)) bs .== eval (sIf c l r) bs
+                                                              ?? npc `at` (Inst @"p" p, Inst @"q" q, Inst @"s" rc, Inst @"l" l, Inst @"r" r)
+                                                              ?? ih  `at` (Inst @"f" transformed, Inst @"bs" bs)
+                                                              =: sTrue
+                                                              =: qed
+                                                          , sNot (isIf c) ==>
+                                                                 eval (normalize (sIf c l r)) bs .== eval (sIf c l r) bs
+                                                              =: eval (sIf c (normalize l) (normalize r)) bs .== eval (sIf c l r) bs
+                                                              =: ite (eval c bs) (eval (normalize l) bs) (eval (normalize r) bs) .== ite (eval c bs) (eval l bs) (eval r bs)
+                                                              ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                              ?? ih  `at` (Inst @"f" l, Inst @"bs" bs)
+                                                              ?? ih  `at` (Inst @"f" r, Inst @"bs" bs)
+                                                              =: sTrue
+                                                              =: qed
+                                                          ]
+                                ]
+
+-- * Main soundness theorem
+
+-- | \(\mathit{isTautology}(f) \implies \mathit{eval}(f, \mathit{bindings})\)
+--
+-- If the tautology checker says a formula is a tautology, then it evaluates
+-- to true under any binding environment. This is the soundness theorem.
+--
+-- >>> runTP soundness
+-- Lemma: tautologyImpliesEval                         Q.E.D.
+-- Lemma: normalizeRespectsTruth                       Q.E.D.
+-- Lemma: normalizeCorrect                             Q.E.D.
+-- Lemma: soundness
+--   Step: 1                                           Q.E.D.
+--   Step: 2                                           Q.E.D.
+--   Result:                                           Q.E.D.
+-- Functions proven terminating: eval, ifComplexity, ifDepth, isAssigned, isNormal, isTautology', lookUp, normalize
+-- [Proven] soundness :: Ɐf ∷ Formula → Ɐbindings ∷ [Binding] → Bool
+soundness :: TP (Proof (Forall "f" Formula -> Forall "bindings" [Binding] -> SBool))
+soundness = do
+  tie <- recallWith cvc5 tautologyImpliesEval
+  nrt <- recall normalizeRespectsTruth
+  nc  <- recall normalizeCorrect
+
+  calc "soundness"
+       (\(Forall f) (Forall bindings) -> isTautology f .=> eval f bindings) $
+       \f bindings -> [isTautology f]
+                   |- eval f bindings
+                   ?? nrt `at` (Inst @"f" f, Inst @"bs" bindings)
+                   =: eval (normalize f) bindings
+                   ?? nc  `at` Inst @"f" f
+                   ?? tie `at` (Inst @"f" (normalize f), Inst @"a" bindings, Inst @"b" [])
+                   =: sTrue
+                   =: qed
+
+-- * Completeness
+
+-- | Result of attempting to falsify a formula.
+data FalsifyResult = FalsifyResult { falsified :: Bool
+                                   , cex       :: [Binding]
+                                   }
+
+-- | Make FalsifyResult symbolic.
+mkSymbolic [''FalsifyResult]
+
+-- | Attempt to falsify a normalized formula under given bindings.
+-- Returns whether falsification succeeded and the counterexample bindings.
+falsify' :: SFormula -> SList Binding -> SFalsifyResult
+falsify' = smtFunction "falsify'" $ \f bs ->
+  [sCase| f of
+    FTrue  -> sFalsifyResult sFalse []
+    FFalse -> sFalsifyResult sTrue bs
+
+    Var i
+      | isAssigned i bs, eval (sVar i) bs -> sFalsifyResult sFalse []
+      | isAssigned i bs                   -> sFalsifyResult sTrue bs
+      | True                              -> sFalsifyResult sTrue (sBinding i sFalse .: bs)
+
+    If (Var i) l r
+      | isAssigned i bs, eval (sVar i) bs -> falsify' l bs
+      | isAssigned i bs                   -> falsify' r bs
+      | True                              -> let resL = falsify' l (assumeTrue i bs)
+                                             in ite (sNot (sfalsified resL))
+                                                    (falsify' r (assumeFalse i bs))
+                                                    resL
+    If FTrue  l _  -> falsify' l bs
+    If FFalse _ r  -> falsify' r bs
+    If _      _ _  -> sFalsifyResult sFalse []  -- Shouldn't happen for normal formulas
+  |]
+
+-- | Falsify a formula by first normalizing it.
+falsify :: SFormula -> SFalsifyResult
+falsify f = falsify' (normalize f) []
+
+-- * Completeness lemmas
+
+-- | If a normalized formula is not a tautology, then falsify' returns falsified = true.
+--
+-- >>> runTPWith cvc5 nonTautIsFalsified
+-- Lemma: ifComplexityPos                          Q.E.D.
+-- Lemma: ifComplexitySmaller                      Q.E.D.
+-- Inductive lemma (strong): nonTautIsFalsified
+--   Step: Measure is non-negative                 Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                                   Q.E.D.
+--     Step: 1.2                                   Q.E.D.
+--     Step: 1.3                                   Q.E.D.
+--     Step: 1.4                                   Q.E.D.
+--     Step: 1.Completeness                        Q.E.D.
+--   Result:                                       Q.E.D.
+-- Functions proven terminating: eval, falsify', ifComplexity, isAssigned, isNormal, isTautology', lookUp
+-- [Proven] nonTautIsFalsified :: Ɐf ∷ Formula → Ɐbs ∷ [Binding] → Bool
+nonTautIsFalsified :: TP (Proof (Forall "f" Formula -> Forall "bs" [Binding] -> SBool))
+nonTautIsFalsified = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+
+  sInduct "nonTautIsFalsified"
+          (\(Forall f) (Forall bs) -> isNormal f .&& sNot (isTautology' f bs) .=> sfalsified (falsify' f bs))
+          (\f _ -> ifComplexity f, [proofOf icp]) $
+          \ih f bs -> [isNormal f, sNot (isTautology' f bs)]
+                   |- cases [ isFTrue  f ==> trivial
+                            , isFFalse f ==> trivial
+                            , isVar    f ==> trivial
+                            , isIf     f ==> let c = sifCond f
+                                                 l = sifThen f
+                                                 r = sifElse f
+                                             in sfalsified (falsify' f bs)
+                                             ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                             ?? ih  `at` (Inst @"f" l, Inst @"bs" bs)
+                                             ?? ih  `at` (Inst @"f" r, Inst @"bs" bs)
+                                             ?? ih  `at` (Inst @"f" l, Inst @"bs" (assumeTrue (sfVar c) bs))
+                                             ?? ih  `at` (Inst @"f" r, Inst @"bs" (assumeFalse (sfVar c) bs))
+                                             =: sTrue
+                                             =: qed
+                            ]
+
+-- | If a variable is assigned in the input bindings and falsify' succeeds,
+-- the lookup value is preserved in the output bindings.
+--
+-- >>> runTPWith cvc5 falsifyExtendsBindings
+-- Lemma: ifComplexityPos                              Q.E.D.
+-- Lemma: ifComplexitySmaller                          Q.E.D.
+-- Lemma: isAssignedExtends                            Q.E.D.
+-- Lemma: lookUpExtends                                Q.E.D.
+-- Inductive lemma (strong): falsifyExtendsBindings
+--   Step: Measure is non-negative                     Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1                                       Q.E.D.
+--     Step: 1.2                                       Q.E.D.
+--     Step: 1.3                                       Q.E.D.
+--     Step: 1.4                                       Q.E.D.
+--     Step: 1.Completeness                            Q.E.D.
+--   Result:                                           Q.E.D.
+-- Functions proven terminating: eval, falsify', ifComplexity, isAssigned, lookUp
+-- [Proven] falsifyExtendsBindings :: Ɐf ∷ Formula → Ɐbs ∷ [Binding] → Ɐi ∷ Integer → Bool
+falsifyExtendsBindings :: TP (Proof (Forall "f" Formula -> Forall "bs" [Binding] -> Forall "i" Integer -> SBool))
+falsifyExtendsBindings = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+  iae <- recall isAssignedExtends
+  lue <- recall lookUpExtends
+
+  sInduct "falsifyExtendsBindings"
+          (\(Forall f) (Forall bs) (Forall i) ->
+             isAssigned i bs .&& sfalsified (falsify' f bs) .=>
+             lookUp i (scex (falsify' f bs)) .== lookUp i bs)
+          (\f _ _ -> ifComplexity f, [proofOf icp]) $
+          \ih f bs i -> [isAssigned i bs, sfalsified (falsify' f bs)]
+                     |- cases [ isFTrue  f ==> trivial
+                              , isFFalse f ==> trivial
+                              , isVar    f ==> let n = sfVar f
+                                               in lookUp i (scex (falsify' f bs)) .== lookUp i bs
+                                               ?? lue `at` (Inst @"i" i, Inst @"n" n, Inst @"v" sFalse, Inst @"bs" bs)
+                                               =: sTrue
+                                               =: qed
+                              , isIf     f ==> let c = sifCond f
+                                                   l = sifThen f
+                                                   r = sifElse f
+                                                   n = sfVar c
+                                               in lookUp i (scex (falsify' f bs)) .== lookUp i bs
+                                               ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                               ?? iae `at` (Inst @"i" i, Inst @"n" n, Inst @"v" sTrue,  Inst @"bs" bs)
+                                               ?? iae `at` (Inst @"i" i, Inst @"n" n, Inst @"v" sFalse, Inst @"bs" bs)
+                                               ?? lue `at` (Inst @"i" i, Inst @"n" n, Inst @"v" sTrue,  Inst @"bs" bs)
+                                               ?? lue `at` (Inst @"i" i, Inst @"n" n, Inst @"v" sFalse, Inst @"bs" bs)
+                                               ?? ih  `at` (Inst @"f" l, Inst @"bs" bs, Inst @"i" i)
+                                               ?? ih  `at` (Inst @"f" r, Inst @"bs" bs, Inst @"i" i)
+                                               ?? ih  `at` (Inst @"f" l, Inst @"bs" (assumeTrue n bs), Inst @"i" i)
+                                               ?? ih  `at` (Inst @"f" r, Inst @"bs" (assumeFalse n bs), Inst @"i" i)
+                                               =: sTrue
+                                               =: qed
+                              ]
+
+-- | If falsify' returns falsified = true, then evaluating the formula
+-- with the returned bindings gives false.
+--
+-- >>> runTPWith cvc5 falsifyFalsifies
+-- Lemma: ifComplexityPos                              Q.E.D.
+-- Lemma: ifComplexitySmaller                          Q.E.D.
+-- Lemma: falsifyExtendsBindings                       Q.E.D.
+-- Lemma: lookUpSame                                   Q.E.D.
+-- Lemma: isAssignedSame                               Q.E.D.
+-- Inductive lemma (strong): falsifyFalsifies
+--   Step: Measure is non-negative                     Q.E.D.
+--   Step: 1 (4 way case split)
+--     Step: 1.1.1                                     Q.E.D.
+--     Step: 1.1.2                                     Q.E.D.
+--     Step: 1.1.3                                     Q.E.D.
+--     Step: 1.2.1                                     Q.E.D.
+--     Step: 1.2.2                                     Q.E.D.
+--     Step: 1.2.3                                     Q.E.D.
+--     Step: 1.3.1                                     Q.E.D.
+--     Step: 1.3.2                                     Q.E.D.
+--     Step: 1.3.3                                     Q.E.D.
+--     Step: 1.4 (4 way case split)
+--       Step: 1.4.1                                   Q.E.D.
+--       Step: 1.4.2                                   Q.E.D.
+--       Step: 1.4.3 (2 way case split)
+--         Step: 1.4.3.1 (2 way case split)
+--           Step: 1.4.3.1.1                           Q.E.D.
+--           Step: 1.4.3.1.2                           Q.E.D.
+--           Step: 1.4.3.1.Completeness                Q.E.D.
+--         Step: 1.4.3.2 (2 way case split)
+--           Step: 1.4.3.2.1                           Q.E.D.
+--           Step: 1.4.3.2.2                           Q.E.D.
+--           Step: 1.4.3.2.Completeness                Q.E.D.
+--         Step: 1.4.3.Completeness                    Q.E.D.
+--       Step: 1.4.4                                   Q.E.D.
+--       Step: 1.4.Completeness                        Q.E.D.
+--     Step: 1.Completeness                            Q.E.D.
+--   Result:                                           Q.E.D.
+-- Functions proven terminating: eval, falsify', ifComplexity, isAssigned, isNormal, lookUp
+-- [Proven] falsifyFalsifies :: Ɐf ∷ Formula → Ɐbs ∷ [Binding] → Bool
+falsifyFalsifies :: TP (Proof (Forall "f" Formula -> Forall "bs" [Binding] -> SBool))
+falsifyFalsifies = do
+  icp <- recall ifComplexityPos
+  ibs <- recall ifComplexitySmaller
+  feb <- recall falsifyExtendsBindings
+  lus <- recall lookUpSame
+  ias <- recall isAssignedSame
+
+  sInduct "falsifyFalsifies"
+          (\(Forall f) (Forall bs) -> isNormal f .&& sfalsified (falsify' f bs) .=> sNot (eval f (scex (falsify' f bs))))
+          (\f _ -> ifComplexity f, [proofOf icp]) $
+          \ih f bs -> [isNormal f, sfalsified (falsify' f bs)]
+                   |- cases [ isFTrue  f ==> sNot (eval f (scex (falsify' f bs)))
+                                          =: sNot (eval sFTrue (scex (falsify' sFTrue bs)))
+                                          =: sNot sTrue
+                                          =: sFalse
+                                          =: qed
+                            , isFFalse f ==> sNot (eval f (scex (falsify' f bs)))
+                                          =: sNot (eval sFFalse bs)
+                                          =: sNot sFalse
+                                          =: sTrue
+                                          =: qed
+                            , isVar    f ==> let n = sfVar f
+                                             in sNot (eval f (scex (falsify' f bs)))
+                                             =: sNot (eval (sVar n) (scex (falsify' (sVar n) bs)))
+                                             =: sNot (lookUp n (scex (falsify' (sVar n) bs)))
+                                             =: sTrue
+                                             =: qed
+                            , isIf     f ==> let c = sifCond f
+                                                 l = sifThen f
+                                                 r = sifElse f
+                                             in cases [ isFTrue  c ==> sNot (eval f (scex (falsify' f bs)))
+                                                                    ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                    ?? ih  `at` (Inst @"f" l, Inst @"bs" bs)
+                                                                    =: sTrue
+                                                                    =: qed
+                                                      , isFFalse c ==> sNot (eval f (scex (falsify' f bs)))
+                                                                    ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                    ?? ih  `at` (Inst @"f" r, Inst @"bs" bs)
+                                                                    =: sTrue
+                                                                    =: qed
+                                                      , isVar    c ==> let n = sfVar c
+                                                                       in cases [ isAssigned n bs ==>
+                                                                                      cases [ lookUp n bs ==>
+                                                                                                  sNot (eval f (scex (falsify' f bs)))
+                                                                                               ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                                               ?? feb `at` (Inst @"f" l, Inst @"bs" bs, Inst @"i" n)
+                                                                                               ?? ih  `at` (Inst @"f" l, Inst @"bs" bs)
+                                                                                               =: sTrue
+                                                                                               =: qed
+                                                                                            , sNot (lookUp n bs) ==>
+                                                                                                  sNot (eval f (scex (falsify' f bs)))
+                                                                                               ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                                               ?? feb `at` (Inst @"f" r, Inst @"bs" bs, Inst @"i" n)
+                                                                                               ?? ih  `at` (Inst @"f" r, Inst @"bs" bs)
+                                                                                               =: sTrue
+                                                                                               =: qed
+                                                                                            ]
+                                                                                , sNot (isAssigned n bs) ==>
+                                                                                      let resL = falsify' l (assumeTrue n bs)
+                                                                                      in cases [ sfalsified resL ==>
+                                                                                                     sNot (eval f (scex (falsify' f bs)))
+                                                                                                  ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                                                  ?? ias `at` (Inst @"n" n, Inst @"v" sTrue, Inst @"bs" bs)
+                                                                                                  ?? lus `at` (Inst @"n" n, Inst @"v" sTrue, Inst @"bs" bs)
+                                                                                                  ?? feb `at` (Inst @"f" l, Inst @"bs" (assumeTrue n bs), Inst @"i" n)
+                                                                                                  ?? ih  `at` (Inst @"f" l, Inst @"bs" (assumeTrue n bs))
+                                                                                                  =: sTrue
+                                                                                                  =: qed
+                                                                                               , sNot (sfalsified resL) ==>
+                                                                                                     sNot (eval f (scex (falsify' f bs)))
+                                                                                                  ?? ibs `at` (Inst @"c" c, Inst @"l" l, Inst @"r" r)
+                                                                                                  ?? ias `at` (Inst @"n" n, Inst @"v" sFalse, Inst @"bs" bs)
+                                                                                                  ?? lus `at` (Inst @"n" n, Inst @"v" sFalse, Inst @"bs" bs)
+                                                                                                  ?? feb `at` (Inst @"f" r, Inst @"bs" (assumeFalse n bs), Inst @"i" n)
+                                                                                                  ?? ih  `at` (Inst @"f" r, Inst @"bs" (assumeFalse n bs))
+                                                                                                  =: sTrue
+                                                                                                  =: qed
+                                                                                               ]
+                                                                                ]
+                                                      , isIf     c ==> sNot (eval f (scex (falsify' f bs)))
+                                                                    =: sTrue  -- Contradicts isNormal
+                                                                    =: qed
+                                                      ]
+                            ]
+
+-- | Helper lemma for completeness: If a formula is not a tautology,
+-- evaluating its normalization with falsify's bindings gives false.
+--
+-- >>> runTPWith cvc5 completenessHelper
+-- Lemma: falsifyFalsifies                             Q.E.D.
+-- Lemma: nonTautIsFalsified                           Q.E.D.
+-- Lemma: normalizeCorrect                             Q.E.D.
+-- Lemma: completenessHelper                           Q.E.D.
+-- Functions proven terminating:
+--   eval, falsify', ifComplexity, ifDepth, isAssigned, isNormal, isTautology', lookUp, normalize
+-- [Proven] completenessHelper :: Ɐf ∷ Formula → Bool
+completenessHelper :: TP (Proof (Forall "f" Formula -> SBool))
+completenessHelper = do
+  ff  <- recall falsifyFalsifies
+  nti <- recall nonTautIsFalsified
+  nc  <- recallWith z3 normalizeCorrect
+
+  lemma "completenessHelper"
+        (\(Forall f) -> sNot (isTautology f) .=> sNot (eval (normalize f) (scex (falsify f))))
+        [proofOf ff, proofOf nti, proofOf nc]
+
+-- * Main completeness theorem
+
+-- | \(\lnot\mathit{isTautology}(f) \implies \lnot\mathit{eval}(f, \mathit{falsify}(f).\mathit{bindings})\)
+--
+-- If the tautology checker says a formula is not a tautology, then there exists
+-- a binding environment (provided by falsify) under which it evaluates to false.
+-- This is the completeness theorem.
+--
+-- >>> runTPWith cvc5 completeness
+-- Lemma: completenessHelper                           Q.E.D.
+-- Lemma: normalizeRespectsTruth                       Q.E.D.
+-- Lemma: completeness                                 Q.E.D.
+-- Functions proven terminating:
+--   eval, falsify', ifComplexity, ifDepth, isAssigned, isNormal, isTautology', lookUp, normalize
+-- [Proven] completeness :: Ɐf ∷ Formula → Bool
+completeness :: TP (Proof (Forall "f" Formula -> SBool))
+completeness = do
+  ch  <- recall completenessHelper
+  nrt <- recallWith z3 normalizeRespectsTruth
+
+  lemma "completeness"
+        (\(Forall f) -> sNot (isTautology f) .=> sNot (eval f (scex (falsify f))))
+        [proofOf ch, proofOf nrt]
diff --git a/Documentation/SBV/Examples/TP/UpDown.hs b/Documentation/SBV/Examples/TP/UpDown.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/UpDown.hs
@@ -0,0 +1,114 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.UpDown
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves @reverse (down n) = up n@.
+--
+-- This problem is motivated by an ACL2 midterm exam question, from Fall 2011.
+-- See: <https://www.cs.utexas.edu/~moore/classes/cs389r/midterm-answers.lisp>.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP              #-}
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE OverloadedLists  #-}
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE TypeAbstractions #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.UpDown where
+
+import Prelude hiding (reverse, (++))
+
+import Data.SBV
+import Data.SBV.TP
+import Data.SBV.List
+
+import Documentation.SBV.Examples.TP.Lists
+import Documentation.SBV.Examples.TP.Peano
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+#endif
+
+-- | Construct a list of size @n@, containing numbers @1@ to @n@.
+--
+-- >>> up 0
+-- [] :: [SInteger]
+-- >>> up 5
+-- [1,2,3,4,5] :: [SInteger]
+up :: SNat -> SList Integer
+up n = upAcc n []
+
+-- | Keep consing the first argument on to the accumulator, until we hit zero. After that, return the second argument.
+-- Normally, we'd define this as a local function, but the definition needs to be visible for the proofs.
+upAcc :: SNat -> SList Integer -> SList Integer
+upAcc = smtFunction "up"
+      $ \n lst -> [sCase| n of
+                     Zero   -> lst
+                     Succ p -> upAcc p (n2i n .: lst)
+                  |]
+
+-- | Construct a list of size @n@, containing numbers @n-1@ down to @0@.
+--
+-- >>> down 0
+-- [] :: [SInteger]
+-- >>> down 5
+-- [5,4,3,2,1] :: [SInteger]
+down :: SNat -> SList Integer
+down = smtFunction "down"
+     $ \n -> [sCase| n of
+                Zero   -> []
+                Succ p -> n2i n .: down p
+             |]
+
+-- | Prove that @reverse (down n)@ is the same as @up n@
+--
+-- >>> runTP upDown
+-- Lemma: n2iNonNeg                       Q.E.D.
+-- Lemma: revCons                         Q.E.D.
+-- Inductive lemma (strong): upDownGen
+--   Step: Measure is non-negative        Q.E.D.
+--   Step: 1 (2 way case split)
+--     Step: 1.1                          Q.E.D.
+--     Step: 1.2.1                        Q.E.D.
+--     Step: 1.2.2                        Q.E.D.
+--     Step: 1.2.3                        Q.E.D.
+--     Step: 1.2.4                        Q.E.D.
+--     Step: 1.Completeness               Q.E.D.
+--   Result:                              Q.E.D.
+-- Lemma: upDown                          Q.E.D.
+-- Functions proven terminating: down, n2i, sbv.reverse, up
+-- [Proven] upDown :: Ɐn ∷ Nat → Bool
+upDown :: TP (Proof (Forall "n" Nat -> SBool))
+upDown = do
+   n2inn <- recall n2iNonNeg
+   rc    <- recall (revCons @Integer)
+
+   -- We first generalize the theorem, to make it inductive
+   upDownGen <- sInduct "upDownGen"
+           (\(Forall @"n" n) (Forall @"xs" xs) -> reverse (down n) ++ xs .== upAcc n xs)
+           (\n _ -> n2i n, [proofOf n2inn]) $
+           \ih n xs -> [] |- cases [ isZero n ==> trivial
+                                   , isSucc n ==> let p = getSucc_1 n
+                                               in reverse (down (sSucc p)) ++ xs
+                                               =: reverse (n2i n .: down p) ++ xs
+                                               ?? rc
+                                               =: reverse (down p) ++ (n2i n .: xs)
+                                               ?? ih `at` (Inst @"n" p, Inst @"xs" (n2i n .: xs))
+                                               =: upAcc p (n2i n .: xs)
+                                               =: upAcc n xs
+                                               =: qed
+                                   ]
+
+   -- The theorem we want to prove follows by instantiating the list at empty, and
+   -- the SMT solver can figure it out by itself
+   lemma "upDown"
+         (\(Forall n) -> reverse (down n) .== up n)
+         [proofOf upDownGen]
diff --git a/Documentation/SBV/Examples/TP/VM.hs b/Documentation/SBV/Examples/TP/VM.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/TP/VM.hs
@@ -0,0 +1,448 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.TP.VM
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Correctness of a simple interpreter vs virtual-machine interpretation of a language.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.TP.VM
+#ifndef DOCTEST
+ (   -- * Language
+     Expr(..), SExpr, size
+
+
+     -- * Symbolic accessors
+   , sCaseExpr
+   , isVar, sVar, getVar_1,                     svar
+   , isCon, sCon, getCon_1,                     scon
+   , isSqr, sSqr, getSqr_1,                     ssqrVal
+   , isInc, sInc, getInc_1,                     sincVal
+   , isAdd, sAdd, getAdd_1, getAdd_2,           sadd1, sadd2
+   , isMul, sMul, getMul_1, getMul_2,           smul1, smul2
+   , isLet, sLet, getLet_1, getLet_2, getLet_3, slvar, slval, slbody
+
+     -- * Environment and the stack
+   , Env, Stack
+
+     -- * Interpretation
+   , interpInEnv, interp
+
+     -- * Virtual machine
+   , Instr(..), SInstr
+
+     -- * Compilation
+   , compile, compileAndRun
+
+     -- * Correctness of the compiler
+   , correctness)
+#endif
+where
+
+import Data.SBV
+import Data.SBV.Tuple as ST
+import Data.SBV.List  as SL
+
+import Data.SBV.TP
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV.TP
+-- >>> :set -XTypeApplications
+#endif
+
+-- * Language
+
+-- | Basic expression language.
+data Expr nm val = Var {var    :: nm                                            } -- ^ Variables
+                 | Con {con    :: val                                           } -- ^ Constants
+                 | Sqr {sqrVal :: Expr nm val                                   } -- ^ Squaring
+                 | Inc {incVal :: Expr nm val                                   } -- ^ Increment
+                 | Add {add1   :: Expr nm val, add2 :: Expr nm val              } -- ^ Addition
+                 | Mul {mul1   :: Expr nm val, mul2 :: Expr nm val              } -- ^ Addition
+                 | Let {lvar   :: nm, lval ::  Expr nm val, lbody :: Expr nm val} -- ^ Let expression
+
+-- | Create symbolic version of expressions
+mkSymbolic [''Expr]
+
+-- | Size of an expression. Used in strong induction.
+size :: (SymVal nm, SymVal val) => SExpr nm val -> SInteger
+size = smtFunction "exprSize"
+     $ \expr -> [sCase| expr of
+                   Var _     -> 0
+                   Con _     -> 0
+                   Sqr a     -> 1 + size a
+                   Inc a     -> 1 + size a
+                   Add a b   -> 1 + size a `smax` size b
+                   Mul a b   -> 1 + size a `smax` size b
+                   Let _ a b -> 1 + size a `smax` size b
+                |]
+
+-- | Environment, binding names to values
+type Env nm val = SList (nm, val)
+
+-- * Functional interpretation
+
+-- | Interpreter, in the usual functional style, taking an arbitrary environment.
+interpInEnv :: (SymVal nm, SymVal val, Num (SBV val)) => Env nm val -> SExpr nm val -> SBV val
+interpInEnv = smtFunction "interpInEnv"
+            $ \env expr ->
+                 [sCase| expr of
+                    Var nm    -> nm `SL.lookup` env
+                    Con v     -> v
+                    Sqr a     -> let av = interpInEnv env a in av * av
+                    Inc a     -> let av = interpInEnv env a in av + 1
+                    Add a b   -> let av = interpInEnv env a; bv = interpInEnv env b in av + bv
+                    Mul a b   -> let av = interpInEnv env a; bv = interpInEnv env b in av * bv
+                    Let v a b -> let av = interpInEnv env a in interpInEnv (tuple (v, av) .: env) b
+                 |]
+
+-- | Interpret starting from empty environment.
+interp :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+interp = interpInEnv []
+
+-- * Virtual machine
+
+-- | Instructions
+data Instr nm val = IPushN { ivar :: nm  } -- ^ Push the value of nm from the environment on to the stack
+                  | IPushV { ival :: val } -- ^ Push a value on to the stack
+                  | IDup                   -- ^ Duplicate the top of the stack
+                  | IAdd                   -- ^ Add      the top two elements and push back
+                  | IMul                   -- ^ Multiply the top two elements and push back
+                  | IBind nm               -- ^ Bind the value on top of stack to name
+                  | IForget                -- ^ Pop and ignore the binding on the environment
+
+-- | Create symbolic version of instructions
+mkSymbolic [''Instr]
+
+-- | Stack of values.
+type Stack val = SList val
+
+-- | Pushing on to the stack.
+push :: SymVal val => SBV val -> Stack val  -> Stack val
+push = (SL..:)
+
+-- | Top of the stack. If the stack is empty, the result is underspecified.
+top :: SymVal val => Stack val  -> SBV val
+top = SL.head
+
+-- | Popping from the stack. If the stack is empty, the result is underspecified.
+pop :: SymVal val => Stack val  -> Stack val
+pop = SL.tail
+
+-- | A pair containing an environment and a stack
+type EnvStack nm val = SBV ([(nm, val)], [val])
+
+-- | Executing a single instruction in a given environment and the instruction stack.
+-- We produce the new environment, and the new stack.
+execute :: (SymVal nm, SymVal val, Num (SBV val)) => EnvStack nm val -> SInstr nm val -> EnvStack nm val
+execute envStk instr = let (env, stk) = untuple envStk
+                       in tuple [sCase| instr of
+                                   IPushN nm   -> (env, push (nm `SL.lookup` env) stk)
+                                   IPushV v    -> (env, push v stk)
+                                   IDup        -> (env, push (top stk) stk)
+                                   IAdd        -> (env, let a = top stk; b = top (pop stk) in push (a + b) (pop (pop stk)))
+                                   IMul        -> (env, let a = top stk; b = top (pop stk) in push (a * b) (pop (pop stk)))
+                                   IBind nm    -> (push (tuple (nm, top stk)) env, pop stk)
+                                   IForget     -> (pop env, stk)
+                                |]
+
+-- | Execute a sequence of instructions, in a given stack and env. Returnsg the final environment and the stack. This is a
+-- simple fold-left.
+run :: (SymVal nm, SymVal val, Num (SBV val)) => EnvStack nm val -> SList (Instr nm val) -> EnvStack nm val
+run = SL.foldl execute
+
+-- * Compiler
+
+-- | Convert an expression to a sequence of instructions for our virtual machine.
+compile :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SList (Instr nm val)
+compile = smtFunction "compile"
+        $ \expr -> [sCase| expr of
+                      Var nm    -> [sIPushN nm]
+                      Con v     -> [sIPushV v]
+                      Sqr a     -> compile a SL.++ [sIDup,     sIMul]
+                      Inc a     -> compile a SL.++ [sIPushV 1, sIAdd]
+                      Add a b   -> compile a SL.++ compile b  SL.++ [sIAdd]
+                      Mul a b   -> compile a SL.++ compile b  SL.++ [sIMul]
+                      Let v a b -> compile a SL.++ [sIBind v] SL.++ compile b SL.++ [sIForget]
+                   |]
+
+-- | Compile and run an expression.
+compileAndRun :: (SymVal nm, SymVal val, Num (SBV val)) => SExpr nm val -> SBV val
+compileAndRun = top . ST.snd . run (tuple ([], [])) . compile
+
+-- * Correctness
+
+-- | The property we're after is that interpreting an expression is the same as
+-- first compiling it to virtual-machine instructions, and then running them.
+--
+-- >>> runTP (correctness @String @Integer)
+-- Inductive lemma: runSeq
+--   Step: Base                        Q.E.D.
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: runOne                       Q.E.D.
+-- Lemma: runTwo
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: runMul                       Q.E.D.
+-- Lemma: measureNonNeg                Q.E.D.
+-- Inductive lemma (strong): helper
+--   Step: Measure is non-negative     Q.E.D.
+--   Step: 1 (7 way case split)
+--     Step: 1.1.1 (case Var)          Q.E.D.
+--     Step: 1.1.2                     Q.E.D.
+--     Step: 1.2.1 (case Con)          Q.E.D.
+--     Step: 1.2.2                     Q.E.D.
+--     Step: 1.2.3                     Q.E.D.
+--     Step: 1.3.1 (case Sqr)          Q.E.D.
+--     Step: 1.3.2                     Q.E.D.
+--     Step: 1.3.3                     Q.E.D.
+--     Step: 1.3.4                     Q.E.D.
+--     Step: 1.3.5                     Q.E.D.
+--     Step: 1.3.6                     Q.E.D.
+--     Step: 1.3.7                     Q.E.D.
+--     Step: 1.4.1 (case Inc)          Q.E.D.
+--     Step: 1.4.2                     Q.E.D.
+--     Step: 1.4.3                     Q.E.D.
+--     Step: 1.4.4                     Q.E.D.
+--     Step: 1.4.5                     Q.E.D.
+--     Step: 1.4.6                     Q.E.D.
+--     Step: 1.4.7                     Q.E.D.
+--     Step: 1.5.1 (case sAdd)         Q.E.D.
+--     Step: 1.5.2                     Q.E.D.
+--     Step: 1.5.3                     Q.E.D.
+--     Step: 1.5.4                     Q.E.D.
+--     Step: 1.5.5                     Q.E.D.
+--     Step: 1.5.6                     Q.E.D.
+--     Step: 1.5.7                     Q.E.D.
+--     Step: 1.5.8                     Q.E.D.
+--     Step: 1.5.9                     Q.E.D.
+--     Step: 1.6.1 (case sMul)         Q.E.D.
+--     Step: 1.6.2                     Q.E.D.
+--     Step: 1.6.3                     Q.E.D.
+--     Step: 1.6.4                     Q.E.D.
+--     Step: 1.6.5                     Q.E.D.
+--     Step: 1.6.6                     Q.E.D.
+--     Step: 1.6.7                     Q.E.D.
+--     Step: 1.6.8                     Q.E.D.
+--     Step: 1.6.9                     Q.E.D.
+--     Step: 1.7.1 (case Let)          Q.E.D.
+--     Step: 1.7.2                     Q.E.D.
+--     Step: 1.7.3                     Q.E.D.
+--     Step: 1.7.4                     Q.E.D.
+--     Step: 1.7.5                     Q.E.D.
+--     Step: 1.7.6                     Q.E.D.
+--     Step: 1.7.7                     Q.E.D.
+--     Step: 1.7.8                     Q.E.D.
+--     Step: 1.7.9                     Q.E.D.
+--     Step: 1.7.10                    Q.E.D.
+--     Step: 1.7.11                    Q.E.D.
+--     Step: 1.Completeness            Q.E.D.
+--   Result:                           Q.E.D.
+-- Lemma: correctness
+--   Step: 1                           Q.E.D.
+--   Step: 2                           Q.E.D.
+--   Step: 3                           Q.E.D.
+--   Step: 4                           Q.E.D.
+--   Result:                           Q.E.D.
+-- Functions proven terminating: compile, exprSize, interpInEnv, sbv.foldl, sbv.lookup
+-- [Proven] correctness :: Ɐexpr ∷ (Expr String Integer) → Bool
+correctness :: forall nm val. (SymVal nm, SymVal val, Num (SBV val)) => TP (Proof (Forall "expr" (Expr nm val) -> SBool))
+correctness = do
+
+   -- Running a sequence of instructions that are appended is equivalent to running them in sequence:
+   runSeq <- induct "runSeq"
+                    (\(Forall @"xs" xs) (Forall @"ys" ys) (Forall @"es" (es :: EnvStack nm val))
+                         -> run es (xs SL.++ ys) .== run (run es xs) ys) $
+                    \ih (x, xs) ys es -> [] |- run es ((x .: xs) SL.++ ys)
+                                            =: run es (x .: (xs SL.++ ys))
+                                            =: run (execute es x) (xs SL.++ ys)
+                                            ?? ih `at` (Inst @"ys" ys, Inst @"es" (execute es x))
+                                            =: run (run es (x .: xs)) ys
+                                            =: qed
+
+   -- The following few lemmas make the proof go thru faster, even though they're really easy to prove themselves.
+
+   -- Running one instruction is equal to just executing it
+   runOne <- lemma "runOne"
+                   (\(Forall @"es" (es :: EnvStack nm val)) (Forall @"i" i) -> run es [i] .== execute es i)
+                   []
+
+   -- Same for two
+   runTwo <- calc "runTwo"
+                   (\(Forall @"es" (es :: EnvStack nm val)) (Forall @"i" i) (Forall @"j" j)
+                             -> run es [i, j] .== execute (execute es i) j) $
+                   \es i j -> [] |- run es [i, j]
+                                 =: run (execute es i) [j]
+                                 =: execute (execute es i) j
+                                 =: qed
+
+   -- Provers struggle with multiplication, so help them a bit here even though this is really
+   -- a trivial proof. What's hard is the correct instantiation of it, so abstracting it away helps
+   -- us speed up the solver.
+   runMul <- lemma "runMul"
+                    (\(Forall @"a" a) (Forall @"b" b) (Forall  @"env" (env :: Env nm val)) (Forall @"stk" stk)
+                                 ->   execute (tuple (env, push a (push b stk))) sIMul
+                                 .==  tuple (env, push (a * b) stk))
+                   []
+
+   -- We will use the size of the expression as the measure. We need to show that it is
+   -- always positive for the inductive proof to go thru.
+   measureNonNeg <- inductiveLemma "measureNonNeg"
+                                   (\(Forall @"e" (e :: SExpr nm val)) -> size e .>= 0)
+                                   []
+
+   -- A more general version of the theorem, starting with an arbitrary env and stack.
+   -- We prove this using the induction principle for expressions.
+   helper <- sInductWith cvc5 "helper"
+               (\(Forall @"e" e) (Forall @"env" (env :: Env nm val)) (Forall @"stk" stk) ->
+                             run (tuple (env, stk)) (compile e)
+                         .== tuple (env, push (interpInEnv env e) stk))
+               (\e _ _  -> size e, [proofOf measureNonNeg]) $
+               \ih e env stk -> []
+                 |- [pCase| e of
+                      Var nm     -> run (tuple (env, stk)) (compile (sVar nm))
+                                 ?? "case Var"
+                                 =: run (tuple (env, stk)) [sIPushN nm]
+                                 =: tuple (env, push (interpInEnv env (sVar nm)) stk)
+                                 =: qed
+
+                      Con v      -> run (tuple (env, stk)) (compile (sCon v))
+                                 ?? "case Con"
+                                 =: run (tuple (env, stk)) [sIPushV v]
+                                 =: tuple (env, push v stk)
+                                 =: tuple (env, push (interpInEnv env (sCon v)) stk)
+                                 =: qed
+
+                      Sqr a      -> run (tuple (env, stk)) (compile (sSqr a))
+                                 ?? "case Sqr"
+                                 =: run (tuple (env, stk)) (compile a SL.++ [sIDup, sIMul])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk)) (compile a)) [sIDup, sIMul]
+                                 ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                 =: let stk' = push (interpInEnv env a) stk
+                                 in run (tuple (env, stk')) [sIDup, sIMul]
+                                 ?? runTwo `at` (Inst @"es" (tuple (env, stk')), Inst @"i" sIDup, Inst @"j" sIMul)
+                                 =: execute (execute (tuple (env, stk')) sIDup) sIMul
+                                 =: let stk'' = push (interpInEnv env a) stk'
+                                 in execute (tuple (env, stk'')) sIMul
+                                 =: tuple (env, push (interpInEnv env a * interpInEnv env a) stk)
+                                 =: tuple (env, push (interpInEnv env (sSqr a)) stk)
+                                 =: qed
+
+                      Inc a      -> run (tuple (env, stk)) (compile (sInc a))
+                                 ?? "case Inc"
+                                 =: run (tuple (env, stk)) (compile a SL.++ [sIPushV 1, sIAdd])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk)) (compile a)) [sIPushV 1, sIAdd]
+                                 ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                 =: let stk' = push (interpInEnv env a) stk
+                                 in run (tuple (env, stk')) [sIPushV 1, sIAdd]
+                                 ?? runTwo `at` (Inst @"es" (tuple (env, stk')), Inst @"i" (sIPushV 1), Inst @"j" sIAdd)
+                                 =: execute (execute (tuple (env, stk')) (sIPushV 1)) sIAdd
+                                 =: let stk'' = push 1 stk'
+                                 in execute (tuple (env, stk'')) sIAdd
+                                 =: tuple (env, push (1 + interpInEnv env a) stk)
+                                 =: tuple (env, push (interpInEnv env (sInc a)) stk)
+                                 =: qed
+
+                      Add a b    -> run (tuple (env, stk)) (compile (sAdd a b))
+                                 ?? "case sAdd"
+                                 =: run (tuple (env, stk)) (compile a SL.++ compile b SL.++ [sIAdd])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk)) (compile a)) (compile b SL.++ [sIAdd])
+                                 ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                 =: let stk' = push (interpInEnv env a) stk
+                                 in run (tuple (env, stk')) (compile b SL.++ [sIAdd])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk')) (compile b)) [sIAdd]
+                                 ?? ih `at` (Inst @"e" b, Inst @"env" env, Inst @"stk" stk')
+                                 =: let stk'' = push (interpInEnv env b) stk'
+                                 in run (tuple (env, stk'')) [sIAdd]
+                                 ?? runOne `at` (Inst @"es" (tuple (env, stk'')), Inst @"i" sIAdd)
+                                 =: execute (tuple (env, stk'')) sIAdd
+                                 =: tuple (env, push (interpInEnv env b + interpInEnv env a) stk)
+                                 =: tuple (env, push (interpInEnv env a + interpInEnv env b) stk)
+                                 =: tuple (env, push (interpInEnv env (sAdd a b)) stk)
+                                 =: qed
+
+                      Mul a b    -> run (tuple (env, stk)) (compile (sMul a b))
+                                 ?? "case sMul"
+                                 =: run (tuple (env, stk)) (compile a SL.++ compile b SL.++ [sIMul])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk)) (compile a)) (compile b SL.++ [sIMul])
+                                 ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                 =: let stk' = push (interpInEnv env a) stk
+                                 in run (tuple (env, stk')) (compile b SL.++ [sIMul])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk')) (compile b)) [sIMul]
+                                 ?? ih `at` (Inst @"e" b, Inst @"env" env, Inst @"stk" stk')
+                                 =: let stk'' = push (interpInEnv env b) stk'
+                                 in run (tuple (env, stk'')) [sIMul]
+                                 ?? runOne `at` (Inst @"es" (tuple (env, stk'')), Inst @"i" sIMul)
+                                 =: execute (tuple (env, stk'')) sIMul
+                                 ?? runMul `at` ( Inst @"a"   (interpInEnv env b)
+                                                , Inst @"b"   (interpInEnv env a)
+                                                , Inst @"env" env
+                                                , Inst @"stk" stk)
+                                 =: tuple (env, push (interpInEnv env b * interpInEnv env a) stk)
+                                 =: tuple (env, push (interpInEnv env a * interpInEnv env b) stk)
+                                 =: tuple (env, push (interpInEnv env (sMul a b)) stk)
+                                 =: qed
+
+                      Let nm a b -> run (tuple (env, stk)) (compile (sLet nm a b))
+                                 ?? "case Let"
+                                 =: run (tuple (env, stk)) (compile a SL.++ [sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk)) (compile a)) ([sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                 ?? ih `at` (Inst @"e" a, Inst @"env" env, Inst @"stk" stk)
+                                 =: let stk' = push (interpInEnv env a) stk
+                                 in run (tuple (env, stk')) ([sIBind nm] SL.++ compile b SL.++ [sIForget])
+                                 ?? runSeq
+                                 =: run (run (tuple (env, stk')) [sIBind nm]) (compile b SL.++ [sIForget])
+                                 ?? runOne
+                                 =: run (execute (tuple (env, stk')) (sIBind nm)) (compile b SL.++ [sIForget])
+                                 =: let env' = push (tuple (nm, interpInEnv env a)) env
+                                 in run (tuple (env', stk)) (compile b SL.++ [sIForget])
+                                 ?? runSeq
+                                 =: run (run (tuple (env', stk)) (compile b)) [sIForget]
+                                 ?? ih `at` (Inst @"e" b, Inst @"env" env', Inst @"stk" stk)
+                                 =: let stk'' = push (interpInEnv env' b) stk
+                                 in run (tuple (env', stk'')) [sIForget]
+                                 ?? runOne
+                                 =: execute (tuple (env', stk'')) sIForget
+                                 =: tuple (env, stk'')
+                                 =: tuple (env, push (interpInEnv env (sLet nm a b)) stk)
+                                 =: qed
+                    |]
+
+   -- We can now prove the final correctness theorem, based on the helper.
+   calc "correctness"
+        (\(Forall @"expr" (e :: SExpr nm val)) -> compileAndRun e .== interp e) $
+        \(e :: SExpr nm val) -> [] |- compileAndRun e
+                                   =: top (ST.snd (run (tuple ([], [])) (compile e)))
+                                   ?? helper `at` (Inst @"e" e, Inst @"env" [], Inst @"stk" [])
+                                   =: top (ST.snd (tuple ([] :: Env nm val, push (interpInEnv [] e) [])))
+                                   =: interpInEnv [] e
+                                   =: interp e
+                                   =: qed
diff --git a/Documentation/SBV/Examples/Transformers/SymbolicEval.hs b/Documentation/SBV/Examples/Transformers/SymbolicEval.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Transformers/SymbolicEval.hs
@@ -0,0 +1,214 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Transformers.SymbolicEval
+-- Copyright : (c) Brian Schroeder
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A demonstration of the use of the t'SymbolicT' and t'QueryT' transformers in
+-- the setting of symbolic program evaluation.
+--
+-- In this example, we perform symbolic evaluation across three steps:
+--
+-- 1. allocate free variables, so we can extract a model after evaluation
+-- 2. perform symbolic evaluation of a program and an associated property
+-- 3. querying the solver for whether it's possible to find a set of program
+--    inputs that falsify the property. if there is, we extract a model.
+--
+-- To simplify the example, our programs always have exactly two integer inputs
+-- named @x@ and @y@.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveFunctor              #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE KindSignatures             #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Transformers.SymbolicEval where
+
+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(reader), asks, ReaderT, runReaderT)
+import Control.Monad.Trans    (lift)
+import Data.Kind              (Type)
+
+import Data.SBV.Dynamic   (SVal)
+import Data.SBV.Internals (SBV(SBV), unSBV)
+import Data.SBV.Trans.Control
+
+-- Data.Bits exports And, which conflicts with the definition here
+import Data.SBV.Trans hiding(And)
+
+-- * Allocation of symbolic variables, so we can extract a model later.
+
+-- | Monad for allocating free variables.
+newtype Alloc a = Alloc { runAlloc :: SymbolicT (ExceptT String IO) a }
+    deriving (Functor, Applicative, Monad, MonadIO,
+              MonadError String, MonadSymbolic)
+
+-- | Environment holding allocated variables.
+data Env = Env { envX   :: SBV Integer
+               , envY   :: SBV Integer
+               , result :: Maybe SVal -- could be integer or bool. during
+                                      -- program evaluation, this is Nothing.
+                                      -- we only have a value during property
+                                      -- evaluation.
+               }
+    deriving Show
+
+-- | Allocate an integer variable with the provided name.
+alloc :: String -> Alloc (SBV Integer)
+alloc "" = throwError "tried to allocate unnamed value"
+alloc nm = free nm
+
+-- | Allocate an t'Env' holding all input variables for the program.
+allocEnv :: Alloc Env
+allocEnv = do
+    x <- alloc "x"
+    y <- alloc "y"
+    pure $ Env x y Nothing
+
+-- * Symbolic term evaluation
+
+-- | The term language we use to express programs and properties.
+data Term :: Type -> Type where
+    Var         :: String                       -> Term r
+    Lit         :: Integer                      -> Term Integer
+    Plus        :: Term Integer -> Term Integer -> Term Integer
+    LessThan    :: Term Integer -> Term Integer -> Term Bool
+    GreaterThan :: Term Integer -> Term Integer -> Term Bool
+    Equals      :: Term Integer -> Term Integer -> Term Bool
+    Not         :: Term Bool                    -> Term Bool
+    Or          :: Term Bool    -> Term Bool    -> Term Bool
+    And         :: Term Bool    -> Term Bool    -> Term Bool
+    Implies     :: Term Bool    -> Term Bool    -> Term Bool
+
+-- | Monad for performing symbolic evaluation.
+newtype Eval a = Eval { unEval :: ReaderT Env (Except String) a }
+    deriving (Functor, Applicative, Monad, MonadReader Env, MonadError String)
+
+-- | Unsafe cast for symbolic values. In production code, we would check types instead.
+unsafeCastSBV :: SBV a -> SBV b
+unsafeCastSBV = SBV . unSBV
+
+-- | Symbolic evaluation function for 'Term'.
+eval :: Term r -> Eval (SBV r)
+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"
+                                Just sv -> pure $ SBV sv
+eval (Var _)             = throwError "unknown variable"
+eval (Lit i)             = pure $ literal i
+eval (Plus        t1 t2) = (+)   <$> eval t1 <*> eval t2
+eval (LessThan    t1 t2) = (.<)  <$> eval t1 <*> eval t2
+eval (GreaterThan t1 t2) = (.>)  <$> eval t1 <*> eval t2
+eval (Equals      t1 t2) = (.==) <$> eval t1 <*> eval t2
+eval (Not         t)     = sNot  <$> eval t
+eval (Or          t1 t2) = (.||) <$> eval t1 <*> eval t2
+eval (And         t1 t2) = (.&&) <$> eval t1 <*> eval t2
+eval (Implies     t1 t2) = (.=>) <$> eval t1 <*> eval t2
+
+-- | Runs symbolic evaluation, sending a 'Term' to a symbolic value (or
+-- failing). Used for symbolic evaluation of programs and properties.
+runEval :: Env -> Term a -> Except String (SBV a)
+runEval env term = runReaderT (unEval $ eval term) env
+
+-- | A program that can reference two input variables, @x@ and @y@.
+newtype Program a = Program (Term a)
+
+-- | A symbolic value representing the result of running a program -- its
+-- output.
+newtype Result = Result SVal
+
+-- | Makes a t'Result' from a symbolic value.
+mkResult :: SBV a -> Result
+mkResult = Result . unSBV
+
+-- | Performs symbolic evaluation of a t'Program'.
+runProgramEval :: Env -> Program a -> Except String Result
+runProgramEval env (Program term) = mkResult <$> runEval env term
+
+-- * Property evaluation
+
+-- | A property describes a quality of a t'Program'. It is a 'Term' yields a
+-- boolean value.
+newtype Property = Property (Term Bool)
+
+-- | Performs symbolic evaluation of a t'Property.
+runPropertyEval :: Result -> Env -> Property -> Except String (SBV Bool)
+runPropertyEval (Result res) env (Property term) =
+    runEval (env { result = Just res }) term
+
+-- * Checking whether a program satisfies a property
+
+-- | The result of 'check'ing the combination of a t'Program' and a t'Property'.
+data CheckResult = Proved | Counterexample Integer Integer
+    deriving (Eq, Show)
+
+-- | Sends an 'Identity' computation to an arbitrary monadic computation.
+generalize :: Monad m => Identity a -> m a
+generalize = pure . runIdentity
+
+-- | Monad for querying a solver.
+newtype Q a = Q { runQ :: QueryT (ExceptT String IO) a }
+    deriving (Functor, Applicative, Monad, MonadIO, MonadError String, MonadQuery)
+
+-- | Creates a computation that queries a solver and yields a 'CheckResult'.
+mkQuery :: Env -> Q CheckResult
+mkQuery env = do
+    satResult <- checkSat
+    case satResult of
+        Sat    -> Counterexample <$> getValue (envX env)
+                                 <*> getValue (envY env)
+        Unsat  -> pure Proved
+        DSat{} -> throwError "delta-sat"
+        Unk    -> throwError "unknown"
+
+-- | Checks a t'Property' of a t'Program' (or fails).
+check :: Program a -> Property -> IO (Either String CheckResult)
+check program prop = runExceptT $ runSMTWith z3 $ do
+    env <- runAlloc allocEnv
+    test <- lift $ mapExceptT generalize $ do
+        res <- runProgramEval env program
+        runPropertyEval res env prop
+    constrain $ sNot test
+    query $ runQ $ mkQuery env
+
+-- * Some examples
+
+-- | Check that @x+1+y@ generates a counter-example for the property that the
+-- result is less than @10@ when @x+y@ is at least @9@. We have:
+--
+-- >>> ex1
+-- Right (Counterexample 0 9)
+ex1 :: IO (Either String CheckResult)
+ex1 = check (Program  $ Var "x" `Plus` Lit 1 `Plus` Var "y")
+            (Property $ Var "result" `LessThan` Lit 10)
+
+-- | Check that the program @x+y@ correctly produces a result greater than @1@ when
+-- both @x@ and @y@ are at least @1@. We have:
+--
+-- >>> ex2
+-- Right Proved
+ex2 :: IO (Either String CheckResult)
+ex2 = check (Program  $ Var "x" `Plus` Var "y")
+            (Property $ (positive (Var "x") `And` positive (Var "y"))
+                `Implies` (Var "result" `GreaterThan` Lit 1))
+  where positive t = t `GreaterThan` Lit 0
+
+-- | Check that we catch the cases properly through the monad stack when there is a
+-- syntax error, like an undefined variable. We have:
+--
+-- >>> ex3
+-- Left "unknown variable"
+ex3 :: IO (Either String CheckResult)
+ex3 = check (Program  $ Var "notAValidVar")
+            (Property $ Var "result" `LessThan` Lit 10)
+
+{- HLint ignore module "Use fewer imports" -}
diff --git a/Documentation/SBV/Examples/Uninterpreted/AUF.hs b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.AUF
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Formalizes and proves the following theorem about arithmetic,
+-- uninterpreted functions, and arrays. (For reference, see <http://research.microsoft.com/en-us/um/redmond/projects/z3/fmcad06-slides.pdf>
+-- slide number 24):
+--
+-- @
+--    x + 2 = y  implies  f (read (write (a, x, 3), y - 2)) = f (y - x + 1)
+-- @
+--
+-- We interpret the types as follows (other interpretations certainly possible):
+--
+--    [/x/] 'SWord32' (32-bit unsigned address)
+--
+--    [/y/] 'SWord32' (32-bit unsigned address)
+--
+--    [/a/] An array, indexed by 32-bit addresses, returning 32-bit unsigned integers
+--
+--    [/f/] An uninterpreted function of type @'SWord32' -> 'SWord64'@
+--
+-- The function @read@ and @write@ are usual array operations.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.AUF where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | Uninterpreted function in the theorem
+f :: SWord32 -> SWord64
+f = uninterpret "f"
+
+-- | Correctness theorem. We state it for all values of @x@, @y@, and the given array @a@. We have:
+--
+-- >>> prove thm
+-- Q.E.D.
+thm :: SWord32 -> SWord32 -> SArray Word32 Word32 -> SBool
+thm x y a = lhs .=> rhs
+  where lhs = x + 2 .== y
+        rhs =     f (readArray (writeArray a x 3) (y - 2))
+              .== f (y - x + 1)
diff --git a/Documentation/SBV/Examples/Uninterpreted/Deduce.hs b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
@@ -0,0 +1,71 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.Deduce
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates uninterpreted sorts and how they can be used for deduction.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Deduce where
+
+import Data.SBV
+
+-- we will have our own "uninterpreted" functions corresponding
+-- to not/or/and, so hide their Prelude counterparts.
+import Prelude hiding (not, or, and)
+
+-----------------------------------------------------------------------------
+-- * Representing uninterpreted booleans
+-----------------------------------------------------------------------------
+
+-- | The uninterpreted sort 'B', corresponding to the carrier.
+data B
+
+-- | Make this sort uninterpreted. This splice will automatically introduce
+-- the type 'SB' into the environment, as a synonym for 'SBV' 'B'.
+mkSymbolic [''B]
+
+-----------------------------------------------------------------------------
+-- * Uninterpreted connectives over 'B'
+-----------------------------------------------------------------------------
+
+-- | Uninterpreted logical connective 'and'
+and :: SB -> SB -> SB
+and = uninterpret "AND"
+
+-- | Uninterpreted logical connective 'or'
+or :: SB -> SB -> SB
+or  = uninterpret "OR"
+
+-- | Uninterpreted logical connective 'not'
+not :: SB -> SB
+not = uninterpret "NOT"
+
+-----------------------------------------------------------------------------
+-- * Demonstrated deduction
+-----------------------------------------------------------------------------
+
+-- | Proves the equivalence @NOT (p OR (q AND r)) == (NOT p AND NOT q) OR (NOT p AND NOT r)@,
+-- following from the axioms we have specified above. We have:
+--
+-- >>> test
+-- Q.E.D.
+test :: IO ThmResult
+test = prove $ do constrain $ \(Forall p) (Forall q) (Forall r) -> (p `or` q) `and` (p `or` r) .== p `or` (q `and` r)
+                  constrain $ \(Forall p) (Forall q)            -> not (p `or` q) .== not p `and` not q
+                  constrain $ \(Forall p)                       -> not (not p) .== p
+                  p <- free "p"
+                  q <- free "q"
+                  r <- free "r"
+                  pure $   not (p `or` (q `and` r))
+                       .== (not p `and` not q) `or` (not p `and` not r)
+
+-- Hlint gets confused and thinks the use of @not@ above is from the prelude. Sigh.
+{- HLint ignore test "Redundant not" -}
diff --git a/Documentation/SBV/Examples/Uninterpreted/EUFLogic.hs b/Documentation/SBV/Examples/Uninterpreted/EUFLogic.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/EUFLogic.hs
@@ -0,0 +1,340 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.EUFLogic
+-- License   : BSD3
+-- Stability : experimental
+--
+-- Demonstrates the ability to generate uninterpreted functions of arbitrarily
+-- many arguments, whose types are generated programmatically. The high-level
+-- idea of this module is to provide a strongly-typed representation, using a
+-- GADT, of a logic that includes uninterpreted functions. This module then
+-- defines an interpretation of this logic into SBV, which it uses to perform
+-- SMT queries in the logic.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                  #-}
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE GADTs                #-}
+{-# LANGUAGE RankNTypes           #-}
+{-# LANGUAGE TypeFamilies         #-}
+{-# LANGUAGE TypeOperators        #-}
+{-# LANGUAGE UndecidableInstances #-}
+
+module Documentation.SBV.Examples.Uninterpreted.EUFLogic where
+
+import Data.SBV
+
+import Control.Monad.State
+
+import Data.Kind
+import Data.Type.Equality
+import Data.Map (Map)
+import qualified Data.Map as Map
+
+import GHC.TypeLits
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+----------------------------------------------------------------------
+-- * Types of the EUF Logic
+----------------------------------------------------------------------
+
+-- | The datakind for the types in our EUF logic.
+data EUFType = Tp_Bool | Tp_BV Natural
+
+-- | A singleton type for natural numbers that can be used as the widths of bitvectors.
+data BVWidth w = (KnownNat w, BVIsNonZero w) => BVWidth (SNat w)
+
+-- | Create a t'BVWidth' object for a 'KnownNat' that is non-zero
+knownBVWidth :: (KnownNat w, BVIsNonZero w) => BVWidth w
+knownBVWidth = BVWidth natSing
+
+-- | TestEquality instance for BVWidth.
+instance TestEquality BVWidth where
+  testEquality (BVWidth w1) (BVWidth w2) | Just Refl <- testEquality w1 w2 = Just Refl
+                                         | True                            = Nothing
+
+-- | A singleton type that represents type-level 'EUFType's at the object level
+data TypeRepr (tp :: EUFType) where
+  Repr_Bool :: TypeRepr Tp_Bool
+  Repr_BV   :: BVWidth w -> TypeRepr (Tp_BV w)
+
+-- | TestEquality instance for Type representations
+instance TestEquality TypeRepr where
+  testEquality Repr_Bool    Repr_Bool                                      = Just Refl
+  testEquality (Repr_BV w1) (Repr_BV w2) | Just Refl <- testEquality w1 w2 = Just Refl
+  testEquality _            _                                              = Nothing
+
+-- | A list of 'TypeRepr's for each type in a type-level list
+data TypeReprs tps where
+  Repr_Nil  :: TypeReprs '[]
+  Repr_Cons :: TypeRepr tp -> TypeReprs tps -> TypeReprs (tp ': tps)
+
+instance TestEquality TypeReprs where
+  testEquality Repr_Nil             Repr_Nil                                                    = Just Refl
+  testEquality (Repr_Cons tps1 tp1) (Repr_Cons tps2 tp2) | Just Refl <- testEquality tps1 tps2
+                                                         , Just Refl <- testEquality tp1  tp2   = Just Refl
+  testEquality _                    _                                                           = Nothing
+
+-- | An 'EUFType' with a known 'TypeRepr' representation
+class KnownEUFType tp where
+  knownEUFType :: TypeRepr tp
+
+-- | Mapping from Tp_Bool
+instance KnownEUFType Tp_Bool where
+  knownEUFType = Repr_Bool
+
+-- | Mapping from Tp_BV
+instance (KnownNat w, BVIsNonZero w) => KnownEUFType (Tp_BV w) where
+  knownEUFType = Repr_BV (BVWidth natSing)
+
+-- | A sequence of types t'EUFType' with a known 'TypeReprs' representation
+class KnownEUFTypes tps where
+  knownEUFTypes :: TypeReprs tps
+
+instance KnownEUFTypes '[] where
+  knownEUFTypes = Repr_Nil
+
+instance (KnownEUFType tp, KnownEUFTypes tps) => KnownEUFTypes (tp ': tps) where
+  knownEUFTypes = Repr_Cons knownEUFType knownEUFTypes
+
+----------------------------------------------------------------------
+-- * Operations of the EUF Logic
+----------------------------------------------------------------------
+
+-- | An uninterpreted function in our EUF logic, which is a string name plus the input and output types.
+data UnintOp (ins :: [EUFType]) (out :: EUFType) = UnintOp { unintOpName :: String
+                                                           , unintOpIns :: TypeReprs ins
+                                                           , unintOpOut :: TypeRepr  out
+                                                           }
+
+-- | The operations of our EUF logic, which are indexed by a list of 0 or more
+-- input types and a single output type.
+data Op (ins :: [EUFType]) (out :: EUFType) where
+  -- Uninterpreted functions
+  Op_Unint :: UnintOp ins out -> Op ins out
+
+  -- Boolean operations
+  Op_And        :: Op (Tp_Bool ': Tp_Bool ': '[]) Tp_Bool
+  Op_Or         :: Op (Tp_Bool ': Tp_Bool ': '[]) Tp_Bool
+  Op_Not        :: Op (Tp_Bool ': '[])            Tp_Bool
+  Op_BoolLit    :: Bool -> Op '[] Tp_Bool
+  Op_IfThenElse :: TypeRepr a -> Op (Tp_Bool ': a ': a ': '[]) a
+
+  -- Bitvector operations
+  Op_Plus   :: BVWidth w -> Op (Tp_BV w ': Tp_BV w ': '[]) (Tp_BV w)
+  Op_Minus  :: BVWidth w -> Op (Tp_BV w ': Tp_BV w ': '[]) (Tp_BV w)
+  Op_Times  :: BVWidth w -> Op (Tp_BV w ': Tp_BV w ': '[]) (Tp_BV w)
+
+  Op_Abs    :: BVWidth w -> Op (Tp_BV w ': '[]) (Tp_BV w)
+  Op_Signum :: BVWidth w -> Op (Tp_BV w ': '[]) (Tp_BV w)
+
+  Op_BVLit  :: BVWidth w -> Integer -> Op '[] (Tp_BV w)
+
+  Op_BVEq   :: BVWidth w -> Op (Tp_BV w ': Tp_BV w ': '[]) Tp_Bool
+  Op_BVLt   :: BVWidth w -> Op (Tp_BV w ': Tp_BV w ': '[]) Tp_Bool
+
+-- | Create an uninterpreted 'Op' of known type
+mkUnintOp :: (KnownEUFTypes ins, KnownEUFType out) => String -> Op ins out
+mkUnintOp nm = Op_Unint $ UnintOp nm knownEUFTypes knownEUFType
+
+-- | Get the input types and output type of an 'Op'
+opInsOut :: Op ins out -> (TypeReprs ins, TypeRepr out)
+opInsOut (Op_Unint uop)                      = (unintOpIns uop, unintOpOut uop)
+opInsOut Op_And                              = (knownEUFTypes, knownEUFType)
+opInsOut Op_Or                               = (knownEUFTypes, knownEUFType)
+opInsOut Op_Not                              = (knownEUFTypes, knownEUFType)
+opInsOut (Op_BoolLit _)                      = (knownEUFTypes, knownEUFType)
+opInsOut (Op_IfThenElse Repr_Bool)           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_IfThenElse (Repr_BV BVWidth{})) = (knownEUFTypes, knownEUFType)
+opInsOut (Op_Plus       BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_Minus      BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_Times      BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_Abs        BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_Signum     BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_BVLit      BVWidth{} _)         = (knownEUFTypes, knownEUFType)
+opInsOut (Op_BVEq       BVWidth{})           = (knownEUFTypes, knownEUFType)
+opInsOut (Op_BVLt       BVWidth{})           = (knownEUFTypes, knownEUFType)
+
+-- | Get the input types of an 'Op'
+opIns :: Op ins out -> TypeReprs ins
+opIns = fst . opInsOut
+
+----------------------------------------------------------------------
+-- * Expressions of the EUF Logic
+----------------------------------------------------------------------
+
+-- | The expressions of our EUF logic, which are just operations applied to argument expressions.
+data EUFExpr tp where
+  EUFExpr :: Op ins out -> EUFExprs ins -> EUFExpr out
+
+-- | A sequence of expressions for each type in a type-level list
+data EUFExprs tps where
+  EUFExprsNil  :: EUFExprs '[]
+  EUFExprsCons :: EUFExpr tp -> EUFExprs tps -> EUFExprs (tp ': tps)
+
+-- | Build the type @t'EUFExpr' in1 -> ... -> t'EUFExpr' inn -> out@
+type family EUFExprFun (ins :: [EUFType]) (out :: EUFType) :: Type where
+  EUFExprFun '[]         out = EUFExpr out
+  EUFExprFun (tp ': tps) out = EUFExpr tp -> EUFExprFun tps out
+
+-- | Build an t'EUFExprFun' from a function on t'EUFExprs'
+lambdaEUFExprFun :: TypeReprs ins -> (EUFExprs ins -> EUFExpr out) -> EUFExprFun ins out
+lambdaEUFExprFun Repr_Nil          f = f EUFExprsNil
+lambdaEUFExprFun (Repr_Cons _ tps) f = \e -> lambdaEUFExprFun tps (f . EUFExprsCons e)
+
+-- | Apply an 'Op' to t'EUFExprs' for its input types, returning an t'EUFExpr' for its output type
+applyOp :: Op ins out -> EUFExprFun ins out
+applyOp op = lambdaEUFExprFun (opIns op) (EUFExpr op)
+
+instance (KnownNat w, BVIsNonZero w) => Num (EUFExpr (Tp_BV w)) where
+  fromInteger i = applyOp (Op_BVLit knownBVWidth i)
+
+  e1 + e2 = applyOp (Op_Plus  knownBVWidth) e1 e2
+  e1 - e2 = applyOp (Op_Minus knownBVWidth) e1 e2
+  e1 * e2 = applyOp (Op_Times knownBVWidth) e1 e2
+
+  abs    e = applyOp (Op_Abs    knownBVWidth) e
+  signum e = applyOp (Op_Signum knownBVWidth) e
+
+-- | Build an expression from an uninterpreted operation of a known type
+mkUnintExpr :: KnownEUFType tp => String -> EUFExpr tp
+mkUnintExpr nm = EUFExpr (mkUnintOp nm) EUFExprsNil
+
+----------------------------------------------------------------------
+-- * Interpreting the EUF Logic into SBV
+----------------------------------------------------------------------
+
+-- | Convert an 'EUFType' to a type of SBV expressions
+type family Type2SBV (tp :: EUFType) :: Type where
+  Type2SBV Tp_Bool   = SBool
+  Type2SBV (Tp_BV w) = SBV (WordN w)
+
+-- | Convert the type inputs plus output of an 'Op' to a function over 'SBV' values
+type family OpTypes2SBV (ins :: [EUFType]) (out :: EUFType) :: Type where
+  OpTypes2SBV '[] out         = Type2SBV out
+  OpTypes2SBV (tp ': tps) out = Type2SBV tp -> OpTypes2SBV tps out
+
+-- | Create an 'SMTDefinable' instance for the type returned by 'OpTypes2SBV' and pass it to a local function
+withSMTDefOpTypes :: TypeReprs ins -> TypeRepr out -> (SMTDefinable (OpTypes2SBV ins out) => a) -> a
+withSMTDefOpTypes Repr_Nil                            Repr_Bool           f = f
+withSMTDefOpTypes Repr_Nil                            (Repr_BV BVWidth{}) f = f
+withSMTDefOpTypes (Repr_Cons Repr_Bool ins)           out                 f = withSMTDefOpTypes ins out f
+withSMTDefOpTypes (Repr_Cons (Repr_BV BVWidth{}) ins) out                 f = withSMTDefOpTypes ins out f
+
+-- | An uninterpreted function that has been resolved to an 'SBV' function
+data ResolvedUnintOp = forall ins out. ResolvedUnintOp (UnintOp ins out) (OpTypes2SBV ins out)
+
+-- | A 'Map' for resolving uninterpreted operations
+type UnintMap = Map String ResolvedUnintOp
+
+-- | Look up the uninterpreted op associated with a 'String' in an 'UnintMap' at
+-- a particular type, raising an error if that 'String' is associated with a
+-- different type. If the 'String' is not associated with any uninterpreted
+-- function, create one and return it, updating the 'UnintMap'.
+unintEnsure :: UnintOp ins out -> UnintMap -> (OpTypes2SBV ins out, UnintMap)
+unintEnsure uop m
+  | Just (ResolvedUnintOp uop' f) <- Map.lookup (unintOpName uop) m
+  , Just Refl <- testEquality (unintOpIns uop) (unintOpIns uop')
+  , Just Refl <- testEquality (unintOpOut uop) (unintOpOut uop')
+  = (f, m)
+unintEnsure uop m
+  | Just _ <- Map.lookup (unintOpName uop) m
+  = error $ "unintEnsure: uninterpreted op " ++ unintOpName uop ++ " used at incorrect type"
+unintEnsure uop m =
+  withSMTDefOpTypes (unintOpIns uop) (unintOpOut uop)
+     $ let f = uninterpret (unintOpName uop)
+       in (f, Map.insert (unintOpName uop) (ResolvedUnintOp uop f) m)
+
+-- | The monad for interpreting t'EUFExpr's into SBV, which is just a state monad
+-- over an 'UnintMap'
+type InterpM = State UnintMap
+
+-- | Run an 'InterpM' computation starting with the empty 'UnintMap'
+runInterpM :: InterpM a -> a
+runInterpM = flip evalState Map.empty
+
+-- | Interpret an 'Op' into a function over SBV values
+interpOp :: Op ins out -> InterpM (OpTypes2SBV ins out)
+interpOp (Op_Unint uop)                      = state (unintEnsure uop)
+interpOp Op_And                              = pure (.&&)
+interpOp Op_Or                               = pure (.||)
+interpOp Op_Not                              = pure sNot
+interpOp (Op_BoolLit    b)                   = pure $ fromBool b
+interpOp (Op_IfThenElse Repr_Bool)           = pure ite
+interpOp (Op_IfThenElse (Repr_BV BVWidth{})) = pure ite
+interpOp (Op_Plus       BVWidth{})           = pure (+)
+interpOp (Op_Minus      BVWidth{})           = pure (-)
+interpOp (Op_Times      BVWidth{})           = pure (*)
+interpOp (Op_Abs        BVWidth{})           = pure abs
+interpOp (Op_Signum     BVWidth{})           = pure signum
+interpOp (Op_BVLit      BVWidth{} i)         = pure $ fromInteger i
+interpOp (Op_BVEq       BVWidth{})           = pure (.==)
+interpOp (Op_BVLt       BVWidth{})           = pure (.<)
+
+-- | Interpret an t'EUFExpr' into an SBV value.
+interpEUFExpr :: EUFExpr tp -> InterpM (Type2SBV tp)
+interpEUFExpr (EUFExpr op args) = do f <- interpOp op
+                                     interpApplyEUFExprs op f args
+
+-- | Apply an interpretation of an operator to the interpretations of a sequence of arguments for it.
+interpApplyEUFExprs :: ghost out -> OpTypes2SBV ins out -> EUFExprs ins -> InterpM (Type2SBV out)
+interpApplyEUFExprs _   f EUFExprsNil         = pure f
+interpApplyEUFExprs out f (EUFExprsCons e es) = do f_app <- f <$> interpEUFExpr e
+                                                   interpApplyEUFExprs out f_app es
+
+-- | Top-level call to interpret an t'EUFExpr' to an 'SBV' value
+interpEUF :: EUFExpr a -> Type2SBV a
+interpEUF = runInterpM . interpEUFExpr
+
+----------------------------------------------------------------------
+-- * Examples
+----------------------------------------------------------------------
+
+-- | Example EUF problem
+--
+-- > f (f (a) - f (b)) /= f (c), b >= a, a >= b + c, c >= 0
+--
+-- from <https://goto.ucsd.edu/~rjhala/classes/sp13/cse291/slides/lec-smt.markdown.pdf>
+-- noting that @x >= y@ is the same as @not (x < y)@. We have:
+--
+-- >>> sat $ interpEUF example
+-- Satisfiable. Model:
+--   a =  996506182 :: Word32
+--   b = 3298461113 :: Word32
+--   c = 1445036292 :: Word32
+-- <BLANKLINE>
+--   f :: Word32 -> Word32
+--   f 0          = 4188219399
+--   f 1445036292 = 285239361
+--   f 3298461113 = 4054018119
+--   f 996506182  = 4054018119
+--   f _          = 0
+--
+--  Note that the original example is unsatisfiable over integers. It is however satisfiable
+--  over 32-bit words, hence the model above.
+example :: EUFExpr Tp_Bool
+example =
+  applyOp Op_And (applyOp Op_Not (applyOp (Op_BVEq knownBVWidth)
+                                          (applyOp f (applyOp f a - applyOp f b))
+                                          (applyOp f c)))
+                 (applyOp Op_And (applyOp Op_Not (applyOp (Op_BVLt knownBVWidth) b a))
+                                 (applyOp Op_And
+                                          (applyOp Op_Not (applyOp (Op_BVLt knownBVWidth) a (b + c)))
+                                          (applyOp Op_Not (applyOp (Op_BVLt knownBVWidth) c 0))))
+  where
+    f :: Op '[Tp_BV 32] (Tp_BV 32)
+    f = mkUnintOp "f"
+
+    a, b, c :: EUFExpr (Tp_BV 32)
+    a = mkUnintExpr "a"
+    b = mkUnintExpr "b"
+    c = mkUnintExpr "c"
+
+{- HLint ignore "Use camelCase" -}
+{- HLint ignore "Eta reduce"    -}
diff --git a/Documentation/SBV/Examples/Uninterpreted/Function.hs b/Documentation/SBV/Examples/Uninterpreted/Function.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/Function.hs
@@ -0,0 +1,34 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.Function
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates function counter-examples
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Function where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | An uninterpreted function
+f :: SWord8 -> SWord8 -> SWord16
+f = uninterpret "f"
+
+-- | Asserts that @f x z == f (y+2) z@ whenever @x == y+2@. Naturally correct:
+--
+-- >>> prove thmGood
+-- Q.E.D.
+thmGood :: SWord8 -> SWord8 -> SWord8 -> SBool
+thmGood x y z = x .== y+2 .=> f x z .== f (y + 2) z
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,91 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                 #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Multiply where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | 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 defining @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  True  = True
+--   mul22_hi True  True  False True  = True
+--   mul22_hi True  False True  True  = True
+--   mul22_hi True  False False True  = True
+--   mul22_hi False True  True  False = 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, let's define the function we have synthesized  into a symbolic
+-- function:
+--
+-- >>> :{
+-- mul22_hi :: (SBool, SBool, SBool, SBool) -> SBool
+-- mul22_hi params = params `sElem` [ (sFalse, sTrue,  sTrue,  sTrue)
+--                                  , (sTrue,  sTrue,  sFalse, sTrue)
+--                                  , (sTrue,  sFalse, sTrue,  sTrue)
+--                                  , (sTrue,  sFalse, sFalse, sTrue)
+--                                  , (sFalse, sTrue,  sTrue,  sFalse)
+--                                  , (sTrue,  sTrue,  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 :: ConstraintSet
+synthMul22 = constrain $ \(Forall (a :: SWord8)) (Forall b) -> mul22 (lsb2 a) (lsb2 b) .== lsb2 (a * b)
+  where lsb2 x = case blastLE x of
+                   (x0 : x1 : _) -> (x1, x0)
+                   _             -> error "synthMul22: Can't get enough bits from x!"
diff --git a/Documentation/SBV/Examples/Uninterpreted/Shannon.hs b/Documentation/SBV/Examples/Uninterpreted/Shannon.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/Shannon.hs
@@ -0,0 +1,131 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.Shannon
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves (instances of) Shannon's expansion theorem and other relevant
+-- facts.  See: <http://en.wikipedia.org/wiki/Shannon's_expansion>
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Shannon where
+
+import Data.SBV
+
+-----------------------------------------------------------------------------
+-- * Boolean functions
+-----------------------------------------------------------------------------
+
+-- | A ternary boolean function
+type Ternary = SBool -> SBool -> SBool -> SBool
+
+-- | A binary boolean function
+type Binary = SBool -> SBool-> SBool
+
+-----------------------------------------------------------------------------
+-- * Shannon cofactors
+-----------------------------------------------------------------------------
+
+-- | Positive Shannon cofactor of a boolean function, with
+-- respect to its first argument
+pos :: (SBool -> a) -> a
+pos f = f sTrue
+
+-- | Negative Shannon cofactor of a boolean function, with
+-- respect to its first argument
+neg :: (SBool -> a) -> a
+neg f = f sFalse
+
+-----------------------------------------------------------------------------
+-- * Shannon expansion theorem
+-----------------------------------------------------------------------------
+
+-- | Shannon's expansion over the first argument of a function. We have:
+--
+-- >>> shannon
+-- Q.E.D.
+shannon :: IO ThmResult
+shannon = prove $ \x y z -> f x y z .== (x .&& pos f y z .|| sNot x .&& neg f y z)
+ where f :: Ternary
+       f = uninterpret "f"
+
+-- | Alternative form of Shannon's expansion over the first argument of a function. We have:
+--
+-- >>> shannon2
+-- Q.E.D.
+shannon2 :: IO ThmResult
+shannon2 = prove $ \x y z -> f x y z .== ((x .|| neg f y z) .&& (sNot x .|| pos f y z))
+ where f :: Ternary
+       f = uninterpret "f"
+
+-----------------------------------------------------------------------------
+-- * Derivatives
+-----------------------------------------------------------------------------
+
+-- | Computing the derivative of a boolean function (boolean difference).
+-- Defined as exclusive-or of Shannon cofactors with respect to that
+-- variable.
+derivative :: Ternary -> Binary
+derivative f y z = pos f y z .<+> neg f y z
+
+-- | The no-wiggle theorem: If the derivative of a function with respect to
+-- a variable is constant False, then that variable does not "wiggle" the
+-- function; i.e., any changes to it won't affect the result of the function.
+-- In fact, we have an equivalence: The variable only changes the
+-- result of the function iff the derivative with respect to it is not False:
+--
+-- >>> noWiggle
+-- Q.E.D.
+noWiggle :: IO ThmResult
+noWiggle = prove $ \y z -> sNot (f' y z) .<=> pos f y z .== neg f y z
+  where f :: Ternary
+        f  = uninterpret "f"
+        f' = derivative f
+
+-----------------------------------------------------------------------------
+-- * Universal quantification
+-----------------------------------------------------------------------------
+
+-- | Universal quantification of a boolean function with respect to a variable.
+-- Simply defined as the conjunction of the Shannon cofactors.
+universal :: Ternary -> Binary
+universal f y z = pos f y z .&& neg f y z
+
+-- | Show that universal quantification is really meaningful: That is, if the universal
+-- quantification with respect to a variable is True, then both cofactors are true for
+-- those arguments. Of course, this is a trivial theorem if you think about it for a
+-- moment, or you can just let SBV prove it for you:
+--
+-- >>> univOK
+-- Q.E.D.
+univOK :: IO ThmResult
+univOK = prove $ \y z -> f' y z .=> pos f y z .&& neg f y z
+  where f :: Ternary
+        f  = uninterpret "f"
+        f' = universal f
+
+-----------------------------------------------------------------------------
+-- * Existential quantification
+-----------------------------------------------------------------------------
+
+-- | Existential quantification of a boolean function with respect to a variable.
+-- Simply defined as the conjunction of the Shannon cofactors.
+existential :: Ternary -> Binary
+existential f y z = pos f y z .|| neg f y z
+
+-- | Show that existential quantification is really meaningful: That is, if the existential
+-- quantification with respect to a variable is True, then one of the cofactors must be true for
+-- those arguments. Again, this is a trivial theorem if you think about it for a moment, but
+-- we will just let SBV prove it:
+--
+-- >>> existsOK
+-- Q.E.D.
+existsOK :: IO ThmResult
+existsOK = prove $ \y z -> f' y z .=> pos f y z .|| neg f y z
+  where f :: Ternary
+        f  = uninterpret "f"
+        f' = existential f
diff --git a/Documentation/SBV/Examples/Uninterpreted/Sort.hs b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.Sort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates uninterpreted sorts, together with axioms.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Sort where
+
+import Data.SBV
+
+-- | A new data-type that we expect to use in an uninterpreted fashion
+-- in the backend SMT solver.
+data Q
+
+-- | Make 'Q' an uninterpreted sort. This will automatically introduce the
+-- type 'SQ' into our environment, which is the symbolic version of the
+-- carrier type 'Q'.
+mkSymbolic [''Q]
+
+-- | Declare an uninterpreted function that works over Q's
+f :: SQ -> SQ
+f = uninterpret "f"
+
+-- | A satisfiable example, stating that there is an element of the domain
+-- 'Q' such that 'f' returns a different element. Note that this is valid only
+-- when the domain 'Q' has at least two elements. We have:
+--
+-- >>> t1
+-- Satisfiable. Model:
+--   x = Q_0 :: Q
+-- <BLANKLINE>
+--   f :: Q -> Q
+--   f _ = Q_1
+t1 :: IO SatResult
+t1 = sat $ do x <- free "x"
+              pure $ f x ./= x
+
+-- | This is a variant on the first example, except we also add an axiom
+-- for the sort, stating that the domain 'Q' has only one element. In this case
+-- the problem naturally becomes unsat. We have:
+--
+-- >>> t2
+-- Unsatisfiable
+t2 :: IO SatResult
+t2 = sat $ do x <- free "x"
+              constrain $ \(Forall a) (Forall b) -> a .== (b :: SQ)
+              pure $ f x ./= x
diff --git a/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
@@ -0,0 +1,88 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.UISortAllSat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates uninterpreted sorts and how all-sat behaves for them.
+-- Thanks to Eric Seidel for the idea.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP             #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.Uninterpreted.UISortAllSat where
+
+import Data.SBV
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- | A "list-like" data type, but one we plan to uninterpret at the SMT level.
+-- The actual shape is really immaterial for us.
+data L
+
+-- | Make 'L' into an uninterpreted sort, automatically introducing 'SL'
+-- as a synonym for 'SBV' 'L'.
+mkSymbolic [''L]
+
+-- | An uninterpreted "classify" function. Really, we only care about
+-- the fact that such a function exists, not what it does.
+classify :: SL -> SInteger
+classify = uninterpret "classify"
+
+-- | Formulate a query that essentially asserts a cardinality constraint on
+-- the uninterpreted sort 'L'. The goal is to say there are precisely 3
+-- such things, as it might be the case. We manage this by declaring four
+-- elements, and asserting that for a free variable of this sort, the
+-- shape of the data matches one of these three instances. That is, we
+-- assert that all the instances of the data 'L' can be classified into
+-- 3 equivalence classes. Then, allSat returns all the possible instances,
+-- which of course are all uninterpreted.
+--
+-- As expected, we have:
+--
+-- >>> allSat genLs
+-- Solution #1:
+--   l  = L_2 :: L
+--   l0 = L_0 :: L
+--   l1 = L_1 :: L
+--   l2 = L_2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L_2 = 2
+--   classify L_1 = 1
+--   classify _   = 0
+-- Solution #2:
+--   l  = L_1 :: L
+--   l0 = L_0 :: L
+--   l1 = L_1 :: L
+--   l2 = L_2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L_2 = 2
+--   classify L_1 = 1
+--   classify _   = 0
+-- Solution #3:
+--   l  = L_0 :: L
+--   l0 = L_0 :: L
+--   l1 = L_1 :: L
+--   l2 = L_2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L_2 = 2
+--   classify L_1 = 1
+--   classify _   = 0
+-- Found 3 different solutions.
+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
+           pure $ 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,113 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedLists       #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Append where
+
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import Prelude hiding ((++))
+import qualified Prelude as P
+
+import           Data.SBV.List ((++))
+import qualified Data.SBV.List as L
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state of the length program, parameterized over the element type @a@
+data AppS a = AppS { xs :: a  -- ^ The first input list
+                   , ys :: a  -- ^ The second input list
+                   , ts :: a  -- ^ Temporary variable
+                   , zs :: a  -- ^ Output
+                   }
+                   deriving (Generic, Mergeable, Traversable, Functor, Foldable)
+
+-- | Show instance, a bit more prettier than what would be derived:
+instance Show (f a) => Show (AppS (f a)) where
+  show AppS{xs, ys, ts, zs} = "{xs = " P.++ show xs P.++ ", ys = " P.++ show ys P.++ ", ts = " P.++ show ts P.++ ", zs = " P.++ show zs P.++ "}"
+
+-- | 'Queriable' instance for the program state
+instance Queriable IO (AppS (SList Integer)) where
+  type QueryResult (AppS (SList Integer)) = AppS [Integer]
+  create = AppS <$> freshVar_  <*> freshVar_  <*> freshVar_  <*> freshVar_
+
+-- | Helper type synonym
+type A = AppS (SList 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 " P.++ 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         = pure ()
+                           , 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 (AppS [Integer]))
+correctness = wpProveWith defaultWPCfg{wpVerbose=True} imperativeAppend
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Basics.hs b/Documentation/SBV/Examples/WeakestPreconditions/Basics.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Basics.hs
@@ -0,0 +1,181 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.Basics
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Some basic aspects of weakest preconditions, demonstrating programs
+-- that do not use while loops. We use a simple increment program as
+-- an example.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                   #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Basics where
+
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Control
+-- >>> import Data.SBV.Tools.WeakestPreconditions
+#endif
+
+-- * Program state
+
+-- | The state for the swap program, parameterized over a base type @a@.
+data IncS a = IncS { x :: a    -- ^ Input value
+                   , y :: a    -- ^ Output
+                   }
+                   deriving (Show, Generic, Mergeable, Traversable, Functor, Foldable)
+
+-- | Show instance for t'IncS'. 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 (IncS (SBV a)) where
+   show (IncS x y) = "{x = " ++ sh x ++ ", y = " ++ sh y ++ "}"
+     where sh v = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (IncS SInteger) where
+  type QueryResult (IncS SInteger) = IncS Integer
+  create = IncS <$> freshVar_ <*> freshVar_
+
+-- | Helper type synonym
+type I = IncS SInteger
+
+-- * The algorithm
+
+-- | The increment algorithm:
+--
+-- @
+--    y = x+1
+-- @
+--
+-- The point here isn't really that this program is interesting, but we want to
+-- demonstrate various aspects of WP proofs. So, we take a before and after
+-- program to annotate our algorithm so we can experiment later.
+algorithm :: Stmt I -> Stmt I -> Stmt I
+algorithm before after = Seq [ before
+                             , Assign $ \st@IncS{x} -> st{y = x+1}
+                             , after
+                             ]
+
+-- | Precondition for our program. Strictly speaking, we don't really need any preconditions,
+-- but for example purposes, we'll require @x@ to be non-negative.
+pre :: I -> SBool
+pre IncS{x} = x .>= 0
+
+-- | Postcondition for our program: @y@ must equal @x+1@.
+post :: I -> SBool
+post IncS{x, y} = y .== x+1
+
+-- | Stability: @x@ must remain unchanged.
+noChange :: Stable I
+noChange = [stable "x" x]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeInc :: Stmt I -> Stmt I -> Program I
+imperativeInc before after = Program { setup         = pure ()
+                                     , precondition  = pre
+                                     , program       = algorithm before after
+                                     , postcondition = post
+                                     , stability     = noChange
+                                     }
+
+-- * Correctness
+
+-- | State the correctness with respect to before/after programs. In the simple
+-- case of nothing prior/after, we have the obvious proof:
+--
+-- >>> correctness Skip Skip
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: Stmt I -> Stmt I -> IO (ProofResult (IncS Integer))
+correctness before after = wpProveWith defaultWPCfg{wpVerbose=True} (imperativeInc before after)
+
+-- * Example proof attempts
+--
+-- $examples
+
+{- $examples
+It is instructive to look at how the proof changes as we put in different @pre@ and @post@ values.
+
+== Violating the post condition
+
+If we stick in an extra increment for @y@ after, we can easily break the postcondition:
+
+>>> :set -XNamedFieldPuns
+>>> import Control.Monad (void)
+>>> void $ correctness Skip $ Assign $ \st@IncS{y} -> st{y = y+1}
+Following proof obligation failed:
+==================================
+  Postcondition fails:
+    Start: IncS {x = 0, y = 0}
+    End  : IncS {x = 0, y = 2}
+
+We're told that the program ends up in a state where @x=0@ and @y=2@, violating the requirement @y=x+1@, as expected.
+
+== Using 'assert'
+
+There are two main use cases for 'assert', which merely ends up being a call to 'Abort'.
+One is making sure the inputs are well formed. And the other is the user putting in their
+own invariants into the code.
+
+Let's assume that we only want to accept strictly positive values of @x@. We can try:
+
+>>> void $ correctness (assert "x > 0" (\st@IncS{x} -> x .> 0)) Skip
+Following proof obligation failed:
+==================================
+  Abort "x > 0" condition is satisfiable:
+    Before: IncS {x = 0, y = 0}
+    After : IncS {x = 0, y = 0}
+
+Recall that our precondition ('pre') required @x@ to be non-negative. So, we can put in something weaker and it would be fine:
+
+>>> void $ correctness (assert "x > -5" (\st@IncS{x} -> x .> -5)) Skip
+Total correctness is established.
+
+In this case the precondition to our program ensures that the 'assert' will always be satisfied.
+
+As another example, let us put a post assertion that @y@ is even:
+
+>>> void $ correctness Skip (assert "y is even" (\st@IncS{y} -> y `sMod` 2 .== 0))
+Following proof obligation failed:
+==================================
+  Abort "y is even" condition is satisfiable:
+    Before: IncS {x = 0, y = 0}
+    After : IncS {x = 0, y = 1}
+
+It is important to emphasize that you can put whatever invariant you might want:
+
+>>> void $ correctness Skip (assert "y > x" (\st@IncS{x, y} -> y .> x))
+Total correctness is established.
+
+== Violating stability
+
+What happens if our program modifies @x@? After all, we can simply set @x=10@ and @y=11@ and our post condition would be satisfied:
+
+>>> void $ correctness Skip (Assign $ \st -> st{x = 10, y = 11})
+Following proof obligation failed:
+==================================
+  Stability fails for "x":
+    Before: IncS {x = 0, y = 1}
+    After : IncS {x = 10, y = 11}
+
+So, the stability condition prevents programs from cheating!
+-}
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 CPP                   #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Fib where
+
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Control
+-- >>> import Data.SBV.Tools.WeakestPreconditions
+#endif
+
+-- * Program state
+
+-- | The state for the fibonacci 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, Traversable, Functor, Foldable)
+
+-- | Show instance for t'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 = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (FibS SInteger) where
+  type QueryResult (FibS SInteger) = FibS Integer
+  create = 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
+
+                   constrain $ \(Forall n) -> fib (n+2) .== fib (n+1) + fib n
+
+-- | 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,215 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                   #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.GCD where
+
+import Data.SBV
+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)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+-- >>> import Data.SBV.Control
+-- >>> import Data.SBV.Tools.WeakestPreconditions
+#endif
+
+-- * Program state
+
+-- | The state for the GCD 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, Traversable, Functor, Foldable)
+
+-- | Show instance for t'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 = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable instance for our state
+instance Queriable IO (GCDS SInteger) where
+  type QueryResult (GCDS SInteger) = GCDS Integer
+  create = 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 constrain $ \(Forall x)            -> x .> 0            .=> gcd x x     .== x
+                   constrain $ \(Forall x) (Forall y) -> x .> 0 .&& y .> 0 .=> gcd (x+y) y .== gcd x y
+                   constrain $ \(Forall x) (Forall y) -> 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,122 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.IntDiv where
+
+import Data.SBV
+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, Traversable, Functor, Foldable)
+
+-- | Show instance for t'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 = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable' instance for the program state
+instance SymVal a => Queriable IO (DivS (SBV a)) where
+  type QueryResult (DivS (SBV a)) = DivS a
+  create = 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 (WPMeasure 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 (WPMeasure D) -> Program D
+imperativeDiv inv msr = Program { setup         = pure ()
+                                , 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 :: WPMeasure 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,135 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.IntSqrt where
+
+import Data.SBV
+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, Traversable, Functor, Foldable)
+
+-- | Show instance for t'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 = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable instance for the program state
+instance SymVal a => Queriable IO (SqrtS (SBV a)) where
+  type QueryResult (SqrtS (SBV a)) = SqrtS a
+  create = 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 (WPMeasure 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 (WPMeasure S) -> Program S
+imperativeSqrt inv msr = Program { setup         = pure ()
+                                 , 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 :: WPMeasure 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,122 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Length where
+
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import qualified Data.SBV.List as L
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state of the length program, parameterized over the element type @a@
+data LenS a b = LenS { xs :: a  -- ^ The input list
+                     , ys :: a  -- ^ Copy of input
+                     , l  :: b  -- ^ Running length
+                     }
+                     deriving (Generic, Mergeable)
+
+-- | Show instance: A simplified version of what would otherwise be generated.
+instance (SymVal a, Show (f a), Show b) => Show (LenS (f a) b) where
+  show LenS{xs, ys, l} = "{xs = " ++ show xs ++ ", ys = " ++ show ys ++ ", l = " ++ show l ++ "}"
+
+-- | Injection/projection from concrete and symbolic values.
+instance Queriable IO (LenS (SList Integer) SInteger) where
+  type QueryResult (LenS (SList Integer) SInteger) = LenS [Integer] Integer
+
+  create                 = LenS <$> freshVar_  <*> freshVar_  <*> freshVar_
+  project (LenS xs ys l) = LenS <$> project xs <*> project ys <*> project l
+  embed   (LenS xs ys l) = LenS <$> embed   xs <*> embed   ys <*> embed   l
+
+-- | Helper type synonym
+type S = LenS (SList Integer) SInteger
+
+-- * 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 (WPMeasure 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 (WPMeasure S) -> Program S
+imperativeLength inv msr = Program { setup         = pure ()
+                                   , 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 :: WPMeasure 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,249 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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 CPP                   #-}
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Sum where
+
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+#ifdef DOCTEST
+-- $setup
+-- >>> import Data.SBV
+#endif
+
+-- * 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, Traversable, Functor, Foldable)
+
+-- | Show instance for t'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 = maybe "<symbolic>" show (unliteral v)
+
+-- | 'Queriable' instance for our state
+instance Queriable IO (SumS SInteger) where
+  type QueryResult (SumS SInteger) = SumS Integer
+  create = 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 (WPMeasure 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 (WPMeasure S) -> Program S
+imperativeSum inv msr = Program { setup         = pure ()
+                                , 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 (WPMeasure 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 maintained by the body:
+    Before: SumS {n = 3, i = 1, s = 1}
+    After : SumS {n = 3, 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
+/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}    = [1-i]
+>>> void $ correctness invariant (Just measure)
+Following proof obligation failed:
+==================================
+  Measure for loop "i < n" is negative:
+    State  : SumS {n = 7, i = 6, s = 21}
+    Measure: -5
+
+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 = 1, i = -1, s = 0}
+    Measure: 0
+    After  : SumS {n = 1, i = 0, s = 0}
+    Measure: 1
+
+Clearly, as @i@ increases, so does our bogus measure @n+i@. (Note that in this case the counterexample might have @i@ and @n@ as negative values, as the SMT solver finds a counter-example to induction, not
+necessarily a reachable state. Obviously, all such failures need to be addressed for the full proof.)
+-}
diff --git a/GHC/SrcLoc/Compat.hs b/GHC/SrcLoc/Compat.hs
deleted file mode 100644
--- a/GHC/SrcLoc/Compat.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-{-# LANGUAGE CPP #-}
-
--- | Compatibility shims for the SrcLoc interface across GHC versions
-
-module GHC.SrcLoc.Compat (module X) where
-
-#if MIN_VERSION_base(4,9,0)
-import SrcLoc as X hiding (srcLocFile)
-#else
-import GHC.SrcLoc as X
-#endif
diff --git a/GHC/Stack/Compat.hs b/GHC/Stack/Compat.hs
deleted file mode 100644
--- a/GHC/Stack/Compat.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-{-# LANGUAGE CPP #-}
-
--- | Compatibility shims for the Stack interface across GHC versions
-
-module GHC.Stack.Compat (module GHC.Stack) where
-import GHC.Stack
diff --git a/INSTALL b/INSTALL
--- a/INSTALL
+++ b/INSTALL
@@ -3,17 +3,9 @@
 
      cabal install sbv
 
-Once the installation is done, you will get the Data.SBV library.
-The installation will also put a binary named
-
-     SBVUnitTests
+SBV relies on an external SMT solver to be installed. We currently support
+ABC, Boolector, Bitwuzla, CVC4, CVC5, DReal, MathSAT, OpenSMT, Yices, and Z3. We recommend installing the
+freely available z3 SMT solver from Microsoft, the default solver used
+by SBV. You can get it from <http://github.com/Z3Prover/z3>.
 
-in your .cabal/bin directory (or wherever you installed it.) It's
-highly recommended that you run this program to ensure everything
-is working correctly. In particular, you will first need to install
-Z3, the default SMT solver used by sbv, from Microsoft. (You can get it
-from <http://github.com/Z3Prover/z3>.)
 Please make sure that the "z3" executable is in your path.
-
-Once you have installed sbv, you can use it in your Haskell programs
-by simply importing the Data.SBV module.
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 SBV: SMT Based Verification in Haskell
 
-Copyright (c) 2010-2017, Levent Erkok (erkokl@gmail.com)
+Copyright (c) 2010-2026, Levent Erkok (erkokl@gmail.com)
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,285 @@
-## SBV: SMT Based Verification in Haskell
+# SBV: SMT Based Verification in Haskell
 
-[![Hackage version](http://img.shields.io/hackage/v/sbv.svg?label=Hackage)](http://hackage.haskell.org/package/sbv)
-[![Build Status](http://img.shields.io/travis/LeventErkok/sbv.svg?label=Build)](http://travis-ci.org/LeventErkok/sbv)
+[![Build Status](https://github.com/LeventErkok/sbv/actions/workflows/ci.yml/badge.svg)](https://github.com/LeventErkok/sbv/actions/workflows/ci.yml)
 
-Please see: http://leventerkok.github.io/sbv/
+***Express properties about Haskell programs and automatically prove them using SMT solvers.***
+
+[Hackage](http://hackage.haskell.org/package/sbv) | [Release Notes](http://github.com/LeventErkok/sbv/tree/master/CHANGES.md) | [Documentation](http://hackage.haskell.org/package/sbv/docs/Data-SBV.html)
+
+SBV provides symbolic versions of Haskell types. Programs written with these types can be automatically verified, checked for satisfiability, optimized, or compiled to C — all via SMT solvers.
+
+## SBV in 5 Minutes
+
+Fire up GHCi with SBV:
+
+```
+$ cabal repl --build-depends sbv
+```
+
+For unbounded integers, `x + 1 .> x` is always true:
+
+```haskell
+ghci> :m Data.SBV
+ghci> prove $ \x -> x + 1 .> (x :: SInteger)
+Q.E.D.
+```
+
+But with machine arithmetic, overflow lurks:
+
+```haskell
+ghci> prove $ \x -> x + 1 .> (x :: SInt8)
+Falsifiable. Counter-example:
+  s0 = 127 :: Int8
+```
+
+IEEE-754 floats break reflexivity of equality:
+
+```haskell
+ghci> prove $ \x -> (x :: SFloat) .== x
+Falsifiable. Counter-example:
+  s0 = NaN :: Float
+```
+
+What's the multiplicative inverse of 3 modulo 256?
+
+```haskell
+ghci> sat $ \x -> x * 3 .== (1 :: SWord8)
+Satisfiable. Model:
+  s0 = 171 :: Word8
+```
+
+Use quantifiers for named results:
+
+```haskell
+ghci> sat $ skolemize $ \(Exists @"x" x) (Exists @"y" y) -> x * y .== (96::SInteger) .&& x + y .== 28
+Satisfiable. Model:
+  x = 24 :: Integer
+  y =  4 :: Integer
+```
+
+Optimize a cost function subject to constraints:
+
+```haskell
+ghci> :{
+optimize Lexicographic $ do x <- sInteger "x"
+                            y <- sInteger "y"
+                            constrain $ x + y .== 20
+                            constrain $ x .>= 5
+                            constrain $ y .>= 5
+                            minimize "cost" $ x * y
+:}
+Optimal in an extension field:
+  x    =  5 :: Integer
+  y    = 15 :: Integer
+  cost = 75 :: Integer
+```
+
+For inductive proofs and equational reasoning, SBV includes a theorem prover:
+
+```haskell
+revApp :: forall a. SymVal a => TP (Proof (Forall "xs" [a] -> Forall "ys" [a] -> SBool))
+revApp = induct "revApp"
+                 (\(Forall xs) (Forall ys) -> reverse (xs ++ ys) .== reverse ys ++ reverse xs) $
+                 \ih (x, xs) ys -> [] |- reverse ((x .: xs) ++ ys)
+                                      =: reverse (x .: (xs ++ ys))
+                                      =: reverse (xs ++ ys) ++ [x]
+                                      ?? ih
+                                      =: (reverse ys ++ reverse xs) ++ [x]
+                                      =: reverse ys ++ (reverse xs ++ [x])
+                                      =: reverse ys ++ reverse (x .: xs)
+                                      =: qed
+```
+
+```
+ghci> runTP $ revApp @Integer
+Inductive lemma: revApp
+  Step: Base                            Q.E.D.
+  Step: 1                               Q.E.D.
+  Step: 2                               Q.E.D.
+  Step: 3                               Q.E.D.
+  Step: 4                               Q.E.D.
+  Step: 5                               Q.E.D.
+  Result:                               Q.E.D.
+Functions proven terminating: sbv.reverse
+[Proven] revApp :: Ɐxs ∷ [Integer] → Ɐys ∷ [Integer] → Bool
+```
+
+## Features
+
+**Symbolic types** — Booleans, signed/unsigned integers (8/16/32/64-bit and arbitrary-width), unbounded integers, reals, rationals, IEEE-754 floats, characters, strings, lists, tuples, sums, optionals, sets, enumerations, algebraic data types, and uninterpreted sorts.
+
+**Verification** — `prove`/`sat`/`allSat` for property checking and model finding, `safe`/`sAssert` for assertion verification, `dsat`/`dprove` for delta-satisfiability, and QuickCheck integration.
+
+**Optimization** — Minimize/maximize cost functions subject to constraints via `optimize`/`maximize`/`minimize`, with support for lexicographic, independent, and Pareto objectives.
+
+**Quantifiers and functions** — Universal and existential quantifiers (including alternating), with skolemization for named bindings. Define SMT-level functions directly from Haskell via `smtFunction`, including recursive and mutually recursive definitions with automatic termination checking.
+
+**Theorem proving (TP)** — Semi-automated inductive proofs (including strong induction) with equational reasoning chains. Includes termination checking, recursive and mutually recursive definitions, productive (co-recursive) functions, and user-defined measures.
+
+**Code generation** — Compile symbolic programs to C as straight-line programs or libraries (`compileToC`, `compileToCLib`), and generate test vectors (`genTest`).
+
+**SMT interaction** — Incremental mode via `runSMT`/`query` for programmatic solver interaction with a high-level typed API. Run multiple solvers simultaneously with `proveWithAny`/`proveWithAll`.
+
+## Algebraic Data Types
+
+User-defined algebraic data types — including enumerations, recursive, and parametric types — are supported via `mkSymbolic`, with pattern matching via `sCase` (and its proof counterpart `pCase`):
+
+```haskell
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE TemplateHaskell #-}
+
+import Data.SBV
+
+data Expr a = Val a
+            | Add (Expr a) (Expr a)
+            | Mul (Expr a) (Expr a)
+            deriving Show
+
+-- Make Expr symbolically available, named SExpr
+mkSymbolic [''Expr]
+
+eval :: SymVal a => (SBV a -> SBV a -> SBV a) -> (SBV a -> SBV a -> SBV a) -> SBV (Expr a) -> SBV a
+eval add mul = smtFunction "eval" $ \e ->
+    [sCase| e of
+       Val v   -> v
+       Add x y -> eval add mul x `add` eval add mul y
+       Mul x y -> eval add mul x `mul` eval add mul y
+    |]
+```
+
+The `sCase` construct supports nested pattern matching, as-patterns, guards, and wildcards, making programming with algebraic data types natural. Plain `case` expressions inside `sCase` are automatically treated as symbolic case-splits. The `pCase` variant provides the same features for proof case-splits in the theorem proving context.
+
+## Supported SMT Solvers
+
+SBV communicates with solvers via the standard SMT-Lib interface:
+
+| Solver | From | | Solver | From |
+|--------|------|-|--------|------|
+| [ABC](http://www.eecs.berkeley.edu/~alanmi/abc) | Berkeley | | [DReal](http://dreal.github.io/) | CMU |
+| [Bitwuzla](http://bitwuzla.github.io/) | Stanford | | [MathSAT](http://mathsat.fbk.eu/) | FBK / Trento |
+| [Boolector](http://boolector.github.io/) | JKU | | [OpenSMT](http://verify.inf.usi.ch/opensmt) | USI |
+| [CVC4](http://cvc4.github.io/) | Stanford / Iowa | | [Yices](http://github.com/SRI-CSL/yices2) | SRI |
+| [CVC5](http://cvc5.github.io/) | Stanford / Iowa | | [Z3](http://github.com/Z3Prover/z3/wiki) | Microsoft |
+
+**Z3** is the default solver. Use `proveWith`, `satWith`, etc. to select a different one (e.g., `proveWith cvc5`). See [tested versions](http://github.com/LeventErkok/sbv/blob/master/SMTSolverVersions.md) for details. Other SMT-Lib compatible solvers can be hooked up with minimal effort — get in touch if you'd like to use one not listed here.
+
+## A Selection of Examples
+
+SBV ships with many worked examples. Here are some highlights:
+
+| Example | Description |
+|---------|-------------|
+| [Sudoku](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Puzzles-Sudoku.html) | Solve Sudoku puzzles using SMT constraints |
+| [N-Queens](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Puzzles-NQueens.html) | Solve the N-Queens placement puzzle |
+| [SEND + MORE = MONEY](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Puzzles-SendMoreMoney.html) | The classic cryptarithmetic puzzle |
+| [Fish/Zebra](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Puzzles-Fish.html) | Einstein's logic puzzle |
+| [SQL Injection](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Strings-SQLInjection.html) | Find inputs that cause SQL injection vulnerabilities |
+| [Regex Crossword](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Strings-RegexCrossword.html) | Solve regex crossword puzzles |
+| [BitTricks](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-BitPrecise-BitTricks.html) | Verify bit-manipulation tricks from Stanford's bithacks collection |
+| [Legato multiplier](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-BitPrecise-Legato.html) | Correctness proof of Legato's 8-bit multiplier |
+| [Prefix sum](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-BitPrecise-PrefixSum.html) | Ladner-Fischer prefix-sum implementation proof |
+| [AES](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-Crypto-AES.html) | AES encryption with C code generation |
+| [CRC](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-CodeGeneration-CRC_USB5.html) | Symbolic CRC computation with C code generation |
+| [Sqrt2 irrational](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-Sqrt2IsIrrational.html) | Prove that the square root of 2 is irrational |
+| [Sorting](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-InsertionSort.html) | Prove [insertion sort](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-InsertionSort.html), [merge sort](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-MergeSort.html), and [quick sort](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-QuickSort.html) correct |
+| [Kadane](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-Kadane.html) | Prove Kadane's maximum segment-sum algorithm correct |
+| [McCarthy91](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-McCarthy91.html) | Prove McCarthy's 91 function meets its specification |
+| [Binary search](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-BinarySearch.html) | Prove binary search correct |
+| [Collatz](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-Collatz.html) | Explore properties of the Collatz sequence |
+| [Infinitely many primes](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-Primes.html) | Prove there are infinitely many primes |
+| [Tautology checker](http://hackage.haskell.org/package/sbv/docs/Documentation-SBV-Examples-TP-TautologyChecker.html) | A verified BDD-style tautology checker |
+
+Browse the full collection in `Documentation.SBV.Examples` [on Hackage](http://hackage.haskell.org/package/sbv).
+
+## License
+
+SBV is distributed under the [BSD3](http://en.wikipedia.org/wiki/BSD_licenses) license. See [COPYRIGHT](http://github.com/LeventErkok/sbv/tree/master/COPYRIGHT) and [LICENSE](http://github.com/LeventErkok/sbv/tree/master/LICENSE) for details.
+
+Please report bugs and feature requests at the [GitHub issue tracker](http://github.com/LeventErkok/sbv/issues).
+
+## Thanks
+
+The following people made major contributions to SBV, by developing new features and contributing to the design in significant ways: Joel Burget, Brian Huffman, Brian Schroeder, and Jeffrey Young.
+
+The following people reported bugs, provided comments/feedback, or contributed to the development of SBV in various ways:
+Andreas Abel,
+Ara Adkins,
+Andrew Anderson,
+Kanishka Azimi,
+Markus Barenhoff,
+Reid Barton,
+Ben Blaxill,
+Ian Blumenfeld,
+Guillaume Bouchard,
+Martin Brain,
+Ian Calvert,
+Oliver Charles,
+Christian Conkle,
+Matthew Danish,
+Iavor Diatchki,
+Alex Dixon,
+Robert Dockins,
+Thomas DuBuisson,
+Trevor Elliott,
+Gergő Érdi,
+John Erickson,
+Richard Fergie,
+Adam Foltzer,
+Joshua Gancher,
+Remy Goldschmidt,
+Jan Grant,
+Brad Hardy,
+Tom Hawkins,
+Greg Horn,
+Jan Hrcek,
+Georges-Axel Jaloyan,
+Anders Kaseorg,
+Tom Sydney Kerckhove,
+Lars Kuhtz,
+Piërre van de Laar,
+Pablo Lamela,
+Ken Friis Larsen,
+Andrew Lelechenko,
+Joe Leslie-Hurd,
+Nick Lewchenko,
+Brett Letner,
+Sirui Lu,
+Georgy Lukyanov,
+Martin Lundfall,
+Daniel Matichuk,
+John Matthews,
+Curran McConnell,
+Philipp Meyer,
+Fabian Mitterwallner,
+Joshua Moerman,
+Matt Parker,
+Jan Path,
+Matt Peddie,
+Lucas Peña,
+Matthew Pickering,
+Lee Pike,
+Gleb Popov,
+Rohit Ramesh,
+Geoffrey Ramseyer,
+Blake C. Rawlings,
+Jaro Reinders,
+Stephan Renatus,
+Dan Rosén,
+Ryan Scott,
+Eric Seidel,
+Austin Seipp,
+Andrés Sicard-Ramírez,
+Don Stewart,
+Greg Sullivan,
+Josef Svenningsson,
+George Thomas,
+May Torrence,
+Daniel Wagner,
+Sean Weaver,
+Robin Webbers,
+Eddy Westbrook,
+Nis Wegmann,
+Jared Ziegler,
+and Marco Zocca.
+
+Thanks!
diff --git a/SBVBenchSuite/BenchSuite/Bench/Bench.hs b/SBVBenchSuite/BenchSuite/Bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Bench/Bench.hs
@@ -0,0 +1,187 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Bench.Bench
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Assessing the overhead of calling solving examples via sbv vs individual solvers
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+{-# LANGUAGE CPP                       #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts          #-}
+{-# LANGUAGE FlexibleInstances         #-}
+{-# LANGUAGE GADTs                     #-}
+{-# LANGUAGE RankNTypes                #-}
+{-# LANGUAGE RecordWildCards           #-}
+{-# LANGUAGE ScopedTypeVariables       #-}
+
+module BenchSuite.Bench.Bench
+  ( run
+  , run'
+  , runWith
+  , runIOWith
+  , runIO
+  , runPure
+  , rGroup
+  , runBenchmark
+  , onConfig
+  , onDesc
+  , runner
+  , onProblem
+  , Runner(..)
+  , using
+  ) where
+
+import           Control.DeepSeq         (NFData (..), rwhnf)
+
+import qualified Test.Tasty.Bench        as B
+import qualified Utils.SBVBenchFramework as U
+
+-- | The type of the problem to benchmark. This allows us to operate on Runners
+-- as values themselves yet still have a unified interface with gauge.
+data Problem = forall a . (U.Provable a, U.Satisfiable a) => Problem a
+
+-- | Similarly to Problem, BenchResult is boilerplate for a nice api
+data BenchResult = forall a . (Show a, NFData a) => BenchResult a
+
+-- | A runner is anything that allows the solver to solve, such as:
+-- 'Data.SBV.proveWith' or 'Data.SBV.satWith'. We utilize existential types to
+-- lose type information and create a unified interface with gauge. We
+-- require a runner in order to generate a 'Data.SBV.transcript' and then to run
+-- the actual benchmark. We bundle this redundantly into a record so that the
+-- benchmarks can be defined in each respective module, with the run function
+-- that makes sense for that problem, and then redefined in 'SBVBench'. This is
+-- useful because problems that require 'Data.SBV.allSatWith' can lead to a lot
+-- of variance in the benchmarking data. Single benchmark runners like
+-- 'Data.SBV.satWith' and 'Data.SBV.proveWith' work best.
+data RunnerI = RunnerI { runI        :: U.SMTConfig -> Problem -> IO BenchResult
+                       , config      :: U.SMTConfig
+                       , description :: String
+                       , problem     :: Problem
+                       }
+
+-- | GADT to allow arbitrary nesting of runners. This copies criterion's design
+-- so that we don't have to separate out runners that run a single benchmark
+-- from runners that need to run several benchmarks
+data Runner where
+  RBenchmark  :: B.Benchmark -> Runner   -- ^ a wrapper around tasty-bench benchmarks
+  Runner      :: RunnerI     -> Runner   -- ^ a single run
+  RunnerGroup :: [Runner]    -> Runner   -- ^ a group of runs
+
+-- | Convenience boilerplate functions, simply avoiding a lens dependency
+using :: Runner -> (Runner -> Runner) -> Runner
+using = flip ($)
+{-# INLINE using #-}
+
+-- | Set the runner function
+runner :: (Show c, NFData c) =>
+  (forall a. (U.Provable a, U.Satisfiable a) => U.SMTConfig -> a -> IO c) -> Runner -> Runner
+runner r' (Runner r@RunnerI{}) = Runner $ r{runI = toRun r'}
+runner r' (RunnerGroup rs)     = RunnerGroup $ runner r' <$> rs
+runner _  x                    = x
+{-# INLINE runner #-}
+
+toRun :: (Show c, NFData c) =>
+  (forall a. (U.Provable a, U.Satisfiable a) => U.SMTConfig -> a -> IO c)
+  -> U.SMTConfig
+  -> Problem
+  -> IO BenchResult
+toRun f c p = BenchResult <$> helper p
+  -- similar to helper in onProblem, this is lmap from profunctor land, i.e., we
+  -- curry with a config, then change the runner function from (a -> IO c), to
+  -- (Problem -> IO c)
+  where helper (Problem a) = f c a
+{-# INLINE toRun #-}
+
+onConfig :: (U.SMTConfig -> U.SMTConfig) -> RunnerI -> RunnerI
+onConfig f r@RunnerI{..} = r{config = f config}
+{-# INLINE onConfig #-}
+
+onDesc :: (String -> String) -> RunnerI -> RunnerI
+onDesc f r@RunnerI{..} = r{description = f description}
+{-# INLINE onDesc #-}
+
+onProblem :: (forall a. a -> a) -> RunnerI -> RunnerI
+onProblem f r@RunnerI{..} = r{problem = helper problem}
+  where
+    -- helper function to avoid profunctor dependency, this is simply fmap, or
+    -- rmap for profunctor land
+    helper :: Problem -> Problem
+    helper (Problem p) = Problem $ f p
+{-# INLINE onProblem #-}
+
+-- | make a normal benchmark without the overhead comparison. Notice this is
+-- just unpacking the Runner record
+mkBenchmark :: RunnerI -> B.Benchmark
+mkBenchmark RunnerI{..} = B.bench description . B.nfIO $! runI config problem
+{-# INLINE  mkBenchmark #-}
+
+-- | Convert a Runner or a group of Runners to Benchmarks, this is an api level
+-- function to convert the runners defined in each file to benchmarks which can
+-- be run by gauge
+runBenchmark :: Runner -> B.Benchmark
+runBenchmark (Runner r@RunnerI{}) = mkBenchmark r
+runBenchmark (RunnerGroup rs)     = B.bgroup "" $ runBenchmark <$> rs
+runBenchmark (RBenchmark b)       = b
+{-# INLINE runBenchmark #-}
+
+-- | This is just a wrapper around the RunnerI constructor and serves as the main
+-- entry point to make a runner for a user in case they need something custom.
+run' :: (NFData b, Show b) =>
+  (forall a. (U.Provable a, U.Satisfiable a) => U.SMTConfig -> a -> IO b)
+  -> U.SMTConfig
+  -> String
+  -> Problem
+  -> Runner
+run' r config description problem = Runner $ RunnerI{..}
+  where runI = toRun r
+{-# INLINE run' #-}
+
+-- | Convenience function for creating benchmarks that exposes a configuration
+runWith :: (U.Provable a, U.Satisfiable a) => U.SMTConfig -> String -> a -> Runner
+runWith c d p = run' U.satWith c d (Problem p)
+{-# INLINE runWith #-}
+
+-- | Main entry point for simple benchmarks. See 'mkRunner'' or 'mkRunnerWith'
+-- for versions of this function that allows custom inputs. If you have some use
+-- case that is not considered then you can simply overload the record fields.
+run :: (U.Provable a, U.Satisfiable a) => String -> a -> Runner
+run d p = runWith U.z3 d p `using` runner U.satWith
+{-# INLINE run #-}
+
+-- | Entry point for problems that return IO or to benchmark IO results
+runIOWith :: NFData a => (a -> B.Benchmarkable) -> String -> a -> Runner
+runIOWith f d = RBenchmark . B.bench d . f
+{-# INLINE runIOWith #-}
+
+-- | Benchmark an IO result of sbv, this could be codegen, return models, etc..
+-- See @runIOWith@ for a version which allows the consumer to select the
+-- Benchmarkable injection function
+runIO :: NFData a => String -> IO a -> Runner
+runIO d = RBenchmark . B.bench d . B.nfIO -- . silence
+{-# INLINE runIO #-}
+
+-- | Benchmark an pure result
+runPure :: NFData a => String -> (a -> b) -> a -> Runner
+runPure d = (RBenchmark . B.bench d) .: B.whnf
+  where (.:) = (.).(.)
+{-# INLINE runPure  #-}
+
+-- | create a runner group. Useful for benchmarks that need to run several
+-- benchmarks. See 'BenchSuite.Puzzles.NQueens' for an example.
+rGroup :: [Runner] -> Runner
+rGroup = RunnerGroup
+{-# INLINE rGroup #-}
+
+-- | Orphaned instances just for benchmarking
+instance NFData U.AllSatResult where
+  rnf (U.AllSatResult a b c results) =
+    rnf a `seq` rnf b `seq` rnf c `seq` rwhnf results
+
+-- | Unwrap the existential type to make gauge happy
+instance NFData BenchResult where rnf (BenchResult a) = rnf a
diff --git a/SBVBenchSuite/BenchSuite/BitPrecise/BitTricks.hs b/SBVBenchSuite/BenchSuite/BitPrecise/BitTricks.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/BitPrecise/BitTricks.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.BitPrecise.BitTricks
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.BitPrecise.BitTricks
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.BitPrecise.BitTricks(benchmarks) where
+
+import Documentation.SBV.Examples.BitPrecise.BitTricks
+import BenchSuite.Bench.Bench as B
+
+import Data.SBV (proveWith)
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ B.run "Fast-min" fastMinCorrect `using` runner proveWith
+  , B.run  "Fast-max" fastMaxCorrect `using` runner proveWith
+  ]
diff --git a/SBVBenchSuite/BenchSuite/BitPrecise/BrokenSearch.hs b/SBVBenchSuite/BenchSuite/BitPrecise/BrokenSearch.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/BitPrecise/BrokenSearch.hs
@@ -0,0 +1,42 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.BitPrecise.BrokenSearch
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.BitPrecise.BrokenSearch
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.BitPrecise.BrokenSearch(benchmarks) where
+
+import Documentation.SBV.Examples.BitPrecise.BrokenSearch
+import BenchSuite.Bench.Bench as B
+
+import Data.SBV (proveWith,sInt32,(.>=),(.<=),(.==),sFromIntegral,SInt64,sDiv,constrain)
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ B.run  "Arith.MidPointFixed"  (checkCorrect midPointFixed)        `using` runner Data.SBV.proveWith
+  , B.run  "Arith-Overflow"       (checkCorrect midPointAlternative)  `using` runner Data.SBV.proveWith
+  ]
+
+  where checkCorrect f = do low  <- sInt32 "low"
+                            high <- sInt32 "high"
+
+                            constrain $ low .>= 0
+                            constrain $ low .<= high
+
+                            let low', high' :: SInt64
+                                low'  = sFromIntegral low
+                                high' = sFromIntegral high
+                                mid'  = (low' + high') `sDiv` 2
+
+                                mid   = f low high
+
+                            return $ sFromIntegral mid .== mid'
diff --git a/SBVBenchSuite/BenchSuite/BitPrecise/Legato.hs b/SBVBenchSuite/BenchSuite/BitPrecise/Legato.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/BitPrecise/Legato.hs
@@ -0,0 +1,40 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.BitPrecise.Legato
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.BitPrecise.Legato
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.BitPrecise.Legato(benchmarks) where
+
+import Documentation.SBV.Examples.BitPrecise.Legato
+import BenchSuite.Bench.Bench as B
+
+import Data.SBV
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ B.run    "Correctness.Legato" correctnessThm `using` runner Data.SBV.proveWith
+  , B.runIO  "CodeGen.Legato" legatoInC
+  ]
+  where correctnessThm = do
+          lo <- sWord "lo"
+
+          x <- sWord  "x"
+          y <- sWord  "y"
+
+          regX  <- sWord "regX"
+          regA  <- sWord "regA"
+
+          flagC <- sBool "flagC"
+          flagZ <- sBool "flagZ"
+
+          return $ legatoIsCorrect (x, y, lo, regX, regA, flagC, flagZ)
diff --git a/SBVBenchSuite/BenchSuite/BitPrecise/MergeSort.hs b/SBVBenchSuite/BenchSuite/BitPrecise/MergeSort.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/BitPrecise/MergeSort.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.BitPrecise.MergeSort
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.BitPrecise.MergeSort
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.BitPrecise.MergeSort(benchmarks) where
+
+import Documentation.SBV.Examples.BitPrecise.MergeSort
+import BenchSuite.Bench.Bench as B
+
+import Data.SBV
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ B.run    "Correctness.MergeSort 3"  (correctness' 3)  `using` runner Data.SBV.proveWith
+  , B.run    "Correctness.MergeSort 4"  (correctness' 4)  `using` runner Data.SBV.proveWith
+  , B.runIO  "CodeGen.MergeSort 3" $ codeGen 3
+  , B.runIO  "CodeGen.MergeSort 4" $ codeGen 4
+  ]
+  where correctness' n = do xs <- mkFreeVars n
+                            let ys = mergeSort xs
+                            return $ nonDecreasing ys .&& isPermutationOf xs ys
diff --git a/SBVBenchSuite/BenchSuite/BitPrecise/PrefixSum.hs b/SBVBenchSuite/BenchSuite/BitPrecise/PrefixSum.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/BitPrecise/PrefixSum.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.BitPrecise.PrefixSum
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.BitPrecise.PrefixSum
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.BitPrecise.PrefixSum(benchmarks) where
+
+import Documentation.SBV.Examples.BitPrecise.PrefixSum
+import BenchSuite.Bench.Bench as B
+
+import Data.SBV
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ B.run    "Correctness.PrefixSum 8"  (flIsCorrect 8  (0,(+)))  `using` runner proveWith
+  , B.run    "Correctness.PrefixSum 16" (flIsCorrect 16 (0,smax)) `using` runner proveWith
+  ]
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/AddSub.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/AddSub.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/AddSub.hs
@@ -0,0 +1,23 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.AddSub
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.AddSub
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.AddSub(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.AddSub
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = runIO "genAddSub" genAddSub
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/CRC_USB5.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/CRC_USB5.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/CRC_USB5.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.CRC_USB5
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.CRC_USB5(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Correctness" crcGood
+  , runIO "CodeGen 1" cg1
+  , runIO "CodeGen 2" cg2
+  ]
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/Fibonacci.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/Fibonacci.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.Fibonacci
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.Fibonacci
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.Fibonacci(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.Fibonacci
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Fib1 1"  $ genFib1 1
+  , runIO "Fib1 10" $ genFib1 10
+  , runIO "Fib1 20" $ genFib1 20
+  , runIO "Fib2 1"  $ genFib1 1
+  , runIO "Fib2 10" $ genFib1 10
+  , runIO "Fib2 20" $ genFib1 20
+  ]
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/GCD.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/GCD.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/GCD.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.GCD
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.GCD
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.GCD(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.GCD
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "Correctness" sgcdIsCorrect `using` runner proveWith
+  , runIO "CodeGen" genGCDInC
+  ]
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/PopulationCount.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/PopulationCount.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/PopulationCount.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.PopulationCount
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.PopulationCount
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.PopulationCount(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.PopulationCount
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "Correctness" fastPopCountIsCorrect `using` runner proveWith
+  , runIO "CodeGen" genPopCountInC
+  ]
diff --git a/SBVBenchSuite/BenchSuite/CodeGeneration/Uninterpreted.hs b/SBVBenchSuite/BenchSuite/CodeGeneration/Uninterpreted.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/CodeGeneration/Uninterpreted.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.CodeGeneration.Uninterpreted
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.CodeGeneration.Uninterpreted(benchmarks) where
+
+import Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "Correctness" testLeft `using` runner proveWith
+  , runIO "CodeGen" genCCode
+  ]
+  where testLeft = \x y -> tstShiftLeft x y 0 .== x + y
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Crypto/AES.hs b/SBVBenchSuite/BenchSuite/Crypto/AES.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Crypto/AES.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Crypto.AES
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Crypto.AES
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Crypto.AES(benchmarks) where
+
+import Documentation.SBV.Examples.Crypto.AES
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "InverseGF"               inverseGFPrf       `using` runner proveWith
+  , run "Correctness.SBoxInverse" sboxInverseCorrect `using` runner proveWith
+  , runPure "t128Enc" (fmap hex8) t128Enc
+  , runPure "t128Dec" (fmap hex8) t128Dec
+  , runPure "t192Enc" (fmap hex8) t192Enc
+  , runPure "t192Dec" (fmap hex8) t192Dec
+  , runPure "t256Enc" (fmap hex8) t256Enc
+  , runPure "t256Dec" (fmap hex8) t256Dec
+  , runIO   "CodeGen.AES128Lib" cgAES128Library
+  ]
+  where inverseGFPrf = \x -> x ./= 0 .=> x `gf28Mult` gf28Inverse x .== 1
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Crypto/RC4.hs b/SBVBenchSuite/BenchSuite/Crypto/RC4.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Crypto/RC4.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Crypto.RC4
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Crypto.RC4
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Crypto.RC4(benchmarks) where
+
+import Documentation.SBV.Examples.Crypto.RC4
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Correctness" rc4IsCorrect
+  , runPure "encrypt 1" (concatMap hex2) $ encrypt "Key" "Plaintext"
+  , runPure "encrypt 2" (concatMap hex2) $ encrypt "Wiki" "pedia"
+  , runPure "encrypt 3" (concatMap hex2) $ encrypt "Secret" "Attack at dawn"
+  , runPure "decrypt 1" (decrypt "Key")    [0xbb, 0xf3, 0x16, 0xe8, 0xd9, 0x40, 0xaf, 0x0a, 0xd3]
+  , runPure "decrypt 2" (decrypt "Wiki")   [0x10, 0x21, 0xbf, 0x04, 0x20]
+  , runPure "decrypt 3" (decrypt "Secret") [0x45, 0xa0, 0x1f, 0x64, 0x5f, 0xc3, 0x5b, 0x38, 0x35, 0x52, 0x54, 0x4b, 0x9b, 0xf5]
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Crypto/SHA.hs b/SBVBenchSuite/BenchSuite/Crypto/SHA.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Crypto/SHA.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Crypto.SHA
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Crypto.SHA
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Crypto.SHA(benchmarks) where
+
+import Documentation.SBV.Examples.Crypto.SHA
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO   "CodeGeneration" cgSHA256
+  , runPure "knownTests 1"   knownAnswerTests 1
+  , runPure "knownTests 10"  knownAnswerTests 10
+  , runPure "knownTests 24"  knownAnswerTests 24
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Existentials/Diophantine.hs b/SBVBenchSuite/BenchSuite/Existentials/Diophantine.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Existentials/Diophantine.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Existentials.Diophantine
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Existentials.Diophantine
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Existentials.Diophantine(benchmarks) where
+
+import Documentation.SBV.Examples.Existentials.Diophantine
+import Control.DeepSeq
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup
+              [ runIO "Test"    test
+              , runIO "Sailors" sailors
+              ]
+
+
+
+instance NFData Solution where rnf x = seq x ()
diff --git a/SBVBenchSuite/BenchSuite/Lists/BoundedMutex.hs b/SBVBenchSuite/BenchSuite/Lists/BoundedMutex.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Lists/BoundedMutex.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Lists.BoundedMutex
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Lists.BoundedMutex
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Lists.BoundedMutex(benchmarks) where
+
+import Documentation.SBV.Examples.Lists.BoundedMutex
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ runIO "CheckMutex.1"  $ checkMutex 1
+             , runIO "CheckMutex.3"  $ checkMutex 3
+             , runIO "CheckMutex.5"  $ checkMutex 5
+             , runIO "NotFair.1"     $ notFair 1
+             , runIO "NotFair.3"     $ notFair 3
+             , runIO "NotFair.5"     $ notFair 5
+             ]
diff --git a/SBVBenchSuite/BenchSuite/Lists/Fibonacci.hs b/SBVBenchSuite/BenchSuite/Lists/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Lists/Fibonacci.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Lists.Fibonacci
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Lists.Fibonacci
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Lists.Fibonacci(benchmarks) where
+
+import Documentation.SBV.Examples.Lists.Fibonacci
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ runIO "GenFibs" $ runSMT genFibs
+             ]
diff --git a/SBVBenchSuite/BenchSuite/Misc/Auxiliary.hs b/SBVBenchSuite/BenchSuite/Misc/Auxiliary.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Auxiliary.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Auxiliary
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Auxiliary
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.Auxiliary(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Auxiliary
+
+import BenchSuite.Bench.Bench as S
+import Utils.SBVBenchFramework
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = S.run "Birthday" problem `using` runner allSatWith
diff --git a/SBVBenchSuite/BenchSuite/Misc/Enumerate.hs b/SBVBenchSuite/BenchSuite/Misc/Enumerate.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Enumerate.hs
@@ -0,0 +1,39 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Enumerate
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Enumerate
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Misc.Enumerate(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Enumerate
+
+import BenchSuite.Bench.Bench
+import Utils.SBVBenchFramework
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ run "Elts" _elts `using` runner allSatWith
+             , run "Four" _four
+             , run "MaxE" _maxE
+             , run "MinE" _minE
+             ]
+  where _elts = \(x::SE) -> x .== x
+        _four = \a b c (d::SE) -> distinct [a, b, c, d]
+        _maxE = do mx <- free "maxE"
+                   constrain $ \(Forall e) -> mx .>= (e::SE)
+        _minE = do mx <- free "minE"
+                   constrain $ \(Forall e) -> mx .<= (e::SE)
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Misc/Floating.hs b/SBVBenchSuite/BenchSuite/Misc/Floating.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Floating.hs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Floating
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Floating
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Misc.Floating(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Floating
+
+import BenchSuite.Bench.Bench
+import Utils.SBVBenchFramework
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ run "notAssoc"        (assocPlus (0/0)) `using` runner proveWith
+             , run "AssocPlusReg"    _assocPlusRegular `using` runner proveWith
+             , run "NonZeroAddition" _nonZeroAddition  `using` runner proveWith
+             , run "MultInverse"     _multInverse      `using` runner proveWith
+             , run "RoundingAdd"     _roundingAdd
+             ]
+  where _assocPlusRegular = do [x, y, z] <- sFloats ["x", "y", "z"]
+                               let lhs = x+(y+z)
+                                   rhs = (x+y)+z
+                               -- make sure we do not overflow at the intermediate points
+                               constrain $ fpIsPoint lhs
+                               constrain $ fpIsPoint rhs
+                               return $ lhs .== rhs
+
+        _nonZeroAddition  = do [a, b] <- sFloats ["a", "b"]
+                               constrain $ fpIsPoint a
+                               constrain $ fpIsPoint b
+                               constrain $ a + b .== a
+                               return $ b .== 0
+
+        _multInverse      = do a <- sFloat "a"
+                               constrain $ fpIsPoint a
+                               constrain $ fpIsPoint (1/a)
+                               return $ a * (1/a) .== 1
+
+        _roundingAdd      = do m :: SRoundingMode <- free "rm"
+                               constrain $ m ./= literal RoundNearestTiesToEven
+                               x <- sFloat "x"
+                               y <- sFloat "y"
+                               let lhs = fpAdd m x y
+                               let rhs = x + y
+                               constrain $ fpIsPoint lhs
+                               constrain $ fpIsPoint rhs
+                               return $ lhs ./= rhs
diff --git a/SBVBenchSuite/BenchSuite/Misc/ModelExtract.hs b/SBVBenchSuite/BenchSuite/Misc/ModelExtract.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/ModelExtract.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.ModelExtract
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.ModelExtract
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.ModelExtract(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.ModelExtract
+
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  runIO "genVals" genVals
diff --git a/SBVBenchSuite/BenchSuite/Misc/Newtypes.hs b/SBVBenchSuite/BenchSuite/Misc/Newtypes.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Newtypes.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Newtypes
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Newtypes
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.Newtypes(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Newtypes
+
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  run "Problem" problem
diff --git a/SBVBenchSuite/BenchSuite/Misc/NoDiv0.hs b/SBVBenchSuite/BenchSuite/Misc/NoDiv0.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/NoDiv0.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.NoDiv0
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.NoDiv0
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Misc.NoDiv0(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.NoDiv0
+
+import Data.SBV
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ runIO "test.1" test1
+             , runIO "test.2" test2
+             ]
+
+instance NFData SafeResult where rnf x = seq x ()
diff --git a/SBVBenchSuite/BenchSuite/Misc/Polynomials.hs b/SBVBenchSuite/BenchSuite/Misc/Polynomials.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Polynomials.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Polynomials
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Polynomials
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.Polynomials(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Polynomials
+
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  runIO "testGF28 " testGF28
diff --git a/SBVBenchSuite/BenchSuite/Misc/SetAlgebra.hs b/SBVBenchSuite/BenchSuite/Misc/SetAlgebra.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/SetAlgebra.hs
@@ -0,0 +1,133 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.SetAlgebra
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.SetAlgebra
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Misc.SetAlgebra(benchmarks) where
+
+import Data.SBV hiding (complement)
+import Data.SBV.Set
+import Documentation.SBV.Examples.Misc.SetAlgebra
+
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup $ fmap (`using` _prove)
+              [ run "Commutivity.Union"           commutivityCup
+              , run "Commutivity.Intersection"    commutivityCap
+              , run "Associativity.Union"         assocCup
+              , run "Associativity.Intersection"  assocCap
+              , run "Distributivity.Union"        distribCup
+              , run "Distributivity.Intersection" distribCap
+              , run "Identity.Union"              identCup
+              , run "Identity.Intersection"       identCap
+              , run "Complement.Union"            compCup
+              , run "Complement.Intersection"     compCap
+              , run "Complement.Empty"            compEmpty
+              , run "Complement.Complement"       compComp
+              , run "Complement.Full"             compFull
+              , run "Complement.Unique"           compUniq
+              , run "Idempotency.Cup"             idempCup
+              , run "Idempotency.Cap"             idempCap
+              , run "Domination.Cup"              domCup
+              , run "Domination.Cap"              domCap
+              , run "Absorption.Cup"              absorbCup
+              , run "Absorption.Cap"              absorbCap
+              , run "Intersection.Difference"     intdiff
+              , run "DeMorgans.Cup"               demorgCup
+              , run "DeMorgans.Cap"               demorgCap
+              , run "InclusionIsPO"               incPo
+              , run "SubsetEquality"              subEq
+              , run "SubsetEquality.Transitivity" subEqTrans
+              , run "JoinMeet.1"                  joinMeet1
+              , run "JoinMeet.2"                  joinMeet2
+              , run "JoinMeet.3"                  joinMeet3
+              , run "JoinMeet.4"                  joinMeet4
+              , run "JoinMeet.5"                  joinMeet5
+              , run "SubsetChar.Union"            subsetCharCup
+              , run "SubsetChar.Intersection"     subsetCharCap
+              , run "SubsetChar.Implication"      subsetCharImpl
+              , run "SubsetChar.Complement"       subsetCharComp
+
+              , run "RelativeComplements.Union"              relCompCup
+              , run "RelativeComplements.Intersection"       relCompCap
+              , run "RelativeComplements.UnionInters"        relCompCapCup
+              , run "RelativeComplements.InterInters.1"      relCompCapCap
+              , run "RelativeComplements.InterInters.2"      relCompCapCap2
+              , run "RelativeComplements.UnionUnion"         relCompCupCup
+              , run "RelativeComplements.Identity"           relCompIdent
+              , run "RelativeComplements.UnitLeft"           relCompUnitL
+              , run "RelativeComplements.UnitRight"          relCompUnitR
+              , run "RelativeComplements.ComplementIdentity" relCompCompInt
+              , run "RelativeComplements.ComplementUnion"    relCompCompUni
+              , run "RelativeComplements.CompComp"           relCompComp
+              , run "RelativeComplements.CompFull"           relCompFull
+              , run "DistributionSubset.Union"               distSubset1
+              , run "DistributionSubset.Intersection"        distSubset2
+              ]
+  where _prove = runner proveWith
+        commutivityCup = \(a :: SI) b -> a `union` b .== b `union` a
+        commutivityCap = \(a :: SI) b -> a `intersection` b .== b `intersection` a
+        assocCup       = \(a :: SI) b c -> a `union` (b `union` c) .== (a `union` b) `union` c
+        assocCap       = \(a :: SI) b c -> a `intersection` (b `intersection` c) .== (a `intersection` b) `intersection` c
+        distribCup     = \(a :: SI) b c -> a `union` (b `intersection` c) .== (a `union` b) `intersection` (a `union` c)
+        distribCap     = \(a :: SI) b c -> a `intersection` (b `union` c) .== (a `intersection` b) `union` (a `intersection` c)
+        identCup       = \(a :: SI) -> a `union` empty .== a
+        identCap       = \(a :: SI) -> a `intersection` full .== a
+        compCup        = \(a :: SI) -> a `union` complement a .== full
+        compCap        = \(a :: SI) -> a `intersection` complement a .== empty
+        compEmpty      = complement (empty :: SI) .== full
+        compComp       = \(a :: SI) -> complement (complement a) .== a
+        compFull       = complement (full :: SI) .== empty
+        compUniq       = \(a :: SI) b -> a `union` b .== full .&& a `intersection` b .== empty .<=> b .== complement a
+        idempCup       = \(a :: SI) -> a `union` a .== a
+        idempCap       = \(a :: SI) -> a `intersection` a .== a
+        domCup         = \(a :: SI) -> a `union` full .== full
+        domCap         = \(a :: SI) -> a `intersection` empty .== empty
+        absorbCup      = \(a :: SI) b -> a `union` (a `intersection` b) .== a
+        absorbCap      = \(a :: SI) b -> a `intersection` (a `union` b) .== a
+        intdiff        = \(a :: SI) b -> a `intersection` b .== a `difference` (a `difference` b)
+        demorgCup      = \(a :: SI) b -> complement (a `union` b) .== complement a `intersection` complement b
+        demorgCap      = \(a :: SI) b -> complement (a `intersection` b) .== complement a `union` complement b
+        incPo          = \(a :: SI) -> a `isSubsetOf` a
+        subEq          = \(a :: SI) b -> a `isSubsetOf` b .&& b `isSubsetOf` a .<=> a .== b
+        subEqTrans     = \(a :: SI) b c -> a `isSubsetOf` b .&& b `isSubsetOf` c .=> a `isSubsetOf` c
+        joinMeet1      = \(a :: SI) b -> a `isSubsetOf` (a `union` b)
+        joinMeet2      = \(a :: SI) b c -> a `isSubsetOf` c .&& b `isSubsetOf` c .=> (a `union` b) `isSubsetOf` c
+        joinMeet3      = \(a :: SI) b -> (a `intersection` b) `isSubsetOf` a
+        joinMeet4      = \(a :: SI) b -> (a `intersection` b) `isSubsetOf` b
+        joinMeet5      = \(a :: SI) b c -> c `isSubsetOf` a .&& c `isSubsetOf` b .=> c `isSubsetOf` (a `intersection` b)
+        subsetCharCup  = \(a :: SI) b -> a `isSubsetOf` b .<=> a `union` b .== b
+        subsetCharCap  = \(a :: SI) b -> a `isSubsetOf` b .<=> a `intersection` b .== a
+        subsetCharImpl = \(a :: SI) b -> a `isSubsetOf` b .<=> a `difference` b .== empty
+        subsetCharComp = \(a :: SI) b -> a `isSubsetOf` b .<=> complement b `isSubsetOf` complement a
+        relCompCup     = \(a :: SI) b c -> c \\ (a `union` b) .== (c \\ a) `intersection` (c \\ b)
+        relCompCap     = \(a :: SI) b c -> c \\ (a `intersection` b) .== (c \\ a) `union` (c \\ b)
+        relCompCapCup  = \(a :: SI) b c -> c \\ (b \\ a) .== (a `intersection` c) `union` (c \\ b)
+        relCompCapCap  = \(a :: SI) b c -> (b \\ a) `intersection` c .== (b `intersection` c) \\ a
+        relCompCapCap2 = \(a :: SI) b c -> (b \\ a) `intersection` c .== b `intersection` (c \\ a)
+        relCompCupCup  = \(a :: SI) b c -> (b \\ a) `union` c .== (b `union` c) \\ (a \\ c)
+        relCompIdent   = \(a :: SI) -> a \\ a .== empty
+        relCompUnitL   = \(a :: SI) -> empty \\ a .== empty
+        relCompUnitR   = \(a :: SI) -> empty \\ empty .== a
+        relCompCompInt = \(a :: SI) b -> b \\ a .== complement a `intersection` b
+        relCompCompUni = \(a :: SI) b -> complement (b \\ a) .== a `union` complement b
+        relCompComp    = \(a :: SI) -> full \\ a .== complement a
+        relCompFull    = \(a :: SI) -> a \\ full .== empty
+        distSubset1    = \(a :: SI) b c -> a `isSubsetOf` (b `union` c) .=> a `isSubsetOf` b .&& a `isSubsetOf` c
+        distSubset2    = \(a :: SI) b c -> (b `intersection` c) `isSubsetOf` a .=> b `isSubsetOf` a .&& c `isSubsetOf` a
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Misc/SoftConstrain.hs b/SBVBenchSuite/BenchSuite/Misc/SoftConstrain.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/SoftConstrain.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.SoftConstrain
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.SoftConstrain
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.SoftConstrain(benchmarks) where
+
+import Data.SBV
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup [ run "SoftConstrain" softC ]
+  where softC = do x <- sString "x"
+                   y <- sString "y"
+
+                   constrain $ x .== "x-must-really-be-hello"
+                   constrain $ y ./= "y-can-be-anything-but-hello"
+
+                   -- Now add soft-constraints to indicate our preference
+                   -- for what these variables should be:
+                   softConstrain $ x .== "default-x-value"
+                   softConstrain $ y .== "default-y-value"
+
+                   return sTrue
diff --git a/SBVBenchSuite/BenchSuite/Misc/Tuple.hs b/SBVBenchSuite/BenchSuite/Misc/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Misc/Tuple.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Misc.Tuple
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Misc.Tuple
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Misc.Tuple(benchmarks) where
+
+import Documentation.SBV.Examples.Misc.Tuple
+
+import BenchSuite.Bench.Bench
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup [ runIO "Tuple" example ]
diff --git a/SBVBenchSuite/BenchSuite/Optimization/Enumerate.hs b/SBVBenchSuite/BenchSuite/Optimization/Enumerate.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/Enumerate.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.Enumerate
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Optimization.Enumerate
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Optimization.Enumerate(benchmarks) where
+
+import Documentation.SBV.Examples.Optimization.Enumerate
+import BenchSuite.Bench.Bench as B
+
+import BenchSuite.Optimization.Instances()
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Enumerate.AlmostWeekend"    almostWeekend
+  , runIO "Enumerate.WeekendJustOver"  weekendJustOver
+  , runIO "Enumerate.firstWeekend"     firstWeekend
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Optimization/ExtField.hs b/SBVBenchSuite/BenchSuite/Optimization/ExtField.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/ExtField.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.ExtField
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Optimization.ExtField
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Optimization.ExtField(benchmarks) where
+
+import Documentation.SBV.Examples.Optimization.ExtField
+import BenchSuite.Bench.Bench as B
+import BenchSuite.Optimization.Instances()
+
+import Data.SBV
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ run "ExtField.problem" problem `using` runner (`optimizeWith` Lexicographic)
+             ]
diff --git a/SBVBenchSuite/BenchSuite/Optimization/Instances.hs b/SBVBenchSuite/BenchSuite/Optimization/Instances.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/Instances.hs
@@ -0,0 +1,23 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.Instance
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Helper file to provide common orphaned instances for Optimization benchmarks
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Optimization.Instances where
+
+import Data.SBV
+
+import Control.DeepSeq
+
+
+-- | orphaned instance for benchmarks
+instance NFData OptimizeResult where rnf x = seq x ()
diff --git a/SBVBenchSuite/BenchSuite/Optimization/LinearOpt.hs b/SBVBenchSuite/BenchSuite/Optimization/LinearOpt.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/LinearOpt.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.LinearOpt
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Optimization.LinearOpt
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Optimization.LinearOpt(benchmarks) where
+
+import Documentation.SBV.Examples.Optimization.LinearOpt
+import BenchSuite.Bench.Bench as B
+import BenchSuite.Optimization.Instances()
+
+import Data.SBV
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = run "LinearOpt.problem" problem `using` runner (`optimizeWith` Lexicographic)
diff --git a/SBVBenchSuite/BenchSuite/Optimization/Production.hs b/SBVBenchSuite/BenchSuite/Optimization/Production.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/Production.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.Production
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Optimization.Production
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Optimization.Production(benchmarks) where
+
+import Documentation.SBV.Examples.Optimization.Production
+import BenchSuite.Bench.Bench as B
+import BenchSuite.Optimization.Instances()
+
+import Data.SBV
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = run "Production.production" production `using` runner (`optimizeWith` Lexicographic)
diff --git a/SBVBenchSuite/BenchSuite/Optimization/VM.hs b/SBVBenchSuite/BenchSuite/Optimization/VM.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Optimization/VM.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Optimization.VM
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Optimization.VM
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Optimization.VM(benchmarks) where
+
+import Documentation.SBV.Examples.Optimization.VM
+import BenchSuite.Bench.Bench as B
+import BenchSuite.Optimization.Instances()
+
+import Data.SBV
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = run "VM.allocate" allocate `using` runner (`optimizeWith` Lexicographic)
diff --git a/SBVBenchSuite/BenchSuite/ProofTools/BMC.hs b/SBVBenchSuite/BenchSuite/ProofTools/BMC.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/ProofTools/BMC.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.ProofTools.BMC
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.ProofTools.BMC
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.ProofTools.BMC(benchmarks) where
+
+import Control.DeepSeq
+import Documentation.SBV.Examples.ProofTools.BMC
+
+import BenchSuite.Bench.Bench as B
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "BMC.ex1" ex1
+  , runIO "BMC.ex2" ex2
+  ]
+
+
+instance NFData a => NFData (S a) where rnf a = seq a ()
diff --git a/SBVBenchSuite/BenchSuite/ProofTools/Fibonacci.hs b/SBVBenchSuite/BenchSuite/ProofTools/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/ProofTools/Fibonacci.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.ProofTools.Fibonacci
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.ProofTools.Fibonacci
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.ProofTools.Fibonacci(benchmarks) where
+
+import Control.DeepSeq
+
+import Data.SBV.Tools.Induction
+import Documentation.SBV.Examples.ProofTools.Fibonacci
+
+import BenchSuite.Bench.Bench as B
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  runIO "Fibonacci.Correctness" fibCorrect
+
+
+instance NFData a => NFData (S a)               where rnf a = seq a ()
+instance NFData a => NFData (InductionResult a) where rnf a = seq a ()
diff --git a/SBVBenchSuite/BenchSuite/ProofTools/Strengthen.hs b/SBVBenchSuite/BenchSuite/ProofTools/Strengthen.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/ProofTools/Strengthen.hs
@@ -0,0 +1,36 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.ProofTools.Strengthen
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.ProofTools.Strengthen
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.ProofTools.Strengthen(benchmarks) where
+
+import Control.DeepSeq
+
+import Data.SBV.Tools.Induction
+import Documentation.SBV.Examples.ProofTools.Strengthen
+
+import BenchSuite.Bench.Bench as B
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Strengthen.ex1" ex1
+  , runIO "Strengthen.ex2" ex2
+  , runIO "Strengthen.ex3" ex3
+  , runIO "Strengthen.ex4" ex4
+  , runIO "Strengthen.ex5" ex5
+  , runIO "Strengthen.ex6" ex6
+  ]
+
+instance NFData a => NFData (S a)               where rnf a = seq a ()
+instance NFData a => NFData (InductionResult a) where rnf a = seq a ()
diff --git a/SBVBenchSuite/BenchSuite/ProofTools/Sum.hs b/SBVBenchSuite/BenchSuite/ProofTools/Sum.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/ProofTools/Sum.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.ProofTools.Sum
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.ProofTools.Sum
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.ProofTools.Sum(benchmarks) where
+
+import Control.DeepSeq
+
+import Data.SBV.Tools.Induction
+import Documentation.SBV.Examples.ProofTools.Sum
+
+import BenchSuite.Bench.Bench as B
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = runIO "Sum.Correctness" sumCorrect
+
+instance NFData a => NFData (S a) where rnf a = seq a ()
+instance NFData a => NFData (InductionResult a) where rnf a = seq a ()
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Birthday.hs b/SBVBenchSuite/BenchSuite/Puzzles/Birthday.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Birthday.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Birthday
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Birthday
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.Birthday(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.Birthday
+
+import BenchSuite.Bench.Bench as S
+import Utils.SBVBenchFramework
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ S.run "Birthday" puzzle `using` runner allSatWith
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Coins.hs b/SBVBenchSuite/BenchSuite/Puzzles/Coins.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Coins.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Coins
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Coins
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.Coins(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.Coins
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "Coins" coinsPgm ]
+  where coinsPgm = do cs <- mapM mkCoin [1..6]
+                      mapM_ constrain [c s | s <- combinations cs, length s >= 2, c <- [c1, c2, c3, c4, c5, c6]]
+                      constrain $ sAnd $ zipWith (.>=) cs (drop 1 cs)
+                      -- normally we would call output here, but returning
+                      -- several outputs from a symbolic computation doesn't
+                      -- play nice with either the transcript generation or the benchmarking apparently
+
+                      -- output $ sum cs .== 115
+
+                      return $ sum cs .== 115
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Counts.hs b/SBVBenchSuite/BenchSuite/Puzzles/Counts.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Counts.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Counts
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Counts
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.Counts(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.Counts
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "Counts" countPgm ]
+ where countPgm = puzzle `fmap` mkFreeVars 10
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/DogCatMouse.hs b/SBVBenchSuite/BenchSuite/Puzzles/DogCatMouse.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/DogCatMouse.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.DogCatMouse
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.DogCatMouse
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.DogCatMouse(benchmarks) where
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "DogCatMouse" p `using` runner allSatWith ]
+  where p = do [dog, cat, mouse] <- sIntegers ["dog", "cat", "mouse"]
+               solve [ dog   .>= 1                                   -- at least one dog
+                     , cat   .>= 1                                   -- at least one cat
+                     , mouse .>= 1                                   -- at least one mouse
+                     , dog + cat + mouse .== 100                     -- buy precisely 100 animals
+                     , 1500 * dog + 100 * cat + 25 * mouse .== 10000 -- spend exactly 100 dollars (use cents since we don't have fractions)
+                     ]
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Euler185.hs b/SBVBenchSuite/BenchSuite/Puzzles/Euler185.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Euler185.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Euler185
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Euler185
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.Euler185(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.Euler185
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "Euler185" euler185 `using` runner satWith ]
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Garden.hs b/SBVBenchSuite/BenchSuite/Puzzles/Garden.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Garden.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Garden
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Garden
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror  #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module BenchSuite.Puzzles.Garden(benchmarks) where
+
+import Data.List (isSuffixOf)
+
+import Documentation.SBV.Examples.Puzzles.Garden
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.runWith s "Garden" puzzle `using` runner allSatWith ]
+  where s = z3{allSatTrackUFs = False, isNonModelVar = ("_modelIgnore" `isSuffixOf`)}
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/LadyAndTigers.hs b/SBVBenchSuite/BenchSuite/Puzzles/LadyAndTigers.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/LadyAndTigers.hs
@@ -0,0 +1,46 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.LadyAndTigers
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.LadyAndTigers
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.LadyAndTigers(benchmarks) where
+
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "LadyAndTigers" p `using` runner allSatWith ]
+  where p = do
+
+          -- One boolean for each of the correctness of the signs
+          [sign1, sign2, sign3] <- mapM sBool ["sign1", "sign2", "sign3"]
+
+          -- One boolean for each of the presence of the tigers
+          [tiger1, tiger2, tiger3] <- mapM sBool ["tiger1", "tiger2", "tiger3"]
+
+          -- Room 1 sign: A Tiger is in this room
+          constrain $ sign1 .<=> tiger1
+
+          -- Room 2 sign: A Lady is in this room
+          constrain $ sign2 .<=> sNot tiger2
+
+          -- Room 3 sign: A Tiger is in room 2
+          constrain $ sign3 .<=> tiger2
+
+          -- At most one sign is true
+          constrain $ [sign1, sign2, sign3] `pbAtMost` 1
+
+          -- There are precisely two tigers
+          constrain $ [tiger1, tiger2, tiger3] `pbExactly` 2
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/MagicSquare.hs b/SBVBenchSuite/BenchSuite/Puzzles/MagicSquare.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/MagicSquare.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.MagicSquare
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.MagicSquare
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.MagicSquare(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.MagicSquare
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ S.run "MagicSquare.magic 2" (mkMagic 2) `using` runner allSatWith
+  , S.run "MagicSquare.magic 3" (mkMagic 3) `using` runner allSatWith
+  ]
+
+mkMagic :: Int -> Symbolic SBool
+mkMagic n = (isMagic . chunk n) `fmap` mkFreeVars (n*n)
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/NQueens.hs b/SBVBenchSuite/BenchSuite/Puzzles/NQueens.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/NQueens.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.NQueens
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.NQueens
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.NQueens(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.NQueens
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ S.run "NQueens.NQueens 1" (mkQueens 1) `using` runner allSatWith
+  , S.run "NQueens.NQueens 2" (mkQueens 2) `using` runner allSatWith
+  , S.run "NQueens.NQueens 3" (mkQueens 3) `using` runner allSatWith
+  , S.run "NQueens.NQueens 4" (mkQueens 4) `using` runner allSatWith
+  , S.run "NQueens.NQueens 5" (mkQueens 5) `using` runner allSatWith
+  , S.run "NQueens.NQueens 6" (mkQueens 6) `using` runner allSatWith
+  , S.run "NQueens.NQueens 7" (mkQueens 7) `using` runner allSatWith
+  , S.run "NQueens.NQueens 8" (mkQueens 8) `using` runner allSatWith
+  ]
+
+mkQueens :: Int -> Symbolic SBool
+mkQueens n = isValid n `fmap` mkFreeVars n
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/SendMoreMoney.hs b/SBVBenchSuite/BenchSuite/Puzzles/SendMoreMoney.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/SendMoreMoney.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.SendMoreMoney
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.SendMoreMoney
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.SendMoreMoney(benchmarks) where
+
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup [ S.run "Puzzles.SendMoreMoney" p `using` runner allSatWith ]
+  where p = do
+          ds@[s,e,n,d,m,o,r,y] <- mapM sInteger ["s", "e", "n", "d", "m", "o", "r", "y"]
+          let isDigit x = x .>= 0 .&& x .<= 9
+              val xs    = sum $ zipWith (*) (reverse xs) (iterate (*10) 1)
+              send      = val [s,e,n,d]
+              more      = val [m,o,r,e]
+              money     = val [m,o,n,e,y]
+          constrain $ sAll isDigit ds
+          constrain $ distinct ds
+          constrain $ s ./= 0 .&& m ./= 0
+          solve [send + more .== money]
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/Sudoku.hs b/SBVBenchSuite/BenchSuite/Puzzles/Sudoku.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/Sudoku.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.Sudoku
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.Sudoku
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.Sudoku(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.Sudoku
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+    [ runIO ("sudoku" ++ show n) (checkPuzzle s)
+    | (n, s) <- zip [(0::Int)..] [puzzle1, puzzle2, puzzle3, puzzle4, puzzle5, puzzle6] ]
+
+
+checkPuzzle :: Puzzle -> IO Bool
+checkPuzzle p = do final <- fillBoard p
+                   let vld = valid (map (map literal) final)
+                   pure $ Just True == unliteral vld
diff --git a/SBVBenchSuite/BenchSuite/Puzzles/U2Bridge.hs b/SBVBenchSuite/BenchSuite/Puzzles/U2Bridge.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Puzzles/U2Bridge.hs
@@ -0,0 +1,34 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Puzzles.U2Bridge
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Puzzles.U2Bridge
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Puzzles.U2Bridge(benchmarks) where
+
+import Documentation.SBV.Examples.Puzzles.U2Bridge
+
+import Utils.SBVBenchFramework
+import BenchSuite.Bench.Bench as S
+
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+  [ S.run "U2Bridge_cnt1" (count 1) `using` runner satWith
+  , S.run "U2Bridge_cnt2" (count 2) `using` runner satWith
+  , S.run "U2Bridge_cnt3" (count 3) `using` runner satWith
+  , S.run "U2Bridge_cnt4" (count 4) `using` runner satWith
+  , S.run "U2Bridge_cnt6" (count 6) `using` runner satWith
+  ]
+  where
+    act     = do b <- free_; p1 <- free_; p2 <- free_; return (b, p1, p2)
+    count n = isValid `fmap` mapM (const act) [1..(n::Int)]
diff --git a/SBVBenchSuite/BenchSuite/Queries/AllSat.hs b/SBVBenchSuite/BenchSuite/Queries/AllSat.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/AllSat.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.AllSat
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.AllSat
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.AllSat(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.AllSat
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = runIO "AllSat" demo
diff --git a/SBVBenchSuite/BenchSuite/Queries/CaseSplit.hs b/SBVBenchSuite/BenchSuite/Queries/CaseSplit.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/CaseSplit.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.CaseSplit
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.CaseSplit
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.CaseSplit(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.CaseSplit
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup [ runIO "CaseSplit.1" csDemo1
+                    , runIO "CaseSplit.2" csDemo2
+                    ]
diff --git a/SBVBenchSuite/BenchSuite/Queries/Concurrency.hs b/SBVBenchSuite/BenchSuite/Queries/Concurrency.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/Concurrency.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.Concurrency
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.Concurrency
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.Concurrency(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.Concurrency
+
+import BenchSuite.Bench.Bench
+
+-- these benchmarks won't run in multithreaded mode. The benchmark target is not
+-- build as -threaded
+benchmarks :: Runner
+benchmarks = rGroup [ runIO "Concurrency.demo"          demo
+                    , runIO "Concurrency.demoDependent" demoDependent
+                    ]
diff --git a/SBVBenchSuite/BenchSuite/Queries/Enums.hs b/SBVBenchSuite/BenchSuite/Queries/Enums.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/Enums.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.Enums
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.Enums
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Queries.Enums(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.Enums
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+
+-- | orphaned instance for benchmarks
+instance NFData Day where rnf x = seq x ()
+
+benchmarks :: Runner
+benchmarks = rGroup [ runIO "Enums.findDays" findDays
+                    ]
diff --git a/SBVBenchSuite/BenchSuite/Queries/FourFours.hs b/SBVBenchSuite/BenchSuite/Queries/FourFours.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/FourFours.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.FourFours
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.FourFours
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.FourFours(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.FourFours
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks =  runIO "FourFours.puzzle" puzzle
diff --git a/SBVBenchSuite/BenchSuite/Queries/GuessNumber.hs b/SBVBenchSuite/BenchSuite/Queries/GuessNumber.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/GuessNumber.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.GuessNumber
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.GuessNumber
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Queries.GuessNumber(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.GuessNumber
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks =  runIO "GuessNumber.play" play
diff --git a/SBVBenchSuite/BenchSuite/Queries/Interpolants.hs b/SBVBenchSuite/BenchSuite/Queries/Interpolants.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/Interpolants.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.Interpolants
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.Interpolants
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.Interpolants(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.Interpolants
+
+import BenchSuite.Bench.Bench
+
+import Data.SBV
+
+benchmarks :: Runner
+benchmarks =  runIO "Interpolants.evenOdd" $ runSMT evenOdd
diff --git a/SBVBenchSuite/BenchSuite/Queries/UnsatCore.hs b/SBVBenchSuite/BenchSuite/Queries/UnsatCore.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Queries/UnsatCore.hs
@@ -0,0 +1,22 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Queries.UnsatCore
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Queries.UnsatCore
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Queries.UnsatCore(benchmarks) where
+
+import Documentation.SBV.Examples.Queries.UnsatCore
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks =  runIO "UnsatCore.ucCore" ucCore
diff --git a/SBVBenchSuite/BenchSuite/Strings/RegexCrossword.hs b/SBVBenchSuite/BenchSuite/Strings/RegexCrossword.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Strings/RegexCrossword.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Strings.RegexCrossword
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Strings.RegexCrossword
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Strings.RegexCrossword(benchmarks) where
+
+import Documentation.SBV.Examples.Strings.RegexCrossword
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks = rGroup
+             [ runIO "puzzle1" puzzle1
+             , runIO "puzzle2" puzzle2
+             , runIO "puzzle3" puzzle3
+             ]
diff --git a/SBVBenchSuite/BenchSuite/Strings/SQLInjection.hs b/SBVBenchSuite/BenchSuite/Strings/SQLInjection.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Strings/SQLInjection.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Strings.SQLInjection
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Strings.SQLInjection
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Strings.SQLInjection(benchmarks) where
+
+import Documentation.SBV.Examples.Strings.SQLInjection
+import Data.List
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup
+  [ runIO "FindInjection" $ ("'; DROP TABLE 'users" `Data.List.isSuffixOf`) <$> findInjection exampleProgram
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Transformers/SymbolicEval.hs b/SBVBenchSuite/BenchSuite/Transformers/SymbolicEval.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Transformers/SymbolicEval.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Transformers.SymbolicEval
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Transformers.SymbolicEval
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.Transformers.SymbolicEval(benchmarks) where
+
+import Documentation.SBV.Examples.Transformers.SymbolicEval
+import Control.DeepSeq
+
+import BenchSuite.Bench.Bench
+
+-- benchmark suite
+benchmarks :: Runner
+benchmarks =  rGroup
+              [ runIO "Example.1" ex1
+              , runIO "Example.2" ex2
+              , runIO "Example.3" ex3
+              ]
+
+instance NFData CheckResult where rnf x = seq x ()
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/AUF.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/AUF.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/AUF.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.AUF
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.AUF
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Uninterpreted.AUF(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.AUF
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "SArray" array `using` runner proveWith
+  ]
+  where array = do x <- free "x"
+                   y <- free "y"
+                   a :: SArray Word32 Word32 <- sArray_
+                   return $ thm x y a
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/Deduce.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/Deduce.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/Deduce.hs
@@ -0,0 +1,38 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.Deduce
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.Deduce
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Uninterpreted.Deduce(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.Deduce
+import Data.SBV
+
+import Prelude hiding (not, or, and)
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "test" t `using` runner proveWith
+  ]
+  where t = do constrain $ \(Forall p) (Forall q) (Forall r) -> (p `or` q) `and` (p `or` r) .== p `or` (q `and` r)
+               constrain $ \(Forall p) (Forall q)            -> not (p `or` q) .== not p `and` not q
+               constrain $ \(Forall p)                       -> not (not p) .== p
+               p <- free "p"
+               q <- free "q"
+               r <- free "r"
+               return $ not (p `or` (q `and` r))
+                 .== (not p `and` not q) `or` (not p `and` not r)
+
+{- HLint ignore module "Redundant lambda" -}
+{- HLint ignore module "Redundant not"    -}
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/Function.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/Function.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/Function.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.Function
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.Function
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Uninterpreted.Function(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.Function
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "thmGood" thmGood `using` runner proveWith
+  ]
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/Multiply.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/Multiply.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/Multiply.hs
@@ -0,0 +1,40 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.Multiply
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.Multiply
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Uninterpreted.Multiply(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.Multiply
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "synthMul22" synthMul22 `using` runner satWith
+  , run "Correctness" correct `using` runner proveWith
+  ]
+  where
+    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
+
+    correct = \a1 a0 b1 b0 -> mul22_hi a1 a0 b1 b0 .== (a1 .&& b0) .<+> (a0 .&& b1)
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/Shannon.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/Shannon.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/Shannon.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.Shannon
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.Shannon
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module BenchSuite.Uninterpreted.Shannon(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.Shannon
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "shannon"  _shannon  `using` runner proveWith
+  , run "shannon2" _shannon2 `using` runner proveWith
+  , run "noWiggle" _noWiggle `using` runner proveWith
+  , run "univOk"   _univOK   `using` runner proveWith
+  , run "existsOk" _existsOK `using` runner proveWith
+  ]
+  where _shannon  = \x y z -> f x y z .== (x .&& pos f y z .|| sNot x .&& neg f y z)
+        _shannon2 = \x y z -> f x y z .== ((x .|| neg f y z) .&& (sNot x .|| pos f y z))
+        _noWiggle = \y z -> sNot (f' y z) .<=> pos f y z .== neg f y z
+        _univOK   = \y z -> f'' y z .=> pos f y z .&& neg f y z
+        _existsOK = \y z -> f''' y z .=> pos f y z .|| neg f y z
+
+
+f :: Ternary
+f    = uninterpret "f"
+f', f'', f''' :: Binary
+f'   = derivative f
+f''  = universal f
+f''' = existential f
+
+{- HLint ignore module "Redundant lambda" -}
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/Sort.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/Sort.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/Sort.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.Sort
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.Sort
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Uninterpreted.Sort(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.Sort
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ run "t1" _t1 `using` runner satWith
+  , run "t2" _t2 `using` runner satWith
+  ]
+  where _t1 = do x <- free "x"
+                 return $ f x ./= x
+
+        _t2 = do constrain $ \(Forall x) (Forall y) -> x .== (y :: SQ)
+                 x <- free "x"
+                 return $ f x ./= x
diff --git a/SBVBenchSuite/BenchSuite/Uninterpreted/UISortAllSat.hs b/SBVBenchSuite/BenchSuite/Uninterpreted/UISortAllSat.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/Uninterpreted/UISortAllSat.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.Uninterpreted.UISortAllSat
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.Uninterpreted.UISortAllSat
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module BenchSuite.Uninterpreted.UISortAllSat(benchmarks) where
+
+import Documentation.SBV.Examples.Uninterpreted.UISortAllSat
+import Data.SBV
+
+import BenchSuite.Bench.Bench
+
+benchmarks :: Runner
+benchmarks =  rGroup
+  [ run "genLs" genLs `using` runner allSatWith -- could be expensive
+  ]
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Append.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Append.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Append.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Append
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.Append
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.Append(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.Append
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+
+-- | orphaned instance for benchmarks
+instance NFData a => NFData (AppS a) where rnf x = seq x ()
+
+benchmarks :: Runner
+benchmarks = runIO "Correctness.Append" correctness
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Basics.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Basics.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Basics.hs
@@ -0,0 +1,38 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Basics
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.Basics
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wno-orphans #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+module BenchSuite.WeakestPreconditions.Basics(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.Basics
+import Data.SBV
+import Data.SBV.Tools.WeakestPreconditions
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (IncS a)
+
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Correctness.Basics skip"        $ correctness Skip Skip
+  , runIO "Correctness.Basics y+1"         $ correctness Skip $ Assign $ \st@IncS{y} -> st{y = y+1}
+  , runIO "Correctness.Basics x>0"         $ correctness (assert "x > 0" (\IncS{x} -> x .> 0)) Skip
+  , runIO "Correctness.Basics x>-5"        $ correctness (assert "x > -5" (\IncS{x} -> x .> -5)) Skip
+  , runIO "Correctness.Basics y is even"   $ correctness Skip (assert "y is even" (\IncS{y} -> y `sMod` 2 .== 0))
+  , runIO "Correctness.Basics y > x"       $ correctness Skip (assert "y > x" (\IncS{x, y} -> y .> x))
+  , runIO "Correctness.Basics skip-assign" $ correctness Skip (Assign $ \st -> st{x = 10, y = 11})
+  ]
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Fib.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Fib.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Fib.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Fig
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.Fig
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.Fib(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.Fib
+import Data.SBV.Tools.WeakestPreconditions
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (FibS a)
+
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Correctness.Fib" correctness
+  , runIO "ImperativeFib" $ traceExecution imperativeFib $ FibS {n = 3, i = 0, k = 0, m = 0}
+  ]
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/GCD.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/GCD.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/GCD.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.GCD
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.GCD
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.GCD(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.GCD
+import Data.SBV.Tools.WeakestPreconditions
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (GCDS a)
+
+
+benchmarks :: Runner
+benchmarks = rGroup
+  [ runIO "Correctness.GCD" correctness
+  , runIO "ImperativeGCD" $ traceExecution imperativeGCD $ GCDS {x = 14, y = 4, i = 0, j = 0}
+  ]
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Instances.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Instances.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Instances.hs
@@ -0,0 +1,24 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Instance
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Helper file to provide common orphaned instances for WeakestPrecondition benchmarks
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.Instances where
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import Control.DeepSeq
+
+
+-- | orphaned instance for benchmarks
+instance NFData a => NFData (ProofResult a) where rnf x = seq x ()
+instance NFData a => NFData (Status a) where rnf x = seq x ()
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntDiv.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntDiv.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntDiv.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.IntDiv
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.IntDiv
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.IntDiv(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.IntDiv
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (DivS a)
+
+
+benchmarks :: Runner
+benchmarks = runIO "Correctness.IntDiv" correctness
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntSqrt.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntSqrt.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/IntSqrt.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.IntSqrt
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.IntSqrt
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.IntSqrt(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.IntSqrt
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (SqrtS a)
+
+
+benchmarks :: Runner
+benchmarks = runIO "Correctness.IntSqrt" correctness
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Length.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Length.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Length.hs
@@ -0,0 +1,23 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Length
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.Length
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module BenchSuite.WeakestPreconditions.Length(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.Length
+
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+benchmarks :: Runner
+benchmarks = runIO "Correctness.Length" correctness
diff --git a/SBVBenchSuite/BenchSuite/WeakestPreconditions/Sum.hs b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Sum.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/BenchSuite/WeakestPreconditions/Sum.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : BenchSuite.WeakestPreconditions.Sum
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Bench suite for Documentation.SBV.Examples.WeakestPreconditions.Sum
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+module BenchSuite.WeakestPreconditions.Sum(benchmarks) where
+
+import Documentation.SBV.Examples.WeakestPreconditions.Sum
+import Data.SBV
+
+import Control.DeepSeq
+import BenchSuite.Bench.Bench
+import BenchSuite.WeakestPreconditions.Instances()
+
+instance NFData a => NFData (SumS a)
+
+
+benchmarks :: Runner
+benchmarks = rGroup [ runIO "Correctness.Sum.correctInvariant"     $ correctness correctInvariant (Just measure)
+                    , runIO "Correctness.Sum.alwaysFalseInvariant" $ correctness alwaysFalseInvariant Nothing
+                    , runIO "Correctness.Sum.alwaysTrueInvariant"  $ correctness alwaysTrueInvariant Nothing
+                    , runIO "Correctness.Sum.loopInvariant"        $ correctness loopInvariant Nothing
+                    , runIO "Correctness.Sum.badMeasure1"          $ correctness badMeasure1Invariant (Just badMeasure1)
+                    , runIO "Correctness.Sum.badMeasure2"          $ correctness badMeasure2Invariant (Just badMeasure2)
+                    ]
+             where
+               correctInvariant     SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+               measure              SumS{n, i}    = [n - i]
+               alwaysFalseInvariant _             = sFalse
+               alwaysTrueInvariant  _             =  sTrue
+               loopInvariant        SumS{n, i, s} = s .<= i .&& s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+               badMeasure1Invariant SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+               badMeasure1          SumS{i}       = [- i]
+               badMeasure2Invariant SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+               badMeasure2          SumS{n, i}    = [n + i]
diff --git a/SBVBenchSuite/SBVBench.hs b/SBVBenchSuite/SBVBench.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/SBVBench.hs
@@ -0,0 +1,376 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : SBVBench
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Entry point to benchmark SBV. We define this as a separate cabal target so
+-- that performance regressions can continue to occur as other fine-tuning
+-- happens in parallel
+-----------------------------------------------------------------------------
+
+module Main where
+
+import           Test.Tasty hiding (defaultMain)
+import           Test.Tasty.Bench
+
+import           BenchSuite.Bench.Bench
+
+-- Puzzles
+import qualified BenchSuite.Puzzles.Birthday
+import qualified BenchSuite.Puzzles.Coins
+-- import qualified BenchSuite.Puzzles.Counts -- see comment below
+import qualified BenchSuite.Puzzles.DogCatMouse
+-- import qualified BenchSuite.Puzzles.Euler185
+import qualified BenchSuite.Puzzles.Garden
+import qualified BenchSuite.Puzzles.LadyAndTigers
+import qualified BenchSuite.Puzzles.MagicSquare
+import qualified BenchSuite.Puzzles.NQueens
+import qualified BenchSuite.Puzzles.SendMoreMoney
+import qualified BenchSuite.Puzzles.Sudoku
+-- import qualified BenchSuite.Puzzles.U2Bridge
+
+-- BitPrecise
+import qualified BenchSuite.BitPrecise.BitTricks
+-- import qualified BenchSuite.BitPrecise.BrokenSearch
+-- import qualified BenchSuite.BitPrecise.Legato
+-- import qualified BenchSuite.BitPrecise.MergeSort
+-- import qualified BenchSuite.BitPrecise.MultMask
+-- import qualified BenchSuite.BitPrecise.PrefixSum
+
+-- Queries
+import qualified BenchSuite.Queries.AllSat
+import qualified BenchSuite.Queries.CaseSplit
+-- import qualified BenchSuite.Queries.Concurrency
+import qualified BenchSuite.Queries.Enums
+import qualified BenchSuite.Queries.FourFours
+import qualified BenchSuite.Queries.GuessNumber
+import qualified BenchSuite.Queries.Interpolants
+import qualified BenchSuite.Queries.UnsatCore
+
+-- Weakest Preconditions
+import qualified BenchSuite.WeakestPreconditions.Append
+import qualified BenchSuite.WeakestPreconditions.Basics
+import qualified BenchSuite.WeakestPreconditions.Fib
+import qualified BenchSuite.WeakestPreconditions.GCD
+import qualified BenchSuite.WeakestPreconditions.IntDiv
+import qualified BenchSuite.WeakestPreconditions.IntSqrt
+import qualified BenchSuite.WeakestPreconditions.Length
+import qualified BenchSuite.WeakestPreconditions.Sum
+
+-- Optimization
+import qualified BenchSuite.Optimization.Enumerate
+import qualified BenchSuite.Optimization.ExtField
+import qualified BenchSuite.Optimization.LinearOpt
+import qualified BenchSuite.Optimization.Production
+import qualified BenchSuite.Optimization.VM
+
+-- Uninterpreted
+import qualified BenchSuite.Uninterpreted.AUF
+import qualified BenchSuite.Uninterpreted.Deduce
+import qualified BenchSuite.Uninterpreted.Function
+import qualified BenchSuite.Uninterpreted.Multiply
+import qualified BenchSuite.Uninterpreted.Shannon
+import qualified BenchSuite.Uninterpreted.Sort
+import qualified BenchSuite.Uninterpreted.UISortAllSat
+
+-- Proof Tools
+import qualified BenchSuite.ProofTools.BMC
+import qualified BenchSuite.ProofTools.Fibonacci
+import qualified BenchSuite.ProofTools.Strengthen
+import qualified BenchSuite.ProofTools.Sum
+
+-- Code Generation
+import qualified BenchSuite.CodeGeneration.AddSub
+import qualified BenchSuite.CodeGeneration.CRC_USB5
+import qualified BenchSuite.CodeGeneration.Fibonacci
+import qualified BenchSuite.CodeGeneration.GCD
+import qualified BenchSuite.CodeGeneration.PopulationCount
+import qualified BenchSuite.CodeGeneration.Uninterpreted
+
+-- Crypto
+import qualified BenchSuite.Crypto.AES
+import qualified BenchSuite.Crypto.RC4
+import qualified BenchSuite.Crypto.SHA
+
+-- Miscellaneous
+import qualified BenchSuite.Misc.Auxiliary
+import qualified BenchSuite.Misc.Enumerate
+-- import qualified BenchSuite.Misc.Floating
+import qualified BenchSuite.Misc.ModelExtract
+import qualified BenchSuite.Misc.Newtypes
+import qualified BenchSuite.Misc.NoDiv0
+-- import qualified BenchSuite.Misc.Polynomials
+import qualified BenchSuite.Misc.SetAlgebra
+import qualified BenchSuite.Misc.SoftConstrain
+import qualified BenchSuite.Misc.Tuple
+
+-- Lists
+import qualified BenchSuite.Lists.BoundedMutex
+import qualified BenchSuite.Lists.Fibonacci
+
+-- Strings
+import qualified BenchSuite.Strings.RegexCrossword
+import qualified BenchSuite.Strings.SQLInjection
+
+-- Existentials
+-- import qualified BenchSuite.Existentials.CRCPolynomial
+import qualified BenchSuite.Existentials.Diophantine
+
+-- Transformers
+import qualified BenchSuite.Transformers.SymbolicEval
+
+
+{-
+To benchmark sbv we require two use cases: For continuous integration we want a
+snapshot of all benchmarks at a given point in time and we want to be able to
+compare benchmarks over time for performance tuning. For this module we default
+to the continuous integration flow. The workflow for fine grained performance
+analysis is to run a benchmark, make your changes, then rerun the benchmark. See
+<https://hackage.haskell.org/package/tasty-bench> package, for instructions on
+comparing benchmarks, using patterns to run a single benchmark or log results to
+a file. Furthermore, we provide a few utility functions to ease the details in
+benchmarking standalone z3 programs and sbv programs in Utils.SBVBenchFramework.
+`cabal build SBVBench; ./SBVBench --match=pattern -- 'NQueens'`. Note that
+comparisons with benchmarks run on different machines will be spurious so use
+your best judgment.
+-}
+main :: IO ()
+main = do
+  -- timeout is set to 2 minutes
+  let timeout    = localOption (mkTimeout 120000000)
+      opts       = [timeout]
+      setOptions :: Benchmark -> Benchmark
+      setOptions = foldr (.) id opts
+
+  -- run the benchmarks
+  defaultMain
+    $ setOptions <$> [ puzzles
+                     , bitPrecise
+                     , queries
+                     , weakestPreconditions
+                     , optimizations
+                     , uninterpreted
+                     , proofTools
+                     -- , codeGeneration :NOTE code generation takes too much time and memory
+                     -- crypto :NOTE crypto also is too expensive
+                     , misc
+                     , lists
+                     , strings
+                     , transformers
+                     ]
+
+-- | Benchmarks for 'Documentation.SBV.Examples.Puzzles'. Each benchmark file
+-- defines a 'benchmarks' function which returns a
+-- 'BenchSuite.Bench.Bench.Runner'. We want to allow benchmarks to be defined as
+-- closely as possible to the problems being solved. But for practical reasons
+-- we may desire to prevent benchmarking 'Data.SBV.allSat' calls because they
+-- could timeout. Thus by using 'BenchSuite.Bench.Bench.Runner' we can define
+-- the benchmark mirroring the logic of the symbolic program and change solver
+-- details _without_ redefining the benchmark, as I have done below by
+-- converting all examples to use 'Data.SBV.satWith'. For benchmarks which do
+-- not need to run with different solver configurations, such as queries we run
+-- with `BenchSuite.Bench.Bench.Runner.runIO`
+
+--------------------------- Puzzles ---------------------------------------------
+puzzleBenchmarks :: [Runner]
+puzzleBenchmarks = [ BenchSuite.Puzzles.Coins.benchmarks
+                   -- disable Counts for now, there is some issue with the counts function
+                   -- in a repl it works fine, when compiled it does not terminate
+                   -- , BenchSuite.Puzzles.Counts.benchmarks
+                   , BenchSuite.Puzzles.Birthday.benchmarks
+                   , BenchSuite.Puzzles.DogCatMouse.benchmarks
+                   -- expensive
+                   -- , BenchSuite.Puzzles.Euler185.benchmarks
+                   , BenchSuite.Puzzles.Garden.benchmarks
+                   , BenchSuite.Puzzles.LadyAndTigers.benchmarks
+                   , BenchSuite.Puzzles.SendMoreMoney.benchmarks
+                   , BenchSuite.Puzzles.NQueens.benchmarks
+                   , BenchSuite.Puzzles.MagicSquare.benchmarks
+                   , BenchSuite.Puzzles.Sudoku.benchmarks
+                   -- TODO: sbv finishes cnt3 in 100s but z3 does so in 83 ms,
+                   -- probably an issue with z3 here ,
+                   -- BenchSuite.Puzzles.U2Bridge.benchmarks
+                   ]
+
+puzzles :: Benchmark
+puzzles = bgroup "Puzzles" $ runBenchmark <$> puzzleBenchmarks
+
+
+--------------------------- BitPrecise ------------------------------------------
+bitPreciseBenchmarks :: [Runner]
+bitPreciseBenchmarks = [ BenchSuite.BitPrecise.BitTricks.benchmarks
+                       -- These benchmarks blow the stack :TODO fix them
+                       -- , BenchSuite.BitPrecise.BrokenSearch.benchmarks
+                       -- , BenchSuite.BitPrecise.Legato.benchmarks
+                       -- , BenchSuite.BitPrecise.MergeSort.benchmarks
+                       -- , BenchSuite.BitPrecise.MultMask.benchmarks
+                       -- expensive
+                       -- , BenchSuite.BitPrecise.PrefixSum.benchmarks
+                       ]
+
+bitPrecise :: Benchmark
+bitPrecise = bgroup "BitPrecise" $ runBenchmark <$> bitPreciseBenchmarks
+
+
+--------------------------- Query -----------------------------------------------
+queryBenchmarks :: [Runner]
+queryBenchmarks = [ BenchSuite.Queries.AllSat.benchmarks
+                  , BenchSuite.Queries.CaseSplit.benchmarks
+                  -- The concurrency demo has STM blocking when benchmarking
+                  -- , BenchSuite.Queries.Concurrency.benchmarks
+                  , BenchSuite.Queries.Enums.benchmarks
+                  , BenchSuite.Queries.FourFours.benchmarks
+                  , BenchSuite.Queries.GuessNumber.benchmarks
+                  , BenchSuite.Queries.Interpolants.benchmarks
+                  , BenchSuite.Queries.UnsatCore.benchmarks
+                  ]
+
+queries :: Benchmark
+queries = bgroup "Queries" $ runBenchmark <$> queryBenchmarks
+
+
+--------------------------- WeakestPreconditions --------------------------------
+weakestPreconditionBenchmarks :: [Runner]
+weakestPreconditionBenchmarks =
+  [ BenchSuite.WeakestPreconditions.Append.benchmarks
+  , BenchSuite.WeakestPreconditions.Basics.benchmarks
+  , BenchSuite.WeakestPreconditions.Fib.benchmarks
+  , BenchSuite.WeakestPreconditions.GCD.benchmarks
+  , BenchSuite.WeakestPreconditions.IntDiv.benchmarks
+  , BenchSuite.WeakestPreconditions.IntSqrt.benchmarks
+  , BenchSuite.WeakestPreconditions.Length.benchmarks
+  , BenchSuite.WeakestPreconditions.Sum.benchmarks
+  ]
+
+weakestPreconditions :: Benchmark
+weakestPreconditions = bgroup "WeakestPreconditions" $
+  runBenchmark <$> weakestPreconditionBenchmarks
+
+
+--------------------------- Optimizations ---------------------------------------
+optimizationBenchmarks :: [Runner]
+optimizationBenchmarks = [ BenchSuite.Optimization.Enumerate.benchmarks
+                         , BenchSuite.Optimization.ExtField.benchmarks
+                         , BenchSuite.Optimization.LinearOpt.benchmarks
+                         , BenchSuite.Optimization.Production.benchmarks
+                         , BenchSuite.Optimization.VM.benchmarks
+                         ]
+
+optimizations :: Benchmark
+optimizations = bgroup "Optimizations" $ runBenchmark <$> optimizationBenchmarks
+
+
+--------------------------- Uninterpreted ---------------------------------------
+uninterpretedBenchmarks :: [Runner]
+uninterpretedBenchmarks = [ BenchSuite.Uninterpreted.AUF.benchmarks
+                          , BenchSuite.Uninterpreted.Deduce.benchmarks
+                          , BenchSuite.Uninterpreted.Function.benchmarks
+                          , BenchSuite.Uninterpreted.Multiply.benchmarks
+                          , BenchSuite.Uninterpreted.Shannon.benchmarks
+                          , BenchSuite.Uninterpreted.Sort.benchmarks
+                          , BenchSuite.Uninterpreted.UISortAllSat.benchmarks
+                          ]
+
+uninterpreted :: Benchmark
+uninterpreted = bgroup "Uninterpreted" $ runBenchmark <$> uninterpretedBenchmarks
+
+
+--------------------------- ProofTools -----------------------------------------
+proofToolBenchmarks :: [Runner]
+proofToolBenchmarks = [ BenchSuite.ProofTools.BMC.benchmarks
+                      , BenchSuite.ProofTools.Fibonacci.benchmarks
+                      , BenchSuite.ProofTools.Strengthen.benchmarks
+                      , BenchSuite.ProofTools.Sum.benchmarks
+                      ]
+
+proofTools :: Benchmark
+proofTools = bgroup "ProofTools" $ runBenchmark <$> proofToolBenchmarks
+
+
+--------------------------- Code Generation -------------------------------------
+codeGenerationBenchmarks :: [Runner]
+codeGenerationBenchmarks = [ BenchSuite.CodeGeneration.AddSub.benchmarks
+                           , BenchSuite.CodeGeneration.CRC_USB5.benchmarks
+                           , BenchSuite.CodeGeneration.Fibonacci.benchmarks
+                           , BenchSuite.CodeGeneration.GCD.benchmarks
+                           , BenchSuite.CodeGeneration.PopulationCount.benchmarks
+                           , BenchSuite.CodeGeneration.Uninterpreted.benchmarks
+                           ]
+
+codeGeneration :: Benchmark
+codeGeneration = bgroup "CodeGeneration" $
+                 runBenchmark <$> codeGenerationBenchmarks
+
+
+--------------------------- Crypto ----------------------------------------------
+cryptoBenchmarks :: [Runner]
+cryptoBenchmarks = [ BenchSuite.Crypto.AES.benchmarks
+                   , BenchSuite.Crypto.RC4.benchmarks
+                   , BenchSuite.Crypto.SHA.benchmarks
+                   ]
+
+crypto :: Benchmark
+crypto = bgroup "Crypto" $ runBenchmark <$> cryptoBenchmarks
+
+
+--------------------------- Miscellaneous ---------------------------------------
+miscBenchmarks :: [Runner]
+miscBenchmarks = [ BenchSuite.Misc.Auxiliary.benchmarks
+                 , BenchSuite.Misc.Enumerate.benchmarks
+                 -- expensive
+                 -- , BenchSuite.Misc.Floating.benchmarks
+                 , BenchSuite.Misc.ModelExtract.benchmarks
+                 , BenchSuite.Misc.Newtypes.benchmarks
+                 , BenchSuite.Misc.NoDiv0.benchmarks
+                 -- killed by OS, TODO: Investigate
+                 -- , BenchSuite.Misc.Polynomials.benchmarks
+                 , BenchSuite.Misc.SetAlgebra.benchmarks
+                 , BenchSuite.Misc.SoftConstrain.benchmarks
+                 , BenchSuite.Misc.Tuple.benchmarks
+                 ]
+
+misc :: Benchmark
+misc = bgroup "Miscellaneous" $ runBenchmark <$> miscBenchmarks
+
+
+--------------------------- Lists -----------------------------------------------
+listBenchmarks :: [Runner]
+listBenchmarks = [ BenchSuite.Lists.BoundedMutex.benchmarks
+                 , BenchSuite.Lists.Fibonacci.benchmarks
+                 ]
+
+lists :: Benchmark
+lists = bgroup "Lists" $ runBenchmark <$> listBenchmarks
+
+
+--------------------------- Strings ---------------------------------------------
+stringBenchmarks :: [Runner]
+stringBenchmarks = [ BenchSuite.Strings.RegexCrossword.benchmarks
+                   , BenchSuite.Strings.SQLInjection.benchmarks
+                   ]
+
+strings :: Benchmark
+strings = bgroup "Strings" $ runBenchmark <$> stringBenchmarks
+
+
+--------------------------- Existentials ----------------------------------------
+existentialBenchmarks :: [Runner]
+existentialBenchmarks = [ -- BenchSuite.Existentials.CRCPolynomial.benchmarks
+                          BenchSuite.Existentials.Diophantine.benchmarks
+                        ]
+
+existentials :: Benchmark
+existentials = bgroup "Existentials" $ runBenchmark <$> existentialBenchmarks
+
+
+--------------------------- Transformers ----------------------------------------
+transformerBenchmarks :: [Runner]
+transformerBenchmarks = [ BenchSuite.Transformers.SymbolicEval.benchmarks
+                        ]
+
+transformers :: Benchmark
+transformers = bgroup "Transformers" $ runBenchmark <$> transformerBenchmarks
diff --git a/SBVBenchSuite/Utils/SBVBenchFramework.hs b/SBVBenchSuite/Utils/SBVBenchFramework.hs
new file mode 100644
--- /dev/null
+++ b/SBVBenchSuite/Utils/SBVBenchFramework.hs
@@ -0,0 +1,126 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Utils.SBVTestFramework
+-- Copyright : (c) Jeffrey Young
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Various goodies for benchmarking SBV
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
+{-# OPTIONS_GHC -Wno-orphans -Wno-missing-methods #-} -- for ProvableM orphan
+
+module Utils.SBVBenchFramework
+  ( mkExecString
+  , mkFileName
+  , module Data.SBV
+  , timeStamp
+  , getDate
+  , dateStamp
+  , benchResultsFile
+  , classifier
+  , overheadClassifier
+  , filterOverhead
+  ) where
+
+import qualified Data.List      as L
+import           System.Process (showCommandForUser)
+import           System.Random
+import           Data.Char (isSpace)
+import           System.FilePath ((</>), (<.>))
+import           Data.Time.Clock
+import           Data.Time.Calendar
+
+import           Data.SBV
+import           Data.SBV.Internals
+
+-- | make the string to call executable from the command line. All the heavy
+-- lifting is done by 'System.Process.showCommandForUser', the rest is just
+-- projections out of 'Data.SBV.SMTConfig'
+mkExecString :: SMTConfig -> FilePath -> String
+mkExecString config inputFile = showCommandForUser exec $ inputFile:opts
+  where smtSolver = solver config
+        exec      = executable smtSolver
+        opts'     = options smtSolver config
+        opts      = L.delete "-in" opts' -- remove opt for interactive mode so
+                                         -- that this plays nice with
+                                         -- criterion environments
+
+-- | simple wrapper to create random file names.
+mkFileName :: IO String
+mkFileName = do gen <- newStdGen
+                return . take 32 $ randomRs ('a','z') gen
+
+
+-- | Get (year, month, day)
+getDate :: IO (Integer, Int, Int)
+getDate = toGregorian . utctDay <$> getCurrentTime
+
+dateStamp :: IO String
+dateStamp = (\(y,m,d) -> show y ++ "-" ++
+                         show m ++ "-" ++
+                         show d) <$> getDate
+
+-- | Construct a timestamp
+timeStamp :: IO String
+timeStamp = fmap (spaceTo '-') . show <$> getCurrentTime
+
+spaceTo :: Char -> Char -> Char
+spaceTo c x | isSpace x = c
+            | True      = x
+
+-- | Construct a benchmark file name. The input name should be a time stamp or
+-- whatever you want to name the benchmark
+benchResultsFile :: FilePath -> FilePath
+benchResultsFile nm = "SBVBenchSuite" </> "BenchResults" </> nm <.> "csv"
+
+-- | The classifier takes a line of text and chunks it into (group-name,
+-- benchmark-name), for example:
+classifier :: Char -> String -> Maybe (String, String)
+classifier e nm = Just $ last chunks
+  where
+    is :: [Int]
+    is = L.elemIndices e nm
+
+    chunks = [(a, drop 1 b) | (a, b) <- fmap (`L.splitAt` nm) is]
+
+-- | We live with some code duplication due to the way overhead benchmarks apply
+-- the "standalone" and "sbv" labels. By abstracting for overhead benchmarks
+-- these labels will be appended to the description string. This is counter to
+-- the assumptions of the bench-show package, thus we define a specialty
+-- classifier to handle the overhead case
+overheadClassifier :: Char -> String -> Maybe (String, String)
+overheadClassifier e nm = Just $ last $ fmap (\(a,b) -> (drop 1 b, a)) chunks
+  where
+    is :: [Int]
+    is = L.elemIndices e nm
+
+    chunks = fmap (`L.splitAt` nm) is
+
+-- | a helper function to remove benchmarks where the over head benchmark
+-- doesn't work or failed for some reason. This will write a filtered version
+-- and return the file path to that filtered version.
+filterOverhead :: Char -> FilePath -> IO FilePath
+filterOverhead e fp = do (header:file) <- L.lines <$> readFile fp
+                         -- only keep instances of 3 or greater. This number
+                         -- comes from splitting benchmark output by '/'.
+                         -- Because our groups are separated by '//' and the
+                         -- overhead by '/' an overhead run will have >3 splits,
+                         -- but a normal benchmark will only have two from '//'
+                         let filteredContent   = filter ((>=3) . length . L.elemIndices e) file
+                             filteredFilePath  = fp ++ "_filtered"
+                         writeFile  filteredFilePath (concat $ header:filteredContent)
+                         return filteredFilePath
+
+-- NO INSTANCE ON PURPOSE; don't want to prove goals. We provide this instance
+-- just to allow the testsuite to run tests with try to Prove Goals. In general,
+-- this violates the invariants promised by the @ProvableM@ and @SatisfiableM@
+-- type classes. Thus, this should not be publicly exposed under any
+-- circumstances.
+instance ProvableM IO (SymbolicT IO ())
diff --git a/SBVTestSuite/GoldFiles/U2Bridge.gold b/SBVTestSuite/GoldFiles/U2Bridge.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/U2Bridge.gold
@@ -0,0 +1,33 @@
+Solution #1:
+  s0  = False :: Bool
+  s1  =  Edge :: U2Member
+  s2  =  Bono :: U2Member
+  s3  =  True :: Bool
+  s4  =  Bono :: U2Member
+  s5  =  Bono :: U2Member
+  s6  = False :: Bool
+  s7  = Larry :: U2Member
+  s8  =  Adam :: U2Member
+  s9  =  True :: Bool
+  s10 =  Edge :: U2Member
+  s11 =  Bono :: U2Member
+  s12 = False :: Bool
+  s13 =  Edge :: U2Member
+  s14 =  Bono :: U2Member
+Solution #2:
+  s0  = False :: Bool
+  s1  =  Edge :: U2Member
+  s2  =  Bono :: U2Member
+  s3  =  True :: Bool
+  s4  =  Edge :: U2Member
+  s5  =  Bono :: U2Member
+  s6  = False :: Bool
+  s7  = Larry :: U2Member
+  s8  =  Adam :: U2Member
+  s9  =  True :: Bool
+  s10 =  Bono :: U2Member
+  s11 =  Bono :: U2Member
+  s12 = False :: Bool
+  s13 =  Edge :: U2Member
+  s14 =  Bono :: U2Member
+Found 2 different solutions.
diff --git a/SBVTestSuite/GoldFiles/addSub.gold b/SBVTestSuite/GoldFiles/addSub.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/addSub.gold
@@ -0,0 +1,105 @@
+== BEGIN: "Makefile" ================
+# Makefile for addSub. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: addSub_driver
+
+addSub.o: addSub.c addSub.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+addSub_driver.o: addSub_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+addSub_driver: addSub.o addSub_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f addSub_driver
+== END: "Makefile" ==================
+== BEGIN: "addSub.h" ================
+/* Header file for addSub. Automatically generated by SBV. Do not edit! */
+
+#ifndef __addSub__HEADER_INCLUDED__
+#define __addSub__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
+            SWord8 *dif);
+
+#endif /* __addSub__HEADER_INCLUDED__ */
+== END: "addSub.h" ==================
+== BEGIN: "addSub_driver.c" ================
+/* Example driver program for addSub. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "addSub.h"
+
+int main(void)
+{
+  SWord8 sum;
+  SWord8 dif;
+
+  addSub(76, 92, &sum, &dif);
+
+  printf("addSub(76, 92, &sum, &dif) ->\n");
+  printf("  sum = %"PRIu8"\n", sum);
+  printf("  dif = %"PRIu8"\n", dif);
+
+  return 0;
+}
+== END: "addSub_driver.c" ==================
+== BEGIN: "addSub.c" ================
+/* File: "addSub.c". Automatically generated by SBV. Do not edit! */
+
+#include "addSub.h"
+
+void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
+            SWord8 *dif)
+{
+  const SWord8 s0 = x;
+  const SWord8 s1 = y;
+  const SWord8 s2 = s0 + s1;
+  const SWord8 s3 = s0 - s1;
+
+  *sum = s2;
+  *dif = s3;
+}
+== END: "addSub.c" ==================
diff --git a/SBVTestSuite/GoldFiles/adt00.gold b/SBVTestSuite/GoldFiles/adt00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt00.gold
@@ -0,0 +1,94 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (= s0 s0))
+[GOOD] (define-fun s2 () Bool (not s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt01.gold b/SBVTestSuite/GoldFiles/adt01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt01.gold
@@ -0,0 +1,102 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () ADT ((as APair ADT) ((as AInt64 ADT) #x0000000000000004) ((as AMaybe ADT) ((as Just (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))) (mkSBVTuple3 0.0 (fp #b0 #b10000010 #b10000000000000000000000) (mkSBVTuple2 ((as Left (Either Int (_ FloatingPoint  8 24))) 3) (seq.++ (seq.unit false) (seq.unit true))))))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (APair (AInt64 #x0000000000000004)
+              (AMaybe (Just (mkSBVTuple3 0.0
+                                         (fp #b0 #x82 #b10000000000000000000000)
+                                         (mkSBVTuple2 (Left 3)
+                                                      (seq.++ (seq.unit false)
+                                                              (seq.unit true)))))))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("e",APair (AInt64 4) (AMaybe (Just (0.0,12.0,(Left 3,[False,True])))) :: ADT)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt02.gold b/SBVTestSuite/GoldFiles/adt02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt02.gold
@@ -0,0 +1,96 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AList Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AList (seq.unit 2))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("e",AList [2] :: ADT)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt03.gold b/SBVTestSuite/GoldFiles/adt03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt03.gold
@@ -0,0 +1,95 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "e"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AList Bool) s0))
+[GOOD] (define-fun s2 () Bool ((as is-AFP Bool) s0))
+[GOOD] (define-fun s3 () Bool (and s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt04.gold b/SBVTestSuite/GoldFiles/adt04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt04.gold
@@ -0,0 +1,180 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s5 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AInteger Bool) s0))
+[GOOD] (define-fun s2 () Int (getAInteger_1 s0))
+[GOOD] (define-fun s4 () Bool (>= s2 s3))
+[GOOD] (define-fun s6 () Bool (<= s2 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 4)))
+[GOOD] (push 1)
+[GOOD] (define-fun s7 () ADT ((as AInteger ADT) 4))
+[GOOD] (define-fun s8 () Bool (= s0 s7))
+[GOOD] (define-fun s9 () Bool (not s8))
+[GOOD] (assert s9)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 0)))
+[GOOD] (push 1)
+[GOOD] (define-fun s10 () ADT ((as AInteger ADT) 0))
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] (assert s12)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 3)))
+[GOOD] (push 1)
+[GOOD] (define-fun s13 () ADT ((as AInteger ADT) 3))
+[GOOD] (define-fun s14 () Bool (= s0 s13))
+[GOOD] (define-fun s15 () Bool (not s14))
+[GOOD] (assert s15)
+Fast allSat, Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 5)))
+[GOOD] (push 1)
+[GOOD] (define-fun s16 () ADT ((as AInteger ADT) 5))
+[GOOD] (define-fun s17 () Bool (= s0 s16))
+[GOOD] (define-fun s18 () Bool (not s17))
+[GOOD] (assert s18)
+Fast allSat, Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 2)))
+[GOOD] (push 1)
+[GOOD] (define-fun s19 () ADT ((as AInteger ADT) 2))
+[GOOD] (define-fun s20 () Bool (= s0 s19))
+[GOOD] (define-fun s21 () Bool (not s20))
+[GOOD] (assert s21)
+Fast allSat, Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AInteger 1)))
+[GOOD] (push 1)
+[GOOD] (define-fun s22 () ADT ((as AInteger ADT) 1))
+[GOOD] (define-fun s23 () Bool (= s0 s22))
+[GOOD] (define-fun s24 () Bool (not s23))
+[GOOD] (assert s24)
+Fast allSat, Looking for solution 7
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+MODEL:Satisfiable. Model:
+  a = AInteger 1 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 2 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 5 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 3 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 0 :: ADT
+MODEL:Satisfiable. Model:
+  a = AInteger 4 :: ADT
diff --git a/SBVTestSuite/GoldFiles/adt05.gold b/SBVTestSuite/GoldFiles/adt05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt05.gold
@@ -0,0 +1,130 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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 HO_ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s4 () (_ FloatingPoint  8 24) (fp #b0 #b10000001 #b00000000000000000000000))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] (declare-fun s1 () ADT) ; tracks user variable "b"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s1)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s1)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (is-AFloat s0))
+[GOOD] (define-fun s3 () (_ FloatingPoint  8 24) (getAFloat_1 s0))
+[GOOD] (define-fun s5 () Bool (fp.eq s3 s4))
+[GOOD] (define-fun s6 () Bool (and s2 s5))
+[GOOD] (define-fun s7 () Bool (is-AFloat s1))
+[GOOD] (define-fun s8 () (_ FloatingPoint  8 24) (getAFloat_1 s1))
+[GOOD] (define-fun s9 () Bool (fp.isNaN s8))
+[GOOD] (define-fun s10 () Bool (and s7 s9))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (assert s10)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AFloat (fp #b0 #b10000001 #b00000000000000000000000))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (AFloat (fp #b0 #b11111111 #b10000000000000000000000))))
+[GOOD] (push 1)
+[GOOD] (define-fun s11 () ADT ((as AFloat ADT) (fp #b0 #b10000001 #b00000000000000000000000)))
+[GOOD] (define-fun s12 () Bool (= s0 s11))
+[GOOD] (define-fun s13 () Bool (not s12))
+[GOOD] (assert s13)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s14 () ADT ((as AFloat ADT) (_ NaN 8 24)))
+[GOOD] (define-fun s15 () Bool (= s1 s14))
+[GOOD] (define-fun s16 () Bool (not s15))
+[GOOD] (assert s16)
+[GOOD] (assert s12)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+MODEL:Satisfiable. Model:
+  a = AFloat 4.0 :: ADT
+  b = AFloat NaN :: ADT
diff --git a/SBVTestSuite/GoldFiles/adt06.gold b/SBVTestSuite/GoldFiles/adt06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt06.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; User defined ADT: ADT
+[GOOD] (declare-datatype ADT (
+           (AEmpty)
+           (ABool (getABool_1 Bool))
+           (AInteger (getAInteger_1 Int))
+           (AWord8 (getAWord8_1 (_ BitVec 8)))
+           (AWord16 (getAWord16_1 (_ BitVec 16)))
+           (AWord32 (getAWord32_1 (_ BitVec 32)))
+           (AWord64 (getAWord64_1 (_ BitVec 64)))
+           (AInt8 (getAInt8_1 (_ BitVec 8)))
+           (AInt16 (getAInt16_1 (_ BitVec 16)))
+           (AInt32 (getAInt32_1 (_ BitVec 32)))
+           (AInt64 (getAInt64_1 (_ BitVec 64)))
+           (AWord1 (getAWord1_1 (_ BitVec 1)))
+           (AWord5 (getAWord5_1 (_ BitVec 5)))
+           (AWord30 (getAWord30_1 (_ BitVec 30)))
+           (AInt1 (getAInt1_1 (_ BitVec 1)))
+           (AInt5 (getAInt5_1 (_ BitVec 5)))
+           (AInt30 (getAInt30_1 (_ BitVec 30)))
+           (AReal (getAReal_1 Real))
+           (AFloat (getAFloat_1 (_ FloatingPoint  8 24)))
+           (ADouble (getADouble_1 (_ FloatingPoint 11 53)))
+           (AFP (getAFP_1 (_ FloatingPoint 5 12)))
+           (AString (getAString_1 String))
+           (AList (getAList_1 (Seq Int)))
+           (ATuple (getATuple_1 (SBVTuple2 (_ FloatingPoint 11 53) (Seq (SBVTuple2 (_ BitVec 5) (Seq (_ FloatingPoint  8 24)))))))
+           (AMaybe (getAMaybe_1 (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool))))))
+           (AEither (getAEither_1 (Either (SBVTuple2 (Maybe Int) Bool) (Seq Int))))
+           (APair (getAPair_1 ADT) (getAPair_2 ADT))
+           (KChar (getKChar_1 String))
+           (KRational (getKRational_1 SBVRational))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () ADT) ; tracks user variable "a"
+[GOOD] (assert (and (= 1 (str.len (getKChar_1 s0)))
+                    (< 0 (sbv.rat.denominator (getKRational_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-AMaybe Bool) s0))
+[GOOD] (define-fun s2 () (Maybe (SBVTuple3 Real (_ FloatingPoint  8 24) (SBVTuple2 (Either Int (_ FloatingPoint  8 24)) (Seq Bool)))) (getAMaybe_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (AMaybe (Just (mkSBVTuple3 2.0
+                                  (fp #b0 #x00 #b00000000000000000000001)
+                                  (mkSBVTuple2 (Right (fp #b0 #x00 #b00000000000000000100000))
+                                               (seq.unit true)))))))
+
+getValue: AMaybe (Just (2.0,1.0e-45,(Right 4.5e-44,[True])))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_chk01.gold b/SBVTestSuite/GoldFiles/adt_chk01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_chk01.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (
+           (A (getA_1 Int))
+           (B (getB_1 (_ BitVec 8)))
+           (C (getC_1 A) (getC_2 A))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () A ((as A A) 13))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () A) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A 13)))
+Result: A 13
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr00.gold b/SBVTestSuite/GoldFiles/adt_expr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr00.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr00c.gold b/SBVTestSuite/GoldFiles/adt_expr00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr00c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr01.gold b/SBVTestSuite/GoldFiles/adt_expr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr01.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 7)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr01c.gold b/SBVTestSuite/GoldFiles/adt_expr01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr01c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr02.gold b/SBVTestSuite/GoldFiles/adt_expr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr02.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr02c.gold b/SBVTestSuite/GoldFiles/adt_expr02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr02c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr03.gold b/SBVTestSuite/GoldFiles/adt_expr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr03.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 28)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr03c.gold b/SBVTestSuite/GoldFiles/adt_expr03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr03c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr04.gold b/SBVTestSuite/GoldFiles/adt_expr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr04.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 63)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 63))
+Result: 63
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr05.gold b/SBVTestSuite/GoldFiles/adt_expr05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr05.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3969)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3969))
+Result: 3969
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr06.gold b/SBVTestSuite/GoldFiles/adt_expr06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr06.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "a"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s8 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr06c.gold b/SBVTestSuite/GoldFiles/adt_expr06c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr06c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr07.gold b/SBVTestSuite/GoldFiles/adt_expr07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr07.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "b"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr07c.gold b/SBVTestSuite/GoldFiles/adt_expr07c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr07c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr08.gold b/SBVTestSuite/GoldFiles/adt_expr08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr08.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "c"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr08c.gold b/SBVTestSuite/GoldFiles/adt_expr08c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr08c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr09.gold b/SBVTestSuite/GoldFiles/adt_expr09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr09.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "d"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s16 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr09c.gold b/SBVTestSuite/GoldFiles/adt_expr09c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr09c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr10.gold b/SBVTestSuite/GoldFiles/adt_expr10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr10.gold
@@ -0,0 +1,454 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s15 () Expr ((as Val Expr) (- 5)))
+[GOOD] (define-fun s17 () Expr ((as Val Expr) (- 4)))
+[GOOD] (define-fun s19 () Expr ((as Val Expr) (- 3)))
+[GOOD] (define-fun s21 () Expr ((as Val Expr) (- 2)))
+[GOOD] (define-fun s23 () Expr ((as Val Expr) (- 1)))
+[GOOD] (define-fun s25 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s27 () Expr ((as Val Expr) 1))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) 2))
+[GOOD] (define-fun s31 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 4))
+[GOOD] (define-fun s35 () Expr ((as Val Expr) 5))
+[GOOD] (define-fun s37 () Expr ((as Val Expr) 6))
+[GOOD] (define-fun s39 () Expr ((as Val Expr) 7))
+[GOOD] (define-fun s41 () Expr ((as Val Expr) 8))
+[GOOD] (define-fun s43 () Expr ((as Val Expr) 9))
+[GOOD] (define-fun s61 () String "a")
+[GOOD] (define-fun s64 () Int 0)
+[GOOD] (define-fun s65 () String "b")
+[GOOD] (define-fun s67 () String "c")
+[GOOD] (define-fun s71 () Int 1)
+[GOOD] (define-fun s72 () Int 2)
+[GOOD] (define-fun s75 () Int 10)
+[GOOD] (define-fun s78 () Int 3)
+[GOOD] (define-fun s81 () Int 4)
+[GOOD] (define-fun s84 () Int 5)
+[GOOD] (define-fun s85 () Int 6)
+[GOOD] (define-fun s414 () Int 45)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] (declare-fun s2 () Expr)
+[GOOD] (declare-fun s3 () Expr)
+[GOOD] (declare-fun s4 () Expr)
+[GOOD] (declare-fun s5 () Expr)
+[GOOD] (declare-fun s6 () Expr)
+[GOOD] (declare-fun s7 () Expr)
+[GOOD] (declare-fun s8 () Expr)
+[GOOD] (declare-fun s9 () Expr)
+[GOOD] (declare-fun s10 () Expr)
+[GOOD] (declare-fun s11 () Expr)
+[GOOD] (declare-fun s12 () Expr)
+[GOOD] (declare-fun s13 () Expr)
+[GOOD] (declare-fun s14 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s16 () Bool (= s0 s15))
+[GOOD] (define-fun s18 () Bool (= s1 s17))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () Bool (= s3 s21))
+[GOOD] (define-fun s24 () Bool (= s4 s23))
+[GOOD] (define-fun s26 () Bool (= s5 s25))
+[GOOD] (define-fun s28 () Bool (= s6 s27))
+[GOOD] (define-fun s30 () Bool (= s7 s29))
+[GOOD] (define-fun s32 () Bool (= s8 s31))
+[GOOD] (define-fun s34 () Bool (= s9 s33))
+[GOOD] (define-fun s36 () Bool (= s10 s35))
+[GOOD] (define-fun s38 () Bool (= s11 s37))
+[GOOD] (define-fun s40 () Bool (= s12 s39))
+[GOOD] (define-fun s42 () Bool (= s13 s41))
+[GOOD] (define-fun s44 () Bool (= s14 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Bool (and s38 s46))
+[GOOD] (define-fun s48 () Bool (and s36 s47))
+[GOOD] (define-fun s49 () Bool (and s34 s48))
+[GOOD] (define-fun s50 () Bool (and s32 s49))
+[GOOD] (define-fun s51 () Bool (and s30 s50))
+[GOOD] (define-fun s52 () Bool (and s28 s51))
+[GOOD] (define-fun s53 () Bool (and s26 s52))
+[GOOD] (define-fun s54 () Bool (and s24 s53))
+[GOOD] (define-fun s55 () Bool (and s22 s54))
+[GOOD] (define-fun s56 () Bool (and s20 s55))
+[GOOD] (define-fun s57 () Bool (and s18 s56))
+[GOOD] (define-fun s58 () Bool (and s16 s57))
+[GOOD] (define-fun s59 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s60 () String (getVar_1 s0))
+[GOOD] (define-fun s62 () Bool (= s60 s61))
+[GOOD] (define-fun s63 () Bool (and s59 s62))
+[GOOD] (define-fun s66 () Bool (= s60 s65))
+[GOOD] (define-fun s68 () Bool (= s60 s67))
+[GOOD] (define-fun s69 () Bool (or s66 s68))
+[GOOD] (define-fun s70 () Bool (and s59 s69))
+[GOOD] (define-fun s73 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s74 () Int (getVal_1 s0))
+[GOOD] (define-fun s76 () Bool (< s74 s75))
+[GOOD] (define-fun s77 () Bool (and s73 s76))
+[GOOD] (define-fun s79 () Bool (= s74 s75))
+[GOOD] (define-fun s80 () Bool (and s73 s79))
+[GOOD] (define-fun s82 () Bool (> s74 s75))
+[GOOD] (define-fun s83 () Bool (and s73 s82))
+[GOOD] (define-fun s86 () Int (ite s83 s84 s85))
+[GOOD] (define-fun s87 () Int (ite s80 s81 s86))
+[GOOD] (define-fun s88 () Int (ite s77 s78 s87))
+[GOOD] (define-fun s89 () Int (ite s59 s72 s88))
+[GOOD] (define-fun s90 () Int (ite s70 s71 s89))
+[GOOD] (define-fun s91 () Int (ite s63 s64 s90))
+[GOOD] (define-fun s92 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s93 () String (getVar_1 s1))
+[GOOD] (define-fun s94 () Bool (= s61 s93))
+[GOOD] (define-fun s95 () Bool (and s92 s94))
+[GOOD] (define-fun s96 () Bool (= s65 s93))
+[GOOD] (define-fun s97 () Bool (= s67 s93))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (and s92 s98))
+[GOOD] (define-fun s100 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s101 () Int (getVal_1 s1))
+[GOOD] (define-fun s102 () Bool (< s101 s75))
+[GOOD] (define-fun s103 () Bool (and s100 s102))
+[GOOD] (define-fun s104 () Bool (= s75 s101))
+[GOOD] (define-fun s105 () Bool (and s100 s104))
+[GOOD] (define-fun s106 () Bool (> s101 s75))
+[GOOD] (define-fun s107 () Bool (and s100 s106))
+[GOOD] (define-fun s108 () Int (ite s107 s84 s85))
+[GOOD] (define-fun s109 () Int (ite s105 s81 s108))
+[GOOD] (define-fun s110 () Int (ite s103 s78 s109))
+[GOOD] (define-fun s111 () Int (ite s92 s72 s110))
+[GOOD] (define-fun s112 () Int (ite s99 s71 s111))
+[GOOD] (define-fun s113 () Int (ite s95 s64 s112))
+[GOOD] (define-fun s114 () Int (+ s91 s113))
+[GOOD] (define-fun s115 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s116 () String (getVar_1 s2))
+[GOOD] (define-fun s117 () Bool (= s61 s116))
+[GOOD] (define-fun s118 () Bool (and s115 s117))
+[GOOD] (define-fun s119 () Bool (= s65 s116))
+[GOOD] (define-fun s120 () Bool (= s67 s116))
+[GOOD] (define-fun s121 () Bool (or s119 s120))
+[GOOD] (define-fun s122 () Bool (and s115 s121))
+[GOOD] (define-fun s123 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s124 () Int (getVal_1 s2))
+[GOOD] (define-fun s125 () Bool (< s124 s75))
+[GOOD] (define-fun s126 () Bool (and s123 s125))
+[GOOD] (define-fun s127 () Bool (= s75 s124))
+[GOOD] (define-fun s128 () Bool (and s123 s127))
+[GOOD] (define-fun s129 () Bool (> s124 s75))
+[GOOD] (define-fun s130 () Bool (and s123 s129))
+[GOOD] (define-fun s131 () Int (ite s130 s84 s85))
+[GOOD] (define-fun s132 () Int (ite s128 s81 s131))
+[GOOD] (define-fun s133 () Int (ite s126 s78 s132))
+[GOOD] (define-fun s134 () Int (ite s115 s72 s133))
+[GOOD] (define-fun s135 () Int (ite s122 s71 s134))
+[GOOD] (define-fun s136 () Int (ite s118 s64 s135))
+[GOOD] (define-fun s137 () Int (+ s114 s136))
+[GOOD] (define-fun s138 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s139 () String (getVar_1 s3))
+[GOOD] (define-fun s140 () Bool (= s61 s139))
+[GOOD] (define-fun s141 () Bool (and s138 s140))
+[GOOD] (define-fun s142 () Bool (= s65 s139))
+[GOOD] (define-fun s143 () Bool (= s67 s139))
+[GOOD] (define-fun s144 () Bool (or s142 s143))
+[GOOD] (define-fun s145 () Bool (and s138 s144))
+[GOOD] (define-fun s146 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s147 () Int (getVal_1 s3))
+[GOOD] (define-fun s148 () Bool (< s147 s75))
+[GOOD] (define-fun s149 () Bool (and s146 s148))
+[GOOD] (define-fun s150 () Bool (= s75 s147))
+[GOOD] (define-fun s151 () Bool (and s146 s150))
+[GOOD] (define-fun s152 () Bool (> s147 s75))
+[GOOD] (define-fun s153 () Bool (and s146 s152))
+[GOOD] (define-fun s154 () Int (ite s153 s84 s85))
+[GOOD] (define-fun s155 () Int (ite s151 s81 s154))
+[GOOD] (define-fun s156 () Int (ite s149 s78 s155))
+[GOOD] (define-fun s157 () Int (ite s138 s72 s156))
+[GOOD] (define-fun s158 () Int (ite s145 s71 s157))
+[GOOD] (define-fun s159 () Int (ite s141 s64 s158))
+[GOOD] (define-fun s160 () Int (+ s137 s159))
+[GOOD] (define-fun s161 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s162 () String (getVar_1 s4))
+[GOOD] (define-fun s163 () Bool (= s61 s162))
+[GOOD] (define-fun s164 () Bool (and s161 s163))
+[GOOD] (define-fun s165 () Bool (= s65 s162))
+[GOOD] (define-fun s166 () Bool (= s67 s162))
+[GOOD] (define-fun s167 () Bool (or s165 s166))
+[GOOD] (define-fun s168 () Bool (and s161 s167))
+[GOOD] (define-fun s169 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s170 () Int (getVal_1 s4))
+[GOOD] (define-fun s171 () Bool (< s170 s75))
+[GOOD] (define-fun s172 () Bool (and s169 s171))
+[GOOD] (define-fun s173 () Bool (= s75 s170))
+[GOOD] (define-fun s174 () Bool (and s169 s173))
+[GOOD] (define-fun s175 () Bool (> s170 s75))
+[GOOD] (define-fun s176 () Bool (and s169 s175))
+[GOOD] (define-fun s177 () Int (ite s176 s84 s85))
+[GOOD] (define-fun s178 () Int (ite s174 s81 s177))
+[GOOD] (define-fun s179 () Int (ite s172 s78 s178))
+[GOOD] (define-fun s180 () Int (ite s161 s72 s179))
+[GOOD] (define-fun s181 () Int (ite s168 s71 s180))
+[GOOD] (define-fun s182 () Int (ite s164 s64 s181))
+[GOOD] (define-fun s183 () Int (+ s160 s182))
+[GOOD] (define-fun s184 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s185 () String (getVar_1 s5))
+[GOOD] (define-fun s186 () Bool (= s61 s185))
+[GOOD] (define-fun s187 () Bool (and s184 s186))
+[GOOD] (define-fun s188 () Bool (= s65 s185))
+[GOOD] (define-fun s189 () Bool (= s67 s185))
+[GOOD] (define-fun s190 () Bool (or s188 s189))
+[GOOD] (define-fun s191 () Bool (and s184 s190))
+[GOOD] (define-fun s192 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s193 () Int (getVal_1 s5))
+[GOOD] (define-fun s194 () Bool (< s193 s75))
+[GOOD] (define-fun s195 () Bool (and s192 s194))
+[GOOD] (define-fun s196 () Bool (= s75 s193))
+[GOOD] (define-fun s197 () Bool (and s192 s196))
+[GOOD] (define-fun s198 () Bool (> s193 s75))
+[GOOD] (define-fun s199 () Bool (and s192 s198))
+[GOOD] (define-fun s200 () Int (ite s199 s84 s85))
+[GOOD] (define-fun s201 () Int (ite s197 s81 s200))
+[GOOD] (define-fun s202 () Int (ite s195 s78 s201))
+[GOOD] (define-fun s203 () Int (ite s184 s72 s202))
+[GOOD] (define-fun s204 () Int (ite s191 s71 s203))
+[GOOD] (define-fun s205 () Int (ite s187 s64 s204))
+[GOOD] (define-fun s206 () Int (+ s183 s205))
+[GOOD] (define-fun s207 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s208 () String (getVar_1 s6))
+[GOOD] (define-fun s209 () Bool (= s61 s208))
+[GOOD] (define-fun s210 () Bool (and s207 s209))
+[GOOD] (define-fun s211 () Bool (= s65 s208))
+[GOOD] (define-fun s212 () Bool (= s67 s208))
+[GOOD] (define-fun s213 () Bool (or s211 s212))
+[GOOD] (define-fun s214 () Bool (and s207 s213))
+[GOOD] (define-fun s215 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s216 () Int (getVal_1 s6))
+[GOOD] (define-fun s217 () Bool (< s216 s75))
+[GOOD] (define-fun s218 () Bool (and s215 s217))
+[GOOD] (define-fun s219 () Bool (= s75 s216))
+[GOOD] (define-fun s220 () Bool (and s215 s219))
+[GOOD] (define-fun s221 () Bool (> s216 s75))
+[GOOD] (define-fun s222 () Bool (and s215 s221))
+[GOOD] (define-fun s223 () Int (ite s222 s84 s85))
+[GOOD] (define-fun s224 () Int (ite s220 s81 s223))
+[GOOD] (define-fun s225 () Int (ite s218 s78 s224))
+[GOOD] (define-fun s226 () Int (ite s207 s72 s225))
+[GOOD] (define-fun s227 () Int (ite s214 s71 s226))
+[GOOD] (define-fun s228 () Int (ite s210 s64 s227))
+[GOOD] (define-fun s229 () Int (+ s206 s228))
+[GOOD] (define-fun s230 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s231 () String (getVar_1 s7))
+[GOOD] (define-fun s232 () Bool (= s61 s231))
+[GOOD] (define-fun s233 () Bool (and s230 s232))
+[GOOD] (define-fun s234 () Bool (= s65 s231))
+[GOOD] (define-fun s235 () Bool (= s67 s231))
+[GOOD] (define-fun s236 () Bool (or s234 s235))
+[GOOD] (define-fun s237 () Bool (and s230 s236))
+[GOOD] (define-fun s238 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s239 () Int (getVal_1 s7))
+[GOOD] (define-fun s240 () Bool (< s239 s75))
+[GOOD] (define-fun s241 () Bool (and s238 s240))
+[GOOD] (define-fun s242 () Bool (= s75 s239))
+[GOOD] (define-fun s243 () Bool (and s238 s242))
+[GOOD] (define-fun s244 () Bool (> s239 s75))
+[GOOD] (define-fun s245 () Bool (and s238 s244))
+[GOOD] (define-fun s246 () Int (ite s245 s84 s85))
+[GOOD] (define-fun s247 () Int (ite s243 s81 s246))
+[GOOD] (define-fun s248 () Int (ite s241 s78 s247))
+[GOOD] (define-fun s249 () Int (ite s230 s72 s248))
+[GOOD] (define-fun s250 () Int (ite s237 s71 s249))
+[GOOD] (define-fun s251 () Int (ite s233 s64 s250))
+[GOOD] (define-fun s252 () Int (+ s229 s251))
+[GOOD] (define-fun s253 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s254 () String (getVar_1 s8))
+[GOOD] (define-fun s255 () Bool (= s61 s254))
+[GOOD] (define-fun s256 () Bool (and s253 s255))
+[GOOD] (define-fun s257 () Bool (= s65 s254))
+[GOOD] (define-fun s258 () Bool (= s67 s254))
+[GOOD] (define-fun s259 () Bool (or s257 s258))
+[GOOD] (define-fun s260 () Bool (and s253 s259))
+[GOOD] (define-fun s261 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s262 () Int (getVal_1 s8))
+[GOOD] (define-fun s263 () Bool (< s262 s75))
+[GOOD] (define-fun s264 () Bool (and s261 s263))
+[GOOD] (define-fun s265 () Bool (= s75 s262))
+[GOOD] (define-fun s266 () Bool (and s261 s265))
+[GOOD] (define-fun s267 () Bool (> s262 s75))
+[GOOD] (define-fun s268 () Bool (and s261 s267))
+[GOOD] (define-fun s269 () Int (ite s268 s84 s85))
+[GOOD] (define-fun s270 () Int (ite s266 s81 s269))
+[GOOD] (define-fun s271 () Int (ite s264 s78 s270))
+[GOOD] (define-fun s272 () Int (ite s253 s72 s271))
+[GOOD] (define-fun s273 () Int (ite s260 s71 s272))
+[GOOD] (define-fun s274 () Int (ite s256 s64 s273))
+[GOOD] (define-fun s275 () Int (+ s252 s274))
+[GOOD] (define-fun s276 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s277 () String (getVar_1 s9))
+[GOOD] (define-fun s278 () Bool (= s61 s277))
+[GOOD] (define-fun s279 () Bool (and s276 s278))
+[GOOD] (define-fun s280 () Bool (= s65 s277))
+[GOOD] (define-fun s281 () Bool (= s67 s277))
+[GOOD] (define-fun s282 () Bool (or s280 s281))
+[GOOD] (define-fun s283 () Bool (and s276 s282))
+[GOOD] (define-fun s284 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s285 () Int (getVal_1 s9))
+[GOOD] (define-fun s286 () Bool (< s285 s75))
+[GOOD] (define-fun s287 () Bool (and s284 s286))
+[GOOD] (define-fun s288 () Bool (= s75 s285))
+[GOOD] (define-fun s289 () Bool (and s284 s288))
+[GOOD] (define-fun s290 () Bool (> s285 s75))
+[GOOD] (define-fun s291 () Bool (and s284 s290))
+[GOOD] (define-fun s292 () Int (ite s291 s84 s85))
+[GOOD] (define-fun s293 () Int (ite s289 s81 s292))
+[GOOD] (define-fun s294 () Int (ite s287 s78 s293))
+[GOOD] (define-fun s295 () Int (ite s276 s72 s294))
+[GOOD] (define-fun s296 () Int (ite s283 s71 s295))
+[GOOD] (define-fun s297 () Int (ite s279 s64 s296))
+[GOOD] (define-fun s298 () Int (+ s275 s297))
+[GOOD] (define-fun s299 () Bool ((as is-Var Bool) s10))
+[GOOD] (define-fun s300 () String (getVar_1 s10))
+[GOOD] (define-fun s301 () Bool (= s61 s300))
+[GOOD] (define-fun s302 () Bool (and s299 s301))
+[GOOD] (define-fun s303 () Bool (= s65 s300))
+[GOOD] (define-fun s304 () Bool (= s67 s300))
+[GOOD] (define-fun s305 () Bool (or s303 s304))
+[GOOD] (define-fun s306 () Bool (and s299 s305))
+[GOOD] (define-fun s307 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s308 () Int (getVal_1 s10))
+[GOOD] (define-fun s309 () Bool (< s308 s75))
+[GOOD] (define-fun s310 () Bool (and s307 s309))
+[GOOD] (define-fun s311 () Bool (= s75 s308))
+[GOOD] (define-fun s312 () Bool (and s307 s311))
+[GOOD] (define-fun s313 () Bool (> s308 s75))
+[GOOD] (define-fun s314 () Bool (and s307 s313))
+[GOOD] (define-fun s315 () Int (ite s314 s84 s85))
+[GOOD] (define-fun s316 () Int (ite s312 s81 s315))
+[GOOD] (define-fun s317 () Int (ite s310 s78 s316))
+[GOOD] (define-fun s318 () Int (ite s299 s72 s317))
+[GOOD] (define-fun s319 () Int (ite s306 s71 s318))
+[GOOD] (define-fun s320 () Int (ite s302 s64 s319))
+[GOOD] (define-fun s321 () Int (+ s298 s320))
+[GOOD] (define-fun s322 () Bool ((as is-Var Bool) s11))
+[GOOD] (define-fun s323 () String (getVar_1 s11))
+[GOOD] (define-fun s324 () Bool (= s61 s323))
+[GOOD] (define-fun s325 () Bool (and s322 s324))
+[GOOD] (define-fun s326 () Bool (= s65 s323))
+[GOOD] (define-fun s327 () Bool (= s67 s323))
+[GOOD] (define-fun s328 () Bool (or s326 s327))
+[GOOD] (define-fun s329 () Bool (and s322 s328))
+[GOOD] (define-fun s330 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s331 () Int (getVal_1 s11))
+[GOOD] (define-fun s332 () Bool (< s331 s75))
+[GOOD] (define-fun s333 () Bool (and s330 s332))
+[GOOD] (define-fun s334 () Bool (= s75 s331))
+[GOOD] (define-fun s335 () Bool (and s330 s334))
+[GOOD] (define-fun s336 () Bool (> s331 s75))
+[GOOD] (define-fun s337 () Bool (and s330 s336))
+[GOOD] (define-fun s338 () Int (ite s337 s84 s85))
+[GOOD] (define-fun s339 () Int (ite s335 s81 s338))
+[GOOD] (define-fun s340 () Int (ite s333 s78 s339))
+[GOOD] (define-fun s341 () Int (ite s322 s72 s340))
+[GOOD] (define-fun s342 () Int (ite s329 s71 s341))
+[GOOD] (define-fun s343 () Int (ite s325 s64 s342))
+[GOOD] (define-fun s344 () Int (+ s321 s343))
+[GOOD] (define-fun s345 () Bool ((as is-Var Bool) s12))
+[GOOD] (define-fun s346 () String (getVar_1 s12))
+[GOOD] (define-fun s347 () Bool (= s61 s346))
+[GOOD] (define-fun s348 () Bool (and s345 s347))
+[GOOD] (define-fun s349 () Bool (= s65 s346))
+[GOOD] (define-fun s350 () Bool (= s67 s346))
+[GOOD] (define-fun s351 () Bool (or s349 s350))
+[GOOD] (define-fun s352 () Bool (and s345 s351))
+[GOOD] (define-fun s353 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s354 () Int (getVal_1 s12))
+[GOOD] (define-fun s355 () Bool (< s354 s75))
+[GOOD] (define-fun s356 () Bool (and s353 s355))
+[GOOD] (define-fun s357 () Bool (= s75 s354))
+[GOOD] (define-fun s358 () Bool (and s353 s357))
+[GOOD] (define-fun s359 () Bool (> s354 s75))
+[GOOD] (define-fun s360 () Bool (and s353 s359))
+[GOOD] (define-fun s361 () Int (ite s360 s84 s85))
+[GOOD] (define-fun s362 () Int (ite s358 s81 s361))
+[GOOD] (define-fun s363 () Int (ite s356 s78 s362))
+[GOOD] (define-fun s364 () Int (ite s345 s72 s363))
+[GOOD] (define-fun s365 () Int (ite s352 s71 s364))
+[GOOD] (define-fun s366 () Int (ite s348 s64 s365))
+[GOOD] (define-fun s367 () Int (+ s344 s366))
+[GOOD] (define-fun s368 () Bool ((as is-Var Bool) s13))
+[GOOD] (define-fun s369 () String (getVar_1 s13))
+[GOOD] (define-fun s370 () Bool (= s61 s369))
+[GOOD] (define-fun s371 () Bool (and s368 s370))
+[GOOD] (define-fun s372 () Bool (= s65 s369))
+[GOOD] (define-fun s373 () Bool (= s67 s369))
+[GOOD] (define-fun s374 () Bool (or s372 s373))
+[GOOD] (define-fun s375 () Bool (and s368 s374))
+[GOOD] (define-fun s376 () Bool ((as is-Val Bool) s13))
+[GOOD] (define-fun s377 () Int (getVal_1 s13))
+[GOOD] (define-fun s378 () Bool (< s377 s75))
+[GOOD] (define-fun s379 () Bool (and s376 s378))
+[GOOD] (define-fun s380 () Bool (= s75 s377))
+[GOOD] (define-fun s381 () Bool (and s376 s380))
+[GOOD] (define-fun s382 () Bool (> s377 s75))
+[GOOD] (define-fun s383 () Bool (and s376 s382))
+[GOOD] (define-fun s384 () Int (ite s383 s84 s85))
+[GOOD] (define-fun s385 () Int (ite s381 s81 s384))
+[GOOD] (define-fun s386 () Int (ite s379 s78 s385))
+[GOOD] (define-fun s387 () Int (ite s368 s72 s386))
+[GOOD] (define-fun s388 () Int (ite s375 s71 s387))
+[GOOD] (define-fun s389 () Int (ite s371 s64 s388))
+[GOOD] (define-fun s390 () Int (+ s367 s389))
+[GOOD] (define-fun s391 () Bool ((as is-Var Bool) s14))
+[GOOD] (define-fun s392 () String (getVar_1 s14))
+[GOOD] (define-fun s393 () Bool (= s61 s392))
+[GOOD] (define-fun s394 () Bool (and s391 s393))
+[GOOD] (define-fun s395 () Bool (= s65 s392))
+[GOOD] (define-fun s396 () Bool (= s67 s392))
+[GOOD] (define-fun s397 () Bool (or s395 s396))
+[GOOD] (define-fun s398 () Bool (and s391 s397))
+[GOOD] (define-fun s399 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s400 () Int (getVal_1 s14))
+[GOOD] (define-fun s401 () Bool (< s400 s75))
+[GOOD] (define-fun s402 () Bool (and s399 s401))
+[GOOD] (define-fun s403 () Bool (= s75 s400))
+[GOOD] (define-fun s404 () Bool (and s399 s403))
+[GOOD] (define-fun s405 () Bool (> s400 s75))
+[GOOD] (define-fun s406 () Bool (and s399 s405))
+[GOOD] (define-fun s407 () Int (ite s406 s84 s85))
+[GOOD] (define-fun s408 () Int (ite s404 s81 s407))
+[GOOD] (define-fun s409 () Int (ite s402 s78 s408))
+[GOOD] (define-fun s410 () Int (ite s391 s72 s409))
+[GOOD] (define-fun s411 () Int (ite s398 s71 s410))
+[GOOD] (define-fun s412 () Int (ite s394 s64 s411))
+[GOOD] (define-fun s413 () Int (+ s390 s412))
+[GOOD] (define-fun s415 () Bool (distinct s413 s414))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s58)
+[GOOD] (assert s415)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr10c.gold b/SBVTestSuite/GoldFiles/adt_expr10c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr10c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr11.gold b/SBVTestSuite/GoldFiles/adt_expr11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr11.gold
@@ -0,0 +1,102 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Expr ((as Val Expr) 10))
+[GOOD] (define-fun s8 () String "a")
+[GOOD] (define-fun s11 () Int 0)
+[GOOD] (define-fun s12 () String "b")
+[GOOD] (define-fun s14 () String "c")
+[GOOD] (define-fun s18 () Int 1)
+[GOOD] (define-fun s19 () Int 2)
+[GOOD] (define-fun s22 () Int 10)
+[GOOD] (define-fun s25 () Int 3)
+[GOOD] (define-fun s28 () Int 4)
+[GOOD] (define-fun s31 () Int 5)
+[GOOD] (define-fun s32 () Int 6)
+[GOOD] (define-fun s62 () Int 8)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () Bool (and s3 s4))
+[GOOD] (define-fun s6 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s7 () String (getVar_1 s0))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s13 () Bool (= s7 s12))
+[GOOD] (define-fun s15 () Bool (= s7 s14))
+[GOOD] (define-fun s16 () Bool (or s13 s15))
+[GOOD] (define-fun s17 () Bool (and s6 s16))
+[GOOD] (define-fun s20 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s21 () Int (getVal_1 s0))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s26 () Bool (= s21 s22))
+[GOOD] (define-fun s27 () Bool (and s20 s26))
+[GOOD] (define-fun s29 () Bool (> s21 s22))
+[GOOD] (define-fun s30 () Bool (and s20 s29))
+[GOOD] (define-fun s33 () Int (ite s30 s31 s32))
+[GOOD] (define-fun s34 () Int (ite s27 s28 s33))
+[GOOD] (define-fun s35 () Int (ite s24 s25 s34))
+[GOOD] (define-fun s36 () Int (ite s6 s19 s35))
+[GOOD] (define-fun s37 () Int (ite s17 s18 s36))
+[GOOD] (define-fun s38 () Int (ite s10 s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s40 () String (getVar_1 s1))
+[GOOD] (define-fun s41 () Bool (= s8 s40))
+[GOOD] (define-fun s42 () Bool (and s39 s41))
+[GOOD] (define-fun s43 () Bool (= s12 s40))
+[GOOD] (define-fun s44 () Bool (= s14 s40))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () Bool (and s39 s45))
+[GOOD] (define-fun s47 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s48 () Int (getVal_1 s1))
+[GOOD] (define-fun s49 () Bool (< s48 s22))
+[GOOD] (define-fun s50 () Bool (and s47 s49))
+[GOOD] (define-fun s51 () Bool (= s22 s48))
+[GOOD] (define-fun s52 () Bool (and s47 s51))
+[GOOD] (define-fun s53 () Bool (> s48 s22))
+[GOOD] (define-fun s54 () Bool (and s47 s53))
+[GOOD] (define-fun s55 () Int (ite s54 s31 s32))
+[GOOD] (define-fun s56 () Int (ite s52 s28 s55))
+[GOOD] (define-fun s57 () Int (ite s50 s25 s56))
+[GOOD] (define-fun s58 () Int (ite s39 s19 s57))
+[GOOD] (define-fun s59 () Int (ite s46 s18 s58))
+[GOOD] (define-fun s60 () Int (ite s42 s11 s59))
+[GOOD] (define-fun s61 () Int (+ s38 s60))
+[GOOD] (define-fun s63 () Bool (distinct s61 s62))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s63)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr11c.gold b/SBVTestSuite/GoldFiles/adt_expr11c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr11c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr12.gold b/SBVTestSuite/GoldFiles/adt_expr12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr12.gold
@@ -0,0 +1,319 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s10 () Expr ((as Val Expr) 11))
+[GOOD] (define-fun s12 () Expr ((as Val Expr) 12))
+[GOOD] (define-fun s14 () Expr ((as Val Expr) 13))
+[GOOD] (define-fun s16 () Expr ((as Val Expr) 14))
+[GOOD] (define-fun s18 () Expr ((as Val Expr) 15))
+[GOOD] (define-fun s20 () Expr ((as Val Expr) 16))
+[GOOD] (define-fun s22 () Expr ((as Val Expr) 17))
+[GOOD] (define-fun s24 () Expr ((as Val Expr) 18))
+[GOOD] (define-fun s26 () Expr ((as Val Expr) 19))
+[GOOD] (define-fun s28 () Expr ((as Val Expr) 20))
+[GOOD] (define-fun s41 () String "a")
+[GOOD] (define-fun s44 () Int 0)
+[GOOD] (define-fun s45 () String "b")
+[GOOD] (define-fun s47 () String "c")
+[GOOD] (define-fun s51 () Int 1)
+[GOOD] (define-fun s52 () Int 2)
+[GOOD] (define-fun s55 () Int 10)
+[GOOD] (define-fun s58 () Int 3)
+[GOOD] (define-fun s61 () Int 4)
+[GOOD] (define-fun s64 () Int 5)
+[GOOD] (define-fun s65 () Int 6)
+[GOOD] (define-fun s279 () Int 50)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] (declare-fun s1 () Expr)
+[GOOD] (declare-fun s2 () Expr)
+[GOOD] (declare-fun s3 () Expr)
+[GOOD] (declare-fun s4 () Expr)
+[GOOD] (declare-fun s5 () Expr)
+[GOOD] (declare-fun s6 () Expr)
+[GOOD] (declare-fun s7 () Expr)
+[GOOD] (declare-fun s8 () Expr)
+[GOOD] (declare-fun s9 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s13 () Bool (= s1 s12))
+[GOOD] (define-fun s15 () Bool (= s2 s14))
+[GOOD] (define-fun s17 () Bool (= s3 s16))
+[GOOD] (define-fun s19 () Bool (= s4 s18))
+[GOOD] (define-fun s21 () Bool (= s5 s20))
+[GOOD] (define-fun s23 () Bool (= s6 s22))
+[GOOD] (define-fun s25 () Bool (= s7 s24))
+[GOOD] (define-fun s27 () Bool (= s8 s26))
+[GOOD] (define-fun s29 () Bool (= s9 s28))
+[GOOD] (define-fun s30 () Bool (and s27 s29))
+[GOOD] (define-fun s31 () Bool (and s25 s30))
+[GOOD] (define-fun s32 () Bool (and s23 s31))
+[GOOD] (define-fun s33 () Bool (and s21 s32))
+[GOOD] (define-fun s34 () Bool (and s19 s33))
+[GOOD] (define-fun s35 () Bool (and s17 s34))
+[GOOD] (define-fun s36 () Bool (and s15 s35))
+[GOOD] (define-fun s37 () Bool (and s13 s36))
+[GOOD] (define-fun s38 () Bool (and s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s40 () String (getVar_1 s0))
+[GOOD] (define-fun s42 () Bool (= s40 s41))
+[GOOD] (define-fun s43 () Bool (and s39 s42))
+[GOOD] (define-fun s46 () Bool (= s40 s45))
+[GOOD] (define-fun s48 () Bool (= s40 s47))
+[GOOD] (define-fun s49 () Bool (or s46 s48))
+[GOOD] (define-fun s50 () Bool (and s39 s49))
+[GOOD] (define-fun s53 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s54 () Int (getVal_1 s0))
+[GOOD] (define-fun s56 () Bool (< s54 s55))
+[GOOD] (define-fun s57 () Bool (and s53 s56))
+[GOOD] (define-fun s59 () Bool (= s54 s55))
+[GOOD] (define-fun s60 () Bool (and s53 s59))
+[GOOD] (define-fun s62 () Bool (> s54 s55))
+[GOOD] (define-fun s63 () Bool (and s53 s62))
+[GOOD] (define-fun s66 () Int (ite s63 s64 s65))
+[GOOD] (define-fun s67 () Int (ite s60 s61 s66))
+[GOOD] (define-fun s68 () Int (ite s57 s58 s67))
+[GOOD] (define-fun s69 () Int (ite s39 s52 s68))
+[GOOD] (define-fun s70 () Int (ite s50 s51 s69))
+[GOOD] (define-fun s71 () Int (ite s43 s44 s70))
+[GOOD] (define-fun s72 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s73 () String (getVar_1 s1))
+[GOOD] (define-fun s74 () Bool (= s41 s73))
+[GOOD] (define-fun s75 () Bool (and s72 s74))
+[GOOD] (define-fun s76 () Bool (= s45 s73))
+[GOOD] (define-fun s77 () Bool (= s47 s73))
+[GOOD] (define-fun s78 () Bool (or s76 s77))
+[GOOD] (define-fun s79 () Bool (and s72 s78))
+[GOOD] (define-fun s80 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s81 () Int (getVal_1 s1))
+[GOOD] (define-fun s82 () Bool (< s81 s55))
+[GOOD] (define-fun s83 () Bool (and s80 s82))
+[GOOD] (define-fun s84 () Bool (= s55 s81))
+[GOOD] (define-fun s85 () Bool (and s80 s84))
+[GOOD] (define-fun s86 () Bool (> s81 s55))
+[GOOD] (define-fun s87 () Bool (and s80 s86))
+[GOOD] (define-fun s88 () Int (ite s87 s64 s65))
+[GOOD] (define-fun s89 () Int (ite s85 s61 s88))
+[GOOD] (define-fun s90 () Int (ite s83 s58 s89))
+[GOOD] (define-fun s91 () Int (ite s72 s52 s90))
+[GOOD] (define-fun s92 () Int (ite s79 s51 s91))
+[GOOD] (define-fun s93 () Int (ite s75 s44 s92))
+[GOOD] (define-fun s94 () Int (+ s71 s93))
+[GOOD] (define-fun s95 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s96 () String (getVar_1 s2))
+[GOOD] (define-fun s97 () Bool (= s41 s96))
+[GOOD] (define-fun s98 () Bool (and s95 s97))
+[GOOD] (define-fun s99 () Bool (= s45 s96))
+[GOOD] (define-fun s100 () Bool (= s47 s96))
+[GOOD] (define-fun s101 () Bool (or s99 s100))
+[GOOD] (define-fun s102 () Bool (and s95 s101))
+[GOOD] (define-fun s103 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s104 () Int (getVal_1 s2))
+[GOOD] (define-fun s105 () Bool (< s104 s55))
+[GOOD] (define-fun s106 () Bool (and s103 s105))
+[GOOD] (define-fun s107 () Bool (= s55 s104))
+[GOOD] (define-fun s108 () Bool (and s103 s107))
+[GOOD] (define-fun s109 () Bool (> s104 s55))
+[GOOD] (define-fun s110 () Bool (and s103 s109))
+[GOOD] (define-fun s111 () Int (ite s110 s64 s65))
+[GOOD] (define-fun s112 () Int (ite s108 s61 s111))
+[GOOD] (define-fun s113 () Int (ite s106 s58 s112))
+[GOOD] (define-fun s114 () Int (ite s95 s52 s113))
+[GOOD] (define-fun s115 () Int (ite s102 s51 s114))
+[GOOD] (define-fun s116 () Int (ite s98 s44 s115))
+[GOOD] (define-fun s117 () Int (+ s94 s116))
+[GOOD] (define-fun s118 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s119 () String (getVar_1 s3))
+[GOOD] (define-fun s120 () Bool (= s41 s119))
+[GOOD] (define-fun s121 () Bool (and s118 s120))
+[GOOD] (define-fun s122 () Bool (= s45 s119))
+[GOOD] (define-fun s123 () Bool (= s47 s119))
+[GOOD] (define-fun s124 () Bool (or s122 s123))
+[GOOD] (define-fun s125 () Bool (and s118 s124))
+[GOOD] (define-fun s126 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s127 () Int (getVal_1 s3))
+[GOOD] (define-fun s128 () Bool (< s127 s55))
+[GOOD] (define-fun s129 () Bool (and s126 s128))
+[GOOD] (define-fun s130 () Bool (= s55 s127))
+[GOOD] (define-fun s131 () Bool (and s126 s130))
+[GOOD] (define-fun s132 () Bool (> s127 s55))
+[GOOD] (define-fun s133 () Bool (and s126 s132))
+[GOOD] (define-fun s134 () Int (ite s133 s64 s65))
+[GOOD] (define-fun s135 () Int (ite s131 s61 s134))
+[GOOD] (define-fun s136 () Int (ite s129 s58 s135))
+[GOOD] (define-fun s137 () Int (ite s118 s52 s136))
+[GOOD] (define-fun s138 () Int (ite s125 s51 s137))
+[GOOD] (define-fun s139 () Int (ite s121 s44 s138))
+[GOOD] (define-fun s140 () Int (+ s117 s139))
+[GOOD] (define-fun s141 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s142 () String (getVar_1 s4))
+[GOOD] (define-fun s143 () Bool (= s41 s142))
+[GOOD] (define-fun s144 () Bool (and s141 s143))
+[GOOD] (define-fun s145 () Bool (= s45 s142))
+[GOOD] (define-fun s146 () Bool (= s47 s142))
+[GOOD] (define-fun s147 () Bool (or s145 s146))
+[GOOD] (define-fun s148 () Bool (and s141 s147))
+[GOOD] (define-fun s149 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s150 () Int (getVal_1 s4))
+[GOOD] (define-fun s151 () Bool (< s150 s55))
+[GOOD] (define-fun s152 () Bool (and s149 s151))
+[GOOD] (define-fun s153 () Bool (= s55 s150))
+[GOOD] (define-fun s154 () Bool (and s149 s153))
+[GOOD] (define-fun s155 () Bool (> s150 s55))
+[GOOD] (define-fun s156 () Bool (and s149 s155))
+[GOOD] (define-fun s157 () Int (ite s156 s64 s65))
+[GOOD] (define-fun s158 () Int (ite s154 s61 s157))
+[GOOD] (define-fun s159 () Int (ite s152 s58 s158))
+[GOOD] (define-fun s160 () Int (ite s141 s52 s159))
+[GOOD] (define-fun s161 () Int (ite s148 s51 s160))
+[GOOD] (define-fun s162 () Int (ite s144 s44 s161))
+[GOOD] (define-fun s163 () Int (+ s140 s162))
+[GOOD] (define-fun s164 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s165 () String (getVar_1 s5))
+[GOOD] (define-fun s166 () Bool (= s41 s165))
+[GOOD] (define-fun s167 () Bool (and s164 s166))
+[GOOD] (define-fun s168 () Bool (= s45 s165))
+[GOOD] (define-fun s169 () Bool (= s47 s165))
+[GOOD] (define-fun s170 () Bool (or s168 s169))
+[GOOD] (define-fun s171 () Bool (and s164 s170))
+[GOOD] (define-fun s172 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s173 () Int (getVal_1 s5))
+[GOOD] (define-fun s174 () Bool (< s173 s55))
+[GOOD] (define-fun s175 () Bool (and s172 s174))
+[GOOD] (define-fun s176 () Bool (= s55 s173))
+[GOOD] (define-fun s177 () Bool (and s172 s176))
+[GOOD] (define-fun s178 () Bool (> s173 s55))
+[GOOD] (define-fun s179 () Bool (and s172 s178))
+[GOOD] (define-fun s180 () Int (ite s179 s64 s65))
+[GOOD] (define-fun s181 () Int (ite s177 s61 s180))
+[GOOD] (define-fun s182 () Int (ite s175 s58 s181))
+[GOOD] (define-fun s183 () Int (ite s164 s52 s182))
+[GOOD] (define-fun s184 () Int (ite s171 s51 s183))
+[GOOD] (define-fun s185 () Int (ite s167 s44 s184))
+[GOOD] (define-fun s186 () Int (+ s163 s185))
+[GOOD] (define-fun s187 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s188 () String (getVar_1 s6))
+[GOOD] (define-fun s189 () Bool (= s41 s188))
+[GOOD] (define-fun s190 () Bool (and s187 s189))
+[GOOD] (define-fun s191 () Bool (= s45 s188))
+[GOOD] (define-fun s192 () Bool (= s47 s188))
+[GOOD] (define-fun s193 () Bool (or s191 s192))
+[GOOD] (define-fun s194 () Bool (and s187 s193))
+[GOOD] (define-fun s195 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s196 () Int (getVal_1 s6))
+[GOOD] (define-fun s197 () Bool (< s196 s55))
+[GOOD] (define-fun s198 () Bool (and s195 s197))
+[GOOD] (define-fun s199 () Bool (= s55 s196))
+[GOOD] (define-fun s200 () Bool (and s195 s199))
+[GOOD] (define-fun s201 () Bool (> s196 s55))
+[GOOD] (define-fun s202 () Bool (and s195 s201))
+[GOOD] (define-fun s203 () Int (ite s202 s64 s65))
+[GOOD] (define-fun s204 () Int (ite s200 s61 s203))
+[GOOD] (define-fun s205 () Int (ite s198 s58 s204))
+[GOOD] (define-fun s206 () Int (ite s187 s52 s205))
+[GOOD] (define-fun s207 () Int (ite s194 s51 s206))
+[GOOD] (define-fun s208 () Int (ite s190 s44 s207))
+[GOOD] (define-fun s209 () Int (+ s186 s208))
+[GOOD] (define-fun s210 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s211 () String (getVar_1 s7))
+[GOOD] (define-fun s212 () Bool (= s41 s211))
+[GOOD] (define-fun s213 () Bool (and s210 s212))
+[GOOD] (define-fun s214 () Bool (= s45 s211))
+[GOOD] (define-fun s215 () Bool (= s47 s211))
+[GOOD] (define-fun s216 () Bool (or s214 s215))
+[GOOD] (define-fun s217 () Bool (and s210 s216))
+[GOOD] (define-fun s218 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s219 () Int (getVal_1 s7))
+[GOOD] (define-fun s220 () Bool (< s219 s55))
+[GOOD] (define-fun s221 () Bool (and s218 s220))
+[GOOD] (define-fun s222 () Bool (= s55 s219))
+[GOOD] (define-fun s223 () Bool (and s218 s222))
+[GOOD] (define-fun s224 () Bool (> s219 s55))
+[GOOD] (define-fun s225 () Bool (and s218 s224))
+[GOOD] (define-fun s226 () Int (ite s225 s64 s65))
+[GOOD] (define-fun s227 () Int (ite s223 s61 s226))
+[GOOD] (define-fun s228 () Int (ite s221 s58 s227))
+[GOOD] (define-fun s229 () Int (ite s210 s52 s228))
+[GOOD] (define-fun s230 () Int (ite s217 s51 s229))
+[GOOD] (define-fun s231 () Int (ite s213 s44 s230))
+[GOOD] (define-fun s232 () Int (+ s209 s231))
+[GOOD] (define-fun s233 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s234 () String (getVar_1 s8))
+[GOOD] (define-fun s235 () Bool (= s41 s234))
+[GOOD] (define-fun s236 () Bool (and s233 s235))
+[GOOD] (define-fun s237 () Bool (= s45 s234))
+[GOOD] (define-fun s238 () Bool (= s47 s234))
+[GOOD] (define-fun s239 () Bool (or s237 s238))
+[GOOD] (define-fun s240 () Bool (and s233 s239))
+[GOOD] (define-fun s241 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s242 () Int (getVal_1 s8))
+[GOOD] (define-fun s243 () Bool (< s242 s55))
+[GOOD] (define-fun s244 () Bool (and s241 s243))
+[GOOD] (define-fun s245 () Bool (= s55 s242))
+[GOOD] (define-fun s246 () Bool (and s241 s245))
+[GOOD] (define-fun s247 () Bool (> s242 s55))
+[GOOD] (define-fun s248 () Bool (and s241 s247))
+[GOOD] (define-fun s249 () Int (ite s248 s64 s65))
+[GOOD] (define-fun s250 () Int (ite s246 s61 s249))
+[GOOD] (define-fun s251 () Int (ite s244 s58 s250))
+[GOOD] (define-fun s252 () Int (ite s233 s52 s251))
+[GOOD] (define-fun s253 () Int (ite s240 s51 s252))
+[GOOD] (define-fun s254 () Int (ite s236 s44 s253))
+[GOOD] (define-fun s255 () Int (+ s232 s254))
+[GOOD] (define-fun s256 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s257 () String (getVar_1 s9))
+[GOOD] (define-fun s258 () Bool (= s41 s257))
+[GOOD] (define-fun s259 () Bool (and s256 s258))
+[GOOD] (define-fun s260 () Bool (= s45 s257))
+[GOOD] (define-fun s261 () Bool (= s47 s257))
+[GOOD] (define-fun s262 () Bool (or s260 s261))
+[GOOD] (define-fun s263 () Bool (and s256 s262))
+[GOOD] (define-fun s264 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s265 () Int (getVal_1 s9))
+[GOOD] (define-fun s266 () Bool (< s265 s55))
+[GOOD] (define-fun s267 () Bool (and s264 s266))
+[GOOD] (define-fun s268 () Bool (= s55 s265))
+[GOOD] (define-fun s269 () Bool (and s264 s268))
+[GOOD] (define-fun s270 () Bool (> s265 s55))
+[GOOD] (define-fun s271 () Bool (and s264 s270))
+[GOOD] (define-fun s272 () Int (ite s271 s64 s65))
+[GOOD] (define-fun s273 () Int (ite s269 s61 s272))
+[GOOD] (define-fun s274 () Int (ite s267 s58 s273))
+[GOOD] (define-fun s275 () Int (ite s256 s52 s274))
+[GOOD] (define-fun s276 () Int (ite s263 s51 s275))
+[GOOD] (define-fun s277 () Int (ite s259 s44 s276))
+[GOOD] (define-fun s278 () Int (+ s255 s277))
+[GOOD] (define-fun s280 () Bool (distinct s278 s279))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s38)
+[GOOD] (assert s280)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr12c.gold b/SBVTestSuite/GoldFiles/adt_expr12c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr12c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr13.gold b/SBVTestSuite/GoldFiles/adt_expr13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr13.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 3))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s22 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr13c.gold b/SBVTestSuite/GoldFiles/adt_expr13c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr13c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr14.gold b/SBVTestSuite/GoldFiles/adt_expr14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr14.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr14c.gold b/SBVTestSuite/GoldFiles/adt_expr14c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr14c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr15.gold b/SBVTestSuite/GoldFiles/adt_expr15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr15.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr15c.gold b/SBVTestSuite/GoldFiles/adt_expr15c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr15c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr16.gold b/SBVTestSuite/GoldFiles/adt_expr16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr16.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr16c.gold b/SBVTestSuite/GoldFiles/adt_expr16c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr16c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr17.gold b/SBVTestSuite/GoldFiles/adt_expr17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr17.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Let Expr) "a" ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr17c.gold b/SBVTestSuite/GoldFiles/adt_expr17c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr17c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr18.gold b/SBVTestSuite/GoldFiles/adt_expr18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr18.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "a" ((as Add Expr) ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Let Expr) "a" ((as Let Expr) "a" ((as Mul Expr) ((as Val Expr) 3) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))) ((as Add Expr) ((as Var Expr) "a") ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))) ((as Mul Expr) ((as Var Expr) "a") ((as Var Expr) "a"))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_expr18c.gold b/SBVTestSuite/GoldFiles/adt_expr18c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_expr18c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen00.gold b/SBVTestSuite/GoldFiles/adt_gen00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen00.gold
@@ -0,0 +1,277 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer), valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): barified = "|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|"
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): Uninterpreted ops in DAG: [("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)|",2)]
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): recursive calls found = 6
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): trying sbv.dt.size.Expr arg2
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] valid @(SBV [[Char]] -> SBV Expr -> SBV Bool): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq String) (as seq.empty (Seq String)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 12)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| :: [SString] -> Expr -> SBool [Recursive]
+[GOOD] (define-fun-rec |valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| ((l1_s0 (Seq String)) (l1_s1 Expr)) Bool
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s4 (getVar_1 l1_s1)))
+                                 (let ((l1_s5 (str.in_re l1_s4 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s6 (seq.unit l1_s4)))
+                                 (let ((l1_s7 (seq.contains l1_s0 l1_s6)))
+                                 (let ((l1_s8 (and l1_s5 l1_s7)))
+                                 (let ((l1_s9 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s10 (getAdd_1 l1_s1)))
+                                 (let ((l1_s11 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (getAdd_2 l1_s1)))
+                                 (let ((l1_s13 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s12)))
+                                 (let ((l1_s14 (and l1_s11 l1_s13)))
+                                 (let ((l1_s15 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s16 (getMul_1 l1_s1)))
+                                 (let ((l1_s17 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (getMul_2 l1_s1)))
+                                 (let ((l1_s19 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s18)))
+                                 (let ((l1_s20 (and l1_s17 l1_s19)))
+                                 (let ((l1_s21 (getLet_1 l1_s1)))
+                                 (let ((l1_s22 (str.in_re l1_s21 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s23 (getLet_2 l1_s1)))
+                                 (let ((l1_s24 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s0 l1_s23)))
+                                 (let ((l1_s25 (seq.unit l1_s21)))
+                                 (let ((l1_s26 (seq.++ l1_s25 l1_s0)))
+                                 (let ((l1_s27 (getLet_3 l1_s1)))
+                                 (let ((l1_s28 (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| l1_s26 l1_s27)))
+                                 (let ((l1_s29 (and l1_s24 l1_s28)))
+                                 (let ((l1_s30 (and l1_s22 l1_s29)))
+                                 (let ((l1_s31 (ite l1_s15 l1_s20 l1_s30)))
+                                 (let ((l1_s32 (ite l1_s9 l1_s14 l1_s31)))
+                                 (let ((l1_s33 (ite l1_s3 l1_s8 l1_s32)))
+                                 (let ((l1_s34 (or l1_s2 l1_s33)))
+                                 l1_s34))))))))))))))))))))))))))))))))))
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (|valid @(SBV [[Char]] -> SBV Expr -> SBV Bool)| s1 s0))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s8 () Expr (getLet_3 s0))
+[GOOD] (define-fun s9 () Bool ((as is-Let Bool) s8))
+[GOOD] (define-fun s10 () Expr (getLet_3 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Add Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "l"
+            (Val 6)
+            (Let "a" (Val 0) (Add (Mul (Val 3) (Let "p" (Val 4) (Var "p"))) (Var "a"))))))
+
+Got: (let l = 6 in (let a = 0 in ((3 * (let p = 4 in p)) + a)))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen01.gold b/SBVTestSuite/GoldFiles/adt_gen01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen01.gold
@@ -0,0 +1,83 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int (- 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen02.gold b/SBVTestSuite/GoldFiles/adt_gen02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen02.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s6 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "a")))
+
+Got: a
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen03.gold b/SBVTestSuite/GoldFiles/adt_gen03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen03.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s13 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "b")))
+
+Got: b
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen04.gold b/SBVTestSuite/GoldFiles/adt_gen04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen04.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s14 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "")))
+
+Got: 
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen05.gold b/SBVTestSuite/GoldFiles/adt_gen05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen05.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s20 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 0)))
+
+Got: 0
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen06.gold b/SBVTestSuite/GoldFiles/adt_gen06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen06.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s23 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 10)))
+
+Got: 10
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen07.gold b/SBVTestSuite/GoldFiles/adt_gen07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen07.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s26 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 11)))
+
+Got: 11
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen08.gold b/SBVTestSuite/GoldFiles/adt_gen08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen08.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s28 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Add (Var "!0!") (Var "!0!"))))
+
+Got: (!0! + !0!)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen09.gold b/SBVTestSuite/GoldFiles/adt_gen09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen09.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s30 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Var "!0!") (Var "!0!"))))
+
+Got: (!0! * !0!)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen10.gold b/SBVTestSuite/GoldFiles/adt_gen10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen10.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s32 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "!0!" (Var "!0!") (Var "!0!"))))
+
+Got: (let !0! = !0! in !0!)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen11.gold b/SBVTestSuite/GoldFiles/adt_gen11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen11.gold
@@ -0,0 +1,83 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int 9)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_gen12.gold b/SBVTestSuite/GoldFiles/adt_gen12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_gen12.gold
@@ -0,0 +1,82 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s33 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit00.gold b/SBVTestSuite/GoldFiles/adt_lit00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit00.gold
@@ -0,0 +1,240 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s27 () Bool (distinct s8 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s27)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit00c.gold b/SBVTestSuite/GoldFiles/adt_lit00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit00c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit01.gold b/SBVTestSuite/GoldFiles/adt_lit01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit01.gold
@@ -0,0 +1,240 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 1))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s27 () Bool (distinct s12 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s27)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit01c.gold b/SBVTestSuite/GoldFiles/adt_lit01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit01c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit02.gold b/SBVTestSuite/GoldFiles/adt_lit02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit02.gold
@@ -0,0 +1,241 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 2))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s27 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s28 () Bool (distinct s26 s27))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s28)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit02c.gold b/SBVTestSuite/GoldFiles/adt_lit02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit02c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit03.gold b/SBVTestSuite/GoldFiles/adt_lit03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit03.gold
@@ -0,0 +1,241 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Val Expr) 5)))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s27 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s28 () Bool (distinct s26 s27))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s28)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit03c.gold b/SBVTestSuite/GoldFiles/adt_lit03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit03c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit04.gold b/SBVTestSuite/GoldFiles/adt_lit04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit04.gold
@@ -0,0 +1,241 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 1) ((as Val Expr) 5)))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s27 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s28 () Bool (distinct s26 s27))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s28)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit04c.gold b/SBVTestSuite/GoldFiles/adt_lit04c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit04c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit05.gold b/SBVTestSuite/GoldFiles/adt_lit05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit05.gold
@@ -0,0 +1,240 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "x"))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s8 () Int 100)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s12 () Int 200)
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s4 () Int (getVal_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s11 () Bool (and s3 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s14 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Int (getVal_1 s14))
+[GOOD] (define-fun s17 () Bool (= s5 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] (define-fun s19 () Bool (and s13 s18))
+[GOOD] (define-fun s21 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s22 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s21))
+[GOOD] (define-fun s23 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s20 s0))
+[GOOD] (define-fun s24 () Int (ite s19 s22 s23))
+[GOOD] (define-fun s25 () Int (ite s11 s12 s24))
+[GOOD] (define-fun s26 () Int (ite s7 s8 s25))
+[GOOD] (define-fun s27 () Bool (distinct s5 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s27)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_lit05c.gold b/SBVTestSuite/GoldFiles/adt_lit05c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_lit05c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr00.gold b/SBVTestSuite/GoldFiles/adt_mr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr00.gold
@@ -0,0 +1,69 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (var val) (
+           (Con (getCon_1 val))
+           (Var (getVar_1 var))
+           (Add (getAdd_1 (Expr var val)) (getAdd_2 (Expr var val)))
+           (Mul (getMul_1 (Expr var val)) (getMul_2 (Expr var val)))
+       )))
+[GOOD] ; User defined ADT: Stmt
+[GOOD] (declare-datatype Stmt (par (var val) (
+           (Assign (getAssign_1 var) (getAssign_2 (Expr var val)))
+           (Seq (getSeq_1 (Stmt var val)) (getSeq_2 (Stmt var val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Stmt String Int)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Seq Bool) s0))
+[GOOD] (define-fun s2 () (Stmt String Int) (getSeq_2 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Seq Bool) s2))
+[GOOD] (define-fun s4 () (Stmt String Int) (getSeq_2 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Seq Bool) s4))
+[GOOD] (define-fun s6 () (Stmt String Int) (getSeq_2 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Assign Bool) s6))
+[GOOD] (define-fun s8 () (Expr String Int) (getAssign_2 s6))
+[GOOD] (define-fun s9 () Bool ((as is-Add Bool) s8))
+[GOOD] (define-fun s10 () (Expr String Int) (getAdd_1 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Var Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Seq (Assign "!3!" (Var "!6!"))
+            (Seq (Assign "!5!" (Var "!8!"))
+                 (Seq (Assign "!4!" (Var "!7!"))
+                      (Assign "!0!" (Add (Var "!1!") (Var "!2!"))))))))
+
+Got:
+!3! := !6!;
+!5! := !8!;
+!4! := !7!;
+!0! := (!1! + !2!)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr01.gold b/SBVTestSuite/GoldFiles/adt_mr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr01.gold
@@ -0,0 +1,73 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (var val) (
+           (Con (getCon_1 val))
+           (Var (getVar_1 var))
+           (Add (getAdd_1 (Expr var val)) (getAdd_2 (Expr var val)))
+           (Mul (getMul_1 (Expr var val)) (getMul_2 (Expr var val)))
+       )))
+[GOOD] ; User defined ADT: Stmt
+[GOOD] (declare-datatype Stmt (par (var val) (
+           (Assign (getAssign_1 var) (getAssign_2 (Expr var val)))
+           (Seq (getSeq_1 (Stmt var val)) (getSeq_2 (Stmt var val)))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Stmt String (Maybe (Either Int Bool)))) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Assign Bool) s0))
+[GOOD] (define-fun s2 () (Expr String (Maybe (Either Int Bool))) (getAssign_2 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s2))
+[GOOD] (define-fun s4 () (Expr String (Maybe (Either Int Bool))) (getAdd_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Con Bool) s4))
+[GOOD] (define-fun s6 () (Expr String (Maybe (Either Int Bool))) (getAdd_2 s2))
+[GOOD] (define-fun s7 () Bool ((as is-Con Bool) s6))
+[GOOD] (define-fun s8 () (Maybe (Either Int Bool)) (getCon_1 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Nothing Bool) s8))
+[GOOD] (define-fun s10 () (Maybe (Either Int Bool)) (getCon_1 s6))
+[GOOD] (define-fun s11 () Bool ((as is-Just Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Assign "!0!" (Add (Con Nothing) (Con (Just (Left 2)))))))
+
+Got:
+!0! := (Nothing + Just (Left 2))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr02.gold b/SBVTestSuite/GoldFiles/adt_mr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr02.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int Bool)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A2 Bool) s0))
+[GOOD] (define-fun s2 () (A Bool String) (getA2_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-A2 Bool) s2))
+[GOOD] (define-fun s4 () (A String String) (getA2_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Aa Bool) s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A2 ((as A2 (A Bool String)) (Aa "!0!")))))
+
+Got:
+A2 {a2 = A2 {a2 = Aa {aa = "!0!"}}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr03.gold b/SBVTestSuite/GoldFiles/adt_mr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr03.gold
@@ -0,0 +1,47 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int Bool)) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A3 Bool) s0))
+[GOOD] (define-fun s2 () (A Bool Int) (getA3_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-Ab Bool) s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A3 (Ab 2))))
+
+Got:
+A3 {a3 = Ab {ab = 2}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_mr04.gold b/SBVTestSuite/GoldFiles/adt_mr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_mr04.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (par (a b) (
+           (Aa (getAa_1 a))
+           (Ab (getAb_1 b))
+           (Aab (getAab_1 a) (getAab_2 b))
+           (A2 (getA2_1 (A b String)))
+           (A3 (getA3_1 (A b a)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (A Int (A (_ FloatingPoint  8 24) Bool))) ; tracks user variable "p"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-A2 Bool) s0))
+[GOOD] (define-fun s2 () (A (A (_ FloatingPoint  8 24) Bool) String) (getA2_1 s0))
+[GOOD] (define-fun s3 () Bool ((as is-A3 Bool) s2))
+[GOOD] (define-fun s4 () (A String (A (_ FloatingPoint  8 24) Bool)) (getA3_1 s2))
+[GOOD] (define-fun s5 () Bool ((as is-Aab Bool) s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as A2 (A Int (A (_ FloatingPoint 8 24) Bool))) (A3 (Aab "!0!"
+                    (Aab (_ +zero 8 24) false))))))
+
+Got:
+A2 {a2 = A3 {a3 = Aab {aba = "!0!", abb = Aab {aba = 0.0, abb = False}}}}
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested00.gold b/SBVTestSuite/GoldFiles/adt_nested00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested00.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Val Expr) 5)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Val Expr) 5))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested00c.gold b/SBVTestSuite/GoldFiles/adt_nested00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested00c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested01.gold b/SBVTestSuite/GoldFiles/adt_nested01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested01.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 7) ((as Val Expr) 0)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Val Expr) 7))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested01c.gold b/SBVTestSuite/GoldFiles/adt_nested01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested01c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested02.gold b/SBVTestSuite/GoldFiles/adt_nested02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested02.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Val Expr) 9)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Val Expr) 9))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested02c.gold b/SBVTestSuite/GoldFiles/adt_nested02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested02c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested03.gold b/SBVTestSuite/GoldFiles/adt_nested03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested03.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 4) ((as Val Expr) 1)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Val Expr) 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested03c.gold b/SBVTestSuite/GoldFiles/adt_nested03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested03c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested04.gold b/SBVTestSuite/GoldFiles/adt_nested04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested04.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 0) ((as Val Expr) 99)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s34 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested04c.gold b/SBVTestSuite/GoldFiles/adt_nested04c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested04c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested05.gold b/SBVTestSuite/GoldFiles/adt_nested05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested05.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested05c.gold b/SBVTestSuite/GoldFiles/adt_nested05c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested05c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested06.gold b/SBVTestSuite/GoldFiles/adt_nested06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested06.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 1) ((as Val Expr) 5)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested06c.gold b/SBVTestSuite/GoldFiles/adt_nested06c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested06c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested07.gold b/SBVTestSuite/GoldFiles/adt_nested07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested07.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Val Expr) 0)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s34 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested07c.gold b/SBVTestSuite/GoldFiles/adt_nested07c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested07c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested08.gold b/SBVTestSuite/GoldFiles/adt_nested08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested08.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested08c.gold b/SBVTestSuite/GoldFiles/adt_nested08c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested08c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested09.gold b/SBVTestSuite/GoldFiles/adt_nested09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested09.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 0) ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s34 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested09c.gold b/SBVTestSuite/GoldFiles/adt_nested09c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested09c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested10.gold b/SBVTestSuite/GoldFiles/adt_nested10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested10.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Var Expr) "x"))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested10c.gold b/SBVTestSuite/GoldFiles/adt_nested10c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested10c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested11.gold b/SBVTestSuite/GoldFiles/adt_nested11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested11.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Val Expr) 42))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested11c.gold b/SBVTestSuite/GoldFiles/adt_nested11c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested11c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested12.gold b/SBVTestSuite/GoldFiles/adt_nested12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested12.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Let Expr) "x" ((as Val Expr) 1) ((as Var Expr) "x")))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested12c.gold b/SBVTestSuite/GoldFiles/adt_nested12c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested12c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested13.gold b/SBVTestSuite/GoldFiles/adt_nested13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested13.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 0) ((as Var Expr) "x")))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s34 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested13c.gold b/SBVTestSuite/GoldFiles/adt_nested13c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested13c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested14.gold b/SBVTestSuite/GoldFiles/adt_nested14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested14.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested14c.gold b/SBVTestSuite/GoldFiles/adt_nested14c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested14c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested15.gold b/SBVTestSuite/GoldFiles/adt_nested15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested15.gold
@@ -0,0 +1,114 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Val Expr) 5)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s74 () Expr ((as Val Expr) 5))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Val Bool) s41))
+[GOOD] (define-fun s43 () Int (getVal_1 s41))
+[GOOD] (define-fun s44 () Bool (= s7 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Val Bool) s47))
+[GOOD] (define-fun s49 () Int (getVal_1 s47))
+[GOOD] (define-fun s50 () Bool (= s7 s49))
+[GOOD] (define-fun s51 () Bool (and s48 s50))
+[GOOD] (define-fun s52 () Bool (and s40 s51))
+[GOOD] (define-fun s53 () Bool ((as is-Mul Bool) s39))
+[GOOD] (define-fun s54 () Expr (getMul_1 s39))
+[GOOD] (define-fun s55 () Bool ((as is-Val Bool) s54))
+[GOOD] (define-fun s56 () Int (getVal_1 s54))
+[GOOD] (define-fun s57 () Bool (= s21 s56))
+[GOOD] (define-fun s58 () Bool (and s55 s57))
+[GOOD] (define-fun s59 () Bool (and s53 s58))
+[GOOD] (define-fun s60 () Expr (getMul_2 s39))
+[GOOD] (define-fun s61 () Bool ((as is-Val Bool) s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s60))
+[GOOD] (define-fun s63 () Bool (= s21 s62))
+[GOOD] (define-fun s64 () Bool (and s61 s63))
+[GOOD] (define-fun s65 () Bool (and s53 s64))
+[GOOD] (define-fun s66 () Bool (= s7 s56))
+[GOOD] (define-fun s67 () Bool (and s55 s66))
+[GOOD] (define-fun s68 () Bool (and s53 s67))
+[GOOD] (define-fun s69 () Expr (ite s68 s34 s39))
+[GOOD] (define-fun s70 () Expr (ite s65 s54 s69))
+[GOOD] (define-fun s71 () Expr (ite s59 s60 s70))
+[GOOD] (define-fun s72 () Expr (ite s52 s41 s71))
+[GOOD] (define-fun s73 () Expr (ite s46 s47 s72))
+[GOOD] (define-fun s75 () Bool (distinct s73 s74))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s75)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested15c.gold b/SBVTestSuite/GoldFiles/adt_nested15c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested15c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested16.gold b/SBVTestSuite/GoldFiles/adt_nested16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested16.gold
@@ -0,0 +1,113 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 3) ((as Val Expr) 4)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Val Bool) s41))
+[GOOD] (define-fun s43 () Int (getVal_1 s41))
+[GOOD] (define-fun s44 () Bool (= s7 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Val Bool) s47))
+[GOOD] (define-fun s49 () Int (getVal_1 s47))
+[GOOD] (define-fun s50 () Bool (= s7 s49))
+[GOOD] (define-fun s51 () Bool (and s48 s50))
+[GOOD] (define-fun s52 () Bool (and s40 s51))
+[GOOD] (define-fun s53 () Bool ((as is-Mul Bool) s39))
+[GOOD] (define-fun s54 () Expr (getMul_1 s39))
+[GOOD] (define-fun s55 () Bool ((as is-Val Bool) s54))
+[GOOD] (define-fun s56 () Int (getVal_1 s54))
+[GOOD] (define-fun s57 () Bool (= s21 s56))
+[GOOD] (define-fun s58 () Bool (and s55 s57))
+[GOOD] (define-fun s59 () Bool (and s53 s58))
+[GOOD] (define-fun s60 () Expr (getMul_2 s39))
+[GOOD] (define-fun s61 () Bool ((as is-Val Bool) s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s60))
+[GOOD] (define-fun s63 () Bool (= s21 s62))
+[GOOD] (define-fun s64 () Bool (and s61 s63))
+[GOOD] (define-fun s65 () Bool (and s53 s64))
+[GOOD] (define-fun s66 () Bool (= s7 s56))
+[GOOD] (define-fun s67 () Bool (and s55 s66))
+[GOOD] (define-fun s68 () Bool (and s53 s67))
+[GOOD] (define-fun s69 () Expr (ite s68 s34 s39))
+[GOOD] (define-fun s70 () Expr (ite s65 s54 s69))
+[GOOD] (define-fun s71 () Expr (ite s59 s60 s70))
+[GOOD] (define-fun s72 () Expr (ite s52 s41 s71))
+[GOOD] (define-fun s73 () Expr (ite s46 s47 s72))
+[GOOD] (define-fun s74 () Bool (distinct s1 s73))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s74)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested16c.gold b/SBVTestSuite/GoldFiles/adt_nested16c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested16c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested17.gold b/SBVTestSuite/GoldFiles/adt_nested17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested17.gold
@@ -0,0 +1,114 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Add Expr) ((as Val Expr) 0) ((as Val Expr) 5))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s74 () Expr ((as Val Expr) 5))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Val Bool) s41))
+[GOOD] (define-fun s43 () Int (getVal_1 s41))
+[GOOD] (define-fun s44 () Bool (= s7 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Val Bool) s47))
+[GOOD] (define-fun s49 () Int (getVal_1 s47))
+[GOOD] (define-fun s50 () Bool (= s7 s49))
+[GOOD] (define-fun s51 () Bool (and s48 s50))
+[GOOD] (define-fun s52 () Bool (and s40 s51))
+[GOOD] (define-fun s53 () Bool ((as is-Mul Bool) s39))
+[GOOD] (define-fun s54 () Expr (getMul_1 s39))
+[GOOD] (define-fun s55 () Bool ((as is-Val Bool) s54))
+[GOOD] (define-fun s56 () Int (getVal_1 s54))
+[GOOD] (define-fun s57 () Bool (= s21 s56))
+[GOOD] (define-fun s58 () Bool (and s55 s57))
+[GOOD] (define-fun s59 () Bool (and s53 s58))
+[GOOD] (define-fun s60 () Expr (getMul_2 s39))
+[GOOD] (define-fun s61 () Bool ((as is-Val Bool) s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s60))
+[GOOD] (define-fun s63 () Bool (= s21 s62))
+[GOOD] (define-fun s64 () Bool (and s61 s63))
+[GOOD] (define-fun s65 () Bool (and s53 s64))
+[GOOD] (define-fun s66 () Bool (= s7 s56))
+[GOOD] (define-fun s67 () Bool (and s55 s66))
+[GOOD] (define-fun s68 () Bool (and s53 s67))
+[GOOD] (define-fun s69 () Expr (ite s68 s34 s39))
+[GOOD] (define-fun s70 () Expr (ite s65 s54 s69))
+[GOOD] (define-fun s71 () Expr (ite s59 s60 s70))
+[GOOD] (define-fun s72 () Expr (ite s52 s41 s71))
+[GOOD] (define-fun s73 () Expr (ite s46 s47 s72))
+[GOOD] (define-fun s75 () Bool (distinct s73 s74))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s75)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested17c.gold b/SBVTestSuite/GoldFiles/adt_nested17c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested17c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested18.gold b/SBVTestSuite/GoldFiles/adt_nested18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested18.gold
@@ -0,0 +1,252 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s20 () Int 1)
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "e"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s3 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s4 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s5 () Int (getVal_1 s3))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s8 () Bool (and s4 s7))
+[GOOD] (define-fun s9 () Bool (and s2 s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s12 () Int (getVal_1 s10))
+[GOOD] (define-fun s13 () Bool (= s6 s12))
+[GOOD] (define-fun s14 () Bool (and s11 s13))
+[GOOD] (define-fun s15 () Bool (and s2 s14))
+[GOOD] (define-fun s16 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s17 () Expr (getMul_1 s0))
+[GOOD] (define-fun s18 () Bool ((as is-Val Bool) s17))
+[GOOD] (define-fun s19 () Int (getVal_1 s17))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s22 () Bool (and s18 s21))
+[GOOD] (define-fun s23 () Bool (and s16 s22))
+[GOOD] (define-fun s24 () Expr (getMul_2 s0))
+[GOOD] (define-fun s25 () Bool ((as is-Val Bool) s24))
+[GOOD] (define-fun s26 () Int (getVal_1 s24))
+[GOOD] (define-fun s27 () Bool (= s20 s26))
+[GOOD] (define-fun s28 () Bool (and s25 s27))
+[GOOD] (define-fun s29 () Bool (and s16 s28))
+[GOOD] (define-fun s30 () Bool (= s6 s19))
+[GOOD] (define-fun s31 () Bool (and s18 s30))
+[GOOD] (define-fun s32 () Bool (and s16 s31))
+[GOOD] (define-fun s34 () Expr (ite s32 s33 s0))
+[GOOD] (define-fun s35 () Expr (ite s29 s17 s34))
+[GOOD] (define-fun s36 () Expr (ite s23 s24 s35))
+[GOOD] (define-fun s37 () Expr (ite s15 s3 s36))
+[GOOD] (define-fun s38 () Expr (ite s9 s10 s37))
+[GOOD] (define-fun s39 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s38))
+[GOOD] (define-fun s40 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s0))
+[GOOD] (define-fun s41 () Bool (= s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s41))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested19.gold b/SBVTestSuite/GoldFiles/adt_nested19.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested19.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Val Expr) 1)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Val Expr) 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested19c.gold b/SBVTestSuite/GoldFiles/adt_nested19c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested19c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested20.gold b/SBVTestSuite/GoldFiles/adt_nested20.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested20.gold
@@ -0,0 +1,79 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool (distinct s1 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s40)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested20c.gold b/SBVTestSuite/GoldFiles/adt_nested20c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested20c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested21.gold b/SBVTestSuite/GoldFiles/adt_nested21.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested21.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Var Expr) "x")))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Var Expr) "x"))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested21c.gold b/SBVTestSuite/GoldFiles/adt_nested21c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested21c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested22.gold b/SBVTestSuite/GoldFiles/adt_nested22.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested22.gold
@@ -0,0 +1,80 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Var Expr) "x")))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s40 () Expr ((as Var Expr) "x"))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s41 () Bool (distinct s39 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s41)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested22c.gold b/SBVTestSuite/GoldFiles/adt_nested22c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested22c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested23.gold b/SBVTestSuite/GoldFiles/adt_nested23.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested23.gold
@@ -0,0 +1,253 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s20 () Int 1)
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "e"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s3 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s4 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s5 () Int (getVal_1 s3))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s8 () Bool (and s4 s7))
+[GOOD] (define-fun s9 () Bool (and s1 s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s12 () Int (getVal_1 s10))
+[GOOD] (define-fun s13 () Bool (= s6 s12))
+[GOOD] (define-fun s14 () Bool (and s11 s13))
+[GOOD] (define-fun s15 () Bool (and s1 s14))
+[GOOD] (define-fun s16 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s17 () Expr (getMul_1 s0))
+[GOOD] (define-fun s18 () Bool ((as is-Val Bool) s17))
+[GOOD] (define-fun s19 () Int (getVal_1 s17))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s22 () Bool (and s18 s21))
+[GOOD] (define-fun s23 () Bool (and s16 s22))
+[GOOD] (define-fun s24 () Expr (getMul_2 s0))
+[GOOD] (define-fun s25 () Bool ((as is-Val Bool) s24))
+[GOOD] (define-fun s26 () Int (getVal_1 s24))
+[GOOD] (define-fun s27 () Bool (= s20 s26))
+[GOOD] (define-fun s28 () Bool (and s25 s27))
+[GOOD] (define-fun s29 () Bool (and s16 s28))
+[GOOD] (define-fun s30 () Bool (= s6 s19))
+[GOOD] (define-fun s31 () Bool (and s18 s30))
+[GOOD] (define-fun s32 () Bool (and s16 s31))
+[GOOD] (define-fun s34 () Expr (ite s32 s33 s0))
+[GOOD] (define-fun s35 () Expr (ite s29 s17 s34))
+[GOOD] (define-fun s36 () Expr (ite s23 s24 s35))
+[GOOD] (define-fun s37 () Expr (ite s15 s3 s36))
+[GOOD] (define-fun s38 () Expr (ite s9 s10 s37))
+[GOOD] (define-fun s39 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s2 s38))
+[GOOD] (define-fun s40 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s2 s0))
+[GOOD] (define-fun s41 () Bool (= s39 s40))
+[GOOD] (define-fun s42 () Bool (=> s1 s41))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s42))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested24.gold b/SBVTestSuite/GoldFiles/adt_nested24.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested24.gold
@@ -0,0 +1,253 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s20 () Int 1)
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "e"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Expr (getMul_1 s0))
+[GOOD] (define-fun s18 () Bool ((as is-Val Bool) s17))
+[GOOD] (define-fun s19 () Int (getVal_1 s17))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s22 () Bool (and s18 s21))
+[GOOD] (define-fun s23 () Bool (and s1 s22))
+[GOOD] (define-fun s24 () Expr (getMul_2 s0))
+[GOOD] (define-fun s25 () Bool ((as is-Val Bool) s24))
+[GOOD] (define-fun s26 () Int (getVal_1 s24))
+[GOOD] (define-fun s27 () Bool (= s20 s26))
+[GOOD] (define-fun s28 () Bool (and s25 s27))
+[GOOD] (define-fun s29 () Bool (and s1 s28))
+[GOOD] (define-fun s30 () Bool (= s7 s19))
+[GOOD] (define-fun s31 () Bool (and s18 s30))
+[GOOD] (define-fun s32 () Bool (and s1 s31))
+[GOOD] (define-fun s34 () Expr (ite s32 s33 s0))
+[GOOD] (define-fun s35 () Expr (ite s29 s17 s34))
+[GOOD] (define-fun s36 () Expr (ite s23 s24 s35))
+[GOOD] (define-fun s37 () Expr (ite s16 s4 s36))
+[GOOD] (define-fun s38 () Expr (ite s10 s11 s37))
+[GOOD] (define-fun s39 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s2 s38))
+[GOOD] (define-fun s40 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s2 s0))
+[GOOD] (define-fun s41 () Bool (= s39 s40))
+[GOOD] (define-fun s42 () Bool (=> s1 s41))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s42))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested25.gold b/SBVTestSuite/GoldFiles/adt_nested25.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested25.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)) ((as Mul Expr) ((as Val Expr) 4) ((as Val Expr) 5))))
+[GOOD] (define-fun s31 () Expr ((as Val Expr) 26))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Mul Bool) s4))
+[GOOD] (define-fun s6 () Expr (getMul_1 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s8 () Expr (getMul_2 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Mul Bool) s10))
+[GOOD] (define-fun s12 () Expr (getMul_1 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s14 () Expr (getMul_2 s10))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] (define-fun s17 () Bool (and s11 s16))
+[GOOD] (define-fun s18 () Bool (and s9 s17))
+[GOOD] (define-fun s19 () Bool (and s7 s18))
+[GOOD] (define-fun s20 () Bool (and s5 s19))
+[GOOD] (define-fun s21 () Bool (and s3 s20))
+[GOOD] (define-fun s22 () Int (getVal_1 s6))
+[GOOD] (define-fun s23 () Int (getVal_1 s8))
+[GOOD] (define-fun s24 () Int (* s22 s23))
+[GOOD] (define-fun s25 () Int (getVal_1 s12))
+[GOOD] (define-fun s26 () Int (getVal_1 s14))
+[GOOD] (define-fun s27 () Int (* s25 s26))
+[GOOD] (define-fun s28 () Int (+ s24 s27))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) s28))
+[GOOD] (define-fun s30 () Expr (ite s21 s29 s0))
+[GOOD] (define-fun s32 () Bool (distinct s30 s31))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s32)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested25c.gold b/SBVTestSuite/GoldFiles/adt_nested25c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested25c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested26.gold b/SBVTestSuite/GoldFiles/adt_nested26.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested26.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Mul Expr) ((as Val Expr) 0) ((as Val Expr) 99)) ((as Mul Expr) ((as Val Expr) 1) ((as Val Expr) 1))))
+[GOOD] (define-fun s31 () Expr ((as Val Expr) 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Mul Bool) s4))
+[GOOD] (define-fun s6 () Expr (getMul_1 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s8 () Expr (getMul_2 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Mul Bool) s10))
+[GOOD] (define-fun s12 () Expr (getMul_1 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s14 () Expr (getMul_2 s10))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] (define-fun s17 () Bool (and s11 s16))
+[GOOD] (define-fun s18 () Bool (and s9 s17))
+[GOOD] (define-fun s19 () Bool (and s7 s18))
+[GOOD] (define-fun s20 () Bool (and s5 s19))
+[GOOD] (define-fun s21 () Bool (and s3 s20))
+[GOOD] (define-fun s22 () Int (getVal_1 s6))
+[GOOD] (define-fun s23 () Int (getVal_1 s8))
+[GOOD] (define-fun s24 () Int (* s22 s23))
+[GOOD] (define-fun s25 () Int (getVal_1 s12))
+[GOOD] (define-fun s26 () Int (getVal_1 s14))
+[GOOD] (define-fun s27 () Int (* s25 s26))
+[GOOD] (define-fun s28 () Int (+ s24 s27))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) s28))
+[GOOD] (define-fun s30 () Expr (ite s21 s29 s0))
+[GOOD] (define-fun s32 () Bool (distinct s30 s31))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s32)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested26c.gold b/SBVTestSuite/GoldFiles/adt_nested26c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested26c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested27.gold b/SBVTestSuite/GoldFiles/adt_nested27.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested27.gold
@@ -0,0 +1,70 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)) ((as Var Expr) "x")))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Mul Bool) s4))
+[GOOD] (define-fun s6 () Expr (getMul_1 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s8 () Expr (getMul_2 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Mul Bool) s10))
+[GOOD] (define-fun s12 () Expr (getMul_1 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s14 () Expr (getMul_2 s10))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] (define-fun s17 () Bool (and s11 s16))
+[GOOD] (define-fun s18 () Bool (and s9 s17))
+[GOOD] (define-fun s19 () Bool (and s7 s18))
+[GOOD] (define-fun s20 () Bool (and s5 s19))
+[GOOD] (define-fun s21 () Bool (and s3 s20))
+[GOOD] (define-fun s22 () Int (getVal_1 s6))
+[GOOD] (define-fun s23 () Int (getVal_1 s8))
+[GOOD] (define-fun s24 () Int (* s22 s23))
+[GOOD] (define-fun s25 () Int (getVal_1 s12))
+[GOOD] (define-fun s26 () Int (getVal_1 s14))
+[GOOD] (define-fun s27 () Int (* s25 s26))
+[GOOD] (define-fun s28 () Int (+ s24 s27))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) s28))
+[GOOD] (define-fun s30 () Expr (ite s21 s29 s0))
+[GOOD] (define-fun s31 () Bool (distinct s1 s30))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s31)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested27c.gold b/SBVTestSuite/GoldFiles/adt_nested27c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested27c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested28.gold b/SBVTestSuite/GoldFiles/adt_nested28.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested28.gold
@@ -0,0 +1,70 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Mul Bool) s4))
+[GOOD] (define-fun s6 () Expr (getMul_1 s4))
+[GOOD] (define-fun s7 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s8 () Expr (getMul_2 s4))
+[GOOD] (define-fun s9 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Mul Bool) s10))
+[GOOD] (define-fun s12 () Expr (getMul_1 s10))
+[GOOD] (define-fun s13 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s14 () Expr (getMul_2 s10))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] (define-fun s17 () Bool (and s11 s16))
+[GOOD] (define-fun s18 () Bool (and s9 s17))
+[GOOD] (define-fun s19 () Bool (and s7 s18))
+[GOOD] (define-fun s20 () Bool (and s5 s19))
+[GOOD] (define-fun s21 () Bool (and s3 s20))
+[GOOD] (define-fun s22 () Int (getVal_1 s6))
+[GOOD] (define-fun s23 () Int (getVal_1 s8))
+[GOOD] (define-fun s24 () Int (* s22 s23))
+[GOOD] (define-fun s25 () Int (getVal_1 s12))
+[GOOD] (define-fun s26 () Int (getVal_1 s14))
+[GOOD] (define-fun s27 () Int (* s25 s26))
+[GOOD] (define-fun s28 () Int (+ s24 s27))
+[GOOD] (define-fun s29 () Expr ((as Val Expr) s28))
+[GOOD] (define-fun s30 () Expr (ite s21 s29 s0))
+[GOOD] (define-fun s31 () Bool (distinct s1 s30))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s31)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested28c.gold b/SBVTestSuite/GoldFiles/adt_nested28c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested28c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested29.gold b/SBVTestSuite/GoldFiles/adt_nested29.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested29.gold
@@ -0,0 +1,243 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "e"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s3 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s4 () Bool ((as is-Mul Bool) s3))
+[GOOD] (define-fun s5 () Expr (getMul_1 s3))
+[GOOD] (define-fun s6 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s7 () Expr (getMul_2 s3))
+[GOOD] (define-fun s8 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s9 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s10 () Bool ((as is-Mul Bool) s9))
+[GOOD] (define-fun s11 () Expr (getMul_1 s9))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Expr (getMul_2 s9))
+[GOOD] (define-fun s14 () Bool ((as is-Val Bool) s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s10 s15))
+[GOOD] (define-fun s17 () Bool (and s8 s16))
+[GOOD] (define-fun s18 () Bool (and s6 s17))
+[GOOD] (define-fun s19 () Bool (and s4 s18))
+[GOOD] (define-fun s20 () Bool (and s2 s19))
+[GOOD] (define-fun s21 () Int (getVal_1 s5))
+[GOOD] (define-fun s22 () Int (getVal_1 s7))
+[GOOD] (define-fun s23 () Int (* s21 s22))
+[GOOD] (define-fun s24 () Int (getVal_1 s11))
+[GOOD] (define-fun s25 () Int (getVal_1 s13))
+[GOOD] (define-fun s26 () Int (* s24 s25))
+[GOOD] (define-fun s27 () Int (+ s23 s26))
+[GOOD] (define-fun s28 () Expr ((as Val Expr) s27))
+[GOOD] (define-fun s29 () Expr (ite s20 s28 s0))
+[GOOD] (define-fun s30 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s29))
+[GOOD] (define-fun s31 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s0))
+[GOOD] (define-fun s32 () Bool (= s30 s31))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s32))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested30.gold b/SBVTestSuite/GoldFiles/adt_nested30.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested30.gold
@@ -0,0 +1,108 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)) ((as Mul Expr) ((as Val Expr) 4) ((as Val Expr) 5))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s68 () Expr ((as Val Expr) 26))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Mul Bool) s41))
+[GOOD] (define-fun s43 () Expr (getMul_1 s41))
+[GOOD] (define-fun s44 () Bool ((as is-Val Bool) s43))
+[GOOD] (define-fun s45 () Expr (getMul_2 s41))
+[GOOD] (define-fun s46 () Bool ((as is-Val Bool) s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Mul Bool) s47))
+[GOOD] (define-fun s49 () Expr (getMul_1 s47))
+[GOOD] (define-fun s50 () Bool ((as is-Val Bool) s49))
+[GOOD] (define-fun s51 () Expr (getMul_2 s47))
+[GOOD] (define-fun s52 () Bool ((as is-Val Bool) s51))
+[GOOD] (define-fun s53 () Bool (and s50 s52))
+[GOOD] (define-fun s54 () Bool (and s48 s53))
+[GOOD] (define-fun s55 () Bool (and s46 s54))
+[GOOD] (define-fun s56 () Bool (and s44 s55))
+[GOOD] (define-fun s57 () Bool (and s42 s56))
+[GOOD] (define-fun s58 () Bool (and s40 s57))
+[GOOD] (define-fun s59 () Int (getVal_1 s43))
+[GOOD] (define-fun s60 () Int (getVal_1 s45))
+[GOOD] (define-fun s61 () Int (* s59 s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s49))
+[GOOD] (define-fun s63 () Int (getVal_1 s51))
+[GOOD] (define-fun s64 () Int (* s62 s63))
+[GOOD] (define-fun s65 () Int (+ s61 s64))
+[GOOD] (define-fun s66 () Expr ((as Val Expr) s65))
+[GOOD] (define-fun s67 () Expr (ite s58 s66 s39))
+[GOOD] (define-fun s69 () Bool (distinct s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested30c.gold b/SBVTestSuite/GoldFiles/adt_nested30c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested30c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested31.gold b/SBVTestSuite/GoldFiles/adt_nested31.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested31.gold
@@ -0,0 +1,108 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Mul Expr) ((as Val Expr) 1) ((as Val Expr) 2)) ((as Mul Expr) ((as Val Expr) 0) ((as Val Expr) 4))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s68 () Expr ((as Val Expr) 2))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Mul Bool) s41))
+[GOOD] (define-fun s43 () Expr (getMul_1 s41))
+[GOOD] (define-fun s44 () Bool ((as is-Val Bool) s43))
+[GOOD] (define-fun s45 () Expr (getMul_2 s41))
+[GOOD] (define-fun s46 () Bool ((as is-Val Bool) s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Mul Bool) s47))
+[GOOD] (define-fun s49 () Expr (getMul_1 s47))
+[GOOD] (define-fun s50 () Bool ((as is-Val Bool) s49))
+[GOOD] (define-fun s51 () Expr (getMul_2 s47))
+[GOOD] (define-fun s52 () Bool ((as is-Val Bool) s51))
+[GOOD] (define-fun s53 () Bool (and s50 s52))
+[GOOD] (define-fun s54 () Bool (and s48 s53))
+[GOOD] (define-fun s55 () Bool (and s46 s54))
+[GOOD] (define-fun s56 () Bool (and s44 s55))
+[GOOD] (define-fun s57 () Bool (and s42 s56))
+[GOOD] (define-fun s58 () Bool (and s40 s57))
+[GOOD] (define-fun s59 () Int (getVal_1 s43))
+[GOOD] (define-fun s60 () Int (getVal_1 s45))
+[GOOD] (define-fun s61 () Int (* s59 s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s49))
+[GOOD] (define-fun s63 () Int (getVal_1 s51))
+[GOOD] (define-fun s64 () Int (* s62 s63))
+[GOOD] (define-fun s65 () Int (+ s61 s64))
+[GOOD] (define-fun s66 () Expr ((as Val Expr) s65))
+[GOOD] (define-fun s67 () Expr (ite s58 s66 s39))
+[GOOD] (define-fun s69 () Bool (distinct s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested31c.gold b/SBVTestSuite/GoldFiles/adt_nested31c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested31c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested32.gold b/SBVTestSuite/GoldFiles/adt_nested32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested32.gold
@@ -0,0 +1,108 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Mul Expr) ((as Val Expr) 1) ((as Add Expr) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)) ((as Mul Expr) ((as Val Expr) 4) ((as Val Expr) 5)))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s68 () Expr ((as Val Expr) 26))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Mul Bool) s41))
+[GOOD] (define-fun s43 () Expr (getMul_1 s41))
+[GOOD] (define-fun s44 () Bool ((as is-Val Bool) s43))
+[GOOD] (define-fun s45 () Expr (getMul_2 s41))
+[GOOD] (define-fun s46 () Bool ((as is-Val Bool) s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Mul Bool) s47))
+[GOOD] (define-fun s49 () Expr (getMul_1 s47))
+[GOOD] (define-fun s50 () Bool ((as is-Val Bool) s49))
+[GOOD] (define-fun s51 () Expr (getMul_2 s47))
+[GOOD] (define-fun s52 () Bool ((as is-Val Bool) s51))
+[GOOD] (define-fun s53 () Bool (and s50 s52))
+[GOOD] (define-fun s54 () Bool (and s48 s53))
+[GOOD] (define-fun s55 () Bool (and s46 s54))
+[GOOD] (define-fun s56 () Bool (and s44 s55))
+[GOOD] (define-fun s57 () Bool (and s42 s56))
+[GOOD] (define-fun s58 () Bool (and s40 s57))
+[GOOD] (define-fun s59 () Int (getVal_1 s43))
+[GOOD] (define-fun s60 () Int (getVal_1 s45))
+[GOOD] (define-fun s61 () Int (* s59 s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s49))
+[GOOD] (define-fun s63 () Int (getVal_1 s51))
+[GOOD] (define-fun s64 () Int (* s62 s63))
+[GOOD] (define-fun s65 () Int (+ s61 s64))
+[GOOD] (define-fun s66 () Expr ((as Val Expr) s65))
+[GOOD] (define-fun s67 () Expr (ite s58 s66 s39))
+[GOOD] (define-fun s69 () Bool (distinct s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested32c.gold b/SBVTestSuite/GoldFiles/adt_nested32c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested32c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested33.gold b/SBVTestSuite/GoldFiles/adt_nested33.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested33.gold
@@ -0,0 +1,108 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Expr ((as Add Expr) ((as Val Expr) 0) ((as Add Expr) ((as Mul Expr) ((as Val Expr) 2) ((as Val Expr) 3)) ((as Mul Expr) ((as Val Expr) 4) ((as Val Expr) 5)))))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] (define-fun s21 () Int 1)
+[GOOD] (define-fun s34 () Expr ((as Val Expr) 0))
+[GOOD] (define-fun s68 () Expr ((as Val Expr) 26))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s4 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s5 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s6 () Int (getVal_1 s4))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (and s3 s9))
+[GOOD] (define-fun s11 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s12 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s13 () Int (getVal_1 s11))
+[GOOD] (define-fun s14 () Bool (= s7 s13))
+[GOOD] (define-fun s15 () Bool (and s12 s14))
+[GOOD] (define-fun s16 () Bool (and s3 s15))
+[GOOD] (define-fun s17 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s18 () Expr (getMul_1 s0))
+[GOOD] (define-fun s19 () Bool ((as is-Val Bool) s18))
+[GOOD] (define-fun s20 () Int (getVal_1 s18))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s23 () Bool (and s19 s22))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s25 () Expr (getMul_2 s0))
+[GOOD] (define-fun s26 () Bool ((as is-Val Bool) s25))
+[GOOD] (define-fun s27 () Int (getVal_1 s25))
+[GOOD] (define-fun s28 () Bool (= s21 s27))
+[GOOD] (define-fun s29 () Bool (and s26 s28))
+[GOOD] (define-fun s30 () Bool (and s17 s29))
+[GOOD] (define-fun s31 () Bool (= s7 s20))
+[GOOD] (define-fun s32 () Bool (and s19 s31))
+[GOOD] (define-fun s33 () Bool (and s17 s32))
+[GOOD] (define-fun s35 () Expr (ite s33 s34 s0))
+[GOOD] (define-fun s36 () Expr (ite s30 s18 s35))
+[GOOD] (define-fun s37 () Expr (ite s24 s25 s36))
+[GOOD] (define-fun s38 () Expr (ite s16 s4 s37))
+[GOOD] (define-fun s39 () Expr (ite s10 s11 s38))
+[GOOD] (define-fun s40 () Bool ((as is-Add Bool) s39))
+[GOOD] (define-fun s41 () Expr (getAdd_1 s39))
+[GOOD] (define-fun s42 () Bool ((as is-Mul Bool) s41))
+[GOOD] (define-fun s43 () Expr (getMul_1 s41))
+[GOOD] (define-fun s44 () Bool ((as is-Val Bool) s43))
+[GOOD] (define-fun s45 () Expr (getMul_2 s41))
+[GOOD] (define-fun s46 () Bool ((as is-Val Bool) s45))
+[GOOD] (define-fun s47 () Expr (getAdd_2 s39))
+[GOOD] (define-fun s48 () Bool ((as is-Mul Bool) s47))
+[GOOD] (define-fun s49 () Expr (getMul_1 s47))
+[GOOD] (define-fun s50 () Bool ((as is-Val Bool) s49))
+[GOOD] (define-fun s51 () Expr (getMul_2 s47))
+[GOOD] (define-fun s52 () Bool ((as is-Val Bool) s51))
+[GOOD] (define-fun s53 () Bool (and s50 s52))
+[GOOD] (define-fun s54 () Bool (and s48 s53))
+[GOOD] (define-fun s55 () Bool (and s46 s54))
+[GOOD] (define-fun s56 () Bool (and s44 s55))
+[GOOD] (define-fun s57 () Bool (and s42 s56))
+[GOOD] (define-fun s58 () Bool (and s40 s57))
+[GOOD] (define-fun s59 () Int (getVal_1 s43))
+[GOOD] (define-fun s60 () Int (getVal_1 s45))
+[GOOD] (define-fun s61 () Int (* s59 s60))
+[GOOD] (define-fun s62 () Int (getVal_1 s49))
+[GOOD] (define-fun s63 () Int (getVal_1 s51))
+[GOOD] (define-fun s64 () Int (* s62 s63))
+[GOOD] (define-fun s65 () Int (+ s61 s64))
+[GOOD] (define-fun s66 () Expr ((as Val Expr) s65))
+[GOOD] (define-fun s67 () Expr (ite s58 s66 s39))
+[GOOD] (define-fun s69 () Bool (distinct s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested33c.gold b/SBVTestSuite/GoldFiles/adt_nested33c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested33c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_nested34.gold b/SBVTestSuite/GoldFiles/adt_nested34.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_nested34.gold
@@ -0,0 +1,157 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (
+           (Val (getVal_1 Int))
+           (Var (getVar_1 String))
+           (Add (getAdd_1 Expr) (getAdd_2 Expr))
+           (Mul (getMul_1 Expr) (getMul_2 Expr))
+           (Let (getLet_1 String) (getLet_2 Expr) (getLet_3 Expr))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s20 () Int 1)
+[GOOD] (define-fun s33 () Expr ((as Val Expr) 0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Expr) ; tracks user variable "e"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s9 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s6 (proj_1_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s7 (= l2_s1 l2_s6)))
+                                                 (let ((l2_s8 (proj_2_SBVTuple2 l2_s5)))
+                                                 (let ((l2_s10 (- l2_s2 l2_s9)))
+                                                 (let ((l2_s11 (seq.extract l2_s0 l2_s9 l2_s10)))
+                                                 (let ((l2_s12 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s11 l2_s1)))
+                                                 (let ((l2_s13 (ite l2_s7 l2_s8 l2_s12)))
+                                                 (let ((l2_s14 (ite l2_s4 l2_s3 l2_s13)))
+                                                 l2_s14))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| :: [(SString, SInteger)] -> Expr -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 Expr)) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s3 () Expr (getAdd_1 s0))
+[GOOD] (define-fun s4 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s5 () Int (getVal_1 s3))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s8 () Bool (and s4 s7))
+[GOOD] (define-fun s9 () Bool (and s2 s8))
+[GOOD] (define-fun s10 () Expr (getAdd_2 s0))
+[GOOD] (define-fun s11 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s12 () Int (getVal_1 s10))
+[GOOD] (define-fun s13 () Bool (= s6 s12))
+[GOOD] (define-fun s14 () Bool (and s11 s13))
+[GOOD] (define-fun s15 () Bool (and s2 s14))
+[GOOD] (define-fun s16 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s17 () Expr (getMul_1 s0))
+[GOOD] (define-fun s18 () Bool ((as is-Val Bool) s17))
+[GOOD] (define-fun s19 () Int (getVal_1 s17))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s22 () Bool (and s18 s21))
+[GOOD] (define-fun s23 () Bool (and s16 s22))
+[GOOD] (define-fun s24 () Expr (getMul_2 s0))
+[GOOD] (define-fun s25 () Bool ((as is-Val Bool) s24))
+[GOOD] (define-fun s26 () Int (getVal_1 s24))
+[GOOD] (define-fun s27 () Bool (= s20 s26))
+[GOOD] (define-fun s28 () Bool (and s25 s27))
+[GOOD] (define-fun s29 () Bool (and s16 s28))
+[GOOD] (define-fun s30 () Bool (= s6 s19))
+[GOOD] (define-fun s31 () Bool (and s18 s30))
+[GOOD] (define-fun s32 () Bool (and s16 s31))
+[GOOD] (define-fun s34 () Expr (ite s32 s33 s0))
+[GOOD] (define-fun s35 () Expr (ite s29 s17 s34))
+[GOOD] (define-fun s36 () Expr (ite s23 s24 s35))
+[GOOD] (define-fun s37 () Expr (ite s15 s3 s36))
+[GOOD] (define-fun s38 () Expr (ite s9 s10 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Add Bool) s38))
+[GOOD] (define-fun s40 () Expr (getAdd_1 s38))
+[GOOD] (define-fun s41 () Bool ((as is-Mul Bool) s40))
+[GOOD] (define-fun s42 () Expr (getMul_1 s40))
+[GOOD] (define-fun s43 () Bool ((as is-Val Bool) s42))
+[GOOD] (define-fun s44 () Expr (getMul_2 s40))
+[GOOD] (define-fun s45 () Bool ((as is-Val Bool) s44))
+[GOOD] (define-fun s46 () Expr (getAdd_2 s38))
+[GOOD] (define-fun s47 () Bool ((as is-Mul Bool) s46))
+[GOOD] (define-fun s48 () Expr (getMul_1 s46))
+[GOOD] (define-fun s49 () Bool ((as is-Val Bool) s48))
+[GOOD] (define-fun s50 () Expr (getMul_2 s46))
+[GOOD] (define-fun s51 () Bool ((as is-Val Bool) s50))
+[GOOD] (define-fun s52 () Bool (and s49 s51))
+[GOOD] (define-fun s53 () Bool (and s47 s52))
+[GOOD] (define-fun s54 () Bool (and s45 s53))
+[GOOD] (define-fun s55 () Bool (and s43 s54))
+[GOOD] (define-fun s56 () Bool (and s41 s55))
+[GOOD] (define-fun s57 () Bool (and s39 s56))
+[GOOD] (define-fun s58 () Int (getVal_1 s42))
+[GOOD] (define-fun s59 () Int (getVal_1 s44))
+[GOOD] (define-fun s60 () Int (* s58 s59))
+[GOOD] (define-fun s61 () Int (getVal_1 s48))
+[GOOD] (define-fun s62 () Int (getVal_1 s50))
+[GOOD] (define-fun s63 () Int (* s61 s62))
+[GOOD] (define-fun s64 () Int (+ s60 s63))
+[GOOD] (define-fun s65 () Expr ((as Val Expr) s64))
+[GOOD] (define-fun s66 () Expr (ite s57 s65 s38))
+[GOOD] (define-fun s67 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s66))
+[GOOD] (define-fun s68 () Int (|eval @(SBV [([Char],Integer)] -> SBV Expr -> SBV Integer)| s1 s0))
+[GOOD] (define-fun s69 () Bool (= s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s69))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pchk01.gold b/SBVTestSuite/GoldFiles/adt_pchk01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pchk01.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: A
+[GOOD] (declare-datatype A (
+           (A (getA_1 Int))
+           (B (getB_1 (_ BitVec 8)))
+           (C (getC_1 A) (getC_2 A))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () A ((as A A) 13))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () A) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (A 13)))
+Result: A 13
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr00.gold b/SBVTestSuite/GoldFiles/adt_pexpr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr00.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr00c.gold b/SBVTestSuite/GoldFiles/adt_pexpr00c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr00c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr01.gold b/SBVTestSuite/GoldFiles/adt_pexpr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr01.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 7)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr01c.gold b/SBVTestSuite/GoldFiles/adt_pexpr01c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr01c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr02.gold b/SBVTestSuite/GoldFiles/adt_pexpr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr02.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr02c.gold b/SBVTestSuite/GoldFiles/adt_pexpr02c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr02c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr03.gold b/SBVTestSuite/GoldFiles/adt_pexpr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr03.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 28)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr03c.gold b/SBVTestSuite/GoldFiles/adt_pexpr03c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr03c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr04.gold b/SBVTestSuite/GoldFiles/adt_pexpr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr04.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 63)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 63))
+Result: 63
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr05.gold b/SBVTestSuite/GoldFiles/adt_pexpr05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr05.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3969)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "res"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3969))
+Result: 3969
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr06.gold b/SBVTestSuite/GoldFiles/adt_pexpr06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr06.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "a"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s8 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr06c.gold b/SBVTestSuite/GoldFiles/adt_pexpr06c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr06c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr07.gold b/SBVTestSuite/GoldFiles/adt_pexpr07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr07.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "b"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr07c.gold b/SBVTestSuite/GoldFiles/adt_pexpr07c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr07c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr08.gold b/SBVTestSuite/GoldFiles/adt_pexpr08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr08.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "c"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s15 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr08c.gold b/SBVTestSuite/GoldFiles/adt_pexpr08c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr08c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr09.gold b/SBVTestSuite/GoldFiles/adt_pexpr09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr09.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Var (Expr String Int)) "d"))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s16 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr09c.gold b/SBVTestSuite/GoldFiles/adt_pexpr09c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr09c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr10.gold b/SBVTestSuite/GoldFiles/adt_pexpr10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr10.gold
@@ -0,0 +1,454 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s15 () (Expr String Int) ((as Val (Expr String Int)) (- 5)))
+[GOOD] (define-fun s17 () (Expr String Int) ((as Val (Expr String Int)) (- 4)))
+[GOOD] (define-fun s19 () (Expr String Int) ((as Val (Expr String Int)) (- 3)))
+[GOOD] (define-fun s21 () (Expr String Int) ((as Val (Expr String Int)) (- 2)))
+[GOOD] (define-fun s23 () (Expr String Int) ((as Val (Expr String Int)) (- 1)))
+[GOOD] (define-fun s25 () (Expr String Int) ((as Val (Expr String Int)) 0))
+[GOOD] (define-fun s27 () (Expr String Int) ((as Val (Expr String Int)) 1))
+[GOOD] (define-fun s29 () (Expr String Int) ((as Val (Expr String Int)) 2))
+[GOOD] (define-fun s31 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s33 () (Expr String Int) ((as Val (Expr String Int)) 4))
+[GOOD] (define-fun s35 () (Expr String Int) ((as Val (Expr String Int)) 5))
+[GOOD] (define-fun s37 () (Expr String Int) ((as Val (Expr String Int)) 6))
+[GOOD] (define-fun s39 () (Expr String Int) ((as Val (Expr String Int)) 7))
+[GOOD] (define-fun s41 () (Expr String Int) ((as Val (Expr String Int)) 8))
+[GOOD] (define-fun s43 () (Expr String Int) ((as Val (Expr String Int)) 9))
+[GOOD] (define-fun s61 () String "a")
+[GOOD] (define-fun s64 () Int 0)
+[GOOD] (define-fun s65 () String "b")
+[GOOD] (define-fun s67 () String "c")
+[GOOD] (define-fun s71 () Int 1)
+[GOOD] (define-fun s72 () Int 2)
+[GOOD] (define-fun s75 () Int 10)
+[GOOD] (define-fun s78 () Int 3)
+[GOOD] (define-fun s81 () Int 4)
+[GOOD] (define-fun s84 () Int 5)
+[GOOD] (define-fun s85 () Int 6)
+[GOOD] (define-fun s414 () Int 45)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] (declare-fun s2 () (Expr String Int))
+[GOOD] (declare-fun s3 () (Expr String Int))
+[GOOD] (declare-fun s4 () (Expr String Int))
+[GOOD] (declare-fun s5 () (Expr String Int))
+[GOOD] (declare-fun s6 () (Expr String Int))
+[GOOD] (declare-fun s7 () (Expr String Int))
+[GOOD] (declare-fun s8 () (Expr String Int))
+[GOOD] (declare-fun s9 () (Expr String Int))
+[GOOD] (declare-fun s10 () (Expr String Int))
+[GOOD] (declare-fun s11 () (Expr String Int))
+[GOOD] (declare-fun s12 () (Expr String Int))
+[GOOD] (declare-fun s13 () (Expr String Int))
+[GOOD] (declare-fun s14 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s16 () Bool (= s0 s15))
+[GOOD] (define-fun s18 () Bool (= s1 s17))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () Bool (= s3 s21))
+[GOOD] (define-fun s24 () Bool (= s4 s23))
+[GOOD] (define-fun s26 () Bool (= s5 s25))
+[GOOD] (define-fun s28 () Bool (= s6 s27))
+[GOOD] (define-fun s30 () Bool (= s7 s29))
+[GOOD] (define-fun s32 () Bool (= s8 s31))
+[GOOD] (define-fun s34 () Bool (= s9 s33))
+[GOOD] (define-fun s36 () Bool (= s10 s35))
+[GOOD] (define-fun s38 () Bool (= s11 s37))
+[GOOD] (define-fun s40 () Bool (= s12 s39))
+[GOOD] (define-fun s42 () Bool (= s13 s41))
+[GOOD] (define-fun s44 () Bool (= s14 s43))
+[GOOD] (define-fun s45 () Bool (and s42 s44))
+[GOOD] (define-fun s46 () Bool (and s40 s45))
+[GOOD] (define-fun s47 () Bool (and s38 s46))
+[GOOD] (define-fun s48 () Bool (and s36 s47))
+[GOOD] (define-fun s49 () Bool (and s34 s48))
+[GOOD] (define-fun s50 () Bool (and s32 s49))
+[GOOD] (define-fun s51 () Bool (and s30 s50))
+[GOOD] (define-fun s52 () Bool (and s28 s51))
+[GOOD] (define-fun s53 () Bool (and s26 s52))
+[GOOD] (define-fun s54 () Bool (and s24 s53))
+[GOOD] (define-fun s55 () Bool (and s22 s54))
+[GOOD] (define-fun s56 () Bool (and s20 s55))
+[GOOD] (define-fun s57 () Bool (and s18 s56))
+[GOOD] (define-fun s58 () Bool (and s16 s57))
+[GOOD] (define-fun s59 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s60 () String (getVar_1 s0))
+[GOOD] (define-fun s62 () Bool (= s60 s61))
+[GOOD] (define-fun s63 () Bool (and s59 s62))
+[GOOD] (define-fun s66 () Bool (= s60 s65))
+[GOOD] (define-fun s68 () Bool (= s60 s67))
+[GOOD] (define-fun s69 () Bool (or s66 s68))
+[GOOD] (define-fun s70 () Bool (and s59 s69))
+[GOOD] (define-fun s73 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s74 () Int (getVal_1 s0))
+[GOOD] (define-fun s76 () Bool (< s74 s75))
+[GOOD] (define-fun s77 () Bool (and s73 s76))
+[GOOD] (define-fun s79 () Bool (= s74 s75))
+[GOOD] (define-fun s80 () Bool (and s73 s79))
+[GOOD] (define-fun s82 () Bool (> s74 s75))
+[GOOD] (define-fun s83 () Bool (and s73 s82))
+[GOOD] (define-fun s86 () Int (ite s83 s84 s85))
+[GOOD] (define-fun s87 () Int (ite s80 s81 s86))
+[GOOD] (define-fun s88 () Int (ite s77 s78 s87))
+[GOOD] (define-fun s89 () Int (ite s59 s72 s88))
+[GOOD] (define-fun s90 () Int (ite s70 s71 s89))
+[GOOD] (define-fun s91 () Int (ite s63 s64 s90))
+[GOOD] (define-fun s92 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s93 () String (getVar_1 s1))
+[GOOD] (define-fun s94 () Bool (= s61 s93))
+[GOOD] (define-fun s95 () Bool (and s92 s94))
+[GOOD] (define-fun s96 () Bool (= s65 s93))
+[GOOD] (define-fun s97 () Bool (= s67 s93))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (and s92 s98))
+[GOOD] (define-fun s100 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s101 () Int (getVal_1 s1))
+[GOOD] (define-fun s102 () Bool (< s101 s75))
+[GOOD] (define-fun s103 () Bool (and s100 s102))
+[GOOD] (define-fun s104 () Bool (= s75 s101))
+[GOOD] (define-fun s105 () Bool (and s100 s104))
+[GOOD] (define-fun s106 () Bool (> s101 s75))
+[GOOD] (define-fun s107 () Bool (and s100 s106))
+[GOOD] (define-fun s108 () Int (ite s107 s84 s85))
+[GOOD] (define-fun s109 () Int (ite s105 s81 s108))
+[GOOD] (define-fun s110 () Int (ite s103 s78 s109))
+[GOOD] (define-fun s111 () Int (ite s92 s72 s110))
+[GOOD] (define-fun s112 () Int (ite s99 s71 s111))
+[GOOD] (define-fun s113 () Int (ite s95 s64 s112))
+[GOOD] (define-fun s114 () Int (+ s91 s113))
+[GOOD] (define-fun s115 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s116 () String (getVar_1 s2))
+[GOOD] (define-fun s117 () Bool (= s61 s116))
+[GOOD] (define-fun s118 () Bool (and s115 s117))
+[GOOD] (define-fun s119 () Bool (= s65 s116))
+[GOOD] (define-fun s120 () Bool (= s67 s116))
+[GOOD] (define-fun s121 () Bool (or s119 s120))
+[GOOD] (define-fun s122 () Bool (and s115 s121))
+[GOOD] (define-fun s123 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s124 () Int (getVal_1 s2))
+[GOOD] (define-fun s125 () Bool (< s124 s75))
+[GOOD] (define-fun s126 () Bool (and s123 s125))
+[GOOD] (define-fun s127 () Bool (= s75 s124))
+[GOOD] (define-fun s128 () Bool (and s123 s127))
+[GOOD] (define-fun s129 () Bool (> s124 s75))
+[GOOD] (define-fun s130 () Bool (and s123 s129))
+[GOOD] (define-fun s131 () Int (ite s130 s84 s85))
+[GOOD] (define-fun s132 () Int (ite s128 s81 s131))
+[GOOD] (define-fun s133 () Int (ite s126 s78 s132))
+[GOOD] (define-fun s134 () Int (ite s115 s72 s133))
+[GOOD] (define-fun s135 () Int (ite s122 s71 s134))
+[GOOD] (define-fun s136 () Int (ite s118 s64 s135))
+[GOOD] (define-fun s137 () Int (+ s114 s136))
+[GOOD] (define-fun s138 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s139 () String (getVar_1 s3))
+[GOOD] (define-fun s140 () Bool (= s61 s139))
+[GOOD] (define-fun s141 () Bool (and s138 s140))
+[GOOD] (define-fun s142 () Bool (= s65 s139))
+[GOOD] (define-fun s143 () Bool (= s67 s139))
+[GOOD] (define-fun s144 () Bool (or s142 s143))
+[GOOD] (define-fun s145 () Bool (and s138 s144))
+[GOOD] (define-fun s146 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s147 () Int (getVal_1 s3))
+[GOOD] (define-fun s148 () Bool (< s147 s75))
+[GOOD] (define-fun s149 () Bool (and s146 s148))
+[GOOD] (define-fun s150 () Bool (= s75 s147))
+[GOOD] (define-fun s151 () Bool (and s146 s150))
+[GOOD] (define-fun s152 () Bool (> s147 s75))
+[GOOD] (define-fun s153 () Bool (and s146 s152))
+[GOOD] (define-fun s154 () Int (ite s153 s84 s85))
+[GOOD] (define-fun s155 () Int (ite s151 s81 s154))
+[GOOD] (define-fun s156 () Int (ite s149 s78 s155))
+[GOOD] (define-fun s157 () Int (ite s138 s72 s156))
+[GOOD] (define-fun s158 () Int (ite s145 s71 s157))
+[GOOD] (define-fun s159 () Int (ite s141 s64 s158))
+[GOOD] (define-fun s160 () Int (+ s137 s159))
+[GOOD] (define-fun s161 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s162 () String (getVar_1 s4))
+[GOOD] (define-fun s163 () Bool (= s61 s162))
+[GOOD] (define-fun s164 () Bool (and s161 s163))
+[GOOD] (define-fun s165 () Bool (= s65 s162))
+[GOOD] (define-fun s166 () Bool (= s67 s162))
+[GOOD] (define-fun s167 () Bool (or s165 s166))
+[GOOD] (define-fun s168 () Bool (and s161 s167))
+[GOOD] (define-fun s169 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s170 () Int (getVal_1 s4))
+[GOOD] (define-fun s171 () Bool (< s170 s75))
+[GOOD] (define-fun s172 () Bool (and s169 s171))
+[GOOD] (define-fun s173 () Bool (= s75 s170))
+[GOOD] (define-fun s174 () Bool (and s169 s173))
+[GOOD] (define-fun s175 () Bool (> s170 s75))
+[GOOD] (define-fun s176 () Bool (and s169 s175))
+[GOOD] (define-fun s177 () Int (ite s176 s84 s85))
+[GOOD] (define-fun s178 () Int (ite s174 s81 s177))
+[GOOD] (define-fun s179 () Int (ite s172 s78 s178))
+[GOOD] (define-fun s180 () Int (ite s161 s72 s179))
+[GOOD] (define-fun s181 () Int (ite s168 s71 s180))
+[GOOD] (define-fun s182 () Int (ite s164 s64 s181))
+[GOOD] (define-fun s183 () Int (+ s160 s182))
+[GOOD] (define-fun s184 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s185 () String (getVar_1 s5))
+[GOOD] (define-fun s186 () Bool (= s61 s185))
+[GOOD] (define-fun s187 () Bool (and s184 s186))
+[GOOD] (define-fun s188 () Bool (= s65 s185))
+[GOOD] (define-fun s189 () Bool (= s67 s185))
+[GOOD] (define-fun s190 () Bool (or s188 s189))
+[GOOD] (define-fun s191 () Bool (and s184 s190))
+[GOOD] (define-fun s192 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s193 () Int (getVal_1 s5))
+[GOOD] (define-fun s194 () Bool (< s193 s75))
+[GOOD] (define-fun s195 () Bool (and s192 s194))
+[GOOD] (define-fun s196 () Bool (= s75 s193))
+[GOOD] (define-fun s197 () Bool (and s192 s196))
+[GOOD] (define-fun s198 () Bool (> s193 s75))
+[GOOD] (define-fun s199 () Bool (and s192 s198))
+[GOOD] (define-fun s200 () Int (ite s199 s84 s85))
+[GOOD] (define-fun s201 () Int (ite s197 s81 s200))
+[GOOD] (define-fun s202 () Int (ite s195 s78 s201))
+[GOOD] (define-fun s203 () Int (ite s184 s72 s202))
+[GOOD] (define-fun s204 () Int (ite s191 s71 s203))
+[GOOD] (define-fun s205 () Int (ite s187 s64 s204))
+[GOOD] (define-fun s206 () Int (+ s183 s205))
+[GOOD] (define-fun s207 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s208 () String (getVar_1 s6))
+[GOOD] (define-fun s209 () Bool (= s61 s208))
+[GOOD] (define-fun s210 () Bool (and s207 s209))
+[GOOD] (define-fun s211 () Bool (= s65 s208))
+[GOOD] (define-fun s212 () Bool (= s67 s208))
+[GOOD] (define-fun s213 () Bool (or s211 s212))
+[GOOD] (define-fun s214 () Bool (and s207 s213))
+[GOOD] (define-fun s215 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s216 () Int (getVal_1 s6))
+[GOOD] (define-fun s217 () Bool (< s216 s75))
+[GOOD] (define-fun s218 () Bool (and s215 s217))
+[GOOD] (define-fun s219 () Bool (= s75 s216))
+[GOOD] (define-fun s220 () Bool (and s215 s219))
+[GOOD] (define-fun s221 () Bool (> s216 s75))
+[GOOD] (define-fun s222 () Bool (and s215 s221))
+[GOOD] (define-fun s223 () Int (ite s222 s84 s85))
+[GOOD] (define-fun s224 () Int (ite s220 s81 s223))
+[GOOD] (define-fun s225 () Int (ite s218 s78 s224))
+[GOOD] (define-fun s226 () Int (ite s207 s72 s225))
+[GOOD] (define-fun s227 () Int (ite s214 s71 s226))
+[GOOD] (define-fun s228 () Int (ite s210 s64 s227))
+[GOOD] (define-fun s229 () Int (+ s206 s228))
+[GOOD] (define-fun s230 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s231 () String (getVar_1 s7))
+[GOOD] (define-fun s232 () Bool (= s61 s231))
+[GOOD] (define-fun s233 () Bool (and s230 s232))
+[GOOD] (define-fun s234 () Bool (= s65 s231))
+[GOOD] (define-fun s235 () Bool (= s67 s231))
+[GOOD] (define-fun s236 () Bool (or s234 s235))
+[GOOD] (define-fun s237 () Bool (and s230 s236))
+[GOOD] (define-fun s238 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s239 () Int (getVal_1 s7))
+[GOOD] (define-fun s240 () Bool (< s239 s75))
+[GOOD] (define-fun s241 () Bool (and s238 s240))
+[GOOD] (define-fun s242 () Bool (= s75 s239))
+[GOOD] (define-fun s243 () Bool (and s238 s242))
+[GOOD] (define-fun s244 () Bool (> s239 s75))
+[GOOD] (define-fun s245 () Bool (and s238 s244))
+[GOOD] (define-fun s246 () Int (ite s245 s84 s85))
+[GOOD] (define-fun s247 () Int (ite s243 s81 s246))
+[GOOD] (define-fun s248 () Int (ite s241 s78 s247))
+[GOOD] (define-fun s249 () Int (ite s230 s72 s248))
+[GOOD] (define-fun s250 () Int (ite s237 s71 s249))
+[GOOD] (define-fun s251 () Int (ite s233 s64 s250))
+[GOOD] (define-fun s252 () Int (+ s229 s251))
+[GOOD] (define-fun s253 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s254 () String (getVar_1 s8))
+[GOOD] (define-fun s255 () Bool (= s61 s254))
+[GOOD] (define-fun s256 () Bool (and s253 s255))
+[GOOD] (define-fun s257 () Bool (= s65 s254))
+[GOOD] (define-fun s258 () Bool (= s67 s254))
+[GOOD] (define-fun s259 () Bool (or s257 s258))
+[GOOD] (define-fun s260 () Bool (and s253 s259))
+[GOOD] (define-fun s261 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s262 () Int (getVal_1 s8))
+[GOOD] (define-fun s263 () Bool (< s262 s75))
+[GOOD] (define-fun s264 () Bool (and s261 s263))
+[GOOD] (define-fun s265 () Bool (= s75 s262))
+[GOOD] (define-fun s266 () Bool (and s261 s265))
+[GOOD] (define-fun s267 () Bool (> s262 s75))
+[GOOD] (define-fun s268 () Bool (and s261 s267))
+[GOOD] (define-fun s269 () Int (ite s268 s84 s85))
+[GOOD] (define-fun s270 () Int (ite s266 s81 s269))
+[GOOD] (define-fun s271 () Int (ite s264 s78 s270))
+[GOOD] (define-fun s272 () Int (ite s253 s72 s271))
+[GOOD] (define-fun s273 () Int (ite s260 s71 s272))
+[GOOD] (define-fun s274 () Int (ite s256 s64 s273))
+[GOOD] (define-fun s275 () Int (+ s252 s274))
+[GOOD] (define-fun s276 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s277 () String (getVar_1 s9))
+[GOOD] (define-fun s278 () Bool (= s61 s277))
+[GOOD] (define-fun s279 () Bool (and s276 s278))
+[GOOD] (define-fun s280 () Bool (= s65 s277))
+[GOOD] (define-fun s281 () Bool (= s67 s277))
+[GOOD] (define-fun s282 () Bool (or s280 s281))
+[GOOD] (define-fun s283 () Bool (and s276 s282))
+[GOOD] (define-fun s284 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s285 () Int (getVal_1 s9))
+[GOOD] (define-fun s286 () Bool (< s285 s75))
+[GOOD] (define-fun s287 () Bool (and s284 s286))
+[GOOD] (define-fun s288 () Bool (= s75 s285))
+[GOOD] (define-fun s289 () Bool (and s284 s288))
+[GOOD] (define-fun s290 () Bool (> s285 s75))
+[GOOD] (define-fun s291 () Bool (and s284 s290))
+[GOOD] (define-fun s292 () Int (ite s291 s84 s85))
+[GOOD] (define-fun s293 () Int (ite s289 s81 s292))
+[GOOD] (define-fun s294 () Int (ite s287 s78 s293))
+[GOOD] (define-fun s295 () Int (ite s276 s72 s294))
+[GOOD] (define-fun s296 () Int (ite s283 s71 s295))
+[GOOD] (define-fun s297 () Int (ite s279 s64 s296))
+[GOOD] (define-fun s298 () Int (+ s275 s297))
+[GOOD] (define-fun s299 () Bool ((as is-Var Bool) s10))
+[GOOD] (define-fun s300 () String (getVar_1 s10))
+[GOOD] (define-fun s301 () Bool (= s61 s300))
+[GOOD] (define-fun s302 () Bool (and s299 s301))
+[GOOD] (define-fun s303 () Bool (= s65 s300))
+[GOOD] (define-fun s304 () Bool (= s67 s300))
+[GOOD] (define-fun s305 () Bool (or s303 s304))
+[GOOD] (define-fun s306 () Bool (and s299 s305))
+[GOOD] (define-fun s307 () Bool ((as is-Val Bool) s10))
+[GOOD] (define-fun s308 () Int (getVal_1 s10))
+[GOOD] (define-fun s309 () Bool (< s308 s75))
+[GOOD] (define-fun s310 () Bool (and s307 s309))
+[GOOD] (define-fun s311 () Bool (= s75 s308))
+[GOOD] (define-fun s312 () Bool (and s307 s311))
+[GOOD] (define-fun s313 () Bool (> s308 s75))
+[GOOD] (define-fun s314 () Bool (and s307 s313))
+[GOOD] (define-fun s315 () Int (ite s314 s84 s85))
+[GOOD] (define-fun s316 () Int (ite s312 s81 s315))
+[GOOD] (define-fun s317 () Int (ite s310 s78 s316))
+[GOOD] (define-fun s318 () Int (ite s299 s72 s317))
+[GOOD] (define-fun s319 () Int (ite s306 s71 s318))
+[GOOD] (define-fun s320 () Int (ite s302 s64 s319))
+[GOOD] (define-fun s321 () Int (+ s298 s320))
+[GOOD] (define-fun s322 () Bool ((as is-Var Bool) s11))
+[GOOD] (define-fun s323 () String (getVar_1 s11))
+[GOOD] (define-fun s324 () Bool (= s61 s323))
+[GOOD] (define-fun s325 () Bool (and s322 s324))
+[GOOD] (define-fun s326 () Bool (= s65 s323))
+[GOOD] (define-fun s327 () Bool (= s67 s323))
+[GOOD] (define-fun s328 () Bool (or s326 s327))
+[GOOD] (define-fun s329 () Bool (and s322 s328))
+[GOOD] (define-fun s330 () Bool ((as is-Val Bool) s11))
+[GOOD] (define-fun s331 () Int (getVal_1 s11))
+[GOOD] (define-fun s332 () Bool (< s331 s75))
+[GOOD] (define-fun s333 () Bool (and s330 s332))
+[GOOD] (define-fun s334 () Bool (= s75 s331))
+[GOOD] (define-fun s335 () Bool (and s330 s334))
+[GOOD] (define-fun s336 () Bool (> s331 s75))
+[GOOD] (define-fun s337 () Bool (and s330 s336))
+[GOOD] (define-fun s338 () Int (ite s337 s84 s85))
+[GOOD] (define-fun s339 () Int (ite s335 s81 s338))
+[GOOD] (define-fun s340 () Int (ite s333 s78 s339))
+[GOOD] (define-fun s341 () Int (ite s322 s72 s340))
+[GOOD] (define-fun s342 () Int (ite s329 s71 s341))
+[GOOD] (define-fun s343 () Int (ite s325 s64 s342))
+[GOOD] (define-fun s344 () Int (+ s321 s343))
+[GOOD] (define-fun s345 () Bool ((as is-Var Bool) s12))
+[GOOD] (define-fun s346 () String (getVar_1 s12))
+[GOOD] (define-fun s347 () Bool (= s61 s346))
+[GOOD] (define-fun s348 () Bool (and s345 s347))
+[GOOD] (define-fun s349 () Bool (= s65 s346))
+[GOOD] (define-fun s350 () Bool (= s67 s346))
+[GOOD] (define-fun s351 () Bool (or s349 s350))
+[GOOD] (define-fun s352 () Bool (and s345 s351))
+[GOOD] (define-fun s353 () Bool ((as is-Val Bool) s12))
+[GOOD] (define-fun s354 () Int (getVal_1 s12))
+[GOOD] (define-fun s355 () Bool (< s354 s75))
+[GOOD] (define-fun s356 () Bool (and s353 s355))
+[GOOD] (define-fun s357 () Bool (= s75 s354))
+[GOOD] (define-fun s358 () Bool (and s353 s357))
+[GOOD] (define-fun s359 () Bool (> s354 s75))
+[GOOD] (define-fun s360 () Bool (and s353 s359))
+[GOOD] (define-fun s361 () Int (ite s360 s84 s85))
+[GOOD] (define-fun s362 () Int (ite s358 s81 s361))
+[GOOD] (define-fun s363 () Int (ite s356 s78 s362))
+[GOOD] (define-fun s364 () Int (ite s345 s72 s363))
+[GOOD] (define-fun s365 () Int (ite s352 s71 s364))
+[GOOD] (define-fun s366 () Int (ite s348 s64 s365))
+[GOOD] (define-fun s367 () Int (+ s344 s366))
+[GOOD] (define-fun s368 () Bool ((as is-Var Bool) s13))
+[GOOD] (define-fun s369 () String (getVar_1 s13))
+[GOOD] (define-fun s370 () Bool (= s61 s369))
+[GOOD] (define-fun s371 () Bool (and s368 s370))
+[GOOD] (define-fun s372 () Bool (= s65 s369))
+[GOOD] (define-fun s373 () Bool (= s67 s369))
+[GOOD] (define-fun s374 () Bool (or s372 s373))
+[GOOD] (define-fun s375 () Bool (and s368 s374))
+[GOOD] (define-fun s376 () Bool ((as is-Val Bool) s13))
+[GOOD] (define-fun s377 () Int (getVal_1 s13))
+[GOOD] (define-fun s378 () Bool (< s377 s75))
+[GOOD] (define-fun s379 () Bool (and s376 s378))
+[GOOD] (define-fun s380 () Bool (= s75 s377))
+[GOOD] (define-fun s381 () Bool (and s376 s380))
+[GOOD] (define-fun s382 () Bool (> s377 s75))
+[GOOD] (define-fun s383 () Bool (and s376 s382))
+[GOOD] (define-fun s384 () Int (ite s383 s84 s85))
+[GOOD] (define-fun s385 () Int (ite s381 s81 s384))
+[GOOD] (define-fun s386 () Int (ite s379 s78 s385))
+[GOOD] (define-fun s387 () Int (ite s368 s72 s386))
+[GOOD] (define-fun s388 () Int (ite s375 s71 s387))
+[GOOD] (define-fun s389 () Int (ite s371 s64 s388))
+[GOOD] (define-fun s390 () Int (+ s367 s389))
+[GOOD] (define-fun s391 () Bool ((as is-Var Bool) s14))
+[GOOD] (define-fun s392 () String (getVar_1 s14))
+[GOOD] (define-fun s393 () Bool (= s61 s392))
+[GOOD] (define-fun s394 () Bool (and s391 s393))
+[GOOD] (define-fun s395 () Bool (= s65 s392))
+[GOOD] (define-fun s396 () Bool (= s67 s392))
+[GOOD] (define-fun s397 () Bool (or s395 s396))
+[GOOD] (define-fun s398 () Bool (and s391 s397))
+[GOOD] (define-fun s399 () Bool ((as is-Val Bool) s14))
+[GOOD] (define-fun s400 () Int (getVal_1 s14))
+[GOOD] (define-fun s401 () Bool (< s400 s75))
+[GOOD] (define-fun s402 () Bool (and s399 s401))
+[GOOD] (define-fun s403 () Bool (= s75 s400))
+[GOOD] (define-fun s404 () Bool (and s399 s403))
+[GOOD] (define-fun s405 () Bool (> s400 s75))
+[GOOD] (define-fun s406 () Bool (and s399 s405))
+[GOOD] (define-fun s407 () Int (ite s406 s84 s85))
+[GOOD] (define-fun s408 () Int (ite s404 s81 s407))
+[GOOD] (define-fun s409 () Int (ite s402 s78 s408))
+[GOOD] (define-fun s410 () Int (ite s391 s72 s409))
+[GOOD] (define-fun s411 () Int (ite s398 s71 s410))
+[GOOD] (define-fun s412 () Int (ite s394 s64 s411))
+[GOOD] (define-fun s413 () Int (+ s390 s412))
+[GOOD] (define-fun s415 () Bool (distinct s413 s414))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s58)
+[GOOD] (assert s415)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr10c.gold b/SBVTestSuite/GoldFiles/adt_pexpr10c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr10c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr11.gold b/SBVTestSuite/GoldFiles/adt_pexpr11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr11.gold
@@ -0,0 +1,102 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Expr String Int) ((as Val (Expr String Int)) 10))
+[GOOD] (define-fun s8 () String "a")
+[GOOD] (define-fun s11 () Int 0)
+[GOOD] (define-fun s12 () String "b")
+[GOOD] (define-fun s14 () String "c")
+[GOOD] (define-fun s18 () Int 1)
+[GOOD] (define-fun s19 () Int 2)
+[GOOD] (define-fun s22 () Int 10)
+[GOOD] (define-fun s25 () Int 3)
+[GOOD] (define-fun s28 () Int 4)
+[GOOD] (define-fun s31 () Int 5)
+[GOOD] (define-fun s32 () Int 6)
+[GOOD] (define-fun s62 () Int 8)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () Bool (and s3 s4))
+[GOOD] (define-fun s6 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s7 () String (getVar_1 s0))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s13 () Bool (= s7 s12))
+[GOOD] (define-fun s15 () Bool (= s7 s14))
+[GOOD] (define-fun s16 () Bool (or s13 s15))
+[GOOD] (define-fun s17 () Bool (and s6 s16))
+[GOOD] (define-fun s20 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s21 () Int (getVal_1 s0))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s26 () Bool (= s21 s22))
+[GOOD] (define-fun s27 () Bool (and s20 s26))
+[GOOD] (define-fun s29 () Bool (> s21 s22))
+[GOOD] (define-fun s30 () Bool (and s20 s29))
+[GOOD] (define-fun s33 () Int (ite s30 s31 s32))
+[GOOD] (define-fun s34 () Int (ite s27 s28 s33))
+[GOOD] (define-fun s35 () Int (ite s24 s25 s34))
+[GOOD] (define-fun s36 () Int (ite s6 s19 s35))
+[GOOD] (define-fun s37 () Int (ite s17 s18 s36))
+[GOOD] (define-fun s38 () Int (ite s10 s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s40 () String (getVar_1 s1))
+[GOOD] (define-fun s41 () Bool (= s8 s40))
+[GOOD] (define-fun s42 () Bool (and s39 s41))
+[GOOD] (define-fun s43 () Bool (= s12 s40))
+[GOOD] (define-fun s44 () Bool (= s14 s40))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () Bool (and s39 s45))
+[GOOD] (define-fun s47 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s48 () Int (getVal_1 s1))
+[GOOD] (define-fun s49 () Bool (< s48 s22))
+[GOOD] (define-fun s50 () Bool (and s47 s49))
+[GOOD] (define-fun s51 () Bool (= s22 s48))
+[GOOD] (define-fun s52 () Bool (and s47 s51))
+[GOOD] (define-fun s53 () Bool (> s48 s22))
+[GOOD] (define-fun s54 () Bool (and s47 s53))
+[GOOD] (define-fun s55 () Int (ite s54 s31 s32))
+[GOOD] (define-fun s56 () Int (ite s52 s28 s55))
+[GOOD] (define-fun s57 () Int (ite s50 s25 s56))
+[GOOD] (define-fun s58 () Int (ite s39 s19 s57))
+[GOOD] (define-fun s59 () Int (ite s46 s18 s58))
+[GOOD] (define-fun s60 () Int (ite s42 s11 s59))
+[GOOD] (define-fun s61 () Int (+ s38 s60))
+[GOOD] (define-fun s63 () Bool (distinct s61 s62))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s63)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr11c.gold b/SBVTestSuite/GoldFiles/adt_pexpr11c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr11c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr12.gold b/SBVTestSuite/GoldFiles/adt_pexpr12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr12.gold
@@ -0,0 +1,319 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s10 () (Expr String Int) ((as Val (Expr String Int)) 11))
+[GOOD] (define-fun s12 () (Expr String Int) ((as Val (Expr String Int)) 12))
+[GOOD] (define-fun s14 () (Expr String Int) ((as Val (Expr String Int)) 13))
+[GOOD] (define-fun s16 () (Expr String Int) ((as Val (Expr String Int)) 14))
+[GOOD] (define-fun s18 () (Expr String Int) ((as Val (Expr String Int)) 15))
+[GOOD] (define-fun s20 () (Expr String Int) ((as Val (Expr String Int)) 16))
+[GOOD] (define-fun s22 () (Expr String Int) ((as Val (Expr String Int)) 17))
+[GOOD] (define-fun s24 () (Expr String Int) ((as Val (Expr String Int)) 18))
+[GOOD] (define-fun s26 () (Expr String Int) ((as Val (Expr String Int)) 19))
+[GOOD] (define-fun s28 () (Expr String Int) ((as Val (Expr String Int)) 20))
+[GOOD] (define-fun s41 () String "a")
+[GOOD] (define-fun s44 () Int 0)
+[GOOD] (define-fun s45 () String "b")
+[GOOD] (define-fun s47 () String "c")
+[GOOD] (define-fun s51 () Int 1)
+[GOOD] (define-fun s52 () Int 2)
+[GOOD] (define-fun s55 () Int 10)
+[GOOD] (define-fun s58 () Int 3)
+[GOOD] (define-fun s61 () Int 4)
+[GOOD] (define-fun s64 () Int 5)
+[GOOD] (define-fun s65 () Int 6)
+[GOOD] (define-fun s279 () Int 50)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] (declare-fun s1 () (Expr String Int))
+[GOOD] (declare-fun s2 () (Expr String Int))
+[GOOD] (declare-fun s3 () (Expr String Int))
+[GOOD] (declare-fun s4 () (Expr String Int))
+[GOOD] (declare-fun s5 () (Expr String Int))
+[GOOD] (declare-fun s6 () (Expr String Int))
+[GOOD] (declare-fun s7 () (Expr String Int))
+[GOOD] (declare-fun s8 () (Expr String Int))
+[GOOD] (declare-fun s9 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s13 () Bool (= s1 s12))
+[GOOD] (define-fun s15 () Bool (= s2 s14))
+[GOOD] (define-fun s17 () Bool (= s3 s16))
+[GOOD] (define-fun s19 () Bool (= s4 s18))
+[GOOD] (define-fun s21 () Bool (= s5 s20))
+[GOOD] (define-fun s23 () Bool (= s6 s22))
+[GOOD] (define-fun s25 () Bool (= s7 s24))
+[GOOD] (define-fun s27 () Bool (= s8 s26))
+[GOOD] (define-fun s29 () Bool (= s9 s28))
+[GOOD] (define-fun s30 () Bool (and s27 s29))
+[GOOD] (define-fun s31 () Bool (and s25 s30))
+[GOOD] (define-fun s32 () Bool (and s23 s31))
+[GOOD] (define-fun s33 () Bool (and s21 s32))
+[GOOD] (define-fun s34 () Bool (and s19 s33))
+[GOOD] (define-fun s35 () Bool (and s17 s34))
+[GOOD] (define-fun s36 () Bool (and s15 s35))
+[GOOD] (define-fun s37 () Bool (and s13 s36))
+[GOOD] (define-fun s38 () Bool (and s11 s37))
+[GOOD] (define-fun s39 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s40 () String (getVar_1 s0))
+[GOOD] (define-fun s42 () Bool (= s40 s41))
+[GOOD] (define-fun s43 () Bool (and s39 s42))
+[GOOD] (define-fun s46 () Bool (= s40 s45))
+[GOOD] (define-fun s48 () Bool (= s40 s47))
+[GOOD] (define-fun s49 () Bool (or s46 s48))
+[GOOD] (define-fun s50 () Bool (and s39 s49))
+[GOOD] (define-fun s53 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s54 () Int (getVal_1 s0))
+[GOOD] (define-fun s56 () Bool (< s54 s55))
+[GOOD] (define-fun s57 () Bool (and s53 s56))
+[GOOD] (define-fun s59 () Bool (= s54 s55))
+[GOOD] (define-fun s60 () Bool (and s53 s59))
+[GOOD] (define-fun s62 () Bool (> s54 s55))
+[GOOD] (define-fun s63 () Bool (and s53 s62))
+[GOOD] (define-fun s66 () Int (ite s63 s64 s65))
+[GOOD] (define-fun s67 () Int (ite s60 s61 s66))
+[GOOD] (define-fun s68 () Int (ite s57 s58 s67))
+[GOOD] (define-fun s69 () Int (ite s39 s52 s68))
+[GOOD] (define-fun s70 () Int (ite s50 s51 s69))
+[GOOD] (define-fun s71 () Int (ite s43 s44 s70))
+[GOOD] (define-fun s72 () Bool ((as is-Var Bool) s1))
+[GOOD] (define-fun s73 () String (getVar_1 s1))
+[GOOD] (define-fun s74 () Bool (= s41 s73))
+[GOOD] (define-fun s75 () Bool (and s72 s74))
+[GOOD] (define-fun s76 () Bool (= s45 s73))
+[GOOD] (define-fun s77 () Bool (= s47 s73))
+[GOOD] (define-fun s78 () Bool (or s76 s77))
+[GOOD] (define-fun s79 () Bool (and s72 s78))
+[GOOD] (define-fun s80 () Bool ((as is-Val Bool) s1))
+[GOOD] (define-fun s81 () Int (getVal_1 s1))
+[GOOD] (define-fun s82 () Bool (< s81 s55))
+[GOOD] (define-fun s83 () Bool (and s80 s82))
+[GOOD] (define-fun s84 () Bool (= s55 s81))
+[GOOD] (define-fun s85 () Bool (and s80 s84))
+[GOOD] (define-fun s86 () Bool (> s81 s55))
+[GOOD] (define-fun s87 () Bool (and s80 s86))
+[GOOD] (define-fun s88 () Int (ite s87 s64 s65))
+[GOOD] (define-fun s89 () Int (ite s85 s61 s88))
+[GOOD] (define-fun s90 () Int (ite s83 s58 s89))
+[GOOD] (define-fun s91 () Int (ite s72 s52 s90))
+[GOOD] (define-fun s92 () Int (ite s79 s51 s91))
+[GOOD] (define-fun s93 () Int (ite s75 s44 s92))
+[GOOD] (define-fun s94 () Int (+ s71 s93))
+[GOOD] (define-fun s95 () Bool ((as is-Var Bool) s2))
+[GOOD] (define-fun s96 () String (getVar_1 s2))
+[GOOD] (define-fun s97 () Bool (= s41 s96))
+[GOOD] (define-fun s98 () Bool (and s95 s97))
+[GOOD] (define-fun s99 () Bool (= s45 s96))
+[GOOD] (define-fun s100 () Bool (= s47 s96))
+[GOOD] (define-fun s101 () Bool (or s99 s100))
+[GOOD] (define-fun s102 () Bool (and s95 s101))
+[GOOD] (define-fun s103 () Bool ((as is-Val Bool) s2))
+[GOOD] (define-fun s104 () Int (getVal_1 s2))
+[GOOD] (define-fun s105 () Bool (< s104 s55))
+[GOOD] (define-fun s106 () Bool (and s103 s105))
+[GOOD] (define-fun s107 () Bool (= s55 s104))
+[GOOD] (define-fun s108 () Bool (and s103 s107))
+[GOOD] (define-fun s109 () Bool (> s104 s55))
+[GOOD] (define-fun s110 () Bool (and s103 s109))
+[GOOD] (define-fun s111 () Int (ite s110 s64 s65))
+[GOOD] (define-fun s112 () Int (ite s108 s61 s111))
+[GOOD] (define-fun s113 () Int (ite s106 s58 s112))
+[GOOD] (define-fun s114 () Int (ite s95 s52 s113))
+[GOOD] (define-fun s115 () Int (ite s102 s51 s114))
+[GOOD] (define-fun s116 () Int (ite s98 s44 s115))
+[GOOD] (define-fun s117 () Int (+ s94 s116))
+[GOOD] (define-fun s118 () Bool ((as is-Var Bool) s3))
+[GOOD] (define-fun s119 () String (getVar_1 s3))
+[GOOD] (define-fun s120 () Bool (= s41 s119))
+[GOOD] (define-fun s121 () Bool (and s118 s120))
+[GOOD] (define-fun s122 () Bool (= s45 s119))
+[GOOD] (define-fun s123 () Bool (= s47 s119))
+[GOOD] (define-fun s124 () Bool (or s122 s123))
+[GOOD] (define-fun s125 () Bool (and s118 s124))
+[GOOD] (define-fun s126 () Bool ((as is-Val Bool) s3))
+[GOOD] (define-fun s127 () Int (getVal_1 s3))
+[GOOD] (define-fun s128 () Bool (< s127 s55))
+[GOOD] (define-fun s129 () Bool (and s126 s128))
+[GOOD] (define-fun s130 () Bool (= s55 s127))
+[GOOD] (define-fun s131 () Bool (and s126 s130))
+[GOOD] (define-fun s132 () Bool (> s127 s55))
+[GOOD] (define-fun s133 () Bool (and s126 s132))
+[GOOD] (define-fun s134 () Int (ite s133 s64 s65))
+[GOOD] (define-fun s135 () Int (ite s131 s61 s134))
+[GOOD] (define-fun s136 () Int (ite s129 s58 s135))
+[GOOD] (define-fun s137 () Int (ite s118 s52 s136))
+[GOOD] (define-fun s138 () Int (ite s125 s51 s137))
+[GOOD] (define-fun s139 () Int (ite s121 s44 s138))
+[GOOD] (define-fun s140 () Int (+ s117 s139))
+[GOOD] (define-fun s141 () Bool ((as is-Var Bool) s4))
+[GOOD] (define-fun s142 () String (getVar_1 s4))
+[GOOD] (define-fun s143 () Bool (= s41 s142))
+[GOOD] (define-fun s144 () Bool (and s141 s143))
+[GOOD] (define-fun s145 () Bool (= s45 s142))
+[GOOD] (define-fun s146 () Bool (= s47 s142))
+[GOOD] (define-fun s147 () Bool (or s145 s146))
+[GOOD] (define-fun s148 () Bool (and s141 s147))
+[GOOD] (define-fun s149 () Bool ((as is-Val Bool) s4))
+[GOOD] (define-fun s150 () Int (getVal_1 s4))
+[GOOD] (define-fun s151 () Bool (< s150 s55))
+[GOOD] (define-fun s152 () Bool (and s149 s151))
+[GOOD] (define-fun s153 () Bool (= s55 s150))
+[GOOD] (define-fun s154 () Bool (and s149 s153))
+[GOOD] (define-fun s155 () Bool (> s150 s55))
+[GOOD] (define-fun s156 () Bool (and s149 s155))
+[GOOD] (define-fun s157 () Int (ite s156 s64 s65))
+[GOOD] (define-fun s158 () Int (ite s154 s61 s157))
+[GOOD] (define-fun s159 () Int (ite s152 s58 s158))
+[GOOD] (define-fun s160 () Int (ite s141 s52 s159))
+[GOOD] (define-fun s161 () Int (ite s148 s51 s160))
+[GOOD] (define-fun s162 () Int (ite s144 s44 s161))
+[GOOD] (define-fun s163 () Int (+ s140 s162))
+[GOOD] (define-fun s164 () Bool ((as is-Var Bool) s5))
+[GOOD] (define-fun s165 () String (getVar_1 s5))
+[GOOD] (define-fun s166 () Bool (= s41 s165))
+[GOOD] (define-fun s167 () Bool (and s164 s166))
+[GOOD] (define-fun s168 () Bool (= s45 s165))
+[GOOD] (define-fun s169 () Bool (= s47 s165))
+[GOOD] (define-fun s170 () Bool (or s168 s169))
+[GOOD] (define-fun s171 () Bool (and s164 s170))
+[GOOD] (define-fun s172 () Bool ((as is-Val Bool) s5))
+[GOOD] (define-fun s173 () Int (getVal_1 s5))
+[GOOD] (define-fun s174 () Bool (< s173 s55))
+[GOOD] (define-fun s175 () Bool (and s172 s174))
+[GOOD] (define-fun s176 () Bool (= s55 s173))
+[GOOD] (define-fun s177 () Bool (and s172 s176))
+[GOOD] (define-fun s178 () Bool (> s173 s55))
+[GOOD] (define-fun s179 () Bool (and s172 s178))
+[GOOD] (define-fun s180 () Int (ite s179 s64 s65))
+[GOOD] (define-fun s181 () Int (ite s177 s61 s180))
+[GOOD] (define-fun s182 () Int (ite s175 s58 s181))
+[GOOD] (define-fun s183 () Int (ite s164 s52 s182))
+[GOOD] (define-fun s184 () Int (ite s171 s51 s183))
+[GOOD] (define-fun s185 () Int (ite s167 s44 s184))
+[GOOD] (define-fun s186 () Int (+ s163 s185))
+[GOOD] (define-fun s187 () Bool ((as is-Var Bool) s6))
+[GOOD] (define-fun s188 () String (getVar_1 s6))
+[GOOD] (define-fun s189 () Bool (= s41 s188))
+[GOOD] (define-fun s190 () Bool (and s187 s189))
+[GOOD] (define-fun s191 () Bool (= s45 s188))
+[GOOD] (define-fun s192 () Bool (= s47 s188))
+[GOOD] (define-fun s193 () Bool (or s191 s192))
+[GOOD] (define-fun s194 () Bool (and s187 s193))
+[GOOD] (define-fun s195 () Bool ((as is-Val Bool) s6))
+[GOOD] (define-fun s196 () Int (getVal_1 s6))
+[GOOD] (define-fun s197 () Bool (< s196 s55))
+[GOOD] (define-fun s198 () Bool (and s195 s197))
+[GOOD] (define-fun s199 () Bool (= s55 s196))
+[GOOD] (define-fun s200 () Bool (and s195 s199))
+[GOOD] (define-fun s201 () Bool (> s196 s55))
+[GOOD] (define-fun s202 () Bool (and s195 s201))
+[GOOD] (define-fun s203 () Int (ite s202 s64 s65))
+[GOOD] (define-fun s204 () Int (ite s200 s61 s203))
+[GOOD] (define-fun s205 () Int (ite s198 s58 s204))
+[GOOD] (define-fun s206 () Int (ite s187 s52 s205))
+[GOOD] (define-fun s207 () Int (ite s194 s51 s206))
+[GOOD] (define-fun s208 () Int (ite s190 s44 s207))
+[GOOD] (define-fun s209 () Int (+ s186 s208))
+[GOOD] (define-fun s210 () Bool ((as is-Var Bool) s7))
+[GOOD] (define-fun s211 () String (getVar_1 s7))
+[GOOD] (define-fun s212 () Bool (= s41 s211))
+[GOOD] (define-fun s213 () Bool (and s210 s212))
+[GOOD] (define-fun s214 () Bool (= s45 s211))
+[GOOD] (define-fun s215 () Bool (= s47 s211))
+[GOOD] (define-fun s216 () Bool (or s214 s215))
+[GOOD] (define-fun s217 () Bool (and s210 s216))
+[GOOD] (define-fun s218 () Bool ((as is-Val Bool) s7))
+[GOOD] (define-fun s219 () Int (getVal_1 s7))
+[GOOD] (define-fun s220 () Bool (< s219 s55))
+[GOOD] (define-fun s221 () Bool (and s218 s220))
+[GOOD] (define-fun s222 () Bool (= s55 s219))
+[GOOD] (define-fun s223 () Bool (and s218 s222))
+[GOOD] (define-fun s224 () Bool (> s219 s55))
+[GOOD] (define-fun s225 () Bool (and s218 s224))
+[GOOD] (define-fun s226 () Int (ite s225 s64 s65))
+[GOOD] (define-fun s227 () Int (ite s223 s61 s226))
+[GOOD] (define-fun s228 () Int (ite s221 s58 s227))
+[GOOD] (define-fun s229 () Int (ite s210 s52 s228))
+[GOOD] (define-fun s230 () Int (ite s217 s51 s229))
+[GOOD] (define-fun s231 () Int (ite s213 s44 s230))
+[GOOD] (define-fun s232 () Int (+ s209 s231))
+[GOOD] (define-fun s233 () Bool ((as is-Var Bool) s8))
+[GOOD] (define-fun s234 () String (getVar_1 s8))
+[GOOD] (define-fun s235 () Bool (= s41 s234))
+[GOOD] (define-fun s236 () Bool (and s233 s235))
+[GOOD] (define-fun s237 () Bool (= s45 s234))
+[GOOD] (define-fun s238 () Bool (= s47 s234))
+[GOOD] (define-fun s239 () Bool (or s237 s238))
+[GOOD] (define-fun s240 () Bool (and s233 s239))
+[GOOD] (define-fun s241 () Bool ((as is-Val Bool) s8))
+[GOOD] (define-fun s242 () Int (getVal_1 s8))
+[GOOD] (define-fun s243 () Bool (< s242 s55))
+[GOOD] (define-fun s244 () Bool (and s241 s243))
+[GOOD] (define-fun s245 () Bool (= s55 s242))
+[GOOD] (define-fun s246 () Bool (and s241 s245))
+[GOOD] (define-fun s247 () Bool (> s242 s55))
+[GOOD] (define-fun s248 () Bool (and s241 s247))
+[GOOD] (define-fun s249 () Int (ite s248 s64 s65))
+[GOOD] (define-fun s250 () Int (ite s246 s61 s249))
+[GOOD] (define-fun s251 () Int (ite s244 s58 s250))
+[GOOD] (define-fun s252 () Int (ite s233 s52 s251))
+[GOOD] (define-fun s253 () Int (ite s240 s51 s252))
+[GOOD] (define-fun s254 () Int (ite s236 s44 s253))
+[GOOD] (define-fun s255 () Int (+ s232 s254))
+[GOOD] (define-fun s256 () Bool ((as is-Var Bool) s9))
+[GOOD] (define-fun s257 () String (getVar_1 s9))
+[GOOD] (define-fun s258 () Bool (= s41 s257))
+[GOOD] (define-fun s259 () Bool (and s256 s258))
+[GOOD] (define-fun s260 () Bool (= s45 s257))
+[GOOD] (define-fun s261 () Bool (= s47 s257))
+[GOOD] (define-fun s262 () Bool (or s260 s261))
+[GOOD] (define-fun s263 () Bool (and s256 s262))
+[GOOD] (define-fun s264 () Bool ((as is-Val Bool) s9))
+[GOOD] (define-fun s265 () Int (getVal_1 s9))
+[GOOD] (define-fun s266 () Bool (< s265 s55))
+[GOOD] (define-fun s267 () Bool (and s264 s266))
+[GOOD] (define-fun s268 () Bool (= s55 s265))
+[GOOD] (define-fun s269 () Bool (and s264 s268))
+[GOOD] (define-fun s270 () Bool (> s265 s55))
+[GOOD] (define-fun s271 () Bool (and s264 s270))
+[GOOD] (define-fun s272 () Int (ite s271 s64 s65))
+[GOOD] (define-fun s273 () Int (ite s269 s61 s272))
+[GOOD] (define-fun s274 () Int (ite s267 s58 s273))
+[GOOD] (define-fun s275 () Int (ite s256 s52 s274))
+[GOOD] (define-fun s276 () Int (ite s263 s51 s275))
+[GOOD] (define-fun s277 () Int (ite s259 s44 s276))
+[GOOD] (define-fun s278 () Int (+ s255 s277))
+[GOOD] (define-fun s280 () Bool (distinct s278 s279))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s38)
+[GOOD] (assert s280)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr12c.gold b/SBVTestSuite/GoldFiles/adt_pexpr12c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr12c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr13.gold b/SBVTestSuite/GoldFiles/adt_pexpr13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr13.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Val (Expr String Int)) 3))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s22 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr13c.gold b/SBVTestSuite/GoldFiles/adt_pexpr13c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr13c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr14.gold b/SBVTestSuite/GoldFiles/adt_pexpr14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr14.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr14c.gold b/SBVTestSuite/GoldFiles/adt_pexpr14c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr14c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr15.gold b/SBVTestSuite/GoldFiles/adt_pexpr15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr15.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr15c.gold b/SBVTestSuite/GoldFiles/adt_pexpr15c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr15c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr16.gold b/SBVTestSuite/GoldFiles/adt_pexpr16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr16.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr16c.gold b/SBVTestSuite/GoldFiles/adt_pexpr16c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr16c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr17.gold b/SBVTestSuite/GoldFiles/adt_pexpr17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr17.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Add (Expr String Int)) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Let (Expr String Int)) "a" ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr17c.gold b/SBVTestSuite/GoldFiles/adt_pexpr17c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr17c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr18.gold b/SBVTestSuite/GoldFiles/adt_pexpr18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr18.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Expr String Int) ((as Let (Expr String Int)) "a" ((as Add (Expr String Int)) ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Let (Expr String Int)) "a" ((as Let (Expr String Int)) "a" ((as Mul (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4)))) ((as Add (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Add (Expr String Int)) ((as Val (Expr String Int)) 3) ((as Val (Expr String Int)) 4))))) ((as Mul (Expr String Int)) ((as Var (Expr String Int)) "a") ((as Var (Expr String Int)) "a"))))
+[GOOD] (define-fun s5 () String "a")
+[GOOD] (define-fun s8 () Int 0)
+[GOOD] (define-fun s9 () String "b")
+[GOOD] (define-fun s11 () String "c")
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s19 () Int 10)
+[GOOD] (define-fun s22 () Int 3)
+[GOOD] (define-fun s25 () Int 4)
+[GOOD] (define-fun s28 () Int 5)
+[GOOD] (define-fun s29 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s4 () String (getVar_1 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] (define-fun s10 () Bool (= s4 s9))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] (define-fun s13 () Bool (or s10 s12))
+[GOOD] (define-fun s14 () Bool (and s3 s13))
+[GOOD] (define-fun s17 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s18 () Int (getVal_1 s0))
+[GOOD] (define-fun s20 () Bool (< s18 s19))
+[GOOD] (define-fun s21 () Bool (and s17 s20))
+[GOOD] (define-fun s23 () Bool (= s18 s19))
+[GOOD] (define-fun s24 () Bool (and s17 s23))
+[GOOD] (define-fun s26 () Bool (> s18 s19))
+[GOOD] (define-fun s27 () Bool (and s17 s26))
+[GOOD] (define-fun s30 () Int (ite s27 s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s25 s30))
+[GOOD] (define-fun s32 () Int (ite s21 s22 s31))
+[GOOD] (define-fun s33 () Int (ite s3 s16 s32))
+[GOOD] (define-fun s34 () Int (ite s14 s15 s33))
+[GOOD] (define-fun s35 () Int (ite s7 s8 s34))
+[GOOD] (define-fun s36 () Bool (distinct s29 s35))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s36)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr18c.gold b/SBVTestSuite/GoldFiles/adt_pexpr18c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr18c.gold
@@ -0,0 +1,25 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+All good.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr19.gold b/SBVTestSuite/GoldFiles/adt_pexpr19.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr19.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr Int (_ BitVec 8))) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Let Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let 2 (Var 3) (Var 4))))
+Result: (let 2 = 3 in 4)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr20.gold b/SBVTestSuite/GoldFiles/adt_pexpr20.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr20.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr (_ BitVec 8) SBVRational)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Mul Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Var #x00) (Var #x00))))
+Result: (0 * 0)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pexpr21.gold b/SBVTestSuite/GoldFiles/adt_pexpr21.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pexpr21.gold
@@ -0,0 +1,52 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[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] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr (SBVMaybe (SBVTuple2 Int String)) (SBVEither (_ BitVec 8) (_ BitVec 16)))) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Let Bool) s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let nothing_SBVMaybe
+            (Val (right_SBVEither #x0000))
+            (Val (right_SBVEither #x0000)))))
+Result: (let Nothing = Right 0 in Right 0)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen00.gold b/SBVTestSuite/GoldFiles/adt_pgen00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen00.gold
@@ -0,0 +1,277 @@
+[MEASURE] Verifying termination measures for: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer), get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer), valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): barified = "|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|"
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2),("|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)|",2)]
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): recursive calls found = 6
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): trying sbv.dt.size.Expr arg2
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)
+[MEASURE] Checking: get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): barified = "|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|"
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): Uninterpreted ops in DAG: [("|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|",2)]
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): recursive calls found = 1
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 String Int))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "arg1"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () (SBVTuple2 String Int) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () String (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool (and s6 s9))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s12 () Int (- s4 s3))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 String Int)) (seq.extract s0 s3 s12))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Int (ite s5 s2 s15))
+[GOOD] (define-fun s17 () Int (seq.len s13))
+[GOOD] (define-fun s18 () Bool (not s10))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s4 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)
+[MEASURE] Checking: valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): barified = "|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|"
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): Uninterpreted ops in DAG: [("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2),("|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)|",2)]
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): recursive calls found = 6
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): trying sbv.dt.size.Expr arg2
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): sbv.dt.size.Expr arg2 -> OK (structural recursion)
+[MEASURE] valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool): sbv.dt.size.Expr arg2 -> OK
+[MEASURE] Passed (terminating): valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Seq String) (as seq.empty (Seq String)))
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 String Int)) (as seq.empty (Seq (SBVTuple2 String Int))))
+[GOOD] (define-fun s5 () Int 12)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| :: [SString] -> Expr String Integer -> SBool [Recursive]
+[GOOD] (define-fun-rec |valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| ((l1_s0 (Seq String)) (l1_s1 (Expr String Int))) Bool
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s4 (getVar_1 l1_s1)))
+                                 (let ((l1_s5 (str.in_re l1_s4 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s6 (seq.unit l1_s4)))
+                                 (let ((l1_s7 (seq.contains l1_s0 l1_s6)))
+                                 (let ((l1_s8 (and l1_s5 l1_s7)))
+                                 (let ((l1_s9 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s10 (getAdd_1 l1_s1)))
+                                 (let ((l1_s11 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (getAdd_2 l1_s1)))
+                                 (let ((l1_s13 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s0 l1_s12)))
+                                 (let ((l1_s14 (and l1_s11 l1_s13)))
+                                 (let ((l1_s15 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s16 (getMul_1 l1_s1)))
+                                 (let ((l1_s17 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (getMul_2 l1_s1)))
+                                 (let ((l1_s19 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s0 l1_s18)))
+                                 (let ((l1_s20 (and l1_s17 l1_s19)))
+                                 (let ((l1_s21 (getLet_1 l1_s1)))
+                                 (let ((l1_s22 (str.in_re l1_s21 (re.++ (re.range "a" "z") (re.* (re.union (re.range "a" "z") (re.range "A" "Z") (re.range "0" "9")))))))
+                                 (let ((l1_s23 (getLet_2 l1_s1)))
+                                 (let ((l1_s24 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s0 l1_s23)))
+                                 (let ((l1_s25 (seq.unit l1_s21)))
+                                 (let ((l1_s26 (seq.++ l1_s25 l1_s0)))
+                                 (let ((l1_s27 (getLet_3 l1_s1)))
+                                 (let ((l1_s28 (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| l1_s26 l1_s27)))
+                                 (let ((l1_s29 (and l1_s24 l1_s28)))
+                                 (let ((l1_s30 (and l1_s22 l1_s29)))
+                                 (let ((l1_s31 (ite l1_s15 l1_s20 l1_s30)))
+                                 (let ((l1_s32 (ite l1_s9 l1_s14 l1_s31)))
+                                 (let ((l1_s33 (ite l1_s3 l1_s8 l1_s32)))
+                                 (let ((l1_s34 (or l1_s2 l1_s33)))
+                                 l1_s34))))))))))))))))))))))))))))))))))
+[GOOD] ; |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| :: [(SString, SInteger)] -> SString -> SInteger [Recursive]
+[GOOD] (define-fun-rec |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| ((l2_s0 (Seq (SBVTuple2 String Int))) (l2_s1 String)) Int
+                                                 (let ((l2_s3 0))
+                                                 (let ((l2_s11 1))
+                                                 (let ((l2_s2 (seq.len l2_s0)))
+                                                 (let ((l2_s4 (= l2_s2 l2_s3)))
+                                                 (let ((l2_s5 (not l2_s4)))
+                                                 (let ((l2_s6 (seq.nth l2_s0 l2_s3)))
+                                                 (let ((l2_s7 (proj_1_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s8 (= l2_s1 l2_s7)))
+                                                 (let ((l2_s9 (and l2_s5 l2_s8)))
+                                                 (let ((l2_s10 (proj_2_SBVTuple2 l2_s6)))
+                                                 (let ((l2_s12 (- l2_s2 l2_s11)))
+                                                 (let ((l2_s13 (seq.extract l2_s0 l2_s11 l2_s12)))
+                                                 (let ((l2_s14 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l2_s13 l2_s1)))
+                                                 (let ((l2_s15 (ite l2_s9 l2_s10 l2_s14)))
+                                                 (let ((l2_s16 (ite l2_s4 l2_s3 l2_s15)))
+                                                 l2_s16))))))))))))))))
+[GOOD] ; |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| :: [(SString, SInteger)] -> Expr String Integer -> SInteger [Recursive] [Refers to: |get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)|]
+[GOOD] (define-fun-rec |eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| ((l1_s0 (Seq (SBVTuple2 String Int))) (l1_s1 (Expr String Int))) Int
+                                 (let ((l1_s2 ((as is-Val Bool) l1_s1)))
+                                 (let ((l1_s3 (getVal_1 l1_s1)))
+                                 (let ((l1_s4 ((as is-Var Bool) l1_s1)))
+                                 (let ((l1_s5 (getVar_1 l1_s1)))
+                                 (let ((l1_s6 (|get @(SBV [([Char],Integer)] -> SBV [Char] -> SBV Integer)| l1_s0 l1_s5)))
+                                 (let ((l1_s7 ((as is-Add Bool) l1_s1)))
+                                 (let ((l1_s8 (getAdd_1 l1_s1)))
+                                 (let ((l1_s9 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s8)))
+                                 (let ((l1_s10 (getAdd_2 l1_s1)))
+                                 (let ((l1_s11 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s10)))
+                                 (let ((l1_s12 (+ l1_s9 l1_s11)))
+                                 (let ((l1_s13 ((as is-Mul Bool) l1_s1)))
+                                 (let ((l1_s14 (getMul_1 l1_s1)))
+                                 (let ((l1_s15 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s14)))
+                                 (let ((l1_s16 (getMul_2 l1_s1)))
+                                 (let ((l1_s17 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s16)))
+                                 (let ((l1_s18 (* l1_s15 l1_s17)))
+                                 (let ((l1_s19 (getLet_1 l1_s1)))
+                                 (let ((l1_s20 (getLet_2 l1_s1)))
+                                 (let ((l1_s21 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s0 l1_s20)))
+                                 (let ((l1_s22 ((as mkSBVTuple2 (SBVTuple2 String Int)) l1_s19 l1_s21)))
+                                 (let ((l1_s23 (seq.unit l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s23 l1_s0)))
+                                 (let ((l1_s25 (getLet_3 l1_s1)))
+                                 (let ((l1_s26 (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| l1_s24 l1_s25)))
+                                 (let ((l1_s27 (ite l1_s13 l1_s18 l1_s26)))
+                                 (let ((l1_s28 (ite l1_s7 l1_s12 l1_s27)))
+                                 (let ((l1_s29 (ite l1_s4 l1_s6 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s2 l1_s3 l1_s29)))
+                                 l1_s30))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (|valid @(SBV [[Char]] -> SBV (Expr [Char] Integer) -> SBV Bool)| s1 s0))
+[GOOD] (define-fun s4 () Int (|eval @(SBV [([Char],Integer)] -> SBV (Expr [Char] Integer) -> SBV Integer)| s3 s0))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s8 () (Expr String Int) (getLet_3 s0))
+[GOOD] (define-fun s9 () Bool ((as is-Let Bool) s8))
+[GOOD] (define-fun s10 () (Expr String Int) (getLet_3 s8))
+[GOOD] (define-fun s11 () Bool ((as is-Add Bool) s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "t"
+            (Val 4)
+            (Let "l" (Val 7) (Add (Val (- 28281)) (Let "x" (Val 28293) (Var "x")))))))
+
+Got: (let t = 4 in (let l = 7 in (-28281 + (let x = 28293 in x))))
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen01.gold b/SBVTestSuite/GoldFiles/adt_pgen01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen01.gold
@@ -0,0 +1,83 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int (- 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen02.gold b/SBVTestSuite/GoldFiles/adt_pgen02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen02.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s6 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "a")))
+
+Got: a
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen03.gold b/SBVTestSuite/GoldFiles/adt_pgen03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen03.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s13 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "b")))
+
+Got: b
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen04.gold b/SBVTestSuite/GoldFiles/adt_pgen04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen04.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s14 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Var "")))
+
+Got: 
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen05.gold b/SBVTestSuite/GoldFiles/adt_pgen05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen05.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s20 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 0)))
+
+Got: 0
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen06.gold b/SBVTestSuite/GoldFiles/adt_pgen06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen06.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s23 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 10)))
+
+Got: 10
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen07.gold b/SBVTestSuite/GoldFiles/adt_pgen07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen07.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s26 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Val 11)))
+
+Got: 11
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen08.gold b/SBVTestSuite/GoldFiles/adt_pgen08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen08.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s28 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Add (Val 3) (Val 2))))
+
+Got: (3 + 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen09.gold b/SBVTestSuite/GoldFiles/adt_pgen09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen09.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s30 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Mul (Val 3) (Val 2))))
+
+Got: (3 * 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen10.gold b/SBVTestSuite/GoldFiles/adt_pgen10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen10.gold
@@ -0,0 +1,85 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s32 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Let "!0!" (Val 3) (Val 2))))
+
+Got: (let !0! = 3 in 2)
+DONE
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen11.gold b/SBVTestSuite/GoldFiles/adt_pgen11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen11.gold
@@ -0,0 +1,83 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] (define-fun s43 () Int 9)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s44 () Bool (= s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s44)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/adt_pgen12.gold b/SBVTestSuite/GoldFiles/adt_pgen12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/adt_pgen12.gold
@@ -0,0 +1,82 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Expr
+[GOOD] (declare-datatype Expr (par (nm val) (
+           (Val (getVal_1 val))
+           (Var (getVar_1 nm))
+           (Add (getAdd_1 (Expr nm val)) (getAdd_2 (Expr nm val)))
+           (Mul (getMul_1 (Expr nm val)) (getMul_2 (Expr nm val)))
+           (Let (getLet_1 nm) (getLet_2 (Expr nm val)) (getLet_3 (Expr nm val)))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "a")
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () String "b")
+[GOOD] (define-fun s9 () String "c")
+[GOOD] (define-fun s13 () Int 1)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 10)
+[GOOD] (define-fun s20 () Int 3)
+[GOOD] (define-fun s23 () Int 4)
+[GOOD] (define-fun s26 () Int 5)
+[GOOD] (define-fun s28 () Int 6)
+[GOOD] (define-fun s30 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s33 () Int 100)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Expr String Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Var Bool) s0))
+[GOOD] (define-fun s2 () String (getVar_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Bool (= s2 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (and s1 s11))
+[GOOD] (define-fun s15 () Bool ((as is-Val Bool) s0))
+[GOOD] (define-fun s16 () Int (getVal_1 s0))
+[GOOD] (define-fun s18 () Bool (< s16 s17))
+[GOOD] (define-fun s19 () Bool (and s15 s18))
+[GOOD] (define-fun s21 () Bool (= s16 s17))
+[GOOD] (define-fun s22 () Bool (and s15 s21))
+[GOOD] (define-fun s24 () Bool (> s16 s17))
+[GOOD] (define-fun s25 () Bool (and s15 s24))
+[GOOD] (define-fun s27 () Bool ((as is-Add Bool) s0))
+[GOOD] (define-fun s29 () Bool ((as is-Mul Bool) s0))
+[GOOD] (define-fun s31 () Bool ((as is-Let Bool) s0))
+[GOOD] (define-fun s34 () Int (ite s31 s32 s33))
+[GOOD] (define-fun s35 () Int (ite s29 s30 s34))
+[GOOD] (define-fun s36 () Int (ite s27 s28 s35))
+[GOOD] (define-fun s37 () Int (ite s25 s26 s36))
+[GOOD] (define-fun s38 () Int (ite s22 s23 s37))
+[GOOD] (define-fun s39 () Int (ite s19 s20 s38))
+[GOOD] (define-fun s40 () Int (ite s1 s14 s39))
+[GOOD] (define-fun s41 () Int (ite s12 s13 s40))
+[GOOD] (define-fun s42 () Int (ite s5 s6 s41))
+[GOOD] (define-fun s43 () Bool (= s33 s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+
+UNSAT
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/aes128Dec.gold b/SBVTestSuite/GoldFiles/aes128Dec.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/aes128Dec.gold
@@ -0,0 +1,2437 @@
+== BEGIN: "Makefile" ================
+# Makefile for aes128Dec. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: aes128Dec_driver
+
+aes128Dec.o: aes128Dec.c aes128Dec.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128Dec_driver.o: aes128Dec_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128Dec_driver: aes128Dec.o aes128Dec_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f aes128Dec_driver
+== END: "Makefile" ==================
+== BEGIN: "aes128Dec.h" ================
+/* Header file for aes128Dec. Automatically generated by SBV. Do not edit! */
+
+#ifndef __aes128Dec__HEADER_INCLUDED__
+#define __aes128Dec__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void aes128Dec(const SWord32 *pt, const SWord32 *key, SWord32 *ct);
+
+#endif /* __aes128Dec__HEADER_INCLUDED__ */
+== END: "aes128Dec.h" ==================
+== BEGIN: "aes128Dec_driver.c" ================
+/* Example driver program for aes128Dec. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "aes128Dec.h"
+
+int main(void)
+{
+  const SWord32 pt[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array pt:\n");
+  int pt_ctr;
+  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
+    printf("  pt[%1d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
+
+  const SWord32 key[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array key:\n");
+  int key_ctr;
+  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
+    printf("  key[%1d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
+
+  SWord32 ct[4];
+
+  aes128Dec(pt, key, ct);
+
+  printf("aes128Dec(pt, key, ct) ->\n");
+  int ct_ctr;
+  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
+    printf("  ct[%1d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
+
+  return 0;
+}
+== END: "aes128Dec_driver.c" ==================
+== BEGIN: "aes128Dec.c" ================
+/* File: "aes128Dec.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Dec.h"
+
+void aes128Dec(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
+{
+  const SWord32 s0 = pt[0];
+  const SWord32 s1 = pt[1];
+  const SWord32 s2 = pt[2];
+  const SWord32 s3 = pt[3];
+  const SWord32 s4 = key[0];
+  const SWord32 s5 = key[1];
+  const SWord32 s6 = key[2];
+  const SWord32 s7 = key[3];
+  static const SWord8 table0[] = {
+       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129,
+      243, 215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,
+       67,  68, 196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,
+       61, 238,  76, 149,  11,  66, 250, 195,  78,   8,  46, 161, 102,
+       40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 114,
+      248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101,
+      182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,
+       87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10,
+      247, 228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,
+       63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,  58, 145,
+       17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230,
+      115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,
+       28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 111,
+      183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
+      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
+       51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
+       96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147,
+      201, 156, 239, 160, 224,  59,  77, 174,  42, 245, 176, 200, 235,
+      187,  60, 131,  83, 153,  97,  23,  43,   4, 126, 186, 119, 214,
+       38, 225, 105,  20,  99,  85,  33,  12, 125
+  };
+  static const SWord32 table1[] = {
+      0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+      0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+      0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+      0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+      0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+      0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+      0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+      0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+      0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+      0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+      0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+      0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+      0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+      0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+      0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+      0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+      0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+      0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+      0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+      0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+      0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+      0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+      0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+      0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+      0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+      0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+      0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+      0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+      0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+      0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+      0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+      0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+      0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+      0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+      0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+      0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+      0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+      0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+      0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+      0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+      0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+      0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+      0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+      0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+      0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+      0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+      0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+      0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+      0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+      0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+      0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+      0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+      0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+      0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+      0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+      0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+      0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+      0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+      0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+      0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+      0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+      0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+      0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+      0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL
+  };
+  static const SWord8 table2[] = {
+       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
+      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
+      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
+      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
+       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
+      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
+       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
+       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
+       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
+      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
+       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
+      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
+      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
+      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
+       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
+       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
+      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
+      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
+      104,  65, 153,  45,  15, 176,  84, 187,  22
+  };
+  static const SWord32 table3[] = {
+      0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
+      0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
+      0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
+      0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
+      0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
+      0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
+      0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
+      0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
+      0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
+      0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
+      0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
+      0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
+      0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
+      0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
+      0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
+      0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
+      0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
+      0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
+      0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
+      0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
+      0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
+      0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
+      0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
+      0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
+      0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
+      0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
+      0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
+      0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
+      0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
+      0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
+      0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
+      0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
+      0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
+      0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
+      0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
+      0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
+      0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
+      0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
+      0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
+      0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
+      0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
+      0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
+      0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
+      0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
+      0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
+      0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
+      0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
+      0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
+      0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
+      0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
+      0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
+      0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
+      0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
+      0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
+      0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
+      0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
+      0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
+      0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
+      0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
+      0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
+      0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
+      0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
+      0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
+      0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL
+  };
+  static const SWord32 table4[] = {
+      0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
+      0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
+      0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
+      0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
+      0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
+      0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
+      0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
+      0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
+      0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
+      0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
+      0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
+      0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
+      0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
+      0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
+      0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
+      0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
+      0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
+      0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
+      0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
+      0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
+      0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
+      0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
+      0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
+      0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
+      0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
+      0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
+      0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
+      0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
+      0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
+      0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
+      0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
+      0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
+      0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
+      0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
+      0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
+      0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
+      0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
+      0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
+      0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
+      0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
+      0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
+      0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
+      0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
+      0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
+      0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
+      0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
+      0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
+      0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
+      0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
+      0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
+      0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
+      0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
+      0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
+      0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
+      0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
+      0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
+      0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
+      0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
+      0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
+      0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
+      0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
+      0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
+      0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
+      0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL
+  };
+  static const SWord32 table5[] = {
+      0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
+      0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
+      0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
+      0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
+      0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
+      0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
+      0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
+      0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
+      0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
+      0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
+      0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
+      0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
+      0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
+      0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
+      0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
+      0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
+      0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
+      0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
+      0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
+      0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
+      0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
+      0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
+      0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
+      0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
+      0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
+      0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
+      0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
+      0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
+      0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
+      0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
+      0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
+      0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
+      0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
+      0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
+      0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
+      0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
+      0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
+      0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
+      0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
+      0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
+      0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
+      0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
+      0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
+      0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
+      0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
+      0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
+      0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
+      0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
+      0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
+      0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
+      0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
+      0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
+      0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
+      0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
+      0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
+      0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
+      0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
+      0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
+      0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
+      0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
+      0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
+      0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
+      0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
+      0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL
+  };
+  static const SWord8 table6[] = {
+        0,  14,  28,  18,  56,  54,  36,  42, 112, 126, 108,  98,  72,
+       70,  84,  90, 224, 238, 252, 242, 216, 214, 196, 202, 144, 158,
+      140, 130, 168, 166, 180, 186, 219, 213, 199, 201, 227, 237, 255,
+      241, 171, 165, 183, 185, 147, 157, 143, 129,  59,  53,  39,  41,
+        3,  13,  31,  17,  75,  69,  87,  89, 115, 125, 111,  97, 173,
+      163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235,
+      249, 247,  77,  67,  81,  95, 117, 123, 105, 103,  61,  51,  33,
+       47,   5,  11,  25,  23, 118, 120, 106, 100,  78,  64,  82,  92,
+        6,   8,  26,  20,  62,  48,  34,  44, 150, 152, 138, 132, 174,
+      160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204,  65,  79,
+       93,  83, 121, 119, 101, 107,  49,  63,  45,  35,   9,   7,  21,
+       27, 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205, 195,
+      233, 231, 245, 251, 154, 148, 134, 136, 162, 172, 190, 176, 234,
+      228, 246, 248, 210, 220, 206, 192, 122, 116, 102, 104,  66,  76,
+       94,  80,  10,   4,  22,  24,  50,  60,  46,  32, 236, 226, 240,
+      254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182,
+       12,   2,  16,  30,  52,  58,  40,  38, 124, 114,  96, 110,  68,
+       74,  88,  86,  55,  57,  43,  37,  15,   1,  19,  29,  71,  73,
+       91,  85, 127, 113,  99, 109, 215, 217, 203, 197, 239, 225, 243,
+      253, 167, 169, 187, 181, 159, 145, 131, 141
+  };
+  static const SWord8 table7[] = {
+        0,  11,  22,  29,  44,  39,  58,  49,  88,  83,  78,  69, 116,
+      127,  98, 105, 176, 187, 166, 173, 156, 151, 138, 129, 232, 227,
+      254, 245, 196, 207, 210, 217, 123, 112, 109, 102,  87,  92,  65,
+       74,  35,  40,  53,  62,  15,   4,  25,  18, 203, 192, 221, 214,
+      231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, 246,
+      253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137,
+      148, 159,  70,  77,  80,  91, 106,  97, 124, 119,  30,  21,   8,
+        3,  50,  57,  36,  47, 141, 134, 155, 144, 161, 170, 183, 188,
+      213, 222, 195, 200, 249, 242, 239, 228,  61,  54,  43,  32,  17,
+       26,   7,  12, 101, 110, 115, 120,  73,  66,  95,  84, 247, 252,
+      225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149,
+      158,  71,  76,  81,  90, 107,  96, 125, 118,  31,  20,   9,   2,
+       51,  56,  37,  46, 140, 135, 154, 145, 160, 171, 182, 189, 212,
+      223, 194, 201, 248, 243, 238, 229,  60,  55,  42,  33,  16,  27,
+        6,  13, 100, 111, 114, 121,  72,  67,  94,  85,   1,  10,  23,
+       28,  45,  38,  59,  48,  89,  82,  79,  68, 117, 126,  99, 104,
+      177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197,
+      206, 211, 216, 122, 113, 108, 103,  86,  93,  64,  75,  34,  41,
+       52,  63,  14,   5,  24,  19, 202, 193, 220, 215, 230, 237, 240,
+      251, 146, 153, 132, 143, 190, 181, 168, 163
+  };
+  static const SWord8 table8[] = {
+        0,  13,  26,  23,  52,  57,  46,  35, 104, 101, 114, 127,  92,
+       81,  70,  75, 208, 221, 202, 199, 228, 233, 254, 243, 184, 181,
+      162, 175, 140, 129, 150, 155, 187, 182, 161, 172, 143, 130, 149,
+      152, 211, 222, 201, 196, 231, 234, 253, 240, 107, 102, 113, 124,
+       95,  82,  69,  72,   3,  14,  25,  20,  55,  58,  45,  32, 109,
+       96, 119, 122,  89,  84,  67,  78,   5,   8,  31,  18,  49,  60,
+       43,  38, 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207,
+      194, 225, 236, 251, 246, 214, 219, 204, 193, 226, 239, 248, 245,
+      190, 179, 164, 169, 138, 135, 144, 157,   6,  11,  28,  17,  50,
+       63,  40,  37, 110,  99, 116, 121,  90,  87,  64,  77, 218, 215,
+      192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156,
+      145,  10,   7,  16,  29,  62,  51,  36,  41,  98, 111, 120, 117,
+       86,  91,  76,  65,  97, 108, 123, 118,  85,  88,  79,  66,   9,
+        4,  19,  30,  61,  48,  39,  42, 177, 188, 171, 166, 133, 136,
+      159, 146, 217, 212, 195, 206, 237, 224, 247, 250, 183, 186, 173,
+      160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252,
+      103, 106, 125, 112,  83,  94,  73,  68,  15,   2,  21,  24,  59,
+       54,  33,  44,  12,   1,  22,  27,  56,  53,  34,  47, 100, 105,
+      126, 115,  80,  93,  74,  71, 220, 209, 198, 203, 232, 229, 242,
+      255, 180, 185, 174, 163, 128, 141, 154, 151
+  };
+  static const SWord8 table9[] = {
+        0,   9,  18,  27,  36,  45,  54,  63,  72,  65,  90,  83, 108,
+      101, 126, 119, 144, 153, 130, 139, 180, 189, 166, 175, 216, 209,
+      202, 195, 252, 245, 238, 231,  59,  50,  41,  32,  31,  22,  13,
+        4, 115, 122,  97, 104,  87,  94,  69,  76, 171, 162, 185, 176,
+      143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, 118,
+      127, 100, 109,  82,  91,  64,  73,  62,  55,  44,  37,  26,  19,
+        8,   1, 230, 239, 244, 253, 194, 203, 208, 217, 174, 167, 188,
+      181, 138, 131, 152, 145,  77,  68,  95,  86, 105,  96, 123, 114,
+        5,  12,  23,  30,  33,  40,  51,  58, 221, 212, 207, 198, 249,
+      240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, 236, 229,
+      254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146,
+      155, 124, 117, 110, 103,  88,  81,  74,  67,  52,  61,  38,  47,
+       16,  25,   2,  11, 215, 222, 197, 204, 243, 250, 225, 232, 159,
+      150, 141, 132, 187, 178, 169, 160,  71,  78,  85,  92,  99, 106,
+      113, 120,  15,   6,  29,  20,  43,  34,  57,  48, 154, 147, 136,
+      129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237,
+       10,   3,  24,  17,  46,  39,  60,  53,  66,  75,  80,  89, 102,
+      111, 116, 125, 161, 168, 179, 186, 133, 140, 151, 158, 233, 224,
+      251, 242, 205, 196, 223, 214,  49,  56,  35,  42,  21,  28,   7,
+       14, 121, 112, 107,  98,  93,  84,  79,  70
+  };
+  const SWord32 s520 = (s7 << 8) | (s7 >> 24);
+  const SWord8  s521 = (SWord8) (s520 >> 24);
+  const SWord8  s522 = table2[s521];
+  const SWord8  s523 = 1 ^ s522;
+  const SWord8  s524 = (SWord8) (s520 >> 16);
+  const SWord8  s525 = table2[s524];
+  const SWord16 s526 = (((SWord16) s523) << 8) | ((SWord16) s525);
+  const SWord8  s527 = (SWord8) (s520 >> 8);
+  const SWord8  s528 = table2[s527];
+  const SWord8  s529 = (SWord8) s520;
+  const SWord8  s530 = table2[s529];
+  const SWord16 s531 = (((SWord16) s528) << 8) | ((SWord16) s530);
+  const SWord32 s532 = (((SWord32) s526) << 16) | ((SWord32) s531);
+  const SWord32 s533 = s4 ^ s532;
+  const SWord32 s534 = s5 ^ s533;
+  const SWord32 s535 = s6 ^ s534;
+  const SWord32 s536 = s7 ^ s535;
+  const SWord32 s537 = (s536 << 8) | (s536 >> 24);
+  const SWord8  s538 = (SWord8) (s537 >> 24);
+  const SWord8  s539 = table2[s538];
+  const SWord8  s540 = 2 ^ s539;
+  const SWord8  s541 = (SWord8) (s537 >> 16);
+  const SWord8  s542 = table2[s541];
+  const SWord16 s543 = (((SWord16) s540) << 8) | ((SWord16) s542);
+  const SWord8  s544 = (SWord8) (s537 >> 8);
+  const SWord8  s545 = table2[s544];
+  const SWord8  s546 = (SWord8) s537;
+  const SWord8  s547 = table2[s546];
+  const SWord16 s548 = (((SWord16) s545) << 8) | ((SWord16) s547);
+  const SWord32 s549 = (((SWord32) s543) << 16) | ((SWord32) s548);
+  const SWord32 s550 = s533 ^ s549;
+  const SWord32 s551 = s534 ^ s550;
+  const SWord32 s552 = s535 ^ s551;
+  const SWord32 s553 = s536 ^ s552;
+  const SWord32 s554 = (s553 << 8) | (s553 >> 24);
+  const SWord8  s555 = (SWord8) (s554 >> 24);
+  const SWord8  s556 = table2[s555];
+  const SWord8  s557 = 4 ^ s556;
+  const SWord8  s558 = (SWord8) (s554 >> 16);
+  const SWord8  s559 = table2[s558];
+  const SWord16 s560 = (((SWord16) s557) << 8) | ((SWord16) s559);
+  const SWord8  s561 = (SWord8) (s554 >> 8);
+  const SWord8  s562 = table2[s561];
+  const SWord8  s563 = (SWord8) s554;
+  const SWord8  s564 = table2[s563];
+  const SWord16 s565 = (((SWord16) s562) << 8) | ((SWord16) s564);
+  const SWord32 s566 = (((SWord32) s560) << 16) | ((SWord32) s565);
+  const SWord32 s567 = s550 ^ s566;
+  const SWord32 s568 = s551 ^ s567;
+  const SWord32 s569 = s552 ^ s568;
+  const SWord32 s570 = s553 ^ s569;
+  const SWord32 s571 = (s570 << 8) | (s570 >> 24);
+  const SWord8  s572 = (SWord8) (s571 >> 24);
+  const SWord8  s573 = table2[s572];
+  const SWord8  s574 = 8 ^ s573;
+  const SWord8  s575 = (SWord8) (s571 >> 16);
+  const SWord8  s576 = table2[s575];
+  const SWord16 s577 = (((SWord16) s574) << 8) | ((SWord16) s576);
+  const SWord8  s578 = (SWord8) (s571 >> 8);
+  const SWord8  s579 = table2[s578];
+  const SWord8  s580 = (SWord8) s571;
+  const SWord8  s581 = table2[s580];
+  const SWord16 s582 = (((SWord16) s579) << 8) | ((SWord16) s581);
+  const SWord32 s583 = (((SWord32) s577) << 16) | ((SWord32) s582);
+  const SWord32 s584 = s567 ^ s583;
+  const SWord32 s585 = s568 ^ s584;
+  const SWord32 s586 = s569 ^ s585;
+  const SWord32 s587 = s570 ^ s586;
+  const SWord32 s588 = (s587 << 8) | (s587 >> 24);
+  const SWord8  s589 = (SWord8) (s588 >> 24);
+  const SWord8  s590 = table2[s589];
+  const SWord8  s591 = 16 ^ s590;
+  const SWord8  s592 = (SWord8) (s588 >> 16);
+  const SWord8  s593 = table2[s592];
+  const SWord16 s594 = (((SWord16) s591) << 8) | ((SWord16) s593);
+  const SWord8  s595 = (SWord8) (s588 >> 8);
+  const SWord8  s596 = table2[s595];
+  const SWord8  s597 = (SWord8) s588;
+  const SWord8  s598 = table2[s597];
+  const SWord16 s599 = (((SWord16) s596) << 8) | ((SWord16) s598);
+  const SWord32 s600 = (((SWord32) s594) << 16) | ((SWord32) s599);
+  const SWord32 s601 = s584 ^ s600;
+  const SWord32 s602 = s585 ^ s601;
+  const SWord32 s603 = s586 ^ s602;
+  const SWord32 s604 = s587 ^ s603;
+  const SWord32 s605 = (s604 << 8) | (s604 >> 24);
+  const SWord8  s606 = (SWord8) (s605 >> 24);
+  const SWord8  s607 = table2[s606];
+  const SWord8  s608 = 32 ^ s607;
+  const SWord8  s609 = (SWord8) (s605 >> 16);
+  const SWord8  s610 = table2[s609];
+  const SWord16 s611 = (((SWord16) s608) << 8) | ((SWord16) s610);
+  const SWord8  s612 = (SWord8) (s605 >> 8);
+  const SWord8  s613 = table2[s612];
+  const SWord8  s614 = (SWord8) s605;
+  const SWord8  s615 = table2[s614];
+  const SWord16 s616 = (((SWord16) s613) << 8) | ((SWord16) s615);
+  const SWord32 s617 = (((SWord32) s611) << 16) | ((SWord32) s616);
+  const SWord32 s618 = s601 ^ s617;
+  const SWord32 s619 = s602 ^ s618;
+  const SWord32 s620 = s603 ^ s619;
+  const SWord32 s621 = s604 ^ s620;
+  const SWord32 s622 = (s621 << 8) | (s621 >> 24);
+  const SWord8  s623 = (SWord8) (s622 >> 24);
+  const SWord8  s624 = table2[s623];
+  const SWord8  s625 = 64 ^ s624;
+  const SWord8  s626 = (SWord8) (s622 >> 16);
+  const SWord8  s627 = table2[s626];
+  const SWord16 s628 = (((SWord16) s625) << 8) | ((SWord16) s627);
+  const SWord8  s629 = (SWord8) (s622 >> 8);
+  const SWord8  s630 = table2[s629];
+  const SWord8  s631 = (SWord8) s622;
+  const SWord8  s632 = table2[s631];
+  const SWord16 s633 = (((SWord16) s630) << 8) | ((SWord16) s632);
+  const SWord32 s634 = (((SWord32) s628) << 16) | ((SWord32) s633);
+  const SWord32 s635 = s618 ^ s634;
+  const SWord32 s636 = s619 ^ s635;
+  const SWord32 s637 = s620 ^ s636;
+  const SWord32 s638 = s621 ^ s637;
+  const SWord32 s639 = (s638 << 8) | (s638 >> 24);
+  const SWord8  s640 = (SWord8) (s639 >> 24);
+  const SWord8  s641 = table2[s640];
+  const SWord8  s642 = 128 ^ s641;
+  const SWord8  s643 = (SWord8) (s639 >> 16);
+  const SWord8  s644 = table2[s643];
+  const SWord16 s645 = (((SWord16) s642) << 8) | ((SWord16) s644);
+  const SWord8  s646 = (SWord8) (s639 >> 8);
+  const SWord8  s647 = table2[s646];
+  const SWord8  s648 = (SWord8) s639;
+  const SWord8  s649 = table2[s648];
+  const SWord16 s650 = (((SWord16) s647) << 8) | ((SWord16) s649);
+  const SWord32 s651 = (((SWord32) s645) << 16) | ((SWord32) s650);
+  const SWord32 s652 = s635 ^ s651;
+  const SWord32 s653 = s636 ^ s652;
+  const SWord32 s654 = s637 ^ s653;
+  const SWord32 s655 = s638 ^ s654;
+  const SWord32 s656 = (s655 << 8) | (s655 >> 24);
+  const SWord8  s657 = (SWord8) (s656 >> 24);
+  const SWord8  s658 = table2[s657];
+  const SWord8  s659 = 27 ^ s658;
+  const SWord8  s660 = (SWord8) (s656 >> 16);
+  const SWord8  s661 = table2[s660];
+  const SWord16 s662 = (((SWord16) s659) << 8) | ((SWord16) s661);
+  const SWord8  s663 = (SWord8) (s656 >> 8);
+  const SWord8  s664 = table2[s663];
+  const SWord8  s665 = (SWord8) s656;
+  const SWord8  s666 = table2[s665];
+  const SWord16 s667 = (((SWord16) s664) << 8) | ((SWord16) s666);
+  const SWord32 s668 = (((SWord32) s662) << 16) | ((SWord32) s667);
+  const SWord32 s669 = s652 ^ s668;
+  const SWord32 s670 = s653 ^ s669;
+  const SWord32 s671 = s654 ^ s670;
+  const SWord32 s672 = s655 ^ s671;
+  const SWord32 s673 = (s672 << 8) | (s672 >> 24);
+  const SWord8  s674 = (SWord8) (s673 >> 24);
+  const SWord8  s675 = table2[s674];
+  const SWord8  s676 = 54 ^ s675;
+  const SWord8  s677 = (SWord8) (s673 >> 16);
+  const SWord8  s678 = table2[s677];
+  const SWord16 s679 = (((SWord16) s676) << 8) | ((SWord16) s678);
+  const SWord8  s680 = (SWord8) (s673 >> 8);
+  const SWord8  s681 = table2[s680];
+  const SWord8  s682 = (SWord8) s673;
+  const SWord8  s683 = table2[s682];
+  const SWord16 s684 = (((SWord16) s681) << 8) | ((SWord16) s683);
+  const SWord32 s685 = (((SWord32) s679) << 16) | ((SWord32) s684);
+  const SWord32 s686 = s669 ^ s685;
+  const SWord32 s687 = s0 ^ s686;
+  const SWord8  s688 = (SWord8) (s687 >> 24);
+  const SWord32 s689 = table1[s688];
+  const SWord32 s945 = s670 ^ s686;
+  const SWord32 s946 = s671 ^ s945;
+  const SWord32 s947 = s672 ^ s946;
+  const SWord32 s948 = s3 ^ s947;
+  const SWord8  s949 = (SWord8) (s948 >> 16);
+  const SWord32 s950 = table3[s949];
+  const SWord32 s951 = s689 ^ s950;
+  const SWord32 s1207 = s2 ^ s946;
+  const SWord8  s1208 = (SWord8) (s1207 >> 8);
+  const SWord32 s1209 = table4[s1208];
+  const SWord32 s1210 = s951 ^ s1209;
+  const SWord32 s1466 = s1 ^ s945;
+  const SWord8  s1467 = (SWord8) s1466;
+  const SWord32 s1468 = table5[s1467];
+  const SWord32 s1469 = s1210 ^ s1468;
+  const SWord8  s1470 = (SWord8) (s669 >> 24);
+  const SWord8  s1471 = table6[s1470];
+  const SWord8  s1472 = (SWord8) (s669 >> 16);
+  const SWord8  s1473 = table7[s1472];
+  const SWord8  s1474 = (SWord8) (s669 >> 8);
+  const SWord8  s1475 = table8[s1474];
+  const SWord8  s1476 = (SWord8) s669;
+  const SWord8  s1477 = table9[s1476];
+  const SWord8  s1478 = s1475 ^ s1477;
+  const SWord8  s1479 = s1473 ^ s1478;
+  const SWord8  s1480 = s1471 ^ s1479;
+  const SWord8  s1481 = table9[s1470];
+  const SWord8  s1482 = table6[s1472];
+  const SWord8  s1483 = table7[s1474];
+  const SWord8  s1484 = table8[s1476];
+  const SWord8  s1485 = s1483 ^ s1484;
+  const SWord8  s1486 = s1482 ^ s1485;
+  const SWord8  s1487 = s1481 ^ s1486;
+  const SWord16 s1488 = (((SWord16) s1480) << 8) | ((SWord16) s1487);
+  const SWord8  s1489 = table8[s1470];
+  const SWord8  s1490 = table9[s1472];
+  const SWord8  s1491 = table6[s1474];
+  const SWord8  s1492 = table7[s1476];
+  const SWord8  s1493 = s1491 ^ s1492;
+  const SWord8  s1494 = s1490 ^ s1493;
+  const SWord8  s1495 = s1489 ^ s1494;
+  const SWord8  s1496 = table7[s1470];
+  const SWord8  s1497 = table8[s1472];
+  const SWord8  s1498 = table9[s1474];
+  const SWord8  s1499 = table6[s1476];
+  const SWord8  s1500 = s1498 ^ s1499;
+  const SWord8  s1501 = s1497 ^ s1500;
+  const SWord8  s1502 = s1496 ^ s1501;
+  const SWord16 s1503 = (((SWord16) s1495) << 8) | ((SWord16) s1502);
+  const SWord32 s1504 = (((SWord32) s1488) << 16) | ((SWord32) s1503);
+  const SWord32 s1505 = s1469 ^ s1504;
+  const SWord8  s1506 = (SWord8) (s1505 >> 24);
+  const SWord32 s1507 = table1[s1506];
+  const SWord8  s1508 = (SWord8) (s948 >> 24);
+  const SWord32 s1509 = table1[s1508];
+  const SWord8  s1510 = (SWord8) (s1207 >> 16);
+  const SWord32 s1511 = table3[s1510];
+  const SWord32 s1512 = s1509 ^ s1511;
+  const SWord8  s1513 = (SWord8) (s1466 >> 8);
+  const SWord32 s1514 = table4[s1513];
+  const SWord32 s1515 = s1512 ^ s1514;
+  const SWord8  s1516 = (SWord8) s687;
+  const SWord32 s1517 = table5[s1516];
+  const SWord32 s1518 = s1515 ^ s1517;
+  const SWord8  s1519 = (SWord8) (s672 >> 24);
+  const SWord8  s1520 = table6[s1519];
+  const SWord8  s1521 = (SWord8) (s672 >> 16);
+  const SWord8  s1522 = table7[s1521];
+  const SWord8  s1523 = (SWord8) (s672 >> 8);
+  const SWord8  s1524 = table8[s1523];
+  const SWord8  s1525 = (SWord8) s672;
+  const SWord8  s1526 = table9[s1525];
+  const SWord8  s1527 = s1524 ^ s1526;
+  const SWord8  s1528 = s1522 ^ s1527;
+  const SWord8  s1529 = s1520 ^ s1528;
+  const SWord8  s1530 = table9[s1519];
+  const SWord8  s1531 = table6[s1521];
+  const SWord8  s1532 = table7[s1523];
+  const SWord8  s1533 = table8[s1525];
+  const SWord8  s1534 = s1532 ^ s1533;
+  const SWord8  s1535 = s1531 ^ s1534;
+  const SWord8  s1536 = s1530 ^ s1535;
+  const SWord16 s1537 = (((SWord16) s1529) << 8) | ((SWord16) s1536);
+  const SWord8  s1538 = table8[s1519];
+  const SWord8  s1539 = table9[s1521];
+  const SWord8  s1540 = table6[s1523];
+  const SWord8  s1541 = table7[s1525];
+  const SWord8  s1542 = s1540 ^ s1541;
+  const SWord8  s1543 = s1539 ^ s1542;
+  const SWord8  s1544 = s1538 ^ s1543;
+  const SWord8  s1545 = table7[s1519];
+  const SWord8  s1546 = table8[s1521];
+  const SWord8  s1547 = table9[s1523];
+  const SWord8  s1548 = table6[s1525];
+  const SWord8  s1549 = s1547 ^ s1548;
+  const SWord8  s1550 = s1546 ^ s1549;
+  const SWord8  s1551 = s1545 ^ s1550;
+  const SWord16 s1552 = (((SWord16) s1544) << 8) | ((SWord16) s1551);
+  const SWord32 s1553 = (((SWord32) s1537) << 16) | ((SWord32) s1552);
+  const SWord32 s1554 = s1518 ^ s1553;
+  const SWord8  s1555 = (SWord8) (s1554 >> 16);
+  const SWord32 s1556 = table3[s1555];
+  const SWord32 s1557 = s1507 ^ s1556;
+  const SWord8  s1558 = (SWord8) (s1207 >> 24);
+  const SWord32 s1559 = table1[s1558];
+  const SWord8  s1560 = (SWord8) (s1466 >> 16);
+  const SWord32 s1561 = table3[s1560];
+  const SWord32 s1562 = s1559 ^ s1561;
+  const SWord8  s1563 = (SWord8) (s687 >> 8);
+  const SWord32 s1564 = table4[s1563];
+  const SWord32 s1565 = s1562 ^ s1564;
+  const SWord8  s1566 = (SWord8) s948;
+  const SWord32 s1567 = table5[s1566];
+  const SWord32 s1568 = s1565 ^ s1567;
+  const SWord8  s1569 = (SWord8) (s671 >> 24);
+  const SWord8  s1570 = table6[s1569];
+  const SWord8  s1571 = (SWord8) (s671 >> 16);
+  const SWord8  s1572 = table7[s1571];
+  const SWord8  s1573 = (SWord8) (s671 >> 8);
+  const SWord8  s1574 = table8[s1573];
+  const SWord8  s1575 = (SWord8) s671;
+  const SWord8  s1576 = table9[s1575];
+  const SWord8  s1577 = s1574 ^ s1576;
+  const SWord8  s1578 = s1572 ^ s1577;
+  const SWord8  s1579 = s1570 ^ s1578;
+  const SWord8  s1580 = table9[s1569];
+  const SWord8  s1581 = table6[s1571];
+  const SWord8  s1582 = table7[s1573];
+  const SWord8  s1583 = table8[s1575];
+  const SWord8  s1584 = s1582 ^ s1583;
+  const SWord8  s1585 = s1581 ^ s1584;
+  const SWord8  s1586 = s1580 ^ s1585;
+  const SWord16 s1587 = (((SWord16) s1579) << 8) | ((SWord16) s1586);
+  const SWord8  s1588 = table8[s1569];
+  const SWord8  s1589 = table9[s1571];
+  const SWord8  s1590 = table6[s1573];
+  const SWord8  s1591 = table7[s1575];
+  const SWord8  s1592 = s1590 ^ s1591;
+  const SWord8  s1593 = s1589 ^ s1592;
+  const SWord8  s1594 = s1588 ^ s1593;
+  const SWord8  s1595 = table7[s1569];
+  const SWord8  s1596 = table8[s1571];
+  const SWord8  s1597 = table9[s1573];
+  const SWord8  s1598 = table6[s1575];
+  const SWord8  s1599 = s1597 ^ s1598;
+  const SWord8  s1600 = s1596 ^ s1599;
+  const SWord8  s1601 = s1595 ^ s1600;
+  const SWord16 s1602 = (((SWord16) s1594) << 8) | ((SWord16) s1601);
+  const SWord32 s1603 = (((SWord32) s1587) << 16) | ((SWord32) s1602);
+  const SWord32 s1604 = s1568 ^ s1603;
+  const SWord8  s1605 = (SWord8) (s1604 >> 8);
+  const SWord32 s1606 = table4[s1605];
+  const SWord32 s1607 = s1557 ^ s1606;
+  const SWord8  s1608 = (SWord8) (s1466 >> 24);
+  const SWord32 s1609 = table1[s1608];
+  const SWord8  s1610 = (SWord8) (s687 >> 16);
+  const SWord32 s1611 = table3[s1610];
+  const SWord32 s1612 = s1609 ^ s1611;
+  const SWord8  s1613 = (SWord8) (s948 >> 8);
+  const SWord32 s1614 = table4[s1613];
+  const SWord32 s1615 = s1612 ^ s1614;
+  const SWord8  s1616 = (SWord8) s1207;
+  const SWord32 s1617 = table5[s1616];
+  const SWord32 s1618 = s1615 ^ s1617;
+  const SWord8  s1619 = (SWord8) (s670 >> 24);
+  const SWord8  s1620 = table6[s1619];
+  const SWord8  s1621 = (SWord8) (s670 >> 16);
+  const SWord8  s1622 = table7[s1621];
+  const SWord8  s1623 = (SWord8) (s670 >> 8);
+  const SWord8  s1624 = table8[s1623];
+  const SWord8  s1625 = (SWord8) s670;
+  const SWord8  s1626 = table9[s1625];
+  const SWord8  s1627 = s1624 ^ s1626;
+  const SWord8  s1628 = s1622 ^ s1627;
+  const SWord8  s1629 = s1620 ^ s1628;
+  const SWord8  s1630 = table9[s1619];
+  const SWord8  s1631 = table6[s1621];
+  const SWord8  s1632 = table7[s1623];
+  const SWord8  s1633 = table8[s1625];
+  const SWord8  s1634 = s1632 ^ s1633;
+  const SWord8  s1635 = s1631 ^ s1634;
+  const SWord8  s1636 = s1630 ^ s1635;
+  const SWord16 s1637 = (((SWord16) s1629) << 8) | ((SWord16) s1636);
+  const SWord8  s1638 = table8[s1619];
+  const SWord8  s1639 = table9[s1621];
+  const SWord8  s1640 = table6[s1623];
+  const SWord8  s1641 = table7[s1625];
+  const SWord8  s1642 = s1640 ^ s1641;
+  const SWord8  s1643 = s1639 ^ s1642;
+  const SWord8  s1644 = s1638 ^ s1643;
+  const SWord8  s1645 = table7[s1619];
+  const SWord8  s1646 = table8[s1621];
+  const SWord8  s1647 = table9[s1623];
+  const SWord8  s1648 = table6[s1625];
+  const SWord8  s1649 = s1647 ^ s1648;
+  const SWord8  s1650 = s1646 ^ s1649;
+  const SWord8  s1651 = s1645 ^ s1650;
+  const SWord16 s1652 = (((SWord16) s1644) << 8) | ((SWord16) s1651);
+  const SWord32 s1653 = (((SWord32) s1637) << 16) | ((SWord32) s1652);
+  const SWord32 s1654 = s1618 ^ s1653;
+  const SWord8  s1655 = (SWord8) s1654;
+  const SWord32 s1656 = table5[s1655];
+  const SWord32 s1657 = s1607 ^ s1656;
+  const SWord8  s1658 = (SWord8) (s652 >> 24);
+  const SWord8  s1659 = table6[s1658];
+  const SWord8  s1660 = (SWord8) (s652 >> 16);
+  const SWord8  s1661 = table7[s1660];
+  const SWord8  s1662 = (SWord8) (s652 >> 8);
+  const SWord8  s1663 = table8[s1662];
+  const SWord8  s1664 = (SWord8) s652;
+  const SWord8  s1665 = table9[s1664];
+  const SWord8  s1666 = s1663 ^ s1665;
+  const SWord8  s1667 = s1661 ^ s1666;
+  const SWord8  s1668 = s1659 ^ s1667;
+  const SWord8  s1669 = table9[s1658];
+  const SWord8  s1670 = table6[s1660];
+  const SWord8  s1671 = table7[s1662];
+  const SWord8  s1672 = table8[s1664];
+  const SWord8  s1673 = s1671 ^ s1672;
+  const SWord8  s1674 = s1670 ^ s1673;
+  const SWord8  s1675 = s1669 ^ s1674;
+  const SWord16 s1676 = (((SWord16) s1668) << 8) | ((SWord16) s1675);
+  const SWord8  s1677 = table8[s1658];
+  const SWord8  s1678 = table9[s1660];
+  const SWord8  s1679 = table6[s1662];
+  const SWord8  s1680 = table7[s1664];
+  const SWord8  s1681 = s1679 ^ s1680;
+  const SWord8  s1682 = s1678 ^ s1681;
+  const SWord8  s1683 = s1677 ^ s1682;
+  const SWord8  s1684 = table7[s1658];
+  const SWord8  s1685 = table8[s1660];
+  const SWord8  s1686 = table9[s1662];
+  const SWord8  s1687 = table6[s1664];
+  const SWord8  s1688 = s1686 ^ s1687;
+  const SWord8  s1689 = s1685 ^ s1688;
+  const SWord8  s1690 = s1684 ^ s1689;
+  const SWord16 s1691 = (((SWord16) s1683) << 8) | ((SWord16) s1690);
+  const SWord32 s1692 = (((SWord32) s1676) << 16) | ((SWord32) s1691);
+  const SWord32 s1693 = s1657 ^ s1692;
+  const SWord8  s1694 = (SWord8) (s1693 >> 24);
+  const SWord32 s1695 = table1[s1694];
+  const SWord8  s1696 = (SWord8) (s1554 >> 24);
+  const SWord32 s1697 = table1[s1696];
+  const SWord8  s1698 = (SWord8) (s1604 >> 16);
+  const SWord32 s1699 = table3[s1698];
+  const SWord32 s1700 = s1697 ^ s1699;
+  const SWord8  s1701 = (SWord8) (s1654 >> 8);
+  const SWord32 s1702 = table4[s1701];
+  const SWord32 s1703 = s1700 ^ s1702;
+  const SWord8  s1704 = (SWord8) s1505;
+  const SWord32 s1705 = table5[s1704];
+  const SWord32 s1706 = s1703 ^ s1705;
+  const SWord8  s1707 = (SWord8) (s655 >> 24);
+  const SWord8  s1708 = table6[s1707];
+  const SWord8  s1709 = (SWord8) (s655 >> 16);
+  const SWord8  s1710 = table7[s1709];
+  const SWord8  s1711 = (SWord8) (s655 >> 8);
+  const SWord8  s1712 = table8[s1711];
+  const SWord8  s1713 = (SWord8) s655;
+  const SWord8  s1714 = table9[s1713];
+  const SWord8  s1715 = s1712 ^ s1714;
+  const SWord8  s1716 = s1710 ^ s1715;
+  const SWord8  s1717 = s1708 ^ s1716;
+  const SWord8  s1718 = table9[s1707];
+  const SWord8  s1719 = table6[s1709];
+  const SWord8  s1720 = table7[s1711];
+  const SWord8  s1721 = table8[s1713];
+  const SWord8  s1722 = s1720 ^ s1721;
+  const SWord8  s1723 = s1719 ^ s1722;
+  const SWord8  s1724 = s1718 ^ s1723;
+  const SWord16 s1725 = (((SWord16) s1717) << 8) | ((SWord16) s1724);
+  const SWord8  s1726 = table8[s1707];
+  const SWord8  s1727 = table9[s1709];
+  const SWord8  s1728 = table6[s1711];
+  const SWord8  s1729 = table7[s1713];
+  const SWord8  s1730 = s1728 ^ s1729;
+  const SWord8  s1731 = s1727 ^ s1730;
+  const SWord8  s1732 = s1726 ^ s1731;
+  const SWord8  s1733 = table7[s1707];
+  const SWord8  s1734 = table8[s1709];
+  const SWord8  s1735 = table9[s1711];
+  const SWord8  s1736 = table6[s1713];
+  const SWord8  s1737 = s1735 ^ s1736;
+  const SWord8  s1738 = s1734 ^ s1737;
+  const SWord8  s1739 = s1733 ^ s1738;
+  const SWord16 s1740 = (((SWord16) s1732) << 8) | ((SWord16) s1739);
+  const SWord32 s1741 = (((SWord32) s1725) << 16) | ((SWord32) s1740);
+  const SWord32 s1742 = s1706 ^ s1741;
+  const SWord8  s1743 = (SWord8) (s1742 >> 16);
+  const SWord32 s1744 = table3[s1743];
+  const SWord32 s1745 = s1695 ^ s1744;
+  const SWord8  s1746 = (SWord8) (s1604 >> 24);
+  const SWord32 s1747 = table1[s1746];
+  const SWord8  s1748 = (SWord8) (s1654 >> 16);
+  const SWord32 s1749 = table3[s1748];
+  const SWord32 s1750 = s1747 ^ s1749;
+  const SWord8  s1751 = (SWord8) (s1505 >> 8);
+  const SWord32 s1752 = table4[s1751];
+  const SWord32 s1753 = s1750 ^ s1752;
+  const SWord8  s1754 = (SWord8) s1554;
+  const SWord32 s1755 = table5[s1754];
+  const SWord32 s1756 = s1753 ^ s1755;
+  const SWord8  s1757 = (SWord8) (s654 >> 24);
+  const SWord8  s1758 = table6[s1757];
+  const SWord8  s1759 = (SWord8) (s654 >> 16);
+  const SWord8  s1760 = table7[s1759];
+  const SWord8  s1761 = (SWord8) (s654 >> 8);
+  const SWord8  s1762 = table8[s1761];
+  const SWord8  s1763 = (SWord8) s654;
+  const SWord8  s1764 = table9[s1763];
+  const SWord8  s1765 = s1762 ^ s1764;
+  const SWord8  s1766 = s1760 ^ s1765;
+  const SWord8  s1767 = s1758 ^ s1766;
+  const SWord8  s1768 = table9[s1757];
+  const SWord8  s1769 = table6[s1759];
+  const SWord8  s1770 = table7[s1761];
+  const SWord8  s1771 = table8[s1763];
+  const SWord8  s1772 = s1770 ^ s1771;
+  const SWord8  s1773 = s1769 ^ s1772;
+  const SWord8  s1774 = s1768 ^ s1773;
+  const SWord16 s1775 = (((SWord16) s1767) << 8) | ((SWord16) s1774);
+  const SWord8  s1776 = table8[s1757];
+  const SWord8  s1777 = table9[s1759];
+  const SWord8  s1778 = table6[s1761];
+  const SWord8  s1779 = table7[s1763];
+  const SWord8  s1780 = s1778 ^ s1779;
+  const SWord8  s1781 = s1777 ^ s1780;
+  const SWord8  s1782 = s1776 ^ s1781;
+  const SWord8  s1783 = table7[s1757];
+  const SWord8  s1784 = table8[s1759];
+  const SWord8  s1785 = table9[s1761];
+  const SWord8  s1786 = table6[s1763];
+  const SWord8  s1787 = s1785 ^ s1786;
+  const SWord8  s1788 = s1784 ^ s1787;
+  const SWord8  s1789 = s1783 ^ s1788;
+  const SWord16 s1790 = (((SWord16) s1782) << 8) | ((SWord16) s1789);
+  const SWord32 s1791 = (((SWord32) s1775) << 16) | ((SWord32) s1790);
+  const SWord32 s1792 = s1756 ^ s1791;
+  const SWord8  s1793 = (SWord8) (s1792 >> 8);
+  const SWord32 s1794 = table4[s1793];
+  const SWord32 s1795 = s1745 ^ s1794;
+  const SWord8  s1796 = (SWord8) (s1654 >> 24);
+  const SWord32 s1797 = table1[s1796];
+  const SWord8  s1798 = (SWord8) (s1505 >> 16);
+  const SWord32 s1799 = table3[s1798];
+  const SWord32 s1800 = s1797 ^ s1799;
+  const SWord8  s1801 = (SWord8) (s1554 >> 8);
+  const SWord32 s1802 = table4[s1801];
+  const SWord32 s1803 = s1800 ^ s1802;
+  const SWord8  s1804 = (SWord8) s1604;
+  const SWord32 s1805 = table5[s1804];
+  const SWord32 s1806 = s1803 ^ s1805;
+  const SWord8  s1807 = (SWord8) (s653 >> 24);
+  const SWord8  s1808 = table6[s1807];
+  const SWord8  s1809 = (SWord8) (s653 >> 16);
+  const SWord8  s1810 = table7[s1809];
+  const SWord8  s1811 = (SWord8) (s653 >> 8);
+  const SWord8  s1812 = table8[s1811];
+  const SWord8  s1813 = (SWord8) s653;
+  const SWord8  s1814 = table9[s1813];
+  const SWord8  s1815 = s1812 ^ s1814;
+  const SWord8  s1816 = s1810 ^ s1815;
+  const SWord8  s1817 = s1808 ^ s1816;
+  const SWord8  s1818 = table9[s1807];
+  const SWord8  s1819 = table6[s1809];
+  const SWord8  s1820 = table7[s1811];
+  const SWord8  s1821 = table8[s1813];
+  const SWord8  s1822 = s1820 ^ s1821;
+  const SWord8  s1823 = s1819 ^ s1822;
+  const SWord8  s1824 = s1818 ^ s1823;
+  const SWord16 s1825 = (((SWord16) s1817) << 8) | ((SWord16) s1824);
+  const SWord8  s1826 = table8[s1807];
+  const SWord8  s1827 = table9[s1809];
+  const SWord8  s1828 = table6[s1811];
+  const SWord8  s1829 = table7[s1813];
+  const SWord8  s1830 = s1828 ^ s1829;
+  const SWord8  s1831 = s1827 ^ s1830;
+  const SWord8  s1832 = s1826 ^ s1831;
+  const SWord8  s1833 = table7[s1807];
+  const SWord8  s1834 = table8[s1809];
+  const SWord8  s1835 = table9[s1811];
+  const SWord8  s1836 = table6[s1813];
+  const SWord8  s1837 = s1835 ^ s1836;
+  const SWord8  s1838 = s1834 ^ s1837;
+  const SWord8  s1839 = s1833 ^ s1838;
+  const SWord16 s1840 = (((SWord16) s1832) << 8) | ((SWord16) s1839);
+  const SWord32 s1841 = (((SWord32) s1825) << 16) | ((SWord32) s1840);
+  const SWord32 s1842 = s1806 ^ s1841;
+  const SWord8  s1843 = (SWord8) s1842;
+  const SWord32 s1844 = table5[s1843];
+  const SWord32 s1845 = s1795 ^ s1844;
+  const SWord8  s1846 = (SWord8) (s635 >> 24);
+  const SWord8  s1847 = table6[s1846];
+  const SWord8  s1848 = (SWord8) (s635 >> 16);
+  const SWord8  s1849 = table7[s1848];
+  const SWord8  s1850 = (SWord8) (s635 >> 8);
+  const SWord8  s1851 = table8[s1850];
+  const SWord8  s1852 = (SWord8) s635;
+  const SWord8  s1853 = table9[s1852];
+  const SWord8  s1854 = s1851 ^ s1853;
+  const SWord8  s1855 = s1849 ^ s1854;
+  const SWord8  s1856 = s1847 ^ s1855;
+  const SWord8  s1857 = table9[s1846];
+  const SWord8  s1858 = table6[s1848];
+  const SWord8  s1859 = table7[s1850];
+  const SWord8  s1860 = table8[s1852];
+  const SWord8  s1861 = s1859 ^ s1860;
+  const SWord8  s1862 = s1858 ^ s1861;
+  const SWord8  s1863 = s1857 ^ s1862;
+  const SWord16 s1864 = (((SWord16) s1856) << 8) | ((SWord16) s1863);
+  const SWord8  s1865 = table8[s1846];
+  const SWord8  s1866 = table9[s1848];
+  const SWord8  s1867 = table6[s1850];
+  const SWord8  s1868 = table7[s1852];
+  const SWord8  s1869 = s1867 ^ s1868;
+  const SWord8  s1870 = s1866 ^ s1869;
+  const SWord8  s1871 = s1865 ^ s1870;
+  const SWord8  s1872 = table7[s1846];
+  const SWord8  s1873 = table8[s1848];
+  const SWord8  s1874 = table9[s1850];
+  const SWord8  s1875 = table6[s1852];
+  const SWord8  s1876 = s1874 ^ s1875;
+  const SWord8  s1877 = s1873 ^ s1876;
+  const SWord8  s1878 = s1872 ^ s1877;
+  const SWord16 s1879 = (((SWord16) s1871) << 8) | ((SWord16) s1878);
+  const SWord32 s1880 = (((SWord32) s1864) << 16) | ((SWord32) s1879);
+  const SWord32 s1881 = s1845 ^ s1880;
+  const SWord8  s1882 = (SWord8) (s1881 >> 24);
+  const SWord32 s1883 = table1[s1882];
+  const SWord8  s1884 = (SWord8) (s1742 >> 24);
+  const SWord32 s1885 = table1[s1884];
+  const SWord8  s1886 = (SWord8) (s1792 >> 16);
+  const SWord32 s1887 = table3[s1886];
+  const SWord32 s1888 = s1885 ^ s1887;
+  const SWord8  s1889 = (SWord8) (s1842 >> 8);
+  const SWord32 s1890 = table4[s1889];
+  const SWord32 s1891 = s1888 ^ s1890;
+  const SWord8  s1892 = (SWord8) s1693;
+  const SWord32 s1893 = table5[s1892];
+  const SWord32 s1894 = s1891 ^ s1893;
+  const SWord8  s1895 = (SWord8) (s638 >> 24);
+  const SWord8  s1896 = table6[s1895];
+  const SWord8  s1897 = (SWord8) (s638 >> 16);
+  const SWord8  s1898 = table7[s1897];
+  const SWord8  s1899 = (SWord8) (s638 >> 8);
+  const SWord8  s1900 = table8[s1899];
+  const SWord8  s1901 = (SWord8) s638;
+  const SWord8  s1902 = table9[s1901];
+  const SWord8  s1903 = s1900 ^ s1902;
+  const SWord8  s1904 = s1898 ^ s1903;
+  const SWord8  s1905 = s1896 ^ s1904;
+  const SWord8  s1906 = table9[s1895];
+  const SWord8  s1907 = table6[s1897];
+  const SWord8  s1908 = table7[s1899];
+  const SWord8  s1909 = table8[s1901];
+  const SWord8  s1910 = s1908 ^ s1909;
+  const SWord8  s1911 = s1907 ^ s1910;
+  const SWord8  s1912 = s1906 ^ s1911;
+  const SWord16 s1913 = (((SWord16) s1905) << 8) | ((SWord16) s1912);
+  const SWord8  s1914 = table8[s1895];
+  const SWord8  s1915 = table9[s1897];
+  const SWord8  s1916 = table6[s1899];
+  const SWord8  s1917 = table7[s1901];
+  const SWord8  s1918 = s1916 ^ s1917;
+  const SWord8  s1919 = s1915 ^ s1918;
+  const SWord8  s1920 = s1914 ^ s1919;
+  const SWord8  s1921 = table7[s1895];
+  const SWord8  s1922 = table8[s1897];
+  const SWord8  s1923 = table9[s1899];
+  const SWord8  s1924 = table6[s1901];
+  const SWord8  s1925 = s1923 ^ s1924;
+  const SWord8  s1926 = s1922 ^ s1925;
+  const SWord8  s1927 = s1921 ^ s1926;
+  const SWord16 s1928 = (((SWord16) s1920) << 8) | ((SWord16) s1927);
+  const SWord32 s1929 = (((SWord32) s1913) << 16) | ((SWord32) s1928);
+  const SWord32 s1930 = s1894 ^ s1929;
+  const SWord8  s1931 = (SWord8) (s1930 >> 16);
+  const SWord32 s1932 = table3[s1931];
+  const SWord32 s1933 = s1883 ^ s1932;
+  const SWord8  s1934 = (SWord8) (s1792 >> 24);
+  const SWord32 s1935 = table1[s1934];
+  const SWord8  s1936 = (SWord8) (s1842 >> 16);
+  const SWord32 s1937 = table3[s1936];
+  const SWord32 s1938 = s1935 ^ s1937;
+  const SWord8  s1939 = (SWord8) (s1693 >> 8);
+  const SWord32 s1940 = table4[s1939];
+  const SWord32 s1941 = s1938 ^ s1940;
+  const SWord8  s1942 = (SWord8) s1742;
+  const SWord32 s1943 = table5[s1942];
+  const SWord32 s1944 = s1941 ^ s1943;
+  const SWord8  s1945 = (SWord8) (s637 >> 24);
+  const SWord8  s1946 = table6[s1945];
+  const SWord8  s1947 = (SWord8) (s637 >> 16);
+  const SWord8  s1948 = table7[s1947];
+  const SWord8  s1949 = (SWord8) (s637 >> 8);
+  const SWord8  s1950 = table8[s1949];
+  const SWord8  s1951 = (SWord8) s637;
+  const SWord8  s1952 = table9[s1951];
+  const SWord8  s1953 = s1950 ^ s1952;
+  const SWord8  s1954 = s1948 ^ s1953;
+  const SWord8  s1955 = s1946 ^ s1954;
+  const SWord8  s1956 = table9[s1945];
+  const SWord8  s1957 = table6[s1947];
+  const SWord8  s1958 = table7[s1949];
+  const SWord8  s1959 = table8[s1951];
+  const SWord8  s1960 = s1958 ^ s1959;
+  const SWord8  s1961 = s1957 ^ s1960;
+  const SWord8  s1962 = s1956 ^ s1961;
+  const SWord16 s1963 = (((SWord16) s1955) << 8) | ((SWord16) s1962);
+  const SWord8  s1964 = table8[s1945];
+  const SWord8  s1965 = table9[s1947];
+  const SWord8  s1966 = table6[s1949];
+  const SWord8  s1967 = table7[s1951];
+  const SWord8  s1968 = s1966 ^ s1967;
+  const SWord8  s1969 = s1965 ^ s1968;
+  const SWord8  s1970 = s1964 ^ s1969;
+  const SWord8  s1971 = table7[s1945];
+  const SWord8  s1972 = table8[s1947];
+  const SWord8  s1973 = table9[s1949];
+  const SWord8  s1974 = table6[s1951];
+  const SWord8  s1975 = s1973 ^ s1974;
+  const SWord8  s1976 = s1972 ^ s1975;
+  const SWord8  s1977 = s1971 ^ s1976;
+  const SWord16 s1978 = (((SWord16) s1970) << 8) | ((SWord16) s1977);
+  const SWord32 s1979 = (((SWord32) s1963) << 16) | ((SWord32) s1978);
+  const SWord32 s1980 = s1944 ^ s1979;
+  const SWord8  s1981 = (SWord8) (s1980 >> 8);
+  const SWord32 s1982 = table4[s1981];
+  const SWord32 s1983 = s1933 ^ s1982;
+  const SWord8  s1984 = (SWord8) (s1842 >> 24);
+  const SWord32 s1985 = table1[s1984];
+  const SWord8  s1986 = (SWord8) (s1693 >> 16);
+  const SWord32 s1987 = table3[s1986];
+  const SWord32 s1988 = s1985 ^ s1987;
+  const SWord8  s1989 = (SWord8) (s1742 >> 8);
+  const SWord32 s1990 = table4[s1989];
+  const SWord32 s1991 = s1988 ^ s1990;
+  const SWord8  s1992 = (SWord8) s1792;
+  const SWord32 s1993 = table5[s1992];
+  const SWord32 s1994 = s1991 ^ s1993;
+  const SWord8  s1995 = (SWord8) (s636 >> 24);
+  const SWord8  s1996 = table6[s1995];
+  const SWord8  s1997 = (SWord8) (s636 >> 16);
+  const SWord8  s1998 = table7[s1997];
+  const SWord8  s1999 = (SWord8) (s636 >> 8);
+  const SWord8  s2000 = table8[s1999];
+  const SWord8  s2001 = (SWord8) s636;
+  const SWord8  s2002 = table9[s2001];
+  const SWord8  s2003 = s2000 ^ s2002;
+  const SWord8  s2004 = s1998 ^ s2003;
+  const SWord8  s2005 = s1996 ^ s2004;
+  const SWord8  s2006 = table9[s1995];
+  const SWord8  s2007 = table6[s1997];
+  const SWord8  s2008 = table7[s1999];
+  const SWord8  s2009 = table8[s2001];
+  const SWord8  s2010 = s2008 ^ s2009;
+  const SWord8  s2011 = s2007 ^ s2010;
+  const SWord8  s2012 = s2006 ^ s2011;
+  const SWord16 s2013 = (((SWord16) s2005) << 8) | ((SWord16) s2012);
+  const SWord8  s2014 = table8[s1995];
+  const SWord8  s2015 = table9[s1997];
+  const SWord8  s2016 = table6[s1999];
+  const SWord8  s2017 = table7[s2001];
+  const SWord8  s2018 = s2016 ^ s2017;
+  const SWord8  s2019 = s2015 ^ s2018;
+  const SWord8  s2020 = s2014 ^ s2019;
+  const SWord8  s2021 = table7[s1995];
+  const SWord8  s2022 = table8[s1997];
+  const SWord8  s2023 = table9[s1999];
+  const SWord8  s2024 = table6[s2001];
+  const SWord8  s2025 = s2023 ^ s2024;
+  const SWord8  s2026 = s2022 ^ s2025;
+  const SWord8  s2027 = s2021 ^ s2026;
+  const SWord16 s2028 = (((SWord16) s2020) << 8) | ((SWord16) s2027);
+  const SWord32 s2029 = (((SWord32) s2013) << 16) | ((SWord32) s2028);
+  const SWord32 s2030 = s1994 ^ s2029;
+  const SWord8  s2031 = (SWord8) s2030;
+  const SWord32 s2032 = table5[s2031];
+  const SWord32 s2033 = s1983 ^ s2032;
+  const SWord8  s2034 = (SWord8) (s618 >> 24);
+  const SWord8  s2035 = table6[s2034];
+  const SWord8  s2036 = (SWord8) (s618 >> 16);
+  const SWord8  s2037 = table7[s2036];
+  const SWord8  s2038 = (SWord8) (s618 >> 8);
+  const SWord8  s2039 = table8[s2038];
+  const SWord8  s2040 = (SWord8) s618;
+  const SWord8  s2041 = table9[s2040];
+  const SWord8  s2042 = s2039 ^ s2041;
+  const SWord8  s2043 = s2037 ^ s2042;
+  const SWord8  s2044 = s2035 ^ s2043;
+  const SWord8  s2045 = table9[s2034];
+  const SWord8  s2046 = table6[s2036];
+  const SWord8  s2047 = table7[s2038];
+  const SWord8  s2048 = table8[s2040];
+  const SWord8  s2049 = s2047 ^ s2048;
+  const SWord8  s2050 = s2046 ^ s2049;
+  const SWord8  s2051 = s2045 ^ s2050;
+  const SWord16 s2052 = (((SWord16) s2044) << 8) | ((SWord16) s2051);
+  const SWord8  s2053 = table8[s2034];
+  const SWord8  s2054 = table9[s2036];
+  const SWord8  s2055 = table6[s2038];
+  const SWord8  s2056 = table7[s2040];
+  const SWord8  s2057 = s2055 ^ s2056;
+  const SWord8  s2058 = s2054 ^ s2057;
+  const SWord8  s2059 = s2053 ^ s2058;
+  const SWord8  s2060 = table7[s2034];
+  const SWord8  s2061 = table8[s2036];
+  const SWord8  s2062 = table9[s2038];
+  const SWord8  s2063 = table6[s2040];
+  const SWord8  s2064 = s2062 ^ s2063;
+  const SWord8  s2065 = s2061 ^ s2064;
+  const SWord8  s2066 = s2060 ^ s2065;
+  const SWord16 s2067 = (((SWord16) s2059) << 8) | ((SWord16) s2066);
+  const SWord32 s2068 = (((SWord32) s2052) << 16) | ((SWord32) s2067);
+  const SWord32 s2069 = s2033 ^ s2068;
+  const SWord8  s2070 = (SWord8) (s2069 >> 24);
+  const SWord32 s2071 = table1[s2070];
+  const SWord8  s2072 = (SWord8) (s1930 >> 24);
+  const SWord32 s2073 = table1[s2072];
+  const SWord8  s2074 = (SWord8) (s1980 >> 16);
+  const SWord32 s2075 = table3[s2074];
+  const SWord32 s2076 = s2073 ^ s2075;
+  const SWord8  s2077 = (SWord8) (s2030 >> 8);
+  const SWord32 s2078 = table4[s2077];
+  const SWord32 s2079 = s2076 ^ s2078;
+  const SWord8  s2080 = (SWord8) s1881;
+  const SWord32 s2081 = table5[s2080];
+  const SWord32 s2082 = s2079 ^ s2081;
+  const SWord8  s2083 = (SWord8) (s621 >> 24);
+  const SWord8  s2084 = table6[s2083];
+  const SWord8  s2085 = (SWord8) (s621 >> 16);
+  const SWord8  s2086 = table7[s2085];
+  const SWord8  s2087 = (SWord8) (s621 >> 8);
+  const SWord8  s2088 = table8[s2087];
+  const SWord8  s2089 = (SWord8) s621;
+  const SWord8  s2090 = table9[s2089];
+  const SWord8  s2091 = s2088 ^ s2090;
+  const SWord8  s2092 = s2086 ^ s2091;
+  const SWord8  s2093 = s2084 ^ s2092;
+  const SWord8  s2094 = table9[s2083];
+  const SWord8  s2095 = table6[s2085];
+  const SWord8  s2096 = table7[s2087];
+  const SWord8  s2097 = table8[s2089];
+  const SWord8  s2098 = s2096 ^ s2097;
+  const SWord8  s2099 = s2095 ^ s2098;
+  const SWord8  s2100 = s2094 ^ s2099;
+  const SWord16 s2101 = (((SWord16) s2093) << 8) | ((SWord16) s2100);
+  const SWord8  s2102 = table8[s2083];
+  const SWord8  s2103 = table9[s2085];
+  const SWord8  s2104 = table6[s2087];
+  const SWord8  s2105 = table7[s2089];
+  const SWord8  s2106 = s2104 ^ s2105;
+  const SWord8  s2107 = s2103 ^ s2106;
+  const SWord8  s2108 = s2102 ^ s2107;
+  const SWord8  s2109 = table7[s2083];
+  const SWord8  s2110 = table8[s2085];
+  const SWord8  s2111 = table9[s2087];
+  const SWord8  s2112 = table6[s2089];
+  const SWord8  s2113 = s2111 ^ s2112;
+  const SWord8  s2114 = s2110 ^ s2113;
+  const SWord8  s2115 = s2109 ^ s2114;
+  const SWord16 s2116 = (((SWord16) s2108) << 8) | ((SWord16) s2115);
+  const SWord32 s2117 = (((SWord32) s2101) << 16) | ((SWord32) s2116);
+  const SWord32 s2118 = s2082 ^ s2117;
+  const SWord8  s2119 = (SWord8) (s2118 >> 16);
+  const SWord32 s2120 = table3[s2119];
+  const SWord32 s2121 = s2071 ^ s2120;
+  const SWord8  s2122 = (SWord8) (s1980 >> 24);
+  const SWord32 s2123 = table1[s2122];
+  const SWord8  s2124 = (SWord8) (s2030 >> 16);
+  const SWord32 s2125 = table3[s2124];
+  const SWord32 s2126 = s2123 ^ s2125;
+  const SWord8  s2127 = (SWord8) (s1881 >> 8);
+  const SWord32 s2128 = table4[s2127];
+  const SWord32 s2129 = s2126 ^ s2128;
+  const SWord8  s2130 = (SWord8) s1930;
+  const SWord32 s2131 = table5[s2130];
+  const SWord32 s2132 = s2129 ^ s2131;
+  const SWord8  s2133 = (SWord8) (s620 >> 24);
+  const SWord8  s2134 = table6[s2133];
+  const SWord8  s2135 = (SWord8) (s620 >> 16);
+  const SWord8  s2136 = table7[s2135];
+  const SWord8  s2137 = (SWord8) (s620 >> 8);
+  const SWord8  s2138 = table8[s2137];
+  const SWord8  s2139 = (SWord8) s620;
+  const SWord8  s2140 = table9[s2139];
+  const SWord8  s2141 = s2138 ^ s2140;
+  const SWord8  s2142 = s2136 ^ s2141;
+  const SWord8  s2143 = s2134 ^ s2142;
+  const SWord8  s2144 = table9[s2133];
+  const SWord8  s2145 = table6[s2135];
+  const SWord8  s2146 = table7[s2137];
+  const SWord8  s2147 = table8[s2139];
+  const SWord8  s2148 = s2146 ^ s2147;
+  const SWord8  s2149 = s2145 ^ s2148;
+  const SWord8  s2150 = s2144 ^ s2149;
+  const SWord16 s2151 = (((SWord16) s2143) << 8) | ((SWord16) s2150);
+  const SWord8  s2152 = table8[s2133];
+  const SWord8  s2153 = table9[s2135];
+  const SWord8  s2154 = table6[s2137];
+  const SWord8  s2155 = table7[s2139];
+  const SWord8  s2156 = s2154 ^ s2155;
+  const SWord8  s2157 = s2153 ^ s2156;
+  const SWord8  s2158 = s2152 ^ s2157;
+  const SWord8  s2159 = table7[s2133];
+  const SWord8  s2160 = table8[s2135];
+  const SWord8  s2161 = table9[s2137];
+  const SWord8  s2162 = table6[s2139];
+  const SWord8  s2163 = s2161 ^ s2162;
+  const SWord8  s2164 = s2160 ^ s2163;
+  const SWord8  s2165 = s2159 ^ s2164;
+  const SWord16 s2166 = (((SWord16) s2158) << 8) | ((SWord16) s2165);
+  const SWord32 s2167 = (((SWord32) s2151) << 16) | ((SWord32) s2166);
+  const SWord32 s2168 = s2132 ^ s2167;
+  const SWord8  s2169 = (SWord8) (s2168 >> 8);
+  const SWord32 s2170 = table4[s2169];
+  const SWord32 s2171 = s2121 ^ s2170;
+  const SWord8  s2172 = (SWord8) (s2030 >> 24);
+  const SWord32 s2173 = table1[s2172];
+  const SWord8  s2174 = (SWord8) (s1881 >> 16);
+  const SWord32 s2175 = table3[s2174];
+  const SWord32 s2176 = s2173 ^ s2175;
+  const SWord8  s2177 = (SWord8) (s1930 >> 8);
+  const SWord32 s2178 = table4[s2177];
+  const SWord32 s2179 = s2176 ^ s2178;
+  const SWord8  s2180 = (SWord8) s1980;
+  const SWord32 s2181 = table5[s2180];
+  const SWord32 s2182 = s2179 ^ s2181;
+  const SWord8  s2183 = (SWord8) (s619 >> 24);
+  const SWord8  s2184 = table6[s2183];
+  const SWord8  s2185 = (SWord8) (s619 >> 16);
+  const SWord8  s2186 = table7[s2185];
+  const SWord8  s2187 = (SWord8) (s619 >> 8);
+  const SWord8  s2188 = table8[s2187];
+  const SWord8  s2189 = (SWord8) s619;
+  const SWord8  s2190 = table9[s2189];
+  const SWord8  s2191 = s2188 ^ s2190;
+  const SWord8  s2192 = s2186 ^ s2191;
+  const SWord8  s2193 = s2184 ^ s2192;
+  const SWord8  s2194 = table9[s2183];
+  const SWord8  s2195 = table6[s2185];
+  const SWord8  s2196 = table7[s2187];
+  const SWord8  s2197 = table8[s2189];
+  const SWord8  s2198 = s2196 ^ s2197;
+  const SWord8  s2199 = s2195 ^ s2198;
+  const SWord8  s2200 = s2194 ^ s2199;
+  const SWord16 s2201 = (((SWord16) s2193) << 8) | ((SWord16) s2200);
+  const SWord8  s2202 = table8[s2183];
+  const SWord8  s2203 = table9[s2185];
+  const SWord8  s2204 = table6[s2187];
+  const SWord8  s2205 = table7[s2189];
+  const SWord8  s2206 = s2204 ^ s2205;
+  const SWord8  s2207 = s2203 ^ s2206;
+  const SWord8  s2208 = s2202 ^ s2207;
+  const SWord8  s2209 = table7[s2183];
+  const SWord8  s2210 = table8[s2185];
+  const SWord8  s2211 = table9[s2187];
+  const SWord8  s2212 = table6[s2189];
+  const SWord8  s2213 = s2211 ^ s2212;
+  const SWord8  s2214 = s2210 ^ s2213;
+  const SWord8  s2215 = s2209 ^ s2214;
+  const SWord16 s2216 = (((SWord16) s2208) << 8) | ((SWord16) s2215);
+  const SWord32 s2217 = (((SWord32) s2201) << 16) | ((SWord32) s2216);
+  const SWord32 s2218 = s2182 ^ s2217;
+  const SWord8  s2219 = (SWord8) s2218;
+  const SWord32 s2220 = table5[s2219];
+  const SWord32 s2221 = s2171 ^ s2220;
+  const SWord8  s2222 = (SWord8) (s601 >> 24);
+  const SWord8  s2223 = table6[s2222];
+  const SWord8  s2224 = (SWord8) (s601 >> 16);
+  const SWord8  s2225 = table7[s2224];
+  const SWord8  s2226 = (SWord8) (s601 >> 8);
+  const SWord8  s2227 = table8[s2226];
+  const SWord8  s2228 = (SWord8) s601;
+  const SWord8  s2229 = table9[s2228];
+  const SWord8  s2230 = s2227 ^ s2229;
+  const SWord8  s2231 = s2225 ^ s2230;
+  const SWord8  s2232 = s2223 ^ s2231;
+  const SWord8  s2233 = table9[s2222];
+  const SWord8  s2234 = table6[s2224];
+  const SWord8  s2235 = table7[s2226];
+  const SWord8  s2236 = table8[s2228];
+  const SWord8  s2237 = s2235 ^ s2236;
+  const SWord8  s2238 = s2234 ^ s2237;
+  const SWord8  s2239 = s2233 ^ s2238;
+  const SWord16 s2240 = (((SWord16) s2232) << 8) | ((SWord16) s2239);
+  const SWord8  s2241 = table8[s2222];
+  const SWord8  s2242 = table9[s2224];
+  const SWord8  s2243 = table6[s2226];
+  const SWord8  s2244 = table7[s2228];
+  const SWord8  s2245 = s2243 ^ s2244;
+  const SWord8  s2246 = s2242 ^ s2245;
+  const SWord8  s2247 = s2241 ^ s2246;
+  const SWord8  s2248 = table7[s2222];
+  const SWord8  s2249 = table8[s2224];
+  const SWord8  s2250 = table9[s2226];
+  const SWord8  s2251 = table6[s2228];
+  const SWord8  s2252 = s2250 ^ s2251;
+  const SWord8  s2253 = s2249 ^ s2252;
+  const SWord8  s2254 = s2248 ^ s2253;
+  const SWord16 s2255 = (((SWord16) s2247) << 8) | ((SWord16) s2254);
+  const SWord32 s2256 = (((SWord32) s2240) << 16) | ((SWord32) s2255);
+  const SWord32 s2257 = s2221 ^ s2256;
+  const SWord8  s2258 = (SWord8) (s2257 >> 24);
+  const SWord32 s2259 = table1[s2258];
+  const SWord8  s2260 = (SWord8) (s2118 >> 24);
+  const SWord32 s2261 = table1[s2260];
+  const SWord8  s2262 = (SWord8) (s2168 >> 16);
+  const SWord32 s2263 = table3[s2262];
+  const SWord32 s2264 = s2261 ^ s2263;
+  const SWord8  s2265 = (SWord8) (s2218 >> 8);
+  const SWord32 s2266 = table4[s2265];
+  const SWord32 s2267 = s2264 ^ s2266;
+  const SWord8  s2268 = (SWord8) s2069;
+  const SWord32 s2269 = table5[s2268];
+  const SWord32 s2270 = s2267 ^ s2269;
+  const SWord8  s2271 = (SWord8) (s604 >> 24);
+  const SWord8  s2272 = table6[s2271];
+  const SWord8  s2273 = (SWord8) (s604 >> 16);
+  const SWord8  s2274 = table7[s2273];
+  const SWord8  s2275 = (SWord8) (s604 >> 8);
+  const SWord8  s2276 = table8[s2275];
+  const SWord8  s2277 = (SWord8) s604;
+  const SWord8  s2278 = table9[s2277];
+  const SWord8  s2279 = s2276 ^ s2278;
+  const SWord8  s2280 = s2274 ^ s2279;
+  const SWord8  s2281 = s2272 ^ s2280;
+  const SWord8  s2282 = table9[s2271];
+  const SWord8  s2283 = table6[s2273];
+  const SWord8  s2284 = table7[s2275];
+  const SWord8  s2285 = table8[s2277];
+  const SWord8  s2286 = s2284 ^ s2285;
+  const SWord8  s2287 = s2283 ^ s2286;
+  const SWord8  s2288 = s2282 ^ s2287;
+  const SWord16 s2289 = (((SWord16) s2281) << 8) | ((SWord16) s2288);
+  const SWord8  s2290 = table8[s2271];
+  const SWord8  s2291 = table9[s2273];
+  const SWord8  s2292 = table6[s2275];
+  const SWord8  s2293 = table7[s2277];
+  const SWord8  s2294 = s2292 ^ s2293;
+  const SWord8  s2295 = s2291 ^ s2294;
+  const SWord8  s2296 = s2290 ^ s2295;
+  const SWord8  s2297 = table7[s2271];
+  const SWord8  s2298 = table8[s2273];
+  const SWord8  s2299 = table9[s2275];
+  const SWord8  s2300 = table6[s2277];
+  const SWord8  s2301 = s2299 ^ s2300;
+  const SWord8  s2302 = s2298 ^ s2301;
+  const SWord8  s2303 = s2297 ^ s2302;
+  const SWord16 s2304 = (((SWord16) s2296) << 8) | ((SWord16) s2303);
+  const SWord32 s2305 = (((SWord32) s2289) << 16) | ((SWord32) s2304);
+  const SWord32 s2306 = s2270 ^ s2305;
+  const SWord8  s2307 = (SWord8) (s2306 >> 16);
+  const SWord32 s2308 = table3[s2307];
+  const SWord32 s2309 = s2259 ^ s2308;
+  const SWord8  s2310 = (SWord8) (s2168 >> 24);
+  const SWord32 s2311 = table1[s2310];
+  const SWord8  s2312 = (SWord8) (s2218 >> 16);
+  const SWord32 s2313 = table3[s2312];
+  const SWord32 s2314 = s2311 ^ s2313;
+  const SWord8  s2315 = (SWord8) (s2069 >> 8);
+  const SWord32 s2316 = table4[s2315];
+  const SWord32 s2317 = s2314 ^ s2316;
+  const SWord8  s2318 = (SWord8) s2118;
+  const SWord32 s2319 = table5[s2318];
+  const SWord32 s2320 = s2317 ^ s2319;
+  const SWord8  s2321 = (SWord8) (s603 >> 24);
+  const SWord8  s2322 = table6[s2321];
+  const SWord8  s2323 = (SWord8) (s603 >> 16);
+  const SWord8  s2324 = table7[s2323];
+  const SWord8  s2325 = (SWord8) (s603 >> 8);
+  const SWord8  s2326 = table8[s2325];
+  const SWord8  s2327 = (SWord8) s603;
+  const SWord8  s2328 = table9[s2327];
+  const SWord8  s2329 = s2326 ^ s2328;
+  const SWord8  s2330 = s2324 ^ s2329;
+  const SWord8  s2331 = s2322 ^ s2330;
+  const SWord8  s2332 = table9[s2321];
+  const SWord8  s2333 = table6[s2323];
+  const SWord8  s2334 = table7[s2325];
+  const SWord8  s2335 = table8[s2327];
+  const SWord8  s2336 = s2334 ^ s2335;
+  const SWord8  s2337 = s2333 ^ s2336;
+  const SWord8  s2338 = s2332 ^ s2337;
+  const SWord16 s2339 = (((SWord16) s2331) << 8) | ((SWord16) s2338);
+  const SWord8  s2340 = table8[s2321];
+  const SWord8  s2341 = table9[s2323];
+  const SWord8  s2342 = table6[s2325];
+  const SWord8  s2343 = table7[s2327];
+  const SWord8  s2344 = s2342 ^ s2343;
+  const SWord8  s2345 = s2341 ^ s2344;
+  const SWord8  s2346 = s2340 ^ s2345;
+  const SWord8  s2347 = table7[s2321];
+  const SWord8  s2348 = table8[s2323];
+  const SWord8  s2349 = table9[s2325];
+  const SWord8  s2350 = table6[s2327];
+  const SWord8  s2351 = s2349 ^ s2350;
+  const SWord8  s2352 = s2348 ^ s2351;
+  const SWord8  s2353 = s2347 ^ s2352;
+  const SWord16 s2354 = (((SWord16) s2346) << 8) | ((SWord16) s2353);
+  const SWord32 s2355 = (((SWord32) s2339) << 16) | ((SWord32) s2354);
+  const SWord32 s2356 = s2320 ^ s2355;
+  const SWord8  s2357 = (SWord8) (s2356 >> 8);
+  const SWord32 s2358 = table4[s2357];
+  const SWord32 s2359 = s2309 ^ s2358;
+  const SWord8  s2360 = (SWord8) (s2218 >> 24);
+  const SWord32 s2361 = table1[s2360];
+  const SWord8  s2362 = (SWord8) (s2069 >> 16);
+  const SWord32 s2363 = table3[s2362];
+  const SWord32 s2364 = s2361 ^ s2363;
+  const SWord8  s2365 = (SWord8) (s2118 >> 8);
+  const SWord32 s2366 = table4[s2365];
+  const SWord32 s2367 = s2364 ^ s2366;
+  const SWord8  s2368 = (SWord8) s2168;
+  const SWord32 s2369 = table5[s2368];
+  const SWord32 s2370 = s2367 ^ s2369;
+  const SWord8  s2371 = (SWord8) (s602 >> 24);
+  const SWord8  s2372 = table6[s2371];
+  const SWord8  s2373 = (SWord8) (s602 >> 16);
+  const SWord8  s2374 = table7[s2373];
+  const SWord8  s2375 = (SWord8) (s602 >> 8);
+  const SWord8  s2376 = table8[s2375];
+  const SWord8  s2377 = (SWord8) s602;
+  const SWord8  s2378 = table9[s2377];
+  const SWord8  s2379 = s2376 ^ s2378;
+  const SWord8  s2380 = s2374 ^ s2379;
+  const SWord8  s2381 = s2372 ^ s2380;
+  const SWord8  s2382 = table9[s2371];
+  const SWord8  s2383 = table6[s2373];
+  const SWord8  s2384 = table7[s2375];
+  const SWord8  s2385 = table8[s2377];
+  const SWord8  s2386 = s2384 ^ s2385;
+  const SWord8  s2387 = s2383 ^ s2386;
+  const SWord8  s2388 = s2382 ^ s2387;
+  const SWord16 s2389 = (((SWord16) s2381) << 8) | ((SWord16) s2388);
+  const SWord8  s2390 = table8[s2371];
+  const SWord8  s2391 = table9[s2373];
+  const SWord8  s2392 = table6[s2375];
+  const SWord8  s2393 = table7[s2377];
+  const SWord8  s2394 = s2392 ^ s2393;
+  const SWord8  s2395 = s2391 ^ s2394;
+  const SWord8  s2396 = s2390 ^ s2395;
+  const SWord8  s2397 = table7[s2371];
+  const SWord8  s2398 = table8[s2373];
+  const SWord8  s2399 = table9[s2375];
+  const SWord8  s2400 = table6[s2377];
+  const SWord8  s2401 = s2399 ^ s2400;
+  const SWord8  s2402 = s2398 ^ s2401;
+  const SWord8  s2403 = s2397 ^ s2402;
+  const SWord16 s2404 = (((SWord16) s2396) << 8) | ((SWord16) s2403);
+  const SWord32 s2405 = (((SWord32) s2389) << 16) | ((SWord32) s2404);
+  const SWord32 s2406 = s2370 ^ s2405;
+  const SWord8  s2407 = (SWord8) s2406;
+  const SWord32 s2408 = table5[s2407];
+  const SWord32 s2409 = s2359 ^ s2408;
+  const SWord8  s2410 = (SWord8) (s584 >> 24);
+  const SWord8  s2411 = table6[s2410];
+  const SWord8  s2412 = (SWord8) (s584 >> 16);
+  const SWord8  s2413 = table7[s2412];
+  const SWord8  s2414 = (SWord8) (s584 >> 8);
+  const SWord8  s2415 = table8[s2414];
+  const SWord8  s2416 = (SWord8) s584;
+  const SWord8  s2417 = table9[s2416];
+  const SWord8  s2418 = s2415 ^ s2417;
+  const SWord8  s2419 = s2413 ^ s2418;
+  const SWord8  s2420 = s2411 ^ s2419;
+  const SWord8  s2421 = table9[s2410];
+  const SWord8  s2422 = table6[s2412];
+  const SWord8  s2423 = table7[s2414];
+  const SWord8  s2424 = table8[s2416];
+  const SWord8  s2425 = s2423 ^ s2424;
+  const SWord8  s2426 = s2422 ^ s2425;
+  const SWord8  s2427 = s2421 ^ s2426;
+  const SWord16 s2428 = (((SWord16) s2420) << 8) | ((SWord16) s2427);
+  const SWord8  s2429 = table8[s2410];
+  const SWord8  s2430 = table9[s2412];
+  const SWord8  s2431 = table6[s2414];
+  const SWord8  s2432 = table7[s2416];
+  const SWord8  s2433 = s2431 ^ s2432;
+  const SWord8  s2434 = s2430 ^ s2433;
+  const SWord8  s2435 = s2429 ^ s2434;
+  const SWord8  s2436 = table7[s2410];
+  const SWord8  s2437 = table8[s2412];
+  const SWord8  s2438 = table9[s2414];
+  const SWord8  s2439 = table6[s2416];
+  const SWord8  s2440 = s2438 ^ s2439;
+  const SWord8  s2441 = s2437 ^ s2440;
+  const SWord8  s2442 = s2436 ^ s2441;
+  const SWord16 s2443 = (((SWord16) s2435) << 8) | ((SWord16) s2442);
+  const SWord32 s2444 = (((SWord32) s2428) << 16) | ((SWord32) s2443);
+  const SWord32 s2445 = s2409 ^ s2444;
+  const SWord8  s2446 = (SWord8) (s2445 >> 24);
+  const SWord32 s2447 = table1[s2446];
+  const SWord8  s2448 = (SWord8) (s2306 >> 24);
+  const SWord32 s2449 = table1[s2448];
+  const SWord8  s2450 = (SWord8) (s2356 >> 16);
+  const SWord32 s2451 = table3[s2450];
+  const SWord32 s2452 = s2449 ^ s2451;
+  const SWord8  s2453 = (SWord8) (s2406 >> 8);
+  const SWord32 s2454 = table4[s2453];
+  const SWord32 s2455 = s2452 ^ s2454;
+  const SWord8  s2456 = (SWord8) s2257;
+  const SWord32 s2457 = table5[s2456];
+  const SWord32 s2458 = s2455 ^ s2457;
+  const SWord8  s2459 = (SWord8) (s587 >> 24);
+  const SWord8  s2460 = table6[s2459];
+  const SWord8  s2461 = (SWord8) (s587 >> 16);
+  const SWord8  s2462 = table7[s2461];
+  const SWord8  s2463 = (SWord8) (s587 >> 8);
+  const SWord8  s2464 = table8[s2463];
+  const SWord8  s2465 = (SWord8) s587;
+  const SWord8  s2466 = table9[s2465];
+  const SWord8  s2467 = s2464 ^ s2466;
+  const SWord8  s2468 = s2462 ^ s2467;
+  const SWord8  s2469 = s2460 ^ s2468;
+  const SWord8  s2470 = table9[s2459];
+  const SWord8  s2471 = table6[s2461];
+  const SWord8  s2472 = table7[s2463];
+  const SWord8  s2473 = table8[s2465];
+  const SWord8  s2474 = s2472 ^ s2473;
+  const SWord8  s2475 = s2471 ^ s2474;
+  const SWord8  s2476 = s2470 ^ s2475;
+  const SWord16 s2477 = (((SWord16) s2469) << 8) | ((SWord16) s2476);
+  const SWord8  s2478 = table8[s2459];
+  const SWord8  s2479 = table9[s2461];
+  const SWord8  s2480 = table6[s2463];
+  const SWord8  s2481 = table7[s2465];
+  const SWord8  s2482 = s2480 ^ s2481;
+  const SWord8  s2483 = s2479 ^ s2482;
+  const SWord8  s2484 = s2478 ^ s2483;
+  const SWord8  s2485 = table7[s2459];
+  const SWord8  s2486 = table8[s2461];
+  const SWord8  s2487 = table9[s2463];
+  const SWord8  s2488 = table6[s2465];
+  const SWord8  s2489 = s2487 ^ s2488;
+  const SWord8  s2490 = s2486 ^ s2489;
+  const SWord8  s2491 = s2485 ^ s2490;
+  const SWord16 s2492 = (((SWord16) s2484) << 8) | ((SWord16) s2491);
+  const SWord32 s2493 = (((SWord32) s2477) << 16) | ((SWord32) s2492);
+  const SWord32 s2494 = s2458 ^ s2493;
+  const SWord8  s2495 = (SWord8) (s2494 >> 16);
+  const SWord32 s2496 = table3[s2495];
+  const SWord32 s2497 = s2447 ^ s2496;
+  const SWord8  s2498 = (SWord8) (s2356 >> 24);
+  const SWord32 s2499 = table1[s2498];
+  const SWord8  s2500 = (SWord8) (s2406 >> 16);
+  const SWord32 s2501 = table3[s2500];
+  const SWord32 s2502 = s2499 ^ s2501;
+  const SWord8  s2503 = (SWord8) (s2257 >> 8);
+  const SWord32 s2504 = table4[s2503];
+  const SWord32 s2505 = s2502 ^ s2504;
+  const SWord8  s2506 = (SWord8) s2306;
+  const SWord32 s2507 = table5[s2506];
+  const SWord32 s2508 = s2505 ^ s2507;
+  const SWord8  s2509 = (SWord8) (s586 >> 24);
+  const SWord8  s2510 = table6[s2509];
+  const SWord8  s2511 = (SWord8) (s586 >> 16);
+  const SWord8  s2512 = table7[s2511];
+  const SWord8  s2513 = (SWord8) (s586 >> 8);
+  const SWord8  s2514 = table8[s2513];
+  const SWord8  s2515 = (SWord8) s586;
+  const SWord8  s2516 = table9[s2515];
+  const SWord8  s2517 = s2514 ^ s2516;
+  const SWord8  s2518 = s2512 ^ s2517;
+  const SWord8  s2519 = s2510 ^ s2518;
+  const SWord8  s2520 = table9[s2509];
+  const SWord8  s2521 = table6[s2511];
+  const SWord8  s2522 = table7[s2513];
+  const SWord8  s2523 = table8[s2515];
+  const SWord8  s2524 = s2522 ^ s2523;
+  const SWord8  s2525 = s2521 ^ s2524;
+  const SWord8  s2526 = s2520 ^ s2525;
+  const SWord16 s2527 = (((SWord16) s2519) << 8) | ((SWord16) s2526);
+  const SWord8  s2528 = table8[s2509];
+  const SWord8  s2529 = table9[s2511];
+  const SWord8  s2530 = table6[s2513];
+  const SWord8  s2531 = table7[s2515];
+  const SWord8  s2532 = s2530 ^ s2531;
+  const SWord8  s2533 = s2529 ^ s2532;
+  const SWord8  s2534 = s2528 ^ s2533;
+  const SWord8  s2535 = table7[s2509];
+  const SWord8  s2536 = table8[s2511];
+  const SWord8  s2537 = table9[s2513];
+  const SWord8  s2538 = table6[s2515];
+  const SWord8  s2539 = s2537 ^ s2538;
+  const SWord8  s2540 = s2536 ^ s2539;
+  const SWord8  s2541 = s2535 ^ s2540;
+  const SWord16 s2542 = (((SWord16) s2534) << 8) | ((SWord16) s2541);
+  const SWord32 s2543 = (((SWord32) s2527) << 16) | ((SWord32) s2542);
+  const SWord32 s2544 = s2508 ^ s2543;
+  const SWord8  s2545 = (SWord8) (s2544 >> 8);
+  const SWord32 s2546 = table4[s2545];
+  const SWord32 s2547 = s2497 ^ s2546;
+  const SWord8  s2548 = (SWord8) (s2406 >> 24);
+  const SWord32 s2549 = table1[s2548];
+  const SWord8  s2550 = (SWord8) (s2257 >> 16);
+  const SWord32 s2551 = table3[s2550];
+  const SWord32 s2552 = s2549 ^ s2551;
+  const SWord8  s2553 = (SWord8) (s2306 >> 8);
+  const SWord32 s2554 = table4[s2553];
+  const SWord32 s2555 = s2552 ^ s2554;
+  const SWord8  s2556 = (SWord8) s2356;
+  const SWord32 s2557 = table5[s2556];
+  const SWord32 s2558 = s2555 ^ s2557;
+  const SWord8  s2559 = (SWord8) (s585 >> 24);
+  const SWord8  s2560 = table6[s2559];
+  const SWord8  s2561 = (SWord8) (s585 >> 16);
+  const SWord8  s2562 = table7[s2561];
+  const SWord8  s2563 = (SWord8) (s585 >> 8);
+  const SWord8  s2564 = table8[s2563];
+  const SWord8  s2565 = (SWord8) s585;
+  const SWord8  s2566 = table9[s2565];
+  const SWord8  s2567 = s2564 ^ s2566;
+  const SWord8  s2568 = s2562 ^ s2567;
+  const SWord8  s2569 = s2560 ^ s2568;
+  const SWord8  s2570 = table9[s2559];
+  const SWord8  s2571 = table6[s2561];
+  const SWord8  s2572 = table7[s2563];
+  const SWord8  s2573 = table8[s2565];
+  const SWord8  s2574 = s2572 ^ s2573;
+  const SWord8  s2575 = s2571 ^ s2574;
+  const SWord8  s2576 = s2570 ^ s2575;
+  const SWord16 s2577 = (((SWord16) s2569) << 8) | ((SWord16) s2576);
+  const SWord8  s2578 = table8[s2559];
+  const SWord8  s2579 = table9[s2561];
+  const SWord8  s2580 = table6[s2563];
+  const SWord8  s2581 = table7[s2565];
+  const SWord8  s2582 = s2580 ^ s2581;
+  const SWord8  s2583 = s2579 ^ s2582;
+  const SWord8  s2584 = s2578 ^ s2583;
+  const SWord8  s2585 = table7[s2559];
+  const SWord8  s2586 = table8[s2561];
+  const SWord8  s2587 = table9[s2563];
+  const SWord8  s2588 = table6[s2565];
+  const SWord8  s2589 = s2587 ^ s2588;
+  const SWord8  s2590 = s2586 ^ s2589;
+  const SWord8  s2591 = s2585 ^ s2590;
+  const SWord16 s2592 = (((SWord16) s2584) << 8) | ((SWord16) s2591);
+  const SWord32 s2593 = (((SWord32) s2577) << 16) | ((SWord32) s2592);
+  const SWord32 s2594 = s2558 ^ s2593;
+  const SWord8  s2595 = (SWord8) s2594;
+  const SWord32 s2596 = table5[s2595];
+  const SWord32 s2597 = s2547 ^ s2596;
+  const SWord8  s2598 = (SWord8) (s567 >> 24);
+  const SWord8  s2599 = table6[s2598];
+  const SWord8  s2600 = (SWord8) (s567 >> 16);
+  const SWord8  s2601 = table7[s2600];
+  const SWord8  s2602 = (SWord8) (s567 >> 8);
+  const SWord8  s2603 = table8[s2602];
+  const SWord8  s2604 = (SWord8) s567;
+  const SWord8  s2605 = table9[s2604];
+  const SWord8  s2606 = s2603 ^ s2605;
+  const SWord8  s2607 = s2601 ^ s2606;
+  const SWord8  s2608 = s2599 ^ s2607;
+  const SWord8  s2609 = table9[s2598];
+  const SWord8  s2610 = table6[s2600];
+  const SWord8  s2611 = table7[s2602];
+  const SWord8  s2612 = table8[s2604];
+  const SWord8  s2613 = s2611 ^ s2612;
+  const SWord8  s2614 = s2610 ^ s2613;
+  const SWord8  s2615 = s2609 ^ s2614;
+  const SWord16 s2616 = (((SWord16) s2608) << 8) | ((SWord16) s2615);
+  const SWord8  s2617 = table8[s2598];
+  const SWord8  s2618 = table9[s2600];
+  const SWord8  s2619 = table6[s2602];
+  const SWord8  s2620 = table7[s2604];
+  const SWord8  s2621 = s2619 ^ s2620;
+  const SWord8  s2622 = s2618 ^ s2621;
+  const SWord8  s2623 = s2617 ^ s2622;
+  const SWord8  s2624 = table7[s2598];
+  const SWord8  s2625 = table8[s2600];
+  const SWord8  s2626 = table9[s2602];
+  const SWord8  s2627 = table6[s2604];
+  const SWord8  s2628 = s2626 ^ s2627;
+  const SWord8  s2629 = s2625 ^ s2628;
+  const SWord8  s2630 = s2624 ^ s2629;
+  const SWord16 s2631 = (((SWord16) s2623) << 8) | ((SWord16) s2630);
+  const SWord32 s2632 = (((SWord32) s2616) << 16) | ((SWord32) s2631);
+  const SWord32 s2633 = s2597 ^ s2632;
+  const SWord8  s2634 = (SWord8) (s2633 >> 24);
+  const SWord32 s2635 = table1[s2634];
+  const SWord8  s2636 = (SWord8) (s2494 >> 24);
+  const SWord32 s2637 = table1[s2636];
+  const SWord8  s2638 = (SWord8) (s2544 >> 16);
+  const SWord32 s2639 = table3[s2638];
+  const SWord32 s2640 = s2637 ^ s2639;
+  const SWord8  s2641 = (SWord8) (s2594 >> 8);
+  const SWord32 s2642 = table4[s2641];
+  const SWord32 s2643 = s2640 ^ s2642;
+  const SWord8  s2644 = (SWord8) s2445;
+  const SWord32 s2645 = table5[s2644];
+  const SWord32 s2646 = s2643 ^ s2645;
+  const SWord8  s2647 = (SWord8) (s570 >> 24);
+  const SWord8  s2648 = table6[s2647];
+  const SWord8  s2649 = (SWord8) (s570 >> 16);
+  const SWord8  s2650 = table7[s2649];
+  const SWord8  s2651 = (SWord8) (s570 >> 8);
+  const SWord8  s2652 = table8[s2651];
+  const SWord8  s2653 = (SWord8) s570;
+  const SWord8  s2654 = table9[s2653];
+  const SWord8  s2655 = s2652 ^ s2654;
+  const SWord8  s2656 = s2650 ^ s2655;
+  const SWord8  s2657 = s2648 ^ s2656;
+  const SWord8  s2658 = table9[s2647];
+  const SWord8  s2659 = table6[s2649];
+  const SWord8  s2660 = table7[s2651];
+  const SWord8  s2661 = table8[s2653];
+  const SWord8  s2662 = s2660 ^ s2661;
+  const SWord8  s2663 = s2659 ^ s2662;
+  const SWord8  s2664 = s2658 ^ s2663;
+  const SWord16 s2665 = (((SWord16) s2657) << 8) | ((SWord16) s2664);
+  const SWord8  s2666 = table8[s2647];
+  const SWord8  s2667 = table9[s2649];
+  const SWord8  s2668 = table6[s2651];
+  const SWord8  s2669 = table7[s2653];
+  const SWord8  s2670 = s2668 ^ s2669;
+  const SWord8  s2671 = s2667 ^ s2670;
+  const SWord8  s2672 = s2666 ^ s2671;
+  const SWord8  s2673 = table7[s2647];
+  const SWord8  s2674 = table8[s2649];
+  const SWord8  s2675 = table9[s2651];
+  const SWord8  s2676 = table6[s2653];
+  const SWord8  s2677 = s2675 ^ s2676;
+  const SWord8  s2678 = s2674 ^ s2677;
+  const SWord8  s2679 = s2673 ^ s2678;
+  const SWord16 s2680 = (((SWord16) s2672) << 8) | ((SWord16) s2679);
+  const SWord32 s2681 = (((SWord32) s2665) << 16) | ((SWord32) s2680);
+  const SWord32 s2682 = s2646 ^ s2681;
+  const SWord8  s2683 = (SWord8) (s2682 >> 16);
+  const SWord32 s2684 = table3[s2683];
+  const SWord32 s2685 = s2635 ^ s2684;
+  const SWord8  s2686 = (SWord8) (s2544 >> 24);
+  const SWord32 s2687 = table1[s2686];
+  const SWord8  s2688 = (SWord8) (s2594 >> 16);
+  const SWord32 s2689 = table3[s2688];
+  const SWord32 s2690 = s2687 ^ s2689;
+  const SWord8  s2691 = (SWord8) (s2445 >> 8);
+  const SWord32 s2692 = table4[s2691];
+  const SWord32 s2693 = s2690 ^ s2692;
+  const SWord8  s2694 = (SWord8) s2494;
+  const SWord32 s2695 = table5[s2694];
+  const SWord32 s2696 = s2693 ^ s2695;
+  const SWord8  s2697 = (SWord8) (s569 >> 24);
+  const SWord8  s2698 = table6[s2697];
+  const SWord8  s2699 = (SWord8) (s569 >> 16);
+  const SWord8  s2700 = table7[s2699];
+  const SWord8  s2701 = (SWord8) (s569 >> 8);
+  const SWord8  s2702 = table8[s2701];
+  const SWord8  s2703 = (SWord8) s569;
+  const SWord8  s2704 = table9[s2703];
+  const SWord8  s2705 = s2702 ^ s2704;
+  const SWord8  s2706 = s2700 ^ s2705;
+  const SWord8  s2707 = s2698 ^ s2706;
+  const SWord8  s2708 = table9[s2697];
+  const SWord8  s2709 = table6[s2699];
+  const SWord8  s2710 = table7[s2701];
+  const SWord8  s2711 = table8[s2703];
+  const SWord8  s2712 = s2710 ^ s2711;
+  const SWord8  s2713 = s2709 ^ s2712;
+  const SWord8  s2714 = s2708 ^ s2713;
+  const SWord16 s2715 = (((SWord16) s2707) << 8) | ((SWord16) s2714);
+  const SWord8  s2716 = table8[s2697];
+  const SWord8  s2717 = table9[s2699];
+  const SWord8  s2718 = table6[s2701];
+  const SWord8  s2719 = table7[s2703];
+  const SWord8  s2720 = s2718 ^ s2719;
+  const SWord8  s2721 = s2717 ^ s2720;
+  const SWord8  s2722 = s2716 ^ s2721;
+  const SWord8  s2723 = table7[s2697];
+  const SWord8  s2724 = table8[s2699];
+  const SWord8  s2725 = table9[s2701];
+  const SWord8  s2726 = table6[s2703];
+  const SWord8  s2727 = s2725 ^ s2726;
+  const SWord8  s2728 = s2724 ^ s2727;
+  const SWord8  s2729 = s2723 ^ s2728;
+  const SWord16 s2730 = (((SWord16) s2722) << 8) | ((SWord16) s2729);
+  const SWord32 s2731 = (((SWord32) s2715) << 16) | ((SWord32) s2730);
+  const SWord32 s2732 = s2696 ^ s2731;
+  const SWord8  s2733 = (SWord8) (s2732 >> 8);
+  const SWord32 s2734 = table4[s2733];
+  const SWord32 s2735 = s2685 ^ s2734;
+  const SWord8  s2736 = (SWord8) (s2594 >> 24);
+  const SWord32 s2737 = table1[s2736];
+  const SWord8  s2738 = (SWord8) (s2445 >> 16);
+  const SWord32 s2739 = table3[s2738];
+  const SWord32 s2740 = s2737 ^ s2739;
+  const SWord8  s2741 = (SWord8) (s2494 >> 8);
+  const SWord32 s2742 = table4[s2741];
+  const SWord32 s2743 = s2740 ^ s2742;
+  const SWord8  s2744 = (SWord8) s2544;
+  const SWord32 s2745 = table5[s2744];
+  const SWord32 s2746 = s2743 ^ s2745;
+  const SWord8  s2747 = (SWord8) (s568 >> 24);
+  const SWord8  s2748 = table6[s2747];
+  const SWord8  s2749 = (SWord8) (s568 >> 16);
+  const SWord8  s2750 = table7[s2749];
+  const SWord8  s2751 = (SWord8) (s568 >> 8);
+  const SWord8  s2752 = table8[s2751];
+  const SWord8  s2753 = (SWord8) s568;
+  const SWord8  s2754 = table9[s2753];
+  const SWord8  s2755 = s2752 ^ s2754;
+  const SWord8  s2756 = s2750 ^ s2755;
+  const SWord8  s2757 = s2748 ^ s2756;
+  const SWord8  s2758 = table9[s2747];
+  const SWord8  s2759 = table6[s2749];
+  const SWord8  s2760 = table7[s2751];
+  const SWord8  s2761 = table8[s2753];
+  const SWord8  s2762 = s2760 ^ s2761;
+  const SWord8  s2763 = s2759 ^ s2762;
+  const SWord8  s2764 = s2758 ^ s2763;
+  const SWord16 s2765 = (((SWord16) s2757) << 8) | ((SWord16) s2764);
+  const SWord8  s2766 = table8[s2747];
+  const SWord8  s2767 = table9[s2749];
+  const SWord8  s2768 = table6[s2751];
+  const SWord8  s2769 = table7[s2753];
+  const SWord8  s2770 = s2768 ^ s2769;
+  const SWord8  s2771 = s2767 ^ s2770;
+  const SWord8  s2772 = s2766 ^ s2771;
+  const SWord8  s2773 = table7[s2747];
+  const SWord8  s2774 = table8[s2749];
+  const SWord8  s2775 = table9[s2751];
+  const SWord8  s2776 = table6[s2753];
+  const SWord8  s2777 = s2775 ^ s2776;
+  const SWord8  s2778 = s2774 ^ s2777;
+  const SWord8  s2779 = s2773 ^ s2778;
+  const SWord16 s2780 = (((SWord16) s2772) << 8) | ((SWord16) s2779);
+  const SWord32 s2781 = (((SWord32) s2765) << 16) | ((SWord32) s2780);
+  const SWord32 s2782 = s2746 ^ s2781;
+  const SWord8  s2783 = (SWord8) s2782;
+  const SWord32 s2784 = table5[s2783];
+  const SWord32 s2785 = s2735 ^ s2784;
+  const SWord8  s2786 = (SWord8) (s550 >> 24);
+  const SWord8  s2787 = table6[s2786];
+  const SWord8  s2788 = (SWord8) (s550 >> 16);
+  const SWord8  s2789 = table7[s2788];
+  const SWord8  s2790 = (SWord8) (s550 >> 8);
+  const SWord8  s2791 = table8[s2790];
+  const SWord8  s2792 = (SWord8) s550;
+  const SWord8  s2793 = table9[s2792];
+  const SWord8  s2794 = s2791 ^ s2793;
+  const SWord8  s2795 = s2789 ^ s2794;
+  const SWord8  s2796 = s2787 ^ s2795;
+  const SWord8  s2797 = table9[s2786];
+  const SWord8  s2798 = table6[s2788];
+  const SWord8  s2799 = table7[s2790];
+  const SWord8  s2800 = table8[s2792];
+  const SWord8  s2801 = s2799 ^ s2800;
+  const SWord8  s2802 = s2798 ^ s2801;
+  const SWord8  s2803 = s2797 ^ s2802;
+  const SWord16 s2804 = (((SWord16) s2796) << 8) | ((SWord16) s2803);
+  const SWord8  s2805 = table8[s2786];
+  const SWord8  s2806 = table9[s2788];
+  const SWord8  s2807 = table6[s2790];
+  const SWord8  s2808 = table7[s2792];
+  const SWord8  s2809 = s2807 ^ s2808;
+  const SWord8  s2810 = s2806 ^ s2809;
+  const SWord8  s2811 = s2805 ^ s2810;
+  const SWord8  s2812 = table7[s2786];
+  const SWord8  s2813 = table8[s2788];
+  const SWord8  s2814 = table9[s2790];
+  const SWord8  s2815 = table6[s2792];
+  const SWord8  s2816 = s2814 ^ s2815;
+  const SWord8  s2817 = s2813 ^ s2816;
+  const SWord8  s2818 = s2812 ^ s2817;
+  const SWord16 s2819 = (((SWord16) s2811) << 8) | ((SWord16) s2818);
+  const SWord32 s2820 = (((SWord32) s2804) << 16) | ((SWord32) s2819);
+  const SWord32 s2821 = s2785 ^ s2820;
+  const SWord8  s2822 = (SWord8) (s2821 >> 24);
+  const SWord32 s2823 = table1[s2822];
+  const SWord8  s2824 = (SWord8) (s2682 >> 24);
+  const SWord32 s2825 = table1[s2824];
+  const SWord8  s2826 = (SWord8) (s2732 >> 16);
+  const SWord32 s2827 = table3[s2826];
+  const SWord32 s2828 = s2825 ^ s2827;
+  const SWord8  s2829 = (SWord8) (s2782 >> 8);
+  const SWord32 s2830 = table4[s2829];
+  const SWord32 s2831 = s2828 ^ s2830;
+  const SWord8  s2832 = (SWord8) s2633;
+  const SWord32 s2833 = table5[s2832];
+  const SWord32 s2834 = s2831 ^ s2833;
+  const SWord8  s2835 = (SWord8) (s553 >> 24);
+  const SWord8  s2836 = table6[s2835];
+  const SWord8  s2837 = (SWord8) (s553 >> 16);
+  const SWord8  s2838 = table7[s2837];
+  const SWord8  s2839 = (SWord8) (s553 >> 8);
+  const SWord8  s2840 = table8[s2839];
+  const SWord8  s2841 = (SWord8) s553;
+  const SWord8  s2842 = table9[s2841];
+  const SWord8  s2843 = s2840 ^ s2842;
+  const SWord8  s2844 = s2838 ^ s2843;
+  const SWord8  s2845 = s2836 ^ s2844;
+  const SWord8  s2846 = table9[s2835];
+  const SWord8  s2847 = table6[s2837];
+  const SWord8  s2848 = table7[s2839];
+  const SWord8  s2849 = table8[s2841];
+  const SWord8  s2850 = s2848 ^ s2849;
+  const SWord8  s2851 = s2847 ^ s2850;
+  const SWord8  s2852 = s2846 ^ s2851;
+  const SWord16 s2853 = (((SWord16) s2845) << 8) | ((SWord16) s2852);
+  const SWord8  s2854 = table8[s2835];
+  const SWord8  s2855 = table9[s2837];
+  const SWord8  s2856 = table6[s2839];
+  const SWord8  s2857 = table7[s2841];
+  const SWord8  s2858 = s2856 ^ s2857;
+  const SWord8  s2859 = s2855 ^ s2858;
+  const SWord8  s2860 = s2854 ^ s2859;
+  const SWord8  s2861 = table7[s2835];
+  const SWord8  s2862 = table8[s2837];
+  const SWord8  s2863 = table9[s2839];
+  const SWord8  s2864 = table6[s2841];
+  const SWord8  s2865 = s2863 ^ s2864;
+  const SWord8  s2866 = s2862 ^ s2865;
+  const SWord8  s2867 = s2861 ^ s2866;
+  const SWord16 s2868 = (((SWord16) s2860) << 8) | ((SWord16) s2867);
+  const SWord32 s2869 = (((SWord32) s2853) << 16) | ((SWord32) s2868);
+  const SWord32 s2870 = s2834 ^ s2869;
+  const SWord8  s2871 = (SWord8) (s2870 >> 16);
+  const SWord32 s2872 = table3[s2871];
+  const SWord32 s2873 = s2823 ^ s2872;
+  const SWord8  s2874 = (SWord8) (s2732 >> 24);
+  const SWord32 s2875 = table1[s2874];
+  const SWord8  s2876 = (SWord8) (s2782 >> 16);
+  const SWord32 s2877 = table3[s2876];
+  const SWord32 s2878 = s2875 ^ s2877;
+  const SWord8  s2879 = (SWord8) (s2633 >> 8);
+  const SWord32 s2880 = table4[s2879];
+  const SWord32 s2881 = s2878 ^ s2880;
+  const SWord8  s2882 = (SWord8) s2682;
+  const SWord32 s2883 = table5[s2882];
+  const SWord32 s2884 = s2881 ^ s2883;
+  const SWord8  s2885 = (SWord8) (s552 >> 24);
+  const SWord8  s2886 = table6[s2885];
+  const SWord8  s2887 = (SWord8) (s552 >> 16);
+  const SWord8  s2888 = table7[s2887];
+  const SWord8  s2889 = (SWord8) (s552 >> 8);
+  const SWord8  s2890 = table8[s2889];
+  const SWord8  s2891 = (SWord8) s552;
+  const SWord8  s2892 = table9[s2891];
+  const SWord8  s2893 = s2890 ^ s2892;
+  const SWord8  s2894 = s2888 ^ s2893;
+  const SWord8  s2895 = s2886 ^ s2894;
+  const SWord8  s2896 = table9[s2885];
+  const SWord8  s2897 = table6[s2887];
+  const SWord8  s2898 = table7[s2889];
+  const SWord8  s2899 = table8[s2891];
+  const SWord8  s2900 = s2898 ^ s2899;
+  const SWord8  s2901 = s2897 ^ s2900;
+  const SWord8  s2902 = s2896 ^ s2901;
+  const SWord16 s2903 = (((SWord16) s2895) << 8) | ((SWord16) s2902);
+  const SWord8  s2904 = table8[s2885];
+  const SWord8  s2905 = table9[s2887];
+  const SWord8  s2906 = table6[s2889];
+  const SWord8  s2907 = table7[s2891];
+  const SWord8  s2908 = s2906 ^ s2907;
+  const SWord8  s2909 = s2905 ^ s2908;
+  const SWord8  s2910 = s2904 ^ s2909;
+  const SWord8  s2911 = table7[s2885];
+  const SWord8  s2912 = table8[s2887];
+  const SWord8  s2913 = table9[s2889];
+  const SWord8  s2914 = table6[s2891];
+  const SWord8  s2915 = s2913 ^ s2914;
+  const SWord8  s2916 = s2912 ^ s2915;
+  const SWord8  s2917 = s2911 ^ s2916;
+  const SWord16 s2918 = (((SWord16) s2910) << 8) | ((SWord16) s2917);
+  const SWord32 s2919 = (((SWord32) s2903) << 16) | ((SWord32) s2918);
+  const SWord32 s2920 = s2884 ^ s2919;
+  const SWord8  s2921 = (SWord8) (s2920 >> 8);
+  const SWord32 s2922 = table4[s2921];
+  const SWord32 s2923 = s2873 ^ s2922;
+  const SWord8  s2924 = (SWord8) (s2782 >> 24);
+  const SWord32 s2925 = table1[s2924];
+  const SWord8  s2926 = (SWord8) (s2633 >> 16);
+  const SWord32 s2927 = table3[s2926];
+  const SWord32 s2928 = s2925 ^ s2927;
+  const SWord8  s2929 = (SWord8) (s2682 >> 8);
+  const SWord32 s2930 = table4[s2929];
+  const SWord32 s2931 = s2928 ^ s2930;
+  const SWord8  s2932 = (SWord8) s2732;
+  const SWord32 s2933 = table5[s2932];
+  const SWord32 s2934 = s2931 ^ s2933;
+  const SWord8  s2935 = (SWord8) (s551 >> 24);
+  const SWord8  s2936 = table6[s2935];
+  const SWord8  s2937 = (SWord8) (s551 >> 16);
+  const SWord8  s2938 = table7[s2937];
+  const SWord8  s2939 = (SWord8) (s551 >> 8);
+  const SWord8  s2940 = table8[s2939];
+  const SWord8  s2941 = (SWord8) s551;
+  const SWord8  s2942 = table9[s2941];
+  const SWord8  s2943 = s2940 ^ s2942;
+  const SWord8  s2944 = s2938 ^ s2943;
+  const SWord8  s2945 = s2936 ^ s2944;
+  const SWord8  s2946 = table9[s2935];
+  const SWord8  s2947 = table6[s2937];
+  const SWord8  s2948 = table7[s2939];
+  const SWord8  s2949 = table8[s2941];
+  const SWord8  s2950 = s2948 ^ s2949;
+  const SWord8  s2951 = s2947 ^ s2950;
+  const SWord8  s2952 = s2946 ^ s2951;
+  const SWord16 s2953 = (((SWord16) s2945) << 8) | ((SWord16) s2952);
+  const SWord8  s2954 = table8[s2935];
+  const SWord8  s2955 = table9[s2937];
+  const SWord8  s2956 = table6[s2939];
+  const SWord8  s2957 = table7[s2941];
+  const SWord8  s2958 = s2956 ^ s2957;
+  const SWord8  s2959 = s2955 ^ s2958;
+  const SWord8  s2960 = s2954 ^ s2959;
+  const SWord8  s2961 = table7[s2935];
+  const SWord8  s2962 = table8[s2937];
+  const SWord8  s2963 = table9[s2939];
+  const SWord8  s2964 = table6[s2941];
+  const SWord8  s2965 = s2963 ^ s2964;
+  const SWord8  s2966 = s2962 ^ s2965;
+  const SWord8  s2967 = s2961 ^ s2966;
+  const SWord16 s2968 = (((SWord16) s2960) << 8) | ((SWord16) s2967);
+  const SWord32 s2969 = (((SWord32) s2953) << 16) | ((SWord32) s2968);
+  const SWord32 s2970 = s2934 ^ s2969;
+  const SWord8  s2971 = (SWord8) s2970;
+  const SWord32 s2972 = table5[s2971];
+  const SWord32 s2973 = s2923 ^ s2972;
+  const SWord8  s2974 = (SWord8) (s533 >> 24);
+  const SWord8  s2975 = table6[s2974];
+  const SWord8  s2976 = (SWord8) (s533 >> 16);
+  const SWord8  s2977 = table7[s2976];
+  const SWord8  s2978 = (SWord8) (s533 >> 8);
+  const SWord8  s2979 = table8[s2978];
+  const SWord8  s2980 = (SWord8) s533;
+  const SWord8  s2981 = table9[s2980];
+  const SWord8  s2982 = s2979 ^ s2981;
+  const SWord8  s2983 = s2977 ^ s2982;
+  const SWord8  s2984 = s2975 ^ s2983;
+  const SWord8  s2985 = table9[s2974];
+  const SWord8  s2986 = table6[s2976];
+  const SWord8  s2987 = table7[s2978];
+  const SWord8  s2988 = table8[s2980];
+  const SWord8  s2989 = s2987 ^ s2988;
+  const SWord8  s2990 = s2986 ^ s2989;
+  const SWord8  s2991 = s2985 ^ s2990;
+  const SWord16 s2992 = (((SWord16) s2984) << 8) | ((SWord16) s2991);
+  const SWord8  s2993 = table8[s2974];
+  const SWord8  s2994 = table9[s2976];
+  const SWord8  s2995 = table6[s2978];
+  const SWord8  s2996 = table7[s2980];
+  const SWord8  s2997 = s2995 ^ s2996;
+  const SWord8  s2998 = s2994 ^ s2997;
+  const SWord8  s2999 = s2993 ^ s2998;
+  const SWord8  s3000 = table7[s2974];
+  const SWord8  s3001 = table8[s2976];
+  const SWord8  s3002 = table9[s2978];
+  const SWord8  s3003 = table6[s2980];
+  const SWord8  s3004 = s3002 ^ s3003;
+  const SWord8  s3005 = s3001 ^ s3004;
+  const SWord8  s3006 = s3000 ^ s3005;
+  const SWord16 s3007 = (((SWord16) s2999) << 8) | ((SWord16) s3006);
+  const SWord32 s3008 = (((SWord32) s2992) << 16) | ((SWord32) s3007);
+  const SWord32 s3009 = s2973 ^ s3008;
+  const SWord8  s3010 = (SWord8) (s3009 >> 24);
+  const SWord8  s3011 = table0[s3010];
+  const SWord8  s3012 = (SWord8) (s2870 >> 24);
+  const SWord32 s3013 = table1[s3012];
+  const SWord8  s3014 = (SWord8) (s2920 >> 16);
+  const SWord32 s3015 = table3[s3014];
+  const SWord32 s3016 = s3013 ^ s3015;
+  const SWord8  s3017 = (SWord8) (s2970 >> 8);
+  const SWord32 s3018 = table4[s3017];
+  const SWord32 s3019 = s3016 ^ s3018;
+  const SWord8  s3020 = (SWord8) s2821;
+  const SWord32 s3021 = table5[s3020];
+  const SWord32 s3022 = s3019 ^ s3021;
+  const SWord8  s3023 = (SWord8) (s536 >> 24);
+  const SWord8  s3024 = table6[s3023];
+  const SWord8  s3025 = (SWord8) (s536 >> 16);
+  const SWord8  s3026 = table7[s3025];
+  const SWord8  s3027 = (SWord8) (s536 >> 8);
+  const SWord8  s3028 = table8[s3027];
+  const SWord8  s3029 = (SWord8) s536;
+  const SWord8  s3030 = table9[s3029];
+  const SWord8  s3031 = s3028 ^ s3030;
+  const SWord8  s3032 = s3026 ^ s3031;
+  const SWord8  s3033 = s3024 ^ s3032;
+  const SWord8  s3034 = table9[s3023];
+  const SWord8  s3035 = table6[s3025];
+  const SWord8  s3036 = table7[s3027];
+  const SWord8  s3037 = table8[s3029];
+  const SWord8  s3038 = s3036 ^ s3037;
+  const SWord8  s3039 = s3035 ^ s3038;
+  const SWord8  s3040 = s3034 ^ s3039;
+  const SWord16 s3041 = (((SWord16) s3033) << 8) | ((SWord16) s3040);
+  const SWord8  s3042 = table8[s3023];
+  const SWord8  s3043 = table9[s3025];
+  const SWord8  s3044 = table6[s3027];
+  const SWord8  s3045 = table7[s3029];
+  const SWord8  s3046 = s3044 ^ s3045;
+  const SWord8  s3047 = s3043 ^ s3046;
+  const SWord8  s3048 = s3042 ^ s3047;
+  const SWord8  s3049 = table7[s3023];
+  const SWord8  s3050 = table8[s3025];
+  const SWord8  s3051 = table9[s3027];
+  const SWord8  s3052 = table6[s3029];
+  const SWord8  s3053 = s3051 ^ s3052;
+  const SWord8  s3054 = s3050 ^ s3053;
+  const SWord8  s3055 = s3049 ^ s3054;
+  const SWord16 s3056 = (((SWord16) s3048) << 8) | ((SWord16) s3055);
+  const SWord32 s3057 = (((SWord32) s3041) << 16) | ((SWord32) s3056);
+  const SWord32 s3058 = s3022 ^ s3057;
+  const SWord8  s3059 = (SWord8) (s3058 >> 16);
+  const SWord8  s3060 = table0[s3059];
+  const SWord16 s3061 = (((SWord16) s3011) << 8) | ((SWord16) s3060);
+  const SWord8  s3062 = (SWord8) (s2920 >> 24);
+  const SWord32 s3063 = table1[s3062];
+  const SWord8  s3064 = (SWord8) (s2970 >> 16);
+  const SWord32 s3065 = table3[s3064];
+  const SWord32 s3066 = s3063 ^ s3065;
+  const SWord8  s3067 = (SWord8) (s2821 >> 8);
+  const SWord32 s3068 = table4[s3067];
+  const SWord32 s3069 = s3066 ^ s3068;
+  const SWord8  s3070 = (SWord8) s2870;
+  const SWord32 s3071 = table5[s3070];
+  const SWord32 s3072 = s3069 ^ s3071;
+  const SWord8  s3073 = (SWord8) (s535 >> 24);
+  const SWord8  s3074 = table6[s3073];
+  const SWord8  s3075 = (SWord8) (s535 >> 16);
+  const SWord8  s3076 = table7[s3075];
+  const SWord8  s3077 = (SWord8) (s535 >> 8);
+  const SWord8  s3078 = table8[s3077];
+  const SWord8  s3079 = (SWord8) s535;
+  const SWord8  s3080 = table9[s3079];
+  const SWord8  s3081 = s3078 ^ s3080;
+  const SWord8  s3082 = s3076 ^ s3081;
+  const SWord8  s3083 = s3074 ^ s3082;
+  const SWord8  s3084 = table9[s3073];
+  const SWord8  s3085 = table6[s3075];
+  const SWord8  s3086 = table7[s3077];
+  const SWord8  s3087 = table8[s3079];
+  const SWord8  s3088 = s3086 ^ s3087;
+  const SWord8  s3089 = s3085 ^ s3088;
+  const SWord8  s3090 = s3084 ^ s3089;
+  const SWord16 s3091 = (((SWord16) s3083) << 8) | ((SWord16) s3090);
+  const SWord8  s3092 = table8[s3073];
+  const SWord8  s3093 = table9[s3075];
+  const SWord8  s3094 = table6[s3077];
+  const SWord8  s3095 = table7[s3079];
+  const SWord8  s3096 = s3094 ^ s3095;
+  const SWord8  s3097 = s3093 ^ s3096;
+  const SWord8  s3098 = s3092 ^ s3097;
+  const SWord8  s3099 = table7[s3073];
+  const SWord8  s3100 = table8[s3075];
+  const SWord8  s3101 = table9[s3077];
+  const SWord8  s3102 = table6[s3079];
+  const SWord8  s3103 = s3101 ^ s3102;
+  const SWord8  s3104 = s3100 ^ s3103;
+  const SWord8  s3105 = s3099 ^ s3104;
+  const SWord16 s3106 = (((SWord16) s3098) << 8) | ((SWord16) s3105);
+  const SWord32 s3107 = (((SWord32) s3091) << 16) | ((SWord32) s3106);
+  const SWord32 s3108 = s3072 ^ s3107;
+  const SWord8  s3109 = (SWord8) (s3108 >> 8);
+  const SWord8  s3110 = table0[s3109];
+  const SWord8  s3111 = (SWord8) (s2970 >> 24);
+  const SWord32 s3112 = table1[s3111];
+  const SWord8  s3113 = (SWord8) (s2821 >> 16);
+  const SWord32 s3114 = table3[s3113];
+  const SWord32 s3115 = s3112 ^ s3114;
+  const SWord8  s3116 = (SWord8) (s2870 >> 8);
+  const SWord32 s3117 = table4[s3116];
+  const SWord32 s3118 = s3115 ^ s3117;
+  const SWord8  s3119 = (SWord8) s2920;
+  const SWord32 s3120 = table5[s3119];
+  const SWord32 s3121 = s3118 ^ s3120;
+  const SWord8  s3122 = (SWord8) (s534 >> 24);
+  const SWord8  s3123 = table6[s3122];
+  const SWord8  s3124 = (SWord8) (s534 >> 16);
+  const SWord8  s3125 = table7[s3124];
+  const SWord8  s3126 = (SWord8) (s534 >> 8);
+  const SWord8  s3127 = table8[s3126];
+  const SWord8  s3128 = (SWord8) s534;
+  const SWord8  s3129 = table9[s3128];
+  const SWord8  s3130 = s3127 ^ s3129;
+  const SWord8  s3131 = s3125 ^ s3130;
+  const SWord8  s3132 = s3123 ^ s3131;
+  const SWord8  s3133 = table9[s3122];
+  const SWord8  s3134 = table6[s3124];
+  const SWord8  s3135 = table7[s3126];
+  const SWord8  s3136 = table8[s3128];
+  const SWord8  s3137 = s3135 ^ s3136;
+  const SWord8  s3138 = s3134 ^ s3137;
+  const SWord8  s3139 = s3133 ^ s3138;
+  const SWord16 s3140 = (((SWord16) s3132) << 8) | ((SWord16) s3139);
+  const SWord8  s3141 = table8[s3122];
+  const SWord8  s3142 = table9[s3124];
+  const SWord8  s3143 = table6[s3126];
+  const SWord8  s3144 = table7[s3128];
+  const SWord8  s3145 = s3143 ^ s3144;
+  const SWord8  s3146 = s3142 ^ s3145;
+  const SWord8  s3147 = s3141 ^ s3146;
+  const SWord8  s3148 = table7[s3122];
+  const SWord8  s3149 = table8[s3124];
+  const SWord8  s3150 = table9[s3126];
+  const SWord8  s3151 = table6[s3128];
+  const SWord8  s3152 = s3150 ^ s3151;
+  const SWord8  s3153 = s3149 ^ s3152;
+  const SWord8  s3154 = s3148 ^ s3153;
+  const SWord16 s3155 = (((SWord16) s3147) << 8) | ((SWord16) s3154);
+  const SWord32 s3156 = (((SWord32) s3140) << 16) | ((SWord32) s3155);
+  const SWord32 s3157 = s3121 ^ s3156;
+  const SWord8  s3158 = (SWord8) s3157;
+  const SWord8  s3159 = table0[s3158];
+  const SWord16 s3160 = (((SWord16) s3110) << 8) | ((SWord16) s3159);
+  const SWord32 s3161 = (((SWord32) s3061) << 16) | ((SWord32) s3160);
+  const SWord32 s3162 = s4 ^ s3161;
+  const SWord8  s3163 = (SWord8) (s3157 >> 24);
+  const SWord8  s3164 = table0[s3163];
+  const SWord8  s3165 = (SWord8) (s3009 >> 16);
+  const SWord8  s3166 = table0[s3165];
+  const SWord16 s3167 = (((SWord16) s3164) << 8) | ((SWord16) s3166);
+  const SWord8  s3168 = (SWord8) (s3058 >> 8);
+  const SWord8  s3169 = table0[s3168];
+  const SWord8  s3170 = (SWord8) s3108;
+  const SWord8  s3171 = table0[s3170];
+  const SWord16 s3172 = (((SWord16) s3169) << 8) | ((SWord16) s3171);
+  const SWord32 s3173 = (((SWord32) s3167) << 16) | ((SWord32) s3172);
+  const SWord32 s3174 = s5 ^ s3173;
+  const SWord8  s3175 = (SWord8) (s3108 >> 24);
+  const SWord8  s3176 = table0[s3175];
+  const SWord8  s3177 = (SWord8) (s3157 >> 16);
+  const SWord8  s3178 = table0[s3177];
+  const SWord16 s3179 = (((SWord16) s3176) << 8) | ((SWord16) s3178);
+  const SWord8  s3180 = (SWord8) (s3009 >> 8);
+  const SWord8  s3181 = table0[s3180];
+  const SWord8  s3182 = (SWord8) s3058;
+  const SWord8  s3183 = table0[s3182];
+  const SWord16 s3184 = (((SWord16) s3181) << 8) | ((SWord16) s3183);
+  const SWord32 s3185 = (((SWord32) s3179) << 16) | ((SWord32) s3184);
+  const SWord32 s3186 = s6 ^ s3185;
+  const SWord8  s3187 = (SWord8) (s3058 >> 24);
+  const SWord8  s3188 = table0[s3187];
+  const SWord8  s3189 = (SWord8) (s3108 >> 16);
+  const SWord8  s3190 = table0[s3189];
+  const SWord16 s3191 = (((SWord16) s3188) << 8) | ((SWord16) s3190);
+  const SWord8  s3192 = (SWord8) (s3157 >> 8);
+  const SWord8  s3193 = table0[s3192];
+  const SWord8  s3194 = (SWord8) s3009;
+  const SWord8  s3195 = table0[s3194];
+  const SWord16 s3196 = (((SWord16) s3193) << 8) | ((SWord16) s3195);
+  const SWord32 s3197 = (((SWord32) s3191) << 16) | ((SWord32) s3196);
+  const SWord32 s3198 = s7 ^ s3197;
+
+  ct[0] = s3162;
+  ct[1] = s3174;
+  ct[2] = s3186;
+  ct[3] = s3198;
+}
+== END: "aes128Dec.c" ==================
diff --git a/SBVTestSuite/GoldFiles/aes128Enc.gold b/SBVTestSuite/GoldFiles/aes128Enc.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/aes128Enc.gold
@@ -0,0 +1,1067 @@
+== BEGIN: "Makefile" ================
+# Makefile for aes128Enc. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: aes128Enc_driver
+
+aes128Enc.o: aes128Enc.c aes128Enc.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128Enc_driver.o: aes128Enc_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128Enc_driver: aes128Enc.o aes128Enc_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f aes128Enc_driver
+== END: "Makefile" ==================
+== BEGIN: "aes128Enc.h" ================
+/* Header file for aes128Enc. Automatically generated by SBV. Do not edit! */
+
+#ifndef __aes128Enc__HEADER_INCLUDED__
+#define __aes128Enc__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void aes128Enc(const SWord32 *pt, const SWord32 *key, SWord32 *ct);
+
+#endif /* __aes128Enc__HEADER_INCLUDED__ */
+== END: "aes128Enc.h" ==================
+== BEGIN: "aes128Enc_driver.c" ================
+/* Example driver program for aes128Enc. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "aes128Enc.h"
+
+int main(void)
+{
+  const SWord32 pt[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array pt:\n");
+  int pt_ctr;
+  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
+    printf("  pt[%1d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
+
+  const SWord32 key[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array key:\n");
+  int key_ctr;
+  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
+    printf("  key[%1d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
+
+  SWord32 ct[4];
+
+  aes128Enc(pt, key, ct);
+
+  printf("aes128Enc(pt, key, ct) ->\n");
+  int ct_ctr;
+  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
+    printf("  ct[%1d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
+
+  return 0;
+}
+== END: "aes128Enc_driver.c" ==================
+== BEGIN: "aes128Enc.c" ================
+/* File: "aes128Enc.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Enc.h"
+
+void aes128Enc(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
+{
+  const SWord32 s0 = pt[0];
+  const SWord32 s1 = pt[1];
+  const SWord32 s2 = pt[2];
+  const SWord32 s3 = pt[3];
+  const SWord32 s4 = key[0];
+  const SWord32 s5 = key[1];
+  const SWord32 s6 = key[2];
+  const SWord32 s7 = key[3];
+  static const SWord8 table0[] = {
+       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
+      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
+      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
+      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
+       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
+      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
+       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
+       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
+       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
+      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
+       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
+      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
+      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
+      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
+       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
+       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
+      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
+      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
+      104,  65, 153,  45,  15, 176,  84, 187,  22
+  };
+  static const SWord32 table1[] = {
+      0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+      0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+      0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+      0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+      0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+      0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+      0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+      0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+      0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+      0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+      0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+      0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+      0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+      0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+      0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+      0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+      0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+      0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+      0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+      0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+      0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+      0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+      0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+      0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+      0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+      0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+      0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+      0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+      0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+      0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+      0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+      0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+      0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+      0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+      0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+      0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+      0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+      0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+      0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+      0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+      0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+      0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+      0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+      0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+      0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+      0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+      0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+      0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+      0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+      0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+      0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+      0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+      0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+      0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+      0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+      0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+      0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+      0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+      0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+      0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+      0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+      0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+      0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+      0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL
+  };
+  static const SWord32 table2[] = {
+      0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
+      0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
+      0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
+      0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
+      0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
+      0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
+      0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
+      0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
+      0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
+      0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
+      0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
+      0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
+      0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
+      0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
+      0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
+      0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
+      0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
+      0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
+      0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
+      0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
+      0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
+      0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
+      0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
+      0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
+      0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
+      0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
+      0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
+      0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
+      0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
+      0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
+      0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
+      0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
+      0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
+      0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
+      0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
+      0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
+      0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
+      0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
+      0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
+      0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
+      0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
+      0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
+      0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
+      0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
+      0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
+      0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
+      0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
+      0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
+      0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
+      0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
+      0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
+      0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
+      0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
+      0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
+      0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
+      0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
+      0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
+      0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
+      0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
+      0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
+      0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
+      0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
+      0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
+      0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL
+  };
+  static const SWord32 table3[] = {
+      0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
+      0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
+      0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
+      0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
+      0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
+      0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
+      0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
+      0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
+      0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
+      0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
+      0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
+      0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
+      0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
+      0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
+      0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
+      0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
+      0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
+      0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
+      0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
+      0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
+      0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
+      0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
+      0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
+      0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
+      0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
+      0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
+      0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
+      0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
+      0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
+      0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
+      0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
+      0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
+      0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
+      0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
+      0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
+      0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
+      0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
+      0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
+      0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
+      0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
+      0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
+      0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
+      0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
+      0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
+      0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
+      0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
+      0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
+      0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
+      0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
+      0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
+      0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
+      0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
+      0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
+      0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
+      0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
+      0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
+      0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
+      0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
+      0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
+      0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
+      0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
+      0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
+      0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
+      0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL
+  };
+  static const SWord32 table4[] = {
+      0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
+      0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
+      0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
+      0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
+      0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
+      0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
+      0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
+      0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
+      0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
+      0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
+      0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
+      0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
+      0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
+      0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
+      0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
+      0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
+      0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
+      0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
+      0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
+      0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
+      0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
+      0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
+      0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
+      0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
+      0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
+      0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
+      0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
+      0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
+      0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
+      0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
+      0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
+      0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
+      0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
+      0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
+      0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
+      0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
+      0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
+      0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
+      0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
+      0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
+      0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
+      0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
+      0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
+      0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
+      0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
+      0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
+      0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
+      0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
+      0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
+      0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
+      0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
+      0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
+      0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
+      0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
+      0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
+      0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
+      0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
+      0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
+      0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
+      0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
+      0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
+      0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
+      0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
+      0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL
+  };
+  const SWord32 s520 = s0 ^ s4;
+  const SWord8  s521 = (SWord8) (s520 >> 24);
+  const SWord32 s522 = table1[s521];
+  const SWord32 s778 = s1 ^ s5;
+  const SWord8  s779 = (SWord8) (s778 >> 16);
+  const SWord32 s780 = table2[s779];
+  const SWord32 s781 = s522 ^ s780;
+  const SWord32 s1037 = s2 ^ s6;
+  const SWord8  s1038 = (SWord8) (s1037 >> 8);
+  const SWord32 s1039 = table3[s1038];
+  const SWord32 s1040 = s781 ^ s1039;
+  const SWord32 s1296 = s3 ^ s7;
+  const SWord8  s1297 = (SWord8) s1296;
+  const SWord32 s1298 = table4[s1297];
+  const SWord32 s1299 = s1040 ^ s1298;
+  const SWord32 s1300 = (s7 << 8) | (s7 >> 24);
+  const SWord8  s1301 = (SWord8) (s1300 >> 24);
+  const SWord8  s1302 = table0[s1301];
+  const SWord8  s1303 = 1 ^ s1302;
+  const SWord8  s1304 = (SWord8) (s1300 >> 16);
+  const SWord8  s1305 = table0[s1304];
+  const SWord16 s1306 = (((SWord16) s1303) << 8) | ((SWord16) s1305);
+  const SWord8  s1307 = (SWord8) (s1300 >> 8);
+  const SWord8  s1308 = table0[s1307];
+  const SWord8  s1309 = (SWord8) s1300;
+  const SWord8  s1310 = table0[s1309];
+  const SWord16 s1311 = (((SWord16) s1308) << 8) | ((SWord16) s1310);
+  const SWord32 s1312 = (((SWord32) s1306) << 16) | ((SWord32) s1311);
+  const SWord32 s1313 = s4 ^ s1312;
+  const SWord32 s1314 = s1299 ^ s1313;
+  const SWord8  s1315 = (SWord8) (s1314 >> 24);
+  const SWord32 s1316 = table1[s1315];
+  const SWord8  s1317 = (SWord8) (s778 >> 24);
+  const SWord32 s1318 = table1[s1317];
+  const SWord8  s1319 = (SWord8) (s1037 >> 16);
+  const SWord32 s1320 = table2[s1319];
+  const SWord32 s1321 = s1318 ^ s1320;
+  const SWord8  s1322 = (SWord8) (s1296 >> 8);
+  const SWord32 s1323 = table3[s1322];
+  const SWord32 s1324 = s1321 ^ s1323;
+  const SWord8  s1325 = (SWord8) s520;
+  const SWord32 s1326 = table4[s1325];
+  const SWord32 s1327 = s1324 ^ s1326;
+  const SWord32 s1328 = s5 ^ s1313;
+  const SWord32 s1329 = s1327 ^ s1328;
+  const SWord8  s1330 = (SWord8) (s1329 >> 16);
+  const SWord32 s1331 = table2[s1330];
+  const SWord32 s1332 = s1316 ^ s1331;
+  const SWord8  s1333 = (SWord8) (s1037 >> 24);
+  const SWord32 s1334 = table1[s1333];
+  const SWord8  s1335 = (SWord8) (s1296 >> 16);
+  const SWord32 s1336 = table2[s1335];
+  const SWord32 s1337 = s1334 ^ s1336;
+  const SWord8  s1338 = (SWord8) (s520 >> 8);
+  const SWord32 s1339 = table3[s1338];
+  const SWord32 s1340 = s1337 ^ s1339;
+  const SWord8  s1341 = (SWord8) s778;
+  const SWord32 s1342 = table4[s1341];
+  const SWord32 s1343 = s1340 ^ s1342;
+  const SWord32 s1344 = s6 ^ s1328;
+  const SWord32 s1345 = s1343 ^ s1344;
+  const SWord8  s1346 = (SWord8) (s1345 >> 8);
+  const SWord32 s1347 = table3[s1346];
+  const SWord32 s1348 = s1332 ^ s1347;
+  const SWord8  s1349 = (SWord8) (s1296 >> 24);
+  const SWord32 s1350 = table1[s1349];
+  const SWord8  s1351 = (SWord8) (s520 >> 16);
+  const SWord32 s1352 = table2[s1351];
+  const SWord32 s1353 = s1350 ^ s1352;
+  const SWord8  s1354 = (SWord8) (s778 >> 8);
+  const SWord32 s1355 = table3[s1354];
+  const SWord32 s1356 = s1353 ^ s1355;
+  const SWord8  s1357 = (SWord8) s1037;
+  const SWord32 s1358 = table4[s1357];
+  const SWord32 s1359 = s1356 ^ s1358;
+  const SWord32 s1360 = s7 ^ s1344;
+  const SWord32 s1361 = s1359 ^ s1360;
+  const SWord8  s1362 = (SWord8) s1361;
+  const SWord32 s1363 = table4[s1362];
+  const SWord32 s1364 = s1348 ^ s1363;
+  const SWord32 s1365 = (s1360 << 8) | (s1360 >> 24);
+  const SWord8  s1366 = (SWord8) (s1365 >> 24);
+  const SWord8  s1367 = table0[s1366];
+  const SWord8  s1368 = 2 ^ s1367;
+  const SWord8  s1369 = (SWord8) (s1365 >> 16);
+  const SWord8  s1370 = table0[s1369];
+  const SWord16 s1371 = (((SWord16) s1368) << 8) | ((SWord16) s1370);
+  const SWord8  s1372 = (SWord8) (s1365 >> 8);
+  const SWord8  s1373 = table0[s1372];
+  const SWord8  s1374 = (SWord8) s1365;
+  const SWord8  s1375 = table0[s1374];
+  const SWord16 s1376 = (((SWord16) s1373) << 8) | ((SWord16) s1375);
+  const SWord32 s1377 = (((SWord32) s1371) << 16) | ((SWord32) s1376);
+  const SWord32 s1378 = s1313 ^ s1377;
+  const SWord32 s1379 = s1364 ^ s1378;
+  const SWord8  s1380 = (SWord8) (s1379 >> 24);
+  const SWord32 s1381 = table1[s1380];
+  const SWord8  s1382 = (SWord8) (s1329 >> 24);
+  const SWord32 s1383 = table1[s1382];
+  const SWord8  s1384 = (SWord8) (s1345 >> 16);
+  const SWord32 s1385 = table2[s1384];
+  const SWord32 s1386 = s1383 ^ s1385;
+  const SWord8  s1387 = (SWord8) (s1361 >> 8);
+  const SWord32 s1388 = table3[s1387];
+  const SWord32 s1389 = s1386 ^ s1388;
+  const SWord8  s1390 = (SWord8) s1314;
+  const SWord32 s1391 = table4[s1390];
+  const SWord32 s1392 = s1389 ^ s1391;
+  const SWord32 s1393 = s1328 ^ s1378;
+  const SWord32 s1394 = s1392 ^ s1393;
+  const SWord8  s1395 = (SWord8) (s1394 >> 16);
+  const SWord32 s1396 = table2[s1395];
+  const SWord32 s1397 = s1381 ^ s1396;
+  const SWord8  s1398 = (SWord8) (s1345 >> 24);
+  const SWord32 s1399 = table1[s1398];
+  const SWord8  s1400 = (SWord8) (s1361 >> 16);
+  const SWord32 s1401 = table2[s1400];
+  const SWord32 s1402 = s1399 ^ s1401;
+  const SWord8  s1403 = (SWord8) (s1314 >> 8);
+  const SWord32 s1404 = table3[s1403];
+  const SWord32 s1405 = s1402 ^ s1404;
+  const SWord8  s1406 = (SWord8) s1329;
+  const SWord32 s1407 = table4[s1406];
+  const SWord32 s1408 = s1405 ^ s1407;
+  const SWord32 s1409 = s1344 ^ s1393;
+  const SWord32 s1410 = s1408 ^ s1409;
+  const SWord8  s1411 = (SWord8) (s1410 >> 8);
+  const SWord32 s1412 = table3[s1411];
+  const SWord32 s1413 = s1397 ^ s1412;
+  const SWord8  s1414 = (SWord8) (s1361 >> 24);
+  const SWord32 s1415 = table1[s1414];
+  const SWord8  s1416 = (SWord8) (s1314 >> 16);
+  const SWord32 s1417 = table2[s1416];
+  const SWord32 s1418 = s1415 ^ s1417;
+  const SWord8  s1419 = (SWord8) (s1329 >> 8);
+  const SWord32 s1420 = table3[s1419];
+  const SWord32 s1421 = s1418 ^ s1420;
+  const SWord8  s1422 = (SWord8) s1345;
+  const SWord32 s1423 = table4[s1422];
+  const SWord32 s1424 = s1421 ^ s1423;
+  const SWord32 s1425 = s1360 ^ s1409;
+  const SWord32 s1426 = s1424 ^ s1425;
+  const SWord8  s1427 = (SWord8) s1426;
+  const SWord32 s1428 = table4[s1427];
+  const SWord32 s1429 = s1413 ^ s1428;
+  const SWord32 s1430 = (s1425 << 8) | (s1425 >> 24);
+  const SWord8  s1431 = (SWord8) (s1430 >> 24);
+  const SWord8  s1432 = table0[s1431];
+  const SWord8  s1433 = 4 ^ s1432;
+  const SWord8  s1434 = (SWord8) (s1430 >> 16);
+  const SWord8  s1435 = table0[s1434];
+  const SWord16 s1436 = (((SWord16) s1433) << 8) | ((SWord16) s1435);
+  const SWord8  s1437 = (SWord8) (s1430 >> 8);
+  const SWord8  s1438 = table0[s1437];
+  const SWord8  s1439 = (SWord8) s1430;
+  const SWord8  s1440 = table0[s1439];
+  const SWord16 s1441 = (((SWord16) s1438) << 8) | ((SWord16) s1440);
+  const SWord32 s1442 = (((SWord32) s1436) << 16) | ((SWord32) s1441);
+  const SWord32 s1443 = s1378 ^ s1442;
+  const SWord32 s1444 = s1429 ^ s1443;
+  const SWord8  s1445 = (SWord8) (s1444 >> 24);
+  const SWord32 s1446 = table1[s1445];
+  const SWord8  s1447 = (SWord8) (s1394 >> 24);
+  const SWord32 s1448 = table1[s1447];
+  const SWord8  s1449 = (SWord8) (s1410 >> 16);
+  const SWord32 s1450 = table2[s1449];
+  const SWord32 s1451 = s1448 ^ s1450;
+  const SWord8  s1452 = (SWord8) (s1426 >> 8);
+  const SWord32 s1453 = table3[s1452];
+  const SWord32 s1454 = s1451 ^ s1453;
+  const SWord8  s1455 = (SWord8) s1379;
+  const SWord32 s1456 = table4[s1455];
+  const SWord32 s1457 = s1454 ^ s1456;
+  const SWord32 s1458 = s1393 ^ s1443;
+  const SWord32 s1459 = s1457 ^ s1458;
+  const SWord8  s1460 = (SWord8) (s1459 >> 16);
+  const SWord32 s1461 = table2[s1460];
+  const SWord32 s1462 = s1446 ^ s1461;
+  const SWord8  s1463 = (SWord8) (s1410 >> 24);
+  const SWord32 s1464 = table1[s1463];
+  const SWord8  s1465 = (SWord8) (s1426 >> 16);
+  const SWord32 s1466 = table2[s1465];
+  const SWord32 s1467 = s1464 ^ s1466;
+  const SWord8  s1468 = (SWord8) (s1379 >> 8);
+  const SWord32 s1469 = table3[s1468];
+  const SWord32 s1470 = s1467 ^ s1469;
+  const SWord8  s1471 = (SWord8) s1394;
+  const SWord32 s1472 = table4[s1471];
+  const SWord32 s1473 = s1470 ^ s1472;
+  const SWord32 s1474 = s1409 ^ s1458;
+  const SWord32 s1475 = s1473 ^ s1474;
+  const SWord8  s1476 = (SWord8) (s1475 >> 8);
+  const SWord32 s1477 = table3[s1476];
+  const SWord32 s1478 = s1462 ^ s1477;
+  const SWord8  s1479 = (SWord8) (s1426 >> 24);
+  const SWord32 s1480 = table1[s1479];
+  const SWord8  s1481 = (SWord8) (s1379 >> 16);
+  const SWord32 s1482 = table2[s1481];
+  const SWord32 s1483 = s1480 ^ s1482;
+  const SWord8  s1484 = (SWord8) (s1394 >> 8);
+  const SWord32 s1485 = table3[s1484];
+  const SWord32 s1486 = s1483 ^ s1485;
+  const SWord8  s1487 = (SWord8) s1410;
+  const SWord32 s1488 = table4[s1487];
+  const SWord32 s1489 = s1486 ^ s1488;
+  const SWord32 s1490 = s1425 ^ s1474;
+  const SWord32 s1491 = s1489 ^ s1490;
+  const SWord8  s1492 = (SWord8) s1491;
+  const SWord32 s1493 = table4[s1492];
+  const SWord32 s1494 = s1478 ^ s1493;
+  const SWord32 s1495 = (s1490 << 8) | (s1490 >> 24);
+  const SWord8  s1496 = (SWord8) (s1495 >> 24);
+  const SWord8  s1497 = table0[s1496];
+  const SWord8  s1498 = 8 ^ s1497;
+  const SWord8  s1499 = (SWord8) (s1495 >> 16);
+  const SWord8  s1500 = table0[s1499];
+  const SWord16 s1501 = (((SWord16) s1498) << 8) | ((SWord16) s1500);
+  const SWord8  s1502 = (SWord8) (s1495 >> 8);
+  const SWord8  s1503 = table0[s1502];
+  const SWord8  s1504 = (SWord8) s1495;
+  const SWord8  s1505 = table0[s1504];
+  const SWord16 s1506 = (((SWord16) s1503) << 8) | ((SWord16) s1505);
+  const SWord32 s1507 = (((SWord32) s1501) << 16) | ((SWord32) s1506);
+  const SWord32 s1508 = s1443 ^ s1507;
+  const SWord32 s1509 = s1494 ^ s1508;
+  const SWord8  s1510 = (SWord8) (s1509 >> 24);
+  const SWord32 s1511 = table1[s1510];
+  const SWord8  s1512 = (SWord8) (s1459 >> 24);
+  const SWord32 s1513 = table1[s1512];
+  const SWord8  s1514 = (SWord8) (s1475 >> 16);
+  const SWord32 s1515 = table2[s1514];
+  const SWord32 s1516 = s1513 ^ s1515;
+  const SWord8  s1517 = (SWord8) (s1491 >> 8);
+  const SWord32 s1518 = table3[s1517];
+  const SWord32 s1519 = s1516 ^ s1518;
+  const SWord8  s1520 = (SWord8) s1444;
+  const SWord32 s1521 = table4[s1520];
+  const SWord32 s1522 = s1519 ^ s1521;
+  const SWord32 s1523 = s1458 ^ s1508;
+  const SWord32 s1524 = s1522 ^ s1523;
+  const SWord8  s1525 = (SWord8) (s1524 >> 16);
+  const SWord32 s1526 = table2[s1525];
+  const SWord32 s1527 = s1511 ^ s1526;
+  const SWord8  s1528 = (SWord8) (s1475 >> 24);
+  const SWord32 s1529 = table1[s1528];
+  const SWord8  s1530 = (SWord8) (s1491 >> 16);
+  const SWord32 s1531 = table2[s1530];
+  const SWord32 s1532 = s1529 ^ s1531;
+  const SWord8  s1533 = (SWord8) (s1444 >> 8);
+  const SWord32 s1534 = table3[s1533];
+  const SWord32 s1535 = s1532 ^ s1534;
+  const SWord8  s1536 = (SWord8) s1459;
+  const SWord32 s1537 = table4[s1536];
+  const SWord32 s1538 = s1535 ^ s1537;
+  const SWord32 s1539 = s1474 ^ s1523;
+  const SWord32 s1540 = s1538 ^ s1539;
+  const SWord8  s1541 = (SWord8) (s1540 >> 8);
+  const SWord32 s1542 = table3[s1541];
+  const SWord32 s1543 = s1527 ^ s1542;
+  const SWord8  s1544 = (SWord8) (s1491 >> 24);
+  const SWord32 s1545 = table1[s1544];
+  const SWord8  s1546 = (SWord8) (s1444 >> 16);
+  const SWord32 s1547 = table2[s1546];
+  const SWord32 s1548 = s1545 ^ s1547;
+  const SWord8  s1549 = (SWord8) (s1459 >> 8);
+  const SWord32 s1550 = table3[s1549];
+  const SWord32 s1551 = s1548 ^ s1550;
+  const SWord8  s1552 = (SWord8) s1475;
+  const SWord32 s1553 = table4[s1552];
+  const SWord32 s1554 = s1551 ^ s1553;
+  const SWord32 s1555 = s1490 ^ s1539;
+  const SWord32 s1556 = s1554 ^ s1555;
+  const SWord8  s1557 = (SWord8) s1556;
+  const SWord32 s1558 = table4[s1557];
+  const SWord32 s1559 = s1543 ^ s1558;
+  const SWord32 s1560 = (s1555 << 8) | (s1555 >> 24);
+  const SWord8  s1561 = (SWord8) (s1560 >> 24);
+  const SWord8  s1562 = table0[s1561];
+  const SWord8  s1563 = 16 ^ s1562;
+  const SWord8  s1564 = (SWord8) (s1560 >> 16);
+  const SWord8  s1565 = table0[s1564];
+  const SWord16 s1566 = (((SWord16) s1563) << 8) | ((SWord16) s1565);
+  const SWord8  s1567 = (SWord8) (s1560 >> 8);
+  const SWord8  s1568 = table0[s1567];
+  const SWord8  s1569 = (SWord8) s1560;
+  const SWord8  s1570 = table0[s1569];
+  const SWord16 s1571 = (((SWord16) s1568) << 8) | ((SWord16) s1570);
+  const SWord32 s1572 = (((SWord32) s1566) << 16) | ((SWord32) s1571);
+  const SWord32 s1573 = s1508 ^ s1572;
+  const SWord32 s1574 = s1559 ^ s1573;
+  const SWord8  s1575 = (SWord8) (s1574 >> 24);
+  const SWord32 s1576 = table1[s1575];
+  const SWord8  s1577 = (SWord8) (s1524 >> 24);
+  const SWord32 s1578 = table1[s1577];
+  const SWord8  s1579 = (SWord8) (s1540 >> 16);
+  const SWord32 s1580 = table2[s1579];
+  const SWord32 s1581 = s1578 ^ s1580;
+  const SWord8  s1582 = (SWord8) (s1556 >> 8);
+  const SWord32 s1583 = table3[s1582];
+  const SWord32 s1584 = s1581 ^ s1583;
+  const SWord8  s1585 = (SWord8) s1509;
+  const SWord32 s1586 = table4[s1585];
+  const SWord32 s1587 = s1584 ^ s1586;
+  const SWord32 s1588 = s1523 ^ s1573;
+  const SWord32 s1589 = s1587 ^ s1588;
+  const SWord8  s1590 = (SWord8) (s1589 >> 16);
+  const SWord32 s1591 = table2[s1590];
+  const SWord32 s1592 = s1576 ^ s1591;
+  const SWord8  s1593 = (SWord8) (s1540 >> 24);
+  const SWord32 s1594 = table1[s1593];
+  const SWord8  s1595 = (SWord8) (s1556 >> 16);
+  const SWord32 s1596 = table2[s1595];
+  const SWord32 s1597 = s1594 ^ s1596;
+  const SWord8  s1598 = (SWord8) (s1509 >> 8);
+  const SWord32 s1599 = table3[s1598];
+  const SWord32 s1600 = s1597 ^ s1599;
+  const SWord8  s1601 = (SWord8) s1524;
+  const SWord32 s1602 = table4[s1601];
+  const SWord32 s1603 = s1600 ^ s1602;
+  const SWord32 s1604 = s1539 ^ s1588;
+  const SWord32 s1605 = s1603 ^ s1604;
+  const SWord8  s1606 = (SWord8) (s1605 >> 8);
+  const SWord32 s1607 = table3[s1606];
+  const SWord32 s1608 = s1592 ^ s1607;
+  const SWord8  s1609 = (SWord8) (s1556 >> 24);
+  const SWord32 s1610 = table1[s1609];
+  const SWord8  s1611 = (SWord8) (s1509 >> 16);
+  const SWord32 s1612 = table2[s1611];
+  const SWord32 s1613 = s1610 ^ s1612;
+  const SWord8  s1614 = (SWord8) (s1524 >> 8);
+  const SWord32 s1615 = table3[s1614];
+  const SWord32 s1616 = s1613 ^ s1615;
+  const SWord8  s1617 = (SWord8) s1540;
+  const SWord32 s1618 = table4[s1617];
+  const SWord32 s1619 = s1616 ^ s1618;
+  const SWord32 s1620 = s1555 ^ s1604;
+  const SWord32 s1621 = s1619 ^ s1620;
+  const SWord8  s1622 = (SWord8) s1621;
+  const SWord32 s1623 = table4[s1622];
+  const SWord32 s1624 = s1608 ^ s1623;
+  const SWord32 s1625 = (s1620 << 8) | (s1620 >> 24);
+  const SWord8  s1626 = (SWord8) (s1625 >> 24);
+  const SWord8  s1627 = table0[s1626];
+  const SWord8  s1628 = 32 ^ s1627;
+  const SWord8  s1629 = (SWord8) (s1625 >> 16);
+  const SWord8  s1630 = table0[s1629];
+  const SWord16 s1631 = (((SWord16) s1628) << 8) | ((SWord16) s1630);
+  const SWord8  s1632 = (SWord8) (s1625 >> 8);
+  const SWord8  s1633 = table0[s1632];
+  const SWord8  s1634 = (SWord8) s1625;
+  const SWord8  s1635 = table0[s1634];
+  const SWord16 s1636 = (((SWord16) s1633) << 8) | ((SWord16) s1635);
+  const SWord32 s1637 = (((SWord32) s1631) << 16) | ((SWord32) s1636);
+  const SWord32 s1638 = s1573 ^ s1637;
+  const SWord32 s1639 = s1624 ^ s1638;
+  const SWord8  s1640 = (SWord8) (s1639 >> 24);
+  const SWord32 s1641 = table1[s1640];
+  const SWord8  s1642 = (SWord8) (s1589 >> 24);
+  const SWord32 s1643 = table1[s1642];
+  const SWord8  s1644 = (SWord8) (s1605 >> 16);
+  const SWord32 s1645 = table2[s1644];
+  const SWord32 s1646 = s1643 ^ s1645;
+  const SWord8  s1647 = (SWord8) (s1621 >> 8);
+  const SWord32 s1648 = table3[s1647];
+  const SWord32 s1649 = s1646 ^ s1648;
+  const SWord8  s1650 = (SWord8) s1574;
+  const SWord32 s1651 = table4[s1650];
+  const SWord32 s1652 = s1649 ^ s1651;
+  const SWord32 s1653 = s1588 ^ s1638;
+  const SWord32 s1654 = s1652 ^ s1653;
+  const SWord8  s1655 = (SWord8) (s1654 >> 16);
+  const SWord32 s1656 = table2[s1655];
+  const SWord32 s1657 = s1641 ^ s1656;
+  const SWord8  s1658 = (SWord8) (s1605 >> 24);
+  const SWord32 s1659 = table1[s1658];
+  const SWord8  s1660 = (SWord8) (s1621 >> 16);
+  const SWord32 s1661 = table2[s1660];
+  const SWord32 s1662 = s1659 ^ s1661;
+  const SWord8  s1663 = (SWord8) (s1574 >> 8);
+  const SWord32 s1664 = table3[s1663];
+  const SWord32 s1665 = s1662 ^ s1664;
+  const SWord8  s1666 = (SWord8) s1589;
+  const SWord32 s1667 = table4[s1666];
+  const SWord32 s1668 = s1665 ^ s1667;
+  const SWord32 s1669 = s1604 ^ s1653;
+  const SWord32 s1670 = s1668 ^ s1669;
+  const SWord8  s1671 = (SWord8) (s1670 >> 8);
+  const SWord32 s1672 = table3[s1671];
+  const SWord32 s1673 = s1657 ^ s1672;
+  const SWord8  s1674 = (SWord8) (s1621 >> 24);
+  const SWord32 s1675 = table1[s1674];
+  const SWord8  s1676 = (SWord8) (s1574 >> 16);
+  const SWord32 s1677 = table2[s1676];
+  const SWord32 s1678 = s1675 ^ s1677;
+  const SWord8  s1679 = (SWord8) (s1589 >> 8);
+  const SWord32 s1680 = table3[s1679];
+  const SWord32 s1681 = s1678 ^ s1680;
+  const SWord8  s1682 = (SWord8) s1605;
+  const SWord32 s1683 = table4[s1682];
+  const SWord32 s1684 = s1681 ^ s1683;
+  const SWord32 s1685 = s1620 ^ s1669;
+  const SWord32 s1686 = s1684 ^ s1685;
+  const SWord8  s1687 = (SWord8) s1686;
+  const SWord32 s1688 = table4[s1687];
+  const SWord32 s1689 = s1673 ^ s1688;
+  const SWord32 s1690 = (s1685 << 8) | (s1685 >> 24);
+  const SWord8  s1691 = (SWord8) (s1690 >> 24);
+  const SWord8  s1692 = table0[s1691];
+  const SWord8  s1693 = 64 ^ s1692;
+  const SWord8  s1694 = (SWord8) (s1690 >> 16);
+  const SWord8  s1695 = table0[s1694];
+  const SWord16 s1696 = (((SWord16) s1693) << 8) | ((SWord16) s1695);
+  const SWord8  s1697 = (SWord8) (s1690 >> 8);
+  const SWord8  s1698 = table0[s1697];
+  const SWord8  s1699 = (SWord8) s1690;
+  const SWord8  s1700 = table0[s1699];
+  const SWord16 s1701 = (((SWord16) s1698) << 8) | ((SWord16) s1700);
+  const SWord32 s1702 = (((SWord32) s1696) << 16) | ((SWord32) s1701);
+  const SWord32 s1703 = s1638 ^ s1702;
+  const SWord32 s1704 = s1689 ^ s1703;
+  const SWord8  s1705 = (SWord8) (s1704 >> 24);
+  const SWord32 s1706 = table1[s1705];
+  const SWord8  s1707 = (SWord8) (s1654 >> 24);
+  const SWord32 s1708 = table1[s1707];
+  const SWord8  s1709 = (SWord8) (s1670 >> 16);
+  const SWord32 s1710 = table2[s1709];
+  const SWord32 s1711 = s1708 ^ s1710;
+  const SWord8  s1712 = (SWord8) (s1686 >> 8);
+  const SWord32 s1713 = table3[s1712];
+  const SWord32 s1714 = s1711 ^ s1713;
+  const SWord8  s1715 = (SWord8) s1639;
+  const SWord32 s1716 = table4[s1715];
+  const SWord32 s1717 = s1714 ^ s1716;
+  const SWord32 s1718 = s1653 ^ s1703;
+  const SWord32 s1719 = s1717 ^ s1718;
+  const SWord8  s1720 = (SWord8) (s1719 >> 16);
+  const SWord32 s1721 = table2[s1720];
+  const SWord32 s1722 = s1706 ^ s1721;
+  const SWord8  s1723 = (SWord8) (s1670 >> 24);
+  const SWord32 s1724 = table1[s1723];
+  const SWord8  s1725 = (SWord8) (s1686 >> 16);
+  const SWord32 s1726 = table2[s1725];
+  const SWord32 s1727 = s1724 ^ s1726;
+  const SWord8  s1728 = (SWord8) (s1639 >> 8);
+  const SWord32 s1729 = table3[s1728];
+  const SWord32 s1730 = s1727 ^ s1729;
+  const SWord8  s1731 = (SWord8) s1654;
+  const SWord32 s1732 = table4[s1731];
+  const SWord32 s1733 = s1730 ^ s1732;
+  const SWord32 s1734 = s1669 ^ s1718;
+  const SWord32 s1735 = s1733 ^ s1734;
+  const SWord8  s1736 = (SWord8) (s1735 >> 8);
+  const SWord32 s1737 = table3[s1736];
+  const SWord32 s1738 = s1722 ^ s1737;
+  const SWord8  s1739 = (SWord8) (s1686 >> 24);
+  const SWord32 s1740 = table1[s1739];
+  const SWord8  s1741 = (SWord8) (s1639 >> 16);
+  const SWord32 s1742 = table2[s1741];
+  const SWord32 s1743 = s1740 ^ s1742;
+  const SWord8  s1744 = (SWord8) (s1654 >> 8);
+  const SWord32 s1745 = table3[s1744];
+  const SWord32 s1746 = s1743 ^ s1745;
+  const SWord8  s1747 = (SWord8) s1670;
+  const SWord32 s1748 = table4[s1747];
+  const SWord32 s1749 = s1746 ^ s1748;
+  const SWord32 s1750 = s1685 ^ s1734;
+  const SWord32 s1751 = s1749 ^ s1750;
+  const SWord8  s1752 = (SWord8) s1751;
+  const SWord32 s1753 = table4[s1752];
+  const SWord32 s1754 = s1738 ^ s1753;
+  const SWord32 s1755 = (s1750 << 8) | (s1750 >> 24);
+  const SWord8  s1756 = (SWord8) (s1755 >> 24);
+  const SWord8  s1757 = table0[s1756];
+  const SWord8  s1758 = 128 ^ s1757;
+  const SWord8  s1759 = (SWord8) (s1755 >> 16);
+  const SWord8  s1760 = table0[s1759];
+  const SWord16 s1761 = (((SWord16) s1758) << 8) | ((SWord16) s1760);
+  const SWord8  s1762 = (SWord8) (s1755 >> 8);
+  const SWord8  s1763 = table0[s1762];
+  const SWord8  s1764 = (SWord8) s1755;
+  const SWord8  s1765 = table0[s1764];
+  const SWord16 s1766 = (((SWord16) s1763) << 8) | ((SWord16) s1765);
+  const SWord32 s1767 = (((SWord32) s1761) << 16) | ((SWord32) s1766);
+  const SWord32 s1768 = s1703 ^ s1767;
+  const SWord32 s1769 = s1754 ^ s1768;
+  const SWord8  s1770 = (SWord8) (s1769 >> 24);
+  const SWord32 s1771 = table1[s1770];
+  const SWord8  s1772 = (SWord8) (s1719 >> 24);
+  const SWord32 s1773 = table1[s1772];
+  const SWord8  s1774 = (SWord8) (s1735 >> 16);
+  const SWord32 s1775 = table2[s1774];
+  const SWord32 s1776 = s1773 ^ s1775;
+  const SWord8  s1777 = (SWord8) (s1751 >> 8);
+  const SWord32 s1778 = table3[s1777];
+  const SWord32 s1779 = s1776 ^ s1778;
+  const SWord8  s1780 = (SWord8) s1704;
+  const SWord32 s1781 = table4[s1780];
+  const SWord32 s1782 = s1779 ^ s1781;
+  const SWord32 s1783 = s1718 ^ s1768;
+  const SWord32 s1784 = s1782 ^ s1783;
+  const SWord8  s1785 = (SWord8) (s1784 >> 16);
+  const SWord32 s1786 = table2[s1785];
+  const SWord32 s1787 = s1771 ^ s1786;
+  const SWord8  s1788 = (SWord8) (s1735 >> 24);
+  const SWord32 s1789 = table1[s1788];
+  const SWord8  s1790 = (SWord8) (s1751 >> 16);
+  const SWord32 s1791 = table2[s1790];
+  const SWord32 s1792 = s1789 ^ s1791;
+  const SWord8  s1793 = (SWord8) (s1704 >> 8);
+  const SWord32 s1794 = table3[s1793];
+  const SWord32 s1795 = s1792 ^ s1794;
+  const SWord8  s1796 = (SWord8) s1719;
+  const SWord32 s1797 = table4[s1796];
+  const SWord32 s1798 = s1795 ^ s1797;
+  const SWord32 s1799 = s1734 ^ s1783;
+  const SWord32 s1800 = s1798 ^ s1799;
+  const SWord8  s1801 = (SWord8) (s1800 >> 8);
+  const SWord32 s1802 = table3[s1801];
+  const SWord32 s1803 = s1787 ^ s1802;
+  const SWord8  s1804 = (SWord8) (s1751 >> 24);
+  const SWord32 s1805 = table1[s1804];
+  const SWord8  s1806 = (SWord8) (s1704 >> 16);
+  const SWord32 s1807 = table2[s1806];
+  const SWord32 s1808 = s1805 ^ s1807;
+  const SWord8  s1809 = (SWord8) (s1719 >> 8);
+  const SWord32 s1810 = table3[s1809];
+  const SWord32 s1811 = s1808 ^ s1810;
+  const SWord8  s1812 = (SWord8) s1735;
+  const SWord32 s1813 = table4[s1812];
+  const SWord32 s1814 = s1811 ^ s1813;
+  const SWord32 s1815 = s1750 ^ s1799;
+  const SWord32 s1816 = s1814 ^ s1815;
+  const SWord8  s1817 = (SWord8) s1816;
+  const SWord32 s1818 = table4[s1817];
+  const SWord32 s1819 = s1803 ^ s1818;
+  const SWord32 s1820 = (s1815 << 8) | (s1815 >> 24);
+  const SWord8  s1821 = (SWord8) (s1820 >> 24);
+  const SWord8  s1822 = table0[s1821];
+  const SWord8  s1823 = 27 ^ s1822;
+  const SWord8  s1824 = (SWord8) (s1820 >> 16);
+  const SWord8  s1825 = table0[s1824];
+  const SWord16 s1826 = (((SWord16) s1823) << 8) | ((SWord16) s1825);
+  const SWord8  s1827 = (SWord8) (s1820 >> 8);
+  const SWord8  s1828 = table0[s1827];
+  const SWord8  s1829 = (SWord8) s1820;
+  const SWord8  s1830 = table0[s1829];
+  const SWord16 s1831 = (((SWord16) s1828) << 8) | ((SWord16) s1830);
+  const SWord32 s1832 = (((SWord32) s1826) << 16) | ((SWord32) s1831);
+  const SWord32 s1833 = s1768 ^ s1832;
+  const SWord32 s1834 = s1819 ^ s1833;
+  const SWord8  s1835 = (SWord8) (s1834 >> 24);
+  const SWord8  s1836 = table0[s1835];
+  const SWord8  s1837 = (SWord8) (s1784 >> 24);
+  const SWord32 s1838 = table1[s1837];
+  const SWord8  s1839 = (SWord8) (s1800 >> 16);
+  const SWord32 s1840 = table2[s1839];
+  const SWord32 s1841 = s1838 ^ s1840;
+  const SWord8  s1842 = (SWord8) (s1816 >> 8);
+  const SWord32 s1843 = table3[s1842];
+  const SWord32 s1844 = s1841 ^ s1843;
+  const SWord8  s1845 = (SWord8) s1769;
+  const SWord32 s1846 = table4[s1845];
+  const SWord32 s1847 = s1844 ^ s1846;
+  const SWord32 s1848 = s1783 ^ s1833;
+  const SWord32 s1849 = s1847 ^ s1848;
+  const SWord8  s1850 = (SWord8) (s1849 >> 16);
+  const SWord8  s1851 = table0[s1850];
+  const SWord16 s1852 = (((SWord16) s1836) << 8) | ((SWord16) s1851);
+  const SWord8  s1853 = (SWord8) (s1800 >> 24);
+  const SWord32 s1854 = table1[s1853];
+  const SWord8  s1855 = (SWord8) (s1816 >> 16);
+  const SWord32 s1856 = table2[s1855];
+  const SWord32 s1857 = s1854 ^ s1856;
+  const SWord8  s1858 = (SWord8) (s1769 >> 8);
+  const SWord32 s1859 = table3[s1858];
+  const SWord32 s1860 = s1857 ^ s1859;
+  const SWord8  s1861 = (SWord8) s1784;
+  const SWord32 s1862 = table4[s1861];
+  const SWord32 s1863 = s1860 ^ s1862;
+  const SWord32 s1864 = s1799 ^ s1848;
+  const SWord32 s1865 = s1863 ^ s1864;
+  const SWord8  s1866 = (SWord8) (s1865 >> 8);
+  const SWord8  s1867 = table0[s1866];
+  const SWord8  s1868 = (SWord8) (s1816 >> 24);
+  const SWord32 s1869 = table1[s1868];
+  const SWord8  s1870 = (SWord8) (s1769 >> 16);
+  const SWord32 s1871 = table2[s1870];
+  const SWord32 s1872 = s1869 ^ s1871;
+  const SWord8  s1873 = (SWord8) (s1784 >> 8);
+  const SWord32 s1874 = table3[s1873];
+  const SWord32 s1875 = s1872 ^ s1874;
+  const SWord8  s1876 = (SWord8) s1800;
+  const SWord32 s1877 = table4[s1876];
+  const SWord32 s1878 = s1875 ^ s1877;
+  const SWord32 s1879 = s1815 ^ s1864;
+  const SWord32 s1880 = s1878 ^ s1879;
+  const SWord8  s1881 = (SWord8) s1880;
+  const SWord8  s1882 = table0[s1881];
+  const SWord16 s1883 = (((SWord16) s1867) << 8) | ((SWord16) s1882);
+  const SWord32 s1884 = (((SWord32) s1852) << 16) | ((SWord32) s1883);
+  const SWord32 s1885 = (s1879 << 8) | (s1879 >> 24);
+  const SWord8  s1886 = (SWord8) (s1885 >> 24);
+  const SWord8  s1887 = table0[s1886];
+  const SWord8  s1888 = 54 ^ s1887;
+  const SWord8  s1889 = (SWord8) (s1885 >> 16);
+  const SWord8  s1890 = table0[s1889];
+  const SWord16 s1891 = (((SWord16) s1888) << 8) | ((SWord16) s1890);
+  const SWord8  s1892 = (SWord8) (s1885 >> 8);
+  const SWord8  s1893 = table0[s1892];
+  const SWord8  s1894 = (SWord8) s1885;
+  const SWord8  s1895 = table0[s1894];
+  const SWord16 s1896 = (((SWord16) s1893) << 8) | ((SWord16) s1895);
+  const SWord32 s1897 = (((SWord32) s1891) << 16) | ((SWord32) s1896);
+  const SWord32 s1898 = s1833 ^ s1897;
+  const SWord32 s1899 = s1884 ^ s1898;
+  const SWord8  s1900 = (SWord8) (s1849 >> 24);
+  const SWord8  s1901 = table0[s1900];
+  const SWord8  s1902 = (SWord8) (s1865 >> 16);
+  const SWord8  s1903 = table0[s1902];
+  const SWord16 s1904 = (((SWord16) s1901) << 8) | ((SWord16) s1903);
+  const SWord8  s1905 = (SWord8) (s1880 >> 8);
+  const SWord8  s1906 = table0[s1905];
+  const SWord8  s1907 = (SWord8) s1834;
+  const SWord8  s1908 = table0[s1907];
+  const SWord16 s1909 = (((SWord16) s1906) << 8) | ((SWord16) s1908);
+  const SWord32 s1910 = (((SWord32) s1904) << 16) | ((SWord32) s1909);
+  const SWord32 s1911 = s1848 ^ s1898;
+  const SWord32 s1912 = s1910 ^ s1911;
+  const SWord8  s1913 = (SWord8) (s1865 >> 24);
+  const SWord8  s1914 = table0[s1913];
+  const SWord8  s1915 = (SWord8) (s1880 >> 16);
+  const SWord8  s1916 = table0[s1915];
+  const SWord16 s1917 = (((SWord16) s1914) << 8) | ((SWord16) s1916);
+  const SWord8  s1918 = (SWord8) (s1834 >> 8);
+  const SWord8  s1919 = table0[s1918];
+  const SWord8  s1920 = (SWord8) s1849;
+  const SWord8  s1921 = table0[s1920];
+  const SWord16 s1922 = (((SWord16) s1919) << 8) | ((SWord16) s1921);
+  const SWord32 s1923 = (((SWord32) s1917) << 16) | ((SWord32) s1922);
+  const SWord32 s1924 = s1864 ^ s1911;
+  const SWord32 s1925 = s1923 ^ s1924;
+  const SWord8  s1926 = (SWord8) (s1880 >> 24);
+  const SWord8  s1927 = table0[s1926];
+  const SWord8  s1928 = (SWord8) (s1834 >> 16);
+  const SWord8  s1929 = table0[s1928];
+  const SWord16 s1930 = (((SWord16) s1927) << 8) | ((SWord16) s1929);
+  const SWord8  s1931 = (SWord8) (s1849 >> 8);
+  const SWord8  s1932 = table0[s1931];
+  const SWord8  s1933 = (SWord8) s1865;
+  const SWord8  s1934 = table0[s1933];
+  const SWord16 s1935 = (((SWord16) s1932) << 8) | ((SWord16) s1934);
+  const SWord32 s1936 = (((SWord32) s1930) << 16) | ((SWord32) s1935);
+  const SWord32 s1937 = s1879 ^ s1924;
+  const SWord32 s1938 = s1936 ^ s1937;
+
+  ct[0] = s1899;
+  ct[1] = s1912;
+  ct[2] = s1925;
+  ct[3] = s1938;
+}
+== END: "aes128Enc.c" ==================
diff --git a/SBVTestSuite/GoldFiles/aes128Lib.gold b/SBVTestSuite/GoldFiles/aes128Lib.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/aes128Lib.gold
@@ -0,0 +1,5079 @@
+== BEGIN: "aes128KeySchedule.c" ================
+/* File: "aes128KeySchedule.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Lib.h"
+
+void aes128KeySchedule(const SWord32 *key, SWord32 *encKS,
+                       SWord32 *decKS)
+{
+  const SWord32 s0 = key[0];
+  const SWord32 s1 = key[1];
+  const SWord32 s2 = key[2];
+  const SWord32 s3 = key[3];
+  static const SWord8 table0[] = {
+       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
+      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
+      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
+      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
+       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
+      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
+       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
+       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
+       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
+      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
+       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
+      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
+      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
+      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
+       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
+       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
+      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
+      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
+      104,  65, 153,  45,  15, 176,  84, 187,  22
+  };
+  static const SWord8 table1[] = {
+        0,  14,  28,  18,  56,  54,  36,  42, 112, 126, 108,  98,  72,
+       70,  84,  90, 224, 238, 252, 242, 216, 214, 196, 202, 144, 158,
+      140, 130, 168, 166, 180, 186, 219, 213, 199, 201, 227, 237, 255,
+      241, 171, 165, 183, 185, 147, 157, 143, 129,  59,  53,  39,  41,
+        3,  13,  31,  17,  75,  69,  87,  89, 115, 125, 111,  97, 173,
+      163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235,
+      249, 247,  77,  67,  81,  95, 117, 123, 105, 103,  61,  51,  33,
+       47,   5,  11,  25,  23, 118, 120, 106, 100,  78,  64,  82,  92,
+        6,   8,  26,  20,  62,  48,  34,  44, 150, 152, 138, 132, 174,
+      160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204,  65,  79,
+       93,  83, 121, 119, 101, 107,  49,  63,  45,  35,   9,   7,  21,
+       27, 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205, 195,
+      233, 231, 245, 251, 154, 148, 134, 136, 162, 172, 190, 176, 234,
+      228, 246, 248, 210, 220, 206, 192, 122, 116, 102, 104,  66,  76,
+       94,  80,  10,   4,  22,  24,  50,  60,  46,  32, 236, 226, 240,
+      254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182,
+       12,   2,  16,  30,  52,  58,  40,  38, 124, 114,  96, 110,  68,
+       74,  88,  86,  55,  57,  43,  37,  15,   1,  19,  29,  71,  73,
+       91,  85, 127, 113,  99, 109, 215, 217, 203, 197, 239, 225, 243,
+      253, 167, 169, 187, 181, 159, 145, 131, 141
+  };
+  static const SWord8 table2[] = {
+        0,  11,  22,  29,  44,  39,  58,  49,  88,  83,  78,  69, 116,
+      127,  98, 105, 176, 187, 166, 173, 156, 151, 138, 129, 232, 227,
+      254, 245, 196, 207, 210, 217, 123, 112, 109, 102,  87,  92,  65,
+       74,  35,  40,  53,  62,  15,   4,  25,  18, 203, 192, 221, 214,
+      231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, 246,
+      253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137,
+      148, 159,  70,  77,  80,  91, 106,  97, 124, 119,  30,  21,   8,
+        3,  50,  57,  36,  47, 141, 134, 155, 144, 161, 170, 183, 188,
+      213, 222, 195, 200, 249, 242, 239, 228,  61,  54,  43,  32,  17,
+       26,   7,  12, 101, 110, 115, 120,  73,  66,  95,  84, 247, 252,
+      225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149,
+      158,  71,  76,  81,  90, 107,  96, 125, 118,  31,  20,   9,   2,
+       51,  56,  37,  46, 140, 135, 154, 145, 160, 171, 182, 189, 212,
+      223, 194, 201, 248, 243, 238, 229,  60,  55,  42,  33,  16,  27,
+        6,  13, 100, 111, 114, 121,  72,  67,  94,  85,   1,  10,  23,
+       28,  45,  38,  59,  48,  89,  82,  79,  68, 117, 126,  99, 104,
+      177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197,
+      206, 211, 216, 122, 113, 108, 103,  86,  93,  64,  75,  34,  41,
+       52,  63,  14,   5,  24,  19, 202, 193, 220, 215, 230, 237, 240,
+      251, 146, 153, 132, 143, 190, 181, 168, 163
+  };
+  static const SWord8 table3[] = {
+        0,  13,  26,  23,  52,  57,  46,  35, 104, 101, 114, 127,  92,
+       81,  70,  75, 208, 221, 202, 199, 228, 233, 254, 243, 184, 181,
+      162, 175, 140, 129, 150, 155, 187, 182, 161, 172, 143, 130, 149,
+      152, 211, 222, 201, 196, 231, 234, 253, 240, 107, 102, 113, 124,
+       95,  82,  69,  72,   3,  14,  25,  20,  55,  58,  45,  32, 109,
+       96, 119, 122,  89,  84,  67,  78,   5,   8,  31,  18,  49,  60,
+       43,  38, 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207,
+      194, 225, 236, 251, 246, 214, 219, 204, 193, 226, 239, 248, 245,
+      190, 179, 164, 169, 138, 135, 144, 157,   6,  11,  28,  17,  50,
+       63,  40,  37, 110,  99, 116, 121,  90,  87,  64,  77, 218, 215,
+      192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156,
+      145,  10,   7,  16,  29,  62,  51,  36,  41,  98, 111, 120, 117,
+       86,  91,  76,  65,  97, 108, 123, 118,  85,  88,  79,  66,   9,
+        4,  19,  30,  61,  48,  39,  42, 177, 188, 171, 166, 133, 136,
+      159, 146, 217, 212, 195, 206, 237, 224, 247, 250, 183, 186, 173,
+      160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252,
+      103, 106, 125, 112,  83,  94,  73,  68,  15,   2,  21,  24,  59,
+       54,  33,  44,  12,   1,  22,  27,  56,  53,  34,  47, 100, 105,
+      126, 115,  80,  93,  74,  71, 220, 209, 198, 203, 232, 229, 242,
+      255, 180, 185, 174, 163, 128, 141, 154, 151
+  };
+  static const SWord8 table4[] = {
+        0,   9,  18,  27,  36,  45,  54,  63,  72,  65,  90,  83, 108,
+      101, 126, 119, 144, 153, 130, 139, 180, 189, 166, 175, 216, 209,
+      202, 195, 252, 245, 238, 231,  59,  50,  41,  32,  31,  22,  13,
+        4, 115, 122,  97, 104,  87,  94,  69,  76, 171, 162, 185, 176,
+      143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, 118,
+      127, 100, 109,  82,  91,  64,  73,  62,  55,  44,  37,  26,  19,
+        8,   1, 230, 239, 244, 253, 194, 203, 208, 217, 174, 167, 188,
+      181, 138, 131, 152, 145,  77,  68,  95,  86, 105,  96, 123, 114,
+        5,  12,  23,  30,  33,  40,  51,  58, 221, 212, 207, 198, 249,
+      240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, 236, 229,
+      254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146,
+      155, 124, 117, 110, 103,  88,  81,  74,  67,  52,  61,  38,  47,
+       16,  25,   2,  11, 215, 222, 197, 204, 243, 250, 225, 232, 159,
+      150, 141, 132, 187, 178, 169, 160,  71,  78,  85,  92,  99, 106,
+      113, 120,  15,   6,  29,  20,  43,  34,  57,  48, 154, 147, 136,
+      129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237,
+       10,   3,  24,  17,  46,  39,  60,  53,  66,  75,  80,  89, 102,
+      111, 116, 125, 161, 168, 179, 186, 133, 140, 151, 158, 233, 224,
+      251, 242, 205, 196, 223, 214,  49,  56,  35,  42,  21,  28,   7,
+       14, 121, 112, 107,  98,  93,  84,  79,  70
+  };
+  const SWord32 s260 = (s3 << 8) | (s3 >> 24);
+  const SWord8  s261 = (SWord8) (s260 >> 24);
+  const SWord8  s262 = table0[s261];
+  const SWord8  s263 = 1 ^ s262;
+  const SWord8  s264 = (SWord8) (s260 >> 16);
+  const SWord8  s265 = table0[s264];
+  const SWord16 s266 = (((SWord16) s263) << 8) | ((SWord16) s265);
+  const SWord8  s267 = (SWord8) (s260 >> 8);
+  const SWord8  s268 = table0[s267];
+  const SWord8  s269 = (SWord8) s260;
+  const SWord8  s270 = table0[s269];
+  const SWord16 s271 = (((SWord16) s268) << 8) | ((SWord16) s270);
+  const SWord32 s272 = (((SWord32) s266) << 16) | ((SWord32) s271);
+  const SWord32 s273 = s0 ^ s272;
+  const SWord32 s274 = s1 ^ s273;
+  const SWord32 s275 = s2 ^ s274;
+  const SWord32 s276 = s3 ^ s275;
+  const SWord32 s277 = (s276 << 8) | (s276 >> 24);
+  const SWord8  s278 = (SWord8) (s277 >> 24);
+  const SWord8  s279 = table0[s278];
+  const SWord8  s280 = 2 ^ s279;
+  const SWord8  s281 = (SWord8) (s277 >> 16);
+  const SWord8  s282 = table0[s281];
+  const SWord16 s283 = (((SWord16) s280) << 8) | ((SWord16) s282);
+  const SWord8  s284 = (SWord8) (s277 >> 8);
+  const SWord8  s285 = table0[s284];
+  const SWord8  s286 = (SWord8) s277;
+  const SWord8  s287 = table0[s286];
+  const SWord16 s288 = (((SWord16) s285) << 8) | ((SWord16) s287);
+  const SWord32 s289 = (((SWord32) s283) << 16) | ((SWord32) s288);
+  const SWord32 s290 = s273 ^ s289;
+  const SWord32 s291 = s274 ^ s290;
+  const SWord32 s292 = s275 ^ s291;
+  const SWord32 s293 = s276 ^ s292;
+  const SWord32 s294 = (s293 << 8) | (s293 >> 24);
+  const SWord8  s295 = (SWord8) (s294 >> 24);
+  const SWord8  s296 = table0[s295];
+  const SWord8  s297 = 4 ^ s296;
+  const SWord8  s298 = (SWord8) (s294 >> 16);
+  const SWord8  s299 = table0[s298];
+  const SWord16 s300 = (((SWord16) s297) << 8) | ((SWord16) s299);
+  const SWord8  s301 = (SWord8) (s294 >> 8);
+  const SWord8  s302 = table0[s301];
+  const SWord8  s303 = (SWord8) s294;
+  const SWord8  s304 = table0[s303];
+  const SWord16 s305 = (((SWord16) s302) << 8) | ((SWord16) s304);
+  const SWord32 s306 = (((SWord32) s300) << 16) | ((SWord32) s305);
+  const SWord32 s307 = s290 ^ s306;
+  const SWord32 s308 = s291 ^ s307;
+  const SWord32 s309 = s292 ^ s308;
+  const SWord32 s310 = s293 ^ s309;
+  const SWord32 s311 = (s310 << 8) | (s310 >> 24);
+  const SWord8  s312 = (SWord8) (s311 >> 24);
+  const SWord8  s313 = table0[s312];
+  const SWord8  s314 = 8 ^ s313;
+  const SWord8  s315 = (SWord8) (s311 >> 16);
+  const SWord8  s316 = table0[s315];
+  const SWord16 s317 = (((SWord16) s314) << 8) | ((SWord16) s316);
+  const SWord8  s318 = (SWord8) (s311 >> 8);
+  const SWord8  s319 = table0[s318];
+  const SWord8  s320 = (SWord8) s311;
+  const SWord8  s321 = table0[s320];
+  const SWord16 s322 = (((SWord16) s319) << 8) | ((SWord16) s321);
+  const SWord32 s323 = (((SWord32) s317) << 16) | ((SWord32) s322);
+  const SWord32 s324 = s307 ^ s323;
+  const SWord32 s325 = s308 ^ s324;
+  const SWord32 s326 = s309 ^ s325;
+  const SWord32 s327 = s310 ^ s326;
+  const SWord32 s328 = (s327 << 8) | (s327 >> 24);
+  const SWord8  s329 = (SWord8) (s328 >> 24);
+  const SWord8  s330 = table0[s329];
+  const SWord8  s331 = 16 ^ s330;
+  const SWord8  s332 = (SWord8) (s328 >> 16);
+  const SWord8  s333 = table0[s332];
+  const SWord16 s334 = (((SWord16) s331) << 8) | ((SWord16) s333);
+  const SWord8  s335 = (SWord8) (s328 >> 8);
+  const SWord8  s336 = table0[s335];
+  const SWord8  s337 = (SWord8) s328;
+  const SWord8  s338 = table0[s337];
+  const SWord16 s339 = (((SWord16) s336) << 8) | ((SWord16) s338);
+  const SWord32 s340 = (((SWord32) s334) << 16) | ((SWord32) s339);
+  const SWord32 s341 = s324 ^ s340;
+  const SWord32 s342 = s325 ^ s341;
+  const SWord32 s343 = s326 ^ s342;
+  const SWord32 s344 = s327 ^ s343;
+  const SWord32 s345 = (s344 << 8) | (s344 >> 24);
+  const SWord8  s346 = (SWord8) (s345 >> 24);
+  const SWord8  s347 = table0[s346];
+  const SWord8  s348 = 32 ^ s347;
+  const SWord8  s349 = (SWord8) (s345 >> 16);
+  const SWord8  s350 = table0[s349];
+  const SWord16 s351 = (((SWord16) s348) << 8) | ((SWord16) s350);
+  const SWord8  s352 = (SWord8) (s345 >> 8);
+  const SWord8  s353 = table0[s352];
+  const SWord8  s354 = (SWord8) s345;
+  const SWord8  s355 = table0[s354];
+  const SWord16 s356 = (((SWord16) s353) << 8) | ((SWord16) s355);
+  const SWord32 s357 = (((SWord32) s351) << 16) | ((SWord32) s356);
+  const SWord32 s358 = s341 ^ s357;
+  const SWord32 s359 = s342 ^ s358;
+  const SWord32 s360 = s343 ^ s359;
+  const SWord32 s361 = s344 ^ s360;
+  const SWord32 s362 = (s361 << 8) | (s361 >> 24);
+  const SWord8  s363 = (SWord8) (s362 >> 24);
+  const SWord8  s364 = table0[s363];
+  const SWord8  s365 = 64 ^ s364;
+  const SWord8  s366 = (SWord8) (s362 >> 16);
+  const SWord8  s367 = table0[s366];
+  const SWord16 s368 = (((SWord16) s365) << 8) | ((SWord16) s367);
+  const SWord8  s369 = (SWord8) (s362 >> 8);
+  const SWord8  s370 = table0[s369];
+  const SWord8  s371 = (SWord8) s362;
+  const SWord8  s372 = table0[s371];
+  const SWord16 s373 = (((SWord16) s370) << 8) | ((SWord16) s372);
+  const SWord32 s374 = (((SWord32) s368) << 16) | ((SWord32) s373);
+  const SWord32 s375 = s358 ^ s374;
+  const SWord32 s376 = s359 ^ s375;
+  const SWord32 s377 = s360 ^ s376;
+  const SWord32 s378 = s361 ^ s377;
+  const SWord32 s379 = (s378 << 8) | (s378 >> 24);
+  const SWord8  s380 = (SWord8) (s379 >> 24);
+  const SWord8  s381 = table0[s380];
+  const SWord8  s382 = 128 ^ s381;
+  const SWord8  s383 = (SWord8) (s379 >> 16);
+  const SWord8  s384 = table0[s383];
+  const SWord16 s385 = (((SWord16) s382) << 8) | ((SWord16) s384);
+  const SWord8  s386 = (SWord8) (s379 >> 8);
+  const SWord8  s387 = table0[s386];
+  const SWord8  s388 = (SWord8) s379;
+  const SWord8  s389 = table0[s388];
+  const SWord16 s390 = (((SWord16) s387) << 8) | ((SWord16) s389);
+  const SWord32 s391 = (((SWord32) s385) << 16) | ((SWord32) s390);
+  const SWord32 s392 = s375 ^ s391;
+  const SWord32 s393 = s376 ^ s392;
+  const SWord32 s394 = s377 ^ s393;
+  const SWord32 s395 = s378 ^ s394;
+  const SWord32 s396 = (s395 << 8) | (s395 >> 24);
+  const SWord8  s397 = (SWord8) (s396 >> 24);
+  const SWord8  s398 = table0[s397];
+  const SWord8  s399 = 27 ^ s398;
+  const SWord8  s400 = (SWord8) (s396 >> 16);
+  const SWord8  s401 = table0[s400];
+  const SWord16 s402 = (((SWord16) s399) << 8) | ((SWord16) s401);
+  const SWord8  s403 = (SWord8) (s396 >> 8);
+  const SWord8  s404 = table0[s403];
+  const SWord8  s405 = (SWord8) s396;
+  const SWord8  s406 = table0[s405];
+  const SWord16 s407 = (((SWord16) s404) << 8) | ((SWord16) s406);
+  const SWord32 s408 = (((SWord32) s402) << 16) | ((SWord32) s407);
+  const SWord32 s409 = s392 ^ s408;
+  const SWord32 s410 = s393 ^ s409;
+  const SWord32 s411 = s394 ^ s410;
+  const SWord32 s412 = s395 ^ s411;
+  const SWord32 s413 = (s412 << 8) | (s412 >> 24);
+  const SWord8  s414 = (SWord8) (s413 >> 24);
+  const SWord8  s415 = table0[s414];
+  const SWord8  s416 = 54 ^ s415;
+  const SWord8  s417 = (SWord8) (s413 >> 16);
+  const SWord8  s418 = table0[s417];
+  const SWord16 s419 = (((SWord16) s416) << 8) | ((SWord16) s418);
+  const SWord8  s420 = (SWord8) (s413 >> 8);
+  const SWord8  s421 = table0[s420];
+  const SWord8  s422 = (SWord8) s413;
+  const SWord8  s423 = table0[s422];
+  const SWord16 s424 = (((SWord16) s421) << 8) | ((SWord16) s423);
+  const SWord32 s425 = (((SWord32) s419) << 16) | ((SWord32) s424);
+  const SWord32 s426 = s409 ^ s425;
+  const SWord32 s427 = s410 ^ s426;
+  const SWord32 s428 = s411 ^ s427;
+  const SWord32 s429 = s412 ^ s428;
+  const SWord8  s430 = (SWord8) (s409 >> 24);
+  const SWord8  s431 = table1[s430];
+  const SWord8  s432 = (SWord8) (s409 >> 16);
+  const SWord8  s433 = table2[s432];
+  const SWord8  s434 = (SWord8) (s409 >> 8);
+  const SWord8  s435 = table3[s434];
+  const SWord8  s436 = (SWord8) s409;
+  const SWord8  s437 = table4[s436];
+  const SWord8  s438 = s435 ^ s437;
+  const SWord8  s439 = s433 ^ s438;
+  const SWord8  s440 = s431 ^ s439;
+  const SWord8  s441 = table4[s430];
+  const SWord8  s442 = table1[s432];
+  const SWord8  s443 = table2[s434];
+  const SWord8  s444 = table3[s436];
+  const SWord8  s445 = s443 ^ s444;
+  const SWord8  s446 = s442 ^ s445;
+  const SWord8  s447 = s441 ^ s446;
+  const SWord16 s448 = (((SWord16) s440) << 8) | ((SWord16) s447);
+  const SWord8  s449 = table3[s430];
+  const SWord8  s450 = table4[s432];
+  const SWord8  s451 = table1[s434];
+  const SWord8  s452 = table2[s436];
+  const SWord8  s453 = s451 ^ s452;
+  const SWord8  s454 = s450 ^ s453;
+  const SWord8  s455 = s449 ^ s454;
+  const SWord8  s456 = table2[s430];
+  const SWord8  s457 = table3[s432];
+  const SWord8  s458 = table4[s434];
+  const SWord8  s459 = table1[s436];
+  const SWord8  s460 = s458 ^ s459;
+  const SWord8  s461 = s457 ^ s460;
+  const SWord8  s462 = s456 ^ s461;
+  const SWord16 s463 = (((SWord16) s455) << 8) | ((SWord16) s462);
+  const SWord32 s464 = (((SWord32) s448) << 16) | ((SWord32) s463);
+  const SWord8  s465 = (SWord8) (s410 >> 24);
+  const SWord8  s466 = table1[s465];
+  const SWord8  s467 = (SWord8) (s410 >> 16);
+  const SWord8  s468 = table2[s467];
+  const SWord8  s469 = (SWord8) (s410 >> 8);
+  const SWord8  s470 = table3[s469];
+  const SWord8  s471 = (SWord8) s410;
+  const SWord8  s472 = table4[s471];
+  const SWord8  s473 = s470 ^ s472;
+  const SWord8  s474 = s468 ^ s473;
+  const SWord8  s475 = s466 ^ s474;
+  const SWord8  s476 = table4[s465];
+  const SWord8  s477 = table1[s467];
+  const SWord8  s478 = table2[s469];
+  const SWord8  s479 = table3[s471];
+  const SWord8  s480 = s478 ^ s479;
+  const SWord8  s481 = s477 ^ s480;
+  const SWord8  s482 = s476 ^ s481;
+  const SWord16 s483 = (((SWord16) s475) << 8) | ((SWord16) s482);
+  const SWord8  s484 = table3[s465];
+  const SWord8  s485 = table4[s467];
+  const SWord8  s486 = table1[s469];
+  const SWord8  s487 = table2[s471];
+  const SWord8  s488 = s486 ^ s487;
+  const SWord8  s489 = s485 ^ s488;
+  const SWord8  s490 = s484 ^ s489;
+  const SWord8  s491 = table2[s465];
+  const SWord8  s492 = table3[s467];
+  const SWord8  s493 = table4[s469];
+  const SWord8  s494 = table1[s471];
+  const SWord8  s495 = s493 ^ s494;
+  const SWord8  s496 = s492 ^ s495;
+  const SWord8  s497 = s491 ^ s496;
+  const SWord16 s498 = (((SWord16) s490) << 8) | ((SWord16) s497);
+  const SWord32 s499 = (((SWord32) s483) << 16) | ((SWord32) s498);
+  const SWord8  s500 = (SWord8) (s411 >> 24);
+  const SWord8  s501 = table1[s500];
+  const SWord8  s502 = (SWord8) (s411 >> 16);
+  const SWord8  s503 = table2[s502];
+  const SWord8  s504 = (SWord8) (s411 >> 8);
+  const SWord8  s505 = table3[s504];
+  const SWord8  s506 = (SWord8) s411;
+  const SWord8  s507 = table4[s506];
+  const SWord8  s508 = s505 ^ s507;
+  const SWord8  s509 = s503 ^ s508;
+  const SWord8  s510 = s501 ^ s509;
+  const SWord8  s511 = table4[s500];
+  const SWord8  s512 = table1[s502];
+  const SWord8  s513 = table2[s504];
+  const SWord8  s514 = table3[s506];
+  const SWord8  s515 = s513 ^ s514;
+  const SWord8  s516 = s512 ^ s515;
+  const SWord8  s517 = s511 ^ s516;
+  const SWord16 s518 = (((SWord16) s510) << 8) | ((SWord16) s517);
+  const SWord8  s519 = table3[s500];
+  const SWord8  s520 = table4[s502];
+  const SWord8  s521 = table1[s504];
+  const SWord8  s522 = table2[s506];
+  const SWord8  s523 = s521 ^ s522;
+  const SWord8  s524 = s520 ^ s523;
+  const SWord8  s525 = s519 ^ s524;
+  const SWord8  s526 = table2[s500];
+  const SWord8  s527 = table3[s502];
+  const SWord8  s528 = table4[s504];
+  const SWord8  s529 = table1[s506];
+  const SWord8  s530 = s528 ^ s529;
+  const SWord8  s531 = s527 ^ s530;
+  const SWord8  s532 = s526 ^ s531;
+  const SWord16 s533 = (((SWord16) s525) << 8) | ((SWord16) s532);
+  const SWord32 s534 = (((SWord32) s518) << 16) | ((SWord32) s533);
+  const SWord8  s535 = (SWord8) (s412 >> 24);
+  const SWord8  s536 = table1[s535];
+  const SWord8  s537 = (SWord8) (s412 >> 16);
+  const SWord8  s538 = table2[s537];
+  const SWord8  s539 = (SWord8) (s412 >> 8);
+  const SWord8  s540 = table3[s539];
+  const SWord8  s541 = (SWord8) s412;
+  const SWord8  s542 = table4[s541];
+  const SWord8  s543 = s540 ^ s542;
+  const SWord8  s544 = s538 ^ s543;
+  const SWord8  s545 = s536 ^ s544;
+  const SWord8  s546 = table4[s535];
+  const SWord8  s547 = table1[s537];
+  const SWord8  s548 = table2[s539];
+  const SWord8  s549 = table3[s541];
+  const SWord8  s550 = s548 ^ s549;
+  const SWord8  s551 = s547 ^ s550;
+  const SWord8  s552 = s546 ^ s551;
+  const SWord16 s553 = (((SWord16) s545) << 8) | ((SWord16) s552);
+  const SWord8  s554 = table3[s535];
+  const SWord8  s555 = table4[s537];
+  const SWord8  s556 = table1[s539];
+  const SWord8  s557 = table2[s541];
+  const SWord8  s558 = s556 ^ s557;
+  const SWord8  s559 = s555 ^ s558;
+  const SWord8  s560 = s554 ^ s559;
+  const SWord8  s561 = table2[s535];
+  const SWord8  s562 = table3[s537];
+  const SWord8  s563 = table4[s539];
+  const SWord8  s564 = table1[s541];
+  const SWord8  s565 = s563 ^ s564;
+  const SWord8  s566 = s562 ^ s565;
+  const SWord8  s567 = s561 ^ s566;
+  const SWord16 s568 = (((SWord16) s560) << 8) | ((SWord16) s567);
+  const SWord32 s569 = (((SWord32) s553) << 16) | ((SWord32) s568);
+  const SWord8  s570 = (SWord8) (s392 >> 24);
+  const SWord8  s571 = table1[s570];
+  const SWord8  s572 = (SWord8) (s392 >> 16);
+  const SWord8  s573 = table2[s572];
+  const SWord8  s574 = (SWord8) (s392 >> 8);
+  const SWord8  s575 = table3[s574];
+  const SWord8  s576 = (SWord8) s392;
+  const SWord8  s577 = table4[s576];
+  const SWord8  s578 = s575 ^ s577;
+  const SWord8  s579 = s573 ^ s578;
+  const SWord8  s580 = s571 ^ s579;
+  const SWord8  s581 = table4[s570];
+  const SWord8  s582 = table1[s572];
+  const SWord8  s583 = table2[s574];
+  const SWord8  s584 = table3[s576];
+  const SWord8  s585 = s583 ^ s584;
+  const SWord8  s586 = s582 ^ s585;
+  const SWord8  s587 = s581 ^ s586;
+  const SWord16 s588 = (((SWord16) s580) << 8) | ((SWord16) s587);
+  const SWord8  s589 = table3[s570];
+  const SWord8  s590 = table4[s572];
+  const SWord8  s591 = table1[s574];
+  const SWord8  s592 = table2[s576];
+  const SWord8  s593 = s591 ^ s592;
+  const SWord8  s594 = s590 ^ s593;
+  const SWord8  s595 = s589 ^ s594;
+  const SWord8  s596 = table2[s570];
+  const SWord8  s597 = table3[s572];
+  const SWord8  s598 = table4[s574];
+  const SWord8  s599 = table1[s576];
+  const SWord8  s600 = s598 ^ s599;
+  const SWord8  s601 = s597 ^ s600;
+  const SWord8  s602 = s596 ^ s601;
+  const SWord16 s603 = (((SWord16) s595) << 8) | ((SWord16) s602);
+  const SWord32 s604 = (((SWord32) s588) << 16) | ((SWord32) s603);
+  const SWord8  s605 = (SWord8) (s393 >> 24);
+  const SWord8  s606 = table1[s605];
+  const SWord8  s607 = (SWord8) (s393 >> 16);
+  const SWord8  s608 = table2[s607];
+  const SWord8  s609 = (SWord8) (s393 >> 8);
+  const SWord8  s610 = table3[s609];
+  const SWord8  s611 = (SWord8) s393;
+  const SWord8  s612 = table4[s611];
+  const SWord8  s613 = s610 ^ s612;
+  const SWord8  s614 = s608 ^ s613;
+  const SWord8  s615 = s606 ^ s614;
+  const SWord8  s616 = table4[s605];
+  const SWord8  s617 = table1[s607];
+  const SWord8  s618 = table2[s609];
+  const SWord8  s619 = table3[s611];
+  const SWord8  s620 = s618 ^ s619;
+  const SWord8  s621 = s617 ^ s620;
+  const SWord8  s622 = s616 ^ s621;
+  const SWord16 s623 = (((SWord16) s615) << 8) | ((SWord16) s622);
+  const SWord8  s624 = table3[s605];
+  const SWord8  s625 = table4[s607];
+  const SWord8  s626 = table1[s609];
+  const SWord8  s627 = table2[s611];
+  const SWord8  s628 = s626 ^ s627;
+  const SWord8  s629 = s625 ^ s628;
+  const SWord8  s630 = s624 ^ s629;
+  const SWord8  s631 = table2[s605];
+  const SWord8  s632 = table3[s607];
+  const SWord8  s633 = table4[s609];
+  const SWord8  s634 = table1[s611];
+  const SWord8  s635 = s633 ^ s634;
+  const SWord8  s636 = s632 ^ s635;
+  const SWord8  s637 = s631 ^ s636;
+  const SWord16 s638 = (((SWord16) s630) << 8) | ((SWord16) s637);
+  const SWord32 s639 = (((SWord32) s623) << 16) | ((SWord32) s638);
+  const SWord8  s640 = (SWord8) (s394 >> 24);
+  const SWord8  s641 = table1[s640];
+  const SWord8  s642 = (SWord8) (s394 >> 16);
+  const SWord8  s643 = table2[s642];
+  const SWord8  s644 = (SWord8) (s394 >> 8);
+  const SWord8  s645 = table3[s644];
+  const SWord8  s646 = (SWord8) s394;
+  const SWord8  s647 = table4[s646];
+  const SWord8  s648 = s645 ^ s647;
+  const SWord8  s649 = s643 ^ s648;
+  const SWord8  s650 = s641 ^ s649;
+  const SWord8  s651 = table4[s640];
+  const SWord8  s652 = table1[s642];
+  const SWord8  s653 = table2[s644];
+  const SWord8  s654 = table3[s646];
+  const SWord8  s655 = s653 ^ s654;
+  const SWord8  s656 = s652 ^ s655;
+  const SWord8  s657 = s651 ^ s656;
+  const SWord16 s658 = (((SWord16) s650) << 8) | ((SWord16) s657);
+  const SWord8  s659 = table3[s640];
+  const SWord8  s660 = table4[s642];
+  const SWord8  s661 = table1[s644];
+  const SWord8  s662 = table2[s646];
+  const SWord8  s663 = s661 ^ s662;
+  const SWord8  s664 = s660 ^ s663;
+  const SWord8  s665 = s659 ^ s664;
+  const SWord8  s666 = table2[s640];
+  const SWord8  s667 = table3[s642];
+  const SWord8  s668 = table4[s644];
+  const SWord8  s669 = table1[s646];
+  const SWord8  s670 = s668 ^ s669;
+  const SWord8  s671 = s667 ^ s670;
+  const SWord8  s672 = s666 ^ s671;
+  const SWord16 s673 = (((SWord16) s665) << 8) | ((SWord16) s672);
+  const SWord32 s674 = (((SWord32) s658) << 16) | ((SWord32) s673);
+  const SWord8  s675 = (SWord8) (s395 >> 24);
+  const SWord8  s676 = table1[s675];
+  const SWord8  s677 = (SWord8) (s395 >> 16);
+  const SWord8  s678 = table2[s677];
+  const SWord8  s679 = (SWord8) (s395 >> 8);
+  const SWord8  s680 = table3[s679];
+  const SWord8  s681 = (SWord8) s395;
+  const SWord8  s682 = table4[s681];
+  const SWord8  s683 = s680 ^ s682;
+  const SWord8  s684 = s678 ^ s683;
+  const SWord8  s685 = s676 ^ s684;
+  const SWord8  s686 = table4[s675];
+  const SWord8  s687 = table1[s677];
+  const SWord8  s688 = table2[s679];
+  const SWord8  s689 = table3[s681];
+  const SWord8  s690 = s688 ^ s689;
+  const SWord8  s691 = s687 ^ s690;
+  const SWord8  s692 = s686 ^ s691;
+  const SWord16 s693 = (((SWord16) s685) << 8) | ((SWord16) s692);
+  const SWord8  s694 = table3[s675];
+  const SWord8  s695 = table4[s677];
+  const SWord8  s696 = table1[s679];
+  const SWord8  s697 = table2[s681];
+  const SWord8  s698 = s696 ^ s697;
+  const SWord8  s699 = s695 ^ s698;
+  const SWord8  s700 = s694 ^ s699;
+  const SWord8  s701 = table2[s675];
+  const SWord8  s702 = table3[s677];
+  const SWord8  s703 = table4[s679];
+  const SWord8  s704 = table1[s681];
+  const SWord8  s705 = s703 ^ s704;
+  const SWord8  s706 = s702 ^ s705;
+  const SWord8  s707 = s701 ^ s706;
+  const SWord16 s708 = (((SWord16) s700) << 8) | ((SWord16) s707);
+  const SWord32 s709 = (((SWord32) s693) << 16) | ((SWord32) s708);
+  const SWord8  s710 = (SWord8) (s375 >> 24);
+  const SWord8  s711 = table1[s710];
+  const SWord8  s712 = (SWord8) (s375 >> 16);
+  const SWord8  s713 = table2[s712];
+  const SWord8  s714 = (SWord8) (s375 >> 8);
+  const SWord8  s715 = table3[s714];
+  const SWord8  s716 = (SWord8) s375;
+  const SWord8  s717 = table4[s716];
+  const SWord8  s718 = s715 ^ s717;
+  const SWord8  s719 = s713 ^ s718;
+  const SWord8  s720 = s711 ^ s719;
+  const SWord8  s721 = table4[s710];
+  const SWord8  s722 = table1[s712];
+  const SWord8  s723 = table2[s714];
+  const SWord8  s724 = table3[s716];
+  const SWord8  s725 = s723 ^ s724;
+  const SWord8  s726 = s722 ^ s725;
+  const SWord8  s727 = s721 ^ s726;
+  const SWord16 s728 = (((SWord16) s720) << 8) | ((SWord16) s727);
+  const SWord8  s729 = table3[s710];
+  const SWord8  s730 = table4[s712];
+  const SWord8  s731 = table1[s714];
+  const SWord8  s732 = table2[s716];
+  const SWord8  s733 = s731 ^ s732;
+  const SWord8  s734 = s730 ^ s733;
+  const SWord8  s735 = s729 ^ s734;
+  const SWord8  s736 = table2[s710];
+  const SWord8  s737 = table3[s712];
+  const SWord8  s738 = table4[s714];
+  const SWord8  s739 = table1[s716];
+  const SWord8  s740 = s738 ^ s739;
+  const SWord8  s741 = s737 ^ s740;
+  const SWord8  s742 = s736 ^ s741;
+  const SWord16 s743 = (((SWord16) s735) << 8) | ((SWord16) s742);
+  const SWord32 s744 = (((SWord32) s728) << 16) | ((SWord32) s743);
+  const SWord8  s745 = (SWord8) (s376 >> 24);
+  const SWord8  s746 = table1[s745];
+  const SWord8  s747 = (SWord8) (s376 >> 16);
+  const SWord8  s748 = table2[s747];
+  const SWord8  s749 = (SWord8) (s376 >> 8);
+  const SWord8  s750 = table3[s749];
+  const SWord8  s751 = (SWord8) s376;
+  const SWord8  s752 = table4[s751];
+  const SWord8  s753 = s750 ^ s752;
+  const SWord8  s754 = s748 ^ s753;
+  const SWord8  s755 = s746 ^ s754;
+  const SWord8  s756 = table4[s745];
+  const SWord8  s757 = table1[s747];
+  const SWord8  s758 = table2[s749];
+  const SWord8  s759 = table3[s751];
+  const SWord8  s760 = s758 ^ s759;
+  const SWord8  s761 = s757 ^ s760;
+  const SWord8  s762 = s756 ^ s761;
+  const SWord16 s763 = (((SWord16) s755) << 8) | ((SWord16) s762);
+  const SWord8  s764 = table3[s745];
+  const SWord8  s765 = table4[s747];
+  const SWord8  s766 = table1[s749];
+  const SWord8  s767 = table2[s751];
+  const SWord8  s768 = s766 ^ s767;
+  const SWord8  s769 = s765 ^ s768;
+  const SWord8  s770 = s764 ^ s769;
+  const SWord8  s771 = table2[s745];
+  const SWord8  s772 = table3[s747];
+  const SWord8  s773 = table4[s749];
+  const SWord8  s774 = table1[s751];
+  const SWord8  s775 = s773 ^ s774;
+  const SWord8  s776 = s772 ^ s775;
+  const SWord8  s777 = s771 ^ s776;
+  const SWord16 s778 = (((SWord16) s770) << 8) | ((SWord16) s777);
+  const SWord32 s779 = (((SWord32) s763) << 16) | ((SWord32) s778);
+  const SWord8  s780 = (SWord8) (s377 >> 24);
+  const SWord8  s781 = table1[s780];
+  const SWord8  s782 = (SWord8) (s377 >> 16);
+  const SWord8  s783 = table2[s782];
+  const SWord8  s784 = (SWord8) (s377 >> 8);
+  const SWord8  s785 = table3[s784];
+  const SWord8  s786 = (SWord8) s377;
+  const SWord8  s787 = table4[s786];
+  const SWord8  s788 = s785 ^ s787;
+  const SWord8  s789 = s783 ^ s788;
+  const SWord8  s790 = s781 ^ s789;
+  const SWord8  s791 = table4[s780];
+  const SWord8  s792 = table1[s782];
+  const SWord8  s793 = table2[s784];
+  const SWord8  s794 = table3[s786];
+  const SWord8  s795 = s793 ^ s794;
+  const SWord8  s796 = s792 ^ s795;
+  const SWord8  s797 = s791 ^ s796;
+  const SWord16 s798 = (((SWord16) s790) << 8) | ((SWord16) s797);
+  const SWord8  s799 = table3[s780];
+  const SWord8  s800 = table4[s782];
+  const SWord8  s801 = table1[s784];
+  const SWord8  s802 = table2[s786];
+  const SWord8  s803 = s801 ^ s802;
+  const SWord8  s804 = s800 ^ s803;
+  const SWord8  s805 = s799 ^ s804;
+  const SWord8  s806 = table2[s780];
+  const SWord8  s807 = table3[s782];
+  const SWord8  s808 = table4[s784];
+  const SWord8  s809 = table1[s786];
+  const SWord8  s810 = s808 ^ s809;
+  const SWord8  s811 = s807 ^ s810;
+  const SWord8  s812 = s806 ^ s811;
+  const SWord16 s813 = (((SWord16) s805) << 8) | ((SWord16) s812);
+  const SWord32 s814 = (((SWord32) s798) << 16) | ((SWord32) s813);
+  const SWord8  s815 = (SWord8) (s378 >> 24);
+  const SWord8  s816 = table1[s815];
+  const SWord8  s817 = (SWord8) (s378 >> 16);
+  const SWord8  s818 = table2[s817];
+  const SWord8  s819 = (SWord8) (s378 >> 8);
+  const SWord8  s820 = table3[s819];
+  const SWord8  s821 = (SWord8) s378;
+  const SWord8  s822 = table4[s821];
+  const SWord8  s823 = s820 ^ s822;
+  const SWord8  s824 = s818 ^ s823;
+  const SWord8  s825 = s816 ^ s824;
+  const SWord8  s826 = table4[s815];
+  const SWord8  s827 = table1[s817];
+  const SWord8  s828 = table2[s819];
+  const SWord8  s829 = table3[s821];
+  const SWord8  s830 = s828 ^ s829;
+  const SWord8  s831 = s827 ^ s830;
+  const SWord8  s832 = s826 ^ s831;
+  const SWord16 s833 = (((SWord16) s825) << 8) | ((SWord16) s832);
+  const SWord8  s834 = table3[s815];
+  const SWord8  s835 = table4[s817];
+  const SWord8  s836 = table1[s819];
+  const SWord8  s837 = table2[s821];
+  const SWord8  s838 = s836 ^ s837;
+  const SWord8  s839 = s835 ^ s838;
+  const SWord8  s840 = s834 ^ s839;
+  const SWord8  s841 = table2[s815];
+  const SWord8  s842 = table3[s817];
+  const SWord8  s843 = table4[s819];
+  const SWord8  s844 = table1[s821];
+  const SWord8  s845 = s843 ^ s844;
+  const SWord8  s846 = s842 ^ s845;
+  const SWord8  s847 = s841 ^ s846;
+  const SWord16 s848 = (((SWord16) s840) << 8) | ((SWord16) s847);
+  const SWord32 s849 = (((SWord32) s833) << 16) | ((SWord32) s848);
+  const SWord8  s850 = (SWord8) (s358 >> 24);
+  const SWord8  s851 = table1[s850];
+  const SWord8  s852 = (SWord8) (s358 >> 16);
+  const SWord8  s853 = table2[s852];
+  const SWord8  s854 = (SWord8) (s358 >> 8);
+  const SWord8  s855 = table3[s854];
+  const SWord8  s856 = (SWord8) s358;
+  const SWord8  s857 = table4[s856];
+  const SWord8  s858 = s855 ^ s857;
+  const SWord8  s859 = s853 ^ s858;
+  const SWord8  s860 = s851 ^ s859;
+  const SWord8  s861 = table4[s850];
+  const SWord8  s862 = table1[s852];
+  const SWord8  s863 = table2[s854];
+  const SWord8  s864 = table3[s856];
+  const SWord8  s865 = s863 ^ s864;
+  const SWord8  s866 = s862 ^ s865;
+  const SWord8  s867 = s861 ^ s866;
+  const SWord16 s868 = (((SWord16) s860) << 8) | ((SWord16) s867);
+  const SWord8  s869 = table3[s850];
+  const SWord8  s870 = table4[s852];
+  const SWord8  s871 = table1[s854];
+  const SWord8  s872 = table2[s856];
+  const SWord8  s873 = s871 ^ s872;
+  const SWord8  s874 = s870 ^ s873;
+  const SWord8  s875 = s869 ^ s874;
+  const SWord8  s876 = table2[s850];
+  const SWord8  s877 = table3[s852];
+  const SWord8  s878 = table4[s854];
+  const SWord8  s879 = table1[s856];
+  const SWord8  s880 = s878 ^ s879;
+  const SWord8  s881 = s877 ^ s880;
+  const SWord8  s882 = s876 ^ s881;
+  const SWord16 s883 = (((SWord16) s875) << 8) | ((SWord16) s882);
+  const SWord32 s884 = (((SWord32) s868) << 16) | ((SWord32) s883);
+  const SWord8  s885 = (SWord8) (s359 >> 24);
+  const SWord8  s886 = table1[s885];
+  const SWord8  s887 = (SWord8) (s359 >> 16);
+  const SWord8  s888 = table2[s887];
+  const SWord8  s889 = (SWord8) (s359 >> 8);
+  const SWord8  s890 = table3[s889];
+  const SWord8  s891 = (SWord8) s359;
+  const SWord8  s892 = table4[s891];
+  const SWord8  s893 = s890 ^ s892;
+  const SWord8  s894 = s888 ^ s893;
+  const SWord8  s895 = s886 ^ s894;
+  const SWord8  s896 = table4[s885];
+  const SWord8  s897 = table1[s887];
+  const SWord8  s898 = table2[s889];
+  const SWord8  s899 = table3[s891];
+  const SWord8  s900 = s898 ^ s899;
+  const SWord8  s901 = s897 ^ s900;
+  const SWord8  s902 = s896 ^ s901;
+  const SWord16 s903 = (((SWord16) s895) << 8) | ((SWord16) s902);
+  const SWord8  s904 = table3[s885];
+  const SWord8  s905 = table4[s887];
+  const SWord8  s906 = table1[s889];
+  const SWord8  s907 = table2[s891];
+  const SWord8  s908 = s906 ^ s907;
+  const SWord8  s909 = s905 ^ s908;
+  const SWord8  s910 = s904 ^ s909;
+  const SWord8  s911 = table2[s885];
+  const SWord8  s912 = table3[s887];
+  const SWord8  s913 = table4[s889];
+  const SWord8  s914 = table1[s891];
+  const SWord8  s915 = s913 ^ s914;
+  const SWord8  s916 = s912 ^ s915;
+  const SWord8  s917 = s911 ^ s916;
+  const SWord16 s918 = (((SWord16) s910) << 8) | ((SWord16) s917);
+  const SWord32 s919 = (((SWord32) s903) << 16) | ((SWord32) s918);
+  const SWord8  s920 = (SWord8) (s360 >> 24);
+  const SWord8  s921 = table1[s920];
+  const SWord8  s922 = (SWord8) (s360 >> 16);
+  const SWord8  s923 = table2[s922];
+  const SWord8  s924 = (SWord8) (s360 >> 8);
+  const SWord8  s925 = table3[s924];
+  const SWord8  s926 = (SWord8) s360;
+  const SWord8  s927 = table4[s926];
+  const SWord8  s928 = s925 ^ s927;
+  const SWord8  s929 = s923 ^ s928;
+  const SWord8  s930 = s921 ^ s929;
+  const SWord8  s931 = table4[s920];
+  const SWord8  s932 = table1[s922];
+  const SWord8  s933 = table2[s924];
+  const SWord8  s934 = table3[s926];
+  const SWord8  s935 = s933 ^ s934;
+  const SWord8  s936 = s932 ^ s935;
+  const SWord8  s937 = s931 ^ s936;
+  const SWord16 s938 = (((SWord16) s930) << 8) | ((SWord16) s937);
+  const SWord8  s939 = table3[s920];
+  const SWord8  s940 = table4[s922];
+  const SWord8  s941 = table1[s924];
+  const SWord8  s942 = table2[s926];
+  const SWord8  s943 = s941 ^ s942;
+  const SWord8  s944 = s940 ^ s943;
+  const SWord8  s945 = s939 ^ s944;
+  const SWord8  s946 = table2[s920];
+  const SWord8  s947 = table3[s922];
+  const SWord8  s948 = table4[s924];
+  const SWord8  s949 = table1[s926];
+  const SWord8  s950 = s948 ^ s949;
+  const SWord8  s951 = s947 ^ s950;
+  const SWord8  s952 = s946 ^ s951;
+  const SWord16 s953 = (((SWord16) s945) << 8) | ((SWord16) s952);
+  const SWord32 s954 = (((SWord32) s938) << 16) | ((SWord32) s953);
+  const SWord8  s955 = (SWord8) (s361 >> 24);
+  const SWord8  s956 = table1[s955];
+  const SWord8  s957 = (SWord8) (s361 >> 16);
+  const SWord8  s958 = table2[s957];
+  const SWord8  s959 = (SWord8) (s361 >> 8);
+  const SWord8  s960 = table3[s959];
+  const SWord8  s961 = (SWord8) s361;
+  const SWord8  s962 = table4[s961];
+  const SWord8  s963 = s960 ^ s962;
+  const SWord8  s964 = s958 ^ s963;
+  const SWord8  s965 = s956 ^ s964;
+  const SWord8  s966 = table4[s955];
+  const SWord8  s967 = table1[s957];
+  const SWord8  s968 = table2[s959];
+  const SWord8  s969 = table3[s961];
+  const SWord8  s970 = s968 ^ s969;
+  const SWord8  s971 = s967 ^ s970;
+  const SWord8  s972 = s966 ^ s971;
+  const SWord16 s973 = (((SWord16) s965) << 8) | ((SWord16) s972);
+  const SWord8  s974 = table3[s955];
+  const SWord8  s975 = table4[s957];
+  const SWord8  s976 = table1[s959];
+  const SWord8  s977 = table2[s961];
+  const SWord8  s978 = s976 ^ s977;
+  const SWord8  s979 = s975 ^ s978;
+  const SWord8  s980 = s974 ^ s979;
+  const SWord8  s981 = table2[s955];
+  const SWord8  s982 = table3[s957];
+  const SWord8  s983 = table4[s959];
+  const SWord8  s984 = table1[s961];
+  const SWord8  s985 = s983 ^ s984;
+  const SWord8  s986 = s982 ^ s985;
+  const SWord8  s987 = s981 ^ s986;
+  const SWord16 s988 = (((SWord16) s980) << 8) | ((SWord16) s987);
+  const SWord32 s989 = (((SWord32) s973) << 16) | ((SWord32) s988);
+  const SWord8  s990 = (SWord8) (s341 >> 24);
+  const SWord8  s991 = table1[s990];
+  const SWord8  s992 = (SWord8) (s341 >> 16);
+  const SWord8  s993 = table2[s992];
+  const SWord8  s994 = (SWord8) (s341 >> 8);
+  const SWord8  s995 = table3[s994];
+  const SWord8  s996 = (SWord8) s341;
+  const SWord8  s997 = table4[s996];
+  const SWord8  s998 = s995 ^ s997;
+  const SWord8  s999 = s993 ^ s998;
+  const SWord8  s1000 = s991 ^ s999;
+  const SWord8  s1001 = table4[s990];
+  const SWord8  s1002 = table1[s992];
+  const SWord8  s1003 = table2[s994];
+  const SWord8  s1004 = table3[s996];
+  const SWord8  s1005 = s1003 ^ s1004;
+  const SWord8  s1006 = s1002 ^ s1005;
+  const SWord8  s1007 = s1001 ^ s1006;
+  const SWord16 s1008 = (((SWord16) s1000) << 8) | ((SWord16) s1007);
+  const SWord8  s1009 = table3[s990];
+  const SWord8  s1010 = table4[s992];
+  const SWord8  s1011 = table1[s994];
+  const SWord8  s1012 = table2[s996];
+  const SWord8  s1013 = s1011 ^ s1012;
+  const SWord8  s1014 = s1010 ^ s1013;
+  const SWord8  s1015 = s1009 ^ s1014;
+  const SWord8  s1016 = table2[s990];
+  const SWord8  s1017 = table3[s992];
+  const SWord8  s1018 = table4[s994];
+  const SWord8  s1019 = table1[s996];
+  const SWord8  s1020 = s1018 ^ s1019;
+  const SWord8  s1021 = s1017 ^ s1020;
+  const SWord8  s1022 = s1016 ^ s1021;
+  const SWord16 s1023 = (((SWord16) s1015) << 8) | ((SWord16) s1022);
+  const SWord32 s1024 = (((SWord32) s1008) << 16) | ((SWord32) s1023);
+  const SWord8  s1025 = (SWord8) (s342 >> 24);
+  const SWord8  s1026 = table1[s1025];
+  const SWord8  s1027 = (SWord8) (s342 >> 16);
+  const SWord8  s1028 = table2[s1027];
+  const SWord8  s1029 = (SWord8) (s342 >> 8);
+  const SWord8  s1030 = table3[s1029];
+  const SWord8  s1031 = (SWord8) s342;
+  const SWord8  s1032 = table4[s1031];
+  const SWord8  s1033 = s1030 ^ s1032;
+  const SWord8  s1034 = s1028 ^ s1033;
+  const SWord8  s1035 = s1026 ^ s1034;
+  const SWord8  s1036 = table4[s1025];
+  const SWord8  s1037 = table1[s1027];
+  const SWord8  s1038 = table2[s1029];
+  const SWord8  s1039 = table3[s1031];
+  const SWord8  s1040 = s1038 ^ s1039;
+  const SWord8  s1041 = s1037 ^ s1040;
+  const SWord8  s1042 = s1036 ^ s1041;
+  const SWord16 s1043 = (((SWord16) s1035) << 8) | ((SWord16) s1042);
+  const SWord8  s1044 = table3[s1025];
+  const SWord8  s1045 = table4[s1027];
+  const SWord8  s1046 = table1[s1029];
+  const SWord8  s1047 = table2[s1031];
+  const SWord8  s1048 = s1046 ^ s1047;
+  const SWord8  s1049 = s1045 ^ s1048;
+  const SWord8  s1050 = s1044 ^ s1049;
+  const SWord8  s1051 = table2[s1025];
+  const SWord8  s1052 = table3[s1027];
+  const SWord8  s1053 = table4[s1029];
+  const SWord8  s1054 = table1[s1031];
+  const SWord8  s1055 = s1053 ^ s1054;
+  const SWord8  s1056 = s1052 ^ s1055;
+  const SWord8  s1057 = s1051 ^ s1056;
+  const SWord16 s1058 = (((SWord16) s1050) << 8) | ((SWord16) s1057);
+  const SWord32 s1059 = (((SWord32) s1043) << 16) | ((SWord32) s1058);
+  const SWord8  s1060 = (SWord8) (s343 >> 24);
+  const SWord8  s1061 = table1[s1060];
+  const SWord8  s1062 = (SWord8) (s343 >> 16);
+  const SWord8  s1063 = table2[s1062];
+  const SWord8  s1064 = (SWord8) (s343 >> 8);
+  const SWord8  s1065 = table3[s1064];
+  const SWord8  s1066 = (SWord8) s343;
+  const SWord8  s1067 = table4[s1066];
+  const SWord8  s1068 = s1065 ^ s1067;
+  const SWord8  s1069 = s1063 ^ s1068;
+  const SWord8  s1070 = s1061 ^ s1069;
+  const SWord8  s1071 = table4[s1060];
+  const SWord8  s1072 = table1[s1062];
+  const SWord8  s1073 = table2[s1064];
+  const SWord8  s1074 = table3[s1066];
+  const SWord8  s1075 = s1073 ^ s1074;
+  const SWord8  s1076 = s1072 ^ s1075;
+  const SWord8  s1077 = s1071 ^ s1076;
+  const SWord16 s1078 = (((SWord16) s1070) << 8) | ((SWord16) s1077);
+  const SWord8  s1079 = table3[s1060];
+  const SWord8  s1080 = table4[s1062];
+  const SWord8  s1081 = table1[s1064];
+  const SWord8  s1082 = table2[s1066];
+  const SWord8  s1083 = s1081 ^ s1082;
+  const SWord8  s1084 = s1080 ^ s1083;
+  const SWord8  s1085 = s1079 ^ s1084;
+  const SWord8  s1086 = table2[s1060];
+  const SWord8  s1087 = table3[s1062];
+  const SWord8  s1088 = table4[s1064];
+  const SWord8  s1089 = table1[s1066];
+  const SWord8  s1090 = s1088 ^ s1089;
+  const SWord8  s1091 = s1087 ^ s1090;
+  const SWord8  s1092 = s1086 ^ s1091;
+  const SWord16 s1093 = (((SWord16) s1085) << 8) | ((SWord16) s1092);
+  const SWord32 s1094 = (((SWord32) s1078) << 16) | ((SWord32) s1093);
+  const SWord8  s1095 = (SWord8) (s344 >> 24);
+  const SWord8  s1096 = table1[s1095];
+  const SWord8  s1097 = (SWord8) (s344 >> 16);
+  const SWord8  s1098 = table2[s1097];
+  const SWord8  s1099 = (SWord8) (s344 >> 8);
+  const SWord8  s1100 = table3[s1099];
+  const SWord8  s1101 = (SWord8) s344;
+  const SWord8  s1102 = table4[s1101];
+  const SWord8  s1103 = s1100 ^ s1102;
+  const SWord8  s1104 = s1098 ^ s1103;
+  const SWord8  s1105 = s1096 ^ s1104;
+  const SWord8  s1106 = table4[s1095];
+  const SWord8  s1107 = table1[s1097];
+  const SWord8  s1108 = table2[s1099];
+  const SWord8  s1109 = table3[s1101];
+  const SWord8  s1110 = s1108 ^ s1109;
+  const SWord8  s1111 = s1107 ^ s1110;
+  const SWord8  s1112 = s1106 ^ s1111;
+  const SWord16 s1113 = (((SWord16) s1105) << 8) | ((SWord16) s1112);
+  const SWord8  s1114 = table3[s1095];
+  const SWord8  s1115 = table4[s1097];
+  const SWord8  s1116 = table1[s1099];
+  const SWord8  s1117 = table2[s1101];
+  const SWord8  s1118 = s1116 ^ s1117;
+  const SWord8  s1119 = s1115 ^ s1118;
+  const SWord8  s1120 = s1114 ^ s1119;
+  const SWord8  s1121 = table2[s1095];
+  const SWord8  s1122 = table3[s1097];
+  const SWord8  s1123 = table4[s1099];
+  const SWord8  s1124 = table1[s1101];
+  const SWord8  s1125 = s1123 ^ s1124;
+  const SWord8  s1126 = s1122 ^ s1125;
+  const SWord8  s1127 = s1121 ^ s1126;
+  const SWord16 s1128 = (((SWord16) s1120) << 8) | ((SWord16) s1127);
+  const SWord32 s1129 = (((SWord32) s1113) << 16) | ((SWord32) s1128);
+  const SWord8  s1130 = (SWord8) (s324 >> 24);
+  const SWord8  s1131 = table1[s1130];
+  const SWord8  s1132 = (SWord8) (s324 >> 16);
+  const SWord8  s1133 = table2[s1132];
+  const SWord8  s1134 = (SWord8) (s324 >> 8);
+  const SWord8  s1135 = table3[s1134];
+  const SWord8  s1136 = (SWord8) s324;
+  const SWord8  s1137 = table4[s1136];
+  const SWord8  s1138 = s1135 ^ s1137;
+  const SWord8  s1139 = s1133 ^ s1138;
+  const SWord8  s1140 = s1131 ^ s1139;
+  const SWord8  s1141 = table4[s1130];
+  const SWord8  s1142 = table1[s1132];
+  const SWord8  s1143 = table2[s1134];
+  const SWord8  s1144 = table3[s1136];
+  const SWord8  s1145 = s1143 ^ s1144;
+  const SWord8  s1146 = s1142 ^ s1145;
+  const SWord8  s1147 = s1141 ^ s1146;
+  const SWord16 s1148 = (((SWord16) s1140) << 8) | ((SWord16) s1147);
+  const SWord8  s1149 = table3[s1130];
+  const SWord8  s1150 = table4[s1132];
+  const SWord8  s1151 = table1[s1134];
+  const SWord8  s1152 = table2[s1136];
+  const SWord8  s1153 = s1151 ^ s1152;
+  const SWord8  s1154 = s1150 ^ s1153;
+  const SWord8  s1155 = s1149 ^ s1154;
+  const SWord8  s1156 = table2[s1130];
+  const SWord8  s1157 = table3[s1132];
+  const SWord8  s1158 = table4[s1134];
+  const SWord8  s1159 = table1[s1136];
+  const SWord8  s1160 = s1158 ^ s1159;
+  const SWord8  s1161 = s1157 ^ s1160;
+  const SWord8  s1162 = s1156 ^ s1161;
+  const SWord16 s1163 = (((SWord16) s1155) << 8) | ((SWord16) s1162);
+  const SWord32 s1164 = (((SWord32) s1148) << 16) | ((SWord32) s1163);
+  const SWord8  s1165 = (SWord8) (s325 >> 24);
+  const SWord8  s1166 = table1[s1165];
+  const SWord8  s1167 = (SWord8) (s325 >> 16);
+  const SWord8  s1168 = table2[s1167];
+  const SWord8  s1169 = (SWord8) (s325 >> 8);
+  const SWord8  s1170 = table3[s1169];
+  const SWord8  s1171 = (SWord8) s325;
+  const SWord8  s1172 = table4[s1171];
+  const SWord8  s1173 = s1170 ^ s1172;
+  const SWord8  s1174 = s1168 ^ s1173;
+  const SWord8  s1175 = s1166 ^ s1174;
+  const SWord8  s1176 = table4[s1165];
+  const SWord8  s1177 = table1[s1167];
+  const SWord8  s1178 = table2[s1169];
+  const SWord8  s1179 = table3[s1171];
+  const SWord8  s1180 = s1178 ^ s1179;
+  const SWord8  s1181 = s1177 ^ s1180;
+  const SWord8  s1182 = s1176 ^ s1181;
+  const SWord16 s1183 = (((SWord16) s1175) << 8) | ((SWord16) s1182);
+  const SWord8  s1184 = table3[s1165];
+  const SWord8  s1185 = table4[s1167];
+  const SWord8  s1186 = table1[s1169];
+  const SWord8  s1187 = table2[s1171];
+  const SWord8  s1188 = s1186 ^ s1187;
+  const SWord8  s1189 = s1185 ^ s1188;
+  const SWord8  s1190 = s1184 ^ s1189;
+  const SWord8  s1191 = table2[s1165];
+  const SWord8  s1192 = table3[s1167];
+  const SWord8  s1193 = table4[s1169];
+  const SWord8  s1194 = table1[s1171];
+  const SWord8  s1195 = s1193 ^ s1194;
+  const SWord8  s1196 = s1192 ^ s1195;
+  const SWord8  s1197 = s1191 ^ s1196;
+  const SWord16 s1198 = (((SWord16) s1190) << 8) | ((SWord16) s1197);
+  const SWord32 s1199 = (((SWord32) s1183) << 16) | ((SWord32) s1198);
+  const SWord8  s1200 = (SWord8) (s326 >> 24);
+  const SWord8  s1201 = table1[s1200];
+  const SWord8  s1202 = (SWord8) (s326 >> 16);
+  const SWord8  s1203 = table2[s1202];
+  const SWord8  s1204 = (SWord8) (s326 >> 8);
+  const SWord8  s1205 = table3[s1204];
+  const SWord8  s1206 = (SWord8) s326;
+  const SWord8  s1207 = table4[s1206];
+  const SWord8  s1208 = s1205 ^ s1207;
+  const SWord8  s1209 = s1203 ^ s1208;
+  const SWord8  s1210 = s1201 ^ s1209;
+  const SWord8  s1211 = table4[s1200];
+  const SWord8  s1212 = table1[s1202];
+  const SWord8  s1213 = table2[s1204];
+  const SWord8  s1214 = table3[s1206];
+  const SWord8  s1215 = s1213 ^ s1214;
+  const SWord8  s1216 = s1212 ^ s1215;
+  const SWord8  s1217 = s1211 ^ s1216;
+  const SWord16 s1218 = (((SWord16) s1210) << 8) | ((SWord16) s1217);
+  const SWord8  s1219 = table3[s1200];
+  const SWord8  s1220 = table4[s1202];
+  const SWord8  s1221 = table1[s1204];
+  const SWord8  s1222 = table2[s1206];
+  const SWord8  s1223 = s1221 ^ s1222;
+  const SWord8  s1224 = s1220 ^ s1223;
+  const SWord8  s1225 = s1219 ^ s1224;
+  const SWord8  s1226 = table2[s1200];
+  const SWord8  s1227 = table3[s1202];
+  const SWord8  s1228 = table4[s1204];
+  const SWord8  s1229 = table1[s1206];
+  const SWord8  s1230 = s1228 ^ s1229;
+  const SWord8  s1231 = s1227 ^ s1230;
+  const SWord8  s1232 = s1226 ^ s1231;
+  const SWord16 s1233 = (((SWord16) s1225) << 8) | ((SWord16) s1232);
+  const SWord32 s1234 = (((SWord32) s1218) << 16) | ((SWord32) s1233);
+  const SWord8  s1235 = (SWord8) (s327 >> 24);
+  const SWord8  s1236 = table1[s1235];
+  const SWord8  s1237 = (SWord8) (s327 >> 16);
+  const SWord8  s1238 = table2[s1237];
+  const SWord8  s1239 = (SWord8) (s327 >> 8);
+  const SWord8  s1240 = table3[s1239];
+  const SWord8  s1241 = (SWord8) s327;
+  const SWord8  s1242 = table4[s1241];
+  const SWord8  s1243 = s1240 ^ s1242;
+  const SWord8  s1244 = s1238 ^ s1243;
+  const SWord8  s1245 = s1236 ^ s1244;
+  const SWord8  s1246 = table4[s1235];
+  const SWord8  s1247 = table1[s1237];
+  const SWord8  s1248 = table2[s1239];
+  const SWord8  s1249 = table3[s1241];
+  const SWord8  s1250 = s1248 ^ s1249;
+  const SWord8  s1251 = s1247 ^ s1250;
+  const SWord8  s1252 = s1246 ^ s1251;
+  const SWord16 s1253 = (((SWord16) s1245) << 8) | ((SWord16) s1252);
+  const SWord8  s1254 = table3[s1235];
+  const SWord8  s1255 = table4[s1237];
+  const SWord8  s1256 = table1[s1239];
+  const SWord8  s1257 = table2[s1241];
+  const SWord8  s1258 = s1256 ^ s1257;
+  const SWord8  s1259 = s1255 ^ s1258;
+  const SWord8  s1260 = s1254 ^ s1259;
+  const SWord8  s1261 = table2[s1235];
+  const SWord8  s1262 = table3[s1237];
+  const SWord8  s1263 = table4[s1239];
+  const SWord8  s1264 = table1[s1241];
+  const SWord8  s1265 = s1263 ^ s1264;
+  const SWord8  s1266 = s1262 ^ s1265;
+  const SWord8  s1267 = s1261 ^ s1266;
+  const SWord16 s1268 = (((SWord16) s1260) << 8) | ((SWord16) s1267);
+  const SWord32 s1269 = (((SWord32) s1253) << 16) | ((SWord32) s1268);
+  const SWord8  s1270 = (SWord8) (s307 >> 24);
+  const SWord8  s1271 = table1[s1270];
+  const SWord8  s1272 = (SWord8) (s307 >> 16);
+  const SWord8  s1273 = table2[s1272];
+  const SWord8  s1274 = (SWord8) (s307 >> 8);
+  const SWord8  s1275 = table3[s1274];
+  const SWord8  s1276 = (SWord8) s307;
+  const SWord8  s1277 = table4[s1276];
+  const SWord8  s1278 = s1275 ^ s1277;
+  const SWord8  s1279 = s1273 ^ s1278;
+  const SWord8  s1280 = s1271 ^ s1279;
+  const SWord8  s1281 = table4[s1270];
+  const SWord8  s1282 = table1[s1272];
+  const SWord8  s1283 = table2[s1274];
+  const SWord8  s1284 = table3[s1276];
+  const SWord8  s1285 = s1283 ^ s1284;
+  const SWord8  s1286 = s1282 ^ s1285;
+  const SWord8  s1287 = s1281 ^ s1286;
+  const SWord16 s1288 = (((SWord16) s1280) << 8) | ((SWord16) s1287);
+  const SWord8  s1289 = table3[s1270];
+  const SWord8  s1290 = table4[s1272];
+  const SWord8  s1291 = table1[s1274];
+  const SWord8  s1292 = table2[s1276];
+  const SWord8  s1293 = s1291 ^ s1292;
+  const SWord8  s1294 = s1290 ^ s1293;
+  const SWord8  s1295 = s1289 ^ s1294;
+  const SWord8  s1296 = table2[s1270];
+  const SWord8  s1297 = table3[s1272];
+  const SWord8  s1298 = table4[s1274];
+  const SWord8  s1299 = table1[s1276];
+  const SWord8  s1300 = s1298 ^ s1299;
+  const SWord8  s1301 = s1297 ^ s1300;
+  const SWord8  s1302 = s1296 ^ s1301;
+  const SWord16 s1303 = (((SWord16) s1295) << 8) | ((SWord16) s1302);
+  const SWord32 s1304 = (((SWord32) s1288) << 16) | ((SWord32) s1303);
+  const SWord8  s1305 = (SWord8) (s308 >> 24);
+  const SWord8  s1306 = table1[s1305];
+  const SWord8  s1307 = (SWord8) (s308 >> 16);
+  const SWord8  s1308 = table2[s1307];
+  const SWord8  s1309 = (SWord8) (s308 >> 8);
+  const SWord8  s1310 = table3[s1309];
+  const SWord8  s1311 = (SWord8) s308;
+  const SWord8  s1312 = table4[s1311];
+  const SWord8  s1313 = s1310 ^ s1312;
+  const SWord8  s1314 = s1308 ^ s1313;
+  const SWord8  s1315 = s1306 ^ s1314;
+  const SWord8  s1316 = table4[s1305];
+  const SWord8  s1317 = table1[s1307];
+  const SWord8  s1318 = table2[s1309];
+  const SWord8  s1319 = table3[s1311];
+  const SWord8  s1320 = s1318 ^ s1319;
+  const SWord8  s1321 = s1317 ^ s1320;
+  const SWord8  s1322 = s1316 ^ s1321;
+  const SWord16 s1323 = (((SWord16) s1315) << 8) | ((SWord16) s1322);
+  const SWord8  s1324 = table3[s1305];
+  const SWord8  s1325 = table4[s1307];
+  const SWord8  s1326 = table1[s1309];
+  const SWord8  s1327 = table2[s1311];
+  const SWord8  s1328 = s1326 ^ s1327;
+  const SWord8  s1329 = s1325 ^ s1328;
+  const SWord8  s1330 = s1324 ^ s1329;
+  const SWord8  s1331 = table2[s1305];
+  const SWord8  s1332 = table3[s1307];
+  const SWord8  s1333 = table4[s1309];
+  const SWord8  s1334 = table1[s1311];
+  const SWord8  s1335 = s1333 ^ s1334;
+  const SWord8  s1336 = s1332 ^ s1335;
+  const SWord8  s1337 = s1331 ^ s1336;
+  const SWord16 s1338 = (((SWord16) s1330) << 8) | ((SWord16) s1337);
+  const SWord32 s1339 = (((SWord32) s1323) << 16) | ((SWord32) s1338);
+  const SWord8  s1340 = (SWord8) (s309 >> 24);
+  const SWord8  s1341 = table1[s1340];
+  const SWord8  s1342 = (SWord8) (s309 >> 16);
+  const SWord8  s1343 = table2[s1342];
+  const SWord8  s1344 = (SWord8) (s309 >> 8);
+  const SWord8  s1345 = table3[s1344];
+  const SWord8  s1346 = (SWord8) s309;
+  const SWord8  s1347 = table4[s1346];
+  const SWord8  s1348 = s1345 ^ s1347;
+  const SWord8  s1349 = s1343 ^ s1348;
+  const SWord8  s1350 = s1341 ^ s1349;
+  const SWord8  s1351 = table4[s1340];
+  const SWord8  s1352 = table1[s1342];
+  const SWord8  s1353 = table2[s1344];
+  const SWord8  s1354 = table3[s1346];
+  const SWord8  s1355 = s1353 ^ s1354;
+  const SWord8  s1356 = s1352 ^ s1355;
+  const SWord8  s1357 = s1351 ^ s1356;
+  const SWord16 s1358 = (((SWord16) s1350) << 8) | ((SWord16) s1357);
+  const SWord8  s1359 = table3[s1340];
+  const SWord8  s1360 = table4[s1342];
+  const SWord8  s1361 = table1[s1344];
+  const SWord8  s1362 = table2[s1346];
+  const SWord8  s1363 = s1361 ^ s1362;
+  const SWord8  s1364 = s1360 ^ s1363;
+  const SWord8  s1365 = s1359 ^ s1364;
+  const SWord8  s1366 = table2[s1340];
+  const SWord8  s1367 = table3[s1342];
+  const SWord8  s1368 = table4[s1344];
+  const SWord8  s1369 = table1[s1346];
+  const SWord8  s1370 = s1368 ^ s1369;
+  const SWord8  s1371 = s1367 ^ s1370;
+  const SWord8  s1372 = s1366 ^ s1371;
+  const SWord16 s1373 = (((SWord16) s1365) << 8) | ((SWord16) s1372);
+  const SWord32 s1374 = (((SWord32) s1358) << 16) | ((SWord32) s1373);
+  const SWord8  s1375 = (SWord8) (s310 >> 24);
+  const SWord8  s1376 = table1[s1375];
+  const SWord8  s1377 = (SWord8) (s310 >> 16);
+  const SWord8  s1378 = table2[s1377];
+  const SWord8  s1379 = (SWord8) (s310 >> 8);
+  const SWord8  s1380 = table3[s1379];
+  const SWord8  s1381 = (SWord8) s310;
+  const SWord8  s1382 = table4[s1381];
+  const SWord8  s1383 = s1380 ^ s1382;
+  const SWord8  s1384 = s1378 ^ s1383;
+  const SWord8  s1385 = s1376 ^ s1384;
+  const SWord8  s1386 = table4[s1375];
+  const SWord8  s1387 = table1[s1377];
+  const SWord8  s1388 = table2[s1379];
+  const SWord8  s1389 = table3[s1381];
+  const SWord8  s1390 = s1388 ^ s1389;
+  const SWord8  s1391 = s1387 ^ s1390;
+  const SWord8  s1392 = s1386 ^ s1391;
+  const SWord16 s1393 = (((SWord16) s1385) << 8) | ((SWord16) s1392);
+  const SWord8  s1394 = table3[s1375];
+  const SWord8  s1395 = table4[s1377];
+  const SWord8  s1396 = table1[s1379];
+  const SWord8  s1397 = table2[s1381];
+  const SWord8  s1398 = s1396 ^ s1397;
+  const SWord8  s1399 = s1395 ^ s1398;
+  const SWord8  s1400 = s1394 ^ s1399;
+  const SWord8  s1401 = table2[s1375];
+  const SWord8  s1402 = table3[s1377];
+  const SWord8  s1403 = table4[s1379];
+  const SWord8  s1404 = table1[s1381];
+  const SWord8  s1405 = s1403 ^ s1404;
+  const SWord8  s1406 = s1402 ^ s1405;
+  const SWord8  s1407 = s1401 ^ s1406;
+  const SWord16 s1408 = (((SWord16) s1400) << 8) | ((SWord16) s1407);
+  const SWord32 s1409 = (((SWord32) s1393) << 16) | ((SWord32) s1408);
+  const SWord8  s1410 = (SWord8) (s290 >> 24);
+  const SWord8  s1411 = table1[s1410];
+  const SWord8  s1412 = (SWord8) (s290 >> 16);
+  const SWord8  s1413 = table2[s1412];
+  const SWord8  s1414 = (SWord8) (s290 >> 8);
+  const SWord8  s1415 = table3[s1414];
+  const SWord8  s1416 = (SWord8) s290;
+  const SWord8  s1417 = table4[s1416];
+  const SWord8  s1418 = s1415 ^ s1417;
+  const SWord8  s1419 = s1413 ^ s1418;
+  const SWord8  s1420 = s1411 ^ s1419;
+  const SWord8  s1421 = table4[s1410];
+  const SWord8  s1422 = table1[s1412];
+  const SWord8  s1423 = table2[s1414];
+  const SWord8  s1424 = table3[s1416];
+  const SWord8  s1425 = s1423 ^ s1424;
+  const SWord8  s1426 = s1422 ^ s1425;
+  const SWord8  s1427 = s1421 ^ s1426;
+  const SWord16 s1428 = (((SWord16) s1420) << 8) | ((SWord16) s1427);
+  const SWord8  s1429 = table3[s1410];
+  const SWord8  s1430 = table4[s1412];
+  const SWord8  s1431 = table1[s1414];
+  const SWord8  s1432 = table2[s1416];
+  const SWord8  s1433 = s1431 ^ s1432;
+  const SWord8  s1434 = s1430 ^ s1433;
+  const SWord8  s1435 = s1429 ^ s1434;
+  const SWord8  s1436 = table2[s1410];
+  const SWord8  s1437 = table3[s1412];
+  const SWord8  s1438 = table4[s1414];
+  const SWord8  s1439 = table1[s1416];
+  const SWord8  s1440 = s1438 ^ s1439;
+  const SWord8  s1441 = s1437 ^ s1440;
+  const SWord8  s1442 = s1436 ^ s1441;
+  const SWord16 s1443 = (((SWord16) s1435) << 8) | ((SWord16) s1442);
+  const SWord32 s1444 = (((SWord32) s1428) << 16) | ((SWord32) s1443);
+  const SWord8  s1445 = (SWord8) (s291 >> 24);
+  const SWord8  s1446 = table1[s1445];
+  const SWord8  s1447 = (SWord8) (s291 >> 16);
+  const SWord8  s1448 = table2[s1447];
+  const SWord8  s1449 = (SWord8) (s291 >> 8);
+  const SWord8  s1450 = table3[s1449];
+  const SWord8  s1451 = (SWord8) s291;
+  const SWord8  s1452 = table4[s1451];
+  const SWord8  s1453 = s1450 ^ s1452;
+  const SWord8  s1454 = s1448 ^ s1453;
+  const SWord8  s1455 = s1446 ^ s1454;
+  const SWord8  s1456 = table4[s1445];
+  const SWord8  s1457 = table1[s1447];
+  const SWord8  s1458 = table2[s1449];
+  const SWord8  s1459 = table3[s1451];
+  const SWord8  s1460 = s1458 ^ s1459;
+  const SWord8  s1461 = s1457 ^ s1460;
+  const SWord8  s1462 = s1456 ^ s1461;
+  const SWord16 s1463 = (((SWord16) s1455) << 8) | ((SWord16) s1462);
+  const SWord8  s1464 = table3[s1445];
+  const SWord8  s1465 = table4[s1447];
+  const SWord8  s1466 = table1[s1449];
+  const SWord8  s1467 = table2[s1451];
+  const SWord8  s1468 = s1466 ^ s1467;
+  const SWord8  s1469 = s1465 ^ s1468;
+  const SWord8  s1470 = s1464 ^ s1469;
+  const SWord8  s1471 = table2[s1445];
+  const SWord8  s1472 = table3[s1447];
+  const SWord8  s1473 = table4[s1449];
+  const SWord8  s1474 = table1[s1451];
+  const SWord8  s1475 = s1473 ^ s1474;
+  const SWord8  s1476 = s1472 ^ s1475;
+  const SWord8  s1477 = s1471 ^ s1476;
+  const SWord16 s1478 = (((SWord16) s1470) << 8) | ((SWord16) s1477);
+  const SWord32 s1479 = (((SWord32) s1463) << 16) | ((SWord32) s1478);
+  const SWord8  s1480 = (SWord8) (s292 >> 24);
+  const SWord8  s1481 = table1[s1480];
+  const SWord8  s1482 = (SWord8) (s292 >> 16);
+  const SWord8  s1483 = table2[s1482];
+  const SWord8  s1484 = (SWord8) (s292 >> 8);
+  const SWord8  s1485 = table3[s1484];
+  const SWord8  s1486 = (SWord8) s292;
+  const SWord8  s1487 = table4[s1486];
+  const SWord8  s1488 = s1485 ^ s1487;
+  const SWord8  s1489 = s1483 ^ s1488;
+  const SWord8  s1490 = s1481 ^ s1489;
+  const SWord8  s1491 = table4[s1480];
+  const SWord8  s1492 = table1[s1482];
+  const SWord8  s1493 = table2[s1484];
+  const SWord8  s1494 = table3[s1486];
+  const SWord8  s1495 = s1493 ^ s1494;
+  const SWord8  s1496 = s1492 ^ s1495;
+  const SWord8  s1497 = s1491 ^ s1496;
+  const SWord16 s1498 = (((SWord16) s1490) << 8) | ((SWord16) s1497);
+  const SWord8  s1499 = table3[s1480];
+  const SWord8  s1500 = table4[s1482];
+  const SWord8  s1501 = table1[s1484];
+  const SWord8  s1502 = table2[s1486];
+  const SWord8  s1503 = s1501 ^ s1502;
+  const SWord8  s1504 = s1500 ^ s1503;
+  const SWord8  s1505 = s1499 ^ s1504;
+  const SWord8  s1506 = table2[s1480];
+  const SWord8  s1507 = table3[s1482];
+  const SWord8  s1508 = table4[s1484];
+  const SWord8  s1509 = table1[s1486];
+  const SWord8  s1510 = s1508 ^ s1509;
+  const SWord8  s1511 = s1507 ^ s1510;
+  const SWord8  s1512 = s1506 ^ s1511;
+  const SWord16 s1513 = (((SWord16) s1505) << 8) | ((SWord16) s1512);
+  const SWord32 s1514 = (((SWord32) s1498) << 16) | ((SWord32) s1513);
+  const SWord8  s1515 = (SWord8) (s293 >> 24);
+  const SWord8  s1516 = table1[s1515];
+  const SWord8  s1517 = (SWord8) (s293 >> 16);
+  const SWord8  s1518 = table2[s1517];
+  const SWord8  s1519 = (SWord8) (s293 >> 8);
+  const SWord8  s1520 = table3[s1519];
+  const SWord8  s1521 = (SWord8) s293;
+  const SWord8  s1522 = table4[s1521];
+  const SWord8  s1523 = s1520 ^ s1522;
+  const SWord8  s1524 = s1518 ^ s1523;
+  const SWord8  s1525 = s1516 ^ s1524;
+  const SWord8  s1526 = table4[s1515];
+  const SWord8  s1527 = table1[s1517];
+  const SWord8  s1528 = table2[s1519];
+  const SWord8  s1529 = table3[s1521];
+  const SWord8  s1530 = s1528 ^ s1529;
+  const SWord8  s1531 = s1527 ^ s1530;
+  const SWord8  s1532 = s1526 ^ s1531;
+  const SWord16 s1533 = (((SWord16) s1525) << 8) | ((SWord16) s1532);
+  const SWord8  s1534 = table3[s1515];
+  const SWord8  s1535 = table4[s1517];
+  const SWord8  s1536 = table1[s1519];
+  const SWord8  s1537 = table2[s1521];
+  const SWord8  s1538 = s1536 ^ s1537;
+  const SWord8  s1539 = s1535 ^ s1538;
+  const SWord8  s1540 = s1534 ^ s1539;
+  const SWord8  s1541 = table2[s1515];
+  const SWord8  s1542 = table3[s1517];
+  const SWord8  s1543 = table4[s1519];
+  const SWord8  s1544 = table1[s1521];
+  const SWord8  s1545 = s1543 ^ s1544;
+  const SWord8  s1546 = s1542 ^ s1545;
+  const SWord8  s1547 = s1541 ^ s1546;
+  const SWord16 s1548 = (((SWord16) s1540) << 8) | ((SWord16) s1547);
+  const SWord32 s1549 = (((SWord32) s1533) << 16) | ((SWord32) s1548);
+  const SWord8  s1550 = (SWord8) (s273 >> 24);
+  const SWord8  s1551 = table1[s1550];
+  const SWord8  s1552 = (SWord8) (s273 >> 16);
+  const SWord8  s1553 = table2[s1552];
+  const SWord8  s1554 = (SWord8) (s273 >> 8);
+  const SWord8  s1555 = table3[s1554];
+  const SWord8  s1556 = (SWord8) s273;
+  const SWord8  s1557 = table4[s1556];
+  const SWord8  s1558 = s1555 ^ s1557;
+  const SWord8  s1559 = s1553 ^ s1558;
+  const SWord8  s1560 = s1551 ^ s1559;
+  const SWord8  s1561 = table4[s1550];
+  const SWord8  s1562 = table1[s1552];
+  const SWord8  s1563 = table2[s1554];
+  const SWord8  s1564 = table3[s1556];
+  const SWord8  s1565 = s1563 ^ s1564;
+  const SWord8  s1566 = s1562 ^ s1565;
+  const SWord8  s1567 = s1561 ^ s1566;
+  const SWord16 s1568 = (((SWord16) s1560) << 8) | ((SWord16) s1567);
+  const SWord8  s1569 = table3[s1550];
+  const SWord8  s1570 = table4[s1552];
+  const SWord8  s1571 = table1[s1554];
+  const SWord8  s1572 = table2[s1556];
+  const SWord8  s1573 = s1571 ^ s1572;
+  const SWord8  s1574 = s1570 ^ s1573;
+  const SWord8  s1575 = s1569 ^ s1574;
+  const SWord8  s1576 = table2[s1550];
+  const SWord8  s1577 = table3[s1552];
+  const SWord8  s1578 = table4[s1554];
+  const SWord8  s1579 = table1[s1556];
+  const SWord8  s1580 = s1578 ^ s1579;
+  const SWord8  s1581 = s1577 ^ s1580;
+  const SWord8  s1582 = s1576 ^ s1581;
+  const SWord16 s1583 = (((SWord16) s1575) << 8) | ((SWord16) s1582);
+  const SWord32 s1584 = (((SWord32) s1568) << 16) | ((SWord32) s1583);
+  const SWord8  s1585 = (SWord8) (s274 >> 24);
+  const SWord8  s1586 = table1[s1585];
+  const SWord8  s1587 = (SWord8) (s274 >> 16);
+  const SWord8  s1588 = table2[s1587];
+  const SWord8  s1589 = (SWord8) (s274 >> 8);
+  const SWord8  s1590 = table3[s1589];
+  const SWord8  s1591 = (SWord8) s274;
+  const SWord8  s1592 = table4[s1591];
+  const SWord8  s1593 = s1590 ^ s1592;
+  const SWord8  s1594 = s1588 ^ s1593;
+  const SWord8  s1595 = s1586 ^ s1594;
+  const SWord8  s1596 = table4[s1585];
+  const SWord8  s1597 = table1[s1587];
+  const SWord8  s1598 = table2[s1589];
+  const SWord8  s1599 = table3[s1591];
+  const SWord8  s1600 = s1598 ^ s1599;
+  const SWord8  s1601 = s1597 ^ s1600;
+  const SWord8  s1602 = s1596 ^ s1601;
+  const SWord16 s1603 = (((SWord16) s1595) << 8) | ((SWord16) s1602);
+  const SWord8  s1604 = table3[s1585];
+  const SWord8  s1605 = table4[s1587];
+  const SWord8  s1606 = table1[s1589];
+  const SWord8  s1607 = table2[s1591];
+  const SWord8  s1608 = s1606 ^ s1607;
+  const SWord8  s1609 = s1605 ^ s1608;
+  const SWord8  s1610 = s1604 ^ s1609;
+  const SWord8  s1611 = table2[s1585];
+  const SWord8  s1612 = table3[s1587];
+  const SWord8  s1613 = table4[s1589];
+  const SWord8  s1614 = table1[s1591];
+  const SWord8  s1615 = s1613 ^ s1614;
+  const SWord8  s1616 = s1612 ^ s1615;
+  const SWord8  s1617 = s1611 ^ s1616;
+  const SWord16 s1618 = (((SWord16) s1610) << 8) | ((SWord16) s1617);
+  const SWord32 s1619 = (((SWord32) s1603) << 16) | ((SWord32) s1618);
+  const SWord8  s1620 = (SWord8) (s275 >> 24);
+  const SWord8  s1621 = table1[s1620];
+  const SWord8  s1622 = (SWord8) (s275 >> 16);
+  const SWord8  s1623 = table2[s1622];
+  const SWord8  s1624 = (SWord8) (s275 >> 8);
+  const SWord8  s1625 = table3[s1624];
+  const SWord8  s1626 = (SWord8) s275;
+  const SWord8  s1627 = table4[s1626];
+  const SWord8  s1628 = s1625 ^ s1627;
+  const SWord8  s1629 = s1623 ^ s1628;
+  const SWord8  s1630 = s1621 ^ s1629;
+  const SWord8  s1631 = table4[s1620];
+  const SWord8  s1632 = table1[s1622];
+  const SWord8  s1633 = table2[s1624];
+  const SWord8  s1634 = table3[s1626];
+  const SWord8  s1635 = s1633 ^ s1634;
+  const SWord8  s1636 = s1632 ^ s1635;
+  const SWord8  s1637 = s1631 ^ s1636;
+  const SWord16 s1638 = (((SWord16) s1630) << 8) | ((SWord16) s1637);
+  const SWord8  s1639 = table3[s1620];
+  const SWord8  s1640 = table4[s1622];
+  const SWord8  s1641 = table1[s1624];
+  const SWord8  s1642 = table2[s1626];
+  const SWord8  s1643 = s1641 ^ s1642;
+  const SWord8  s1644 = s1640 ^ s1643;
+  const SWord8  s1645 = s1639 ^ s1644;
+  const SWord8  s1646 = table2[s1620];
+  const SWord8  s1647 = table3[s1622];
+  const SWord8  s1648 = table4[s1624];
+  const SWord8  s1649 = table1[s1626];
+  const SWord8  s1650 = s1648 ^ s1649;
+  const SWord8  s1651 = s1647 ^ s1650;
+  const SWord8  s1652 = s1646 ^ s1651;
+  const SWord16 s1653 = (((SWord16) s1645) << 8) | ((SWord16) s1652);
+  const SWord32 s1654 = (((SWord32) s1638) << 16) | ((SWord32) s1653);
+  const SWord8  s1655 = (SWord8) (s276 >> 24);
+  const SWord8  s1656 = table1[s1655];
+  const SWord8  s1657 = (SWord8) (s276 >> 16);
+  const SWord8  s1658 = table2[s1657];
+  const SWord8  s1659 = (SWord8) (s276 >> 8);
+  const SWord8  s1660 = table3[s1659];
+  const SWord8  s1661 = (SWord8) s276;
+  const SWord8  s1662 = table4[s1661];
+  const SWord8  s1663 = s1660 ^ s1662;
+  const SWord8  s1664 = s1658 ^ s1663;
+  const SWord8  s1665 = s1656 ^ s1664;
+  const SWord8  s1666 = table4[s1655];
+  const SWord8  s1667 = table1[s1657];
+  const SWord8  s1668 = table2[s1659];
+  const SWord8  s1669 = table3[s1661];
+  const SWord8  s1670 = s1668 ^ s1669;
+  const SWord8  s1671 = s1667 ^ s1670;
+  const SWord8  s1672 = s1666 ^ s1671;
+  const SWord16 s1673 = (((SWord16) s1665) << 8) | ((SWord16) s1672);
+  const SWord8  s1674 = table3[s1655];
+  const SWord8  s1675 = table4[s1657];
+  const SWord8  s1676 = table1[s1659];
+  const SWord8  s1677 = table2[s1661];
+  const SWord8  s1678 = s1676 ^ s1677;
+  const SWord8  s1679 = s1675 ^ s1678;
+  const SWord8  s1680 = s1674 ^ s1679;
+  const SWord8  s1681 = table2[s1655];
+  const SWord8  s1682 = table3[s1657];
+  const SWord8  s1683 = table4[s1659];
+  const SWord8  s1684 = table1[s1661];
+  const SWord8  s1685 = s1683 ^ s1684;
+  const SWord8  s1686 = s1682 ^ s1685;
+  const SWord8  s1687 = s1681 ^ s1686;
+  const SWord16 s1688 = (((SWord16) s1680) << 8) | ((SWord16) s1687);
+  const SWord32 s1689 = (((SWord32) s1673) << 16) | ((SWord32) s1688);
+
+  encKS[0] = s0;
+  encKS[1] = s1;
+  encKS[2] = s2;
+  encKS[3] = s3;
+  encKS[4] = s273;
+  encKS[5] = s274;
+  encKS[6] = s275;
+  encKS[7] = s276;
+  encKS[8] = s290;
+  encKS[9] = s291;
+  encKS[10] = s292;
+  encKS[11] = s293;
+  encKS[12] = s307;
+  encKS[13] = s308;
+  encKS[14] = s309;
+  encKS[15] = s310;
+  encKS[16] = s324;
+  encKS[17] = s325;
+  encKS[18] = s326;
+  encKS[19] = s327;
+  encKS[20] = s341;
+  encKS[21] = s342;
+  encKS[22] = s343;
+  encKS[23] = s344;
+  encKS[24] = s358;
+  encKS[25] = s359;
+  encKS[26] = s360;
+  encKS[27] = s361;
+  encKS[28] = s375;
+  encKS[29] = s376;
+  encKS[30] = s377;
+  encKS[31] = s378;
+  encKS[32] = s392;
+  encKS[33] = s393;
+  encKS[34] = s394;
+  encKS[35] = s395;
+  encKS[36] = s409;
+  encKS[37] = s410;
+  encKS[38] = s411;
+  encKS[39] = s412;
+  encKS[40] = s426;
+  encKS[41] = s427;
+  encKS[42] = s428;
+  encKS[43] = s429;
+  decKS[0] = s426;
+  decKS[1] = s427;
+  decKS[2] = s428;
+  decKS[3] = s429;
+  decKS[4] = s464;
+  decKS[5] = s499;
+  decKS[6] = s534;
+  decKS[7] = s569;
+  decKS[8] = s604;
+  decKS[9] = s639;
+  decKS[10] = s674;
+  decKS[11] = s709;
+  decKS[12] = s744;
+  decKS[13] = s779;
+  decKS[14] = s814;
+  decKS[15] = s849;
+  decKS[16] = s884;
+  decKS[17] = s919;
+  decKS[18] = s954;
+  decKS[19] = s989;
+  decKS[20] = s1024;
+  decKS[21] = s1059;
+  decKS[22] = s1094;
+  decKS[23] = s1129;
+  decKS[24] = s1164;
+  decKS[25] = s1199;
+  decKS[26] = s1234;
+  decKS[27] = s1269;
+  decKS[28] = s1304;
+  decKS[29] = s1339;
+  decKS[30] = s1374;
+  decKS[31] = s1409;
+  decKS[32] = s1444;
+  decKS[33] = s1479;
+  decKS[34] = s1514;
+  decKS[35] = s1549;
+  decKS[36] = s1584;
+  decKS[37] = s1619;
+  decKS[38] = s1654;
+  decKS[39] = s1689;
+  decKS[40] = s0;
+  decKS[41] = s1;
+  decKS[42] = s2;
+  decKS[43] = s3;
+}
+== END: "aes128KeySchedule.c" ==================
+== BEGIN: "aes128BlockEncrypt.c" ================
+/* File: "aes128BlockEncrypt.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Lib.h"
+
+void aes128BlockEncrypt(const SWord32 *pt, const SWord32 *xkey,
+                        SWord32 *ct)
+{
+  const SWord32 s0 = pt[0];
+  const SWord32 s1 = pt[1];
+  const SWord32 s2 = pt[2];
+  const SWord32 s3 = pt[3];
+  const SWord32 s4 = xkey[0];
+  const SWord32 s5 = xkey[1];
+  const SWord32 s6 = xkey[2];
+  const SWord32 s7 = xkey[3];
+  const SWord32 s8 = xkey[4];
+  const SWord32 s9 = xkey[5];
+  const SWord32 s10 = xkey[6];
+  const SWord32 s11 = xkey[7];
+  const SWord32 s12 = xkey[8];
+  const SWord32 s13 = xkey[9];
+  const SWord32 s14 = xkey[10];
+  const SWord32 s15 = xkey[11];
+  const SWord32 s16 = xkey[12];
+  const SWord32 s17 = xkey[13];
+  const SWord32 s18 = xkey[14];
+  const SWord32 s19 = xkey[15];
+  const SWord32 s20 = xkey[16];
+  const SWord32 s21 = xkey[17];
+  const SWord32 s22 = xkey[18];
+  const SWord32 s23 = xkey[19];
+  const SWord32 s24 = xkey[20];
+  const SWord32 s25 = xkey[21];
+  const SWord32 s26 = xkey[22];
+  const SWord32 s27 = xkey[23];
+  const SWord32 s28 = xkey[24];
+  const SWord32 s29 = xkey[25];
+  const SWord32 s30 = xkey[26];
+  const SWord32 s31 = xkey[27];
+  const SWord32 s32 = xkey[28];
+  const SWord32 s33 = xkey[29];
+  const SWord32 s34 = xkey[30];
+  const SWord32 s35 = xkey[31];
+  const SWord32 s36 = xkey[32];
+  const SWord32 s37 = xkey[33];
+  const SWord32 s38 = xkey[34];
+  const SWord32 s39 = xkey[35];
+  const SWord32 s40 = xkey[36];
+  const SWord32 s41 = xkey[37];
+  const SWord32 s42 = xkey[38];
+  const SWord32 s43 = xkey[39];
+  const SWord32 s44 = xkey[40];
+  const SWord32 s45 = xkey[41];
+  const SWord32 s46 = xkey[42];
+  const SWord32 s47 = xkey[43];
+  static const SWord8 table0[] = {
+       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
+      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
+      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
+      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
+       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
+      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
+       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
+       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
+       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
+      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
+       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
+      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
+      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
+      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
+       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
+       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
+      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
+      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
+      104,  65, 153,  45,  15, 176,  84, 187,  22
+  };
+  static const SWord32 table1[] = {
+      0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+      0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+      0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+      0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+      0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+      0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+      0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+      0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+      0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+      0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+      0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+      0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+      0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+      0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+      0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+      0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+      0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+      0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+      0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+      0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+      0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+      0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+      0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+      0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+      0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+      0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+      0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+      0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+      0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+      0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+      0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+      0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+      0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+      0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+      0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+      0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+      0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+      0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+      0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+      0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+      0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+      0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+      0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+      0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+      0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+      0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+      0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+      0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+      0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+      0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+      0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+      0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+      0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+      0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+      0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+      0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+      0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+      0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+      0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+      0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+      0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+      0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+      0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+      0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL
+  };
+  static const SWord32 table2[] = {
+      0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
+      0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
+      0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
+      0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
+      0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
+      0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
+      0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
+      0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
+      0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
+      0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
+      0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
+      0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
+      0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
+      0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
+      0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
+      0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
+      0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
+      0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
+      0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
+      0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
+      0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
+      0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
+      0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
+      0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
+      0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
+      0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
+      0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
+      0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
+      0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
+      0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
+      0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
+      0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
+      0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
+      0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
+      0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
+      0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
+      0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
+      0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
+      0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
+      0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
+      0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
+      0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
+      0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
+      0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
+      0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
+      0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
+      0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
+      0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
+      0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
+      0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
+      0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
+      0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
+      0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
+      0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
+      0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
+      0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
+      0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
+      0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
+      0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
+      0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
+      0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
+      0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
+      0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
+      0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL
+  };
+  static const SWord32 table3[] = {
+      0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
+      0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
+      0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
+      0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
+      0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
+      0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
+      0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
+      0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
+      0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
+      0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
+      0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
+      0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
+      0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
+      0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
+      0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
+      0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
+      0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
+      0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
+      0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
+      0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
+      0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
+      0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
+      0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
+      0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
+      0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
+      0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
+      0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
+      0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
+      0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
+      0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
+      0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
+      0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
+      0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
+      0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
+      0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
+      0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
+      0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
+      0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
+      0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
+      0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
+      0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
+      0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
+      0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
+      0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
+      0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
+      0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
+      0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
+      0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
+      0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
+      0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
+      0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
+      0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
+      0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
+      0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
+      0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
+      0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
+      0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
+      0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
+      0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
+      0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
+      0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
+      0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
+      0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
+      0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL
+  };
+  static const SWord32 table4[] = {
+      0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
+      0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
+      0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
+      0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
+      0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
+      0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
+      0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
+      0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
+      0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
+      0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
+      0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
+      0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
+      0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
+      0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
+      0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
+      0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
+      0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
+      0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
+      0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
+      0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
+      0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
+      0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
+      0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
+      0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
+      0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
+      0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
+      0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
+      0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
+      0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
+      0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
+      0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
+      0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
+      0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
+      0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
+      0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
+      0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
+      0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
+      0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
+      0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
+      0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
+      0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
+      0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
+      0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
+      0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
+      0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
+      0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
+      0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
+      0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
+      0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
+      0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
+      0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
+      0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
+      0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
+      0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
+      0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
+      0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
+      0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
+      0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
+      0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
+      0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
+      0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
+      0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
+      0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
+      0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL
+  };
+  const SWord32 s560 = s0 ^ s4;
+  const SWord8  s561 = (SWord8) (s560 >> 24);
+  const SWord32 s562 = table1[s561];
+  const SWord32 s818 = s1 ^ s5;
+  const SWord8  s819 = (SWord8) (s818 >> 16);
+  const SWord32 s820 = table2[s819];
+  const SWord32 s821 = s562 ^ s820;
+  const SWord32 s1077 = s2 ^ s6;
+  const SWord8  s1078 = (SWord8) (s1077 >> 8);
+  const SWord32 s1079 = table3[s1078];
+  const SWord32 s1080 = s821 ^ s1079;
+  const SWord32 s1336 = s3 ^ s7;
+  const SWord8  s1337 = (SWord8) s1336;
+  const SWord32 s1338 = table4[s1337];
+  const SWord32 s1339 = s1080 ^ s1338;
+  const SWord32 s1340 = s8 ^ s1339;
+  const SWord8  s1341 = (SWord8) (s1340 >> 24);
+  const SWord32 s1342 = table1[s1341];
+  const SWord8  s1343 = (SWord8) (s818 >> 24);
+  const SWord32 s1344 = table1[s1343];
+  const SWord8  s1345 = (SWord8) (s1077 >> 16);
+  const SWord32 s1346 = table2[s1345];
+  const SWord32 s1347 = s1344 ^ s1346;
+  const SWord8  s1348 = (SWord8) (s1336 >> 8);
+  const SWord32 s1349 = table3[s1348];
+  const SWord32 s1350 = s1347 ^ s1349;
+  const SWord8  s1351 = (SWord8) s560;
+  const SWord32 s1352 = table4[s1351];
+  const SWord32 s1353 = s1350 ^ s1352;
+  const SWord32 s1354 = s9 ^ s1353;
+  const SWord8  s1355 = (SWord8) (s1354 >> 16);
+  const SWord32 s1356 = table2[s1355];
+  const SWord32 s1357 = s1342 ^ s1356;
+  const SWord8  s1358 = (SWord8) (s1077 >> 24);
+  const SWord32 s1359 = table1[s1358];
+  const SWord8  s1360 = (SWord8) (s1336 >> 16);
+  const SWord32 s1361 = table2[s1360];
+  const SWord32 s1362 = s1359 ^ s1361;
+  const SWord8  s1363 = (SWord8) (s560 >> 8);
+  const SWord32 s1364 = table3[s1363];
+  const SWord32 s1365 = s1362 ^ s1364;
+  const SWord8  s1366 = (SWord8) s818;
+  const SWord32 s1367 = table4[s1366];
+  const SWord32 s1368 = s1365 ^ s1367;
+  const SWord32 s1369 = s10 ^ s1368;
+  const SWord8  s1370 = (SWord8) (s1369 >> 8);
+  const SWord32 s1371 = table3[s1370];
+  const SWord32 s1372 = s1357 ^ s1371;
+  const SWord8  s1373 = (SWord8) (s1336 >> 24);
+  const SWord32 s1374 = table1[s1373];
+  const SWord8  s1375 = (SWord8) (s560 >> 16);
+  const SWord32 s1376 = table2[s1375];
+  const SWord32 s1377 = s1374 ^ s1376;
+  const SWord8  s1378 = (SWord8) (s818 >> 8);
+  const SWord32 s1379 = table3[s1378];
+  const SWord32 s1380 = s1377 ^ s1379;
+  const SWord8  s1381 = (SWord8) s1077;
+  const SWord32 s1382 = table4[s1381];
+  const SWord32 s1383 = s1380 ^ s1382;
+  const SWord32 s1384 = s11 ^ s1383;
+  const SWord8  s1385 = (SWord8) s1384;
+  const SWord32 s1386 = table4[s1385];
+  const SWord32 s1387 = s1372 ^ s1386;
+  const SWord32 s1388 = s12 ^ s1387;
+  const SWord8  s1389 = (SWord8) (s1388 >> 24);
+  const SWord32 s1390 = table1[s1389];
+  const SWord8  s1391 = (SWord8) (s1354 >> 24);
+  const SWord32 s1392 = table1[s1391];
+  const SWord8  s1393 = (SWord8) (s1369 >> 16);
+  const SWord32 s1394 = table2[s1393];
+  const SWord32 s1395 = s1392 ^ s1394;
+  const SWord8  s1396 = (SWord8) (s1384 >> 8);
+  const SWord32 s1397 = table3[s1396];
+  const SWord32 s1398 = s1395 ^ s1397;
+  const SWord8  s1399 = (SWord8) s1340;
+  const SWord32 s1400 = table4[s1399];
+  const SWord32 s1401 = s1398 ^ s1400;
+  const SWord32 s1402 = s13 ^ s1401;
+  const SWord8  s1403 = (SWord8) (s1402 >> 16);
+  const SWord32 s1404 = table2[s1403];
+  const SWord32 s1405 = s1390 ^ s1404;
+  const SWord8  s1406 = (SWord8) (s1369 >> 24);
+  const SWord32 s1407 = table1[s1406];
+  const SWord8  s1408 = (SWord8) (s1384 >> 16);
+  const SWord32 s1409 = table2[s1408];
+  const SWord32 s1410 = s1407 ^ s1409;
+  const SWord8  s1411 = (SWord8) (s1340 >> 8);
+  const SWord32 s1412 = table3[s1411];
+  const SWord32 s1413 = s1410 ^ s1412;
+  const SWord8  s1414 = (SWord8) s1354;
+  const SWord32 s1415 = table4[s1414];
+  const SWord32 s1416 = s1413 ^ s1415;
+  const SWord32 s1417 = s14 ^ s1416;
+  const SWord8  s1418 = (SWord8) (s1417 >> 8);
+  const SWord32 s1419 = table3[s1418];
+  const SWord32 s1420 = s1405 ^ s1419;
+  const SWord8  s1421 = (SWord8) (s1384 >> 24);
+  const SWord32 s1422 = table1[s1421];
+  const SWord8  s1423 = (SWord8) (s1340 >> 16);
+  const SWord32 s1424 = table2[s1423];
+  const SWord32 s1425 = s1422 ^ s1424;
+  const SWord8  s1426 = (SWord8) (s1354 >> 8);
+  const SWord32 s1427 = table3[s1426];
+  const SWord32 s1428 = s1425 ^ s1427;
+  const SWord8  s1429 = (SWord8) s1369;
+  const SWord32 s1430 = table4[s1429];
+  const SWord32 s1431 = s1428 ^ s1430;
+  const SWord32 s1432 = s15 ^ s1431;
+  const SWord8  s1433 = (SWord8) s1432;
+  const SWord32 s1434 = table4[s1433];
+  const SWord32 s1435 = s1420 ^ s1434;
+  const SWord32 s1436 = s16 ^ s1435;
+  const SWord8  s1437 = (SWord8) (s1436 >> 24);
+  const SWord32 s1438 = table1[s1437];
+  const SWord8  s1439 = (SWord8) (s1402 >> 24);
+  const SWord32 s1440 = table1[s1439];
+  const SWord8  s1441 = (SWord8) (s1417 >> 16);
+  const SWord32 s1442 = table2[s1441];
+  const SWord32 s1443 = s1440 ^ s1442;
+  const SWord8  s1444 = (SWord8) (s1432 >> 8);
+  const SWord32 s1445 = table3[s1444];
+  const SWord32 s1446 = s1443 ^ s1445;
+  const SWord8  s1447 = (SWord8) s1388;
+  const SWord32 s1448 = table4[s1447];
+  const SWord32 s1449 = s1446 ^ s1448;
+  const SWord32 s1450 = s17 ^ s1449;
+  const SWord8  s1451 = (SWord8) (s1450 >> 16);
+  const SWord32 s1452 = table2[s1451];
+  const SWord32 s1453 = s1438 ^ s1452;
+  const SWord8  s1454 = (SWord8) (s1417 >> 24);
+  const SWord32 s1455 = table1[s1454];
+  const SWord8  s1456 = (SWord8) (s1432 >> 16);
+  const SWord32 s1457 = table2[s1456];
+  const SWord32 s1458 = s1455 ^ s1457;
+  const SWord8  s1459 = (SWord8) (s1388 >> 8);
+  const SWord32 s1460 = table3[s1459];
+  const SWord32 s1461 = s1458 ^ s1460;
+  const SWord8  s1462 = (SWord8) s1402;
+  const SWord32 s1463 = table4[s1462];
+  const SWord32 s1464 = s1461 ^ s1463;
+  const SWord32 s1465 = s18 ^ s1464;
+  const SWord8  s1466 = (SWord8) (s1465 >> 8);
+  const SWord32 s1467 = table3[s1466];
+  const SWord32 s1468 = s1453 ^ s1467;
+  const SWord8  s1469 = (SWord8) (s1432 >> 24);
+  const SWord32 s1470 = table1[s1469];
+  const SWord8  s1471 = (SWord8) (s1388 >> 16);
+  const SWord32 s1472 = table2[s1471];
+  const SWord32 s1473 = s1470 ^ s1472;
+  const SWord8  s1474 = (SWord8) (s1402 >> 8);
+  const SWord32 s1475 = table3[s1474];
+  const SWord32 s1476 = s1473 ^ s1475;
+  const SWord8  s1477 = (SWord8) s1417;
+  const SWord32 s1478 = table4[s1477];
+  const SWord32 s1479 = s1476 ^ s1478;
+  const SWord32 s1480 = s19 ^ s1479;
+  const SWord8  s1481 = (SWord8) s1480;
+  const SWord32 s1482 = table4[s1481];
+  const SWord32 s1483 = s1468 ^ s1482;
+  const SWord32 s1484 = s20 ^ s1483;
+  const SWord8  s1485 = (SWord8) (s1484 >> 24);
+  const SWord32 s1486 = table1[s1485];
+  const SWord8  s1487 = (SWord8) (s1450 >> 24);
+  const SWord32 s1488 = table1[s1487];
+  const SWord8  s1489 = (SWord8) (s1465 >> 16);
+  const SWord32 s1490 = table2[s1489];
+  const SWord32 s1491 = s1488 ^ s1490;
+  const SWord8  s1492 = (SWord8) (s1480 >> 8);
+  const SWord32 s1493 = table3[s1492];
+  const SWord32 s1494 = s1491 ^ s1493;
+  const SWord8  s1495 = (SWord8) s1436;
+  const SWord32 s1496 = table4[s1495];
+  const SWord32 s1497 = s1494 ^ s1496;
+  const SWord32 s1498 = s21 ^ s1497;
+  const SWord8  s1499 = (SWord8) (s1498 >> 16);
+  const SWord32 s1500 = table2[s1499];
+  const SWord32 s1501 = s1486 ^ s1500;
+  const SWord8  s1502 = (SWord8) (s1465 >> 24);
+  const SWord32 s1503 = table1[s1502];
+  const SWord8  s1504 = (SWord8) (s1480 >> 16);
+  const SWord32 s1505 = table2[s1504];
+  const SWord32 s1506 = s1503 ^ s1505;
+  const SWord8  s1507 = (SWord8) (s1436 >> 8);
+  const SWord32 s1508 = table3[s1507];
+  const SWord32 s1509 = s1506 ^ s1508;
+  const SWord8  s1510 = (SWord8) s1450;
+  const SWord32 s1511 = table4[s1510];
+  const SWord32 s1512 = s1509 ^ s1511;
+  const SWord32 s1513 = s22 ^ s1512;
+  const SWord8  s1514 = (SWord8) (s1513 >> 8);
+  const SWord32 s1515 = table3[s1514];
+  const SWord32 s1516 = s1501 ^ s1515;
+  const SWord8  s1517 = (SWord8) (s1480 >> 24);
+  const SWord32 s1518 = table1[s1517];
+  const SWord8  s1519 = (SWord8) (s1436 >> 16);
+  const SWord32 s1520 = table2[s1519];
+  const SWord32 s1521 = s1518 ^ s1520;
+  const SWord8  s1522 = (SWord8) (s1450 >> 8);
+  const SWord32 s1523 = table3[s1522];
+  const SWord32 s1524 = s1521 ^ s1523;
+  const SWord8  s1525 = (SWord8) s1465;
+  const SWord32 s1526 = table4[s1525];
+  const SWord32 s1527 = s1524 ^ s1526;
+  const SWord32 s1528 = s23 ^ s1527;
+  const SWord8  s1529 = (SWord8) s1528;
+  const SWord32 s1530 = table4[s1529];
+  const SWord32 s1531 = s1516 ^ s1530;
+  const SWord32 s1532 = s24 ^ s1531;
+  const SWord8  s1533 = (SWord8) (s1532 >> 24);
+  const SWord32 s1534 = table1[s1533];
+  const SWord8  s1535 = (SWord8) (s1498 >> 24);
+  const SWord32 s1536 = table1[s1535];
+  const SWord8  s1537 = (SWord8) (s1513 >> 16);
+  const SWord32 s1538 = table2[s1537];
+  const SWord32 s1539 = s1536 ^ s1538;
+  const SWord8  s1540 = (SWord8) (s1528 >> 8);
+  const SWord32 s1541 = table3[s1540];
+  const SWord32 s1542 = s1539 ^ s1541;
+  const SWord8  s1543 = (SWord8) s1484;
+  const SWord32 s1544 = table4[s1543];
+  const SWord32 s1545 = s1542 ^ s1544;
+  const SWord32 s1546 = s25 ^ s1545;
+  const SWord8  s1547 = (SWord8) (s1546 >> 16);
+  const SWord32 s1548 = table2[s1547];
+  const SWord32 s1549 = s1534 ^ s1548;
+  const SWord8  s1550 = (SWord8) (s1513 >> 24);
+  const SWord32 s1551 = table1[s1550];
+  const SWord8  s1552 = (SWord8) (s1528 >> 16);
+  const SWord32 s1553 = table2[s1552];
+  const SWord32 s1554 = s1551 ^ s1553;
+  const SWord8  s1555 = (SWord8) (s1484 >> 8);
+  const SWord32 s1556 = table3[s1555];
+  const SWord32 s1557 = s1554 ^ s1556;
+  const SWord8  s1558 = (SWord8) s1498;
+  const SWord32 s1559 = table4[s1558];
+  const SWord32 s1560 = s1557 ^ s1559;
+  const SWord32 s1561 = s26 ^ s1560;
+  const SWord8  s1562 = (SWord8) (s1561 >> 8);
+  const SWord32 s1563 = table3[s1562];
+  const SWord32 s1564 = s1549 ^ s1563;
+  const SWord8  s1565 = (SWord8) (s1528 >> 24);
+  const SWord32 s1566 = table1[s1565];
+  const SWord8  s1567 = (SWord8) (s1484 >> 16);
+  const SWord32 s1568 = table2[s1567];
+  const SWord32 s1569 = s1566 ^ s1568;
+  const SWord8  s1570 = (SWord8) (s1498 >> 8);
+  const SWord32 s1571 = table3[s1570];
+  const SWord32 s1572 = s1569 ^ s1571;
+  const SWord8  s1573 = (SWord8) s1513;
+  const SWord32 s1574 = table4[s1573];
+  const SWord32 s1575 = s1572 ^ s1574;
+  const SWord32 s1576 = s27 ^ s1575;
+  const SWord8  s1577 = (SWord8) s1576;
+  const SWord32 s1578 = table4[s1577];
+  const SWord32 s1579 = s1564 ^ s1578;
+  const SWord32 s1580 = s28 ^ s1579;
+  const SWord8  s1581 = (SWord8) (s1580 >> 24);
+  const SWord32 s1582 = table1[s1581];
+  const SWord8  s1583 = (SWord8) (s1546 >> 24);
+  const SWord32 s1584 = table1[s1583];
+  const SWord8  s1585 = (SWord8) (s1561 >> 16);
+  const SWord32 s1586 = table2[s1585];
+  const SWord32 s1587 = s1584 ^ s1586;
+  const SWord8  s1588 = (SWord8) (s1576 >> 8);
+  const SWord32 s1589 = table3[s1588];
+  const SWord32 s1590 = s1587 ^ s1589;
+  const SWord8  s1591 = (SWord8) s1532;
+  const SWord32 s1592 = table4[s1591];
+  const SWord32 s1593 = s1590 ^ s1592;
+  const SWord32 s1594 = s29 ^ s1593;
+  const SWord8  s1595 = (SWord8) (s1594 >> 16);
+  const SWord32 s1596 = table2[s1595];
+  const SWord32 s1597 = s1582 ^ s1596;
+  const SWord8  s1598 = (SWord8) (s1561 >> 24);
+  const SWord32 s1599 = table1[s1598];
+  const SWord8  s1600 = (SWord8) (s1576 >> 16);
+  const SWord32 s1601 = table2[s1600];
+  const SWord32 s1602 = s1599 ^ s1601;
+  const SWord8  s1603 = (SWord8) (s1532 >> 8);
+  const SWord32 s1604 = table3[s1603];
+  const SWord32 s1605 = s1602 ^ s1604;
+  const SWord8  s1606 = (SWord8) s1546;
+  const SWord32 s1607 = table4[s1606];
+  const SWord32 s1608 = s1605 ^ s1607;
+  const SWord32 s1609 = s30 ^ s1608;
+  const SWord8  s1610 = (SWord8) (s1609 >> 8);
+  const SWord32 s1611 = table3[s1610];
+  const SWord32 s1612 = s1597 ^ s1611;
+  const SWord8  s1613 = (SWord8) (s1576 >> 24);
+  const SWord32 s1614 = table1[s1613];
+  const SWord8  s1615 = (SWord8) (s1532 >> 16);
+  const SWord32 s1616 = table2[s1615];
+  const SWord32 s1617 = s1614 ^ s1616;
+  const SWord8  s1618 = (SWord8) (s1546 >> 8);
+  const SWord32 s1619 = table3[s1618];
+  const SWord32 s1620 = s1617 ^ s1619;
+  const SWord8  s1621 = (SWord8) s1561;
+  const SWord32 s1622 = table4[s1621];
+  const SWord32 s1623 = s1620 ^ s1622;
+  const SWord32 s1624 = s31 ^ s1623;
+  const SWord8  s1625 = (SWord8) s1624;
+  const SWord32 s1626 = table4[s1625];
+  const SWord32 s1627 = s1612 ^ s1626;
+  const SWord32 s1628 = s32 ^ s1627;
+  const SWord8  s1629 = (SWord8) (s1628 >> 24);
+  const SWord32 s1630 = table1[s1629];
+  const SWord8  s1631 = (SWord8) (s1594 >> 24);
+  const SWord32 s1632 = table1[s1631];
+  const SWord8  s1633 = (SWord8) (s1609 >> 16);
+  const SWord32 s1634 = table2[s1633];
+  const SWord32 s1635 = s1632 ^ s1634;
+  const SWord8  s1636 = (SWord8) (s1624 >> 8);
+  const SWord32 s1637 = table3[s1636];
+  const SWord32 s1638 = s1635 ^ s1637;
+  const SWord8  s1639 = (SWord8) s1580;
+  const SWord32 s1640 = table4[s1639];
+  const SWord32 s1641 = s1638 ^ s1640;
+  const SWord32 s1642 = s33 ^ s1641;
+  const SWord8  s1643 = (SWord8) (s1642 >> 16);
+  const SWord32 s1644 = table2[s1643];
+  const SWord32 s1645 = s1630 ^ s1644;
+  const SWord8  s1646 = (SWord8) (s1609 >> 24);
+  const SWord32 s1647 = table1[s1646];
+  const SWord8  s1648 = (SWord8) (s1624 >> 16);
+  const SWord32 s1649 = table2[s1648];
+  const SWord32 s1650 = s1647 ^ s1649;
+  const SWord8  s1651 = (SWord8) (s1580 >> 8);
+  const SWord32 s1652 = table3[s1651];
+  const SWord32 s1653 = s1650 ^ s1652;
+  const SWord8  s1654 = (SWord8) s1594;
+  const SWord32 s1655 = table4[s1654];
+  const SWord32 s1656 = s1653 ^ s1655;
+  const SWord32 s1657 = s34 ^ s1656;
+  const SWord8  s1658 = (SWord8) (s1657 >> 8);
+  const SWord32 s1659 = table3[s1658];
+  const SWord32 s1660 = s1645 ^ s1659;
+  const SWord8  s1661 = (SWord8) (s1624 >> 24);
+  const SWord32 s1662 = table1[s1661];
+  const SWord8  s1663 = (SWord8) (s1580 >> 16);
+  const SWord32 s1664 = table2[s1663];
+  const SWord32 s1665 = s1662 ^ s1664;
+  const SWord8  s1666 = (SWord8) (s1594 >> 8);
+  const SWord32 s1667 = table3[s1666];
+  const SWord32 s1668 = s1665 ^ s1667;
+  const SWord8  s1669 = (SWord8) s1609;
+  const SWord32 s1670 = table4[s1669];
+  const SWord32 s1671 = s1668 ^ s1670;
+  const SWord32 s1672 = s35 ^ s1671;
+  const SWord8  s1673 = (SWord8) s1672;
+  const SWord32 s1674 = table4[s1673];
+  const SWord32 s1675 = s1660 ^ s1674;
+  const SWord32 s1676 = s36 ^ s1675;
+  const SWord8  s1677 = (SWord8) (s1676 >> 24);
+  const SWord32 s1678 = table1[s1677];
+  const SWord8  s1679 = (SWord8) (s1642 >> 24);
+  const SWord32 s1680 = table1[s1679];
+  const SWord8  s1681 = (SWord8) (s1657 >> 16);
+  const SWord32 s1682 = table2[s1681];
+  const SWord32 s1683 = s1680 ^ s1682;
+  const SWord8  s1684 = (SWord8) (s1672 >> 8);
+  const SWord32 s1685 = table3[s1684];
+  const SWord32 s1686 = s1683 ^ s1685;
+  const SWord8  s1687 = (SWord8) s1628;
+  const SWord32 s1688 = table4[s1687];
+  const SWord32 s1689 = s1686 ^ s1688;
+  const SWord32 s1690 = s37 ^ s1689;
+  const SWord8  s1691 = (SWord8) (s1690 >> 16);
+  const SWord32 s1692 = table2[s1691];
+  const SWord32 s1693 = s1678 ^ s1692;
+  const SWord8  s1694 = (SWord8) (s1657 >> 24);
+  const SWord32 s1695 = table1[s1694];
+  const SWord8  s1696 = (SWord8) (s1672 >> 16);
+  const SWord32 s1697 = table2[s1696];
+  const SWord32 s1698 = s1695 ^ s1697;
+  const SWord8  s1699 = (SWord8) (s1628 >> 8);
+  const SWord32 s1700 = table3[s1699];
+  const SWord32 s1701 = s1698 ^ s1700;
+  const SWord8  s1702 = (SWord8) s1642;
+  const SWord32 s1703 = table4[s1702];
+  const SWord32 s1704 = s1701 ^ s1703;
+  const SWord32 s1705 = s38 ^ s1704;
+  const SWord8  s1706 = (SWord8) (s1705 >> 8);
+  const SWord32 s1707 = table3[s1706];
+  const SWord32 s1708 = s1693 ^ s1707;
+  const SWord8  s1709 = (SWord8) (s1672 >> 24);
+  const SWord32 s1710 = table1[s1709];
+  const SWord8  s1711 = (SWord8) (s1628 >> 16);
+  const SWord32 s1712 = table2[s1711];
+  const SWord32 s1713 = s1710 ^ s1712;
+  const SWord8  s1714 = (SWord8) (s1642 >> 8);
+  const SWord32 s1715 = table3[s1714];
+  const SWord32 s1716 = s1713 ^ s1715;
+  const SWord8  s1717 = (SWord8) s1657;
+  const SWord32 s1718 = table4[s1717];
+  const SWord32 s1719 = s1716 ^ s1718;
+  const SWord32 s1720 = s39 ^ s1719;
+  const SWord8  s1721 = (SWord8) s1720;
+  const SWord32 s1722 = table4[s1721];
+  const SWord32 s1723 = s1708 ^ s1722;
+  const SWord32 s1724 = s40 ^ s1723;
+  const SWord8  s1725 = (SWord8) (s1724 >> 24);
+  const SWord8  s1726 = table0[s1725];
+  const SWord8  s1727 = (SWord8) (s1690 >> 24);
+  const SWord32 s1728 = table1[s1727];
+  const SWord8  s1729 = (SWord8) (s1705 >> 16);
+  const SWord32 s1730 = table2[s1729];
+  const SWord32 s1731 = s1728 ^ s1730;
+  const SWord8  s1732 = (SWord8) (s1720 >> 8);
+  const SWord32 s1733 = table3[s1732];
+  const SWord32 s1734 = s1731 ^ s1733;
+  const SWord8  s1735 = (SWord8) s1676;
+  const SWord32 s1736 = table4[s1735];
+  const SWord32 s1737 = s1734 ^ s1736;
+  const SWord32 s1738 = s41 ^ s1737;
+  const SWord8  s1739 = (SWord8) (s1738 >> 16);
+  const SWord8  s1740 = table0[s1739];
+  const SWord16 s1741 = (((SWord16) s1726) << 8) | ((SWord16) s1740);
+  const SWord8  s1742 = (SWord8) (s1705 >> 24);
+  const SWord32 s1743 = table1[s1742];
+  const SWord8  s1744 = (SWord8) (s1720 >> 16);
+  const SWord32 s1745 = table2[s1744];
+  const SWord32 s1746 = s1743 ^ s1745;
+  const SWord8  s1747 = (SWord8) (s1676 >> 8);
+  const SWord32 s1748 = table3[s1747];
+  const SWord32 s1749 = s1746 ^ s1748;
+  const SWord8  s1750 = (SWord8) s1690;
+  const SWord32 s1751 = table4[s1750];
+  const SWord32 s1752 = s1749 ^ s1751;
+  const SWord32 s1753 = s42 ^ s1752;
+  const SWord8  s1754 = (SWord8) (s1753 >> 8);
+  const SWord8  s1755 = table0[s1754];
+  const SWord8  s1756 = (SWord8) (s1720 >> 24);
+  const SWord32 s1757 = table1[s1756];
+  const SWord8  s1758 = (SWord8) (s1676 >> 16);
+  const SWord32 s1759 = table2[s1758];
+  const SWord32 s1760 = s1757 ^ s1759;
+  const SWord8  s1761 = (SWord8) (s1690 >> 8);
+  const SWord32 s1762 = table3[s1761];
+  const SWord32 s1763 = s1760 ^ s1762;
+  const SWord8  s1764 = (SWord8) s1705;
+  const SWord32 s1765 = table4[s1764];
+  const SWord32 s1766 = s1763 ^ s1765;
+  const SWord32 s1767 = s43 ^ s1766;
+  const SWord8  s1768 = (SWord8) s1767;
+  const SWord8  s1769 = table0[s1768];
+  const SWord16 s1770 = (((SWord16) s1755) << 8) | ((SWord16) s1769);
+  const SWord32 s1771 = (((SWord32) s1741) << 16) | ((SWord32) s1770);
+  const SWord32 s1772 = s44 ^ s1771;
+  const SWord8  s1773 = (SWord8) (s1738 >> 24);
+  const SWord8  s1774 = table0[s1773];
+  const SWord8  s1775 = (SWord8) (s1753 >> 16);
+  const SWord8  s1776 = table0[s1775];
+  const SWord16 s1777 = (((SWord16) s1774) << 8) | ((SWord16) s1776);
+  const SWord8  s1778 = (SWord8) (s1767 >> 8);
+  const SWord8  s1779 = table0[s1778];
+  const SWord8  s1780 = (SWord8) s1724;
+  const SWord8  s1781 = table0[s1780];
+  const SWord16 s1782 = (((SWord16) s1779) << 8) | ((SWord16) s1781);
+  const SWord32 s1783 = (((SWord32) s1777) << 16) | ((SWord32) s1782);
+  const SWord32 s1784 = s45 ^ s1783;
+  const SWord8  s1785 = (SWord8) (s1753 >> 24);
+  const SWord8  s1786 = table0[s1785];
+  const SWord8  s1787 = (SWord8) (s1767 >> 16);
+  const SWord8  s1788 = table0[s1787];
+  const SWord16 s1789 = (((SWord16) s1786) << 8) | ((SWord16) s1788);
+  const SWord8  s1790 = (SWord8) (s1724 >> 8);
+  const SWord8  s1791 = table0[s1790];
+  const SWord8  s1792 = (SWord8) s1738;
+  const SWord8  s1793 = table0[s1792];
+  const SWord16 s1794 = (((SWord16) s1791) << 8) | ((SWord16) s1793);
+  const SWord32 s1795 = (((SWord32) s1789) << 16) | ((SWord32) s1794);
+  const SWord32 s1796 = s46 ^ s1795;
+  const SWord8  s1797 = (SWord8) (s1767 >> 24);
+  const SWord8  s1798 = table0[s1797];
+  const SWord8  s1799 = (SWord8) (s1724 >> 16);
+  const SWord8  s1800 = table0[s1799];
+  const SWord16 s1801 = (((SWord16) s1798) << 8) | ((SWord16) s1800);
+  const SWord8  s1802 = (SWord8) (s1738 >> 8);
+  const SWord8  s1803 = table0[s1802];
+  const SWord8  s1804 = (SWord8) s1753;
+  const SWord8  s1805 = table0[s1804];
+  const SWord16 s1806 = (((SWord16) s1803) << 8) | ((SWord16) s1805);
+  const SWord32 s1807 = (((SWord32) s1801) << 16) | ((SWord32) s1806);
+  const SWord32 s1808 = s47 ^ s1807;
+
+  ct[0] = s1772;
+  ct[1] = s1784;
+  ct[2] = s1796;
+  ct[3] = s1808;
+}
+== END: "aes128BlockEncrypt.c" ==================
+== BEGIN: "aes128BlockDecrypt.c" ================
+/* File: "aes128BlockDecrypt.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Lib.h"
+
+void aes128BlockDecrypt(const SWord32 *ct, const SWord32 *xkey,
+                        SWord32 *pt)
+{
+  const SWord32 s0 = ct[0];
+  const SWord32 s1 = ct[1];
+  const SWord32 s2 = ct[2];
+  const SWord32 s3 = ct[3];
+  const SWord32 s4 = xkey[0];
+  const SWord32 s5 = xkey[1];
+  const SWord32 s6 = xkey[2];
+  const SWord32 s7 = xkey[3];
+  const SWord32 s8 = xkey[4];
+  const SWord32 s9 = xkey[5];
+  const SWord32 s10 = xkey[6];
+  const SWord32 s11 = xkey[7];
+  const SWord32 s12 = xkey[8];
+  const SWord32 s13 = xkey[9];
+  const SWord32 s14 = xkey[10];
+  const SWord32 s15 = xkey[11];
+  const SWord32 s16 = xkey[12];
+  const SWord32 s17 = xkey[13];
+  const SWord32 s18 = xkey[14];
+  const SWord32 s19 = xkey[15];
+  const SWord32 s20 = xkey[16];
+  const SWord32 s21 = xkey[17];
+  const SWord32 s22 = xkey[18];
+  const SWord32 s23 = xkey[19];
+  const SWord32 s24 = xkey[20];
+  const SWord32 s25 = xkey[21];
+  const SWord32 s26 = xkey[22];
+  const SWord32 s27 = xkey[23];
+  const SWord32 s28 = xkey[24];
+  const SWord32 s29 = xkey[25];
+  const SWord32 s30 = xkey[26];
+  const SWord32 s31 = xkey[27];
+  const SWord32 s32 = xkey[28];
+  const SWord32 s33 = xkey[29];
+  const SWord32 s34 = xkey[30];
+  const SWord32 s35 = xkey[31];
+  const SWord32 s36 = xkey[32];
+  const SWord32 s37 = xkey[33];
+  const SWord32 s38 = xkey[34];
+  const SWord32 s39 = xkey[35];
+  const SWord32 s40 = xkey[36];
+  const SWord32 s41 = xkey[37];
+  const SWord32 s42 = xkey[38];
+  const SWord32 s43 = xkey[39];
+  const SWord32 s44 = xkey[40];
+  const SWord32 s45 = xkey[41];
+  const SWord32 s46 = xkey[42];
+  const SWord32 s47 = xkey[43];
+  static const SWord8 table0[] = {
+       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129,
+      243, 215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,
+       67,  68, 196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,
+       61, 238,  76, 149,  11,  66, 250, 195,  78,   8,  46, 161, 102,
+       40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 114,
+      248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101,
+      182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,
+       87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10,
+      247, 228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,
+       63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,  58, 145,
+       17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230,
+      115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,
+       28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 111,
+      183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
+      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
+       51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
+       96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147,
+      201, 156, 239, 160, 224,  59,  77, 174,  42, 245, 176, 200, 235,
+      187,  60, 131,  83, 153,  97,  23,  43,   4, 126, 186, 119, 214,
+       38, 225, 105,  20,  99,  85,  33,  12, 125
+  };
+  static const SWord32 table1[] = {
+      0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+      0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+      0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+      0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+      0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+      0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+      0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+      0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+      0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+      0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+      0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+      0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+      0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+      0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+      0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+      0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+      0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+      0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+      0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+      0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+      0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+      0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+      0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+      0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+      0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+      0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+      0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+      0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+      0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+      0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+      0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+      0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+      0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+      0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+      0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+      0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+      0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+      0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+      0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+      0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+      0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+      0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+      0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+      0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+      0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+      0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+      0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+      0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+      0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+      0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+      0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+      0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+      0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+      0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+      0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+      0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+      0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+      0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+      0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+      0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+      0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+      0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+      0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+      0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL
+  };
+  static const SWord32 table2[] = {
+      0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
+      0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
+      0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
+      0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
+      0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
+      0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
+      0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
+      0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
+      0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
+      0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
+      0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
+      0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
+      0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
+      0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
+      0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
+      0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
+      0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
+      0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
+      0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
+      0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
+      0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
+      0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
+      0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
+      0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
+      0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
+      0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
+      0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
+      0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
+      0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
+      0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
+      0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
+      0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
+      0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
+      0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
+      0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
+      0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
+      0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
+      0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
+      0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
+      0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
+      0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
+      0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
+      0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
+      0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
+      0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
+      0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
+      0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
+      0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
+      0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
+      0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
+      0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
+      0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
+      0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
+      0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
+      0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
+      0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
+      0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
+      0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
+      0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
+      0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
+      0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
+      0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
+      0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
+      0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL
+  };
+  static const SWord32 table3[] = {
+      0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
+      0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
+      0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
+      0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
+      0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
+      0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
+      0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
+      0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
+      0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
+      0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
+      0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
+      0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
+      0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
+      0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
+      0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
+      0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
+      0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
+      0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
+      0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
+      0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
+      0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
+      0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
+      0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
+      0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
+      0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
+      0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
+      0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
+      0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
+      0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
+      0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
+      0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
+      0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
+      0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
+      0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
+      0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
+      0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
+      0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
+      0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
+      0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
+      0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
+      0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
+      0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
+      0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
+      0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
+      0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
+      0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
+      0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
+      0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
+      0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
+      0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
+      0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
+      0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
+      0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
+      0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
+      0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
+      0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
+      0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
+      0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
+      0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
+      0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
+      0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
+      0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
+      0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
+      0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL
+  };
+  static const SWord32 table4[] = {
+      0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
+      0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
+      0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
+      0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
+      0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
+      0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
+      0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
+      0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
+      0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
+      0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
+      0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
+      0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
+      0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
+      0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
+      0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
+      0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
+      0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
+      0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
+      0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
+      0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
+      0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
+      0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
+      0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
+      0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
+      0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
+      0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
+      0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
+      0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
+      0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
+      0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
+      0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
+      0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
+      0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
+      0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
+      0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
+      0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
+      0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
+      0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
+      0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
+      0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
+      0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
+      0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
+      0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
+      0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
+      0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
+      0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
+      0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
+      0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
+      0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
+      0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
+      0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
+      0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
+      0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
+      0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
+      0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
+      0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
+      0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
+      0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
+      0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
+      0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
+      0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
+      0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
+      0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
+      0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL
+  };
+  const SWord32 s560 = s0 ^ s4;
+  const SWord8  s561 = (SWord8) (s560 >> 24);
+  const SWord32 s562 = table1[s561];
+  const SWord32 s818 = s3 ^ s7;
+  const SWord8  s819 = (SWord8) (s818 >> 16);
+  const SWord32 s820 = table2[s819];
+  const SWord32 s821 = s562 ^ s820;
+  const SWord32 s1077 = s2 ^ s6;
+  const SWord8  s1078 = (SWord8) (s1077 >> 8);
+  const SWord32 s1079 = table3[s1078];
+  const SWord32 s1080 = s821 ^ s1079;
+  const SWord32 s1336 = s1 ^ s5;
+  const SWord8  s1337 = (SWord8) s1336;
+  const SWord32 s1338 = table4[s1337];
+  const SWord32 s1339 = s1080 ^ s1338;
+  const SWord32 s1340 = s8 ^ s1339;
+  const SWord8  s1341 = (SWord8) (s1340 >> 24);
+  const SWord32 s1342 = table1[s1341];
+  const SWord8  s1343 = (SWord8) (s818 >> 24);
+  const SWord32 s1344 = table1[s1343];
+  const SWord8  s1345 = (SWord8) (s1077 >> 16);
+  const SWord32 s1346 = table2[s1345];
+  const SWord32 s1347 = s1344 ^ s1346;
+  const SWord8  s1348 = (SWord8) (s1336 >> 8);
+  const SWord32 s1349 = table3[s1348];
+  const SWord32 s1350 = s1347 ^ s1349;
+  const SWord8  s1351 = (SWord8) s560;
+  const SWord32 s1352 = table4[s1351];
+  const SWord32 s1353 = s1350 ^ s1352;
+  const SWord32 s1354 = s11 ^ s1353;
+  const SWord8  s1355 = (SWord8) (s1354 >> 16);
+  const SWord32 s1356 = table2[s1355];
+  const SWord32 s1357 = s1342 ^ s1356;
+  const SWord8  s1358 = (SWord8) (s1077 >> 24);
+  const SWord32 s1359 = table1[s1358];
+  const SWord8  s1360 = (SWord8) (s1336 >> 16);
+  const SWord32 s1361 = table2[s1360];
+  const SWord32 s1362 = s1359 ^ s1361;
+  const SWord8  s1363 = (SWord8) (s560 >> 8);
+  const SWord32 s1364 = table3[s1363];
+  const SWord32 s1365 = s1362 ^ s1364;
+  const SWord8  s1366 = (SWord8) s818;
+  const SWord32 s1367 = table4[s1366];
+  const SWord32 s1368 = s1365 ^ s1367;
+  const SWord32 s1369 = s10 ^ s1368;
+  const SWord8  s1370 = (SWord8) (s1369 >> 8);
+  const SWord32 s1371 = table3[s1370];
+  const SWord32 s1372 = s1357 ^ s1371;
+  const SWord8  s1373 = (SWord8) (s1336 >> 24);
+  const SWord32 s1374 = table1[s1373];
+  const SWord8  s1375 = (SWord8) (s560 >> 16);
+  const SWord32 s1376 = table2[s1375];
+  const SWord32 s1377 = s1374 ^ s1376;
+  const SWord8  s1378 = (SWord8) (s818 >> 8);
+  const SWord32 s1379 = table3[s1378];
+  const SWord32 s1380 = s1377 ^ s1379;
+  const SWord8  s1381 = (SWord8) s1077;
+  const SWord32 s1382 = table4[s1381];
+  const SWord32 s1383 = s1380 ^ s1382;
+  const SWord32 s1384 = s9 ^ s1383;
+  const SWord8  s1385 = (SWord8) s1384;
+  const SWord32 s1386 = table4[s1385];
+  const SWord32 s1387 = s1372 ^ s1386;
+  const SWord32 s1388 = s12 ^ s1387;
+  const SWord8  s1389 = (SWord8) (s1388 >> 24);
+  const SWord32 s1390 = table1[s1389];
+  const SWord8  s1391 = (SWord8) (s1354 >> 24);
+  const SWord32 s1392 = table1[s1391];
+  const SWord8  s1393 = (SWord8) (s1369 >> 16);
+  const SWord32 s1394 = table2[s1393];
+  const SWord32 s1395 = s1392 ^ s1394;
+  const SWord8  s1396 = (SWord8) (s1384 >> 8);
+  const SWord32 s1397 = table3[s1396];
+  const SWord32 s1398 = s1395 ^ s1397;
+  const SWord8  s1399 = (SWord8) s1340;
+  const SWord32 s1400 = table4[s1399];
+  const SWord32 s1401 = s1398 ^ s1400;
+  const SWord32 s1402 = s15 ^ s1401;
+  const SWord8  s1403 = (SWord8) (s1402 >> 16);
+  const SWord32 s1404 = table2[s1403];
+  const SWord32 s1405 = s1390 ^ s1404;
+  const SWord8  s1406 = (SWord8) (s1369 >> 24);
+  const SWord32 s1407 = table1[s1406];
+  const SWord8  s1408 = (SWord8) (s1384 >> 16);
+  const SWord32 s1409 = table2[s1408];
+  const SWord32 s1410 = s1407 ^ s1409;
+  const SWord8  s1411 = (SWord8) (s1340 >> 8);
+  const SWord32 s1412 = table3[s1411];
+  const SWord32 s1413 = s1410 ^ s1412;
+  const SWord8  s1414 = (SWord8) s1354;
+  const SWord32 s1415 = table4[s1414];
+  const SWord32 s1416 = s1413 ^ s1415;
+  const SWord32 s1417 = s14 ^ s1416;
+  const SWord8  s1418 = (SWord8) (s1417 >> 8);
+  const SWord32 s1419 = table3[s1418];
+  const SWord32 s1420 = s1405 ^ s1419;
+  const SWord8  s1421 = (SWord8) (s1384 >> 24);
+  const SWord32 s1422 = table1[s1421];
+  const SWord8  s1423 = (SWord8) (s1340 >> 16);
+  const SWord32 s1424 = table2[s1423];
+  const SWord32 s1425 = s1422 ^ s1424;
+  const SWord8  s1426 = (SWord8) (s1354 >> 8);
+  const SWord32 s1427 = table3[s1426];
+  const SWord32 s1428 = s1425 ^ s1427;
+  const SWord8  s1429 = (SWord8) s1369;
+  const SWord32 s1430 = table4[s1429];
+  const SWord32 s1431 = s1428 ^ s1430;
+  const SWord32 s1432 = s13 ^ s1431;
+  const SWord8  s1433 = (SWord8) s1432;
+  const SWord32 s1434 = table4[s1433];
+  const SWord32 s1435 = s1420 ^ s1434;
+  const SWord32 s1436 = s16 ^ s1435;
+  const SWord8  s1437 = (SWord8) (s1436 >> 24);
+  const SWord32 s1438 = table1[s1437];
+  const SWord8  s1439 = (SWord8) (s1402 >> 24);
+  const SWord32 s1440 = table1[s1439];
+  const SWord8  s1441 = (SWord8) (s1417 >> 16);
+  const SWord32 s1442 = table2[s1441];
+  const SWord32 s1443 = s1440 ^ s1442;
+  const SWord8  s1444 = (SWord8) (s1432 >> 8);
+  const SWord32 s1445 = table3[s1444];
+  const SWord32 s1446 = s1443 ^ s1445;
+  const SWord8  s1447 = (SWord8) s1388;
+  const SWord32 s1448 = table4[s1447];
+  const SWord32 s1449 = s1446 ^ s1448;
+  const SWord32 s1450 = s19 ^ s1449;
+  const SWord8  s1451 = (SWord8) (s1450 >> 16);
+  const SWord32 s1452 = table2[s1451];
+  const SWord32 s1453 = s1438 ^ s1452;
+  const SWord8  s1454 = (SWord8) (s1417 >> 24);
+  const SWord32 s1455 = table1[s1454];
+  const SWord8  s1456 = (SWord8) (s1432 >> 16);
+  const SWord32 s1457 = table2[s1456];
+  const SWord32 s1458 = s1455 ^ s1457;
+  const SWord8  s1459 = (SWord8) (s1388 >> 8);
+  const SWord32 s1460 = table3[s1459];
+  const SWord32 s1461 = s1458 ^ s1460;
+  const SWord8  s1462 = (SWord8) s1402;
+  const SWord32 s1463 = table4[s1462];
+  const SWord32 s1464 = s1461 ^ s1463;
+  const SWord32 s1465 = s18 ^ s1464;
+  const SWord8  s1466 = (SWord8) (s1465 >> 8);
+  const SWord32 s1467 = table3[s1466];
+  const SWord32 s1468 = s1453 ^ s1467;
+  const SWord8  s1469 = (SWord8) (s1432 >> 24);
+  const SWord32 s1470 = table1[s1469];
+  const SWord8  s1471 = (SWord8) (s1388 >> 16);
+  const SWord32 s1472 = table2[s1471];
+  const SWord32 s1473 = s1470 ^ s1472;
+  const SWord8  s1474 = (SWord8) (s1402 >> 8);
+  const SWord32 s1475 = table3[s1474];
+  const SWord32 s1476 = s1473 ^ s1475;
+  const SWord8  s1477 = (SWord8) s1417;
+  const SWord32 s1478 = table4[s1477];
+  const SWord32 s1479 = s1476 ^ s1478;
+  const SWord32 s1480 = s17 ^ s1479;
+  const SWord8  s1481 = (SWord8) s1480;
+  const SWord32 s1482 = table4[s1481];
+  const SWord32 s1483 = s1468 ^ s1482;
+  const SWord32 s1484 = s20 ^ s1483;
+  const SWord8  s1485 = (SWord8) (s1484 >> 24);
+  const SWord32 s1486 = table1[s1485];
+  const SWord8  s1487 = (SWord8) (s1450 >> 24);
+  const SWord32 s1488 = table1[s1487];
+  const SWord8  s1489 = (SWord8) (s1465 >> 16);
+  const SWord32 s1490 = table2[s1489];
+  const SWord32 s1491 = s1488 ^ s1490;
+  const SWord8  s1492 = (SWord8) (s1480 >> 8);
+  const SWord32 s1493 = table3[s1492];
+  const SWord32 s1494 = s1491 ^ s1493;
+  const SWord8  s1495 = (SWord8) s1436;
+  const SWord32 s1496 = table4[s1495];
+  const SWord32 s1497 = s1494 ^ s1496;
+  const SWord32 s1498 = s23 ^ s1497;
+  const SWord8  s1499 = (SWord8) (s1498 >> 16);
+  const SWord32 s1500 = table2[s1499];
+  const SWord32 s1501 = s1486 ^ s1500;
+  const SWord8  s1502 = (SWord8) (s1465 >> 24);
+  const SWord32 s1503 = table1[s1502];
+  const SWord8  s1504 = (SWord8) (s1480 >> 16);
+  const SWord32 s1505 = table2[s1504];
+  const SWord32 s1506 = s1503 ^ s1505;
+  const SWord8  s1507 = (SWord8) (s1436 >> 8);
+  const SWord32 s1508 = table3[s1507];
+  const SWord32 s1509 = s1506 ^ s1508;
+  const SWord8  s1510 = (SWord8) s1450;
+  const SWord32 s1511 = table4[s1510];
+  const SWord32 s1512 = s1509 ^ s1511;
+  const SWord32 s1513 = s22 ^ s1512;
+  const SWord8  s1514 = (SWord8) (s1513 >> 8);
+  const SWord32 s1515 = table3[s1514];
+  const SWord32 s1516 = s1501 ^ s1515;
+  const SWord8  s1517 = (SWord8) (s1480 >> 24);
+  const SWord32 s1518 = table1[s1517];
+  const SWord8  s1519 = (SWord8) (s1436 >> 16);
+  const SWord32 s1520 = table2[s1519];
+  const SWord32 s1521 = s1518 ^ s1520;
+  const SWord8  s1522 = (SWord8) (s1450 >> 8);
+  const SWord32 s1523 = table3[s1522];
+  const SWord32 s1524 = s1521 ^ s1523;
+  const SWord8  s1525 = (SWord8) s1465;
+  const SWord32 s1526 = table4[s1525];
+  const SWord32 s1527 = s1524 ^ s1526;
+  const SWord32 s1528 = s21 ^ s1527;
+  const SWord8  s1529 = (SWord8) s1528;
+  const SWord32 s1530 = table4[s1529];
+  const SWord32 s1531 = s1516 ^ s1530;
+  const SWord32 s1532 = s24 ^ s1531;
+  const SWord8  s1533 = (SWord8) (s1532 >> 24);
+  const SWord32 s1534 = table1[s1533];
+  const SWord8  s1535 = (SWord8) (s1498 >> 24);
+  const SWord32 s1536 = table1[s1535];
+  const SWord8  s1537 = (SWord8) (s1513 >> 16);
+  const SWord32 s1538 = table2[s1537];
+  const SWord32 s1539 = s1536 ^ s1538;
+  const SWord8  s1540 = (SWord8) (s1528 >> 8);
+  const SWord32 s1541 = table3[s1540];
+  const SWord32 s1542 = s1539 ^ s1541;
+  const SWord8  s1543 = (SWord8) s1484;
+  const SWord32 s1544 = table4[s1543];
+  const SWord32 s1545 = s1542 ^ s1544;
+  const SWord32 s1546 = s27 ^ s1545;
+  const SWord8  s1547 = (SWord8) (s1546 >> 16);
+  const SWord32 s1548 = table2[s1547];
+  const SWord32 s1549 = s1534 ^ s1548;
+  const SWord8  s1550 = (SWord8) (s1513 >> 24);
+  const SWord32 s1551 = table1[s1550];
+  const SWord8  s1552 = (SWord8) (s1528 >> 16);
+  const SWord32 s1553 = table2[s1552];
+  const SWord32 s1554 = s1551 ^ s1553;
+  const SWord8  s1555 = (SWord8) (s1484 >> 8);
+  const SWord32 s1556 = table3[s1555];
+  const SWord32 s1557 = s1554 ^ s1556;
+  const SWord8  s1558 = (SWord8) s1498;
+  const SWord32 s1559 = table4[s1558];
+  const SWord32 s1560 = s1557 ^ s1559;
+  const SWord32 s1561 = s26 ^ s1560;
+  const SWord8  s1562 = (SWord8) (s1561 >> 8);
+  const SWord32 s1563 = table3[s1562];
+  const SWord32 s1564 = s1549 ^ s1563;
+  const SWord8  s1565 = (SWord8) (s1528 >> 24);
+  const SWord32 s1566 = table1[s1565];
+  const SWord8  s1567 = (SWord8) (s1484 >> 16);
+  const SWord32 s1568 = table2[s1567];
+  const SWord32 s1569 = s1566 ^ s1568;
+  const SWord8  s1570 = (SWord8) (s1498 >> 8);
+  const SWord32 s1571 = table3[s1570];
+  const SWord32 s1572 = s1569 ^ s1571;
+  const SWord8  s1573 = (SWord8) s1513;
+  const SWord32 s1574 = table4[s1573];
+  const SWord32 s1575 = s1572 ^ s1574;
+  const SWord32 s1576 = s25 ^ s1575;
+  const SWord8  s1577 = (SWord8) s1576;
+  const SWord32 s1578 = table4[s1577];
+  const SWord32 s1579 = s1564 ^ s1578;
+  const SWord32 s1580 = s28 ^ s1579;
+  const SWord8  s1581 = (SWord8) (s1580 >> 24);
+  const SWord32 s1582 = table1[s1581];
+  const SWord8  s1583 = (SWord8) (s1546 >> 24);
+  const SWord32 s1584 = table1[s1583];
+  const SWord8  s1585 = (SWord8) (s1561 >> 16);
+  const SWord32 s1586 = table2[s1585];
+  const SWord32 s1587 = s1584 ^ s1586;
+  const SWord8  s1588 = (SWord8) (s1576 >> 8);
+  const SWord32 s1589 = table3[s1588];
+  const SWord32 s1590 = s1587 ^ s1589;
+  const SWord8  s1591 = (SWord8) s1532;
+  const SWord32 s1592 = table4[s1591];
+  const SWord32 s1593 = s1590 ^ s1592;
+  const SWord32 s1594 = s31 ^ s1593;
+  const SWord8  s1595 = (SWord8) (s1594 >> 16);
+  const SWord32 s1596 = table2[s1595];
+  const SWord32 s1597 = s1582 ^ s1596;
+  const SWord8  s1598 = (SWord8) (s1561 >> 24);
+  const SWord32 s1599 = table1[s1598];
+  const SWord8  s1600 = (SWord8) (s1576 >> 16);
+  const SWord32 s1601 = table2[s1600];
+  const SWord32 s1602 = s1599 ^ s1601;
+  const SWord8  s1603 = (SWord8) (s1532 >> 8);
+  const SWord32 s1604 = table3[s1603];
+  const SWord32 s1605 = s1602 ^ s1604;
+  const SWord8  s1606 = (SWord8) s1546;
+  const SWord32 s1607 = table4[s1606];
+  const SWord32 s1608 = s1605 ^ s1607;
+  const SWord32 s1609 = s30 ^ s1608;
+  const SWord8  s1610 = (SWord8) (s1609 >> 8);
+  const SWord32 s1611 = table3[s1610];
+  const SWord32 s1612 = s1597 ^ s1611;
+  const SWord8  s1613 = (SWord8) (s1576 >> 24);
+  const SWord32 s1614 = table1[s1613];
+  const SWord8  s1615 = (SWord8) (s1532 >> 16);
+  const SWord32 s1616 = table2[s1615];
+  const SWord32 s1617 = s1614 ^ s1616;
+  const SWord8  s1618 = (SWord8) (s1546 >> 8);
+  const SWord32 s1619 = table3[s1618];
+  const SWord32 s1620 = s1617 ^ s1619;
+  const SWord8  s1621 = (SWord8) s1561;
+  const SWord32 s1622 = table4[s1621];
+  const SWord32 s1623 = s1620 ^ s1622;
+  const SWord32 s1624 = s29 ^ s1623;
+  const SWord8  s1625 = (SWord8) s1624;
+  const SWord32 s1626 = table4[s1625];
+  const SWord32 s1627 = s1612 ^ s1626;
+  const SWord32 s1628 = s32 ^ s1627;
+  const SWord8  s1629 = (SWord8) (s1628 >> 24);
+  const SWord32 s1630 = table1[s1629];
+  const SWord8  s1631 = (SWord8) (s1594 >> 24);
+  const SWord32 s1632 = table1[s1631];
+  const SWord8  s1633 = (SWord8) (s1609 >> 16);
+  const SWord32 s1634 = table2[s1633];
+  const SWord32 s1635 = s1632 ^ s1634;
+  const SWord8  s1636 = (SWord8) (s1624 >> 8);
+  const SWord32 s1637 = table3[s1636];
+  const SWord32 s1638 = s1635 ^ s1637;
+  const SWord8  s1639 = (SWord8) s1580;
+  const SWord32 s1640 = table4[s1639];
+  const SWord32 s1641 = s1638 ^ s1640;
+  const SWord32 s1642 = s35 ^ s1641;
+  const SWord8  s1643 = (SWord8) (s1642 >> 16);
+  const SWord32 s1644 = table2[s1643];
+  const SWord32 s1645 = s1630 ^ s1644;
+  const SWord8  s1646 = (SWord8) (s1609 >> 24);
+  const SWord32 s1647 = table1[s1646];
+  const SWord8  s1648 = (SWord8) (s1624 >> 16);
+  const SWord32 s1649 = table2[s1648];
+  const SWord32 s1650 = s1647 ^ s1649;
+  const SWord8  s1651 = (SWord8) (s1580 >> 8);
+  const SWord32 s1652 = table3[s1651];
+  const SWord32 s1653 = s1650 ^ s1652;
+  const SWord8  s1654 = (SWord8) s1594;
+  const SWord32 s1655 = table4[s1654];
+  const SWord32 s1656 = s1653 ^ s1655;
+  const SWord32 s1657 = s34 ^ s1656;
+  const SWord8  s1658 = (SWord8) (s1657 >> 8);
+  const SWord32 s1659 = table3[s1658];
+  const SWord32 s1660 = s1645 ^ s1659;
+  const SWord8  s1661 = (SWord8) (s1624 >> 24);
+  const SWord32 s1662 = table1[s1661];
+  const SWord8  s1663 = (SWord8) (s1580 >> 16);
+  const SWord32 s1664 = table2[s1663];
+  const SWord32 s1665 = s1662 ^ s1664;
+  const SWord8  s1666 = (SWord8) (s1594 >> 8);
+  const SWord32 s1667 = table3[s1666];
+  const SWord32 s1668 = s1665 ^ s1667;
+  const SWord8  s1669 = (SWord8) s1609;
+  const SWord32 s1670 = table4[s1669];
+  const SWord32 s1671 = s1668 ^ s1670;
+  const SWord32 s1672 = s33 ^ s1671;
+  const SWord8  s1673 = (SWord8) s1672;
+  const SWord32 s1674 = table4[s1673];
+  const SWord32 s1675 = s1660 ^ s1674;
+  const SWord32 s1676 = s36 ^ s1675;
+  const SWord8  s1677 = (SWord8) (s1676 >> 24);
+  const SWord32 s1678 = table1[s1677];
+  const SWord8  s1679 = (SWord8) (s1642 >> 24);
+  const SWord32 s1680 = table1[s1679];
+  const SWord8  s1681 = (SWord8) (s1657 >> 16);
+  const SWord32 s1682 = table2[s1681];
+  const SWord32 s1683 = s1680 ^ s1682;
+  const SWord8  s1684 = (SWord8) (s1672 >> 8);
+  const SWord32 s1685 = table3[s1684];
+  const SWord32 s1686 = s1683 ^ s1685;
+  const SWord8  s1687 = (SWord8) s1628;
+  const SWord32 s1688 = table4[s1687];
+  const SWord32 s1689 = s1686 ^ s1688;
+  const SWord32 s1690 = s39 ^ s1689;
+  const SWord8  s1691 = (SWord8) (s1690 >> 16);
+  const SWord32 s1692 = table2[s1691];
+  const SWord32 s1693 = s1678 ^ s1692;
+  const SWord8  s1694 = (SWord8) (s1657 >> 24);
+  const SWord32 s1695 = table1[s1694];
+  const SWord8  s1696 = (SWord8) (s1672 >> 16);
+  const SWord32 s1697 = table2[s1696];
+  const SWord32 s1698 = s1695 ^ s1697;
+  const SWord8  s1699 = (SWord8) (s1628 >> 8);
+  const SWord32 s1700 = table3[s1699];
+  const SWord32 s1701 = s1698 ^ s1700;
+  const SWord8  s1702 = (SWord8) s1642;
+  const SWord32 s1703 = table4[s1702];
+  const SWord32 s1704 = s1701 ^ s1703;
+  const SWord32 s1705 = s38 ^ s1704;
+  const SWord8  s1706 = (SWord8) (s1705 >> 8);
+  const SWord32 s1707 = table3[s1706];
+  const SWord32 s1708 = s1693 ^ s1707;
+  const SWord8  s1709 = (SWord8) (s1672 >> 24);
+  const SWord32 s1710 = table1[s1709];
+  const SWord8  s1711 = (SWord8) (s1628 >> 16);
+  const SWord32 s1712 = table2[s1711];
+  const SWord32 s1713 = s1710 ^ s1712;
+  const SWord8  s1714 = (SWord8) (s1642 >> 8);
+  const SWord32 s1715 = table3[s1714];
+  const SWord32 s1716 = s1713 ^ s1715;
+  const SWord8  s1717 = (SWord8) s1657;
+  const SWord32 s1718 = table4[s1717];
+  const SWord32 s1719 = s1716 ^ s1718;
+  const SWord32 s1720 = s37 ^ s1719;
+  const SWord8  s1721 = (SWord8) s1720;
+  const SWord32 s1722 = table4[s1721];
+  const SWord32 s1723 = s1708 ^ s1722;
+  const SWord32 s1724 = s40 ^ s1723;
+  const SWord8  s1725 = (SWord8) (s1724 >> 24);
+  const SWord8  s1726 = table0[s1725];
+  const SWord8  s1727 = (SWord8) (s1690 >> 24);
+  const SWord32 s1728 = table1[s1727];
+  const SWord8  s1729 = (SWord8) (s1705 >> 16);
+  const SWord32 s1730 = table2[s1729];
+  const SWord32 s1731 = s1728 ^ s1730;
+  const SWord8  s1732 = (SWord8) (s1720 >> 8);
+  const SWord32 s1733 = table3[s1732];
+  const SWord32 s1734 = s1731 ^ s1733;
+  const SWord8  s1735 = (SWord8) s1676;
+  const SWord32 s1736 = table4[s1735];
+  const SWord32 s1737 = s1734 ^ s1736;
+  const SWord32 s1738 = s43 ^ s1737;
+  const SWord8  s1739 = (SWord8) (s1738 >> 16);
+  const SWord8  s1740 = table0[s1739];
+  const SWord16 s1741 = (((SWord16) s1726) << 8) | ((SWord16) s1740);
+  const SWord8  s1742 = (SWord8) (s1705 >> 24);
+  const SWord32 s1743 = table1[s1742];
+  const SWord8  s1744 = (SWord8) (s1720 >> 16);
+  const SWord32 s1745 = table2[s1744];
+  const SWord32 s1746 = s1743 ^ s1745;
+  const SWord8  s1747 = (SWord8) (s1676 >> 8);
+  const SWord32 s1748 = table3[s1747];
+  const SWord32 s1749 = s1746 ^ s1748;
+  const SWord8  s1750 = (SWord8) s1690;
+  const SWord32 s1751 = table4[s1750];
+  const SWord32 s1752 = s1749 ^ s1751;
+  const SWord32 s1753 = s42 ^ s1752;
+  const SWord8  s1754 = (SWord8) (s1753 >> 8);
+  const SWord8  s1755 = table0[s1754];
+  const SWord8  s1756 = (SWord8) (s1720 >> 24);
+  const SWord32 s1757 = table1[s1756];
+  const SWord8  s1758 = (SWord8) (s1676 >> 16);
+  const SWord32 s1759 = table2[s1758];
+  const SWord32 s1760 = s1757 ^ s1759;
+  const SWord8  s1761 = (SWord8) (s1690 >> 8);
+  const SWord32 s1762 = table3[s1761];
+  const SWord32 s1763 = s1760 ^ s1762;
+  const SWord8  s1764 = (SWord8) s1705;
+  const SWord32 s1765 = table4[s1764];
+  const SWord32 s1766 = s1763 ^ s1765;
+  const SWord32 s1767 = s41 ^ s1766;
+  const SWord8  s1768 = (SWord8) s1767;
+  const SWord8  s1769 = table0[s1768];
+  const SWord16 s1770 = (((SWord16) s1755) << 8) | ((SWord16) s1769);
+  const SWord32 s1771 = (((SWord32) s1741) << 16) | ((SWord32) s1770);
+  const SWord32 s1772 = s44 ^ s1771;
+  const SWord8  s1773 = (SWord8) (s1767 >> 24);
+  const SWord8  s1774 = table0[s1773];
+  const SWord8  s1775 = (SWord8) (s1724 >> 16);
+  const SWord8  s1776 = table0[s1775];
+  const SWord16 s1777 = (((SWord16) s1774) << 8) | ((SWord16) s1776);
+  const SWord8  s1778 = (SWord8) (s1738 >> 8);
+  const SWord8  s1779 = table0[s1778];
+  const SWord8  s1780 = (SWord8) s1753;
+  const SWord8  s1781 = table0[s1780];
+  const SWord16 s1782 = (((SWord16) s1779) << 8) | ((SWord16) s1781);
+  const SWord32 s1783 = (((SWord32) s1777) << 16) | ((SWord32) s1782);
+  const SWord32 s1784 = s45 ^ s1783;
+  const SWord8  s1785 = (SWord8) (s1753 >> 24);
+  const SWord8  s1786 = table0[s1785];
+  const SWord8  s1787 = (SWord8) (s1767 >> 16);
+  const SWord8  s1788 = table0[s1787];
+  const SWord16 s1789 = (((SWord16) s1786) << 8) | ((SWord16) s1788);
+  const SWord8  s1790 = (SWord8) (s1724 >> 8);
+  const SWord8  s1791 = table0[s1790];
+  const SWord8  s1792 = (SWord8) s1738;
+  const SWord8  s1793 = table0[s1792];
+  const SWord16 s1794 = (((SWord16) s1791) << 8) | ((SWord16) s1793);
+  const SWord32 s1795 = (((SWord32) s1789) << 16) | ((SWord32) s1794);
+  const SWord32 s1796 = s46 ^ s1795;
+  const SWord8  s1797 = (SWord8) (s1738 >> 24);
+  const SWord8  s1798 = table0[s1797];
+  const SWord8  s1799 = (SWord8) (s1753 >> 16);
+  const SWord8  s1800 = table0[s1799];
+  const SWord16 s1801 = (((SWord16) s1798) << 8) | ((SWord16) s1800);
+  const SWord8  s1802 = (SWord8) (s1767 >> 8);
+  const SWord8  s1803 = table0[s1802];
+  const SWord8  s1804 = (SWord8) s1724;
+  const SWord8  s1805 = table0[s1804];
+  const SWord16 s1806 = (((SWord16) s1803) << 8) | ((SWord16) s1805);
+  const SWord32 s1807 = (((SWord32) s1801) << 16) | ((SWord32) s1806);
+  const SWord32 s1808 = s47 ^ s1807;
+
+  pt[0] = s1772;
+  pt[1] = s1784;
+  pt[2] = s1796;
+  pt[3] = s1808;
+}
+== END: "aes128BlockDecrypt.c" ==================
+== BEGIN: "aes128InvKeySchedule.c" ================
+/* File: "aes128InvKeySchedule.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Lib.h"
+
+void aes128InvKeySchedule(const SWord32 *key, SWord32 *decKS)
+{
+  const SWord32 s0 = key[0];
+  const SWord32 s1 = key[1];
+  const SWord32 s2 = key[2];
+  const SWord32 s3 = key[3];
+  static const SWord8 table0[] = {
+       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
+      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
+      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
+      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
+       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
+      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
+       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
+       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
+       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
+      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
+       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
+      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
+      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
+      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
+       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
+       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
+      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
+      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
+      104,  65, 153,  45,  15, 176,  84, 187,  22
+  };
+  const SWord32 s260 = s2 ^ s3;
+  const SWord32 s261 = (s260 << 8) | (s260 >> 24);
+  const SWord8  s262 = (SWord8) (s261 >> 24);
+  const SWord8  s263 = table0[s262];
+  const SWord8  s264 = 54 ^ s263;
+  const SWord8  s265 = (SWord8) (s261 >> 16);
+  const SWord8  s266 = table0[s265];
+  const SWord16 s267 = (((SWord16) s264) << 8) | ((SWord16) s266);
+  const SWord8  s268 = (SWord8) (s261 >> 8);
+  const SWord8  s269 = table0[s268];
+  const SWord8  s270 = (SWord8) s261;
+  const SWord8  s271 = table0[s270];
+  const SWord16 s272 = (((SWord16) s269) << 8) | ((SWord16) s271);
+  const SWord32 s273 = (((SWord32) s267) << 16) | ((SWord32) s272);
+  const SWord32 s274 = s0 ^ s273;
+  const SWord32 s275 = s0 ^ s1;
+  const SWord32 s276 = s1 ^ s2;
+  const SWord32 s277 = s260 ^ s276;
+  const SWord32 s278 = (s277 << 8) | (s277 >> 24);
+  const SWord8  s279 = (SWord8) (s278 >> 24);
+  const SWord8  s280 = table0[s279];
+  const SWord8  s281 = 27 ^ s280;
+  const SWord8  s282 = (SWord8) (s278 >> 16);
+  const SWord8  s283 = table0[s282];
+  const SWord16 s284 = (((SWord16) s281) << 8) | ((SWord16) s283);
+  const SWord8  s285 = (SWord8) (s278 >> 8);
+  const SWord8  s286 = table0[s285];
+  const SWord8  s287 = (SWord8) s278;
+  const SWord8  s288 = table0[s287];
+  const SWord16 s289 = (((SWord16) s286) << 8) | ((SWord16) s288);
+  const SWord32 s290 = (((SWord32) s284) << 16) | ((SWord32) s289);
+  const SWord32 s291 = s274 ^ s290;
+  const SWord32 s292 = s274 ^ s275;
+  const SWord32 s293 = s275 ^ s276;
+  const SWord32 s294 = s277 ^ s293;
+  const SWord32 s295 = (s294 << 8) | (s294 >> 24);
+  const SWord8  s296 = (SWord8) (s295 >> 24);
+  const SWord8  s297 = table0[s296];
+  const SWord8  s298 = 128 ^ s297;
+  const SWord8  s299 = (SWord8) (s295 >> 16);
+  const SWord8  s300 = table0[s299];
+  const SWord16 s301 = (((SWord16) s298) << 8) | ((SWord16) s300);
+  const SWord8  s302 = (SWord8) (s295 >> 8);
+  const SWord8  s303 = table0[s302];
+  const SWord8  s304 = (SWord8) s295;
+  const SWord8  s305 = table0[s304];
+  const SWord16 s306 = (((SWord16) s303) << 8) | ((SWord16) s305);
+  const SWord32 s307 = (((SWord32) s301) << 16) | ((SWord32) s306);
+  const SWord32 s308 = s291 ^ s307;
+  const SWord32 s309 = s291 ^ s292;
+  const SWord32 s310 = s292 ^ s293;
+  const SWord32 s311 = s294 ^ s310;
+  const SWord32 s312 = (s311 << 8) | (s311 >> 24);
+  const SWord8  s313 = (SWord8) (s312 >> 24);
+  const SWord8  s314 = table0[s313];
+  const SWord8  s315 = 64 ^ s314;
+  const SWord8  s316 = (SWord8) (s312 >> 16);
+  const SWord8  s317 = table0[s316];
+  const SWord16 s318 = (((SWord16) s315) << 8) | ((SWord16) s317);
+  const SWord8  s319 = (SWord8) (s312 >> 8);
+  const SWord8  s320 = table0[s319];
+  const SWord8  s321 = (SWord8) s312;
+  const SWord8  s322 = table0[s321];
+  const SWord16 s323 = (((SWord16) s320) << 8) | ((SWord16) s322);
+  const SWord32 s324 = (((SWord32) s318) << 16) | ((SWord32) s323);
+  const SWord32 s325 = s308 ^ s324;
+  const SWord32 s326 = s308 ^ s309;
+  const SWord32 s327 = s309 ^ s310;
+  const SWord32 s328 = s311 ^ s327;
+  const SWord32 s329 = (s328 << 8) | (s328 >> 24);
+  const SWord8  s330 = (SWord8) (s329 >> 24);
+  const SWord8  s331 = table0[s330];
+  const SWord8  s332 = 32 ^ s331;
+  const SWord8  s333 = (SWord8) (s329 >> 16);
+  const SWord8  s334 = table0[s333];
+  const SWord16 s335 = (((SWord16) s332) << 8) | ((SWord16) s334);
+  const SWord8  s336 = (SWord8) (s329 >> 8);
+  const SWord8  s337 = table0[s336];
+  const SWord8  s338 = (SWord8) s329;
+  const SWord8  s339 = table0[s338];
+  const SWord16 s340 = (((SWord16) s337) << 8) | ((SWord16) s339);
+  const SWord32 s341 = (((SWord32) s335) << 16) | ((SWord32) s340);
+  const SWord32 s342 = s325 ^ s341;
+  const SWord32 s343 = s325 ^ s326;
+  const SWord32 s344 = s326 ^ s327;
+  const SWord32 s345 = s328 ^ s344;
+  const SWord32 s346 = (s345 << 8) | (s345 >> 24);
+  const SWord8  s347 = (SWord8) (s346 >> 24);
+  const SWord8  s348 = table0[s347];
+  const SWord8  s349 = 16 ^ s348;
+  const SWord8  s350 = (SWord8) (s346 >> 16);
+  const SWord8  s351 = table0[s350];
+  const SWord16 s352 = (((SWord16) s349) << 8) | ((SWord16) s351);
+  const SWord8  s353 = (SWord8) (s346 >> 8);
+  const SWord8  s354 = table0[s353];
+  const SWord8  s355 = (SWord8) s346;
+  const SWord8  s356 = table0[s355];
+  const SWord16 s357 = (((SWord16) s354) << 8) | ((SWord16) s356);
+  const SWord32 s358 = (((SWord32) s352) << 16) | ((SWord32) s357);
+  const SWord32 s359 = s342 ^ s358;
+  const SWord32 s360 = s342 ^ s343;
+  const SWord32 s361 = s343 ^ s344;
+  const SWord32 s362 = s345 ^ s361;
+  const SWord32 s363 = (s362 << 8) | (s362 >> 24);
+  const SWord8  s364 = (SWord8) (s363 >> 24);
+  const SWord8  s365 = table0[s364];
+  const SWord8  s366 = 8 ^ s365;
+  const SWord8  s367 = (SWord8) (s363 >> 16);
+  const SWord8  s368 = table0[s367];
+  const SWord16 s369 = (((SWord16) s366) << 8) | ((SWord16) s368);
+  const SWord8  s370 = (SWord8) (s363 >> 8);
+  const SWord8  s371 = table0[s370];
+  const SWord8  s372 = (SWord8) s363;
+  const SWord8  s373 = table0[s372];
+  const SWord16 s374 = (((SWord16) s371) << 8) | ((SWord16) s373);
+  const SWord32 s375 = (((SWord32) s369) << 16) | ((SWord32) s374);
+  const SWord32 s376 = s359 ^ s375;
+  const SWord32 s377 = s359 ^ s360;
+  const SWord32 s378 = s360 ^ s361;
+  const SWord32 s379 = s362 ^ s378;
+  const SWord32 s380 = (s379 << 8) | (s379 >> 24);
+  const SWord8  s381 = (SWord8) (s380 >> 24);
+  const SWord8  s382 = table0[s381];
+  const SWord8  s383 = 4 ^ s382;
+  const SWord8  s384 = (SWord8) (s380 >> 16);
+  const SWord8  s385 = table0[s384];
+  const SWord16 s386 = (((SWord16) s383) << 8) | ((SWord16) s385);
+  const SWord8  s387 = (SWord8) (s380 >> 8);
+  const SWord8  s388 = table0[s387];
+  const SWord8  s389 = (SWord8) s380;
+  const SWord8  s390 = table0[s389];
+  const SWord16 s391 = (((SWord16) s388) << 8) | ((SWord16) s390);
+  const SWord32 s392 = (((SWord32) s386) << 16) | ((SWord32) s391);
+  const SWord32 s393 = s376 ^ s392;
+  const SWord32 s394 = s376 ^ s377;
+  const SWord32 s395 = s377 ^ s378;
+  const SWord32 s396 = s379 ^ s395;
+  const SWord32 s397 = (s396 << 8) | (s396 >> 24);
+  const SWord8  s398 = (SWord8) (s397 >> 24);
+  const SWord8  s399 = table0[s398];
+  const SWord8  s400 = 2 ^ s399;
+  const SWord8  s401 = (SWord8) (s397 >> 16);
+  const SWord8  s402 = table0[s401];
+  const SWord16 s403 = (((SWord16) s400) << 8) | ((SWord16) s402);
+  const SWord8  s404 = (SWord8) (s397 >> 8);
+  const SWord8  s405 = table0[s404];
+  const SWord8  s406 = (SWord8) s397;
+  const SWord8  s407 = table0[s406];
+  const SWord16 s408 = (((SWord16) s405) << 8) | ((SWord16) s407);
+  const SWord32 s409 = (((SWord32) s403) << 16) | ((SWord32) s408);
+  const SWord32 s410 = s393 ^ s409;
+  const SWord32 s411 = s393 ^ s394;
+  const SWord32 s412 = s394 ^ s395;
+  const SWord32 s413 = s396 ^ s412;
+  const SWord32 s414 = (s413 << 8) | (s413 >> 24);
+  const SWord8  s415 = (SWord8) (s414 >> 24);
+  const SWord8  s416 = table0[s415];
+  const SWord8  s417 = 1 ^ s416;
+  const SWord8  s418 = (SWord8) (s414 >> 16);
+  const SWord8  s419 = table0[s418];
+  const SWord16 s420 = (((SWord16) s417) << 8) | ((SWord16) s419);
+  const SWord8  s421 = (SWord8) (s414 >> 8);
+  const SWord8  s422 = table0[s421];
+  const SWord8  s423 = (SWord8) s414;
+  const SWord8  s424 = table0[s423];
+  const SWord16 s425 = (((SWord16) s422) << 8) | ((SWord16) s424);
+  const SWord32 s426 = (((SWord32) s420) << 16) | ((SWord32) s425);
+  const SWord32 s427 = s410 ^ s426;
+  const SWord32 s428 = s410 ^ s411;
+  const SWord32 s429 = s411 ^ s412;
+
+  decKS[0] = s0;
+  decKS[1] = s1;
+  decKS[2] = s2;
+  decKS[3] = s3;
+  decKS[4] = s274;
+  decKS[5] = s275;
+  decKS[6] = s276;
+  decKS[7] = s260;
+  decKS[8] = s291;
+  decKS[9] = s292;
+  decKS[10] = s293;
+  decKS[11] = s277;
+  decKS[12] = s308;
+  decKS[13] = s309;
+  decKS[14] = s310;
+  decKS[15] = s294;
+  decKS[16] = s325;
+  decKS[17] = s326;
+  decKS[18] = s327;
+  decKS[19] = s311;
+  decKS[20] = s342;
+  decKS[21] = s343;
+  decKS[22] = s344;
+  decKS[23] = s328;
+  decKS[24] = s359;
+  decKS[25] = s360;
+  decKS[26] = s361;
+  decKS[27] = s345;
+  decKS[28] = s376;
+  decKS[29] = s377;
+  decKS[30] = s378;
+  decKS[31] = s362;
+  decKS[32] = s393;
+  decKS[33] = s394;
+  decKS[34] = s395;
+  decKS[35] = s379;
+  decKS[36] = s410;
+  decKS[37] = s411;
+  decKS[38] = s412;
+  decKS[39] = s396;
+  decKS[40] = s427;
+  decKS[41] = s428;
+  decKS[42] = s429;
+  decKS[43] = s413;
+}
+== END: "aes128InvKeySchedule.c" ==================
+== BEGIN: "aes128OTFDecrypt.c" ================
+/* File: "aes128OTFDecrypt.c". Automatically generated by SBV. Do not edit! */
+
+#include "aes128Lib.h"
+
+void aes128OTFDecrypt(const SWord32 *ct, const SWord32 *xkey,
+                      SWord32 *pt)
+{
+  const SWord32 s0 = ct[0];
+  const SWord32 s1 = ct[1];
+  const SWord32 s2 = ct[2];
+  const SWord32 s3 = ct[3];
+  const SWord32 s4 = xkey[0];
+  const SWord32 s5 = xkey[1];
+  const SWord32 s6 = xkey[2];
+  const SWord32 s7 = xkey[3];
+  const SWord32 s8 = xkey[4];
+  const SWord32 s9 = xkey[5];
+  const SWord32 s10 = xkey[6];
+  const SWord32 s11 = xkey[7];
+  const SWord32 s12 = xkey[8];
+  const SWord32 s13 = xkey[9];
+  const SWord32 s14 = xkey[10];
+  const SWord32 s15 = xkey[11];
+  const SWord32 s16 = xkey[12];
+  const SWord32 s17 = xkey[13];
+  const SWord32 s18 = xkey[14];
+  const SWord32 s19 = xkey[15];
+  const SWord32 s20 = xkey[16];
+  const SWord32 s21 = xkey[17];
+  const SWord32 s22 = xkey[18];
+  const SWord32 s23 = xkey[19];
+  const SWord32 s24 = xkey[20];
+  const SWord32 s25 = xkey[21];
+  const SWord32 s26 = xkey[22];
+  const SWord32 s27 = xkey[23];
+  const SWord32 s28 = xkey[24];
+  const SWord32 s29 = xkey[25];
+  const SWord32 s30 = xkey[26];
+  const SWord32 s31 = xkey[27];
+  const SWord32 s32 = xkey[28];
+  const SWord32 s33 = xkey[29];
+  const SWord32 s34 = xkey[30];
+  const SWord32 s35 = xkey[31];
+  const SWord32 s36 = xkey[32];
+  const SWord32 s37 = xkey[33];
+  const SWord32 s38 = xkey[34];
+  const SWord32 s39 = xkey[35];
+  const SWord32 s40 = xkey[36];
+  const SWord32 s41 = xkey[37];
+  const SWord32 s42 = xkey[38];
+  const SWord32 s43 = xkey[39];
+  const SWord32 s44 = xkey[40];
+  const SWord32 s45 = xkey[41];
+  const SWord32 s46 = xkey[42];
+  const SWord32 s47 = xkey[43];
+  static const SWord8 table0[] = {
+       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129,
+      243, 215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,
+       67,  68, 196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,
+       61, 238,  76, 149,  11,  66, 250, 195,  78,   8,  46, 161, 102,
+       40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 114,
+      248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101,
+      182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,
+       87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10,
+      247, 228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,
+       63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,  58, 145,
+       17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230,
+      115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,
+       28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 111,
+      183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
+      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
+       51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
+       96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147,
+      201, 156, 239, 160, 224,  59,  77, 174,  42, 245, 176, 200, 235,
+      187,  60, 131,  83, 153,  97,  23,  43,   4, 126, 186, 119, 214,
+       38, 225, 105,  20,  99,  85,  33,  12, 125
+  };
+  static const SWord32 table1[] = {
+      0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL,
+      0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL,
+      0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL,
+      0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL,
+      0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL,
+      0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL,
+      0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL,
+      0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL,
+      0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL,
+      0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL,
+      0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL,
+      0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL,
+      0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL,
+      0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL,
+      0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL,
+      0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL,
+      0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL,
+      0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL,
+      0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL,
+      0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL,
+      0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL,
+      0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL,
+      0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL,
+      0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL,
+      0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL,
+      0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL,
+      0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL,
+      0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL,
+      0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL,
+      0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL,
+      0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL,
+      0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL,
+      0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL,
+      0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL,
+      0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL,
+      0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL,
+      0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL,
+      0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL,
+      0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL,
+      0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL,
+      0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL,
+      0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL,
+      0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL,
+      0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL,
+      0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL,
+      0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL,
+      0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL,
+      0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL,
+      0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL,
+      0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL,
+      0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL,
+      0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL,
+      0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL,
+      0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL,
+      0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL,
+      0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL,
+      0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL,
+      0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL,
+      0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL,
+      0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL,
+      0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL,
+      0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL,
+      0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL,
+      0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
+  };
+  static const SWord32 table2[] = {
+      0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL,
+      0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL,
+      0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL,
+      0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL,
+      0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL,
+      0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL,
+      0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL,
+      0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL,
+      0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL,
+      0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL,
+      0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL,
+      0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL,
+      0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL,
+      0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL,
+      0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL,
+      0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL,
+      0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL,
+      0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL,
+      0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL,
+      0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL,
+      0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL,
+      0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL,
+      0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL,
+      0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL,
+      0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL,
+      0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL,
+      0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL,
+      0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL,
+      0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL,
+      0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL,
+      0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL,
+      0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL,
+      0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL,
+      0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL,
+      0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL,
+      0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL,
+      0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL,
+      0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL,
+      0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL,
+      0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL,
+      0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL,
+      0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL,
+      0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL,
+      0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL,
+      0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL,
+      0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL,
+      0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL,
+      0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL,
+      0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL,
+      0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL,
+      0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL,
+      0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL,
+      0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL,
+      0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL,
+      0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL,
+      0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL,
+      0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL,
+      0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL,
+      0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL,
+      0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL,
+      0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL,
+      0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL,
+      0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL,
+      0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
+  };
+  static const SWord32 table3[] = {
+      0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL,
+      0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL,
+      0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL,
+      0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL,
+      0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL,
+      0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL,
+      0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL,
+      0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL,
+      0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL,
+      0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL,
+      0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL,
+      0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL,
+      0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL,
+      0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL,
+      0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL,
+      0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL,
+      0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL,
+      0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL,
+      0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL,
+      0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL,
+      0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL,
+      0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL,
+      0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL,
+      0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL,
+      0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL,
+      0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL,
+      0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL,
+      0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL,
+      0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL,
+      0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL,
+      0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL,
+      0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL,
+      0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL,
+      0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL,
+      0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL,
+      0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL,
+      0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL,
+      0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL,
+      0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL,
+      0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL,
+      0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL,
+      0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL,
+      0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL,
+      0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL,
+      0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL,
+      0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL,
+      0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL,
+      0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL,
+      0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL,
+      0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL,
+      0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL,
+      0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL,
+      0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL,
+      0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL,
+      0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL,
+      0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL,
+      0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL,
+      0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL,
+      0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL,
+      0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL,
+      0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL,
+      0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL,
+      0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL,
+      0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
+  };
+  static const SWord32 table4[] = {
+      0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL,
+      0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL,
+      0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL,
+      0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL,
+      0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL,
+      0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL,
+      0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL,
+      0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL,
+      0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL,
+      0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL,
+      0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL,
+      0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL,
+      0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL,
+      0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL,
+      0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL,
+      0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL,
+      0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL,
+      0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL,
+      0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL,
+      0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL,
+      0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL,
+      0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL,
+      0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL,
+      0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL,
+      0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL,
+      0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL,
+      0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL,
+      0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL,
+      0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL,
+      0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL,
+      0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL,
+      0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL,
+      0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL,
+      0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL,
+      0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL,
+      0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL,
+      0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL,
+      0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL,
+      0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL,
+      0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL,
+      0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL,
+      0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL,
+      0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL,
+      0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL,
+      0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL,
+      0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL,
+      0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL,
+      0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL,
+      0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL,
+      0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL,
+      0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL,
+      0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL,
+      0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL,
+      0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL,
+      0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL,
+      0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL,
+      0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL,
+      0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL,
+      0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL,
+      0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL,
+      0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL,
+      0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL,
+      0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL,
+      0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
+  };
+  const SWord32 s560 = s0 ^ s4;
+  const SWord8  s561 = (SWord8) (s560 >> 24);
+  const SWord8  s562 = table0[s561];
+  const SWord8  s563 = (SWord8) (s8 >> 24);
+  const SWord8  s564 = s562 ^ s563;
+  const SWord32 s565 = table1[s564];
+  const SWord32 s821 = s3 ^ s7;
+  const SWord8  s822 = (SWord8) (s821 >> 16);
+  const SWord8  s823 = table0[s822];
+  const SWord8  s824 = (SWord8) (s8 >> 16);
+  const SWord8  s825 = s823 ^ s824;
+  const SWord32 s826 = table2[s825];
+  const SWord32 s827 = s565 ^ s826;
+  const SWord32 s1083 = s2 ^ s6;
+  const SWord8  s1084 = (SWord8) (s1083 >> 8);
+  const SWord8  s1085 = table0[s1084];
+  const SWord8  s1086 = (SWord8) (s8 >> 8);
+  const SWord8  s1087 = s1085 ^ s1086;
+  const SWord32 s1088 = table3[s1087];
+  const SWord32 s1089 = s827 ^ s1088;
+  const SWord32 s1345 = s1 ^ s5;
+  const SWord8  s1346 = (SWord8) s1345;
+  const SWord8  s1347 = table0[s1346];
+  const SWord8  s1348 = (SWord8) s8;
+  const SWord8  s1349 = s1347 ^ s1348;
+  const SWord32 s1350 = table4[s1349];
+  const SWord32 s1351 = s1089 ^ s1350;
+  const SWord8  s1352 = (SWord8) (s1351 >> 24);
+  const SWord8  s1353 = table0[s1352];
+  const SWord8  s1354 = (SWord8) (s12 >> 24);
+  const SWord8  s1355 = s1353 ^ s1354;
+  const SWord32 s1356 = table1[s1355];
+  const SWord8  s1357 = (SWord8) (s821 >> 24);
+  const SWord8  s1358 = table0[s1357];
+  const SWord8  s1359 = (SWord8) (s11 >> 24);
+  const SWord8  s1360 = s1358 ^ s1359;
+  const SWord32 s1361 = table1[s1360];
+  const SWord8  s1362 = (SWord8) (s1083 >> 16);
+  const SWord8  s1363 = table0[s1362];
+  const SWord8  s1364 = (SWord8) (s11 >> 16);
+  const SWord8  s1365 = s1363 ^ s1364;
+  const SWord32 s1366 = table2[s1365];
+  const SWord32 s1367 = s1361 ^ s1366;
+  const SWord8  s1368 = (SWord8) (s1345 >> 8);
+  const SWord8  s1369 = table0[s1368];
+  const SWord8  s1370 = (SWord8) (s11 >> 8);
+  const SWord8  s1371 = s1369 ^ s1370;
+  const SWord32 s1372 = table3[s1371];
+  const SWord32 s1373 = s1367 ^ s1372;
+  const SWord8  s1374 = (SWord8) s560;
+  const SWord8  s1375 = table0[s1374];
+  const SWord8  s1376 = (SWord8) s11;
+  const SWord8  s1377 = s1375 ^ s1376;
+  const SWord32 s1378 = table4[s1377];
+  const SWord32 s1379 = s1373 ^ s1378;
+  const SWord8  s1380 = (SWord8) (s1379 >> 16);
+  const SWord8  s1381 = table0[s1380];
+  const SWord8  s1382 = (SWord8) (s12 >> 16);
+  const SWord8  s1383 = s1381 ^ s1382;
+  const SWord32 s1384 = table2[s1383];
+  const SWord32 s1385 = s1356 ^ s1384;
+  const SWord8  s1386 = (SWord8) (s1083 >> 24);
+  const SWord8  s1387 = table0[s1386];
+  const SWord8  s1388 = (SWord8) (s10 >> 24);
+  const SWord8  s1389 = s1387 ^ s1388;
+  const SWord32 s1390 = table1[s1389];
+  const SWord8  s1391 = (SWord8) (s1345 >> 16);
+  const SWord8  s1392 = table0[s1391];
+  const SWord8  s1393 = (SWord8) (s10 >> 16);
+  const SWord8  s1394 = s1392 ^ s1393;
+  const SWord32 s1395 = table2[s1394];
+  const SWord32 s1396 = s1390 ^ s1395;
+  const SWord8  s1397 = (SWord8) (s560 >> 8);
+  const SWord8  s1398 = table0[s1397];
+  const SWord8  s1399 = (SWord8) (s10 >> 8);
+  const SWord8  s1400 = s1398 ^ s1399;
+  const SWord32 s1401 = table3[s1400];
+  const SWord32 s1402 = s1396 ^ s1401;
+  const SWord8  s1403 = (SWord8) s821;
+  const SWord8  s1404 = table0[s1403];
+  const SWord8  s1405 = (SWord8) s10;
+  const SWord8  s1406 = s1404 ^ s1405;
+  const SWord32 s1407 = table4[s1406];
+  const SWord32 s1408 = s1402 ^ s1407;
+  const SWord8  s1409 = (SWord8) (s1408 >> 8);
+  const SWord8  s1410 = table0[s1409];
+  const SWord8  s1411 = (SWord8) (s12 >> 8);
+  const SWord8  s1412 = s1410 ^ s1411;
+  const SWord32 s1413 = table3[s1412];
+  const SWord32 s1414 = s1385 ^ s1413;
+  const SWord8  s1415 = (SWord8) (s1345 >> 24);
+  const SWord8  s1416 = table0[s1415];
+  const SWord8  s1417 = (SWord8) (s9 >> 24);
+  const SWord8  s1418 = s1416 ^ s1417;
+  const SWord32 s1419 = table1[s1418];
+  const SWord8  s1420 = (SWord8) (s560 >> 16);
+  const SWord8  s1421 = table0[s1420];
+  const SWord8  s1422 = (SWord8) (s9 >> 16);
+  const SWord8  s1423 = s1421 ^ s1422;
+  const SWord32 s1424 = table2[s1423];
+  const SWord32 s1425 = s1419 ^ s1424;
+  const SWord8  s1426 = (SWord8) (s821 >> 8);
+  const SWord8  s1427 = table0[s1426];
+  const SWord8  s1428 = (SWord8) (s9 >> 8);
+  const SWord8  s1429 = s1427 ^ s1428;
+  const SWord32 s1430 = table3[s1429];
+  const SWord32 s1431 = s1425 ^ s1430;
+  const SWord8  s1432 = (SWord8) s1083;
+  const SWord8  s1433 = table0[s1432];
+  const SWord8  s1434 = (SWord8) s9;
+  const SWord8  s1435 = s1433 ^ s1434;
+  const SWord32 s1436 = table4[s1435];
+  const SWord32 s1437 = s1431 ^ s1436;
+  const SWord8  s1438 = (SWord8) s1437;
+  const SWord8  s1439 = table0[s1438];
+  const SWord8  s1440 = (SWord8) s12;
+  const SWord8  s1441 = s1439 ^ s1440;
+  const SWord32 s1442 = table4[s1441];
+  const SWord32 s1443 = s1414 ^ s1442;
+  const SWord8  s1444 = (SWord8) (s1443 >> 24);
+  const SWord8  s1445 = table0[s1444];
+  const SWord8  s1446 = (SWord8) (s16 >> 24);
+  const SWord8  s1447 = s1445 ^ s1446;
+  const SWord32 s1448 = table1[s1447];
+  const SWord8  s1449 = (SWord8) (s1379 >> 24);
+  const SWord8  s1450 = table0[s1449];
+  const SWord8  s1451 = (SWord8) (s15 >> 24);
+  const SWord8  s1452 = s1450 ^ s1451;
+  const SWord32 s1453 = table1[s1452];
+  const SWord8  s1454 = (SWord8) (s1408 >> 16);
+  const SWord8  s1455 = table0[s1454];
+  const SWord8  s1456 = (SWord8) (s15 >> 16);
+  const SWord8  s1457 = s1455 ^ s1456;
+  const SWord32 s1458 = table2[s1457];
+  const SWord32 s1459 = s1453 ^ s1458;
+  const SWord8  s1460 = (SWord8) (s1437 >> 8);
+  const SWord8  s1461 = table0[s1460];
+  const SWord8  s1462 = (SWord8) (s15 >> 8);
+  const SWord8  s1463 = s1461 ^ s1462;
+  const SWord32 s1464 = table3[s1463];
+  const SWord32 s1465 = s1459 ^ s1464;
+  const SWord8  s1466 = (SWord8) s1351;
+  const SWord8  s1467 = table0[s1466];
+  const SWord8  s1468 = (SWord8) s15;
+  const SWord8  s1469 = s1467 ^ s1468;
+  const SWord32 s1470 = table4[s1469];
+  const SWord32 s1471 = s1465 ^ s1470;
+  const SWord8  s1472 = (SWord8) (s1471 >> 16);
+  const SWord8  s1473 = table0[s1472];
+  const SWord8  s1474 = (SWord8) (s16 >> 16);
+  const SWord8  s1475 = s1473 ^ s1474;
+  const SWord32 s1476 = table2[s1475];
+  const SWord32 s1477 = s1448 ^ s1476;
+  const SWord8  s1478 = (SWord8) (s1408 >> 24);
+  const SWord8  s1479 = table0[s1478];
+  const SWord8  s1480 = (SWord8) (s14 >> 24);
+  const SWord8  s1481 = s1479 ^ s1480;
+  const SWord32 s1482 = table1[s1481];
+  const SWord8  s1483 = (SWord8) (s1437 >> 16);
+  const SWord8  s1484 = table0[s1483];
+  const SWord8  s1485 = (SWord8) (s14 >> 16);
+  const SWord8  s1486 = s1484 ^ s1485;
+  const SWord32 s1487 = table2[s1486];
+  const SWord32 s1488 = s1482 ^ s1487;
+  const SWord8  s1489 = (SWord8) (s1351 >> 8);
+  const SWord8  s1490 = table0[s1489];
+  const SWord8  s1491 = (SWord8) (s14 >> 8);
+  const SWord8  s1492 = s1490 ^ s1491;
+  const SWord32 s1493 = table3[s1492];
+  const SWord32 s1494 = s1488 ^ s1493;
+  const SWord8  s1495 = (SWord8) s1379;
+  const SWord8  s1496 = table0[s1495];
+  const SWord8  s1497 = (SWord8) s14;
+  const SWord8  s1498 = s1496 ^ s1497;
+  const SWord32 s1499 = table4[s1498];
+  const SWord32 s1500 = s1494 ^ s1499;
+  const SWord8  s1501 = (SWord8) (s1500 >> 8);
+  const SWord8  s1502 = table0[s1501];
+  const SWord8  s1503 = (SWord8) (s16 >> 8);
+  const SWord8  s1504 = s1502 ^ s1503;
+  const SWord32 s1505 = table3[s1504];
+  const SWord32 s1506 = s1477 ^ s1505;
+  const SWord8  s1507 = (SWord8) (s1437 >> 24);
+  const SWord8  s1508 = table0[s1507];
+  const SWord8  s1509 = (SWord8) (s13 >> 24);
+  const SWord8  s1510 = s1508 ^ s1509;
+  const SWord32 s1511 = table1[s1510];
+  const SWord8  s1512 = (SWord8) (s1351 >> 16);
+  const SWord8  s1513 = table0[s1512];
+  const SWord8  s1514 = (SWord8) (s13 >> 16);
+  const SWord8  s1515 = s1513 ^ s1514;
+  const SWord32 s1516 = table2[s1515];
+  const SWord32 s1517 = s1511 ^ s1516;
+  const SWord8  s1518 = (SWord8) (s1379 >> 8);
+  const SWord8  s1519 = table0[s1518];
+  const SWord8  s1520 = (SWord8) (s13 >> 8);
+  const SWord8  s1521 = s1519 ^ s1520;
+  const SWord32 s1522 = table3[s1521];
+  const SWord32 s1523 = s1517 ^ s1522;
+  const SWord8  s1524 = (SWord8) s1408;
+  const SWord8  s1525 = table0[s1524];
+  const SWord8  s1526 = (SWord8) s13;
+  const SWord8  s1527 = s1525 ^ s1526;
+  const SWord32 s1528 = table4[s1527];
+  const SWord32 s1529 = s1523 ^ s1528;
+  const SWord8  s1530 = (SWord8) s1529;
+  const SWord8  s1531 = table0[s1530];
+  const SWord8  s1532 = (SWord8) s16;
+  const SWord8  s1533 = s1531 ^ s1532;
+  const SWord32 s1534 = table4[s1533];
+  const SWord32 s1535 = s1506 ^ s1534;
+  const SWord8  s1536 = (SWord8) (s1535 >> 24);
+  const SWord8  s1537 = table0[s1536];
+  const SWord8  s1538 = (SWord8) (s20 >> 24);
+  const SWord8  s1539 = s1537 ^ s1538;
+  const SWord32 s1540 = table1[s1539];
+  const SWord8  s1541 = (SWord8) (s1471 >> 24);
+  const SWord8  s1542 = table0[s1541];
+  const SWord8  s1543 = (SWord8) (s19 >> 24);
+  const SWord8  s1544 = s1542 ^ s1543;
+  const SWord32 s1545 = table1[s1544];
+  const SWord8  s1546 = (SWord8) (s1500 >> 16);
+  const SWord8  s1547 = table0[s1546];
+  const SWord8  s1548 = (SWord8) (s19 >> 16);
+  const SWord8  s1549 = s1547 ^ s1548;
+  const SWord32 s1550 = table2[s1549];
+  const SWord32 s1551 = s1545 ^ s1550;
+  const SWord8  s1552 = (SWord8) (s1529 >> 8);
+  const SWord8  s1553 = table0[s1552];
+  const SWord8  s1554 = (SWord8) (s19 >> 8);
+  const SWord8  s1555 = s1553 ^ s1554;
+  const SWord32 s1556 = table3[s1555];
+  const SWord32 s1557 = s1551 ^ s1556;
+  const SWord8  s1558 = (SWord8) s1443;
+  const SWord8  s1559 = table0[s1558];
+  const SWord8  s1560 = (SWord8) s19;
+  const SWord8  s1561 = s1559 ^ s1560;
+  const SWord32 s1562 = table4[s1561];
+  const SWord32 s1563 = s1557 ^ s1562;
+  const SWord8  s1564 = (SWord8) (s1563 >> 16);
+  const SWord8  s1565 = table0[s1564];
+  const SWord8  s1566 = (SWord8) (s20 >> 16);
+  const SWord8  s1567 = s1565 ^ s1566;
+  const SWord32 s1568 = table2[s1567];
+  const SWord32 s1569 = s1540 ^ s1568;
+  const SWord8  s1570 = (SWord8) (s1500 >> 24);
+  const SWord8  s1571 = table0[s1570];
+  const SWord8  s1572 = (SWord8) (s18 >> 24);
+  const SWord8  s1573 = s1571 ^ s1572;
+  const SWord32 s1574 = table1[s1573];
+  const SWord8  s1575 = (SWord8) (s1529 >> 16);
+  const SWord8  s1576 = table0[s1575];
+  const SWord8  s1577 = (SWord8) (s18 >> 16);
+  const SWord8  s1578 = s1576 ^ s1577;
+  const SWord32 s1579 = table2[s1578];
+  const SWord32 s1580 = s1574 ^ s1579;
+  const SWord8  s1581 = (SWord8) (s1443 >> 8);
+  const SWord8  s1582 = table0[s1581];
+  const SWord8  s1583 = (SWord8) (s18 >> 8);
+  const SWord8  s1584 = s1582 ^ s1583;
+  const SWord32 s1585 = table3[s1584];
+  const SWord32 s1586 = s1580 ^ s1585;
+  const SWord8  s1587 = (SWord8) s1471;
+  const SWord8  s1588 = table0[s1587];
+  const SWord8  s1589 = (SWord8) s18;
+  const SWord8  s1590 = s1588 ^ s1589;
+  const SWord32 s1591 = table4[s1590];
+  const SWord32 s1592 = s1586 ^ s1591;
+  const SWord8  s1593 = (SWord8) (s1592 >> 8);
+  const SWord8  s1594 = table0[s1593];
+  const SWord8  s1595 = (SWord8) (s20 >> 8);
+  const SWord8  s1596 = s1594 ^ s1595;
+  const SWord32 s1597 = table3[s1596];
+  const SWord32 s1598 = s1569 ^ s1597;
+  const SWord8  s1599 = (SWord8) (s1529 >> 24);
+  const SWord8  s1600 = table0[s1599];
+  const SWord8  s1601 = (SWord8) (s17 >> 24);
+  const SWord8  s1602 = s1600 ^ s1601;
+  const SWord32 s1603 = table1[s1602];
+  const SWord8  s1604 = (SWord8) (s1443 >> 16);
+  const SWord8  s1605 = table0[s1604];
+  const SWord8  s1606 = (SWord8) (s17 >> 16);
+  const SWord8  s1607 = s1605 ^ s1606;
+  const SWord32 s1608 = table2[s1607];
+  const SWord32 s1609 = s1603 ^ s1608;
+  const SWord8  s1610 = (SWord8) (s1471 >> 8);
+  const SWord8  s1611 = table0[s1610];
+  const SWord8  s1612 = (SWord8) (s17 >> 8);
+  const SWord8  s1613 = s1611 ^ s1612;
+  const SWord32 s1614 = table3[s1613];
+  const SWord32 s1615 = s1609 ^ s1614;
+  const SWord8  s1616 = (SWord8) s1500;
+  const SWord8  s1617 = table0[s1616];
+  const SWord8  s1618 = (SWord8) s17;
+  const SWord8  s1619 = s1617 ^ s1618;
+  const SWord32 s1620 = table4[s1619];
+  const SWord32 s1621 = s1615 ^ s1620;
+  const SWord8  s1622 = (SWord8) s1621;
+  const SWord8  s1623 = table0[s1622];
+  const SWord8  s1624 = (SWord8) s20;
+  const SWord8  s1625 = s1623 ^ s1624;
+  const SWord32 s1626 = table4[s1625];
+  const SWord32 s1627 = s1598 ^ s1626;
+  const SWord8  s1628 = (SWord8) (s1627 >> 24);
+  const SWord8  s1629 = table0[s1628];
+  const SWord8  s1630 = (SWord8) (s24 >> 24);
+  const SWord8  s1631 = s1629 ^ s1630;
+  const SWord32 s1632 = table1[s1631];
+  const SWord8  s1633 = (SWord8) (s1563 >> 24);
+  const SWord8  s1634 = table0[s1633];
+  const SWord8  s1635 = (SWord8) (s23 >> 24);
+  const SWord8  s1636 = s1634 ^ s1635;
+  const SWord32 s1637 = table1[s1636];
+  const SWord8  s1638 = (SWord8) (s1592 >> 16);
+  const SWord8  s1639 = table0[s1638];
+  const SWord8  s1640 = (SWord8) (s23 >> 16);
+  const SWord8  s1641 = s1639 ^ s1640;
+  const SWord32 s1642 = table2[s1641];
+  const SWord32 s1643 = s1637 ^ s1642;
+  const SWord8  s1644 = (SWord8) (s1621 >> 8);
+  const SWord8  s1645 = table0[s1644];
+  const SWord8  s1646 = (SWord8) (s23 >> 8);
+  const SWord8  s1647 = s1645 ^ s1646;
+  const SWord32 s1648 = table3[s1647];
+  const SWord32 s1649 = s1643 ^ s1648;
+  const SWord8  s1650 = (SWord8) s1535;
+  const SWord8  s1651 = table0[s1650];
+  const SWord8  s1652 = (SWord8) s23;
+  const SWord8  s1653 = s1651 ^ s1652;
+  const SWord32 s1654 = table4[s1653];
+  const SWord32 s1655 = s1649 ^ s1654;
+  const SWord8  s1656 = (SWord8) (s1655 >> 16);
+  const SWord8  s1657 = table0[s1656];
+  const SWord8  s1658 = (SWord8) (s24 >> 16);
+  const SWord8  s1659 = s1657 ^ s1658;
+  const SWord32 s1660 = table2[s1659];
+  const SWord32 s1661 = s1632 ^ s1660;
+  const SWord8  s1662 = (SWord8) (s1592 >> 24);
+  const SWord8  s1663 = table0[s1662];
+  const SWord8  s1664 = (SWord8) (s22 >> 24);
+  const SWord8  s1665 = s1663 ^ s1664;
+  const SWord32 s1666 = table1[s1665];
+  const SWord8  s1667 = (SWord8) (s1621 >> 16);
+  const SWord8  s1668 = table0[s1667];
+  const SWord8  s1669 = (SWord8) (s22 >> 16);
+  const SWord8  s1670 = s1668 ^ s1669;
+  const SWord32 s1671 = table2[s1670];
+  const SWord32 s1672 = s1666 ^ s1671;
+  const SWord8  s1673 = (SWord8) (s1535 >> 8);
+  const SWord8  s1674 = table0[s1673];
+  const SWord8  s1675 = (SWord8) (s22 >> 8);
+  const SWord8  s1676 = s1674 ^ s1675;
+  const SWord32 s1677 = table3[s1676];
+  const SWord32 s1678 = s1672 ^ s1677;
+  const SWord8  s1679 = (SWord8) s1563;
+  const SWord8  s1680 = table0[s1679];
+  const SWord8  s1681 = (SWord8) s22;
+  const SWord8  s1682 = s1680 ^ s1681;
+  const SWord32 s1683 = table4[s1682];
+  const SWord32 s1684 = s1678 ^ s1683;
+  const SWord8  s1685 = (SWord8) (s1684 >> 8);
+  const SWord8  s1686 = table0[s1685];
+  const SWord8  s1687 = (SWord8) (s24 >> 8);
+  const SWord8  s1688 = s1686 ^ s1687;
+  const SWord32 s1689 = table3[s1688];
+  const SWord32 s1690 = s1661 ^ s1689;
+  const SWord8  s1691 = (SWord8) (s1621 >> 24);
+  const SWord8  s1692 = table0[s1691];
+  const SWord8  s1693 = (SWord8) (s21 >> 24);
+  const SWord8  s1694 = s1692 ^ s1693;
+  const SWord32 s1695 = table1[s1694];
+  const SWord8  s1696 = (SWord8) (s1535 >> 16);
+  const SWord8  s1697 = table0[s1696];
+  const SWord8  s1698 = (SWord8) (s21 >> 16);
+  const SWord8  s1699 = s1697 ^ s1698;
+  const SWord32 s1700 = table2[s1699];
+  const SWord32 s1701 = s1695 ^ s1700;
+  const SWord8  s1702 = (SWord8) (s1563 >> 8);
+  const SWord8  s1703 = table0[s1702];
+  const SWord8  s1704 = (SWord8) (s21 >> 8);
+  const SWord8  s1705 = s1703 ^ s1704;
+  const SWord32 s1706 = table3[s1705];
+  const SWord32 s1707 = s1701 ^ s1706;
+  const SWord8  s1708 = (SWord8) s1592;
+  const SWord8  s1709 = table0[s1708];
+  const SWord8  s1710 = (SWord8) s21;
+  const SWord8  s1711 = s1709 ^ s1710;
+  const SWord32 s1712 = table4[s1711];
+  const SWord32 s1713 = s1707 ^ s1712;
+  const SWord8  s1714 = (SWord8) s1713;
+  const SWord8  s1715 = table0[s1714];
+  const SWord8  s1716 = (SWord8) s24;
+  const SWord8  s1717 = s1715 ^ s1716;
+  const SWord32 s1718 = table4[s1717];
+  const SWord32 s1719 = s1690 ^ s1718;
+  const SWord8  s1720 = (SWord8) (s1719 >> 24);
+  const SWord8  s1721 = table0[s1720];
+  const SWord8  s1722 = (SWord8) (s28 >> 24);
+  const SWord8  s1723 = s1721 ^ s1722;
+  const SWord32 s1724 = table1[s1723];
+  const SWord8  s1725 = (SWord8) (s1655 >> 24);
+  const SWord8  s1726 = table0[s1725];
+  const SWord8  s1727 = (SWord8) (s27 >> 24);
+  const SWord8  s1728 = s1726 ^ s1727;
+  const SWord32 s1729 = table1[s1728];
+  const SWord8  s1730 = (SWord8) (s1684 >> 16);
+  const SWord8  s1731 = table0[s1730];
+  const SWord8  s1732 = (SWord8) (s27 >> 16);
+  const SWord8  s1733 = s1731 ^ s1732;
+  const SWord32 s1734 = table2[s1733];
+  const SWord32 s1735 = s1729 ^ s1734;
+  const SWord8  s1736 = (SWord8) (s1713 >> 8);
+  const SWord8  s1737 = table0[s1736];
+  const SWord8  s1738 = (SWord8) (s27 >> 8);
+  const SWord8  s1739 = s1737 ^ s1738;
+  const SWord32 s1740 = table3[s1739];
+  const SWord32 s1741 = s1735 ^ s1740;
+  const SWord8  s1742 = (SWord8) s1627;
+  const SWord8  s1743 = table0[s1742];
+  const SWord8  s1744 = (SWord8) s27;
+  const SWord8  s1745 = s1743 ^ s1744;
+  const SWord32 s1746 = table4[s1745];
+  const SWord32 s1747 = s1741 ^ s1746;
+  const SWord8  s1748 = (SWord8) (s1747 >> 16);
+  const SWord8  s1749 = table0[s1748];
+  const SWord8  s1750 = (SWord8) (s28 >> 16);
+  const SWord8  s1751 = s1749 ^ s1750;
+  const SWord32 s1752 = table2[s1751];
+  const SWord32 s1753 = s1724 ^ s1752;
+  const SWord8  s1754 = (SWord8) (s1684 >> 24);
+  const SWord8  s1755 = table0[s1754];
+  const SWord8  s1756 = (SWord8) (s26 >> 24);
+  const SWord8  s1757 = s1755 ^ s1756;
+  const SWord32 s1758 = table1[s1757];
+  const SWord8  s1759 = (SWord8) (s1713 >> 16);
+  const SWord8  s1760 = table0[s1759];
+  const SWord8  s1761 = (SWord8) (s26 >> 16);
+  const SWord8  s1762 = s1760 ^ s1761;
+  const SWord32 s1763 = table2[s1762];
+  const SWord32 s1764 = s1758 ^ s1763;
+  const SWord8  s1765 = (SWord8) (s1627 >> 8);
+  const SWord8  s1766 = table0[s1765];
+  const SWord8  s1767 = (SWord8) (s26 >> 8);
+  const SWord8  s1768 = s1766 ^ s1767;
+  const SWord32 s1769 = table3[s1768];
+  const SWord32 s1770 = s1764 ^ s1769;
+  const SWord8  s1771 = (SWord8) s1655;
+  const SWord8  s1772 = table0[s1771];
+  const SWord8  s1773 = (SWord8) s26;
+  const SWord8  s1774 = s1772 ^ s1773;
+  const SWord32 s1775 = table4[s1774];
+  const SWord32 s1776 = s1770 ^ s1775;
+  const SWord8  s1777 = (SWord8) (s1776 >> 8);
+  const SWord8  s1778 = table0[s1777];
+  const SWord8  s1779 = (SWord8) (s28 >> 8);
+  const SWord8  s1780 = s1778 ^ s1779;
+  const SWord32 s1781 = table3[s1780];
+  const SWord32 s1782 = s1753 ^ s1781;
+  const SWord8  s1783 = (SWord8) (s1713 >> 24);
+  const SWord8  s1784 = table0[s1783];
+  const SWord8  s1785 = (SWord8) (s25 >> 24);
+  const SWord8  s1786 = s1784 ^ s1785;
+  const SWord32 s1787 = table1[s1786];
+  const SWord8  s1788 = (SWord8) (s1627 >> 16);
+  const SWord8  s1789 = table0[s1788];
+  const SWord8  s1790 = (SWord8) (s25 >> 16);
+  const SWord8  s1791 = s1789 ^ s1790;
+  const SWord32 s1792 = table2[s1791];
+  const SWord32 s1793 = s1787 ^ s1792;
+  const SWord8  s1794 = (SWord8) (s1655 >> 8);
+  const SWord8  s1795 = table0[s1794];
+  const SWord8  s1796 = (SWord8) (s25 >> 8);
+  const SWord8  s1797 = s1795 ^ s1796;
+  const SWord32 s1798 = table3[s1797];
+  const SWord32 s1799 = s1793 ^ s1798;
+  const SWord8  s1800 = (SWord8) s1684;
+  const SWord8  s1801 = table0[s1800];
+  const SWord8  s1802 = (SWord8) s25;
+  const SWord8  s1803 = s1801 ^ s1802;
+  const SWord32 s1804 = table4[s1803];
+  const SWord32 s1805 = s1799 ^ s1804;
+  const SWord8  s1806 = (SWord8) s1805;
+  const SWord8  s1807 = table0[s1806];
+  const SWord8  s1808 = (SWord8) s28;
+  const SWord8  s1809 = s1807 ^ s1808;
+  const SWord32 s1810 = table4[s1809];
+  const SWord32 s1811 = s1782 ^ s1810;
+  const SWord8  s1812 = (SWord8) (s1811 >> 24);
+  const SWord8  s1813 = table0[s1812];
+  const SWord8  s1814 = (SWord8) (s32 >> 24);
+  const SWord8  s1815 = s1813 ^ s1814;
+  const SWord32 s1816 = table1[s1815];
+  const SWord8  s1817 = (SWord8) (s1747 >> 24);
+  const SWord8  s1818 = table0[s1817];
+  const SWord8  s1819 = (SWord8) (s31 >> 24);
+  const SWord8  s1820 = s1818 ^ s1819;
+  const SWord32 s1821 = table1[s1820];
+  const SWord8  s1822 = (SWord8) (s1776 >> 16);
+  const SWord8  s1823 = table0[s1822];
+  const SWord8  s1824 = (SWord8) (s31 >> 16);
+  const SWord8  s1825 = s1823 ^ s1824;
+  const SWord32 s1826 = table2[s1825];
+  const SWord32 s1827 = s1821 ^ s1826;
+  const SWord8  s1828 = (SWord8) (s1805 >> 8);
+  const SWord8  s1829 = table0[s1828];
+  const SWord8  s1830 = (SWord8) (s31 >> 8);
+  const SWord8  s1831 = s1829 ^ s1830;
+  const SWord32 s1832 = table3[s1831];
+  const SWord32 s1833 = s1827 ^ s1832;
+  const SWord8  s1834 = (SWord8) s1719;
+  const SWord8  s1835 = table0[s1834];
+  const SWord8  s1836 = (SWord8) s31;
+  const SWord8  s1837 = s1835 ^ s1836;
+  const SWord32 s1838 = table4[s1837];
+  const SWord32 s1839 = s1833 ^ s1838;
+  const SWord8  s1840 = (SWord8) (s1839 >> 16);
+  const SWord8  s1841 = table0[s1840];
+  const SWord8  s1842 = (SWord8) (s32 >> 16);
+  const SWord8  s1843 = s1841 ^ s1842;
+  const SWord32 s1844 = table2[s1843];
+  const SWord32 s1845 = s1816 ^ s1844;
+  const SWord8  s1846 = (SWord8) (s1776 >> 24);
+  const SWord8  s1847 = table0[s1846];
+  const SWord8  s1848 = (SWord8) (s30 >> 24);
+  const SWord8  s1849 = s1847 ^ s1848;
+  const SWord32 s1850 = table1[s1849];
+  const SWord8  s1851 = (SWord8) (s1805 >> 16);
+  const SWord8  s1852 = table0[s1851];
+  const SWord8  s1853 = (SWord8) (s30 >> 16);
+  const SWord8  s1854 = s1852 ^ s1853;
+  const SWord32 s1855 = table2[s1854];
+  const SWord32 s1856 = s1850 ^ s1855;
+  const SWord8  s1857 = (SWord8) (s1719 >> 8);
+  const SWord8  s1858 = table0[s1857];
+  const SWord8  s1859 = (SWord8) (s30 >> 8);
+  const SWord8  s1860 = s1858 ^ s1859;
+  const SWord32 s1861 = table3[s1860];
+  const SWord32 s1862 = s1856 ^ s1861;
+  const SWord8  s1863 = (SWord8) s1747;
+  const SWord8  s1864 = table0[s1863];
+  const SWord8  s1865 = (SWord8) s30;
+  const SWord8  s1866 = s1864 ^ s1865;
+  const SWord32 s1867 = table4[s1866];
+  const SWord32 s1868 = s1862 ^ s1867;
+  const SWord8  s1869 = (SWord8) (s1868 >> 8);
+  const SWord8  s1870 = table0[s1869];
+  const SWord8  s1871 = (SWord8) (s32 >> 8);
+  const SWord8  s1872 = s1870 ^ s1871;
+  const SWord32 s1873 = table3[s1872];
+  const SWord32 s1874 = s1845 ^ s1873;
+  const SWord8  s1875 = (SWord8) (s1805 >> 24);
+  const SWord8  s1876 = table0[s1875];
+  const SWord8  s1877 = (SWord8) (s29 >> 24);
+  const SWord8  s1878 = s1876 ^ s1877;
+  const SWord32 s1879 = table1[s1878];
+  const SWord8  s1880 = (SWord8) (s1719 >> 16);
+  const SWord8  s1881 = table0[s1880];
+  const SWord8  s1882 = (SWord8) (s29 >> 16);
+  const SWord8  s1883 = s1881 ^ s1882;
+  const SWord32 s1884 = table2[s1883];
+  const SWord32 s1885 = s1879 ^ s1884;
+  const SWord8  s1886 = (SWord8) (s1747 >> 8);
+  const SWord8  s1887 = table0[s1886];
+  const SWord8  s1888 = (SWord8) (s29 >> 8);
+  const SWord8  s1889 = s1887 ^ s1888;
+  const SWord32 s1890 = table3[s1889];
+  const SWord32 s1891 = s1885 ^ s1890;
+  const SWord8  s1892 = (SWord8) s1776;
+  const SWord8  s1893 = table0[s1892];
+  const SWord8  s1894 = (SWord8) s29;
+  const SWord8  s1895 = s1893 ^ s1894;
+  const SWord32 s1896 = table4[s1895];
+  const SWord32 s1897 = s1891 ^ s1896;
+  const SWord8  s1898 = (SWord8) s1897;
+  const SWord8  s1899 = table0[s1898];
+  const SWord8  s1900 = (SWord8) s32;
+  const SWord8  s1901 = s1899 ^ s1900;
+  const SWord32 s1902 = table4[s1901];
+  const SWord32 s1903 = s1874 ^ s1902;
+  const SWord8  s1904 = (SWord8) (s1903 >> 24);
+  const SWord8  s1905 = table0[s1904];
+  const SWord8  s1906 = (SWord8) (s36 >> 24);
+  const SWord8  s1907 = s1905 ^ s1906;
+  const SWord32 s1908 = table1[s1907];
+  const SWord8  s1909 = (SWord8) (s1839 >> 24);
+  const SWord8  s1910 = table0[s1909];
+  const SWord8  s1911 = (SWord8) (s35 >> 24);
+  const SWord8  s1912 = s1910 ^ s1911;
+  const SWord32 s1913 = table1[s1912];
+  const SWord8  s1914 = (SWord8) (s1868 >> 16);
+  const SWord8  s1915 = table0[s1914];
+  const SWord8  s1916 = (SWord8) (s35 >> 16);
+  const SWord8  s1917 = s1915 ^ s1916;
+  const SWord32 s1918 = table2[s1917];
+  const SWord32 s1919 = s1913 ^ s1918;
+  const SWord8  s1920 = (SWord8) (s1897 >> 8);
+  const SWord8  s1921 = table0[s1920];
+  const SWord8  s1922 = (SWord8) (s35 >> 8);
+  const SWord8  s1923 = s1921 ^ s1922;
+  const SWord32 s1924 = table3[s1923];
+  const SWord32 s1925 = s1919 ^ s1924;
+  const SWord8  s1926 = (SWord8) s1811;
+  const SWord8  s1927 = table0[s1926];
+  const SWord8  s1928 = (SWord8) s35;
+  const SWord8  s1929 = s1927 ^ s1928;
+  const SWord32 s1930 = table4[s1929];
+  const SWord32 s1931 = s1925 ^ s1930;
+  const SWord8  s1932 = (SWord8) (s1931 >> 16);
+  const SWord8  s1933 = table0[s1932];
+  const SWord8  s1934 = (SWord8) (s36 >> 16);
+  const SWord8  s1935 = s1933 ^ s1934;
+  const SWord32 s1936 = table2[s1935];
+  const SWord32 s1937 = s1908 ^ s1936;
+  const SWord8  s1938 = (SWord8) (s1868 >> 24);
+  const SWord8  s1939 = table0[s1938];
+  const SWord8  s1940 = (SWord8) (s34 >> 24);
+  const SWord8  s1941 = s1939 ^ s1940;
+  const SWord32 s1942 = table1[s1941];
+  const SWord8  s1943 = (SWord8) (s1897 >> 16);
+  const SWord8  s1944 = table0[s1943];
+  const SWord8  s1945 = (SWord8) (s34 >> 16);
+  const SWord8  s1946 = s1944 ^ s1945;
+  const SWord32 s1947 = table2[s1946];
+  const SWord32 s1948 = s1942 ^ s1947;
+  const SWord8  s1949 = (SWord8) (s1811 >> 8);
+  const SWord8  s1950 = table0[s1949];
+  const SWord8  s1951 = (SWord8) (s34 >> 8);
+  const SWord8  s1952 = s1950 ^ s1951;
+  const SWord32 s1953 = table3[s1952];
+  const SWord32 s1954 = s1948 ^ s1953;
+  const SWord8  s1955 = (SWord8) s1839;
+  const SWord8  s1956 = table0[s1955];
+  const SWord8  s1957 = (SWord8) s34;
+  const SWord8  s1958 = s1956 ^ s1957;
+  const SWord32 s1959 = table4[s1958];
+  const SWord32 s1960 = s1954 ^ s1959;
+  const SWord8  s1961 = (SWord8) (s1960 >> 8);
+  const SWord8  s1962 = table0[s1961];
+  const SWord8  s1963 = (SWord8) (s36 >> 8);
+  const SWord8  s1964 = s1962 ^ s1963;
+  const SWord32 s1965 = table3[s1964];
+  const SWord32 s1966 = s1937 ^ s1965;
+  const SWord8  s1967 = (SWord8) (s1897 >> 24);
+  const SWord8  s1968 = table0[s1967];
+  const SWord8  s1969 = (SWord8) (s33 >> 24);
+  const SWord8  s1970 = s1968 ^ s1969;
+  const SWord32 s1971 = table1[s1970];
+  const SWord8  s1972 = (SWord8) (s1811 >> 16);
+  const SWord8  s1973 = table0[s1972];
+  const SWord8  s1974 = (SWord8) (s33 >> 16);
+  const SWord8  s1975 = s1973 ^ s1974;
+  const SWord32 s1976 = table2[s1975];
+  const SWord32 s1977 = s1971 ^ s1976;
+  const SWord8  s1978 = (SWord8) (s1839 >> 8);
+  const SWord8  s1979 = table0[s1978];
+  const SWord8  s1980 = (SWord8) (s33 >> 8);
+  const SWord8  s1981 = s1979 ^ s1980;
+  const SWord32 s1982 = table3[s1981];
+  const SWord32 s1983 = s1977 ^ s1982;
+  const SWord8  s1984 = (SWord8) s1868;
+  const SWord8  s1985 = table0[s1984];
+  const SWord8  s1986 = (SWord8) s33;
+  const SWord8  s1987 = s1985 ^ s1986;
+  const SWord32 s1988 = table4[s1987];
+  const SWord32 s1989 = s1983 ^ s1988;
+  const SWord8  s1990 = (SWord8) s1989;
+  const SWord8  s1991 = table0[s1990];
+  const SWord8  s1992 = (SWord8) s36;
+  const SWord8  s1993 = s1991 ^ s1992;
+  const SWord32 s1994 = table4[s1993];
+  const SWord32 s1995 = s1966 ^ s1994;
+  const SWord8  s1996 = (SWord8) (s1995 >> 24);
+  const SWord8  s1997 = table0[s1996];
+  const SWord8  s1998 = (SWord8) (s40 >> 24);
+  const SWord8  s1999 = s1997 ^ s1998;
+  const SWord32 s2000 = table1[s1999];
+  const SWord8  s2001 = (SWord8) (s1931 >> 24);
+  const SWord8  s2002 = table0[s2001];
+  const SWord8  s2003 = (SWord8) (s39 >> 24);
+  const SWord8  s2004 = s2002 ^ s2003;
+  const SWord32 s2005 = table1[s2004];
+  const SWord8  s2006 = (SWord8) (s1960 >> 16);
+  const SWord8  s2007 = table0[s2006];
+  const SWord8  s2008 = (SWord8) (s39 >> 16);
+  const SWord8  s2009 = s2007 ^ s2008;
+  const SWord32 s2010 = table2[s2009];
+  const SWord32 s2011 = s2005 ^ s2010;
+  const SWord8  s2012 = (SWord8) (s1989 >> 8);
+  const SWord8  s2013 = table0[s2012];
+  const SWord8  s2014 = (SWord8) (s39 >> 8);
+  const SWord8  s2015 = s2013 ^ s2014;
+  const SWord32 s2016 = table3[s2015];
+  const SWord32 s2017 = s2011 ^ s2016;
+  const SWord8  s2018 = (SWord8) s1903;
+  const SWord8  s2019 = table0[s2018];
+  const SWord8  s2020 = (SWord8) s39;
+  const SWord8  s2021 = s2019 ^ s2020;
+  const SWord32 s2022 = table4[s2021];
+  const SWord32 s2023 = s2017 ^ s2022;
+  const SWord8  s2024 = (SWord8) (s2023 >> 16);
+  const SWord8  s2025 = table0[s2024];
+  const SWord8  s2026 = (SWord8) (s40 >> 16);
+  const SWord8  s2027 = s2025 ^ s2026;
+  const SWord32 s2028 = table2[s2027];
+  const SWord32 s2029 = s2000 ^ s2028;
+  const SWord8  s2030 = (SWord8) (s1960 >> 24);
+  const SWord8  s2031 = table0[s2030];
+  const SWord8  s2032 = (SWord8) (s38 >> 24);
+  const SWord8  s2033 = s2031 ^ s2032;
+  const SWord32 s2034 = table1[s2033];
+  const SWord8  s2035 = (SWord8) (s1989 >> 16);
+  const SWord8  s2036 = table0[s2035];
+  const SWord8  s2037 = (SWord8) (s38 >> 16);
+  const SWord8  s2038 = s2036 ^ s2037;
+  const SWord32 s2039 = table2[s2038];
+  const SWord32 s2040 = s2034 ^ s2039;
+  const SWord8  s2041 = (SWord8) (s1903 >> 8);
+  const SWord8  s2042 = table0[s2041];
+  const SWord8  s2043 = (SWord8) (s38 >> 8);
+  const SWord8  s2044 = s2042 ^ s2043;
+  const SWord32 s2045 = table3[s2044];
+  const SWord32 s2046 = s2040 ^ s2045;
+  const SWord8  s2047 = (SWord8) s1931;
+  const SWord8  s2048 = table0[s2047];
+  const SWord8  s2049 = (SWord8) s38;
+  const SWord8  s2050 = s2048 ^ s2049;
+  const SWord32 s2051 = table4[s2050];
+  const SWord32 s2052 = s2046 ^ s2051;
+  const SWord8  s2053 = (SWord8) (s2052 >> 8);
+  const SWord8  s2054 = table0[s2053];
+  const SWord8  s2055 = (SWord8) (s40 >> 8);
+  const SWord8  s2056 = s2054 ^ s2055;
+  const SWord32 s2057 = table3[s2056];
+  const SWord32 s2058 = s2029 ^ s2057;
+  const SWord8  s2059 = (SWord8) (s1989 >> 24);
+  const SWord8  s2060 = table0[s2059];
+  const SWord8  s2061 = (SWord8) (s37 >> 24);
+  const SWord8  s2062 = s2060 ^ s2061;
+  const SWord32 s2063 = table1[s2062];
+  const SWord8  s2064 = (SWord8) (s1903 >> 16);
+  const SWord8  s2065 = table0[s2064];
+  const SWord8  s2066 = (SWord8) (s37 >> 16);
+  const SWord8  s2067 = s2065 ^ s2066;
+  const SWord32 s2068 = table2[s2067];
+  const SWord32 s2069 = s2063 ^ s2068;
+  const SWord8  s2070 = (SWord8) (s1931 >> 8);
+  const SWord8  s2071 = table0[s2070];
+  const SWord8  s2072 = (SWord8) (s37 >> 8);
+  const SWord8  s2073 = s2071 ^ s2072;
+  const SWord32 s2074 = table3[s2073];
+  const SWord32 s2075 = s2069 ^ s2074;
+  const SWord8  s2076 = (SWord8) s1960;
+  const SWord8  s2077 = table0[s2076];
+  const SWord8  s2078 = (SWord8) s37;
+  const SWord8  s2079 = s2077 ^ s2078;
+  const SWord32 s2080 = table4[s2079];
+  const SWord32 s2081 = s2075 ^ s2080;
+  const SWord8  s2082 = (SWord8) s2081;
+  const SWord8  s2083 = table0[s2082];
+  const SWord8  s2084 = (SWord8) s40;
+  const SWord8  s2085 = s2083 ^ s2084;
+  const SWord32 s2086 = table4[s2085];
+  const SWord32 s2087 = s2058 ^ s2086;
+  const SWord8  s2088 = (SWord8) (s2087 >> 24);
+  const SWord8  s2089 = table0[s2088];
+  const SWord8  s2090 = (SWord8) (s2023 >> 24);
+  const SWord8  s2091 = table0[s2090];
+  const SWord8  s2092 = (SWord8) (s43 >> 24);
+  const SWord8  s2093 = s2091 ^ s2092;
+  const SWord32 s2094 = table1[s2093];
+  const SWord8  s2095 = (SWord8) (s2052 >> 16);
+  const SWord8  s2096 = table0[s2095];
+  const SWord8  s2097 = (SWord8) (s43 >> 16);
+  const SWord8  s2098 = s2096 ^ s2097;
+  const SWord32 s2099 = table2[s2098];
+  const SWord32 s2100 = s2094 ^ s2099;
+  const SWord8  s2101 = (SWord8) (s2081 >> 8);
+  const SWord8  s2102 = table0[s2101];
+  const SWord8  s2103 = (SWord8) (s43 >> 8);
+  const SWord8  s2104 = s2102 ^ s2103;
+  const SWord32 s2105 = table3[s2104];
+  const SWord32 s2106 = s2100 ^ s2105;
+  const SWord8  s2107 = (SWord8) s1995;
+  const SWord8  s2108 = table0[s2107];
+  const SWord8  s2109 = (SWord8) s43;
+  const SWord8  s2110 = s2108 ^ s2109;
+  const SWord32 s2111 = table4[s2110];
+  const SWord32 s2112 = s2106 ^ s2111;
+  const SWord8  s2113 = (SWord8) (s2112 >> 16);
+  const SWord8  s2114 = table0[s2113];
+  const SWord16 s2115 = (((SWord16) s2089) << 8) | ((SWord16) s2114);
+  const SWord8  s2116 = (SWord8) (s2052 >> 24);
+  const SWord8  s2117 = table0[s2116];
+  const SWord8  s2118 = (SWord8) (s42 >> 24);
+  const SWord8  s2119 = s2117 ^ s2118;
+  const SWord32 s2120 = table1[s2119];
+  const SWord8  s2121 = (SWord8) (s2081 >> 16);
+  const SWord8  s2122 = table0[s2121];
+  const SWord8  s2123 = (SWord8) (s42 >> 16);
+  const SWord8  s2124 = s2122 ^ s2123;
+  const SWord32 s2125 = table2[s2124];
+  const SWord32 s2126 = s2120 ^ s2125;
+  const SWord8  s2127 = (SWord8) (s1995 >> 8);
+  const SWord8  s2128 = table0[s2127];
+  const SWord8  s2129 = (SWord8) (s42 >> 8);
+  const SWord8  s2130 = s2128 ^ s2129;
+  const SWord32 s2131 = table3[s2130];
+  const SWord32 s2132 = s2126 ^ s2131;
+  const SWord8  s2133 = (SWord8) s2023;
+  const SWord8  s2134 = table0[s2133];
+  const SWord8  s2135 = (SWord8) s42;
+  const SWord8  s2136 = s2134 ^ s2135;
+  const SWord32 s2137 = table4[s2136];
+  const SWord32 s2138 = s2132 ^ s2137;
+  const SWord8  s2139 = (SWord8) (s2138 >> 8);
+  const SWord8  s2140 = table0[s2139];
+  const SWord8  s2141 = (SWord8) (s2081 >> 24);
+  const SWord8  s2142 = table0[s2141];
+  const SWord8  s2143 = (SWord8) (s41 >> 24);
+  const SWord8  s2144 = s2142 ^ s2143;
+  const SWord32 s2145 = table1[s2144];
+  const SWord8  s2146 = (SWord8) (s1995 >> 16);
+  const SWord8  s2147 = table0[s2146];
+  const SWord8  s2148 = (SWord8) (s41 >> 16);
+  const SWord8  s2149 = s2147 ^ s2148;
+  const SWord32 s2150 = table2[s2149];
+  const SWord32 s2151 = s2145 ^ s2150;
+  const SWord8  s2152 = (SWord8) (s2023 >> 8);
+  const SWord8  s2153 = table0[s2152];
+  const SWord8  s2154 = (SWord8) (s41 >> 8);
+  const SWord8  s2155 = s2153 ^ s2154;
+  const SWord32 s2156 = table3[s2155];
+  const SWord32 s2157 = s2151 ^ s2156;
+  const SWord8  s2158 = (SWord8) s2052;
+  const SWord8  s2159 = table0[s2158];
+  const SWord8  s2160 = (SWord8) s41;
+  const SWord8  s2161 = s2159 ^ s2160;
+  const SWord32 s2162 = table4[s2161];
+  const SWord32 s2163 = s2157 ^ s2162;
+  const SWord8  s2164 = (SWord8) s2163;
+  const SWord8  s2165 = table0[s2164];
+  const SWord16 s2166 = (((SWord16) s2140) << 8) | ((SWord16) s2165);
+  const SWord32 s2167 = (((SWord32) s2115) << 16) | ((SWord32) s2166);
+  const SWord32 s2168 = s44 ^ s2167;
+  const SWord8  s2169 = (SWord8) (s2163 >> 24);
+  const SWord8  s2170 = table0[s2169];
+  const SWord8  s2171 = (SWord8) (s2087 >> 16);
+  const SWord8  s2172 = table0[s2171];
+  const SWord16 s2173 = (((SWord16) s2170) << 8) | ((SWord16) s2172);
+  const SWord8  s2174 = (SWord8) (s2112 >> 8);
+  const SWord8  s2175 = table0[s2174];
+  const SWord8  s2176 = (SWord8) s2138;
+  const SWord8  s2177 = table0[s2176];
+  const SWord16 s2178 = (((SWord16) s2175) << 8) | ((SWord16) s2177);
+  const SWord32 s2179 = (((SWord32) s2173) << 16) | ((SWord32) s2178);
+  const SWord32 s2180 = s45 ^ s2179;
+  const SWord8  s2181 = (SWord8) (s2138 >> 24);
+  const SWord8  s2182 = table0[s2181];
+  const SWord8  s2183 = (SWord8) (s2163 >> 16);
+  const SWord8  s2184 = table0[s2183];
+  const SWord16 s2185 = (((SWord16) s2182) << 8) | ((SWord16) s2184);
+  const SWord8  s2186 = (SWord8) (s2087 >> 8);
+  const SWord8  s2187 = table0[s2186];
+  const SWord8  s2188 = (SWord8) s2112;
+  const SWord8  s2189 = table0[s2188];
+  const SWord16 s2190 = (((SWord16) s2187) << 8) | ((SWord16) s2189);
+  const SWord32 s2191 = (((SWord32) s2185) << 16) | ((SWord32) s2190);
+  const SWord32 s2192 = s46 ^ s2191;
+  const SWord8  s2193 = (SWord8) (s2112 >> 24);
+  const SWord8  s2194 = table0[s2193];
+  const SWord8  s2195 = (SWord8) (s2138 >> 16);
+  const SWord8  s2196 = table0[s2195];
+  const SWord16 s2197 = (((SWord16) s2194) << 8) | ((SWord16) s2196);
+  const SWord8  s2198 = (SWord8) (s2163 >> 8);
+  const SWord8  s2199 = table0[s2198];
+  const SWord8  s2200 = (SWord8) s2087;
+  const SWord8  s2201 = table0[s2200];
+  const SWord16 s2202 = (((SWord16) s2199) << 8) | ((SWord16) s2201);
+  const SWord32 s2203 = (((SWord32) s2197) << 16) | ((SWord32) s2202);
+  const SWord32 s2204 = s47 ^ s2203;
+
+  pt[0] = s2168;
+  pt[1] = s2180;
+  pt[2] = s2192;
+  pt[3] = s2204;
+}
+== END: "aes128OTFDecrypt.c" ==================
+== BEGIN: "aes128Lib.h" ================
+/* Header file for aes128Lib. Automatically generated by SBV. Do not edit! */
+
+#ifndef __aes128Lib__HEADER_INCLUDED__
+#define __aes128Lib__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototypes: */
+void aes128KeySchedule(const SWord32 *key, SWord32 *encKS,
+                       SWord32 *decKS);
+void aes128BlockEncrypt(const SWord32 *pt, const SWord32 *xkey,
+                        SWord32 *ct);
+void aes128BlockDecrypt(const SWord32 *ct, const SWord32 *xkey,
+                        SWord32 *pt);
+void aes128InvKeySchedule(const SWord32 *key, SWord32 *decKS);
+void aes128OTFDecrypt(const SWord32 *ct, const SWord32 *xkey,
+                      SWord32 *pt);
+
+#endif /* __aes128Lib__HEADER_INCLUDED__ */
+== END: "aes128Lib.h" ==================
+== BEGIN: "aes128Lib_driver.c" ================
+/* Example driver program for aes128Lib. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "aes128Lib.h"
+
+void aes128KeySchedule_driver(void)
+{
+  const SWord32 key[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array key:\n");
+  int key_ctr;
+  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
+    printf("  key[%1d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
+
+  SWord32 encKS[44];
+  SWord32 decKS[44];
+
+  aes128KeySchedule(key, encKS, decKS);
+
+  printf("aes128KeySchedule(key, encKS, decKS) ->\n");
+  int encKS_ctr;
+  for(encKS_ctr = 0; encKS_ctr < 44 ; ++encKS_ctr)
+    printf("  encKS[%2d] = 0x%08"PRIx32"UL\n", encKS_ctr ,encKS[encKS_ctr]);
+  int decKS_ctr;
+  for(decKS_ctr = 0; decKS_ctr < 44 ; ++decKS_ctr)
+    printf("  decKS[%2d] = 0x%08"PRIx32"UL\n", decKS_ctr ,decKS[decKS_ctr]);
+}
+
+void aes128BlockEncrypt_driver(void)
+{
+  const SWord32 pt[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array pt:\n");
+  int pt_ctr;
+  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
+    printf("  pt[%1d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
+
+  const SWord32 xkey[44] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array xkey:\n");
+  int xkey_ctr;
+  for(xkey_ctr = 0; xkey_ctr < 44 ; ++xkey_ctr)
+    printf("  xkey[%2d] = 0x%08"PRIx32"UL\n", xkey_ctr ,xkey[xkey_ctr]);
+
+  SWord32 ct[4];
+
+  aes128BlockEncrypt(pt, xkey, ct);
+
+  printf("aes128BlockEncrypt(pt, xkey, ct) ->\n");
+  int ct_ctr;
+  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
+    printf("  ct[%1d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
+}
+
+void aes128BlockDecrypt_driver(void)
+{
+  const SWord32 ct[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array ct:\n");
+  int ct_ctr;
+  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
+    printf("  ct[%1d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
+
+  const SWord32 xkey[44] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array xkey:\n");
+  int xkey_ctr;
+  for(xkey_ctr = 0; xkey_ctr < 44 ; ++xkey_ctr)
+    printf("  xkey[%2d] = 0x%08"PRIx32"UL\n", xkey_ctr ,xkey[xkey_ctr]);
+
+  SWord32 pt[4];
+
+  aes128BlockDecrypt(ct, xkey, pt);
+
+  printf("aes128BlockDecrypt(ct, xkey, pt) ->\n");
+  int pt_ctr;
+  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
+    printf("  pt[%1d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
+}
+
+void aes128InvKeySchedule_driver(void)
+{
+  const SWord32 key[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array key:\n");
+  int key_ctr;
+  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
+    printf("  key[%1d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
+
+  SWord32 decKS[44];
+
+  aes128InvKeySchedule(key, decKS);
+
+  printf("aes128InvKeySchedule(key, decKS) ->\n");
+  int decKS_ctr;
+  for(decKS_ctr = 0; decKS_ctr < 44 ; ++decKS_ctr)
+    printf("  decKS[%2d] = 0x%08"PRIx32"UL\n", decKS_ctr ,decKS[decKS_ctr]);
+}
+
+void aes128OTFDecrypt_driver(void)
+{
+  const SWord32 ct[4] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array ct:\n");
+  int ct_ctr;
+  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
+    printf("  ct[%1d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
+
+  const SWord32 xkey[44] = {
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
+  };
+
+  printf("Contents of input array xkey:\n");
+  int xkey_ctr;
+  for(xkey_ctr = 0; xkey_ctr < 44 ; ++xkey_ctr)
+    printf("  xkey[%2d] = 0x%08"PRIx32"UL\n", xkey_ctr ,xkey[xkey_ctr]);
+
+  SWord32 pt[4];
+
+  aes128OTFDecrypt(ct, xkey, pt);
+
+  printf("aes128OTFDecrypt(ct, xkey, pt) ->\n");
+  int pt_ctr;
+  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
+    printf("  pt[%1d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
+}
+
+int main(void)
+{
+  printf("====================================\n");
+  printf("** Driver run for aes128KeySchedule:\n");
+  printf("====================================\n");
+  aes128KeySchedule_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for aes128BlockEncrypt:\n");
+  printf("=====================================\n");
+  aes128BlockEncrypt_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for aes128BlockDecrypt:\n");
+  printf("=====================================\n");
+  aes128BlockDecrypt_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for aes128InvKeySchedule:\n");
+  printf("=======================================\n");
+  aes128InvKeySchedule_driver();
+
+  printf("===================================\n");
+  printf("** Driver run for aes128OTFDecrypt:\n");
+  printf("===================================\n");
+  aes128OTFDecrypt_driver();
+
+  return 0;
+}
+== END: "aes128Lib_driver.c" ==================
+== BEGIN: "Makefile" ================
+# Makefile for aes128Lib. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+AR?=ar
+ARFLAGS?=cr
+
+all: aes128Lib.a aes128Lib_driver
+
+aes128Lib.a: aes128KeySchedule.o aes128BlockEncrypt.o aes128BlockDecrypt.o aes128InvKeySchedule.o aes128OTFDecrypt.o
+	${AR} ${ARFLAGS} $@ $^
+
+aes128Lib_driver: aes128Lib_driver.c aes128Lib.h
+	${CC} ${CCFLAGS} $< -o $@ aes128Lib.a
+
+aes128KeySchedule.o: aes128KeySchedule.c aes128Lib.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128BlockEncrypt.o: aes128BlockEncrypt.c aes128Lib.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128BlockDecrypt.o: aes128BlockDecrypt.c aes128Lib.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128InvKeySchedule.o: aes128InvKeySchedule.c aes128Lib.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+aes128OTFDecrypt.o: aes128OTFDecrypt.c aes128Lib.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f aes128Lib.a aes128Lib_driver
+== END: "Makefile" ==================
diff --git a/SBVTestSuite/GoldFiles/allSat1.gold b/SBVTestSuite/GoldFiles/allSat1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat1.gold
@@ -0,0 +1,4 @@
+Solution #1:
+  x = Q_0 :: Q
+  y = Q_0 :: Q
+This is the only solution.
diff --git a/SBVTestSuite/GoldFiles/allSat2.gold b/SBVTestSuite/GoldFiles/allSat2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat2.gold
@@ -0,0 +1,9 @@
+Solution #1:
+  x = Q_0 :: Q
+  y = Q_0 :: Q
+  z = Q_1 :: Q
+Solution #2:
+  x = Q_0 :: Q
+  y = Q_0 :: Q
+  z = Q_0 :: Q
+Found 2 different solutions.
diff --git a/SBVTestSuite/GoldFiles/allSat3.gold b/SBVTestSuite/GoldFiles/allSat3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat3.gold
@@ -0,0 +1,5 @@
+Solution #1:
+  s0 = -0.0 :: Float
+Solution #2:
+  s0 = 0.0 :: Float
+Found 2 different solutions.
diff --git a/SBVTestSuite/GoldFiles/allSat4.gold b/SBVTestSuite/GoldFiles/allSat4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat4.gold
@@ -0,0 +1,1 @@
+No solutions found.
diff --git a/SBVTestSuite/GoldFiles/allSat5.gold b/SBVTestSuite/GoldFiles/allSat5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat5.gold
@@ -0,0 +1,19 @@
+Solution #1:
+  s0 = 0 :: Word8
+  s1 = 1 :: Word8
+Solution #2:
+  s0 = 0 :: Word8
+  s1 = 2 :: Word8
+Solution #3:
+  s0 = 0 :: Word8
+  s1 = 3 :: Word8
+Solution #4:
+  s0 = 1 :: Word8
+  s1 = 2 :: Word8
+Solution #5:
+  s0 = 1 :: Word8
+  s1 = 3 :: Word8
+Solution #6:
+  s0 = 2 :: Word8
+  s1 = 3 :: Word8
+Found 6 different solutions.
diff --git a/SBVTestSuite/GoldFiles/allSat6.gold b/SBVTestSuite/GoldFiles/allSat6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat6.gold
@@ -0,0 +1,10 @@
+Solution #1:
+  x = 0 :: Word8
+  y = 2 :: Word8
+Solution #2:
+  x = 0 :: Word8
+  y = 1 :: Word8
+Solution #3:
+  x = 1 :: Word8
+  y = 2 :: Word8
+Found 3 different solutions.
diff --git a/SBVTestSuite/GoldFiles/allSat7.gold b/SBVTestSuite/GoldFiles/allSat7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat7.gold
@@ -0,0 +1,34482 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s5 () Int 15)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "y"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "z"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (>= s0 s3))
+[GOOD] (define-fun s6 () Bool (<= s0 s5))
+[GOOD] (define-fun s7 () Bool (and s4 s6))
+[GOOD] (define-fun s8 () Bool (>= s1 s3))
+[GOOD] (define-fun s9 () Bool (<= s1 s5))
+[GOOD] (define-fun s10 () Bool (and s8 s9))
+[GOOD] (define-fun s11 () Bool (>= s2 s3))
+[GOOD] (define-fun s12 () Bool (<= s2 s5))
+[GOOD] (define-fun s13 () Bool (and s11 s12))
+[GOOD] (define-fun s14 () Bool (distinct s0 s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[GOOD] (assert s10)
+[GOOD] (assert s13)
+[GOOD] (assert s14)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (define-fun s15 () Bool (distinct s0 s3))
+[GOOD] (assert s15)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (define-fun s16 () Int 2)
+[GOOD] (define-fun s17 () Bool (distinct s0 s16))
+[GOOD] (assert s17)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (define-fun s18 () Int 3)
+[GOOD] (define-fun s19 () Bool (distinct s0 s18))
+[GOOD] (assert s19)
+Fast allSat, Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (define-fun s20 () Int 4)
+[GOOD] (define-fun s21 () Bool (distinct s0 s20))
+[GOOD] (assert s21)
+Fast allSat, Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (define-fun s22 () Int 5)
+[GOOD] (define-fun s23 () Bool (distinct s0 s22))
+[GOOD] (assert s23)
+Fast allSat, Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (define-fun s24 () Int 6)
+[GOOD] (define-fun s25 () Bool (distinct s0 s24))
+[GOOD] (assert s25)
+Fast allSat, Looking for solution 7
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (define-fun s26 () Int 7)
+[GOOD] (define-fun s27 () Bool (distinct s0 s26))
+[GOOD] (assert s27)
+Fast allSat, Looking for solution 8
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (define-fun s28 () Int 8)
+[GOOD] (define-fun s29 () Bool (distinct s0 s28))
+[GOOD] (assert s29)
+Fast allSat, Looking for solution 9
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (define-fun s30 () Int 9)
+[GOOD] (define-fun s31 () Bool (distinct s0 s30))
+[GOOD] (assert s31)
+Fast allSat, Looking for solution 10
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (define-fun s32 () Int 10)
+[GOOD] (define-fun s33 () Bool (distinct s0 s32))
+[GOOD] (assert s33)
+Fast allSat, Looking for solution 11
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (define-fun s34 () Int 11)
+[GOOD] (define-fun s35 () Bool (distinct s0 s34))
+[GOOD] (assert s35)
+Fast allSat, Looking for solution 12
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (define-fun s36 () Int 12)
+[GOOD] (define-fun s37 () Bool (distinct s0 s36))
+[GOOD] (assert s37)
+Fast allSat, Looking for solution 13
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (define-fun s38 () Int 13)
+[GOOD] (define-fun s39 () Bool (distinct s0 s38))
+[GOOD] (assert s39)
+Fast allSat, Looking for solution 14
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (define-fun s40 () Int 14)
+[GOOD] (define-fun s41 () Bool (distinct s0 s40))
+[GOOD] (assert s41)
+Fast allSat, Looking for solution 15
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (define-fun s42 () Bool (distinct s0 s5))
+[GOOD] (assert s42)
+Fast allSat, Looking for solution 16
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s43 () Bool (distinct s1 s40))
+[GOOD] (assert s43)
+[GOOD] (define-fun s44 () Bool (= s0 s5))
+[GOOD] (assert s44)
+Fast allSat, Looking for solution 16
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (define-fun s45 () Bool (distinct s1 s38))
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 17
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (define-fun s46 () Bool (distinct s1 s36))
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 18
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (define-fun s47 () Bool (distinct s1 s34))
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 19
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (define-fun s48 () Bool (distinct s1 s32))
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 20
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (define-fun s49 () Bool (distinct s1 s30))
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 21
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (define-fun s50 () Bool (distinct s1 s28))
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 22
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (define-fun s51 () Bool (distinct s1 s26))
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 23
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (define-fun s52 () Bool (distinct s1 s24))
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 24
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (define-fun s53 () Bool (distinct s1 s22))
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 25
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (define-fun s54 () Bool (distinct s1 s20))
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 26
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (define-fun s55 () Bool (distinct s1 s18))
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 27
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (define-fun s56 () Bool (distinct s1 s16))
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 28
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (define-fun s57 () Bool (distinct s1 s3))
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 29
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s58 () Bool (distinct s2 s16))
+[GOOD] (assert s58)
+[GOOD] (define-fun s59 () Bool (= s1 s3))
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 29
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (define-fun s60 () Bool (distinct s2 s18))
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 30
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (define-fun s61 () Bool (distinct s2 s20))
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 31
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (define-fun s62 () Bool (distinct s2 s22))
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 32
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (define-fun s63 () Bool (distinct s2 s24))
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 33
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (define-fun s64 () Bool (distinct s2 s26))
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 34
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (define-fun s65 () Bool (distinct s2 s28))
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 35
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (define-fun s66 () Bool (distinct s2 s30))
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 36
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (define-fun s67 () Bool (distinct s2 s32))
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 37
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (define-fun s68 () Bool (distinct s2 s34))
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 38
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (define-fun s69 () Bool (distinct s2 s36))
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 39
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (define-fun s70 () Bool (distinct s2 s38))
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 40
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (define-fun s71 () Bool (distinct s2 s40))
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 41
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s72 () Bool (distinct s2 s3))
+[GOOD] (assert s72)
+[GOOD] (define-fun s73 () Bool (= s1 s16))
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 41
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 42
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 43
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 44
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 45
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 46
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 47
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 48
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 49
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 50
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 51
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 52
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 53
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (define-fun s74 () Bool (= s1 s18))
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 53
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 54
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 55
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 56
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 57
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 58
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 59
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 60
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 61
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 62
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 63
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 64
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 65
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (define-fun s75 () Bool (= s1 s20))
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 65
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 66
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 67
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 68
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 69
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 70
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 71
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 72
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 73
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 74
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 75
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 76
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 77
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (define-fun s76 () Bool (= s1 s22))
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 77
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 78
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 79
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 80
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 81
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 82
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 83
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 84
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 85
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 86
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 87
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 88
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 89
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (define-fun s77 () Bool (= s1 s24))
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 89
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 90
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 91
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 92
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 93
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 94
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 95
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 96
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 97
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 98
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 99
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 100
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 101
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (define-fun s78 () Bool (= s1 s26))
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 101
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 102
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 103
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 104
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 105
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 106
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 107
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 108
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 109
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 110
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 111
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 112
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 113
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (define-fun s79 () Bool (= s1 s28))
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 113
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 114
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 115
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 116
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 117
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 118
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 119
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 120
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 121
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 122
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 123
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 124
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 125
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (define-fun s80 () Bool (= s1 s30))
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 125
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 126
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 127
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 128
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 129
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 130
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 131
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 132
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 133
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 134
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 135
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 136
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 137
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s66)
+[GOOD] (define-fun s81 () Bool (= s1 s32))
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 137
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 138
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 139
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 140
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 141
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 142
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 143
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 144
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 145
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 146
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 147
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 148
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 149
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (define-fun s82 () Bool (= s1 s34))
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 149
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 150
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 151
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 152
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 153
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 154
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 155
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 156
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 157
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 158
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 159
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 160
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 161
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (define-fun s83 () Bool (= s1 s36))
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 161
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 162
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 163
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 164
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 165
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 166
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 167
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 168
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 169
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 170
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 171
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 172
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 173
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (define-fun s84 () Bool (= s1 s38))
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 173
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 174
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 175
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 176
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 177
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 178
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 179
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 180
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 181
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 182
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 183
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 184
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 185
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s44)
+[GOOD] (define-fun s85 () Bool (= s1 s40))
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 185
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 186
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 187
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 188
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 189
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 190
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 191
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 192
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 193
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 194
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 195
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 196
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 197
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s86 () Bool (distinct s1 s5))
+[GOOD] (assert s86)
+[GOOD] (define-fun s87 () Bool (= s0 s40))
+[GOOD] (assert s87)
+Fast allSat, Looking for solution 197
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 198
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 199
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 200
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 201
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 202
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 203
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 204
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 205
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 206
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 207
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 208
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 209
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 210
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 210
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 211
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 212
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 213
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 214
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 215
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 216
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 217
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 218
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 219
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 220
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 221
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (define-fun s88 () Bool (distinct s2 s5))
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 222
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 222
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 223
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 224
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 225
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 226
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 227
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 228
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 229
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 230
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 231
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 232
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 233
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 234
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 234
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 235
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 236
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 237
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 238
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 239
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 240
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 241
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 242
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 243
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 244
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 245
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 246
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 246
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 247
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 248
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 249
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 250
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 251
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 252
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 253
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 254
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 255
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 256
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 257
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 258
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 258
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 259
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 260
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 261
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 262
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 263
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 264
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 265
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 266
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 267
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 268
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 269
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 270
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 270
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 271
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 272
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 273
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 274
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 275
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 276
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 277
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 278
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 279
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 280
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 281
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 282
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 282
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 283
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 284
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 285
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 286
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 287
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 288
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 289
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 290
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 291
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 292
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 293
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 294
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 294
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 295
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 296
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 297
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 298
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 299
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 300
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 301
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 302
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 303
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 304
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 305
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 306
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 306
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 307
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 308
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 309
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 310
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 311
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 312
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 313
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 314
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 315
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 316
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 317
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 318
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s66)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 318
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 319
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 320
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 321
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 322
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 323
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 324
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 325
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 326
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 327
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 328
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 329
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 330
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 330
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 331
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 332
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 333
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 334
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 335
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 336
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 337
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 338
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 339
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 340
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 341
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 342
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 342
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 343
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 344
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 345
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 346
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 347
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 348
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 349
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 350
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 351
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 352
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 353
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 354
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 354
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 355
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 356
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 357
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 358
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 359
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 360
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 361
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 362
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 363
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 364
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 365
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 366
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s87)
+[GOOD] (define-fun s89 () Bool (= s1 s5))
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 366
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 367
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 368
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 369
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 370
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 371
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 372
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 373
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 374
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 375
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 376
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 377
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 14))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 378
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s43)
+[GOOD] (define-fun s90 () Bool (= s0 s38))
+[GOOD] (assert s90)
+Fast allSat, Looking for solution 378
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 379
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 380
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 381
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 382
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 383
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 384
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 385
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 386
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 387
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 388
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 389
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 390
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 391
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 391
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 392
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 393
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 394
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 395
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 396
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 397
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 398
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 399
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 400
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 401
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 402
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 403
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 403
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 404
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 405
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 406
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 407
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 408
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 409
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 410
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 411
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 412
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 413
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 414
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 415
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 415
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 416
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 417
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 418
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 419
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 420
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 421
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 422
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 423
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 424
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 425
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 426
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 427
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 427
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 428
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 429
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 430
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 431
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 432
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 433
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 434
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 435
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 436
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 437
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 438
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 439
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 439
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 440
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 441
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 442
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 443
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 444
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 445
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 446
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 447
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 448
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 449
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 450
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 451
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 451
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 452
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 453
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 454
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 455
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 456
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 457
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 458
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 459
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 460
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 461
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 462
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 463
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 463
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 464
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 465
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 466
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 467
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 468
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 469
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 470
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 471
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 472
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 473
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 474
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 475
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 475
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 476
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 477
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 478
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 479
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 480
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 481
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 482
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 483
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 484
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 485
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 486
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 487
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 487
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 488
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 489
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 490
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 491
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 492
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 493
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 494
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 495
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 496
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 497
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 498
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 499
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 499
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 500
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 501
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 502
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 503
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 504
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 505
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 506
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 507
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 508
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 509
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 510
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 511
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 511
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 512
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 513
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 514
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 515
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 516
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 517
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 518
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 519
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 520
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 521
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 522
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 523
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 523
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 524
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 525
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 526
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 527
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 528
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 529
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 530
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 531
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 532
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 533
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 534
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 535
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 535
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 536
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 537
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 538
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 539
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 540
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 541
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 542
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 543
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 544
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 545
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 546
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 547
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s90)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 547
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 548
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 549
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 550
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 551
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 552
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 553
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 554
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 555
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 556
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 557
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 558
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 559
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s45)
+[GOOD] (define-fun s91 () Bool (= s0 s36))
+[GOOD] (assert s91)
+Fast allSat, Looking for solution 559
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 560
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 561
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 562
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 563
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 564
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 565
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 566
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 567
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 568
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 569
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 570
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 571
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 572
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 572
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 573
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 574
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 575
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 576
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 577
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 578
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 579
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 580
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 581
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 582
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 583
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 584
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 584
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 585
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 586
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 587
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 588
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 589
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 590
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 591
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 592
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 593
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 594
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 595
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 596
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 596
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 597
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 598
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 599
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 600
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 601
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 602
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 603
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 604
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 605
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 606
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 607
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 608
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 608
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 609
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 610
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 611
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 612
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 613
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 614
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 615
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 616
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 617
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 618
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 619
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 620
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 620
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 621
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 622
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 623
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 624
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 625
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 626
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 627
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 628
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 629
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 630
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 631
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 632
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 632
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 633
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 634
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 635
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 636
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 637
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 638
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 639
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 640
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 641
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 642
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 643
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 644
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 644
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 645
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 646
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 647
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 648
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 649
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 650
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 651
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 652
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 653
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 654
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 655
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 656
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 656
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 657
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 658
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 659
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 660
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 661
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 662
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 663
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 664
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 665
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 666
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 667
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 668
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 668
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 669
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 670
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 671
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 672
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 673
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 674
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 675
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 676
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 677
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 678
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 679
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 680
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s66)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 680
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 681
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 682
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 683
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 684
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 685
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 686
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 687
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 688
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 689
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 690
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 691
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 692
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 692
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 693
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 694
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 695
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 696
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 697
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 698
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 699
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 700
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 701
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 702
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 703
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 704
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 704
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 705
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 706
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 707
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 708
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 709
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 710
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 711
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 712
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 713
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 714
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 715
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 716
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 716
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 717
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 718
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 719
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 720
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 721
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 722
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 723
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 724
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 725
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 726
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 727
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 728
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s91)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 728
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 729
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 730
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 731
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 732
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 733
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 734
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 735
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 736
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 737
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 738
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 739
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 740
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s46)
+[GOOD] (define-fun s92 () Bool (= s0 s34))
+[GOOD] (assert s92)
+Fast allSat, Looking for solution 740
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 741
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 742
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 743
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 744
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 745
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 746
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 747
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 748
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 749
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 750
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 751
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 752
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 753
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 753
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 754
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 755
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 756
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 757
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 758
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 759
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 760
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 761
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 762
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 763
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 764
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 765
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 765
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 766
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 767
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 768
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 769
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 770
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 771
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 772
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 773
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 774
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 775
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 776
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 777
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 777
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 778
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 779
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 780
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 781
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 782
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 783
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 784
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 785
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 786
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 787
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 788
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 789
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 789
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 790
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 791
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 792
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 793
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 794
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 795
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 796
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 797
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 798
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 799
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 800
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 801
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 801
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 802
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 803
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 804
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 805
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 806
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 807
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 808
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 809
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 810
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 811
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 812
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 813
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 813
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 814
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 815
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 816
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 817
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 818
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 819
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 820
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 821
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 822
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 823
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 824
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 825
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 825
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 826
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 827
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 828
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 829
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 830
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 831
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 832
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 833
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 834
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 835
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 836
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 837
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 837
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 838
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 839
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 840
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 841
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 842
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 843
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 844
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 845
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 846
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 847
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 848
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 849
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 849
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 850
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 851
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 852
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 853
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 854
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 855
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 856
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 857
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 858
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 859
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 860
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 861
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 861
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 862
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 863
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 864
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 865
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 866
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 867
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 868
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 869
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 870
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 871
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 872
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 873
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 873
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 874
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 875
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 876
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 877
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 878
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 879
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 880
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 881
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 882
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 883
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 884
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 885
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 885
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 886
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 887
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 888
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 889
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 890
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 891
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 892
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 893
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 894
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 895
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 896
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 897
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 897
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 898
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 899
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 900
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 901
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 902
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 903
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 904
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 905
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 906
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 907
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 908
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 909
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s92)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 909
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 910
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 911
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 912
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 913
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 914
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 915
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 916
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 917
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 918
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 919
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 920
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 11))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 921
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s47)
+[GOOD] (define-fun s93 () Bool (= s0 s32))
+[GOOD] (assert s93)
+Fast allSat, Looking for solution 921
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 922
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 923
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 924
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 925
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 926
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 927
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 928
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 929
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 930
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 931
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 932
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 933
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 934
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 934
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 935
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 936
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 937
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 938
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 939
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 940
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 941
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 942
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 943
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 944
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 945
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 946
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 946
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 947
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 948
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 949
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 950
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 951
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 952
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 953
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 954
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 955
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 956
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 957
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 958
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 958
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 959
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 960
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 961
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 962
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 963
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 964
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 965
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 966
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 967
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 968
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 969
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 970
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 970
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 971
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 972
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 973
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 974
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 975
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 976
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 977
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 978
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 979
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 980
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 981
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 982
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 982
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 983
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 984
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 985
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 986
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 987
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 988
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 989
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 990
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 991
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 992
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 993
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 994
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 994
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 995
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 996
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 997
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 998
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 999
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1000
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1001
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1002
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1003
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1004
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1005
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1006
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 1006
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1007
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1008
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1009
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1010
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1011
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1012
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1013
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1014
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1015
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1016
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1017
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1018
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 1018
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1019
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1020
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1021
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1022
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1023
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1024
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1025
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1026
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1027
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1028
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1029
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1030
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 1030
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1031
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1032
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1033
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1034
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1035
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1036
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1037
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1038
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1039
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1040
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1041
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1042
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 1042
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1043
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1044
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1045
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1046
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1047
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1048
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1049
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1050
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1051
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1052
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1053
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1054
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1054
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1055
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1056
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1057
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1058
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1059
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1060
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1061
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1062
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1063
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1064
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1065
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1066
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1066
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1067
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1068
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1069
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1070
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1071
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1072
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1073
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1074
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1075
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1076
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1077
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1078
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1078
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1079
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1080
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1081
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1082
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1083
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1084
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1085
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1086
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1087
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1088
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1089
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1090
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s93)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1090
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1091
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1092
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1093
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1094
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1095
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1096
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1097
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1098
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1099
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1100
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1101
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 10))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1102
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s48)
+[GOOD] (define-fun s94 () Bool (= s0 s30))
+[GOOD] (assert s94)
+Fast allSat, Looking for solution 1102
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 1103
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 1104
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 1105
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 1106
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 1107
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 1108
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 1109
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 1110
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 1111
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 1112
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 1113
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 1114
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 1115
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 1115
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1116
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1117
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1118
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1119
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1120
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1121
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1122
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1123
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1124
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1125
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1126
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1127
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 1127
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1128
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1129
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1130
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1131
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1132
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1133
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1134
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1135
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1136
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1137
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1138
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1139
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 1139
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1140
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1141
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1142
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1143
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1144
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1145
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1146
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1147
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1148
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1149
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1150
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1151
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 1151
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1152
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1153
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1154
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1155
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1156
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1157
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1158
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1159
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1160
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1161
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1162
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1163
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 1163
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1164
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1165
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1166
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1167
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1168
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1169
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1170
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1171
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1172
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1173
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1174
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1175
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 1175
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1176
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1177
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1178
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1179
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1180
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1181
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1182
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1183
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1184
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1185
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1186
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1187
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 1187
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1188
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1189
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1190
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1191
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1192
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1193
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1194
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1195
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1196
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1197
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1198
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1199
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 1199
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1200
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1201
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1202
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1203
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1204
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1205
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1206
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1207
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1208
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1209
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1210
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1211
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 1211
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1212
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1213
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1214
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1215
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1216
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1217
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1218
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1219
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1220
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1221
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1222
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1223
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1223
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1224
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1225
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1226
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1227
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1228
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1229
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1230
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1231
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1232
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1233
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1234
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1235
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1235
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1236
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1237
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1238
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1239
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1240
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1241
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1242
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1243
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1244
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1245
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1246
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1247
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1247
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1248
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1249
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1250
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1251
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1252
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1253
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1254
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1255
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1256
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1257
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1258
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1259
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1259
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1260
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1261
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1262
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1263
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1264
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1265
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1266
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1267
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1268
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1269
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1270
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1271
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s94)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 1271
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1272
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1273
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1274
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1275
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1276
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1277
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1278
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1279
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1280
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1281
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1282
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1283
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s49)
+[GOOD] (define-fun s95 () Bool (= s0 s28))
+[GOOD] (assert s95)
+Fast allSat, Looking for solution 1283
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 1284
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 1285
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 1286
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 1287
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 1288
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 1289
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 1290
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 1291
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 1292
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 1293
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 1294
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 1295
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 1296
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 1296
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1297
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1298
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1299
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1300
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1301
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1302
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1303
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1304
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1305
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1306
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1307
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1308
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 1308
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1309
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1310
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1311
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1312
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1313
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1314
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1315
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1316
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1317
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1318
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1319
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1320
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 1320
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1321
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1322
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1323
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1324
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1325
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1326
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1327
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1328
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1329
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1330
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1331
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1332
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 1332
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1333
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1334
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1335
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1336
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1337
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1338
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1339
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1340
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1341
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1342
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1343
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1344
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 1344
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1345
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1346
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1347
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1348
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1349
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1350
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1351
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1352
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1353
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1354
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1355
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1356
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 1356
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1357
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1358
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1359
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1360
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1361
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1362
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1363
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1364
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1365
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1366
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1367
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1368
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 1368
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1369
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1370
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1371
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1372
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1373
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1374
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1375
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1376
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1377
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1378
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1379
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1380
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 1380
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1381
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1382
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1383
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1384
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1385
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1386
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1387
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1388
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1389
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1390
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1391
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1392
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1392
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1393
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1394
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1395
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1396
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1397
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1398
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1399
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1400
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1401
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1402
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1403
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1404
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1404
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1405
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1406
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1407
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1408
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1409
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1410
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1411
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1412
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1413
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1414
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1415
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1416
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1416
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1417
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1418
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1419
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1420
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1421
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1422
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1423
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1424
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1425
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1426
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1427
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1428
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1428
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1429
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1430
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1431
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1432
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1433
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1434
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1435
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1436
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1437
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1438
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1439
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1440
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 1440
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1441
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1442
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1443
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1444
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1445
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1446
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1447
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1448
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1449
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1450
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1451
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1452
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s95)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 1452
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1453
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1454
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1455
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1456
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1457
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1458
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1459
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1460
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1461
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1462
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1463
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 8))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1464
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s50)
+[GOOD] (define-fun s96 () Bool (= s0 s26))
+[GOOD] (assert s96)
+Fast allSat, Looking for solution 1464
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 1465
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 1466
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 1467
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 1468
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 1469
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 1470
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 1471
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 1472
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 1473
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 1474
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 1475
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 1476
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 1477
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 1477
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1478
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1479
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1480
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1481
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1482
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1483
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1484
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1485
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1486
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1487
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1488
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1489
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 1489
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1490
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1491
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1492
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1493
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1494
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1495
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1496
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1497
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1498
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1499
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1500
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1501
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 1501
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1502
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1503
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1504
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1505
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1506
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1507
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1508
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1509
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1510
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1511
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1512
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1513
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 1513
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1514
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1515
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1516
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1517
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1518
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1519
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1520
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1521
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1522
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1523
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1524
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1525
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 1525
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1526
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1527
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1528
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1529
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1530
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1531
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1532
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1533
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1534
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1535
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1536
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1537
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 1537
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1538
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1539
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1540
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1541
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1542
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1543
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1544
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1545
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1546
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1547
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1548
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1549
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 1549
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1550
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1551
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1552
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1553
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1554
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1555
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1556
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1557
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1558
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1559
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1560
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1561
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1561
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1562
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1563
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1564
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1565
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1566
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1567
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1568
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1569
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1570
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1571
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1572
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1573
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1573
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1574
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1575
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1576
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1577
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1578
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1579
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1580
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1581
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1582
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1583
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1584
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1585
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1585
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1586
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1587
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1588
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1589
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1590
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1591
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1592
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1593
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1594
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1595
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1596
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1597
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1597
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1598
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1599
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1600
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1601
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1602
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1603
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1604
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1605
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1606
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1607
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1608
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1609
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 1609
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1610
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1611
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1612
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1613
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1614
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1615
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1616
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1617
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1618
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1619
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1620
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1621
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 1621
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1622
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1623
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1624
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1625
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1626
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1627
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1628
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1629
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1630
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1631
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1632
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1633
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s66)
+[GOOD] (assert s96)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 1633
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1634
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1635
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1636
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1637
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1638
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1639
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1640
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1641
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1642
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1643
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1644
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 7))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1645
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s51)
+[GOOD] (define-fun s97 () Bool (= s0 s24))
+[GOOD] (assert s97)
+Fast allSat, Looking for solution 1645
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 1646
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 1647
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 1648
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 1649
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 1650
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 1651
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 1652
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 1653
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 1654
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 1655
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 1656
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 1657
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 1658
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 1658
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1659
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1660
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1661
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1662
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1663
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1664
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1665
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1666
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1667
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1668
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1669
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1670
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1670
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1671
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1672
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1673
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1674
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1675
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1676
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1677
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1678
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1679
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1680
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1681
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1682
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 1682
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1683
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1684
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1685
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1686
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1687
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1688
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1689
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1690
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1691
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1692
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1693
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1694
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1694
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1695
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1696
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1697
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1698
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1699
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1700
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1701
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1702
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1703
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1704
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1705
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1706
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 1706
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1707
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1708
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1709
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1710
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1711
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1712
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1713
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1714
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1715
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1716
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1717
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1718
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1718
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1719
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1720
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1721
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1722
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1723
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1724
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1725
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1726
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1727
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1728
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1729
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1730
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 1730
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1731
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1732
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1733
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1734
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1735
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1736
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1737
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1738
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1739
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1740
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1741
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1742
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1742
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1743
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1744
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1745
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1746
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1747
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1748
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1749
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1750
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1751
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1752
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1753
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1754
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 1754
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1755
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1756
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1757
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1758
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1759
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1760
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1761
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1762
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1763
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1764
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1765
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1766
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 1766
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1767
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1768
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1769
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1770
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1771
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1772
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1773
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1774
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1775
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1776
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1777
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1778
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 1778
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1779
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1780
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1781
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1782
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1783
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1784
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1785
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1786
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1787
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1788
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1789
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1790
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 1790
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1791
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1792
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1793
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1794
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1795
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1796
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1797
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1798
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1799
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1800
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1801
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1802
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s66)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 1802
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1803
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1804
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1805
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1806
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1807
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1808
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1809
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1810
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1811
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1812
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1813
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1814
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s65)
+[GOOD] (assert s97)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 1814
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1815
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1816
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1817
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1818
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1819
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1820
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1821
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 1822
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1823
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1824
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1825
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1826
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s52)
+[GOOD] (define-fun s98 () Bool (= s0 s22))
+[GOOD] (assert s98)
+Fast allSat, Looking for solution 1826
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 1827
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 1828
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 1829
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 1830
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 1831
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 1832
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 1833
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 1834
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 1835
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 1836
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 1837
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 1838
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 1839
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 1839
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1840
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1841
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1842
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1843
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1844
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1845
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1846
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1847
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1848
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1849
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1850
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1851
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 1851
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1852
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1853
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1854
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1855
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1856
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1857
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1858
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1859
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1860
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1861
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1862
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1863
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 1863
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1864
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1865
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1866
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1867
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1868
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1869
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1870
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1871
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1872
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1873
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1874
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1875
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 1875
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 1876
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1877
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1878
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1879
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1880
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1881
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1882
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1883
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1884
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1885
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1886
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1887
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 1887
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1888
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1889
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1890
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1891
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1892
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1893
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1894
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1895
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1896
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1897
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1898
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1899
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 1899
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1900
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1901
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1902
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1903
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1904
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1905
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1906
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1907
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1908
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1909
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1910
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1911
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 1911
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1912
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1913
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1914
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1915
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1916
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1917
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1918
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1919
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1920
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1921
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1922
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1923
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 1923
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1924
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1925
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1926
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1927
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1928
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1929
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1930
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1931
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1932
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1933
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1934
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1935
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 1935
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1936
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1937
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1938
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1939
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1940
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1941
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1942
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1943
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1944
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1945
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1946
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1947
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 1947
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1948
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1949
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1950
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1951
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1952
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1953
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1954
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1955
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1956
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1957
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1958
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1959
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 1959
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1960
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1961
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1962
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1963
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1964
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1965
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1966
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1967
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1968
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1969
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1970
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1971
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 1971
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1972
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1973
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1974
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1975
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1976
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1977
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 1978
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1979
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1980
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1981
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1982
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1983
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 1983
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1984
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1985
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1986
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1987
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 1988
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 1989
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 1990
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 1991
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 1992
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 1993
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 1994
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 1995
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s64)
+[GOOD] (assert s98)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 1995
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 1996
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 1997
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 1998
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 1999
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2000
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2001
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2002
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2003
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2004
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2005
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2006
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2007
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s53)
+[GOOD] (define-fun s99 () Bool (= s0 s20))
+[GOOD] (assert s99)
+Fast allSat, Looking for solution 2007
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 2008
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 2009
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 2010
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 2011
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 2012
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 2013
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 2014
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 2015
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 2016
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 2017
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 2018
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 2019
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 2020
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 2020
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2021
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2022
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2023
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2024
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2025
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2026
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2027
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2028
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2029
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2030
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2031
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2032
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 2032
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2033
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2034
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2035
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2036
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2037
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2038
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2039
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2040
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2041
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2042
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2043
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2044
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 2044
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2045
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2046
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2047
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2048
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2049
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2050
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2051
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2052
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2053
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2054
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2055
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2056
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 2056
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2057
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2058
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2059
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2060
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2061
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2062
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2063
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2064
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2065
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2066
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2067
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2068
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 2068
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2069
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2070
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2071
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2072
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2073
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2074
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2075
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2076
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2077
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2078
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2079
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2080
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 2080
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2081
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2082
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2083
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2084
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2085
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2086
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2087
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2088
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2089
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2090
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2091
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2092
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 2092
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2093
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2094
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2095
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2096
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2097
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2098
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2099
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2100
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2101
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2102
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2103
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2104
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 2104
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2105
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2106
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2107
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2108
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2109
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2110
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2111
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2112
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2113
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2114
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2115
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2116
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 2116
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2117
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2118
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2119
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2120
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2121
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2122
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2123
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2124
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2125
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2126
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2127
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2128
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 2128
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2129
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2130
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2131
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2132
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2133
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2134
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2135
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2136
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2137
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2138
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2139
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2140
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 2140
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2141
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2142
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2143
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2144
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2145
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2146
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2147
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2148
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2149
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2150
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2151
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2152
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 2152
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2153
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2154
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2155
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2156
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2157
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2158
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2159
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2160
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2161
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2162
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2163
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2164
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 2164
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2165
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2166
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2167
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2168
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2169
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2170
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2171
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2172
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2173
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2174
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2175
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2176
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s63)
+[GOOD] (assert s99)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 2176
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2177
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2178
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2179
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2180
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2181
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2182
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2183
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2184
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2185
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2186
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2187
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2188
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s54)
+[GOOD] (define-fun s100 () Bool (= s0 s18))
+[GOOD] (assert s100)
+Fast allSat, Looking for solution 2188
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 2189
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 2190
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 2191
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 2192
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 2193
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 2194
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 2195
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 2196
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 2197
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 2198
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 2199
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s56)
+Fast allSat, Looking for solution 2200
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 2201
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s58)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 2201
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2202
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2203
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2204
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2205
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2206
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2207
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2208
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2209
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2210
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2211
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2212
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2213
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s72)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 2213
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2214
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2215
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2216
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2217
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2218
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2219
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2220
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2221
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2222
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2223
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2224
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2225
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 2225
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2226
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2227
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2228
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2229
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2230
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2231
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2232
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2233
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2234
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2235
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2236
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2237
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 2237
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2238
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2239
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2240
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2241
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2242
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2243
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2244
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2245
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2246
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2247
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2248
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2249
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 2249
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2250
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2251
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2252
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2253
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2254
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2255
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2256
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2257
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2258
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2259
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2260
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2261
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 2261
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2262
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2263
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2264
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2265
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2266
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2267
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2268
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2269
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2270
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2271
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2272
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2273
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 2273
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2274
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2275
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2276
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2277
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2278
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2279
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2280
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2281
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2282
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2283
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2284
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2285
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 2285
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2286
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2287
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2288
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2289
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2290
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2291
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2292
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2293
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2294
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2295
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2296
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2297
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 2297
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2298
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2299
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2300
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2301
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2302
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2303
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2304
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2305
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2306
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2307
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2308
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2309
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 2309
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2310
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2311
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2312
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2313
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2314
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2315
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2316
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2317
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2318
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2319
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2320
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2321
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 2321
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2322
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2323
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2324
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2325
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2326
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2327
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2328
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2329
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2330
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2331
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2332
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2333
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 2333
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2334
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2335
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2336
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2337
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2338
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2339
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2340
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2341
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2342
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2343
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2344
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2345
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 2345
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2346
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2347
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2348
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2349
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2350
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2351
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2352
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2353
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2354
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2355
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2356
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2357
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s62)
+[GOOD] (assert s100)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 2357
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2358
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2359
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2360
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2361
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2362
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2363
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2364
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2365
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2366
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2367
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2368
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2369
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s55)
+[GOOD] (define-fun s101 () Bool (= s0 s16))
+[GOOD] (assert s101)
+Fast allSat, Looking for solution 2369
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s57)
+Fast allSat, Looking for solution 2370
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 2371
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 2372
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 2373
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 2374
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 2375
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 2376
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 2377
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 2378
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 2379
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 2380
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 2381
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 2382
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 2382
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2383
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2384
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2385
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2386
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2387
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2388
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2389
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2390
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2391
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2392
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2393
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2394
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 2394
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2395
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2396
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2397
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2398
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2399
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2400
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2401
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2402
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2403
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2404
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2405
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2406
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 2406
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2407
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2408
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2409
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2410
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2411
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2412
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2413
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2414
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2415
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2416
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2417
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2418
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s70)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 2418
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2419
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2420
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2421
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2422
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2423
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2424
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2425
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2426
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2427
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2428
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2429
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2430
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s69)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 2430
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2431
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2432
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2433
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2434
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2435
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2436
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2437
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2438
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2439
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2440
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2441
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2442
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s68)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 2442
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2443
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2444
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2445
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2446
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2447
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2448
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2449
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2450
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2451
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2452
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2453
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2454
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 2454
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2455
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2456
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2457
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2458
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2459
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2460
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2461
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2462
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2463
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2464
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2465
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2466
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 2466
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2467
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2468
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2469
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2470
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2471
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2472
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2473
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2474
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2475
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2476
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2477
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2478
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 2478
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2479
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2480
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2481
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2482
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2483
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2484
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2485
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2486
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2487
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2488
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2489
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2490
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 2490
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2491
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2492
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2493
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2494
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2495
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2496
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2497
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2498
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2499
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2500
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2501
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2502
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 2502
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2503
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2504
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2505
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2506
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2507
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2508
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2509
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2510
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2511
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2512
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2513
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2514
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 2514
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2515
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2516
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2517
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2518
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2519
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2520
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2521
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2522
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2523
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2524
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2525
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2526
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s67)
+[GOOD] (assert s59)
+Fast allSat, Looking for solution 2526
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2527
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2528
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2529
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2530
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2531
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2532
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2533
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2534
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2535
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2536
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2537
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2538
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s61)
+[GOOD] (assert s101)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 2538
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2539
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2540
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2541
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2542
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2543
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2544
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2545
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2546
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2547
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2548
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2549
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[GOOD] (push 1)
+[GOOD] (assert s72)
+Fast allSat, Looking for solution 2550
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s56)
+[GOOD] (define-fun s102 () Bool (= s0 s3))
+[GOOD] (assert s102)
+Fast allSat, Looking for solution 2550
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s55)
+Fast allSat, Looking for solution 2551
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s54)
+Fast allSat, Looking for solution 2552
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s53)
+Fast allSat, Looking for solution 2553
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s52)
+Fast allSat, Looking for solution 2554
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s51)
+Fast allSat, Looking for solution 2555
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s50)
+Fast allSat, Looking for solution 2556
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s49)
+Fast allSat, Looking for solution 2557
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s48)
+Fast allSat, Looking for solution 2558
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s47)
+Fast allSat, Looking for solution 2559
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s46)
+Fast allSat, Looking for solution 2560
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s45)
+Fast allSat, Looking for solution 2561
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s43)
+Fast allSat, Looking for solution 2562
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s86)
+Fast allSat, Looking for solution 2563
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s89)
+Fast allSat, Looking for solution 2563
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2564
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2565
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2566
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2567
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2568
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2569
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2570
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2571
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2572
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2573
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2574
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2575
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s88)
+[GOOD] (assert s85)
+Fast allSat, Looking for solution 2575
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2576
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2577
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2578
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2579
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2580
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2581
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2582
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2583
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2584
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2585
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2586
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 14))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2587
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s84)
+Fast allSat, Looking for solution 2587
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2588
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2589
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2590
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2591
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2592
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2593
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2594
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2595
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2596
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2597
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2598
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 13))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2599
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s83)
+Fast allSat, Looking for solution 2599
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2600
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2601
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2602
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2603
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2604
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2605
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2606
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2607
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2608
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2609
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2610
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 12))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2611
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s82)
+Fast allSat, Looking for solution 2611
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2612
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2613
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2614
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2615
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2616
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2617
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2618
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2619
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2620
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2621
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2622
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2623
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s81)
+Fast allSat, Looking for solution 2623
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2624
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2625
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2626
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2627
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2628
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2629
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2630
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2631
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2632
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2633
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2634
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2635
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s80)
+Fast allSat, Looking for solution 2635
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2636
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2637
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2638
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2639
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2640
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2641
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2642
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2643
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2644
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2645
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2646
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 9))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2647
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s79)
+Fast allSat, Looking for solution 2647
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2648
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2649
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2650
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2651
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2652
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2653
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2654
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2655
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2656
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2657
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2658
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 8))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2659
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s78)
+Fast allSat, Looking for solution 2659
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2660
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2661
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2662
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2663
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2664
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2665
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2666
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2667
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2668
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2669
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2670
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2671
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s77)
+Fast allSat, Looking for solution 2671
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2672
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2673
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2674
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2675
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2676
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2677
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2678
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2679
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2680
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2681
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2682
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 6))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2683
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s76)
+Fast allSat, Looking for solution 2683
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2684
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2685
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2686
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2687
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2688
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2689
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2690
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2691
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2692
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2693
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2694
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 5))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2695
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s75)
+Fast allSat, Looking for solution 2695
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2696
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2697
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2698
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2699
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2700
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2701
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2702
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2703
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2704
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2705
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[GOOD] (push 1)
+[GOOD] (assert s60)
+Fast allSat, Looking for solution 2706
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 4))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2707
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s71)
+[GOOD] (assert s74)
+Fast allSat, Looking for solution 2707
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2708
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2709
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2710
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2711
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2712
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2713
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2714
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2715
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2716
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2717
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2718
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s2))
+[RECV] ((s2 2))
+[GOOD] (push 1)
+[GOOD] (assert s58)
+Fast allSat, Looking for solution 2719
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s60)
+[GOOD] (assert s102)
+[GOOD] (assert s73)
+Fast allSat, Looking for solution 2719
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 4))
+[GOOD] (push 1)
+[GOOD] (assert s61)
+Fast allSat, Looking for solution 2720
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 5))
+[GOOD] (push 1)
+[GOOD] (assert s62)
+Fast allSat, Looking for solution 2721
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 6))
+[GOOD] (push 1)
+[GOOD] (assert s63)
+Fast allSat, Looking for solution 2722
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 7))
+[GOOD] (push 1)
+[GOOD] (assert s64)
+Fast allSat, Looking for solution 2723
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 8))
+[GOOD] (push 1)
+[GOOD] (assert s65)
+Fast allSat, Looking for solution 2724
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 9))
+[GOOD] (push 1)
+[GOOD] (assert s66)
+Fast allSat, Looking for solution 2725
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 10))
+[GOOD] (push 1)
+[GOOD] (assert s67)
+Fast allSat, Looking for solution 2726
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 11))
+[GOOD] (push 1)
+[GOOD] (assert s68)
+Fast allSat, Looking for solution 2727
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 12))
+[GOOD] (push 1)
+[GOOD] (assert s69)
+Fast allSat, Looking for solution 2728
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 13))
+[GOOD] (push 1)
+[GOOD] (assert s70)
+Fast allSat, Looking for solution 2729
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 14))
+[GOOD] (push 1)
+[GOOD] (assert s71)
+Fast allSat, Looking for solution 2730
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 15))
+[GOOD] (push 1)
+[GOOD] (assert s88)
+Fast allSat, Looking for solution 2731
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/allSat8.gold b/SBVTestSuite/GoldFiles/allSat8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/allSat8.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun f (Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s2 1))
+                                 (let ((l1_s1 (f l1_s0)))
+                                 (let ((l1_s3 (+ l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (f))
+[RECV] ((f (lambda ((x!1 Int)) (+ 1 x!1))))
+*** Solver   : Z3
+*** Exit code: ExitFailure (-15)
+
+EXCEPTION CAUGHT:
+
+*** allSat: Unsupported: Building a rejecting instance for:
+***
+***     f :: SInteger -> SInteger
+***     f x = x + 1
+***
+*** At this time, SBV cannot compute allSat when the model has a non-table definition.
+***
+*** You can ignore specific functions via the 'isNonModelVar' filter:
+***
+***    allSatWith z3{isNonModelVar = (`elem` ["f"])} ...
+***
+*** Or you can ignore all uninterpreted functions for all-sat purposes using the 'allSatTrackUFs' parameter:
+***
+***    allSatWith z3{allSatTrackUFs = False} ...
+***
+*** You can see the response from the solver by running with the '{verbose = True}' option.
+***
+*** NB. If this is a use case you'd like SBV to support, please get in touch!
+
diff --git a/SBVTestSuite/GoldFiles/arbFp_opt_1.gold b/SBVTestSuite/GoldFiles/arbFp_opt_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/arbFp_opt_1.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  s0               = 65504.0 :: FloatingPoint 5 11
+  toMetricSpace(x) =   64511 :: Word16
+  x                = 65504.0 :: FloatingPoint 5 11
diff --git a/SBVTestSuite/GoldFiles/arrayGetValTest1.gold b/SBVTestSuite/GoldFiles/arrayGetValTest1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/arrayGetValTest1.gold
@@ -0,0 +1,36 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s3 () (Array Int Int) (store s0 s1 s2))
+[GOOD] (define-fun s4 () Int (select s3 s1))
+[SEND] (get-value (s4))
+[RECV] ((s4 2))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:2
+DONE!
diff --git a/SBVTestSuite/GoldFiles/array_caching_01.gold b/SBVTestSuite/GoldFiles/array_caching_01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_caching_01.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s3 () (Array Int Int) (store ((as const (Array Int Int)) 0) 0 2))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () Int (+ s0 s4))
+[GOOD] (define-fun s6 () Int (select s3 s5))
+[GOOD] (define-fun s7 () (Array Int Int) (store s3 s1 s6))
+[GOOD] (define-fun s8 () Int (select s7 s1))
+[GOOD] (define-fun s9 () (Array Int Int) (store s3 s5 s4))
+[GOOD] (define-fun s10 () Int (select s9 s1))
+[GOOD] (define-fun s11 () Int (ite s2 s8 s10))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (- 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  x = -1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_caching_02.gold b/SBVTestSuite/GoldFiles/array_caching_02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_caching_02.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s3 () (Array Int Int) (store ((as const (Array Int Int)) 0) 0 2))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] (define-fun s5 () Int (+ s0 s4))
+[GOOD] (define-fun s6 () (Array Int Int) (store s3 s5 s4))
+[GOOD] (define-fun s7 () Int (select s6 s1))
+[GOOD] (define-fun s8 () Int (select s3 s5))
+[GOOD] (define-fun s9 () (Array Int Int) (store s3 s1 s8))
+[GOOD] (define-fun s10 () Int (select s9 s1))
+[GOOD] (define-fun s11 () Int (ite s2 s7 s10))
+[GOOD] (define-fun s12 () Bool (= s4 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (- 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  x = -1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_1.gold b/SBVTestSuite/GoldFiles/array_misc_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_1.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array Bool Int) (store (store ((as const (Array Bool Int)) 3) false 0) true 1))
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (select s1 s0))
+[GOOD] (define-fun s4 () Bool (<= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s4))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/array_misc_11.gold b/SBVTestSuite/GoldFiles/array_misc_11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_11.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () (SBVTuple2 Int Int) (mkSBVTuple2 1 2))
+[GOOD] (define-fun s3 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (SBVTuple2 Int Int) Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array (SBVTuple2 Int Int) Int)) 3)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([], 3) :: Array (Integer, Integer) Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_12.gold b/SBVTestSuite/GoldFiles/array_misc_12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_12.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 3)
+[GOOD] (define-fun s3 () (SBVTuple2 Int Int) (mkSBVTuple2 1 2))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int (SBVTuple2 Int Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (SBVTuple2 Int Int) (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array Int (SBVTuple2 Int Int))) (mkSBVTuple2 1 2))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([], (1,2)) :: Array Integer (Integer, Integer)
diff --git a/SBVTestSuite/GoldFiles/array_misc_13.gold b/SBVTestSuite/GoldFiles/array_misc_13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_13.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () (SBVTuple2 Int Int) (mkSBVTuple2 1 2))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (SBVTuple2 Int Int) (SBVTuple2 Int Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (SBVTuple2 Int Int) (select s0 s1))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array (SBVTuple2 Int Int) (SBVTuple2 Int Int))) (mkSBVTuple2 1 2))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([], (1,2)) :: Array (Integer, Integer) (Integer, Integer)
diff --git a/SBVTestSuite/GoldFiles/array_misc_14.gold b/SBVTestSuite/GoldFiles/array_misc_14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_14.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int (_ FloatingPoint  8 24)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (select s0 s1))
+[GOOD] (define-fun s3 () Bool (fp.isNaN s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array Int (_ FloatingPoint 8 24))) (_ NaN 8 24))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([], NaN) :: Array Integer Float
diff --git a/SBVTestSuite/GoldFiles/array_misc_15.gold b/SBVTestSuite/GoldFiles/array_misc_15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_15.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ FloatingPoint  8 24) (_ NaN 8 24))
+[GOOD] (define-fun s3 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (_ FloatingPoint  8 24) Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array (_ FloatingPoint 8 24) Int)) 3)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([], 3) :: Array Float Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_16.gold b/SBVTestSuite/GoldFiles/array_misc_16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_16.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint  8 24) Int) (store ((as const (Array (_ FloatingPoint  8 24) Int)) 3) (_ +zero 8 24) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (_ +zero 8 24))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_17.gold b/SBVTestSuite/GoldFiles/array_misc_17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_17.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 11 53) Int) (store ((as const (Array (_ FloatingPoint 11 53) Int)) 3) (_ +zero 11 53) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 11 53) (_ +zero 11 53))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_18.gold b/SBVTestSuite/GoldFiles/array_misc_18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_18.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 10 4) Int) (store ((as const (Array (_ FloatingPoint 10 4) Int)) 3) (_ +zero 10 4) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 10 4) (_ +zero 10 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_19.gold b/SBVTestSuite/GoldFiles/array_misc_19.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_19.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint  8 24) Int) (store ((as const (Array (_ FloatingPoint  8 24) Int)) 3) (_ +zero 8 24) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (_ -zero 8 24))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_2.gold b/SBVTestSuite/GoldFiles/array_misc_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_2.gold
@@ -0,0 +1,57 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () Int 4)
+[GOOD] (define-fun s8 () Int 5)
+[GOOD] (define-fun s11 () Int 12)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] (declare-fun s2 () Int)
+[GOOD] (declare-fun s3 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (select s0 s1))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Int (select s0 s2))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s10 () Int (select s0 s3))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s13 () Bool (and s9 s12))
+[GOOD] (define-fun s14 () Bool (and s6 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array Int Int)) 4) 6 12) 3 5)))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s2))
+[RECV] ((s2 3))
+[SEND] (get-value (s3))
+[RECV] ((s3 6))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = ([(3,5),(6,12)], 4) :: Array Integer Integer
+  s1 =                   2 :: Integer
+  s2 =                   3 :: Integer
+  s3 =                   6 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_20.gold b/SBVTestSuite/GoldFiles/array_misc_20.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_20.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 11 53) Int) (store ((as const (Array (_ FloatingPoint 11 53) Int)) 3) (_ +zero 11 53) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 11 53) (_ -zero 11 53))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_21.gold b/SBVTestSuite/GoldFiles/array_misc_21.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_21.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 10 4) Int) (store ((as const (Array (_ FloatingPoint 10 4) Int)) 3) (_ +zero 10 4) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 10 4) (_ -zero 10 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_22.gold b/SBVTestSuite/GoldFiles/array_misc_22.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_22.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint  8 24) Int) (store ((as const (Array (_ FloatingPoint  8 24) Int)) 3) (_ NaN 8 24) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (_ NaN 8 24))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_23.gold b/SBVTestSuite/GoldFiles/array_misc_23.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_23.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 11 53) Int) (store ((as const (Array (_ FloatingPoint 11 53) Int)) 3) (_ NaN 11 53) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 11 53) (_ NaN 11 53))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_24.gold b/SBVTestSuite/GoldFiles/array_misc_24.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_24.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 10 4) Int) (store ((as const (Array (_ FloatingPoint 10 4) Int)) 3) (_ NaN 10 4) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 10 4) (_ NaN 10 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_25.gold b/SBVTestSuite/GoldFiles/array_misc_25.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_25.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint  8 24) Int) (store ((as const (Array (_ FloatingPoint  8 24) Int)) 3) (_ +oo 8 24) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (_ +oo 8 24))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_26.gold b/SBVTestSuite/GoldFiles/array_misc_26.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_26.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 11 53) Int) (store ((as const (Array (_ FloatingPoint 11 53) Int)) 3) (_ +oo 11 53) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 11 53) (_ +oo 11 53))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_27.gold b/SBVTestSuite/GoldFiles/array_misc_27.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_27.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 10 4) Int) (store ((as const (Array (_ FloatingPoint 10 4) Int)) 3) (_ +oo 10 4) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 10 4) (_ +oo 10 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 12))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 12 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_28.gold b/SBVTestSuite/GoldFiles/array_misc_28.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_28.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint  8 24) Int) (store ((as const (Array (_ FloatingPoint  8 24) Int)) 3) (_ +oo 8 24) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (_ -oo 8 24))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_29.gold b/SBVTestSuite/GoldFiles/array_misc_29.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_29.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 11 53) Int) (store ((as const (Array (_ FloatingPoint 11 53) Int)) 3) (_ +oo 11 53) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 11 53) (_ -oo 11 53))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_3.gold b/SBVTestSuite/GoldFiles/array_misc_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_3.gold
@@ -0,0 +1,27 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/array_misc_30.gold b/SBVTestSuite/GoldFiles/array_misc_30.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_30.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ FloatingPoint 10 4) Int) (store ((as const (Array (_ FloatingPoint 10 4) Int)) 3) (_ +oo 10 4) 12))
+[GOOD] (define-fun s2 () (_ FloatingPoint 10 4) (_ -oo 10 4))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (select s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/array_misc_31.gold b/SBVTestSuite/GoldFiles/array_misc_31.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_31.gold
@@ -0,0 +1,27 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/array_misc_5.gold b/SBVTestSuite/GoldFiles/array_misc_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_5.gold
@@ -0,0 +1,33 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s0 () (Array (_ BitVec 2) (_ BitVec 2)) (store (store (store (store ((as const (Array (_ BitVec 2) (_ BitVec 2))) #b00) #b11 #b11) #b10 #b10) #b01 #b01) #b00 #b00))
+[GOOD] (define-fun s1 () (Array (_ BitVec 2) (_ BitVec 2)) (store (store (store (store ((as const (Array (_ BitVec 2) (_ BitVec 2))) #b01) #b11 #b11) #b10 #b10) #b01 #b01) #b00 #b00))
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s2))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/array_misc_7.gold b/SBVTestSuite/GoldFiles/array_misc_7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_7.gold
@@ -0,0 +1,27 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/array_misc_9.gold b/SBVTestSuite/GoldFiles/array_misc_9.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/array_misc_9.gold
@@ -0,0 +1,26 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Falsifiable
diff --git a/SBVTestSuite/GoldFiles/assertWithPenalty1.gold b/SBVTestSuite/GoldFiles/assertWithPenalty1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/assertWithPenalty1.gold
@@ -0,0 +1,7 @@
+Optimal model:
+  x   =     0 :: Integer
+  y   =     1 :: Integer
+  as1 = False :: Bool
+  as2 =  True :: Bool
+  as3 =  True :: Bool
+  as4 = False :: Bool
diff --git a/SBVTestSuite/GoldFiles/assertWithPenalty2.gold b/SBVTestSuite/GoldFiles/assertWithPenalty2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/assertWithPenalty2.gold
@@ -0,0 +1,8 @@
+Optimal model:
+  a1    = False :: Bool
+  a2    =  True :: Bool
+  a3    =  True :: Bool
+  as_a1 = False :: Bool
+  as_a2 =  True :: Bool
+  as_a3 =  True :: Bool
+  as_a4 =  True :: Bool
diff --git a/SBVTestSuite/GoldFiles/auf-1.gold b/SBVTestSuite/GoldFiles/auf-1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/auf-1.gold
@@ -0,0 +1,29 @@
+INPUTS
+  s0 :: SArray Word32 Word32, aliasing "a"
+  s1 :: SWord32, aliasing "x"
+  s2 :: SWord32, aliasing "y"
+CONSTANTS
+  s3 = 2 :: Word32
+  s6 = 3 :: Word32
+  s12 = 1 :: Word32
+TABLES
+UNINTERPRETED CONSTANTS
+  [uninterpreted] f :: (True,Nothing,SWord32 -> SWord64)
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s4 :: SWord32 = s1 + s3
+  s5 :: SBool = s2 == s4
+  s7 :: SArray Word32 Word32 = store s0 s1 s6
+  s8 :: SWord32 = s2 - s3
+  s9 :: SWord32 = select s7 s8
+  s10 :: SWord64 = [uninterpreted] f s9
+  s11 :: SWord32 = s2 - s1
+  s13 :: SWord32 = s11 + s12
+  s14 :: SWord64 = [uninterpreted] f s13
+  s15 :: SBool = s10 == s14
+  s16 :: SBool = s5 => s15
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s16
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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,82 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,118 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,186 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+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,62 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[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] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/basic-1_1.gold b/SBVTestSuite/GoldFiles/basic-1_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-1_1.gold
@@ -0,0 +1,1 @@
+5 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-1_2.gold b/SBVTestSuite/GoldFiles/basic-1_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-1_2.gold
@@ -0,0 +1,1 @@
+5 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-1_3.gold b/SBVTestSuite/GoldFiles/basic-1_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-1_3.gold
@@ -0,0 +1,1 @@
+25 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-1_4.gold b/SBVTestSuite/GoldFiles/basic-1_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-1_4.gold
@@ -0,0 +1,1 @@
+25 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-1_5.gold b/SBVTestSuite/GoldFiles/basic-1_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-1_5.gold
@@ -0,0 +1,1 @@
+4 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-2_1.gold b/SBVTestSuite/GoldFiles/basic-2_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-2_1.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "y"
+CONSTANTS
+  s1 = 3 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s1 - s0
+  s4 :: SWord8 = s2 * s3
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s4
diff --git a/SBVTestSuite/GoldFiles/basic-2_2.gold b/SBVTestSuite/GoldFiles/basic-2_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-2_2.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "y"
+CONSTANTS
+  s1 = 9 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 * s0
+  s3 :: SWord8 = s1 - s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-2_3.gold b/SBVTestSuite/GoldFiles/basic-2_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-2_3.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "y"
+CONSTANTS
+  s1 = 3 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-2_4.gold b/SBVTestSuite/GoldFiles/basic-2_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-2_4.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "y"
+CONSTANTS
+  s1 = 3 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-2_5.gold b/SBVTestSuite/GoldFiles/basic-2_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-2_5.gold
@@ -0,0 +1,1 @@
+4 :: Word8
diff --git a/SBVTestSuite/GoldFiles/basic-3_1.gold b/SBVTestSuite/GoldFiles/basic-3_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-3_1.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s0 - s1
+  s4 :: SWord8 = s2 * s3
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s4
diff --git a/SBVTestSuite/GoldFiles/basic-3_2.gold b/SBVTestSuite/GoldFiles/basic-3_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-3_2.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 * s0
+  s3 :: SWord8 = s1 * s1
+  s4 :: SWord8 = s2 - s3
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s4
diff --git a/SBVTestSuite/GoldFiles/basic-3_3.gold b/SBVTestSuite/GoldFiles/basic-3_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-3_3.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-3_4.gold b/SBVTestSuite/GoldFiles/basic-3_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-3_4.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-3_5.gold b/SBVTestSuite/GoldFiles/basic-3_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-3_5.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+CONSTANTS
+  s2 = 1 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s3 :: SWord8 = s0 + s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-4_1.gold b/SBVTestSuite/GoldFiles/basic-4_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-4_1.gold
@@ -0,0 +1,15 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s1 :: SWord8 = s0 + s0
+  s2 :: SWord8 = s0 - s0
+  s3 :: SWord8 = s1 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-4_2.gold b/SBVTestSuite/GoldFiles/basic-4_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-4_2.gold
@@ -0,0 +1,14 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s1 :: SWord8 = s0 * s0
+  s2 :: SWord8 = s1 - s1
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s2
diff --git a/SBVTestSuite/GoldFiles/basic-4_3.gold b/SBVTestSuite/GoldFiles/basic-4_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-4_3.gold
@@ -0,0 +1,14 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s1 :: SWord8 = s0 + s0
+  s2 :: SWord8 = s1 * s1
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s2
diff --git a/SBVTestSuite/GoldFiles/basic-4_4.gold b/SBVTestSuite/GoldFiles/basic-4_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-4_4.gold
@@ -0,0 +1,14 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s1 :: SWord8 = s0 + s0
+  s2 :: SWord8 = s1 * s1
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s2
diff --git a/SBVTestSuite/GoldFiles/basic-4_5.gold b/SBVTestSuite/GoldFiles/basic-4_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-4_5.gold
@@ -0,0 +1,14 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+CONSTANTS
+  s1 = 1 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s1
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s2
diff --git a/SBVTestSuite/GoldFiles/basic-5_1.gold b/SBVTestSuite/GoldFiles/basic-5_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-5_1.gold
@@ -0,0 +1,17 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "q"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s0
+  s3 :: SWord8 = s0 - s0
+  s4 :: SWord8 = s2 * s3
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1
+  s4
diff --git a/SBVTestSuite/GoldFiles/basic-5_2.gold b/SBVTestSuite/GoldFiles/basic-5_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-5_2.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "q"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 * s0
+  s3 :: SWord8 = s2 - s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-5_3.gold b/SBVTestSuite/GoldFiles/basic-5_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-5_3.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "q"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s0
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-5_4.gold b/SBVTestSuite/GoldFiles/basic-5_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-5_4.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "q"
+CONSTANTS
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SWord8 = s0 + s0
+  s3 :: SWord8 = s2 * s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1
+  s3
diff --git a/SBVTestSuite/GoldFiles/basic-5_5.gold b/SBVTestSuite/GoldFiles/basic-5_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/basic-5_5.gold
@@ -0,0 +1,16 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "q"
+CONSTANTS
+  s2 = 1 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s3 :: SWord8 = s0 + s2
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1
+  s3
diff --git a/SBVTestSuite/GoldFiles/ccitt.gold b/SBVTestSuite/GoldFiles/ccitt.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/ccitt.gold
@@ -0,0 +1,2196 @@
+INPUTS
+  s0 :: SWord 48
+  s1 :: SWord 48
+CONSTANTS
+  s4 = 0 :: WordN 1
+  s100 = 65536 :: Word64
+  s101 = 0 :: Word64
+  s103 = 131072 :: Word64
+  s106 = 262144 :: Word64
+  s109 = 524288 :: Word64
+  s112 = 1048576 :: Word64
+  s115 = 2097152 :: Word64
+  s118 = 4194304 :: Word64
+  s121 = 8388608 :: Word64
+  s124 = 16777216 :: Word64
+  s127 = 33554432 :: Word64
+  s130 = 67108864 :: Word64
+  s133 = 134217728 :: Word64
+  s136 = 268435456 :: Word64
+  s139 = 536870912 :: Word64
+  s142 = 1073741824 :: Word64
+  s145 = 2147483648 :: Word64
+  s148 = 4294967296 :: Word64
+  s151 = 8589934592 :: Word64
+  s154 = 17179869184 :: Word64
+  s157 = 34359738368 :: Word64
+  s160 = 68719476736 :: Word64
+  s163 = 137438953472 :: Word64
+  s166 = 274877906944 :: Word64
+  s169 = 549755813888 :: Word64
+  s172 = 1099511627776 :: Word64
+  s175 = 2199023255552 :: Word64
+  s178 = 4398046511104 :: Word64
+  s181 = 8796093022208 :: Word64
+  s184 = 17592186044416 :: Word64
+  s187 = 35184372088832 :: Word64
+  s190 = 70368744177664 :: Word64
+  s193 = 140737488355328 :: Word64
+  s196 = 281474976710656 :: Word64
+  s199 = 562949953421312 :: Word64
+  s202 = 1125899906842624 :: Word64
+  s205 = 2251799813685248 :: Word64
+  s208 = 4503599627370496 :: Word64
+  s211 = 9007199254740992 :: Word64
+  s214 = 18014398509481984 :: Word64
+  s217 = 36028797018963968 :: Word64
+  s220 = 72057594037927936 :: Word64
+  s223 = 144115188075855872 :: Word64
+  s226 = 288230376151711744 :: Word64
+  s229 = 576460752303423488 :: Word64
+  s232 = 1152921504606846976 :: Word64
+  s235 = 2305843009213693952 :: Word64
+  s238 = 4611686018427387904 :: Word64
+  s241 = 9223372036854775808 :: Word64
+  s756 = 1 :: Word64
+  s758 = 2 :: Word64
+  s761 = 4 :: Word64
+  s764 = 8 :: Word64
+  s767 = 16 :: Word64
+  s770 = 32 :: Word64
+  s773 = 64 :: Word64
+  s776 = 128 :: Word64
+  s779 = 256 :: Word64
+  s782 = 512 :: Word64
+  s785 = 1024 :: Word64
+  s788 = 2048 :: Word64
+  s791 = 4096 :: Word64
+  s794 = 8192 :: Word64
+  s797 = 16384 :: Word64
+  s800 = 32768 :: Word64
+  s2053 = 0 :: Word8
+  s2054 = 1 :: Word8
+  s2182 = 3 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SBool = s0 /= s1
+  s3 :: SWord 1 = choose [47:47] s0
+  s5 :: SBool = s3 /= s4
+  s6 :: SWord 1 = choose [46:46] s0
+  s7 :: SBool = s4 /= s6
+  s8 :: SWord 1 = choose [45:45] s0
+  s9 :: SBool = s4 /= s8
+  s10 :: SWord 1 = choose [44:44] s0
+  s11 :: SBool = s4 /= s10
+  s12 :: SWord 1 = choose [43:43] s0
+  s13 :: SBool = s4 /= s12
+  s14 :: SWord 1 = choose [42:42] s0
+  s15 :: SBool = s4 /= s14
+  s16 :: SWord 1 = choose [41:41] s0
+  s17 :: SBool = s4 /= s16
+  s18 :: SWord 1 = choose [40:40] s0
+  s19 :: SBool = s4 /= s18
+  s20 :: SWord 1 = choose [39:39] s0
+  s21 :: SBool = s4 /= s20
+  s22 :: SWord 1 = choose [38:38] s0
+  s23 :: SBool = s4 /= s22
+  s24 :: SWord 1 = choose [37:37] s0
+  s25 :: SBool = s4 /= s24
+  s26 :: SWord 1 = choose [36:36] s0
+  s27 :: SBool = s4 /= s26
+  s28 :: SWord 1 = choose [35:35] s0
+  s29 :: SBool = s4 /= s28
+  s30 :: SWord 1 = choose [34:34] s0
+  s31 :: SBool = s4 /= s30
+  s32 :: SWord 1 = choose [33:33] s0
+  s33 :: SBool = s4 /= s32
+  s34 :: SWord 1 = choose [32:32] s0
+  s35 :: SBool = s4 /= s34
+  s36 :: SWord 1 = choose [31:31] s0
+  s37 :: SBool = s4 /= s36
+  s38 :: SWord 1 = choose [30:30] s0
+  s39 :: SBool = s4 /= s38
+  s40 :: SWord 1 = choose [29:29] s0
+  s41 :: SBool = s4 /= s40
+  s42 :: SWord 1 = choose [28:28] s0
+  s43 :: SBool = s4 /= s42
+  s44 :: SWord 1 = choose [27:27] s0
+  s45 :: SBool = s4 /= s44
+  s46 :: SWord 1 = choose [26:26] s0
+  s47 :: SBool = s4 /= s46
+  s48 :: SWord 1 = choose [25:25] s0
+  s49 :: SBool = s4 /= s48
+  s50 :: SWord 1 = choose [24:24] s0
+  s51 :: SBool = s4 /= s50
+  s52 :: SWord 1 = choose [23:23] s0
+  s53 :: SBool = s4 /= s52
+  s54 :: SWord 1 = choose [22:22] s0
+  s55 :: SBool = s4 /= s54
+  s56 :: SWord 1 = choose [21:21] s0
+  s57 :: SBool = s4 /= s56
+  s58 :: SWord 1 = choose [20:20] s0
+  s59 :: SBool = s4 /= s58
+  s60 :: SWord 1 = choose [19:19] s0
+  s61 :: SBool = s4 /= s60
+  s62 :: SWord 1 = choose [18:18] s0
+  s63 :: SBool = s4 /= s62
+  s64 :: SWord 1 = choose [17:17] s0
+  s65 :: SBool = s4 /= s64
+  s66 :: SWord 1 = choose [16:16] s0
+  s67 :: SBool = s4 /= s66
+  s68 :: SWord 1 = choose [15:15] s0
+  s69 :: SBool = s4 /= s68
+  s70 :: SWord 1 = choose [14:14] s0
+  s71 :: SBool = s4 /= s70
+  s72 :: SWord 1 = choose [13:13] s0
+  s73 :: SBool = s4 /= s72
+  s74 :: SWord 1 = choose [12:12] s0
+  s75 :: SBool = s4 /= s74
+  s76 :: SWord 1 = choose [11:11] s0
+  s77 :: SBool = s4 /= s76
+  s78 :: SWord 1 = choose [10:10] s0
+  s79 :: SBool = s4 /= s78
+  s80 :: SWord 1 = choose [9:9] s0
+  s81 :: SBool = s4 /= s80
+  s82 :: SWord 1 = choose [8:8] s0
+  s83 :: SBool = s4 /= s82
+  s84 :: SWord 1 = choose [7:7] s0
+  s85 :: SBool = s4 /= s84
+  s86 :: SWord 1 = choose [6:6] s0
+  s87 :: SBool = s4 /= s86
+  s88 :: SWord 1 = choose [5:5] s0
+  s89 :: SBool = s4 /= s88
+  s90 :: SWord 1 = choose [4:4] s0
+  s91 :: SBool = s4 /= s90
+  s92 :: SWord 1 = choose [3:3] s0
+  s93 :: SBool = s4 /= s92
+  s94 :: SWord 1 = choose [2:2] s0
+  s95 :: SBool = s4 /= s94
+  s96 :: SWord 1 = choose [1:1] s0
+  s97 :: SBool = s4 /= s96
+  s98 :: SWord 1 = choose [0:0] s0
+  s99 :: SBool = s4 /= s98
+  s102 :: SWord64 = if s99 then s100 else s101
+  s104 :: SWord64 = s102 | s103
+  s105 :: SWord64 = if s97 then s104 else s102
+  s107 :: SWord64 = s105 | s106
+  s108 :: SWord64 = if s95 then s107 else s105
+  s110 :: SWord64 = s108 | s109
+  s111 :: SWord64 = if s93 then s110 else s108
+  s113 :: SWord64 = s111 | s112
+  s114 :: SWord64 = if s91 then s113 else s111
+  s116 :: SWord64 = s114 | s115
+  s117 :: SWord64 = if s89 then s116 else s114
+  s119 :: SWord64 = s117 | s118
+  s120 :: SWord64 = if s87 then s119 else s117
+  s122 :: SWord64 = s120 | s121
+  s123 :: SWord64 = if s85 then s122 else s120
+  s125 :: SWord64 = s123 | s124
+  s126 :: SWord64 = if s83 then s125 else s123
+  s128 :: SWord64 = s126 | s127
+  s129 :: SWord64 = if s81 then s128 else s126
+  s131 :: SWord64 = s129 | s130
+  s132 :: SWord64 = if s79 then s131 else s129
+  s134 :: SWord64 = s132 | s133
+  s135 :: SWord64 = if s77 then s134 else s132
+  s137 :: SWord64 = s135 | s136
+  s138 :: SWord64 = if s75 then s137 else s135
+  s140 :: SWord64 = s138 | s139
+  s141 :: SWord64 = if s73 then s140 else s138
+  s143 :: SWord64 = s141 | s142
+  s144 :: SWord64 = if s71 then s143 else s141
+  s146 :: SWord64 = s144 | s145
+  s147 :: SWord64 = if s69 then s146 else s144
+  s149 :: SWord64 = s147 | s148
+  s150 :: SWord64 = if s67 then s149 else s147
+  s152 :: SWord64 = s150 | s151
+  s153 :: SWord64 = if s65 then s152 else s150
+  s155 :: SWord64 = s153 | s154
+  s156 :: SWord64 = if s63 then s155 else s153
+  s158 :: SWord64 = s156 | s157
+  s159 :: SWord64 = if s61 then s158 else s156
+  s161 :: SWord64 = s159 | s160
+  s162 :: SWord64 = if s59 then s161 else s159
+  s164 :: SWord64 = s162 | s163
+  s165 :: SWord64 = if s57 then s164 else s162
+  s167 :: SWord64 = s165 | s166
+  s168 :: SWord64 = if s55 then s167 else s165
+  s170 :: SWord64 = s168 | s169
+  s171 :: SWord64 = if s53 then s170 else s168
+  s173 :: SWord64 = s171 | s172
+  s174 :: SWord64 = if s51 then s173 else s171
+  s176 :: SWord64 = s174 | s175
+  s177 :: SWord64 = if s49 then s176 else s174
+  s179 :: SWord64 = s177 | s178
+  s180 :: SWord64 = if s47 then s179 else s177
+  s182 :: SWord64 = s180 | s181
+  s183 :: SWord64 = if s45 then s182 else s180
+  s185 :: SWord64 = s183 | s184
+  s186 :: SWord64 = if s43 then s185 else s183
+  s188 :: SWord64 = s186 | s187
+  s189 :: SWord64 = if s41 then s188 else s186
+  s191 :: SWord64 = s189 | s190
+  s192 :: SWord64 = if s39 then s191 else s189
+  s194 :: SWord64 = s192 | s193
+  s195 :: SWord64 = if s37 then s194 else s192
+  s197 :: SWord64 = s195 | s196
+  s198 :: SWord64 = if s35 then s197 else s195
+  s200 :: SWord64 = s198 | s199
+  s201 :: SWord64 = if s33 then s200 else s198
+  s203 :: SWord64 = s201 | s202
+  s204 :: SWord64 = if s31 then s203 else s201
+  s206 :: SWord64 = s204 | s205
+  s207 :: SWord64 = if s29 then s206 else s204
+  s209 :: SWord64 = s207 | s208
+  s210 :: SWord64 = if s27 then s209 else s207
+  s212 :: SWord64 = s210 | s211
+  s213 :: SWord64 = if s25 then s212 else s210
+  s215 :: SWord64 = s213 | s214
+  s216 :: SWord64 = if s23 then s215 else s213
+  s218 :: SWord64 = s216 | s217
+  s219 :: SWord64 = if s21 then s218 else s216
+  s221 :: SWord64 = s219 | s220
+  s222 :: SWord64 = if s19 then s221 else s219
+  s224 :: SWord64 = s222 | s223
+  s225 :: SWord64 = if s17 then s224 else s222
+  s227 :: SWord64 = s225 | s226
+  s228 :: SWord64 = if s15 then s227 else s225
+  s230 :: SWord64 = s228 | s229
+  s231 :: SWord64 = if s13 then s230 else s228
+  s233 :: SWord64 = s231 | s232
+  s234 :: SWord64 = if s11 then s233 else s231
+  s236 :: SWord64 = s234 | s235
+  s237 :: SWord64 = if s9 then s236 else s234
+  s239 :: SWord64 = s237 | s238
+  s240 :: SWord64 = if s7 then s239 else s237
+  s242 :: SWord64 = s240 | s241
+  s243 :: SWord64 = if s5 then s242 else s240
+  s244 :: SWord 1 = choose [63:63] s243
+  s245 :: SBool = s4 /= s244
+  s246 :: SWord 1 = choose [62:62] s243
+  s247 :: SBool = s4 /= s246
+  s248 :: SWord 1 = choose [61:61] s243
+  s249 :: SBool = s4 /= s248
+  s250 :: SWord 1 = choose [60:60] s243
+  s251 :: SBool = s4 /= s250
+  s252 :: SWord 1 = choose [59:59] s243
+  s253 :: SBool = s4 /= s252
+  s254 :: SBool = ~ s253
+  s255 :: SBool = if s245 then s254 else s253
+  s256 :: SWord 1 = choose [58:58] s243
+  s257 :: SBool = s4 /= s256
+  s258 :: SBool = ~ s257
+  s259 :: SBool = if s247 then s258 else s257
+  s260 :: SWord 1 = choose [57:57] s243
+  s261 :: SBool = s4 /= s260
+  s262 :: SBool = ~ s261
+  s263 :: SBool = if s249 then s262 else s261
+  s264 :: SWord 1 = choose [56:56] s243
+  s265 :: SBool = s4 /= s264
+  s266 :: SBool = ~ s265
+  s267 :: SBool = if s251 then s266 else s265
+  s268 :: SWord 1 = choose [55:55] s243
+  s269 :: SBool = s4 /= s268
+  s270 :: SBool = ~ s269
+  s271 :: SBool = if s255 then s270 else s269
+  s272 :: SWord 1 = choose [54:54] s243
+  s273 :: SBool = s4 /= s272
+  s274 :: SBool = ~ s273
+  s275 :: SBool = if s259 then s274 else s273
+  s276 :: SWord 1 = choose [53:53] s243
+  s277 :: SBool = s4 /= s276
+  s278 :: SBool = ~ s277
+  s279 :: SBool = if s263 then s278 else s277
+  s280 :: SWord 1 = choose [52:52] s243
+  s281 :: SBool = s4 /= s280
+  s282 :: SBool = ~ s281
+  s283 :: SBool = if s245 then s282 else s281
+  s284 :: SBool = ~ s283
+  s285 :: SBool = if s267 then s284 else s283
+  s286 :: SWord 1 = choose [51:51] s243
+  s287 :: SBool = s4 /= s286
+  s288 :: SBool = ~ s287
+  s289 :: SBool = if s247 then s288 else s287
+  s290 :: SBool = ~ s289
+  s291 :: SBool = if s271 then s290 else s289
+  s292 :: SWord 1 = choose [50:50] s243
+  s293 :: SBool = s4 /= s292
+  s294 :: SBool = ~ s293
+  s295 :: SBool = if s249 then s294 else s293
+  s296 :: SBool = ~ s295
+  s297 :: SBool = if s275 then s296 else s295
+  s298 :: SWord 1 = choose [49:49] s243
+  s299 :: SBool = s4 /= s298
+  s300 :: SBool = ~ s299
+  s301 :: SBool = if s251 then s300 else s299
+  s302 :: SBool = ~ s301
+  s303 :: SBool = if s279 then s302 else s301
+  s304 :: SWord 1 = choose [48:48] s243
+  s305 :: SBool = s4 /= s304
+  s306 :: SBool = ~ s305
+  s307 :: SBool = if s255 then s306 else s305
+  s308 :: SBool = ~ s307
+  s309 :: SBool = if s285 then s308 else s307
+  s310 :: SWord 1 = choose [47:47] s243
+  s311 :: SBool = s4 /= s310
+  s312 :: SBool = ~ s311
+  s313 :: SBool = if s245 then s312 else s311
+  s314 :: SBool = ~ s313
+  s315 :: SBool = if s259 then s314 else s313
+  s316 :: SBool = ~ s315
+  s317 :: SBool = if s291 then s316 else s315
+  s318 :: SWord 1 = choose [46:46] s243
+  s319 :: SBool = s4 /= s318
+  s320 :: SBool = ~ s319
+  s321 :: SBool = if s247 then s320 else s319
+  s322 :: SBool = ~ s321
+  s323 :: SBool = if s263 then s322 else s321
+  s324 :: SBool = ~ s323
+  s325 :: SBool = if s297 then s324 else s323
+  s326 :: SWord 1 = choose [45:45] s243
+  s327 :: SBool = s4 /= s326
+  s328 :: SBool = ~ s327
+  s329 :: SBool = if s249 then s328 else s327
+  s330 :: SBool = ~ s329
+  s331 :: SBool = if s267 then s330 else s329
+  s332 :: SBool = ~ s331
+  s333 :: SBool = if s303 then s332 else s331
+  s334 :: SWord 1 = choose [44:44] s243
+  s335 :: SBool = s4 /= s334
+  s336 :: SBool = ~ s335
+  s337 :: SBool = if s251 then s336 else s335
+  s338 :: SBool = ~ s337
+  s339 :: SBool = if s271 then s338 else s337
+  s340 :: SBool = ~ s339
+  s341 :: SBool = if s309 then s340 else s339
+  s342 :: SWord 1 = choose [43:43] s243
+  s343 :: SBool = s4 /= s342
+  s344 :: SBool = ~ s343
+  s345 :: SBool = if s255 then s344 else s343
+  s346 :: SBool = ~ s345
+  s347 :: SBool = if s275 then s346 else s345
+  s348 :: SBool = ~ s347
+  s349 :: SBool = if s317 then s348 else s347
+  s350 :: SWord 1 = choose [42:42] s243
+  s351 :: SBool = s4 /= s350
+  s352 :: SBool = ~ s351
+  s353 :: SBool = if s259 then s352 else s351
+  s354 :: SBool = ~ s353
+  s355 :: SBool = if s279 then s354 else s353
+  s356 :: SBool = ~ s355
+  s357 :: SBool = if s325 then s356 else s355
+  s358 :: SWord 1 = choose [41:41] s243
+  s359 :: SBool = s4 /= s358
+  s360 :: SBool = ~ s359
+  s361 :: SBool = if s263 then s360 else s359
+  s362 :: SBool = ~ s361
+  s363 :: SBool = if s285 then s362 else s361
+  s364 :: SBool = ~ s363
+  s365 :: SBool = if s333 then s364 else s363
+  s366 :: SWord 1 = choose [40:40] s243
+  s367 :: SBool = s4 /= s366
+  s368 :: SBool = ~ s367
+  s369 :: SBool = if s267 then s368 else s367
+  s370 :: SBool = ~ s369
+  s371 :: SBool = if s291 then s370 else s369
+  s372 :: SBool = ~ s371
+  s373 :: SBool = if s341 then s372 else s371
+  s374 :: SWord 1 = choose [39:39] s243
+  s375 :: SBool = s4 /= s374
+  s376 :: SBool = ~ s375
+  s377 :: SBool = if s271 then s376 else s375
+  s378 :: SBool = ~ s377
+  s379 :: SBool = if s297 then s378 else s377
+  s380 :: SBool = ~ s379
+  s381 :: SBool = if s349 then s380 else s379
+  s382 :: SWord 1 = choose [38:38] s243
+  s383 :: SBool = s4 /= s382
+  s384 :: SBool = ~ s383
+  s385 :: SBool = if s275 then s384 else s383
+  s386 :: SBool = ~ s385
+  s387 :: SBool = if s303 then s386 else s385
+  s388 :: SBool = ~ s387
+  s389 :: SBool = if s357 then s388 else s387
+  s390 :: SWord 1 = choose [37:37] s243
+  s391 :: SBool = s4 /= s390
+  s392 :: SBool = ~ s391
+  s393 :: SBool = if s279 then s392 else s391
+  s394 :: SBool = ~ s393
+  s395 :: SBool = if s309 then s394 else s393
+  s396 :: SBool = ~ s395
+  s397 :: SBool = if s365 then s396 else s395
+  s398 :: SWord 1 = choose [36:36] s243
+  s399 :: SBool = s4 /= s398
+  s400 :: SBool = ~ s399
+  s401 :: SBool = if s285 then s400 else s399
+  s402 :: SBool = ~ s401
+  s403 :: SBool = if s317 then s402 else s401
+  s404 :: SBool = ~ s403
+  s405 :: SBool = if s373 then s404 else s403
+  s406 :: SWord 1 = choose [35:35] s243
+  s407 :: SBool = s4 /= s406
+  s408 :: SBool = ~ s407
+  s409 :: SBool = if s291 then s408 else s407
+  s410 :: SBool = ~ s409
+  s411 :: SBool = if s325 then s410 else s409
+  s412 :: SBool = ~ s411
+  s413 :: SBool = if s381 then s412 else s411
+  s414 :: SWord 1 = choose [34:34] s243
+  s415 :: SBool = s4 /= s414
+  s416 :: SBool = ~ s415
+  s417 :: SBool = if s297 then s416 else s415
+  s418 :: SBool = ~ s417
+  s419 :: SBool = if s333 then s418 else s417
+  s420 :: SBool = ~ s419
+  s421 :: SBool = if s389 then s420 else s419
+  s422 :: SWord 1 = choose [33:33] s243
+  s423 :: SBool = s4 /= s422
+  s424 :: SBool = ~ s423
+  s425 :: SBool = if s303 then s424 else s423
+  s426 :: SBool = ~ s425
+  s427 :: SBool = if s341 then s426 else s425
+  s428 :: SBool = ~ s427
+  s429 :: SBool = if s397 then s428 else s427
+  s430 :: SWord 1 = choose [32:32] s243
+  s431 :: SBool = s4 /= s430
+  s432 :: SBool = ~ s431
+  s433 :: SBool = if s309 then s432 else s431
+  s434 :: SBool = ~ s433
+  s435 :: SBool = if s349 then s434 else s433
+  s436 :: SBool = ~ s435
+  s437 :: SBool = if s405 then s436 else s435
+  s438 :: SWord 1 = choose [31:31] s243
+  s439 :: SBool = s4 /= s438
+  s440 :: SBool = ~ s439
+  s441 :: SBool = if s317 then s440 else s439
+  s442 :: SBool = ~ s441
+  s443 :: SBool = if s357 then s442 else s441
+  s444 :: SBool = ~ s443
+  s445 :: SBool = if s413 then s444 else s443
+  s446 :: SWord 1 = choose [30:30] s243
+  s447 :: SBool = s4 /= s446
+  s448 :: SBool = ~ s447
+  s449 :: SBool = if s325 then s448 else s447
+  s450 :: SBool = ~ s449
+  s451 :: SBool = if s365 then s450 else s449
+  s452 :: SBool = ~ s451
+  s453 :: SBool = if s421 then s452 else s451
+  s454 :: SWord 1 = choose [29:29] s243
+  s455 :: SBool = s4 /= s454
+  s456 :: SBool = ~ s455
+  s457 :: SBool = if s333 then s456 else s455
+  s458 :: SBool = ~ s457
+  s459 :: SBool = if s373 then s458 else s457
+  s460 :: SBool = ~ s459
+  s461 :: SBool = if s429 then s460 else s459
+  s462 :: SWord 1 = choose [28:28] s243
+  s463 :: SBool = s4 /= s462
+  s464 :: SBool = ~ s463
+  s465 :: SBool = if s341 then s464 else s463
+  s466 :: SBool = ~ s465
+  s467 :: SBool = if s381 then s466 else s465
+  s468 :: SBool = ~ s467
+  s469 :: SBool = if s437 then s468 else s467
+  s470 :: SWord 1 = choose [27:27] s243
+  s471 :: SBool = s4 /= s470
+  s472 :: SBool = ~ s471
+  s473 :: SBool = if s349 then s472 else s471
+  s474 :: SBool = ~ s473
+  s475 :: SBool = if s389 then s474 else s473
+  s476 :: SBool = ~ s475
+  s477 :: SBool = if s445 then s476 else s475
+  s478 :: SWord 1 = choose [26:26] s243
+  s479 :: SBool = s4 /= s478
+  s480 :: SBool = ~ s479
+  s481 :: SBool = if s357 then s480 else s479
+  s482 :: SBool = ~ s481
+  s483 :: SBool = if s397 then s482 else s481
+  s484 :: SBool = ~ s483
+  s485 :: SBool = if s453 then s484 else s483
+  s486 :: SWord 1 = choose [25:25] s243
+  s487 :: SBool = s4 /= s486
+  s488 :: SBool = ~ s487
+  s489 :: SBool = if s365 then s488 else s487
+  s490 :: SBool = ~ s489
+  s491 :: SBool = if s405 then s490 else s489
+  s492 :: SBool = ~ s491
+  s493 :: SBool = if s461 then s492 else s491
+  s494 :: SWord 1 = choose [24:24] s243
+  s495 :: SBool = s4 /= s494
+  s496 :: SBool = ~ s495
+  s497 :: SBool = if s373 then s496 else s495
+  s498 :: SBool = ~ s497
+  s499 :: SBool = if s413 then s498 else s497
+  s500 :: SBool = ~ s499
+  s501 :: SBool = if s469 then s500 else s499
+  s502 :: SWord 1 = choose [23:23] s243
+  s503 :: SBool = s4 /= s502
+  s504 :: SBool = ~ s503
+  s505 :: SBool = if s381 then s504 else s503
+  s506 :: SBool = ~ s505
+  s507 :: SBool = if s421 then s506 else s505
+  s508 :: SBool = ~ s507
+  s509 :: SBool = if s477 then s508 else s507
+  s510 :: SWord 1 = choose [22:22] s243
+  s511 :: SBool = s4 /= s510
+  s512 :: SBool = ~ s511
+  s513 :: SBool = if s389 then s512 else s511
+  s514 :: SBool = ~ s513
+  s515 :: SBool = if s429 then s514 else s513
+  s516 :: SBool = ~ s515
+  s517 :: SBool = if s485 then s516 else s515
+  s518 :: SWord 1 = choose [21:21] s243
+  s519 :: SBool = s4 /= s518
+  s520 :: SBool = ~ s519
+  s521 :: SBool = if s397 then s520 else s519
+  s522 :: SBool = ~ s521
+  s523 :: SBool = if s437 then s522 else s521
+  s524 :: SBool = ~ s523
+  s525 :: SBool = if s493 then s524 else s523
+  s526 :: SWord 1 = choose [20:20] s243
+  s527 :: SBool = s4 /= s526
+  s528 :: SBool = ~ s527
+  s529 :: SBool = if s405 then s528 else s527
+  s530 :: SBool = ~ s529
+  s531 :: SBool = if s445 then s530 else s529
+  s532 :: SBool = ~ s531
+  s533 :: SBool = if s501 then s532 else s531
+  s534 :: SWord 1 = choose [19:19] s243
+  s535 :: SBool = s4 /= s534
+  s536 :: SBool = ~ s535
+  s537 :: SBool = if s413 then s536 else s535
+  s538 :: SBool = ~ s537
+  s539 :: SBool = if s453 then s538 else s537
+  s540 :: SBool = ~ s539
+  s541 :: SBool = if s509 then s540 else s539
+  s542 :: SWord 1 = choose [18:18] s243
+  s543 :: SBool = s4 /= s542
+  s544 :: SBool = ~ s543
+  s545 :: SBool = if s421 then s544 else s543
+  s546 :: SBool = ~ s545
+  s547 :: SBool = if s461 then s546 else s545
+  s548 :: SBool = ~ s547
+  s549 :: SBool = if s517 then s548 else s547
+  s550 :: SWord 1 = choose [17:17] s243
+  s551 :: SBool = s4 /= s550
+  s552 :: SBool = ~ s551
+  s553 :: SBool = if s429 then s552 else s551
+  s554 :: SBool = ~ s553
+  s555 :: SBool = if s469 then s554 else s553
+  s556 :: SBool = ~ s555
+  s557 :: SBool = if s525 then s556 else s555
+  s558 :: SWord 1 = choose [16:16] s243
+  s559 :: SBool = s4 /= s558
+  s560 :: SBool = ~ s559
+  s561 :: SBool = if s437 then s560 else s559
+  s562 :: SBool = ~ s561
+  s563 :: SBool = if s477 then s562 else s561
+  s564 :: SBool = ~ s563
+  s565 :: SBool = if s533 then s564 else s563
+  s566 :: SBool = ~ s245
+  s567 :: SBool = if s245 then s566 else s245
+  s568 :: SBool = ~ s247
+  s569 :: SBool = if s247 then s568 else s247
+  s570 :: SBool = ~ s249
+  s571 :: SBool = if s249 then s570 else s249
+  s572 :: SBool = ~ s251
+  s573 :: SBool = if s251 then s572 else s251
+  s574 :: SBool = ~ s255
+  s575 :: SBool = if s255 then s574 else s255
+  s576 :: SBool = ~ s259
+  s577 :: SBool = if s259 then s576 else s259
+  s578 :: SBool = ~ s263
+  s579 :: SBool = if s263 then s578 else s263
+  s580 :: SBool = ~ s267
+  s581 :: SBool = if s267 then s580 else s267
+  s582 :: SBool = ~ s271
+  s583 :: SBool = if s271 then s582 else s271
+  s584 :: SBool = ~ s275
+  s585 :: SBool = if s275 then s584 else s275
+  s586 :: SBool = ~ s279
+  s587 :: SBool = if s279 then s586 else s279
+  s588 :: SBool = ~ s285
+  s589 :: SBool = if s285 then s588 else s285
+  s590 :: SBool = ~ s291
+  s591 :: SBool = if s291 then s590 else s291
+  s592 :: SBool = ~ s297
+  s593 :: SBool = if s297 then s592 else s297
+  s594 :: SBool = ~ s303
+  s595 :: SBool = if s303 then s594 else s303
+  s596 :: SBool = ~ s309
+  s597 :: SBool = if s309 then s596 else s309
+  s598 :: SBool = ~ s317
+  s599 :: SBool = if s317 then s598 else s317
+  s600 :: SBool = ~ s325
+  s601 :: SBool = if s325 then s600 else s325
+  s602 :: SBool = ~ s333
+  s603 :: SBool = if s333 then s602 else s333
+  s604 :: SBool = ~ s341
+  s605 :: SBool = if s341 then s604 else s341
+  s606 :: SBool = ~ s349
+  s607 :: SBool = if s349 then s606 else s349
+  s608 :: SBool = ~ s357
+  s609 :: SBool = if s357 then s608 else s357
+  s610 :: SBool = ~ s365
+  s611 :: SBool = if s365 then s610 else s365
+  s612 :: SBool = ~ s373
+  s613 :: SBool = if s373 then s612 else s373
+  s614 :: SBool = ~ s381
+  s615 :: SBool = if s381 then s614 else s381
+  s616 :: SBool = ~ s389
+  s617 :: SBool = if s389 then s616 else s389
+  s618 :: SBool = ~ s397
+  s619 :: SBool = if s397 then s618 else s397
+  s620 :: SBool = ~ s405
+  s621 :: SBool = if s405 then s620 else s405
+  s622 :: SBool = ~ s413
+  s623 :: SBool = if s413 then s622 else s413
+  s624 :: SBool = ~ s421
+  s625 :: SBool = if s421 then s624 else s421
+  s626 :: SBool = ~ s429
+  s627 :: SBool = if s429 then s626 else s429
+  s628 :: SBool = ~ s437
+  s629 :: SBool = if s437 then s628 else s437
+  s630 :: SBool = ~ s445
+  s631 :: SBool = if s445 then s630 else s445
+  s632 :: SBool = ~ s453
+  s633 :: SBool = if s453 then s632 else s453
+  s634 :: SBool = ~ s461
+  s635 :: SBool = if s461 then s634 else s461
+  s636 :: SBool = ~ s469
+  s637 :: SBool = if s469 then s636 else s469
+  s638 :: SBool = ~ s477
+  s639 :: SBool = if s477 then s638 else s477
+  s640 :: SBool = ~ s485
+  s641 :: SBool = if s485 then s640 else s485
+  s642 :: SBool = ~ s493
+  s643 :: SBool = if s493 then s642 else s493
+  s644 :: SBool = ~ s501
+  s645 :: SBool = if s501 then s644 else s501
+  s646 :: SBool = ~ s509
+  s647 :: SBool = if s509 then s646 else s509
+  s648 :: SBool = ~ s517
+  s649 :: SBool = if s517 then s648 else s517
+  s650 :: SBool = ~ s525
+  s651 :: SBool = if s525 then s650 else s525
+  s652 :: SBool = ~ s533
+  s653 :: SBool = if s533 then s652 else s533
+  s654 :: SBool = ~ s541
+  s655 :: SBool = if s541 then s654 else s541
+  s656 :: SBool = ~ s549
+  s657 :: SBool = if s549 then s656 else s549
+  s658 :: SBool = ~ s557
+  s659 :: SBool = if s557 then s658 else s557
+  s660 :: SBool = ~ s565
+  s661 :: SBool = if s565 then s660 else s565
+  s662 :: SWord 1 = choose [15:15] s243
+  s663 :: SBool = s4 /= s662
+  s664 :: SBool = ~ s663
+  s665 :: SBool = if s445 then s664 else s663
+  s666 :: SBool = ~ s665
+  s667 :: SBool = if s485 then s666 else s665
+  s668 :: SBool = ~ s667
+  s669 :: SBool = if s541 then s668 else s667
+  s670 :: SWord 1 = choose [14:14] s243
+  s671 :: SBool = s4 /= s670
+  s672 :: SBool = ~ s671
+  s673 :: SBool = if s453 then s672 else s671
+  s674 :: SBool = ~ s673
+  s675 :: SBool = if s493 then s674 else s673
+  s676 :: SBool = ~ s675
+  s677 :: SBool = if s549 then s676 else s675
+  s678 :: SWord 1 = choose [13:13] s243
+  s679 :: SBool = s4 /= s678
+  s680 :: SBool = ~ s679
+  s681 :: SBool = if s461 then s680 else s679
+  s682 :: SBool = ~ s681
+  s683 :: SBool = if s501 then s682 else s681
+  s684 :: SBool = ~ s683
+  s685 :: SBool = if s557 then s684 else s683
+  s686 :: SWord 1 = choose [12:12] s243
+  s687 :: SBool = s4 /= s686
+  s688 :: SBool = ~ s687
+  s689 :: SBool = if s469 then s688 else s687
+  s690 :: SBool = ~ s689
+  s691 :: SBool = if s509 then s690 else s689
+  s692 :: SBool = ~ s691
+  s693 :: SBool = if s565 then s692 else s691
+  s694 :: SWord 1 = choose [11:11] s243
+  s695 :: SBool = s4 /= s694
+  s696 :: SBool = ~ s695
+  s697 :: SBool = if s477 then s696 else s695
+  s698 :: SBool = ~ s697
+  s699 :: SBool = if s517 then s698 else s697
+  s700 :: SWord 1 = choose [10:10] s243
+  s701 :: SBool = s4 /= s700
+  s702 :: SBool = ~ s701
+  s703 :: SBool = if s485 then s702 else s701
+  s704 :: SBool = ~ s703
+  s705 :: SBool = if s525 then s704 else s703
+  s706 :: SWord 1 = choose [9:9] s243
+  s707 :: SBool = s4 /= s706
+  s708 :: SBool = ~ s707
+  s709 :: SBool = if s493 then s708 else s707
+  s710 :: SBool = ~ s709
+  s711 :: SBool = if s533 then s710 else s709
+  s712 :: SWord 1 = choose [8:8] s243
+  s713 :: SBool = s4 /= s712
+  s714 :: SBool = ~ s713
+  s715 :: SBool = if s501 then s714 else s713
+  s716 :: SBool = ~ s715
+  s717 :: SBool = if s541 then s716 else s715
+  s718 :: SWord 1 = choose [7:7] s243
+  s719 :: SBool = s4 /= s718
+  s720 :: SBool = ~ s719
+  s721 :: SBool = if s509 then s720 else s719
+  s722 :: SBool = ~ s721
+  s723 :: SBool = if s549 then s722 else s721
+  s724 :: SWord 1 = choose [6:6] s243
+  s725 :: SBool = s4 /= s724
+  s726 :: SBool = ~ s725
+  s727 :: SBool = if s517 then s726 else s725
+  s728 :: SBool = ~ s727
+  s729 :: SBool = if s557 then s728 else s727
+  s730 :: SWord 1 = choose [5:5] s243
+  s731 :: SBool = s4 /= s730
+  s732 :: SBool = ~ s731
+  s733 :: SBool = if s525 then s732 else s731
+  s734 :: SBool = ~ s733
+  s735 :: SBool = if s565 then s734 else s733
+  s736 :: SWord 1 = choose [4:4] s243
+  s737 :: SBool = s4 /= s736
+  s738 :: SBool = ~ s737
+  s739 :: SBool = if s533 then s738 else s737
+  s740 :: SWord 1 = choose [3:3] s243
+  s741 :: SBool = s4 /= s740
+  s742 :: SBool = ~ s741
+  s743 :: SBool = if s541 then s742 else s741
+  s744 :: SWord 1 = choose [2:2] s243
+  s745 :: SBool = s4 /= s744
+  s746 :: SBool = ~ s745
+  s747 :: SBool = if s549 then s746 else s745
+  s748 :: SWord 1 = choose [1:1] s243
+  s749 :: SBool = s4 /= s748
+  s750 :: SBool = ~ s749
+  s751 :: SBool = if s557 then s750 else s749
+  s752 :: SWord 1 = choose [0:0] s243
+  s753 :: SBool = s4 /= s752
+  s754 :: SBool = ~ s753
+  s755 :: SBool = if s565 then s754 else s753
+  s757 :: SWord64 = if s755 then s756 else s101
+  s759 :: SWord64 = s757 | s758
+  s760 :: SWord64 = if s751 then s759 else s757
+  s762 :: SWord64 = s760 | s761
+  s763 :: SWord64 = if s747 then s762 else s760
+  s765 :: SWord64 = s763 | s764
+  s766 :: SWord64 = if s743 then s765 else s763
+  s768 :: SWord64 = s766 | s767
+  s769 :: SWord64 = if s739 then s768 else s766
+  s771 :: SWord64 = s769 | s770
+  s772 :: SWord64 = if s735 then s771 else s769
+  s774 :: SWord64 = s772 | s773
+  s775 :: SWord64 = if s729 then s774 else s772
+  s777 :: SWord64 = s775 | s776
+  s778 :: SWord64 = if s723 then s777 else s775
+  s780 :: SWord64 = s778 | s779
+  s781 :: SWord64 = if s717 then s780 else s778
+  s783 :: SWord64 = s781 | s782
+  s784 :: SWord64 = if s711 then s783 else s781
+  s786 :: SWord64 = s784 | s785
+  s787 :: SWord64 = if s705 then s786 else s784
+  s789 :: SWord64 = s787 | s788
+  s790 :: SWord64 = if s699 then s789 else s787
+  s792 :: SWord64 = s790 | s791
+  s793 :: SWord64 = if s693 then s792 else s790
+  s795 :: SWord64 = s793 | s794
+  s796 :: SWord64 = if s685 then s795 else s793
+  s798 :: SWord64 = s796 | s797
+  s799 :: SWord64 = if s677 then s798 else s796
+  s801 :: SWord64 = s799 | s800
+  s802 :: SWord64 = if s669 then s801 else s799
+  s803 :: SWord64 = s100 | s802
+  s804 :: SWord64 = if s661 then s803 else s802
+  s805 :: SWord64 = s103 | s804
+  s806 :: SWord64 = if s659 then s805 else s804
+  s807 :: SWord64 = s106 | s806
+  s808 :: SWord64 = if s657 then s807 else s806
+  s809 :: SWord64 = s109 | s808
+  s810 :: SWord64 = if s655 then s809 else s808
+  s811 :: SWord64 = s112 | s810
+  s812 :: SWord64 = if s653 then s811 else s810
+  s813 :: SWord64 = s115 | s812
+  s814 :: SWord64 = if s651 then s813 else s812
+  s815 :: SWord64 = s118 | s814
+  s816 :: SWord64 = if s649 then s815 else s814
+  s817 :: SWord64 = s121 | s816
+  s818 :: SWord64 = if s647 then s817 else s816
+  s819 :: SWord64 = s124 | s818
+  s820 :: SWord64 = if s645 then s819 else s818
+  s821 :: SWord64 = s127 | s820
+  s822 :: SWord64 = if s643 then s821 else s820
+  s823 :: SWord64 = s130 | s822
+  s824 :: SWord64 = if s641 then s823 else s822
+  s825 :: SWord64 = s133 | s824
+  s826 :: SWord64 = if s639 then s825 else s824
+  s827 :: SWord64 = s136 | s826
+  s828 :: SWord64 = if s637 then s827 else s826
+  s829 :: SWord64 = s139 | s828
+  s830 :: SWord64 = if s635 then s829 else s828
+  s831 :: SWord64 = s142 | s830
+  s832 :: SWord64 = if s633 then s831 else s830
+  s833 :: SWord64 = s145 | s832
+  s834 :: SWord64 = if s631 then s833 else s832
+  s835 :: SWord64 = s148 | s834
+  s836 :: SWord64 = if s629 then s835 else s834
+  s837 :: SWord64 = s151 | s836
+  s838 :: SWord64 = if s627 then s837 else s836
+  s839 :: SWord64 = s154 | s838
+  s840 :: SWord64 = if s625 then s839 else s838
+  s841 :: SWord64 = s157 | s840
+  s842 :: SWord64 = if s623 then s841 else s840
+  s843 :: SWord64 = s160 | s842
+  s844 :: SWord64 = if s621 then s843 else s842
+  s845 :: SWord64 = s163 | s844
+  s846 :: SWord64 = if s619 then s845 else s844
+  s847 :: SWord64 = s166 | s846
+  s848 :: SWord64 = if s617 then s847 else s846
+  s849 :: SWord64 = s169 | s848
+  s850 :: SWord64 = if s615 then s849 else s848
+  s851 :: SWord64 = s172 | s850
+  s852 :: SWord64 = if s613 then s851 else s850
+  s853 :: SWord64 = s175 | s852
+  s854 :: SWord64 = if s611 then s853 else s852
+  s855 :: SWord64 = s178 | s854
+  s856 :: SWord64 = if s609 then s855 else s854
+  s857 :: SWord64 = s181 | s856
+  s858 :: SWord64 = if s607 then s857 else s856
+  s859 :: SWord64 = s184 | s858
+  s860 :: SWord64 = if s605 then s859 else s858
+  s861 :: SWord64 = s187 | s860
+  s862 :: SWord64 = if s603 then s861 else s860
+  s863 :: SWord64 = s190 | s862
+  s864 :: SWord64 = if s601 then s863 else s862
+  s865 :: SWord64 = s193 | s864
+  s866 :: SWord64 = if s599 then s865 else s864
+  s867 :: SWord64 = s196 | s866
+  s868 :: SWord64 = if s597 then s867 else s866
+  s869 :: SWord64 = s199 | s868
+  s870 :: SWord64 = if s595 then s869 else s868
+  s871 :: SWord64 = s202 | s870
+  s872 :: SWord64 = if s593 then s871 else s870
+  s873 :: SWord64 = s205 | s872
+  s874 :: SWord64 = if s591 then s873 else s872
+  s875 :: SWord64 = s208 | s874
+  s876 :: SWord64 = if s589 then s875 else s874
+  s877 :: SWord64 = s211 | s876
+  s878 :: SWord64 = if s587 then s877 else s876
+  s879 :: SWord64 = s214 | s878
+  s880 :: SWord64 = if s585 then s879 else s878
+  s881 :: SWord64 = s217 | s880
+  s882 :: SWord64 = if s583 then s881 else s880
+  s883 :: SWord64 = s220 | s882
+  s884 :: SWord64 = if s581 then s883 else s882
+  s885 :: SWord64 = s223 | s884
+  s886 :: SWord64 = if s579 then s885 else s884
+  s887 :: SWord64 = s226 | s886
+  s888 :: SWord64 = if s577 then s887 else s886
+  s889 :: SWord64 = s229 | s888
+  s890 :: SWord64 = if s575 then s889 else s888
+  s891 :: SWord64 = s232 | s890
+  s892 :: SWord64 = if s573 then s891 else s890
+  s893 :: SWord64 = s235 | s892
+  s894 :: SWord64 = if s571 then s893 else s892
+  s895 :: SWord64 = s238 | s894
+  s896 :: SWord64 = if s569 then s895 else s894
+  s897 :: SWord64 = s241 | s896
+  s898 :: SWord64 = if s567 then s897 else s896
+  s899 :: SWord16 = choose [15:0] s898
+  s900 :: SWord64 = s0 # s899
+  s901 :: SWord 1 = choose [0:0] s900
+  s902 :: SBool = s4 /= s901
+  s903 :: SWord 1 = choose [47:47] s1
+  s904 :: SBool = s4 /= s903
+  s905 :: SWord 1 = choose [46:46] s1
+  s906 :: SBool = s4 /= s905
+  s907 :: SWord 1 = choose [45:45] s1
+  s908 :: SBool = s4 /= s907
+  s909 :: SWord 1 = choose [44:44] s1
+  s910 :: SBool = s4 /= s909
+  s911 :: SWord 1 = choose [43:43] s1
+  s912 :: SBool = s4 /= s911
+  s913 :: SWord 1 = choose [42:42] s1
+  s914 :: SBool = s4 /= s913
+  s915 :: SWord 1 = choose [41:41] s1
+  s916 :: SBool = s4 /= s915
+  s917 :: SWord 1 = choose [40:40] s1
+  s918 :: SBool = s4 /= s917
+  s919 :: SWord 1 = choose [39:39] s1
+  s920 :: SBool = s4 /= s919
+  s921 :: SWord 1 = choose [38:38] s1
+  s922 :: SBool = s4 /= s921
+  s923 :: SWord 1 = choose [37:37] s1
+  s924 :: SBool = s4 /= s923
+  s925 :: SWord 1 = choose [36:36] s1
+  s926 :: SBool = s4 /= s925
+  s927 :: SWord 1 = choose [35:35] s1
+  s928 :: SBool = s4 /= s927
+  s929 :: SWord 1 = choose [34:34] s1
+  s930 :: SBool = s4 /= s929
+  s931 :: SWord 1 = choose [33:33] s1
+  s932 :: SBool = s4 /= s931
+  s933 :: SWord 1 = choose [32:32] s1
+  s934 :: SBool = s4 /= s933
+  s935 :: SWord 1 = choose [31:31] s1
+  s936 :: SBool = s4 /= s935
+  s937 :: SWord 1 = choose [30:30] s1
+  s938 :: SBool = s4 /= s937
+  s939 :: SWord 1 = choose [29:29] s1
+  s940 :: SBool = s4 /= s939
+  s941 :: SWord 1 = choose [28:28] s1
+  s942 :: SBool = s4 /= s941
+  s943 :: SWord 1 = choose [27:27] s1
+  s944 :: SBool = s4 /= s943
+  s945 :: SWord 1 = choose [26:26] s1
+  s946 :: SBool = s4 /= s945
+  s947 :: SWord 1 = choose [25:25] s1
+  s948 :: SBool = s4 /= s947
+  s949 :: SWord 1 = choose [24:24] s1
+  s950 :: SBool = s4 /= s949
+  s951 :: SWord 1 = choose [23:23] s1
+  s952 :: SBool = s4 /= s951
+  s953 :: SWord 1 = choose [22:22] s1
+  s954 :: SBool = s4 /= s953
+  s955 :: SWord 1 = choose [21:21] s1
+  s956 :: SBool = s4 /= s955
+  s957 :: SWord 1 = choose [20:20] s1
+  s958 :: SBool = s4 /= s957
+  s959 :: SWord 1 = choose [19:19] s1
+  s960 :: SBool = s4 /= s959
+  s961 :: SWord 1 = choose [18:18] s1
+  s962 :: SBool = s4 /= s961
+  s963 :: SWord 1 = choose [17:17] s1
+  s964 :: SBool = s4 /= s963
+  s965 :: SWord 1 = choose [16:16] s1
+  s966 :: SBool = s4 /= s965
+  s967 :: SWord 1 = choose [15:15] s1
+  s968 :: SBool = s4 /= s967
+  s969 :: SWord 1 = choose [14:14] s1
+  s970 :: SBool = s4 /= s969
+  s971 :: SWord 1 = choose [13:13] s1
+  s972 :: SBool = s4 /= s971
+  s973 :: SWord 1 = choose [12:12] s1
+  s974 :: SBool = s4 /= s973
+  s975 :: SWord 1 = choose [11:11] s1
+  s976 :: SBool = s4 /= s975
+  s977 :: SWord 1 = choose [10:10] s1
+  s978 :: SBool = s4 /= s977
+  s979 :: SWord 1 = choose [9:9] s1
+  s980 :: SBool = s4 /= s979
+  s981 :: SWord 1 = choose [8:8] s1
+  s982 :: SBool = s4 /= s981
+  s983 :: SWord 1 = choose [7:7] s1
+  s984 :: SBool = s4 /= s983
+  s985 :: SWord 1 = choose [6:6] s1
+  s986 :: SBool = s4 /= s985
+  s987 :: SWord 1 = choose [5:5] s1
+  s988 :: SBool = s4 /= s987
+  s989 :: SWord 1 = choose [4:4] s1
+  s990 :: SBool = s4 /= s989
+  s991 :: SWord 1 = choose [3:3] s1
+  s992 :: SBool = s4 /= s991
+  s993 :: SWord 1 = choose [2:2] s1
+  s994 :: SBool = s4 /= s993
+  s995 :: SWord 1 = choose [1:1] s1
+  s996 :: SBool = s4 /= s995
+  s997 :: SWord 1 = choose [0:0] s1
+  s998 :: SBool = s4 /= s997
+  s999 :: SWord64 = if s998 then s100 else s101
+  s1000 :: SWord64 = s103 | s999
+  s1001 :: SWord64 = if s996 then s1000 else s999
+  s1002 :: SWord64 = s106 | s1001
+  s1003 :: SWord64 = if s994 then s1002 else s1001
+  s1004 :: SWord64 = s109 | s1003
+  s1005 :: SWord64 = if s992 then s1004 else s1003
+  s1006 :: SWord64 = s112 | s1005
+  s1007 :: SWord64 = if s990 then s1006 else s1005
+  s1008 :: SWord64 = s115 | s1007
+  s1009 :: SWord64 = if s988 then s1008 else s1007
+  s1010 :: SWord64 = s118 | s1009
+  s1011 :: SWord64 = if s986 then s1010 else s1009
+  s1012 :: SWord64 = s121 | s1011
+  s1013 :: SWord64 = if s984 then s1012 else s1011
+  s1014 :: SWord64 = s124 | s1013
+  s1015 :: SWord64 = if s982 then s1014 else s1013
+  s1016 :: SWord64 = s127 | s1015
+  s1017 :: SWord64 = if s980 then s1016 else s1015
+  s1018 :: SWord64 = s130 | s1017
+  s1019 :: SWord64 = if s978 then s1018 else s1017
+  s1020 :: SWord64 = s133 | s1019
+  s1021 :: SWord64 = if s976 then s1020 else s1019
+  s1022 :: SWord64 = s136 | s1021
+  s1023 :: SWord64 = if s974 then s1022 else s1021
+  s1024 :: SWord64 = s139 | s1023
+  s1025 :: SWord64 = if s972 then s1024 else s1023
+  s1026 :: SWord64 = s142 | s1025
+  s1027 :: SWord64 = if s970 then s1026 else s1025
+  s1028 :: SWord64 = s145 | s1027
+  s1029 :: SWord64 = if s968 then s1028 else s1027
+  s1030 :: SWord64 = s148 | s1029
+  s1031 :: SWord64 = if s966 then s1030 else s1029
+  s1032 :: SWord64 = s151 | s1031
+  s1033 :: SWord64 = if s964 then s1032 else s1031
+  s1034 :: SWord64 = s154 | s1033
+  s1035 :: SWord64 = if s962 then s1034 else s1033
+  s1036 :: SWord64 = s157 | s1035
+  s1037 :: SWord64 = if s960 then s1036 else s1035
+  s1038 :: SWord64 = s160 | s1037
+  s1039 :: SWord64 = if s958 then s1038 else s1037
+  s1040 :: SWord64 = s163 | s1039
+  s1041 :: SWord64 = if s956 then s1040 else s1039
+  s1042 :: SWord64 = s166 | s1041
+  s1043 :: SWord64 = if s954 then s1042 else s1041
+  s1044 :: SWord64 = s169 | s1043
+  s1045 :: SWord64 = if s952 then s1044 else s1043
+  s1046 :: SWord64 = s172 | s1045
+  s1047 :: SWord64 = if s950 then s1046 else s1045
+  s1048 :: SWord64 = s175 | s1047
+  s1049 :: SWord64 = if s948 then s1048 else s1047
+  s1050 :: SWord64 = s178 | s1049
+  s1051 :: SWord64 = if s946 then s1050 else s1049
+  s1052 :: SWord64 = s181 | s1051
+  s1053 :: SWord64 = if s944 then s1052 else s1051
+  s1054 :: SWord64 = s184 | s1053
+  s1055 :: SWord64 = if s942 then s1054 else s1053
+  s1056 :: SWord64 = s187 | s1055
+  s1057 :: SWord64 = if s940 then s1056 else s1055
+  s1058 :: SWord64 = s190 | s1057
+  s1059 :: SWord64 = if s938 then s1058 else s1057
+  s1060 :: SWord64 = s193 | s1059
+  s1061 :: SWord64 = if s936 then s1060 else s1059
+  s1062 :: SWord64 = s196 | s1061
+  s1063 :: SWord64 = if s934 then s1062 else s1061
+  s1064 :: SWord64 = s199 | s1063
+  s1065 :: SWord64 = if s932 then s1064 else s1063
+  s1066 :: SWord64 = s202 | s1065
+  s1067 :: SWord64 = if s930 then s1066 else s1065
+  s1068 :: SWord64 = s205 | s1067
+  s1069 :: SWord64 = if s928 then s1068 else s1067
+  s1070 :: SWord64 = s208 | s1069
+  s1071 :: SWord64 = if s926 then s1070 else s1069
+  s1072 :: SWord64 = s211 | s1071
+  s1073 :: SWord64 = if s924 then s1072 else s1071
+  s1074 :: SWord64 = s214 | s1073
+  s1075 :: SWord64 = if s922 then s1074 else s1073
+  s1076 :: SWord64 = s217 | s1075
+  s1077 :: SWord64 = if s920 then s1076 else s1075
+  s1078 :: SWord64 = s220 | s1077
+  s1079 :: SWord64 = if s918 then s1078 else s1077
+  s1080 :: SWord64 = s223 | s1079
+  s1081 :: SWord64 = if s916 then s1080 else s1079
+  s1082 :: SWord64 = s226 | s1081
+  s1083 :: SWord64 = if s914 then s1082 else s1081
+  s1084 :: SWord64 = s229 | s1083
+  s1085 :: SWord64 = if s912 then s1084 else s1083
+  s1086 :: SWord64 = s232 | s1085
+  s1087 :: SWord64 = if s910 then s1086 else s1085
+  s1088 :: SWord64 = s235 | s1087
+  s1089 :: SWord64 = if s908 then s1088 else s1087
+  s1090 :: SWord64 = s238 | s1089
+  s1091 :: SWord64 = if s906 then s1090 else s1089
+  s1092 :: SWord64 = s241 | s1091
+  s1093 :: SWord64 = if s904 then s1092 else s1091
+  s1094 :: SWord 1 = choose [63:63] s1093
+  s1095 :: SBool = s4 /= s1094
+  s1096 :: SWord 1 = choose [62:62] s1093
+  s1097 :: SBool = s4 /= s1096
+  s1098 :: SWord 1 = choose [61:61] s1093
+  s1099 :: SBool = s4 /= s1098
+  s1100 :: SWord 1 = choose [60:60] s1093
+  s1101 :: SBool = s4 /= s1100
+  s1102 :: SWord 1 = choose [59:59] s1093
+  s1103 :: SBool = s4 /= s1102
+  s1104 :: SBool = ~ s1103
+  s1105 :: SBool = if s1095 then s1104 else s1103
+  s1106 :: SWord 1 = choose [58:58] s1093
+  s1107 :: SBool = s4 /= s1106
+  s1108 :: SBool = ~ s1107
+  s1109 :: SBool = if s1097 then s1108 else s1107
+  s1110 :: SWord 1 = choose [57:57] s1093
+  s1111 :: SBool = s4 /= s1110
+  s1112 :: SBool = ~ s1111
+  s1113 :: SBool = if s1099 then s1112 else s1111
+  s1114 :: SWord 1 = choose [56:56] s1093
+  s1115 :: SBool = s4 /= s1114
+  s1116 :: SBool = ~ s1115
+  s1117 :: SBool = if s1101 then s1116 else s1115
+  s1118 :: SWord 1 = choose [55:55] s1093
+  s1119 :: SBool = s4 /= s1118
+  s1120 :: SBool = ~ s1119
+  s1121 :: SBool = if s1105 then s1120 else s1119
+  s1122 :: SWord 1 = choose [54:54] s1093
+  s1123 :: SBool = s4 /= s1122
+  s1124 :: SBool = ~ s1123
+  s1125 :: SBool = if s1109 then s1124 else s1123
+  s1126 :: SWord 1 = choose [53:53] s1093
+  s1127 :: SBool = s4 /= s1126
+  s1128 :: SBool = ~ s1127
+  s1129 :: SBool = if s1113 then s1128 else s1127
+  s1130 :: SWord 1 = choose [52:52] s1093
+  s1131 :: SBool = s4 /= s1130
+  s1132 :: SBool = ~ s1131
+  s1133 :: SBool = if s1095 then s1132 else s1131
+  s1134 :: SBool = ~ s1133
+  s1135 :: SBool = if s1117 then s1134 else s1133
+  s1136 :: SWord 1 = choose [51:51] s1093
+  s1137 :: SBool = s4 /= s1136
+  s1138 :: SBool = ~ s1137
+  s1139 :: SBool = if s1097 then s1138 else s1137
+  s1140 :: SBool = ~ s1139
+  s1141 :: SBool = if s1121 then s1140 else s1139
+  s1142 :: SWord 1 = choose [50:50] s1093
+  s1143 :: SBool = s4 /= s1142
+  s1144 :: SBool = ~ s1143
+  s1145 :: SBool = if s1099 then s1144 else s1143
+  s1146 :: SBool = ~ s1145
+  s1147 :: SBool = if s1125 then s1146 else s1145
+  s1148 :: SWord 1 = choose [49:49] s1093
+  s1149 :: SBool = s4 /= s1148
+  s1150 :: SBool = ~ s1149
+  s1151 :: SBool = if s1101 then s1150 else s1149
+  s1152 :: SBool = ~ s1151
+  s1153 :: SBool = if s1129 then s1152 else s1151
+  s1154 :: SWord 1 = choose [48:48] s1093
+  s1155 :: SBool = s4 /= s1154
+  s1156 :: SBool = ~ s1155
+  s1157 :: SBool = if s1105 then s1156 else s1155
+  s1158 :: SBool = ~ s1157
+  s1159 :: SBool = if s1135 then s1158 else s1157
+  s1160 :: SWord 1 = choose [47:47] s1093
+  s1161 :: SBool = s4 /= s1160
+  s1162 :: SBool = ~ s1161
+  s1163 :: SBool = if s1095 then s1162 else s1161
+  s1164 :: SBool = ~ s1163
+  s1165 :: SBool = if s1109 then s1164 else s1163
+  s1166 :: SBool = ~ s1165
+  s1167 :: SBool = if s1141 then s1166 else s1165
+  s1168 :: SWord 1 = choose [46:46] s1093
+  s1169 :: SBool = s4 /= s1168
+  s1170 :: SBool = ~ s1169
+  s1171 :: SBool = if s1097 then s1170 else s1169
+  s1172 :: SBool = ~ s1171
+  s1173 :: SBool = if s1113 then s1172 else s1171
+  s1174 :: SBool = ~ s1173
+  s1175 :: SBool = if s1147 then s1174 else s1173
+  s1176 :: SWord 1 = choose [45:45] s1093
+  s1177 :: SBool = s4 /= s1176
+  s1178 :: SBool = ~ s1177
+  s1179 :: SBool = if s1099 then s1178 else s1177
+  s1180 :: SBool = ~ s1179
+  s1181 :: SBool = if s1117 then s1180 else s1179
+  s1182 :: SBool = ~ s1181
+  s1183 :: SBool = if s1153 then s1182 else s1181
+  s1184 :: SWord 1 = choose [44:44] s1093
+  s1185 :: SBool = s4 /= s1184
+  s1186 :: SBool = ~ s1185
+  s1187 :: SBool = if s1101 then s1186 else s1185
+  s1188 :: SBool = ~ s1187
+  s1189 :: SBool = if s1121 then s1188 else s1187
+  s1190 :: SBool = ~ s1189
+  s1191 :: SBool = if s1159 then s1190 else s1189
+  s1192 :: SWord 1 = choose [43:43] s1093
+  s1193 :: SBool = s4 /= s1192
+  s1194 :: SBool = ~ s1193
+  s1195 :: SBool = if s1105 then s1194 else s1193
+  s1196 :: SBool = ~ s1195
+  s1197 :: SBool = if s1125 then s1196 else s1195
+  s1198 :: SBool = ~ s1197
+  s1199 :: SBool = if s1167 then s1198 else s1197
+  s1200 :: SWord 1 = choose [42:42] s1093
+  s1201 :: SBool = s4 /= s1200
+  s1202 :: SBool = ~ s1201
+  s1203 :: SBool = if s1109 then s1202 else s1201
+  s1204 :: SBool = ~ s1203
+  s1205 :: SBool = if s1129 then s1204 else s1203
+  s1206 :: SBool = ~ s1205
+  s1207 :: SBool = if s1175 then s1206 else s1205
+  s1208 :: SWord 1 = choose [41:41] s1093
+  s1209 :: SBool = s4 /= s1208
+  s1210 :: SBool = ~ s1209
+  s1211 :: SBool = if s1113 then s1210 else s1209
+  s1212 :: SBool = ~ s1211
+  s1213 :: SBool = if s1135 then s1212 else s1211
+  s1214 :: SBool = ~ s1213
+  s1215 :: SBool = if s1183 then s1214 else s1213
+  s1216 :: SWord 1 = choose [40:40] s1093
+  s1217 :: SBool = s4 /= s1216
+  s1218 :: SBool = ~ s1217
+  s1219 :: SBool = if s1117 then s1218 else s1217
+  s1220 :: SBool = ~ s1219
+  s1221 :: SBool = if s1141 then s1220 else s1219
+  s1222 :: SBool = ~ s1221
+  s1223 :: SBool = if s1191 then s1222 else s1221
+  s1224 :: SWord 1 = choose [39:39] s1093
+  s1225 :: SBool = s4 /= s1224
+  s1226 :: SBool = ~ s1225
+  s1227 :: SBool = if s1121 then s1226 else s1225
+  s1228 :: SBool = ~ s1227
+  s1229 :: SBool = if s1147 then s1228 else s1227
+  s1230 :: SBool = ~ s1229
+  s1231 :: SBool = if s1199 then s1230 else s1229
+  s1232 :: SWord 1 = choose [38:38] s1093
+  s1233 :: SBool = s4 /= s1232
+  s1234 :: SBool = ~ s1233
+  s1235 :: SBool = if s1125 then s1234 else s1233
+  s1236 :: SBool = ~ s1235
+  s1237 :: SBool = if s1153 then s1236 else s1235
+  s1238 :: SBool = ~ s1237
+  s1239 :: SBool = if s1207 then s1238 else s1237
+  s1240 :: SWord 1 = choose [37:37] s1093
+  s1241 :: SBool = s4 /= s1240
+  s1242 :: SBool = ~ s1241
+  s1243 :: SBool = if s1129 then s1242 else s1241
+  s1244 :: SBool = ~ s1243
+  s1245 :: SBool = if s1159 then s1244 else s1243
+  s1246 :: SBool = ~ s1245
+  s1247 :: SBool = if s1215 then s1246 else s1245
+  s1248 :: SWord 1 = choose [36:36] s1093
+  s1249 :: SBool = s4 /= s1248
+  s1250 :: SBool = ~ s1249
+  s1251 :: SBool = if s1135 then s1250 else s1249
+  s1252 :: SBool = ~ s1251
+  s1253 :: SBool = if s1167 then s1252 else s1251
+  s1254 :: SBool = ~ s1253
+  s1255 :: SBool = if s1223 then s1254 else s1253
+  s1256 :: SWord 1 = choose [35:35] s1093
+  s1257 :: SBool = s4 /= s1256
+  s1258 :: SBool = ~ s1257
+  s1259 :: SBool = if s1141 then s1258 else s1257
+  s1260 :: SBool = ~ s1259
+  s1261 :: SBool = if s1175 then s1260 else s1259
+  s1262 :: SBool = ~ s1261
+  s1263 :: SBool = if s1231 then s1262 else s1261
+  s1264 :: SWord 1 = choose [34:34] s1093
+  s1265 :: SBool = s4 /= s1264
+  s1266 :: SBool = ~ s1265
+  s1267 :: SBool = if s1147 then s1266 else s1265
+  s1268 :: SBool = ~ s1267
+  s1269 :: SBool = if s1183 then s1268 else s1267
+  s1270 :: SBool = ~ s1269
+  s1271 :: SBool = if s1239 then s1270 else s1269
+  s1272 :: SWord 1 = choose [33:33] s1093
+  s1273 :: SBool = s4 /= s1272
+  s1274 :: SBool = ~ s1273
+  s1275 :: SBool = if s1153 then s1274 else s1273
+  s1276 :: SBool = ~ s1275
+  s1277 :: SBool = if s1191 then s1276 else s1275
+  s1278 :: SBool = ~ s1277
+  s1279 :: SBool = if s1247 then s1278 else s1277
+  s1280 :: SWord 1 = choose [32:32] s1093
+  s1281 :: SBool = s4 /= s1280
+  s1282 :: SBool = ~ s1281
+  s1283 :: SBool = if s1159 then s1282 else s1281
+  s1284 :: SBool = ~ s1283
+  s1285 :: SBool = if s1199 then s1284 else s1283
+  s1286 :: SBool = ~ s1285
+  s1287 :: SBool = if s1255 then s1286 else s1285
+  s1288 :: SWord 1 = choose [31:31] s1093
+  s1289 :: SBool = s4 /= s1288
+  s1290 :: SBool = ~ s1289
+  s1291 :: SBool = if s1167 then s1290 else s1289
+  s1292 :: SBool = ~ s1291
+  s1293 :: SBool = if s1207 then s1292 else s1291
+  s1294 :: SBool = ~ s1293
+  s1295 :: SBool = if s1263 then s1294 else s1293
+  s1296 :: SWord 1 = choose [30:30] s1093
+  s1297 :: SBool = s4 /= s1296
+  s1298 :: SBool = ~ s1297
+  s1299 :: SBool = if s1175 then s1298 else s1297
+  s1300 :: SBool = ~ s1299
+  s1301 :: SBool = if s1215 then s1300 else s1299
+  s1302 :: SBool = ~ s1301
+  s1303 :: SBool = if s1271 then s1302 else s1301
+  s1304 :: SWord 1 = choose [29:29] s1093
+  s1305 :: SBool = s4 /= s1304
+  s1306 :: SBool = ~ s1305
+  s1307 :: SBool = if s1183 then s1306 else s1305
+  s1308 :: SBool = ~ s1307
+  s1309 :: SBool = if s1223 then s1308 else s1307
+  s1310 :: SBool = ~ s1309
+  s1311 :: SBool = if s1279 then s1310 else s1309
+  s1312 :: SWord 1 = choose [28:28] s1093
+  s1313 :: SBool = s4 /= s1312
+  s1314 :: SBool = ~ s1313
+  s1315 :: SBool = if s1191 then s1314 else s1313
+  s1316 :: SBool = ~ s1315
+  s1317 :: SBool = if s1231 then s1316 else s1315
+  s1318 :: SBool = ~ s1317
+  s1319 :: SBool = if s1287 then s1318 else s1317
+  s1320 :: SWord 1 = choose [27:27] s1093
+  s1321 :: SBool = s4 /= s1320
+  s1322 :: SBool = ~ s1321
+  s1323 :: SBool = if s1199 then s1322 else s1321
+  s1324 :: SBool = ~ s1323
+  s1325 :: SBool = if s1239 then s1324 else s1323
+  s1326 :: SBool = ~ s1325
+  s1327 :: SBool = if s1295 then s1326 else s1325
+  s1328 :: SWord 1 = choose [26:26] s1093
+  s1329 :: SBool = s4 /= s1328
+  s1330 :: SBool = ~ s1329
+  s1331 :: SBool = if s1207 then s1330 else s1329
+  s1332 :: SBool = ~ s1331
+  s1333 :: SBool = if s1247 then s1332 else s1331
+  s1334 :: SBool = ~ s1333
+  s1335 :: SBool = if s1303 then s1334 else s1333
+  s1336 :: SWord 1 = choose [25:25] s1093
+  s1337 :: SBool = s4 /= s1336
+  s1338 :: SBool = ~ s1337
+  s1339 :: SBool = if s1215 then s1338 else s1337
+  s1340 :: SBool = ~ s1339
+  s1341 :: SBool = if s1255 then s1340 else s1339
+  s1342 :: SBool = ~ s1341
+  s1343 :: SBool = if s1311 then s1342 else s1341
+  s1344 :: SWord 1 = choose [24:24] s1093
+  s1345 :: SBool = s4 /= s1344
+  s1346 :: SBool = ~ s1345
+  s1347 :: SBool = if s1223 then s1346 else s1345
+  s1348 :: SBool = ~ s1347
+  s1349 :: SBool = if s1263 then s1348 else s1347
+  s1350 :: SBool = ~ s1349
+  s1351 :: SBool = if s1319 then s1350 else s1349
+  s1352 :: SWord 1 = choose [23:23] s1093
+  s1353 :: SBool = s4 /= s1352
+  s1354 :: SBool = ~ s1353
+  s1355 :: SBool = if s1231 then s1354 else s1353
+  s1356 :: SBool = ~ s1355
+  s1357 :: SBool = if s1271 then s1356 else s1355
+  s1358 :: SBool = ~ s1357
+  s1359 :: SBool = if s1327 then s1358 else s1357
+  s1360 :: SWord 1 = choose [22:22] s1093
+  s1361 :: SBool = s4 /= s1360
+  s1362 :: SBool = ~ s1361
+  s1363 :: SBool = if s1239 then s1362 else s1361
+  s1364 :: SBool = ~ s1363
+  s1365 :: SBool = if s1279 then s1364 else s1363
+  s1366 :: SBool = ~ s1365
+  s1367 :: SBool = if s1335 then s1366 else s1365
+  s1368 :: SWord 1 = choose [21:21] s1093
+  s1369 :: SBool = s4 /= s1368
+  s1370 :: SBool = ~ s1369
+  s1371 :: SBool = if s1247 then s1370 else s1369
+  s1372 :: SBool = ~ s1371
+  s1373 :: SBool = if s1287 then s1372 else s1371
+  s1374 :: SBool = ~ s1373
+  s1375 :: SBool = if s1343 then s1374 else s1373
+  s1376 :: SWord 1 = choose [20:20] s1093
+  s1377 :: SBool = s4 /= s1376
+  s1378 :: SBool = ~ s1377
+  s1379 :: SBool = if s1255 then s1378 else s1377
+  s1380 :: SBool = ~ s1379
+  s1381 :: SBool = if s1295 then s1380 else s1379
+  s1382 :: SBool = ~ s1381
+  s1383 :: SBool = if s1351 then s1382 else s1381
+  s1384 :: SWord 1 = choose [19:19] s1093
+  s1385 :: SBool = s4 /= s1384
+  s1386 :: SBool = ~ s1385
+  s1387 :: SBool = if s1263 then s1386 else s1385
+  s1388 :: SBool = ~ s1387
+  s1389 :: SBool = if s1303 then s1388 else s1387
+  s1390 :: SBool = ~ s1389
+  s1391 :: SBool = if s1359 then s1390 else s1389
+  s1392 :: SWord 1 = choose [18:18] s1093
+  s1393 :: SBool = s4 /= s1392
+  s1394 :: SBool = ~ s1393
+  s1395 :: SBool = if s1271 then s1394 else s1393
+  s1396 :: SBool = ~ s1395
+  s1397 :: SBool = if s1311 then s1396 else s1395
+  s1398 :: SBool = ~ s1397
+  s1399 :: SBool = if s1367 then s1398 else s1397
+  s1400 :: SWord 1 = choose [17:17] s1093
+  s1401 :: SBool = s4 /= s1400
+  s1402 :: SBool = ~ s1401
+  s1403 :: SBool = if s1279 then s1402 else s1401
+  s1404 :: SBool = ~ s1403
+  s1405 :: SBool = if s1319 then s1404 else s1403
+  s1406 :: SBool = ~ s1405
+  s1407 :: SBool = if s1375 then s1406 else s1405
+  s1408 :: SWord 1 = choose [16:16] s1093
+  s1409 :: SBool = s4 /= s1408
+  s1410 :: SBool = ~ s1409
+  s1411 :: SBool = if s1287 then s1410 else s1409
+  s1412 :: SBool = ~ s1411
+  s1413 :: SBool = if s1327 then s1412 else s1411
+  s1414 :: SBool = ~ s1413
+  s1415 :: SBool = if s1383 then s1414 else s1413
+  s1416 :: SBool = ~ s1095
+  s1417 :: SBool = if s1095 then s1416 else s1095
+  s1418 :: SBool = ~ s1097
+  s1419 :: SBool = if s1097 then s1418 else s1097
+  s1420 :: SBool = ~ s1099
+  s1421 :: SBool = if s1099 then s1420 else s1099
+  s1422 :: SBool = ~ s1101
+  s1423 :: SBool = if s1101 then s1422 else s1101
+  s1424 :: SBool = ~ s1105
+  s1425 :: SBool = if s1105 then s1424 else s1105
+  s1426 :: SBool = ~ s1109
+  s1427 :: SBool = if s1109 then s1426 else s1109
+  s1428 :: SBool = ~ s1113
+  s1429 :: SBool = if s1113 then s1428 else s1113
+  s1430 :: SBool = ~ s1117
+  s1431 :: SBool = if s1117 then s1430 else s1117
+  s1432 :: SBool = ~ s1121
+  s1433 :: SBool = if s1121 then s1432 else s1121
+  s1434 :: SBool = ~ s1125
+  s1435 :: SBool = if s1125 then s1434 else s1125
+  s1436 :: SBool = ~ s1129
+  s1437 :: SBool = if s1129 then s1436 else s1129
+  s1438 :: SBool = ~ s1135
+  s1439 :: SBool = if s1135 then s1438 else s1135
+  s1440 :: SBool = ~ s1141
+  s1441 :: SBool = if s1141 then s1440 else s1141
+  s1442 :: SBool = ~ s1147
+  s1443 :: SBool = if s1147 then s1442 else s1147
+  s1444 :: SBool = ~ s1153
+  s1445 :: SBool = if s1153 then s1444 else s1153
+  s1446 :: SBool = ~ s1159
+  s1447 :: SBool = if s1159 then s1446 else s1159
+  s1448 :: SBool = ~ s1167
+  s1449 :: SBool = if s1167 then s1448 else s1167
+  s1450 :: SBool = ~ s1175
+  s1451 :: SBool = if s1175 then s1450 else s1175
+  s1452 :: SBool = ~ s1183
+  s1453 :: SBool = if s1183 then s1452 else s1183
+  s1454 :: SBool = ~ s1191
+  s1455 :: SBool = if s1191 then s1454 else s1191
+  s1456 :: SBool = ~ s1199
+  s1457 :: SBool = if s1199 then s1456 else s1199
+  s1458 :: SBool = ~ s1207
+  s1459 :: SBool = if s1207 then s1458 else s1207
+  s1460 :: SBool = ~ s1215
+  s1461 :: SBool = if s1215 then s1460 else s1215
+  s1462 :: SBool = ~ s1223
+  s1463 :: SBool = if s1223 then s1462 else s1223
+  s1464 :: SBool = ~ s1231
+  s1465 :: SBool = if s1231 then s1464 else s1231
+  s1466 :: SBool = ~ s1239
+  s1467 :: SBool = if s1239 then s1466 else s1239
+  s1468 :: SBool = ~ s1247
+  s1469 :: SBool = if s1247 then s1468 else s1247
+  s1470 :: SBool = ~ s1255
+  s1471 :: SBool = if s1255 then s1470 else s1255
+  s1472 :: SBool = ~ s1263
+  s1473 :: SBool = if s1263 then s1472 else s1263
+  s1474 :: SBool = ~ s1271
+  s1475 :: SBool = if s1271 then s1474 else s1271
+  s1476 :: SBool = ~ s1279
+  s1477 :: SBool = if s1279 then s1476 else s1279
+  s1478 :: SBool = ~ s1287
+  s1479 :: SBool = if s1287 then s1478 else s1287
+  s1480 :: SBool = ~ s1295
+  s1481 :: SBool = if s1295 then s1480 else s1295
+  s1482 :: SBool = ~ s1303
+  s1483 :: SBool = if s1303 then s1482 else s1303
+  s1484 :: SBool = ~ s1311
+  s1485 :: SBool = if s1311 then s1484 else s1311
+  s1486 :: SBool = ~ s1319
+  s1487 :: SBool = if s1319 then s1486 else s1319
+  s1488 :: SBool = ~ s1327
+  s1489 :: SBool = if s1327 then s1488 else s1327
+  s1490 :: SBool = ~ s1335
+  s1491 :: SBool = if s1335 then s1490 else s1335
+  s1492 :: SBool = ~ s1343
+  s1493 :: SBool = if s1343 then s1492 else s1343
+  s1494 :: SBool = ~ s1351
+  s1495 :: SBool = if s1351 then s1494 else s1351
+  s1496 :: SBool = ~ s1359
+  s1497 :: SBool = if s1359 then s1496 else s1359
+  s1498 :: SBool = ~ s1367
+  s1499 :: SBool = if s1367 then s1498 else s1367
+  s1500 :: SBool = ~ s1375
+  s1501 :: SBool = if s1375 then s1500 else s1375
+  s1502 :: SBool = ~ s1383
+  s1503 :: SBool = if s1383 then s1502 else s1383
+  s1504 :: SBool = ~ s1391
+  s1505 :: SBool = if s1391 then s1504 else s1391
+  s1506 :: SBool = ~ s1399
+  s1507 :: SBool = if s1399 then s1506 else s1399
+  s1508 :: SBool = ~ s1407
+  s1509 :: SBool = if s1407 then s1508 else s1407
+  s1510 :: SBool = ~ s1415
+  s1511 :: SBool = if s1415 then s1510 else s1415
+  s1512 :: SWord 1 = choose [15:15] s1093
+  s1513 :: SBool = s4 /= s1512
+  s1514 :: SBool = ~ s1513
+  s1515 :: SBool = if s1295 then s1514 else s1513
+  s1516 :: SBool = ~ s1515
+  s1517 :: SBool = if s1335 then s1516 else s1515
+  s1518 :: SBool = ~ s1517
+  s1519 :: SBool = if s1391 then s1518 else s1517
+  s1520 :: SWord 1 = choose [14:14] s1093
+  s1521 :: SBool = s4 /= s1520
+  s1522 :: SBool = ~ s1521
+  s1523 :: SBool = if s1303 then s1522 else s1521
+  s1524 :: SBool = ~ s1523
+  s1525 :: SBool = if s1343 then s1524 else s1523
+  s1526 :: SBool = ~ s1525
+  s1527 :: SBool = if s1399 then s1526 else s1525
+  s1528 :: SWord 1 = choose [13:13] s1093
+  s1529 :: SBool = s4 /= s1528
+  s1530 :: SBool = ~ s1529
+  s1531 :: SBool = if s1311 then s1530 else s1529
+  s1532 :: SBool = ~ s1531
+  s1533 :: SBool = if s1351 then s1532 else s1531
+  s1534 :: SBool = ~ s1533
+  s1535 :: SBool = if s1407 then s1534 else s1533
+  s1536 :: SWord 1 = choose [12:12] s1093
+  s1537 :: SBool = s4 /= s1536
+  s1538 :: SBool = ~ s1537
+  s1539 :: SBool = if s1319 then s1538 else s1537
+  s1540 :: SBool = ~ s1539
+  s1541 :: SBool = if s1359 then s1540 else s1539
+  s1542 :: SBool = ~ s1541
+  s1543 :: SBool = if s1415 then s1542 else s1541
+  s1544 :: SWord 1 = choose [11:11] s1093
+  s1545 :: SBool = s4 /= s1544
+  s1546 :: SBool = ~ s1545
+  s1547 :: SBool = if s1327 then s1546 else s1545
+  s1548 :: SBool = ~ s1547
+  s1549 :: SBool = if s1367 then s1548 else s1547
+  s1550 :: SWord 1 = choose [10:10] s1093
+  s1551 :: SBool = s4 /= s1550
+  s1552 :: SBool = ~ s1551
+  s1553 :: SBool = if s1335 then s1552 else s1551
+  s1554 :: SBool = ~ s1553
+  s1555 :: SBool = if s1375 then s1554 else s1553
+  s1556 :: SWord 1 = choose [9:9] s1093
+  s1557 :: SBool = s4 /= s1556
+  s1558 :: SBool = ~ s1557
+  s1559 :: SBool = if s1343 then s1558 else s1557
+  s1560 :: SBool = ~ s1559
+  s1561 :: SBool = if s1383 then s1560 else s1559
+  s1562 :: SWord 1 = choose [8:8] s1093
+  s1563 :: SBool = s4 /= s1562
+  s1564 :: SBool = ~ s1563
+  s1565 :: SBool = if s1351 then s1564 else s1563
+  s1566 :: SBool = ~ s1565
+  s1567 :: SBool = if s1391 then s1566 else s1565
+  s1568 :: SWord 1 = choose [7:7] s1093
+  s1569 :: SBool = s4 /= s1568
+  s1570 :: SBool = ~ s1569
+  s1571 :: SBool = if s1359 then s1570 else s1569
+  s1572 :: SBool = ~ s1571
+  s1573 :: SBool = if s1399 then s1572 else s1571
+  s1574 :: SWord 1 = choose [6:6] s1093
+  s1575 :: SBool = s4 /= s1574
+  s1576 :: SBool = ~ s1575
+  s1577 :: SBool = if s1367 then s1576 else s1575
+  s1578 :: SBool = ~ s1577
+  s1579 :: SBool = if s1407 then s1578 else s1577
+  s1580 :: SWord 1 = choose [5:5] s1093
+  s1581 :: SBool = s4 /= s1580
+  s1582 :: SBool = ~ s1581
+  s1583 :: SBool = if s1375 then s1582 else s1581
+  s1584 :: SBool = ~ s1583
+  s1585 :: SBool = if s1415 then s1584 else s1583
+  s1586 :: SWord 1 = choose [4:4] s1093
+  s1587 :: SBool = s4 /= s1586
+  s1588 :: SBool = ~ s1587
+  s1589 :: SBool = if s1383 then s1588 else s1587
+  s1590 :: SWord 1 = choose [3:3] s1093
+  s1591 :: SBool = s4 /= s1590
+  s1592 :: SBool = ~ s1591
+  s1593 :: SBool = if s1391 then s1592 else s1591
+  s1594 :: SWord 1 = choose [2:2] s1093
+  s1595 :: SBool = s4 /= s1594
+  s1596 :: SBool = ~ s1595
+  s1597 :: SBool = if s1399 then s1596 else s1595
+  s1598 :: SWord 1 = choose [1:1] s1093
+  s1599 :: SBool = s4 /= s1598
+  s1600 :: SBool = ~ s1599
+  s1601 :: SBool = if s1407 then s1600 else s1599
+  s1602 :: SWord 1 = choose [0:0] s1093
+  s1603 :: SBool = s4 /= s1602
+  s1604 :: SBool = ~ s1603
+  s1605 :: SBool = if s1415 then s1604 else s1603
+  s1606 :: SWord64 = if s1605 then s756 else s101
+  s1607 :: SWord64 = s758 | s1606
+  s1608 :: SWord64 = if s1601 then s1607 else s1606
+  s1609 :: SWord64 = s761 | s1608
+  s1610 :: SWord64 = if s1597 then s1609 else s1608
+  s1611 :: SWord64 = s764 | s1610
+  s1612 :: SWord64 = if s1593 then s1611 else s1610
+  s1613 :: SWord64 = s767 | s1612
+  s1614 :: SWord64 = if s1589 then s1613 else s1612
+  s1615 :: SWord64 = s770 | s1614
+  s1616 :: SWord64 = if s1585 then s1615 else s1614
+  s1617 :: SWord64 = s773 | s1616
+  s1618 :: SWord64 = if s1579 then s1617 else s1616
+  s1619 :: SWord64 = s776 | s1618
+  s1620 :: SWord64 = if s1573 then s1619 else s1618
+  s1621 :: SWord64 = s779 | s1620
+  s1622 :: SWord64 = if s1567 then s1621 else s1620
+  s1623 :: SWord64 = s782 | s1622
+  s1624 :: SWord64 = if s1561 then s1623 else s1622
+  s1625 :: SWord64 = s785 | s1624
+  s1626 :: SWord64 = if s1555 then s1625 else s1624
+  s1627 :: SWord64 = s788 | s1626
+  s1628 :: SWord64 = if s1549 then s1627 else s1626
+  s1629 :: SWord64 = s791 | s1628
+  s1630 :: SWord64 = if s1543 then s1629 else s1628
+  s1631 :: SWord64 = s794 | s1630
+  s1632 :: SWord64 = if s1535 then s1631 else s1630
+  s1633 :: SWord64 = s797 | s1632
+  s1634 :: SWord64 = if s1527 then s1633 else s1632
+  s1635 :: SWord64 = s800 | s1634
+  s1636 :: SWord64 = if s1519 then s1635 else s1634
+  s1637 :: SWord64 = s100 | s1636
+  s1638 :: SWord64 = if s1511 then s1637 else s1636
+  s1639 :: SWord64 = s103 | s1638
+  s1640 :: SWord64 = if s1509 then s1639 else s1638
+  s1641 :: SWord64 = s106 | s1640
+  s1642 :: SWord64 = if s1507 then s1641 else s1640
+  s1643 :: SWord64 = s109 | s1642
+  s1644 :: SWord64 = if s1505 then s1643 else s1642
+  s1645 :: SWord64 = s112 | s1644
+  s1646 :: SWord64 = if s1503 then s1645 else s1644
+  s1647 :: SWord64 = s115 | s1646
+  s1648 :: SWord64 = if s1501 then s1647 else s1646
+  s1649 :: SWord64 = s118 | s1648
+  s1650 :: SWord64 = if s1499 then s1649 else s1648
+  s1651 :: SWord64 = s121 | s1650
+  s1652 :: SWord64 = if s1497 then s1651 else s1650
+  s1653 :: SWord64 = s124 | s1652
+  s1654 :: SWord64 = if s1495 then s1653 else s1652
+  s1655 :: SWord64 = s127 | s1654
+  s1656 :: SWord64 = if s1493 then s1655 else s1654
+  s1657 :: SWord64 = s130 | s1656
+  s1658 :: SWord64 = if s1491 then s1657 else s1656
+  s1659 :: SWord64 = s133 | s1658
+  s1660 :: SWord64 = if s1489 then s1659 else s1658
+  s1661 :: SWord64 = s136 | s1660
+  s1662 :: SWord64 = if s1487 then s1661 else s1660
+  s1663 :: SWord64 = s139 | s1662
+  s1664 :: SWord64 = if s1485 then s1663 else s1662
+  s1665 :: SWord64 = s142 | s1664
+  s1666 :: SWord64 = if s1483 then s1665 else s1664
+  s1667 :: SWord64 = s145 | s1666
+  s1668 :: SWord64 = if s1481 then s1667 else s1666
+  s1669 :: SWord64 = s148 | s1668
+  s1670 :: SWord64 = if s1479 then s1669 else s1668
+  s1671 :: SWord64 = s151 | s1670
+  s1672 :: SWord64 = if s1477 then s1671 else s1670
+  s1673 :: SWord64 = s154 | s1672
+  s1674 :: SWord64 = if s1475 then s1673 else s1672
+  s1675 :: SWord64 = s157 | s1674
+  s1676 :: SWord64 = if s1473 then s1675 else s1674
+  s1677 :: SWord64 = s160 | s1676
+  s1678 :: SWord64 = if s1471 then s1677 else s1676
+  s1679 :: SWord64 = s163 | s1678
+  s1680 :: SWord64 = if s1469 then s1679 else s1678
+  s1681 :: SWord64 = s166 | s1680
+  s1682 :: SWord64 = if s1467 then s1681 else s1680
+  s1683 :: SWord64 = s169 | s1682
+  s1684 :: SWord64 = if s1465 then s1683 else s1682
+  s1685 :: SWord64 = s172 | s1684
+  s1686 :: SWord64 = if s1463 then s1685 else s1684
+  s1687 :: SWord64 = s175 | s1686
+  s1688 :: SWord64 = if s1461 then s1687 else s1686
+  s1689 :: SWord64 = s178 | s1688
+  s1690 :: SWord64 = if s1459 then s1689 else s1688
+  s1691 :: SWord64 = s181 | s1690
+  s1692 :: SWord64 = if s1457 then s1691 else s1690
+  s1693 :: SWord64 = s184 | s1692
+  s1694 :: SWord64 = if s1455 then s1693 else s1692
+  s1695 :: SWord64 = s187 | s1694
+  s1696 :: SWord64 = if s1453 then s1695 else s1694
+  s1697 :: SWord64 = s190 | s1696
+  s1698 :: SWord64 = if s1451 then s1697 else s1696
+  s1699 :: SWord64 = s193 | s1698
+  s1700 :: SWord64 = if s1449 then s1699 else s1698
+  s1701 :: SWord64 = s196 | s1700
+  s1702 :: SWord64 = if s1447 then s1701 else s1700
+  s1703 :: SWord64 = s199 | s1702
+  s1704 :: SWord64 = if s1445 then s1703 else s1702
+  s1705 :: SWord64 = s202 | s1704
+  s1706 :: SWord64 = if s1443 then s1705 else s1704
+  s1707 :: SWord64 = s205 | s1706
+  s1708 :: SWord64 = if s1441 then s1707 else s1706
+  s1709 :: SWord64 = s208 | s1708
+  s1710 :: SWord64 = if s1439 then s1709 else s1708
+  s1711 :: SWord64 = s211 | s1710
+  s1712 :: SWord64 = if s1437 then s1711 else s1710
+  s1713 :: SWord64 = s214 | s1712
+  s1714 :: SWord64 = if s1435 then s1713 else s1712
+  s1715 :: SWord64 = s217 | s1714
+  s1716 :: SWord64 = if s1433 then s1715 else s1714
+  s1717 :: SWord64 = s220 | s1716
+  s1718 :: SWord64 = if s1431 then s1717 else s1716
+  s1719 :: SWord64 = s223 | s1718
+  s1720 :: SWord64 = if s1429 then s1719 else s1718
+  s1721 :: SWord64 = s226 | s1720
+  s1722 :: SWord64 = if s1427 then s1721 else s1720
+  s1723 :: SWord64 = s229 | s1722
+  s1724 :: SWord64 = if s1425 then s1723 else s1722
+  s1725 :: SWord64 = s232 | s1724
+  s1726 :: SWord64 = if s1423 then s1725 else s1724
+  s1727 :: SWord64 = s235 | s1726
+  s1728 :: SWord64 = if s1421 then s1727 else s1726
+  s1729 :: SWord64 = s238 | s1728
+  s1730 :: SWord64 = if s1419 then s1729 else s1728
+  s1731 :: SWord64 = s241 | s1730
+  s1732 :: SWord64 = if s1417 then s1731 else s1730
+  s1733 :: SWord16 = choose [15:0] s1732
+  s1734 :: SWord64 = s1 # s1733
+  s1735 :: SWord 1 = choose [0:0] s1734
+  s1736 :: SBool = s4 /= s1735
+  s1737 :: SBool = s902 == s1736
+  s1738 :: SWord 1 = choose [1:1] s900
+  s1739 :: SBool = s4 /= s1738
+  s1740 :: SWord 1 = choose [1:1] s1734
+  s1741 :: SBool = s4 /= s1740
+  s1742 :: SBool = s1739 == s1741
+  s1743 :: SWord 1 = choose [2:2] s900
+  s1744 :: SBool = s4 /= s1743
+  s1745 :: SWord 1 = choose [2:2] s1734
+  s1746 :: SBool = s4 /= s1745
+  s1747 :: SBool = s1744 == s1746
+  s1748 :: SWord 1 = choose [3:3] s900
+  s1749 :: SBool = s4 /= s1748
+  s1750 :: SWord 1 = choose [3:3] s1734
+  s1751 :: SBool = s4 /= s1750
+  s1752 :: SBool = s1749 == s1751
+  s1753 :: SWord 1 = choose [4:4] s900
+  s1754 :: SBool = s4 /= s1753
+  s1755 :: SWord 1 = choose [4:4] s1734
+  s1756 :: SBool = s4 /= s1755
+  s1757 :: SBool = s1754 == s1756
+  s1758 :: SWord 1 = choose [5:5] s900
+  s1759 :: SBool = s4 /= s1758
+  s1760 :: SWord 1 = choose [5:5] s1734
+  s1761 :: SBool = s4 /= s1760
+  s1762 :: SBool = s1759 == s1761
+  s1763 :: SWord 1 = choose [6:6] s900
+  s1764 :: SBool = s4 /= s1763
+  s1765 :: SWord 1 = choose [6:6] s1734
+  s1766 :: SBool = s4 /= s1765
+  s1767 :: SBool = s1764 == s1766
+  s1768 :: SWord 1 = choose [7:7] s900
+  s1769 :: SBool = s4 /= s1768
+  s1770 :: SWord 1 = choose [7:7] s1734
+  s1771 :: SBool = s4 /= s1770
+  s1772 :: SBool = s1769 == s1771
+  s1773 :: SWord 1 = choose [8:8] s900
+  s1774 :: SBool = s4 /= s1773
+  s1775 :: SWord 1 = choose [8:8] s1734
+  s1776 :: SBool = s4 /= s1775
+  s1777 :: SBool = s1774 == s1776
+  s1778 :: SWord 1 = choose [9:9] s900
+  s1779 :: SBool = s4 /= s1778
+  s1780 :: SWord 1 = choose [9:9] s1734
+  s1781 :: SBool = s4 /= s1780
+  s1782 :: SBool = s1779 == s1781
+  s1783 :: SWord 1 = choose [10:10] s900
+  s1784 :: SBool = s4 /= s1783
+  s1785 :: SWord 1 = choose [10:10] s1734
+  s1786 :: SBool = s4 /= s1785
+  s1787 :: SBool = s1784 == s1786
+  s1788 :: SWord 1 = choose [11:11] s900
+  s1789 :: SBool = s4 /= s1788
+  s1790 :: SWord 1 = choose [11:11] s1734
+  s1791 :: SBool = s4 /= s1790
+  s1792 :: SBool = s1789 == s1791
+  s1793 :: SWord 1 = choose [12:12] s900
+  s1794 :: SBool = s4 /= s1793
+  s1795 :: SWord 1 = choose [12:12] s1734
+  s1796 :: SBool = s4 /= s1795
+  s1797 :: SBool = s1794 == s1796
+  s1798 :: SWord 1 = choose [13:13] s900
+  s1799 :: SBool = s4 /= s1798
+  s1800 :: SWord 1 = choose [13:13] s1734
+  s1801 :: SBool = s4 /= s1800
+  s1802 :: SBool = s1799 == s1801
+  s1803 :: SWord 1 = choose [14:14] s900
+  s1804 :: SBool = s4 /= s1803
+  s1805 :: SWord 1 = choose [14:14] s1734
+  s1806 :: SBool = s4 /= s1805
+  s1807 :: SBool = s1804 == s1806
+  s1808 :: SWord 1 = choose [15:15] s900
+  s1809 :: SBool = s4 /= s1808
+  s1810 :: SWord 1 = choose [15:15] s1734
+  s1811 :: SBool = s4 /= s1810
+  s1812 :: SBool = s1809 == s1811
+  s1813 :: SWord 1 = choose [16:16] s900
+  s1814 :: SBool = s4 /= s1813
+  s1815 :: SWord 1 = choose [16:16] s1734
+  s1816 :: SBool = s4 /= s1815
+  s1817 :: SBool = s1814 == s1816
+  s1818 :: SWord 1 = choose [17:17] s900
+  s1819 :: SBool = s4 /= s1818
+  s1820 :: SWord 1 = choose [17:17] s1734
+  s1821 :: SBool = s4 /= s1820
+  s1822 :: SBool = s1819 == s1821
+  s1823 :: SWord 1 = choose [18:18] s900
+  s1824 :: SBool = s4 /= s1823
+  s1825 :: SWord 1 = choose [18:18] s1734
+  s1826 :: SBool = s4 /= s1825
+  s1827 :: SBool = s1824 == s1826
+  s1828 :: SWord 1 = choose [19:19] s900
+  s1829 :: SBool = s4 /= s1828
+  s1830 :: SWord 1 = choose [19:19] s1734
+  s1831 :: SBool = s4 /= s1830
+  s1832 :: SBool = s1829 == s1831
+  s1833 :: SWord 1 = choose [20:20] s900
+  s1834 :: SBool = s4 /= s1833
+  s1835 :: SWord 1 = choose [20:20] s1734
+  s1836 :: SBool = s4 /= s1835
+  s1837 :: SBool = s1834 == s1836
+  s1838 :: SWord 1 = choose [21:21] s900
+  s1839 :: SBool = s4 /= s1838
+  s1840 :: SWord 1 = choose [21:21] s1734
+  s1841 :: SBool = s4 /= s1840
+  s1842 :: SBool = s1839 == s1841
+  s1843 :: SWord 1 = choose [22:22] s900
+  s1844 :: SBool = s4 /= s1843
+  s1845 :: SWord 1 = choose [22:22] s1734
+  s1846 :: SBool = s4 /= s1845
+  s1847 :: SBool = s1844 == s1846
+  s1848 :: SWord 1 = choose [23:23] s900
+  s1849 :: SBool = s4 /= s1848
+  s1850 :: SWord 1 = choose [23:23] s1734
+  s1851 :: SBool = s4 /= s1850
+  s1852 :: SBool = s1849 == s1851
+  s1853 :: SWord 1 = choose [24:24] s900
+  s1854 :: SBool = s4 /= s1853
+  s1855 :: SWord 1 = choose [24:24] s1734
+  s1856 :: SBool = s4 /= s1855
+  s1857 :: SBool = s1854 == s1856
+  s1858 :: SWord 1 = choose [25:25] s900
+  s1859 :: SBool = s4 /= s1858
+  s1860 :: SWord 1 = choose [25:25] s1734
+  s1861 :: SBool = s4 /= s1860
+  s1862 :: SBool = s1859 == s1861
+  s1863 :: SWord 1 = choose [26:26] s900
+  s1864 :: SBool = s4 /= s1863
+  s1865 :: SWord 1 = choose [26:26] s1734
+  s1866 :: SBool = s4 /= s1865
+  s1867 :: SBool = s1864 == s1866
+  s1868 :: SWord 1 = choose [27:27] s900
+  s1869 :: SBool = s4 /= s1868
+  s1870 :: SWord 1 = choose [27:27] s1734
+  s1871 :: SBool = s4 /= s1870
+  s1872 :: SBool = s1869 == s1871
+  s1873 :: SWord 1 = choose [28:28] s900
+  s1874 :: SBool = s4 /= s1873
+  s1875 :: SWord 1 = choose [28:28] s1734
+  s1876 :: SBool = s4 /= s1875
+  s1877 :: SBool = s1874 == s1876
+  s1878 :: SWord 1 = choose [29:29] s900
+  s1879 :: SBool = s4 /= s1878
+  s1880 :: SWord 1 = choose [29:29] s1734
+  s1881 :: SBool = s4 /= s1880
+  s1882 :: SBool = s1879 == s1881
+  s1883 :: SWord 1 = choose [30:30] s900
+  s1884 :: SBool = s4 /= s1883
+  s1885 :: SWord 1 = choose [30:30] s1734
+  s1886 :: SBool = s4 /= s1885
+  s1887 :: SBool = s1884 == s1886
+  s1888 :: SWord 1 = choose [31:31] s900
+  s1889 :: SBool = s4 /= s1888
+  s1890 :: SWord 1 = choose [31:31] s1734
+  s1891 :: SBool = s4 /= s1890
+  s1892 :: SBool = s1889 == s1891
+  s1893 :: SWord 1 = choose [32:32] s900
+  s1894 :: SBool = s4 /= s1893
+  s1895 :: SWord 1 = choose [32:32] s1734
+  s1896 :: SBool = s4 /= s1895
+  s1897 :: SBool = s1894 == s1896
+  s1898 :: SWord 1 = choose [33:33] s900
+  s1899 :: SBool = s4 /= s1898
+  s1900 :: SWord 1 = choose [33:33] s1734
+  s1901 :: SBool = s4 /= s1900
+  s1902 :: SBool = s1899 == s1901
+  s1903 :: SWord 1 = choose [34:34] s900
+  s1904 :: SBool = s4 /= s1903
+  s1905 :: SWord 1 = choose [34:34] s1734
+  s1906 :: SBool = s4 /= s1905
+  s1907 :: SBool = s1904 == s1906
+  s1908 :: SWord 1 = choose [35:35] s900
+  s1909 :: SBool = s4 /= s1908
+  s1910 :: SWord 1 = choose [35:35] s1734
+  s1911 :: SBool = s4 /= s1910
+  s1912 :: SBool = s1909 == s1911
+  s1913 :: SWord 1 = choose [36:36] s900
+  s1914 :: SBool = s4 /= s1913
+  s1915 :: SWord 1 = choose [36:36] s1734
+  s1916 :: SBool = s4 /= s1915
+  s1917 :: SBool = s1914 == s1916
+  s1918 :: SWord 1 = choose [37:37] s900
+  s1919 :: SBool = s4 /= s1918
+  s1920 :: SWord 1 = choose [37:37] s1734
+  s1921 :: SBool = s4 /= s1920
+  s1922 :: SBool = s1919 == s1921
+  s1923 :: SWord 1 = choose [38:38] s900
+  s1924 :: SBool = s4 /= s1923
+  s1925 :: SWord 1 = choose [38:38] s1734
+  s1926 :: SBool = s4 /= s1925
+  s1927 :: SBool = s1924 == s1926
+  s1928 :: SWord 1 = choose [39:39] s900
+  s1929 :: SBool = s4 /= s1928
+  s1930 :: SWord 1 = choose [39:39] s1734
+  s1931 :: SBool = s4 /= s1930
+  s1932 :: SBool = s1929 == s1931
+  s1933 :: SWord 1 = choose [40:40] s900
+  s1934 :: SBool = s4 /= s1933
+  s1935 :: SWord 1 = choose [40:40] s1734
+  s1936 :: SBool = s4 /= s1935
+  s1937 :: SBool = s1934 == s1936
+  s1938 :: SWord 1 = choose [41:41] s900
+  s1939 :: SBool = s4 /= s1938
+  s1940 :: SWord 1 = choose [41:41] s1734
+  s1941 :: SBool = s4 /= s1940
+  s1942 :: SBool = s1939 == s1941
+  s1943 :: SWord 1 = choose [42:42] s900
+  s1944 :: SBool = s4 /= s1943
+  s1945 :: SWord 1 = choose [42:42] s1734
+  s1946 :: SBool = s4 /= s1945
+  s1947 :: SBool = s1944 == s1946
+  s1948 :: SWord 1 = choose [43:43] s900
+  s1949 :: SBool = s4 /= s1948
+  s1950 :: SWord 1 = choose [43:43] s1734
+  s1951 :: SBool = s4 /= s1950
+  s1952 :: SBool = s1949 == s1951
+  s1953 :: SWord 1 = choose [44:44] s900
+  s1954 :: SBool = s4 /= s1953
+  s1955 :: SWord 1 = choose [44:44] s1734
+  s1956 :: SBool = s4 /= s1955
+  s1957 :: SBool = s1954 == s1956
+  s1958 :: SWord 1 = choose [45:45] s900
+  s1959 :: SBool = s4 /= s1958
+  s1960 :: SWord 1 = choose [45:45] s1734
+  s1961 :: SBool = s4 /= s1960
+  s1962 :: SBool = s1959 == s1961
+  s1963 :: SWord 1 = choose [46:46] s900
+  s1964 :: SBool = s4 /= s1963
+  s1965 :: SWord 1 = choose [46:46] s1734
+  s1966 :: SBool = s4 /= s1965
+  s1967 :: SBool = s1964 == s1966
+  s1968 :: SWord 1 = choose [47:47] s900
+  s1969 :: SBool = s4 /= s1968
+  s1970 :: SWord 1 = choose [47:47] s1734
+  s1971 :: SBool = s4 /= s1970
+  s1972 :: SBool = s1969 == s1971
+  s1973 :: SWord 1 = choose [48:48] s900
+  s1974 :: SBool = s4 /= s1973
+  s1975 :: SWord 1 = choose [48:48] s1734
+  s1976 :: SBool = s4 /= s1975
+  s1977 :: SBool = s1974 == s1976
+  s1978 :: SWord 1 = choose [49:49] s900
+  s1979 :: SBool = s4 /= s1978
+  s1980 :: SWord 1 = choose [49:49] s1734
+  s1981 :: SBool = s4 /= s1980
+  s1982 :: SBool = s1979 == s1981
+  s1983 :: SWord 1 = choose [50:50] s900
+  s1984 :: SBool = s4 /= s1983
+  s1985 :: SWord 1 = choose [50:50] s1734
+  s1986 :: SBool = s4 /= s1985
+  s1987 :: SBool = s1984 == s1986
+  s1988 :: SWord 1 = choose [51:51] s900
+  s1989 :: SBool = s4 /= s1988
+  s1990 :: SWord 1 = choose [51:51] s1734
+  s1991 :: SBool = s4 /= s1990
+  s1992 :: SBool = s1989 == s1991
+  s1993 :: SWord 1 = choose [52:52] s900
+  s1994 :: SBool = s4 /= s1993
+  s1995 :: SWord 1 = choose [52:52] s1734
+  s1996 :: SBool = s4 /= s1995
+  s1997 :: SBool = s1994 == s1996
+  s1998 :: SWord 1 = choose [53:53] s900
+  s1999 :: SBool = s4 /= s1998
+  s2000 :: SWord 1 = choose [53:53] s1734
+  s2001 :: SBool = s4 /= s2000
+  s2002 :: SBool = s1999 == s2001
+  s2003 :: SWord 1 = choose [54:54] s900
+  s2004 :: SBool = s4 /= s2003
+  s2005 :: SWord 1 = choose [54:54] s1734
+  s2006 :: SBool = s4 /= s2005
+  s2007 :: SBool = s2004 == s2006
+  s2008 :: SWord 1 = choose [55:55] s900
+  s2009 :: SBool = s4 /= s2008
+  s2010 :: SWord 1 = choose [55:55] s1734
+  s2011 :: SBool = s4 /= s2010
+  s2012 :: SBool = s2009 == s2011
+  s2013 :: SWord 1 = choose [56:56] s900
+  s2014 :: SBool = s4 /= s2013
+  s2015 :: SWord 1 = choose [56:56] s1734
+  s2016 :: SBool = s4 /= s2015
+  s2017 :: SBool = s2014 == s2016
+  s2018 :: SWord 1 = choose [57:57] s900
+  s2019 :: SBool = s4 /= s2018
+  s2020 :: SWord 1 = choose [57:57] s1734
+  s2021 :: SBool = s4 /= s2020
+  s2022 :: SBool = s2019 == s2021
+  s2023 :: SWord 1 = choose [58:58] s900
+  s2024 :: SBool = s4 /= s2023
+  s2025 :: SWord 1 = choose [58:58] s1734
+  s2026 :: SBool = s4 /= s2025
+  s2027 :: SBool = s2024 == s2026
+  s2028 :: SWord 1 = choose [59:59] s900
+  s2029 :: SBool = s4 /= s2028
+  s2030 :: SWord 1 = choose [59:59] s1734
+  s2031 :: SBool = s4 /= s2030
+  s2032 :: SBool = s2029 == s2031
+  s2033 :: SWord 1 = choose [60:60] s900
+  s2034 :: SBool = s4 /= s2033
+  s2035 :: SWord 1 = choose [60:60] s1734
+  s2036 :: SBool = s4 /= s2035
+  s2037 :: SBool = s2034 == s2036
+  s2038 :: SWord 1 = choose [61:61] s900
+  s2039 :: SBool = s4 /= s2038
+  s2040 :: SWord 1 = choose [61:61] s1734
+  s2041 :: SBool = s4 /= s2040
+  s2042 :: SBool = s2039 == s2041
+  s2043 :: SWord 1 = choose [62:62] s900
+  s2044 :: SBool = s4 /= s2043
+  s2045 :: SWord 1 = choose [62:62] s1734
+  s2046 :: SBool = s4 /= s2045
+  s2047 :: SBool = s2044 == s2046
+  s2048 :: SWord 1 = choose [63:63] s900
+  s2049 :: SBool = s4 /= s2048
+  s2050 :: SWord 1 = choose [63:63] s1734
+  s2051 :: SBool = s4 /= s2050
+  s2052 :: SBool = s2049 == s2051
+  s2055 :: SWord8 = if s2052 then s2053 else s2054
+  s2056 :: SWord8 = s2054 + s2055
+  s2057 :: SWord8 = if s2047 then s2055 else s2056
+  s2058 :: SWord8 = s2054 + s2057
+  s2059 :: SWord8 = if s2042 then s2057 else s2058
+  s2060 :: SWord8 = s2054 + s2059
+  s2061 :: SWord8 = if s2037 then s2059 else s2060
+  s2062 :: SWord8 = s2054 + s2061
+  s2063 :: SWord8 = if s2032 then s2061 else s2062
+  s2064 :: SWord8 = s2054 + s2063
+  s2065 :: SWord8 = if s2027 then s2063 else s2064
+  s2066 :: SWord8 = s2054 + s2065
+  s2067 :: SWord8 = if s2022 then s2065 else s2066
+  s2068 :: SWord8 = s2054 + s2067
+  s2069 :: SWord8 = if s2017 then s2067 else s2068
+  s2070 :: SWord8 = s2054 + s2069
+  s2071 :: SWord8 = if s2012 then s2069 else s2070
+  s2072 :: SWord8 = s2054 + s2071
+  s2073 :: SWord8 = if s2007 then s2071 else s2072
+  s2074 :: SWord8 = s2054 + s2073
+  s2075 :: SWord8 = if s2002 then s2073 else s2074
+  s2076 :: SWord8 = s2054 + s2075
+  s2077 :: SWord8 = if s1997 then s2075 else s2076
+  s2078 :: SWord8 = s2054 + s2077
+  s2079 :: SWord8 = if s1992 then s2077 else s2078
+  s2080 :: SWord8 = s2054 + s2079
+  s2081 :: SWord8 = if s1987 then s2079 else s2080
+  s2082 :: SWord8 = s2054 + s2081
+  s2083 :: SWord8 = if s1982 then s2081 else s2082
+  s2084 :: SWord8 = s2054 + s2083
+  s2085 :: SWord8 = if s1977 then s2083 else s2084
+  s2086 :: SWord8 = s2054 + s2085
+  s2087 :: SWord8 = if s1972 then s2085 else s2086
+  s2088 :: SWord8 = s2054 + s2087
+  s2089 :: SWord8 = if s1967 then s2087 else s2088
+  s2090 :: SWord8 = s2054 + s2089
+  s2091 :: SWord8 = if s1962 then s2089 else s2090
+  s2092 :: SWord8 = s2054 + s2091
+  s2093 :: SWord8 = if s1957 then s2091 else s2092
+  s2094 :: SWord8 = s2054 + s2093
+  s2095 :: SWord8 = if s1952 then s2093 else s2094
+  s2096 :: SWord8 = s2054 + s2095
+  s2097 :: SWord8 = if s1947 then s2095 else s2096
+  s2098 :: SWord8 = s2054 + s2097
+  s2099 :: SWord8 = if s1942 then s2097 else s2098
+  s2100 :: SWord8 = s2054 + s2099
+  s2101 :: SWord8 = if s1937 then s2099 else s2100
+  s2102 :: SWord8 = s2054 + s2101
+  s2103 :: SWord8 = if s1932 then s2101 else s2102
+  s2104 :: SWord8 = s2054 + s2103
+  s2105 :: SWord8 = if s1927 then s2103 else s2104
+  s2106 :: SWord8 = s2054 + s2105
+  s2107 :: SWord8 = if s1922 then s2105 else s2106
+  s2108 :: SWord8 = s2054 + s2107
+  s2109 :: SWord8 = if s1917 then s2107 else s2108
+  s2110 :: SWord8 = s2054 + s2109
+  s2111 :: SWord8 = if s1912 then s2109 else s2110
+  s2112 :: SWord8 = s2054 + s2111
+  s2113 :: SWord8 = if s1907 then s2111 else s2112
+  s2114 :: SWord8 = s2054 + s2113
+  s2115 :: SWord8 = if s1902 then s2113 else s2114
+  s2116 :: SWord8 = s2054 + s2115
+  s2117 :: SWord8 = if s1897 then s2115 else s2116
+  s2118 :: SWord8 = s2054 + s2117
+  s2119 :: SWord8 = if s1892 then s2117 else s2118
+  s2120 :: SWord8 = s2054 + s2119
+  s2121 :: SWord8 = if s1887 then s2119 else s2120
+  s2122 :: SWord8 = s2054 + s2121
+  s2123 :: SWord8 = if s1882 then s2121 else s2122
+  s2124 :: SWord8 = s2054 + s2123
+  s2125 :: SWord8 = if s1877 then s2123 else s2124
+  s2126 :: SWord8 = s2054 + s2125
+  s2127 :: SWord8 = if s1872 then s2125 else s2126
+  s2128 :: SWord8 = s2054 + s2127
+  s2129 :: SWord8 = if s1867 then s2127 else s2128
+  s2130 :: SWord8 = s2054 + s2129
+  s2131 :: SWord8 = if s1862 then s2129 else s2130
+  s2132 :: SWord8 = s2054 + s2131
+  s2133 :: SWord8 = if s1857 then s2131 else s2132
+  s2134 :: SWord8 = s2054 + s2133
+  s2135 :: SWord8 = if s1852 then s2133 else s2134
+  s2136 :: SWord8 = s2054 + s2135
+  s2137 :: SWord8 = if s1847 then s2135 else s2136
+  s2138 :: SWord8 = s2054 + s2137
+  s2139 :: SWord8 = if s1842 then s2137 else s2138
+  s2140 :: SWord8 = s2054 + s2139
+  s2141 :: SWord8 = if s1837 then s2139 else s2140
+  s2142 :: SWord8 = s2054 + s2141
+  s2143 :: SWord8 = if s1832 then s2141 else s2142
+  s2144 :: SWord8 = s2054 + s2143
+  s2145 :: SWord8 = if s1827 then s2143 else s2144
+  s2146 :: SWord8 = s2054 + s2145
+  s2147 :: SWord8 = if s1822 then s2145 else s2146
+  s2148 :: SWord8 = s2054 + s2147
+  s2149 :: SWord8 = if s1817 then s2147 else s2148
+  s2150 :: SWord8 = s2054 + s2149
+  s2151 :: SWord8 = if s1812 then s2149 else s2150
+  s2152 :: SWord8 = s2054 + s2151
+  s2153 :: SWord8 = if s1807 then s2151 else s2152
+  s2154 :: SWord8 = s2054 + s2153
+  s2155 :: SWord8 = if s1802 then s2153 else s2154
+  s2156 :: SWord8 = s2054 + s2155
+  s2157 :: SWord8 = if s1797 then s2155 else s2156
+  s2158 :: SWord8 = s2054 + s2157
+  s2159 :: SWord8 = if s1792 then s2157 else s2158
+  s2160 :: SWord8 = s2054 + s2159
+  s2161 :: SWord8 = if s1787 then s2159 else s2160
+  s2162 :: SWord8 = s2054 + s2161
+  s2163 :: SWord8 = if s1782 then s2161 else s2162
+  s2164 :: SWord8 = s2054 + s2163
+  s2165 :: SWord8 = if s1777 then s2163 else s2164
+  s2166 :: SWord8 = s2054 + s2165
+  s2167 :: SWord8 = if s1772 then s2165 else s2166
+  s2168 :: SWord8 = s2054 + s2167
+  s2169 :: SWord8 = if s1767 then s2167 else s2168
+  s2170 :: SWord8 = s2054 + s2169
+  s2171 :: SWord8 = if s1762 then s2169 else s2170
+  s2172 :: SWord8 = s2054 + s2171
+  s2173 :: SWord8 = if s1757 then s2171 else s2172
+  s2174 :: SWord8 = s2054 + s2173
+  s2175 :: SWord8 = if s1752 then s2173 else s2174
+  s2176 :: SWord8 = s2054 + s2175
+  s2177 :: SWord8 = if s1747 then s2175 else s2176
+  s2178 :: SWord8 = s2054 + s2177
+  s2179 :: SWord8 = if s1742 then s2177 else s2178
+  s2180 :: SWord8 = s2054 + s2179
+  s2181 :: SWord8 = if s1737 then s2179 else s2180
+  s2183 :: SBool = s2181 > s2182
+  s2184 :: SBool = s2 => s2183
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s2184
diff --git a/SBVTestSuite/GoldFiles/cgUninterpret.gold b/SBVTestSuite/GoldFiles/cgUninterpret.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/cgUninterpret.gold
@@ -0,0 +1,114 @@
+== BEGIN: "Makefile" ================
+# Makefile for tstShiftLeft. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: tstShiftLeft_driver
+
+tstShiftLeft.o: tstShiftLeft.c tstShiftLeft.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+tstShiftLeft_driver.o: tstShiftLeft_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+tstShiftLeft_driver: tstShiftLeft.o tstShiftLeft_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f tstShiftLeft_driver
+== END: "Makefile" ==================
+== BEGIN: "tstShiftLeft.h" ================
+/* Header file for tstShiftLeft. Automatically generated by SBV. Do not edit! */
+
+#ifndef __tstShiftLeft__HEADER_INCLUDED__
+#define __tstShiftLeft__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord32 tstShiftLeft(const SWord32 *vs);
+
+#endif /* __tstShiftLeft__HEADER_INCLUDED__ */
+== END: "tstShiftLeft.h" ==================
+== BEGIN: "tstShiftLeft_driver.c" ================
+/* Example driver program for tstShiftLeft. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "tstShiftLeft.h"
+
+int main(void)
+{
+  const SWord32 vs[3] = {
+      0x00000001UL, 0x00000002UL, 0x00000003UL
+  };
+
+  printf("Contents of input array vs:\n");
+  int vs_ctr;
+  for(vs_ctr = 0; vs_ctr < 3 ; ++vs_ctr)
+    printf("  vs[%1d] = 0x%08"PRIx32"UL\n", vs_ctr ,vs[vs_ctr]);
+
+
+  const SWord32 __result = tstShiftLeft(vs);
+
+  printf("tstShiftLeft(vs) = 0x%08"PRIx32"UL\n", __result);
+
+  return 0;
+}
+== END: "tstShiftLeft_driver.c" ==================
+== BEGIN: "tstShiftLeft.c" ================
+/* File: "tstShiftLeft.c". Automatically generated by SBV. Do not edit! */
+
+#include "tstShiftLeft.h"
+
+/* User specified custom code for "SBV_SHIFTLEFT" */
+#define SBV_SHIFTLEFT(x, y) ((x) << (y))
+
+SWord32 tstShiftLeft(const SWord32 *vs)
+{
+  const SWord32 s0 = vs[0];
+  const SWord32 s1 = vs[1];
+  const SWord32 s2 = vs[2];
+  const SWord32 s3 = /* Uninterpreted function */ SBV_SHIFTLEFT(s0,
+                                                                s2);
+  const SWord32 s4 = /* Uninterpreted function */ SBV_SHIFTLEFT(s1,
+                                                                s2);
+  const SWord32 s5 = s3 + s4;
+
+  return s5;
+}
+== END: "tstShiftLeft.c" ==================
diff --git a/SBVTestSuite/GoldFiles/charConstr00.gold b/SBVTestSuite/GoldFiles/charConstr00.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr00.gold
@@ -0,0 +1,32 @@
+** 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 chars, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () String (_ char #x41))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len s0)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 "B"))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",'B' :: Char)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr01.gold b/SBVTestSuite/GoldFiles/charConstr01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr01.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s0 () Int 4)
+[GOOD] (define-fun s2 () String (_ char #x41))
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun cf (Int) String)
+[GOOD] (assert (forall ((a1 Int))
+                       (let ((result (cf a1)))
+                            (= 1 (str.len result))
+                       )))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () String (cf s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (cf))
+[RECV] ((cf ((as const (Array Int String)) "B")))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("cf",(True,SInteger -> SChar,Right ([],'B' :: Char)))]}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr02.gold b/SBVTestSuite/GoldFiles/charConstr02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr02.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s0 () Int 4)
+[GOOD] (define-fun s2 () (SBVTuple3 String String String) (mkSBVTuple3 (_ char #x41) (_ char #x42) (_ char #x43)))
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun cf3 (Int) (SBVTuple3 String String String))
+[GOOD] (assert (forall ((a1 Int))
+                       (let ((result (cf3 a1)))
+                            (and (= 1 (str.len (proj_1_SBVTuple3 result)))
+                                 (= 1 (str.len (proj_2_SBVTuple3 result)))
+                                 (= 1 (str.len (proj_3_SBVTuple3 result)))
+                            )
+                       )))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (SBVTuple3 String String String) (cf3 s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (cf3))
+[RECV] ((cf3 ((as const (Array Int (SBVTuple3 String String String)))
+         (mkSBVTuple3 "A" "A" "A"))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("cf3",(True,SInteger -> (SChar, SChar, SChar),Right ([],('A','A','A') :: (Char, Char, Char))))]}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr03.gold b/SBVTestSuite/GoldFiles/charConstr03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr03.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Either String String) ((as Left (Either String String)) (_ char #x41)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either String String)) ; tracks user variable "x"
+[GOOD] (assert (and (= 1 (str.len (getLeft_1 s0)))
+                    (= 1 (str.len (getRight_1 s0)))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left "B")))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char Char)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr04.gold b/SBVTestSuite/GoldFiles/charConstr04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr04.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Either Int String) ((as Right (Either Int String)) (_ char #x41)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int String)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getRight_1 s0))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 2)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 2 :: Either Integer Char)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr05.gold b/SBVTestSuite/GoldFiles/charConstr05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr05.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Either String Int) ((as Left (Either String Int)) (_ char #x41)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either String Int)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getLeft_1 s0))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left "B")))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char Integer)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr06.gold b/SBVTestSuite/GoldFiles/charConstr06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr06.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Either String (Either String Int)) ((as Left (Either String (Either String Int))) (_ char #x41)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either String (Either String Int))) ; tracks user variable "x"
+[GOOD] (assert (and (= 1 (str.len (getLeft_1 s0)))
+                    (= 1 (str.len (getLeft_1 (getRight_1 s0))))
+               ))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as Left (Either String (Either String Int))) "B")))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 'B' :: Either Char (Either Char Integer))], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr07.gold b/SBVTestSuite/GoldFiles/charConstr07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr07.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Maybe String) ((as Just (Maybe String)) (_ char #x41)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Maybe String)) ; tracks user variable "x"
+[GOOD] (assert (= 1 (str.len (getJust_1 s0))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Just Bool) s0))
+[GOOD] (define-fun s3 () Bool (distinct s0 s2))
+[GOOD] (define-fun s4 () Bool (and s1 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Just "B")))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Just 'B' :: Maybe Char)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr08.gold b/SBVTestSuite/GoldFiles/charConstr08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr08.gold
@@ -0,0 +1,39 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () String (_ char #x41))
+[GOOD] (define-fun s3 () String (_ char #x42))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array String Bool)) ; tracks user variable "x"
+[GOOD] (assert (forall ((set0 String)) (=> (select s0 set0) (= 1 (str.len set0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (select s0 s1))
+[GOOD] (define-fun s4 () Bool (select s0 s3))
+[GOOD] (define-fun s5 () Bool (not s4))
+[GOOD] (define-fun s6 () Bool (and s2 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (lambda ((x!1 String)) (= x!1 "A"))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",{'A'} :: {Char})], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr09.gold b/SBVTestSuite/GoldFiles/charConstr09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr09.gold
@@ -0,0 +1,39 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 (SBVTuple2 String String) (Seq Int)))) ; tracks user variable "x"
+[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (and (= 1 (str.len (proj_1_SBVTuple2 (proj_1_SBVTuple2 (seq.nth s0 seq0))))) (= 1 (str.len (proj_2_SBVTuple2 (proj_1_SBVTuple2 (seq.nth s0 seq0)))))))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.unit (mkSBVTuple2 (mkSBVTuple2 "A" "A") (seq.unit 2)))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",[(('A','A'),[2])] :: [((Char, Char), [Integer])])], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr10.gold b/SBVTestSuite/GoldFiles/charConstr10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr10.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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] (define-fun s4 () Int 0)
+[GOOD] (define-fun s8 () String (_ char #x42))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 (SBVTuple2 String String) (Seq Int)))) ; tracks user variable "x"
+[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (and (= 1 (str.len (proj_1_SBVTuple2 (proj_1_SBVTuple2 (seq.nth s0 seq0))))) (= 1 (str.len (proj_2_SBVTuple2 (proj_1_SBVTuple2 (seq.nth s0 seq0)))))))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 (SBVTuple2 String String) (Seq Int)) (seq.nth s0 s4))
+[GOOD] (define-fun s6 () (SBVTuple2 String String) (proj_1_SBVTuple2 s5))
+[GOOD] (define-fun s7 () String (proj_1_SBVTuple2 s6))
+[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.unit (mkSBVTuple2 (mkSBVTuple2 "B" "B") (seq.unit 2)))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",[(('B','B'),[2])] :: [((Char, Char), [Integer])])], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/charConstr11.gold b/SBVTestSuite/GoldFiles/charConstr11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/charConstr11.gold
@@ -0,0 +1,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "c"
+[GOOD] (assert (= 1 (str.len s1)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun cf4 (Int String) (Seq (SBVTuple2 (SBVTuple2 String String) (Seq Int))))
+[GOOD] (assert (forall ((a1 Int) (a2 String))
+                       (let ((result (cf4 a1 a2)))
+                            (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len result))) (and (= 1 (str.len (proj_1_SBVTuple2 (proj_1_SBVTuple2 (seq.nth result seq0))))) (= 1 (str.len (proj_2_SBVTuple2 (proj_1_SBVTuple2 (seq.nth result seq0))))))))
+                       )))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Seq (SBVTuple2 (SBVTuple2 String String) (Seq Int))) (cf4 s0 s1))
+[GOOD] (define-fun s3 () Int (seq.len s2))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s1))
+[RECV] ((s1 "A"))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (cf4))
+[RECV] ((cf4 ((as const
+            (Array Int String (Seq (SBVTuple2 (SBVTuple2 String String) (Seq Int)))))
+         (seq.unit (mkSBVTuple2 (mkSBVTuple2 "A" "A") (seq.unit 2))))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",3 :: Integer),("c",'A' :: Char)], modelUIFuns = [("cf4",(True,SInteger -> SChar -> [((SChar, SChar), [SInteger])],Right ([],[(('A','A'),[2])] :: [((Char, Char), [Integer])])))]}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/check1.gold b/SBVTestSuite/GoldFiles/check1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/check1.gold
@@ -0,0 +1,39 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] (declare-fun s2 () (_ BitVec 8))
+[GOOD] (declare-fun s3 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s3))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s6))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #xff))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x0000))
+[SEND] (get-value (s2))
+[RECV] ((s2 #x00))
+[SEND] (get-value (s3))
+[RECV] ((s3 #x0000))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/check2.gold b/SBVTestSuite/GoldFiles/check2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/check2.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 QF_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x0000))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/codeGen1.gold b/SBVTestSuite/GoldFiles/codeGen1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/codeGen1.gold
@@ -0,0 +1,230 @@
+== BEGIN: "Makefile" ================
+# Makefile for foo. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: foo_driver
+
+foo.o: foo.c foo.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+foo_driver.o: foo_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+foo_driver: foo.o foo_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f foo_driver
+== END: "Makefile" ==================
+== BEGIN: "foo.h" ================
+/* Header file for foo. Automatically generated by SBV. Do not edit! */
+
+#ifndef __foo__HEADER_INCLUDED__
+#define __foo__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SInt16 foo(const SInt16 x, const SInt64 *xArr, SWord16 *z,
+           SInt16 *zArr, SInt64 *yArr);
+
+#endif /* __foo__HEADER_INCLUDED__ */
+== END: "foo.h" ==================
+== BEGIN: "foo_driver.c" ================
+/* Example driver program for foo. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "foo.h"
+
+int main(void)
+{
+  const SInt64 xArr[45] = {
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
+      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL
+  };
+
+  printf("Contents of input array xArr:\n");
+  int xArr_ctr;
+  for(xArr_ctr = 0; xArr_ctr < 45 ; ++xArr_ctr)
+    printf("  xArr[%2d] = %"PRId64"LL\n", xArr_ctr ,xArr[xArr_ctr]);
+
+  SWord16 z;
+  SInt16 zArr[7];
+  SInt64 yArr[45];
+
+  const SInt16 __result = foo(0x0000, xArr, &z, zArr, yArr);
+
+  printf("foo(0x0000, xArr, &z, zArr, yArr) = %"PRId16"\n", __result);
+  printf("  z = 0x%04"PRIx16"U\n", z);
+  int zArr_ctr;
+  for(zArr_ctr = 0; zArr_ctr < 7 ; ++zArr_ctr)
+    printf("  zArr[%1d] = %"PRId16"\n", zArr_ctr ,zArr[zArr_ctr]);
+  int yArr_ctr;
+  for(yArr_ctr = 0; yArr_ctr < 45 ; ++yArr_ctr)
+    printf("  yArr[%2d] = %"PRId64"LL\n", yArr_ctr ,yArr[yArr_ctr]);
+
+  return 0;
+}
+== END: "foo_driver.c" ==================
+== BEGIN: "foo.c" ================
+/* File: "foo.c". Automatically generated by SBV. Do not edit! */
+
+#include "foo.h"
+
+SInt16 foo(const SInt16 x, const SInt64 *xArr, SWord16 *z,
+           SInt16 *zArr, SInt64 *yArr)
+{
+  const SInt16 s0 = x;
+  const SInt64 s1 = xArr[0];
+  const SInt64 s2 = xArr[1];
+  const SInt64 s3 = xArr[2];
+  const SInt64 s4 = xArr[3];
+  const SInt64 s5 = xArr[4];
+  const SInt64 s6 = xArr[5];
+  const SInt64 s7 = xArr[6];
+  const SInt64 s8 = xArr[7];
+  const SInt64 s9 = xArr[8];
+  const SInt64 s10 = xArr[9];
+  const SInt64 s11 = xArr[10];
+  const SInt64 s12 = xArr[11];
+  const SInt64 s13 = xArr[12];
+  const SInt64 s14 = xArr[13];
+  const SInt64 s15 = xArr[14];
+  const SInt64 s16 = xArr[15];
+  const SInt64 s17 = xArr[16];
+  const SInt64 s18 = xArr[17];
+  const SInt64 s19 = xArr[18];
+  const SInt64 s20 = xArr[19];
+  const SInt64 s21 = xArr[20];
+  const SInt64 s22 = xArr[21];
+  const SInt64 s23 = xArr[22];
+  const SInt64 s24 = xArr[23];
+  const SInt64 s25 = xArr[24];
+  const SInt64 s26 = xArr[25];
+  const SInt64 s27 = xArr[26];
+  const SInt64 s28 = xArr[27];
+  const SInt64 s29 = xArr[28];
+  const SInt64 s30 = xArr[29];
+  const SInt64 s31 = xArr[30];
+  const SInt64 s32 = xArr[31];
+  const SInt64 s33 = xArr[32];
+  const SInt64 s34 = xArr[33];
+  const SInt64 s35 = xArr[34];
+  const SInt64 s36 = xArr[35];
+  const SInt64 s37 = xArr[36];
+  const SInt64 s38 = xArr[37];
+  const SInt64 s39 = xArr[38];
+  const SInt64 s40 = xArr[39];
+  const SInt64 s41 = xArr[40];
+  const SInt64 s42 = xArr[41];
+  const SInt64 s43 = xArr[42];
+  const SInt64 s44 = xArr[43];
+  const SInt64 s45 = xArr[44];
+  const SInt16 s48 = s0 + 0x0001;
+  const SInt16 s50 = s0 * 0x0002;
+
+  *z = 0x0005U;
+  zArr[0] = s48;
+  zArr[1] = s48;
+  zArr[2] = s48;
+  zArr[3] = s48;
+  zArr[4] = s48;
+  zArr[5] = s48;
+  zArr[6] = s48;
+  yArr[0] = s1;
+  yArr[1] = s2;
+  yArr[2] = s3;
+  yArr[3] = s4;
+  yArr[4] = s5;
+  yArr[5] = s6;
+  yArr[6] = s7;
+  yArr[7] = s8;
+  yArr[8] = s9;
+  yArr[9] = s10;
+  yArr[10] = s11;
+  yArr[11] = s12;
+  yArr[12] = s13;
+  yArr[13] = s14;
+  yArr[14] = s15;
+  yArr[15] = s16;
+  yArr[16] = s17;
+  yArr[17] = s18;
+  yArr[18] = s19;
+  yArr[19] = s20;
+  yArr[20] = s21;
+  yArr[21] = s22;
+  yArr[22] = s23;
+  yArr[23] = s24;
+  yArr[24] = s25;
+  yArr[25] = s26;
+  yArr[26] = s27;
+  yArr[27] = s28;
+  yArr[28] = s29;
+  yArr[29] = s30;
+  yArr[30] = s31;
+  yArr[31] = s32;
+  yArr[32] = s33;
+  yArr[33] = s34;
+  yArr[34] = s35;
+  yArr[35] = s36;
+  yArr[36] = s37;
+  yArr[37] = s38;
+  yArr[38] = s39;
+  yArr[39] = s40;
+  yArr[40] = s41;
+  yArr[41] = s42;
+  yArr[42] = s43;
+  yArr[43] = s44;
+  yArr[44] = s45;
+  return s50;
+}
+== END: "foo.c" ==================
diff --git a/SBVTestSuite/GoldFiles/coins.gold b/SBVTestSuite/GoldFiles/coins.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/coins.gold
@@ -0,0 +1,913 @@
+INPUTS
+  s0 :: SWord16, aliasing "c1"
+  s18 :: SWord16, aliasing "c2"
+  s30 :: SWord16, aliasing "c3"
+  s42 :: SWord16, aliasing "c4"
+  s54 :: SWord16, aliasing "c5"
+  s66 :: SWord16, aliasing "c6"
+CONSTANTS
+  s1 = 1 :: Word16
+  s3 = 5 :: Word16
+  s5 = 10 :: Word16
+  s7 = 25 :: Word16
+  s9 = 50 :: Word16
+  s11 = 100 :: Word16
+  s84 = 0 :: Word16
+  s88 = 95 :: Word16
+  s551 = 115 :: Word16
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s2 :: SBool = s0 == s1
+  s4 :: SBool = s0 == s3
+  s6 :: SBool = s0 == s5
+  s8 :: SBool = s0 == s7
+  s10 :: SBool = s0 == s9
+  s12 :: SBool = s0 == s11
+  s13 :: SBool = s10 | s12
+  s14 :: SBool = s8 | s13
+  s15 :: SBool = s6 | s14
+  s16 :: SBool = s4 | s15
+  s17 :: SBool = s2 | s16
+  s19 :: SBool = s1 == s18
+  s20 :: SBool = s3 == s18
+  s21 :: SBool = s5 == s18
+  s22 :: SBool = s7 == s18
+  s23 :: SBool = s9 == s18
+  s24 :: SBool = s11 == s18
+  s25 :: SBool = s23 | s24
+  s26 :: SBool = s22 | s25
+  s27 :: SBool = s21 | s26
+  s28 :: SBool = s20 | s27
+  s29 :: SBool = s19 | s28
+  s31 :: SBool = s1 == s30
+  s32 :: SBool = s3 == s30
+  s33 :: SBool = s5 == s30
+  s34 :: SBool = s7 == s30
+  s35 :: SBool = s9 == s30
+  s36 :: SBool = s11 == s30
+  s37 :: SBool = s35 | s36
+  s38 :: SBool = s34 | s37
+  s39 :: SBool = s33 | s38
+  s40 :: SBool = s32 | s39
+  s41 :: SBool = s31 | s40
+  s43 :: SBool = s1 == s42
+  s44 :: SBool = s3 == s42
+  s45 :: SBool = s5 == s42
+  s46 :: SBool = s7 == s42
+  s47 :: SBool = s9 == s42
+  s48 :: SBool = s11 == s42
+  s49 :: SBool = s47 | s48
+  s50 :: SBool = s46 | s49
+  s51 :: SBool = s45 | s50
+  s52 :: SBool = s44 | s51
+  s53 :: SBool = s43 | s52
+  s55 :: SBool = s1 == s54
+  s56 :: SBool = s3 == s54
+  s57 :: SBool = s5 == s54
+  s58 :: SBool = s7 == s54
+  s59 :: SBool = s9 == s54
+  s60 :: SBool = s11 == s54
+  s61 :: SBool = s59 | s60
+  s62 :: SBool = s58 | s61
+  s63 :: SBool = s57 | s62
+  s64 :: SBool = s56 | s63
+  s65 :: SBool = s55 | s64
+  s67 :: SBool = s1 == s66
+  s68 :: SBool = s3 == s66
+  s69 :: SBool = s5 == s66
+  s70 :: SBool = s7 == s66
+  s71 :: SBool = s9 == s66
+  s72 :: SBool = s11 == s66
+  s73 :: SBool = s71 | s72
+  s74 :: SBool = s70 | s73
+  s75 :: SBool = s69 | s74
+  s76 :: SBool = s68 | s75
+  s77 :: SBool = s67 | s76
+  s78 :: SWord16 = s0 + s18
+  s79 :: SBool = s11 /= s78
+  s80 :: SBool = s9 /= s78
+  s81 :: SBool = s7 /= s78
+  s82 :: SBool = s5 /= s78
+  s83 :: SBool = s3 /= s78
+  s85 :: SWord16 = if s10 then s84 else s0
+  s86 :: SWord16 = if s23 then s84 else s18
+  s87 :: SWord16 = s85 + s86
+  s89 :: SBool = s87 /= s88
+  s90 :: SWord16 = s0 + s30
+  s91 :: SBool = s11 /= s90
+  s92 :: SBool = s9 /= s90
+  s93 :: SBool = s7 /= s90
+  s94 :: SBool = s5 /= s90
+  s95 :: SBool = s3 /= s90
+  s96 :: SWord16 = if s35 then s84 else s30
+  s97 :: SWord16 = s85 + s96
+  s98 :: SBool = s88 /= s97
+  s99 :: SWord16 = s0 + s42
+  s100 :: SBool = s11 /= s99
+  s101 :: SBool = s9 /= s99
+  s102 :: SBool = s7 /= s99
+  s103 :: SBool = s5 /= s99
+  s104 :: SBool = s3 /= s99
+  s105 :: SWord16 = if s47 then s84 else s42
+  s106 :: SWord16 = s85 + s105
+  s107 :: SBool = s88 /= s106
+  s108 :: SWord16 = s0 + s54
+  s109 :: SBool = s11 /= s108
+  s110 :: SBool = s9 /= s108
+  s111 :: SBool = s7 /= s108
+  s112 :: SBool = s5 /= s108
+  s113 :: SBool = s3 /= s108
+  s114 :: SWord16 = if s59 then s84 else s54
+  s115 :: SWord16 = s85 + s114
+  s116 :: SBool = s88 /= s115
+  s117 :: SWord16 = s0 + s66
+  s118 :: SBool = s11 /= s117
+  s119 :: SBool = s9 /= s117
+  s120 :: SBool = s7 /= s117
+  s121 :: SBool = s5 /= s117
+  s122 :: SBool = s3 /= s117
+  s123 :: SWord16 = if s71 then s84 else s66
+  s124 :: SWord16 = s85 + s123
+  s125 :: SBool = s88 /= s124
+  s126 :: SWord16 = s18 + s30
+  s127 :: SBool = s11 /= s126
+  s128 :: SBool = s9 /= s126
+  s129 :: SBool = s7 /= s126
+  s130 :: SBool = s5 /= s126
+  s131 :: SBool = s3 /= s126
+  s132 :: SWord16 = s86 + s96
+  s133 :: SBool = s88 /= s132
+  s134 :: SWord16 = s18 + s42
+  s135 :: SBool = s11 /= s134
+  s136 :: SBool = s9 /= s134
+  s137 :: SBool = s7 /= s134
+  s138 :: SBool = s5 /= s134
+  s139 :: SBool = s3 /= s134
+  s140 :: SWord16 = s86 + s105
+  s141 :: SBool = s88 /= s140
+  s142 :: SWord16 = s18 + s54
+  s143 :: SBool = s11 /= s142
+  s144 :: SBool = s9 /= s142
+  s145 :: SBool = s7 /= s142
+  s146 :: SBool = s5 /= s142
+  s147 :: SBool = s3 /= s142
+  s148 :: SWord16 = s86 + s114
+  s149 :: SBool = s88 /= s148
+  s150 :: SWord16 = s18 + s66
+  s151 :: SBool = s11 /= s150
+  s152 :: SBool = s9 /= s150
+  s153 :: SBool = s7 /= s150
+  s154 :: SBool = s5 /= s150
+  s155 :: SBool = s3 /= s150
+  s156 :: SWord16 = s86 + s123
+  s157 :: SBool = s88 /= s156
+  s158 :: SWord16 = s30 + s42
+  s159 :: SBool = s11 /= s158
+  s160 :: SBool = s9 /= s158
+  s161 :: SBool = s7 /= s158
+  s162 :: SBool = s5 /= s158
+  s163 :: SBool = s3 /= s158
+  s164 :: SWord16 = s96 + s105
+  s165 :: SBool = s88 /= s164
+  s166 :: SWord16 = s30 + s54
+  s167 :: SBool = s11 /= s166
+  s168 :: SBool = s9 /= s166
+  s169 :: SBool = s7 /= s166
+  s170 :: SBool = s5 /= s166
+  s171 :: SBool = s3 /= s166
+  s172 :: SWord16 = s96 + s114
+  s173 :: SBool = s88 /= s172
+  s174 :: SWord16 = s30 + s66
+  s175 :: SBool = s11 /= s174
+  s176 :: SBool = s9 /= s174
+  s177 :: SBool = s7 /= s174
+  s178 :: SBool = s5 /= s174
+  s179 :: SBool = s3 /= s174
+  s180 :: SWord16 = s96 + s123
+  s181 :: SBool = s88 /= s180
+  s182 :: SWord16 = s42 + s54
+  s183 :: SBool = s11 /= s182
+  s184 :: SBool = s9 /= s182
+  s185 :: SBool = s7 /= s182
+  s186 :: SBool = s5 /= s182
+  s187 :: SBool = s3 /= s182
+  s188 :: SWord16 = s105 + s114
+  s189 :: SBool = s88 /= s188
+  s190 :: SWord16 = s42 + s66
+  s191 :: SBool = s11 /= s190
+  s192 :: SBool = s9 /= s190
+  s193 :: SBool = s7 /= s190
+  s194 :: SBool = s5 /= s190
+  s195 :: SBool = s3 /= s190
+  s196 :: SWord16 = s105 + s123
+  s197 :: SBool = s88 /= s196
+  s198 :: SWord16 = s54 + s66
+  s199 :: SBool = s11 /= s198
+  s200 :: SBool = s9 /= s198
+  s201 :: SBool = s7 /= s198
+  s202 :: SBool = s5 /= s198
+  s203 :: SBool = s3 /= s198
+  s204 :: SWord16 = s114 + s123
+  s205 :: SBool = s88 /= s204
+  s206 :: SWord16 = s30 + s78
+  s207 :: SBool = s11 /= s206
+  s208 :: SBool = s9 /= s206
+  s209 :: SBool = s7 /= s206
+  s210 :: SBool = s5 /= s206
+  s211 :: SBool = s3 /= s206
+  s212 :: SWord16 = s87 + s96
+  s213 :: SBool = s88 /= s212
+  s214 :: SWord16 = s42 + s78
+  s215 :: SBool = s11 /= s214
+  s216 :: SBool = s9 /= s214
+  s217 :: SBool = s7 /= s214
+  s218 :: SBool = s5 /= s214
+  s219 :: SBool = s3 /= s214
+  s220 :: SWord16 = s87 + s105
+  s221 :: SBool = s88 /= s220
+  s222 :: SWord16 = s54 + s78
+  s223 :: SBool = s11 /= s222
+  s224 :: SBool = s9 /= s222
+  s225 :: SBool = s7 /= s222
+  s226 :: SBool = s5 /= s222
+  s227 :: SBool = s3 /= s222
+  s228 :: SWord16 = s87 + s114
+  s229 :: SBool = s88 /= s228
+  s230 :: SWord16 = s66 + s78
+  s231 :: SBool = s11 /= s230
+  s232 :: SBool = s9 /= s230
+  s233 :: SBool = s7 /= s230
+  s234 :: SBool = s5 /= s230
+  s235 :: SBool = s3 /= s230
+  s236 :: SWord16 = s87 + s123
+  s237 :: SBool = s88 /= s236
+  s238 :: SWord16 = s42 + s90
+  s239 :: SBool = s11 /= s238
+  s240 :: SBool = s9 /= s238
+  s241 :: SBool = s7 /= s238
+  s242 :: SBool = s5 /= s238
+  s243 :: SBool = s3 /= s238
+  s244 :: SWord16 = s97 + s105
+  s245 :: SBool = s88 /= s244
+  s246 :: SWord16 = s54 + s90
+  s247 :: SBool = s11 /= s246
+  s248 :: SBool = s9 /= s246
+  s249 :: SBool = s7 /= s246
+  s250 :: SBool = s5 /= s246
+  s251 :: SBool = s3 /= s246
+  s252 :: SWord16 = s97 + s114
+  s253 :: SBool = s88 /= s252
+  s254 :: SWord16 = s66 + s90
+  s255 :: SBool = s11 /= s254
+  s256 :: SBool = s9 /= s254
+  s257 :: SBool = s7 /= s254
+  s258 :: SBool = s5 /= s254
+  s259 :: SBool = s3 /= s254
+  s260 :: SWord16 = s97 + s123
+  s261 :: SBool = s88 /= s260
+  s262 :: SWord16 = s54 + s99
+  s263 :: SBool = s11 /= s262
+  s264 :: SBool = s9 /= s262
+  s265 :: SBool = s7 /= s262
+  s266 :: SBool = s5 /= s262
+  s267 :: SBool = s3 /= s262
+  s268 :: SWord16 = s106 + s114
+  s269 :: SBool = s88 /= s268
+  s270 :: SWord16 = s66 + s99
+  s271 :: SBool = s11 /= s270
+  s272 :: SBool = s9 /= s270
+  s273 :: SBool = s7 /= s270
+  s274 :: SBool = s5 /= s270
+  s275 :: SBool = s3 /= s270
+  s276 :: SWord16 = s106 + s123
+  s277 :: SBool = s88 /= s276
+  s278 :: SWord16 = s66 + s108
+  s279 :: SBool = s11 /= s278
+  s280 :: SBool = s9 /= s278
+  s281 :: SBool = s7 /= s278
+  s282 :: SBool = s5 /= s278
+  s283 :: SBool = s3 /= s278
+  s284 :: SWord16 = s115 + s123
+  s285 :: SBool = s88 /= s284
+  s286 :: SWord16 = s42 + s126
+  s287 :: SBool = s11 /= s286
+  s288 :: SBool = s9 /= s286
+  s289 :: SBool = s7 /= s286
+  s290 :: SBool = s5 /= s286
+  s291 :: SBool = s3 /= s286
+  s292 :: SWord16 = s105 + s132
+  s293 :: SBool = s88 /= s292
+  s294 :: SWord16 = s54 + s126
+  s295 :: SBool = s11 /= s294
+  s296 :: SBool = s9 /= s294
+  s297 :: SBool = s7 /= s294
+  s298 :: SBool = s5 /= s294
+  s299 :: SBool = s3 /= s294
+  s300 :: SWord16 = s114 + s132
+  s301 :: SBool = s88 /= s300
+  s302 :: SWord16 = s66 + s126
+  s303 :: SBool = s11 /= s302
+  s304 :: SBool = s9 /= s302
+  s305 :: SBool = s7 /= s302
+  s306 :: SBool = s5 /= s302
+  s307 :: SBool = s3 /= s302
+  s308 :: SWord16 = s123 + s132
+  s309 :: SBool = s88 /= s308
+  s310 :: SWord16 = s54 + s134
+  s311 :: SBool = s11 /= s310
+  s312 :: SBool = s9 /= s310
+  s313 :: SBool = s7 /= s310
+  s314 :: SBool = s5 /= s310
+  s315 :: SBool = s3 /= s310
+  s316 :: SWord16 = s114 + s140
+  s317 :: SBool = s88 /= s316
+  s318 :: SWord16 = s66 + s134
+  s319 :: SBool = s11 /= s318
+  s320 :: SBool = s9 /= s318
+  s321 :: SBool = s7 /= s318
+  s322 :: SBool = s5 /= s318
+  s323 :: SBool = s3 /= s318
+  s324 :: SWord16 = s123 + s140
+  s325 :: SBool = s88 /= s324
+  s326 :: SWord16 = s66 + s142
+  s327 :: SBool = s11 /= s326
+  s328 :: SBool = s9 /= s326
+  s329 :: SBool = s7 /= s326
+  s330 :: SBool = s5 /= s326
+  s331 :: SBool = s3 /= s326
+  s332 :: SWord16 = s123 + s148
+  s333 :: SBool = s88 /= s332
+  s334 :: SWord16 = s54 + s158
+  s335 :: SBool = s11 /= s334
+  s336 :: SBool = s9 /= s334
+  s337 :: SBool = s7 /= s334
+  s338 :: SBool = s5 /= s334
+  s339 :: SBool = s3 /= s334
+  s340 :: SWord16 = s114 + s164
+  s341 :: SBool = s88 /= s340
+  s342 :: SWord16 = s66 + s158
+  s343 :: SBool = s11 /= s342
+  s344 :: SBool = s9 /= s342
+  s345 :: SBool = s7 /= s342
+  s346 :: SBool = s5 /= s342
+  s347 :: SBool = s3 /= s342
+  s348 :: SWord16 = s123 + s164
+  s349 :: SBool = s88 /= s348
+  s350 :: SWord16 = s66 + s166
+  s351 :: SBool = s11 /= s350
+  s352 :: SBool = s9 /= s350
+  s353 :: SBool = s7 /= s350
+  s354 :: SBool = s5 /= s350
+  s355 :: SBool = s3 /= s350
+  s356 :: SWord16 = s123 + s172
+  s357 :: SBool = s88 /= s356
+  s358 :: SWord16 = s66 + s182
+  s359 :: SBool = s11 /= s358
+  s360 :: SBool = s9 /= s358
+  s361 :: SBool = s7 /= s358
+  s362 :: SBool = s5 /= s358
+  s363 :: SBool = s3 /= s358
+  s364 :: SWord16 = s123 + s188
+  s365 :: SBool = s88 /= s364
+  s366 :: SWord16 = s42 + s206
+  s367 :: SBool = s11 /= s366
+  s368 :: SBool = s9 /= s366
+  s369 :: SBool = s7 /= s366
+  s370 :: SBool = s5 /= s366
+  s371 :: SBool = s3 /= s366
+  s372 :: SWord16 = s105 + s212
+  s373 :: SBool = s88 /= s372
+  s374 :: SWord16 = s54 + s206
+  s375 :: SBool = s11 /= s374
+  s376 :: SBool = s9 /= s374
+  s377 :: SBool = s7 /= s374
+  s378 :: SBool = s5 /= s374
+  s379 :: SBool = s3 /= s374
+  s380 :: SWord16 = s114 + s212
+  s381 :: SBool = s88 /= s380
+  s382 :: SWord16 = s66 + s206
+  s383 :: SBool = s11 /= s382
+  s384 :: SBool = s9 /= s382
+  s385 :: SBool = s7 /= s382
+  s386 :: SBool = s5 /= s382
+  s387 :: SBool = s3 /= s382
+  s388 :: SWord16 = s123 + s212
+  s389 :: SBool = s88 /= s388
+  s390 :: SWord16 = s54 + s214
+  s391 :: SBool = s11 /= s390
+  s392 :: SBool = s9 /= s390
+  s393 :: SBool = s7 /= s390
+  s394 :: SBool = s5 /= s390
+  s395 :: SBool = s3 /= s390
+  s396 :: SWord16 = s114 + s220
+  s397 :: SBool = s88 /= s396
+  s398 :: SWord16 = s66 + s214
+  s399 :: SBool = s11 /= s398
+  s400 :: SBool = s9 /= s398
+  s401 :: SBool = s7 /= s398
+  s402 :: SBool = s5 /= s398
+  s403 :: SBool = s3 /= s398
+  s404 :: SWord16 = s123 + s220
+  s405 :: SBool = s88 /= s404
+  s406 :: SWord16 = s66 + s222
+  s407 :: SBool = s11 /= s406
+  s408 :: SBool = s9 /= s406
+  s409 :: SBool = s7 /= s406
+  s410 :: SBool = s5 /= s406
+  s411 :: SBool = s3 /= s406
+  s412 :: SWord16 = s123 + s228
+  s413 :: SBool = s88 /= s412
+  s414 :: SWord16 = s54 + s238
+  s415 :: SBool = s11 /= s414
+  s416 :: SBool = s9 /= s414
+  s417 :: SBool = s7 /= s414
+  s418 :: SBool = s5 /= s414
+  s419 :: SBool = s3 /= s414
+  s420 :: SWord16 = s114 + s244
+  s421 :: SBool = s88 /= s420
+  s422 :: SWord16 = s66 + s238
+  s423 :: SBool = s11 /= s422
+  s424 :: SBool = s9 /= s422
+  s425 :: SBool = s7 /= s422
+  s426 :: SBool = s5 /= s422
+  s427 :: SBool = s3 /= s422
+  s428 :: SWord16 = s123 + s244
+  s429 :: SBool = s88 /= s428
+  s430 :: SWord16 = s66 + s246
+  s431 :: SBool = s11 /= s430
+  s432 :: SBool = s9 /= s430
+  s433 :: SBool = s7 /= s430
+  s434 :: SBool = s5 /= s430
+  s435 :: SBool = s3 /= s430
+  s436 :: SWord16 = s123 + s252
+  s437 :: SBool = s88 /= s436
+  s438 :: SWord16 = s66 + s262
+  s439 :: SBool = s11 /= s438
+  s440 :: SBool = s9 /= s438
+  s441 :: SBool = s7 /= s438
+  s442 :: SBool = s5 /= s438
+  s443 :: SBool = s3 /= s438
+  s444 :: SWord16 = s123 + s268
+  s445 :: SBool = s88 /= s444
+  s446 :: SWord16 = s54 + s286
+  s447 :: SBool = s11 /= s446
+  s448 :: SBool = s9 /= s446
+  s449 :: SBool = s7 /= s446
+  s450 :: SBool = s5 /= s446
+  s451 :: SBool = s3 /= s446
+  s452 :: SWord16 = s114 + s292
+  s453 :: SBool = s88 /= s452
+  s454 :: SWord16 = s66 + s286
+  s455 :: SBool = s11 /= s454
+  s456 :: SBool = s9 /= s454
+  s457 :: SBool = s7 /= s454
+  s458 :: SBool = s5 /= s454
+  s459 :: SBool = s3 /= s454
+  s460 :: SWord16 = s123 + s292
+  s461 :: SBool = s88 /= s460
+  s462 :: SWord16 = s66 + s294
+  s463 :: SBool = s11 /= s462
+  s464 :: SBool = s9 /= s462
+  s465 :: SBool = s7 /= s462
+  s466 :: SBool = s5 /= s462
+  s467 :: SBool = s3 /= s462
+  s468 :: SWord16 = s123 + s300
+  s469 :: SBool = s88 /= s468
+  s470 :: SWord16 = s66 + s310
+  s471 :: SBool = s11 /= s470
+  s472 :: SBool = s9 /= s470
+  s473 :: SBool = s7 /= s470
+  s474 :: SBool = s5 /= s470
+  s475 :: SBool = s3 /= s470
+  s476 :: SWord16 = s123 + s316
+  s477 :: SBool = s88 /= s476
+  s478 :: SWord16 = s66 + s334
+  s479 :: SBool = s11 /= s478
+  s480 :: SBool = s9 /= s478
+  s481 :: SBool = s7 /= s478
+  s482 :: SBool = s5 /= s478
+  s483 :: SBool = s3 /= s478
+  s484 :: SWord16 = s123 + s340
+  s485 :: SBool = s88 /= s484
+  s486 :: SWord16 = s54 + s366
+  s487 :: SBool = s11 /= s486
+  s488 :: SBool = s9 /= s486
+  s489 :: SBool = s7 /= s486
+  s490 :: SBool = s5 /= s486
+  s491 :: SBool = s3 /= s486
+  s492 :: SWord16 = s114 + s372
+  s493 :: SBool = s88 /= s492
+  s494 :: SWord16 = s66 + s366
+  s495 :: SBool = s11 /= s494
+  s496 :: SBool = s9 /= s494
+  s497 :: SBool = s7 /= s494
+  s498 :: SBool = s5 /= s494
+  s499 :: SBool = s3 /= s494
+  s500 :: SWord16 = s123 + s372
+  s501 :: SBool = s88 /= s500
+  s502 :: SWord16 = s66 + s374
+  s503 :: SBool = s11 /= s502
+  s504 :: SBool = s9 /= s502
+  s505 :: SBool = s7 /= s502
+  s506 :: SBool = s5 /= s502
+  s507 :: SBool = s3 /= s502
+  s508 :: SWord16 = s123 + s380
+  s509 :: SBool = s88 /= s508
+  s510 :: SWord16 = s66 + s390
+  s511 :: SBool = s11 /= s510
+  s512 :: SBool = s9 /= s510
+  s513 :: SBool = s7 /= s510
+  s514 :: SBool = s5 /= s510
+  s515 :: SBool = s3 /= s510
+  s516 :: SWord16 = s123 + s396
+  s517 :: SBool = s88 /= s516
+  s518 :: SWord16 = s66 + s414
+  s519 :: SBool = s11 /= s518
+  s520 :: SBool = s9 /= s518
+  s521 :: SBool = s7 /= s518
+  s522 :: SBool = s5 /= s518
+  s523 :: SBool = s3 /= s518
+  s524 :: SWord16 = s123 + s420
+  s525 :: SBool = s88 /= s524
+  s526 :: SWord16 = s66 + s446
+  s527 :: SBool = s11 /= s526
+  s528 :: SBool = s9 /= s526
+  s529 :: SBool = s7 /= s526
+  s530 :: SBool = s5 /= s526
+  s531 :: SBool = s3 /= s526
+  s532 :: SWord16 = s123 + s452
+  s533 :: SBool = s88 /= s532
+  s534 :: SWord16 = s66 + s486
+  s535 :: SBool = s11 /= s534
+  s536 :: SBool = s9 /= s534
+  s537 :: SBool = s7 /= s534
+  s538 :: SBool = s5 /= s534
+  s539 :: SBool = s3 /= s534
+  s540 :: SWord16 = s123 + s492
+  s541 :: SBool = s88 /= s540
+  s542 :: SBool = s0 >= s18
+  s543 :: SBool = s18 >= s30
+  s544 :: SBool = s30 >= s42
+  s545 :: SBool = s42 >= s54
+  s546 :: SBool = s54 >= s66
+  s547 :: SBool = s545 & s546
+  s548 :: SBool = s544 & s547
+  s549 :: SBool = s543 & s548
+  s550 :: SBool = s542 & s549
+  s552 :: SBool = s534 == s551
+CONSTRAINTS
+  s17
+  s29
+  s41
+  s53
+  s65
+  s77
+  s79
+  s80
+  s81
+  s82
+  s83
+  s89
+  s91
+  s92
+  s93
+  s94
+  s95
+  s98
+  s100
+  s101
+  s102
+  s103
+  s104
+  s107
+  s109
+  s110
+  s111
+  s112
+  s113
+  s116
+  s118
+  s119
+  s120
+  s121
+  s122
+  s125
+  s127
+  s128
+  s129
+  s130
+  s131
+  s133
+  s135
+  s136
+  s137
+  s138
+  s139
+  s141
+  s143
+  s144
+  s145
+  s146
+  s147
+  s149
+  s151
+  s152
+  s153
+  s154
+  s155
+  s157
+  s159
+  s160
+  s161
+  s162
+  s163
+  s165
+  s167
+  s168
+  s169
+  s170
+  s171
+  s173
+  s175
+  s176
+  s177
+  s178
+  s179
+  s181
+  s183
+  s184
+  s185
+  s186
+  s187
+  s189
+  s191
+  s192
+  s193
+  s194
+  s195
+  s197
+  s199
+  s200
+  s201
+  s202
+  s203
+  s205
+  s207
+  s208
+  s209
+  s210
+  s211
+  s213
+  s215
+  s216
+  s217
+  s218
+  s219
+  s221
+  s223
+  s224
+  s225
+  s226
+  s227
+  s229
+  s231
+  s232
+  s233
+  s234
+  s235
+  s237
+  s239
+  s240
+  s241
+  s242
+  s243
+  s245
+  s247
+  s248
+  s249
+  s250
+  s251
+  s253
+  s255
+  s256
+  s257
+  s258
+  s259
+  s261
+  s263
+  s264
+  s265
+  s266
+  s267
+  s269
+  s271
+  s272
+  s273
+  s274
+  s275
+  s277
+  s279
+  s280
+  s281
+  s282
+  s283
+  s285
+  s287
+  s288
+  s289
+  s290
+  s291
+  s293
+  s295
+  s296
+  s297
+  s298
+  s299
+  s301
+  s303
+  s304
+  s305
+  s306
+  s307
+  s309
+  s311
+  s312
+  s313
+  s314
+  s315
+  s317
+  s319
+  s320
+  s321
+  s322
+  s323
+  s325
+  s327
+  s328
+  s329
+  s330
+  s331
+  s333
+  s335
+  s336
+  s337
+  s338
+  s339
+  s341
+  s343
+  s344
+  s345
+  s346
+  s347
+  s349
+  s351
+  s352
+  s353
+  s354
+  s355
+  s357
+  s359
+  s360
+  s361
+  s362
+  s363
+  s365
+  s367
+  s368
+  s369
+  s370
+  s371
+  s373
+  s375
+  s376
+  s377
+  s378
+  s379
+  s381
+  s383
+  s384
+  s385
+  s386
+  s387
+  s389
+  s391
+  s392
+  s393
+  s394
+  s395
+  s397
+  s399
+  s400
+  s401
+  s402
+  s403
+  s405
+  s407
+  s408
+  s409
+  s410
+  s411
+  s413
+  s415
+  s416
+  s417
+  s418
+  s419
+  s421
+  s423
+  s424
+  s425
+  s426
+  s427
+  s429
+  s431
+  s432
+  s433
+  s434
+  s435
+  s437
+  s439
+  s440
+  s441
+  s442
+  s443
+  s445
+  s447
+  s448
+  s449
+  s450
+  s451
+  s453
+  s455
+  s456
+  s457
+  s458
+  s459
+  s461
+  s463
+  s464
+  s465
+  s466
+  s467
+  s469
+  s471
+  s472
+  s473
+  s474
+  s475
+  s477
+  s479
+  s480
+  s481
+  s482
+  s483
+  s485
+  s487
+  s488
+  s489
+  s490
+  s491
+  s493
+  s495
+  s496
+  s497
+  s498
+  s499
+  s501
+  s503
+  s504
+  s505
+  s506
+  s507
+  s509
+  s511
+  s512
+  s513
+  s514
+  s515
+  s517
+  s519
+  s520
+  s521
+  s522
+  s523
+  s525
+  s527
+  s528
+  s529
+  s530
+  s531
+  s533
+  s535
+  s536
+  s537
+  s538
+  s539
+  s541
+  s550
+ASSERTIONS
+OUTPUTS
+  s552
diff --git a/SBVTestSuite/GoldFiles/combined1.gold b/SBVTestSuite/GoldFiles/combined1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/combined1.gold
@@ -0,0 +1,6 @@
+Optimal model:
+  x     = 3 :: Integer
+  y     = 2 :: Integer
+  z     = 4 :: Integer
+  max_x = 3 :: Integer
+  max_y = 2 :: Integer
diff --git a/SBVTestSuite/GoldFiles/combined2.gold b/SBVTestSuite/GoldFiles/combined2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/combined2.gold
@@ -0,0 +1,7 @@
+Optimal model:
+  a      =  True :: Bool
+  b      = False :: Bool
+  c      =  True :: Bool
+  soft_a =  True :: Bool
+  soft_b = False :: Bool
+  soft_c =  True :: Bool
diff --git a/SBVTestSuite/GoldFiles/constArr2_SArray.gold b/SBVTestSuite/GoldFiles/constArr2_SArray.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/constArr2_SArray.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s5 () Int 2)
+[GOOD] (define-fun s7 () Int 3)
+[GOOD] (define-fun s9 () Int 75)
+[GOOD] (define-fun s14 () (Array Int Int) (store (store (store (store ((as const (Array Int Int)) 2) 75 5) 3 6) 2 5) 1 12))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "j"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (< s0 s1))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s0 s5))
+[GOOD] (define-fun s8 () Bool (= s0 s7))
+[GOOD] (define-fun s10 () Bool (= s0 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (or s6 s11))
+[GOOD] (define-fun s13 () Bool (or s4 s12))
+[GOOD] (define-fun s15 () Int (select s14 s0))
+[GOOD] (define-fun s16 () Int (select s14 s1))
+[GOOD] (define-fun s17 () Bool (= s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s13)
+[GOOD] (assert s17)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 75))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  i =  2 :: Integer
+  j = 75 :: Integer
diff --git a/SBVTestSuite/GoldFiles/constArr_SArray.gold b/SBVTestSuite/GoldFiles/constArr_SArray.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/constArr_SArray.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s5 () Int 2)
+[GOOD] (define-fun s7 () Int 3)
+[GOOD] (define-fun s9 () Int 75)
+[GOOD] (define-fun s14 () (Array Int Int) (store (store (store (store ((as const (Array Int Int)) 7) 75 5) 3 6) 2 5) 1 12))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "j"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (< s0 s1))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s0 s5))
+[GOOD] (define-fun s8 () Bool (= s0 s7))
+[GOOD] (define-fun s10 () Bool (= s0 s9))
+[GOOD] (define-fun s11 () Bool (or s8 s10))
+[GOOD] (define-fun s12 () Bool (or s6 s11))
+[GOOD] (define-fun s13 () Bool (or s4 s12))
+[GOOD] (define-fun s15 () Int (select s14 s0))
+[GOOD] (define-fun s16 () Int (select s14 s1))
+[GOOD] (define-fun s17 () Bool (= s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s13)
+[GOOD] (assert s17)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 75))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  i =  2 :: Integer
+  j = 75 :: Integer
diff --git a/SBVTestSuite/GoldFiles/counts.gold b/SBVTestSuite/GoldFiles/counts.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/counts.gold
@@ -0,0 +1,1702 @@
+INPUTS
+  s0 :: SWord8
+  s1 :: SWord8
+  s2 :: SWord8
+  s3 :: SWord8
+  s4 :: SWord8
+  s5 :: SWord8
+  s6 :: SWord8
+  s7 :: SWord8
+  s8 :: SWord8
+  s9 :: SWord8
+CONSTANTS
+  s10 = 10 :: Word8
+  s12 = 0 :: Word8
+  s32 = 2 :: Word8
+  s33 = 1 :: Word8
+  s35 = 100 :: Word8
+  s555 = 3 :: Word8
+  s716 = 4 :: Word8
+  s877 = 5 :: Word8
+  s1038 = 6 :: Word8
+  s1199 = 7 :: Word8
+  s1360 = 8 :: Word8
+  s1521 = 9 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s11 :: SBool = s9 < s10
+  s13 :: SBool = s9 == s12
+  s14 :: SBool = s8 < s10
+  s15 :: SBool = s8 == s12
+  s16 :: SBool = s7 < s10
+  s17 :: SBool = s7 == s12
+  s18 :: SBool = s6 < s10
+  s19 :: SBool = s6 == s12
+  s20 :: SBool = s5 < s10
+  s21 :: SBool = s5 == s12
+  s22 :: SBool = s4 < s10
+  s23 :: SBool = s4 == s12
+  s24 :: SBool = s3 < s10
+  s25 :: SBool = s3 == s12
+  s26 :: SBool = s2 < s10
+  s27 :: SBool = s2 == s12
+  s28 :: SBool = s1 < s10
+  s29 :: SBool = s1 == s12
+  s30 :: SBool = s0 < s10
+  s31 :: SBool = s0 == s12
+  s34 :: SWord8 = if s31 then s32 else s33
+  s36 :: SBool = s0 < s35
+  s37 :: SWord8 = s0 rem s10
+  s38 :: SBool = s12 == s37
+  s39 :: SWord8 = s0 quot s10
+  s40 :: SWord8 = s39 rem s10
+  s41 :: SBool = s12 == s40
+  s42 :: SWord8 = if s41 then s32 else s33
+  s43 :: SWord8 = s33 + s42
+  s44 :: SWord8 = if s38 then s43 else s42
+  s45 :: SWord8 = s39 quot s10
+  s46 :: SBool = s12 == s45
+  s47 :: SWord8 = if s46 then s32 else s33
+  s48 :: SWord8 = s33 + s47
+  s49 :: SWord8 = if s41 then s48 else s47
+  s50 :: SWord8 = s33 + s49
+  s51 :: SWord8 = if s38 then s50 else s49
+  s52 :: SWord8 = if s36 then s44 else s51
+  s53 :: SWord8 = if s30 then s34 else s52
+  s54 :: SWord8 = s33 + s53
+  s55 :: SWord8 = if s29 then s54 else s53
+  s56 :: SBool = s1 < s35
+  s57 :: SWord8 = s1 rem s10
+  s58 :: SBool = s12 == s57
+  s59 :: SWord8 = s1 quot s10
+  s60 :: SWord8 = s59 rem s10
+  s61 :: SBool = s12 == s60
+  s62 :: SWord8 = if s61 then s54 else s53
+  s63 :: SWord8 = s33 + s62
+  s64 :: SWord8 = if s58 then s63 else s62
+  s65 :: SWord8 = s59 quot s10
+  s66 :: SBool = s12 == s65
+  s67 :: SWord8 = if s66 then s54 else s53
+  s68 :: SWord8 = s33 + s67
+  s69 :: SWord8 = if s61 then s68 else s67
+  s70 :: SWord8 = s33 + s69
+  s71 :: SWord8 = if s58 then s70 else s69
+  s72 :: SWord8 = if s56 then s64 else s71
+  s73 :: SWord8 = if s28 then s55 else s72
+  s74 :: SWord8 = s33 + s73
+  s75 :: SWord8 = if s27 then s74 else s73
+  s76 :: SBool = s2 < s35
+  s77 :: SWord8 = s2 rem s10
+  s78 :: SBool = s12 == s77
+  s79 :: SWord8 = s2 quot s10
+  s80 :: SWord8 = s79 rem s10
+  s81 :: SBool = s12 == s80
+  s82 :: SWord8 = if s81 then s74 else s73
+  s83 :: SWord8 = s33 + s82
+  s84 :: SWord8 = if s78 then s83 else s82
+  s85 :: SWord8 = s79 quot s10
+  s86 :: SBool = s12 == s85
+  s87 :: SWord8 = if s86 then s74 else s73
+  s88 :: SWord8 = s33 + s87
+  s89 :: SWord8 = if s81 then s88 else s87
+  s90 :: SWord8 = s33 + s89
+  s91 :: SWord8 = if s78 then s90 else s89
+  s92 :: SWord8 = if s76 then s84 else s91
+  s93 :: SWord8 = if s26 then s75 else s92
+  s94 :: SWord8 = s33 + s93
+  s95 :: SWord8 = if s25 then s94 else s93
+  s96 :: SBool = s3 < s35
+  s97 :: SWord8 = s3 rem s10
+  s98 :: SBool = s12 == s97
+  s99 :: SWord8 = s3 quot s10
+  s100 :: SWord8 = s99 rem s10
+  s101 :: SBool = s12 == s100
+  s102 :: SWord8 = if s101 then s94 else s93
+  s103 :: SWord8 = s33 + s102
+  s104 :: SWord8 = if s98 then s103 else s102
+  s105 :: SWord8 = s99 quot s10
+  s106 :: SBool = s12 == s105
+  s107 :: SWord8 = if s106 then s94 else s93
+  s108 :: SWord8 = s33 + s107
+  s109 :: SWord8 = if s101 then s108 else s107
+  s110 :: SWord8 = s33 + s109
+  s111 :: SWord8 = if s98 then s110 else s109
+  s112 :: SWord8 = if s96 then s104 else s111
+  s113 :: SWord8 = if s24 then s95 else s112
+  s114 :: SWord8 = s33 + s113
+  s115 :: SWord8 = if s23 then s114 else s113
+  s116 :: SBool = s4 < s35
+  s117 :: SWord8 = s4 rem s10
+  s118 :: SBool = s12 == s117
+  s119 :: SWord8 = s4 quot s10
+  s120 :: SWord8 = s119 rem s10
+  s121 :: SBool = s12 == s120
+  s122 :: SWord8 = if s121 then s114 else s113
+  s123 :: SWord8 = s33 + s122
+  s124 :: SWord8 = if s118 then s123 else s122
+  s125 :: SWord8 = s119 quot s10
+  s126 :: SBool = s12 == s125
+  s127 :: SWord8 = if s126 then s114 else s113
+  s128 :: SWord8 = s33 + s127
+  s129 :: SWord8 = if s121 then s128 else s127
+  s130 :: SWord8 = s33 + s129
+  s131 :: SWord8 = if s118 then s130 else s129
+  s132 :: SWord8 = if s116 then s124 else s131
+  s133 :: SWord8 = if s22 then s115 else s132
+  s134 :: SWord8 = s33 + s133
+  s135 :: SWord8 = if s21 then s134 else s133
+  s136 :: SBool = s5 < s35
+  s137 :: SWord8 = s5 rem s10
+  s138 :: SBool = s12 == s137
+  s139 :: SWord8 = s5 quot s10
+  s140 :: SWord8 = s139 rem s10
+  s141 :: SBool = s12 == s140
+  s142 :: SWord8 = if s141 then s134 else s133
+  s143 :: SWord8 = s33 + s142
+  s144 :: SWord8 = if s138 then s143 else s142
+  s145 :: SWord8 = s139 quot s10
+  s146 :: SBool = s12 == s145
+  s147 :: SWord8 = if s146 then s134 else s133
+  s148 :: SWord8 = s33 + s147
+  s149 :: SWord8 = if s141 then s148 else s147
+  s150 :: SWord8 = s33 + s149
+  s151 :: SWord8 = if s138 then s150 else s149
+  s152 :: SWord8 = if s136 then s144 else s151
+  s153 :: SWord8 = if s20 then s135 else s152
+  s154 :: SWord8 = s33 + s153
+  s155 :: SWord8 = if s19 then s154 else s153
+  s156 :: SBool = s6 < s35
+  s157 :: SWord8 = s6 rem s10
+  s158 :: SBool = s12 == s157
+  s159 :: SWord8 = s6 quot s10
+  s160 :: SWord8 = s159 rem s10
+  s161 :: SBool = s12 == s160
+  s162 :: SWord8 = if s161 then s154 else s153
+  s163 :: SWord8 = s33 + s162
+  s164 :: SWord8 = if s158 then s163 else s162
+  s165 :: SWord8 = s159 quot s10
+  s166 :: SBool = s12 == s165
+  s167 :: SWord8 = if s166 then s154 else s153
+  s168 :: SWord8 = s33 + s167
+  s169 :: SWord8 = if s161 then s168 else s167
+  s170 :: SWord8 = s33 + s169
+  s171 :: SWord8 = if s158 then s170 else s169
+  s172 :: SWord8 = if s156 then s164 else s171
+  s173 :: SWord8 = if s18 then s155 else s172
+  s174 :: SWord8 = s33 + s173
+  s175 :: SWord8 = if s17 then s174 else s173
+  s176 :: SBool = s7 < s35
+  s177 :: SWord8 = s7 rem s10
+  s178 :: SBool = s12 == s177
+  s179 :: SWord8 = s7 quot s10
+  s180 :: SWord8 = s179 rem s10
+  s181 :: SBool = s12 == s180
+  s182 :: SWord8 = if s181 then s174 else s173
+  s183 :: SWord8 = s33 + s182
+  s184 :: SWord8 = if s178 then s183 else s182
+  s185 :: SWord8 = s179 quot s10
+  s186 :: SBool = s12 == s185
+  s187 :: SWord8 = if s186 then s174 else s173
+  s188 :: SWord8 = s33 + s187
+  s189 :: SWord8 = if s181 then s188 else s187
+  s190 :: SWord8 = s33 + s189
+  s191 :: SWord8 = if s178 then s190 else s189
+  s192 :: SWord8 = if s176 then s184 else s191
+  s193 :: SWord8 = if s16 then s175 else s192
+  s194 :: SWord8 = s33 + s193
+  s195 :: SWord8 = if s15 then s194 else s193
+  s196 :: SBool = s8 < s35
+  s197 :: SWord8 = s8 rem s10
+  s198 :: SBool = s12 == s197
+  s199 :: SWord8 = s8 quot s10
+  s200 :: SWord8 = s199 rem s10
+  s201 :: SBool = s12 == s200
+  s202 :: SWord8 = if s201 then s194 else s193
+  s203 :: SWord8 = s33 + s202
+  s204 :: SWord8 = if s198 then s203 else s202
+  s205 :: SWord8 = s199 quot s10
+  s206 :: SBool = s12 == s205
+  s207 :: SWord8 = if s206 then s194 else s193
+  s208 :: SWord8 = s33 + s207
+  s209 :: SWord8 = if s201 then s208 else s207
+  s210 :: SWord8 = s33 + s209
+  s211 :: SWord8 = if s198 then s210 else s209
+  s212 :: SWord8 = if s196 then s204 else s211
+  s213 :: SWord8 = if s14 then s195 else s212
+  s214 :: SWord8 = s33 + s213
+  s215 :: SWord8 = if s13 then s214 else s213
+  s216 :: SBool = s9 < s35
+  s217 :: SWord8 = s9 rem s10
+  s218 :: SBool = s12 == s217
+  s219 :: SWord8 = s9 quot s10
+  s220 :: SWord8 = s219 rem s10
+  s221 :: SBool = s12 == s220
+  s222 :: SWord8 = if s221 then s214 else s213
+  s223 :: SWord8 = s33 + s222
+  s224 :: SWord8 = if s218 then s223 else s222
+  s225 :: SWord8 = s219 quot s10
+  s226 :: SBool = s12 == s225
+  s227 :: SWord8 = if s226 then s214 else s213
+  s228 :: SWord8 = s33 + s227
+  s229 :: SWord8 = if s221 then s228 else s227
+  s230 :: SWord8 = s33 + s229
+  s231 :: SWord8 = if s218 then s230 else s229
+  s232 :: SWord8 = if s216 then s224 else s231
+  s233 :: SWord8 = if s11 then s215 else s232
+  s234 :: SBool = s0 == s233
+  s235 :: SBool = s9 == s33
+  s236 :: SBool = s8 == s33
+  s237 :: SBool = s7 == s33
+  s238 :: SBool = s6 == s33
+  s239 :: SBool = s5 == s33
+  s240 :: SBool = s4 == s33
+  s241 :: SBool = s3 == s33
+  s242 :: SBool = s2 == s33
+  s243 :: SBool = s1 == s33
+  s244 :: SBool = s0 == s33
+  s245 :: SWord8 = if s244 then s32 else s33
+  s246 :: SBool = s33 == s37
+  s247 :: SBool = s33 == s40
+  s248 :: SWord8 = if s247 then s32 else s33
+  s249 :: SWord8 = s33 + s248
+  s250 :: SWord8 = if s246 then s249 else s248
+  s251 :: SBool = s33 == s45
+  s252 :: SWord8 = if s251 then s32 else s33
+  s253 :: SWord8 = s33 + s252
+  s254 :: SWord8 = if s247 then s253 else s252
+  s255 :: SWord8 = s33 + s254
+  s256 :: SWord8 = if s246 then s255 else s254
+  s257 :: SWord8 = if s36 then s250 else s256
+  s258 :: SWord8 = if s30 then s245 else s257
+  s259 :: SWord8 = s33 + s258
+  s260 :: SWord8 = if s243 then s259 else s258
+  s261 :: SBool = s33 == s57
+  s262 :: SBool = s33 == s60
+  s263 :: SWord8 = if s262 then s259 else s258
+  s264 :: SWord8 = s33 + s263
+  s265 :: SWord8 = if s261 then s264 else s263
+  s266 :: SBool = s33 == s65
+  s267 :: SWord8 = if s266 then s259 else s258
+  s268 :: SWord8 = s33 + s267
+  s269 :: SWord8 = if s262 then s268 else s267
+  s270 :: SWord8 = s33 + s269
+  s271 :: SWord8 = if s261 then s270 else s269
+  s272 :: SWord8 = if s56 then s265 else s271
+  s273 :: SWord8 = if s28 then s260 else s272
+  s274 :: SWord8 = s33 + s273
+  s275 :: SWord8 = if s242 then s274 else s273
+  s276 :: SBool = s33 == s77
+  s277 :: SBool = s33 == s80
+  s278 :: SWord8 = if s277 then s274 else s273
+  s279 :: SWord8 = s33 + s278
+  s280 :: SWord8 = if s276 then s279 else s278
+  s281 :: SBool = s33 == s85
+  s282 :: SWord8 = if s281 then s274 else s273
+  s283 :: SWord8 = s33 + s282
+  s284 :: SWord8 = if s277 then s283 else s282
+  s285 :: SWord8 = s33 + s284
+  s286 :: SWord8 = if s276 then s285 else s284
+  s287 :: SWord8 = if s76 then s280 else s286
+  s288 :: SWord8 = if s26 then s275 else s287
+  s289 :: SWord8 = s33 + s288
+  s290 :: SWord8 = if s241 then s289 else s288
+  s291 :: SBool = s33 == s97
+  s292 :: SBool = s33 == s100
+  s293 :: SWord8 = if s292 then s289 else s288
+  s294 :: SWord8 = s33 + s293
+  s295 :: SWord8 = if s291 then s294 else s293
+  s296 :: SBool = s33 == s105
+  s297 :: SWord8 = if s296 then s289 else s288
+  s298 :: SWord8 = s33 + s297
+  s299 :: SWord8 = if s292 then s298 else s297
+  s300 :: SWord8 = s33 + s299
+  s301 :: SWord8 = if s291 then s300 else s299
+  s302 :: SWord8 = if s96 then s295 else s301
+  s303 :: SWord8 = if s24 then s290 else s302
+  s304 :: SWord8 = s33 + s303
+  s305 :: SWord8 = if s240 then s304 else s303
+  s306 :: SBool = s33 == s117
+  s307 :: SBool = s33 == s120
+  s308 :: SWord8 = if s307 then s304 else s303
+  s309 :: SWord8 = s33 + s308
+  s310 :: SWord8 = if s306 then s309 else s308
+  s311 :: SBool = s33 == s125
+  s312 :: SWord8 = if s311 then s304 else s303
+  s313 :: SWord8 = s33 + s312
+  s314 :: SWord8 = if s307 then s313 else s312
+  s315 :: SWord8 = s33 + s314
+  s316 :: SWord8 = if s306 then s315 else s314
+  s317 :: SWord8 = if s116 then s310 else s316
+  s318 :: SWord8 = if s22 then s305 else s317
+  s319 :: SWord8 = s33 + s318
+  s320 :: SWord8 = if s239 then s319 else s318
+  s321 :: SBool = s33 == s137
+  s322 :: SBool = s33 == s140
+  s323 :: SWord8 = if s322 then s319 else s318
+  s324 :: SWord8 = s33 + s323
+  s325 :: SWord8 = if s321 then s324 else s323
+  s326 :: SBool = s33 == s145
+  s327 :: SWord8 = if s326 then s319 else s318
+  s328 :: SWord8 = s33 + s327
+  s329 :: SWord8 = if s322 then s328 else s327
+  s330 :: SWord8 = s33 + s329
+  s331 :: SWord8 = if s321 then s330 else s329
+  s332 :: SWord8 = if s136 then s325 else s331
+  s333 :: SWord8 = if s20 then s320 else s332
+  s334 :: SWord8 = s33 + s333
+  s335 :: SWord8 = if s238 then s334 else s333
+  s336 :: SBool = s33 == s157
+  s337 :: SBool = s33 == s160
+  s338 :: SWord8 = if s337 then s334 else s333
+  s339 :: SWord8 = s33 + s338
+  s340 :: SWord8 = if s336 then s339 else s338
+  s341 :: SBool = s33 == s165
+  s342 :: SWord8 = if s341 then s334 else s333
+  s343 :: SWord8 = s33 + s342
+  s344 :: SWord8 = if s337 then s343 else s342
+  s345 :: SWord8 = s33 + s344
+  s346 :: SWord8 = if s336 then s345 else s344
+  s347 :: SWord8 = if s156 then s340 else s346
+  s348 :: SWord8 = if s18 then s335 else s347
+  s349 :: SWord8 = s33 + s348
+  s350 :: SWord8 = if s237 then s349 else s348
+  s351 :: SBool = s33 == s177
+  s352 :: SBool = s33 == s180
+  s353 :: SWord8 = if s352 then s349 else s348
+  s354 :: SWord8 = s33 + s353
+  s355 :: SWord8 = if s351 then s354 else s353
+  s356 :: SBool = s33 == s185
+  s357 :: SWord8 = if s356 then s349 else s348
+  s358 :: SWord8 = s33 + s357
+  s359 :: SWord8 = if s352 then s358 else s357
+  s360 :: SWord8 = s33 + s359
+  s361 :: SWord8 = if s351 then s360 else s359
+  s362 :: SWord8 = if s176 then s355 else s361
+  s363 :: SWord8 = if s16 then s350 else s362
+  s364 :: SWord8 = s33 + s363
+  s365 :: SWord8 = if s236 then s364 else s363
+  s366 :: SBool = s33 == s197
+  s367 :: SBool = s33 == s200
+  s368 :: SWord8 = if s367 then s364 else s363
+  s369 :: SWord8 = s33 + s368
+  s370 :: SWord8 = if s366 then s369 else s368
+  s371 :: SBool = s33 == s205
+  s372 :: SWord8 = if s371 then s364 else s363
+  s373 :: SWord8 = s33 + s372
+  s374 :: SWord8 = if s367 then s373 else s372
+  s375 :: SWord8 = s33 + s374
+  s376 :: SWord8 = if s366 then s375 else s374
+  s377 :: SWord8 = if s196 then s370 else s376
+  s378 :: SWord8 = if s14 then s365 else s377
+  s379 :: SWord8 = s33 + s378
+  s380 :: SWord8 = if s235 then s379 else s378
+  s381 :: SBool = s33 == s217
+  s382 :: SBool = s33 == s220
+  s383 :: SWord8 = if s382 then s379 else s378
+  s384 :: SWord8 = s33 + s383
+  s385 :: SWord8 = if s381 then s384 else s383
+  s386 :: SBool = s33 == s225
+  s387 :: SWord8 = if s386 then s379 else s378
+  s388 :: SWord8 = s33 + s387
+  s389 :: SWord8 = if s382 then s388 else s387
+  s390 :: SWord8 = s33 + s389
+  s391 :: SWord8 = if s381 then s390 else s389
+  s392 :: SWord8 = if s216 then s385 else s391
+  s393 :: SWord8 = if s11 then s380 else s392
+  s394 :: SBool = s1 == s393
+  s395 :: SBool = s9 == s32
+  s396 :: SBool = s8 == s32
+  s397 :: SBool = s7 == s32
+  s398 :: SBool = s6 == s32
+  s399 :: SBool = s5 == s32
+  s400 :: SBool = s4 == s32
+  s401 :: SBool = s3 == s32
+  s402 :: SBool = s2 == s32
+  s403 :: SBool = s1 == s32
+  s404 :: SBool = s0 == s32
+  s405 :: SWord8 = if s404 then s32 else s33
+  s406 :: SBool = s32 == s37
+  s407 :: SBool = s32 == s40
+  s408 :: SWord8 = if s407 then s32 else s33
+  s409 :: SWord8 = s33 + s408
+  s410 :: SWord8 = if s406 then s409 else s408
+  s411 :: SBool = s32 == s45
+  s412 :: SWord8 = if s411 then s32 else s33
+  s413 :: SWord8 = s33 + s412
+  s414 :: SWord8 = if s407 then s413 else s412
+  s415 :: SWord8 = s33 + s414
+  s416 :: SWord8 = if s406 then s415 else s414
+  s417 :: SWord8 = if s36 then s410 else s416
+  s418 :: SWord8 = if s30 then s405 else s417
+  s419 :: SWord8 = s33 + s418
+  s420 :: SWord8 = if s403 then s419 else s418
+  s421 :: SBool = s32 == s57
+  s422 :: SBool = s32 == s60
+  s423 :: SWord8 = if s422 then s419 else s418
+  s424 :: SWord8 = s33 + s423
+  s425 :: SWord8 = if s421 then s424 else s423
+  s426 :: SBool = s32 == s65
+  s427 :: SWord8 = if s426 then s419 else s418
+  s428 :: SWord8 = s33 + s427
+  s429 :: SWord8 = if s422 then s428 else s427
+  s430 :: SWord8 = s33 + s429
+  s431 :: SWord8 = if s421 then s430 else s429
+  s432 :: SWord8 = if s56 then s425 else s431
+  s433 :: SWord8 = if s28 then s420 else s432
+  s434 :: SWord8 = s33 + s433
+  s435 :: SWord8 = if s402 then s434 else s433
+  s436 :: SBool = s32 == s77
+  s437 :: SBool = s32 == s80
+  s438 :: SWord8 = if s437 then s434 else s433
+  s439 :: SWord8 = s33 + s438
+  s440 :: SWord8 = if s436 then s439 else s438
+  s441 :: SBool = s32 == s85
+  s442 :: SWord8 = if s441 then s434 else s433
+  s443 :: SWord8 = s33 + s442
+  s444 :: SWord8 = if s437 then s443 else s442
+  s445 :: SWord8 = s33 + s444
+  s446 :: SWord8 = if s436 then s445 else s444
+  s447 :: SWord8 = if s76 then s440 else s446
+  s448 :: SWord8 = if s26 then s435 else s447
+  s449 :: SWord8 = s33 + s448
+  s450 :: SWord8 = if s401 then s449 else s448
+  s451 :: SBool = s32 == s97
+  s452 :: SBool = s32 == s100
+  s453 :: SWord8 = if s452 then s449 else s448
+  s454 :: SWord8 = s33 + s453
+  s455 :: SWord8 = if s451 then s454 else s453
+  s456 :: SBool = s32 == s105
+  s457 :: SWord8 = if s456 then s449 else s448
+  s458 :: SWord8 = s33 + s457
+  s459 :: SWord8 = if s452 then s458 else s457
+  s460 :: SWord8 = s33 + s459
+  s461 :: SWord8 = if s451 then s460 else s459
+  s462 :: SWord8 = if s96 then s455 else s461
+  s463 :: SWord8 = if s24 then s450 else s462
+  s464 :: SWord8 = s33 + s463
+  s465 :: SWord8 = if s400 then s464 else s463
+  s466 :: SBool = s32 == s117
+  s467 :: SBool = s32 == s120
+  s468 :: SWord8 = if s467 then s464 else s463
+  s469 :: SWord8 = s33 + s468
+  s470 :: SWord8 = if s466 then s469 else s468
+  s471 :: SBool = s32 == s125
+  s472 :: SWord8 = if s471 then s464 else s463
+  s473 :: SWord8 = s33 + s472
+  s474 :: SWord8 = if s467 then s473 else s472
+  s475 :: SWord8 = s33 + s474
+  s476 :: SWord8 = if s466 then s475 else s474
+  s477 :: SWord8 = if s116 then s470 else s476
+  s478 :: SWord8 = if s22 then s465 else s477
+  s479 :: SWord8 = s33 + s478
+  s480 :: SWord8 = if s399 then s479 else s478
+  s481 :: SBool = s32 == s137
+  s482 :: SBool = s32 == s140
+  s483 :: SWord8 = if s482 then s479 else s478
+  s484 :: SWord8 = s33 + s483
+  s485 :: SWord8 = if s481 then s484 else s483
+  s486 :: SBool = s32 == s145
+  s487 :: SWord8 = if s486 then s479 else s478
+  s488 :: SWord8 = s33 + s487
+  s489 :: SWord8 = if s482 then s488 else s487
+  s490 :: SWord8 = s33 + s489
+  s491 :: SWord8 = if s481 then s490 else s489
+  s492 :: SWord8 = if s136 then s485 else s491
+  s493 :: SWord8 = if s20 then s480 else s492
+  s494 :: SWord8 = s33 + s493
+  s495 :: SWord8 = if s398 then s494 else s493
+  s496 :: SBool = s32 == s157
+  s497 :: SBool = s32 == s160
+  s498 :: SWord8 = if s497 then s494 else s493
+  s499 :: SWord8 = s33 + s498
+  s500 :: SWord8 = if s496 then s499 else s498
+  s501 :: SBool = s32 == s165
+  s502 :: SWord8 = if s501 then s494 else s493
+  s503 :: SWord8 = s33 + s502
+  s504 :: SWord8 = if s497 then s503 else s502
+  s505 :: SWord8 = s33 + s504
+  s506 :: SWord8 = if s496 then s505 else s504
+  s507 :: SWord8 = if s156 then s500 else s506
+  s508 :: SWord8 = if s18 then s495 else s507
+  s509 :: SWord8 = s33 + s508
+  s510 :: SWord8 = if s397 then s509 else s508
+  s511 :: SBool = s32 == s177
+  s512 :: SBool = s32 == s180
+  s513 :: SWord8 = if s512 then s509 else s508
+  s514 :: SWord8 = s33 + s513
+  s515 :: SWord8 = if s511 then s514 else s513
+  s516 :: SBool = s32 == s185
+  s517 :: SWord8 = if s516 then s509 else s508
+  s518 :: SWord8 = s33 + s517
+  s519 :: SWord8 = if s512 then s518 else s517
+  s520 :: SWord8 = s33 + s519
+  s521 :: SWord8 = if s511 then s520 else s519
+  s522 :: SWord8 = if s176 then s515 else s521
+  s523 :: SWord8 = if s16 then s510 else s522
+  s524 :: SWord8 = s33 + s523
+  s525 :: SWord8 = if s396 then s524 else s523
+  s526 :: SBool = s32 == s197
+  s527 :: SBool = s32 == s200
+  s528 :: SWord8 = if s527 then s524 else s523
+  s529 :: SWord8 = s33 + s528
+  s530 :: SWord8 = if s526 then s529 else s528
+  s531 :: SBool = s32 == s205
+  s532 :: SWord8 = if s531 then s524 else s523
+  s533 :: SWord8 = s33 + s532
+  s534 :: SWord8 = if s527 then s533 else s532
+  s535 :: SWord8 = s33 + s534
+  s536 :: SWord8 = if s526 then s535 else s534
+  s537 :: SWord8 = if s196 then s530 else s536
+  s538 :: SWord8 = if s14 then s525 else s537
+  s539 :: SWord8 = s33 + s538
+  s540 :: SWord8 = if s395 then s539 else s538
+  s541 :: SBool = s32 == s217
+  s542 :: SBool = s32 == s220
+  s543 :: SWord8 = if s542 then s539 else s538
+  s544 :: SWord8 = s33 + s543
+  s545 :: SWord8 = if s541 then s544 else s543
+  s546 :: SBool = s32 == s225
+  s547 :: SWord8 = if s546 then s539 else s538
+  s548 :: SWord8 = s33 + s547
+  s549 :: SWord8 = if s542 then s548 else s547
+  s550 :: SWord8 = s33 + s549
+  s551 :: SWord8 = if s541 then s550 else s549
+  s552 :: SWord8 = if s216 then s545 else s551
+  s553 :: SWord8 = if s11 then s540 else s552
+  s554 :: SBool = s2 == s553
+  s556 :: SBool = s9 == s555
+  s557 :: SBool = s8 == s555
+  s558 :: SBool = s7 == s555
+  s559 :: SBool = s6 == s555
+  s560 :: SBool = s5 == s555
+  s561 :: SBool = s4 == s555
+  s562 :: SBool = s3 == s555
+  s563 :: SBool = s2 == s555
+  s564 :: SBool = s1 == s555
+  s565 :: SBool = s0 == s555
+  s566 :: SWord8 = if s565 then s32 else s33
+  s567 :: SBool = s37 == s555
+  s568 :: SBool = s40 == s555
+  s569 :: SWord8 = if s568 then s32 else s33
+  s570 :: SWord8 = s33 + s569
+  s571 :: SWord8 = if s567 then s570 else s569
+  s572 :: SBool = s45 == s555
+  s573 :: SWord8 = if s572 then s32 else s33
+  s574 :: SWord8 = s33 + s573
+  s575 :: SWord8 = if s568 then s574 else s573
+  s576 :: SWord8 = s33 + s575
+  s577 :: SWord8 = if s567 then s576 else s575
+  s578 :: SWord8 = if s36 then s571 else s577
+  s579 :: SWord8 = if s30 then s566 else s578
+  s580 :: SWord8 = s33 + s579
+  s581 :: SWord8 = if s564 then s580 else s579
+  s582 :: SBool = s57 == s555
+  s583 :: SBool = s60 == s555
+  s584 :: SWord8 = if s583 then s580 else s579
+  s585 :: SWord8 = s33 + s584
+  s586 :: SWord8 = if s582 then s585 else s584
+  s587 :: SBool = s65 == s555
+  s588 :: SWord8 = if s587 then s580 else s579
+  s589 :: SWord8 = s33 + s588
+  s590 :: SWord8 = if s583 then s589 else s588
+  s591 :: SWord8 = s33 + s590
+  s592 :: SWord8 = if s582 then s591 else s590
+  s593 :: SWord8 = if s56 then s586 else s592
+  s594 :: SWord8 = if s28 then s581 else s593
+  s595 :: SWord8 = s33 + s594
+  s596 :: SWord8 = if s563 then s595 else s594
+  s597 :: SBool = s77 == s555
+  s598 :: SBool = s80 == s555
+  s599 :: SWord8 = if s598 then s595 else s594
+  s600 :: SWord8 = s33 + s599
+  s601 :: SWord8 = if s597 then s600 else s599
+  s602 :: SBool = s85 == s555
+  s603 :: SWord8 = if s602 then s595 else s594
+  s604 :: SWord8 = s33 + s603
+  s605 :: SWord8 = if s598 then s604 else s603
+  s606 :: SWord8 = s33 + s605
+  s607 :: SWord8 = if s597 then s606 else s605
+  s608 :: SWord8 = if s76 then s601 else s607
+  s609 :: SWord8 = if s26 then s596 else s608
+  s610 :: SWord8 = s33 + s609
+  s611 :: SWord8 = if s562 then s610 else s609
+  s612 :: SBool = s97 == s555
+  s613 :: SBool = s100 == s555
+  s614 :: SWord8 = if s613 then s610 else s609
+  s615 :: SWord8 = s33 + s614
+  s616 :: SWord8 = if s612 then s615 else s614
+  s617 :: SBool = s105 == s555
+  s618 :: SWord8 = if s617 then s610 else s609
+  s619 :: SWord8 = s33 + s618
+  s620 :: SWord8 = if s613 then s619 else s618
+  s621 :: SWord8 = s33 + s620
+  s622 :: SWord8 = if s612 then s621 else s620
+  s623 :: SWord8 = if s96 then s616 else s622
+  s624 :: SWord8 = if s24 then s611 else s623
+  s625 :: SWord8 = s33 + s624
+  s626 :: SWord8 = if s561 then s625 else s624
+  s627 :: SBool = s117 == s555
+  s628 :: SBool = s120 == s555
+  s629 :: SWord8 = if s628 then s625 else s624
+  s630 :: SWord8 = s33 + s629
+  s631 :: SWord8 = if s627 then s630 else s629
+  s632 :: SBool = s125 == s555
+  s633 :: SWord8 = if s632 then s625 else s624
+  s634 :: SWord8 = s33 + s633
+  s635 :: SWord8 = if s628 then s634 else s633
+  s636 :: SWord8 = s33 + s635
+  s637 :: SWord8 = if s627 then s636 else s635
+  s638 :: SWord8 = if s116 then s631 else s637
+  s639 :: SWord8 = if s22 then s626 else s638
+  s640 :: SWord8 = s33 + s639
+  s641 :: SWord8 = if s560 then s640 else s639
+  s642 :: SBool = s137 == s555
+  s643 :: SBool = s140 == s555
+  s644 :: SWord8 = if s643 then s640 else s639
+  s645 :: SWord8 = s33 + s644
+  s646 :: SWord8 = if s642 then s645 else s644
+  s647 :: SBool = s145 == s555
+  s648 :: SWord8 = if s647 then s640 else s639
+  s649 :: SWord8 = s33 + s648
+  s650 :: SWord8 = if s643 then s649 else s648
+  s651 :: SWord8 = s33 + s650
+  s652 :: SWord8 = if s642 then s651 else s650
+  s653 :: SWord8 = if s136 then s646 else s652
+  s654 :: SWord8 = if s20 then s641 else s653
+  s655 :: SWord8 = s33 + s654
+  s656 :: SWord8 = if s559 then s655 else s654
+  s657 :: SBool = s157 == s555
+  s658 :: SBool = s160 == s555
+  s659 :: SWord8 = if s658 then s655 else s654
+  s660 :: SWord8 = s33 + s659
+  s661 :: SWord8 = if s657 then s660 else s659
+  s662 :: SBool = s165 == s555
+  s663 :: SWord8 = if s662 then s655 else s654
+  s664 :: SWord8 = s33 + s663
+  s665 :: SWord8 = if s658 then s664 else s663
+  s666 :: SWord8 = s33 + s665
+  s667 :: SWord8 = if s657 then s666 else s665
+  s668 :: SWord8 = if s156 then s661 else s667
+  s669 :: SWord8 = if s18 then s656 else s668
+  s670 :: SWord8 = s33 + s669
+  s671 :: SWord8 = if s558 then s670 else s669
+  s672 :: SBool = s177 == s555
+  s673 :: SBool = s180 == s555
+  s674 :: SWord8 = if s673 then s670 else s669
+  s675 :: SWord8 = s33 + s674
+  s676 :: SWord8 = if s672 then s675 else s674
+  s677 :: SBool = s185 == s555
+  s678 :: SWord8 = if s677 then s670 else s669
+  s679 :: SWord8 = s33 + s678
+  s680 :: SWord8 = if s673 then s679 else s678
+  s681 :: SWord8 = s33 + s680
+  s682 :: SWord8 = if s672 then s681 else s680
+  s683 :: SWord8 = if s176 then s676 else s682
+  s684 :: SWord8 = if s16 then s671 else s683
+  s685 :: SWord8 = s33 + s684
+  s686 :: SWord8 = if s557 then s685 else s684
+  s687 :: SBool = s197 == s555
+  s688 :: SBool = s200 == s555
+  s689 :: SWord8 = if s688 then s685 else s684
+  s690 :: SWord8 = s33 + s689
+  s691 :: SWord8 = if s687 then s690 else s689
+  s692 :: SBool = s205 == s555
+  s693 :: SWord8 = if s692 then s685 else s684
+  s694 :: SWord8 = s33 + s693
+  s695 :: SWord8 = if s688 then s694 else s693
+  s696 :: SWord8 = s33 + s695
+  s697 :: SWord8 = if s687 then s696 else s695
+  s698 :: SWord8 = if s196 then s691 else s697
+  s699 :: SWord8 = if s14 then s686 else s698
+  s700 :: SWord8 = s33 + s699
+  s701 :: SWord8 = if s556 then s700 else s699
+  s702 :: SBool = s217 == s555
+  s703 :: SBool = s220 == s555
+  s704 :: SWord8 = if s703 then s700 else s699
+  s705 :: SWord8 = s33 + s704
+  s706 :: SWord8 = if s702 then s705 else s704
+  s707 :: SBool = s225 == s555
+  s708 :: SWord8 = if s707 then s700 else s699
+  s709 :: SWord8 = s33 + s708
+  s710 :: SWord8 = if s703 then s709 else s708
+  s711 :: SWord8 = s33 + s710
+  s712 :: SWord8 = if s702 then s711 else s710
+  s713 :: SWord8 = if s216 then s706 else s712
+  s714 :: SWord8 = if s11 then s701 else s713
+  s715 :: SBool = s3 == s714
+  s717 :: SBool = s9 == s716
+  s718 :: SBool = s8 == s716
+  s719 :: SBool = s7 == s716
+  s720 :: SBool = s6 == s716
+  s721 :: SBool = s5 == s716
+  s722 :: SBool = s4 == s716
+  s723 :: SBool = s3 == s716
+  s724 :: SBool = s2 == s716
+  s725 :: SBool = s1 == s716
+  s726 :: SBool = s0 == s716
+  s727 :: SWord8 = if s726 then s32 else s33
+  s728 :: SBool = s37 == s716
+  s729 :: SBool = s40 == s716
+  s730 :: SWord8 = if s729 then s32 else s33
+  s731 :: SWord8 = s33 + s730
+  s732 :: SWord8 = if s728 then s731 else s730
+  s733 :: SBool = s45 == s716
+  s734 :: SWord8 = if s733 then s32 else s33
+  s735 :: SWord8 = s33 + s734
+  s736 :: SWord8 = if s729 then s735 else s734
+  s737 :: SWord8 = s33 + s736
+  s738 :: SWord8 = if s728 then s737 else s736
+  s739 :: SWord8 = if s36 then s732 else s738
+  s740 :: SWord8 = if s30 then s727 else s739
+  s741 :: SWord8 = s33 + s740
+  s742 :: SWord8 = if s725 then s741 else s740
+  s743 :: SBool = s57 == s716
+  s744 :: SBool = s60 == s716
+  s745 :: SWord8 = if s744 then s741 else s740
+  s746 :: SWord8 = s33 + s745
+  s747 :: SWord8 = if s743 then s746 else s745
+  s748 :: SBool = s65 == s716
+  s749 :: SWord8 = if s748 then s741 else s740
+  s750 :: SWord8 = s33 + s749
+  s751 :: SWord8 = if s744 then s750 else s749
+  s752 :: SWord8 = s33 + s751
+  s753 :: SWord8 = if s743 then s752 else s751
+  s754 :: SWord8 = if s56 then s747 else s753
+  s755 :: SWord8 = if s28 then s742 else s754
+  s756 :: SWord8 = s33 + s755
+  s757 :: SWord8 = if s724 then s756 else s755
+  s758 :: SBool = s77 == s716
+  s759 :: SBool = s80 == s716
+  s760 :: SWord8 = if s759 then s756 else s755
+  s761 :: SWord8 = s33 + s760
+  s762 :: SWord8 = if s758 then s761 else s760
+  s763 :: SBool = s85 == s716
+  s764 :: SWord8 = if s763 then s756 else s755
+  s765 :: SWord8 = s33 + s764
+  s766 :: SWord8 = if s759 then s765 else s764
+  s767 :: SWord8 = s33 + s766
+  s768 :: SWord8 = if s758 then s767 else s766
+  s769 :: SWord8 = if s76 then s762 else s768
+  s770 :: SWord8 = if s26 then s757 else s769
+  s771 :: SWord8 = s33 + s770
+  s772 :: SWord8 = if s723 then s771 else s770
+  s773 :: SBool = s97 == s716
+  s774 :: SBool = s100 == s716
+  s775 :: SWord8 = if s774 then s771 else s770
+  s776 :: SWord8 = s33 + s775
+  s777 :: SWord8 = if s773 then s776 else s775
+  s778 :: SBool = s105 == s716
+  s779 :: SWord8 = if s778 then s771 else s770
+  s780 :: SWord8 = s33 + s779
+  s781 :: SWord8 = if s774 then s780 else s779
+  s782 :: SWord8 = s33 + s781
+  s783 :: SWord8 = if s773 then s782 else s781
+  s784 :: SWord8 = if s96 then s777 else s783
+  s785 :: SWord8 = if s24 then s772 else s784
+  s786 :: SWord8 = s33 + s785
+  s787 :: SWord8 = if s722 then s786 else s785
+  s788 :: SBool = s117 == s716
+  s789 :: SBool = s120 == s716
+  s790 :: SWord8 = if s789 then s786 else s785
+  s791 :: SWord8 = s33 + s790
+  s792 :: SWord8 = if s788 then s791 else s790
+  s793 :: SBool = s125 == s716
+  s794 :: SWord8 = if s793 then s786 else s785
+  s795 :: SWord8 = s33 + s794
+  s796 :: SWord8 = if s789 then s795 else s794
+  s797 :: SWord8 = s33 + s796
+  s798 :: SWord8 = if s788 then s797 else s796
+  s799 :: SWord8 = if s116 then s792 else s798
+  s800 :: SWord8 = if s22 then s787 else s799
+  s801 :: SWord8 = s33 + s800
+  s802 :: SWord8 = if s721 then s801 else s800
+  s803 :: SBool = s137 == s716
+  s804 :: SBool = s140 == s716
+  s805 :: SWord8 = if s804 then s801 else s800
+  s806 :: SWord8 = s33 + s805
+  s807 :: SWord8 = if s803 then s806 else s805
+  s808 :: SBool = s145 == s716
+  s809 :: SWord8 = if s808 then s801 else s800
+  s810 :: SWord8 = s33 + s809
+  s811 :: SWord8 = if s804 then s810 else s809
+  s812 :: SWord8 = s33 + s811
+  s813 :: SWord8 = if s803 then s812 else s811
+  s814 :: SWord8 = if s136 then s807 else s813
+  s815 :: SWord8 = if s20 then s802 else s814
+  s816 :: SWord8 = s33 + s815
+  s817 :: SWord8 = if s720 then s816 else s815
+  s818 :: SBool = s157 == s716
+  s819 :: SBool = s160 == s716
+  s820 :: SWord8 = if s819 then s816 else s815
+  s821 :: SWord8 = s33 + s820
+  s822 :: SWord8 = if s818 then s821 else s820
+  s823 :: SBool = s165 == s716
+  s824 :: SWord8 = if s823 then s816 else s815
+  s825 :: SWord8 = s33 + s824
+  s826 :: SWord8 = if s819 then s825 else s824
+  s827 :: SWord8 = s33 + s826
+  s828 :: SWord8 = if s818 then s827 else s826
+  s829 :: SWord8 = if s156 then s822 else s828
+  s830 :: SWord8 = if s18 then s817 else s829
+  s831 :: SWord8 = s33 + s830
+  s832 :: SWord8 = if s719 then s831 else s830
+  s833 :: SBool = s177 == s716
+  s834 :: SBool = s180 == s716
+  s835 :: SWord8 = if s834 then s831 else s830
+  s836 :: SWord8 = s33 + s835
+  s837 :: SWord8 = if s833 then s836 else s835
+  s838 :: SBool = s185 == s716
+  s839 :: SWord8 = if s838 then s831 else s830
+  s840 :: SWord8 = s33 + s839
+  s841 :: SWord8 = if s834 then s840 else s839
+  s842 :: SWord8 = s33 + s841
+  s843 :: SWord8 = if s833 then s842 else s841
+  s844 :: SWord8 = if s176 then s837 else s843
+  s845 :: SWord8 = if s16 then s832 else s844
+  s846 :: SWord8 = s33 + s845
+  s847 :: SWord8 = if s718 then s846 else s845
+  s848 :: SBool = s197 == s716
+  s849 :: SBool = s200 == s716
+  s850 :: SWord8 = if s849 then s846 else s845
+  s851 :: SWord8 = s33 + s850
+  s852 :: SWord8 = if s848 then s851 else s850
+  s853 :: SBool = s205 == s716
+  s854 :: SWord8 = if s853 then s846 else s845
+  s855 :: SWord8 = s33 + s854
+  s856 :: SWord8 = if s849 then s855 else s854
+  s857 :: SWord8 = s33 + s856
+  s858 :: SWord8 = if s848 then s857 else s856
+  s859 :: SWord8 = if s196 then s852 else s858
+  s860 :: SWord8 = if s14 then s847 else s859
+  s861 :: SWord8 = s33 + s860
+  s862 :: SWord8 = if s717 then s861 else s860
+  s863 :: SBool = s217 == s716
+  s864 :: SBool = s220 == s716
+  s865 :: SWord8 = if s864 then s861 else s860
+  s866 :: SWord8 = s33 + s865
+  s867 :: SWord8 = if s863 then s866 else s865
+  s868 :: SBool = s225 == s716
+  s869 :: SWord8 = if s868 then s861 else s860
+  s870 :: SWord8 = s33 + s869
+  s871 :: SWord8 = if s864 then s870 else s869
+  s872 :: SWord8 = s33 + s871
+  s873 :: SWord8 = if s863 then s872 else s871
+  s874 :: SWord8 = if s216 then s867 else s873
+  s875 :: SWord8 = if s11 then s862 else s874
+  s876 :: SBool = s4 == s875
+  s878 :: SBool = s9 == s877
+  s879 :: SBool = s8 == s877
+  s880 :: SBool = s7 == s877
+  s881 :: SBool = s6 == s877
+  s882 :: SBool = s5 == s877
+  s883 :: SBool = s4 == s877
+  s884 :: SBool = s3 == s877
+  s885 :: SBool = s2 == s877
+  s886 :: SBool = s1 == s877
+  s887 :: SBool = s0 == s877
+  s888 :: SWord8 = if s887 then s32 else s33
+  s889 :: SBool = s37 == s877
+  s890 :: SBool = s40 == s877
+  s891 :: SWord8 = if s890 then s32 else s33
+  s892 :: SWord8 = s33 + s891
+  s893 :: SWord8 = if s889 then s892 else s891
+  s894 :: SBool = s45 == s877
+  s895 :: SWord8 = if s894 then s32 else s33
+  s896 :: SWord8 = s33 + s895
+  s897 :: SWord8 = if s890 then s896 else s895
+  s898 :: SWord8 = s33 + s897
+  s899 :: SWord8 = if s889 then s898 else s897
+  s900 :: SWord8 = if s36 then s893 else s899
+  s901 :: SWord8 = if s30 then s888 else s900
+  s902 :: SWord8 = s33 + s901
+  s903 :: SWord8 = if s886 then s902 else s901
+  s904 :: SBool = s57 == s877
+  s905 :: SBool = s60 == s877
+  s906 :: SWord8 = if s905 then s902 else s901
+  s907 :: SWord8 = s33 + s906
+  s908 :: SWord8 = if s904 then s907 else s906
+  s909 :: SBool = s65 == s877
+  s910 :: SWord8 = if s909 then s902 else s901
+  s911 :: SWord8 = s33 + s910
+  s912 :: SWord8 = if s905 then s911 else s910
+  s913 :: SWord8 = s33 + s912
+  s914 :: SWord8 = if s904 then s913 else s912
+  s915 :: SWord8 = if s56 then s908 else s914
+  s916 :: SWord8 = if s28 then s903 else s915
+  s917 :: SWord8 = s33 + s916
+  s918 :: SWord8 = if s885 then s917 else s916
+  s919 :: SBool = s77 == s877
+  s920 :: SBool = s80 == s877
+  s921 :: SWord8 = if s920 then s917 else s916
+  s922 :: SWord8 = s33 + s921
+  s923 :: SWord8 = if s919 then s922 else s921
+  s924 :: SBool = s85 == s877
+  s925 :: SWord8 = if s924 then s917 else s916
+  s926 :: SWord8 = s33 + s925
+  s927 :: SWord8 = if s920 then s926 else s925
+  s928 :: SWord8 = s33 + s927
+  s929 :: SWord8 = if s919 then s928 else s927
+  s930 :: SWord8 = if s76 then s923 else s929
+  s931 :: SWord8 = if s26 then s918 else s930
+  s932 :: SWord8 = s33 + s931
+  s933 :: SWord8 = if s884 then s932 else s931
+  s934 :: SBool = s97 == s877
+  s935 :: SBool = s100 == s877
+  s936 :: SWord8 = if s935 then s932 else s931
+  s937 :: SWord8 = s33 + s936
+  s938 :: SWord8 = if s934 then s937 else s936
+  s939 :: SBool = s105 == s877
+  s940 :: SWord8 = if s939 then s932 else s931
+  s941 :: SWord8 = s33 + s940
+  s942 :: SWord8 = if s935 then s941 else s940
+  s943 :: SWord8 = s33 + s942
+  s944 :: SWord8 = if s934 then s943 else s942
+  s945 :: SWord8 = if s96 then s938 else s944
+  s946 :: SWord8 = if s24 then s933 else s945
+  s947 :: SWord8 = s33 + s946
+  s948 :: SWord8 = if s883 then s947 else s946
+  s949 :: SBool = s117 == s877
+  s950 :: SBool = s120 == s877
+  s951 :: SWord8 = if s950 then s947 else s946
+  s952 :: SWord8 = s33 + s951
+  s953 :: SWord8 = if s949 then s952 else s951
+  s954 :: SBool = s125 == s877
+  s955 :: SWord8 = if s954 then s947 else s946
+  s956 :: SWord8 = s33 + s955
+  s957 :: SWord8 = if s950 then s956 else s955
+  s958 :: SWord8 = s33 + s957
+  s959 :: SWord8 = if s949 then s958 else s957
+  s960 :: SWord8 = if s116 then s953 else s959
+  s961 :: SWord8 = if s22 then s948 else s960
+  s962 :: SWord8 = s33 + s961
+  s963 :: SWord8 = if s882 then s962 else s961
+  s964 :: SBool = s137 == s877
+  s965 :: SBool = s140 == s877
+  s966 :: SWord8 = if s965 then s962 else s961
+  s967 :: SWord8 = s33 + s966
+  s968 :: SWord8 = if s964 then s967 else s966
+  s969 :: SBool = s145 == s877
+  s970 :: SWord8 = if s969 then s962 else s961
+  s971 :: SWord8 = s33 + s970
+  s972 :: SWord8 = if s965 then s971 else s970
+  s973 :: SWord8 = s33 + s972
+  s974 :: SWord8 = if s964 then s973 else s972
+  s975 :: SWord8 = if s136 then s968 else s974
+  s976 :: SWord8 = if s20 then s963 else s975
+  s977 :: SWord8 = s33 + s976
+  s978 :: SWord8 = if s881 then s977 else s976
+  s979 :: SBool = s157 == s877
+  s980 :: SBool = s160 == s877
+  s981 :: SWord8 = if s980 then s977 else s976
+  s982 :: SWord8 = s33 + s981
+  s983 :: SWord8 = if s979 then s982 else s981
+  s984 :: SBool = s165 == s877
+  s985 :: SWord8 = if s984 then s977 else s976
+  s986 :: SWord8 = s33 + s985
+  s987 :: SWord8 = if s980 then s986 else s985
+  s988 :: SWord8 = s33 + s987
+  s989 :: SWord8 = if s979 then s988 else s987
+  s990 :: SWord8 = if s156 then s983 else s989
+  s991 :: SWord8 = if s18 then s978 else s990
+  s992 :: SWord8 = s33 + s991
+  s993 :: SWord8 = if s880 then s992 else s991
+  s994 :: SBool = s177 == s877
+  s995 :: SBool = s180 == s877
+  s996 :: SWord8 = if s995 then s992 else s991
+  s997 :: SWord8 = s33 + s996
+  s998 :: SWord8 = if s994 then s997 else s996
+  s999 :: SBool = s185 == s877
+  s1000 :: SWord8 = if s999 then s992 else s991
+  s1001 :: SWord8 = s33 + s1000
+  s1002 :: SWord8 = if s995 then s1001 else s1000
+  s1003 :: SWord8 = s33 + s1002
+  s1004 :: SWord8 = if s994 then s1003 else s1002
+  s1005 :: SWord8 = if s176 then s998 else s1004
+  s1006 :: SWord8 = if s16 then s993 else s1005
+  s1007 :: SWord8 = s33 + s1006
+  s1008 :: SWord8 = if s879 then s1007 else s1006
+  s1009 :: SBool = s197 == s877
+  s1010 :: SBool = s200 == s877
+  s1011 :: SWord8 = if s1010 then s1007 else s1006
+  s1012 :: SWord8 = s33 + s1011
+  s1013 :: SWord8 = if s1009 then s1012 else s1011
+  s1014 :: SBool = s205 == s877
+  s1015 :: SWord8 = if s1014 then s1007 else s1006
+  s1016 :: SWord8 = s33 + s1015
+  s1017 :: SWord8 = if s1010 then s1016 else s1015
+  s1018 :: SWord8 = s33 + s1017
+  s1019 :: SWord8 = if s1009 then s1018 else s1017
+  s1020 :: SWord8 = if s196 then s1013 else s1019
+  s1021 :: SWord8 = if s14 then s1008 else s1020
+  s1022 :: SWord8 = s33 + s1021
+  s1023 :: SWord8 = if s878 then s1022 else s1021
+  s1024 :: SBool = s217 == s877
+  s1025 :: SBool = s220 == s877
+  s1026 :: SWord8 = if s1025 then s1022 else s1021
+  s1027 :: SWord8 = s33 + s1026
+  s1028 :: SWord8 = if s1024 then s1027 else s1026
+  s1029 :: SBool = s225 == s877
+  s1030 :: SWord8 = if s1029 then s1022 else s1021
+  s1031 :: SWord8 = s33 + s1030
+  s1032 :: SWord8 = if s1025 then s1031 else s1030
+  s1033 :: SWord8 = s33 + s1032
+  s1034 :: SWord8 = if s1024 then s1033 else s1032
+  s1035 :: SWord8 = if s216 then s1028 else s1034
+  s1036 :: SWord8 = if s11 then s1023 else s1035
+  s1037 :: SBool = s5 == s1036
+  s1039 :: SBool = s9 == s1038
+  s1040 :: SBool = s8 == s1038
+  s1041 :: SBool = s7 == s1038
+  s1042 :: SBool = s6 == s1038
+  s1043 :: SBool = s5 == s1038
+  s1044 :: SBool = s4 == s1038
+  s1045 :: SBool = s3 == s1038
+  s1046 :: SBool = s2 == s1038
+  s1047 :: SBool = s1 == s1038
+  s1048 :: SBool = s0 == s1038
+  s1049 :: SWord8 = if s1048 then s32 else s33
+  s1050 :: SBool = s37 == s1038
+  s1051 :: SBool = s40 == s1038
+  s1052 :: SWord8 = if s1051 then s32 else s33
+  s1053 :: SWord8 = s33 + s1052
+  s1054 :: SWord8 = if s1050 then s1053 else s1052
+  s1055 :: SBool = s45 == s1038
+  s1056 :: SWord8 = if s1055 then s32 else s33
+  s1057 :: SWord8 = s33 + s1056
+  s1058 :: SWord8 = if s1051 then s1057 else s1056
+  s1059 :: SWord8 = s33 + s1058
+  s1060 :: SWord8 = if s1050 then s1059 else s1058
+  s1061 :: SWord8 = if s36 then s1054 else s1060
+  s1062 :: SWord8 = if s30 then s1049 else s1061
+  s1063 :: SWord8 = s33 + s1062
+  s1064 :: SWord8 = if s1047 then s1063 else s1062
+  s1065 :: SBool = s57 == s1038
+  s1066 :: SBool = s60 == s1038
+  s1067 :: SWord8 = if s1066 then s1063 else s1062
+  s1068 :: SWord8 = s33 + s1067
+  s1069 :: SWord8 = if s1065 then s1068 else s1067
+  s1070 :: SBool = s65 == s1038
+  s1071 :: SWord8 = if s1070 then s1063 else s1062
+  s1072 :: SWord8 = s33 + s1071
+  s1073 :: SWord8 = if s1066 then s1072 else s1071
+  s1074 :: SWord8 = s33 + s1073
+  s1075 :: SWord8 = if s1065 then s1074 else s1073
+  s1076 :: SWord8 = if s56 then s1069 else s1075
+  s1077 :: SWord8 = if s28 then s1064 else s1076
+  s1078 :: SWord8 = s33 + s1077
+  s1079 :: SWord8 = if s1046 then s1078 else s1077
+  s1080 :: SBool = s77 == s1038
+  s1081 :: SBool = s80 == s1038
+  s1082 :: SWord8 = if s1081 then s1078 else s1077
+  s1083 :: SWord8 = s33 + s1082
+  s1084 :: SWord8 = if s1080 then s1083 else s1082
+  s1085 :: SBool = s85 == s1038
+  s1086 :: SWord8 = if s1085 then s1078 else s1077
+  s1087 :: SWord8 = s33 + s1086
+  s1088 :: SWord8 = if s1081 then s1087 else s1086
+  s1089 :: SWord8 = s33 + s1088
+  s1090 :: SWord8 = if s1080 then s1089 else s1088
+  s1091 :: SWord8 = if s76 then s1084 else s1090
+  s1092 :: SWord8 = if s26 then s1079 else s1091
+  s1093 :: SWord8 = s33 + s1092
+  s1094 :: SWord8 = if s1045 then s1093 else s1092
+  s1095 :: SBool = s97 == s1038
+  s1096 :: SBool = s100 == s1038
+  s1097 :: SWord8 = if s1096 then s1093 else s1092
+  s1098 :: SWord8 = s33 + s1097
+  s1099 :: SWord8 = if s1095 then s1098 else s1097
+  s1100 :: SBool = s105 == s1038
+  s1101 :: SWord8 = if s1100 then s1093 else s1092
+  s1102 :: SWord8 = s33 + s1101
+  s1103 :: SWord8 = if s1096 then s1102 else s1101
+  s1104 :: SWord8 = s33 + s1103
+  s1105 :: SWord8 = if s1095 then s1104 else s1103
+  s1106 :: SWord8 = if s96 then s1099 else s1105
+  s1107 :: SWord8 = if s24 then s1094 else s1106
+  s1108 :: SWord8 = s33 + s1107
+  s1109 :: SWord8 = if s1044 then s1108 else s1107
+  s1110 :: SBool = s117 == s1038
+  s1111 :: SBool = s120 == s1038
+  s1112 :: SWord8 = if s1111 then s1108 else s1107
+  s1113 :: SWord8 = s33 + s1112
+  s1114 :: SWord8 = if s1110 then s1113 else s1112
+  s1115 :: SBool = s125 == s1038
+  s1116 :: SWord8 = if s1115 then s1108 else s1107
+  s1117 :: SWord8 = s33 + s1116
+  s1118 :: SWord8 = if s1111 then s1117 else s1116
+  s1119 :: SWord8 = s33 + s1118
+  s1120 :: SWord8 = if s1110 then s1119 else s1118
+  s1121 :: SWord8 = if s116 then s1114 else s1120
+  s1122 :: SWord8 = if s22 then s1109 else s1121
+  s1123 :: SWord8 = s33 + s1122
+  s1124 :: SWord8 = if s1043 then s1123 else s1122
+  s1125 :: SBool = s137 == s1038
+  s1126 :: SBool = s140 == s1038
+  s1127 :: SWord8 = if s1126 then s1123 else s1122
+  s1128 :: SWord8 = s33 + s1127
+  s1129 :: SWord8 = if s1125 then s1128 else s1127
+  s1130 :: SBool = s145 == s1038
+  s1131 :: SWord8 = if s1130 then s1123 else s1122
+  s1132 :: SWord8 = s33 + s1131
+  s1133 :: SWord8 = if s1126 then s1132 else s1131
+  s1134 :: SWord8 = s33 + s1133
+  s1135 :: SWord8 = if s1125 then s1134 else s1133
+  s1136 :: SWord8 = if s136 then s1129 else s1135
+  s1137 :: SWord8 = if s20 then s1124 else s1136
+  s1138 :: SWord8 = s33 + s1137
+  s1139 :: SWord8 = if s1042 then s1138 else s1137
+  s1140 :: SBool = s157 == s1038
+  s1141 :: SBool = s160 == s1038
+  s1142 :: SWord8 = if s1141 then s1138 else s1137
+  s1143 :: SWord8 = s33 + s1142
+  s1144 :: SWord8 = if s1140 then s1143 else s1142
+  s1145 :: SBool = s165 == s1038
+  s1146 :: SWord8 = if s1145 then s1138 else s1137
+  s1147 :: SWord8 = s33 + s1146
+  s1148 :: SWord8 = if s1141 then s1147 else s1146
+  s1149 :: SWord8 = s33 + s1148
+  s1150 :: SWord8 = if s1140 then s1149 else s1148
+  s1151 :: SWord8 = if s156 then s1144 else s1150
+  s1152 :: SWord8 = if s18 then s1139 else s1151
+  s1153 :: SWord8 = s33 + s1152
+  s1154 :: SWord8 = if s1041 then s1153 else s1152
+  s1155 :: SBool = s177 == s1038
+  s1156 :: SBool = s180 == s1038
+  s1157 :: SWord8 = if s1156 then s1153 else s1152
+  s1158 :: SWord8 = s33 + s1157
+  s1159 :: SWord8 = if s1155 then s1158 else s1157
+  s1160 :: SBool = s185 == s1038
+  s1161 :: SWord8 = if s1160 then s1153 else s1152
+  s1162 :: SWord8 = s33 + s1161
+  s1163 :: SWord8 = if s1156 then s1162 else s1161
+  s1164 :: SWord8 = s33 + s1163
+  s1165 :: SWord8 = if s1155 then s1164 else s1163
+  s1166 :: SWord8 = if s176 then s1159 else s1165
+  s1167 :: SWord8 = if s16 then s1154 else s1166
+  s1168 :: SWord8 = s33 + s1167
+  s1169 :: SWord8 = if s1040 then s1168 else s1167
+  s1170 :: SBool = s197 == s1038
+  s1171 :: SBool = s200 == s1038
+  s1172 :: SWord8 = if s1171 then s1168 else s1167
+  s1173 :: SWord8 = s33 + s1172
+  s1174 :: SWord8 = if s1170 then s1173 else s1172
+  s1175 :: SBool = s205 == s1038
+  s1176 :: SWord8 = if s1175 then s1168 else s1167
+  s1177 :: SWord8 = s33 + s1176
+  s1178 :: SWord8 = if s1171 then s1177 else s1176
+  s1179 :: SWord8 = s33 + s1178
+  s1180 :: SWord8 = if s1170 then s1179 else s1178
+  s1181 :: SWord8 = if s196 then s1174 else s1180
+  s1182 :: SWord8 = if s14 then s1169 else s1181
+  s1183 :: SWord8 = s33 + s1182
+  s1184 :: SWord8 = if s1039 then s1183 else s1182
+  s1185 :: SBool = s217 == s1038
+  s1186 :: SBool = s220 == s1038
+  s1187 :: SWord8 = if s1186 then s1183 else s1182
+  s1188 :: SWord8 = s33 + s1187
+  s1189 :: SWord8 = if s1185 then s1188 else s1187
+  s1190 :: SBool = s225 == s1038
+  s1191 :: SWord8 = if s1190 then s1183 else s1182
+  s1192 :: SWord8 = s33 + s1191
+  s1193 :: SWord8 = if s1186 then s1192 else s1191
+  s1194 :: SWord8 = s33 + s1193
+  s1195 :: SWord8 = if s1185 then s1194 else s1193
+  s1196 :: SWord8 = if s216 then s1189 else s1195
+  s1197 :: SWord8 = if s11 then s1184 else s1196
+  s1198 :: SBool = s6 == s1197
+  s1200 :: SBool = s9 == s1199
+  s1201 :: SBool = s8 == s1199
+  s1202 :: SBool = s7 == s1199
+  s1203 :: SBool = s6 == s1199
+  s1204 :: SBool = s5 == s1199
+  s1205 :: SBool = s4 == s1199
+  s1206 :: SBool = s3 == s1199
+  s1207 :: SBool = s2 == s1199
+  s1208 :: SBool = s1 == s1199
+  s1209 :: SBool = s0 == s1199
+  s1210 :: SWord8 = if s1209 then s32 else s33
+  s1211 :: SBool = s37 == s1199
+  s1212 :: SBool = s40 == s1199
+  s1213 :: SWord8 = if s1212 then s32 else s33
+  s1214 :: SWord8 = s33 + s1213
+  s1215 :: SWord8 = if s1211 then s1214 else s1213
+  s1216 :: SBool = s45 == s1199
+  s1217 :: SWord8 = if s1216 then s32 else s33
+  s1218 :: SWord8 = s33 + s1217
+  s1219 :: SWord8 = if s1212 then s1218 else s1217
+  s1220 :: SWord8 = s33 + s1219
+  s1221 :: SWord8 = if s1211 then s1220 else s1219
+  s1222 :: SWord8 = if s36 then s1215 else s1221
+  s1223 :: SWord8 = if s30 then s1210 else s1222
+  s1224 :: SWord8 = s33 + s1223
+  s1225 :: SWord8 = if s1208 then s1224 else s1223
+  s1226 :: SBool = s57 == s1199
+  s1227 :: SBool = s60 == s1199
+  s1228 :: SWord8 = if s1227 then s1224 else s1223
+  s1229 :: SWord8 = s33 + s1228
+  s1230 :: SWord8 = if s1226 then s1229 else s1228
+  s1231 :: SBool = s65 == s1199
+  s1232 :: SWord8 = if s1231 then s1224 else s1223
+  s1233 :: SWord8 = s33 + s1232
+  s1234 :: SWord8 = if s1227 then s1233 else s1232
+  s1235 :: SWord8 = s33 + s1234
+  s1236 :: SWord8 = if s1226 then s1235 else s1234
+  s1237 :: SWord8 = if s56 then s1230 else s1236
+  s1238 :: SWord8 = if s28 then s1225 else s1237
+  s1239 :: SWord8 = s33 + s1238
+  s1240 :: SWord8 = if s1207 then s1239 else s1238
+  s1241 :: SBool = s77 == s1199
+  s1242 :: SBool = s80 == s1199
+  s1243 :: SWord8 = if s1242 then s1239 else s1238
+  s1244 :: SWord8 = s33 + s1243
+  s1245 :: SWord8 = if s1241 then s1244 else s1243
+  s1246 :: SBool = s85 == s1199
+  s1247 :: SWord8 = if s1246 then s1239 else s1238
+  s1248 :: SWord8 = s33 + s1247
+  s1249 :: SWord8 = if s1242 then s1248 else s1247
+  s1250 :: SWord8 = s33 + s1249
+  s1251 :: SWord8 = if s1241 then s1250 else s1249
+  s1252 :: SWord8 = if s76 then s1245 else s1251
+  s1253 :: SWord8 = if s26 then s1240 else s1252
+  s1254 :: SWord8 = s33 + s1253
+  s1255 :: SWord8 = if s1206 then s1254 else s1253
+  s1256 :: SBool = s97 == s1199
+  s1257 :: SBool = s100 == s1199
+  s1258 :: SWord8 = if s1257 then s1254 else s1253
+  s1259 :: SWord8 = s33 + s1258
+  s1260 :: SWord8 = if s1256 then s1259 else s1258
+  s1261 :: SBool = s105 == s1199
+  s1262 :: SWord8 = if s1261 then s1254 else s1253
+  s1263 :: SWord8 = s33 + s1262
+  s1264 :: SWord8 = if s1257 then s1263 else s1262
+  s1265 :: SWord8 = s33 + s1264
+  s1266 :: SWord8 = if s1256 then s1265 else s1264
+  s1267 :: SWord8 = if s96 then s1260 else s1266
+  s1268 :: SWord8 = if s24 then s1255 else s1267
+  s1269 :: SWord8 = s33 + s1268
+  s1270 :: SWord8 = if s1205 then s1269 else s1268
+  s1271 :: SBool = s117 == s1199
+  s1272 :: SBool = s120 == s1199
+  s1273 :: SWord8 = if s1272 then s1269 else s1268
+  s1274 :: SWord8 = s33 + s1273
+  s1275 :: SWord8 = if s1271 then s1274 else s1273
+  s1276 :: SBool = s125 == s1199
+  s1277 :: SWord8 = if s1276 then s1269 else s1268
+  s1278 :: SWord8 = s33 + s1277
+  s1279 :: SWord8 = if s1272 then s1278 else s1277
+  s1280 :: SWord8 = s33 + s1279
+  s1281 :: SWord8 = if s1271 then s1280 else s1279
+  s1282 :: SWord8 = if s116 then s1275 else s1281
+  s1283 :: SWord8 = if s22 then s1270 else s1282
+  s1284 :: SWord8 = s33 + s1283
+  s1285 :: SWord8 = if s1204 then s1284 else s1283
+  s1286 :: SBool = s137 == s1199
+  s1287 :: SBool = s140 == s1199
+  s1288 :: SWord8 = if s1287 then s1284 else s1283
+  s1289 :: SWord8 = s33 + s1288
+  s1290 :: SWord8 = if s1286 then s1289 else s1288
+  s1291 :: SBool = s145 == s1199
+  s1292 :: SWord8 = if s1291 then s1284 else s1283
+  s1293 :: SWord8 = s33 + s1292
+  s1294 :: SWord8 = if s1287 then s1293 else s1292
+  s1295 :: SWord8 = s33 + s1294
+  s1296 :: SWord8 = if s1286 then s1295 else s1294
+  s1297 :: SWord8 = if s136 then s1290 else s1296
+  s1298 :: SWord8 = if s20 then s1285 else s1297
+  s1299 :: SWord8 = s33 + s1298
+  s1300 :: SWord8 = if s1203 then s1299 else s1298
+  s1301 :: SBool = s157 == s1199
+  s1302 :: SBool = s160 == s1199
+  s1303 :: SWord8 = if s1302 then s1299 else s1298
+  s1304 :: SWord8 = s33 + s1303
+  s1305 :: SWord8 = if s1301 then s1304 else s1303
+  s1306 :: SBool = s165 == s1199
+  s1307 :: SWord8 = if s1306 then s1299 else s1298
+  s1308 :: SWord8 = s33 + s1307
+  s1309 :: SWord8 = if s1302 then s1308 else s1307
+  s1310 :: SWord8 = s33 + s1309
+  s1311 :: SWord8 = if s1301 then s1310 else s1309
+  s1312 :: SWord8 = if s156 then s1305 else s1311
+  s1313 :: SWord8 = if s18 then s1300 else s1312
+  s1314 :: SWord8 = s33 + s1313
+  s1315 :: SWord8 = if s1202 then s1314 else s1313
+  s1316 :: SBool = s177 == s1199
+  s1317 :: SBool = s180 == s1199
+  s1318 :: SWord8 = if s1317 then s1314 else s1313
+  s1319 :: SWord8 = s33 + s1318
+  s1320 :: SWord8 = if s1316 then s1319 else s1318
+  s1321 :: SBool = s185 == s1199
+  s1322 :: SWord8 = if s1321 then s1314 else s1313
+  s1323 :: SWord8 = s33 + s1322
+  s1324 :: SWord8 = if s1317 then s1323 else s1322
+  s1325 :: SWord8 = s33 + s1324
+  s1326 :: SWord8 = if s1316 then s1325 else s1324
+  s1327 :: SWord8 = if s176 then s1320 else s1326
+  s1328 :: SWord8 = if s16 then s1315 else s1327
+  s1329 :: SWord8 = s33 + s1328
+  s1330 :: SWord8 = if s1201 then s1329 else s1328
+  s1331 :: SBool = s197 == s1199
+  s1332 :: SBool = s200 == s1199
+  s1333 :: SWord8 = if s1332 then s1329 else s1328
+  s1334 :: SWord8 = s33 + s1333
+  s1335 :: SWord8 = if s1331 then s1334 else s1333
+  s1336 :: SBool = s205 == s1199
+  s1337 :: SWord8 = if s1336 then s1329 else s1328
+  s1338 :: SWord8 = s33 + s1337
+  s1339 :: SWord8 = if s1332 then s1338 else s1337
+  s1340 :: SWord8 = s33 + s1339
+  s1341 :: SWord8 = if s1331 then s1340 else s1339
+  s1342 :: SWord8 = if s196 then s1335 else s1341
+  s1343 :: SWord8 = if s14 then s1330 else s1342
+  s1344 :: SWord8 = s33 + s1343
+  s1345 :: SWord8 = if s1200 then s1344 else s1343
+  s1346 :: SBool = s217 == s1199
+  s1347 :: SBool = s220 == s1199
+  s1348 :: SWord8 = if s1347 then s1344 else s1343
+  s1349 :: SWord8 = s33 + s1348
+  s1350 :: SWord8 = if s1346 then s1349 else s1348
+  s1351 :: SBool = s225 == s1199
+  s1352 :: SWord8 = if s1351 then s1344 else s1343
+  s1353 :: SWord8 = s33 + s1352
+  s1354 :: SWord8 = if s1347 then s1353 else s1352
+  s1355 :: SWord8 = s33 + s1354
+  s1356 :: SWord8 = if s1346 then s1355 else s1354
+  s1357 :: SWord8 = if s216 then s1350 else s1356
+  s1358 :: SWord8 = if s11 then s1345 else s1357
+  s1359 :: SBool = s7 == s1358
+  s1361 :: SBool = s9 == s1360
+  s1362 :: SBool = s8 == s1360
+  s1363 :: SBool = s7 == s1360
+  s1364 :: SBool = s6 == s1360
+  s1365 :: SBool = s5 == s1360
+  s1366 :: SBool = s4 == s1360
+  s1367 :: SBool = s3 == s1360
+  s1368 :: SBool = s2 == s1360
+  s1369 :: SBool = s1 == s1360
+  s1370 :: SBool = s0 == s1360
+  s1371 :: SWord8 = if s1370 then s32 else s33
+  s1372 :: SBool = s37 == s1360
+  s1373 :: SBool = s40 == s1360
+  s1374 :: SWord8 = if s1373 then s32 else s33
+  s1375 :: SWord8 = s33 + s1374
+  s1376 :: SWord8 = if s1372 then s1375 else s1374
+  s1377 :: SBool = s45 == s1360
+  s1378 :: SWord8 = if s1377 then s32 else s33
+  s1379 :: SWord8 = s33 + s1378
+  s1380 :: SWord8 = if s1373 then s1379 else s1378
+  s1381 :: SWord8 = s33 + s1380
+  s1382 :: SWord8 = if s1372 then s1381 else s1380
+  s1383 :: SWord8 = if s36 then s1376 else s1382
+  s1384 :: SWord8 = if s30 then s1371 else s1383
+  s1385 :: SWord8 = s33 + s1384
+  s1386 :: SWord8 = if s1369 then s1385 else s1384
+  s1387 :: SBool = s57 == s1360
+  s1388 :: SBool = s60 == s1360
+  s1389 :: SWord8 = if s1388 then s1385 else s1384
+  s1390 :: SWord8 = s33 + s1389
+  s1391 :: SWord8 = if s1387 then s1390 else s1389
+  s1392 :: SBool = s65 == s1360
+  s1393 :: SWord8 = if s1392 then s1385 else s1384
+  s1394 :: SWord8 = s33 + s1393
+  s1395 :: SWord8 = if s1388 then s1394 else s1393
+  s1396 :: SWord8 = s33 + s1395
+  s1397 :: SWord8 = if s1387 then s1396 else s1395
+  s1398 :: SWord8 = if s56 then s1391 else s1397
+  s1399 :: SWord8 = if s28 then s1386 else s1398
+  s1400 :: SWord8 = s33 + s1399
+  s1401 :: SWord8 = if s1368 then s1400 else s1399
+  s1402 :: SBool = s77 == s1360
+  s1403 :: SBool = s80 == s1360
+  s1404 :: SWord8 = if s1403 then s1400 else s1399
+  s1405 :: SWord8 = s33 + s1404
+  s1406 :: SWord8 = if s1402 then s1405 else s1404
+  s1407 :: SBool = s85 == s1360
+  s1408 :: SWord8 = if s1407 then s1400 else s1399
+  s1409 :: SWord8 = s33 + s1408
+  s1410 :: SWord8 = if s1403 then s1409 else s1408
+  s1411 :: SWord8 = s33 + s1410
+  s1412 :: SWord8 = if s1402 then s1411 else s1410
+  s1413 :: SWord8 = if s76 then s1406 else s1412
+  s1414 :: SWord8 = if s26 then s1401 else s1413
+  s1415 :: SWord8 = s33 + s1414
+  s1416 :: SWord8 = if s1367 then s1415 else s1414
+  s1417 :: SBool = s97 == s1360
+  s1418 :: SBool = s100 == s1360
+  s1419 :: SWord8 = if s1418 then s1415 else s1414
+  s1420 :: SWord8 = s33 + s1419
+  s1421 :: SWord8 = if s1417 then s1420 else s1419
+  s1422 :: SBool = s105 == s1360
+  s1423 :: SWord8 = if s1422 then s1415 else s1414
+  s1424 :: SWord8 = s33 + s1423
+  s1425 :: SWord8 = if s1418 then s1424 else s1423
+  s1426 :: SWord8 = s33 + s1425
+  s1427 :: SWord8 = if s1417 then s1426 else s1425
+  s1428 :: SWord8 = if s96 then s1421 else s1427
+  s1429 :: SWord8 = if s24 then s1416 else s1428
+  s1430 :: SWord8 = s33 + s1429
+  s1431 :: SWord8 = if s1366 then s1430 else s1429
+  s1432 :: SBool = s117 == s1360
+  s1433 :: SBool = s120 == s1360
+  s1434 :: SWord8 = if s1433 then s1430 else s1429
+  s1435 :: SWord8 = s33 + s1434
+  s1436 :: SWord8 = if s1432 then s1435 else s1434
+  s1437 :: SBool = s125 == s1360
+  s1438 :: SWord8 = if s1437 then s1430 else s1429
+  s1439 :: SWord8 = s33 + s1438
+  s1440 :: SWord8 = if s1433 then s1439 else s1438
+  s1441 :: SWord8 = s33 + s1440
+  s1442 :: SWord8 = if s1432 then s1441 else s1440
+  s1443 :: SWord8 = if s116 then s1436 else s1442
+  s1444 :: SWord8 = if s22 then s1431 else s1443
+  s1445 :: SWord8 = s33 + s1444
+  s1446 :: SWord8 = if s1365 then s1445 else s1444
+  s1447 :: SBool = s137 == s1360
+  s1448 :: SBool = s140 == s1360
+  s1449 :: SWord8 = if s1448 then s1445 else s1444
+  s1450 :: SWord8 = s33 + s1449
+  s1451 :: SWord8 = if s1447 then s1450 else s1449
+  s1452 :: SBool = s145 == s1360
+  s1453 :: SWord8 = if s1452 then s1445 else s1444
+  s1454 :: SWord8 = s33 + s1453
+  s1455 :: SWord8 = if s1448 then s1454 else s1453
+  s1456 :: SWord8 = s33 + s1455
+  s1457 :: SWord8 = if s1447 then s1456 else s1455
+  s1458 :: SWord8 = if s136 then s1451 else s1457
+  s1459 :: SWord8 = if s20 then s1446 else s1458
+  s1460 :: SWord8 = s33 + s1459
+  s1461 :: SWord8 = if s1364 then s1460 else s1459
+  s1462 :: SBool = s157 == s1360
+  s1463 :: SBool = s160 == s1360
+  s1464 :: SWord8 = if s1463 then s1460 else s1459
+  s1465 :: SWord8 = s33 + s1464
+  s1466 :: SWord8 = if s1462 then s1465 else s1464
+  s1467 :: SBool = s165 == s1360
+  s1468 :: SWord8 = if s1467 then s1460 else s1459
+  s1469 :: SWord8 = s33 + s1468
+  s1470 :: SWord8 = if s1463 then s1469 else s1468
+  s1471 :: SWord8 = s33 + s1470
+  s1472 :: SWord8 = if s1462 then s1471 else s1470
+  s1473 :: SWord8 = if s156 then s1466 else s1472
+  s1474 :: SWord8 = if s18 then s1461 else s1473
+  s1475 :: SWord8 = s33 + s1474
+  s1476 :: SWord8 = if s1363 then s1475 else s1474
+  s1477 :: SBool = s177 == s1360
+  s1478 :: SBool = s180 == s1360
+  s1479 :: SWord8 = if s1478 then s1475 else s1474
+  s1480 :: SWord8 = s33 + s1479
+  s1481 :: SWord8 = if s1477 then s1480 else s1479
+  s1482 :: SBool = s185 == s1360
+  s1483 :: SWord8 = if s1482 then s1475 else s1474
+  s1484 :: SWord8 = s33 + s1483
+  s1485 :: SWord8 = if s1478 then s1484 else s1483
+  s1486 :: SWord8 = s33 + s1485
+  s1487 :: SWord8 = if s1477 then s1486 else s1485
+  s1488 :: SWord8 = if s176 then s1481 else s1487
+  s1489 :: SWord8 = if s16 then s1476 else s1488
+  s1490 :: SWord8 = s33 + s1489
+  s1491 :: SWord8 = if s1362 then s1490 else s1489
+  s1492 :: SBool = s197 == s1360
+  s1493 :: SBool = s200 == s1360
+  s1494 :: SWord8 = if s1493 then s1490 else s1489
+  s1495 :: SWord8 = s33 + s1494
+  s1496 :: SWord8 = if s1492 then s1495 else s1494
+  s1497 :: SBool = s205 == s1360
+  s1498 :: SWord8 = if s1497 then s1490 else s1489
+  s1499 :: SWord8 = s33 + s1498
+  s1500 :: SWord8 = if s1493 then s1499 else s1498
+  s1501 :: SWord8 = s33 + s1500
+  s1502 :: SWord8 = if s1492 then s1501 else s1500
+  s1503 :: SWord8 = if s196 then s1496 else s1502
+  s1504 :: SWord8 = if s14 then s1491 else s1503
+  s1505 :: SWord8 = s33 + s1504
+  s1506 :: SWord8 = if s1361 then s1505 else s1504
+  s1507 :: SBool = s217 == s1360
+  s1508 :: SBool = s220 == s1360
+  s1509 :: SWord8 = if s1508 then s1505 else s1504
+  s1510 :: SWord8 = s33 + s1509
+  s1511 :: SWord8 = if s1507 then s1510 else s1509
+  s1512 :: SBool = s225 == s1360
+  s1513 :: SWord8 = if s1512 then s1505 else s1504
+  s1514 :: SWord8 = s33 + s1513
+  s1515 :: SWord8 = if s1508 then s1514 else s1513
+  s1516 :: SWord8 = s33 + s1515
+  s1517 :: SWord8 = if s1507 then s1516 else s1515
+  s1518 :: SWord8 = if s216 then s1511 else s1517
+  s1519 :: SWord8 = if s11 then s1506 else s1518
+  s1520 :: SBool = s8 == s1519
+  s1522 :: SBool = s9 == s1521
+  s1523 :: SBool = s8 == s1521
+  s1524 :: SBool = s7 == s1521
+  s1525 :: SBool = s6 == s1521
+  s1526 :: SBool = s5 == s1521
+  s1527 :: SBool = s4 == s1521
+  s1528 :: SBool = s3 == s1521
+  s1529 :: SBool = s2 == s1521
+  s1530 :: SBool = s1 == s1521
+  s1531 :: SBool = s0 == s1521
+  s1532 :: SWord8 = if s1531 then s32 else s33
+  s1533 :: SBool = s37 == s1521
+  s1534 :: SBool = s40 == s1521
+  s1535 :: SWord8 = if s1534 then s32 else s33
+  s1536 :: SWord8 = s33 + s1535
+  s1537 :: SWord8 = if s1533 then s1536 else s1535
+  s1538 :: SBool = s45 == s1521
+  s1539 :: SWord8 = if s1538 then s32 else s33
+  s1540 :: SWord8 = s33 + s1539
+  s1541 :: SWord8 = if s1534 then s1540 else s1539
+  s1542 :: SWord8 = s33 + s1541
+  s1543 :: SWord8 = if s1533 then s1542 else s1541
+  s1544 :: SWord8 = if s36 then s1537 else s1543
+  s1545 :: SWord8 = if s30 then s1532 else s1544
+  s1546 :: SWord8 = s33 + s1545
+  s1547 :: SWord8 = if s1530 then s1546 else s1545
+  s1548 :: SBool = s57 == s1521
+  s1549 :: SBool = s60 == s1521
+  s1550 :: SWord8 = if s1549 then s1546 else s1545
+  s1551 :: SWord8 = s33 + s1550
+  s1552 :: SWord8 = if s1548 then s1551 else s1550
+  s1553 :: SBool = s65 == s1521
+  s1554 :: SWord8 = if s1553 then s1546 else s1545
+  s1555 :: SWord8 = s33 + s1554
+  s1556 :: SWord8 = if s1549 then s1555 else s1554
+  s1557 :: SWord8 = s33 + s1556
+  s1558 :: SWord8 = if s1548 then s1557 else s1556
+  s1559 :: SWord8 = if s56 then s1552 else s1558
+  s1560 :: SWord8 = if s28 then s1547 else s1559
+  s1561 :: SWord8 = s33 + s1560
+  s1562 :: SWord8 = if s1529 then s1561 else s1560
+  s1563 :: SBool = s77 == s1521
+  s1564 :: SBool = s80 == s1521
+  s1565 :: SWord8 = if s1564 then s1561 else s1560
+  s1566 :: SWord8 = s33 + s1565
+  s1567 :: SWord8 = if s1563 then s1566 else s1565
+  s1568 :: SBool = s85 == s1521
+  s1569 :: SWord8 = if s1568 then s1561 else s1560
+  s1570 :: SWord8 = s33 + s1569
+  s1571 :: SWord8 = if s1564 then s1570 else s1569
+  s1572 :: SWord8 = s33 + s1571
+  s1573 :: SWord8 = if s1563 then s1572 else s1571
+  s1574 :: SWord8 = if s76 then s1567 else s1573
+  s1575 :: SWord8 = if s26 then s1562 else s1574
+  s1576 :: SWord8 = s33 + s1575
+  s1577 :: SWord8 = if s1528 then s1576 else s1575
+  s1578 :: SBool = s97 == s1521
+  s1579 :: SBool = s100 == s1521
+  s1580 :: SWord8 = if s1579 then s1576 else s1575
+  s1581 :: SWord8 = s33 + s1580
+  s1582 :: SWord8 = if s1578 then s1581 else s1580
+  s1583 :: SBool = s105 == s1521
+  s1584 :: SWord8 = if s1583 then s1576 else s1575
+  s1585 :: SWord8 = s33 + s1584
+  s1586 :: SWord8 = if s1579 then s1585 else s1584
+  s1587 :: SWord8 = s33 + s1586
+  s1588 :: SWord8 = if s1578 then s1587 else s1586
+  s1589 :: SWord8 = if s96 then s1582 else s1588
+  s1590 :: SWord8 = if s24 then s1577 else s1589
+  s1591 :: SWord8 = s33 + s1590
+  s1592 :: SWord8 = if s1527 then s1591 else s1590
+  s1593 :: SBool = s117 == s1521
+  s1594 :: SBool = s120 == s1521
+  s1595 :: SWord8 = if s1594 then s1591 else s1590
+  s1596 :: SWord8 = s33 + s1595
+  s1597 :: SWord8 = if s1593 then s1596 else s1595
+  s1598 :: SBool = s125 == s1521
+  s1599 :: SWord8 = if s1598 then s1591 else s1590
+  s1600 :: SWord8 = s33 + s1599
+  s1601 :: SWord8 = if s1594 then s1600 else s1599
+  s1602 :: SWord8 = s33 + s1601
+  s1603 :: SWord8 = if s1593 then s1602 else s1601
+  s1604 :: SWord8 = if s116 then s1597 else s1603
+  s1605 :: SWord8 = if s22 then s1592 else s1604
+  s1606 :: SWord8 = s33 + s1605
+  s1607 :: SWord8 = if s1526 then s1606 else s1605
+  s1608 :: SBool = s137 == s1521
+  s1609 :: SBool = s140 == s1521
+  s1610 :: SWord8 = if s1609 then s1606 else s1605
+  s1611 :: SWord8 = s33 + s1610
+  s1612 :: SWord8 = if s1608 then s1611 else s1610
+  s1613 :: SBool = s145 == s1521
+  s1614 :: SWord8 = if s1613 then s1606 else s1605
+  s1615 :: SWord8 = s33 + s1614
+  s1616 :: SWord8 = if s1609 then s1615 else s1614
+  s1617 :: SWord8 = s33 + s1616
+  s1618 :: SWord8 = if s1608 then s1617 else s1616
+  s1619 :: SWord8 = if s136 then s1612 else s1618
+  s1620 :: SWord8 = if s20 then s1607 else s1619
+  s1621 :: SWord8 = s33 + s1620
+  s1622 :: SWord8 = if s1525 then s1621 else s1620
+  s1623 :: SBool = s157 == s1521
+  s1624 :: SBool = s160 == s1521
+  s1625 :: SWord8 = if s1624 then s1621 else s1620
+  s1626 :: SWord8 = s33 + s1625
+  s1627 :: SWord8 = if s1623 then s1626 else s1625
+  s1628 :: SBool = s165 == s1521
+  s1629 :: SWord8 = if s1628 then s1621 else s1620
+  s1630 :: SWord8 = s33 + s1629
+  s1631 :: SWord8 = if s1624 then s1630 else s1629
+  s1632 :: SWord8 = s33 + s1631
+  s1633 :: SWord8 = if s1623 then s1632 else s1631
+  s1634 :: SWord8 = if s156 then s1627 else s1633
+  s1635 :: SWord8 = if s18 then s1622 else s1634
+  s1636 :: SWord8 = s33 + s1635
+  s1637 :: SWord8 = if s1524 then s1636 else s1635
+  s1638 :: SBool = s177 == s1521
+  s1639 :: SBool = s180 == s1521
+  s1640 :: SWord8 = if s1639 then s1636 else s1635
+  s1641 :: SWord8 = s33 + s1640
+  s1642 :: SWord8 = if s1638 then s1641 else s1640
+  s1643 :: SBool = s185 == s1521
+  s1644 :: SWord8 = if s1643 then s1636 else s1635
+  s1645 :: SWord8 = s33 + s1644
+  s1646 :: SWord8 = if s1639 then s1645 else s1644
+  s1647 :: SWord8 = s33 + s1646
+  s1648 :: SWord8 = if s1638 then s1647 else s1646
+  s1649 :: SWord8 = if s176 then s1642 else s1648
+  s1650 :: SWord8 = if s16 then s1637 else s1649
+  s1651 :: SWord8 = s33 + s1650
+  s1652 :: SWord8 = if s1523 then s1651 else s1650
+  s1653 :: SBool = s197 == s1521
+  s1654 :: SBool = s200 == s1521
+  s1655 :: SWord8 = if s1654 then s1651 else s1650
+  s1656 :: SWord8 = s33 + s1655
+  s1657 :: SWord8 = if s1653 then s1656 else s1655
+  s1658 :: SBool = s205 == s1521
+  s1659 :: SWord8 = if s1658 then s1651 else s1650
+  s1660 :: SWord8 = s33 + s1659
+  s1661 :: SWord8 = if s1654 then s1660 else s1659
+  s1662 :: SWord8 = s33 + s1661
+  s1663 :: SWord8 = if s1653 then s1662 else s1661
+  s1664 :: SWord8 = if s196 then s1657 else s1663
+  s1665 :: SWord8 = if s14 then s1652 else s1664
+  s1666 :: SWord8 = s33 + s1665
+  s1667 :: SWord8 = if s1522 then s1666 else s1665
+  s1668 :: SBool = s217 == s1521
+  s1669 :: SBool = s220 == s1521
+  s1670 :: SWord8 = if s1669 then s1666 else s1665
+  s1671 :: SWord8 = s33 + s1670
+  s1672 :: SWord8 = if s1668 then s1671 else s1670
+  s1673 :: SBool = s225 == s1521
+  s1674 :: SWord8 = if s1673 then s1666 else s1665
+  s1675 :: SWord8 = s33 + s1674
+  s1676 :: SWord8 = if s1669 then s1675 else s1674
+  s1677 :: SWord8 = s33 + s1676
+  s1678 :: SWord8 = if s1668 then s1677 else s1676
+  s1679 :: SWord8 = if s216 then s1672 else s1678
+  s1680 :: SWord8 = if s11 then s1667 else s1679
+  s1681 :: SBool = s9 == s1680
+  s1682 :: SBool = s1520 & s1681
+  s1683 :: SBool = s1359 & s1682
+  s1684 :: SBool = s1198 & s1683
+  s1685 :: SBool = s1037 & s1684
+  s1686 :: SBool = s876 & s1685
+  s1687 :: SBool = s715 & s1686
+  s1688 :: SBool = s554 & s1687
+  s1689 :: SBool = s394 & s1688
+  s1690 :: SBool = s234 & s1689
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s1690
diff --git a/SBVTestSuite/GoldFiles/crcUSB5_1.gold b/SBVTestSuite/GoldFiles/crcUSB5_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/crcUSB5_1.gold
@@ -0,0 +1,181 @@
+== BEGIN: "Makefile" ================
+# Makefile for crcUSB5. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: crcUSB5_driver
+
+crcUSB5.o: crcUSB5.c crcUSB5.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+crcUSB5_driver.o: crcUSB5_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+crcUSB5_driver: crcUSB5.o crcUSB5_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f crcUSB5_driver
+== END: "Makefile" ==================
+== BEGIN: "crcUSB5.h" ================
+/* Header file for crcUSB5. Automatically generated by SBV. Do not edit! */
+
+#ifndef __crcUSB5__HEADER_INCLUDED__
+#define __crcUSB5__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord16 crcUSB5(const SWord16 msg);
+
+#endif /* __crcUSB5__HEADER_INCLUDED__ */
+== END: "crcUSB5.h" ==================
+== BEGIN: "crcUSB5_driver.c" ================
+/* Example driver program for crcUSB5. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "crcUSB5.h"
+
+int main(void)
+{
+  const SWord16 __result = crcUSB5(0xfedcU);
+
+  printf("crcUSB5(0xfedcU) = 0x%04"PRIx16"U\n", __result);
+
+  return 0;
+}
+== END: "crcUSB5_driver.c" ==================
+== BEGIN: "crcUSB5.c" ================
+/* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
+
+#include "crcUSB5.h"
+
+SWord16 crcUSB5(const SWord16 msg)
+{
+  const SWord16 s0 = msg;
+  const SBool   s1 = (SBool) ((s0 >> 10) & 1);
+  const SBool   s3 = s1 != false;
+  const SBool   s4 = (SBool) ((s0 >> 9) & 1);
+  const SBool   s5 = false != s4;
+  const SBool   s6 = (SBool) ((s0 >> 8) & 1);
+  const SBool   s7 = false != s6;
+  const SBool   s8 = (SBool) ((s0 >> 7) & 1);
+  const SBool   s9 = false != s8;
+  const SBool   s10 = (SBool) ((s0 >> 6) & 1);
+  const SBool   s11 = false != s10;
+  const SBool   s12 = (SBool) ((s0 >> 5) & 1);
+  const SBool   s13 = false != s12;
+  const SBool   s14 = (SBool) ((s0 >> 4) & 1);
+  const SBool   s15 = false != s14;
+  const SBool   s16 = (SBool) ((s0 >> 3) & 1);
+  const SBool   s17 = false != s16;
+  const SBool   s18 = (SBool) ((s0 >> 2) & 1);
+  const SBool   s19 = false != s18;
+  const SBool   s20 = (SBool) ((s0 >> 1) & 1);
+  const SBool   s21 = false != s20;
+  const SBool   s22 = (SBool) (s0 & 1);
+  const SBool   s23 = false != s22;
+  const SBool   s24 = !s9;
+  const SBool   s25 = s3 ? s24 : s9;
+  const SBool   s26 = !s11;
+  const SBool   s27 = s5 ? s26 : s11;
+  const SBool   s28 = !s13;
+  const SBool   s29 = s3 ? s28 : s13;
+  const SBool   s30 = !s29;
+  const SBool   s31 = s7 ? s30 : s29;
+  const SBool   s32 = !s15;
+  const SBool   s33 = s5 ? s32 : s15;
+  const SBool   s34 = !s33;
+  const SBool   s35 = s25 ? s34 : s33;
+  const SBool   s36 = !s17;
+  const SBool   s37 = s7 ? s36 : s17;
+  const SBool   s38 = !s37;
+  const SBool   s39 = s27 ? s38 : s37;
+  const SBool   s40 = !s19;
+  const SBool   s41 = s25 ? s40 : s19;
+  const SBool   s42 = !s41;
+  const SBool   s43 = s31 ? s42 : s41;
+  const SBool   s44 = !s21;
+  const SBool   s45 = s27 ? s44 : s21;
+  const SBool   s46 = !s45;
+  const SBool   s47 = s35 ? s46 : s45;
+  const SBool   s48 = !s23;
+  const SBool   s49 = s31 ? s48 : s23;
+  const SBool   s50 = !s49;
+  const SBool   s51 = s39 ? s50 : s49;
+  const SBool   s52 = !s35;
+  const SBool   s53 = s43 ? s52 : s35;
+  const SBool   s54 = !s39;
+  const SBool   s55 = s47 ? s54 : s39;
+  const SBool   s56 = !s43;
+  const SBool   s57 = s51 ? s56 : s43;
+  const SWord16 s60 = s51 ? 0x0001U : 0x0000U;
+  const SWord16 s62 = s60 | 0x0002U;
+  const SWord16 s63 = s47 ? s62 : s60;
+  const SWord16 s65 = s63 | 0x0004U;
+  const SWord16 s66 = s57 ? s65 : s63;
+  const SWord16 s68 = s66 | 0x0008U;
+  const SWord16 s69 = s55 ? s68 : s66;
+  const SWord16 s71 = s69 | 0x0010U;
+  const SWord16 s72 = s53 ? s71 : s69;
+  const SWord16 s74 = s72 | 0x0020U;
+  const SWord16 s75 = s23 ? s74 : s72;
+  const SWord16 s77 = s75 | 0x0040U;
+  const SWord16 s78 = s21 ? s77 : s75;
+  const SWord16 s80 = s78 | 0x0080U;
+  const SWord16 s81 = s19 ? s80 : s78;
+  const SWord16 s83 = s81 | 0x0100U;
+  const SWord16 s84 = s17 ? s83 : s81;
+  const SWord16 s86 = s84 | 0x0200U;
+  const SWord16 s87 = s15 ? s86 : s84;
+  const SWord16 s89 = s87 | 0x0400U;
+  const SWord16 s90 = s13 ? s89 : s87;
+  const SWord16 s92 = s90 | 0x0800U;
+  const SWord16 s93 = s11 ? s92 : s90;
+  const SWord16 s95 = s93 | 0x1000U;
+  const SWord16 s96 = s9 ? s95 : s93;
+  const SWord16 s98 = s96 | 0x2000U;
+  const SWord16 s99 = s7 ? s98 : s96;
+  const SWord16 s101 = s99 | 0x4000U;
+  const SWord16 s102 = s5 ? s101 : s99;
+  const SWord16 s104 = s102 | 0x8000U;
+  const SWord16 s105 = s3 ? s104 : s102;
+
+  return s105;
+}
+== END: "crcUSB5.c" ==================
diff --git a/SBVTestSuite/GoldFiles/crcUSB5_2.gold b/SBVTestSuite/GoldFiles/crcUSB5_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/crcUSB5_2.gold
@@ -0,0 +1,225 @@
+== BEGIN: "Makefile" ================
+# Makefile for crcUSB5. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: crcUSB5_driver
+
+crcUSB5.o: crcUSB5.c crcUSB5.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+crcUSB5_driver.o: crcUSB5_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+crcUSB5_driver: crcUSB5.o crcUSB5_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f crcUSB5_driver
+== END: "Makefile" ==================
+== BEGIN: "crcUSB5.h" ================
+/* Header file for crcUSB5. Automatically generated by SBV. Do not edit! */
+
+#ifndef __crcUSB5__HEADER_INCLUDED__
+#define __crcUSB5__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord16 crcUSB5(const SWord16 msg);
+
+#endif /* __crcUSB5__HEADER_INCLUDED__ */
+== END: "crcUSB5.h" ==================
+== BEGIN: "crcUSB5_driver.c" ================
+/* Example driver program for crcUSB5. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "crcUSB5.h"
+
+int main(void)
+{
+  const SWord16 __result = crcUSB5(0xfedcU);
+
+  printf("crcUSB5(0xfedcU) = 0x%04"PRIx16"U\n", __result);
+
+  return 0;
+}
+== END: "crcUSB5_driver.c" ==================
+== BEGIN: "crcUSB5.c" ================
+/* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
+
+#include "crcUSB5.h"
+
+SWord16 crcUSB5(const SWord16 msg)
+{
+  const SWord16 s0 = msg;
+  const SWord16 s2 = s0 << 5;
+  const SBool   s3 = (SBool) ((s2 >> 15) & 1);
+  const SBool   s5 = s3 != false;
+  const SBool   s6 = (SBool) ((s2 >> 14) & 1);
+  const SBool   s7 = false != s6;
+  const SBool   s8 = (SBool) ((s2 >> 13) & 1);
+  const SBool   s9 = false != s8;
+  const SBool   s10 = (SBool) ((s2 >> 12) & 1);
+  const SBool   s11 = false != s10;
+  const SBool   s12 = !s11;
+  const SBool   s13 = s5 ? s12 : s11;
+  const SBool   s14 = (SBool) ((s2 >> 11) & 1);
+  const SBool   s15 = false != s14;
+  const SBool   s16 = !s15;
+  const SBool   s17 = s7 ? s16 : s15;
+  const SBool   s18 = (SBool) ((s2 >> 10) & 1);
+  const SBool   s19 = false != s18;
+  const SBool   s20 = !s19;
+  const SBool   s21 = s5 ? s20 : s19;
+  const SBool   s22 = !s21;
+  const SBool   s23 = s9 ? s22 : s21;
+  const SBool   s24 = (SBool) ((s2 >> 9) & 1);
+  const SBool   s25 = false != s24;
+  const SBool   s26 = !s25;
+  const SBool   s27 = s7 ? s26 : s25;
+  const SBool   s28 = !s27;
+  const SBool   s29 = s13 ? s28 : s27;
+  const SBool   s30 = (SBool) ((s2 >> 8) & 1);
+  const SBool   s31 = false != s30;
+  const SBool   s32 = !s31;
+  const SBool   s33 = s9 ? s32 : s31;
+  const SBool   s34 = !s33;
+  const SBool   s35 = s17 ? s34 : s33;
+  const SBool   s36 = (SBool) ((s2 >> 7) & 1);
+  const SBool   s37 = false != s36;
+  const SBool   s38 = !s37;
+  const SBool   s39 = s13 ? s38 : s37;
+  const SBool   s40 = !s39;
+  const SBool   s41 = s23 ? s40 : s39;
+  const SBool   s42 = (SBool) ((s2 >> 6) & 1);
+  const SBool   s43 = false != s42;
+  const SBool   s44 = !s43;
+  const SBool   s45 = s17 ? s44 : s43;
+  const SBool   s46 = !s45;
+  const SBool   s47 = s29 ? s46 : s45;
+  const SBool   s48 = (SBool) ((s2 >> 5) & 1);
+  const SBool   s49 = false != s48;
+  const SBool   s50 = !s49;
+  const SBool   s51 = s23 ? s50 : s49;
+  const SBool   s52 = !s51;
+  const SBool   s53 = s35 ? s52 : s51;
+  const SBool   s54 = !s5;
+  const SBool   s55 = s5 ? s54 : s5;
+  const SBool   s56 = !s7;
+  const SBool   s57 = s7 ? s56 : s7;
+  const SBool   s58 = !s9;
+  const SBool   s59 = s9 ? s58 : s9;
+  const SBool   s60 = !s13;
+  const SBool   s61 = s13 ? s60 : s13;
+  const SBool   s62 = !s17;
+  const SBool   s63 = s17 ? s62 : s17;
+  const SBool   s64 = !s23;
+  const SBool   s65 = s23 ? s64 : s23;
+  const SBool   s66 = !s29;
+  const SBool   s67 = s29 ? s66 : s29;
+  const SBool   s68 = !s35;
+  const SBool   s69 = s35 ? s68 : s35;
+  const SBool   s70 = !s41;
+  const SBool   s71 = s41 ? s70 : s41;
+  const SBool   s72 = !s47;
+  const SBool   s73 = s47 ? s72 : s47;
+  const SBool   s74 = !s53;
+  const SBool   s75 = s53 ? s74 : s53;
+  const SBool   s76 = (SBool) ((s2 >> 4) & 1);
+  const SBool   s77 = false != s76;
+  const SBool   s78 = !s77;
+  const SBool   s79 = s29 ? s78 : s77;
+  const SBool   s80 = !s79;
+  const SBool   s81 = s41 ? s80 : s79;
+  const SBool   s82 = (SBool) ((s2 >> 3) & 1);
+  const SBool   s83 = false != s82;
+  const SBool   s84 = !s83;
+  const SBool   s85 = s35 ? s84 : s83;
+  const SBool   s86 = !s85;
+  const SBool   s87 = s47 ? s86 : s85;
+  const SBool   s88 = (SBool) ((s2 >> 2) & 1);
+  const SBool   s89 = false != s88;
+  const SBool   s90 = !s89;
+  const SBool   s91 = s41 ? s90 : s89;
+  const SBool   s92 = !s91;
+  const SBool   s93 = s53 ? s92 : s91;
+  const SBool   s94 = (SBool) ((s2 >> 1) & 1);
+  const SBool   s95 = false != s94;
+  const SBool   s96 = !s95;
+  const SBool   s97 = s47 ? s96 : s95;
+  const SBool   s98 = (SBool) (s2 & 1);
+  const SBool   s99 = false != s98;
+  const SBool   s100 = !s99;
+  const SBool   s101 = s53 ? s100 : s99;
+  const SWord16 s104 = s101 ? 0x0001U : 0x0000U;
+  const SWord16 s106 = s104 | 0x0002U;
+  const SWord16 s107 = s97 ? s106 : s104;
+  const SWord16 s109 = s107 | 0x0004U;
+  const SWord16 s110 = s93 ? s109 : s107;
+  const SWord16 s112 = s110 | 0x0008U;
+  const SWord16 s113 = s87 ? s112 : s110;
+  const SWord16 s115 = s113 | 0x0010U;
+  const SWord16 s116 = s81 ? s115 : s113;
+  const SWord16 s118 = s116 | 0x0020U;
+  const SWord16 s119 = s75 ? s118 : s116;
+  const SWord16 s121 = s119 | 0x0040U;
+  const SWord16 s122 = s73 ? s121 : s119;
+  const SWord16 s124 = s122 | 0x0080U;
+  const SWord16 s125 = s71 ? s124 : s122;
+  const SWord16 s127 = s125 | 0x0100U;
+  const SWord16 s128 = s69 ? s127 : s125;
+  const SWord16 s130 = s128 | 0x0200U;
+  const SWord16 s131 = s67 ? s130 : s128;
+  const SWord16 s133 = s131 | 0x0400U;
+  const SWord16 s134 = s65 ? s133 : s131;
+  const SWord16 s136 = s134 | 0x0800U;
+  const SWord16 s137 = s63 ? s136 : s134;
+  const SWord16 s139 = s137 | 0x1000U;
+  const SWord16 s140 = s61 ? s139 : s137;
+  const SWord16 s142 = s140 | 0x2000U;
+  const SWord16 s143 = s59 ? s142 : s140;
+  const SWord16 s145 = s143 | 0x4000U;
+  const SWord16 s146 = s57 ? s145 : s143;
+  const SWord16 s148 = s146 | 0x8000U;
+  const SWord16 s149 = s55 ? s148 : s146;
+  const SWord16 s150 = s2 | s149;
+
+  return s150;
+}
+== END: "crcUSB5.c" ==================
diff --git a/SBVTestSuite/GoldFiles/doctest_sanity.gold b/SBVTestSuite/GoldFiles/doctest_sanity.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/doctest_sanity.gold
@@ -0,0 +1,3 @@
+Total:      1238; Tried: 1238; Skipped:    0; Success: 1238; Errors:    0; Failures    0
+Examples:   1086; Tried: 1086; Skipped:    0; Success: 1086; Errors:    0; Failures    0
+Setup:       152; Tried:  152; Skipped:    0; Success:  152; Errors:    0; Failures    0
diff --git a/SBVTestSuite/GoldFiles/dogCatMouse.gold b/SBVTestSuite/GoldFiles/dogCatMouse.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/dogCatMouse.gold
@@ -0,0 +1,5 @@
+Solution #1:
+  dog   =  3 :: Integer
+  cat   = 41 :: Integer
+  mouse = 56 :: Integer
+This is the only solution.
diff --git a/SBVTestSuite/GoldFiles/dsat01.gold b/SBVTestSuite/GoldFiles/dsat01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/dsat01.gold
@@ -0,0 +1,70 @@
+** Calling: dReal --in --format smt2
+[ISSUE] ; Automatically generated by SBV. Do not edit.
+** Skipping heart-beat for the solver DReal
+** Backend solver DReal does not support global decls.
+** Some incremental calls, such as pop, will be limited.
+[ISSUE] (set-option :smtlib2_compliant true)
+[ISSUE] (set-option :produce-models true)
+[ISSUE] (set-logic ALL) ; has unbounded values, using catch-all.
+[ISSUE] ; --- tuples ---
+[ISSUE] ; --- sums ---
+[ISSUE] ; --- literal constants ---
+[ISSUE] (define-fun s3 () Real (/ 2.0 1.0))
+[ISSUE] (define-fun s5 () Real (/ 5.0 1.0))
+[ISSUE] ; --- top level inputs ---
+[ISSUE] (declare-fun s0 () Real) ; tracks user variable "a0"
+[ISSUE] (declare-fun s1 () Int) ; tracks user variable "i0"
+[ISSUE] (declare-fun s2 () Bool) ; tracks user variable "b0"
+[ISSUE] ; --- constant tables ---
+[ISSUE] ; --- non-constant tables ---
+[ISSUE] ; --- uninterpreted constants ---
+[ISSUE] ; --- user defined functions ---
+[ISSUE] ; --- assignments ---
+[ISSUE] (define-fun s4 () Bool (> s0 s3))
+[ISSUE] (define-fun s6 () Bool (<= s0 s5))
+[ISSUE] ; --- delayedEqualities ---
+[ISSUE] ; --- formula ---
+[ISSUE] (assert s4)
+[ISSUE] (assert s6)
+[FIRE] (declare-fun s7 () Real)
+[FIRE] (declare-fun s8 () Int)
+[FIRE] (declare-fun s9 () Bool)
+[FIRE] (define-fun s10 () Real (/ 3.0 1.0))
+[FIRE] (define-fun s11 () Bool (> s7 s10))
+[FIRE] (assert s11)
+[FIRE] (define-fun s12 () Real (/ 12.0 1.0))
+[FIRE] (define-fun s13 () Bool (<= s7 s12))
+[FIRE] (assert s13)
+[SEND] (check-sat)
+[RECV] delta-sat
+[SEND] (get-option :precision)
+[RECV] 0.001
+[SEND] (get-value (s0))
+[RECV] (
+       	(s0 (interval (closed (/ 7035748517859557 2251799813685248)) (closed (/ 7038000317673243 2251799813685248))))
+       )
+[SEND] (get-value (s7))
+[RECV] (
+       	(s7 (interval (closed (/ 7177048956168307 1125899906842624)) (closed (/ 7178174856075149 1125899906842624))))
+       )
+[SEND] (get-value (s1))
+[RECV] (
+       	(s1 0)
+       )
+[SEND] (get-value (s8))
+[RECV] (
+       	(s8 0)
+       )
+[SEND] (get-value (s2))
+[RECV] (
+       	(s2 true)
+       )
+[SEND] (get-value (s9))
+[RECV] (
+       	(s9 true)
+       )
+*** Solver   : DReal
+*** Exit code: ExitSuccess
+
+ FINAL:(Just "0.001",[[7035748517859557 % 2251799813685248, 7038000317673243 % 2251799813685248],[7177048956168307 % 1125899906842624, 7178174856075149 % 1125899906842624]],[RatInterval (ClosedPoint (7035748517859557 % 2251799813685248)) (ClosedPoint (7038000317673243 % 2251799813685248)),RatInterval (ClosedPoint (7177048956168307 % 1125899906842624)) (ClosedPoint (7178174856075149 % 1125899906842624))],[0,0],[True,True])
+DONE!
diff --git a/SBVTestSuite/GoldFiles/euler185.gold b/SBVTestSuite/GoldFiles/euler185.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/euler185.gold
@@ -0,0 +1,18 @@
+Solution #1:
+  s0  = 4 :: Word8
+  s1  = 6 :: Word8
+  s2  = 4 :: Word8
+  s3  = 0 :: Word8
+  s4  = 2 :: Word8
+  s5  = 6 :: Word8
+  s6  = 1 :: Word8
+  s7  = 5 :: Word8
+  s8  = 7 :: Word8
+  s9  = 1 :: Word8
+  s10 = 8 :: Word8
+  s11 = 4 :: Word8
+  s12 = 9 :: Word8
+  s13 = 5 :: Word8
+  s14 = 3 :: Word8
+  s15 = 3 :: Word8
+This is the only solution.
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal1.gold b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
@@ -0,0 +1,58 @@
+** Calling: yices-smt2 --incremental
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s67 () (_ BitVec 32) #x00000001)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (_ BitVec 1) ((_ extract 0 0) s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 32) (bvmul s0 s0))
+[GOOD] (define-fun s5 () (_ BitVec 32) (bvmul s4 s4))
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvmul s5 s5))
+[GOOD] (define-fun s7 () (_ BitVec 32) (bvmul s6 s6))
+[GOOD] (define-fun s8 () (_ BitVec 32) (bvmul s7 s7))
+[GOOD] (define-fun s9 () (_ BitVec 32) (bvmul s8 s8))
+[GOOD] (define-fun s10 () (_ BitVec 32) (bvmul s9 s9))
+[GOOD] (define-fun s11 () (_ BitVec 32) (bvmul s10 s10))
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvmul s11 s11))
+[GOOD] (define-fun s13 () (_ BitVec 32) (bvmul s12 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (bvmul s13 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvmul s14 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (bvmul s15 s15))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvmul s16 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (bvmul s17 s17))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvmul s18 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (bvmul s19 s19))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvmul s20 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (bvmul s21 s21))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvmul s22 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (bvmul s23 s23))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvmul s24 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (bvmul s25 s25))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvmul s26 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (bvmul s27 s27))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvmul s28 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (bvmul s29 s29))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvmul s30 s30))
+[GOOD] (define-fun s32 () (_ BitVec 32) (bvmul s31 s31))
+[GOOD] (define-fun s33 () (_ BitVec 32) (bvmul s32 s32))
+CAUGHT SMT EXCEPTION
+*** Data.SBV: Unexpected solver error:
+***
+***    Sent      : (define-fun s34 () (_ BitVec 32) (bvmul s33 s33))
+***
+***    Stderr    : at line 40, column 35: in bvmul: maximal polynomial degree exceeded
+***    Executable: /usr/local/bin/yices-smt2
+***    Options   : --incremental
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal2.gold b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
@@ -0,0 +1,21 @@
+** 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_LIA) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Real (/ 2.0 1.0))
+[GOOD] ; --- top level inputs ---
+CAUGHT SMT EXCEPTION
+*** Data.SBV: Unexpected solver error:
+***
+***    Sent      : (declare-fun s0 () Real) ; tracks user variable "x"
+***
+***    Stderr    : line 8 column 23: logic does not support reals
+***    Executable: /usr/local/bin/z3
+***    Options   : -nw -in -smt2
diff --git a/SBVTestSuite/GoldFiles/exceptionRemote1.gold b/SBVTestSuite/GoldFiles/exceptionRemote1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/exceptionRemote1.gold
@@ -0,0 +1,3 @@
+
+FINAL: "OK, we got: Unexpected solver error"
+DONE!
diff --git a/SBVTestSuite/GoldFiles/fib1.gold b/SBVTestSuite/GoldFiles/fib1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/fib1.gold
@@ -0,0 +1,222 @@
+== BEGIN: "Makefile" ================
+# Makefile for fib1. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: fib1_driver
+
+fib1.o: fib1.c fib1.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fib1_driver.o: fib1_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fib1_driver: fib1.o fib1_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f fib1_driver
+== END: "Makefile" ==================
+== BEGIN: "fib1.h" ================
+/* Header file for fib1. Automatically generated by SBV. Do not edit! */
+
+#ifndef __fib1__HEADER_INCLUDED__
+#define __fib1__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord64 fib1(const SWord64 n);
+
+#endif /* __fib1__HEADER_INCLUDED__ */
+== END: "fib1.h" ==================
+== BEGIN: "fib1_driver.c" ================
+/* Example driver program for fib1. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "fib1.h"
+
+int main(void)
+{
+  const SWord64 __result = fib1(0x000000000000000cULL);
+
+  printf("fib1(0x000000000000000cULL) = 0x%016"PRIx64"ULL\n", __result);
+
+  return 0;
+}
+== END: "fib1_driver.c" ==================
+== BEGIN: "fib1.c" ================
+/* File: "fib1.c". Automatically generated by SBV. Do not edit! */
+
+#include "fib1.h"
+
+SWord64 fib1(const SWord64 n)
+{
+  const SWord64 s0 = n;
+  const SBool   s2 = s0 == 0x0000000000000000ULL;
+  const SBool   s4 = s0 == 0x0000000000000001ULL;
+  const SBool   s6 = s0 == 0x0000000000000002ULL;
+  const SBool   s8 = s0 == 0x0000000000000003ULL;
+  const SBool   s10 = s0 == 0x0000000000000004ULL;
+  const SBool   s12 = s0 == 0x0000000000000005ULL;
+  const SBool   s14 = s0 == 0x0000000000000006ULL;
+  const SBool   s17 = s0 == 0x0000000000000007ULL;
+  const SBool   s19 = s0 == 0x0000000000000008ULL;
+  const SBool   s22 = s0 == 0x0000000000000009ULL;
+  const SBool   s25 = s0 == 0x000000000000000aULL;
+  const SBool   s28 = s0 == 0x000000000000000bULL;
+  const SBool   s31 = s0 == 0x000000000000000cULL;
+  const SBool   s33 = s0 == 0x000000000000000dULL;
+  const SBool   s36 = s0 == 0x000000000000000eULL;
+  const SBool   s39 = s0 == 0x000000000000000fULL;
+  const SBool   s42 = s0 == 0x0000000000000010ULL;
+  const SBool   s45 = s0 == 0x0000000000000011ULL;
+  const SBool   s48 = s0 == 0x0000000000000012ULL;
+  const SBool   s51 = s0 == 0x0000000000000013ULL;
+  const SBool   s54 = s0 == 0x0000000000000014ULL;
+  const SBool   s56 = s0 == 0x0000000000000015ULL;
+  const SBool   s59 = s0 == 0x0000000000000016ULL;
+  const SBool   s62 = s0 == 0x0000000000000017ULL;
+  const SBool   s65 = s0 == 0x0000000000000018ULL;
+  const SBool   s68 = s0 == 0x0000000000000019ULL;
+  const SBool   s71 = s0 == 0x000000000000001aULL;
+  const SBool   s74 = s0 == 0x000000000000001bULL;
+  const SBool   s77 = s0 == 0x000000000000001cULL;
+  const SBool   s80 = s0 == 0x000000000000001dULL;
+  const SBool   s83 = s0 == 0x000000000000001eULL;
+  const SBool   s86 = s0 == 0x000000000000001fULL;
+  const SBool   s89 = s0 == 0x0000000000000020ULL;
+  const SBool   s92 = s0 == 0x0000000000000021ULL;
+  const SBool   s94 = s0 == 0x0000000000000022ULL;
+  const SBool   s97 = s0 == 0x0000000000000023ULL;
+  const SBool   s100 = s0 == 0x0000000000000024ULL;
+  const SBool   s103 = s0 == 0x0000000000000025ULL;
+  const SBool   s106 = s0 == 0x0000000000000026ULL;
+  const SBool   s109 = s0 == 0x0000000000000027ULL;
+  const SBool   s112 = s0 == 0x0000000000000028ULL;
+  const SBool   s115 = s0 == 0x0000000000000029ULL;
+  const SBool   s118 = s0 == 0x000000000000002aULL;
+  const SBool   s121 = s0 == 0x000000000000002bULL;
+  const SBool   s124 = s0 == 0x000000000000002cULL;
+  const SBool   s127 = s0 == 0x000000000000002dULL;
+  const SBool   s130 = s0 == 0x000000000000002eULL;
+  const SBool   s133 = s0 == 0x000000000000002fULL;
+  const SBool   s136 = s0 == 0x0000000000000030ULL;
+  const SBool   s139 = s0 == 0x0000000000000031ULL;
+  const SBool   s142 = s0 == 0x0000000000000032ULL;
+  const SBool   s145 = s0 == 0x0000000000000033ULL;
+  const SBool   s148 = s0 == 0x0000000000000034ULL;
+  const SBool   s151 = s0 == 0x0000000000000035ULL;
+  const SBool   s154 = s0 == 0x0000000000000036ULL;
+  const SBool   s156 = s0 == 0x0000000000000037ULL;
+  const SBool   s159 = s0 == 0x0000000000000038ULL;
+  const SBool   s162 = s0 == 0x0000000000000039ULL;
+  const SBool   s165 = s0 == 0x000000000000003aULL;
+  const SBool   s168 = s0 == 0x000000000000003bULL;
+  const SBool   s171 = s0 == 0x000000000000003cULL;
+  const SBool   s174 = s0 == 0x000000000000003dULL;
+  const SBool   s177 = s0 == 0x000000000000003eULL;
+  const SBool   s180 = s0 == 0x000000000000003fULL;
+  const SWord64 s183 = s180 ? 0x000005f6c7b064e2ULL : 0x000009a661ca20bbULL;
+  const SWord64 s184 = s177 ? 0x000003af9a19bbd9ULL : s183;
+  const SWord64 s185 = s174 ? 0x000002472d96a909ULL : s184;
+  const SWord64 s186 = s171 ? 0x000001686c8312d0ULL : s185;
+  const SWord64 s187 = s168 ? 0x000000dec1139639ULL : s186;
+  const SWord64 s188 = s165 ? 0x00000089ab6f7c97ULL : s187;
+  const SWord64 s189 = s162 ? 0x0000005515a419a2ULL : s188;
+  const SWord64 s190 = s159 ? 0x0000003495cb62f5ULL : s189;
+  const SWord64 s191 = s156 ? 0x000000207fd8b6adULL : s190;
+  const SWord64 s192 = s154 ? 0x0000001415f2ac48ULL : s191;
+  const SWord64 s193 = s151 ? 0x0000000c69e60a65ULL : s192;
+  const SWord64 s194 = s148 ? 0x00000007ac0ca1e3ULL : s193;
+  const SWord64 s195 = s145 ? 0x00000004bdd96882ULL : s194;
+  const SWord64 s196 = s142 ? 0x00000002ee333961ULL : s195;
+  const SWord64 s197 = s139 ? 0x00000001cfa62f21ULL : s196;
+  const SWord64 s198 = s136 ? 0x000000011e8d0a40ULL : s197;
+  const SWord64 s199 = s133 ? 0x00000000b11924e1ULL : s198;
+  const SWord64 s200 = s130 ? 0x000000006d73e55fULL : s199;
+  const SWord64 s201 = s127 ? 0x0000000043a53f82ULL : s200;
+  const SWord64 s202 = s124 ? 0x0000000029cea5ddULL : s201;
+  const SWord64 s203 = s121 ? 0x0000000019d699a5ULL : s202;
+  const SWord64 s204 = s118 ? 0x000000000ff80c38ULL : s203;
+  const SWord64 s205 = s115 ? 0x0000000009de8d6dULL : s204;
+  const SWord64 s206 = s112 ? 0x0000000006197ecbULL : s205;
+  const SWord64 s207 = s109 ? 0x0000000003c50ea2ULL : s206;
+  const SWord64 s208 = s106 ? 0x0000000002547029ULL : s207;
+  const SWord64 s209 = s103 ? 0x0000000001709e79ULL : s208;
+  const SWord64 s210 = s100 ? 0x0000000000e3d1b0ULL : s209;
+  const SWord64 s211 = s97 ? 0x00000000008cccc9ULL : s210;
+  const SWord64 s212 = s94 ? 0x00000000005704e7ULL : s211;
+  const SWord64 s213 = s92 ? 0x000000000035c7e2ULL : s212;
+  const SWord64 s214 = s89 ? 0x0000000000213d05ULL : s213;
+  const SWord64 s215 = s86 ? 0x0000000000148addULL : s214;
+  const SWord64 s216 = s83 ? 0x00000000000cb228ULL : s215;
+  const SWord64 s217 = s80 ? 0x000000000007d8b5ULL : s216;
+  const SWord64 s218 = s77 ? 0x000000000004d973ULL : s217;
+  const SWord64 s219 = s74 ? 0x000000000002ff42ULL : s218;
+  const SWord64 s220 = s71 ? 0x000000000001da31ULL : s219;
+  const SWord64 s221 = s68 ? 0x0000000000012511ULL : s220;
+  const SWord64 s222 = s65 ? 0x000000000000b520ULL : s221;
+  const SWord64 s223 = s62 ? 0x0000000000006ff1ULL : s222;
+  const SWord64 s224 = s59 ? 0x000000000000452fULL : s223;
+  const SWord64 s225 = s56 ? 0x0000000000002ac2ULL : s224;
+  const SWord64 s226 = s54 ? 0x0000000000001a6dULL : s225;
+  const SWord64 s227 = s51 ? 0x0000000000001055ULL : s226;
+  const SWord64 s228 = s48 ? 0x0000000000000a18ULL : s227;
+  const SWord64 s229 = s45 ? 0x000000000000063dULL : s228;
+  const SWord64 s230 = s42 ? 0x00000000000003dbULL : s229;
+  const SWord64 s231 = s39 ? 0x0000000000000262ULL : s230;
+  const SWord64 s232 = s36 ? 0x0000000000000179ULL : s231;
+  const SWord64 s233 = s33 ? 0x00000000000000e9ULL : s232;
+  const SWord64 s234 = s31 ? 0x0000000000000090ULL : s233;
+  const SWord64 s235 = s28 ? 0x0000000000000059ULL : s234;
+  const SWord64 s236 = s25 ? 0x0000000000000037ULL : s235;
+  const SWord64 s237 = s22 ? 0x0000000000000022ULL : s236;
+  const SWord64 s238 = s19 ? 0x0000000000000015ULL : s237;
+  const SWord64 s239 = s17 ? 0x000000000000000dULL : s238;
+  const SWord64 s240 = s14 ? 0x0000000000000008ULL : s239;
+  const SWord64 s241 = s12 ? 0x0000000000000005ULL : s240;
+  const SWord64 s242 = s10 ? 0x0000000000000003ULL : s241;
+  const SWord64 s243 = s8 ? 0x0000000000000002ULL : s242;
+  const SWord64 s244 = s6 ? 0x0000000000000001ULL : s243;
+  const SWord64 s245 = s4 ? 0x0000000000000001ULL : s244;
+  const SWord64 s246 = s2 ? 0x0000000000000000ULL : s245;
+
+  return s246;
+}
+== END: "fib1.c" ==================
diff --git a/SBVTestSuite/GoldFiles/fib2.gold b/SBVTestSuite/GoldFiles/fib2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/fib2.gold
@@ -0,0 +1,129 @@
+== BEGIN: "Makefile" ================
+# Makefile for fib2. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: fib2_driver
+
+fib2.o: fib2.c fib2.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fib2_driver.o: fib2_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fib2_driver: fib2.o fib2_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f fib2_driver
+== END: "Makefile" ==================
+== BEGIN: "fib2.h" ================
+/* Header file for fib2. Automatically generated by SBV. Do not edit! */
+
+#ifndef __fib2__HEADER_INCLUDED__
+#define __fib2__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord64 fib2(const SWord64 n);
+
+#endif /* __fib2__HEADER_INCLUDED__ */
+== END: "fib2.h" ==================
+== BEGIN: "fib2_driver.c" ================
+/* Example driver program for fib2. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "fib2.h"
+
+int main(void)
+{
+  const SWord64 __result = fib2(0x0000000000000014ULL);
+
+  printf("fib2(0x0000000000000014ULL) = 0x%016"PRIx64"ULL\n", __result);
+
+  return 0;
+}
+== END: "fib2_driver.c" ==================
+== BEGIN: "fib2.c" ================
+/* File: "fib2.c". Automatically generated by SBV. Do not edit! */
+
+#include "fib2.h"
+
+SWord64 fib2(const SWord64 n)
+{
+  const SWord64 s0 = n;
+  static const SWord64 table0[] = {
+      0x0000000000000000ULL, 0x0000000000000001ULL,
+      0x0000000000000001ULL, 0x0000000000000002ULL,
+      0x0000000000000003ULL, 0x0000000000000005ULL,
+      0x0000000000000008ULL, 0x000000000000000dULL,
+      0x0000000000000015ULL, 0x0000000000000022ULL,
+      0x0000000000000037ULL, 0x0000000000000059ULL,
+      0x0000000000000090ULL, 0x00000000000000e9ULL,
+      0x0000000000000179ULL, 0x0000000000000262ULL,
+      0x00000000000003dbULL, 0x000000000000063dULL,
+      0x0000000000000a18ULL, 0x0000000000001055ULL,
+      0x0000000000001a6dULL, 0x0000000000002ac2ULL,
+      0x000000000000452fULL, 0x0000000000006ff1ULL,
+      0x000000000000b520ULL, 0x0000000000012511ULL,
+      0x000000000001da31ULL, 0x000000000002ff42ULL,
+      0x000000000004d973ULL, 0x000000000007d8b5ULL,
+      0x00000000000cb228ULL, 0x0000000000148addULL,
+      0x0000000000213d05ULL, 0x000000000035c7e2ULL,
+      0x00000000005704e7ULL, 0x00000000008cccc9ULL,
+      0x0000000000e3d1b0ULL, 0x0000000001709e79ULL,
+      0x0000000002547029ULL, 0x0000000003c50ea2ULL,
+      0x0000000006197ecbULL, 0x0000000009de8d6dULL,
+      0x000000000ff80c38ULL, 0x0000000019d699a5ULL,
+      0x0000000029cea5ddULL, 0x0000000043a53f82ULL,
+      0x000000006d73e55fULL, 0x00000000b11924e1ULL,
+      0x000000011e8d0a40ULL, 0x00000001cfa62f21ULL,
+      0x00000002ee333961ULL, 0x00000004bdd96882ULL,
+      0x00000007ac0ca1e3ULL, 0x0000000c69e60a65ULL,
+      0x0000001415f2ac48ULL, 0x000000207fd8b6adULL,
+      0x0000003495cb62f5ULL, 0x0000005515a419a2ULL,
+      0x00000089ab6f7c97ULL, 0x000000dec1139639ULL,
+      0x000001686c8312d0ULL, 0x000002472d96a909ULL,
+      0x000003af9a19bbd9ULL, 0x000005f6c7b064e2ULL, 0x000009a661ca20bbULL
+  };
+  const SWord64 s65 = s0 >= 65 ? 0x0000000000000000ULL : table0[s0];
+
+  return s65;
+}
+== END: "fib2.c" ==================
diff --git a/SBVTestSuite/GoldFiles/floats_cgen.gold b/SBVTestSuite/GoldFiles/floats_cgen.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/floats_cgen.gold
@@ -0,0 +1,2788 @@
+== BEGIN: "toFP_Int8_ToFloat.c" ================
+/* File: "toFP_Int8_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Int8_ToFloat(const SInt8 a)
+{
+  const SInt8  s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Int8_ToFloat.c" ==================
+== BEGIN: "toFP_Int16_ToFloat.c" ================
+/* File: "toFP_Int16_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Int16_ToFloat(const SInt16 a)
+{
+  const SInt16 s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Int16_ToFloat.c" ==================
+== BEGIN: "toFP_Int32_ToFloat.c" ================
+/* File: "toFP_Int32_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Int32_ToFloat(const SInt32 a)
+{
+  const SInt32 s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Int32_ToFloat.c" ==================
+== BEGIN: "toFP_Int64_ToFloat.c" ================
+/* File: "toFP_Int64_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Int64_ToFloat(const SInt64 a)
+{
+  const SInt64 s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Int64_ToFloat.c" ==================
+== BEGIN: "toFP_Word8_ToFloat.c" ================
+/* File: "toFP_Word8_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Word8_ToFloat(const SWord8 a)
+{
+  const SWord8 s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Word8_ToFloat.c" ==================
+== BEGIN: "toFP_Word16_ToFloat.c" ================
+/* File: "toFP_Word16_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Word16_ToFloat(const SWord16 a)
+{
+  const SWord16 s0 = a;
+  const SFloat  s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Word16_ToFloat.c" ==================
+== BEGIN: "toFP_Word32_ToFloat.c" ================
+/* File: "toFP_Word32_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Word32_ToFloat(const SWord32 a)
+{
+  const SWord32 s0 = a;
+  const SFloat  s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Word32_ToFloat.c" ==================
+== BEGIN: "toFP_Word64_ToFloat.c" ================
+/* File: "toFP_Word64_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Word64_ToFloat(const SWord64 a)
+{
+  const SWord64 s0 = a;
+  const SFloat  s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Word64_ToFloat.c" ==================
+== BEGIN: "toFP_Float_ToFloat.c" ================
+/* File: "toFP_Float_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Float_ToFloat(const SFloat a)
+{
+  const SFloat s0 = a;
+  return s0;
+}
+== END: "toFP_Float_ToFloat.c" ==================
+== BEGIN: "toFP_Double_ToFloat.c" ================
+/* File: "toFP_Double_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Double_ToFloat(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SFloat  s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Double_ToFloat.c" ==================
+== BEGIN: "toFP_Integer_ToFloat.c" ================
+/* File: "toFP_Integer_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Integer_ToFloat(const SInteger a)
+{
+  const SInteger s0 = a;
+  const SFloat   s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Integer_ToFloat.c" ==================
+== BEGIN: "toFP_Real_ToFloat.c" ================
+/* File: "toFP_Real_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat toFP_Real_ToFloat(const SReal a)
+{
+  const SReal  s0 = a;
+  const SFloat s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "toFP_Real_ToFloat.c" ==================
+== BEGIN: "toFP_Int8_ToDouble.c" ================
+/* File: "toFP_Int8_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Int8_ToDouble(const SInt8 a)
+{
+  const SInt8   s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Int8_ToDouble.c" ==================
+== BEGIN: "toFP_Int16_ToDouble.c" ================
+/* File: "toFP_Int16_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Int16_ToDouble(const SInt16 a)
+{
+  const SInt16  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Int16_ToDouble.c" ==================
+== BEGIN: "toFP_Int32_ToDouble.c" ================
+/* File: "toFP_Int32_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Int32_ToDouble(const SInt32 a)
+{
+  const SInt32  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Int32_ToDouble.c" ==================
+== BEGIN: "toFP_Int64_ToDouble.c" ================
+/* File: "toFP_Int64_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Int64_ToDouble(const SInt64 a)
+{
+  const SInt64  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Int64_ToDouble.c" ==================
+== BEGIN: "toFP_Word8_ToDouble.c" ================
+/* File: "toFP_Word8_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Word8_ToDouble(const SWord8 a)
+{
+  const SWord8  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Word8_ToDouble.c" ==================
+== BEGIN: "toFP_Word16_ToDouble.c" ================
+/* File: "toFP_Word16_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Word16_ToDouble(const SWord16 a)
+{
+  const SWord16 s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Word16_ToDouble.c" ==================
+== BEGIN: "toFP_Word32_ToDouble.c" ================
+/* File: "toFP_Word32_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Word32_ToDouble(const SWord32 a)
+{
+  const SWord32 s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Word32_ToDouble.c" ==================
+== BEGIN: "toFP_Word64_ToDouble.c" ================
+/* File: "toFP_Word64_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Word64_ToDouble(const SWord64 a)
+{
+  const SWord64 s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Word64_ToDouble.c" ==================
+== BEGIN: "toFP_Float_ToDouble.c" ================
+/* File: "toFP_Float_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Float_ToDouble(const SFloat a)
+{
+  const SFloat  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Float_ToDouble.c" ==================
+== BEGIN: "toFP_Double_ToDouble.c" ================
+/* File: "toFP_Double_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Double_ToDouble(const SDouble a)
+{
+  const SDouble s0 = a;
+  return s0;
+}
+== END: "toFP_Double_ToDouble.c" ==================
+== BEGIN: "toFP_Integer_ToDouble.c" ================
+/* File: "toFP_Integer_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Integer_ToDouble(const SInteger a)
+{
+  const SInteger s0 = a;
+  const SDouble  s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Integer_ToDouble.c" ==================
+== BEGIN: "toFP_Real_ToDouble.c" ================
+/* File: "toFP_Real_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble toFP_Real_ToDouble(const SReal a)
+{
+  const SReal   s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "toFP_Real_ToDouble.c" ==================
+== BEGIN: "fromFP_Float_ToInt8.c" ================
+/* File: "fromFP_Float_ToInt8.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt8 fromFP_Float_ToInt8(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SInt8  s2 = (SInt8) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToInt8.c" ==================
+== BEGIN: "fromFP_Float_ToInt16.c" ================
+/* File: "fromFP_Float_ToInt16.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt16 fromFP_Float_ToInt16(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SInt16 s2 = (SInt16) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToInt16.c" ==================
+== BEGIN: "fromFP_Float_ToInt32.c" ================
+/* File: "fromFP_Float_ToInt32.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt32 fromFP_Float_ToInt32(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SInt32 s2 = (SInt32) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToInt32.c" ==================
+== BEGIN: "fromFP_Float_ToInt64.c" ================
+/* File: "fromFP_Float_ToInt64.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt64 fromFP_Float_ToInt64(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SInt64 s2 = (SInt64) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToInt64.c" ==================
+== BEGIN: "fromFP_Float_ToWord8.c" ================
+/* File: "fromFP_Float_ToWord8.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord8 fromFP_Float_ToWord8(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SWord8 s2 = (SWord8) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToWord8.c" ==================
+== BEGIN: "fromFP_Float_ToWord16.c" ================
+/* File: "fromFP_Float_ToWord16.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord16 fromFP_Float_ToWord16(const SFloat a)
+{
+  const SFloat  s0 = a;
+  const SWord16 s2 = (SWord16) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToWord16.c" ==================
+== BEGIN: "fromFP_Float_ToWord32.c" ================
+/* File: "fromFP_Float_ToWord32.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord32 fromFP_Float_ToWord32(const SFloat a)
+{
+  const SFloat  s0 = a;
+  const SWord32 s2 = (SWord32) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToWord32.c" ==================
+== BEGIN: "fromFP_Float_ToWord64.c" ================
+/* File: "fromFP_Float_ToWord64.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord64 fromFP_Float_ToWord64(const SFloat a)
+{
+  const SFloat  s0 = a;
+  const SWord64 s2 = (SWord64) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToWord64.c" ==================
+== BEGIN: "fromFP_Float_ToFloat.c" ================
+/* File: "fromFP_Float_ToFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat fromFP_Float_ToFloat(const SFloat a)
+{
+  const SFloat s0 = a;
+  return s0;
+}
+== END: "fromFP_Float_ToFloat.c" ==================
+== BEGIN: "fromFP_Float_ToDouble.c" ================
+/* File: "fromFP_Float_ToDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble fromFP_Float_ToDouble(const SFloat a)
+{
+  const SFloat  s0 = a;
+  const SDouble s2 = (SDouble) s0;
+
+  return s2;
+}
+== END: "fromFP_Float_ToDouble.c" ==================
+== BEGIN: "fromFP_Float_ToInteger.c" ================
+/* File: "fromFP_Float_ToInteger.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInteger fromFP_Float_ToInteger(const SFloat a)
+{
+  const SFloat   s0 = a;
+  const SInteger s2 = (SInteger) rintf(s0);
+
+  return s2;
+}
+== END: "fromFP_Float_ToInteger.c" ==================
+== BEGIN: "fromFP_Float_ToReal.c" ================
+/* File: "fromFP_Float_ToReal.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SReal fromFP_Float_ToReal(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SReal  s2 = (SReal) s0;
+
+  return s2;
+}
+== END: "fromFP_Float_ToReal.c" ==================
+== BEGIN: "fromFP_DoubleTo_Int8.c" ================
+/* File: "fromFP_DoubleTo_Int8.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt8 fromFP_DoubleTo_Int8(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SInt8   s2 = (SInt8) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Int8.c" ==================
+== BEGIN: "fromFP_DoubleTo_Int16.c" ================
+/* File: "fromFP_DoubleTo_Int16.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt16 fromFP_DoubleTo_Int16(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SInt16  s2 = (SInt16) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Int16.c" ==================
+== BEGIN: "fromFP_DoubleTo_Int32.c" ================
+/* File: "fromFP_DoubleTo_Int32.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt32 fromFP_DoubleTo_Int32(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SInt32  s2 = (SInt32) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Int32.c" ==================
+== BEGIN: "fromFP_DoubleTo_Int64.c" ================
+/* File: "fromFP_DoubleTo_Int64.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInt64 fromFP_DoubleTo_Int64(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SInt64  s2 = (SInt64) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Int64.c" ==================
+== BEGIN: "fromFP_DoubleTo_Word8.c" ================
+/* File: "fromFP_DoubleTo_Word8.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord8 fromFP_DoubleTo_Word8(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SWord8  s2 = (SWord8) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Word8.c" ==================
+== BEGIN: "fromFP_DoubleTo_Word16.c" ================
+/* File: "fromFP_DoubleTo_Word16.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord16 fromFP_DoubleTo_Word16(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SWord16 s2 = (SWord16) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Word16.c" ==================
+== BEGIN: "fromFP_DoubleTo_Word32.c" ================
+/* File: "fromFP_DoubleTo_Word32.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord32 fromFP_DoubleTo_Word32(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SWord32 s2 = (SWord32) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Word32.c" ==================
+== BEGIN: "fromFP_DoubleTo_Word64.c" ================
+/* File: "fromFP_DoubleTo_Word64.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord64 fromFP_DoubleTo_Word64(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SWord64 s2 = (SWord64) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Word64.c" ==================
+== BEGIN: "fromFP_DoubleTo_Float.c" ================
+/* File: "fromFP_DoubleTo_Float.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat fromFP_DoubleTo_Float(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SFloat  s2 = (SFloat) s0;
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Float.c" ==================
+== BEGIN: "fromFP_DoubleTo_Double.c" ================
+/* File: "fromFP_DoubleTo_Double.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble fromFP_DoubleTo_Double(const SDouble a)
+{
+  const SDouble s0 = a;
+  return s0;
+}
+== END: "fromFP_DoubleTo_Double.c" ==================
+== BEGIN: "fromFP_DoubleTo_Integer.c" ================
+/* File: "fromFP_DoubleTo_Integer.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SInteger fromFP_DoubleTo_Integer(const SDouble a)
+{
+  const SDouble  s0 = a;
+  const SInteger s2 = (SInteger) rint(s0);
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Integer.c" ==================
+== BEGIN: "fromFP_DoubleTo_Real.c" ================
+/* File: "fromFP_DoubleTo_Real.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SReal fromFP_DoubleTo_Real(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SReal   s2 = (SReal) s0;
+
+  return s2;
+}
+== END: "fromFP_DoubleTo_Real.c" ==================
+== BEGIN: "fromFP_SWord32_SFloat.c" ================
+/* File: "fromFP_SWord32_SFloat.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat fromFP_SWord32_SFloat(const SWord32 a)
+{
+  const SWord32 s0 = a;
+        SFloat  s1; memcpy(&s1, &s0, sizeof(SFloat));
+
+  return s1;
+}
+== END: "fromFP_SWord32_SFloat.c" ==================
+== BEGIN: "fromFP_SWord64_SDouble.c" ================
+/* File: "fromFP_SWord64_SDouble.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble fromFP_SWord64_SDouble(const SWord64 a)
+{
+  const SWord64 s0 = a;
+        SDouble s1; memcpy(&s1, &s0, sizeof(SDouble));
+
+  return s1;
+}
+== END: "fromFP_SWord64_SDouble.c" ==================
+== BEGIN: "fromFP_SFloat_SWord32.c" ================
+/* File: "fromFP_SFloat_SWord32.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord32 fromFP_SFloat_SWord32(const SFloat a)
+{
+  const SFloat  s0 = a;
+        SWord32 s1; memcpy(&s1, &s0, sizeof(SWord32));
+
+  return s1;
+}
+== END: "fromFP_SFloat_SWord32.c" ==================
+== BEGIN: "fromFP_SDouble_SWord64.c" ================
+/* File: "fromFP_SDouble_SWord64.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SWord64 fromFP_SDouble_SWord64(const SDouble a)
+{
+  const SDouble s0 = a;
+        SWord64 s1; memcpy(&s1, &s0, sizeof(SWord64));
+
+  return s1;
+}
+== END: "fromFP_SDouble_SWord64.c" ==================
+== BEGIN: "f_FP_Abs.c" ================
+/* File: "f_FP_Abs.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Abs(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = fabsf(s0);
+
+  return s1;
+}
+== END: "f_FP_Abs.c" ==================
+== BEGIN: "d_FP_Abs.c" ================
+/* File: "d_FP_Abs.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Abs(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = fabs(s0);
+
+  return s1;
+}
+== END: "d_FP_Abs.c" ==================
+== BEGIN: "f_FP_Neg.c" ================
+/* File: "f_FP_Neg.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Neg(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = (- s0);
+
+  return s1;
+}
+== END: "f_FP_Neg.c" ==================
+== BEGIN: "d_FP_Neg.c" ================
+/* File: "d_FP_Neg.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Neg(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = (- s0);
+
+  return s1;
+}
+== END: "d_FP_Neg.c" ==================
+== BEGIN: "f_FP_Add.c" ================
+/* File: "f_FP_Add.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Add(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s3 = s0 + s1;
+
+  return s3;
+}
+== END: "f_FP_Add.c" ==================
+== BEGIN: "d_FP_Add.c" ================
+/* File: "d_FP_Add.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Add(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s3 = s0 + s1;
+
+  return s3;
+}
+== END: "d_FP_Add.c" ==================
+== BEGIN: "f_FP_Sub.c" ================
+/* File: "f_FP_Sub.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Sub(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s3 = s0 - s1;
+
+  return s3;
+}
+== END: "f_FP_Sub.c" ==================
+== BEGIN: "d_FP_Sub.c" ================
+/* File: "d_FP_Sub.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Sub(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s3 = s0 - s1;
+
+  return s3;
+}
+== END: "d_FP_Sub.c" ==================
+== BEGIN: "f_FP_Mul.c" ================
+/* File: "f_FP_Mul.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Mul(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s3 = s0 * s1;
+
+  return s3;
+}
+== END: "f_FP_Mul.c" ==================
+== BEGIN: "d_FP_Mul.c" ================
+/* File: "d_FP_Mul.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Mul(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s3 = s0 * s1;
+
+  return s3;
+}
+== END: "d_FP_Mul.c" ==================
+== BEGIN: "f_FP_Div.c" ================
+/* File: "f_FP_Div.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Div(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s3 = s0 / s1;
+
+  return s3;
+}
+== END: "f_FP_Div.c" ==================
+== BEGIN: "d_FP_Div.c" ================
+/* File: "d_FP_Div.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Div(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s3 = s0 / s1;
+
+  return s3;
+}
+== END: "d_FP_Div.c" ==================
+== BEGIN: "f_FP_FMA.c" ================
+/* File: "f_FP_FMA.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_FMA(const SFloat a, const SFloat b, const SFloat c)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s2 = c;
+  const SFloat s4 = fmaf(s0, s1, s2);
+
+  return s4;
+}
+== END: "f_FP_FMA.c" ==================
+== BEGIN: "d_FP_FMA.c" ================
+/* File: "d_FP_FMA.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_FMA(const SDouble a, const SDouble b, const SDouble c)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s2 = c;
+  const SDouble s4 = fma(s0, s1, s2);
+
+  return s4;
+}
+== END: "d_FP_FMA.c" ==================
+== BEGIN: "f_FP_Sqrt.c" ================
+/* File: "f_FP_Sqrt.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Sqrt(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SFloat s2 = sqrtf(s0);
+
+  return s2;
+}
+== END: "f_FP_Sqrt.c" ==================
+== BEGIN: "d_FP_Sqrt.c" ================
+/* File: "d_FP_Sqrt.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Sqrt(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SDouble s2 = sqrt(s0);
+
+  return s2;
+}
+== END: "d_FP_Sqrt.c" ==================
+== BEGIN: "f_FP_Rem.c" ================
+/* File: "f_FP_Rem.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Rem(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s2 = fmodf(s0, s1);
+
+  return s2;
+}
+== END: "f_FP_Rem.c" ==================
+== BEGIN: "d_FP_Rem.c" ================
+/* File: "d_FP_Rem.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Rem(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s2 = fmod(s0, s1);
+
+  return s2;
+}
+== END: "d_FP_Rem.c" ==================
+== BEGIN: "f_FP_RoundToIntegral.c" ================
+/* File: "f_FP_RoundToIntegral.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_RoundToIntegral(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SFloat s2 = rintf(s0);
+
+  return s2;
+}
+== END: "f_FP_RoundToIntegral.c" ==================
+== BEGIN: "d_FP_RoundToIntegral.c" ================
+/* File: "d_FP_RoundToIntegral.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_RoundToIntegral(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SDouble s2 = rint(s0);
+
+  return s2;
+}
+== END: "d_FP_RoundToIntegral.c" ==================
+== BEGIN: "f_FP_Min.c" ================
+/* File: "f_FP_Min.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Min(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0F /* 0.0F */ : fminf(s0,
+                                                                                                                                              s1);
+
+  return s2;
+}
+== END: "f_FP_Min.c" ==================
+== BEGIN: "d_FP_Min.c" ================
+/* File: "d_FP_Min.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Min(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0 /* 0.0 */ : fmin(s0,
+                                                                                                                                            s1);
+
+  return s2;
+}
+== END: "d_FP_Min.c" ==================
+== BEGIN: "f_FP_Max.c" ================
+/* File: "f_FP_Max.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SFloat f_FP_Max(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0F /* 0.0F */ : fmaxf(s0,
+                                                                                                                                              s1);
+
+  return s2;
+}
+== END: "f_FP_Max.c" ==================
+== BEGIN: "d_FP_Max.c" ================
+/* File: "d_FP_Max.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SDouble d_FP_Max(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0 /* 0.0 */ : fmax(s0,
+                                                                                                                                            s1);
+
+  return s2;
+}
+== END: "d_FP_Max.c" ==================
+== BEGIN: "f_FP_IsEqualObject.c" ================
+/* File: "f_FP_IsEqualObject.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsEqualObject(const SFloat a, const SFloat b)
+{
+  const SFloat s0 = a;
+  const SFloat s1 = b;
+  const SBool  s2 = isnan(s0) ? isnan(s1) : (signbit(s0) && (s0 == 0)) ? (signbit(s1) && (s1 == 0)) : (signbit(s1) && (s1 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s1);
+
+  return s2;
+}
+== END: "f_FP_IsEqualObject.c" ==================
+== BEGIN: "d_FP_IsEqualObject.c" ================
+/* File: "d_FP_IsEqualObject.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsEqualObject(const SDouble a, const SDouble b)
+{
+  const SDouble s0 = a;
+  const SDouble s1 = b;
+  const SBool   s2 = isnan(s0) ? isnan(s1) : (signbit(s0) && (s0 == 0)) ? (signbit(s1) && (s1 == 0)) : (signbit(s1) && (s1 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s1);
+
+  return s2;
+}
+== END: "d_FP_IsEqualObject.c" ==================
+== BEGIN: "f_FP_IsNormal.c" ================
+/* File: "f_FP_IsNormal.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsNormal(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = isnormal(s0);
+
+  return s1;
+}
+== END: "f_FP_IsNormal.c" ==================
+== BEGIN: "d_FP_IsNormal.c" ================
+/* File: "d_FP_IsNormal.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsNormal(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = isnormal(s0);
+
+  return s1;
+}
+== END: "d_FP_IsNormal.c" ==================
+== BEGIN: "f_FP_IsZero.c" ================
+/* File: "f_FP_IsZero.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsZero(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = FP_ZERO == fpclassify(s0);
+
+  return s1;
+}
+== END: "f_FP_IsZero.c" ==================
+== BEGIN: "d_FP_IsZero.c" ================
+/* File: "d_FP_IsZero.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsZero(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = FP_ZERO == fpclassify(s0);
+
+  return s1;
+}
+== END: "d_FP_IsZero.c" ==================
+== BEGIN: "f_FP_IsSubnormal.c" ================
+/* File: "f_FP_IsSubnormal.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsSubnormal(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = FP_SUBNORMAL == fpclassify(s0);
+
+  return s1;
+}
+== END: "f_FP_IsSubnormal.c" ==================
+== BEGIN: "d_FP_IsSubnormal.c" ================
+/* File: "d_FP_IsSubnormal.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsSubnormal(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = FP_SUBNORMAL == fpclassify(s0);
+
+  return s1;
+}
+== END: "d_FP_IsSubnormal.c" ==================
+== BEGIN: "f_FP_IsInfinite.c" ================
+/* File: "f_FP_IsInfinite.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsInfinite(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = isinf(s0);
+
+  return s1;
+}
+== END: "f_FP_IsInfinite.c" ==================
+== BEGIN: "d_FP_IsInfinite.c" ================
+/* File: "d_FP_IsInfinite.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsInfinite(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = isinf(s0);
+
+  return s1;
+}
+== END: "d_FP_IsInfinite.c" ==================
+== BEGIN: "f_FP_IsNaN.c" ================
+/* File: "f_FP_IsNaN.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsNaN(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = isnan(s0);
+
+  return s1;
+}
+== END: "f_FP_IsNaN.c" ==================
+== BEGIN: "d_FP_IsNaN.c" ================
+/* File: "d_FP_IsNaN.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsNaN(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = isnan(s0);
+
+  return s1;
+}
+== END: "d_FP_IsNaN.c" ==================
+== BEGIN: "f_FP_IsNegative.c" ================
+/* File: "f_FP_IsNegative.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsNegative(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = !isnan(s0) && signbit(s0);
+
+  return s1;
+}
+== END: "f_FP_IsNegative.c" ==================
+== BEGIN: "d_FP_IsNegative.c" ================
+/* File: "d_FP_IsNegative.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsNegative(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = !isnan(s0) && signbit(s0);
+
+  return s1;
+}
+== END: "d_FP_IsNegative.c" ==================
+== BEGIN: "f_FP_IsPositive.c" ================
+/* File: "f_FP_IsPositive.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool f_FP_IsPositive(const SFloat a)
+{
+  const SFloat s0 = a;
+  const SBool  s1 = !isnan(s0) && !signbit(s0);
+
+  return s1;
+}
+== END: "f_FP_IsPositive.c" ==================
+== BEGIN: "d_FP_IsPositive.c" ================
+/* File: "d_FP_IsPositive.c". Automatically generated by SBV. Do not edit! */
+
+#include "floatCodeGen.h"
+
+SBool d_FP_IsPositive(const SDouble a)
+{
+  const SDouble s0 = a;
+  const SBool   s1 = !isnan(s0) && !signbit(s0);
+
+  return s1;
+}
+== END: "d_FP_IsPositive.c" ==================
+== BEGIN: "floatCodeGen.h" ================
+/* Header file for floatCodeGen. Automatically generated by SBV. Do not edit! */
+
+#ifndef __floatCodeGen__HEADER_INCLUDED__
+#define __floatCodeGen__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* User requested mapping for SInteger.                                 */
+/* NB. Loss of precision: Target type is subject to modular arithmetic. */
+typedef SInt64 SInteger;
+
+/* User requested mapping for SReal.                          */
+/* NB. Loss of precision: Target type is subject to rounding. */
+typedef long double SReal;
+
+/* Entry point prototypes: */
+SFloat toFP_Int8_ToFloat(const SInt8 a);
+SFloat toFP_Int16_ToFloat(const SInt16 a);
+SFloat toFP_Int32_ToFloat(const SInt32 a);
+SFloat toFP_Int64_ToFloat(const SInt64 a);
+SFloat toFP_Word8_ToFloat(const SWord8 a);
+SFloat toFP_Word16_ToFloat(const SWord16 a);
+SFloat toFP_Word32_ToFloat(const SWord32 a);
+SFloat toFP_Word64_ToFloat(const SWord64 a);
+SFloat toFP_Float_ToFloat(const SFloat a);
+SFloat toFP_Double_ToFloat(const SDouble a);
+SFloat toFP_Integer_ToFloat(const SInteger a);
+SFloat toFP_Real_ToFloat(const SReal a);
+SDouble toFP_Int8_ToDouble(const SInt8 a);
+SDouble toFP_Int16_ToDouble(const SInt16 a);
+SDouble toFP_Int32_ToDouble(const SInt32 a);
+SDouble toFP_Int64_ToDouble(const SInt64 a);
+SDouble toFP_Word8_ToDouble(const SWord8 a);
+SDouble toFP_Word16_ToDouble(const SWord16 a);
+SDouble toFP_Word32_ToDouble(const SWord32 a);
+SDouble toFP_Word64_ToDouble(const SWord64 a);
+SDouble toFP_Float_ToDouble(const SFloat a);
+SDouble toFP_Double_ToDouble(const SDouble a);
+SDouble toFP_Integer_ToDouble(const SInteger a);
+SDouble toFP_Real_ToDouble(const SReal a);
+SInt8 fromFP_Float_ToInt8(const SFloat a);
+SInt16 fromFP_Float_ToInt16(const SFloat a);
+SInt32 fromFP_Float_ToInt32(const SFloat a);
+SInt64 fromFP_Float_ToInt64(const SFloat a);
+SWord8 fromFP_Float_ToWord8(const SFloat a);
+SWord16 fromFP_Float_ToWord16(const SFloat a);
+SWord32 fromFP_Float_ToWord32(const SFloat a);
+SWord64 fromFP_Float_ToWord64(const SFloat a);
+SFloat fromFP_Float_ToFloat(const SFloat a);
+SDouble fromFP_Float_ToDouble(const SFloat a);
+SInteger fromFP_Float_ToInteger(const SFloat a);
+SReal fromFP_Float_ToReal(const SFloat a);
+SInt8 fromFP_DoubleTo_Int8(const SDouble a);
+SInt16 fromFP_DoubleTo_Int16(const SDouble a);
+SInt32 fromFP_DoubleTo_Int32(const SDouble a);
+SInt64 fromFP_DoubleTo_Int64(const SDouble a);
+SWord8 fromFP_DoubleTo_Word8(const SDouble a);
+SWord16 fromFP_DoubleTo_Word16(const SDouble a);
+SWord32 fromFP_DoubleTo_Word32(const SDouble a);
+SWord64 fromFP_DoubleTo_Word64(const SDouble a);
+SFloat fromFP_DoubleTo_Float(const SDouble a);
+SDouble fromFP_DoubleTo_Double(const SDouble a);
+SInteger fromFP_DoubleTo_Integer(const SDouble a);
+SReal fromFP_DoubleTo_Real(const SDouble a);
+SFloat fromFP_SWord32_SFloat(const SWord32 a);
+SDouble fromFP_SWord64_SDouble(const SWord64 a);
+SWord32 fromFP_SFloat_SWord32(const SFloat a);
+SWord64 fromFP_SDouble_SWord64(const SDouble a);
+SFloat f_FP_Abs(const SFloat a);
+SDouble d_FP_Abs(const SDouble a);
+SFloat f_FP_Neg(const SFloat a);
+SDouble d_FP_Neg(const SDouble a);
+SFloat f_FP_Add(const SFloat a, const SFloat b);
+SDouble d_FP_Add(const SDouble a, const SDouble b);
+SFloat f_FP_Sub(const SFloat a, const SFloat b);
+SDouble d_FP_Sub(const SDouble a, const SDouble b);
+SFloat f_FP_Mul(const SFloat a, const SFloat b);
+SDouble d_FP_Mul(const SDouble a, const SDouble b);
+SFloat f_FP_Div(const SFloat a, const SFloat b);
+SDouble d_FP_Div(const SDouble a, const SDouble b);
+SFloat f_FP_FMA(const SFloat a, const SFloat b, const SFloat c);
+SDouble d_FP_FMA(const SDouble a, const SDouble b,
+                 const SDouble c);
+SFloat f_FP_Sqrt(const SFloat a);
+SDouble d_FP_Sqrt(const SDouble a);
+SFloat f_FP_Rem(const SFloat a, const SFloat b);
+SDouble d_FP_Rem(const SDouble a, const SDouble b);
+SFloat f_FP_RoundToIntegral(const SFloat a);
+SDouble d_FP_RoundToIntegral(const SDouble a);
+SFloat f_FP_Min(const SFloat a, const SFloat b);
+SDouble d_FP_Min(const SDouble a, const SDouble b);
+SFloat f_FP_Max(const SFloat a, const SFloat b);
+SDouble d_FP_Max(const SDouble a, const SDouble b);
+SBool f_FP_IsEqualObject(const SFloat a, const SFloat b);
+SBool d_FP_IsEqualObject(const SDouble a, const SDouble b);
+SBool f_FP_IsNormal(const SFloat a);
+SBool d_FP_IsNormal(const SDouble a);
+SBool f_FP_IsZero(const SFloat a);
+SBool d_FP_IsZero(const SDouble a);
+SBool f_FP_IsSubnormal(const SFloat a);
+SBool d_FP_IsSubnormal(const SDouble a);
+SBool f_FP_IsInfinite(const SFloat a);
+SBool d_FP_IsInfinite(const SDouble a);
+SBool f_FP_IsNaN(const SFloat a);
+SBool d_FP_IsNaN(const SDouble a);
+SBool f_FP_IsNegative(const SFloat a);
+SBool d_FP_IsNegative(const SDouble a);
+SBool f_FP_IsPositive(const SFloat a);
+SBool d_FP_IsPositive(const SDouble a);
+
+#endif /* __floatCodeGen__HEADER_INCLUDED__ */
+== END: "floatCodeGen.h" ==================
+== BEGIN: "floatCodeGen_driver.c" ================
+/* Example driver program for floatCodeGen. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "floatCodeGen.h"
+
+void toFP_Int8_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Int8_ToFloat(42);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Int32_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Int32_ToFloat(0x0000002aL);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Word8_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Word8_ToFloat(42);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Word32_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Word32_ToFloat(0x0000002aUL);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Float_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Float_ToFloat(0x1.5p5F /* 42.0F */);
+
+  printf("toFP_Float_ToFloat(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void toFP_Double_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Double_ToFloat(0x1.5p5 /* 42.0 */);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Real_ToFloat_driver(void)
+{
+  const SFloat __result = toFP_Real_ToFloat(42.0L);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Int16_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Int16_ToDouble(0x002a);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Int64_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Int64_ToDouble(0x000000000000002aLL);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Word16_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Word16_ToDouble(0x002aU);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Word64_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Word64_ToDouble(0x000000000000002aULL);
+
+  printf("toFP_Word64_ToDouble(0x000000000000002aULL) = %a\n", __result);
+}
+
+void toFP_Float_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Float_ToDouble(0x1.5p5F /* 42.0F */);
+
+  printf("toFP_Float_ToDouble(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void toFP_Double_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Double_ToDouble(0x1.5p5 /* 42.0 */);
+
+  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) = %a\n", __result);
+}
+
+void toFP_Real_ToDouble_driver(void)
+{
+  const SDouble __result = toFP_Real_ToDouble(42.0L);
+
+  printf("toFP_Real_ToDouble(42.0L) = %a\n", __result);
+}
+
+void fromFP_Float_ToInt8_driver(void)
+{
+  const SInt8 __result = fromFP_Float_ToInt8(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToInt8(0x1.5p5F /* 42.0F */) = %"PRId8"\n", __result);
+}
+
+void fromFP_Float_ToInt16_driver(void)
+{
+  const SInt16 __result = fromFP_Float_ToInt16(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToInt16(0x1.5p5F /* 42.0F */) = %"PRId16"\n", __result);
+}
+
+void fromFP_Float_ToInt32_driver(void)
+{
+  const SInt32 __result = fromFP_Float_ToInt32(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToInt32(0x1.5p5F /* 42.0F */) = %"PRId32"L\n", __result);
+}
+
+void fromFP_Float_ToInt64_driver(void)
+{
+  const SInt64 __result = fromFP_Float_ToInt64(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToInt64(0x1.5p5F /* 42.0F */) = %"PRId64"LL\n", __result);
+}
+
+void fromFP_Float_ToWord8_driver(void)
+{
+  const SWord8 __result = fromFP_Float_ToWord8(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToWord8(0x1.5p5F /* 42.0F */) = %"PRIu8"\n", __result);
+}
+
+void fromFP_Float_ToWord16_driver(void)
+{
+  const SWord16 __result = fromFP_Float_ToWord16(0x1.5p5F /* 42.0F */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToFloat(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void fromFP_Float_ToDouble_driver(void)
+{
+  const SDouble __result = fromFP_Float_ToDouble(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToDouble(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void fromFP_Float_ToInteger_driver(void)
+{
+  const SInteger __result = fromFP_Float_ToInteger(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToInteger(0x1.5p5F /* 42.0F */) = %"PRId64"LL\n", __result);
+}
+
+void fromFP_Float_ToReal_driver(void)
+{
+  const SReal __result = fromFP_Float_ToReal(0x1.5p5F /* 42.0F */);
+
+  printf("fromFP_Float_ToReal(0x1.5p5F /* 42.0F */) = %Lf\n", __result);
+}
+
+void fromFP_DoubleTo_Int8_driver(void)
+{
+  const SInt8 __result = fromFP_DoubleTo_Int8(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Int8(0x1.5p5 /* 42.0 */) = %"PRId8"\n", __result);
+}
+
+void fromFP_DoubleTo_Int16_driver(void)
+{
+  const SInt16 __result = fromFP_DoubleTo_Int16(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Int16(0x1.5p5 /* 42.0 */) = %"PRId16"\n", __result);
+}
+
+void fromFP_DoubleTo_Int32_driver(void)
+{
+  const SInt32 __result = fromFP_DoubleTo_Int32(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Int32(0x1.5p5 /* 42.0 */) = %"PRId32"L\n", __result);
+}
+
+void fromFP_DoubleTo_Int64_driver(void)
+{
+  const SInt64 __result = fromFP_DoubleTo_Int64(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Int64(0x1.5p5 /* 42.0 */) = %"PRId64"LL\n", __result);
+}
+
+void fromFP_DoubleTo_Word8_driver(void)
+{
+  const SWord8 __result = fromFP_DoubleTo_Word8(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Word8(0x1.5p5 /* 42.0 */) = %"PRIu8"\n", __result);
+}
+
+void fromFP_DoubleTo_Word16_driver(void)
+{
+  const SWord16 __result = fromFP_DoubleTo_Word16(0x1.5p5 /* 42.0 */);
+
+  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(0x1.5p5 /* 42.0 */);
+
+  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(0x1.5p5 /* 42.0 */);
+
+  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(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Float(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void fromFP_DoubleTo_Double_driver(void)
+{
+  const SDouble __result = fromFP_DoubleTo_Double(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Double(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void fromFP_DoubleTo_Integer_driver(void)
+{
+  const SInteger __result = fromFP_DoubleTo_Integer(0x1.5p5 /* 42.0 */);
+
+  printf("fromFP_DoubleTo_Integer(0x1.5p5 /* 42.0 */) = %"PRId64"LL\n", __result);
+}
+
+void fromFP_DoubleTo_Real_driver(void)
+{
+  const SReal __result = fromFP_DoubleTo_Real(0x1.5p5 /* 42.0 */);
+
+  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) = %a\n", __result);
+}
+
+void fromFP_SWord64_SDouble_driver(void)
+{
+  const SDouble __result = fromFP_SWord64_SDouble(0x000000000000002aULL);
+
+  printf("fromFP_SWord64_SDouble(0x000000000000002aULL) = %a\n", __result);
+}
+
+void fromFP_SFloat_SWord32_driver(void)
+{
+  const SWord32 __result = fromFP_SFloat_SWord32(0x1.5p5F /* 42.0F */);
+
+  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(0x1.5p5 /* 42.0 */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_Abs(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void d_FP_Abs_driver(void)
+{
+  const SDouble __result = d_FP_Abs(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_Abs(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void f_FP_Neg_driver(void)
+{
+  const SFloat __result = f_FP_Neg(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_Neg(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void d_FP_Neg_driver(void)
+{
+  const SDouble __result = d_FP_Neg(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_Neg(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void f_FP_Add_driver(void)
+{
+  const SFloat __result = f_FP_Add(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */, 0x1.6p5F /* 44.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */, 0x1.6p5 /* 44.0 */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_Sqrt(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void d_FP_Sqrt_driver(void)
+{
+  const SDouble __result = d_FP_Sqrt(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_Sqrt(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void f_FP_Rem_driver(void)
+{
+  const SFloat __result = f_FP_Rem(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_RoundToIntegral(0x1.5p5F /* 42.0F */) = %a\n", __result);
+}
+
+void d_FP_RoundToIntegral_driver(void)
+{
+  const SDouble __result = d_FP_RoundToIntegral(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_RoundToIntegral(0x1.5p5 /* 42.0 */) = %a\n", __result);
+}
+
+void f_FP_Min_driver(void)
+{
+  const SFloat __result = f_FP_Min(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */,
+                                            0x1.58p5F /* 43.0F */);
+
+  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(0x1.5p5 /* 42.0 */,
+                                            0x1.58p5 /* 43.0 */);
+
+  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(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsNormal(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsNormal_driver(void)
+{
+  const SBool __result = d_FP_IsNormal(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsNormal(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsZero_driver(void)
+{
+  const SBool __result = f_FP_IsZero(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsZero(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsZero_driver(void)
+{
+  const SBool __result = d_FP_IsZero(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsZero(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsSubnormal_driver(void)
+{
+  const SBool __result = f_FP_IsSubnormal(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsSubnormal(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsSubnormal_driver(void)
+{
+  const SBool __result = d_FP_IsSubnormal(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsSubnormal(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsInfinite_driver(void)
+{
+  const SBool __result = f_FP_IsInfinite(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsInfinite(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsInfinite_driver(void)
+{
+  const SBool __result = d_FP_IsInfinite(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsInfinite(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsNaN_driver(void)
+{
+  const SBool __result = f_FP_IsNaN(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsNaN(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsNaN_driver(void)
+{
+  const SBool __result = d_FP_IsNaN(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsNaN(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsNegative_driver(void)
+{
+  const SBool __result = f_FP_IsNegative(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsNegative(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsNegative_driver(void)
+{
+  const SBool __result = d_FP_IsNegative(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsNegative(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+void f_FP_IsPositive_driver(void)
+{
+  const SBool __result = f_FP_IsPositive(0x1.5p5F /* 42.0F */);
+
+  printf("f_FP_IsPositive(0x1.5p5F /* 42.0F */) = %d\n", __result);
+}
+
+void d_FP_IsPositive_driver(void)
+{
+  const SBool __result = d_FP_IsPositive(0x1.5p5 /* 42.0 */);
+
+  printf("d_FP_IsPositive(0x1.5p5 /* 42.0 */) = %d\n", __result);
+}
+
+int main(void)
+{
+  printf("====================================\n");
+  printf("** Driver run for toFP_Int8_ToFloat:\n");
+  printf("====================================\n");
+  toFP_Int8_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Int16_ToFloat:\n");
+  printf("=====================================\n");
+  toFP_Int16_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Int32_ToFloat:\n");
+  printf("=====================================\n");
+  toFP_Int32_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Int64_ToFloat:\n");
+  printf("=====================================\n");
+  toFP_Int64_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Word8_ToFloat:\n");
+  printf("=====================================\n");
+  toFP_Word8_ToFloat_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Word16_ToFloat:\n");
+  printf("======================================\n");
+  toFP_Word16_ToFloat_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Word32_ToFloat:\n");
+  printf("======================================\n");
+  toFP_Word32_ToFloat_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Word64_ToFloat:\n");
+  printf("======================================\n");
+  toFP_Word64_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Float_ToFloat:\n");
+  printf("=====================================\n");
+  toFP_Float_ToFloat_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Double_ToFloat:\n");
+  printf("======================================\n");
+  toFP_Double_ToFloat_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for toFP_Integer_ToFloat:\n");
+  printf("=======================================\n");
+  toFP_Integer_ToFloat_driver();
+
+  printf("====================================\n");
+  printf("** Driver run for toFP_Real_ToFloat:\n");
+  printf("====================================\n");
+  toFP_Real_ToFloat_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Int8_ToDouble:\n");
+  printf("=====================================\n");
+  toFP_Int8_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Int16_ToDouble:\n");
+  printf("======================================\n");
+  toFP_Int16_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Int32_ToDouble:\n");
+  printf("======================================\n");
+  toFP_Int32_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Int64_ToDouble:\n");
+  printf("======================================\n");
+  toFP_Int64_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Word8_ToDouble:\n");
+  printf("======================================\n");
+  toFP_Word8_ToDouble_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for toFP_Word16_ToDouble:\n");
+  printf("=======================================\n");
+  toFP_Word16_ToDouble_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for toFP_Word32_ToDouble:\n");
+  printf("=======================================\n");
+  toFP_Word32_ToDouble_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for toFP_Word64_ToDouble:\n");
+  printf("=======================================\n");
+  toFP_Word64_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for toFP_Float_ToDouble:\n");
+  printf("======================================\n");
+  toFP_Float_ToDouble_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for toFP_Double_ToDouble:\n");
+  printf("=======================================\n");
+  toFP_Double_ToDouble_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for toFP_Integer_ToDouble:\n");
+  printf("========================================\n");
+  toFP_Integer_ToDouble_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for toFP_Real_ToDouble:\n");
+  printf("=====================================\n");
+  toFP_Real_ToDouble_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for fromFP_Float_ToInt8:\n");
+  printf("======================================\n");
+  fromFP_Float_ToInt8_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_Float_ToInt16:\n");
+  printf("=======================================\n");
+  fromFP_Float_ToInt16_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_Float_ToInt32:\n");
+  printf("=======================================\n");
+  fromFP_Float_ToInt32_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_Float_ToInt64:\n");
+  printf("=======================================\n");
+  fromFP_Float_ToInt64_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_Float_ToWord8:\n");
+  printf("=======================================\n");
+  fromFP_Float_ToWord8_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_Float_ToWord16:\n");
+  printf("========================================\n");
+  fromFP_Float_ToWord16_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_Float_ToWord32:\n");
+  printf("========================================\n");
+  fromFP_Float_ToWord32_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_Float_ToWord64:\n");
+  printf("========================================\n");
+  fromFP_Float_ToWord64_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_Float_ToFloat:\n");
+  printf("=======================================\n");
+  fromFP_Float_ToFloat_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_Float_ToDouble:\n");
+  printf("========================================\n");
+  fromFP_Float_ToDouble_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_Float_ToInteger:\n");
+  printf("=========================================\n");
+  fromFP_Float_ToInteger_driver();
+
+  printf("======================================\n");
+  printf("** Driver run for fromFP_Float_ToReal:\n");
+  printf("======================================\n");
+  fromFP_Float_ToReal_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Int8:\n");
+  printf("=======================================\n");
+  fromFP_DoubleTo_Int8_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Int16:\n");
+  printf("========================================\n");
+  fromFP_DoubleTo_Int16_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Int32:\n");
+  printf("========================================\n");
+  fromFP_DoubleTo_Int32_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Int64:\n");
+  printf("========================================\n");
+  fromFP_DoubleTo_Int64_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Word8:\n");
+  printf("========================================\n");
+  fromFP_DoubleTo_Word8_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Word16:\n");
+  printf("=========================================\n");
+  fromFP_DoubleTo_Word16_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Word32:\n");
+  printf("=========================================\n");
+  fromFP_DoubleTo_Word32_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Word64:\n");
+  printf("=========================================\n");
+  fromFP_DoubleTo_Word64_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Float:\n");
+  printf("========================================\n");
+  fromFP_DoubleTo_Float_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Double:\n");
+  printf("=========================================\n");
+  fromFP_DoubleTo_Double_driver();
+
+  printf("==========================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Integer:\n");
+  printf("==========================================\n");
+  fromFP_DoubleTo_Integer_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for fromFP_DoubleTo_Real:\n");
+  printf("=======================================\n");
+  fromFP_DoubleTo_Real_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_SWord32_SFloat:\n");
+  printf("========================================\n");
+  fromFP_SWord32_SFloat_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_SWord64_SDouble:\n");
+  printf("=========================================\n");
+  fromFP_SWord64_SDouble_driver();
+
+  printf("========================================\n");
+  printf("** Driver run for fromFP_SFloat_SWord32:\n");
+  printf("========================================\n");
+  fromFP_SFloat_SWord32_driver();
+
+  printf("=========================================\n");
+  printf("** Driver run for fromFP_SDouble_SWord64:\n");
+  printf("=========================================\n");
+  fromFP_SDouble_SWord64_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Abs:\n");
+  printf("===========================\n");
+  f_FP_Abs_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Abs:\n");
+  printf("===========================\n");
+  d_FP_Abs_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Neg:\n");
+  printf("===========================\n");
+  f_FP_Neg_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Neg:\n");
+  printf("===========================\n");
+  d_FP_Neg_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Add:\n");
+  printf("===========================\n");
+  f_FP_Add_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Add:\n");
+  printf("===========================\n");
+  d_FP_Add_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Sub:\n");
+  printf("===========================\n");
+  f_FP_Sub_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Sub:\n");
+  printf("===========================\n");
+  d_FP_Sub_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Mul:\n");
+  printf("===========================\n");
+  f_FP_Mul_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Mul:\n");
+  printf("===========================\n");
+  d_FP_Mul_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Div:\n");
+  printf("===========================\n");
+  f_FP_Div_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Div:\n");
+  printf("===========================\n");
+  d_FP_Div_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_FMA:\n");
+  printf("===========================\n");
+  f_FP_FMA_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_FMA:\n");
+  printf("===========================\n");
+  d_FP_FMA_driver();
+
+  printf("============================\n");
+  printf("** Driver run for f_FP_Sqrt:\n");
+  printf("============================\n");
+  f_FP_Sqrt_driver();
+
+  printf("============================\n");
+  printf("** Driver run for d_FP_Sqrt:\n");
+  printf("============================\n");
+  d_FP_Sqrt_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Rem:\n");
+  printf("===========================\n");
+  f_FP_Rem_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Rem:\n");
+  printf("===========================\n");
+  d_FP_Rem_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for f_FP_RoundToIntegral:\n");
+  printf("=======================================\n");
+  f_FP_RoundToIntegral_driver();
+
+  printf("=======================================\n");
+  printf("** Driver run for d_FP_RoundToIntegral:\n");
+  printf("=======================================\n");
+  d_FP_RoundToIntegral_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Min:\n");
+  printf("===========================\n");
+  f_FP_Min_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Min:\n");
+  printf("===========================\n");
+  d_FP_Min_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for f_FP_Max:\n");
+  printf("===========================\n");
+  f_FP_Max_driver();
+
+  printf("===========================\n");
+  printf("** Driver run for d_FP_Max:\n");
+  printf("===========================\n");
+  d_FP_Max_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for f_FP_IsEqualObject:\n");
+  printf("=====================================\n");
+  f_FP_IsEqualObject_driver();
+
+  printf("=====================================\n");
+  printf("** Driver run for d_FP_IsEqualObject:\n");
+  printf("=====================================\n");
+  d_FP_IsEqualObject_driver();
+
+  printf("================================\n");
+  printf("** Driver run for f_FP_IsNormal:\n");
+  printf("================================\n");
+  f_FP_IsNormal_driver();
+
+  printf("================================\n");
+  printf("** Driver run for d_FP_IsNormal:\n");
+  printf("================================\n");
+  d_FP_IsNormal_driver();
+
+  printf("==============================\n");
+  printf("** Driver run for f_FP_IsZero:\n");
+  printf("==============================\n");
+  f_FP_IsZero_driver();
+
+  printf("==============================\n");
+  printf("** Driver run for d_FP_IsZero:\n");
+  printf("==============================\n");
+  d_FP_IsZero_driver();
+
+  printf("===================================\n");
+  printf("** Driver run for f_FP_IsSubnormal:\n");
+  printf("===================================\n");
+  f_FP_IsSubnormal_driver();
+
+  printf("===================================\n");
+  printf("** Driver run for d_FP_IsSubnormal:\n");
+  printf("===================================\n");
+  d_FP_IsSubnormal_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for f_FP_IsInfinite:\n");
+  printf("==================================\n");
+  f_FP_IsInfinite_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for d_FP_IsInfinite:\n");
+  printf("==================================\n");
+  d_FP_IsInfinite_driver();
+
+  printf("=============================\n");
+  printf("** Driver run for f_FP_IsNaN:\n");
+  printf("=============================\n");
+  f_FP_IsNaN_driver();
+
+  printf("=============================\n");
+  printf("** Driver run for d_FP_IsNaN:\n");
+  printf("=============================\n");
+  d_FP_IsNaN_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for f_FP_IsNegative:\n");
+  printf("==================================\n");
+  f_FP_IsNegative_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for d_FP_IsNegative:\n");
+  printf("==================================\n");
+  d_FP_IsNegative_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for f_FP_IsPositive:\n");
+  printf("==================================\n");
+  f_FP_IsPositive_driver();
+
+  printf("==================================\n");
+  printf("** Driver run for d_FP_IsPositive:\n");
+  printf("==================================\n");
+  d_FP_IsPositive_driver();
+
+  return 0;
+}
+== END: "floatCodeGen_driver.c" ==================
+== BEGIN: "Makefile" ================
+# Makefile for floatCodeGen. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+LDFLAGS?=-lm
+AR?=ar
+ARFLAGS?=cr
+
+all: floatCodeGen.a floatCodeGen_driver
+
+floatCodeGen.a: toFP_Int8_ToFloat.o toFP_Int16_ToFloat.o toFP_Int32_ToFloat.o toFP_Int64_ToFloat.o toFP_Word8_ToFloat.o toFP_Word16_ToFloat.o toFP_Word32_ToFloat.o toFP_Word64_ToFloat.o toFP_Float_ToFloat.o toFP_Double_ToFloat.o toFP_Integer_ToFloat.o toFP_Real_ToFloat.o toFP_Int8_ToDouble.o toFP_Int16_ToDouble.o toFP_Int32_ToDouble.o toFP_Int64_ToDouble.o toFP_Word8_ToDouble.o toFP_Word16_ToDouble.o toFP_Word32_ToDouble.o toFP_Word64_ToDouble.o toFP_Float_ToDouble.o toFP_Double_ToDouble.o toFP_Integer_ToDouble.o toFP_Real_ToDouble.o fromFP_Float_ToInt8.o fromFP_Float_ToInt16.o fromFP_Float_ToInt32.o fromFP_Float_ToInt64.o fromFP_Float_ToWord8.o fromFP_Float_ToWord16.o fromFP_Float_ToWord32.o fromFP_Float_ToWord64.o fromFP_Float_ToFloat.o fromFP_Float_ToDouble.o fromFP_Float_ToInteger.o fromFP_Float_ToReal.o fromFP_DoubleTo_Int8.o fromFP_DoubleTo_Int16.o fromFP_DoubleTo_Int32.o fromFP_DoubleTo_Int64.o fromFP_DoubleTo_Word8.o fromFP_DoubleTo_Word16.o fromFP_DoubleTo_Word32.o fromFP_DoubleTo_Word64.o fromFP_DoubleTo_Float.o fromFP_DoubleTo_Double.o fromFP_DoubleTo_Integer.o fromFP_DoubleTo_Real.o fromFP_SWord32_SFloat.o fromFP_SWord64_SDouble.o fromFP_SFloat_SWord32.o fromFP_SDouble_SWord64.o f_FP_Abs.o d_FP_Abs.o f_FP_Neg.o d_FP_Neg.o f_FP_Add.o d_FP_Add.o f_FP_Sub.o d_FP_Sub.o f_FP_Mul.o d_FP_Mul.o f_FP_Div.o d_FP_Div.o f_FP_FMA.o d_FP_FMA.o f_FP_Sqrt.o d_FP_Sqrt.o f_FP_Rem.o d_FP_Rem.o f_FP_RoundToIntegral.o d_FP_RoundToIntegral.o f_FP_Min.o d_FP_Min.o f_FP_Max.o d_FP_Max.o f_FP_IsEqualObject.o d_FP_IsEqualObject.o f_FP_IsNormal.o d_FP_IsNormal.o f_FP_IsZero.o d_FP_IsZero.o f_FP_IsSubnormal.o d_FP_IsSubnormal.o f_FP_IsInfinite.o d_FP_IsInfinite.o f_FP_IsNaN.o d_FP_IsNaN.o f_FP_IsNegative.o d_FP_IsNegative.o f_FP_IsPositive.o d_FP_IsPositive.o
+	${AR} ${ARFLAGS} $@ $^
+
+floatCodeGen_driver: floatCodeGen_driver.c floatCodeGen.h
+	${CC} ${CCFLAGS} $< -o $@ floatCodeGen.a ${LDFLAGS}
+
+toFP_Int8_ToFloat.o: toFP_Int8_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int16_ToFloat.o: toFP_Int16_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int32_ToFloat.o: toFP_Int32_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int64_ToFloat.o: toFP_Int64_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word8_ToFloat.o: toFP_Word8_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word16_ToFloat.o: toFP_Word16_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word32_ToFloat.o: toFP_Word32_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word64_ToFloat.o: toFP_Word64_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Float_ToFloat.o: toFP_Float_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Double_ToFloat.o: toFP_Double_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Integer_ToFloat.o: toFP_Integer_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Real_ToFloat.o: toFP_Real_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int8_ToDouble.o: toFP_Int8_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int16_ToDouble.o: toFP_Int16_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int32_ToDouble.o: toFP_Int32_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Int64_ToDouble.o: toFP_Int64_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word8_ToDouble.o: toFP_Word8_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word16_ToDouble.o: toFP_Word16_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word32_ToDouble.o: toFP_Word32_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Word64_ToDouble.o: toFP_Word64_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Float_ToDouble.o: toFP_Float_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Double_ToDouble.o: toFP_Double_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Integer_ToDouble.o: toFP_Integer_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+toFP_Real_ToDouble.o: toFP_Real_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToInt8.o: fromFP_Float_ToInt8.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToInt16.o: fromFP_Float_ToInt16.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToInt32.o: fromFP_Float_ToInt32.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToInt64.o: fromFP_Float_ToInt64.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToWord8.o: fromFP_Float_ToWord8.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToWord16.o: fromFP_Float_ToWord16.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToWord32.o: fromFP_Float_ToWord32.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToWord64.o: fromFP_Float_ToWord64.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToFloat.o: fromFP_Float_ToFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToDouble.o: fromFP_Float_ToDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToInteger.o: fromFP_Float_ToInteger.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_Float_ToReal.o: fromFP_Float_ToReal.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Int8.o: fromFP_DoubleTo_Int8.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Int16.o: fromFP_DoubleTo_Int16.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Int32.o: fromFP_DoubleTo_Int32.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Int64.o: fromFP_DoubleTo_Int64.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Word8.o: fromFP_DoubleTo_Word8.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Word16.o: fromFP_DoubleTo_Word16.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Word32.o: fromFP_DoubleTo_Word32.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Word64.o: fromFP_DoubleTo_Word64.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Float.o: fromFP_DoubleTo_Float.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Double.o: fromFP_DoubleTo_Double.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Integer.o: fromFP_DoubleTo_Integer.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_DoubleTo_Real.o: fromFP_DoubleTo_Real.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_SWord32_SFloat.o: fromFP_SWord32_SFloat.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_SWord64_SDouble.o: fromFP_SWord64_SDouble.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_SFloat_SWord32.o: fromFP_SFloat_SWord32.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+fromFP_SDouble_SWord64.o: fromFP_SDouble_SWord64.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Abs.o: f_FP_Abs.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Abs.o: d_FP_Abs.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Neg.o: f_FP_Neg.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Neg.o: d_FP_Neg.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Add.o: f_FP_Add.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Add.o: d_FP_Add.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Sub.o: f_FP_Sub.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Sub.o: d_FP_Sub.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Mul.o: f_FP_Mul.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Mul.o: d_FP_Mul.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Div.o: f_FP_Div.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Div.o: d_FP_Div.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_FMA.o: f_FP_FMA.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_FMA.o: d_FP_FMA.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Sqrt.o: f_FP_Sqrt.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Sqrt.o: d_FP_Sqrt.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Rem.o: f_FP_Rem.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Rem.o: d_FP_Rem.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_RoundToIntegral.o: f_FP_RoundToIntegral.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_RoundToIntegral.o: d_FP_RoundToIntegral.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Min.o: f_FP_Min.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Min.o: d_FP_Min.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_Max.o: f_FP_Max.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_Max.o: d_FP_Max.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsEqualObject.o: f_FP_IsEqualObject.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsEqualObject.o: d_FP_IsEqualObject.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsNormal.o: f_FP_IsNormal.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsNormal.o: d_FP_IsNormal.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsZero.o: f_FP_IsZero.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsZero.o: d_FP_IsZero.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsSubnormal.o: f_FP_IsSubnormal.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsSubnormal.o: d_FP_IsSubnormal.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsInfinite.o: f_FP_IsInfinite.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsInfinite.o: d_FP_IsInfinite.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsNaN.o: f_FP_IsNaN.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsNaN.o: d_FP_IsNaN.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsNegative.o: f_FP_IsNegative.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsNegative.o: d_FP_IsNegative.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+f_FP_IsPositive.o: f_FP_IsPositive.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+d_FP_IsPositive.o: d_FP_IsPositive.c floatCodeGen.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f floatCodeGen.a floatCodeGen_driver
+== END: "Makefile" ==================
diff --git a/SBVTestSuite/GoldFiles/freshVars.gold b/SBVTestSuite/GoldFiles/freshVars.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/freshVars.gold
@@ -0,0 +1,238 @@
+** 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 :pp.max_depth 4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (declare-fun s3 () Bool)
+[GOOD] (declare-fun s4 () (_ BitVec 8))
+[GOOD] (declare-fun s5 () (_ BitVec 16))
+[GOOD] (declare-fun s6 () (_ BitVec 32))
+[GOOD] (declare-fun s7 () (_ BitVec 64))
+[GOOD] (declare-fun s8 () (_ BitVec 8))
+[GOOD] (declare-fun s9 () (_ BitVec 16))
+[GOOD] (declare-fun s10 () (_ BitVec 32))
+[GOOD] (declare-fun s11 () (_ BitVec 64))
+[GOOD] (declare-fun s12 () (_ FloatingPoint  8 24))
+[GOOD] (declare-fun s13 () (_ FloatingPoint 11 53))
+[GOOD] (declare-fun s14 () Real)
+[GOOD] (declare-fun s15 () Int)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: BinOp
+[GOOD] (declare-datatype BinOp (
+           (Plus)
+           (Minus)
+           (Times)
+       ))
+[GOOD] (declare-fun s16 () BinOp)
+[GOOD] (declare-fun s17 () (_ FloatingPoint 15 113))
+[GOOD] (declare-fun s18 () (_ FloatingPoint 15 113))
+[GOOD] (assert s3)
+[GOOD] (define-fun s19 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s20 () Bool (= s4 s19))
+[GOOD] (assert s20)
+[GOOD] (define-fun s21 () (_ BitVec 16) #x0002)
+[GOOD] (define-fun s22 () Bool (= s5 s21))
+[GOOD] (assert s22)
+[GOOD] (define-fun s23 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s24 () Bool (= s6 s23))
+[GOOD] (assert s24)
+[GOOD] (define-fun s25 () (_ BitVec 64) #x0000000000000004)
+[GOOD] (define-fun s26 () Bool (= s7 s25))
+[GOOD] (assert s26)
+[GOOD] (define-fun s27 () (_ BitVec 8) #x05)
+[GOOD] (define-fun s28 () Bool (= s8 s27))
+[GOOD] (assert s28)
+[GOOD] (define-fun s29 () (_ BitVec 16) #x0006)
+[GOOD] (define-fun s30 () Bool (= s9 s29))
+[GOOD] (assert s30)
+[GOOD] (define-fun s31 () (_ BitVec 32) #x00000007)
+[GOOD] (define-fun s32 () Bool (= s10 s31))
+[GOOD] (assert s32)
+[GOOD] (define-fun s33 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s34 () Bool (= s11 s33))
+[GOOD] (assert s34)
+[GOOD] (define-fun s35 () (_ FloatingPoint  8 24) (fp #b0 #b10000010 #b00100000000000000000000))
+[GOOD] (define-fun s36 () Bool (fp.eq s12 s35))
+[GOOD] (assert s36)
+[GOOD] (define-fun s37 () (_ FloatingPoint 11 53) (fp #b0 #b10000000010 #b0100000000000000000000000000000000000000000000000000))
+[GOOD] (define-fun s38 () Bool (fp.eq s13 s37))
+[GOOD] (assert s38)
+[GOOD] (define-fun s39 () Real (/ 11.0 1.0))
+[GOOD] (define-fun s40 () Bool (= s14 s39))
+[GOOD] (assert s40)
+[GOOD] (define-fun s41 () Int 12)
+[GOOD] (define-fun s42 () Bool (= s15 s41))
+[GOOD] (assert s42)
+[GOOD] (define-fun s43 () BinOp (as Plus BinOp))
+[GOOD] (define-fun s44 () Bool (= s16 s43))
+[GOOD] (assert s44)
+[GOOD] (define-fun s45 () Bool (fp.eq s17 s18))
+[GOOD] (assert s45)
+[GOOD] (define-fun s46 () Bool (= s17 s18))
+[GOOD] (define-fun s47 () Bool (not s46))
+[GOOD] (assert s47)
+[GOOD] (define-fun s48 () Bool (fp.isPositive s17))
+[GOOD] (assert s48)
+[GOOD] (declare-fun s49 () (Array Int Int))
+[GOOD] (declare-fun s50 () Int)
+[GOOD] (declare-fun s51 () Bool)
+[GOOD] (define-fun s53 () Int 2)
+[GOOD] (define-fun s52 () Int (select s49 s50))
+[GOOD] (define-fun s54 () Bool (= s52 s53))
+[GOOD] (assert s54)
+[GOOD] (declare-fun s55 () Int)
+[GOOD] (define-fun s56 () Int 42)
+[GOOD] (define-fun s57 () Bool (= s55 s56))
+[GOOD] (assert s57)
+[GOOD] (define-fun s58 () Int 1)
+[GOOD] (define-fun s59 () Bool (= s50 s58))
+[GOOD] (assert s59)
+[GOOD] (define-fun s60 () Bool (not s51))
+[GOOD] (assert s60)
+[GOOD] (declare-fun s61 () String)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (declare-fun s62 () (Seq Int))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (declare-fun s63 () (Seq (Seq Int)))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (declare-fun s64 () (Seq (_ BitVec 8)))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (declare-fun s65 () (Seq (Seq (_ BitVec 16))))
+[GOOD] (define-fun s66 () String "hello")
+[GOOD] (define-fun s67 () Bool (= s61 s66))
+[GOOD] (assert s67)
+[GOOD] (define-fun s68 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4)))
+[GOOD] (define-fun s69 () Bool (= s62 s68))
+[GOOD] (assert s69)
+[GOOD] (define-fun s70 () (Seq (Seq Int)) (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))) (seq.unit (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7)))))
+[GOOD] (define-fun s71 () Bool (= s63 s70))
+[GOOD] (assert s71)
+[GOOD] (define-fun s72 () (Seq (_ BitVec 8)) (seq.++ (seq.unit #x01) (seq.unit #x02)))
+[GOOD] (define-fun s73 () Bool (= s64 s72))
+[GOOD] (assert s73)
+[GOOD] (define-fun s74 () (Seq (Seq (_ BitVec 16))) (seq.++ (seq.unit (seq.++ (seq.unit #x0001) (seq.unit #x0002) (seq.unit #x0003))) (seq.unit (as seq.empty (Seq (_ BitVec 16)))) (seq.unit (seq.++ (seq.unit #x0004) (seq.unit #x0005) (seq.unit #x0006)))))
+[GOOD] (define-fun s75 () Bool (= s65 s74))
+[GOOD] (assert s75)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s3))
+[RECV] ((s3 true))
+[SEND] (get-value (s4))
+[RECV] ((s4 #x01))
+[SEND] (get-value (s5))
+[RECV] ((s5 #x0002))
+[SEND] (get-value (s6))
+[RECV] ((s6 #x00000003))
+[SEND] (get-value (s7))
+[RECV] ((s7 #x0000000000000004))
+[SEND] (get-value (s8))
+[RECV] ((s8 #x05))
+[SEND] (get-value (s9))
+[RECV] ((s9 #x0006))
+[SEND] (get-value (s10))
+[RECV] ((s10 #x00000007))
+[SEND] (get-value (s11))
+[RECV] ((s11 #x0000000000000008))
+[SEND] (get-value (s12))
+[RECV] ((s12 (fp #b0 #x82 #b00100000000000000000000)))
+[SEND] (get-value (s13))
+[RECV] ((s13 (fp #b0 #b10000000010 #x4000000000000)))
+[GOOD] (set-option :pp.decimal false)
+[SEND] (get-value (s14))
+[RECV] ((s14 11.0))
+[GOOD] (set-option :pp.decimal true)
+[GOOD] (set-option :pp.decimal_precision 16)
+[SEND] (get-value (s14))
+[RECV] ((s14 11.0))
+[SEND] (get-value (s15))
+[RECV] ((s15 12))
+[SEND] (get-value (s16))
+[RECV] ((s16 Plus))
+[SEND] (get-value (s49))
+[RECV] ((s49 ((as const (Array Int Int)) 2)))
+[SEND] (get-value (s50))
+[RECV] ((s50 1))
+[SEND] (get-value (s51))
+[RECV] ((s51 false))
+[SEND] (get-value (s55))
+[RECV] ((s55 42))
+[SEND] (get-value (s61))
+[RECV] ((s61 "hello"))
+[SEND] (get-value (s62))
+[RECV] ((s62 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4))))
+[SEND] (get-value (s63))
+[RECV] ((s63 (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+               (seq.unit (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7))))))
+[SEND] (get-value (s64))
+[RECV] ((s64 (seq.++ (seq.unit #x01) (seq.unit #x02))))
+[SEND] (get-value (s65))
+[RECV] ((s65 (seq.++ (seq.unit (seq.++ (seq.unit #x0001) (seq.unit #x0002) (seq.unit #x0003)))
+               (seq.unit (as seq.empty (Seq (_ BitVec 16))))
+               (seq.unit (seq.++ (seq.unit #x0004) (seq.unit #x0005) (seq.unit #x0006))))))
+[SEND] (get-value (s17))
+[RECV] ((s17 (_ +zero 15 113)))
+[SEND] (get-value (s18))
+[RECV] ((s18 (_ -zero 15 113)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Satisfiable. Model:
+  a        =                    0 :: Integer
+  vBool    =                 True :: Bool
+  vWord8   =                    1 :: Word8
+  s5       =                    2 :: Word16
+  s6       =                    3 :: Word32
+  vWord64  =                    4 :: Word64
+  vInt8    =                    5 :: Int8
+  s9       =                    6 :: Int16
+  s10      =                    7 :: Int32
+  vInt64   =                    8 :: Int64
+  vFloat   =                  9.0 :: Float
+  s13      =                 10.0 :: Double
+  s14      =                 11.0 :: Real
+  vInteger =                   12 :: Integer
+  vBinOp   =                 Plus :: BinOp
+  vSArray  =              ([], 2) :: Array Integer Integer
+  i1       =                    1 :: Integer
+  i2       =                False :: Bool
+  mustBe42 =                   42 :: Integer
+  vString  =              "hello" :: String
+  vList1   =            [1,2,3,4] :: [Integer]
+  vList2   =  [[1,2,3],[4,5,6,7]] :: [[Integer]]
+  vList3   =                [1,2] :: [Word8]
+  vList4   = [[1,2,3],[],[4,5,6]] :: [[Word16]]
+  vQuad    =                  0.0 :: FloatingPoint 15 113
+  wQuad    =                 -0.0 :: FloatingPoint 15 113
+DONE!
diff --git a/SBVTestSuite/GoldFiles/gcd.gold b/SBVTestSuite/GoldFiles/gcd.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/gcd.gold
@@ -0,0 +1,141 @@
+== BEGIN: "Makefile" ================
+# Makefile for sgcd. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: sgcd_driver
+
+sgcd.o: sgcd.c sgcd.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+sgcd_driver.o: sgcd_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+sgcd_driver: sgcd.o sgcd_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f sgcd_driver
+== END: "Makefile" ==================
+== BEGIN: "sgcd.h" ================
+/* Header file for sgcd. Automatically generated by SBV. Do not edit! */
+
+#ifndef __sgcd__HEADER_INCLUDED__
+#define __sgcd__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord8 sgcd(const SWord8 x, const SWord8 y);
+
+#endif /* __sgcd__HEADER_INCLUDED__ */
+== END: "sgcd.h" ==================
+== BEGIN: "sgcd_driver.c" ================
+/* Example driver program for sgcd. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "sgcd.h"
+
+int main(void)
+{
+  const SWord8 __result = sgcd(55, 154);
+
+  printf("sgcd(55, 154) = %"PRIu8"\n", __result);
+
+  return 0;
+}
+== END: "sgcd_driver.c" ==================
+== BEGIN: "sgcd.c" ================
+/* File: "sgcd.c". Automatically generated by SBV. Do not edit! */
+
+#include "sgcd.h"
+
+SWord8 sgcd(const SWord8 x, const SWord8 y)
+{
+  const SWord8 s0 = x;
+  const SWord8 s1 = y;
+  const SBool  s3 = s1 == 0;
+  const SWord8 s4 = (s1 == 0) ? s0 : (s0 % s1);
+  const SWord8 s5 = s3 ? s0 : s4;
+  const SBool  s6 = 0 == s5;
+  const SWord8 s7 = (s5 == 0) ? s1 : (s1 % s5);
+  const SWord8 s8 = s6 ? s1 : s7;
+  const SBool  s9 = 0 == s8;
+  const SWord8 s10 = (s8 == 0) ? s5 : (s5 % s8);
+  const SWord8 s11 = s9 ? s5 : s10;
+  const SBool  s12 = 0 == s11;
+  const SWord8 s13 = (s11 == 0) ? s8 : (s8 % s11);
+  const SWord8 s14 = s12 ? s8 : s13;
+  const SBool  s15 = 0 == s14;
+  const SWord8 s16 = (s14 == 0) ? s11 : (s11 % s14);
+  const SWord8 s17 = s15 ? s11 : s16;
+  const SBool  s18 = 0 == s17;
+  const SWord8 s19 = (s17 == 0) ? s14 : (s14 % s17);
+  const SWord8 s20 = s18 ? s14 : s19;
+  const SBool  s21 = 0 == s20;
+  const SWord8 s22 = (s20 == 0) ? s17 : (s17 % s20);
+  const SWord8 s23 = s21 ? s17 : s22;
+  const SBool  s24 = 0 == s23;
+  const SWord8 s25 = (s23 == 0) ? s20 : (s20 % s23);
+  const SWord8 s26 = s24 ? s20 : s25;
+  const SBool  s27 = 0 == s26;
+  const SWord8 s28 = (s26 == 0) ? s23 : (s23 % s26);
+  const SWord8 s29 = s27 ? s23 : s28;
+  const SBool  s30 = 0 == s29;
+  const SWord8 s31 = (s29 == 0) ? s26 : (s26 % s29);
+  const SWord8 s32 = s30 ? s26 : s31;
+  const SBool  s33 = 0 == s32;
+  const SWord8 s34 = (s32 == 0) ? s29 : (s29 % s32);
+  const SWord8 s35 = s33 ? s29 : s34;
+  const SBool  s36 = 0 == s35;
+  const SWord8 s37 = s36 ? s32 : s35;
+  const SWord8 s38 = s33 ? s29 : s37;
+  const SWord8 s39 = s30 ? s26 : s38;
+  const SWord8 s40 = s27 ? s23 : s39;
+  const SWord8 s41 = s24 ? s20 : s40;
+  const SWord8 s42 = s21 ? s17 : s41;
+  const SWord8 s43 = s18 ? s14 : s42;
+  const SWord8 s44 = s15 ? s11 : s43;
+  const SWord8 s45 = s12 ? s8 : s44;
+  const SWord8 s46 = s9 ? s5 : s45;
+  const SWord8 s47 = s6 ? s1 : s46;
+  const SWord8 s48 = s3 ? s0 : s47;
+
+  return s48;
+}
+== END: "sgcd.c" ==================
diff --git a/SBVTestSuite/GoldFiles/genBenchMark1.gold b/SBVTestSuite/GoldFiles/genBenchMark1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/genBenchMark1.gold
@@ -0,0 +1,21 @@
+(set-option :smtlib2_compliant true)
+(set-option :diagnostic-output-channel "stdout")
+(set-option :produce-models true)
+(set-logic QF_BV)
+; --- tuples ---
+; --- sums ---
+; --- literal constants ---
+(define-fun s1 () (_ BitVec 8) #x01)
+; --- top level inputs ---
+(declare-fun s0 () (_ BitVec 8))
+; --- constant tables ---
+; --- non-constant tables ---
+; --- uninterpreted constants ---
+; --- user defined functions ---
+; --- assignments ---
+(define-fun s2 () (_ BitVec 8) (bvadd s0 s1))
+(define-fun s3 () Bool (= s0 s2))
+; --- delayedEqualities ---
+; --- formula ---
+(assert (not s3))
+(check-sat)
diff --git a/SBVTestSuite/GoldFiles/genBenchMark2.gold b/SBVTestSuite/GoldFiles/genBenchMark2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/genBenchMark2.gold
@@ -0,0 +1,21 @@
+(set-option :smtlib2_compliant true)
+(set-option :diagnostic-output-channel "stdout")
+(set-option :produce-models true)
+(set-logic QF_BV)
+; --- tuples ---
+; --- sums ---
+; --- literal constants ---
+(define-fun s1 () (_ BitVec 8) #x01)
+; --- top level inputs ---
+(declare-fun s0 () (_ BitVec 8))
+; --- constant tables ---
+; --- non-constant tables ---
+; --- uninterpreted constants ---
+; --- user defined functions ---
+; --- assignments ---
+(define-fun s2 () (_ BitVec 8) (bvadd s0 s1))
+(define-fun s3 () Bool (= s0 s2))
+; --- delayedEqualities ---
+; --- formula ---
+(assert s3)
+(check-sat)
diff --git a/SBVTestSuite/GoldFiles/higher-1.gold b/SBVTestSuite/GoldFiles/higher-1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-1.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-2.gold b/SBVTestSuite/GoldFiles/higher-2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-2.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-3.gold b/SBVTestSuite/GoldFiles/higher-3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-3.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-4.gold b/SBVTestSuite/GoldFiles/higher-4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-4.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-5.gold b/SBVTestSuite/GoldFiles/higher-5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-5.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-6.gold b/SBVTestSuite/GoldFiles/higher-6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-6.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-7.gold b/SBVTestSuite/GoldFiles/higher-7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-7.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-8.gold b/SBVTestSuite/GoldFiles/higher-8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-8.gold
@@ -0,0 +1,1 @@
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/higher-9.gold b/SBVTestSuite/GoldFiles/higher-9.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/higher-9.gold
@@ -0,0 +1,2 @@
+Falsifiable. Counter-example:
+  s0 = 128 :: Word8
diff --git a/SBVTestSuite/GoldFiles/lambda01.gold b/SBVTestSuite/GoldFiles/lambda01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda01.gold
@@ -0,0 +1,1 @@
+2
diff --git a/SBVTestSuite/GoldFiles/lambda02.gold b/SBVTestSuite/GoldFiles/lambda02.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda02.gold
@@ -0,0 +1,4 @@
+(lambda ((l1_s0 Int))
+                          (let ((l1_s1 1))
+                          (let ((l1_s2 (+ l1_s0 l1_s1)))
+                          l1_s2)))
diff --git a/SBVTestSuite/GoldFiles/lambda03.gold b/SBVTestSuite/GoldFiles/lambda03.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda03.gold
@@ -0,0 +1,5 @@
+(lambda ((l1_s0 Int) (l1_s1 Int))
+                          (let ((l1_s2 2))
+                          (let ((l1_s3 (* l1_s1 l1_s2)))
+                          (let ((l1_s4 (+ l1_s0 l1_s3)))
+                          l1_s4))))
diff --git a/SBVTestSuite/GoldFiles/lambda04.gold b/SBVTestSuite/GoldFiles/lambda04.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda04.gold
@@ -0,0 +1,151 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])
+[MEASURE] sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool]): barified = "|sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])}: replaying 8 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Bool) (as seq.empty (Seq Bool)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s9 () (Seq Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Bool) (seq.unit false))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s0 s2 s7))
+[GOOD] (define-fun s10 () (Seq Bool) (seq.++ s6 s9))
+[GOOD] (define-fun s11 () (Seq Bool) (ite s5 s3 s10))
+[GOOD] (define-fun s12 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])}: replaying 8 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Bool) (as seq.empty (Seq Bool)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s9 () (Seq Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Bool) (seq.unit false))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s0 s2 s7))
+[GOOD] (define-fun s10 () (Seq Bool) (seq.++ s6 s9))
+[GOOD] (define-fun s11 () (Seq Bool) (ite s5 s3 s10))
+[GOOD] (define-fun s12 () Int (seq.len s8))
+[GOOD] (define-fun s13 () Bool (not s5))
+[GOOD] (define-fun s14 () Bool (> s4 s12))
+[GOOD] (define-fun s15 () Bool (=> s13 s14))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Bool))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])| :: [SInteger] -> [SBool] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])| ((l1_s0 (Seq Int))) (Seq Bool)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Bool))))
+                                 (let ((l1_s6 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.unit false)))
+                                 (let ((l1_s7 (- l1_s1 l1_s6)))
+                                 (let ((l1_s8 (seq.extract l1_s0 l1_s6 l1_s7)))
+                                 (let ((l1_s9 (|sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])| l1_s8)))
+                                 (let ((l1_s10 (seq.++ l1_s5 l1_s9)))
+                                 (let ((l1_s11 (ite l1_s3 l1_s4 l1_s10)))
+                                 l1_s11))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Bool) (|sbv.map @(SBV Integer -> SBV Bool)_96a983e094 @(SBV [Integer] -> SBV [Bool])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit false) (seq.unit false) (seq.unit false))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit false) (seq.unit false) (seq.unit false))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =             [1,2,3] :: [Integer]
+  s1 = [False,False,False] :: [Bool]
diff --git a/SBVTestSuite/GoldFiles/lambda05.gold b/SBVTestSuite/GoldFiles/lambda05.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda05.gold
@@ -0,0 +1,273 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]), sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (+ s3 s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (+ s3 s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Int (seq.len s11))
+[GOOD] (define-fun s16 () Bool (not s6))
+[GOOD] (define-fun s17 () Bool (> s5 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq Int)) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (+ s2 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq Int) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq Int) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq Int)) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (+ s2 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq Int) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq Int) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Int (seq.len s10))
+[GOOD] (define-fun s15 () Bool (not s5))
+[GOOD] (define-fun s16 () Bool (> s4 s14))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s9 (- l1_s1 l1_s6)))
+                                 (let ((l1_s10 (seq.extract l1_s0 l1_s6 l1_s9)))
+                                 (let ((l1_s11 (|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| l1_s10)))
+                                 (let ((l1_s12 (seq.++ l1_s8 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s3 l1_s4 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; |sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 2))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.map @(SBV Integer -> SBV Integer)_6e8bf9627c @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () (Seq Int) (|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 = [4,5,6,7,8] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda06.gold b/SBVTestSuite/GoldFiles/lambda06.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda06.gold
@@ -0,0 +1,216 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])}: replaying 27 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s28 () (Seq Int)) ; tracks user variable "__internal_sbv_s28"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (* s6 s6))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (* s6 s7))
+[GOOD] (define-fun s10 () Int (+ s8 s9))
+[GOOD] (define-fun s11 () Int (* s7 s7))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () Int (* s6 s11))
+[GOOD] (define-fun s14 () Int (+ s12 s13))
+[GOOD] (define-fun s15 () Int (* s7 s11))
+[GOOD] (define-fun s16 () Int (+ s14 s15))
+[GOOD] (define-fun s17 () Int (* s6 s15))
+[GOOD] (define-fun s18 () Int (+ s16 s17))
+[GOOD] (define-fun s19 () Int (* s11 s11))
+[GOOD] (define-fun s20 () Int (+ s18 s19))
+[GOOD] (define-fun s21 () Int (* s6 s19))
+[GOOD] (define-fun s22 () Int (+ s20 s21))
+[GOOD] (define-fun s23 () Int (* s7 s19))
+[GOOD] (define-fun s24 () Int (+ s22 s23))
+[GOOD] (define-fun s25 () (Seq Int) (seq.unit s24))
+[GOOD] (define-fun s26 () Int (- s4 s2))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s0 s2 s26))
+[GOOD] (define-fun s29 () (Seq Int) (seq.++ s25 s28))
+[GOOD] (define-fun s30 () (Seq Int) (ite s5 s3 s29))
+[GOOD] (define-fun s31 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s31))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])}: replaying 27 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s28 () (Seq Int)) ; tracks user variable "__internal_sbv_s28"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (* s6 s6))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (* s6 s7))
+[GOOD] (define-fun s10 () Int (+ s8 s9))
+[GOOD] (define-fun s11 () Int (* s7 s7))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () Int (* s6 s11))
+[GOOD] (define-fun s14 () Int (+ s12 s13))
+[GOOD] (define-fun s15 () Int (* s7 s11))
+[GOOD] (define-fun s16 () Int (+ s14 s15))
+[GOOD] (define-fun s17 () Int (* s6 s15))
+[GOOD] (define-fun s18 () Int (+ s16 s17))
+[GOOD] (define-fun s19 () Int (* s11 s11))
+[GOOD] (define-fun s20 () Int (+ s18 s19))
+[GOOD] (define-fun s21 () Int (* s6 s19))
+[GOOD] (define-fun s22 () Int (+ s20 s21))
+[GOOD] (define-fun s23 () Int (* s7 s19))
+[GOOD] (define-fun s24 () Int (+ s22 s23))
+[GOOD] (define-fun s25 () (Seq Int) (seq.unit s24))
+[GOOD] (define-fun s26 () Int (- s4 s2))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s0 s2 s26))
+[GOOD] (define-fun s29 () (Seq Int) (seq.++ s25 s28))
+[GOOD] (define-fun s30 () (Seq Int) (ite s5 s3 s29))
+[GOOD] (define-fun s31 () Int (seq.len s27))
+[GOOD] (define-fun s32 () Bool (not s5))
+[GOOD] (define-fun s33 () Bool (> s4 s31))
+[GOOD] (define-fun s34 () Bool (=> s32 s33))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s34))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s25 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 (* l1_s5 l1_s5)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s8 (* l1_s5 l1_s6)))
+                                 (let ((l1_s9 (+ l1_s7 l1_s8)))
+                                 (let ((l1_s10 (* l1_s6 l1_s6)))
+                                 (let ((l1_s11 (+ l1_s9 l1_s10)))
+                                 (let ((l1_s12 (* l1_s5 l1_s10)))
+                                 (let ((l1_s13 (+ l1_s11 l1_s12)))
+                                 (let ((l1_s14 (* l1_s6 l1_s10)))
+                                 (let ((l1_s15 (+ l1_s13 l1_s14)))
+                                 (let ((l1_s16 (* l1_s5 l1_s14)))
+                                 (let ((l1_s17 (+ l1_s15 l1_s16)))
+                                 (let ((l1_s18 (* l1_s10 l1_s10)))
+                                 (let ((l1_s19 (+ l1_s17 l1_s18)))
+                                 (let ((l1_s20 (* l1_s5 l1_s18)))
+                                 (let ((l1_s21 (+ l1_s19 l1_s20)))
+                                 (let ((l1_s22 (* l1_s6 l1_s18)))
+                                 (let ((l1_s23 (+ l1_s21 l1_s22)))
+                                 (let ((l1_s24 (seq.unit l1_s23)))
+                                 (let ((l1_s26 (- l1_s1 l1_s25)))
+                                 (let ((l1_s27 (seq.extract l1_s0 l1_s25 l1_s26)))
+                                 (let ((l1_s28 (|sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])| l1_s27)))
+                                 (let ((l1_s29 (seq.++ l1_s24 l1_s28)))
+                                 (let ((l1_s30 (ite l1_s3 l1_s4 l1_s29)))
+                                 l1_s30)))))))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.map @(SBV Integer -> SBV Integer)_b01b78a2e9 @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 10)
+               (seq.unit 2046)
+               (seq.unit 88572)
+               (seq.unit 1398100)
+               (seq.unit 12207030))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 10)
+               (seq.unit 2046)
+               (seq.unit 88572)
+               (seq.unit 1398100)
+               (seq.unit 12207030))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =                      [1,2,3,4,5] :: [Integer]
+  s1 = [10,2046,88572,1398100,12207030] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda07.gold b/SBVTestSuite/GoldFiles/lambda07.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda07.gold
@@ -0,0 +1,459 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]), sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]), sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer), sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): barified = "|sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1),("|sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s1 s6))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq (Seq Int)) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s3 s13))
+[GOOD] (define-fun s15 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s1 s6))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq (Seq Int)) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s3 s13))
+[GOOD] (define-fun s15 () Int (seq.len s11))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq (Seq Int)) (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))) (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10))) (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10) (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15) (seq.unit 16) (seq.unit 17) (seq.unit 18) (seq.unit 19) (seq.unit 20)))))
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Seq Int)))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s10)))
+                                 (let ((l1_s12 (+ l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Refers to: |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|]
+[GOOD] (define-fun |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_b97075844e @(SBV (Integer,[Integer]) -> SBV Integer)| ((s0 (SBVTuple2 Int (Seq Int)))) Int
+                 (let ((s3 0))
+                 (let ((s7 1))
+                 (let ((s1 (proj_2_SBVTuple2 s0)))
+                 (let ((s2 (seq.len s1)))
+                 (let ((s4 (= s2 s3)))
+                 (let ((s5 (proj_1_SBVTuple2 s0)))
+                 (let ((s6 (seq.nth s1 s3)))
+                 (let ((s8 (- s2 s7)))
+                 (let ((s9 (seq.extract s1 s7 s8)))
+                 (let ((s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s5 s9)))
+                 (let ((s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s10)))
+                 (let ((s12 (+ s6 s11)))
+                 (let ((s13 (ite s4 s5 s12)))
+                 s13))))))))))))))
+[GOOD] ; |sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])| :: [[SInteger]] -> [SInteger] [Recursive] [Refers to: |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|]
+[GOOD] (define-fun-rec |sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])| ((l1_s0 (Seq (Seq Int)))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s2 l1_s5)))
+                                 (let ((l1_s7 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (Seq Int) (|sbv.map @(SBV [Integer] -> SBV Integer)_1b9bf3f573 @(SBV [[Integer]] -> SBV [Integer])| s0))
+[GOOD] (define-fun s6 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s4 s5))
+[GOOD] (define-fun s7 () Int (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s6))
+[GOOD] (define-fun s8 () Bool (= s1 s7))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s8)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 280))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)))
+               (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.unit 7)
+                                 (seq.unit 8)
+                                 (seq.unit 9)
+                                 (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.unit 7)
+                                 (seq.unit 8)
+                                 (seq.unit 9)
+                                 (seq.unit 10)
+                                 (seq.unit 11)
+                                 (seq.unit 12)
+                                 (seq.unit 13)
+                                 (seq.unit 14)
+                                 (seq.unit 15)
+                                 (seq.unit 16)
+                                 (seq.unit 17)
+                                 (seq.unit 18)
+                                 (seq.unit 19)
+                                 (seq.unit 20))))))
+[SEND] (get-value (s1))
+[RECV] ((s1 280))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [[1,2,3,4,5],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]] :: [[Integer]]
+  s1 =                                                                                       280 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda08.gold b/SBVTestSuite/GoldFiles/lambda08.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda08.gold
@@ -0,0 +1,172 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])
+[MEASURE] Checking: sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])
+[MEASURE] sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64]): barified = "|sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])|"
+[MEASURE] sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])|",1)]
+[MEASURE] sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 64) #x0000000000000001)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 64)) (as seq.empty (Seq (_ BitVec 64))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 64))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 64))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 64) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 64) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 64)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 64)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 64)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 64)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 64) #x0000000000000001)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 64)) (as seq.empty (Seq (_ BitVec 64))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 64))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 64))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 64) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 64) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 64)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 64)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 64)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 64)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Int (seq.len s11))
+[GOOD] (define-fun s16 () Bool (not s6))
+[GOOD] (define-fun s17 () Bool (> s5 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq (_ BitVec 64)) (seq.++ (seq.unit #x0000000000000001) (seq.unit #x0000000000000002) (seq.unit #x0000000000000003) (seq.unit #x0000000000000004) (seq.unit #x0000000000000005)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 64)))
+[GOOD] (declare-fun s1 () (Seq (_ BitVec 64)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])| :: [SInt64] -> [SInt64] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])| ((l1_s0 (Seq (_ BitVec 64)))) (Seq (_ BitVec 64))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (_ BitVec 64)))))
+                                 (let ((l1_s6 #x0000000000000001))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (bvadd l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq (_ BitVec 64)) (|sbv.map @(SBV Int64 -> SBV Int64)_bc2a222730 @(SBV [Int64] -> SBV [Int64])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x0000000000000002)
+               (seq.unit #x0000000000000003)
+               (seq.unit #x0000000000000004)
+               (seq.unit #x0000000000000005)
+               (seq.unit #x0000000000000006))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit #x0000000000000001)
+               (seq.unit #x0000000000000002)
+               (seq.unit #x0000000000000003)
+               (seq.unit #x0000000000000004)
+               (seq.unit #x0000000000000005))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x0000000000000002)
+               (seq.unit #x0000000000000003)
+               (seq.unit #x0000000000000004)
+               (seq.unit #x0000000000000005)
+               (seq.unit #x0000000000000006))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Int64]
+  s1 = [2,3,4,5,6] :: [Int64]
diff --git a/SBVTestSuite/GoldFiles/lambda09.gold b/SBVTestSuite/GoldFiles/lambda09.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda09.gold
@@ -0,0 +1,172 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])
+[MEASURE] Checking: sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])
+[MEASURE] sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8]): barified = "|sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])|"
+[MEASURE] sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])|",1)]
+[MEASURE] sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (as seq.empty (Seq (_ BitVec 8))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 8))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 8) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 8) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 8)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 8)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 8)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 8)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (as seq.empty (Seq (_ BitVec 8))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 8))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 8) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 8) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 8)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 8)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 8)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 8)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Int (seq.len s11))
+[GOOD] (define-fun s16 () Bool (not s6))
+[GOOD] (define-fun s17 () Bool (> s5 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq (_ BitVec 8)) (seq.++ (seq.unit #x01) (seq.unit #x02) (seq.unit #x03) (seq.unit #x04) (seq.unit #x05)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8)))
+[GOOD] (declare-fun s1 () (Seq (_ BitVec 8)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])| :: [SInt8] -> [SInt8] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])| ((l1_s0 (Seq (_ BitVec 8)))) (Seq (_ BitVec 8))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (_ BitVec 8)))))
+                                 (let ((l1_s6 #x01))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (bvadd l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (|sbv.map @(SBV Int8 -> SBV Int8)_5111aac2ea @(SBV [Int8] -> SBV [Int8])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05)
+               (seq.unit #x06))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit #x01)
+               (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05)
+               (seq.unit #x06))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Int8]
+  s1 = [2,3,4,5,6] :: [Int8]
diff --git a/SBVTestSuite/GoldFiles/lambda10.gold b/SBVTestSuite/GoldFiles/lambda10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda10.gold
@@ -0,0 +1,157 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq Int)) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (+ s2 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq Int) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq Int) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq Int)) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (+ s2 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq Int) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq Int) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Int (seq.len s10))
+[GOOD] (define-fun s15 () Bool (not s5))
+[GOOD] (define-fun s16 () Bool (> s4 s14))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s9 (- l1_s1 l1_s6)))
+                                 (let ((l1_s10 (seq.extract l1_s0 l1_s6 l1_s9)))
+                                 (let ((l1_s11 (|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| l1_s10)))
+                                 (let ((l1_s12 (seq.++ l1_s8 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s3 l1_s4 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.map @(SBV Integer -> SBV Integer)_aaa4562f59 @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 = [2,3,4,5,6] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda11.gold b/SBVTestSuite/GoldFiles/lambda11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda11.gold
@@ -0,0 +1,172 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])
+[MEASURE] Checking: sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])
+[MEASURE] sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8]): barified = "|sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])|"
+[MEASURE] sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])|",1)]
+[MEASURE] sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (as seq.empty (Seq (_ BitVec 8))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 8))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 8) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 8) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 8)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 8)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 8)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 8)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (as seq.empty (Seq (_ BitVec 8))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq (_ BitVec 8))) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () (_ BitVec 8) (seq.nth s0 s2))
+[GOOD] (define-fun s8 () (_ BitVec 8) (bvadd s1 s7))
+[GOOD] (define-fun s9 () (Seq (_ BitVec 8)) (seq.unit s8))
+[GOOD] (define-fun s10 () Int (- s5 s3))
+[GOOD] (define-fun s11 () (Seq (_ BitVec 8)) (seq.extract s0 s3 s10))
+[GOOD] (define-fun s13 () (Seq (_ BitVec 8)) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq (_ BitVec 8)) (ite s6 s4 s13))
+[GOOD] (define-fun s15 () Int (seq.len s11))
+[GOOD] (define-fun s16 () Bool (not s6))
+[GOOD] (define-fun s17 () Bool (> s5 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq (_ BitVec 8)) (seq.++ (seq.unit #x01) (seq.unit #x02) (seq.unit #x03) (seq.unit #x04) (seq.unit #x05)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ BitVec 8)))
+[GOOD] (declare-fun s1 () (Seq (_ BitVec 8)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])| :: [SWord8] -> [SWord8] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])| ((l1_s0 (Seq (_ BitVec 8)))) (Seq (_ BitVec 8))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (_ BitVec 8)))))
+                                 (let ((l1_s6 #x01))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (bvadd l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq (_ BitVec 8)) (|sbv.map @(SBV Word8 -> SBV Word8)_5111aac2ea @(SBV [Word8] -> SBV [Word8])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05)
+               (seq.unit #x06))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit #x01)
+               (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit #x02)
+               (seq.unit #x03)
+               (seq.unit #x04)
+               (seq.unit #x05)
+               (seq.unit #x06))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Word8]
+  s1 = [2,3,4,5,6] :: [Word8]
diff --git a/SBVTestSuite/GoldFiles/lambda12.gold b/SBVTestSuite/GoldFiles/lambda12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda12.gold
@@ -0,0 +1,157 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]]): barified = "|sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () (Seq Int) (seq.unit s6))
+[GOOD] (define-fun s8 () (Seq (Seq Int)) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq (Seq Int)) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq (Seq Int)) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s7 () (Seq Int) (seq.unit s6))
+[GOOD] (define-fun s8 () (Seq (Seq Int)) (seq.unit s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s2 s9))
+[GOOD] (define-fun s12 () (Seq (Seq Int)) (seq.++ s8 s11))
+[GOOD] (define-fun s13 () (Seq (Seq Int)) (ite s5 s3 s12))
+[GOOD] (define-fun s14 () Int (seq.len s10))
+[GOOD] (define-fun s15 () Bool (not s5))
+[GOOD] (define-fun s16 () Bool (> s4 s14))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])| :: [SInteger] -> [[SInteger]] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])| ((l1_s0 (Seq Int))) (Seq (Seq Int))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (Seq Int)))))
+                                 (let ((l1_s8 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 (seq.unit l1_s5)))
+                                 (let ((l1_s7 (seq.unit l1_s6)))
+                                 (let ((l1_s9 (- l1_s1 l1_s8)))
+                                 (let ((l1_s10 (seq.extract l1_s0 l1_s8 l1_s9)))
+                                 (let ((l1_s11 (|sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])| l1_s10)))
+                                 (let ((l1_s12 (seq.++ l1_s7 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s3 l1_s4 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq (Seq Int)) (|sbv.map @(SBV Integer -> SBV [Integer])_661d2aaa20 @(SBV [Integer] -> SBV [[Integer]])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit (seq.unit 1)) (seq.unit (seq.unit 2)) (seq.unit (seq.unit 3)))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit (seq.unit 1)) (seq.unit (seq.unit 2)) (seq.unit (seq.unit 3)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =       [1,2,3] :: [Integer]
+  s1 = [[1],[2],[3]] :: [[Integer]]
diff --git a/SBVTestSuite/GoldFiles/lambda13.gold b/SBVTestSuite/GoldFiles/lambda13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda13.gold
@@ -0,0 +1,196 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): barified = "|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (SBVTuple2 Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s6))
+[GOOD] (define-fun s8 () Int (proj_2_SBVTuple2 s6))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (SBVTuple2 Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s6))
+[GOOD] (define-fun s8 () Int (proj_2_SBVTuple2 s6))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Int (seq.len s12))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s4 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq (SBVTuple2 Int Int)) (seq.++ (seq.unit (mkSBVTuple2 1 4)) (seq.unit (mkSBVTuple2 1 5)) (seq.unit (mkSBVTuple2 1 6)) (seq.unit (mkSBVTuple2 2 4)) (seq.unit (mkSBVTuple2 2 5)) (seq.unit (mkSBVTuple2 2 6)) (seq.unit (mkSBVTuple2 3 4)) (seq.unit (mkSBVTuple2 3 5)) (seq.unit (mkSBVTuple2 3 6))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int Int)))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| :: [(SInteger, SInteger)] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| ((l1_s0 (Seq (SBVTuple2 Int Int)))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 (proj_1_SBVTuple2 l1_s5)))
+                                 (let ((l1_s7 (proj_2_SBVTuple2 l1_s5)))
+                                 (let ((l1_s8 (+ l1_s6 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s8)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| l1_s12)))
+                                 (let ((l1_s14 (seq.++ l1_s9 l1_s13)))
+                                 (let ((l1_s15 (ite l1_s3 l1_s4 l1_s14)))
+                                 l1_s15))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (mkSBVTuple2 1 4))
+               (seq.unit (mkSBVTuple2 1 5))
+               (seq.unit (mkSBVTuple2 1 6))
+               (seq.unit (mkSBVTuple2 2 4))
+               (seq.unit (mkSBVTuple2 2 5))
+               (seq.unit (mkSBVTuple2 2 6))
+               (seq.unit (mkSBVTuple2 3 4))
+               (seq.unit (mkSBVTuple2 3 5))
+               (seq.unit (mkSBVTuple2 3 6)))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] :: [(Integer, Integer)]
+  s1 =                                     [5,6,7,6,7,8,7,8,9] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda14.gold b/SBVTestSuite/GoldFiles/lambda14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda14.gold
@@ -0,0 +1,198 @@
+[MEASURE] Verifying termination measures for: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): barified = "|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._1
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () (Seq Int) (proj_1_SBVTuple2 s18))
+[GOOD] (define-fun s24 () Int (seq.len s23))
+[GOOD] (define-fun s25 () Bool (not s9))
+[GOOD] (define-fun s26 () Bool (not s6))
+[GOOD] (define-fun s27 () Bool (and s25 s26))
+[GOOD] (define-fun s28 () Bool (> s5 s24))
+[GOOD] (define-fun s29 () Bool (=> s27 s28))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s29))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._1 -> OK
+[MEASURE] Passed (terminating): sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () (Seq Int) (seq.++ (seq.unit 10) (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| :: ([SInteger], [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq Int))))
+                                 (let ((l1_s13 1))
+                                 (let ((l1_s1 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s7 (seq.len l1_s6)))
+                                 (let ((l1_s8 (= l1_s3 l1_s7)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 (seq.nth l1_s6 l1_s3)))
+                                 (let ((l1_s11 (+ l1_s9 l1_s10)))
+                                 (let ((l1_s12 (seq.unit l1_s11)))
+                                 (let ((l1_s14 (- l1_s2 l1_s13)))
+                                 (let ((l1_s15 (seq.extract l1_s1 l1_s13 l1_s14)))
+                                 (let ((l1_s16 (- l1_s7 l1_s13)))
+                                 (let ((l1_s17 (seq.extract l1_s6 l1_s13 l1_s16)))
+                                 (let ((l1_s18 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s15 l1_s17)))
+                                 (let ((l1_s19 (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| l1_s18)))
+                                 (let ((l1_s20 (seq.++ l1_s12 l1_s19)))
+                                 (let ((l1_s21 (ite l1_s8 l1_s5 l1_s20)))
+                                 (let ((l1_s22 (ite l1_s4 l1_s5 l1_s21)))
+                                 l1_s22)))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () (Seq Int) (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 11) (seq.unit 13) (seq.unit 15) (seq.unit 17) (seq.unit 19))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 11) (seq.unit 13) (seq.unit 15) (seq.unit 17) (seq.unit 19))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =      [1,2,3,4,5] :: [Integer]
+  s1 = [11,13,15,17,19] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda15.gold b/SBVTestSuite/GoldFiles/lambda15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda15.gold
@@ -0,0 +1,281 @@
+[MEASURE] Verifying termination measures for: sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 0))))
+[SEND] (get-value (s12))
+[RECV] ((s12 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[0]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s8 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s9 (- l1_s2 l1_s8)))
+                                 (let ((l1_s10 (seq.extract l1_s1 l1_s8 l1_s9)))
+                                 (let ((l1_s11 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s7 l1_s10)))
+                                 (let ((l1_s12 (|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () Int (|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 =          15 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda16.gold b/SBVTestSuite/GoldFiles/lambda16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda16.gold
@@ -0,0 +1,281 @@
+[MEASURE] Verifying termination measures for: sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (* s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (* s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 1))
+[SEND] (get-value (s16))
+[RECV] ((s16 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 1 (seq.unit 1))))
+[SEND] (get-value (s12))
+[RECV] ((s12 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (1,[1]) :: (Integer, [Integer])
+  before =       1 :: Integer
+  then   =       1 :: Integer
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (* s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () Int) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (* s6 s7))
+[GOOD] (define-fun s9 () Int (- s4 s2))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s3 s2 s9))
+[GOOD] (define-fun s11 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s8 s10))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s8 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s7 (* l1_s5 l1_s6)))
+                                 (let ((l1_s9 (- l1_s2 l1_s8)))
+                                 (let ((l1_s10 (seq.extract l1_s1 l1_s8 l1_s9)))
+                                 (let ((l1_s11 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s7 l1_s10)))
+                                 (let ((l1_s12 (|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () Int (|sbv.foldl @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 120))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 120))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 =         120 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda17.gold b/SBVTestSuite/GoldFiles/lambda17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda17.gold
@@ -0,0 +1,286 @@
+[MEASURE] Verifying termination measures for: sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): barified = "|sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._1
+[MEASURE] replayDAG {sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.++ s8 s6))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s3 s2 s10))
+[GOOD] (define-fun s12 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s9 s11))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Int (seq.len s6))
+[GOOD] (define-fun s16 () Bool (>= s15 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.++ s8 s6))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s3 s2 s10))
+[GOOD] (define-fun s12 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s9 s11))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Int (seq.len s6))
+[GOOD] (define-fun s16 () (Seq Int) (proj_1_SBVTuple2 s12))
+[GOOD] (define-fun s17 () Int (seq.len s16))
+[GOOD] (define-fun s18 () Bool (not s5))
+[GOOD] (define-fun s19 () Bool (> s15 s17))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s15))
+[RECV] ((s15 0))
+[SEND] (get-value (s17))
+[RECV] ((s17 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 (as seq.empty (Seq Int)) (seq.unit 2))))
+[SEND] (get-value (s13))
+[RECV] ((s13 (as seq.empty (Seq Int))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = ([],[2]) :: ([Integer], [Integer])
+  before =        0 :: Integer
+  then   =        1 :: Integer
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying next candidate..
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.++ s8 s6))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s3 s2 s10))
+[GOOD] (define-fun s12 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s9 s11))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s9 () (Seq Int) (seq.++ s8 s6))
+[GOOD] (define-fun s10 () Int (- s4 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s3 s2 s10))
+[GOOD] (define-fun s12 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s9 s11))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () (Seq Int) (proj_2_SBVTuple2 s12))
+[GOOD] (define-fun s16 () Int (seq.len s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s4 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])| :: ([SInteger], [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s7 (seq.unit l1_s6)))
+                                 (let ((l1_s8 (seq.++ l1_s7 l1_s5)))
+                                 (let ((l1_s10 (- l1_s2 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s1 l1_s9 l1_s10)))
+                                 (let ((l1_s12 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s8 l1_s11)))
+                                 (let ((l1_s13 (|sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])| l1_s12)))
+                                 (let ((l1_s14 (ite l1_s4 l1_s5 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () (Seq Int) (|sbv.foldl @(SBV ([Integer],Integer) -> SBV [Integer])_2d6951daf1 @(SBV ([Integer],[Integer]) -> SBV [Integer])| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 = [5,4,3,2,1] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda18.gold b/SBVTestSuite/GoldFiles/lambda18.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda18.gold
@@ -0,0 +1,438 @@
+[MEASURE] Verifying termination measures for: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]), sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)
+[MEASURE] Checking: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): barified = "|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|"
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): Uninterpreted ops in DAG: [("|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|",2)]
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): recursive calls found = 1
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): trying length arg1
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Int (seq.len s14))
+[GOOD] (define-fun s22 () Bool (not s8))
+[GOOD] (define-fun s23 () Bool (not s6))
+[GOOD] (define-fun s24 () Bool (and s22 s23))
+[GOOD] (define-fun s25 () Bool (> s5 s21))
+[GOOD] (define-fun s26 () Bool (=> s24 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] Checking: sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): barified = "|sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)|"
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)}: replaying 14 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) ; tracks user variable "arg"
+[GOOD] (declare-fun s15 () Int) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 Int Int)) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () (SBVTuple2 Int Int) (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s11 () Int (+ s9 s10))
+[GOOD] (define-fun s12 () Int (- s4 s2))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 Int Int)) (seq.extract s3 s2 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int))) ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) s11 s13))
+[GOOD] (define-fun s16 () Int (ite s5 s6 s15))
+[GOOD] (define-fun s17 () Int (abs s6))
+[GOOD] (define-fun s18 () Bool (>= s17 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)}: replaying 14 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) ; tracks user variable "arg"
+[GOOD] (declare-fun s15 () Int) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 Int Int)) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () (SBVTuple2 Int Int) (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s11 () Int (+ s9 s10))
+[GOOD] (define-fun s12 () Int (- s4 s2))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 Int Int)) (seq.extract s3 s2 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int))) ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) s11 s13))
+[GOOD] (define-fun s16 () Int (ite s5 s6 s15))
+[GOOD] (define-fun s17 () Int (abs s6))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s14))
+[GOOD] (define-fun s19 () Int (abs s18))
+[GOOD] (define-fun s20 () Bool (not s5))
+[GOOD] (define-fun s21 () Bool (> s17 s19))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s17))
+[RECV] ((s17 0))
+[SEND] (get-value (s19))
+[RECV] ((s19 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit (mkSBVTuple2 0 0)))))
+[SEND] (get-value (s15))
+[RECV] ((s15 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[(0,0)]) :: (Integer, [(Integer, Integer)])
+  before =           0 :: Integer
+  then   =           0 :: Integer
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)}: replaying 14 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) ; tracks user variable "arg"
+[GOOD] (declare-fun s15 () Int) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 Int Int)) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () (SBVTuple2 Int Int) (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s11 () Int (+ s9 s10))
+[GOOD] (define-fun s12 () Int (- s4 s2))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 Int Int)) (seq.extract s3 s2 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int))) ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) s11 s13))
+[GOOD] (define-fun s16 () Int (ite s5 s6 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)}: replaying 14 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) ; tracks user variable "arg"
+[GOOD] (declare-fun s15 () Int) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq (SBVTuple2 Int Int)) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () (SBVTuple2 Int Int) (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (proj_1_SBVTuple2 s7))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s11 () Int (+ s9 s10))
+[GOOD] (define-fun s12 () Int (- s4 s2))
+[GOOD] (define-fun s13 () (Seq (SBVTuple2 Int Int)) (seq.extract s3 s2 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int))) ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) s11 s13))
+[GOOD] (define-fun s16 () Int (ite s5 s6 s15))
+[GOOD] (define-fun s17 () (Seq (SBVTuple2 Int Int)) (proj_2_SBVTuple2 s14))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s5))
+[GOOD] (define-fun s20 () Bool (> s4 s18))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 10) (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| :: [SInteger] -> [SInteger] -> [(SInteger, SInteger)] [Recursive]
+[GOOD] (define-fun-rec |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| ((l1_s0 (Seq Int)) (l1_s1 (Seq Int))) (Seq (SBVTuple2 Int Int))
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq (SBVTuple2 Int Int)))))
+                                 (let ((l1_s12 1))
+                                 (let ((l1_s2 (seq.len l1_s0)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (seq.len l1_s1)))
+                                 (let ((l1_s7 (= l1_s3 l1_s6)))
+                                 (let ((l1_s8 (seq.nth l1_s0 l1_s3)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int Int)) l1_s8 l1_s9)))
+                                 (let ((l1_s11 (seq.unit l1_s10)))
+                                 (let ((l1_s13 (- l1_s2 l1_s12)))
+                                 (let ((l1_s14 (seq.extract l1_s0 l1_s12 l1_s13)))
+                                 (let ((l1_s15 (- l1_s6 l1_s12)))
+                                 (let ((l1_s16 (seq.extract l1_s1 l1_s12 l1_s15)))
+                                 (let ((l1_s17 (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| l1_s14 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s11 l1_s17)))
+                                 (let ((l1_s19 (ite l1_s7 l1_s5 l1_s18)))
+                                 (let ((l1_s20 (ite l1_s4 l1_s5 l1_s19)))
+                                 l1_s20))))))))))))))))))))
+[GOOD] ; |sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)| :: (SInteger, [(SInteger, SInteger)]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq (SBVTuple2 Int Int))))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s11 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s7 (proj_1_SBVTuple2 l1_s6)))
+                                 (let ((l1_s8 (+ l1_s5 l1_s7)))
+                                 (let ((l1_s9 (proj_2_SBVTuple2 l1_s6)))
+                                 (let ((l1_s10 (+ l1_s8 l1_s9)))
+                                 (let ((l1_s12 (- l1_s2 l1_s11)))
+                                 (let ((l1_s13 (seq.extract l1_s1 l1_s11 l1_s12)))
+                                 (let ((l1_s14 ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) l1_s10 l1_s13)))
+                                 (let ((l1_s15 (|sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)| l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s6 () (Seq (SBVTuple2 Int Int)) (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| s5 s0))
+[GOOD] (define-fun s7 () (SBVTuple2 Int (Seq (SBVTuple2 Int Int))) ((as mkSBVTuple2 (SBVTuple2 Int (Seq (SBVTuple2 Int Int)))) s4 s6))
+[GOOD] (define-fun s8 () Int (|sbv.foldl @(SBV (Integer,(Integer,Integer)) -> SBV Integer)_f29a298542 @(SBV (Integer,[(Integer,Integer)]) -> SBV Integer)| s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 75))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 75))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 =          75 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda19.gold b/SBVTestSuite/GoldFiles/lambda19.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda19.gold
@@ -0,0 +1,281 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s10)))
+                                 (let ((l1_s12 (+ l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () Int (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 =          15 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda20.gold b/SBVTestSuite/GoldFiles/lambda20.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda20.gold
@@ -0,0 +1,281 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (* s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (* s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (* s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (* s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s10)))
+                                 (let ((l1_s12 (* l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () Int (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_dd270bb7de @(SBV (Integer,[Integer]) -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 120))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 120))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 =         120 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda21.gold b/SBVTestSuite/GoldFiles/lambda21.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda21.gold
@@ -0,0 +1,286 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): barified = "|sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s3 s2 s7))
+[GOOD] (define-fun s9 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s6 s8))
+[GOOD] (define-fun s11 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s10 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Int (seq.len s6))
+[GOOD] (define-fun s16 () Bool (>= s15 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s3 s2 s7))
+[GOOD] (define-fun s9 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s6 s8))
+[GOOD] (define-fun s11 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s10 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Int (seq.len s6))
+[GOOD] (define-fun s16 () (Seq Int) (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s17 () Int (seq.len s16))
+[GOOD] (define-fun s18 () Bool (not s5))
+[GOOD] (define-fun s19 () Bool (> s15 s17))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s15))
+[RECV] ((s15 0))
+[SEND] (get-value (s17))
+[RECV] ((s17 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 (as seq.empty (Seq Int)) (seq.unit 2))))
+[SEND] (get-value (s10))
+[RECV] ((s10 (as seq.empty (Seq Int))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = ([],[2]) :: ([Integer], [Integer])
+  before =        0 :: Integer
+  then   =        0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s3 s2 s7))
+[GOOD] (define-fun s9 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s6 s8))
+[GOOD] (define-fun s11 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s10 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (- s4 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.extract s3 s2 s7))
+[GOOD] (define-fun s9 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s6 s8))
+[GOOD] (define-fun s11 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s10 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s5 s6 s13))
+[GOOD] (define-fun s15 () (Seq Int) (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s16 () Int (seq.len s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s4 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])| :: ([SInteger], [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s6 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s7 (- l1_s2 l1_s6)))
+                                 (let ((l1_s8 (seq.extract l1_s1 l1_s6 l1_s7)))
+                                 (let ((l1_s9 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s5 l1_s8)))
+                                 (let ((l1_s10 (|sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])| l1_s9)))
+                                 (let ((l1_s11 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s12 (seq.unit l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s10 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s4 l1_s5 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s4 s0))
+[GOOD] (define-fun s6 () (Seq Int) (|sbv.foldr @(SBV (Integer,[Integer]) -> SBV [Integer])_5c3e05abf3 @(SBV ([Integer],[Integer]) -> SBV [Integer])| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5] :: [Integer]
+  s1 = [5,4,3,2,1] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda22.gold b/SBVTestSuite/GoldFiles/lambda22.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda22.gold
@@ -0,0 +1,231 @@
+[MEASURE] Verifying termination measures for: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] Checking: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): barified = "|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|"
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): Uninterpreted ops in DAG: [("|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|",2)]
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): recursive calls found = 1
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): trying length arg1
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Int (seq.len s14))
+[GOOD] (define-fun s22 () Bool (not s8))
+[GOOD] (define-fun s23 () Bool (not s6))
+[GOOD] (define-fun s24 () Bool (and s22 s23))
+[GOOD] (define-fun s25 () Bool (> s5 s21))
+[GOOD] (define-fun s26 () Bool (=> s24 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15) (seq.unit 16) (seq.unit 17) (seq.unit 18) (seq.unit 19) (seq.unit 20)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () (Seq (SBVTuple2 Int Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| :: [SInteger] -> [SInteger] -> [(SInteger, SInteger)] [Recursive]
+[GOOD] (define-fun-rec |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| ((l1_s0 (Seq Int)) (l1_s1 (Seq Int))) (Seq (SBVTuple2 Int Int))
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq (SBVTuple2 Int Int)))))
+                                 (let ((l1_s12 1))
+                                 (let ((l1_s2 (seq.len l1_s0)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (seq.len l1_s1)))
+                                 (let ((l1_s7 (= l1_s3 l1_s6)))
+                                 (let ((l1_s8 (seq.nth l1_s0 l1_s3)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int Int)) l1_s8 l1_s9)))
+                                 (let ((l1_s11 (seq.unit l1_s10)))
+                                 (let ((l1_s13 (- l1_s2 l1_s12)))
+                                 (let ((l1_s14 (seq.extract l1_s0 l1_s12 l1_s13)))
+                                 (let ((l1_s15 (- l1_s6 l1_s12)))
+                                 (let ((l1_s16 (seq.extract l1_s1 l1_s12 l1_s15)))
+                                 (let ((l1_s17 (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| l1_s14 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s11 l1_s17)))
+                                 (let ((l1_s19 (ite l1_s7 l1_s5 l1_s18)))
+                                 (let ((l1_s20 (ite l1_s4 l1_s5 l1_s19)))
+                                 l1_s20))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq (SBVTuple2 Int Int)) (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| s0 s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s8)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (mkSBVTuple2 1 11))
+               (seq.unit (mkSBVTuple2 2 12))
+               (seq.unit (mkSBVTuple2 3 13))
+               (seq.unit (mkSBVTuple2 4 14))
+               (seq.unit (mkSBVTuple2 5 15))
+               (seq.unit (mkSBVTuple2 6 16))
+               (seq.unit (mkSBVTuple2 7 17))
+               (seq.unit (mkSBVTuple2 8 18))
+               (seq.unit (mkSBVTuple2 9 19))
+               (seq.unit (mkSBVTuple2 10 20)))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 11)
+               (seq.unit 12)
+               (seq.unit 13)
+               (seq.unit 14)
+               (seq.unit 15)
+               (seq.unit 16)
+               (seq.unit 17)
+               (seq.unit 18)
+               (seq.unit 19)
+               (seq.unit 20))))
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (mkSBVTuple2 1 11))
+               (seq.unit (mkSBVTuple2 2 12))
+               (seq.unit (mkSBVTuple2 3 13))
+               (seq.unit (mkSBVTuple2 4 14))
+               (seq.unit (mkSBVTuple2 5 15))
+               (seq.unit (mkSBVTuple2 6 16))
+               (seq.unit (mkSBVTuple2 7 17))
+               (seq.unit (mkSBVTuple2 8 18))
+               (seq.unit (mkSBVTuple2 9 19))
+               (seq.unit (mkSBVTuple2 10 20)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =                                                   [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 =                                          [11,12,13,14,15,16,17,18,19,20] :: [Integer]
+  s2 = [(1,11),(2,12),(3,13),(4,14),(5,15),(6,16),(7,17),(8,18),(9,19),(10,20)] :: [(Integer, Integer)]
diff --git a/SBVTestSuite/GoldFiles/lambda23.gold b/SBVTestSuite/GoldFiles/lambda23.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda23.gold
@@ -0,0 +1,572 @@
+[MEASURE] Verifying termination measures for: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]), sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]), sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): barified = "|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|"
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): Uninterpreted ops in DAG: [("|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])|",2)]
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): recursive calls found = 1
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): trying length arg1
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Bool (>= s5 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s4 () (Seq (SBVTuple2 Int Int)) (as seq.empty (Seq (SBVTuple2 Int Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "arg1"
+[GOOD] (declare-fun s17 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "__internal_sbv_s17"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] (define-fun s9 () Int (seq.nth s0 s2))
+[GOOD] (define-fun s10 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (- s5 s3))
+[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s3 s13))
+[GOOD] (define-fun s15 () Int (- s7 s3))
+[GOOD] (define-fun s16 () (Seq Int) (seq.extract s1 s3 s15))
+[GOOD] (define-fun s18 () (Seq (SBVTuple2 Int Int)) (seq.++ s12 s17))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 Int Int)) (ite s8 s4 s18))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int Int)) (ite s6 s4 s19))
+[GOOD] (define-fun s21 () Int (seq.len s14))
+[GOOD] (define-fun s22 () Bool (not s8))
+[GOOD] (define-fun s23 () Bool (not s6))
+[GOOD] (define-fun s24 () Bool (and s22 s23))
+[GOOD] (define-fun s25 () Bool (> s5 s21))
+[GOOD] (define-fun s26 () Bool (=> s24 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])
+[MEASURE] Checking: sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): barified = "|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])|"
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])|",1)]
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (SBVTuple2 Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s6))
+[GOOD] (define-fun s8 () Int (proj_2_SBVTuple2 s6))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () (SBVTuple2 Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s6))
+[GOOD] (define-fun s8 () Int (proj_2_SBVTuple2 s6))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq (SBVTuple2 Int Int)) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Int (seq.len s12))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s4 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 10) (seq.unit 9) (seq.unit 8) (seq.unit 7) (seq.unit 6) (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| :: [SInteger] -> [SInteger] -> [(SInteger, SInteger)] [Recursive]
+[GOOD] (define-fun-rec |sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| ((l1_s0 (Seq Int)) (l1_s1 (Seq Int))) (Seq (SBVTuple2 Int Int))
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq (SBVTuple2 Int Int)))))
+                                 (let ((l1_s12 1))
+                                 (let ((l1_s2 (seq.len l1_s0)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (seq.len l1_s1)))
+                                 (let ((l1_s7 (= l1_s3 l1_s6)))
+                                 (let ((l1_s8 (seq.nth l1_s0 l1_s3)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int Int)) l1_s8 l1_s9)))
+                                 (let ((l1_s11 (seq.unit l1_s10)))
+                                 (let ((l1_s13 (- l1_s2 l1_s12)))
+                                 (let ((l1_s14 (seq.extract l1_s0 l1_s12 l1_s13)))
+                                 (let ((l1_s15 (- l1_s6 l1_s12)))
+                                 (let ((l1_s16 (seq.extract l1_s1 l1_s12 l1_s15)))
+                                 (let ((l1_s17 (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| l1_s14 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s11 l1_s17)))
+                                 (let ((l1_s19 (ite l1_s7 l1_s5 l1_s18)))
+                                 (let ((l1_s20 (ite l1_s4 l1_s5 l1_s19)))
+                                 l1_s20))))))))))))))))))))
+[GOOD] ; |sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| :: [(SInteger, SInteger)] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| ((l1_s0 (Seq (SBVTuple2 Int Int)))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 (proj_1_SBVTuple2 l1_s5)))
+                                 (let ((l1_s7 (proj_2_SBVTuple2 l1_s5)))
+                                 (let ((l1_s8 (+ l1_s6 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s8)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| l1_s12)))
+                                 (let ((l1_s14 (seq.++ l1_s9 l1_s13)))
+                                 (let ((l1_s15 (ite l1_s3 l1_s4 l1_s14)))
+                                 l1_s15))))))))))))))))
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s10)))
+                                 (let ((l1_s12 (+ l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s8 () (Seq (SBVTuple2 Int Int)) (|sbv.zip @(SBV [Integer] -> SBV [Integer] -> SBV [(Integer,Integer)])| s0 s1))
+[GOOD] (define-fun s9 () (Seq Int) (|sbv.map @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV [(Integer,Integer)] -> SBV [Integer])| s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s9))
+[GOOD] (define-fun s11 () Int (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s10))
+[GOOD] (define-fun s12 () Bool (= s2 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 110))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 10)
+               (seq.unit 9)
+               (seq.unit 8)
+               (seq.unit 7)
+               (seq.unit 6)
+               (seq.unit 5)
+               (seq.unit 4)
+               (seq.unit 3)
+               (seq.unit 2)
+               (seq.unit 1))))
+[SEND] (get-value (s2))
+[RECV] ((s2 110))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 = [10,9,8,7,6,5,4,3,2,1] :: [Integer]
+  s2 =                    110 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda24.gold b/SBVTestSuite/GoldFiles/lambda24.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda24.gold
@@ -0,0 +1,240 @@
+[MEASURE] Verifying termination measures for: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): barified = "|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._1
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () (Seq Int) (proj_1_SBVTuple2 s18))
+[GOOD] (define-fun s24 () Int (seq.len s23))
+[GOOD] (define-fun s25 () Bool (not s9))
+[GOOD] (define-fun s26 () Bool (not s6))
+[GOOD] (define-fun s27 () Bool (and s25 s26))
+[GOOD] (define-fun s28 () Bool (> s5 s24))
+[GOOD] (define-fun s29 () Bool (=> s27 s28))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s29))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._1 -> OK
+[MEASURE] Passed (terminating): sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15) (seq.unit 16) (seq.unit 17) (seq.unit 18) (seq.unit 19) (seq.unit 20)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| :: ([SInteger], [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq Int))))
+                                 (let ((l1_s13 1))
+                                 (let ((l1_s1 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s7 (seq.len l1_s6)))
+                                 (let ((l1_s8 (= l1_s3 l1_s7)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 (seq.nth l1_s6 l1_s3)))
+                                 (let ((l1_s11 (+ l1_s9 l1_s10)))
+                                 (let ((l1_s12 (seq.unit l1_s11)))
+                                 (let ((l1_s14 (- l1_s2 l1_s13)))
+                                 (let ((l1_s15 (seq.extract l1_s1 l1_s13 l1_s14)))
+                                 (let ((l1_s16 (- l1_s7 l1_s13)))
+                                 (let ((l1_s17 (seq.extract l1_s6 l1_s13 l1_s16)))
+                                 (let ((l1_s18 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s15 l1_s17)))
+                                 (let ((l1_s19 (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| l1_s18)))
+                                 (let ((l1_s20 (seq.++ l1_s12 l1_s19)))
+                                 (let ((l1_s21 (ite l1_s8 l1_s5 l1_s20)))
+                                 (let ((l1_s22 (ite l1_s4 l1_s5 l1_s21)))
+                                 l1_s22)))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s0 s1))
+[GOOD] (define-fun s8 () (Seq Int) (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit 12)
+               (seq.unit 14)
+               (seq.unit 16)
+               (seq.unit 18)
+               (seq.unit 20)
+               (seq.unit 22)
+               (seq.unit 24)
+               (seq.unit 26)
+               (seq.unit 28)
+               (seq.unit 30))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 11)
+               (seq.unit 12)
+               (seq.unit 13)
+               (seq.unit 14)
+               (seq.unit 15)
+               (seq.unit 16)
+               (seq.unit 17)
+               (seq.unit 18)
+               (seq.unit 19)
+               (seq.unit 20))))
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit 12)
+               (seq.unit 14)
+               (seq.unit 16)
+               (seq.unit 18)
+               (seq.unit 20)
+               (seq.unit 22)
+               (seq.unit 24)
+               (seq.unit 26)
+               (seq.unit 28)
+               (seq.unit 30))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =          [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 = [11,12,13,14,15,16,17,18,19,20] :: [Integer]
+  s2 = [12,14,16,18,20,22,24,26,28,30] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda25.gold b/SBVTestSuite/GoldFiles/lambda25.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda25.gold
@@ -0,0 +1,456 @@
+[MEASURE] Verifying termination measures for: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]), sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] Checking: sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): barified = "|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): trying length arg1._1
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])}: replaying 19 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s19 () (Seq Int)) ; tracks user variable "__internal_sbv_s19"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s11 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s12 () Int (+ s10 s11))
+[GOOD] (define-fun s13 () (Seq Int) (seq.unit s12))
+[GOOD] (define-fun s14 () Int (- s5 s2))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s4 s2 s14))
+[GOOD] (define-fun s16 () Int (- s8 s2))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s7 s2 s16))
+[GOOD] (define-fun s18 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s17))
+[GOOD] (define-fun s20 () (Seq Int) (seq.++ s13 s19))
+[GOOD] (define-fun s21 () (Seq Int) (ite s9 s3 s20))
+[GOOD] (define-fun s22 () (Seq Int) (ite s6 s3 s21))
+[GOOD] (define-fun s23 () (Seq Int) (proj_1_SBVTuple2 s18))
+[GOOD] (define-fun s24 () Int (seq.len s23))
+[GOOD] (define-fun s25 () Bool (not s9))
+[GOOD] (define-fun s26 () Bool (not s6))
+[GOOD] (define-fun s27 () Bool (and s25 s26))
+[GOOD] (define-fun s28 () Bool (> s5 s24))
+[GOOD] (define-fun s29 () Bool (=> s27 s28))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s29))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer]): length arg1._1 -> OK
+[MEASURE] Passed (terminating): sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): barified = "|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying abs arg1._1
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Int (abs s6))
+[GOOD] (define-fun s15 () Int (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s16 () Int (abs s15))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s14 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s16))
+[RECV] ((s16 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying next candidate..
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (seq.nth s3 s1))
+[GOOD] (define-fun s8 () Int (- s4 s2))
+[GOOD] (define-fun s9 () (Seq Int) (seq.extract s3 s2 s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s9))
+[GOOD] (define-fun s12 () Int (+ s7 s11))
+[GOOD] (define-fun s13 () Int (ite s5 s6 s12))
+[GOOD] (define-fun s14 () (Seq Int) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s15 () Int (seq.len s14))
+[GOOD] (define-fun s16 () Bool (not s5))
+[GOOD] (define-fun s17 () Bool (> s4 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 10) (seq.unit 9) (seq.unit 8) (seq.unit 7) (seq.unit 6) (seq.unit 5) (seq.unit 4) (seq.unit 3) (seq.unit 2) (seq.unit 1)))
+[GOOD] (define-fun s7 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| :: ([SInteger], [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq Int))))
+                                 (let ((l1_s13 1))
+                                 (let ((l1_s1 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s7 (seq.len l1_s6)))
+                                 (let ((l1_s8 (= l1_s3 l1_s7)))
+                                 (let ((l1_s9 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s10 (seq.nth l1_s6 l1_s3)))
+                                 (let ((l1_s11 (+ l1_s9 l1_s10)))
+                                 (let ((l1_s12 (seq.unit l1_s11)))
+                                 (let ((l1_s14 (- l1_s2 l1_s13)))
+                                 (let ((l1_s15 (seq.extract l1_s1 l1_s13 l1_s14)))
+                                 (let ((l1_s16 (- l1_s7 l1_s13)))
+                                 (let ((l1_s17 (seq.extract l1_s6 l1_s13 l1_s16)))
+                                 (let ((l1_s18 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s15 l1_s17)))
+                                 (let ((l1_s19 (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| l1_s18)))
+                                 (let ((l1_s20 (seq.++ l1_s12 l1_s19)))
+                                 (let ((l1_s21 (ite l1_s8 l1_s5 l1_s20)))
+                                 (let ((l1_s22 (ite l1_s4 l1_s5 l1_s21)))
+                                 l1_s22)))))))))))))))))))))))
+[GOOD] ; |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| :: (SInteger, [SInteger]) -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| ((l1_s0 (SBVTuple2 Int (Seq Int)))) Int
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| l1_s10)))
+                                 (let ((l1_s12 (+ l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s8 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s0 s1))
+[GOOD] (define-fun s9 () (Seq Int) (|sbv.zipWith @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV ([Integer],[Integer]) -> SBV [Integer])| s8))
+[GOOD] (define-fun s10 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s9))
+[GOOD] (define-fun s11 () Int (|sbv.foldr @(SBV (Integer,Integer) -> SBV Integer)_1fd06f7602 @(SBV (Integer,[Integer]) -> SBV Integer)| s10))
+[GOOD] (define-fun s12 () Bool (= s2 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 110))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 10)
+               (seq.unit 9)
+               (seq.unit 8)
+               (seq.unit 7)
+               (seq.unit 6)
+               (seq.unit 5)
+               (seq.unit 4)
+               (seq.unit 3)
+               (seq.unit 2)
+               (seq.unit 1))))
+[SEND] (get-value (s2))
+[RECV] ((s2 110))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 = [10,9,8,7,6,5,4,3,2,1] :: [Integer]
+  s2 =                    110 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda26.gold b/SBVTestSuite/GoldFiles/lambda26.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda26.gold
@@ -0,0 +1,167 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq (Seq Int)) (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))) (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10))) (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10) (seq.unit 11) (seq.unit 12) (seq.unit 13) (seq.unit 14) (seq.unit 15) (seq.unit 16) (seq.unit 17) (seq.unit 18) (seq.unit 19) (seq.unit 20)))))
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Seq Int)))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV ([Integer],[Integer]) -> SBV [Integer])_44d71053fc @(SBV ([Integer],[[Integer]]) -> SBV [Integer])| :: ([SInteger], [[SInteger]]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV ([Integer],[Integer]) -> SBV [Integer])_44d71053fc @(SBV ([Integer],[[Integer]]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq (Seq Int))))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (- l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.extract l1_s1 l1_s7 l1_s8)))
+                                 (let ((l1_s10 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq (Seq Int)))) l1_s5 l1_s9)))
+                                 (let ((l1_s11 (|sbv.foldr @(SBV ([Integer],[Integer]) -> SBV [Integer])_44d71053fc @(SBV ([Integer],[[Integer]]) -> SBV [Integer])| l1_s10)))
+                                 (let ((l1_s12 (seq.++ l1_s6 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s4 l1_s5 l1_s12)))
+                                 l1_s13))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () (SBVTuple2 (Seq Int) (Seq (Seq Int))) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq (Seq Int)))) s4 s0))
+[GOOD] (define-fun s6 () (Seq Int) (|sbv.foldr @(SBV ([Integer],[Integer]) -> SBV [Integer])_44d71053fc @(SBV ([Integer],[[Integer]]) -> SBV [Integer])| s5))
+[GOOD] (define-fun s7 () Bool (= s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10)
+               (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10)
+               (seq.unit 11)
+               (seq.unit 12)
+               (seq.unit 13)
+               (seq.unit 14)
+               (seq.unit 15)
+               (seq.unit 16)
+               (seq.unit 17)
+               (seq.unit 18)
+               (seq.unit 19)
+               (seq.unit 20))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)))
+               (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.unit 7)
+                                 (seq.unit 8)
+                                 (seq.unit 9)
+                                 (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.unit 7)
+                                 (seq.unit 8)
+                                 (seq.unit 9)
+                                 (seq.unit 10)
+                                 (seq.unit 11)
+                                 (seq.unit 12)
+                                 (seq.unit 13)
+                                 (seq.unit 14)
+                                 (seq.unit 15)
+                                 (seq.unit 16)
+                                 (seq.unit 17)
+                                 (seq.unit 18)
+                                 (seq.unit 19)
+                                 (seq.unit 20))))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10)
+               (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10)
+               (seq.unit 11)
+               (seq.unit 12)
+               (seq.unit 13)
+               (seq.unit 14)
+               (seq.unit 15)
+               (seq.unit 16)
+               (seq.unit 17)
+               (seq.unit 18)
+               (seq.unit 19)
+               (seq.unit 20))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [[1,2,3,4,5],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]] :: [[Integer]]
+  s1 =       [1,2,3,4,5,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda27.gold b/SBVTestSuite/GoldFiles/lambda27.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda27.gold
@@ -0,0 +1,178 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): barified = "|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (and s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (and s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s6))
+[GOOD] (define-fun s20 () Bool (and s10 s19))
+[GOOD] (define-fun s21 () Bool (> s5 s18))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| :: (SBool, [SInteger]) -> SBool [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| ((l1_s0 (SBVTuple2 Bool (Seq Int)))) Bool
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (mod l1_s6 l1_s7)))
+                                 (let ((l1_s9 (= l1_s3 l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) l1_s5 l1_s12)))
+                                 (let ((l1_s14 (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| l1_s13)))
+                                 (let ((l1_s15 (and l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) true s0))
+[GOOD] (define-fun s5 () Bool (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [2,4,6,8,10] :: [Integer]
+  s1 =         True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda28.gold b/SBVTestSuite/GoldFiles/lambda28.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda28.gold
@@ -0,0 +1,183 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): barified = "|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (and s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (and s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s6))
+[GOOD] (define-fun s20 () Bool (and s10 s19))
+[GOOD] (define-fun s21 () Bool (> s5 s18))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 1) (seq.unit 8) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| :: (SBool, [SInteger]) -> SBool [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| ((l1_s0 (SBVTuple2 Bool (Seq Int)))) Bool
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (mod l1_s6 l1_s7)))
+                                 (let ((l1_s9 (= l1_s3 l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) l1_s5 l1_s12)))
+                                 (let ((l1_s14 (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| l1_s13)))
+                                 (let ((l1_s15 (and l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) true s0))
+[GOOD] (define-fun s5 () Bool (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_574b56f8c4 @(SBV (Bool,[Integer]) -> SBV Bool)| s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 2)
+               (seq.unit 4)
+               (seq.unit 6)
+               (seq.unit 1)
+               (seq.unit 8)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [2,4,6,1,8,10] :: [Integer]
+  s1 =          False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda29.gold b/SBVTestSuite/GoldFiles/lambda29.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda29.gold
@@ -0,0 +1,179 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool): barified = "|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (distinct s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (or s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (distinct s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (or s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s10))
+[GOOD] (define-fun s20 () Bool (not s6))
+[GOOD] (define-fun s21 () Bool (and s19 s20))
+[GOOD] (define-fun s22 () Bool (> s5 s18))
+[GOOD] (define-fun s23 () Bool (=> s21 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)| :: (SBool, [SInteger]) -> SBool [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)| ((l1_s0 (SBVTuple2 Bool (Seq Int)))) Bool
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (mod l1_s6 l1_s7)))
+                                 (let ((l1_s9 (distinct l1_s3 l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) l1_s5 l1_s12)))
+                                 (let ((l1_s14 (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)| l1_s13)))
+                                 (let ((l1_s15 (or l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) false s0))
+[GOOD] (define-fun s5 () Bool (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_01257e6724 @(SBV (Bool,[Integer]) -> SBV Bool)| s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [2,4,6,8,10] :: [Integer]
+  s1 =        False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda30.gold b/SBVTestSuite/GoldFiles/lambda30.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda30.gold
@@ -0,0 +1,184 @@
+[MEASURE] Verifying termination measures for: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] Checking: sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool): barified = "|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)|"
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool): Uninterpreted ops in DAG: [("|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)|",1)]
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool): recursive calls found = 1
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool): trying length arg1._2
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (or s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Bool (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () Bool) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (mod s8 s3))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () Bool (or s10 s14))
+[GOOD] (define-fun s16 () Bool (ite s6 s7 s15))
+[GOOD] (define-fun s17 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s10))
+[GOOD] (define-fun s20 () Bool (not s6))
+[GOOD] (define-fun s21 () Bool (and s19 s20))
+[GOOD] (define-fun s22 () Bool (> s5 s18))
+[GOOD] (define-fun s23 () Bool (=> s21 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 1) (seq.unit 8) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)| :: (SBool, [SInteger]) -> SBool [Recursive]
+[GOOD] (define-fun-rec |sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)| ((l1_s0 (SBVTuple2 Bool (Seq Int)))) Bool
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s7 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (mod l1_s6 l1_s7)))
+                                 (let ((l1_s9 (= l1_s3 l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) l1_s5 l1_s12)))
+                                 (let ((l1_s14 (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)| l1_s13)))
+                                 (let ((l1_s15 (or l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Bool (Seq Int))) false s0))
+[GOOD] (define-fun s5 () Bool (|sbv.foldr @(SBV (Integer,Bool) -> SBV Bool)_7182762f14 @(SBV (Bool,[Integer]) -> SBV Bool)| s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 2)
+               (seq.unit 4)
+               (seq.unit 6)
+               (seq.unit 1)
+               (seq.unit 8)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [2,4,6,1,8,10] :: [Integer]
+  s1 =           True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda31.gold b/SBVTestSuite/GoldFiles/lambda31.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda31.gold
@@ -0,0 +1,177 @@
+[MEASURE] Verifying termination measures for: sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s4 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s4 s15))
+[GOOD] (define-fun s17 () Int (seq.len s12))
+[GOOD] (define-fun s18 () Bool (not s9))
+[GOOD] (define-fun s19 () Bool (not s6))
+[GOOD] (define-fun s20 () Bool (and s18 s19))
+[GOOD] (define-fun s21 () Bool (> s5 s17))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (mod l1_s5 l1_s6)))
+                                 (let ((l1_s8 (= l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s5)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])| l1_s12)))
+                                 (let ((l1_s14 (seq.++ l1_s9 l1_s13)))
+                                 (let ((l1_s15 (ite l1_s8 l1_s14 l1_s13)))
+                                 (let ((l1_s16 (ite l1_s3 l1_s4 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.filter @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 2) (seq.unit 4) (seq.unit 6) (seq.unit 8) (seq.unit 10))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 =           [2,4,6,8,10] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda32.gold b/SBVTestSuite/GoldFiles/lambda32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda32.gold
@@ -0,0 +1,177 @@
+[MEASURE] Verifying termination measures for: sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (distinct s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s4 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (distinct s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s4 s15))
+[GOOD] (define-fun s17 () Int (seq.len s12))
+[GOOD] (define-fun s18 () Bool (not s9))
+[GOOD] (define-fun s19 () Bool (not s6))
+[GOOD] (define-fun s20 () Bool (and s18 s19))
+[GOOD] (define-fun s21 () Bool (> s5 s17))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (mod l1_s5 l1_s6)))
+                                 (let ((l1_s8 (distinct l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s5)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])| l1_s12)))
+                                 (let ((l1_s14 (seq.++ l1_s9 l1_s13)))
+                                 (let ((l1_s15 (ite l1_s8 l1_s14 l1_s13)))
+                                 (let ((l1_s16 (ite l1_s3 l1_s4 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq Int) (|sbv.filter @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 1) (seq.unit 3) (seq.unit 5) (seq.unit 7) (seq.unit 9))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 1) (seq.unit 3) (seq.unit 5) (seq.unit 7) (seq.unit 9))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 =            [1,3,5,7,9] :: [Integer]
diff --git a/SBVTestSuite/GoldFiles/lambda33.gold b/SBVTestSuite/GoldFiles/lambda33.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda33.gold
@@ -0,0 +1,1 @@
+#x00
diff --git a/SBVTestSuite/GoldFiles/lambda34.gold b/SBVTestSuite/GoldFiles/lambda34.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda34.gold
@@ -0,0 +1,4 @@
+(lambda ((l1_s0 (_ BitVec 8)))
+                          (let ((l1_s1 #x01))
+                          (let ((l1_s2 (bvadd l1_s0 l1_s1)))
+                          l1_s2)))
diff --git a/SBVTestSuite/GoldFiles/lambda35.gold b/SBVTestSuite/GoldFiles/lambda35.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda35.gold
@@ -0,0 +1,2 @@
+(lambda ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+  (bvadd l1_s0 l1_s1))
diff --git a/SBVTestSuite/GoldFiles/lambda36.gold b/SBVTestSuite/GoldFiles/lambda36.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda36.gold
@@ -0,0 +1,3 @@
+; user defined axiom: 
+(assert (forall ((l1_s0 Bool))
+                            true))
diff --git a/SBVTestSuite/GoldFiles/lambda37.gold b/SBVTestSuite/GoldFiles/lambda37.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda37.gold
@@ -0,0 +1,3 @@
+; user defined axiom: 
+(assert (forall ((l1_s0 Bool))
+    (not l1_s0)))
diff --git a/SBVTestSuite/GoldFiles/lambda38.gold b/SBVTestSuite/GoldFiles/lambda38.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda38.gold
@@ -0,0 +1,6 @@
+; user defined axiom: 
+(assert (forall ((l1_s0 Int) (l1_s1 Bool))
+                            (let ((l1_s2 0))
+                            (let ((l1_s3 (= l1_s0 l1_s2)))
+                            (let ((l1_s4 (or l1_s1 l1_s3)))
+                            l1_s4)))))
diff --git a/SBVTestSuite/GoldFiles/lambda40.gold b/SBVTestSuite/GoldFiles/lambda40.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda40.gold
@@ -0,0 +1,1 @@
+0
diff --git a/SBVTestSuite/GoldFiles/lambda41.gold b/SBVTestSuite/GoldFiles/lambda41.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda41.gold
@@ -0,0 +1,4 @@
+(lambda ((l1_s0 Int))
+                          (let ((l1_s1 1))
+                          (let ((l1_s2 (+ l1_s0 l1_s1)))
+                          l1_s2)))
diff --git a/SBVTestSuite/GoldFiles/lambda42.gold b/SBVTestSuite/GoldFiles/lambda42.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda42.gold
@@ -0,0 +1,2 @@
+(lambda ((l1_s0 Int) (l1_s1 Int))
+  (+ l1_s0 l1_s1))
diff --git a/SBVTestSuite/GoldFiles/lambda43.gold b/SBVTestSuite/GoldFiles/lambda43.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda43.gold
@@ -0,0 +1,1 @@
+#x00000000
diff --git a/SBVTestSuite/GoldFiles/lambda44.gold b/SBVTestSuite/GoldFiles/lambda44.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda44.gold
@@ -0,0 +1,4 @@
+(lambda ((l1_s0 (_ BitVec 32)))
+                          (let ((l1_s1 #x00000001))
+                          (let ((l1_s2 (bvadd l1_s0 l1_s1)))
+                          l1_s2)))
diff --git a/SBVTestSuite/GoldFiles/lambda45.gold b/SBVTestSuite/GoldFiles/lambda45.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda45.gold
@@ -0,0 +1,2 @@
+(lambda ((l1_s0 (_ BitVec 32)) (l1_s1 (_ BitVec 32)))
+  (bvadd l1_s0 l1_s1))
diff --git a/SBVTestSuite/GoldFiles/lambda46.gold b/SBVTestSuite/GoldFiles/lambda46.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda46.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) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |add1 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |add1 @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 1))
+                                 (let ((l1_s2 (+ l1_s0 l1_s1)))
+                                 l1_s2)))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|add1 @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (declare-fun s4 () Int)
+[GOOD] (define-fun s5 () Int (|add1 @(SBV Integer -> SBV Integer)| s4))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+[SEND] (get-value (s4))
+[RECV] ((s4 4))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = 4 :: Integer
+  s4 = 4 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda47.gold b/SBVTestSuite/GoldFiles/lambda47.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda47.gold
@@ -0,0 +1,143 @@
+[MEASURE] Verifying termination measures for: sumToN @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: sumToN @(SBV Integer -> SBV Integer)
+[MEASURE] sumToN @(SBV Integer -> SBV Integer): barified = "|sumToN @(SBV Integer -> SBV Integer)|"
+[MEASURE] sumToN @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|sumToN @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] sumToN @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] sumToN @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {sumToN @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sumToN @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sumToN @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): sumToN @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sumToN @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+[GOOD] (define-fun-rec |sumToN @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s3 1))
+                                 (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                 (let ((l1_s4 (- l1_s0 l1_s3)))
+                                 (let ((l1_s5 (|sumToN @(SBV Integer -> SBV Integer)| l1_s4)))
+                                 (let ((l1_s6 (+ l1_s0 l1_s5)))
+                                 (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                 l1_s7))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Int (|sumToN @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Bool (and s3 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (declare-fun s7 () Int)
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (define-fun s9 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Int (|sumToN @(SBV Integer -> SBV Integer)| s7))
+[GOOD] (define-fun s11 () Bool (= s8 s10))
+[GOOD] (define-fun s12 () Bool (and s9 s11))
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 15))
+[SEND] (get-value (s7))
+[RECV] ((s7 5))
+[SEND] (get-value (s8))
+[RECV] ((s8 15))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =  5 :: Integer
+  s1 = 15 :: Integer
+  s7 =  5 :: Integer
+  s8 = 15 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda47_c.gold b/SBVTestSuite/GoldFiles/lambda47_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda47_c.gold
@@ -0,0 +1,38 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 15)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (declare-fun s3 () Int)
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 15))
+[SEND] (get-value (s3))
+[RECV] ((s3 15))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = 15 :: Integer
+  s3 = 15 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda48.gold b/SBVTestSuite/GoldFiles/lambda48.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda48.gold
@@ -0,0 +1,156 @@
+[MEASURE] Verifying termination measures for: list_length @(SBV [Integer] -> SBV Integer)
+[MEASURE] Checking: list_length @(SBV [Integer] -> SBV Integer)
+[MEASURE] list_length @(SBV [Integer] -> SBV Integer): barified = "|list_length @(SBV [Integer] -> SBV Integer)|"
+[MEASURE] list_length @(SBV [Integer] -> SBV Integer): Uninterpreted ops in DAG: [("|list_length @(SBV [Integer] -> SBV Integer)|",1)]
+[MEASURE] list_length @(SBV [Integer] -> SBV Integer): recursive calls found = 1
+[MEASURE] list_length @(SBV [Integer] -> SBV Integer): trying length arg1
+[MEASURE] replayDAG {list_length @(SBV [Integer] -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (seq.len s0))
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (define-fun s5 () Int (- s3 s2))
+[GOOD] (define-fun s6 () (Seq Int) (seq.extract s0 s2 s5))
+[GOOD] (define-fun s8 () Int (+ s2 s7))
+[GOOD] (define-fun s9 () Int (ite s4 s1 s8))
+[GOOD] (define-fun s10 () Bool (>= s3 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {list_length @(SBV [Integer] -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (seq.len s0))
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (define-fun s5 () Int (- s3 s2))
+[GOOD] (define-fun s6 () (Seq Int) (seq.extract s0 s2 s5))
+[GOOD] (define-fun s8 () Int (+ s2 s7))
+[GOOD] (define-fun s9 () Int (ite s4 s1 s8))
+[GOOD] (define-fun s10 () Int (seq.len s6))
+[GOOD] (define-fun s11 () Bool (not s4))
+[GOOD] (define-fun s12 () Bool (> s3 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] list_length @(SBV [Integer] -> SBV Integer): length arg1 -> OK
+[MEASURE] Passed (terminating): list_length @(SBV [Integer] -> SBV Integer)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |list_length @(SBV [Integer] -> SBV Integer)| :: [SInteger] -> SInteger [Recursive]
+[GOOD] (define-fun-rec |list_length @(SBV [Integer] -> SBV Integer)| ((l1_s0 (Seq Int))) Int
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (- l1_s1 l1_s4)))
+                                 (let ((l1_s6 (seq.extract l1_s0 l1_s4 l1_s5)))
+                                 (let ((l1_s7 (|list_length @(SBV [Integer] -> SBV Integer)| l1_s6)))
+                                 (let ((l1_s8 (+ l1_s4 l1_s7)))
+                                 (let ((l1_s9 (ite l1_s3 l1_s2 l1_s8)))
+                                 l1_s9))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Int (|list_length @(SBV [Integer] -> SBV Integer)| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Bool (and s3 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (declare-fun s7 () (Seq Int))
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (define-fun s9 () Bool (= s2 s7))
+[GOOD] (define-fun s10 () Int (|list_length @(SBV [Integer] -> SBV Integer)| s7))
+[GOOD] (define-fun s11 () Bool (= s8 s10))
+[GOOD] (define-fun s12 () Bool (and s9 s11))
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))))
+[SEND] (get-value (s1))
+[RECV] ((s1 3))
+[SEND] (get-value (s7))
+[RECV] ((s7 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))))
+[SEND] (get-value (s8))
+[RECV] ((s8 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = [1,2,3] :: [Integer]
+  s1 =       3 :: Integer
+  s7 = [1,2,3] :: [Integer]
+  s8 =       3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda48_c.gold b/SBVTestSuite/GoldFiles/lambda48_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda48_c.gold
@@ -0,0 +1,38 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (declare-fun s3 () Int)
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+[SEND] (get-value (s3))
+[RECV] ((s3 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = 3 :: Integer
+  s3 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda49.gold b/SBVTestSuite/GoldFiles/lambda49.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda49.gold
@@ -0,0 +1,215 @@
+[MEASURE] Verifying termination measures for: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] Checking: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): verifying with 0 helper(s)
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s19 () Bool (>= s18 s1))
+[GOOD] (define-fun s20 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s21 () Bool (>= s20 s1))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (abs s5))
+[GOOD] (define-fun s19 () Bool (< s5 s1))
+[GOOD] (define-fun s20 () Int (ite s19 s2 s1))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Int (abs s8))
+[GOOD] (define-fun s23 () Bool (< s8 s1))
+[GOOD] (define-fun s24 () Int (ite s23 s2 s1))
+[GOOD] (define-fun s25 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s22 s24))
+[GOOD] (define-fun s26 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s27 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Bool (< s26 s27))
+[GOOD] (define-fun s29 () Bool (= s26 s27))
+[GOOD] (define-fun s30 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s31 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s32 () Bool (< s30 s31))
+[GOOD] (define-fun s33 () Bool (and s29 s32))
+[GOOD] (define-fun s34 () Bool (or s28 s33))
+[GOOD] (define-fun s35 () Bool (=> s4 s34))
+[GOOD] (define-fun s36 () Bool (not s7))
+[GOOD] (define-fun s37 () Bool (not s4))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (define-fun s39 () Int (proj_1_SBVTuple2 s25))
+[GOOD] (define-fun s40 () Bool (< s39 s27))
+[GOOD] (define-fun s41 () Bool (= s27 s39))
+[GOOD] (define-fun s42 () Int (proj_2_SBVTuple2 s25))
+[GOOD] (define-fun s43 () Bool (< s42 s31))
+[GOOD] (define-fun s44 () Bool (and s41 s43))
+[GOOD] (define-fun s45 () Bool (or s40 s44))
+[GOOD] (define-fun s46 () Bool (=> s38 s45))
+[GOOD] (define-fun s47 () Bool (and s35 s46))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s47))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 20)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| :: SInteger -> (SBool, SBool) [Recursive]
+[GOOD] (define-fun-rec |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| ((l1_s0 Int)) (SBVTuple2 Bool Bool)
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s6 (mkSBVTuple2 true false)))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s2 (< l1_s0 l1_s1)))
+                                 (let ((l1_s3 (- l1_s0)))
+                                 (let ((l1_s4 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s3)))
+                                 (let ((l1_s5 (= l1_s0 l1_s1)))
+                                 (let ((l1_s8 (- l1_s0 l1_s7)))
+                                 (let ((l1_s9 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s8)))
+                                 (let ((l1_s10 (proj_2_SBVTuple2 l1_s9)))
+                                 (let ((l1_s11 (proj_1_SBVTuple2 l1_s9)))
+                                 (let ((l1_s12 ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) l1_s10 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s5 l1_s6 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s2 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s0))
+[GOOD] (define-fun s5 () Bool (proj_1_SBVTuple2 s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (declare-fun s9 () Bool)
+[GOOD] (define-fun s10 () Bool (= s2 s8))
+[GOOD] (define-fun s11 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s8))
+[GOOD] (define-fun s12 () Bool (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (= s9 s12))
+[GOOD] (define-fun s14 () Bool (and s10 s13))
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 20))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[SEND] (get-value (s8))
+[RECV] ((s8 20))
+[SEND] (get-value (s9))
+[RECV] ((s9 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =   20 :: Integer
+  s1 = True :: Bool
+  s8 =   20 :: Integer
+  s9 = True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda49_c.gold b/SBVTestSuite/GoldFiles/lambda49_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda49_c.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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 true))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = True :: Bool
+  s1 = True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda50.gold b/SBVTestSuite/GoldFiles/lambda50.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda50.gold
@@ -0,0 +1,215 @@
+[MEASURE] Verifying termination measures for: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] Checking: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): verifying with 0 helper(s)
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s19 () Bool (>= s18 s1))
+[GOOD] (define-fun s20 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s21 () Bool (>= s20 s1))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (abs s5))
+[GOOD] (define-fun s19 () Bool (< s5 s1))
+[GOOD] (define-fun s20 () Int (ite s19 s2 s1))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Int (abs s8))
+[GOOD] (define-fun s23 () Bool (< s8 s1))
+[GOOD] (define-fun s24 () Int (ite s23 s2 s1))
+[GOOD] (define-fun s25 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s22 s24))
+[GOOD] (define-fun s26 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s27 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Bool (< s26 s27))
+[GOOD] (define-fun s29 () Bool (= s26 s27))
+[GOOD] (define-fun s30 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s31 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s32 () Bool (< s30 s31))
+[GOOD] (define-fun s33 () Bool (and s29 s32))
+[GOOD] (define-fun s34 () Bool (or s28 s33))
+[GOOD] (define-fun s35 () Bool (=> s4 s34))
+[GOOD] (define-fun s36 () Bool (not s7))
+[GOOD] (define-fun s37 () Bool (not s4))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (define-fun s39 () Int (proj_1_SBVTuple2 s25))
+[GOOD] (define-fun s40 () Bool (< s39 s27))
+[GOOD] (define-fun s41 () Bool (= s27 s39))
+[GOOD] (define-fun s42 () Int (proj_2_SBVTuple2 s25))
+[GOOD] (define-fun s43 () Bool (< s42 s31))
+[GOOD] (define-fun s44 () Bool (and s41 s43))
+[GOOD] (define-fun s45 () Bool (or s40 s44))
+[GOOD] (define-fun s46 () Bool (=> s38 s45))
+[GOOD] (define-fun s47 () Bool (and s35 s46))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s47))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| :: SInteger -> (SBool, SBool) [Recursive]
+[GOOD] (define-fun-rec |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| ((l1_s0 Int)) (SBVTuple2 Bool Bool)
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s6 (mkSBVTuple2 true false)))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s2 (< l1_s0 l1_s1)))
+                                 (let ((l1_s3 (- l1_s0)))
+                                 (let ((l1_s4 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s3)))
+                                 (let ((l1_s5 (= l1_s0 l1_s1)))
+                                 (let ((l1_s8 (- l1_s0 l1_s7)))
+                                 (let ((l1_s9 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s8)))
+                                 (let ((l1_s10 (proj_2_SBVTuple2 l1_s9)))
+                                 (let ((l1_s11 (proj_1_SBVTuple2 l1_s9)))
+                                 (let ((l1_s12 ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) l1_s10 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s5 l1_s6 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s2 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s0))
+[GOOD] (define-fun s5 () Bool (proj_1_SBVTuple2 s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (declare-fun s9 () Bool)
+[GOOD] (define-fun s10 () Bool (= s2 s8))
+[GOOD] (define-fun s11 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s8))
+[GOOD] (define-fun s12 () Bool (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (= s9 s12))
+[GOOD] (define-fun s14 () Bool (and s10 s13))
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 21))
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+[SEND] (get-value (s8))
+[RECV] ((s8 21))
+[SEND] (get-value (s9))
+[RECV] ((s9 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =    21 :: Integer
+  s1 = False :: Bool
+  s8 =    21 :: Integer
+  s9 = False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda50_c.gold b/SBVTestSuite/GoldFiles/lambda50_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda50_c.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-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (not s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () Bool (not s2))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 false))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = False :: Bool
+  s2 = False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda51.gold b/SBVTestSuite/GoldFiles/lambda51.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda51.gold
@@ -0,0 +1,215 @@
+[MEASURE] Verifying termination measures for: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] Checking: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): verifying with 0 helper(s)
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s19 () Bool (>= s18 s1))
+[GOOD] (define-fun s20 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s21 () Bool (>= s20 s1))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (abs s5))
+[GOOD] (define-fun s19 () Bool (< s5 s1))
+[GOOD] (define-fun s20 () Int (ite s19 s2 s1))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Int (abs s8))
+[GOOD] (define-fun s23 () Bool (< s8 s1))
+[GOOD] (define-fun s24 () Int (ite s23 s2 s1))
+[GOOD] (define-fun s25 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s22 s24))
+[GOOD] (define-fun s26 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s27 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Bool (< s26 s27))
+[GOOD] (define-fun s29 () Bool (= s26 s27))
+[GOOD] (define-fun s30 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s31 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s32 () Bool (< s30 s31))
+[GOOD] (define-fun s33 () Bool (and s29 s32))
+[GOOD] (define-fun s34 () Bool (or s28 s33))
+[GOOD] (define-fun s35 () Bool (=> s4 s34))
+[GOOD] (define-fun s36 () Bool (not s7))
+[GOOD] (define-fun s37 () Bool (not s4))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (define-fun s39 () Int (proj_1_SBVTuple2 s25))
+[GOOD] (define-fun s40 () Bool (< s39 s27))
+[GOOD] (define-fun s41 () Bool (= s27 s39))
+[GOOD] (define-fun s42 () Int (proj_2_SBVTuple2 s25))
+[GOOD] (define-fun s43 () Bool (< s42 s31))
+[GOOD] (define-fun s44 () Bool (and s41 s43))
+[GOOD] (define-fun s45 () Bool (or s40 s44))
+[GOOD] (define-fun s46 () Bool (=> s38 s45))
+[GOOD] (define-fun s47 () Bool (and s35 s46))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s47))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 20)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| :: SInteger -> (SBool, SBool) [Recursive]
+[GOOD] (define-fun-rec |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| ((l1_s0 Int)) (SBVTuple2 Bool Bool)
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s6 (mkSBVTuple2 true false)))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s2 (< l1_s0 l1_s1)))
+                                 (let ((l1_s3 (- l1_s0)))
+                                 (let ((l1_s4 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s3)))
+                                 (let ((l1_s5 (= l1_s0 l1_s1)))
+                                 (let ((l1_s8 (- l1_s0 l1_s7)))
+                                 (let ((l1_s9 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s8)))
+                                 (let ((l1_s10 (proj_2_SBVTuple2 l1_s9)))
+                                 (let ((l1_s11 (proj_1_SBVTuple2 l1_s9)))
+                                 (let ((l1_s12 ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) l1_s10 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s5 l1_s6 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s2 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s0))
+[GOOD] (define-fun s5 () Bool (proj_2_SBVTuple2 s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (declare-fun s9 () Bool)
+[GOOD] (define-fun s10 () Bool (= s2 s8))
+[GOOD] (define-fun s11 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s8))
+[GOOD] (define-fun s12 () Bool (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (= s9 s12))
+[GOOD] (define-fun s14 () Bool (and s10 s13))
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 20))
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+[SEND] (get-value (s8))
+[RECV] ((s8 20))
+[SEND] (get-value (s9))
+[RECV] ((s9 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =    20 :: Integer
+  s1 = False :: Bool
+  s8 =    20 :: Integer
+  s9 = False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda51_c.gold b/SBVTestSuite/GoldFiles/lambda51_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda51_c.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-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (not s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () Bool (not s2))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 false))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = False :: Bool
+  s2 = False :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda52.gold b/SBVTestSuite/GoldFiles/lambda52.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda52.gold
@@ -0,0 +1,215 @@
+[MEASURE] Verifying termination measures for: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] Checking: isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): verifying with 0 helper(s)
+[MEASURE] isEvenOdd @(SBV Integer -> SBV (Bool,Bool)): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s19 () Bool (>= s18 s1))
+[GOOD] (define-fun s20 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s21 () Bool (>= s20 s1))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {isEvenOdd @(SBV Integer -> SBV (Bool,Bool))}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (SBVTuple2 Bool Bool) (mkSBVTuple2 true false))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s9 () (SBVTuple2 Bool Bool)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (< s0 s1))
+[GOOD] (define-fun s5 () Int (- s0))
+[GOOD] (define-fun s7 () Bool (= s0 s1))
+[GOOD] (define-fun s8 () Int (- s0 s2))
+[GOOD] (define-fun s10 () Bool (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s11 () Bool (proj_1_SBVTuple2 s9))
+[GOOD] (define-fun s12 () (SBVTuple2 Bool Bool) ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) s10 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Bool Bool) (ite s7 s3 s12))
+[GOOD] (define-fun s14 () (SBVTuple2 Bool Bool) (ite s4 s6 s13))
+[GOOD] (define-fun s15 () Int (abs s0))
+[GOOD] (define-fun s16 () Int (ite s4 s2 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Int (abs s5))
+[GOOD] (define-fun s19 () Bool (< s5 s1))
+[GOOD] (define-fun s20 () Int (ite s19 s2 s1))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Int (abs s8))
+[GOOD] (define-fun s23 () Bool (< s8 s1))
+[GOOD] (define-fun s24 () Int (ite s23 s2 s1))
+[GOOD] (define-fun s25 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s22 s24))
+[GOOD] (define-fun s26 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s27 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Bool (< s26 s27))
+[GOOD] (define-fun s29 () Bool (= s26 s27))
+[GOOD] (define-fun s30 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s31 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s32 () Bool (< s30 s31))
+[GOOD] (define-fun s33 () Bool (and s29 s32))
+[GOOD] (define-fun s34 () Bool (or s28 s33))
+[GOOD] (define-fun s35 () Bool (=> s4 s34))
+[GOOD] (define-fun s36 () Bool (not s7))
+[GOOD] (define-fun s37 () Bool (not s4))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (define-fun s39 () Int (proj_1_SBVTuple2 s25))
+[GOOD] (define-fun s40 () Bool (< s39 s27))
+[GOOD] (define-fun s41 () Bool (= s27 s39))
+[GOOD] (define-fun s42 () Int (proj_2_SBVTuple2 s25))
+[GOOD] (define-fun s43 () Bool (< s42 s31))
+[GOOD] (define-fun s44 () Bool (and s41 s43))
+[GOOD] (define-fun s45 () Bool (or s40 s44))
+[GOOD] (define-fun s46 () Bool (=> s38 s45))
+[GOOD] (define-fun s47 () Bool (and s35 s46))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s47))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): isEvenOdd @(SBV Integer -> SBV (Bool,Bool))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 21)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| :: SInteger -> (SBool, SBool) [Recursive]
+[GOOD] (define-fun-rec |isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| ((l1_s0 Int)) (SBVTuple2 Bool Bool)
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s6 (mkSBVTuple2 true false)))
+                                 (let ((l1_s7 1))
+                                 (let ((l1_s2 (< l1_s0 l1_s1)))
+                                 (let ((l1_s3 (- l1_s0)))
+                                 (let ((l1_s4 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s3)))
+                                 (let ((l1_s5 (= l1_s0 l1_s1)))
+                                 (let ((l1_s8 (- l1_s0 l1_s7)))
+                                 (let ((l1_s9 (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| l1_s8)))
+                                 (let ((l1_s10 (proj_2_SBVTuple2 l1_s9)))
+                                 (let ((l1_s11 (proj_1_SBVTuple2 l1_s9)))
+                                 (let ((l1_s12 ((as mkSBVTuple2 (SBVTuple2 Bool Bool)) l1_s10 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s5 l1_s6 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s2 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s0))
+[GOOD] (define-fun s5 () Bool (proj_2_SBVTuple2 s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[GOOD] (declare-fun s8 () Int)
+[GOOD] (declare-fun s9 () Bool)
+[GOOD] (define-fun s10 () Bool (= s2 s8))
+[GOOD] (define-fun s11 () (SBVTuple2 Bool Bool) (|isEvenOdd @(SBV Integer -> SBV (Bool,Bool))| s8))
+[GOOD] (define-fun s12 () Bool (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (= s9 s12))
+[GOOD] (define-fun s14 () Bool (and s10 s13))
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 21))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[SEND] (get-value (s8))
+[RECV] ((s8 21))
+[SEND] (get-value (s9))
+[RECV] ((s9 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =   21 :: Integer
+  s1 = True :: Bool
+  s8 =   21 :: Integer
+  s9 = True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda52_c.gold b/SBVTestSuite/GoldFiles/lambda52_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda52_c.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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (declare-fun s1 () Bool)
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 true))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = True :: Bool
+  s1 = True :: Bool
diff --git a/SBVTestSuite/GoldFiles/lambda53.gold b/SBVTestSuite/GoldFiles/lambda53.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda53.gold
@@ -0,0 +1,36 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |foo @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |foo @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+         (+ s0 l1_s0))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|foo @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda54.gold b/SBVTestSuite/GoldFiles/lambda54.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda54.gold
@@ -0,0 +1,58 @@
+[MEASURE] Verifying termination measures for: foo @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: foo @(SBV Integer -> SBV Integer)
+[MEASURE] foo @(SBV Integer -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): foo @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |bar @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |bar @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 1))
+                                 (let ((l1_s2 (+ l1_s0 l1_s1)))
+                                 l1_s2)))
+[GOOD] ; |foo @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Refers to: |bar @(SBV Integer -> SBV Integer)|]
+[GOOD] (define-fun |foo @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s2 1))
+                                 (let ((l1_s1 (|bar @(SBV Integer -> SBV Integer)| l1_s0)))
+                                 (let ((l1_s3 (+ l1_s1 l1_s2)))
+                                 l1_s3))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|bar @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Int (|foo @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (declare-fun s5 () Int)
+[GOOD] (define-fun s6 () Int (|bar @(SBV Integer -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Int (|foo @(SBV Integer -> SBV Integer)| s5))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (- 3)))
+[SEND] (get-value (s5))
+[RECV] ((s5 (- 3)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = -3 :: Integer
+  s5 = -3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda55.gold b/SBVTestSuite/GoldFiles/lambda55.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda55.gold
@@ -0,0 +1,58 @@
+[MEASURE] Verifying termination measures for: foo @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: foo @(SBV Integer -> SBV Integer)
+[MEASURE] foo @(SBV Integer -> SBV Integer): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): foo @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |bar @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |bar @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int
+                                                 (let ((l2_s1 1))
+                                                 (let ((l2_s2 (+ l2_s0 l2_s1)))
+                                                 l2_s2)))
+[GOOD] ; |foo @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Refers to: |bar @(SBV Integer -> SBV Integer)|]
+[GOOD] (define-fun |foo @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s2 1))
+                                 (let ((l1_s1 (|bar @(SBV Integer -> SBV Integer)| l1_s0)))
+                                 (let ((l1_s3 (+ l1_s1 l1_s2)))
+                                 l1_s3))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|foo @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Int (|bar @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (declare-fun s5 () Int)
+[GOOD] (define-fun s6 () Int (|foo @(SBV Integer -> SBV Integer)| s5))
+[GOOD] (define-fun s7 () Int (|bar @(SBV Integer -> SBV Integer)| s5))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (- 3)))
+[SEND] (get-value (s5))
+[RECV] ((s5 (- 3)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = -3 :: Integer
+  s5 = -3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda56.gold b/SBVTestSuite/GoldFiles/lambda56.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda56.gold
@@ -0,0 +1,458 @@
+[MEASURE] Verifying termination measures for: foo @(SBV Integer -> SBV Integer), bar @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: foo @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {bar :: SBV Integer -> SBV Integer, foo :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s6 () Bool (>= s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s6))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s5 () Bool (=> true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s5))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s4))
+[RECV] ((s4 0))
+[SEND] (get-value (s4))
+[RECV] ((s4 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s2))
+[RECV] ((s2 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bar @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 0 :: Integer
+  before = 0 :: Integer
+  then   = 0 :: Integer
+[MEASURE] Mutual group: measure abs arg1 failed, trying next
+[MEASURE] Mutual group: trying measure smax 0 arg1 for all members
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s5 () Bool (<= s4 s0))
+[GOOD] (define-fun s6 () Int (ite s5 s0 s4))
+[GOOD] (define-fun s7 () Bool (>= s6 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s7))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s5 () Bool (<= s4 s0))
+[GOOD] (define-fun s6 () Int (ite s5 s0 s4))
+[GOOD] (define-fun s7 () Bool (=> true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s7))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s6))
+[RECV] ((s6 0))
+[SEND] (get-value (s6))
+[RECV] ((s6 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s2))
+[RECV] ((s2 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bar @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 0 :: Integer
+  before = 0 :: Integer
+  then   = 0 :: Integer
+[MEASURE] Mutual group: measure smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure abs arg1 + smax 0 arg1 for all members
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s6 () Bool (<= s5 s0))
+[GOOD] (define-fun s7 () Int (ite s6 s0 s5))
+[GOOD] (define-fun s8 () Int (+ s4 s7))
+[GOOD] (define-fun s9 () Bool (>= s8 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s6 () Bool (<= s5 s0))
+[GOOD] (define-fun s7 () Int (ite s6 s0 s5))
+[GOOD] (define-fun s8 () Int (+ s4 s7))
+[GOOD] (define-fun s9 () Bool (=> true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s2))
+[RECV] ((s2 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bar @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 0 :: Integer
+  before = 0 :: Integer
+  then   = 0 :: Integer
+[MEASURE] Mutual group: measure abs arg1 + smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure (abs arg1, smax 0 arg1) for all members
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 1)
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s6 () Bool (<= s5 s0))
+[GOOD] (define-fun s7 () Int (ite s6 s0 s5))
+[GOOD] (define-fun s8 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s4 s7))
+[GOOD] (define-fun s9 () Int (proj_1_SBVTuple2 s8))
+[GOOD] (define-fun s10 () Bool (>= s9 s5))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s8))
+[GOOD] (define-fun s12 () Bool (>= s11 s5))
+[GOOD] (define-fun s13 () Bool (and s10 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 1)
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () Int (abs s0))
+[GOOD] (define-fun s6 () Bool (<= s5 s0))
+[GOOD] (define-fun s7 () Int (ite s6 s0 s5))
+[GOOD] (define-fun s8 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s4 s7))
+[GOOD] (define-fun s9 () Int (proj_1_SBVTuple2 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s8))
+[GOOD] (define-fun s11 () Bool (=> true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s11))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 (mkSBVTuple2 0 0)))
+[SEND] (get-value (s8))
+[RECV] ((s8 (mkSBVTuple2 0 0)))
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s2))
+[RECV] ((s2 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bar @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     0 :: Integer
+  before = (0,0) :: (Integer, Integer)
+  then   = (0,0) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (abs arg1, smax 0 arg1) failed, trying next
+[MEASURE] Mutual group: trying measure (smax 0 arg1, abs arg1) for all members
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 1)
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s5 () Bool (<= s4 s0))
+[GOOD] (define-fun s6 () Int (ite s5 s0 s4))
+[GOOD] (define-fun s7 () Int (abs s0))
+[GOOD] (define-fun s8 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s6 s7))
+[GOOD] (define-fun s9 () Int (proj_1_SBVTuple2 s8))
+[GOOD] (define-fun s10 () Bool (>= s9 s4))
+[GOOD] (define-fun s11 () Int (proj_2_SBVTuple2 s8))
+[GOOD] (define-fun s12 () Bool (>= s11 s4))
+[GOOD] (define-fun s13 () Bool (and s10 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bar @(SBV Integer -> SBV Integer), foo @(SBV Integer -> SBV Integer)}: replaying 2 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 1)
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "__internal_sbv_s2"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s5 () Bool (<= s4 s0))
+[GOOD] (define-fun s6 () Int (ite s5 s0 s4))
+[GOOD] (define-fun s7 () Int (abs s0))
+[GOOD] (define-fun s8 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s6 s7))
+[GOOD] (define-fun s9 () Int (proj_1_SBVTuple2 s8))
+[GOOD] (define-fun s10 () Int (proj_2_SBVTuple2 s8))
+[GOOD] (define-fun s11 () Bool (=> true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s11))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 (mkSBVTuple2 0 0)))
+[SEND] (get-value (s8))
+[RECV] ((s8 (mkSBVTuple2 0 0)))
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s2))
+[RECV] ((s2 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bar @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     0 :: Integer
+  before = (0,0) :: (Integer, Integer)
+  then   = (0,0) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (smax 0 arg1, abs arg1) failed, trying next
+
+EXCEPTION CAUGHT:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     bar  :: SBV Integer -> SBV Integer
+***     foo  :: SBV Integer -> SBV Integer
+***
+*** Please use 'smtFunctionWithMeasure' to provide explicit measures.
+
diff --git a/SBVTestSuite/GoldFiles/lambda57.gold b/SBVTestSuite/GoldFiles/lambda57.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda57.gold
@@ -0,0 +1,120 @@
+[MEASURE] Verifying termination measures for: f1 @(SBV Word8 -> SBV Word8), f1 @(SBV Word8 -> SBV Word8), f2 @(SBV Word8 -> SBV Word8), f2 @(SBV Word8 -> SBV Word8), f3 @(SBV Word8 -> SBV Word8), f3 @(SBV Word8 -> SBV Word8), f4 @(SBV Word8 -> SBV Word8), f4 @(SBV Word8 -> SBV Word8)
+[MEASURE] Checking: f1 @(SBV Word8 -> SBV Word8)
+[MEASURE] Checking mutual recursion group: {f1 :: SBV Word8 -> SBV Word8, f2 :: SBV Word8 -> SBV Word8, f3 :: SBV Word8 -> SBV Word8, f4 :: SBV Word8 -> SBV Word8}
+[MEASURE] Mutual group: trying measure arg1 for all members
+[MEASURE] replayDAG {f1 @(SBV Word8 -> SBV Word8), f2 @(SBV Word8 -> SBV Word8), f3 @(SBV Word8 -> SBV Word8), f4 @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] (define-fun s13 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s14 () Bool (>= s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1 @(SBV Word8 -> SBV Word8), f2 @(SBV Word8 -> SBV Word8), f3 @(SBV Word8 -> SBV Word8), f4 @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s13 () Int (ubv_to_int s5))
+[GOOD] (define-fun s14 () Int (ubv_to_int s7))
+[GOOD] (define-fun s15 () Bool (not s4))
+[GOOD] (define-fun s16 () Bool (> s12 s13))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] (define-fun s18 () Bool (> s12 s14))
+[GOOD] (define-fun s19 () Bool (=> s15 s18))
+[GOOD] (define-fun s20 () Bool (and s17 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s12))
+[RECV] ((s12 1))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 255))
+[SEND] (get-value (s0))
+[RECV] ((s0 #x01))
+[SEND] (get-value (s6))
+[RECV] ((s6 #x00))
+[SEND] (get-value (s8))
+[RECV] ((s8 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for f1 @(SBV Word8 -> SBV Word8): Falsifiable. Counter-example:
+  arg     =   1 :: Word8
+  before  =   1 :: Integer
+  then[1] =   0 :: Integer
+  then[2] = 255 :: Integer
+[MEASURE] Mutual group: measure arg1 failed, trying next
+
+EXCEPTION CAUGHT:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     f1  :: SBV Word8 -> SBV Word8
+***     f2  :: SBV Word8 -> SBV Word8
+***     f3  :: SBV Word8 -> SBV Word8
+***     f4  :: SBV Word8 -> SBV Word8
+***
+*** Please use 'smtFunctionWithMeasure' to provide explicit measures.
+
diff --git a/SBVTestSuite/GoldFiles/lambda57a.gold b/SBVTestSuite/GoldFiles/lambda57a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda57a.gold
@@ -0,0 +1,928 @@
+[MEASURE] Verifying termination measures for: f1i @(SBV Integer -> SBV Integer), f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f1i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {f1i :: SBV Integer -> SBV Integer, f2i :: SBV Integer -> SBV Integer, f3i :: SBV Integer -> SBV Integer, f4i :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Int (abs s5))
+[GOOD] (define-fun s14 () Int (abs s7))
+[GOOD] (define-fun s15 () Bool (not s4))
+[GOOD] (define-fun s16 () Bool (> s12 s13))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] (define-fun s18 () Bool (> s12 s14))
+[GOOD] (define-fun s19 () Bool (=> s15 s18))
+[GOOD] (define-fun s20 () Bool (and s17 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s12))
+[RECV] ((s12 1))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s6))
+[RECV] ((s6 0))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for f1i @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     = 1 :: Integer
+  before  = 1 :: Integer
+  then[1] = 0 :: Integer
+  then[2] = 1 :: Integer
+[MEASURE] Mutual group: measure abs arg1 failed, trying next
+[MEASURE] Mutual group: trying measure smax 0 arg1 for all members
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f1i @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f2i @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f3i @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer), f2i @(SBV Integer -> SBV Integer), f3i @(SBV Integer -> SBV Integer), f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f4i @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure smax 0 arg1 works for all members
+[MEASURE] Passed (terminating): f1i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f1i @(SBV Integer -> SBV Integer)
+[MEASURE] f1i @(SBV Integer -> SBV Integer): barified = "|f1i @(SBV Integer -> SBV Integer)|"
+[MEASURE] f1i @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|f1i @(SBV Integer -> SBV Integer)|",1),("|f2i @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] f1i @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] f1i @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Int (abs s5))
+[GOOD] (define-fun s14 () Bool (not s4))
+[GOOD] (define-fun s15 () Bool (> s12 s13))
+[GOOD] (define-fun s16 () Bool (=> s14 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] f1i @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): f1i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f2i @(SBV Integer -> SBV Integer)
+[MEASURE] f2i @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f2i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f2i @(SBV Integer -> SBV Integer)
+[MEASURE] f2i @(SBV Integer -> SBV Integer): barified = "|f2i @(SBV Integer -> SBV Integer)|"
+[MEASURE] f2i @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|f2i @(SBV Integer -> SBV Integer)|",1),("|f3i @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] f2i @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] f2i @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {f2i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f2i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Int (abs s5))
+[GOOD] (define-fun s14 () Bool (not s4))
+[GOOD] (define-fun s15 () Bool (> s12 s13))
+[GOOD] (define-fun s16 () Bool (=> s14 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] f2i @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): f2i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f3i @(SBV Integer -> SBV Integer)
+[MEASURE] f3i @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f3i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f3i @(SBV Integer -> SBV Integer)
+[MEASURE] f3i @(SBV Integer -> SBV Integer): barified = "|f3i @(SBV Integer -> SBV Integer)|"
+[MEASURE] f3i @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|f3i @(SBV Integer -> SBV Integer)|",1),("|f4i @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] f3i @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] f3i @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {f3i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f3i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Int (abs s5))
+[GOOD] (define-fun s14 () Bool (not s4))
+[GOOD] (define-fun s15 () Bool (> s12 s13))
+[GOOD] (define-fun s16 () Bool (=> s14 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] f3i @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): f3i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f4i @(SBV Integer -> SBV Integer)
+[MEASURE] f4i @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f4i @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f4i @(SBV Integer -> SBV Integer)
+[MEASURE] f4i @(SBV Integer -> SBV Integer): barified = "|f4i @(SBV Integer -> SBV Integer)|"
+[MEASURE] f4i @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|f4i @(SBV Integer -> SBV Integer)|",1),("|f1i @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] f4i @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] f4i @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f4i @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () Int (abs s5))
+[GOOD] (define-fun s14 () Bool (not s4))
+[GOOD] (define-fun s15 () Bool (> s12 s13))
+[GOOD] (define-fun s16 () Bool (=> s14 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] f4i @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): f4i @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |f1i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f2i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f3i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f4i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|f1i @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|f2i @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int)
+          (|f3i @(SBV Integer -> SBV Integer)| ((l3_s0 Int)) Int)
+          (|f4i @(SBV Integer -> SBV Integer)| ((l4_s0 Int)) Int))
+         (; Definition of: |f1i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f1i @(SBV Integer -> SBV Integer)|, |f2i @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s6 2))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|f1i @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s7 (- l1_s0 l1_s6)))
+                                  (let ((l1_s8 (|f2i @(SBV Integer -> SBV Integer)| l1_s7)))
+                                  (let ((l1_s9 (+ l1_s5 l1_s8)))
+                                  (let ((l1_s10 (+ l1_s3 l1_s9)))
+                                  (let ((l1_s11 (ite l1_s2 l1_s1 l1_s10)))
+                                  l1_s11)))))))))))
+          ; Definition of: |f2i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f2i @(SBV Integer -> SBV Integer)|, |f3i @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s6 2))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|f2i @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s7 (- l2_s0 l2_s6)))
+                                                  (let ((l2_s8 (|f3i @(SBV Integer -> SBV Integer)| l2_s7)))
+                                                  (let ((l2_s9 (+ l2_s5 l2_s8)))
+                                                  (let ((l2_s10 (+ l2_s3 l2_s9)))
+                                                  (let ((l2_s11 (ite l2_s2 l2_s1 l2_s10)))
+                                                  l2_s11)))))))))))
+          ; Definition of: |f3i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f3i @(SBV Integer -> SBV Integer)|, |f4i @(SBV Integer -> SBV Integer)|]
+                                                                  (let ((l3_s1 0))
+                                                                  (let ((l3_s3 1))
+                                                                  (let ((l3_s6 2))
+                                                                  (let ((l3_s2 (<= l3_s0 l3_s1)))
+                                                                  (let ((l3_s4 (- l3_s0 l3_s3)))
+                                                                  (let ((l3_s5 (|f3i @(SBV Integer -> SBV Integer)| l3_s4)))
+                                                                  (let ((l3_s7 (- l3_s0 l3_s6)))
+                                                                  (let ((l3_s8 (|f4i @(SBV Integer -> SBV Integer)| l3_s7)))
+                                                                  (let ((l3_s9 (+ l3_s5 l3_s8)))
+                                                                  (let ((l3_s10 (+ l3_s3 l3_s9)))
+                                                                  (let ((l3_s11 (ite l3_s2 l3_s1 l3_s10)))
+                                                                  l3_s11)))))))))))
+          ; Definition of: |f4i @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f1i @(SBV Integer -> SBV Integer)|, |f4i @(SBV Integer -> SBV Integer)|]
+                                                                                  (let ((l4_s1 0))
+                                                                                  (let ((l4_s3 1))
+                                                                                  (let ((l4_s6 2))
+                                                                                  (let ((l4_s2 (<= l4_s0 l4_s1)))
+                                                                                  (let ((l4_s4 (- l4_s0 l4_s3)))
+                                                                                  (let ((l4_s5 (|f4i @(SBV Integer -> SBV Integer)| l4_s4)))
+                                                                                  (let ((l4_s7 (- l4_s0 l4_s6)))
+                                                                                  (let ((l4_s8 (|f1i @(SBV Integer -> SBV Integer)| l4_s7)))
+                                                                                  (let ((l4_s9 (+ l4_s5 l4_s8)))
+                                                                                  (let ((l4_s10 (+ l4_s3 l4_s9)))
+                                                                                  (let ((l4_s11 (ite l4_s2 l4_s1 l4_s10)))
+                                                                                  l4_s11)))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|f1i @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (declare-fun s3 () Int)
+[GOOD] (define-fun s4 () Int (|f1i @(SBV Integer -> SBV Integer)| s3))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s3))
+[RECV] ((s3 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = 0 :: Integer
+  s3 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda57b.gold b/SBVTestSuite/GoldFiles/lambda57b.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda57b.gold
@@ -0,0 +1,824 @@
+[MEASURE] Verifying termination measures for: f1m @(SBV Integer -> SBV Integer), f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f1m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {f1m :: SBV Integer -> SBV Integer, f2m :: SBV Integer -> SBV Integer, f3m :: SBV Integer -> SBV Integer, f4m :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f1m @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f2m @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f3m @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer), f2m @(SBV Integer -> SBV Integer), f3m @(SBV Integer -> SBV Integer), f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (<= s1 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s1))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (> s13 s15))
+[GOOD] (define-fun s20 () Bool (=> s18 s19))
+[GOOD] (define-fun s21 () Bool (> s13 s17))
+[GOOD] (define-fun s22 () Bool (=> s18 s21))
+[GOOD] (define-fun s23 () Bool (and s20 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for f4m @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: user-provided measure works for all members
+[MEASURE] Passed (terminating): f1m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f1m @(SBV Integer -> SBV Integer)
+[MEASURE] f1m @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] f1m @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (not s4))
+[GOOD] (define-fun s17 () Bool (> s13 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): f1m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f2m @(SBV Integer -> SBV Integer)
+[MEASURE] f2m @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f2m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f2m @(SBV Integer -> SBV Integer)
+[MEASURE] f2m @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] f2m @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {f2m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f2m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (not s4))
+[GOOD] (define-fun s17 () Bool (> s13 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): f2m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f3m @(SBV Integer -> SBV Integer)
+[MEASURE] f3m @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f3m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f3m @(SBV Integer -> SBV Integer)
+[MEASURE] f3m @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] f3m @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {f3m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f3m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (not s4))
+[GOOD] (define-fun s17 () Bool (> s13 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): f3m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f4m @(SBV Integer -> SBV Integer)
+[MEASURE] f4m @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): f4m @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f4m @(SBV Integer -> SBV Integer)
+[MEASURE] f4m @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] f4m @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f4m @(SBV Integer -> SBV Integer)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s1))
+[GOOD] (define-fun s5 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (+ s6 s8))
+[GOOD] (define-fun s10 () Int (+ s2 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s0))
+[GOOD] (define-fun s13 () Int (ite s12 s0 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s5))
+[GOOD] (define-fun s15 () Int (ite s14 s5 s1))
+[GOOD] (define-fun s16 () Bool (not s4))
+[GOOD] (define-fun s17 () Bool (> s13 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): f4m @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |f1m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f2m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f3m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |f4m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|f1m @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|f2m @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int)
+          (|f3m @(SBV Integer -> SBV Integer)| ((l3_s0 Int)) Int)
+          (|f4m @(SBV Integer -> SBV Integer)| ((l4_s0 Int)) Int))
+         (; Definition of: |f1m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f1m @(SBV Integer -> SBV Integer)|, |f2m @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s6 2))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|f1m @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s7 (- l1_s0 l1_s6)))
+                                  (let ((l1_s8 (|f2m @(SBV Integer -> SBV Integer)| l1_s7)))
+                                  (let ((l1_s9 (+ l1_s5 l1_s8)))
+                                  (let ((l1_s10 (+ l1_s3 l1_s9)))
+                                  (let ((l1_s11 (ite l1_s2 l1_s1 l1_s10)))
+                                  l1_s11)))))))))))
+          ; Definition of: |f2m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f2m @(SBV Integer -> SBV Integer)|, |f3m @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s6 2))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|f2m @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s7 (- l2_s0 l2_s6)))
+                                                  (let ((l2_s8 (|f3m @(SBV Integer -> SBV Integer)| l2_s7)))
+                                                  (let ((l2_s9 (+ l2_s5 l2_s8)))
+                                                  (let ((l2_s10 (+ l2_s3 l2_s9)))
+                                                  (let ((l2_s11 (ite l2_s2 l2_s1 l2_s10)))
+                                                  l2_s11)))))))))))
+          ; Definition of: |f3m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f3m @(SBV Integer -> SBV Integer)|, |f4m @(SBV Integer -> SBV Integer)|]
+                                                                  (let ((l3_s1 0))
+                                                                  (let ((l3_s3 1))
+                                                                  (let ((l3_s6 2))
+                                                                  (let ((l3_s2 (<= l3_s0 l3_s1)))
+                                                                  (let ((l3_s4 (- l3_s0 l3_s3)))
+                                                                  (let ((l3_s5 (|f3m @(SBV Integer -> SBV Integer)| l3_s4)))
+                                                                  (let ((l3_s7 (- l3_s0 l3_s6)))
+                                                                  (let ((l3_s8 (|f4m @(SBV Integer -> SBV Integer)| l3_s7)))
+                                                                  (let ((l3_s9 (+ l3_s5 l3_s8)))
+                                                                  (let ((l3_s10 (+ l3_s3 l3_s9)))
+                                                                  (let ((l3_s11 (ite l3_s2 l3_s1 l3_s10)))
+                                                                  l3_s11)))))))))))
+          ; Definition of: |f4m @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |f1m @(SBV Integer -> SBV Integer)|, |f4m @(SBV Integer -> SBV Integer)|]
+                                                                                  (let ((l4_s1 0))
+                                                                                  (let ((l4_s3 1))
+                                                                                  (let ((l4_s6 2))
+                                                                                  (let ((l4_s2 (<= l4_s0 l4_s1)))
+                                                                                  (let ((l4_s4 (- l4_s0 l4_s3)))
+                                                                                  (let ((l4_s5 (|f4m @(SBV Integer -> SBV Integer)| l4_s4)))
+                                                                                  (let ((l4_s7 (- l4_s0 l4_s6)))
+                                                                                  (let ((l4_s8 (|f1m @(SBV Integer -> SBV Integer)| l4_s7)))
+                                                                                  (let ((l4_s9 (+ l4_s5 l4_s8)))
+                                                                                  (let ((l4_s10 (+ l4_s3 l4_s9)))
+                                                                                  (let ((l4_s11 (ite l4_s2 l4_s1 l4_s10)))
+                                                                                  l4_s11)))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|f1m @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (declare-fun s3 () Int)
+[GOOD] (define-fun s4 () Int (|f1m @(SBV Integer -> SBV Integer)| s3))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s3))
+[RECV] ((s3 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 = 0 :: Integer
+  s3 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/lambda57c.gold b/SBVTestSuite/GoldFiles/lambda57c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda57c.gold
@@ -0,0 +1,225 @@
+[MEASURE] Verifying termination measures for: f1w @(SBV Word8 -> SBV Word8), f1w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8)
+[MEASURE] Checking: f1w @(SBV Word8 -> SBV Word8)
+[MEASURE] Checking mutual recursion group: {f1w :: SBV Word8 -> SBV Word8, f2w :: SBV Word8 -> SBV Word8, f3w :: SBV Word8 -> SBV Word8, f4w :: SBV Word8 -> SBV Word8}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {f1w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] (define-fun s13 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s14 () Bool (>= s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s13 () Int (ubv_to_int s5))
+[GOOD] (define-fun s14 () Int (ubv_to_int s7))
+[GOOD] (define-fun s15 () Bool (not s4))
+[GOOD] (define-fun s16 () Bool (> s12 s13))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] (define-fun s18 () Bool (> s12 s14))
+[GOOD] (define-fun s19 () Bool (=> s15 s18))
+[GOOD] (define-fun s20 () Bool (and s17 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s12))
+[RECV] ((s12 1))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 255))
+[SEND] (get-value (s0))
+[RECV] ((s0 #x01))
+[SEND] (get-value (s6))
+[RECV] ((s6 #x00))
+[SEND] (get-value (s8))
+[RECV] ((s8 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for f1w @(SBV Word8 -> SBV Word8): Falsifiable. Counter-example:
+  arg     =   1 :: Word8
+  before  =   1 :: Integer
+  then[1] =   0 :: Integer
+  then[2] = 255 :: Integer
+[MEASURE] Mutual group: user-provided measure failed, falling back to auto-guess
+[MEASURE] Mutual group: trying measure arg1 for all members
+[MEASURE] replayDAG {f1w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] (define-fun s13 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s14 () Bool (>= s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f1w @(SBV Word8 -> SBV Word8), f2w @(SBV Word8 -> SBV Word8), f3w @(SBV Word8 -> SBV Word8), f4w @(SBV Word8 -> SBV Word8)}: replaying 8 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "arg"
+[GOOD] (declare-fun s6 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s6"
+[GOOD] (declare-fun s8 () (_ BitVec 8)) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 8) (bvsub s0 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvsub s0 s3))
+[GOOD] (define-fun s9 () (_ BitVec 8) (bvadd s6 s8))
+[GOOD] (define-fun s10 () (_ BitVec 8) (bvadd s2 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) (ite s4 s1 s10))
+[GOOD] (define-fun s12 () Int (ubv_to_int s0))
+[GOOD] (define-fun s13 () Int (ubv_to_int s5))
+[GOOD] (define-fun s14 () Int (ubv_to_int s7))
+[GOOD] (define-fun s15 () Bool (not s4))
+[GOOD] (define-fun s16 () Bool (> s12 s13))
+[GOOD] (define-fun s17 () Bool (=> s15 s16))
+[GOOD] (define-fun s18 () Bool (> s12 s14))
+[GOOD] (define-fun s19 () Bool (=> s15 s18))
+[GOOD] (define-fun s20 () Bool (and s17 s19))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s12))
+[RECV] ((s12 1))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 255))
+[SEND] (get-value (s0))
+[RECV] ((s0 #x01))
+[SEND] (get-value (s6))
+[RECV] ((s6 #x00))
+[SEND] (get-value (s8))
+[RECV] ((s8 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for f1w @(SBV Word8 -> SBV Word8): Falsifiable. Counter-example:
+  arg     =   1 :: Word8
+  before  =   1 :: Integer
+  then[1] =   0 :: Integer
+  then[2] = 255 :: Integer
+[MEASURE] Mutual group: measure arg1 failed, trying next
+
+EXCEPTION CAUGHT:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     f1w  :: SBV Word8 -> SBV Word8
+***     f2w  :: SBV Word8 -> SBV Word8
+***     f3w  :: SBV Word8 -> SBV Word8
+***     f4w  :: SBV Word8 -> SBV Word8
+***
+*** The user-provided measure did not work, and auto-guessing also failed.
+
diff --git a/SBVTestSuite/GoldFiles/lambda58.gold b/SBVTestSuite/GoldFiles/lambda58.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda58.gold
@@ -0,0 +1,5 @@
+; user defined axiom: 
+(assert (forall ((l1_s0 Bool)) (exists ((l1_s1 Bool))
+                            (let ((l1_s2 (not l1_s0)))
+                            (let ((l1_s3 (or l1_s1 l1_s2)))
+                            l1_s3)))))
diff --git a/SBVTestSuite/GoldFiles/lambda59.gold b/SBVTestSuite/GoldFiles/lambda59.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda59.gold
@@ -0,0 +1,6 @@
+; user defined axiom: 
+(assert (forall ((l1_s0 Int)) (exists ((l1_s1 Bool))
+                            (let ((l1_s2 0))
+                            (let ((l1_s3 (= l1_s0 l1_s2)))
+                            (let ((l1_s4 (or l1_s1 l1_s3)))
+                            l1_s4))))))
diff --git a/SBVTestSuite/GoldFiles/lambda60.gold b/SBVTestSuite/GoldFiles/lambda60.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda60.gold
@@ -0,0 +1,31 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int)) (exists ((l1_s1 Int) (l1_s2 Int))
+                                 (let ((l1_s3 (+ l1_s0 l1_s2)))
+                                 (let ((l1_s4 (> l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+[There are no variables bound by the model.]
diff --git a/SBVTestSuite/GoldFiles/lambda61.gold b/SBVTestSuite/GoldFiles/lambda61.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda61.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+         (bvugt l1_s1 l1_s0))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+All good, expecting: Unsat
diff --git a/SBVTestSuite/GoldFiles/lambda62.gold b/SBVTestSuite/GoldFiles/lambda62.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda62.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) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort P 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun D (P) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 P)) (forall ((l1_s1 P))
+                                 (let ((l1_s2 (D l1_s0)))
+                                 (let ((l1_s3 (D l1_s1)))
+                                 (let ((l1_s4 (=> l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/lambda63.gold b/SBVTestSuite/GoldFiles/lambda63.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda63.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun R (Int Int) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int))
+         (R l1_s0 l1_s0)))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (R))
+[RECV] ((R ((as const (Array Int Int Bool)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Falsifiable. Counter-example:
+  R :: (Integer, Integer) -> Bool
+  R (_, _) = False
diff --git a/SBVTestSuite/GoldFiles/lambda64.gold b/SBVTestSuite/GoldFiles/lambda64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda64.gold
@@ -0,0 +1,39 @@
+** 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] ; has special relations, no logic set.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun R (Int Int) Bool)
+[GOOD] (declare-fun __internal_sbv_IsPartialOrder__poR_ (Int Int) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int) (l1_s1 Int))
+                                 (let ((l1_s2 (R l1_s0 l1_s1)))
+                                 (let ((l1_s3 (__internal_sbv_IsPartialOrder__poR_ l1_s0 l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] (define-fun s1 () Bool (forall ((x Int) (y Int)) (= (__internal_sbv_IsPartialOrder__poR_ x y) ((_ partial-order 0) x y))))
+[GOOD] (define-fun s2 () Bool (forall ((l1_s0 Int))
+         (R l1_s0 l1_s0)))
+[GOOD] (define-fun s3 () Bool (=> s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert (not s3))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/lambda65.gold b/SBVTestSuite/GoldFiles/lambda65.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda65.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] ; has special relations, no logic set.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun __internal_sbv_IsPartialOrder__poI_ (Int Int) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |leq @(SBV Integer -> SBV Integer -> SBV Bool)| :: SInteger -> SInteger -> SBool
+[GOOD] (define-fun |leq @(SBV Integer -> SBV Integer -> SBV Bool)| ((l2_s0 Int) (l2_s1 Int)) Bool
+         (<= l2_s0 l2_s1))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int) (l1_s1 Int))
+                                 (let ((l1_s2 (|leq @(SBV Integer -> SBV Integer -> SBV Bool)| l1_s0 l1_s1)))
+                                 (let ((l1_s3 (__internal_sbv_IsPartialOrder__poI_ l1_s0 l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] (define-fun s1 () Bool (forall ((x Int) (y Int)) (= (__internal_sbv_IsPartialOrder__poI_ x y) ((_ partial-order 0) x y))))
+[GOOD] (define-fun s2 () Bool (forall ((l1_s0 Int))
+         (|leq @(SBV Integer -> SBV Integer -> SBV Bool)| l1_s0 l1_s0)))
+[GOOD] (define-fun s3 () Bool (=> s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert (not s3))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/lambda66.gold b/SBVTestSuite/GoldFiles/lambda66.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda66.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] ; has special relations, no logic set.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun U (Int Int) Bool)
+[GOOD] (declare-fun __internal_sbv__TransitiveClosure_tcU_ (Int Int) Bool)
+[GOOD] (declare-fun tcU (Int Int) Bool)
+[GOOD] (assert (forall ((x Int) (y Int)) (= (tcU x y) ((_ transitive-closure __internal_sbv__TransitiveClosure_tcU_) x y))))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int) (l1_s1 Int))
+                                 (let ((l1_s2 (U l1_s0 l1_s1)))
+                                 (let ((l1_s3 (__internal_sbv__TransitiveClosure_tcU_ l1_s0 l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] (define-fun s1 () Bool (forall ((l1_s0 Int) (l1_s1 Int) (l1_s2 Int))
+                                 (let ((l1_s3 (U l1_s0 l1_s1)))
+                                 (let ((l1_s4 (U l1_s1 l1_s2)))
+                                 (let ((l1_s5 (and l1_s3 l1_s4)))
+                                 (let ((l1_s6 (tcU l1_s0 l1_s2)))
+                                 (let ((l1_s7 (=> l1_s5 l1_s6)))
+                                 l1_s7)))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert (not s1))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/lambda67.gold b/SBVTestSuite/GoldFiles/lambda67.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda67.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] ; has special relations, no logic set.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun U ((_ BitVec 8) (_ BitVec 8)) Bool)
+[GOOD] (declare-fun __internal_sbv__TransitiveClosure_tcU_ ((_ BitVec 8) (_ BitVec 8)) Bool)
+[GOOD] (declare-fun tcU ((_ BitVec 8) (_ BitVec 8)) Bool)
+[GOOD] (assert (forall ((x (_ BitVec 8)) (y (_ BitVec 8))) (= (tcU x y) ((_ transitive-closure __internal_sbv__TransitiveClosure_tcU_) x y))))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (U l1_s0 l1_s1)))
+                                 (let ((l1_s3 (__internal_sbv__TransitiveClosure_tcU_ l1_s0 l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] (define-fun s1 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)))
+                                 (let ((l1_s3 (U l1_s0 l1_s1)))
+                                 (let ((l1_s4 (U l1_s1 l1_s2)))
+                                 (let ((l1_s5 (and l1_s3 l1_s4)))
+                                 (let ((l1_s6 (tcU l1_s0 l1_s2)))
+                                 (let ((l1_s7 (=> l1_s5 l1_s6)))
+                                 l1_s7)))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert (not s1))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/lambda68.gold b/SBVTestSuite/GoldFiles/lambda68.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda68.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun F (Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s2 2))
+                                 (let ((l1_s4 3))
+                                 (let ((l1_s1 (F l1_s0)))
+                                 (let ((l1_s3 (* l1_s0 l1_s2)))
+                                 (let ((l1_s5 (+ l1_s3 l1_s4)))
+                                 (let ((l1_s6 (= l1_s1 l1_s5)))
+                                 l1_s6))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (F))
+[RECV] ((F (lambda ((x!1 Int)) (+ 3 (* 2 x!1)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  F :: Integer -> Integer
+  F x = 2 * x + 3
diff --git a/SBVTestSuite/GoldFiles/lambda69.gold b/SBVTestSuite/GoldFiles/lambda69.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda69.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) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun F (Int Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int) (l1_s1 Int))
+                                 (let ((l1_s3 2))
+                                 (let ((l1_s5 3))
+                                 (let ((l1_s2 (F l1_s0 l1_s1)))
+                                 (let ((l1_s4 (* l1_s0 l1_s3)))
+                                 (let ((l1_s6 (- l1_s5 l1_s1)))
+                                 (let ((l1_s7 (+ l1_s4 l1_s6)))
+                                 (let ((l1_s8 (= l1_s2 l1_s7)))
+                                 l1_s8)))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (F))
+[RECV] ((F (lambda ((x!1 Int) (x!2 Int)) (+ 3 (* 2 x!1) (* (- 1) x!2)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  F :: Integer -> Integer -> Integer
+  F x y = 3 + 2 * x + (-y)
diff --git a/SBVTestSuite/GoldFiles/lambda70.gold b/SBVTestSuite/GoldFiles/lambda70.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda70.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun x_eu1 (Int) Int)
+[GOOD] (declare-fun x_eu2 (Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s3 1))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 (let ((l1_s5 (or l1_s2 l1_s4)))
+                                 (let ((l1_s6 (x_eu1 l1_s0)))
+                                 (let ((l1_s7 (= l1_s1 l1_s6)))
+                                 (let ((l1_s8 (= l1_s3 l1_s6)))
+                                 (let ((l1_s9 (or l1_s7 l1_s8)))
+                                 (let ((l1_s10 (x_eu2 l1_s0)))
+                                 (let ((l1_s11 (= l1_s1 l1_s10)))
+                                 (let ((l1_s12 (= l1_s3 l1_s10)))
+                                 (let ((l1_s13 (or l1_s11 l1_s12)))
+                                 (let ((l1_s14 (and l1_s9 l1_s13)))
+                                 (let ((l1_s15 (= l1_s6 l1_s10)))
+                                 (let ((l1_s16 (=> l1_s14 l1_s15)))
+                                 (let ((l1_s17 (and l1_s5 l1_s16)))
+                                 (let ((l1_s18 (not l1_s17)))
+                                 l1_s18))))))))))))))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (x_eu1))
+[RECV] ((x_eu1 (store ((as const (Array Int Int)) 1) 1 0)))
+[SEND] (get-value (x_eu2))
+[RECV] ((x_eu2 (store ((as const (Array Int Int)) 0) 1 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  x_eu1 :: Integer -> Integer
+  x_eu1 1 = 0
+  x_eu1 _ = 1
+
+  x_eu2 :: Integer -> Integer
+  x_eu2 1 = 1
+  x_eu2 _ = 0
diff --git a/SBVTestSuite/GoldFiles/lambda71.gold b/SBVTestSuite/GoldFiles/lambda71.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda71.gold
@@ -0,0 +1,13 @@
+; Automatically generated by SBV. Do not modify!
+; |bar @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+(define-fun-rec |bar @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int
+                                          (let ((l2_s1 1))
+                                          (let ((l2_s2 (- l2_s0 l2_s1)))
+                                          (let ((l2_s3 (|bar @(SBV Integer -> SBV Integer)| l2_s2)))
+                                          l2_s3))))
+; |foo @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Refers to: |bar @(SBV Integer -> SBV Integer)|]
+(define-fun |foo @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                          (let ((l1_s1 1))
+                          (let ((l1_s2 (- l1_s0 l1_s1)))
+                          (let ((l1_s3 (|bar @(SBV Integer -> SBV Integer)| l1_s2)))
+                          l1_s3))))
diff --git a/SBVTestSuite/GoldFiles/lambda72.gold b/SBVTestSuite/GoldFiles/lambda72.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda72.gold
@@ -0,0 +1,7 @@
+; Automatically generated by SBV. Do not modify!
+; |bar @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+(define-fun-rec |bar @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                          (let ((l1_s1 1))
+                          (let ((l1_s2 (- l1_s0 l1_s1)))
+                          (let ((l1_s3 (|bar @(SBV Integer -> SBV Integer)| l1_s2)))
+                          l1_s3))))
diff --git a/SBVTestSuite/GoldFiles/lambda73.gold b/SBVTestSuite/GoldFiles/lambda73.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda73.gold
@@ -0,0 +1,6 @@
+; Automatically generated by SBV. Do not modify!
+; |baz @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+(define-fun |baz @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                          (let ((l1_s1 1))
+                          (let ((l1_s2 (+ l1_s0 l1_s1)))
+                          l1_s2)))
diff --git a/SBVTestSuite/GoldFiles/lambda74.gold b/SBVTestSuite/GoldFiles/lambda74.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda74.gold
@@ -0,0 +1,15 @@
+; Automatically generated by SBV. Do not modify!
+; |e @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |o @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+(define-funs-rec
+  ((|e @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+   (|o @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+  (; Definition of: |e @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |o @(SBV Integer -> SBV Integer)|]
+                           (let ((l1_s1 1))
+                           (let ((l1_s2 (- l1_s0 l1_s1)))
+                           (let ((l1_s3 (|o @(SBV Integer -> SBV Integer)| l1_s2)))
+                           l1_s3)))
+   ; Definition of: |o @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |e @(SBV Integer -> SBV Integer)|]
+                                           (let ((l2_s1 1))
+                                           (let ((l2_s2 (- l2_s0 l2_s1)))
+                                           (let ((l2_s3 (|e @(SBV Integer -> SBV Integer)| l2_s2)))
+                                           l2_s3)))))
diff --git a/SBVTestSuite/GoldFiles/lambda75.gold b/SBVTestSuite/GoldFiles/lambda75.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda75.gold
@@ -0,0 +1,15 @@
+; Automatically generated by SBV. Do not modify!
+; |e @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |o @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+(define-funs-rec
+  ((|e @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int)
+   (|o @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int))
+  (; Definition of: |e @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |o @(SBV Integer -> SBV Integer)|]
+                                           (let ((l2_s1 1))
+                                           (let ((l2_s2 (- l2_s0 l2_s1)))
+                                           (let ((l2_s3 (|o @(SBV Integer -> SBV Integer)| l2_s2)))
+                                           l2_s3)))
+   ; Definition of: |o @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |e @(SBV Integer -> SBV Integer)|]
+                           (let ((l1_s1 1))
+                           (let ((l1_s2 (- l1_s0 l1_s1)))
+                           (let ((l1_s3 (|e @(SBV Integer -> SBV Integer)| l1_s2)))
+                           l1_s3)))))
diff --git a/SBVTestSuite/GoldFiles/lambda76.gold b/SBVTestSuite/GoldFiles/lambda76.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda76.gold
@@ -0,0 +1,3 @@
+; Automatically generated by SBV. Do not modify!
+; Type: Int
+2
diff --git a/SBVTestSuite/GoldFiles/lambda77.gold b/SBVTestSuite/GoldFiles/lambda77.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda77.gold
@@ -0,0 +1,3 @@
+; Automatically generated by SBV. Do not modify!
+; Type: String
+(_ char #x61)
diff --git a/SBVTestSuite/GoldFiles/lambda78.gold b/SBVTestSuite/GoldFiles/lambda78.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda78.gold
@@ -0,0 +1,3 @@
+; Automatically generated by SBV. Do not modify!
+; Type: (Seq Int)
+(seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))
diff --git a/SBVTestSuite/GoldFiles/lambda79.gold b/SBVTestSuite/GoldFiles/lambda79.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda79.gold
@@ -0,0 +1,10 @@
+; Automatically generated by SBV. Do not modify!
+; |foo @(SBV Integer -> SBV Word32)| :: SInteger -> SWord32
+(define-fun |foo @(SBV Integer -> SBV Word32)| ((l1_s0 Int)) (_ BitVec 32)
+                          (let ((l1_s1 #x00000001))
+                          (let ((l1_s2 #x00000002))
+                          (let ((l1_s3 #x00000003))
+                          (let ((l1_s4 #x00000000))
+                          (let ((table0 (lambda ((idx Int)) (ite (= idx 0) l1_s1 (ite (= idx 1) l1_s2 l1_s3)))))
+                          (let ((l1_s5 (ite (or (< l1_s0 0) (<= 3 l1_s0)) l1_s4 (table0 l1_s0))))
+                          l1_s5)))))))
diff --git a/SBVTestSuite/GoldFiles/lambda80.gold b/SBVTestSuite/GoldFiles/lambda80.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda80.gold
@@ -0,0 +1,13 @@
+; Automatically generated by SBV. Do not modify!
+; |foo @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+(define-fun |foo @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                          (let ((l1_s1 1))
+                          (let ((l1_s3 2))
+                          (let ((l1_s5 3))
+                          (let ((l1_s7 0))
+                          (let ((l1_s2 (+ l1_s0 l1_s1)))
+                          (let ((l1_s4 (+ l1_s0 l1_s3)))
+                          (let ((l1_s6 (+ l1_s0 l1_s5)))
+                          (let ((table0 (lambda ((idx Int)) (ite (= idx 0) l1_s2 (ite (= idx 1) l1_s4 l1_s6)))))
+                          (let ((l1_s8 (ite (or (< l1_s0 0) (<= 3 l1_s0)) l1_s7 (table0 l1_s0))))
+                          l1_s8))))))))))
diff --git a/SBVTestSuite/GoldFiles/lambda81.gold b/SBVTestSuite/GoldFiles/lambda81.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda81.gold
@@ -0,0 +1,279 @@
+[MEASURE] Verifying termination measures for: sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]), sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 4)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Bool (> s7 s3))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s10 () Int (- s5 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (Seq Int) (ite s6 s4 s14))
+[GOOD] (define-fun s16 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 4)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s12 () (Seq Int)) ; tracks user variable "__internal_sbv_s12"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Bool (> s7 s3))
+[GOOD] (define-fun s9 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s10 () Int (- s5 s2))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s0 s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s9 s12))
+[GOOD] (define-fun s14 () (Seq Int) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (Seq Int) (ite s6 s4 s14))
+[GOOD] (define-fun s16 () Int (seq.len s11))
+[GOOD] (define-fun s17 () Bool (not s8))
+[GOOD] (define-fun s18 () Bool (not s6))
+[GOOD] (define-fun s19 () Bool (and s17 s18))
+[GOOD] (define-fun s20 () Bool (> s5 s16))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])
+[MEASURE] Checking: sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer]): barified = "|sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])|"
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])|",1)]
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer]): trying length arg1
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () (Seq Int)) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool (> s6 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s6))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s5 s3 s15))
+[GOOD] (define-fun s17 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])}: replaying 12 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () (Seq Int)) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s13 () (Seq Int)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool (> s6 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s6))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq Int) (ite s9 s14 s13))
+[GOOD] (define-fun s16 () (Seq Int) (ite s5 s3 s15))
+[GOOD] (define-fun s17 () Int (seq.len s12))
+[GOOD] (define-fun s18 () Bool (not s9))
+[GOOD] (define-fun s19 () Bool (not s5))
+[GOOD] (define-fun s20 () Bool (and s18 s19))
+[GOOD] (define-fun s21 () Bool (> s4 s17))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 4))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (> l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s5)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s7 l1_s13 l1_s12)))
+                                 (let ((l1_s15 (ite l1_s3 l1_s4 l1_s14)))
+                                 l1_s15))))))))))))))))
+[GOOD] ; |sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])| :: [SInteger] -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])| ((l1_s0 (Seq Int))) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 (seq.nth s0 l1_s2)))
+                                 (let ((l1_s7 (> l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s5)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s7 l1_s13 l1_s12)))
+                                 (let ((l1_s15 (ite l1_s3 l1_s4 l1_s14)))
+                                 l1_s15))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq Int) (|sbv.filter @(SBV Integer -> SBV Bool)_2611d6a22d @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s2 () (Seq Int) (|sbv.filter @(SBV Integer -> SBV Bool)_f7406d70a9 @(SBV [Integer] -> SBV [Integer])| s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.unit 5)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:"  s0 = [5] :: [Integer]"
+DONE!
diff --git a/SBVTestSuite/GoldFiles/lambda82.gold b/SBVTestSuite/GoldFiles/lambda82.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda82.gold
@@ -0,0 +1,201 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]]): barified = "|sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]]): Uninterpreted ops in DAG: [("|sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])}: replaying 18 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 4)
+[GOOD] (define-fun s4 () Int 5)
+[GOOD] (define-fun s5 () Int 6)
+[GOOD] (define-fun s6 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s7 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s23 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s23"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s8 () Int (seq.len s0))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s11 () Int (+ s3 s10))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (+ s4 s10))
+[GOOD] (define-fun s14 () (Seq Int) (seq.unit s13))
+[GOOD] (define-fun s15 () Int (+ s5 s10))
+[GOOD] (define-fun s16 () (Seq Int) (seq.unit s15))
+[GOOD] (define-fun s17 () (Seq Int) (seq.++ s16 s6))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s14 s17))
+[GOOD] (define-fun s19 () (Seq Int) (seq.++ s12 s18))
+[GOOD] (define-fun s20 () (Seq (Seq Int)) (seq.unit s19))
+[GOOD] (define-fun s21 () Int (- s8 s2))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s0 s2 s21))
+[GOOD] (define-fun s24 () (Seq (Seq Int)) (seq.++ s20 s23))
+[GOOD] (define-fun s25 () (Seq (Seq Int)) (ite s9 s7 s24))
+[GOOD] (define-fun s26 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])}: replaying 18 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 4)
+[GOOD] (define-fun s4 () Int 5)
+[GOOD] (define-fun s5 () Int 6)
+[GOOD] (define-fun s6 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s7 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s23 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s23"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s8 () Int (seq.len s0))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s11 () Int (+ s3 s10))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit s11))
+[GOOD] (define-fun s13 () Int (+ s4 s10))
+[GOOD] (define-fun s14 () (Seq Int) (seq.unit s13))
+[GOOD] (define-fun s15 () Int (+ s5 s10))
+[GOOD] (define-fun s16 () (Seq Int) (seq.unit s15))
+[GOOD] (define-fun s17 () (Seq Int) (seq.++ s16 s6))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s14 s17))
+[GOOD] (define-fun s19 () (Seq Int) (seq.++ s12 s18))
+[GOOD] (define-fun s20 () (Seq (Seq Int)) (seq.unit s19))
+[GOOD] (define-fun s21 () Int (- s8 s2))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s0 s2 s21))
+[GOOD] (define-fun s24 () (Seq (Seq Int)) (seq.++ s20 s23))
+[GOOD] (define-fun s25 () (Seq (Seq Int)) (ite s9 s7 s24))
+[GOOD] (define-fun s26 () Int (seq.len s22))
+[GOOD] (define-fun s27 () Bool (not s9))
+[GOOD] (define-fun s28 () Bool (> s8 s26))
+[GOOD] (define-fun s29 () Bool (=> s27 s28))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s29))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])| :: [SInteger] -> [[SInteger]] [Recursive]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])| ((l1_s0 (Seq Int))) (Seq (Seq Int))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (Seq Int)))))
+                                 (let ((l1_s6 4))
+                                 (let ((l1_s9 5))
+                                 (let ((l1_s12 6))
+                                 (let ((l1_s15 (as seq.empty (Seq Int))))
+                                 (let ((l1_s20 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (+ l1_s5 l1_s9)))
+                                 (let ((l1_s11 (seq.unit l1_s10)))
+                                 (let ((l1_s13 (+ l1_s5 l1_s12)))
+                                 (let ((l1_s14 (seq.unit l1_s13)))
+                                 (let ((l1_s16 (seq.++ l1_s14 l1_s15)))
+                                 (let ((l1_s17 (seq.++ l1_s11 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s8 l1_s17)))
+                                 (let ((l1_s19 (seq.unit l1_s18)))
+                                 (let ((l1_s21 (- l1_s1 l1_s20)))
+                                 (let ((l1_s22 (seq.extract l1_s0 l1_s20 l1_s21)))
+                                 (let ((l1_s23 (|sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])| l1_s22)))
+                                 (let ((l1_s24 (seq.++ l1_s19 l1_s23)))
+                                 (let ((l1_s25 (ite l1_s3 l1_s4 l1_s24)))
+                                 l1_s25))))))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (Seq (Seq Int)) (|sbv.map @(SBV Integer -> SBV [Integer])_136c80b6a3 @(SBV [Integer] -> SBV [[Integer]])| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit (seq.++ (seq.unit 5) (seq.unit 6) (seq.unit 7)))
+               (seq.unit (seq.++ (seq.unit 6) (seq.unit 7) (seq.unit 8)))
+               (seq.unit (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))
+               (seq.unit (seq.++ (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 9) (seq.unit 10) (seq.unit 11))))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit (seq.++ (seq.unit 5) (seq.unit 6) (seq.unit 7)))
+               (seq.unit (seq.++ (seq.unit 6) (seq.unit 7) (seq.unit 8)))
+               (seq.unit (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))
+               (seq.unit (seq.++ (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 9) (seq.unit 10) (seq.unit 11))))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =                                  [1,2,3,4,5] :: [Integer]
+  s1 = [[5,6,7],[6,7,8],[7,8,9],[8,9,10],[9,10,11]] :: [[Integer]]
diff --git a/SBVTestSuite/GoldFiles/lambda83.gold b/SBVTestSuite/GoldFiles/lambda83.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda83.gold
@@ -0,0 +1,32 @@
+CAUGHT EXCEPTION
+
+
+*** Data.SBV.Lambda: Detected free variables passed to a lambda.
+***
+***  Free vars : args0
+***  Definition: (lambda ((s0 Int))
+***                (+ args0 s0))
+***
+*** SBV currently does not support lambda-functions that capture variables. For
+*** instance, consider:
+***
+***     map (\x -> map (\y -> x + y))
+***
+*** where the inner 'map' uses 'x', bound by the outer 'map'. Instead, create
+*** a closure instead:
+***
+***     map (\x -> map (Closure { closureEnv = x
+***                             , closureFun = \env y -> env + y
+***                             }))
+***
+*** which will explicitly create the closure before calling 'map'. The environment can
+*** be any symbolic value: You can use a tuple to support multiple free variables.
+***
+*** (SBV firstifies higher-order functions via a simple translation to make it fit with
+*** SMTLib's first-order logic. This translation does not currently support free
+*** variables. In technical terms, we would need to do closure conversion and lambda-lifting.
+*** SBV isn't capable of doing the closure-conversion part, relying on the user to do so.)
+***
+*** Please rewrite your program to create a closure and use that as an argument.
+*** If this solution isn't applicable, or if you'd like help doing so, please get in
+*** touch for further possible enhancements.
diff --git a/SBVTestSuite/GoldFiles/lambda84.gold b/SBVTestSuite/GoldFiles/lambda84.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda84.gold
@@ -0,0 +1,32 @@
+CAUGHT EXCEPTION
+
+
+*** Data.SBV.Lambda: Detected free variables passed to a lambda.
+***
+***  Free vars : args0
+***  Definition: (lambda ((s0 (Seq Int)))
+***                (seq.++ s0 args0))
+***
+*** SBV currently does not support lambda-functions that capture variables. For
+*** instance, consider:
+***
+***     map (\x -> map (\y -> x + y))
+***
+*** where the inner 'map' uses 'x', bound by the outer 'map'. Instead, create
+*** a closure instead:
+***
+***     map (\x -> map (Closure { closureEnv = x
+***                             , closureFun = \env y -> env + y
+***                             }))
+***
+*** which will explicitly create the closure before calling 'map'. The environment can
+*** be any symbolic value: You can use a tuple to support multiple free variables.
+***
+*** (SBV firstifies higher-order functions via a simple translation to make it fit with
+*** SMTLib's first-order logic. This translation does not currently support free
+*** variables. In technical terms, we would need to do closure conversion and lambda-lifting.
+*** SBV isn't capable of doing the closure-conversion part, relying on the user to do so.)
+***
+*** Please rewrite your program to create a closure and use that as an argument.
+*** If this solution isn't applicable, or if you'd like help doing so, please get in
+*** touch for further possible enhancements.
diff --git a/SBVTestSuite/GoldFiles/lambda85.gold b/SBVTestSuite/GoldFiles/lambda85.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda85.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))
+[MEASURE] Checking: sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer])): barified = "|sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))|"
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer])): Uninterpreted ops in DAG: [("|sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))|",1)]
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer])): recursive calls found = 1
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer])): trying length arg1
+[MEASURE] replayDAG {sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))}: replaying 17 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s16))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s10 s16))
+[GOOD] (define-fun s19 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s14 s18))
+[GOOD] (define-fun s20 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s9 s17 s19))
+[GOOD] (define-fun s21 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s6 s4 s20))
+[GOOD] (define-fun s22 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))}: replaying 17 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s16))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s10 s16))
+[GOOD] (define-fun s19 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s14 s18))
+[GOOD] (define-fun s20 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s9 s17 s19))
+[GOOD] (define-fun s21 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s6 s4 s20))
+[GOOD] (define-fun s22 () Int (seq.len s12))
+[GOOD] (define-fun s23 () Bool (not s9))
+[GOOD] (define-fun s24 () Bool (not s6))
+[GOOD] (define-fun s25 () Bool (and s23 s24))
+[GOOD] (define-fun s26 () Bool (> s5 s22))
+[GOOD] (define-fun s27 () Bool (=> s25 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s27))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer])): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (SBVTuple2 (Seq Int) (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))| :: [SInteger] -> ([SInteger], [SInteger]) [Recursive]
+[GOOD] (define-fun-rec |sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))| ((l1_s0 (Seq Int))) (SBVTuple2 (Seq Int) (Seq Int))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int)))))
+                                 (let ((l1_s6 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (mod l1_s5 l1_s6)))
+                                 (let ((l1_s8 (= l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s5)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))| l1_s12)))
+                                 (let ((l1_s14 (proj_1_SBVTuple2 l1_s13)))
+                                 (let ((l1_s15 (seq.++ l1_s9 l1_s14)))
+                                 (let ((l1_s16 (proj_2_SBVTuple2 l1_s13)))
+                                 (let ((l1_s17 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s15 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s9 l1_s16)))
+                                 (let ((l1_s19 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s14 l1_s18)))
+                                 (let ((l1_s20 (ite l1_s8 l1_s17 l1_s19)))
+                                 (let ((l1_s21 (ite l1_s3 l1_s4 l1_s20)))
+                                 l1_s21))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (|sbv.partition @(SBV Integer -> SBV Bool)_72b7bf5d4c @(SBV [Integer] -> SBV ([Integer],[Integer]))| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple2 (seq.++ (seq.unit 2)
+                            (seq.unit 4)
+                            (seq.unit 6)
+                            (seq.unit 8)
+                            (seq.unit 10))
+                    (seq.++ (seq.unit 1)
+                            (seq.unit 3)
+                            (seq.unit 5)
+                            (seq.unit 7)
+                            (seq.unit 9)))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple2 (seq.++ (seq.unit 2)
+                            (seq.unit 4)
+                            (seq.unit 6)
+                            (seq.unit 8)
+                            (seq.unit 10))
+                    (seq.++ (seq.unit 1)
+                            (seq.unit 3)
+                            (seq.unit 5)
+                            (seq.unit 7)
+                            (seq.unit 9)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =     [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 = ([2,4,6,8,10],[1,3,5,7,9]) :: ([Integer], [Integer])
diff --git a/SBVTestSuite/GoldFiles/lambda86.gold b/SBVTestSuite/GoldFiles/lambda86.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda86.gold
@@ -0,0 +1,219 @@
+[MEASURE] Verifying termination measures for: sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))
+[MEASURE] Checking: sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer])): barified = "|sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))|"
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer])): Uninterpreted ops in DAG: [("|sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))|",1)]
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer])): recursive calls found = 1
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer])): trying length arg1
+[MEASURE] replayDAG {sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))}: replaying 17 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (distinct s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s16))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s10 s16))
+[GOOD] (define-fun s19 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s14 s18))
+[GOOD] (define-fun s20 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s9 s17 s19))
+[GOOD] (define-fun s21 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s6 s4 s20))
+[GOOD] (define-fun s22 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))}: replaying 17 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s13 () (SBVTuple2 (Seq Int) (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () Int (mod s7 s3))
+[GOOD] (define-fun s9 () Bool (distinct s1 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq Int) (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s15 s16))
+[GOOD] (define-fun s18 () (Seq Int) (seq.++ s10 s16))
+[GOOD] (define-fun s19 () (SBVTuple2 (Seq Int) (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) s14 s18))
+[GOOD] (define-fun s20 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s9 s17 s19))
+[GOOD] (define-fun s21 () (SBVTuple2 (Seq Int) (Seq Int)) (ite s6 s4 s20))
+[GOOD] (define-fun s22 () Int (seq.len s12))
+[GOOD] (define-fun s23 () Bool (not s9))
+[GOOD] (define-fun s24 () Bool (not s6))
+[GOOD] (define-fun s25 () Bool (and s23 s24))
+[GOOD] (define-fun s26 () Bool (> s5 s22))
+[GOOD] (define-fun s27 () Bool (=> s25 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s27))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer])): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6) (seq.unit 7) (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (SBVTuple2 (Seq Int) (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))| :: [SInteger] -> ([SInteger], [SInteger]) [Recursive]
+[GOOD] (define-fun-rec |sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))| ((l1_s0 (Seq Int))) (SBVTuple2 (Seq Int) (Seq Int))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (mkSBVTuple2 (as seq.empty (Seq Int)) (as seq.empty (Seq Int)))))
+                                 (let ((l1_s6 2))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s7 (mod l1_s5 l1_s6)))
+                                 (let ((l1_s8 (distinct l1_s2 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s5)))
+                                 (let ((l1_s11 (- l1_s1 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (|sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))| l1_s12)))
+                                 (let ((l1_s14 (proj_1_SBVTuple2 l1_s13)))
+                                 (let ((l1_s15 (seq.++ l1_s9 l1_s14)))
+                                 (let ((l1_s16 (proj_2_SBVTuple2 l1_s13)))
+                                 (let ((l1_s17 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s15 l1_s16)))
+                                 (let ((l1_s18 (seq.++ l1_s9 l1_s16)))
+                                 (let ((l1_s19 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq Int))) l1_s14 l1_s18)))
+                                 (let ((l1_s20 (ite l1_s8 l1_s17 l1_s19)))
+                                 (let ((l1_s21 (ite l1_s3 l1_s4 l1_s20)))
+                                 l1_s21))))))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () (SBVTuple2 (Seq Int) (Seq Int)) (|sbv.partition @(SBV Integer -> SBV Bool)_cb04f986c4 @(SBV [Integer] -> SBV ([Integer],[Integer]))| s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple2 (seq.++ (seq.unit 1)
+                            (seq.unit 3)
+                            (seq.unit 5)
+                            (seq.unit 7)
+                            (seq.unit 9))
+                    (seq.++ (seq.unit 2)
+                            (seq.unit 4)
+                            (seq.unit 6)
+                            (seq.unit 8)
+                            (seq.unit 10)))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1)
+               (seq.unit 2)
+               (seq.unit 3)
+               (seq.unit 4)
+               (seq.unit 5)
+               (seq.unit 6)
+               (seq.unit 7)
+               (seq.unit 8)
+               (seq.unit 9)
+               (seq.unit 10))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple2 (seq.++ (seq.unit 1)
+                            (seq.unit 3)
+                            (seq.unit 5)
+                            (seq.unit 7)
+                            (seq.unit 9))
+                    (seq.++ (seq.unit 2)
+                            (seq.unit 4)
+                            (seq.unit 6)
+                            (seq.unit 8)
+                            (seq.unit 10)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =     [1,2,3,4,5,6,7,8,9,10] :: [Integer]
+  s1 = ([1,3,5,7,9],[2,4,6,8,10]) :: ([Integer], [Integer])
diff --git a/SBVTestSuite/GoldFiles/lambda87.gold b/SBVTestSuite/GoldFiles/lambda87.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda87.gold
@@ -0,0 +1,453 @@
+[MEASURE] Verifying termination measures for: sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]), sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]), sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer]), sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] Checking: sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): barified = "|sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])|"
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): Uninterpreted ops in DAG: [("|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])|",1),("|sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])|",1)]
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): recursive calls found = 1
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): trying length arg1
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () (Seq Int)) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s9 () (Seq Int)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] (declare-fun s13 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s7))
+[GOOD] (define-fun s10 () (Seq (Seq Int)) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq (Seq Int)) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq (Seq Int)) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Bool (>= s4 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])}: replaying 11 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq (Seq Int)) (as seq.empty (Seq (Seq Int))))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () (Seq Int)) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s9 () (Seq Int)) ; tracks user variable "__internal_sbv_s9"
+[GOOD] (declare-fun s13 () (Seq (Seq Int))) ; tracks user variable "__internal_sbv_s13"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (define-fun s6 () Int (seq.nth s0 s1))
+[GOOD] (define-fun s8 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s7))
+[GOOD] (define-fun s10 () (Seq (Seq Int)) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s4 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s2 s11))
+[GOOD] (define-fun s14 () (Seq (Seq Int)) (seq.++ s10 s13))
+[GOOD] (define-fun s15 () (Seq (Seq Int)) (ite s5 s3 s14))
+[GOOD] (define-fun s16 () Int (seq.len s12))
+[GOOD] (define-fun s17 () Bool (not s5))
+[GOOD] (define-fun s18 () Bool (> s4 s16))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s19))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]]): length arg1 -> OK
+[MEASURE] Passed (terminating): sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])
+[MEASURE] Checking: sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer])
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer]): not in a multi-member cycle, skipping mutual check
+[MEASURE] Passed (terminating): sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer])
+[MEASURE] Checking: sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): barified = "|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])|"
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): Uninterpreted ops in DAG: [("|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])|",1)]
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): recursive calls found = 1
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): trying abs arg1._1
+[MEASURE] replayDAG {sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () (Seq Int)) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s3 s15))
+[GOOD] (define-fun s17 () Int (abs s7))
+[GOOD] (define-fun s18 () Bool (>= s17 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () (Seq Int)) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s3 s15))
+[GOOD] (define-fun s17 () Int (abs s7))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s19 () Int (abs s18))
+[GOOD] (define-fun s20 () Bool (not s6))
+[GOOD] (define-fun s21 () Bool (> s17 s19))
+[GOOD] (define-fun s22 () Bool (=> s20 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s17))
+[RECV] ((s17 0))
+[SEND] (get-value (s19))
+[RECV] ((s19 0))
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (seq.unit 2))))
+[SEND] (get-value (s14))
+[RECV] ((s14 (as seq.empty (Seq Int))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): abs arg1._1 failed strict decrease: Falsifiable. Counter-example:
+  arg    = (0,[2]) :: (Integer, [Integer])
+  before =       0 :: Integer
+  then   =       0 :: Integer
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): trying next candidate..
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): trying length arg1._2
+[MEASURE] replayDAG {sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () (Seq Int)) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s3 s15))
+[GOOD] (define-fun s17 () Bool (>= s5 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s17))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])}: replaying 13 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (Seq Int))) ; tracks user variable "arg"
+[GOOD] (declare-fun s14 () (Seq Int)) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s4))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s8 () Int (seq.nth s4 s1))
+[GOOD] (define-fun s9 () Int (+ s7 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
+[GOOD] (define-fun s11 () Int (- s5 s2))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s4 s2 s11))
+[GOOD] (define-fun s13 () (SBVTuple2 Int (Seq Int)) ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s7 s12))
+[GOOD] (define-fun s15 () (Seq Int) (seq.++ s10 s14))
+[GOOD] (define-fun s16 () (Seq Int) (ite s6 s3 s15))
+[GOOD] (define-fun s17 () (Seq Int) (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (not s6))
+[GOOD] (define-fun s20 () Bool (> s5 s18))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer]): length arg1._2 -> OK
+[MEASURE] Passed (terminating): sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 6) (seq.unit 7) (seq.unit 8)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () (Seq (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])| :: (SInteger, [SInteger]) -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])| ((l1_s0 (SBVTuple2 Int (Seq Int)))) (Seq Int)
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq Int))))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s7 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s8 (+ l1_s6 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s6 l1_s12)))
+                                 (let ((l1_s14 (|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])| l1_s13)))
+                                 (let ((l1_s15 (seq.++ l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; |sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])| :: [SInteger] -> [[SInteger]] [Recursive] [Refers to: |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])|]
+[GOOD] (define-fun-rec |sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])| ((l1_s0 (Seq Int))) (Seq (Seq Int))
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq (Seq Int)))))
+                                 (let ((l1_s9 1))
+                                 (let ((l1_s1 (seq.len l1_s0)))
+                                 (let ((l1_s3 (= l1_s1 l1_s2)))
+                                 (let ((l1_s5 (seq.nth l1_s0 l1_s2)))
+                                 (let ((l1_s6 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) l1_s5 s0)))
+                                 (let ((l1_s7 (|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])| l1_s6)))
+                                 (let ((l1_s8 (seq.unit l1_s7)))
+                                 (let ((l1_s10 (- l1_s1 l1_s9)))
+                                 (let ((l1_s11 (seq.extract l1_s0 l1_s9 l1_s10)))
+                                 (let ((l1_s12 (|sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])| l1_s11)))
+                                 (let ((l1_s13 (seq.++ l1_s8 l1_s12)))
+                                 (let ((l1_s14 (ite l1_s3 l1_s4 l1_s13)))
+                                 l1_s14)))))))))))))))
+[GOOD] ; |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer])| :: (SInteger, [SInteger]) -> [SInteger] [Refers to: |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])|]
+[GOOD] (define-fun |sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_3339bda50c @(SBV (Integer,[Integer]) -> SBV [Integer])| ((s0 (SBVTuple2 Int (Seq Int)))) (Seq Int)
+                 (let ((s3 0))
+                 (let ((s5 (as seq.empty (Seq Int))))
+                 (let ((s10 1))
+                 (let ((s1 (proj_2_SBVTuple2 s0)))
+                 (let ((s2 (seq.len s1)))
+                 (let ((s4 (= s2 s3)))
+                 (let ((s6 (proj_1_SBVTuple2 s0)))
+                 (let ((s7 (seq.nth s1 s3)))
+                 (let ((s8 (+ s6 s7)))
+                 (let ((s9 (seq.unit s8)))
+                 (let ((s11 (- s2 s10)))
+                 (let ((s12 (seq.extract s1 s10 s11)))
+                 (let ((s13 ((as mkSBVTuple2 (SBVTuple2 Int (Seq Int))) s6 s12)))
+                 (let ((s14 (|sbv.closureMap @(SBV Integer -> SBV Integer -> SBV Integer)_d8dc9e6fbd @(SBV (Integer,[Integer]) -> SBV [Integer])| s13)))
+                 (let ((s15 (seq.++ s9 s14)))
+                 (let ((s16 (ite s4 s5 s15)))
+                 s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (Seq (Seq Int)) (|sbv.map @(SBV Integer -> SBV [Integer])_8a19cac1b3 @(SBV [Integer] -> SBV [[Integer]])| s1))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s8)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))
+               (seq.unit (seq.++ (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 9) (seq.unit 10) (seq.unit 11))))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 6) (seq.unit 7) (seq.unit 8))))
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))
+               (seq.unit (seq.++ (seq.unit 8) (seq.unit 9) (seq.unit 10)))
+               (seq.unit (seq.++ (seq.unit 9) (seq.unit 10) (seq.unit 11))))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =                      [1,2,3] :: [Integer]
+  s1 =                      [6,7,8] :: [Integer]
+  s2 = [[7,8,9],[8,9,10],[9,10,11]] :: [[Integer]]
diff --git a/SBVTestSuite/GoldFiles/lambda88.gold b/SBVTestSuite/GoldFiles/lambda88.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/lambda88.gold
@@ -0,0 +1,89 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () (Seq (Seq Int)) (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3))) (seq.unit (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6)))))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Seq Int)))
+[GOOD] (declare-fun s1 () (Seq Int))
+[GOOD] (declare-fun s2 () (Seq (Seq Int)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sbv.closureMap @(SBV [Integer] -> SBV [Integer] -> SBV [Integer])_24b5487d7f @(SBV ([Integer],[[Integer]]) -> SBV [[Integer]])| :: ([SInteger], [[SInteger]]) -> [[SInteger]] [Recursive]
+[GOOD] (define-fun-rec |sbv.closureMap @(SBV [Integer] -> SBV [Integer] -> SBV [Integer])_24b5487d7f @(SBV ([Integer],[[Integer]]) -> SBV [[Integer]])| ((l1_s0 (SBVTuple2 (Seq Int) (Seq (Seq Int))))) (Seq (Seq Int))
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s5 (as seq.empty (Seq (Seq Int)))))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s1 (proj_2_SBVTuple2 l1_s0)))
+                                 (let ((l1_s2 (seq.len l1_s1)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s6 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s7 (proj_1_SBVTuple2 l1_s0)))
+                                 (let ((l1_s8 (seq.++ l1_s6 l1_s7)))
+                                 (let ((l1_s9 (seq.unit l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s1 l1_s10 l1_s11)))
+                                 (let ((l1_s13 ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq (Seq Int)))) l1_s7 l1_s12)))
+                                 (let ((l1_s14 (|sbv.closureMap @(SBV [Integer] -> SBV [Integer] -> SBV [Integer])_24b5487d7f @(SBV ([Integer],[[Integer]]) -> SBV [[Integer]])| l1_s13)))
+                                 (let ((l1_s15 (seq.++ l1_s9 l1_s14)))
+                                 (let ((l1_s16 (ite l1_s4 l1_s5 l1_s15)))
+                                 l1_s16)))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () (SBVTuple2 (Seq Int) (Seq (Seq Int))) ((as mkSBVTuple2 (SBVTuple2 (Seq Int) (Seq (Seq Int)))) s1 s0))
+[GOOD] (define-fun s8 () (Seq (Seq Int)) (|sbv.closureMap @(SBV [Integer] -> SBV [Integer] -> SBV [Integer])_24b5487d7f @(SBV ([Integer],[[Integer]]) -> SBV [[Integer]])| s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9))))
+               (seq.unit (seq.++ (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))))))
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+               (seq.unit (seq.++ (seq.unit 4) (seq.unit 5) (seq.unit 6))))))
+[SEND] (get-value (s1))
+[RECV] ((s1 (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9))))
+[SEND] (get-value (s2))
+[RECV] ((s2 (seq.++ (seq.unit (seq.++ (seq.unit 1)
+                                 (seq.unit 2)
+                                 (seq.unit 3)
+                                 (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9))))
+               (seq.unit (seq.++ (seq.unit 4)
+                                 (seq.unit 5)
+                                 (seq.unit 6)
+                                 (seq.++ (seq.unit 7) (seq.unit 8) (seq.unit 9)))))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+  s0 =             [[1,2,3],[4,5,6]] :: [[Integer]]
+  s1 =                       [7,8,9] :: [Integer]
+  s2 = [[1,2,3,7,8,9],[4,5,6,7,8,9]] :: [[Integer]]
diff --git a/SBVTestSuite/GoldFiles/legato.gold b/SBVTestSuite/GoldFiles/legato.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/legato.gold
@@ -0,0 +1,6368 @@
+INPUTS
+  s0 :: SWord8, aliasing "x"
+  s1 :: SWord8, aliasing "y"
+  s2 :: SWord8, aliasing "lo"
+  s3 :: SWord8, aliasing "regX"
+  s4 :: SWord8, aliasing "regA"
+  s5 :: SBool, aliasing "flagC"
+  s6 :: SBool, aliasing "flagZ"
+CONSTANTS
+  s7 = 256 :: Word16
+  s8 = 0 :: Word8
+  s10 = 0 :: WordN 1
+  s14 = 128 :: Word8
+  s16 = 127 :: Word8
+TABLES
+UNINTERPRETED CONSTANTS
+USER GIVEN CODE SEGMENTS
+AXIOMS-DEFINITIONS
+DEFINE
+  s9 :: SWord 1 = choose [0:0] s0
+  s11 :: SBool = s9 /= s10
+  s12 :: SBool = ~ s11
+  s13 :: SWord8 = s0 >>> 1
+  s15 :: SWord8 = s13 | s14
+  s17 :: SWord8 = s13 & s16
+  s18 :: SWord8 = if s5 then s15 else s17
+  s19 :: SWord 1 = choose [0:0] s18
+  s20 :: SBool = s10 /= s19
+  s21 :: SBool = ~ s20
+  s22 :: SWord 1 = choose [0:0] s2
+  s23 :: SBool = s10 /= s22
+  s24 :: SWord8 = s18 >>> 1
+  s25 :: SWord8 = s14 | s24
+  s26 :: SWord8 = s16 & s24
+  s27 :: SWord8 = if s23 then s25 else s26
+  s28 :: SWord 1 = choose [0:0] s27
+  s29 :: SBool = s10 /= s28
+  s30 :: SBool = ~ s29
+  s31 :: SWord8 = s2 >>> 1
+  s32 :: SWord8 = s16 & s31
+  s33 :: SWord 1 = choose [0:0] s32
+  s34 :: SBool = s10 /= s33
+  s35 :: SWord8 = s27 >>> 1
+  s36 :: SWord8 = s14 | s35
+  s37 :: SWord8 = s16 & s35
+  s38 :: SWord8 = if s34 then s36 else s37
+  s39 :: SWord 1 = choose [0:0] s38
+  s40 :: SBool = s10 /= s39
+  s41 :: SBool = ~ s40
+  s42 :: SWord8 = if s11 then s14 else s8
+  s43 :: SWord 1 = choose [0:0] s42
+  s44 :: SBool = s10 /= s43
+  s45 :: SWord8 = s32 >>> 1
+  s46 :: SWord8 = s14 | s45
+  s47 :: SWord8 = s16 & s45
+  s48 :: SWord8 = if s44 then s46 else s47
+  s49 :: SWord 1 = choose [0:0] s48
+  s50 :: SBool = s10 /= s49
+  s51 :: SWord8 = s38 >>> 1
+  s52 :: SWord8 = s14 | s51
+  s53 :: SWord8 = s16 & s51
+  s54 :: SWord8 = if s50 then s52 else s53
+  s55 :: SWord 1 = choose [0:0] s54
+  s56 :: SBool = s10 /= s55
+  s57 :: SBool = ~ s56
+  s58 :: SWord8 = s42 >>> 1
+  s59 :: SWord8 = s14 | s58
+  s60 :: SWord8 = s16 & s58
+  s61 :: SWord8 = if s20 then s59 else s60
+  s62 :: SWord 1 = choose [0:0] s61
+  s63 :: SBool = s10 /= s62
+  s64 :: SWord8 = s48 >>> 1
+  s65 :: SWord8 = s14 | s64
+  s66 :: SWord8 = s16 & s64
+  s67 :: SWord8 = if s63 then s65 else s66
+  s68 :: SWord 1 = choose [0:0] s67
+  s69 :: SBool = s10 /= s68
+  s70 :: SWord8 = s54 >>> 1
+  s71 :: SWord8 = s14 | s70
+  s72 :: SWord8 = s16 & s70
+  s73 :: SWord8 = if s69 then s71 else s72
+  s74 :: SWord 1 = choose [0:0] s73
+  s75 :: SBool = s10 /= s74
+  s76 :: SBool = ~ s75
+  s77 :: SWord8 = s61 >>> 1
+  s78 :: SWord8 = s14 | s77
+  s79 :: SWord8 = s16 & s77
+  s80 :: SWord8 = if s29 then s78 else s79
+  s81 :: SWord 1 = choose [0:0] s80
+  s82 :: SBool = s10 /= s81
+  s83 :: SWord8 = s67 >>> 1
+  s84 :: SWord8 = s14 | s83
+  s85 :: SWord8 = s16 & s83
+  s86 :: SWord8 = if s82 then s84 else s85
+  s87 :: SWord 1 = choose [0:0] s86
+  s88 :: SBool = s10 /= s87
+  s89 :: SWord8 = s73 >>> 1
+  s90 :: SWord8 = s14 | s89
+  s91 :: SWord8 = s16 & s89
+  s92 :: SWord8 = if s88 then s90 else s91
+  s93 :: SWord 1 = choose [0:0] s92
+  s94 :: SBool = s10 /= s93
+  s95 :: SBool = ~ s94
+  s96 :: SWord8 = s80 >>> 1
+  s97 :: SWord8 = s14 | s96
+  s98 :: SWord8 = s16 & s96
+  s99 :: SWord8 = if s40 then s97 else s98
+  s100 :: SWord 1 = choose [0:0] s99
+  s101 :: SBool = s10 /= s100
+  s102 :: SWord8 = s86 >>> 1
+  s103 :: SWord8 = s14 | s102
+  s104 :: SWord8 = s16 & s102
+  s105 :: SWord8 = if s101 then s103 else s104
+  s106 :: SWord 1 = choose [0:0] s105
+  s107 :: SBool = s10 /= s106
+  s108 :: SWord8 = s92 >>> 1
+  s109 :: SWord8 = s14 | s108
+  s110 :: SWord8 = s16 & s108
+  s111 :: SWord8 = if s107 then s109 else s110
+  s112 :: SWord 1 = choose [0:0] s111
+  s113 :: SBool = s10 /= s112
+  s114 :: SBool = ~ s113
+  s115 :: SWord8 = s99 >>> 1
+  s116 :: SWord8 = s14 | s115
+  s117 :: SWord8 = s16 & s115
+  s118 :: SWord8 = if s56 then s116 else s117
+  s119 :: SWord8 = s118 >>> 1
+  s120 :: SWord8 = s14 | s119
+  s121 :: SWord8 = s16 & s119
+  s122 :: SWord8 = if s75 then s120 else s121
+  s123 :: SWord8 = s122 >>> 1
+  s124 :: SWord8 = s14 | s123
+  s125 :: SWord8 = s16 & s123
+  s126 :: SWord8 = if s94 then s124 else s125
+  s127 :: SWord8 = s126 >>> 1
+  s128 :: SWord8 = s14 | s127
+  s129 :: SWord8 = s16 & s127
+  s130 :: SWord8 = if s113 then s128 else s129
+  s131 :: SWord8 = s1 + s126
+  s132 :: SBool = s131 < s1
+  s133 :: SBool = s131 < s126
+  s134 :: SBool = s132 | s133
+  s135 :: SWord8 = s131 >>> 1
+  s136 :: SWord8 = s14 | s135
+  s137 :: SWord8 = s16 & s135
+  s138 :: SWord8 = if s134 then s136 else s137
+  s139 :: SWord8 = if s114 then s130 else s138
+  s140 :: SWord8 = s1 + s122
+  s141 :: SBool = s140 < s1
+  s142 :: SBool = s140 < s122
+  s143 :: SBool = s141 | s142
+  s144 :: SWord8 = s140 >>> 1
+  s145 :: SWord8 = s14 | s144
+  s146 :: SWord8 = s16 & s144
+  s147 :: SWord8 = if s143 then s145 else s146
+  s148 :: SWord8 = s147 >>> 1
+  s149 :: SWord8 = s14 | s148
+  s150 :: SWord8 = s16 & s148
+  s151 :: SWord8 = if s113 then s149 else s150
+  s152 :: SWord8 = s1 + s147
+  s153 :: SBool = s152 < s1
+  s154 :: SBool = s152 < s147
+  s155 :: SBool = s153 | s154
+  s156 :: SWord8 = s152 >>> 1
+  s157 :: SWord8 = s14 | s156
+  s158 :: SWord8 = s16 & s156
+  s159 :: SWord8 = if s155 then s157 else s158
+  s160 :: SWord8 = if s114 then s151 else s159
+  s161 :: SWord8 = if s95 then s139 else s160
+  s162 :: SWord8 = s1 + s118
+  s163 :: SBool = s162 < s1
+  s164 :: SBool = s162 < s118
+  s165 :: SBool = s163 | s164
+  s166 :: SWord8 = s162 >>> 1
+  s167 :: SWord8 = s14 | s166
+  s168 :: SWord8 = s16 & s166
+  s169 :: SWord8 = if s165 then s167 else s168
+  s170 :: SWord8 = s169 >>> 1
+  s171 :: SWord8 = s14 | s170
+  s172 :: SWord8 = s16 & s170
+  s173 :: SWord8 = if s94 then s171 else s172
+  s174 :: SWord8 = s173 >>> 1
+  s175 :: SWord8 = s14 | s174
+  s176 :: SWord8 = s16 & s174
+  s177 :: SWord8 = if s113 then s175 else s176
+  s178 :: SWord8 = s1 + s173
+  s179 :: SBool = s178 < s1
+  s180 :: SBool = s178 < s173
+  s181 :: SBool = s179 | s180
+  s182 :: SWord8 = s178 >>> 1
+  s183 :: SWord8 = s14 | s182
+  s184 :: SWord8 = s16 & s182
+  s185 :: SWord8 = if s181 then s183 else s184
+  s186 :: SWord8 = if s114 then s177 else s185
+  s187 :: SWord8 = s1 + s169
+  s188 :: SBool = s187 < s1
+  s189 :: SBool = s187 < s169
+  s190 :: SBool = s188 | s189
+  s191 :: SWord8 = s187 >>> 1
+  s192 :: SWord8 = s14 | s191
+  s193 :: SWord8 = s16 & s191
+  s194 :: SWord8 = if s190 then s192 else s193
+  s195 :: SWord8 = s194 >>> 1
+  s196 :: SWord8 = s14 | s195
+  s197 :: SWord8 = s16 & s195
+  s198 :: SWord8 = if s113 then s196 else s197
+  s199 :: SWord8 = s1 + s194
+  s200 :: SBool = s199 < s1
+  s201 :: SBool = s199 < s194
+  s202 :: SBool = s200 | s201
+  s203 :: SWord8 = s199 >>> 1
+  s204 :: SWord8 = s14 | s203
+  s205 :: SWord8 = s16 & s203
+  s206 :: SWord8 = if s202 then s204 else s205
+  s207 :: SWord8 = if s114 then s198 else s206
+  s208 :: SWord8 = if s95 then s186 else s207
+  s209 :: SWord8 = if s76 then s161 else s208
+  s210 :: SWord8 = s1 + s99
+  s211 :: SWord 1 = choose [0:0] s210
+  s212 :: SBool = s10 /= s211
+  s213 :: SWord8 = if s212 then s103 else s104
+  s214 :: SWord 1 = choose [0:0] s213
+  s215 :: SBool = s10 /= s214
+  s216 :: SWord8 = if s215 then s109 else s110
+  s217 :: SWord 1 = choose [0:0] s216
+  s218 :: SBool = s10 /= s217
+  s219 :: SBool = ~ s218
+  s220 :: SBool = s210 < s1
+  s221 :: SBool = s210 < s99
+  s222 :: SBool = s220 | s221
+  s223 :: SWord8 = s210 >>> 1
+  s224 :: SWord8 = s14 | s223
+  s225 :: SWord8 = s16 & s223
+  s226 :: SWord8 = if s222 then s224 else s225
+  s227 :: SWord8 = s226 >>> 1
+  s228 :: SWord8 = s14 | s227
+  s229 :: SWord8 = s16 & s227
+  s230 :: SWord8 = if s75 then s228 else s229
+  s231 :: SWord8 = s230 >>> 1
+  s232 :: SWord8 = s14 | s231
+  s233 :: SWord8 = s16 & s231
+  s234 :: SWord8 = if s94 then s232 else s233
+  s235 :: SWord8 = s234 >>> 1
+  s236 :: SWord8 = s14 | s235
+  s237 :: SWord8 = s16 & s235
+  s238 :: SWord8 = if s218 then s236 else s237
+  s239 :: SWord8 = s1 + s234
+  s240 :: SBool = s239 < s1
+  s241 :: SBool = s239 < s234
+  s242 :: SBool = s240 | s241
+  s243 :: SWord8 = s239 >>> 1
+  s244 :: SWord8 = s14 | s243
+  s245 :: SWord8 = s16 & s243
+  s246 :: SWord8 = if s242 then s244 else s245
+  s247 :: SWord8 = if s219 then s238 else s246
+  s248 :: SWord8 = s1 + s230
+  s249 :: SBool = s248 < s1
+  s250 :: SBool = s248 < s230
+  s251 :: SBool = s249 | s250
+  s252 :: SWord8 = s248 >>> 1
+  s253 :: SWord8 = s14 | s252
+  s254 :: SWord8 = s16 & s252
+  s255 :: SWord8 = if s251 then s253 else s254
+  s256 :: SWord8 = s255 >>> 1
+  s257 :: SWord8 = s14 | s256
+  s258 :: SWord8 = s16 & s256
+  s259 :: SWord8 = if s218 then s257 else s258
+  s260 :: SWord8 = s1 + s255
+  s261 :: SBool = s260 < s1
+  s262 :: SBool = s260 < s255
+  s263 :: SBool = s261 | s262
+  s264 :: SWord8 = s260 >>> 1
+  s265 :: SWord8 = s14 | s264
+  s266 :: SWord8 = s16 & s264
+  s267 :: SWord8 = if s263 then s265 else s266
+  s268 :: SWord8 = if s219 then s259 else s267
+  s269 :: SWord8 = if s95 then s247 else s268
+  s270 :: SWord8 = s1 + s226
+  s271 :: SBool = s270 < s1
+  s272 :: SBool = s270 < s226
+  s273 :: SBool = s271 | s272
+  s274 :: SWord8 = s270 >>> 1
+  s275 :: SWord8 = s14 | s274
+  s276 :: SWord8 = s16 & s274
+  s277 :: SWord8 = if s273 then s275 else s276
+  s278 :: SWord8 = s277 >>> 1
+  s279 :: SWord8 = s14 | s278
+  s280 :: SWord8 = s16 & s278
+  s281 :: SWord8 = if s94 then s279 else s280
+  s282 :: SWord8 = s281 >>> 1
+  s283 :: SWord8 = s14 | s282
+  s284 :: SWord8 = s16 & s282
+  s285 :: SWord8 = if s218 then s283 else s284
+  s286 :: SWord8 = s1 + s281
+  s287 :: SBool = s286 < s1
+  s288 :: SBool = s286 < s281
+  s289 :: SBool = s287 | s288
+  s290 :: SWord8 = s286 >>> 1
+  s291 :: SWord8 = s14 | s290
+  s292 :: SWord8 = s16 & s290
+  s293 :: SWord8 = if s289 then s291 else s292
+  s294 :: SWord8 = if s219 then s285 else s293
+  s295 :: SWord8 = s1 + s277
+  s296 :: SBool = s295 < s1
+  s297 :: SBool = s295 < s277
+  s298 :: SBool = s296 | s297
+  s299 :: SWord8 = s295 >>> 1
+  s300 :: SWord8 = s14 | s299
+  s301 :: SWord8 = s16 & s299
+  s302 :: SWord8 = if s298 then s300 else s301
+  s303 :: SWord8 = s302 >>> 1
+  s304 :: SWord8 = s14 | s303
+  s305 :: SWord8 = s16 & s303
+  s306 :: SWord8 = if s218 then s304 else s305
+  s307 :: SWord8 = s1 + s302
+  s308 :: SBool = s307 < s1
+  s309 :: SBool = s307 < s302
+  s310 :: SBool = s308 | s309
+  s311 :: SWord8 = s307 >>> 1
+  s312 :: SWord8 = s14 | s311
+  s313 :: SWord8 = s16 & s311
+  s314 :: SWord8 = if s310 then s312 else s313
+  s315 :: SWord8 = if s219 then s306 else s314
+  s316 :: SWord8 = if s95 then s294 else s315
+  s317 :: SWord8 = if s76 then s269 else s316
+  s318 :: SWord8 = if s57 then s209 else s317
+  s319 :: SWord8 = s1 + s80
+  s320 :: SWord 1 = choose [0:0] s319
+  s321 :: SBool = s10 /= s320
+  s322 :: SWord8 = if s321 then s84 else s85
+  s323 :: SWord 1 = choose [0:0] s322
+  s324 :: SBool = s10 /= s323
+  s325 :: SWord8 = if s324 then s90 else s91
+  s326 :: SWord 1 = choose [0:0] s325
+  s327 :: SBool = s10 /= s326
+  s328 :: SBool = ~ s327
+  s329 :: SBool = s319 < s1
+  s330 :: SBool = s319 < s80
+  s331 :: SBool = s329 | s330
+  s332 :: SWord8 = s319 >>> 1
+  s333 :: SWord8 = s14 | s332
+  s334 :: SWord8 = s16 & s332
+  s335 :: SWord8 = if s331 then s333 else s334
+  s336 :: SWord 1 = choose [0:0] s335
+  s337 :: SBool = s10 /= s336
+  s338 :: SWord8 = s322 >>> 1
+  s339 :: SWord8 = s14 | s338
+  s340 :: SWord8 = s16 & s338
+  s341 :: SWord8 = if s337 then s339 else s340
+  s342 :: SWord 1 = choose [0:0] s341
+  s343 :: SBool = s10 /= s342
+  s344 :: SWord8 = s325 >>> 1
+  s345 :: SWord8 = s14 | s344
+  s346 :: SWord8 = s16 & s344
+  s347 :: SWord8 = if s343 then s345 else s346
+  s348 :: SWord 1 = choose [0:0] s347
+  s349 :: SBool = s10 /= s348
+  s350 :: SBool = ~ s349
+  s351 :: SWord8 = s335 >>> 1
+  s352 :: SWord8 = s14 | s351
+  s353 :: SWord8 = s16 & s351
+  s354 :: SWord8 = if s56 then s352 else s353
+  s355 :: SWord8 = s354 >>> 1
+  s356 :: SWord8 = s14 | s355
+  s357 :: SWord8 = s16 & s355
+  s358 :: SWord8 = if s75 then s356 else s357
+  s359 :: SWord8 = s358 >>> 1
+  s360 :: SWord8 = s14 | s359
+  s361 :: SWord8 = s16 & s359
+  s362 :: SWord8 = if s327 then s360 else s361
+  s363 :: SWord8 = s362 >>> 1
+  s364 :: SWord8 = s14 | s363
+  s365 :: SWord8 = s16 & s363
+  s366 :: SWord8 = if s349 then s364 else s365
+  s367 :: SWord8 = s1 + s362
+  s368 :: SBool = s367 < s1
+  s369 :: SBool = s367 < s362
+  s370 :: SBool = s368 | s369
+  s371 :: SWord8 = s367 >>> 1
+  s372 :: SWord8 = s14 | s371
+  s373 :: SWord8 = s16 & s371
+  s374 :: SWord8 = if s370 then s372 else s373
+  s375 :: SWord8 = if s350 then s366 else s374
+  s376 :: SWord8 = s1 + s358
+  s377 :: SBool = s376 < s1
+  s378 :: SBool = s376 < s358
+  s379 :: SBool = s377 | s378
+  s380 :: SWord8 = s376 >>> 1
+  s381 :: SWord8 = s14 | s380
+  s382 :: SWord8 = s16 & s380
+  s383 :: SWord8 = if s379 then s381 else s382
+  s384 :: SWord8 = s383 >>> 1
+  s385 :: SWord8 = s14 | s384
+  s386 :: SWord8 = s16 & s384
+  s387 :: SWord8 = if s349 then s385 else s386
+  s388 :: SWord8 = s1 + s383
+  s389 :: SBool = s388 < s1
+  s390 :: SBool = s388 < s383
+  s391 :: SBool = s389 | s390
+  s392 :: SWord8 = s388 >>> 1
+  s393 :: SWord8 = s14 | s392
+  s394 :: SWord8 = s16 & s392
+  s395 :: SWord8 = if s391 then s393 else s394
+  s396 :: SWord8 = if s350 then s387 else s395
+  s397 :: SWord8 = if s328 then s375 else s396
+  s398 :: SWord8 = s1 + s354
+  s399 :: SBool = s398 < s1
+  s400 :: SBool = s398 < s354
+  s401 :: SBool = s399 | s400
+  s402 :: SWord8 = s398 >>> 1
+  s403 :: SWord8 = s14 | s402
+  s404 :: SWord8 = s16 & s402
+  s405 :: SWord8 = if s401 then s403 else s404
+  s406 :: SWord8 = s405 >>> 1
+  s407 :: SWord8 = s14 | s406
+  s408 :: SWord8 = s16 & s406
+  s409 :: SWord8 = if s327 then s407 else s408
+  s410 :: SWord8 = s409 >>> 1
+  s411 :: SWord8 = s14 | s410
+  s412 :: SWord8 = s16 & s410
+  s413 :: SWord8 = if s349 then s411 else s412
+  s414 :: SWord8 = s1 + s409
+  s415 :: SBool = s414 < s1
+  s416 :: SBool = s414 < s409
+  s417 :: SBool = s415 | s416
+  s418 :: SWord8 = s414 >>> 1
+  s419 :: SWord8 = s14 | s418
+  s420 :: SWord8 = s16 & s418
+  s421 :: SWord8 = if s417 then s419 else s420
+  s422 :: SWord8 = if s350 then s413 else s421
+  s423 :: SWord8 = s1 + s405
+  s424 :: SBool = s423 < s1
+  s425 :: SBool = s423 < s405
+  s426 :: SBool = s424 | s425
+  s427 :: SWord8 = s423 >>> 1
+  s428 :: SWord8 = s14 | s427
+  s429 :: SWord8 = s16 & s427
+  s430 :: SWord8 = if s426 then s428 else s429
+  s431 :: SWord8 = s430 >>> 1
+  s432 :: SWord8 = s14 | s431
+  s433 :: SWord8 = s16 & s431
+  s434 :: SWord8 = if s349 then s432 else s433
+  s435 :: SWord8 = s1 + s430
+  s436 :: SBool = s435 < s1
+  s437 :: SBool = s435 < s430
+  s438 :: SBool = s436 | s437
+  s439 :: SWord8 = s435 >>> 1
+  s440 :: SWord8 = s14 | s439
+  s441 :: SWord8 = s16 & s439
+  s442 :: SWord8 = if s438 then s440 else s441
+  s443 :: SWord8 = if s350 then s434 else s442
+  s444 :: SWord8 = if s328 then s422 else s443
+  s445 :: SWord8 = if s76 then s397 else s444
+  s446 :: SWord8 = s1 + s335
+  s447 :: SWord 1 = choose [0:0] s446
+  s448 :: SBool = s10 /= s447
+  s449 :: SWord8 = if s448 then s339 else s340
+  s450 :: SWord 1 = choose [0:0] s449
+  s451 :: SBool = s10 /= s450
+  s452 :: SWord8 = if s451 then s345 else s346
+  s453 :: SWord 1 = choose [0:0] s452
+  s454 :: SBool = s10 /= s453
+  s455 :: SBool = ~ s454
+  s456 :: SBool = s446 < s1
+  s457 :: SBool = s446 < s335
+  s458 :: SBool = s456 | s457
+  s459 :: SWord8 = s446 >>> 1
+  s460 :: SWord8 = s14 | s459
+  s461 :: SWord8 = s16 & s459
+  s462 :: SWord8 = if s458 then s460 else s461
+  s463 :: SWord8 = s462 >>> 1
+  s464 :: SWord8 = s14 | s463
+  s465 :: SWord8 = s16 & s463
+  s466 :: SWord8 = if s75 then s464 else s465
+  s467 :: SWord8 = s466 >>> 1
+  s468 :: SWord8 = s14 | s467
+  s469 :: SWord8 = s16 & s467
+  s470 :: SWord8 = if s327 then s468 else s469
+  s471 :: SWord8 = s470 >>> 1
+  s472 :: SWord8 = s14 | s471
+  s473 :: SWord8 = s16 & s471
+  s474 :: SWord8 = if s454 then s472 else s473
+  s475 :: SWord8 = s1 + s470
+  s476 :: SBool = s475 < s1
+  s477 :: SBool = s475 < s470
+  s478 :: SBool = s476 | s477
+  s479 :: SWord8 = s475 >>> 1
+  s480 :: SWord8 = s14 | s479
+  s481 :: SWord8 = s16 & s479
+  s482 :: SWord8 = if s478 then s480 else s481
+  s483 :: SWord8 = if s455 then s474 else s482
+  s484 :: SWord8 = s1 + s466
+  s485 :: SBool = s484 < s1
+  s486 :: SBool = s484 < s466
+  s487 :: SBool = s485 | s486
+  s488 :: SWord8 = s484 >>> 1
+  s489 :: SWord8 = s14 | s488
+  s490 :: SWord8 = s16 & s488
+  s491 :: SWord8 = if s487 then s489 else s490
+  s492 :: SWord8 = s491 >>> 1
+  s493 :: SWord8 = s14 | s492
+  s494 :: SWord8 = s16 & s492
+  s495 :: SWord8 = if s454 then s493 else s494
+  s496 :: SWord8 = s1 + s491
+  s497 :: SBool = s496 < s1
+  s498 :: SBool = s496 < s491
+  s499 :: SBool = s497 | s498
+  s500 :: SWord8 = s496 >>> 1
+  s501 :: SWord8 = s14 | s500
+  s502 :: SWord8 = s16 & s500
+  s503 :: SWord8 = if s499 then s501 else s502
+  s504 :: SWord8 = if s455 then s495 else s503
+  s505 :: SWord8 = if s328 then s483 else s504
+  s506 :: SWord8 = s1 + s462
+  s507 :: SBool = s506 < s1
+  s508 :: SBool = s506 < s462
+  s509 :: SBool = s507 | s508
+  s510 :: SWord8 = s506 >>> 1
+  s511 :: SWord8 = s14 | s510
+  s512 :: SWord8 = s16 & s510
+  s513 :: SWord8 = if s509 then s511 else s512
+  s514 :: SWord8 = s513 >>> 1
+  s515 :: SWord8 = s14 | s514
+  s516 :: SWord8 = s16 & s514
+  s517 :: SWord8 = if s327 then s515 else s516
+  s518 :: SWord8 = s517 >>> 1
+  s519 :: SWord8 = s14 | s518
+  s520 :: SWord8 = s16 & s518
+  s521 :: SWord8 = if s454 then s519 else s520
+  s522 :: SWord8 = s1 + s517
+  s523 :: SBool = s522 < s1
+  s524 :: SBool = s522 < s517
+  s525 :: SBool = s523 | s524
+  s526 :: SWord8 = s522 >>> 1
+  s527 :: SWord8 = s14 | s526
+  s528 :: SWord8 = s16 & s526
+  s529 :: SWord8 = if s525 then s527 else s528
+  s530 :: SWord8 = if s455 then s521 else s529
+  s531 :: SWord8 = s1 + s513
+  s532 :: SBool = s531 < s1
+  s533 :: SBool = s531 < s513
+  s534 :: SBool = s532 | s533
+  s535 :: SWord8 = s531 >>> 1
+  s536 :: SWord8 = s14 | s535
+  s537 :: SWord8 = s16 & s535
+  s538 :: SWord8 = if s534 then s536 else s537
+  s539 :: SWord8 = s538 >>> 1
+  s540 :: SWord8 = s14 | s539
+  s541 :: SWord8 = s16 & s539
+  s542 :: SWord8 = if s454 then s540 else s541
+  s543 :: SWord8 = s1 + s538
+  s544 :: SBool = s543 < s1
+  s545 :: SBool = s543 < s538
+  s546 :: SBool = s544 | s545
+  s547 :: SWord8 = s543 >>> 1
+  s548 :: SWord8 = s14 | s547
+  s549 :: SWord8 = s16 & s547
+  s550 :: SWord8 = if s546 then s548 else s549
+  s551 :: SWord8 = if s455 then s542 else s550
+  s552 :: SWord8 = if s328 then s530 else s551
+  s553 :: SWord8 = if s76 then s505 else s552
+  s554 :: SWord8 = if s57 then s445 else s553
+  s555 :: SWord8 = if s41 then s318 else s554
+  s556 :: SWord8 = s1 + s61
+  s557 :: SWord 1 = choose [0:0] s556
+  s558 :: SBool = s10 /= s557
+  s559 :: SWord8 = if s558 then s65 else s66
+  s560 :: SWord 1 = choose [0:0] s559
+  s561 :: SBool = s10 /= s560
+  s562 :: SWord8 = if s561 then s71 else s72
+  s563 :: SWord 1 = choose [0:0] s562
+  s564 :: SBool = s10 /= s563
+  s565 :: SBool = ~ s564
+  s566 :: SBool = s556 < s1
+  s567 :: SBool = s556 < s61
+  s568 :: SBool = s566 | s567
+  s569 :: SWord8 = s556 >>> 1
+  s570 :: SWord8 = s14 | s569
+  s571 :: SWord8 = s16 & s569
+  s572 :: SWord8 = if s568 then s570 else s571
+  s573 :: SWord 1 = choose [0:0] s572
+  s574 :: SBool = s10 /= s573
+  s575 :: SWord8 = s559 >>> 1
+  s576 :: SWord8 = s14 | s575
+  s577 :: SWord8 = s16 & s575
+  s578 :: SWord8 = if s574 then s576 else s577
+  s579 :: SWord 1 = choose [0:0] s578
+  s580 :: SBool = s10 /= s579
+  s581 :: SWord8 = s562 >>> 1
+  s582 :: SWord8 = s14 | s581
+  s583 :: SWord8 = s16 & s581
+  s584 :: SWord8 = if s580 then s582 else s583
+  s585 :: SWord 1 = choose [0:0] s584
+  s586 :: SBool = s10 /= s585
+  s587 :: SBool = ~ s586
+  s588 :: SWord8 = s572 >>> 1
+  s589 :: SWord8 = s14 | s588
+  s590 :: SWord8 = s16 & s588
+  s591 :: SWord8 = if s40 then s589 else s590
+  s592 :: SWord 1 = choose [0:0] s591
+  s593 :: SBool = s10 /= s592
+  s594 :: SWord8 = s578 >>> 1
+  s595 :: SWord8 = s14 | s594
+  s596 :: SWord8 = s16 & s594
+  s597 :: SWord8 = if s593 then s595 else s596
+  s598 :: SWord 1 = choose [0:0] s597
+  s599 :: SBool = s10 /= s598
+  s600 :: SWord8 = s584 >>> 1
+  s601 :: SWord8 = s14 | s600
+  s602 :: SWord8 = s16 & s600
+  s603 :: SWord8 = if s599 then s601 else s602
+  s604 :: SWord 1 = choose [0:0] s603
+  s605 :: SBool = s10 /= s604
+  s606 :: SBool = ~ s605
+  s607 :: SWord8 = s591 >>> 1
+  s608 :: SWord8 = s14 | s607
+  s609 :: SWord8 = s16 & s607
+  s610 :: SWord8 = if s56 then s608 else s609
+  s611 :: SWord8 = s610 >>> 1
+  s612 :: SWord8 = s14 | s611
+  s613 :: SWord8 = s16 & s611
+  s614 :: SWord8 = if s564 then s612 else s613
+  s615 :: SWord8 = s614 >>> 1
+  s616 :: SWord8 = s14 | s615
+  s617 :: SWord8 = s16 & s615
+  s618 :: SWord8 = if s586 then s616 else s617
+  s619 :: SWord8 = s618 >>> 1
+  s620 :: SWord8 = s14 | s619
+  s621 :: SWord8 = s16 & s619
+  s622 :: SWord8 = if s605 then s620 else s621
+  s623 :: SWord8 = s1 + s618
+  s624 :: SBool = s623 < s1
+  s625 :: SBool = s623 < s618
+  s626 :: SBool = s624 | s625
+  s627 :: SWord8 = s623 >>> 1
+  s628 :: SWord8 = s14 | s627
+  s629 :: SWord8 = s16 & s627
+  s630 :: SWord8 = if s626 then s628 else s629
+  s631 :: SWord8 = if s606 then s622 else s630
+  s632 :: SWord8 = s1 + s614
+  s633 :: SBool = s632 < s1
+  s634 :: SBool = s632 < s614
+  s635 :: SBool = s633 | s634
+  s636 :: SWord8 = s632 >>> 1
+  s637 :: SWord8 = s14 | s636
+  s638 :: SWord8 = s16 & s636
+  s639 :: SWord8 = if s635 then s637 else s638
+  s640 :: SWord8 = s639 >>> 1
+  s641 :: SWord8 = s14 | s640
+  s642 :: SWord8 = s16 & s640
+  s643 :: SWord8 = if s605 then s641 else s642
+  s644 :: SWord8 = s1 + s639
+  s645 :: SBool = s644 < s1
+  s646 :: SBool = s644 < s639
+  s647 :: SBool = s645 | s646
+  s648 :: SWord8 = s644 >>> 1
+  s649 :: SWord8 = s14 | s648
+  s650 :: SWord8 = s16 & s648
+  s651 :: SWord8 = if s647 then s649 else s650
+  s652 :: SWord8 = if s606 then s643 else s651
+  s653 :: SWord8 = if s587 then s631 else s652
+  s654 :: SWord8 = s1 + s610
+  s655 :: SBool = s654 < s1
+  s656 :: SBool = s654 < s610
+  s657 :: SBool = s655 | s656
+  s658 :: SWord8 = s654 >>> 1
+  s659 :: SWord8 = s14 | s658
+  s660 :: SWord8 = s16 & s658
+  s661 :: SWord8 = if s657 then s659 else s660
+  s662 :: SWord8 = s661 >>> 1
+  s663 :: SWord8 = s14 | s662
+  s664 :: SWord8 = s16 & s662
+  s665 :: SWord8 = if s586 then s663 else s664
+  s666 :: SWord8 = s665 >>> 1
+  s667 :: SWord8 = s14 | s666
+  s668 :: SWord8 = s16 & s666
+  s669 :: SWord8 = if s605 then s667 else s668
+  s670 :: SWord8 = s1 + s665
+  s671 :: SBool = s670 < s1
+  s672 :: SBool = s670 < s665
+  s673 :: SBool = s671 | s672
+  s674 :: SWord8 = s670 >>> 1
+  s675 :: SWord8 = s14 | s674
+  s676 :: SWord8 = s16 & s674
+  s677 :: SWord8 = if s673 then s675 else s676
+  s678 :: SWord8 = if s606 then s669 else s677
+  s679 :: SWord8 = s1 + s661
+  s680 :: SBool = s679 < s1
+  s681 :: SBool = s679 < s661
+  s682 :: SBool = s680 | s681
+  s683 :: SWord8 = s679 >>> 1
+  s684 :: SWord8 = s14 | s683
+  s685 :: SWord8 = s16 & s683
+  s686 :: SWord8 = if s682 then s684 else s685
+  s687 :: SWord8 = s686 >>> 1
+  s688 :: SWord8 = s14 | s687
+  s689 :: SWord8 = s16 & s687
+  s690 :: SWord8 = if s605 then s688 else s689
+  s691 :: SWord8 = s1 + s686
+  s692 :: SBool = s691 < s1
+  s693 :: SBool = s691 < s686
+  s694 :: SBool = s692 | s693
+  s695 :: SWord8 = s691 >>> 1
+  s696 :: SWord8 = s14 | s695
+  s697 :: SWord8 = s16 & s695
+  s698 :: SWord8 = if s694 then s696 else s697
+  s699 :: SWord8 = if s606 then s690 else s698
+  s700 :: SWord8 = if s587 then s678 else s699
+  s701 :: SWord8 = if s565 then s653 else s700
+  s702 :: SWord8 = s1 + s591
+  s703 :: SWord 1 = choose [0:0] s702
+  s704 :: SBool = s10 /= s703
+  s705 :: SWord8 = if s704 then s595 else s596
+  s706 :: SWord 1 = choose [0:0] s705
+  s707 :: SBool = s10 /= s706
+  s708 :: SWord8 = if s707 then s601 else s602
+  s709 :: SWord 1 = choose [0:0] s708
+  s710 :: SBool = s10 /= s709
+  s711 :: SBool = ~ s710
+  s712 :: SBool = s702 < s1
+  s713 :: SBool = s702 < s591
+  s714 :: SBool = s712 | s713
+  s715 :: SWord8 = s702 >>> 1
+  s716 :: SWord8 = s14 | s715
+  s717 :: SWord8 = s16 & s715
+  s718 :: SWord8 = if s714 then s716 else s717
+  s719 :: SWord8 = s718 >>> 1
+  s720 :: SWord8 = s14 | s719
+  s721 :: SWord8 = s16 & s719
+  s722 :: SWord8 = if s564 then s720 else s721
+  s723 :: SWord8 = s722 >>> 1
+  s724 :: SWord8 = s14 | s723
+  s725 :: SWord8 = s16 & s723
+  s726 :: SWord8 = if s586 then s724 else s725
+  s727 :: SWord8 = s726 >>> 1
+  s728 :: SWord8 = s14 | s727
+  s729 :: SWord8 = s16 & s727
+  s730 :: SWord8 = if s710 then s728 else s729
+  s731 :: SWord8 = s1 + s726
+  s732 :: SBool = s731 < s1
+  s733 :: SBool = s731 < s726
+  s734 :: SBool = s732 | s733
+  s735 :: SWord8 = s731 >>> 1
+  s736 :: SWord8 = s14 | s735
+  s737 :: SWord8 = s16 & s735
+  s738 :: SWord8 = if s734 then s736 else s737
+  s739 :: SWord8 = if s711 then s730 else s738
+  s740 :: SWord8 = s1 + s722
+  s741 :: SBool = s740 < s1
+  s742 :: SBool = s740 < s722
+  s743 :: SBool = s741 | s742
+  s744 :: SWord8 = s740 >>> 1
+  s745 :: SWord8 = s14 | s744
+  s746 :: SWord8 = s16 & s744
+  s747 :: SWord8 = if s743 then s745 else s746
+  s748 :: SWord8 = s747 >>> 1
+  s749 :: SWord8 = s14 | s748
+  s750 :: SWord8 = s16 & s748
+  s751 :: SWord8 = if s710 then s749 else s750
+  s752 :: SWord8 = s1 + s747
+  s753 :: SBool = s752 < s1
+  s754 :: SBool = s752 < s747
+  s755 :: SBool = s753 | s754
+  s756 :: SWord8 = s752 >>> 1
+  s757 :: SWord8 = s14 | s756
+  s758 :: SWord8 = s16 & s756
+  s759 :: SWord8 = if s755 then s757 else s758
+  s760 :: SWord8 = if s711 then s751 else s759
+  s761 :: SWord8 = if s587 then s739 else s760
+  s762 :: SWord8 = s1 + s718
+  s763 :: SBool = s762 < s1
+  s764 :: SBool = s762 < s718
+  s765 :: SBool = s763 | s764
+  s766 :: SWord8 = s762 >>> 1
+  s767 :: SWord8 = s14 | s766
+  s768 :: SWord8 = s16 & s766
+  s769 :: SWord8 = if s765 then s767 else s768
+  s770 :: SWord8 = s769 >>> 1
+  s771 :: SWord8 = s14 | s770
+  s772 :: SWord8 = s16 & s770
+  s773 :: SWord8 = if s586 then s771 else s772
+  s774 :: SWord8 = s773 >>> 1
+  s775 :: SWord8 = s14 | s774
+  s776 :: SWord8 = s16 & s774
+  s777 :: SWord8 = if s710 then s775 else s776
+  s778 :: SWord8 = s1 + s773
+  s779 :: SBool = s778 < s1
+  s780 :: SBool = s778 < s773
+  s781 :: SBool = s779 | s780
+  s782 :: SWord8 = s778 >>> 1
+  s783 :: SWord8 = s14 | s782
+  s784 :: SWord8 = s16 & s782
+  s785 :: SWord8 = if s781 then s783 else s784
+  s786 :: SWord8 = if s711 then s777 else s785
+  s787 :: SWord8 = s1 + s769
+  s788 :: SBool = s787 < s1
+  s789 :: SBool = s787 < s769
+  s790 :: SBool = s788 | s789
+  s791 :: SWord8 = s787 >>> 1
+  s792 :: SWord8 = s14 | s791
+  s793 :: SWord8 = s16 & s791
+  s794 :: SWord8 = if s790 then s792 else s793
+  s795 :: SWord8 = s794 >>> 1
+  s796 :: SWord8 = s14 | s795
+  s797 :: SWord8 = s16 & s795
+  s798 :: SWord8 = if s710 then s796 else s797
+  s799 :: SWord8 = s1 + s794
+  s800 :: SBool = s799 < s1
+  s801 :: SBool = s799 < s794
+  s802 :: SBool = s800 | s801
+  s803 :: SWord8 = s799 >>> 1
+  s804 :: SWord8 = s14 | s803
+  s805 :: SWord8 = s16 & s803
+  s806 :: SWord8 = if s802 then s804 else s805
+  s807 :: SWord8 = if s711 then s798 else s806
+  s808 :: SWord8 = if s587 then s786 else s807
+  s809 :: SWord8 = if s565 then s761 else s808
+  s810 :: SWord8 = if s57 then s701 else s809
+  s811 :: SWord8 = s1 + s572
+  s812 :: SWord 1 = choose [0:0] s811
+  s813 :: SBool = s10 /= s812
+  s814 :: SWord8 = if s813 then s576 else s577
+  s815 :: SWord 1 = choose [0:0] s814
+  s816 :: SBool = s10 /= s815
+  s817 :: SWord8 = if s816 then s582 else s583
+  s818 :: SWord 1 = choose [0:0] s817
+  s819 :: SBool = s10 /= s818
+  s820 :: SBool = ~ s819
+  s821 :: SBool = s811 < s1
+  s822 :: SBool = s811 < s572
+  s823 :: SBool = s821 | s822
+  s824 :: SWord8 = s811 >>> 1
+  s825 :: SWord8 = s14 | s824
+  s826 :: SWord8 = s16 & s824
+  s827 :: SWord8 = if s823 then s825 else s826
+  s828 :: SWord 1 = choose [0:0] s827
+  s829 :: SBool = s10 /= s828
+  s830 :: SWord8 = s814 >>> 1
+  s831 :: SWord8 = s14 | s830
+  s832 :: SWord8 = s16 & s830
+  s833 :: SWord8 = if s829 then s831 else s832
+  s834 :: SWord 1 = choose [0:0] s833
+  s835 :: SBool = s10 /= s834
+  s836 :: SWord8 = s817 >>> 1
+  s837 :: SWord8 = s14 | s836
+  s838 :: SWord8 = s16 & s836
+  s839 :: SWord8 = if s835 then s837 else s838
+  s840 :: SWord 1 = choose [0:0] s839
+  s841 :: SBool = s10 /= s840
+  s842 :: SBool = ~ s841
+  s843 :: SWord8 = s827 >>> 1
+  s844 :: SWord8 = s14 | s843
+  s845 :: SWord8 = s16 & s843
+  s846 :: SWord8 = if s56 then s844 else s845
+  s847 :: SWord8 = s846 >>> 1
+  s848 :: SWord8 = s14 | s847
+  s849 :: SWord8 = s16 & s847
+  s850 :: SWord8 = if s564 then s848 else s849
+  s851 :: SWord8 = s850 >>> 1
+  s852 :: SWord8 = s14 | s851
+  s853 :: SWord8 = s16 & s851
+  s854 :: SWord8 = if s819 then s852 else s853
+  s855 :: SWord8 = s854 >>> 1
+  s856 :: SWord8 = s14 | s855
+  s857 :: SWord8 = s16 & s855
+  s858 :: SWord8 = if s841 then s856 else s857
+  s859 :: SWord8 = s1 + s854
+  s860 :: SBool = s859 < s1
+  s861 :: SBool = s859 < s854
+  s862 :: SBool = s860 | s861
+  s863 :: SWord8 = s859 >>> 1
+  s864 :: SWord8 = s14 | s863
+  s865 :: SWord8 = s16 & s863
+  s866 :: SWord8 = if s862 then s864 else s865
+  s867 :: SWord8 = if s842 then s858 else s866
+  s868 :: SWord8 = s1 + s850
+  s869 :: SBool = s868 < s1
+  s870 :: SBool = s868 < s850
+  s871 :: SBool = s869 | s870
+  s872 :: SWord8 = s868 >>> 1
+  s873 :: SWord8 = s14 | s872
+  s874 :: SWord8 = s16 & s872
+  s875 :: SWord8 = if s871 then s873 else s874
+  s876 :: SWord8 = s875 >>> 1
+  s877 :: SWord8 = s14 | s876
+  s878 :: SWord8 = s16 & s876
+  s879 :: SWord8 = if s841 then s877 else s878
+  s880 :: SWord8 = s1 + s875
+  s881 :: SBool = s880 < s1
+  s882 :: SBool = s880 < s875
+  s883 :: SBool = s881 | s882
+  s884 :: SWord8 = s880 >>> 1
+  s885 :: SWord8 = s14 | s884
+  s886 :: SWord8 = s16 & s884
+  s887 :: SWord8 = if s883 then s885 else s886
+  s888 :: SWord8 = if s842 then s879 else s887
+  s889 :: SWord8 = if s820 then s867 else s888
+  s890 :: SWord8 = s1 + s846
+  s891 :: SBool = s890 < s1
+  s892 :: SBool = s890 < s846
+  s893 :: SBool = s891 | s892
+  s894 :: SWord8 = s890 >>> 1
+  s895 :: SWord8 = s14 | s894
+  s896 :: SWord8 = s16 & s894
+  s897 :: SWord8 = if s893 then s895 else s896
+  s898 :: SWord8 = s897 >>> 1
+  s899 :: SWord8 = s14 | s898
+  s900 :: SWord8 = s16 & s898
+  s901 :: SWord8 = if s819 then s899 else s900
+  s902 :: SWord8 = s901 >>> 1
+  s903 :: SWord8 = s14 | s902
+  s904 :: SWord8 = s16 & s902
+  s905 :: SWord8 = if s841 then s903 else s904
+  s906 :: SWord8 = s1 + s901
+  s907 :: SBool = s906 < s1
+  s908 :: SBool = s906 < s901
+  s909 :: SBool = s907 | s908
+  s910 :: SWord8 = s906 >>> 1
+  s911 :: SWord8 = s14 | s910
+  s912 :: SWord8 = s16 & s910
+  s913 :: SWord8 = if s909 then s911 else s912
+  s914 :: SWord8 = if s842 then s905 else s913
+  s915 :: SWord8 = s1 + s897
+  s916 :: SBool = s915 < s1
+  s917 :: SBool = s915 < s897
+  s918 :: SBool = s916 | s917
+  s919 :: SWord8 = s915 >>> 1
+  s920 :: SWord8 = s14 | s919
+  s921 :: SWord8 = s16 & s919
+  s922 :: SWord8 = if s918 then s920 else s921
+  s923 :: SWord8 = s922 >>> 1
+  s924 :: SWord8 = s14 | s923
+  s925 :: SWord8 = s16 & s923
+  s926 :: SWord8 = if s841 then s924 else s925
+  s927 :: SWord8 = s1 + s922
+  s928 :: SBool = s927 < s1
+  s929 :: SBool = s927 < s922
+  s930 :: SBool = s928 | s929
+  s931 :: SWord8 = s927 >>> 1
+  s932 :: SWord8 = s14 | s931
+  s933 :: SWord8 = s16 & s931
+  s934 :: SWord8 = if s930 then s932 else s933
+  s935 :: SWord8 = if s842 then s926 else s934
+  s936 :: SWord8 = if s820 then s914 else s935
+  s937 :: SWord8 = if s565 then s889 else s936
+  s938 :: SWord8 = s1 + s827
+  s939 :: SWord 1 = choose [0:0] s938
+  s940 :: SBool = s10 /= s939
+  s941 :: SWord8 = if s940 then s831 else s832
+  s942 :: SWord 1 = choose [0:0] s941
+  s943 :: SBool = s10 /= s942
+  s944 :: SWord8 = if s943 then s837 else s838
+  s945 :: SWord 1 = choose [0:0] s944
+  s946 :: SBool = s10 /= s945
+  s947 :: SBool = ~ s946
+  s948 :: SBool = s938 < s1
+  s949 :: SBool = s938 < s827
+  s950 :: SBool = s948 | s949
+  s951 :: SWord8 = s938 >>> 1
+  s952 :: SWord8 = s14 | s951
+  s953 :: SWord8 = s16 & s951
+  s954 :: SWord8 = if s950 then s952 else s953
+  s955 :: SWord8 = s954 >>> 1
+  s956 :: SWord8 = s14 | s955
+  s957 :: SWord8 = s16 & s955
+  s958 :: SWord8 = if s564 then s956 else s957
+  s959 :: SWord8 = s958 >>> 1
+  s960 :: SWord8 = s14 | s959
+  s961 :: SWord8 = s16 & s959
+  s962 :: SWord8 = if s819 then s960 else s961
+  s963 :: SWord8 = s962 >>> 1
+  s964 :: SWord8 = s14 | s963
+  s965 :: SWord8 = s16 & s963
+  s966 :: SWord8 = if s946 then s964 else s965
+  s967 :: SWord8 = s1 + s962
+  s968 :: SBool = s967 < s1
+  s969 :: SBool = s967 < s962
+  s970 :: SBool = s968 | s969
+  s971 :: SWord8 = s967 >>> 1
+  s972 :: SWord8 = s14 | s971
+  s973 :: SWord8 = s16 & s971
+  s974 :: SWord8 = if s970 then s972 else s973
+  s975 :: SWord8 = if s947 then s966 else s974
+  s976 :: SWord8 = s1 + s958
+  s977 :: SBool = s976 < s1
+  s978 :: SBool = s976 < s958
+  s979 :: SBool = s977 | s978
+  s980 :: SWord8 = s976 >>> 1
+  s981 :: SWord8 = s14 | s980
+  s982 :: SWord8 = s16 & s980
+  s983 :: SWord8 = if s979 then s981 else s982
+  s984 :: SWord8 = s983 >>> 1
+  s985 :: SWord8 = s14 | s984
+  s986 :: SWord8 = s16 & s984
+  s987 :: SWord8 = if s946 then s985 else s986
+  s988 :: SWord8 = s1 + s983
+  s989 :: SBool = s988 < s1
+  s990 :: SBool = s988 < s983
+  s991 :: SBool = s989 | s990
+  s992 :: SWord8 = s988 >>> 1
+  s993 :: SWord8 = s14 | s992
+  s994 :: SWord8 = s16 & s992
+  s995 :: SWord8 = if s991 then s993 else s994
+  s996 :: SWord8 = if s947 then s987 else s995
+  s997 :: SWord8 = if s820 then s975 else s996
+  s998 :: SWord8 = s1 + s954
+  s999 :: SBool = s998 < s1
+  s1000 :: SBool = s998 < s954
+  s1001 :: SBool = s999 | s1000
+  s1002 :: SWord8 = s998 >>> 1
+  s1003 :: SWord8 = s14 | s1002
+  s1004 :: SWord8 = s16 & s1002
+  s1005 :: SWord8 = if s1001 then s1003 else s1004
+  s1006 :: SWord8 = s1005 >>> 1
+  s1007 :: SWord8 = s14 | s1006
+  s1008 :: SWord8 = s16 & s1006
+  s1009 :: SWord8 = if s819 then s1007 else s1008
+  s1010 :: SWord8 = s1009 >>> 1
+  s1011 :: SWord8 = s14 | s1010
+  s1012 :: SWord8 = s16 & s1010
+  s1013 :: SWord8 = if s946 then s1011 else s1012
+  s1014 :: SWord8 = s1 + s1009
+  s1015 :: SBool = s1014 < s1
+  s1016 :: SBool = s1014 < s1009
+  s1017 :: SBool = s1015 | s1016
+  s1018 :: SWord8 = s1014 >>> 1
+  s1019 :: SWord8 = s14 | s1018
+  s1020 :: SWord8 = s16 & s1018
+  s1021 :: SWord8 = if s1017 then s1019 else s1020
+  s1022 :: SWord8 = if s947 then s1013 else s1021
+  s1023 :: SWord8 = s1 + s1005
+  s1024 :: SBool = s1023 < s1
+  s1025 :: SBool = s1023 < s1005
+  s1026 :: SBool = s1024 | s1025
+  s1027 :: SWord8 = s1023 >>> 1
+  s1028 :: SWord8 = s14 | s1027
+  s1029 :: SWord8 = s16 & s1027
+  s1030 :: SWord8 = if s1026 then s1028 else s1029
+  s1031 :: SWord8 = s1030 >>> 1
+  s1032 :: SWord8 = s14 | s1031
+  s1033 :: SWord8 = s16 & s1031
+  s1034 :: SWord8 = if s946 then s1032 else s1033
+  s1035 :: SWord8 = s1 + s1030
+  s1036 :: SBool = s1035 < s1
+  s1037 :: SBool = s1035 < s1030
+  s1038 :: SBool = s1036 | s1037
+  s1039 :: SWord8 = s1035 >>> 1
+  s1040 :: SWord8 = s14 | s1039
+  s1041 :: SWord8 = s16 & s1039
+  s1042 :: SWord8 = if s1038 then s1040 else s1041
+  s1043 :: SWord8 = if s947 then s1034 else s1042
+  s1044 :: SWord8 = if s820 then s1022 else s1043
+  s1045 :: SWord8 = if s565 then s997 else s1044
+  s1046 :: SWord8 = if s57 then s937 else s1045
+  s1047 :: SWord8 = if s41 then s810 else s1046
+  s1048 :: SWord8 = if s30 then s555 else s1047
+  s1049 :: SWord8 = s1 + s42
+  s1050 :: SWord 1 = choose [0:0] s1049
+  s1051 :: SBool = s10 /= s1050
+  s1052 :: SWord8 = if s1051 then s46 else s47
+  s1053 :: SWord 1 = choose [0:0] s1052
+  s1054 :: SBool = s10 /= s1053
+  s1055 :: SWord8 = if s1054 then s52 else s53
+  s1056 :: SWord 1 = choose [0:0] s1055
+  s1057 :: SBool = s10 /= s1056
+  s1058 :: SBool = ~ s1057
+  s1059 :: SBool = s1049 < s1
+  s1060 :: SBool = s1049 < s42
+  s1061 :: SBool = s1059 | s1060
+  s1062 :: SWord8 = s1049 >>> 1
+  s1063 :: SWord8 = s14 | s1062
+  s1064 :: SWord8 = s16 & s1062
+  s1065 :: SWord8 = if s1061 then s1063 else s1064
+  s1066 :: SWord 1 = choose [0:0] s1065
+  s1067 :: SBool = s10 /= s1066
+  s1068 :: SWord8 = s1052 >>> 1
+  s1069 :: SWord8 = s14 | s1068
+  s1070 :: SWord8 = s16 & s1068
+  s1071 :: SWord8 = if s1067 then s1069 else s1070
+  s1072 :: SWord 1 = choose [0:0] s1071
+  s1073 :: SBool = s10 /= s1072
+  s1074 :: SWord8 = s1055 >>> 1
+  s1075 :: SWord8 = s14 | s1074
+  s1076 :: SWord8 = s16 & s1074
+  s1077 :: SWord8 = if s1073 then s1075 else s1076
+  s1078 :: SWord 1 = choose [0:0] s1077
+  s1079 :: SBool = s10 /= s1078
+  s1080 :: SBool = ~ s1079
+  s1081 :: SWord8 = s1065 >>> 1
+  s1082 :: SWord8 = s14 | s1081
+  s1083 :: SWord8 = s16 & s1081
+  s1084 :: SWord8 = if s29 then s1082 else s1083
+  s1085 :: SWord 1 = choose [0:0] s1084
+  s1086 :: SBool = s10 /= s1085
+  s1087 :: SWord8 = s1071 >>> 1
+  s1088 :: SWord8 = s14 | s1087
+  s1089 :: SWord8 = s16 & s1087
+  s1090 :: SWord8 = if s1086 then s1088 else s1089
+  s1091 :: SWord 1 = choose [0:0] s1090
+  s1092 :: SBool = s10 /= s1091
+  s1093 :: SWord8 = s1077 >>> 1
+  s1094 :: SWord8 = s14 | s1093
+  s1095 :: SWord8 = s16 & s1093
+  s1096 :: SWord8 = if s1092 then s1094 else s1095
+  s1097 :: SWord 1 = choose [0:0] s1096
+  s1098 :: SBool = s10 /= s1097
+  s1099 :: SBool = ~ s1098
+  s1100 :: SWord8 = s1084 >>> 1
+  s1101 :: SWord8 = s14 | s1100
+  s1102 :: SWord8 = s16 & s1100
+  s1103 :: SWord8 = if s40 then s1101 else s1102
+  s1104 :: SWord 1 = choose [0:0] s1103
+  s1105 :: SBool = s10 /= s1104
+  s1106 :: SWord8 = s1090 >>> 1
+  s1107 :: SWord8 = s14 | s1106
+  s1108 :: SWord8 = s16 & s1106
+  s1109 :: SWord8 = if s1105 then s1107 else s1108
+  s1110 :: SWord 1 = choose [0:0] s1109
+  s1111 :: SBool = s10 /= s1110
+  s1112 :: SWord8 = s1096 >>> 1
+  s1113 :: SWord8 = s14 | s1112
+  s1114 :: SWord8 = s16 & s1112
+  s1115 :: SWord8 = if s1111 then s1113 else s1114
+  s1116 :: SWord 1 = choose [0:0] s1115
+  s1117 :: SBool = s10 /= s1116
+  s1118 :: SBool = ~ s1117
+  s1119 :: SWord8 = s1103 >>> 1
+  s1120 :: SWord8 = s14 | s1119
+  s1121 :: SWord8 = s16 & s1119
+  s1122 :: SWord8 = if s1057 then s1120 else s1121
+  s1123 :: SWord8 = s1122 >>> 1
+  s1124 :: SWord8 = s14 | s1123
+  s1125 :: SWord8 = s16 & s1123
+  s1126 :: SWord8 = if s1079 then s1124 else s1125
+  s1127 :: SWord8 = s1126 >>> 1
+  s1128 :: SWord8 = s14 | s1127
+  s1129 :: SWord8 = s16 & s1127
+  s1130 :: SWord8 = if s1098 then s1128 else s1129
+  s1131 :: SWord8 = s1130 >>> 1
+  s1132 :: SWord8 = s14 | s1131
+  s1133 :: SWord8 = s16 & s1131
+  s1134 :: SWord8 = if s1117 then s1132 else s1133
+  s1135 :: SWord8 = s1 + s1130
+  s1136 :: SBool = s1135 < s1
+  s1137 :: SBool = s1135 < s1130
+  s1138 :: SBool = s1136 | s1137
+  s1139 :: SWord8 = s1135 >>> 1
+  s1140 :: SWord8 = s14 | s1139
+  s1141 :: SWord8 = s16 & s1139
+  s1142 :: SWord8 = if s1138 then s1140 else s1141
+  s1143 :: SWord8 = if s1118 then s1134 else s1142
+  s1144 :: SWord8 = s1 + s1126
+  s1145 :: SBool = s1144 < s1
+  s1146 :: SBool = s1144 < s1126
+  s1147 :: SBool = s1145 | s1146
+  s1148 :: SWord8 = s1144 >>> 1
+  s1149 :: SWord8 = s14 | s1148
+  s1150 :: SWord8 = s16 & s1148
+  s1151 :: SWord8 = if s1147 then s1149 else s1150
+  s1152 :: SWord8 = s1151 >>> 1
+  s1153 :: SWord8 = s14 | s1152
+  s1154 :: SWord8 = s16 & s1152
+  s1155 :: SWord8 = if s1117 then s1153 else s1154
+  s1156 :: SWord8 = s1 + s1151
+  s1157 :: SBool = s1156 < s1
+  s1158 :: SBool = s1156 < s1151
+  s1159 :: SBool = s1157 | s1158
+  s1160 :: SWord8 = s1156 >>> 1
+  s1161 :: SWord8 = s14 | s1160
+  s1162 :: SWord8 = s16 & s1160
+  s1163 :: SWord8 = if s1159 then s1161 else s1162
+  s1164 :: SWord8 = if s1118 then s1155 else s1163
+  s1165 :: SWord8 = if s1099 then s1143 else s1164
+  s1166 :: SWord8 = s1 + s1122
+  s1167 :: SBool = s1166 < s1
+  s1168 :: SBool = s1166 < s1122
+  s1169 :: SBool = s1167 | s1168
+  s1170 :: SWord8 = s1166 >>> 1
+  s1171 :: SWord8 = s14 | s1170
+  s1172 :: SWord8 = s16 & s1170
+  s1173 :: SWord8 = if s1169 then s1171 else s1172
+  s1174 :: SWord8 = s1173 >>> 1
+  s1175 :: SWord8 = s14 | s1174
+  s1176 :: SWord8 = s16 & s1174
+  s1177 :: SWord8 = if s1098 then s1175 else s1176
+  s1178 :: SWord8 = s1177 >>> 1
+  s1179 :: SWord8 = s14 | s1178
+  s1180 :: SWord8 = s16 & s1178
+  s1181 :: SWord8 = if s1117 then s1179 else s1180
+  s1182 :: SWord8 = s1 + s1177
+  s1183 :: SBool = s1182 < s1
+  s1184 :: SBool = s1182 < s1177
+  s1185 :: SBool = s1183 | s1184
+  s1186 :: SWord8 = s1182 >>> 1
+  s1187 :: SWord8 = s14 | s1186
+  s1188 :: SWord8 = s16 & s1186
+  s1189 :: SWord8 = if s1185 then s1187 else s1188
+  s1190 :: SWord8 = if s1118 then s1181 else s1189
+  s1191 :: SWord8 = s1 + s1173
+  s1192 :: SBool = s1191 < s1
+  s1193 :: SBool = s1191 < s1173
+  s1194 :: SBool = s1192 | s1193
+  s1195 :: SWord8 = s1191 >>> 1
+  s1196 :: SWord8 = s14 | s1195
+  s1197 :: SWord8 = s16 & s1195
+  s1198 :: SWord8 = if s1194 then s1196 else s1197
+  s1199 :: SWord8 = s1198 >>> 1
+  s1200 :: SWord8 = s14 | s1199
+  s1201 :: SWord8 = s16 & s1199
+  s1202 :: SWord8 = if s1117 then s1200 else s1201
+  s1203 :: SWord8 = s1 + s1198
+  s1204 :: SBool = s1203 < s1
+  s1205 :: SBool = s1203 < s1198
+  s1206 :: SBool = s1204 | s1205
+  s1207 :: SWord8 = s1203 >>> 1
+  s1208 :: SWord8 = s14 | s1207
+  s1209 :: SWord8 = s16 & s1207
+  s1210 :: SWord8 = if s1206 then s1208 else s1209
+  s1211 :: SWord8 = if s1118 then s1202 else s1210
+  s1212 :: SWord8 = if s1099 then s1190 else s1211
+  s1213 :: SWord8 = if s1080 then s1165 else s1212
+  s1214 :: SWord8 = s1 + s1103
+  s1215 :: SWord 1 = choose [0:0] s1214
+  s1216 :: SBool = s10 /= s1215
+  s1217 :: SWord8 = if s1216 then s1107 else s1108
+  s1218 :: SWord 1 = choose [0:0] s1217
+  s1219 :: SBool = s10 /= s1218
+  s1220 :: SWord8 = if s1219 then s1113 else s1114
+  s1221 :: SWord 1 = choose [0:0] s1220
+  s1222 :: SBool = s10 /= s1221
+  s1223 :: SBool = ~ s1222
+  s1224 :: SBool = s1214 < s1
+  s1225 :: SBool = s1214 < s1103
+  s1226 :: SBool = s1224 | s1225
+  s1227 :: SWord8 = s1214 >>> 1
+  s1228 :: SWord8 = s14 | s1227
+  s1229 :: SWord8 = s16 & s1227
+  s1230 :: SWord8 = if s1226 then s1228 else s1229
+  s1231 :: SWord8 = s1230 >>> 1
+  s1232 :: SWord8 = s14 | s1231
+  s1233 :: SWord8 = s16 & s1231
+  s1234 :: SWord8 = if s1079 then s1232 else s1233
+  s1235 :: SWord8 = s1234 >>> 1
+  s1236 :: SWord8 = s14 | s1235
+  s1237 :: SWord8 = s16 & s1235
+  s1238 :: SWord8 = if s1098 then s1236 else s1237
+  s1239 :: SWord8 = s1238 >>> 1
+  s1240 :: SWord8 = s14 | s1239
+  s1241 :: SWord8 = s16 & s1239
+  s1242 :: SWord8 = if s1222 then s1240 else s1241
+  s1243 :: SWord8 = s1 + s1238
+  s1244 :: SBool = s1243 < s1
+  s1245 :: SBool = s1243 < s1238
+  s1246 :: SBool = s1244 | s1245
+  s1247 :: SWord8 = s1243 >>> 1
+  s1248 :: SWord8 = s14 | s1247
+  s1249 :: SWord8 = s16 & s1247
+  s1250 :: SWord8 = if s1246 then s1248 else s1249
+  s1251 :: SWord8 = if s1223 then s1242 else s1250
+  s1252 :: SWord8 = s1 + s1234
+  s1253 :: SBool = s1252 < s1
+  s1254 :: SBool = s1252 < s1234
+  s1255 :: SBool = s1253 | s1254
+  s1256 :: SWord8 = s1252 >>> 1
+  s1257 :: SWord8 = s14 | s1256
+  s1258 :: SWord8 = s16 & s1256
+  s1259 :: SWord8 = if s1255 then s1257 else s1258
+  s1260 :: SWord8 = s1259 >>> 1
+  s1261 :: SWord8 = s14 | s1260
+  s1262 :: SWord8 = s16 & s1260
+  s1263 :: SWord8 = if s1222 then s1261 else s1262
+  s1264 :: SWord8 = s1 + s1259
+  s1265 :: SBool = s1264 < s1
+  s1266 :: SBool = s1264 < s1259
+  s1267 :: SBool = s1265 | s1266
+  s1268 :: SWord8 = s1264 >>> 1
+  s1269 :: SWord8 = s14 | s1268
+  s1270 :: SWord8 = s16 & s1268
+  s1271 :: SWord8 = if s1267 then s1269 else s1270
+  s1272 :: SWord8 = if s1223 then s1263 else s1271
+  s1273 :: SWord8 = if s1099 then s1251 else s1272
+  s1274 :: SWord8 = s1 + s1230
+  s1275 :: SBool = s1274 < s1
+  s1276 :: SBool = s1274 < s1230
+  s1277 :: SBool = s1275 | s1276
+  s1278 :: SWord8 = s1274 >>> 1
+  s1279 :: SWord8 = s14 | s1278
+  s1280 :: SWord8 = s16 & s1278
+  s1281 :: SWord8 = if s1277 then s1279 else s1280
+  s1282 :: SWord8 = s1281 >>> 1
+  s1283 :: SWord8 = s14 | s1282
+  s1284 :: SWord8 = s16 & s1282
+  s1285 :: SWord8 = if s1098 then s1283 else s1284
+  s1286 :: SWord8 = s1285 >>> 1
+  s1287 :: SWord8 = s14 | s1286
+  s1288 :: SWord8 = s16 & s1286
+  s1289 :: SWord8 = if s1222 then s1287 else s1288
+  s1290 :: SWord8 = s1 + s1285
+  s1291 :: SBool = s1290 < s1
+  s1292 :: SBool = s1290 < s1285
+  s1293 :: SBool = s1291 | s1292
+  s1294 :: SWord8 = s1290 >>> 1
+  s1295 :: SWord8 = s14 | s1294
+  s1296 :: SWord8 = s16 & s1294
+  s1297 :: SWord8 = if s1293 then s1295 else s1296
+  s1298 :: SWord8 = if s1223 then s1289 else s1297
+  s1299 :: SWord8 = s1 + s1281
+  s1300 :: SBool = s1299 < s1
+  s1301 :: SBool = s1299 < s1281
+  s1302 :: SBool = s1300 | s1301
+  s1303 :: SWord8 = s1299 >>> 1
+  s1304 :: SWord8 = s14 | s1303
+  s1305 :: SWord8 = s16 & s1303
+  s1306 :: SWord8 = if s1302 then s1304 else s1305
+  s1307 :: SWord8 = s1306 >>> 1
+  s1308 :: SWord8 = s14 | s1307
+  s1309 :: SWord8 = s16 & s1307
+  s1310 :: SWord8 = if s1222 then s1308 else s1309
+  s1311 :: SWord8 = s1 + s1306
+  s1312 :: SBool = s1311 < s1
+  s1313 :: SBool = s1311 < s1306
+  s1314 :: SBool = s1312 | s1313
+  s1315 :: SWord8 = s1311 >>> 1
+  s1316 :: SWord8 = s14 | s1315
+  s1317 :: SWord8 = s16 & s1315
+  s1318 :: SWord8 = if s1314 then s1316 else s1317
+  s1319 :: SWord8 = if s1223 then s1310 else s1318
+  s1320 :: SWord8 = if s1099 then s1298 else s1319
+  s1321 :: SWord8 = if s1080 then s1273 else s1320
+  s1322 :: SWord8 = if s1058 then s1213 else s1321
+  s1323 :: SWord8 = s1 + s1084
+  s1324 :: SWord 1 = choose [0:0] s1323
+  s1325 :: SBool = s10 /= s1324
+  s1326 :: SWord8 = if s1325 then s1088 else s1089
+  s1327 :: SWord 1 = choose [0:0] s1326
+  s1328 :: SBool = s10 /= s1327
+  s1329 :: SWord8 = if s1328 then s1094 else s1095
+  s1330 :: SWord 1 = choose [0:0] s1329
+  s1331 :: SBool = s10 /= s1330
+  s1332 :: SBool = ~ s1331
+  s1333 :: SBool = s1323 < s1
+  s1334 :: SBool = s1323 < s1084
+  s1335 :: SBool = s1333 | s1334
+  s1336 :: SWord8 = s1323 >>> 1
+  s1337 :: SWord8 = s14 | s1336
+  s1338 :: SWord8 = s16 & s1336
+  s1339 :: SWord8 = if s1335 then s1337 else s1338
+  s1340 :: SWord 1 = choose [0:0] s1339
+  s1341 :: SBool = s10 /= s1340
+  s1342 :: SWord8 = s1326 >>> 1
+  s1343 :: SWord8 = s14 | s1342
+  s1344 :: SWord8 = s16 & s1342
+  s1345 :: SWord8 = if s1341 then s1343 else s1344
+  s1346 :: SWord 1 = choose [0:0] s1345
+  s1347 :: SBool = s10 /= s1346
+  s1348 :: SWord8 = s1329 >>> 1
+  s1349 :: SWord8 = s14 | s1348
+  s1350 :: SWord8 = s16 & s1348
+  s1351 :: SWord8 = if s1347 then s1349 else s1350
+  s1352 :: SWord 1 = choose [0:0] s1351
+  s1353 :: SBool = s10 /= s1352
+  s1354 :: SBool = ~ s1353
+  s1355 :: SWord8 = s1339 >>> 1
+  s1356 :: SWord8 = s14 | s1355
+  s1357 :: SWord8 = s16 & s1355
+  s1358 :: SWord8 = if s1057 then s1356 else s1357
+  s1359 :: SWord8 = s1358 >>> 1
+  s1360 :: SWord8 = s14 | s1359
+  s1361 :: SWord8 = s16 & s1359
+  s1362 :: SWord8 = if s1079 then s1360 else s1361
+  s1363 :: SWord8 = s1362 >>> 1
+  s1364 :: SWord8 = s14 | s1363
+  s1365 :: SWord8 = s16 & s1363
+  s1366 :: SWord8 = if s1331 then s1364 else s1365
+  s1367 :: SWord8 = s1366 >>> 1
+  s1368 :: SWord8 = s14 | s1367
+  s1369 :: SWord8 = s16 & s1367
+  s1370 :: SWord8 = if s1353 then s1368 else s1369
+  s1371 :: SWord8 = s1 + s1366
+  s1372 :: SBool = s1371 < s1
+  s1373 :: SBool = s1371 < s1366
+  s1374 :: SBool = s1372 | s1373
+  s1375 :: SWord8 = s1371 >>> 1
+  s1376 :: SWord8 = s14 | s1375
+  s1377 :: SWord8 = s16 & s1375
+  s1378 :: SWord8 = if s1374 then s1376 else s1377
+  s1379 :: SWord8 = if s1354 then s1370 else s1378
+  s1380 :: SWord8 = s1 + s1362
+  s1381 :: SBool = s1380 < s1
+  s1382 :: SBool = s1380 < s1362
+  s1383 :: SBool = s1381 | s1382
+  s1384 :: SWord8 = s1380 >>> 1
+  s1385 :: SWord8 = s14 | s1384
+  s1386 :: SWord8 = s16 & s1384
+  s1387 :: SWord8 = if s1383 then s1385 else s1386
+  s1388 :: SWord8 = s1387 >>> 1
+  s1389 :: SWord8 = s14 | s1388
+  s1390 :: SWord8 = s16 & s1388
+  s1391 :: SWord8 = if s1353 then s1389 else s1390
+  s1392 :: SWord8 = s1 + s1387
+  s1393 :: SBool = s1392 < s1
+  s1394 :: SBool = s1392 < s1387
+  s1395 :: SBool = s1393 | s1394
+  s1396 :: SWord8 = s1392 >>> 1
+  s1397 :: SWord8 = s14 | s1396
+  s1398 :: SWord8 = s16 & s1396
+  s1399 :: SWord8 = if s1395 then s1397 else s1398
+  s1400 :: SWord8 = if s1354 then s1391 else s1399
+  s1401 :: SWord8 = if s1332 then s1379 else s1400
+  s1402 :: SWord8 = s1 + s1358
+  s1403 :: SBool = s1402 < s1
+  s1404 :: SBool = s1402 < s1358
+  s1405 :: SBool = s1403 | s1404
+  s1406 :: SWord8 = s1402 >>> 1
+  s1407 :: SWord8 = s14 | s1406
+  s1408 :: SWord8 = s16 & s1406
+  s1409 :: SWord8 = if s1405 then s1407 else s1408
+  s1410 :: SWord8 = s1409 >>> 1
+  s1411 :: SWord8 = s14 | s1410
+  s1412 :: SWord8 = s16 & s1410
+  s1413 :: SWord8 = if s1331 then s1411 else s1412
+  s1414 :: SWord8 = s1413 >>> 1
+  s1415 :: SWord8 = s14 | s1414
+  s1416 :: SWord8 = s16 & s1414
+  s1417 :: SWord8 = if s1353 then s1415 else s1416
+  s1418 :: SWord8 = s1 + s1413
+  s1419 :: SBool = s1418 < s1
+  s1420 :: SBool = s1418 < s1413
+  s1421 :: SBool = s1419 | s1420
+  s1422 :: SWord8 = s1418 >>> 1
+  s1423 :: SWord8 = s14 | s1422
+  s1424 :: SWord8 = s16 & s1422
+  s1425 :: SWord8 = if s1421 then s1423 else s1424
+  s1426 :: SWord8 = if s1354 then s1417 else s1425
+  s1427 :: SWord8 = s1 + s1409
+  s1428 :: SBool = s1427 < s1
+  s1429 :: SBool = s1427 < s1409
+  s1430 :: SBool = s1428 | s1429
+  s1431 :: SWord8 = s1427 >>> 1
+  s1432 :: SWord8 = s14 | s1431
+  s1433 :: SWord8 = s16 & s1431
+  s1434 :: SWord8 = if s1430 then s1432 else s1433
+  s1435 :: SWord8 = s1434 >>> 1
+  s1436 :: SWord8 = s14 | s1435
+  s1437 :: SWord8 = s16 & s1435
+  s1438 :: SWord8 = if s1353 then s1436 else s1437
+  s1439 :: SWord8 = s1 + s1434
+  s1440 :: SBool = s1439 < s1
+  s1441 :: SBool = s1439 < s1434
+  s1442 :: SBool = s1440 | s1441
+  s1443 :: SWord8 = s1439 >>> 1
+  s1444 :: SWord8 = s14 | s1443
+  s1445 :: SWord8 = s16 & s1443
+  s1446 :: SWord8 = if s1442 then s1444 else s1445
+  s1447 :: SWord8 = if s1354 then s1438 else s1446
+  s1448 :: SWord8 = if s1332 then s1426 else s1447
+  s1449 :: SWord8 = if s1080 then s1401 else s1448
+  s1450 :: SWord8 = s1 + s1339
+  s1451 :: SWord 1 = choose [0:0] s1450
+  s1452 :: SBool = s10 /= s1451
+  s1453 :: SWord8 = if s1452 then s1343 else s1344
+  s1454 :: SWord 1 = choose [0:0] s1453
+  s1455 :: SBool = s10 /= s1454
+  s1456 :: SWord8 = if s1455 then s1349 else s1350
+  s1457 :: SWord 1 = choose [0:0] s1456
+  s1458 :: SBool = s10 /= s1457
+  s1459 :: SBool = ~ s1458
+  s1460 :: SBool = s1450 < s1
+  s1461 :: SBool = s1450 < s1339
+  s1462 :: SBool = s1460 | s1461
+  s1463 :: SWord8 = s1450 >>> 1
+  s1464 :: SWord8 = s14 | s1463
+  s1465 :: SWord8 = s16 & s1463
+  s1466 :: SWord8 = if s1462 then s1464 else s1465
+  s1467 :: SWord8 = s1466 >>> 1
+  s1468 :: SWord8 = s14 | s1467
+  s1469 :: SWord8 = s16 & s1467
+  s1470 :: SWord8 = if s1079 then s1468 else s1469
+  s1471 :: SWord8 = s1470 >>> 1
+  s1472 :: SWord8 = s14 | s1471
+  s1473 :: SWord8 = s16 & s1471
+  s1474 :: SWord8 = if s1331 then s1472 else s1473
+  s1475 :: SWord8 = s1474 >>> 1
+  s1476 :: SWord8 = s14 | s1475
+  s1477 :: SWord8 = s16 & s1475
+  s1478 :: SWord8 = if s1458 then s1476 else s1477
+  s1479 :: SWord8 = s1 + s1474
+  s1480 :: SBool = s1479 < s1
+  s1481 :: SBool = s1479 < s1474
+  s1482 :: SBool = s1480 | s1481
+  s1483 :: SWord8 = s1479 >>> 1
+  s1484 :: SWord8 = s14 | s1483
+  s1485 :: SWord8 = s16 & s1483
+  s1486 :: SWord8 = if s1482 then s1484 else s1485
+  s1487 :: SWord8 = if s1459 then s1478 else s1486
+  s1488 :: SWord8 = s1 + s1470
+  s1489 :: SBool = s1488 < s1
+  s1490 :: SBool = s1488 < s1470
+  s1491 :: SBool = s1489 | s1490
+  s1492 :: SWord8 = s1488 >>> 1
+  s1493 :: SWord8 = s14 | s1492
+  s1494 :: SWord8 = s16 & s1492
+  s1495 :: SWord8 = if s1491 then s1493 else s1494
+  s1496 :: SWord8 = s1495 >>> 1
+  s1497 :: SWord8 = s14 | s1496
+  s1498 :: SWord8 = s16 & s1496
+  s1499 :: SWord8 = if s1458 then s1497 else s1498
+  s1500 :: SWord8 = s1 + s1495
+  s1501 :: SBool = s1500 < s1
+  s1502 :: SBool = s1500 < s1495
+  s1503 :: SBool = s1501 | s1502
+  s1504 :: SWord8 = s1500 >>> 1
+  s1505 :: SWord8 = s14 | s1504
+  s1506 :: SWord8 = s16 & s1504
+  s1507 :: SWord8 = if s1503 then s1505 else s1506
+  s1508 :: SWord8 = if s1459 then s1499 else s1507
+  s1509 :: SWord8 = if s1332 then s1487 else s1508
+  s1510 :: SWord8 = s1 + s1466
+  s1511 :: SBool = s1510 < s1
+  s1512 :: SBool = s1510 < s1466
+  s1513 :: SBool = s1511 | s1512
+  s1514 :: SWord8 = s1510 >>> 1
+  s1515 :: SWord8 = s14 | s1514
+  s1516 :: SWord8 = s16 & s1514
+  s1517 :: SWord8 = if s1513 then s1515 else s1516
+  s1518 :: SWord8 = s1517 >>> 1
+  s1519 :: SWord8 = s14 | s1518
+  s1520 :: SWord8 = s16 & s1518
+  s1521 :: SWord8 = if s1331 then s1519 else s1520
+  s1522 :: SWord8 = s1521 >>> 1
+  s1523 :: SWord8 = s14 | s1522
+  s1524 :: SWord8 = s16 & s1522
+  s1525 :: SWord8 = if s1458 then s1523 else s1524
+  s1526 :: SWord8 = s1 + s1521
+  s1527 :: SBool = s1526 < s1
+  s1528 :: SBool = s1526 < s1521
+  s1529 :: SBool = s1527 | s1528
+  s1530 :: SWord8 = s1526 >>> 1
+  s1531 :: SWord8 = s14 | s1530
+  s1532 :: SWord8 = s16 & s1530
+  s1533 :: SWord8 = if s1529 then s1531 else s1532
+  s1534 :: SWord8 = if s1459 then s1525 else s1533
+  s1535 :: SWord8 = s1 + s1517
+  s1536 :: SBool = s1535 < s1
+  s1537 :: SBool = s1535 < s1517
+  s1538 :: SBool = s1536 | s1537
+  s1539 :: SWord8 = s1535 >>> 1
+  s1540 :: SWord8 = s14 | s1539
+  s1541 :: SWord8 = s16 & s1539
+  s1542 :: SWord8 = if s1538 then s1540 else s1541
+  s1543 :: SWord8 = s1542 >>> 1
+  s1544 :: SWord8 = s14 | s1543
+  s1545 :: SWord8 = s16 & s1543
+  s1546 :: SWord8 = if s1458 then s1544 else s1545
+  s1547 :: SWord8 = s1 + s1542
+  s1548 :: SBool = s1547 < s1
+  s1549 :: SBool = s1547 < s1542
+  s1550 :: SBool = s1548 | s1549
+  s1551 :: SWord8 = s1547 >>> 1
+  s1552 :: SWord8 = s14 | s1551
+  s1553 :: SWord8 = s16 & s1551
+  s1554 :: SWord8 = if s1550 then s1552 else s1553
+  s1555 :: SWord8 = if s1459 then s1546 else s1554
+  s1556 :: SWord8 = if s1332 then s1534 else s1555
+  s1557 :: SWord8 = if s1080 then s1509 else s1556
+  s1558 :: SWord8 = if s1058 then s1449 else s1557
+  s1559 :: SWord8 = if s41 then s1322 else s1558
+  s1560 :: SWord8 = s1 + s1065
+  s1561 :: SWord 1 = choose [0:0] s1560
+  s1562 :: SBool = s10 /= s1561
+  s1563 :: SWord8 = if s1562 then s1069 else s1070
+  s1564 :: SWord 1 = choose [0:0] s1563
+  s1565 :: SBool = s10 /= s1564
+  s1566 :: SWord8 = if s1565 then s1075 else s1076
+  s1567 :: SWord 1 = choose [0:0] s1566
+  s1568 :: SBool = s10 /= s1567
+  s1569 :: SBool = ~ s1568
+  s1570 :: SBool = s1560 < s1
+  s1571 :: SBool = s1560 < s1065
+  s1572 :: SBool = s1570 | s1571
+  s1573 :: SWord8 = s1560 >>> 1
+  s1574 :: SWord8 = s14 | s1573
+  s1575 :: SWord8 = s16 & s1573
+  s1576 :: SWord8 = if s1572 then s1574 else s1575
+  s1577 :: SWord 1 = choose [0:0] s1576
+  s1578 :: SBool = s10 /= s1577
+  s1579 :: SWord8 = s1563 >>> 1
+  s1580 :: SWord8 = s14 | s1579
+  s1581 :: SWord8 = s16 & s1579
+  s1582 :: SWord8 = if s1578 then s1580 else s1581
+  s1583 :: SWord 1 = choose [0:0] s1582
+  s1584 :: SBool = s10 /= s1583
+  s1585 :: SWord8 = s1566 >>> 1
+  s1586 :: SWord8 = s14 | s1585
+  s1587 :: SWord8 = s16 & s1585
+  s1588 :: SWord8 = if s1584 then s1586 else s1587
+  s1589 :: SWord 1 = choose [0:0] s1588
+  s1590 :: SBool = s10 /= s1589
+  s1591 :: SBool = ~ s1590
+  s1592 :: SWord8 = s1576 >>> 1
+  s1593 :: SWord8 = s14 | s1592
+  s1594 :: SWord8 = s16 & s1592
+  s1595 :: SWord8 = if s40 then s1593 else s1594
+  s1596 :: SWord 1 = choose [0:0] s1595
+  s1597 :: SBool = s10 /= s1596
+  s1598 :: SWord8 = s1582 >>> 1
+  s1599 :: SWord8 = s14 | s1598
+  s1600 :: SWord8 = s16 & s1598
+  s1601 :: SWord8 = if s1597 then s1599 else s1600
+  s1602 :: SWord 1 = choose [0:0] s1601
+  s1603 :: SBool = s10 /= s1602
+  s1604 :: SWord8 = s1588 >>> 1
+  s1605 :: SWord8 = s14 | s1604
+  s1606 :: SWord8 = s16 & s1604
+  s1607 :: SWord8 = if s1603 then s1605 else s1606
+  s1608 :: SWord 1 = choose [0:0] s1607
+  s1609 :: SBool = s10 /= s1608
+  s1610 :: SBool = ~ s1609
+  s1611 :: SWord8 = s1595 >>> 1
+  s1612 :: SWord8 = s14 | s1611
+  s1613 :: SWord8 = s16 & s1611
+  s1614 :: SWord8 = if s1057 then s1612 else s1613
+  s1615 :: SWord8 = s1614 >>> 1
+  s1616 :: SWord8 = s14 | s1615
+  s1617 :: SWord8 = s16 & s1615
+  s1618 :: SWord8 = if s1568 then s1616 else s1617
+  s1619 :: SWord8 = s1618 >>> 1
+  s1620 :: SWord8 = s14 | s1619
+  s1621 :: SWord8 = s16 & s1619
+  s1622 :: SWord8 = if s1590 then s1620 else s1621
+  s1623 :: SWord8 = s1622 >>> 1
+  s1624 :: SWord8 = s14 | s1623
+  s1625 :: SWord8 = s16 & s1623
+  s1626 :: SWord8 = if s1609 then s1624 else s1625
+  s1627 :: SWord8 = s1 + s1622
+  s1628 :: SBool = s1627 < s1
+  s1629 :: SBool = s1627 < s1622
+  s1630 :: SBool = s1628 | s1629
+  s1631 :: SWord8 = s1627 >>> 1
+  s1632 :: SWord8 = s14 | s1631
+  s1633 :: SWord8 = s16 & s1631
+  s1634 :: SWord8 = if s1630 then s1632 else s1633
+  s1635 :: SWord8 = if s1610 then s1626 else s1634
+  s1636 :: SWord8 = s1 + s1618
+  s1637 :: SBool = s1636 < s1
+  s1638 :: SBool = s1636 < s1618
+  s1639 :: SBool = s1637 | s1638
+  s1640 :: SWord8 = s1636 >>> 1
+  s1641 :: SWord8 = s14 | s1640
+  s1642 :: SWord8 = s16 & s1640
+  s1643 :: SWord8 = if s1639 then s1641 else s1642
+  s1644 :: SWord8 = s1643 >>> 1
+  s1645 :: SWord8 = s14 | s1644
+  s1646 :: SWord8 = s16 & s1644
+  s1647 :: SWord8 = if s1609 then s1645 else s1646
+  s1648 :: SWord8 = s1 + s1643
+  s1649 :: SBool = s1648 < s1
+  s1650 :: SBool = s1648 < s1643
+  s1651 :: SBool = s1649 | s1650
+  s1652 :: SWord8 = s1648 >>> 1
+  s1653 :: SWord8 = s14 | s1652
+  s1654 :: SWord8 = s16 & s1652
+  s1655 :: SWord8 = if s1651 then s1653 else s1654
+  s1656 :: SWord8 = if s1610 then s1647 else s1655
+  s1657 :: SWord8 = if s1591 then s1635 else s1656
+  s1658 :: SWord8 = s1 + s1614
+  s1659 :: SBool = s1658 < s1
+  s1660 :: SBool = s1658 < s1614
+  s1661 :: SBool = s1659 | s1660
+  s1662 :: SWord8 = s1658 >>> 1
+  s1663 :: SWord8 = s14 | s1662
+  s1664 :: SWord8 = s16 & s1662
+  s1665 :: SWord8 = if s1661 then s1663 else s1664
+  s1666 :: SWord8 = s1665 >>> 1
+  s1667 :: SWord8 = s14 | s1666
+  s1668 :: SWord8 = s16 & s1666
+  s1669 :: SWord8 = if s1590 then s1667 else s1668
+  s1670 :: SWord8 = s1669 >>> 1
+  s1671 :: SWord8 = s14 | s1670
+  s1672 :: SWord8 = s16 & s1670
+  s1673 :: SWord8 = if s1609 then s1671 else s1672
+  s1674 :: SWord8 = s1 + s1669
+  s1675 :: SBool = s1674 < s1
+  s1676 :: SBool = s1674 < s1669
+  s1677 :: SBool = s1675 | s1676
+  s1678 :: SWord8 = s1674 >>> 1
+  s1679 :: SWord8 = s14 | s1678
+  s1680 :: SWord8 = s16 & s1678
+  s1681 :: SWord8 = if s1677 then s1679 else s1680
+  s1682 :: SWord8 = if s1610 then s1673 else s1681
+  s1683 :: SWord8 = s1 + s1665
+  s1684 :: SBool = s1683 < s1
+  s1685 :: SBool = s1683 < s1665
+  s1686 :: SBool = s1684 | s1685
+  s1687 :: SWord8 = s1683 >>> 1
+  s1688 :: SWord8 = s14 | s1687
+  s1689 :: SWord8 = s16 & s1687
+  s1690 :: SWord8 = if s1686 then s1688 else s1689
+  s1691 :: SWord8 = s1690 >>> 1
+  s1692 :: SWord8 = s14 | s1691
+  s1693 :: SWord8 = s16 & s1691
+  s1694 :: SWord8 = if s1609 then s1692 else s1693
+  s1695 :: SWord8 = s1 + s1690
+  s1696 :: SBool = s1695 < s1
+  s1697 :: SBool = s1695 < s1690
+  s1698 :: SBool = s1696 | s1697
+  s1699 :: SWord8 = s1695 >>> 1
+  s1700 :: SWord8 = s14 | s1699
+  s1701 :: SWord8 = s16 & s1699
+  s1702 :: SWord8 = if s1698 then s1700 else s1701
+  s1703 :: SWord8 = if s1610 then s1694 else s1702
+  s1704 :: SWord8 = if s1591 then s1682 else s1703
+  s1705 :: SWord8 = if s1569 then s1657 else s1704
+  s1706 :: SWord8 = s1 + s1595
+  s1707 :: SWord 1 = choose [0:0] s1706
+  s1708 :: SBool = s10 /= s1707
+  s1709 :: SWord8 = if s1708 then s1599 else s1600
+  s1710 :: SWord 1 = choose [0:0] s1709
+  s1711 :: SBool = s10 /= s1710
+  s1712 :: SWord8 = if s1711 then s1605 else s1606
+  s1713 :: SWord 1 = choose [0:0] s1712
+  s1714 :: SBool = s10 /= s1713
+  s1715 :: SBool = ~ s1714
+  s1716 :: SBool = s1706 < s1
+  s1717 :: SBool = s1706 < s1595
+  s1718 :: SBool = s1716 | s1717
+  s1719 :: SWord8 = s1706 >>> 1
+  s1720 :: SWord8 = s14 | s1719
+  s1721 :: SWord8 = s16 & s1719
+  s1722 :: SWord8 = if s1718 then s1720 else s1721
+  s1723 :: SWord8 = s1722 >>> 1
+  s1724 :: SWord8 = s14 | s1723
+  s1725 :: SWord8 = s16 & s1723
+  s1726 :: SWord8 = if s1568 then s1724 else s1725
+  s1727 :: SWord8 = s1726 >>> 1
+  s1728 :: SWord8 = s14 | s1727
+  s1729 :: SWord8 = s16 & s1727
+  s1730 :: SWord8 = if s1590 then s1728 else s1729
+  s1731 :: SWord8 = s1730 >>> 1
+  s1732 :: SWord8 = s14 | s1731
+  s1733 :: SWord8 = s16 & s1731
+  s1734 :: SWord8 = if s1714 then s1732 else s1733
+  s1735 :: SWord8 = s1 + s1730
+  s1736 :: SBool = s1735 < s1
+  s1737 :: SBool = s1735 < s1730
+  s1738 :: SBool = s1736 | s1737
+  s1739 :: SWord8 = s1735 >>> 1
+  s1740 :: SWord8 = s14 | s1739
+  s1741 :: SWord8 = s16 & s1739
+  s1742 :: SWord8 = if s1738 then s1740 else s1741
+  s1743 :: SWord8 = if s1715 then s1734 else s1742
+  s1744 :: SWord8 = s1 + s1726
+  s1745 :: SBool = s1744 < s1
+  s1746 :: SBool = s1744 < s1726
+  s1747 :: SBool = s1745 | s1746
+  s1748 :: SWord8 = s1744 >>> 1
+  s1749 :: SWord8 = s14 | s1748
+  s1750 :: SWord8 = s16 & s1748
+  s1751 :: SWord8 = if s1747 then s1749 else s1750
+  s1752 :: SWord8 = s1751 >>> 1
+  s1753 :: SWord8 = s14 | s1752
+  s1754 :: SWord8 = s16 & s1752
+  s1755 :: SWord8 = if s1714 then s1753 else s1754
+  s1756 :: SWord8 = s1 + s1751
+  s1757 :: SBool = s1756 < s1
+  s1758 :: SBool = s1756 < s1751
+  s1759 :: SBool = s1757 | s1758
+  s1760 :: SWord8 = s1756 >>> 1
+  s1761 :: SWord8 = s14 | s1760
+  s1762 :: SWord8 = s16 & s1760
+  s1763 :: SWord8 = if s1759 then s1761 else s1762
+  s1764 :: SWord8 = if s1715 then s1755 else s1763
+  s1765 :: SWord8 = if s1591 then s1743 else s1764
+  s1766 :: SWord8 = s1 + s1722
+  s1767 :: SBool = s1766 < s1
+  s1768 :: SBool = s1766 < s1722
+  s1769 :: SBool = s1767 | s1768
+  s1770 :: SWord8 = s1766 >>> 1
+  s1771 :: SWord8 = s14 | s1770
+  s1772 :: SWord8 = s16 & s1770
+  s1773 :: SWord8 = if s1769 then s1771 else s1772
+  s1774 :: SWord8 = s1773 >>> 1
+  s1775 :: SWord8 = s14 | s1774
+  s1776 :: SWord8 = s16 & s1774
+  s1777 :: SWord8 = if s1590 then s1775 else s1776
+  s1778 :: SWord8 = s1777 >>> 1
+  s1779 :: SWord8 = s14 | s1778
+  s1780 :: SWord8 = s16 & s1778
+  s1781 :: SWord8 = if s1714 then s1779 else s1780
+  s1782 :: SWord8 = s1 + s1777
+  s1783 :: SBool = s1782 < s1
+  s1784 :: SBool = s1782 < s1777
+  s1785 :: SBool = s1783 | s1784
+  s1786 :: SWord8 = s1782 >>> 1
+  s1787 :: SWord8 = s14 | s1786
+  s1788 :: SWord8 = s16 & s1786
+  s1789 :: SWord8 = if s1785 then s1787 else s1788
+  s1790 :: SWord8 = if s1715 then s1781 else s1789
+  s1791 :: SWord8 = s1 + s1773
+  s1792 :: SBool = s1791 < s1
+  s1793 :: SBool = s1791 < s1773
+  s1794 :: SBool = s1792 | s1793
+  s1795 :: SWord8 = s1791 >>> 1
+  s1796 :: SWord8 = s14 | s1795
+  s1797 :: SWord8 = s16 & s1795
+  s1798 :: SWord8 = if s1794 then s1796 else s1797
+  s1799 :: SWord8 = s1798 >>> 1
+  s1800 :: SWord8 = s14 | s1799
+  s1801 :: SWord8 = s16 & s1799
+  s1802 :: SWord8 = if s1714 then s1800 else s1801
+  s1803 :: SWord8 = s1 + s1798
+  s1804 :: SBool = s1803 < s1
+  s1805 :: SBool = s1803 < s1798
+  s1806 :: SBool = s1804 | s1805
+  s1807 :: SWord8 = s1803 >>> 1
+  s1808 :: SWord8 = s14 | s1807
+  s1809 :: SWord8 = s16 & s1807
+  s1810 :: SWord8 = if s1806 then s1808 else s1809
+  s1811 :: SWord8 = if s1715 then s1802 else s1810
+  s1812 :: SWord8 = if s1591 then s1790 else s1811
+  s1813 :: SWord8 = if s1569 then s1765 else s1812
+  s1814 :: SWord8 = if s1058 then s1705 else s1813
+  s1815 :: SWord8 = s1 + s1576
+  s1816 :: SWord 1 = choose [0:0] s1815
+  s1817 :: SBool = s10 /= s1816
+  s1818 :: SWord8 = if s1817 then s1580 else s1581
+  s1819 :: SWord 1 = choose [0:0] s1818
+  s1820 :: SBool = s10 /= s1819
+  s1821 :: SWord8 = if s1820 then s1586 else s1587
+  s1822 :: SWord 1 = choose [0:0] s1821
+  s1823 :: SBool = s10 /= s1822
+  s1824 :: SBool = ~ s1823
+  s1825 :: SBool = s1815 < s1
+  s1826 :: SBool = s1815 < s1576
+  s1827 :: SBool = s1825 | s1826
+  s1828 :: SWord8 = s1815 >>> 1
+  s1829 :: SWord8 = s14 | s1828
+  s1830 :: SWord8 = s16 & s1828
+  s1831 :: SWord8 = if s1827 then s1829 else s1830
+  s1832 :: SWord 1 = choose [0:0] s1831
+  s1833 :: SBool = s10 /= s1832
+  s1834 :: SWord8 = s1818 >>> 1
+  s1835 :: SWord8 = s14 | s1834
+  s1836 :: SWord8 = s16 & s1834
+  s1837 :: SWord8 = if s1833 then s1835 else s1836
+  s1838 :: SWord 1 = choose [0:0] s1837
+  s1839 :: SBool = s10 /= s1838
+  s1840 :: SWord8 = s1821 >>> 1
+  s1841 :: SWord8 = s14 | s1840
+  s1842 :: SWord8 = s16 & s1840
+  s1843 :: SWord8 = if s1839 then s1841 else s1842
+  s1844 :: SWord 1 = choose [0:0] s1843
+  s1845 :: SBool = s10 /= s1844
+  s1846 :: SBool = ~ s1845
+  s1847 :: SWord8 = s1831 >>> 1
+  s1848 :: SWord8 = s14 | s1847
+  s1849 :: SWord8 = s16 & s1847
+  s1850 :: SWord8 = if s1057 then s1848 else s1849
+  s1851 :: SWord8 = s1850 >>> 1
+  s1852 :: SWord8 = s14 | s1851
+  s1853 :: SWord8 = s16 & s1851
+  s1854 :: SWord8 = if s1568 then s1852 else s1853
+  s1855 :: SWord8 = s1854 >>> 1
+  s1856 :: SWord8 = s14 | s1855
+  s1857 :: SWord8 = s16 & s1855
+  s1858 :: SWord8 = if s1823 then s1856 else s1857
+  s1859 :: SWord8 = s1858 >>> 1
+  s1860 :: SWord8 = s14 | s1859
+  s1861 :: SWord8 = s16 & s1859
+  s1862 :: SWord8 = if s1845 then s1860 else s1861
+  s1863 :: SWord8 = s1 + s1858
+  s1864 :: SBool = s1863 < s1
+  s1865 :: SBool = s1863 < s1858
+  s1866 :: SBool = s1864 | s1865
+  s1867 :: SWord8 = s1863 >>> 1
+  s1868 :: SWord8 = s14 | s1867
+  s1869 :: SWord8 = s16 & s1867
+  s1870 :: SWord8 = if s1866 then s1868 else s1869
+  s1871 :: SWord8 = if s1846 then s1862 else s1870
+  s1872 :: SWord8 = s1 + s1854
+  s1873 :: SBool = s1872 < s1
+  s1874 :: SBool = s1872 < s1854
+  s1875 :: SBool = s1873 | s1874
+  s1876 :: SWord8 = s1872 >>> 1
+  s1877 :: SWord8 = s14 | s1876
+  s1878 :: SWord8 = s16 & s1876
+  s1879 :: SWord8 = if s1875 then s1877 else s1878
+  s1880 :: SWord8 = s1879 >>> 1
+  s1881 :: SWord8 = s14 | s1880
+  s1882 :: SWord8 = s16 & s1880
+  s1883 :: SWord8 = if s1845 then s1881 else s1882
+  s1884 :: SWord8 = s1 + s1879
+  s1885 :: SBool = s1884 < s1
+  s1886 :: SBool = s1884 < s1879
+  s1887 :: SBool = s1885 | s1886
+  s1888 :: SWord8 = s1884 >>> 1
+  s1889 :: SWord8 = s14 | s1888
+  s1890 :: SWord8 = s16 & s1888
+  s1891 :: SWord8 = if s1887 then s1889 else s1890
+  s1892 :: SWord8 = if s1846 then s1883 else s1891
+  s1893 :: SWord8 = if s1824 then s1871 else s1892
+  s1894 :: SWord8 = s1 + s1850
+  s1895 :: SBool = s1894 < s1
+  s1896 :: SBool = s1894 < s1850
+  s1897 :: SBool = s1895 | s1896
+  s1898 :: SWord8 = s1894 >>> 1
+  s1899 :: SWord8 = s14 | s1898
+  s1900 :: SWord8 = s16 & s1898
+  s1901 :: SWord8 = if s1897 then s1899 else s1900
+  s1902 :: SWord8 = s1901 >>> 1
+  s1903 :: SWord8 = s14 | s1902
+  s1904 :: SWord8 = s16 & s1902
+  s1905 :: SWord8 = if s1823 then s1903 else s1904
+  s1906 :: SWord8 = s1905 >>> 1
+  s1907 :: SWord8 = s14 | s1906
+  s1908 :: SWord8 = s16 & s1906
+  s1909 :: SWord8 = if s1845 then s1907 else s1908
+  s1910 :: SWord8 = s1 + s1905
+  s1911 :: SBool = s1910 < s1
+  s1912 :: SBool = s1910 < s1905
+  s1913 :: SBool = s1911 | s1912
+  s1914 :: SWord8 = s1910 >>> 1
+  s1915 :: SWord8 = s14 | s1914
+  s1916 :: SWord8 = s16 & s1914
+  s1917 :: SWord8 = if s1913 then s1915 else s1916
+  s1918 :: SWord8 = if s1846 then s1909 else s1917
+  s1919 :: SWord8 = s1 + s1901
+  s1920 :: SBool = s1919 < s1
+  s1921 :: SBool = s1919 < s1901
+  s1922 :: SBool = s1920 | s1921
+  s1923 :: SWord8 = s1919 >>> 1
+  s1924 :: SWord8 = s14 | s1923
+  s1925 :: SWord8 = s16 & s1923
+  s1926 :: SWord8 = if s1922 then s1924 else s1925
+  s1927 :: SWord8 = s1926 >>> 1
+  s1928 :: SWord8 = s14 | s1927
+  s1929 :: SWord8 = s16 & s1927
+  s1930 :: SWord8 = if s1845 then s1928 else s1929
+  s1931 :: SWord8 = s1 + s1926
+  s1932 :: SBool = s1931 < s1
+  s1933 :: SBool = s1931 < s1926
+  s1934 :: SBool = s1932 | s1933
+  s1935 :: SWord8 = s1931 >>> 1
+  s1936 :: SWord8 = s14 | s1935
+  s1937 :: SWord8 = s16 & s1935
+  s1938 :: SWord8 = if s1934 then s1936 else s1937
+  s1939 :: SWord8 = if s1846 then s1930 else s1938
+  s1940 :: SWord8 = if s1824 then s1918 else s1939
+  s1941 :: SWord8 = if s1569 then s1893 else s1940
+  s1942 :: SWord8 = s1 + s1831
+  s1943 :: SWord 1 = choose [0:0] s1942
+  s1944 :: SBool = s10 /= s1943
+  s1945 :: SWord8 = if s1944 then s1835 else s1836
+  s1946 :: SWord 1 = choose [0:0] s1945
+  s1947 :: SBool = s10 /= s1946
+  s1948 :: SWord8 = if s1947 then s1841 else s1842
+  s1949 :: SWord 1 = choose [0:0] s1948
+  s1950 :: SBool = s10 /= s1949
+  s1951 :: SBool = ~ s1950
+  s1952 :: SBool = s1942 < s1
+  s1953 :: SBool = s1942 < s1831
+  s1954 :: SBool = s1952 | s1953
+  s1955 :: SWord8 = s1942 >>> 1
+  s1956 :: SWord8 = s14 | s1955
+  s1957 :: SWord8 = s16 & s1955
+  s1958 :: SWord8 = if s1954 then s1956 else s1957
+  s1959 :: SWord8 = s1958 >>> 1
+  s1960 :: SWord8 = s14 | s1959
+  s1961 :: SWord8 = s16 & s1959
+  s1962 :: SWord8 = if s1568 then s1960 else s1961
+  s1963 :: SWord8 = s1962 >>> 1
+  s1964 :: SWord8 = s14 | s1963
+  s1965 :: SWord8 = s16 & s1963
+  s1966 :: SWord8 = if s1823 then s1964 else s1965
+  s1967 :: SWord8 = s1966 >>> 1
+  s1968 :: SWord8 = s14 | s1967
+  s1969 :: SWord8 = s16 & s1967
+  s1970 :: SWord8 = if s1950 then s1968 else s1969
+  s1971 :: SWord8 = s1 + s1966
+  s1972 :: SBool = s1971 < s1
+  s1973 :: SBool = s1971 < s1966
+  s1974 :: SBool = s1972 | s1973
+  s1975 :: SWord8 = s1971 >>> 1
+  s1976 :: SWord8 = s14 | s1975
+  s1977 :: SWord8 = s16 & s1975
+  s1978 :: SWord8 = if s1974 then s1976 else s1977
+  s1979 :: SWord8 = if s1951 then s1970 else s1978
+  s1980 :: SWord8 = s1 + s1962
+  s1981 :: SBool = s1980 < s1
+  s1982 :: SBool = s1980 < s1962
+  s1983 :: SBool = s1981 | s1982
+  s1984 :: SWord8 = s1980 >>> 1
+  s1985 :: SWord8 = s14 | s1984
+  s1986 :: SWord8 = s16 & s1984
+  s1987 :: SWord8 = if s1983 then s1985 else s1986
+  s1988 :: SWord8 = s1987 >>> 1
+  s1989 :: SWord8 = s14 | s1988
+  s1990 :: SWord8 = s16 & s1988
+  s1991 :: SWord8 = if s1950 then s1989 else s1990
+  s1992 :: SWord8 = s1 + s1987
+  s1993 :: SBool = s1992 < s1
+  s1994 :: SBool = s1992 < s1987
+  s1995 :: SBool = s1993 | s1994
+  s1996 :: SWord8 = s1992 >>> 1
+  s1997 :: SWord8 = s14 | s1996
+  s1998 :: SWord8 = s16 & s1996
+  s1999 :: SWord8 = if s1995 then s1997 else s1998
+  s2000 :: SWord8 = if s1951 then s1991 else s1999
+  s2001 :: SWord8 = if s1824 then s1979 else s2000
+  s2002 :: SWord8 = s1 + s1958
+  s2003 :: SBool = s2002 < s1
+  s2004 :: SBool = s2002 < s1958
+  s2005 :: SBool = s2003 | s2004
+  s2006 :: SWord8 = s2002 >>> 1
+  s2007 :: SWord8 = s14 | s2006
+  s2008 :: SWord8 = s16 & s2006
+  s2009 :: SWord8 = if s2005 then s2007 else s2008
+  s2010 :: SWord8 = s2009 >>> 1
+  s2011 :: SWord8 = s14 | s2010
+  s2012 :: SWord8 = s16 & s2010
+  s2013 :: SWord8 = if s1823 then s2011 else s2012
+  s2014 :: SWord8 = s2013 >>> 1
+  s2015 :: SWord8 = s14 | s2014
+  s2016 :: SWord8 = s16 & s2014
+  s2017 :: SWord8 = if s1950 then s2015 else s2016
+  s2018 :: SWord8 = s1 + s2013
+  s2019 :: SBool = s2018 < s1
+  s2020 :: SBool = s2018 < s2013
+  s2021 :: SBool = s2019 | s2020
+  s2022 :: SWord8 = s2018 >>> 1
+  s2023 :: SWord8 = s14 | s2022
+  s2024 :: SWord8 = s16 & s2022
+  s2025 :: SWord8 = if s2021 then s2023 else s2024
+  s2026 :: SWord8 = if s1951 then s2017 else s2025
+  s2027 :: SWord8 = s1 + s2009
+  s2028 :: SBool = s2027 < s1
+  s2029 :: SBool = s2027 < s2009
+  s2030 :: SBool = s2028 | s2029
+  s2031 :: SWord8 = s2027 >>> 1
+  s2032 :: SWord8 = s14 | s2031
+  s2033 :: SWord8 = s16 & s2031
+  s2034 :: SWord8 = if s2030 then s2032 else s2033
+  s2035 :: SWord8 = s2034 >>> 1
+  s2036 :: SWord8 = s14 | s2035
+  s2037 :: SWord8 = s16 & s2035
+  s2038 :: SWord8 = if s1950 then s2036 else s2037
+  s2039 :: SWord8 = s1 + s2034
+  s2040 :: SBool = s2039 < s1
+  s2041 :: SBool = s2039 < s2034
+  s2042 :: SBool = s2040 | s2041
+  s2043 :: SWord8 = s2039 >>> 1
+  s2044 :: SWord8 = s14 | s2043
+  s2045 :: SWord8 = s16 & s2043
+  s2046 :: SWord8 = if s2042 then s2044 else s2045
+  s2047 :: SWord8 = if s1951 then s2038 else s2046
+  s2048 :: SWord8 = if s1824 then s2026 else s2047
+  s2049 :: SWord8 = if s1569 then s2001 else s2048
+  s2050 :: SWord8 = if s1058 then s1941 else s2049
+  s2051 :: SWord8 = if s41 then s1814 else s2050
+  s2052 :: SWord8 = if s30 then s1559 else s2051
+  s2053 :: SWord8 = if s21 then s1048 else s2052
+  s2054 :: SWord 1 = choose [0:0] s1
+  s2055 :: SBool = s10 /= s2054
+  s2056 :: SWord8 = s14 | s31
+  s2057 :: SWord8 = if s2055 then s2056 else s32
+  s2058 :: SWord 1 = choose [0:0] s2057
+  s2059 :: SBool = s10 /= s2058
+  s2060 :: SWord8 = if s2059 then s36 else s37
+  s2061 :: SWord 1 = choose [0:0] s2060
+  s2062 :: SBool = s10 /= s2061
+  s2063 :: SBool = ~ s2062
+  s2064 :: SWord8 = s1 >>> 1
+  s2065 :: SWord8 = s16 & s2064
+  s2066 :: SWord 1 = choose [0:0] s2065
+  s2067 :: SBool = s10 /= s2066
+  s2068 :: SWord8 = s2057 >>> 1
+  s2069 :: SWord8 = s14 | s2068
+  s2070 :: SWord8 = s16 & s2068
+  s2071 :: SWord8 = if s2067 then s2069 else s2070
+  s2072 :: SWord 1 = choose [0:0] s2071
+  s2073 :: SBool = s10 /= s2072
+  s2074 :: SWord8 = s2060 >>> 1
+  s2075 :: SWord8 = s14 | s2074
+  s2076 :: SWord8 = s16 & s2074
+  s2077 :: SWord8 = if s2073 then s2075 else s2076
+  s2078 :: SWord 1 = choose [0:0] s2077
+  s2079 :: SBool = s10 /= s2078
+  s2080 :: SBool = ~ s2079
+  s2081 :: SWord8 = s2065 >>> 1
+  s2082 :: SWord8 = s14 | s2081
+  s2083 :: SWord8 = s16 & s2081
+  s2084 :: SWord8 = if s20 then s2082 else s2083
+  s2085 :: SWord 1 = choose [0:0] s2084
+  s2086 :: SBool = s10 /= s2085
+  s2087 :: SWord8 = s2071 >>> 1
+  s2088 :: SWord8 = s14 | s2087
+  s2089 :: SWord8 = s16 & s2087
+  s2090 :: SWord8 = if s2086 then s2088 else s2089
+  s2091 :: SWord 1 = choose [0:0] s2090
+  s2092 :: SBool = s10 /= s2091
+  s2093 :: SWord8 = s2077 >>> 1
+  s2094 :: SWord8 = s14 | s2093
+  s2095 :: SWord8 = s16 & s2093
+  s2096 :: SWord8 = if s2092 then s2094 else s2095
+  s2097 :: SWord 1 = choose [0:0] s2096
+  s2098 :: SBool = s10 /= s2097
+  s2099 :: SBool = ~ s2098
+  s2100 :: SWord8 = s2084 >>> 1
+  s2101 :: SWord8 = s14 | s2100
+  s2102 :: SWord8 = s16 & s2100
+  s2103 :: SWord8 = if s29 then s2101 else s2102
+  s2104 :: SWord 1 = choose [0:0] s2103
+  s2105 :: SBool = s10 /= s2104
+  s2106 :: SWord8 = s2090 >>> 1
+  s2107 :: SWord8 = s14 | s2106
+  s2108 :: SWord8 = s16 & s2106
+  s2109 :: SWord8 = if s2105 then s2107 else s2108
+  s2110 :: SWord 1 = choose [0:0] s2109
+  s2111 :: SBool = s10 /= s2110
+  s2112 :: SWord8 = s2096 >>> 1
+  s2113 :: SWord8 = s14 | s2112
+  s2114 :: SWord8 = s16 & s2112
+  s2115 :: SWord8 = if s2111 then s2113 else s2114
+  s2116 :: SWord 1 = choose [0:0] s2115
+  s2117 :: SBool = s10 /= s2116
+  s2118 :: SBool = ~ s2117
+  s2119 :: SWord8 = s2103 >>> 1
+  s2120 :: SWord8 = s14 | s2119
+  s2121 :: SWord8 = s16 & s2119
+  s2122 :: SWord8 = if s2062 then s2120 else s2121
+  s2123 :: SWord 1 = choose [0:0] s2122
+  s2124 :: SBool = s10 /= s2123
+  s2125 :: SWord8 = s2109 >>> 1
+  s2126 :: SWord8 = s14 | s2125
+  s2127 :: SWord8 = s16 & s2125
+  s2128 :: SWord8 = if s2124 then s2126 else s2127
+  s2129 :: SWord 1 = choose [0:0] s2128
+  s2130 :: SBool = s10 /= s2129
+  s2131 :: SWord8 = s2115 >>> 1
+  s2132 :: SWord8 = s14 | s2131
+  s2133 :: SWord8 = s16 & s2131
+  s2134 :: SWord8 = if s2130 then s2132 else s2133
+  s2135 :: SWord 1 = choose [0:0] s2134
+  s2136 :: SBool = s10 /= s2135
+  s2137 :: SBool = ~ s2136
+  s2138 :: SWord8 = s2122 >>> 1
+  s2139 :: SWord8 = s14 | s2138
+  s2140 :: SWord8 = s16 & s2138
+  s2141 :: SWord8 = if s2079 then s2139 else s2140
+  s2142 :: SWord8 = s2141 >>> 1
+  s2143 :: SWord8 = s14 | s2142
+  s2144 :: SWord8 = s16 & s2142
+  s2145 :: SWord8 = if s2098 then s2143 else s2144
+  s2146 :: SWord8 = s2145 >>> 1
+  s2147 :: SWord8 = s14 | s2146
+  s2148 :: SWord8 = s16 & s2146
+  s2149 :: SWord8 = if s2117 then s2147 else s2148
+  s2150 :: SWord8 = s2149 >>> 1
+  s2151 :: SWord8 = s14 | s2150
+  s2152 :: SWord8 = s16 & s2150
+  s2153 :: SWord8 = if s2136 then s2151 else s2152
+  s2154 :: SWord8 = s1 + s2149
+  s2155 :: SBool = s2154 < s1
+  s2156 :: SBool = s2154 < s2149
+  s2157 :: SBool = s2155 | s2156
+  s2158 :: SWord8 = s2154 >>> 1
+  s2159 :: SWord8 = s14 | s2158
+  s2160 :: SWord8 = s16 & s2158
+  s2161 :: SWord8 = if s2157 then s2159 else s2160
+  s2162 :: SWord8 = if s2137 then s2153 else s2161
+  s2163 :: SWord8 = s1 + s2145
+  s2164 :: SBool = s2163 < s1
+  s2165 :: SBool = s2163 < s2145
+  s2166 :: SBool = s2164 | s2165
+  s2167 :: SWord8 = s2163 >>> 1
+  s2168 :: SWord8 = s14 | s2167
+  s2169 :: SWord8 = s16 & s2167
+  s2170 :: SWord8 = if s2166 then s2168 else s2169
+  s2171 :: SWord8 = s2170 >>> 1
+  s2172 :: SWord8 = s14 | s2171
+  s2173 :: SWord8 = s16 & s2171
+  s2174 :: SWord8 = if s2136 then s2172 else s2173
+  s2175 :: SWord8 = s1 + s2170
+  s2176 :: SBool = s2175 < s1
+  s2177 :: SBool = s2175 < s2170
+  s2178 :: SBool = s2176 | s2177
+  s2179 :: SWord8 = s2175 >>> 1
+  s2180 :: SWord8 = s14 | s2179
+  s2181 :: SWord8 = s16 & s2179
+  s2182 :: SWord8 = if s2178 then s2180 else s2181
+  s2183 :: SWord8 = if s2137 then s2174 else s2182
+  s2184 :: SWord8 = if s2118 then s2162 else s2183
+  s2185 :: SWord8 = s1 + s2141
+  s2186 :: SBool = s2185 < s1
+  s2187 :: SBool = s2185 < s2141
+  s2188 :: SBool = s2186 | s2187
+  s2189 :: SWord8 = s2185 >>> 1
+  s2190 :: SWord8 = s14 | s2189
+  s2191 :: SWord8 = s16 & s2189
+  s2192 :: SWord8 = if s2188 then s2190 else s2191
+  s2193 :: SWord8 = s2192 >>> 1
+  s2194 :: SWord8 = s14 | s2193
+  s2195 :: SWord8 = s16 & s2193
+  s2196 :: SWord8 = if s2117 then s2194 else s2195
+  s2197 :: SWord8 = s2196 >>> 1
+  s2198 :: SWord8 = s14 | s2197
+  s2199 :: SWord8 = s16 & s2197
+  s2200 :: SWord8 = if s2136 then s2198 else s2199
+  s2201 :: SWord8 = s1 + s2196
+  s2202 :: SBool = s2201 < s1
+  s2203 :: SBool = s2201 < s2196
+  s2204 :: SBool = s2202 | s2203
+  s2205 :: SWord8 = s2201 >>> 1
+  s2206 :: SWord8 = s14 | s2205
+  s2207 :: SWord8 = s16 & s2205
+  s2208 :: SWord8 = if s2204 then s2206 else s2207
+  s2209 :: SWord8 = if s2137 then s2200 else s2208
+  s2210 :: SWord8 = s1 + s2192
+  s2211 :: SBool = s2210 < s1
+  s2212 :: SBool = s2210 < s2192
+  s2213 :: SBool = s2211 | s2212
+  s2214 :: SWord8 = s2210 >>> 1
+  s2215 :: SWord8 = s14 | s2214
+  s2216 :: SWord8 = s16 & s2214
+  s2217 :: SWord8 = if s2213 then s2215 else s2216
+  s2218 :: SWord8 = s2217 >>> 1
+  s2219 :: SWord8 = s14 | s2218
+  s2220 :: SWord8 = s16 & s2218
+  s2221 :: SWord8 = if s2136 then s2219 else s2220
+  s2222 :: SWord8 = s1 + s2217
+  s2223 :: SBool = s2222 < s1
+  s2224 :: SBool = s2222 < s2217
+  s2225 :: SBool = s2223 | s2224
+  s2226 :: SWord8 = s2222 >>> 1
+  s2227 :: SWord8 = s14 | s2226
+  s2228 :: SWord8 = s16 & s2226
+  s2229 :: SWord8 = if s2225 then s2227 else s2228
+  s2230 :: SWord8 = if s2137 then s2221 else s2229
+  s2231 :: SWord8 = if s2118 then s2209 else s2230
+  s2232 :: SWord8 = if s2099 then s2184 else s2231
+  s2233 :: SWord8 = s1 + s2122
+  s2234 :: SWord 1 = choose [0:0] s2233
+  s2235 :: SBool = s10 /= s2234
+  s2236 :: SWord8 = if s2235 then s2126 else s2127
+  s2237 :: SWord 1 = choose [0:0] s2236
+  s2238 :: SBool = s10 /= s2237
+  s2239 :: SWord8 = if s2238 then s2132 else s2133
+  s2240 :: SWord 1 = choose [0:0] s2239
+  s2241 :: SBool = s10 /= s2240
+  s2242 :: SBool = ~ s2241
+  s2243 :: SBool = s2233 < s1
+  s2244 :: SBool = s2233 < s2122
+  s2245 :: SBool = s2243 | s2244
+  s2246 :: SWord8 = s2233 >>> 1
+  s2247 :: SWord8 = s14 | s2246
+  s2248 :: SWord8 = s16 & s2246
+  s2249 :: SWord8 = if s2245 then s2247 else s2248
+  s2250 :: SWord8 = s2249 >>> 1
+  s2251 :: SWord8 = s14 | s2250
+  s2252 :: SWord8 = s16 & s2250
+  s2253 :: SWord8 = if s2098 then s2251 else s2252
+  s2254 :: SWord8 = s2253 >>> 1
+  s2255 :: SWord8 = s14 | s2254
+  s2256 :: SWord8 = s16 & s2254
+  s2257 :: SWord8 = if s2117 then s2255 else s2256
+  s2258 :: SWord8 = s2257 >>> 1
+  s2259 :: SWord8 = s14 | s2258
+  s2260 :: SWord8 = s16 & s2258
+  s2261 :: SWord8 = if s2241 then s2259 else s2260
+  s2262 :: SWord8 = s1 + s2257
+  s2263 :: SBool = s2262 < s1
+  s2264 :: SBool = s2262 < s2257
+  s2265 :: SBool = s2263 | s2264
+  s2266 :: SWord8 = s2262 >>> 1
+  s2267 :: SWord8 = s14 | s2266
+  s2268 :: SWord8 = s16 & s2266
+  s2269 :: SWord8 = if s2265 then s2267 else s2268
+  s2270 :: SWord8 = if s2242 then s2261 else s2269
+  s2271 :: SWord8 = s1 + s2253
+  s2272 :: SBool = s2271 < s1
+  s2273 :: SBool = s2271 < s2253
+  s2274 :: SBool = s2272 | s2273
+  s2275 :: SWord8 = s2271 >>> 1
+  s2276 :: SWord8 = s14 | s2275
+  s2277 :: SWord8 = s16 & s2275
+  s2278 :: SWord8 = if s2274 then s2276 else s2277
+  s2279 :: SWord8 = s2278 >>> 1
+  s2280 :: SWord8 = s14 | s2279
+  s2281 :: SWord8 = s16 & s2279
+  s2282 :: SWord8 = if s2241 then s2280 else s2281
+  s2283 :: SWord8 = s1 + s2278
+  s2284 :: SBool = s2283 < s1
+  s2285 :: SBool = s2283 < s2278
+  s2286 :: SBool = s2284 | s2285
+  s2287 :: SWord8 = s2283 >>> 1
+  s2288 :: SWord8 = s14 | s2287
+  s2289 :: SWord8 = s16 & s2287
+  s2290 :: SWord8 = if s2286 then s2288 else s2289
+  s2291 :: SWord8 = if s2242 then s2282 else s2290
+  s2292 :: SWord8 = if s2118 then s2270 else s2291
+  s2293 :: SWord8 = s1 + s2249
+  s2294 :: SBool = s2293 < s1
+  s2295 :: SBool = s2293 < s2249
+  s2296 :: SBool = s2294 | s2295
+  s2297 :: SWord8 = s2293 >>> 1
+  s2298 :: SWord8 = s14 | s2297
+  s2299 :: SWord8 = s16 & s2297
+  s2300 :: SWord8 = if s2296 then s2298 else s2299
+  s2301 :: SWord8 = s2300 >>> 1
+  s2302 :: SWord8 = s14 | s2301
+  s2303 :: SWord8 = s16 & s2301
+  s2304 :: SWord8 = if s2117 then s2302 else s2303
+  s2305 :: SWord8 = s2304 >>> 1
+  s2306 :: SWord8 = s14 | s2305
+  s2307 :: SWord8 = s16 & s2305
+  s2308 :: SWord8 = if s2241 then s2306 else s2307
+  s2309 :: SWord8 = s1 + s2304
+  s2310 :: SBool = s2309 < s1
+  s2311 :: SBool = s2309 < s2304
+  s2312 :: SBool = s2310 | s2311
+  s2313 :: SWord8 = s2309 >>> 1
+  s2314 :: SWord8 = s14 | s2313
+  s2315 :: SWord8 = s16 & s2313
+  s2316 :: SWord8 = if s2312 then s2314 else s2315
+  s2317 :: SWord8 = if s2242 then s2308 else s2316
+  s2318 :: SWord8 = s1 + s2300
+  s2319 :: SBool = s2318 < s1
+  s2320 :: SBool = s2318 < s2300
+  s2321 :: SBool = s2319 | s2320
+  s2322 :: SWord8 = s2318 >>> 1
+  s2323 :: SWord8 = s14 | s2322
+  s2324 :: SWord8 = s16 & s2322
+  s2325 :: SWord8 = if s2321 then s2323 else s2324
+  s2326 :: SWord8 = s2325 >>> 1
+  s2327 :: SWord8 = s14 | s2326
+  s2328 :: SWord8 = s16 & s2326
+  s2329 :: SWord8 = if s2241 then s2327 else s2328
+  s2330 :: SWord8 = s1 + s2325
+  s2331 :: SBool = s2330 < s1
+  s2332 :: SBool = s2330 < s2325
+  s2333 :: SBool = s2331 | s2332
+  s2334 :: SWord8 = s2330 >>> 1
+  s2335 :: SWord8 = s14 | s2334
+  s2336 :: SWord8 = s16 & s2334
+  s2337 :: SWord8 = if s2333 then s2335 else s2336
+  s2338 :: SWord8 = if s2242 then s2329 else s2337
+  s2339 :: SWord8 = if s2118 then s2317 else s2338
+  s2340 :: SWord8 = if s2099 then s2292 else s2339
+  s2341 :: SWord8 = if s2080 then s2232 else s2340
+  s2342 :: SWord8 = s1 + s2103
+  s2343 :: SWord 1 = choose [0:0] s2342
+  s2344 :: SBool = s10 /= s2343
+  s2345 :: SWord8 = if s2344 then s2107 else s2108
+  s2346 :: SWord 1 = choose [0:0] s2345
+  s2347 :: SBool = s10 /= s2346
+  s2348 :: SWord8 = if s2347 then s2113 else s2114
+  s2349 :: SWord 1 = choose [0:0] s2348
+  s2350 :: SBool = s10 /= s2349
+  s2351 :: SBool = ~ s2350
+  s2352 :: SBool = s2342 < s1
+  s2353 :: SBool = s2342 < s2103
+  s2354 :: SBool = s2352 | s2353
+  s2355 :: SWord8 = s2342 >>> 1
+  s2356 :: SWord8 = s14 | s2355
+  s2357 :: SWord8 = s16 & s2355
+  s2358 :: SWord8 = if s2354 then s2356 else s2357
+  s2359 :: SWord 1 = choose [0:0] s2358
+  s2360 :: SBool = s10 /= s2359
+  s2361 :: SWord8 = s2345 >>> 1
+  s2362 :: SWord8 = s14 | s2361
+  s2363 :: SWord8 = s16 & s2361
+  s2364 :: SWord8 = if s2360 then s2362 else s2363
+  s2365 :: SWord 1 = choose [0:0] s2364
+  s2366 :: SBool = s10 /= s2365
+  s2367 :: SWord8 = s2348 >>> 1
+  s2368 :: SWord8 = s14 | s2367
+  s2369 :: SWord8 = s16 & s2367
+  s2370 :: SWord8 = if s2366 then s2368 else s2369
+  s2371 :: SWord 1 = choose [0:0] s2370
+  s2372 :: SBool = s10 /= s2371
+  s2373 :: SBool = ~ s2372
+  s2374 :: SWord8 = s2358 >>> 1
+  s2375 :: SWord8 = s14 | s2374
+  s2376 :: SWord8 = s16 & s2374
+  s2377 :: SWord8 = if s2079 then s2375 else s2376
+  s2378 :: SWord8 = s2377 >>> 1
+  s2379 :: SWord8 = s14 | s2378
+  s2380 :: SWord8 = s16 & s2378
+  s2381 :: SWord8 = if s2098 then s2379 else s2380
+  s2382 :: SWord8 = s2381 >>> 1
+  s2383 :: SWord8 = s14 | s2382
+  s2384 :: SWord8 = s16 & s2382
+  s2385 :: SWord8 = if s2350 then s2383 else s2384
+  s2386 :: SWord8 = s2385 >>> 1
+  s2387 :: SWord8 = s14 | s2386
+  s2388 :: SWord8 = s16 & s2386
+  s2389 :: SWord8 = if s2372 then s2387 else s2388
+  s2390 :: SWord8 = s1 + s2385
+  s2391 :: SBool = s2390 < s1
+  s2392 :: SBool = s2390 < s2385
+  s2393 :: SBool = s2391 | s2392
+  s2394 :: SWord8 = s2390 >>> 1
+  s2395 :: SWord8 = s14 | s2394
+  s2396 :: SWord8 = s16 & s2394
+  s2397 :: SWord8 = if s2393 then s2395 else s2396
+  s2398 :: SWord8 = if s2373 then s2389 else s2397
+  s2399 :: SWord8 = s1 + s2381
+  s2400 :: SBool = s2399 < s1
+  s2401 :: SBool = s2399 < s2381
+  s2402 :: SBool = s2400 | s2401
+  s2403 :: SWord8 = s2399 >>> 1
+  s2404 :: SWord8 = s14 | s2403
+  s2405 :: SWord8 = s16 & s2403
+  s2406 :: SWord8 = if s2402 then s2404 else s2405
+  s2407 :: SWord8 = s2406 >>> 1
+  s2408 :: SWord8 = s14 | s2407
+  s2409 :: SWord8 = s16 & s2407
+  s2410 :: SWord8 = if s2372 then s2408 else s2409
+  s2411 :: SWord8 = s1 + s2406
+  s2412 :: SBool = s2411 < s1
+  s2413 :: SBool = s2411 < s2406
+  s2414 :: SBool = s2412 | s2413
+  s2415 :: SWord8 = s2411 >>> 1
+  s2416 :: SWord8 = s14 | s2415
+  s2417 :: SWord8 = s16 & s2415
+  s2418 :: SWord8 = if s2414 then s2416 else s2417
+  s2419 :: SWord8 = if s2373 then s2410 else s2418
+  s2420 :: SWord8 = if s2351 then s2398 else s2419
+  s2421 :: SWord8 = s1 + s2377
+  s2422 :: SBool = s2421 < s1
+  s2423 :: SBool = s2421 < s2377
+  s2424 :: SBool = s2422 | s2423
+  s2425 :: SWord8 = s2421 >>> 1
+  s2426 :: SWord8 = s14 | s2425
+  s2427 :: SWord8 = s16 & s2425
+  s2428 :: SWord8 = if s2424 then s2426 else s2427
+  s2429 :: SWord8 = s2428 >>> 1
+  s2430 :: SWord8 = s14 | s2429
+  s2431 :: SWord8 = s16 & s2429
+  s2432 :: SWord8 = if s2350 then s2430 else s2431
+  s2433 :: SWord8 = s2432 >>> 1
+  s2434 :: SWord8 = s14 | s2433
+  s2435 :: SWord8 = s16 & s2433
+  s2436 :: SWord8 = if s2372 then s2434 else s2435
+  s2437 :: SWord8 = s1 + s2432
+  s2438 :: SBool = s2437 < s1
+  s2439 :: SBool = s2437 < s2432
+  s2440 :: SBool = s2438 | s2439
+  s2441 :: SWord8 = s2437 >>> 1
+  s2442 :: SWord8 = s14 | s2441
+  s2443 :: SWord8 = s16 & s2441
+  s2444 :: SWord8 = if s2440 then s2442 else s2443
+  s2445 :: SWord8 = if s2373 then s2436 else s2444
+  s2446 :: SWord8 = s1 + s2428
+  s2447 :: SBool = s2446 < s1
+  s2448 :: SBool = s2446 < s2428
+  s2449 :: SBool = s2447 | s2448
+  s2450 :: SWord8 = s2446 >>> 1
+  s2451 :: SWord8 = s14 | s2450
+  s2452 :: SWord8 = s16 & s2450
+  s2453 :: SWord8 = if s2449 then s2451 else s2452
+  s2454 :: SWord8 = s2453 >>> 1
+  s2455 :: SWord8 = s14 | s2454
+  s2456 :: SWord8 = s16 & s2454
+  s2457 :: SWord8 = if s2372 then s2455 else s2456
+  s2458 :: SWord8 = s1 + s2453
+  s2459 :: SBool = s2458 < s1
+  s2460 :: SBool = s2458 < s2453
+  s2461 :: SBool = s2459 | s2460
+  s2462 :: SWord8 = s2458 >>> 1
+  s2463 :: SWord8 = s14 | s2462
+  s2464 :: SWord8 = s16 & s2462
+  s2465 :: SWord8 = if s2461 then s2463 else s2464
+  s2466 :: SWord8 = if s2373 then s2457 else s2465
+  s2467 :: SWord8 = if s2351 then s2445 else s2466
+  s2468 :: SWord8 = if s2099 then s2420 else s2467
+  s2469 :: SWord8 = s1 + s2358
+  s2470 :: SWord 1 = choose [0:0] s2469
+  s2471 :: SBool = s10 /= s2470
+  s2472 :: SWord8 = if s2471 then s2362 else s2363
+  s2473 :: SWord 1 = choose [0:0] s2472
+  s2474 :: SBool = s10 /= s2473
+  s2475 :: SWord8 = if s2474 then s2368 else s2369
+  s2476 :: SWord 1 = choose [0:0] s2475
+  s2477 :: SBool = s10 /= s2476
+  s2478 :: SBool = ~ s2477
+  s2479 :: SBool = s2469 < s1
+  s2480 :: SBool = s2469 < s2358
+  s2481 :: SBool = s2479 | s2480
+  s2482 :: SWord8 = s2469 >>> 1
+  s2483 :: SWord8 = s14 | s2482
+  s2484 :: SWord8 = s16 & s2482
+  s2485 :: SWord8 = if s2481 then s2483 else s2484
+  s2486 :: SWord8 = s2485 >>> 1
+  s2487 :: SWord8 = s14 | s2486
+  s2488 :: SWord8 = s16 & s2486
+  s2489 :: SWord8 = if s2098 then s2487 else s2488
+  s2490 :: SWord8 = s2489 >>> 1
+  s2491 :: SWord8 = s14 | s2490
+  s2492 :: SWord8 = s16 & s2490
+  s2493 :: SWord8 = if s2350 then s2491 else s2492
+  s2494 :: SWord8 = s2493 >>> 1
+  s2495 :: SWord8 = s14 | s2494
+  s2496 :: SWord8 = s16 & s2494
+  s2497 :: SWord8 = if s2477 then s2495 else s2496
+  s2498 :: SWord8 = s1 + s2493
+  s2499 :: SBool = s2498 < s1
+  s2500 :: SBool = s2498 < s2493
+  s2501 :: SBool = s2499 | s2500
+  s2502 :: SWord8 = s2498 >>> 1
+  s2503 :: SWord8 = s14 | s2502
+  s2504 :: SWord8 = s16 & s2502
+  s2505 :: SWord8 = if s2501 then s2503 else s2504
+  s2506 :: SWord8 = if s2478 then s2497 else s2505
+  s2507 :: SWord8 = s1 + s2489
+  s2508 :: SBool = s2507 < s1
+  s2509 :: SBool = s2507 < s2489
+  s2510 :: SBool = s2508 | s2509
+  s2511 :: SWord8 = s2507 >>> 1
+  s2512 :: SWord8 = s14 | s2511
+  s2513 :: SWord8 = s16 & s2511
+  s2514 :: SWord8 = if s2510 then s2512 else s2513
+  s2515 :: SWord8 = s2514 >>> 1
+  s2516 :: SWord8 = s14 | s2515
+  s2517 :: SWord8 = s16 & s2515
+  s2518 :: SWord8 = if s2477 then s2516 else s2517
+  s2519 :: SWord8 = s1 + s2514
+  s2520 :: SBool = s2519 < s1
+  s2521 :: SBool = s2519 < s2514
+  s2522 :: SBool = s2520 | s2521
+  s2523 :: SWord8 = s2519 >>> 1
+  s2524 :: SWord8 = s14 | s2523
+  s2525 :: SWord8 = s16 & s2523
+  s2526 :: SWord8 = if s2522 then s2524 else s2525
+  s2527 :: SWord8 = if s2478 then s2518 else s2526
+  s2528 :: SWord8 = if s2351 then s2506 else s2527
+  s2529 :: SWord8 = s1 + s2485
+  s2530 :: SBool = s2529 < s1
+  s2531 :: SBool = s2529 < s2485
+  s2532 :: SBool = s2530 | s2531
+  s2533 :: SWord8 = s2529 >>> 1
+  s2534 :: SWord8 = s14 | s2533
+  s2535 :: SWord8 = s16 & s2533
+  s2536 :: SWord8 = if s2532 then s2534 else s2535
+  s2537 :: SWord8 = s2536 >>> 1
+  s2538 :: SWord8 = s14 | s2537
+  s2539 :: SWord8 = s16 & s2537
+  s2540 :: SWord8 = if s2350 then s2538 else s2539
+  s2541 :: SWord8 = s2540 >>> 1
+  s2542 :: SWord8 = s14 | s2541
+  s2543 :: SWord8 = s16 & s2541
+  s2544 :: SWord8 = if s2477 then s2542 else s2543
+  s2545 :: SWord8 = s1 + s2540
+  s2546 :: SBool = s2545 < s1
+  s2547 :: SBool = s2545 < s2540
+  s2548 :: SBool = s2546 | s2547
+  s2549 :: SWord8 = s2545 >>> 1
+  s2550 :: SWord8 = s14 | s2549
+  s2551 :: SWord8 = s16 & s2549
+  s2552 :: SWord8 = if s2548 then s2550 else s2551
+  s2553 :: SWord8 = if s2478 then s2544 else s2552
+  s2554 :: SWord8 = s1 + s2536
+  s2555 :: SBool = s2554 < s1
+  s2556 :: SBool = s2554 < s2536
+  s2557 :: SBool = s2555 | s2556
+  s2558 :: SWord8 = s2554 >>> 1
+  s2559 :: SWord8 = s14 | s2558
+  s2560 :: SWord8 = s16 & s2558
+  s2561 :: SWord8 = if s2557 then s2559 else s2560
+  s2562 :: SWord8 = s2561 >>> 1
+  s2563 :: SWord8 = s14 | s2562
+  s2564 :: SWord8 = s16 & s2562
+  s2565 :: SWord8 = if s2477 then s2563 else s2564
+  s2566 :: SWord8 = s1 + s2561
+  s2567 :: SBool = s2566 < s1
+  s2568 :: SBool = s2566 < s2561
+  s2569 :: SBool = s2567 | s2568
+  s2570 :: SWord8 = s2566 >>> 1
+  s2571 :: SWord8 = s14 | s2570
+  s2572 :: SWord8 = s16 & s2570
+  s2573 :: SWord8 = if s2569 then s2571 else s2572
+  s2574 :: SWord8 = if s2478 then s2565 else s2573
+  s2575 :: SWord8 = if s2351 then s2553 else s2574
+  s2576 :: SWord8 = if s2099 then s2528 else s2575
+  s2577 :: SWord8 = if s2080 then s2468 else s2576
+  s2578 :: SWord8 = if s2063 then s2341 else s2577
+  s2579 :: SWord8 = s1 + s2084
+  s2580 :: SWord 1 = choose [0:0] s2579
+  s2581 :: SBool = s10 /= s2580
+  s2582 :: SWord8 = if s2581 then s2088 else s2089
+  s2583 :: SWord 1 = choose [0:0] s2582
+  s2584 :: SBool = s10 /= s2583
+  s2585 :: SWord8 = if s2584 then s2094 else s2095
+  s2586 :: SWord 1 = choose [0:0] s2585
+  s2587 :: SBool = s10 /= s2586
+  s2588 :: SBool = ~ s2587
+  s2589 :: SBool = s2579 < s1
+  s2590 :: SBool = s2579 < s2084
+  s2591 :: SBool = s2589 | s2590
+  s2592 :: SWord8 = s2579 >>> 1
+  s2593 :: SWord8 = s14 | s2592
+  s2594 :: SWord8 = s16 & s2592
+  s2595 :: SWord8 = if s2591 then s2593 else s2594
+  s2596 :: SWord 1 = choose [0:0] s2595
+  s2597 :: SBool = s10 /= s2596
+  s2598 :: SWord8 = s2582 >>> 1
+  s2599 :: SWord8 = s14 | s2598
+  s2600 :: SWord8 = s16 & s2598
+  s2601 :: SWord8 = if s2597 then s2599 else s2600
+  s2602 :: SWord 1 = choose [0:0] s2601
+  s2603 :: SBool = s10 /= s2602
+  s2604 :: SWord8 = s2585 >>> 1
+  s2605 :: SWord8 = s14 | s2604
+  s2606 :: SWord8 = s16 & s2604
+  s2607 :: SWord8 = if s2603 then s2605 else s2606
+  s2608 :: SWord 1 = choose [0:0] s2607
+  s2609 :: SBool = s10 /= s2608
+  s2610 :: SBool = ~ s2609
+  s2611 :: SWord8 = s2595 >>> 1
+  s2612 :: SWord8 = s14 | s2611
+  s2613 :: SWord8 = s16 & s2611
+  s2614 :: SWord8 = if s2062 then s2612 else s2613
+  s2615 :: SWord 1 = choose [0:0] s2614
+  s2616 :: SBool = s10 /= s2615
+  s2617 :: SWord8 = s2601 >>> 1
+  s2618 :: SWord8 = s14 | s2617
+  s2619 :: SWord8 = s16 & s2617
+  s2620 :: SWord8 = if s2616 then s2618 else s2619
+  s2621 :: SWord 1 = choose [0:0] s2620
+  s2622 :: SBool = s10 /= s2621
+  s2623 :: SWord8 = s2607 >>> 1
+  s2624 :: SWord8 = s14 | s2623
+  s2625 :: SWord8 = s16 & s2623
+  s2626 :: SWord8 = if s2622 then s2624 else s2625
+  s2627 :: SWord 1 = choose [0:0] s2626
+  s2628 :: SBool = s10 /= s2627
+  s2629 :: SBool = ~ s2628
+  s2630 :: SWord8 = s2614 >>> 1
+  s2631 :: SWord8 = s14 | s2630
+  s2632 :: SWord8 = s16 & s2630
+  s2633 :: SWord8 = if s2079 then s2631 else s2632
+  s2634 :: SWord8 = s2633 >>> 1
+  s2635 :: SWord8 = s14 | s2634
+  s2636 :: SWord8 = s16 & s2634
+  s2637 :: SWord8 = if s2587 then s2635 else s2636
+  s2638 :: SWord8 = s2637 >>> 1
+  s2639 :: SWord8 = s14 | s2638
+  s2640 :: SWord8 = s16 & s2638
+  s2641 :: SWord8 = if s2609 then s2639 else s2640
+  s2642 :: SWord8 = s2641 >>> 1
+  s2643 :: SWord8 = s14 | s2642
+  s2644 :: SWord8 = s16 & s2642
+  s2645 :: SWord8 = if s2628 then s2643 else s2644
+  s2646 :: SWord8 = s1 + s2641
+  s2647 :: SBool = s2646 < s1
+  s2648 :: SBool = s2646 < s2641
+  s2649 :: SBool = s2647 | s2648
+  s2650 :: SWord8 = s2646 >>> 1
+  s2651 :: SWord8 = s14 | s2650
+  s2652 :: SWord8 = s16 & s2650
+  s2653 :: SWord8 = if s2649 then s2651 else s2652
+  s2654 :: SWord8 = if s2629 then s2645 else s2653
+  s2655 :: SWord8 = s1 + s2637
+  s2656 :: SBool = s2655 < s1
+  s2657 :: SBool = s2655 < s2637
+  s2658 :: SBool = s2656 | s2657
+  s2659 :: SWord8 = s2655 >>> 1
+  s2660 :: SWord8 = s14 | s2659
+  s2661 :: SWord8 = s16 & s2659
+  s2662 :: SWord8 = if s2658 then s2660 else s2661
+  s2663 :: SWord8 = s2662 >>> 1
+  s2664 :: SWord8 = s14 | s2663
+  s2665 :: SWord8 = s16 & s2663
+  s2666 :: SWord8 = if s2628 then s2664 else s2665
+  s2667 :: SWord8 = s1 + s2662
+  s2668 :: SBool = s2667 < s1
+  s2669 :: SBool = s2667 < s2662
+  s2670 :: SBool = s2668 | s2669
+  s2671 :: SWord8 = s2667 >>> 1
+  s2672 :: SWord8 = s14 | s2671
+  s2673 :: SWord8 = s16 & s2671
+  s2674 :: SWord8 = if s2670 then s2672 else s2673
+  s2675 :: SWord8 = if s2629 then s2666 else s2674
+  s2676 :: SWord8 = if s2610 then s2654 else s2675
+  s2677 :: SWord8 = s1 + s2633
+  s2678 :: SBool = s2677 < s1
+  s2679 :: SBool = s2677 < s2633
+  s2680 :: SBool = s2678 | s2679
+  s2681 :: SWord8 = s2677 >>> 1
+  s2682 :: SWord8 = s14 | s2681
+  s2683 :: SWord8 = s16 & s2681
+  s2684 :: SWord8 = if s2680 then s2682 else s2683
+  s2685 :: SWord8 = s2684 >>> 1
+  s2686 :: SWord8 = s14 | s2685
+  s2687 :: SWord8 = s16 & s2685
+  s2688 :: SWord8 = if s2609 then s2686 else s2687
+  s2689 :: SWord8 = s2688 >>> 1
+  s2690 :: SWord8 = s14 | s2689
+  s2691 :: SWord8 = s16 & s2689
+  s2692 :: SWord8 = if s2628 then s2690 else s2691
+  s2693 :: SWord8 = s1 + s2688
+  s2694 :: SBool = s2693 < s1
+  s2695 :: SBool = s2693 < s2688
+  s2696 :: SBool = s2694 | s2695
+  s2697 :: SWord8 = s2693 >>> 1
+  s2698 :: SWord8 = s14 | s2697
+  s2699 :: SWord8 = s16 & s2697
+  s2700 :: SWord8 = if s2696 then s2698 else s2699
+  s2701 :: SWord8 = if s2629 then s2692 else s2700
+  s2702 :: SWord8 = s1 + s2684
+  s2703 :: SBool = s2702 < s1
+  s2704 :: SBool = s2702 < s2684
+  s2705 :: SBool = s2703 | s2704
+  s2706 :: SWord8 = s2702 >>> 1
+  s2707 :: SWord8 = s14 | s2706
+  s2708 :: SWord8 = s16 & s2706
+  s2709 :: SWord8 = if s2705 then s2707 else s2708
+  s2710 :: SWord8 = s2709 >>> 1
+  s2711 :: SWord8 = s14 | s2710
+  s2712 :: SWord8 = s16 & s2710
+  s2713 :: SWord8 = if s2628 then s2711 else s2712
+  s2714 :: SWord8 = s1 + s2709
+  s2715 :: SBool = s2714 < s1
+  s2716 :: SBool = s2714 < s2709
+  s2717 :: SBool = s2715 | s2716
+  s2718 :: SWord8 = s2714 >>> 1
+  s2719 :: SWord8 = s14 | s2718
+  s2720 :: SWord8 = s16 & s2718
+  s2721 :: SWord8 = if s2717 then s2719 else s2720
+  s2722 :: SWord8 = if s2629 then s2713 else s2721
+  s2723 :: SWord8 = if s2610 then s2701 else s2722
+  s2724 :: SWord8 = if s2588 then s2676 else s2723
+  s2725 :: SWord8 = s1 + s2614
+  s2726 :: SWord 1 = choose [0:0] s2725
+  s2727 :: SBool = s10 /= s2726
+  s2728 :: SWord8 = if s2727 then s2618 else s2619
+  s2729 :: SWord 1 = choose [0:0] s2728
+  s2730 :: SBool = s10 /= s2729
+  s2731 :: SWord8 = if s2730 then s2624 else s2625
+  s2732 :: SWord 1 = choose [0:0] s2731
+  s2733 :: SBool = s10 /= s2732
+  s2734 :: SBool = ~ s2733
+  s2735 :: SBool = s2725 < s1
+  s2736 :: SBool = s2725 < s2614
+  s2737 :: SBool = s2735 | s2736
+  s2738 :: SWord8 = s2725 >>> 1
+  s2739 :: SWord8 = s14 | s2738
+  s2740 :: SWord8 = s16 & s2738
+  s2741 :: SWord8 = if s2737 then s2739 else s2740
+  s2742 :: SWord8 = s2741 >>> 1
+  s2743 :: SWord8 = s14 | s2742
+  s2744 :: SWord8 = s16 & s2742
+  s2745 :: SWord8 = if s2587 then s2743 else s2744
+  s2746 :: SWord8 = s2745 >>> 1
+  s2747 :: SWord8 = s14 | s2746
+  s2748 :: SWord8 = s16 & s2746
+  s2749 :: SWord8 = if s2609 then s2747 else s2748
+  s2750 :: SWord8 = s2749 >>> 1
+  s2751 :: SWord8 = s14 | s2750
+  s2752 :: SWord8 = s16 & s2750
+  s2753 :: SWord8 = if s2733 then s2751 else s2752
+  s2754 :: SWord8 = s1 + s2749
+  s2755 :: SBool = s2754 < s1
+  s2756 :: SBool = s2754 < s2749
+  s2757 :: SBool = s2755 | s2756
+  s2758 :: SWord8 = s2754 >>> 1
+  s2759 :: SWord8 = s14 | s2758
+  s2760 :: SWord8 = s16 & s2758
+  s2761 :: SWord8 = if s2757 then s2759 else s2760
+  s2762 :: SWord8 = if s2734 then s2753 else s2761
+  s2763 :: SWord8 = s1 + s2745
+  s2764 :: SBool = s2763 < s1
+  s2765 :: SBool = s2763 < s2745
+  s2766 :: SBool = s2764 | s2765
+  s2767 :: SWord8 = s2763 >>> 1
+  s2768 :: SWord8 = s14 | s2767
+  s2769 :: SWord8 = s16 & s2767
+  s2770 :: SWord8 = if s2766 then s2768 else s2769
+  s2771 :: SWord8 = s2770 >>> 1
+  s2772 :: SWord8 = s14 | s2771
+  s2773 :: SWord8 = s16 & s2771
+  s2774 :: SWord8 = if s2733 then s2772 else s2773
+  s2775 :: SWord8 = s1 + s2770
+  s2776 :: SBool = s2775 < s1
+  s2777 :: SBool = s2775 < s2770
+  s2778 :: SBool = s2776 | s2777
+  s2779 :: SWord8 = s2775 >>> 1
+  s2780 :: SWord8 = s14 | s2779
+  s2781 :: SWord8 = s16 & s2779
+  s2782 :: SWord8 = if s2778 then s2780 else s2781
+  s2783 :: SWord8 = if s2734 then s2774 else s2782
+  s2784 :: SWord8 = if s2610 then s2762 else s2783
+  s2785 :: SWord8 = s1 + s2741
+  s2786 :: SBool = s2785 < s1
+  s2787 :: SBool = s2785 < s2741
+  s2788 :: SBool = s2786 | s2787
+  s2789 :: SWord8 = s2785 >>> 1
+  s2790 :: SWord8 = s14 | s2789
+  s2791 :: SWord8 = s16 & s2789
+  s2792 :: SWord8 = if s2788 then s2790 else s2791
+  s2793 :: SWord8 = s2792 >>> 1
+  s2794 :: SWord8 = s14 | s2793
+  s2795 :: SWord8 = s16 & s2793
+  s2796 :: SWord8 = if s2609 then s2794 else s2795
+  s2797 :: SWord8 = s2796 >>> 1
+  s2798 :: SWord8 = s14 | s2797
+  s2799 :: SWord8 = s16 & s2797
+  s2800 :: SWord8 = if s2733 then s2798 else s2799
+  s2801 :: SWord8 = s1 + s2796
+  s2802 :: SBool = s2801 < s1
+  s2803 :: SBool = s2801 < s2796
+  s2804 :: SBool = s2802 | s2803
+  s2805 :: SWord8 = s2801 >>> 1
+  s2806 :: SWord8 = s14 | s2805
+  s2807 :: SWord8 = s16 & s2805
+  s2808 :: SWord8 = if s2804 then s2806 else s2807
+  s2809 :: SWord8 = if s2734 then s2800 else s2808
+  s2810 :: SWord8 = s1 + s2792
+  s2811 :: SBool = s2810 < s1
+  s2812 :: SBool = s2810 < s2792
+  s2813 :: SBool = s2811 | s2812
+  s2814 :: SWord8 = s2810 >>> 1
+  s2815 :: SWord8 = s14 | s2814
+  s2816 :: SWord8 = s16 & s2814
+  s2817 :: SWord8 = if s2813 then s2815 else s2816
+  s2818 :: SWord8 = s2817 >>> 1
+  s2819 :: SWord8 = s14 | s2818
+  s2820 :: SWord8 = s16 & s2818
+  s2821 :: SWord8 = if s2733 then s2819 else s2820
+  s2822 :: SWord8 = s1 + s2817
+  s2823 :: SBool = s2822 < s1
+  s2824 :: SBool = s2822 < s2817
+  s2825 :: SBool = s2823 | s2824
+  s2826 :: SWord8 = s2822 >>> 1
+  s2827 :: SWord8 = s14 | s2826
+  s2828 :: SWord8 = s16 & s2826
+  s2829 :: SWord8 = if s2825 then s2827 else s2828
+  s2830 :: SWord8 = if s2734 then s2821 else s2829
+  s2831 :: SWord8 = if s2610 then s2809 else s2830
+  s2832 :: SWord8 = if s2588 then s2784 else s2831
+  s2833 :: SWord8 = if s2080 then s2724 else s2832
+  s2834 :: SWord8 = s1 + s2595
+  s2835 :: SWord 1 = choose [0:0] s2834
+  s2836 :: SBool = s10 /= s2835
+  s2837 :: SWord8 = if s2836 then s2599 else s2600
+  s2838 :: SWord 1 = choose [0:0] s2837
+  s2839 :: SBool = s10 /= s2838
+  s2840 :: SWord8 = if s2839 then s2605 else s2606
+  s2841 :: SWord 1 = choose [0:0] s2840
+  s2842 :: SBool = s10 /= s2841
+  s2843 :: SBool = ~ s2842
+  s2844 :: SBool = s2834 < s1
+  s2845 :: SBool = s2834 < s2595
+  s2846 :: SBool = s2844 | s2845
+  s2847 :: SWord8 = s2834 >>> 1
+  s2848 :: SWord8 = s14 | s2847
+  s2849 :: SWord8 = s16 & s2847
+  s2850 :: SWord8 = if s2846 then s2848 else s2849
+  s2851 :: SWord 1 = choose [0:0] s2850
+  s2852 :: SBool = s10 /= s2851
+  s2853 :: SWord8 = s2837 >>> 1
+  s2854 :: SWord8 = s14 | s2853
+  s2855 :: SWord8 = s16 & s2853
+  s2856 :: SWord8 = if s2852 then s2854 else s2855
+  s2857 :: SWord 1 = choose [0:0] s2856
+  s2858 :: SBool = s10 /= s2857
+  s2859 :: SWord8 = s2840 >>> 1
+  s2860 :: SWord8 = s14 | s2859
+  s2861 :: SWord8 = s16 & s2859
+  s2862 :: SWord8 = if s2858 then s2860 else s2861
+  s2863 :: SWord 1 = choose [0:0] s2862
+  s2864 :: SBool = s10 /= s2863
+  s2865 :: SBool = ~ s2864
+  s2866 :: SWord8 = s2850 >>> 1
+  s2867 :: SWord8 = s14 | s2866
+  s2868 :: SWord8 = s16 & s2866
+  s2869 :: SWord8 = if s2079 then s2867 else s2868
+  s2870 :: SWord8 = s2869 >>> 1
+  s2871 :: SWord8 = s14 | s2870
+  s2872 :: SWord8 = s16 & s2870
+  s2873 :: SWord8 = if s2587 then s2871 else s2872
+  s2874 :: SWord8 = s2873 >>> 1
+  s2875 :: SWord8 = s14 | s2874
+  s2876 :: SWord8 = s16 & s2874
+  s2877 :: SWord8 = if s2842 then s2875 else s2876
+  s2878 :: SWord8 = s2877 >>> 1
+  s2879 :: SWord8 = s14 | s2878
+  s2880 :: SWord8 = s16 & s2878
+  s2881 :: SWord8 = if s2864 then s2879 else s2880
+  s2882 :: SWord8 = s1 + s2877
+  s2883 :: SBool = s2882 < s1
+  s2884 :: SBool = s2882 < s2877
+  s2885 :: SBool = s2883 | s2884
+  s2886 :: SWord8 = s2882 >>> 1
+  s2887 :: SWord8 = s14 | s2886
+  s2888 :: SWord8 = s16 & s2886
+  s2889 :: SWord8 = if s2885 then s2887 else s2888
+  s2890 :: SWord8 = if s2865 then s2881 else s2889
+  s2891 :: SWord8 = s1 + s2873
+  s2892 :: SBool = s2891 < s1
+  s2893 :: SBool = s2891 < s2873
+  s2894 :: SBool = s2892 | s2893
+  s2895 :: SWord8 = s2891 >>> 1
+  s2896 :: SWord8 = s14 | s2895
+  s2897 :: SWord8 = s16 & s2895
+  s2898 :: SWord8 = if s2894 then s2896 else s2897
+  s2899 :: SWord8 = s2898 >>> 1
+  s2900 :: SWord8 = s14 | s2899
+  s2901 :: SWord8 = s16 & s2899
+  s2902 :: SWord8 = if s2864 then s2900 else s2901
+  s2903 :: SWord8 = s1 + s2898
+  s2904 :: SBool = s2903 < s1
+  s2905 :: SBool = s2903 < s2898
+  s2906 :: SBool = s2904 | s2905
+  s2907 :: SWord8 = s2903 >>> 1
+  s2908 :: SWord8 = s14 | s2907
+  s2909 :: SWord8 = s16 & s2907
+  s2910 :: SWord8 = if s2906 then s2908 else s2909
+  s2911 :: SWord8 = if s2865 then s2902 else s2910
+  s2912 :: SWord8 = if s2843 then s2890 else s2911
+  s2913 :: SWord8 = s1 + s2869
+  s2914 :: SBool = s2913 < s1
+  s2915 :: SBool = s2913 < s2869
+  s2916 :: SBool = s2914 | s2915
+  s2917 :: SWord8 = s2913 >>> 1
+  s2918 :: SWord8 = s14 | s2917
+  s2919 :: SWord8 = s16 & s2917
+  s2920 :: SWord8 = if s2916 then s2918 else s2919
+  s2921 :: SWord8 = s2920 >>> 1
+  s2922 :: SWord8 = s14 | s2921
+  s2923 :: SWord8 = s16 & s2921
+  s2924 :: SWord8 = if s2842 then s2922 else s2923
+  s2925 :: SWord8 = s2924 >>> 1
+  s2926 :: SWord8 = s14 | s2925
+  s2927 :: SWord8 = s16 & s2925
+  s2928 :: SWord8 = if s2864 then s2926 else s2927
+  s2929 :: SWord8 = s1 + s2924
+  s2930 :: SBool = s2929 < s1
+  s2931 :: SBool = s2929 < s2924
+  s2932 :: SBool = s2930 | s2931
+  s2933 :: SWord8 = s2929 >>> 1
+  s2934 :: SWord8 = s14 | s2933
+  s2935 :: SWord8 = s16 & s2933
+  s2936 :: SWord8 = if s2932 then s2934 else s2935
+  s2937 :: SWord8 = if s2865 then s2928 else s2936
+  s2938 :: SWord8 = s1 + s2920
+  s2939 :: SBool = s2938 < s1
+  s2940 :: SBool = s2938 < s2920
+  s2941 :: SBool = s2939 | s2940
+  s2942 :: SWord8 = s2938 >>> 1
+  s2943 :: SWord8 = s14 | s2942
+  s2944 :: SWord8 = s16 & s2942
+  s2945 :: SWord8 = if s2941 then s2943 else s2944
+  s2946 :: SWord8 = s2945 >>> 1
+  s2947 :: SWord8 = s14 | s2946
+  s2948 :: SWord8 = s16 & s2946
+  s2949 :: SWord8 = if s2864 then s2947 else s2948
+  s2950 :: SWord8 = s1 + s2945
+  s2951 :: SBool = s2950 < s1
+  s2952 :: SBool = s2950 < s2945
+  s2953 :: SBool = s2951 | s2952
+  s2954 :: SWord8 = s2950 >>> 1
+  s2955 :: SWord8 = s14 | s2954
+  s2956 :: SWord8 = s16 & s2954
+  s2957 :: SWord8 = if s2953 then s2955 else s2956
+  s2958 :: SWord8 = if s2865 then s2949 else s2957
+  s2959 :: SWord8 = if s2843 then s2937 else s2958
+  s2960 :: SWord8 = if s2588 then s2912 else s2959
+  s2961 :: SWord8 = s1 + s2850
+  s2962 :: SWord 1 = choose [0:0] s2961
+  s2963 :: SBool = s10 /= s2962
+  s2964 :: SWord8 = if s2963 then s2854 else s2855
+  s2965 :: SWord 1 = choose [0:0] s2964
+  s2966 :: SBool = s10 /= s2965
+  s2967 :: SWord8 = if s2966 then s2860 else s2861
+  s2968 :: SWord 1 = choose [0:0] s2967
+  s2969 :: SBool = s10 /= s2968
+  s2970 :: SBool = ~ s2969
+  s2971 :: SBool = s2961 < s1
+  s2972 :: SBool = s2961 < s2850
+  s2973 :: SBool = s2971 | s2972
+  s2974 :: SWord8 = s2961 >>> 1
+  s2975 :: SWord8 = s14 | s2974
+  s2976 :: SWord8 = s16 & s2974
+  s2977 :: SWord8 = if s2973 then s2975 else s2976
+  s2978 :: SWord8 = s2977 >>> 1
+  s2979 :: SWord8 = s14 | s2978
+  s2980 :: SWord8 = s16 & s2978
+  s2981 :: SWord8 = if s2587 then s2979 else s2980
+  s2982 :: SWord8 = s2981 >>> 1
+  s2983 :: SWord8 = s14 | s2982
+  s2984 :: SWord8 = s16 & s2982
+  s2985 :: SWord8 = if s2842 then s2983 else s2984
+  s2986 :: SWord8 = s2985 >>> 1
+  s2987 :: SWord8 = s14 | s2986
+  s2988 :: SWord8 = s16 & s2986
+  s2989 :: SWord8 = if s2969 then s2987 else s2988
+  s2990 :: SWord8 = s1 + s2985
+  s2991 :: SBool = s2990 < s1
+  s2992 :: SBool = s2990 < s2985
+  s2993 :: SBool = s2991 | s2992
+  s2994 :: SWord8 = s2990 >>> 1
+  s2995 :: SWord8 = s14 | s2994
+  s2996 :: SWord8 = s16 & s2994
+  s2997 :: SWord8 = if s2993 then s2995 else s2996
+  s2998 :: SWord8 = if s2970 then s2989 else s2997
+  s2999 :: SWord8 = s1 + s2981
+  s3000 :: SBool = s2999 < s1
+  s3001 :: SBool = s2999 < s2981
+  s3002 :: SBool = s3000 | s3001
+  s3003 :: SWord8 = s2999 >>> 1
+  s3004 :: SWord8 = s14 | s3003
+  s3005 :: SWord8 = s16 & s3003
+  s3006 :: SWord8 = if s3002 then s3004 else s3005
+  s3007 :: SWord8 = s3006 >>> 1
+  s3008 :: SWord8 = s14 | s3007
+  s3009 :: SWord8 = s16 & s3007
+  s3010 :: SWord8 = if s2969 then s3008 else s3009
+  s3011 :: SWord8 = s1 + s3006
+  s3012 :: SBool = s3011 < s1
+  s3013 :: SBool = s3011 < s3006
+  s3014 :: SBool = s3012 | s3013
+  s3015 :: SWord8 = s3011 >>> 1
+  s3016 :: SWord8 = s14 | s3015
+  s3017 :: SWord8 = s16 & s3015
+  s3018 :: SWord8 = if s3014 then s3016 else s3017
+  s3019 :: SWord8 = if s2970 then s3010 else s3018
+  s3020 :: SWord8 = if s2843 then s2998 else s3019
+  s3021 :: SWord8 = s1 + s2977
+  s3022 :: SBool = s3021 < s1
+  s3023 :: SBool = s3021 < s2977
+  s3024 :: SBool = s3022 | s3023
+  s3025 :: SWord8 = s3021 >>> 1
+  s3026 :: SWord8 = s14 | s3025
+  s3027 :: SWord8 = s16 & s3025
+  s3028 :: SWord8 = if s3024 then s3026 else s3027
+  s3029 :: SWord8 = s3028 >>> 1
+  s3030 :: SWord8 = s14 | s3029
+  s3031 :: SWord8 = s16 & s3029
+  s3032 :: SWord8 = if s2842 then s3030 else s3031
+  s3033 :: SWord8 = s3032 >>> 1
+  s3034 :: SWord8 = s14 | s3033
+  s3035 :: SWord8 = s16 & s3033
+  s3036 :: SWord8 = if s2969 then s3034 else s3035
+  s3037 :: SWord8 = s1 + s3032
+  s3038 :: SBool = s3037 < s1
+  s3039 :: SBool = s3037 < s3032
+  s3040 :: SBool = s3038 | s3039
+  s3041 :: SWord8 = s3037 >>> 1
+  s3042 :: SWord8 = s14 | s3041
+  s3043 :: SWord8 = s16 & s3041
+  s3044 :: SWord8 = if s3040 then s3042 else s3043
+  s3045 :: SWord8 = if s2970 then s3036 else s3044
+  s3046 :: SWord8 = s1 + s3028
+  s3047 :: SBool = s3046 < s1
+  s3048 :: SBool = s3046 < s3028
+  s3049 :: SBool = s3047 | s3048
+  s3050 :: SWord8 = s3046 >>> 1
+  s3051 :: SWord8 = s14 | s3050
+  s3052 :: SWord8 = s16 & s3050
+  s3053 :: SWord8 = if s3049 then s3051 else s3052
+  s3054 :: SWord8 = s3053 >>> 1
+  s3055 :: SWord8 = s14 | s3054
+  s3056 :: SWord8 = s16 & s3054
+  s3057 :: SWord8 = if s2969 then s3055 else s3056
+  s3058 :: SWord8 = s1 + s3053
+  s3059 :: SBool = s3058 < s1
+  s3060 :: SBool = s3058 < s3053
+  s3061 :: SBool = s3059 | s3060
+  s3062 :: SWord8 = s3058 >>> 1
+  s3063 :: SWord8 = s14 | s3062
+  s3064 :: SWord8 = s16 & s3062
+  s3065 :: SWord8 = if s3061 then s3063 else s3064
+  s3066 :: SWord8 = if s2970 then s3057 else s3065
+  s3067 :: SWord8 = if s2843 then s3045 else s3066
+  s3068 :: SWord8 = if s2588 then s3020 else s3067
+  s3069 :: SWord8 = if s2080 then s2960 else s3068
+  s3070 :: SWord8 = if s2063 then s2833 else s3069
+  s3071 :: SWord8 = if s30 then s2578 else s3070
+  s3072 :: SWord8 = s1 + s2065
+  s3073 :: SWord 1 = choose [0:0] s3072
+  s3074 :: SBool = s10 /= s3073
+  s3075 :: SWord8 = if s3074 then s2069 else s2070
+  s3076 :: SWord 1 = choose [0:0] s3075
+  s3077 :: SBool = s10 /= s3076
+  s3078 :: SWord8 = if s3077 then s2075 else s2076
+  s3079 :: SWord 1 = choose [0:0] s3078
+  s3080 :: SBool = s10 /= s3079
+  s3081 :: SBool = ~ s3080
+  s3082 :: SBool = s3072 < s1
+  s3083 :: SBool = s3072 < s2065
+  s3084 :: SBool = s3082 | s3083
+  s3085 :: SWord8 = s3072 >>> 1
+  s3086 :: SWord8 = s14 | s3085
+  s3087 :: SWord8 = s16 & s3085
+  s3088 :: SWord8 = if s3084 then s3086 else s3087
+  s3089 :: SWord 1 = choose [0:0] s3088
+  s3090 :: SBool = s10 /= s3089
+  s3091 :: SWord8 = s3075 >>> 1
+  s3092 :: SWord8 = s14 | s3091
+  s3093 :: SWord8 = s16 & s3091
+  s3094 :: SWord8 = if s3090 then s3092 else s3093
+  s3095 :: SWord 1 = choose [0:0] s3094
+  s3096 :: SBool = s10 /= s3095
+  s3097 :: SWord8 = s3078 >>> 1
+  s3098 :: SWord8 = s14 | s3097
+  s3099 :: SWord8 = s16 & s3097
+  s3100 :: SWord8 = if s3096 then s3098 else s3099
+  s3101 :: SWord 1 = choose [0:0] s3100
+  s3102 :: SBool = s10 /= s3101
+  s3103 :: SBool = ~ s3102
+  s3104 :: SWord8 = s3088 >>> 1
+  s3105 :: SWord8 = s14 | s3104
+  s3106 :: SWord8 = s16 & s3104
+  s3107 :: SWord8 = if s29 then s3105 else s3106
+  s3108 :: SWord 1 = choose [0:0] s3107
+  s3109 :: SBool = s10 /= s3108
+  s3110 :: SWord8 = s3094 >>> 1
+  s3111 :: SWord8 = s14 | s3110
+  s3112 :: SWord8 = s16 & s3110
+  s3113 :: SWord8 = if s3109 then s3111 else s3112
+  s3114 :: SWord 1 = choose [0:0] s3113
+  s3115 :: SBool = s10 /= s3114
+  s3116 :: SWord8 = s3100 >>> 1
+  s3117 :: SWord8 = s14 | s3116
+  s3118 :: SWord8 = s16 & s3116
+  s3119 :: SWord8 = if s3115 then s3117 else s3118
+  s3120 :: SWord 1 = choose [0:0] s3119
+  s3121 :: SBool = s10 /= s3120
+  s3122 :: SBool = ~ s3121
+  s3123 :: SWord8 = s3107 >>> 1
+  s3124 :: SWord8 = s14 | s3123
+  s3125 :: SWord8 = s16 & s3123
+  s3126 :: SWord8 = if s2062 then s3124 else s3125
+  s3127 :: SWord 1 = choose [0:0] s3126
+  s3128 :: SBool = s10 /= s3127
+  s3129 :: SWord8 = s3113 >>> 1
+  s3130 :: SWord8 = s14 | s3129
+  s3131 :: SWord8 = s16 & s3129
+  s3132 :: SWord8 = if s3128 then s3130 else s3131
+  s3133 :: SWord 1 = choose [0:0] s3132
+  s3134 :: SBool = s10 /= s3133
+  s3135 :: SWord8 = s3119 >>> 1
+  s3136 :: SWord8 = s14 | s3135
+  s3137 :: SWord8 = s16 & s3135
+  s3138 :: SWord8 = if s3134 then s3136 else s3137
+  s3139 :: SWord 1 = choose [0:0] s3138
+  s3140 :: SBool = s10 /= s3139
+  s3141 :: SBool = ~ s3140
+  s3142 :: SWord8 = s3126 >>> 1
+  s3143 :: SWord8 = s14 | s3142
+  s3144 :: SWord8 = s16 & s3142
+  s3145 :: SWord8 = if s3080 then s3143 else s3144
+  s3146 :: SWord8 = s3145 >>> 1
+  s3147 :: SWord8 = s14 | s3146
+  s3148 :: SWord8 = s16 & s3146
+  s3149 :: SWord8 = if s3102 then s3147 else s3148
+  s3150 :: SWord8 = s3149 >>> 1
+  s3151 :: SWord8 = s14 | s3150
+  s3152 :: SWord8 = s16 & s3150
+  s3153 :: SWord8 = if s3121 then s3151 else s3152
+  s3154 :: SWord8 = s3153 >>> 1
+  s3155 :: SWord8 = s14 | s3154
+  s3156 :: SWord8 = s16 & s3154
+  s3157 :: SWord8 = if s3140 then s3155 else s3156
+  s3158 :: SWord8 = s1 + s3153
+  s3159 :: SBool = s3158 < s1
+  s3160 :: SBool = s3158 < s3153
+  s3161 :: SBool = s3159 | s3160
+  s3162 :: SWord8 = s3158 >>> 1
+  s3163 :: SWord8 = s14 | s3162
+  s3164 :: SWord8 = s16 & s3162
+  s3165 :: SWord8 = if s3161 then s3163 else s3164
+  s3166 :: SWord8 = if s3141 then s3157 else s3165
+  s3167 :: SWord8 = s1 + s3149
+  s3168 :: SBool = s3167 < s1
+  s3169 :: SBool = s3167 < s3149
+  s3170 :: SBool = s3168 | s3169
+  s3171 :: SWord8 = s3167 >>> 1
+  s3172 :: SWord8 = s14 | s3171
+  s3173 :: SWord8 = s16 & s3171
+  s3174 :: SWord8 = if s3170 then s3172 else s3173
+  s3175 :: SWord8 = s3174 >>> 1
+  s3176 :: SWord8 = s14 | s3175
+  s3177 :: SWord8 = s16 & s3175
+  s3178 :: SWord8 = if s3140 then s3176 else s3177
+  s3179 :: SWord8 = s1 + s3174
+  s3180 :: SBool = s3179 < s1
+  s3181 :: SBool = s3179 < s3174
+  s3182 :: SBool = s3180 | s3181
+  s3183 :: SWord8 = s3179 >>> 1
+  s3184 :: SWord8 = s14 | s3183
+  s3185 :: SWord8 = s16 & s3183
+  s3186 :: SWord8 = if s3182 then s3184 else s3185
+  s3187 :: SWord8 = if s3141 then s3178 else s3186
+  s3188 :: SWord8 = if s3122 then s3166 else s3187
+  s3189 :: SWord8 = s1 + s3145
+  s3190 :: SBool = s3189 < s1
+  s3191 :: SBool = s3189 < s3145
+  s3192 :: SBool = s3190 | s3191
+  s3193 :: SWord8 = s3189 >>> 1
+  s3194 :: SWord8 = s14 | s3193
+  s3195 :: SWord8 = s16 & s3193
+  s3196 :: SWord8 = if s3192 then s3194 else s3195
+  s3197 :: SWord8 = s3196 >>> 1
+  s3198 :: SWord8 = s14 | s3197
+  s3199 :: SWord8 = s16 & s3197
+  s3200 :: SWord8 = if s3121 then s3198 else s3199
+  s3201 :: SWord8 = s3200 >>> 1
+  s3202 :: SWord8 = s14 | s3201
+  s3203 :: SWord8 = s16 & s3201
+  s3204 :: SWord8 = if s3140 then s3202 else s3203
+  s3205 :: SWord8 = s1 + s3200
+  s3206 :: SBool = s3205 < s1
+  s3207 :: SBool = s3205 < s3200
+  s3208 :: SBool = s3206 | s3207
+  s3209 :: SWord8 = s3205 >>> 1
+  s3210 :: SWord8 = s14 | s3209
+  s3211 :: SWord8 = s16 & s3209
+  s3212 :: SWord8 = if s3208 then s3210 else s3211
+  s3213 :: SWord8 = if s3141 then s3204 else s3212
+  s3214 :: SWord8 = s1 + s3196
+  s3215 :: SBool = s3214 < s1
+  s3216 :: SBool = s3214 < s3196
+  s3217 :: SBool = s3215 | s3216
+  s3218 :: SWord8 = s3214 >>> 1
+  s3219 :: SWord8 = s14 | s3218
+  s3220 :: SWord8 = s16 & s3218
+  s3221 :: SWord8 = if s3217 then s3219 else s3220
+  s3222 :: SWord8 = s3221 >>> 1
+  s3223 :: SWord8 = s14 | s3222
+  s3224 :: SWord8 = s16 & s3222
+  s3225 :: SWord8 = if s3140 then s3223 else s3224
+  s3226 :: SWord8 = s1 + s3221
+  s3227 :: SBool = s3226 < s1
+  s3228 :: SBool = s3226 < s3221
+  s3229 :: SBool = s3227 | s3228
+  s3230 :: SWord8 = s3226 >>> 1
+  s3231 :: SWord8 = s14 | s3230
+  s3232 :: SWord8 = s16 & s3230
+  s3233 :: SWord8 = if s3229 then s3231 else s3232
+  s3234 :: SWord8 = if s3141 then s3225 else s3233
+  s3235 :: SWord8 = if s3122 then s3213 else s3234
+  s3236 :: SWord8 = if s3103 then s3188 else s3235
+  s3237 :: SWord8 = s1 + s3126
+  s3238 :: SWord 1 = choose [0:0] s3237
+  s3239 :: SBool = s10 /= s3238
+  s3240 :: SWord8 = if s3239 then s3130 else s3131
+  s3241 :: SWord 1 = choose [0:0] s3240
+  s3242 :: SBool = s10 /= s3241
+  s3243 :: SWord8 = if s3242 then s3136 else s3137
+  s3244 :: SWord 1 = choose [0:0] s3243
+  s3245 :: SBool = s10 /= s3244
+  s3246 :: SBool = ~ s3245
+  s3247 :: SBool = s3237 < s1
+  s3248 :: SBool = s3237 < s3126
+  s3249 :: SBool = s3247 | s3248
+  s3250 :: SWord8 = s3237 >>> 1
+  s3251 :: SWord8 = s14 | s3250
+  s3252 :: SWord8 = s16 & s3250
+  s3253 :: SWord8 = if s3249 then s3251 else s3252
+  s3254 :: SWord8 = s3253 >>> 1
+  s3255 :: SWord8 = s14 | s3254
+  s3256 :: SWord8 = s16 & s3254
+  s3257 :: SWord8 = if s3102 then s3255 else s3256
+  s3258 :: SWord8 = s3257 >>> 1
+  s3259 :: SWord8 = s14 | s3258
+  s3260 :: SWord8 = s16 & s3258
+  s3261 :: SWord8 = if s3121 then s3259 else s3260
+  s3262 :: SWord8 = s3261 >>> 1
+  s3263 :: SWord8 = s14 | s3262
+  s3264 :: SWord8 = s16 & s3262
+  s3265 :: SWord8 = if s3245 then s3263 else s3264
+  s3266 :: SWord8 = s1 + s3261
+  s3267 :: SBool = s3266 < s1
+  s3268 :: SBool = s3266 < s3261
+  s3269 :: SBool = s3267 | s3268
+  s3270 :: SWord8 = s3266 >>> 1
+  s3271 :: SWord8 = s14 | s3270
+  s3272 :: SWord8 = s16 & s3270
+  s3273 :: SWord8 = if s3269 then s3271 else s3272
+  s3274 :: SWord8 = if s3246 then s3265 else s3273
+  s3275 :: SWord8 = s1 + s3257
+  s3276 :: SBool = s3275 < s1
+  s3277 :: SBool = s3275 < s3257
+  s3278 :: SBool = s3276 | s3277
+  s3279 :: SWord8 = s3275 >>> 1
+  s3280 :: SWord8 = s14 | s3279
+  s3281 :: SWord8 = s16 & s3279
+  s3282 :: SWord8 = if s3278 then s3280 else s3281
+  s3283 :: SWord8 = s3282 >>> 1
+  s3284 :: SWord8 = s14 | s3283
+  s3285 :: SWord8 = s16 & s3283
+  s3286 :: SWord8 = if s3245 then s3284 else s3285
+  s3287 :: SWord8 = s1 + s3282
+  s3288 :: SBool = s3287 < s1
+  s3289 :: SBool = s3287 < s3282
+  s3290 :: SBool = s3288 | s3289
+  s3291 :: SWord8 = s3287 >>> 1
+  s3292 :: SWord8 = s14 | s3291
+  s3293 :: SWord8 = s16 & s3291
+  s3294 :: SWord8 = if s3290 then s3292 else s3293
+  s3295 :: SWord8 = if s3246 then s3286 else s3294
+  s3296 :: SWord8 = if s3122 then s3274 else s3295
+  s3297 :: SWord8 = s1 + s3253
+  s3298 :: SBool = s3297 < s1
+  s3299 :: SBool = s3297 < s3253
+  s3300 :: SBool = s3298 | s3299
+  s3301 :: SWord8 = s3297 >>> 1
+  s3302 :: SWord8 = s14 | s3301
+  s3303 :: SWord8 = s16 & s3301
+  s3304 :: SWord8 = if s3300 then s3302 else s3303
+  s3305 :: SWord8 = s3304 >>> 1
+  s3306 :: SWord8 = s14 | s3305
+  s3307 :: SWord8 = s16 & s3305
+  s3308 :: SWord8 = if s3121 then s3306 else s3307
+  s3309 :: SWord8 = s3308 >>> 1
+  s3310 :: SWord8 = s14 | s3309
+  s3311 :: SWord8 = s16 & s3309
+  s3312 :: SWord8 = if s3245 then s3310 else s3311
+  s3313 :: SWord8 = s1 + s3308
+  s3314 :: SBool = s3313 < s1
+  s3315 :: SBool = s3313 < s3308
+  s3316 :: SBool = s3314 | s3315
+  s3317 :: SWord8 = s3313 >>> 1
+  s3318 :: SWord8 = s14 | s3317
+  s3319 :: SWord8 = s16 & s3317
+  s3320 :: SWord8 = if s3316 then s3318 else s3319
+  s3321 :: SWord8 = if s3246 then s3312 else s3320
+  s3322 :: SWord8 = s1 + s3304
+  s3323 :: SBool = s3322 < s1
+  s3324 :: SBool = s3322 < s3304
+  s3325 :: SBool = s3323 | s3324
+  s3326 :: SWord8 = s3322 >>> 1
+  s3327 :: SWord8 = s14 | s3326
+  s3328 :: SWord8 = s16 & s3326
+  s3329 :: SWord8 = if s3325 then s3327 else s3328
+  s3330 :: SWord8 = s3329 >>> 1
+  s3331 :: SWord8 = s14 | s3330
+  s3332 :: SWord8 = s16 & s3330
+  s3333 :: SWord8 = if s3245 then s3331 else s3332
+  s3334 :: SWord8 = s1 + s3329
+  s3335 :: SBool = s3334 < s1
+  s3336 :: SBool = s3334 < s3329
+  s3337 :: SBool = s3335 | s3336
+  s3338 :: SWord8 = s3334 >>> 1
+  s3339 :: SWord8 = s14 | s3338
+  s3340 :: SWord8 = s16 & s3338
+  s3341 :: SWord8 = if s3337 then s3339 else s3340
+  s3342 :: SWord8 = if s3246 then s3333 else s3341
+  s3343 :: SWord8 = if s3122 then s3321 else s3342
+  s3344 :: SWord8 = if s3103 then s3296 else s3343
+  s3345 :: SWord8 = if s3081 then s3236 else s3344
+  s3346 :: SWord8 = s1 + s3107
+  s3347 :: SWord 1 = choose [0:0] s3346
+  s3348 :: SBool = s10 /= s3347
+  s3349 :: SWord8 = if s3348 then s3111 else s3112
+  s3350 :: SWord 1 = choose [0:0] s3349
+  s3351 :: SBool = s10 /= s3350
+  s3352 :: SWord8 = if s3351 then s3117 else s3118
+  s3353 :: SWord 1 = choose [0:0] s3352
+  s3354 :: SBool = s10 /= s3353
+  s3355 :: SBool = ~ s3354
+  s3356 :: SBool = s3346 < s1
+  s3357 :: SBool = s3346 < s3107
+  s3358 :: SBool = s3356 | s3357
+  s3359 :: SWord8 = s3346 >>> 1
+  s3360 :: SWord8 = s14 | s3359
+  s3361 :: SWord8 = s16 & s3359
+  s3362 :: SWord8 = if s3358 then s3360 else s3361
+  s3363 :: SWord 1 = choose [0:0] s3362
+  s3364 :: SBool = s10 /= s3363
+  s3365 :: SWord8 = s3349 >>> 1
+  s3366 :: SWord8 = s14 | s3365
+  s3367 :: SWord8 = s16 & s3365
+  s3368 :: SWord8 = if s3364 then s3366 else s3367
+  s3369 :: SWord 1 = choose [0:0] s3368
+  s3370 :: SBool = s10 /= s3369
+  s3371 :: SWord8 = s3352 >>> 1
+  s3372 :: SWord8 = s14 | s3371
+  s3373 :: SWord8 = s16 & s3371
+  s3374 :: SWord8 = if s3370 then s3372 else s3373
+  s3375 :: SWord 1 = choose [0:0] s3374
+  s3376 :: SBool = s10 /= s3375
+  s3377 :: SBool = ~ s3376
+  s3378 :: SWord8 = s3362 >>> 1
+  s3379 :: SWord8 = s14 | s3378
+  s3380 :: SWord8 = s16 & s3378
+  s3381 :: SWord8 = if s3080 then s3379 else s3380
+  s3382 :: SWord8 = s3381 >>> 1
+  s3383 :: SWord8 = s14 | s3382
+  s3384 :: SWord8 = s16 & s3382
+  s3385 :: SWord8 = if s3102 then s3383 else s3384
+  s3386 :: SWord8 = s3385 >>> 1
+  s3387 :: SWord8 = s14 | s3386
+  s3388 :: SWord8 = s16 & s3386
+  s3389 :: SWord8 = if s3354 then s3387 else s3388
+  s3390 :: SWord8 = s3389 >>> 1
+  s3391 :: SWord8 = s14 | s3390
+  s3392 :: SWord8 = s16 & s3390
+  s3393 :: SWord8 = if s3376 then s3391 else s3392
+  s3394 :: SWord8 = s1 + s3389
+  s3395 :: SBool = s3394 < s1
+  s3396 :: SBool = s3394 < s3389
+  s3397 :: SBool = s3395 | s3396
+  s3398 :: SWord8 = s3394 >>> 1
+  s3399 :: SWord8 = s14 | s3398
+  s3400 :: SWord8 = s16 & s3398
+  s3401 :: SWord8 = if s3397 then s3399 else s3400
+  s3402 :: SWord8 = if s3377 then s3393 else s3401
+  s3403 :: SWord8 = s1 + s3385
+  s3404 :: SBool = s3403 < s1
+  s3405 :: SBool = s3403 < s3385
+  s3406 :: SBool = s3404 | s3405
+  s3407 :: SWord8 = s3403 >>> 1
+  s3408 :: SWord8 = s14 | s3407
+  s3409 :: SWord8 = s16 & s3407
+  s3410 :: SWord8 = if s3406 then s3408 else s3409
+  s3411 :: SWord8 = s3410 >>> 1
+  s3412 :: SWord8 = s14 | s3411
+  s3413 :: SWord8 = s16 & s3411
+  s3414 :: SWord8 = if s3376 then s3412 else s3413
+  s3415 :: SWord8 = s1 + s3410
+  s3416 :: SBool = s3415 < s1
+  s3417 :: SBool = s3415 < s3410
+  s3418 :: SBool = s3416 | s3417
+  s3419 :: SWord8 = s3415 >>> 1
+  s3420 :: SWord8 = s14 | s3419
+  s3421 :: SWord8 = s16 & s3419
+  s3422 :: SWord8 = if s3418 then s3420 else s3421
+  s3423 :: SWord8 = if s3377 then s3414 else s3422
+  s3424 :: SWord8 = if s3355 then s3402 else s3423
+  s3425 :: SWord8 = s1 + s3381
+  s3426 :: SBool = s3425 < s1
+  s3427 :: SBool = s3425 < s3381
+  s3428 :: SBool = s3426 | s3427
+  s3429 :: SWord8 = s3425 >>> 1
+  s3430 :: SWord8 = s14 | s3429
+  s3431 :: SWord8 = s16 & s3429
+  s3432 :: SWord8 = if s3428 then s3430 else s3431
+  s3433 :: SWord8 = s3432 >>> 1
+  s3434 :: SWord8 = s14 | s3433
+  s3435 :: SWord8 = s16 & s3433
+  s3436 :: SWord8 = if s3354 then s3434 else s3435
+  s3437 :: SWord8 = s3436 >>> 1
+  s3438 :: SWord8 = s14 | s3437
+  s3439 :: SWord8 = s16 & s3437
+  s3440 :: SWord8 = if s3376 then s3438 else s3439
+  s3441 :: SWord8 = s1 + s3436
+  s3442 :: SBool = s3441 < s1
+  s3443 :: SBool = s3441 < s3436
+  s3444 :: SBool = s3442 | s3443
+  s3445 :: SWord8 = s3441 >>> 1
+  s3446 :: SWord8 = s14 | s3445
+  s3447 :: SWord8 = s16 & s3445
+  s3448 :: SWord8 = if s3444 then s3446 else s3447
+  s3449 :: SWord8 = if s3377 then s3440 else s3448
+  s3450 :: SWord8 = s1 + s3432
+  s3451 :: SBool = s3450 < s1
+  s3452 :: SBool = s3450 < s3432
+  s3453 :: SBool = s3451 | s3452
+  s3454 :: SWord8 = s3450 >>> 1
+  s3455 :: SWord8 = s14 | s3454
+  s3456 :: SWord8 = s16 & s3454
+  s3457 :: SWord8 = if s3453 then s3455 else s3456
+  s3458 :: SWord8 = s3457 >>> 1
+  s3459 :: SWord8 = s14 | s3458
+  s3460 :: SWord8 = s16 & s3458
+  s3461 :: SWord8 = if s3376 then s3459 else s3460
+  s3462 :: SWord8 = s1 + s3457
+  s3463 :: SBool = s3462 < s1
+  s3464 :: SBool = s3462 < s3457
+  s3465 :: SBool = s3463 | s3464
+  s3466 :: SWord8 = s3462 >>> 1
+  s3467 :: SWord8 = s14 | s3466
+  s3468 :: SWord8 = s16 & s3466
+  s3469 :: SWord8 = if s3465 then s3467 else s3468
+  s3470 :: SWord8 = if s3377 then s3461 else s3469
+  s3471 :: SWord8 = if s3355 then s3449 else s3470
+  s3472 :: SWord8 = if s3103 then s3424 else s3471
+  s3473 :: SWord8 = s1 + s3362
+  s3474 :: SWord 1 = choose [0:0] s3473
+  s3475 :: SBool = s10 /= s3474
+  s3476 :: SWord8 = if s3475 then s3366 else s3367
+  s3477 :: SWord 1 = choose [0:0] s3476
+  s3478 :: SBool = s10 /= s3477
+  s3479 :: SWord8 = if s3478 then s3372 else s3373
+  s3480 :: SWord 1 = choose [0:0] s3479
+  s3481 :: SBool = s10 /= s3480
+  s3482 :: SBool = ~ s3481
+  s3483 :: SBool = s3473 < s1
+  s3484 :: SBool = s3473 < s3362
+  s3485 :: SBool = s3483 | s3484
+  s3486 :: SWord8 = s3473 >>> 1
+  s3487 :: SWord8 = s14 | s3486
+  s3488 :: SWord8 = s16 & s3486
+  s3489 :: SWord8 = if s3485 then s3487 else s3488
+  s3490 :: SWord8 = s3489 >>> 1
+  s3491 :: SWord8 = s14 | s3490
+  s3492 :: SWord8 = s16 & s3490
+  s3493 :: SWord8 = if s3102 then s3491 else s3492
+  s3494 :: SWord8 = s3493 >>> 1
+  s3495 :: SWord8 = s14 | s3494
+  s3496 :: SWord8 = s16 & s3494
+  s3497 :: SWord8 = if s3354 then s3495 else s3496
+  s3498 :: SWord8 = s3497 >>> 1
+  s3499 :: SWord8 = s14 | s3498
+  s3500 :: SWord8 = s16 & s3498
+  s3501 :: SWord8 = if s3481 then s3499 else s3500
+  s3502 :: SWord8 = s1 + s3497
+  s3503 :: SBool = s3502 < s1
+  s3504 :: SBool = s3502 < s3497
+  s3505 :: SBool = s3503 | s3504
+  s3506 :: SWord8 = s3502 >>> 1
+  s3507 :: SWord8 = s14 | s3506
+  s3508 :: SWord8 = s16 & s3506
+  s3509 :: SWord8 = if s3505 then s3507 else s3508
+  s3510 :: SWord8 = if s3482 then s3501 else s3509
+  s3511 :: SWord8 = s1 + s3493
+  s3512 :: SBool = s3511 < s1
+  s3513 :: SBool = s3511 < s3493
+  s3514 :: SBool = s3512 | s3513
+  s3515 :: SWord8 = s3511 >>> 1
+  s3516 :: SWord8 = s14 | s3515
+  s3517 :: SWord8 = s16 & s3515
+  s3518 :: SWord8 = if s3514 then s3516 else s3517
+  s3519 :: SWord8 = s3518 >>> 1
+  s3520 :: SWord8 = s14 | s3519
+  s3521 :: SWord8 = s16 & s3519
+  s3522 :: SWord8 = if s3481 then s3520 else s3521
+  s3523 :: SWord8 = s1 + s3518
+  s3524 :: SBool = s3523 < s1
+  s3525 :: SBool = s3523 < s3518
+  s3526 :: SBool = s3524 | s3525
+  s3527 :: SWord8 = s3523 >>> 1
+  s3528 :: SWord8 = s14 | s3527
+  s3529 :: SWord8 = s16 & s3527
+  s3530 :: SWord8 = if s3526 then s3528 else s3529
+  s3531 :: SWord8 = if s3482 then s3522 else s3530
+  s3532 :: SWord8 = if s3355 then s3510 else s3531
+  s3533 :: SWord8 = s1 + s3489
+  s3534 :: SBool = s3533 < s1
+  s3535 :: SBool = s3533 < s3489
+  s3536 :: SBool = s3534 | s3535
+  s3537 :: SWord8 = s3533 >>> 1
+  s3538 :: SWord8 = s14 | s3537
+  s3539 :: SWord8 = s16 & s3537
+  s3540 :: SWord8 = if s3536 then s3538 else s3539
+  s3541 :: SWord8 = s3540 >>> 1
+  s3542 :: SWord8 = s14 | s3541
+  s3543 :: SWord8 = s16 & s3541
+  s3544 :: SWord8 = if s3354 then s3542 else s3543
+  s3545 :: SWord8 = s3544 >>> 1
+  s3546 :: SWord8 = s14 | s3545
+  s3547 :: SWord8 = s16 & s3545
+  s3548 :: SWord8 = if s3481 then s3546 else s3547
+  s3549 :: SWord8 = s1 + s3544
+  s3550 :: SBool = s3549 < s1
+  s3551 :: SBool = s3549 < s3544
+  s3552 :: SBool = s3550 | s3551
+  s3553 :: SWord8 = s3549 >>> 1
+  s3554 :: SWord8 = s14 | s3553
+  s3555 :: SWord8 = s16 & s3553
+  s3556 :: SWord8 = if s3552 then s3554 else s3555
+  s3557 :: SWord8 = if s3482 then s3548 else s3556
+  s3558 :: SWord8 = s1 + s3540
+  s3559 :: SBool = s3558 < s1
+  s3560 :: SBool = s3558 < s3540
+  s3561 :: SBool = s3559 | s3560
+  s3562 :: SWord8 = s3558 >>> 1
+  s3563 :: SWord8 = s14 | s3562
+  s3564 :: SWord8 = s16 & s3562
+  s3565 :: SWord8 = if s3561 then s3563 else s3564
+  s3566 :: SWord8 = s3565 >>> 1
+  s3567 :: SWord8 = s14 | s3566
+  s3568 :: SWord8 = s16 & s3566
+  s3569 :: SWord8 = if s3481 then s3567 else s3568
+  s3570 :: SWord8 = s1 + s3565
+  s3571 :: SBool = s3570 < s1
+  s3572 :: SBool = s3570 < s3565
+  s3573 :: SBool = s3571 | s3572
+  s3574 :: SWord8 = s3570 >>> 1
+  s3575 :: SWord8 = s14 | s3574
+  s3576 :: SWord8 = s16 & s3574
+  s3577 :: SWord8 = if s3573 then s3575 else s3576
+  s3578 :: SWord8 = if s3482 then s3569 else s3577
+  s3579 :: SWord8 = if s3355 then s3557 else s3578
+  s3580 :: SWord8 = if s3103 then s3532 else s3579
+  s3581 :: SWord8 = if s3081 then s3472 else s3580
+  s3582 :: SWord8 = if s2063 then s3345 else s3581
+  s3583 :: SWord8 = s1 + s3088
+  s3584 :: SWord 1 = choose [0:0] s3583
+  s3585 :: SBool = s10 /= s3584
+  s3586 :: SWord8 = if s3585 then s3092 else s3093
+  s3587 :: SWord 1 = choose [0:0] s3586
+  s3588 :: SBool = s10 /= s3587
+  s3589 :: SWord8 = if s3588 then s3098 else s3099
+  s3590 :: SWord 1 = choose [0:0] s3589
+  s3591 :: SBool = s10 /= s3590
+  s3592 :: SBool = ~ s3591
+  s3593 :: SBool = s3583 < s1
+  s3594 :: SBool = s3583 < s3088
+  s3595 :: SBool = s3593 | s3594
+  s3596 :: SWord8 = s3583 >>> 1
+  s3597 :: SWord8 = s14 | s3596
+  s3598 :: SWord8 = s16 & s3596
+  s3599 :: SWord8 = if s3595 then s3597 else s3598
+  s3600 :: SWord 1 = choose [0:0] s3599
+  s3601 :: SBool = s10 /= s3600
+  s3602 :: SWord8 = s3586 >>> 1
+  s3603 :: SWord8 = s14 | s3602
+  s3604 :: SWord8 = s16 & s3602
+  s3605 :: SWord8 = if s3601 then s3603 else s3604
+  s3606 :: SWord 1 = choose [0:0] s3605
+  s3607 :: SBool = s10 /= s3606
+  s3608 :: SWord8 = s3589 >>> 1
+  s3609 :: SWord8 = s14 | s3608
+  s3610 :: SWord8 = s16 & s3608
+  s3611 :: SWord8 = if s3607 then s3609 else s3610
+  s3612 :: SWord 1 = choose [0:0] s3611
+  s3613 :: SBool = s10 /= s3612
+  s3614 :: SBool = ~ s3613
+  s3615 :: SWord8 = s3599 >>> 1
+  s3616 :: SWord8 = s14 | s3615
+  s3617 :: SWord8 = s16 & s3615
+  s3618 :: SWord8 = if s2062 then s3616 else s3617
+  s3619 :: SWord 1 = choose [0:0] s3618
+  s3620 :: SBool = s10 /= s3619
+  s3621 :: SWord8 = s3605 >>> 1
+  s3622 :: SWord8 = s14 | s3621
+  s3623 :: SWord8 = s16 & s3621
+  s3624 :: SWord8 = if s3620 then s3622 else s3623
+  s3625 :: SWord 1 = choose [0:0] s3624
+  s3626 :: SBool = s10 /= s3625
+  s3627 :: SWord8 = s3611 >>> 1
+  s3628 :: SWord8 = s14 | s3627
+  s3629 :: SWord8 = s16 & s3627
+  s3630 :: SWord8 = if s3626 then s3628 else s3629
+  s3631 :: SWord 1 = choose [0:0] s3630
+  s3632 :: SBool = s10 /= s3631
+  s3633 :: SBool = ~ s3632
+  s3634 :: SWord8 = s3618 >>> 1
+  s3635 :: SWord8 = s14 | s3634
+  s3636 :: SWord8 = s16 & s3634
+  s3637 :: SWord8 = if s3080 then s3635 else s3636
+  s3638 :: SWord8 = s3637 >>> 1
+  s3639 :: SWord8 = s14 | s3638
+  s3640 :: SWord8 = s16 & s3638
+  s3641 :: SWord8 = if s3591 then s3639 else s3640
+  s3642 :: SWord8 = s3641 >>> 1
+  s3643 :: SWord8 = s14 | s3642
+  s3644 :: SWord8 = s16 & s3642
+  s3645 :: SWord8 = if s3613 then s3643 else s3644
+  s3646 :: SWord8 = s3645 >>> 1
+  s3647 :: SWord8 = s14 | s3646
+  s3648 :: SWord8 = s16 & s3646
+  s3649 :: SWord8 = if s3632 then s3647 else s3648
+  s3650 :: SWord8 = s1 + s3645
+  s3651 :: SBool = s3650 < s1
+  s3652 :: SBool = s3650 < s3645
+  s3653 :: SBool = s3651 | s3652
+  s3654 :: SWord8 = s3650 >>> 1
+  s3655 :: SWord8 = s14 | s3654
+  s3656 :: SWord8 = s16 & s3654
+  s3657 :: SWord8 = if s3653 then s3655 else s3656
+  s3658 :: SWord8 = if s3633 then s3649 else s3657
+  s3659 :: SWord8 = s1 + s3641
+  s3660 :: SBool = s3659 < s1
+  s3661 :: SBool = s3659 < s3641
+  s3662 :: SBool = s3660 | s3661
+  s3663 :: SWord8 = s3659 >>> 1
+  s3664 :: SWord8 = s14 | s3663
+  s3665 :: SWord8 = s16 & s3663
+  s3666 :: SWord8 = if s3662 then s3664 else s3665
+  s3667 :: SWord8 = s3666 >>> 1
+  s3668 :: SWord8 = s14 | s3667
+  s3669 :: SWord8 = s16 & s3667
+  s3670 :: SWord8 = if s3632 then s3668 else s3669
+  s3671 :: SWord8 = s1 + s3666
+  s3672 :: SBool = s3671 < s1
+  s3673 :: SBool = s3671 < s3666
+  s3674 :: SBool = s3672 | s3673
+  s3675 :: SWord8 = s3671 >>> 1
+  s3676 :: SWord8 = s14 | s3675
+  s3677 :: SWord8 = s16 & s3675
+  s3678 :: SWord8 = if s3674 then s3676 else s3677
+  s3679 :: SWord8 = if s3633 then s3670 else s3678
+  s3680 :: SWord8 = if s3614 then s3658 else s3679
+  s3681 :: SWord8 = s1 + s3637
+  s3682 :: SBool = s3681 < s1
+  s3683 :: SBool = s3681 < s3637
+  s3684 :: SBool = s3682 | s3683
+  s3685 :: SWord8 = s3681 >>> 1
+  s3686 :: SWord8 = s14 | s3685
+  s3687 :: SWord8 = s16 & s3685
+  s3688 :: SWord8 = if s3684 then s3686 else s3687
+  s3689 :: SWord8 = s3688 >>> 1
+  s3690 :: SWord8 = s14 | s3689
+  s3691 :: SWord8 = s16 & s3689
+  s3692 :: SWord8 = if s3613 then s3690 else s3691
+  s3693 :: SWord8 = s3692 >>> 1
+  s3694 :: SWord8 = s14 | s3693
+  s3695 :: SWord8 = s16 & s3693
+  s3696 :: SWord8 = if s3632 then s3694 else s3695
+  s3697 :: SWord8 = s1 + s3692
+  s3698 :: SBool = s3697 < s1
+  s3699 :: SBool = s3697 < s3692
+  s3700 :: SBool = s3698 | s3699
+  s3701 :: SWord8 = s3697 >>> 1
+  s3702 :: SWord8 = s14 | s3701
+  s3703 :: SWord8 = s16 & s3701
+  s3704 :: SWord8 = if s3700 then s3702 else s3703
+  s3705 :: SWord8 = if s3633 then s3696 else s3704
+  s3706 :: SWord8 = s1 + s3688
+  s3707 :: SBool = s3706 < s1
+  s3708 :: SBool = s3706 < s3688
+  s3709 :: SBool = s3707 | s3708
+  s3710 :: SWord8 = s3706 >>> 1
+  s3711 :: SWord8 = s14 | s3710
+  s3712 :: SWord8 = s16 & s3710
+  s3713 :: SWord8 = if s3709 then s3711 else s3712
+  s3714 :: SWord8 = s3713 >>> 1
+  s3715 :: SWord8 = s14 | s3714
+  s3716 :: SWord8 = s16 & s3714
+  s3717 :: SWord8 = if s3632 then s3715 else s3716
+  s3718 :: SWord8 = s1 + s3713
+  s3719 :: SBool = s3718 < s1
+  s3720 :: SBool = s3718 < s3713
+  s3721 :: SBool = s3719 | s3720
+  s3722 :: SWord8 = s3718 >>> 1
+  s3723 :: SWord8 = s14 | s3722
+  s3724 :: SWord8 = s16 & s3722
+  s3725 :: SWord8 = if s3721 then s3723 else s3724
+  s3726 :: SWord8 = if s3633 then s3717 else s3725
+  s3727 :: SWord8 = if s3614 then s3705 else s3726
+  s3728 :: SWord8 = if s3592 then s3680 else s3727
+  s3729 :: SWord8 = s1 + s3618
+  s3730 :: SWord 1 = choose [0:0] s3729
+  s3731 :: SBool = s10 /= s3730
+  s3732 :: SWord8 = if s3731 then s3622 else s3623
+  s3733 :: SWord 1 = choose [0:0] s3732
+  s3734 :: SBool = s10 /= s3733
+  s3735 :: SWord8 = if s3734 then s3628 else s3629
+  s3736 :: SWord 1 = choose [0:0] s3735
+  s3737 :: SBool = s10 /= s3736
+  s3738 :: SBool = ~ s3737
+  s3739 :: SBool = s3729 < s1
+  s3740 :: SBool = s3729 < s3618
+  s3741 :: SBool = s3739 | s3740
+  s3742 :: SWord8 = s3729 >>> 1
+  s3743 :: SWord8 = s14 | s3742
+  s3744 :: SWord8 = s16 & s3742
+  s3745 :: SWord8 = if s3741 then s3743 else s3744
+  s3746 :: SWord8 = s3745 >>> 1
+  s3747 :: SWord8 = s14 | s3746
+  s3748 :: SWord8 = s16 & s3746
+  s3749 :: SWord8 = if s3591 then s3747 else s3748
+  s3750 :: SWord8 = s3749 >>> 1
+  s3751 :: SWord8 = s14 | s3750
+  s3752 :: SWord8 = s16 & s3750
+  s3753 :: SWord8 = if s3613 then s3751 else s3752
+  s3754 :: SWord8 = s3753 >>> 1
+  s3755 :: SWord8 = s14 | s3754
+  s3756 :: SWord8 = s16 & s3754
+  s3757 :: SWord8 = if s3737 then s3755 else s3756
+  s3758 :: SWord8 = s1 + s3753
+  s3759 :: SBool = s3758 < s1
+  s3760 :: SBool = s3758 < s3753
+  s3761 :: SBool = s3759 | s3760
+  s3762 :: SWord8 = s3758 >>> 1
+  s3763 :: SWord8 = s14 | s3762
+  s3764 :: SWord8 = s16 & s3762
+  s3765 :: SWord8 = if s3761 then s3763 else s3764
+  s3766 :: SWord8 = if s3738 then s3757 else s3765
+  s3767 :: SWord8 = s1 + s3749
+  s3768 :: SBool = s3767 < s1
+  s3769 :: SBool = s3767 < s3749
+  s3770 :: SBool = s3768 | s3769
+  s3771 :: SWord8 = s3767 >>> 1
+  s3772 :: SWord8 = s14 | s3771
+  s3773 :: SWord8 = s16 & s3771
+  s3774 :: SWord8 = if s3770 then s3772 else s3773
+  s3775 :: SWord8 = s3774 >>> 1
+  s3776 :: SWord8 = s14 | s3775
+  s3777 :: SWord8 = s16 & s3775
+  s3778 :: SWord8 = if s3737 then s3776 else s3777
+  s3779 :: SWord8 = s1 + s3774
+  s3780 :: SBool = s3779 < s1
+  s3781 :: SBool = s3779 < s3774
+  s3782 :: SBool = s3780 | s3781
+  s3783 :: SWord8 = s3779 >>> 1
+  s3784 :: SWord8 = s14 | s3783
+  s3785 :: SWord8 = s16 & s3783
+  s3786 :: SWord8 = if s3782 then s3784 else s3785
+  s3787 :: SWord8 = if s3738 then s3778 else s3786
+  s3788 :: SWord8 = if s3614 then s3766 else s3787
+  s3789 :: SWord8 = s1 + s3745
+  s3790 :: SBool = s3789 < s1
+  s3791 :: SBool = s3789 < s3745
+  s3792 :: SBool = s3790 | s3791
+  s3793 :: SWord8 = s3789 >>> 1
+  s3794 :: SWord8 = s14 | s3793
+  s3795 :: SWord8 = s16 & s3793
+  s3796 :: SWord8 = if s3792 then s3794 else s3795
+  s3797 :: SWord8 = s3796 >>> 1
+  s3798 :: SWord8 = s14 | s3797
+  s3799 :: SWord8 = s16 & s3797
+  s3800 :: SWord8 = if s3613 then s3798 else s3799
+  s3801 :: SWord8 = s3800 >>> 1
+  s3802 :: SWord8 = s14 | s3801
+  s3803 :: SWord8 = s16 & s3801
+  s3804 :: SWord8 = if s3737 then s3802 else s3803
+  s3805 :: SWord8 = s1 + s3800
+  s3806 :: SBool = s3805 < s1
+  s3807 :: SBool = s3805 < s3800
+  s3808 :: SBool = s3806 | s3807
+  s3809 :: SWord8 = s3805 >>> 1
+  s3810 :: SWord8 = s14 | s3809
+  s3811 :: SWord8 = s16 & s3809
+  s3812 :: SWord8 = if s3808 then s3810 else s3811
+  s3813 :: SWord8 = if s3738 then s3804 else s3812
+  s3814 :: SWord8 = s1 + s3796
+  s3815 :: SBool = s3814 < s1
+  s3816 :: SBool = s3814 < s3796
+  s3817 :: SBool = s3815 | s3816
+  s3818 :: SWord8 = s3814 >>> 1
+  s3819 :: SWord8 = s14 | s3818
+  s3820 :: SWord8 = s16 & s3818
+  s3821 :: SWord8 = if s3817 then s3819 else s3820
+  s3822 :: SWord8 = s3821 >>> 1
+  s3823 :: SWord8 = s14 | s3822
+  s3824 :: SWord8 = s16 & s3822
+  s3825 :: SWord8 = if s3737 then s3823 else s3824
+  s3826 :: SWord8 = s1 + s3821
+  s3827 :: SBool = s3826 < s1
+  s3828 :: SBool = s3826 < s3821
+  s3829 :: SBool = s3827 | s3828
+  s3830 :: SWord8 = s3826 >>> 1
+  s3831 :: SWord8 = s14 | s3830
+  s3832 :: SWord8 = s16 & s3830
+  s3833 :: SWord8 = if s3829 then s3831 else s3832
+  s3834 :: SWord8 = if s3738 then s3825 else s3833
+  s3835 :: SWord8 = if s3614 then s3813 else s3834
+  s3836 :: SWord8 = if s3592 then s3788 else s3835
+  s3837 :: SWord8 = if s3081 then s3728 else s3836
+  s3838 :: SWord8 = s1 + s3599
+  s3839 :: SWord 1 = choose [0:0] s3838
+  s3840 :: SBool = s10 /= s3839
+  s3841 :: SWord8 = if s3840 then s3603 else s3604
+  s3842 :: SWord 1 = choose [0:0] s3841
+  s3843 :: SBool = s10 /= s3842
+  s3844 :: SWord8 = if s3843 then s3609 else s3610
+  s3845 :: SWord 1 = choose [0:0] s3844
+  s3846 :: SBool = s10 /= s3845
+  s3847 :: SBool = ~ s3846
+  s3848 :: SBool = s3838 < s1
+  s3849 :: SBool = s3838 < s3599
+  s3850 :: SBool = s3848 | s3849
+  s3851 :: SWord8 = s3838 >>> 1
+  s3852 :: SWord8 = s14 | s3851
+  s3853 :: SWord8 = s16 & s3851
+  s3854 :: SWord8 = if s3850 then s3852 else s3853
+  s3855 :: SWord 1 = choose [0:0] s3854
+  s3856 :: SBool = s10 /= s3855
+  s3857 :: SWord8 = s3841 >>> 1
+  s3858 :: SWord8 = s14 | s3857
+  s3859 :: SWord8 = s16 & s3857
+  s3860 :: SWord8 = if s3856 then s3858 else s3859
+  s3861 :: SWord 1 = choose [0:0] s3860
+  s3862 :: SBool = s10 /= s3861
+  s3863 :: SWord8 = s3844 >>> 1
+  s3864 :: SWord8 = s14 | s3863
+  s3865 :: SWord8 = s16 & s3863
+  s3866 :: SWord8 = if s3862 then s3864 else s3865
+  s3867 :: SWord 1 = choose [0:0] s3866
+  s3868 :: SBool = s10 /= s3867
+  s3869 :: SBool = ~ s3868
+  s3870 :: SWord8 = s3854 >>> 1
+  s3871 :: SWord8 = s14 | s3870
+  s3872 :: SWord8 = s16 & s3870
+  s3873 :: SWord8 = if s3080 then s3871 else s3872
+  s3874 :: SWord8 = s3873 >>> 1
+  s3875 :: SWord8 = s14 | s3874
+  s3876 :: SWord8 = s16 & s3874
+  s3877 :: SWord8 = if s3591 then s3875 else s3876
+  s3878 :: SWord8 = s3877 >>> 1
+  s3879 :: SWord8 = s14 | s3878
+  s3880 :: SWord8 = s16 & s3878
+  s3881 :: SWord8 = if s3846 then s3879 else s3880
+  s3882 :: SWord8 = s3881 >>> 1
+  s3883 :: SWord8 = s14 | s3882
+  s3884 :: SWord8 = s16 & s3882
+  s3885 :: SWord8 = if s3868 then s3883 else s3884
+  s3886 :: SWord8 = s1 + s3881
+  s3887 :: SBool = s3886 < s1
+  s3888 :: SBool = s3886 < s3881
+  s3889 :: SBool = s3887 | s3888
+  s3890 :: SWord8 = s3886 >>> 1
+  s3891 :: SWord8 = s14 | s3890
+  s3892 :: SWord8 = s16 & s3890
+  s3893 :: SWord8 = if s3889 then s3891 else s3892
+  s3894 :: SWord8 = if s3869 then s3885 else s3893
+  s3895 :: SWord8 = s1 + s3877
+  s3896 :: SBool = s3895 < s1
+  s3897 :: SBool = s3895 < s3877
+  s3898 :: SBool = s3896 | s3897
+  s3899 :: SWord8 = s3895 >>> 1
+  s3900 :: SWord8 = s14 | s3899
+  s3901 :: SWord8 = s16 & s3899
+  s3902 :: SWord8 = if s3898 then s3900 else s3901
+  s3903 :: SWord8 = s3902 >>> 1
+  s3904 :: SWord8 = s14 | s3903
+  s3905 :: SWord8 = s16 & s3903
+  s3906 :: SWord8 = if s3868 then s3904 else s3905
+  s3907 :: SWord8 = s1 + s3902
+  s3908 :: SBool = s3907 < s1
+  s3909 :: SBool = s3907 < s3902
+  s3910 :: SBool = s3908 | s3909
+  s3911 :: SWord8 = s3907 >>> 1
+  s3912 :: SWord8 = s14 | s3911
+  s3913 :: SWord8 = s16 & s3911
+  s3914 :: SWord8 = if s3910 then s3912 else s3913
+  s3915 :: SWord8 = if s3869 then s3906 else s3914
+  s3916 :: SWord8 = if s3847 then s3894 else s3915
+  s3917 :: SWord8 = s1 + s3873
+  s3918 :: SBool = s3917 < s1
+  s3919 :: SBool = s3917 < s3873
+  s3920 :: SBool = s3918 | s3919
+  s3921 :: SWord8 = s3917 >>> 1
+  s3922 :: SWord8 = s14 | s3921
+  s3923 :: SWord8 = s16 & s3921
+  s3924 :: SWord8 = if s3920 then s3922 else s3923
+  s3925 :: SWord8 = s3924 >>> 1
+  s3926 :: SWord8 = s14 | s3925
+  s3927 :: SWord8 = s16 & s3925
+  s3928 :: SWord8 = if s3846 then s3926 else s3927
+  s3929 :: SWord8 = s3928 >>> 1
+  s3930 :: SWord8 = s14 | s3929
+  s3931 :: SWord8 = s16 & s3929
+  s3932 :: SWord8 = if s3868 then s3930 else s3931
+  s3933 :: SWord8 = s1 + s3928
+  s3934 :: SBool = s3933 < s1
+  s3935 :: SBool = s3933 < s3928
+  s3936 :: SBool = s3934 | s3935
+  s3937 :: SWord8 = s3933 >>> 1
+  s3938 :: SWord8 = s14 | s3937
+  s3939 :: SWord8 = s16 & s3937
+  s3940 :: SWord8 = if s3936 then s3938 else s3939
+  s3941 :: SWord8 = if s3869 then s3932 else s3940
+  s3942 :: SWord8 = s1 + s3924
+  s3943 :: SBool = s3942 < s1
+  s3944 :: SBool = s3942 < s3924
+  s3945 :: SBool = s3943 | s3944
+  s3946 :: SWord8 = s3942 >>> 1
+  s3947 :: SWord8 = s14 | s3946
+  s3948 :: SWord8 = s16 & s3946
+  s3949 :: SWord8 = if s3945 then s3947 else s3948
+  s3950 :: SWord8 = s3949 >>> 1
+  s3951 :: SWord8 = s14 | s3950
+  s3952 :: SWord8 = s16 & s3950
+  s3953 :: SWord8 = if s3868 then s3951 else s3952
+  s3954 :: SWord8 = s1 + s3949
+  s3955 :: SBool = s3954 < s1
+  s3956 :: SBool = s3954 < s3949
+  s3957 :: SBool = s3955 | s3956
+  s3958 :: SWord8 = s3954 >>> 1
+  s3959 :: SWord8 = s14 | s3958
+  s3960 :: SWord8 = s16 & s3958
+  s3961 :: SWord8 = if s3957 then s3959 else s3960
+  s3962 :: SWord8 = if s3869 then s3953 else s3961
+  s3963 :: SWord8 = if s3847 then s3941 else s3962
+  s3964 :: SWord8 = if s3592 then s3916 else s3963
+  s3965 :: SWord8 = s1 + s3854
+  s3966 :: SWord 1 = choose [0:0] s3965
+  s3967 :: SBool = s10 /= s3966
+  s3968 :: SWord8 = if s3967 then s3858 else s3859
+  s3969 :: SWord 1 = choose [0:0] s3968
+  s3970 :: SBool = s10 /= s3969
+  s3971 :: SWord8 = if s3970 then s3864 else s3865
+  s3972 :: SWord 1 = choose [0:0] s3971
+  s3973 :: SBool = s10 /= s3972
+  s3974 :: SBool = ~ s3973
+  s3975 :: SBool = s3965 < s1
+  s3976 :: SBool = s3965 < s3854
+  s3977 :: SBool = s3975 | s3976
+  s3978 :: SWord8 = s3965 >>> 1
+  s3979 :: SWord8 = s14 | s3978
+  s3980 :: SWord8 = s16 & s3978
+  s3981 :: SWord8 = if s3977 then s3979 else s3980
+  s3982 :: SWord8 = s3981 >>> 1
+  s3983 :: SWord8 = s14 | s3982
+  s3984 :: SWord8 = s16 & s3982
+  s3985 :: SWord8 = if s3591 then s3983 else s3984
+  s3986 :: SWord8 = s3985 >>> 1
+  s3987 :: SWord8 = s14 | s3986
+  s3988 :: SWord8 = s16 & s3986
+  s3989 :: SWord8 = if s3846 then s3987 else s3988
+  s3990 :: SWord8 = s3989 >>> 1
+  s3991 :: SWord8 = s14 | s3990
+  s3992 :: SWord8 = s16 & s3990
+  s3993 :: SWord8 = if s3973 then s3991 else s3992
+  s3994 :: SWord8 = s1 + s3989
+  s3995 :: SBool = s3994 < s1
+  s3996 :: SBool = s3994 < s3989
+  s3997 :: SBool = s3995 | s3996
+  s3998 :: SWord8 = s3994 >>> 1
+  s3999 :: SWord8 = s14 | s3998
+  s4000 :: SWord8 = s16 & s3998
+  s4001 :: SWord8 = if s3997 then s3999 else s4000
+  s4002 :: SWord8 = if s3974 then s3993 else s4001
+  s4003 :: SWord8 = s1 + s3985
+  s4004 :: SBool = s4003 < s1
+  s4005 :: SBool = s4003 < s3985
+  s4006 :: SBool = s4004 | s4005
+  s4007 :: SWord8 = s4003 >>> 1
+  s4008 :: SWord8 = s14 | s4007
+  s4009 :: SWord8 = s16 & s4007
+  s4010 :: SWord8 = if s4006 then s4008 else s4009
+  s4011 :: SWord8 = s4010 >>> 1
+  s4012 :: SWord8 = s14 | s4011
+  s4013 :: SWord8 = s16 & s4011
+  s4014 :: SWord8 = if s3973 then s4012 else s4013
+  s4015 :: SWord8 = s1 + s4010
+  s4016 :: SBool = s4015 < s1
+  s4017 :: SBool = s4015 < s4010
+  s4018 :: SBool = s4016 | s4017
+  s4019 :: SWord8 = s4015 >>> 1
+  s4020 :: SWord8 = s14 | s4019
+  s4021 :: SWord8 = s16 & s4019
+  s4022 :: SWord8 = if s4018 then s4020 else s4021
+  s4023 :: SWord8 = if s3974 then s4014 else s4022
+  s4024 :: SWord8 = if s3847 then s4002 else s4023
+  s4025 :: SWord8 = s1 + s3981
+  s4026 :: SBool = s4025 < s1
+  s4027 :: SBool = s4025 < s3981
+  s4028 :: SBool = s4026 | s4027
+  s4029 :: SWord8 = s4025 >>> 1
+  s4030 :: SWord8 = s14 | s4029
+  s4031 :: SWord8 = s16 & s4029
+  s4032 :: SWord8 = if s4028 then s4030 else s4031
+  s4033 :: SWord8 = s4032 >>> 1
+  s4034 :: SWord8 = s14 | s4033
+  s4035 :: SWord8 = s16 & s4033
+  s4036 :: SWord8 = if s3846 then s4034 else s4035
+  s4037 :: SWord8 = s4036 >>> 1
+  s4038 :: SWord8 = s14 | s4037
+  s4039 :: SWord8 = s16 & s4037
+  s4040 :: SWord8 = if s3973 then s4038 else s4039
+  s4041 :: SWord8 = s1 + s4036
+  s4042 :: SBool = s4041 < s1
+  s4043 :: SBool = s4041 < s4036
+  s4044 :: SBool = s4042 | s4043
+  s4045 :: SWord8 = s4041 >>> 1
+  s4046 :: SWord8 = s14 | s4045
+  s4047 :: SWord8 = s16 & s4045
+  s4048 :: SWord8 = if s4044 then s4046 else s4047
+  s4049 :: SWord8 = if s3974 then s4040 else s4048
+  s4050 :: SWord8 = s1 + s4032
+  s4051 :: SBool = s4050 < s1
+  s4052 :: SBool = s4050 < s4032
+  s4053 :: SBool = s4051 | s4052
+  s4054 :: SWord8 = s4050 >>> 1
+  s4055 :: SWord8 = s14 | s4054
+  s4056 :: SWord8 = s16 & s4054
+  s4057 :: SWord8 = if s4053 then s4055 else s4056
+  s4058 :: SWord8 = s4057 >>> 1
+  s4059 :: SWord8 = s14 | s4058
+  s4060 :: SWord8 = s16 & s4058
+  s4061 :: SWord8 = if s3973 then s4059 else s4060
+  s4062 :: SWord8 = s1 + s4057
+  s4063 :: SBool = s4062 < s1
+  s4064 :: SBool = s4062 < s4057
+  s4065 :: SBool = s4063 | s4064
+  s4066 :: SWord8 = s4062 >>> 1
+  s4067 :: SWord8 = s14 | s4066
+  s4068 :: SWord8 = s16 & s4066
+  s4069 :: SWord8 = if s4065 then s4067 else s4068
+  s4070 :: SWord8 = if s3974 then s4061 else s4069
+  s4071 :: SWord8 = if s3847 then s4049 else s4070
+  s4072 :: SWord8 = if s3592 then s4024 else s4071
+  s4073 :: SWord8 = if s3081 then s3964 else s4072
+  s4074 :: SWord8 = if s2063 then s3837 else s4073
+  s4075 :: SWord8 = if s30 then s3582 else s4074
+  s4076 :: SWord8 = if s21 then s3071 else s4075
+  s4077 :: SWord8 = if s12 then s2053 else s4076
+  s4078 :: SWord16 = s8 # s4077
+  s4079 :: SWord16 = s7 * s4078
+  s4080 :: SWord 1 = choose [0:0] s126
+  s4081 :: SBool = s10 /= s4080
+  s4082 :: SWord 1 = choose [0:0] s122
+  s4083 :: SBool = s10 /= s4082
+  s4084 :: SWord 1 = choose [0:0] s118
+  s4085 :: SBool = s10 /= s4084
+  s4086 :: SWord8 = s105 >>> 1
+  s4087 :: SWord8 = s14 | s4086
+  s4088 :: SWord8 = s16 & s4086
+  s4089 :: SWord8 = if s4085 then s4087 else s4088
+  s4090 :: SWord8 = s4089 >>> 1
+  s4091 :: SWord8 = s14 | s4090
+  s4092 :: SWord8 = s16 & s4090
+  s4093 :: SWord8 = if s4083 then s4091 else s4092
+  s4094 :: SWord8 = s4093 >>> 1
+  s4095 :: SWord8 = s14 | s4094
+  s4096 :: SWord8 = s16 & s4094
+  s4097 :: SWord8 = if s4081 then s4095 else s4096
+  s4098 :: SWord 1 = choose [0:0] s131
+  s4099 :: SBool = s10 /= s4098
+  s4100 :: SWord8 = if s4099 then s4095 else s4096
+  s4101 :: SWord8 = if s114 then s4097 else s4100
+  s4102 :: SWord 1 = choose [0:0] s147
+  s4103 :: SBool = s10 /= s4102
+  s4104 :: SWord 1 = choose [0:0] s140
+  s4105 :: SBool = s10 /= s4104
+  s4106 :: SWord8 = if s4105 then s4091 else s4092
+  s4107 :: SWord8 = s4106 >>> 1
+  s4108 :: SWord8 = s14 | s4107
+  s4109 :: SWord8 = s16 & s4107
+  s4110 :: SWord8 = if s4103 then s4108 else s4109
+  s4111 :: SWord 1 = choose [0:0] s152
+  s4112 :: SBool = s10 /= s4111
+  s4113 :: SWord8 = if s4112 then s4108 else s4109
+  s4114 :: SWord8 = if s114 then s4110 else s4113
+  s4115 :: SWord8 = if s95 then s4101 else s4114
+  s4116 :: SWord 1 = choose [0:0] s173
+  s4117 :: SBool = s10 /= s4116
+  s4118 :: SWord 1 = choose [0:0] s169
+  s4119 :: SBool = s10 /= s4118
+  s4120 :: SWord 1 = choose [0:0] s162
+  s4121 :: SBool = s10 /= s4120
+  s4122 :: SWord8 = if s4121 then s4087 else s4088
+  s4123 :: SWord8 = s4122 >>> 1
+  s4124 :: SWord8 = s14 | s4123
+  s4125 :: SWord8 = s16 & s4123
+  s4126 :: SWord8 = if s4119 then s4124 else s4125
+  s4127 :: SWord8 = s4126 >>> 1
+  s4128 :: SWord8 = s14 | s4127
+  s4129 :: SWord8 = s16 & s4127
+  s4130 :: SWord8 = if s4117 then s4128 else s4129
+  s4131 :: SWord 1 = choose [0:0] s178
+  s4132 :: SBool = s10 /= s4131
+  s4133 :: SWord8 = if s4132 then s4128 else s4129
+  s4134 :: SWord8 = if s114 then s4130 else s4133
+  s4135 :: SWord 1 = choose [0:0] s194
+  s4136 :: SBool = s10 /= s4135
+  s4137 :: SWord 1 = choose [0:0] s187
+  s4138 :: SBool = s10 /= s4137
+  s4139 :: SWord8 = if s4138 then s4124 else s4125
+  s4140 :: SWord8 = s4139 >>> 1
+  s4141 :: SWord8 = s14 | s4140
+  s4142 :: SWord8 = s16 & s4140
+  s4143 :: SWord8 = if s4136 then s4141 else s4142
+  s4144 :: SWord 1 = choose [0:0] s199
+  s4145 :: SBool = s10 /= s4144
+  s4146 :: SWord8 = if s4145 then s4141 else s4142
+  s4147 :: SWord8 = if s114 then s4143 else s4146
+  s4148 :: SWord8 = if s95 then s4134 else s4147
+  s4149 :: SWord8 = if s76 then s4115 else s4148
+  s4150 :: SWord 1 = choose [0:0] s234
+  s4151 :: SBool = s10 /= s4150
+  s4152 :: SWord 1 = choose [0:0] s230
+  s4153 :: SBool = s10 /= s4152
+  s4154 :: SWord 1 = choose [0:0] s226
+  s4155 :: SBool = s10 /= s4154
+  s4156 :: SWord8 = s213 >>> 1
+  s4157 :: SWord8 = s14 | s4156
+  s4158 :: SWord8 = s16 & s4156
+  s4159 :: SWord8 = if s4155 then s4157 else s4158
+  s4160 :: SWord8 = s4159 >>> 1
+  s4161 :: SWord8 = s14 | s4160
+  s4162 :: SWord8 = s16 & s4160
+  s4163 :: SWord8 = if s4153 then s4161 else s4162
+  s4164 :: SWord8 = s4163 >>> 1
+  s4165 :: SWord8 = s14 | s4164
+  s4166 :: SWord8 = s16 & s4164
+  s4167 :: SWord8 = if s4151 then s4165 else s4166
+  s4168 :: SWord 1 = choose [0:0] s239
+  s4169 :: SBool = s10 /= s4168
+  s4170 :: SWord8 = if s4169 then s4165 else s4166
+  s4171 :: SWord8 = if s219 then s4167 else s4170
+  s4172 :: SWord 1 = choose [0:0] s255
+  s4173 :: SBool = s10 /= s4172
+  s4174 :: SWord 1 = choose [0:0] s248
+  s4175 :: SBool = s10 /= s4174
+  s4176 :: SWord8 = if s4175 then s4161 else s4162
+  s4177 :: SWord8 = s4176 >>> 1
+  s4178 :: SWord8 = s14 | s4177
+  s4179 :: SWord8 = s16 & s4177
+  s4180 :: SWord8 = if s4173 then s4178 else s4179
+  s4181 :: SWord 1 = choose [0:0] s260
+  s4182 :: SBool = s10 /= s4181
+  s4183 :: SWord8 = if s4182 then s4178 else s4179
+  s4184 :: SWord8 = if s219 then s4180 else s4183
+  s4185 :: SWord8 = if s95 then s4171 else s4184
+  s4186 :: SWord 1 = choose [0:0] s281
+  s4187 :: SBool = s10 /= s4186
+  s4188 :: SWord 1 = choose [0:0] s277
+  s4189 :: SBool = s10 /= s4188
+  s4190 :: SWord 1 = choose [0:0] s270
+  s4191 :: SBool = s10 /= s4190
+  s4192 :: SWord8 = if s4191 then s4157 else s4158
+  s4193 :: SWord8 = s4192 >>> 1
+  s4194 :: SWord8 = s14 | s4193
+  s4195 :: SWord8 = s16 & s4193
+  s4196 :: SWord8 = if s4189 then s4194 else s4195
+  s4197 :: SWord8 = s4196 >>> 1
+  s4198 :: SWord8 = s14 | s4197
+  s4199 :: SWord8 = s16 & s4197
+  s4200 :: SWord8 = if s4187 then s4198 else s4199
+  s4201 :: SWord 1 = choose [0:0] s286
+  s4202 :: SBool = s10 /= s4201
+  s4203 :: SWord8 = if s4202 then s4198 else s4199
+  s4204 :: SWord8 = if s219 then s4200 else s4203
+  s4205 :: SWord 1 = choose [0:0] s302
+  s4206 :: SBool = s10 /= s4205
+  s4207 :: SWord 1 = choose [0:0] s295
+  s4208 :: SBool = s10 /= s4207
+  s4209 :: SWord8 = if s4208 then s4194 else s4195
+  s4210 :: SWord8 = s4209 >>> 1
+  s4211 :: SWord8 = s14 | s4210
+  s4212 :: SWord8 = s16 & s4210
+  s4213 :: SWord8 = if s4206 then s4211 else s4212
+  s4214 :: SWord 1 = choose [0:0] s307
+  s4215 :: SBool = s10 /= s4214
+  s4216 :: SWord8 = if s4215 then s4211 else s4212
+  s4217 :: SWord8 = if s219 then s4213 else s4216
+  s4218 :: SWord8 = if s95 then s4204 else s4217
+  s4219 :: SWord8 = if s76 then s4185 else s4218
+  s4220 :: SWord8 = if s57 then s4149 else s4219
+  s4221 :: SWord 1 = choose [0:0] s362
+  s4222 :: SBool = s10 /= s4221
+  s4223 :: SWord 1 = choose [0:0] s358
+  s4224 :: SBool = s10 /= s4223
+  s4225 :: SWord 1 = choose [0:0] s354
+  s4226 :: SBool = s10 /= s4225
+  s4227 :: SWord8 = s341 >>> 1
+  s4228 :: SWord8 = s14 | s4227
+  s4229 :: SWord8 = s16 & s4227
+  s4230 :: SWord8 = if s4226 then s4228 else s4229
+  s4231 :: SWord8 = s4230 >>> 1
+  s4232 :: SWord8 = s14 | s4231
+  s4233 :: SWord8 = s16 & s4231
+  s4234 :: SWord8 = if s4224 then s4232 else s4233
+  s4235 :: SWord8 = s4234 >>> 1
+  s4236 :: SWord8 = s14 | s4235
+  s4237 :: SWord8 = s16 & s4235
+  s4238 :: SWord8 = if s4222 then s4236 else s4237
+  s4239 :: SWord 1 = choose [0:0] s367
+  s4240 :: SBool = s10 /= s4239
+  s4241 :: SWord8 = if s4240 then s4236 else s4237
+  s4242 :: SWord8 = if s350 then s4238 else s4241
+  s4243 :: SWord 1 = choose [0:0] s383
+  s4244 :: SBool = s10 /= s4243
+  s4245 :: SWord 1 = choose [0:0] s376
+  s4246 :: SBool = s10 /= s4245
+  s4247 :: SWord8 = if s4246 then s4232 else s4233
+  s4248 :: SWord8 = s4247 >>> 1
+  s4249 :: SWord8 = s14 | s4248
+  s4250 :: SWord8 = s16 & s4248
+  s4251 :: SWord8 = if s4244 then s4249 else s4250
+  s4252 :: SWord 1 = choose [0:0] s388
+  s4253 :: SBool = s10 /= s4252
+  s4254 :: SWord8 = if s4253 then s4249 else s4250
+  s4255 :: SWord8 = if s350 then s4251 else s4254
+  s4256 :: SWord8 = if s328 then s4242 else s4255
+  s4257 :: SWord 1 = choose [0:0] s409
+  s4258 :: SBool = s10 /= s4257
+  s4259 :: SWord 1 = choose [0:0] s405
+  s4260 :: SBool = s10 /= s4259
+  s4261 :: SWord 1 = choose [0:0] s398
+  s4262 :: SBool = s10 /= s4261
+  s4263 :: SWord8 = if s4262 then s4228 else s4229
+  s4264 :: SWord8 = s4263 >>> 1
+  s4265 :: SWord8 = s14 | s4264
+  s4266 :: SWord8 = s16 & s4264
+  s4267 :: SWord8 = if s4260 then s4265 else s4266
+  s4268 :: SWord8 = s4267 >>> 1
+  s4269 :: SWord8 = s14 | s4268
+  s4270 :: SWord8 = s16 & s4268
+  s4271 :: SWord8 = if s4258 then s4269 else s4270
+  s4272 :: SWord 1 = choose [0:0] s414
+  s4273 :: SBool = s10 /= s4272
+  s4274 :: SWord8 = if s4273 then s4269 else s4270
+  s4275 :: SWord8 = if s350 then s4271 else s4274
+  s4276 :: SWord 1 = choose [0:0] s430
+  s4277 :: SBool = s10 /= s4276
+  s4278 :: SWord 1 = choose [0:0] s423
+  s4279 :: SBool = s10 /= s4278
+  s4280 :: SWord8 = if s4279 then s4265 else s4266
+  s4281 :: SWord8 = s4280 >>> 1
+  s4282 :: SWord8 = s14 | s4281
+  s4283 :: SWord8 = s16 & s4281
+  s4284 :: SWord8 = if s4277 then s4282 else s4283
+  s4285 :: SWord 1 = choose [0:0] s435
+  s4286 :: SBool = s10 /= s4285
+  s4287 :: SWord8 = if s4286 then s4282 else s4283
+  s4288 :: SWord8 = if s350 then s4284 else s4287
+  s4289 :: SWord8 = if s328 then s4275 else s4288
+  s4290 :: SWord8 = if s76 then s4256 else s4289
+  s4291 :: SWord 1 = choose [0:0] s470
+  s4292 :: SBool = s10 /= s4291
+  s4293 :: SWord 1 = choose [0:0] s466
+  s4294 :: SBool = s10 /= s4293
+  s4295 :: SWord 1 = choose [0:0] s462
+  s4296 :: SBool = s10 /= s4295
+  s4297 :: SWord8 = s449 >>> 1
+  s4298 :: SWord8 = s14 | s4297
+  s4299 :: SWord8 = s16 & s4297
+  s4300 :: SWord8 = if s4296 then s4298 else s4299
+  s4301 :: SWord8 = s4300 >>> 1
+  s4302 :: SWord8 = s14 | s4301
+  s4303 :: SWord8 = s16 & s4301
+  s4304 :: SWord8 = if s4294 then s4302 else s4303
+  s4305 :: SWord8 = s4304 >>> 1
+  s4306 :: SWord8 = s14 | s4305
+  s4307 :: SWord8 = s16 & s4305
+  s4308 :: SWord8 = if s4292 then s4306 else s4307
+  s4309 :: SWord 1 = choose [0:0] s475
+  s4310 :: SBool = s10 /= s4309
+  s4311 :: SWord8 = if s4310 then s4306 else s4307
+  s4312 :: SWord8 = if s455 then s4308 else s4311
+  s4313 :: SWord 1 = choose [0:0] s491
+  s4314 :: SBool = s10 /= s4313
+  s4315 :: SWord 1 = choose [0:0] s484
+  s4316 :: SBool = s10 /= s4315
+  s4317 :: SWord8 = if s4316 then s4302 else s4303
+  s4318 :: SWord8 = s4317 >>> 1
+  s4319 :: SWord8 = s14 | s4318
+  s4320 :: SWord8 = s16 & s4318
+  s4321 :: SWord8 = if s4314 then s4319 else s4320
+  s4322 :: SWord 1 = choose [0:0] s496
+  s4323 :: SBool = s10 /= s4322
+  s4324 :: SWord8 = if s4323 then s4319 else s4320
+  s4325 :: SWord8 = if s455 then s4321 else s4324
+  s4326 :: SWord8 = if s328 then s4312 else s4325
+  s4327 :: SWord 1 = choose [0:0] s517
+  s4328 :: SBool = s10 /= s4327
+  s4329 :: SWord 1 = choose [0:0] s513
+  s4330 :: SBool = s10 /= s4329
+  s4331 :: SWord 1 = choose [0:0] s506
+  s4332 :: SBool = s10 /= s4331
+  s4333 :: SWord8 = if s4332 then s4298 else s4299
+  s4334 :: SWord8 = s4333 >>> 1
+  s4335 :: SWord8 = s14 | s4334
+  s4336 :: SWord8 = s16 & s4334
+  s4337 :: SWord8 = if s4330 then s4335 else s4336
+  s4338 :: SWord8 = s4337 >>> 1
+  s4339 :: SWord8 = s14 | s4338
+  s4340 :: SWord8 = s16 & s4338
+  s4341 :: SWord8 = if s4328 then s4339 else s4340
+  s4342 :: SWord 1 = choose [0:0] s522
+  s4343 :: SBool = s10 /= s4342
+  s4344 :: SWord8 = if s4343 then s4339 else s4340
+  s4345 :: SWord8 = if s455 then s4341 else s4344
+  s4346 :: SWord 1 = choose [0:0] s538
+  s4347 :: SBool = s10 /= s4346
+  s4348 :: SWord 1 = choose [0:0] s531
+  s4349 :: SBool = s10 /= s4348
+  s4350 :: SWord8 = if s4349 then s4335 else s4336
+  s4351 :: SWord8 = s4350 >>> 1
+  s4352 :: SWord8 = s14 | s4351
+  s4353 :: SWord8 = s16 & s4351
+  s4354 :: SWord8 = if s4347 then s4352 else s4353
+  s4355 :: SWord 1 = choose [0:0] s543
+  s4356 :: SBool = s10 /= s4355
+  s4357 :: SWord8 = if s4356 then s4352 else s4353
+  s4358 :: SWord8 = if s455 then s4354 else s4357
+  s4359 :: SWord8 = if s328 then s4345 else s4358
+  s4360 :: SWord8 = if s76 then s4326 else s4359
+  s4361 :: SWord8 = if s57 then s4290 else s4360
+  s4362 :: SWord8 = if s41 then s4220 else s4361
+  s4363 :: SWord 1 = choose [0:0] s618
+  s4364 :: SBool = s10 /= s4363
+  s4365 :: SWord 1 = choose [0:0] s614
+  s4366 :: SBool = s10 /= s4365
+  s4367 :: SWord 1 = choose [0:0] s610
+  s4368 :: SBool = s10 /= s4367
+  s4369 :: SWord8 = s597 >>> 1
+  s4370 :: SWord8 = s14 | s4369
+  s4371 :: SWord8 = s16 & s4369
+  s4372 :: SWord8 = if s4368 then s4370 else s4371
+  s4373 :: SWord8 = s4372 >>> 1
+  s4374 :: SWord8 = s14 | s4373
+  s4375 :: SWord8 = s16 & s4373
+  s4376 :: SWord8 = if s4366 then s4374 else s4375
+  s4377 :: SWord8 = s4376 >>> 1
+  s4378 :: SWord8 = s14 | s4377
+  s4379 :: SWord8 = s16 & s4377
+  s4380 :: SWord8 = if s4364 then s4378 else s4379
+  s4381 :: SWord 1 = choose [0:0] s623
+  s4382 :: SBool = s10 /= s4381
+  s4383 :: SWord8 = if s4382 then s4378 else s4379
+  s4384 :: SWord8 = if s606 then s4380 else s4383
+  s4385 :: SWord 1 = choose [0:0] s639
+  s4386 :: SBool = s10 /= s4385
+  s4387 :: SWord 1 = choose [0:0] s632
+  s4388 :: SBool = s10 /= s4387
+  s4389 :: SWord8 = if s4388 then s4374 else s4375
+  s4390 :: SWord8 = s4389 >>> 1
+  s4391 :: SWord8 = s14 | s4390
+  s4392 :: SWord8 = s16 & s4390
+  s4393 :: SWord8 = if s4386 then s4391 else s4392
+  s4394 :: SWord 1 = choose [0:0] s644
+  s4395 :: SBool = s10 /= s4394
+  s4396 :: SWord8 = if s4395 then s4391 else s4392
+  s4397 :: SWord8 = if s606 then s4393 else s4396
+  s4398 :: SWord8 = if s587 then s4384 else s4397
+  s4399 :: SWord 1 = choose [0:0] s665
+  s4400 :: SBool = s10 /= s4399
+  s4401 :: SWord 1 = choose [0:0] s661
+  s4402 :: SBool = s10 /= s4401
+  s4403 :: SWord 1 = choose [0:0] s654
+  s4404 :: SBool = s10 /= s4403
+  s4405 :: SWord8 = if s4404 then s4370 else s4371
+  s4406 :: SWord8 = s4405 >>> 1
+  s4407 :: SWord8 = s14 | s4406
+  s4408 :: SWord8 = s16 & s4406
+  s4409 :: SWord8 = if s4402 then s4407 else s4408
+  s4410 :: SWord8 = s4409 >>> 1
+  s4411 :: SWord8 = s14 | s4410
+  s4412 :: SWord8 = s16 & s4410
+  s4413 :: SWord8 = if s4400 then s4411 else s4412
+  s4414 :: SWord 1 = choose [0:0] s670
+  s4415 :: SBool = s10 /= s4414
+  s4416 :: SWord8 = if s4415 then s4411 else s4412
+  s4417 :: SWord8 = if s606 then s4413 else s4416
+  s4418 :: SWord 1 = choose [0:0] s686
+  s4419 :: SBool = s10 /= s4418
+  s4420 :: SWord 1 = choose [0:0] s679
+  s4421 :: SBool = s10 /= s4420
+  s4422 :: SWord8 = if s4421 then s4407 else s4408
+  s4423 :: SWord8 = s4422 >>> 1
+  s4424 :: SWord8 = s14 | s4423
+  s4425 :: SWord8 = s16 & s4423
+  s4426 :: SWord8 = if s4419 then s4424 else s4425
+  s4427 :: SWord 1 = choose [0:0] s691
+  s4428 :: SBool = s10 /= s4427
+  s4429 :: SWord8 = if s4428 then s4424 else s4425
+  s4430 :: SWord8 = if s606 then s4426 else s4429
+  s4431 :: SWord8 = if s587 then s4417 else s4430
+  s4432 :: SWord8 = if s565 then s4398 else s4431
+  s4433 :: SWord 1 = choose [0:0] s726
+  s4434 :: SBool = s10 /= s4433
+  s4435 :: SWord 1 = choose [0:0] s722
+  s4436 :: SBool = s10 /= s4435
+  s4437 :: SWord 1 = choose [0:0] s718
+  s4438 :: SBool = s10 /= s4437
+  s4439 :: SWord8 = s705 >>> 1
+  s4440 :: SWord8 = s14 | s4439
+  s4441 :: SWord8 = s16 & s4439
+  s4442 :: SWord8 = if s4438 then s4440 else s4441
+  s4443 :: SWord8 = s4442 >>> 1
+  s4444 :: SWord8 = s14 | s4443
+  s4445 :: SWord8 = s16 & s4443
+  s4446 :: SWord8 = if s4436 then s4444 else s4445
+  s4447 :: SWord8 = s4446 >>> 1
+  s4448 :: SWord8 = s14 | s4447
+  s4449 :: SWord8 = s16 & s4447
+  s4450 :: SWord8 = if s4434 then s4448 else s4449
+  s4451 :: SWord 1 = choose [0:0] s731
+  s4452 :: SBool = s10 /= s4451
+  s4453 :: SWord8 = if s4452 then s4448 else s4449
+  s4454 :: SWord8 = if s711 then s4450 else s4453
+  s4455 :: SWord 1 = choose [0:0] s747
+  s4456 :: SBool = s10 /= s4455
+  s4457 :: SWord 1 = choose [0:0] s740
+  s4458 :: SBool = s10 /= s4457
+  s4459 :: SWord8 = if s4458 then s4444 else s4445
+  s4460 :: SWord8 = s4459 >>> 1
+  s4461 :: SWord8 = s14 | s4460
+  s4462 :: SWord8 = s16 & s4460
+  s4463 :: SWord8 = if s4456 then s4461 else s4462
+  s4464 :: SWord 1 = choose [0:0] s752
+  s4465 :: SBool = s10 /= s4464
+  s4466 :: SWord8 = if s4465 then s4461 else s4462
+  s4467 :: SWord8 = if s711 then s4463 else s4466
+  s4468 :: SWord8 = if s587 then s4454 else s4467
+  s4469 :: SWord 1 = choose [0:0] s773
+  s4470 :: SBool = s10 /= s4469
+  s4471 :: SWord 1 = choose [0:0] s769
+  s4472 :: SBool = s10 /= s4471
+  s4473 :: SWord 1 = choose [0:0] s762
+  s4474 :: SBool = s10 /= s4473
+  s4475 :: SWord8 = if s4474 then s4440 else s4441
+  s4476 :: SWord8 = s4475 >>> 1
+  s4477 :: SWord8 = s14 | s4476
+  s4478 :: SWord8 = s16 & s4476
+  s4479 :: SWord8 = if s4472 then s4477 else s4478
+  s4480 :: SWord8 = s4479 >>> 1
+  s4481 :: SWord8 = s14 | s4480
+  s4482 :: SWord8 = s16 & s4480
+  s4483 :: SWord8 = if s4470 then s4481 else s4482
+  s4484 :: SWord 1 = choose [0:0] s778
+  s4485 :: SBool = s10 /= s4484
+  s4486 :: SWord8 = if s4485 then s4481 else s4482
+  s4487 :: SWord8 = if s711 then s4483 else s4486
+  s4488 :: SWord 1 = choose [0:0] s794
+  s4489 :: SBool = s10 /= s4488
+  s4490 :: SWord 1 = choose [0:0] s787
+  s4491 :: SBool = s10 /= s4490
+  s4492 :: SWord8 = if s4491 then s4477 else s4478
+  s4493 :: SWord8 = s4492 >>> 1
+  s4494 :: SWord8 = s14 | s4493
+  s4495 :: SWord8 = s16 & s4493
+  s4496 :: SWord8 = if s4489 then s4494 else s4495
+  s4497 :: SWord 1 = choose [0:0] s799
+  s4498 :: SBool = s10 /= s4497
+  s4499 :: SWord8 = if s4498 then s4494 else s4495
+  s4500 :: SWord8 = if s711 then s4496 else s4499
+  s4501 :: SWord8 = if s587 then s4487 else s4500
+  s4502 :: SWord8 = if s565 then s4468 else s4501
+  s4503 :: SWord8 = if s57 then s4432 else s4502
+  s4504 :: SWord 1 = choose [0:0] s854
+  s4505 :: SBool = s10 /= s4504
+  s4506 :: SWord 1 = choose [0:0] s850
+  s4507 :: SBool = s10 /= s4506
+  s4508 :: SWord 1 = choose [0:0] s846
+  s4509 :: SBool = s10 /= s4508
+  s4510 :: SWord8 = s833 >>> 1
+  s4511 :: SWord8 = s14 | s4510
+  s4512 :: SWord8 = s16 & s4510
+  s4513 :: SWord8 = if s4509 then s4511 else s4512
+  s4514 :: SWord8 = s4513 >>> 1
+  s4515 :: SWord8 = s14 | s4514
+  s4516 :: SWord8 = s16 & s4514
+  s4517 :: SWord8 = if s4507 then s4515 else s4516
+  s4518 :: SWord8 = s4517 >>> 1
+  s4519 :: SWord8 = s14 | s4518
+  s4520 :: SWord8 = s16 & s4518
+  s4521 :: SWord8 = if s4505 then s4519 else s4520
+  s4522 :: SWord 1 = choose [0:0] s859
+  s4523 :: SBool = s10 /= s4522
+  s4524 :: SWord8 = if s4523 then s4519 else s4520
+  s4525 :: SWord8 = if s842 then s4521 else s4524
+  s4526 :: SWord 1 = choose [0:0] s875
+  s4527 :: SBool = s10 /= s4526
+  s4528 :: SWord 1 = choose [0:0] s868
+  s4529 :: SBool = s10 /= s4528
+  s4530 :: SWord8 = if s4529 then s4515 else s4516
+  s4531 :: SWord8 = s4530 >>> 1
+  s4532 :: SWord8 = s14 | s4531
+  s4533 :: SWord8 = s16 & s4531
+  s4534 :: SWord8 = if s4527 then s4532 else s4533
+  s4535 :: SWord 1 = choose [0:0] s880
+  s4536 :: SBool = s10 /= s4535
+  s4537 :: SWord8 = if s4536 then s4532 else s4533
+  s4538 :: SWord8 = if s842 then s4534 else s4537
+  s4539 :: SWord8 = if s820 then s4525 else s4538
+  s4540 :: SWord 1 = choose [0:0] s901
+  s4541 :: SBool = s10 /= s4540
+  s4542 :: SWord 1 = choose [0:0] s897
+  s4543 :: SBool = s10 /= s4542
+  s4544 :: SWord 1 = choose [0:0] s890
+  s4545 :: SBool = s10 /= s4544
+  s4546 :: SWord8 = if s4545 then s4511 else s4512
+  s4547 :: SWord8 = s4546 >>> 1
+  s4548 :: SWord8 = s14 | s4547
+  s4549 :: SWord8 = s16 & s4547
+  s4550 :: SWord8 = if s4543 then s4548 else s4549
+  s4551 :: SWord8 = s4550 >>> 1
+  s4552 :: SWord8 = s14 | s4551
+  s4553 :: SWord8 = s16 & s4551
+  s4554 :: SWord8 = if s4541 then s4552 else s4553
+  s4555 :: SWord 1 = choose [0:0] s906
+  s4556 :: SBool = s10 /= s4555
+  s4557 :: SWord8 = if s4556 then s4552 else s4553
+  s4558 :: SWord8 = if s842 then s4554 else s4557
+  s4559 :: SWord 1 = choose [0:0] s922
+  s4560 :: SBool = s10 /= s4559
+  s4561 :: SWord 1 = choose [0:0] s915
+  s4562 :: SBool = s10 /= s4561
+  s4563 :: SWord8 = if s4562 then s4548 else s4549
+  s4564 :: SWord8 = s4563 >>> 1
+  s4565 :: SWord8 = s14 | s4564
+  s4566 :: SWord8 = s16 & s4564
+  s4567 :: SWord8 = if s4560 then s4565 else s4566
+  s4568 :: SWord 1 = choose [0:0] s927
+  s4569 :: SBool = s10 /= s4568
+  s4570 :: SWord8 = if s4569 then s4565 else s4566
+  s4571 :: SWord8 = if s842 then s4567 else s4570
+  s4572 :: SWord8 = if s820 then s4558 else s4571
+  s4573 :: SWord8 = if s565 then s4539 else s4572
+  s4574 :: SWord 1 = choose [0:0] s962
+  s4575 :: SBool = s10 /= s4574
+  s4576 :: SWord 1 = choose [0:0] s958
+  s4577 :: SBool = s10 /= s4576
+  s4578 :: SWord 1 = choose [0:0] s954
+  s4579 :: SBool = s10 /= s4578
+  s4580 :: SWord8 = s941 >>> 1
+  s4581 :: SWord8 = s14 | s4580
+  s4582 :: SWord8 = s16 & s4580
+  s4583 :: SWord8 = if s4579 then s4581 else s4582
+  s4584 :: SWord8 = s4583 >>> 1
+  s4585 :: SWord8 = s14 | s4584
+  s4586 :: SWord8 = s16 & s4584
+  s4587 :: SWord8 = if s4577 then s4585 else s4586
+  s4588 :: SWord8 = s4587 >>> 1
+  s4589 :: SWord8 = s14 | s4588
+  s4590 :: SWord8 = s16 & s4588
+  s4591 :: SWord8 = if s4575 then s4589 else s4590
+  s4592 :: SWord 1 = choose [0:0] s967
+  s4593 :: SBool = s10 /= s4592
+  s4594 :: SWord8 = if s4593 then s4589 else s4590
+  s4595 :: SWord8 = if s947 then s4591 else s4594
+  s4596 :: SWord 1 = choose [0:0] s983
+  s4597 :: SBool = s10 /= s4596
+  s4598 :: SWord 1 = choose [0:0] s976
+  s4599 :: SBool = s10 /= s4598
+  s4600 :: SWord8 = if s4599 then s4585 else s4586
+  s4601 :: SWord8 = s4600 >>> 1
+  s4602 :: SWord8 = s14 | s4601
+  s4603 :: SWord8 = s16 & s4601
+  s4604 :: SWord8 = if s4597 then s4602 else s4603
+  s4605 :: SWord 1 = choose [0:0] s988
+  s4606 :: SBool = s10 /= s4605
+  s4607 :: SWord8 = if s4606 then s4602 else s4603
+  s4608 :: SWord8 = if s947 then s4604 else s4607
+  s4609 :: SWord8 = if s820 then s4595 else s4608
+  s4610 :: SWord 1 = choose [0:0] s1009
+  s4611 :: SBool = s10 /= s4610
+  s4612 :: SWord 1 = choose [0:0] s1005
+  s4613 :: SBool = s10 /= s4612
+  s4614 :: SWord 1 = choose [0:0] s998
+  s4615 :: SBool = s10 /= s4614
+  s4616 :: SWord8 = if s4615 then s4581 else s4582
+  s4617 :: SWord8 = s4616 >>> 1
+  s4618 :: SWord8 = s14 | s4617
+  s4619 :: SWord8 = s16 & s4617
+  s4620 :: SWord8 = if s4613 then s4618 else s4619
+  s4621 :: SWord8 = s4620 >>> 1
+  s4622 :: SWord8 = s14 | s4621
+  s4623 :: SWord8 = s16 & s4621
+  s4624 :: SWord8 = if s4611 then s4622 else s4623
+  s4625 :: SWord 1 = choose [0:0] s1014
+  s4626 :: SBool = s10 /= s4625
+  s4627 :: SWord8 = if s4626 then s4622 else s4623
+  s4628 :: SWord8 = if s947 then s4624 else s4627
+  s4629 :: SWord 1 = choose [0:0] s1030
+  s4630 :: SBool = s10 /= s4629
+  s4631 :: SWord 1 = choose [0:0] s1023
+  s4632 :: SBool = s10 /= s4631
+  s4633 :: SWord8 = if s4632 then s4618 else s4619
+  s4634 :: SWord8 = s4633 >>> 1
+  s4635 :: SWord8 = s14 | s4634
+  s4636 :: SWord8 = s16 & s4634
+  s4637 :: SWord8 = if s4630 then s4635 else s4636
+  s4638 :: SWord 1 = choose [0:0] s1035
+  s4639 :: SBool = s10 /= s4638
+  s4640 :: SWord8 = if s4639 then s4635 else s4636
+  s4641 :: SWord8 = if s947 then s4637 else s4640
+  s4642 :: SWord8 = if s820 then s4628 else s4641
+  s4643 :: SWord8 = if s565 then s4609 else s4642
+  s4644 :: SWord8 = if s57 then s4573 else s4643
+  s4645 :: SWord8 = if s41 then s4503 else s4644
+  s4646 :: SWord8 = if s30 then s4362 else s4645
+  s4647 :: SWord 1 = choose [0:0] s1130
+  s4648 :: SBool = s10 /= s4647
+  s4649 :: SWord 1 = choose [0:0] s1126
+  s4650 :: SBool = s10 /= s4649
+  s4651 :: SWord 1 = choose [0:0] s1122
+  s4652 :: SBool = s10 /= s4651
+  s4653 :: SWord8 = s1109 >>> 1
+  s4654 :: SWord8 = s14 | s4653
+  s4655 :: SWord8 = s16 & s4653
+  s4656 :: SWord8 = if s4652 then s4654 else s4655
+  s4657 :: SWord8 = s4656 >>> 1
+  s4658 :: SWord8 = s14 | s4657
+  s4659 :: SWord8 = s16 & s4657
+  s4660 :: SWord8 = if s4650 then s4658 else s4659
+  s4661 :: SWord8 = s4660 >>> 1
+  s4662 :: SWord8 = s14 | s4661
+  s4663 :: SWord8 = s16 & s4661
+  s4664 :: SWord8 = if s4648 then s4662 else s4663
+  s4665 :: SWord 1 = choose [0:0] s1135
+  s4666 :: SBool = s10 /= s4665
+  s4667 :: SWord8 = if s4666 then s4662 else s4663
+  s4668 :: SWord8 = if s1118 then s4664 else s4667
+  s4669 :: SWord 1 = choose [0:0] s1151
+  s4670 :: SBool = s10 /= s4669
+  s4671 :: SWord 1 = choose [0:0] s1144
+  s4672 :: SBool = s10 /= s4671
+  s4673 :: SWord8 = if s4672 then s4658 else s4659
+  s4674 :: SWord8 = s4673 >>> 1
+  s4675 :: SWord8 = s14 | s4674
+  s4676 :: SWord8 = s16 & s4674
+  s4677 :: SWord8 = if s4670 then s4675 else s4676
+  s4678 :: SWord 1 = choose [0:0] s1156
+  s4679 :: SBool = s10 /= s4678
+  s4680 :: SWord8 = if s4679 then s4675 else s4676
+  s4681 :: SWord8 = if s1118 then s4677 else s4680
+  s4682 :: SWord8 = if s1099 then s4668 else s4681
+  s4683 :: SWord 1 = choose [0:0] s1177
+  s4684 :: SBool = s10 /= s4683
+  s4685 :: SWord 1 = choose [0:0] s1173
+  s4686 :: SBool = s10 /= s4685
+  s4687 :: SWord 1 = choose [0:0] s1166
+  s4688 :: SBool = s10 /= s4687
+  s4689 :: SWord8 = if s4688 then s4654 else s4655
+  s4690 :: SWord8 = s4689 >>> 1
+  s4691 :: SWord8 = s14 | s4690
+  s4692 :: SWord8 = s16 & s4690
+  s4693 :: SWord8 = if s4686 then s4691 else s4692
+  s4694 :: SWord8 = s4693 >>> 1
+  s4695 :: SWord8 = s14 | s4694
+  s4696 :: SWord8 = s16 & s4694
+  s4697 :: SWord8 = if s4684 then s4695 else s4696
+  s4698 :: SWord 1 = choose [0:0] s1182
+  s4699 :: SBool = s10 /= s4698
+  s4700 :: SWord8 = if s4699 then s4695 else s4696
+  s4701 :: SWord8 = if s1118 then s4697 else s4700
+  s4702 :: SWord 1 = choose [0:0] s1198
+  s4703 :: SBool = s10 /= s4702
+  s4704 :: SWord 1 = choose [0:0] s1191
+  s4705 :: SBool = s10 /= s4704
+  s4706 :: SWord8 = if s4705 then s4691 else s4692
+  s4707 :: SWord8 = s4706 >>> 1
+  s4708 :: SWord8 = s14 | s4707
+  s4709 :: SWord8 = s16 & s4707
+  s4710 :: SWord8 = if s4703 then s4708 else s4709
+  s4711 :: SWord 1 = choose [0:0] s1203
+  s4712 :: SBool = s10 /= s4711
+  s4713 :: SWord8 = if s4712 then s4708 else s4709
+  s4714 :: SWord8 = if s1118 then s4710 else s4713
+  s4715 :: SWord8 = if s1099 then s4701 else s4714
+  s4716 :: SWord8 = if s1080 then s4682 else s4715
+  s4717 :: SWord 1 = choose [0:0] s1238
+  s4718 :: SBool = s10 /= s4717
+  s4719 :: SWord 1 = choose [0:0] s1234
+  s4720 :: SBool = s10 /= s4719
+  s4721 :: SWord 1 = choose [0:0] s1230
+  s4722 :: SBool = s10 /= s4721
+  s4723 :: SWord8 = s1217 >>> 1
+  s4724 :: SWord8 = s14 | s4723
+  s4725 :: SWord8 = s16 & s4723
+  s4726 :: SWord8 = if s4722 then s4724 else s4725
+  s4727 :: SWord8 = s4726 >>> 1
+  s4728 :: SWord8 = s14 | s4727
+  s4729 :: SWord8 = s16 & s4727
+  s4730 :: SWord8 = if s4720 then s4728 else s4729
+  s4731 :: SWord8 = s4730 >>> 1
+  s4732 :: SWord8 = s14 | s4731
+  s4733 :: SWord8 = s16 & s4731
+  s4734 :: SWord8 = if s4718 then s4732 else s4733
+  s4735 :: SWord 1 = choose [0:0] s1243
+  s4736 :: SBool = s10 /= s4735
+  s4737 :: SWord8 = if s4736 then s4732 else s4733
+  s4738 :: SWord8 = if s1223 then s4734 else s4737
+  s4739 :: SWord 1 = choose [0:0] s1259
+  s4740 :: SBool = s10 /= s4739
+  s4741 :: SWord 1 = choose [0:0] s1252
+  s4742 :: SBool = s10 /= s4741
+  s4743 :: SWord8 = if s4742 then s4728 else s4729
+  s4744 :: SWord8 = s4743 >>> 1
+  s4745 :: SWord8 = s14 | s4744
+  s4746 :: SWord8 = s16 & s4744
+  s4747 :: SWord8 = if s4740 then s4745 else s4746
+  s4748 :: SWord 1 = choose [0:0] s1264
+  s4749 :: SBool = s10 /= s4748
+  s4750 :: SWord8 = if s4749 then s4745 else s4746
+  s4751 :: SWord8 = if s1223 then s4747 else s4750
+  s4752 :: SWord8 = if s1099 then s4738 else s4751
+  s4753 :: SWord 1 = choose [0:0] s1285
+  s4754 :: SBool = s10 /= s4753
+  s4755 :: SWord 1 = choose [0:0] s1281
+  s4756 :: SBool = s10 /= s4755
+  s4757 :: SWord 1 = choose [0:0] s1274
+  s4758 :: SBool = s10 /= s4757
+  s4759 :: SWord8 = if s4758 then s4724 else s4725
+  s4760 :: SWord8 = s4759 >>> 1
+  s4761 :: SWord8 = s14 | s4760
+  s4762 :: SWord8 = s16 & s4760
+  s4763 :: SWord8 = if s4756 then s4761 else s4762
+  s4764 :: SWord8 = s4763 >>> 1
+  s4765 :: SWord8 = s14 | s4764
+  s4766 :: SWord8 = s16 & s4764
+  s4767 :: SWord8 = if s4754 then s4765 else s4766
+  s4768 :: SWord 1 = choose [0:0] s1290
+  s4769 :: SBool = s10 /= s4768
+  s4770 :: SWord8 = if s4769 then s4765 else s4766
+  s4771 :: SWord8 = if s1223 then s4767 else s4770
+  s4772 :: SWord 1 = choose [0:0] s1306
+  s4773 :: SBool = s10 /= s4772
+  s4774 :: SWord 1 = choose [0:0] s1299
+  s4775 :: SBool = s10 /= s4774
+  s4776 :: SWord8 = if s4775 then s4761 else s4762
+  s4777 :: SWord8 = s4776 >>> 1
+  s4778 :: SWord8 = s14 | s4777
+  s4779 :: SWord8 = s16 & s4777
+  s4780 :: SWord8 = if s4773 then s4778 else s4779
+  s4781 :: SWord 1 = choose [0:0] s1311
+  s4782 :: SBool = s10 /= s4781
+  s4783 :: SWord8 = if s4782 then s4778 else s4779
+  s4784 :: SWord8 = if s1223 then s4780 else s4783
+  s4785 :: SWord8 = if s1099 then s4771 else s4784
+  s4786 :: SWord8 = if s1080 then s4752 else s4785
+  s4787 :: SWord8 = if s1058 then s4716 else s4786
+  s4788 :: SWord 1 = choose [0:0] s1366
+  s4789 :: SBool = s10 /= s4788
+  s4790 :: SWord 1 = choose [0:0] s1362
+  s4791 :: SBool = s10 /= s4790
+  s4792 :: SWord 1 = choose [0:0] s1358
+  s4793 :: SBool = s10 /= s4792
+  s4794 :: SWord8 = s1345 >>> 1
+  s4795 :: SWord8 = s14 | s4794
+  s4796 :: SWord8 = s16 & s4794
+  s4797 :: SWord8 = if s4793 then s4795 else s4796
+  s4798 :: SWord8 = s4797 >>> 1
+  s4799 :: SWord8 = s14 | s4798
+  s4800 :: SWord8 = s16 & s4798
+  s4801 :: SWord8 = if s4791 then s4799 else s4800
+  s4802 :: SWord8 = s4801 >>> 1
+  s4803 :: SWord8 = s14 | s4802
+  s4804 :: SWord8 = s16 & s4802
+  s4805 :: SWord8 = if s4789 then s4803 else s4804
+  s4806 :: SWord 1 = choose [0:0] s1371
+  s4807 :: SBool = s10 /= s4806
+  s4808 :: SWord8 = if s4807 then s4803 else s4804
+  s4809 :: SWord8 = if s1354 then s4805 else s4808
+  s4810 :: SWord 1 = choose [0:0] s1387
+  s4811 :: SBool = s10 /= s4810
+  s4812 :: SWord 1 = choose [0:0] s1380
+  s4813 :: SBool = s10 /= s4812
+  s4814 :: SWord8 = if s4813 then s4799 else s4800
+  s4815 :: SWord8 = s4814 >>> 1
+  s4816 :: SWord8 = s14 | s4815
+  s4817 :: SWord8 = s16 & s4815
+  s4818 :: SWord8 = if s4811 then s4816 else s4817
+  s4819 :: SWord 1 = choose [0:0] s1392
+  s4820 :: SBool = s10 /= s4819
+  s4821 :: SWord8 = if s4820 then s4816 else s4817
+  s4822 :: SWord8 = if s1354 then s4818 else s4821
+  s4823 :: SWord8 = if s1332 then s4809 else s4822
+  s4824 :: SWord 1 = choose [0:0] s1413
+  s4825 :: SBool = s10 /= s4824
+  s4826 :: SWord 1 = choose [0:0] s1409
+  s4827 :: SBool = s10 /= s4826
+  s4828 :: SWord 1 = choose [0:0] s1402
+  s4829 :: SBool = s10 /= s4828
+  s4830 :: SWord8 = if s4829 then s4795 else s4796
+  s4831 :: SWord8 = s4830 >>> 1
+  s4832 :: SWord8 = s14 | s4831
+  s4833 :: SWord8 = s16 & s4831
+  s4834 :: SWord8 = if s4827 then s4832 else s4833
+  s4835 :: SWord8 = s4834 >>> 1
+  s4836 :: SWord8 = s14 | s4835
+  s4837 :: SWord8 = s16 & s4835
+  s4838 :: SWord8 = if s4825 then s4836 else s4837
+  s4839 :: SWord 1 = choose [0:0] s1418
+  s4840 :: SBool = s10 /= s4839
+  s4841 :: SWord8 = if s4840 then s4836 else s4837
+  s4842 :: SWord8 = if s1354 then s4838 else s4841
+  s4843 :: SWord 1 = choose [0:0] s1434
+  s4844 :: SBool = s10 /= s4843
+  s4845 :: SWord 1 = choose [0:0] s1427
+  s4846 :: SBool = s10 /= s4845
+  s4847 :: SWord8 = if s4846 then s4832 else s4833
+  s4848 :: SWord8 = s4847 >>> 1
+  s4849 :: SWord8 = s14 | s4848
+  s4850 :: SWord8 = s16 & s4848
+  s4851 :: SWord8 = if s4844 then s4849 else s4850
+  s4852 :: SWord 1 = choose [0:0] s1439
+  s4853 :: SBool = s10 /= s4852
+  s4854 :: SWord8 = if s4853 then s4849 else s4850
+  s4855 :: SWord8 = if s1354 then s4851 else s4854
+  s4856 :: SWord8 = if s1332 then s4842 else s4855
+  s4857 :: SWord8 = if s1080 then s4823 else s4856
+  s4858 :: SWord 1 = choose [0:0] s1474
+  s4859 :: SBool = s10 /= s4858
+  s4860 :: SWord 1 = choose [0:0] s1470
+  s4861 :: SBool = s10 /= s4860
+  s4862 :: SWord 1 = choose [0:0] s1466
+  s4863 :: SBool = s10 /= s4862
+  s4864 :: SWord8 = s1453 >>> 1
+  s4865 :: SWord8 = s14 | s4864
+  s4866 :: SWord8 = s16 & s4864
+  s4867 :: SWord8 = if s4863 then s4865 else s4866
+  s4868 :: SWord8 = s4867 >>> 1
+  s4869 :: SWord8 = s14 | s4868
+  s4870 :: SWord8 = s16 & s4868
+  s4871 :: SWord8 = if s4861 then s4869 else s4870
+  s4872 :: SWord8 = s4871 >>> 1
+  s4873 :: SWord8 = s14 | s4872
+  s4874 :: SWord8 = s16 & s4872
+  s4875 :: SWord8 = if s4859 then s4873 else s4874
+  s4876 :: SWord 1 = choose [0:0] s1479
+  s4877 :: SBool = s10 /= s4876
+  s4878 :: SWord8 = if s4877 then s4873 else s4874
+  s4879 :: SWord8 = if s1459 then s4875 else s4878
+  s4880 :: SWord 1 = choose [0:0] s1495
+  s4881 :: SBool = s10 /= s4880
+  s4882 :: SWord 1 = choose [0:0] s1488
+  s4883 :: SBool = s10 /= s4882
+  s4884 :: SWord8 = if s4883 then s4869 else s4870
+  s4885 :: SWord8 = s4884 >>> 1
+  s4886 :: SWord8 = s14 | s4885
+  s4887 :: SWord8 = s16 & s4885
+  s4888 :: SWord8 = if s4881 then s4886 else s4887
+  s4889 :: SWord 1 = choose [0:0] s1500
+  s4890 :: SBool = s10 /= s4889
+  s4891 :: SWord8 = if s4890 then s4886 else s4887
+  s4892 :: SWord8 = if s1459 then s4888 else s4891
+  s4893 :: SWord8 = if s1332 then s4879 else s4892
+  s4894 :: SWord 1 = choose [0:0] s1521
+  s4895 :: SBool = s10 /= s4894
+  s4896 :: SWord 1 = choose [0:0] s1517
+  s4897 :: SBool = s10 /= s4896
+  s4898 :: SWord 1 = choose [0:0] s1510
+  s4899 :: SBool = s10 /= s4898
+  s4900 :: SWord8 = if s4899 then s4865 else s4866
+  s4901 :: SWord8 = s4900 >>> 1
+  s4902 :: SWord8 = s14 | s4901
+  s4903 :: SWord8 = s16 & s4901
+  s4904 :: SWord8 = if s4897 then s4902 else s4903
+  s4905 :: SWord8 = s4904 >>> 1
+  s4906 :: SWord8 = s14 | s4905
+  s4907 :: SWord8 = s16 & s4905
+  s4908 :: SWord8 = if s4895 then s4906 else s4907
+  s4909 :: SWord 1 = choose [0:0] s1526
+  s4910 :: SBool = s10 /= s4909
+  s4911 :: SWord8 = if s4910 then s4906 else s4907
+  s4912 :: SWord8 = if s1459 then s4908 else s4911
+  s4913 :: SWord 1 = choose [0:0] s1542
+  s4914 :: SBool = s10 /= s4913
+  s4915 :: SWord 1 = choose [0:0] s1535
+  s4916 :: SBool = s10 /= s4915
+  s4917 :: SWord8 = if s4916 then s4902 else s4903
+  s4918 :: SWord8 = s4917 >>> 1
+  s4919 :: SWord8 = s14 | s4918
+  s4920 :: SWord8 = s16 & s4918
+  s4921 :: SWord8 = if s4914 then s4919 else s4920
+  s4922 :: SWord 1 = choose [0:0] s1547
+  s4923 :: SBool = s10 /= s4922
+  s4924 :: SWord8 = if s4923 then s4919 else s4920
+  s4925 :: SWord8 = if s1459 then s4921 else s4924
+  s4926 :: SWord8 = if s1332 then s4912 else s4925
+  s4927 :: SWord8 = if s1080 then s4893 else s4926
+  s4928 :: SWord8 = if s1058 then s4857 else s4927
+  s4929 :: SWord8 = if s41 then s4787 else s4928
+  s4930 :: SWord 1 = choose [0:0] s1622
+  s4931 :: SBool = s10 /= s4930
+  s4932 :: SWord 1 = choose [0:0] s1618
+  s4933 :: SBool = s10 /= s4932
+  s4934 :: SWord 1 = choose [0:0] s1614
+  s4935 :: SBool = s10 /= s4934
+  s4936 :: SWord8 = s1601 >>> 1
+  s4937 :: SWord8 = s14 | s4936
+  s4938 :: SWord8 = s16 & s4936
+  s4939 :: SWord8 = if s4935 then s4937 else s4938
+  s4940 :: SWord8 = s4939 >>> 1
+  s4941 :: SWord8 = s14 | s4940
+  s4942 :: SWord8 = s16 & s4940
+  s4943 :: SWord8 = if s4933 then s4941 else s4942
+  s4944 :: SWord8 = s4943 >>> 1
+  s4945 :: SWord8 = s14 | s4944
+  s4946 :: SWord8 = s16 & s4944
+  s4947 :: SWord8 = if s4931 then s4945 else s4946
+  s4948 :: SWord 1 = choose [0:0] s1627
+  s4949 :: SBool = s10 /= s4948
+  s4950 :: SWord8 = if s4949 then s4945 else s4946
+  s4951 :: SWord8 = if s1610 then s4947 else s4950
+  s4952 :: SWord 1 = choose [0:0] s1643
+  s4953 :: SBool = s10 /= s4952
+  s4954 :: SWord 1 = choose [0:0] s1636
+  s4955 :: SBool = s10 /= s4954
+  s4956 :: SWord8 = if s4955 then s4941 else s4942
+  s4957 :: SWord8 = s4956 >>> 1
+  s4958 :: SWord8 = s14 | s4957
+  s4959 :: SWord8 = s16 & s4957
+  s4960 :: SWord8 = if s4953 then s4958 else s4959
+  s4961 :: SWord 1 = choose [0:0] s1648
+  s4962 :: SBool = s10 /= s4961
+  s4963 :: SWord8 = if s4962 then s4958 else s4959
+  s4964 :: SWord8 = if s1610 then s4960 else s4963
+  s4965 :: SWord8 = if s1591 then s4951 else s4964
+  s4966 :: SWord 1 = choose [0:0] s1669
+  s4967 :: SBool = s10 /= s4966
+  s4968 :: SWord 1 = choose [0:0] s1665
+  s4969 :: SBool = s10 /= s4968
+  s4970 :: SWord 1 = choose [0:0] s1658
+  s4971 :: SBool = s10 /= s4970
+  s4972 :: SWord8 = if s4971 then s4937 else s4938
+  s4973 :: SWord8 = s4972 >>> 1
+  s4974 :: SWord8 = s14 | s4973
+  s4975 :: SWord8 = s16 & s4973
+  s4976 :: SWord8 = if s4969 then s4974 else s4975
+  s4977 :: SWord8 = s4976 >>> 1
+  s4978 :: SWord8 = s14 | s4977
+  s4979 :: SWord8 = s16 & s4977
+  s4980 :: SWord8 = if s4967 then s4978 else s4979
+  s4981 :: SWord 1 = choose [0:0] s1674
+  s4982 :: SBool = s10 /= s4981
+  s4983 :: SWord8 = if s4982 then s4978 else s4979
+  s4984 :: SWord8 = if s1610 then s4980 else s4983
+  s4985 :: SWord 1 = choose [0:0] s1690
+  s4986 :: SBool = s10 /= s4985
+  s4987 :: SWord 1 = choose [0:0] s1683
+  s4988 :: SBool = s10 /= s4987
+  s4989 :: SWord8 = if s4988 then s4974 else s4975
+  s4990 :: SWord8 = s4989 >>> 1
+  s4991 :: SWord8 = s14 | s4990
+  s4992 :: SWord8 = s16 & s4990
+  s4993 :: SWord8 = if s4986 then s4991 else s4992
+  s4994 :: SWord 1 = choose [0:0] s1695
+  s4995 :: SBool = s10 /= s4994
+  s4996 :: SWord8 = if s4995 then s4991 else s4992
+  s4997 :: SWord8 = if s1610 then s4993 else s4996
+  s4998 :: SWord8 = if s1591 then s4984 else s4997
+  s4999 :: SWord8 = if s1569 then s4965 else s4998
+  s5000 :: SWord 1 = choose [0:0] s1730
+  s5001 :: SBool = s10 /= s5000
+  s5002 :: SWord 1 = choose [0:0] s1726
+  s5003 :: SBool = s10 /= s5002
+  s5004 :: SWord 1 = choose [0:0] s1722
+  s5005 :: SBool = s10 /= s5004
+  s5006 :: SWord8 = s1709 >>> 1
+  s5007 :: SWord8 = s14 | s5006
+  s5008 :: SWord8 = s16 & s5006
+  s5009 :: SWord8 = if s5005 then s5007 else s5008
+  s5010 :: SWord8 = s5009 >>> 1
+  s5011 :: SWord8 = s14 | s5010
+  s5012 :: SWord8 = s16 & s5010
+  s5013 :: SWord8 = if s5003 then s5011 else s5012
+  s5014 :: SWord8 = s5013 >>> 1
+  s5015 :: SWord8 = s14 | s5014
+  s5016 :: SWord8 = s16 & s5014
+  s5017 :: SWord8 = if s5001 then s5015 else s5016
+  s5018 :: SWord 1 = choose [0:0] s1735
+  s5019 :: SBool = s10 /= s5018
+  s5020 :: SWord8 = if s5019 then s5015 else s5016
+  s5021 :: SWord8 = if s1715 then s5017 else s5020
+  s5022 :: SWord 1 = choose [0:0] s1751
+  s5023 :: SBool = s10 /= s5022
+  s5024 :: SWord 1 = choose [0:0] s1744
+  s5025 :: SBool = s10 /= s5024
+  s5026 :: SWord8 = if s5025 then s5011 else s5012
+  s5027 :: SWord8 = s5026 >>> 1
+  s5028 :: SWord8 = s14 | s5027
+  s5029 :: SWord8 = s16 & s5027
+  s5030 :: SWord8 = if s5023 then s5028 else s5029
+  s5031 :: SWord 1 = choose [0:0] s1756
+  s5032 :: SBool = s10 /= s5031
+  s5033 :: SWord8 = if s5032 then s5028 else s5029
+  s5034 :: SWord8 = if s1715 then s5030 else s5033
+  s5035 :: SWord8 = if s1591 then s5021 else s5034
+  s5036 :: SWord 1 = choose [0:0] s1777
+  s5037 :: SBool = s10 /= s5036
+  s5038 :: SWord 1 = choose [0:0] s1773
+  s5039 :: SBool = s10 /= s5038
+  s5040 :: SWord 1 = choose [0:0] s1766
+  s5041 :: SBool = s10 /= s5040
+  s5042 :: SWord8 = if s5041 then s5007 else s5008
+  s5043 :: SWord8 = s5042 >>> 1
+  s5044 :: SWord8 = s14 | s5043
+  s5045 :: SWord8 = s16 & s5043
+  s5046 :: SWord8 = if s5039 then s5044 else s5045
+  s5047 :: SWord8 = s5046 >>> 1
+  s5048 :: SWord8 = s14 | s5047
+  s5049 :: SWord8 = s16 & s5047
+  s5050 :: SWord8 = if s5037 then s5048 else s5049
+  s5051 :: SWord 1 = choose [0:0] s1782
+  s5052 :: SBool = s10 /= s5051
+  s5053 :: SWord8 = if s5052 then s5048 else s5049
+  s5054 :: SWord8 = if s1715 then s5050 else s5053
+  s5055 :: SWord 1 = choose [0:0] s1798
+  s5056 :: SBool = s10 /= s5055
+  s5057 :: SWord 1 = choose [0:0] s1791
+  s5058 :: SBool = s10 /= s5057
+  s5059 :: SWord8 = if s5058 then s5044 else s5045
+  s5060 :: SWord8 = s5059 >>> 1
+  s5061 :: SWord8 = s14 | s5060
+  s5062 :: SWord8 = s16 & s5060
+  s5063 :: SWord8 = if s5056 then s5061 else s5062
+  s5064 :: SWord 1 = choose [0:0] s1803
+  s5065 :: SBool = s10 /= s5064
+  s5066 :: SWord8 = if s5065 then s5061 else s5062
+  s5067 :: SWord8 = if s1715 then s5063 else s5066
+  s5068 :: SWord8 = if s1591 then s5054 else s5067
+  s5069 :: SWord8 = if s1569 then s5035 else s5068
+  s5070 :: SWord8 = if s1058 then s4999 else s5069
+  s5071 :: SWord 1 = choose [0:0] s1858
+  s5072 :: SBool = s10 /= s5071
+  s5073 :: SWord 1 = choose [0:0] s1854
+  s5074 :: SBool = s10 /= s5073
+  s5075 :: SWord 1 = choose [0:0] s1850
+  s5076 :: SBool = s10 /= s5075
+  s5077 :: SWord8 = s1837 >>> 1
+  s5078 :: SWord8 = s14 | s5077
+  s5079 :: SWord8 = s16 & s5077
+  s5080 :: SWord8 = if s5076 then s5078 else s5079
+  s5081 :: SWord8 = s5080 >>> 1
+  s5082 :: SWord8 = s14 | s5081
+  s5083 :: SWord8 = s16 & s5081
+  s5084 :: SWord8 = if s5074 then s5082 else s5083
+  s5085 :: SWord8 = s5084 >>> 1
+  s5086 :: SWord8 = s14 | s5085
+  s5087 :: SWord8 = s16 & s5085
+  s5088 :: SWord8 = if s5072 then s5086 else s5087
+  s5089 :: SWord 1 = choose [0:0] s1863
+  s5090 :: SBool = s10 /= s5089
+  s5091 :: SWord8 = if s5090 then s5086 else s5087
+  s5092 :: SWord8 = if s1846 then s5088 else s5091
+  s5093 :: SWord 1 = choose [0:0] s1879
+  s5094 :: SBool = s10 /= s5093
+  s5095 :: SWord 1 = choose [0:0] s1872
+  s5096 :: SBool = s10 /= s5095
+  s5097 :: SWord8 = if s5096 then s5082 else s5083
+  s5098 :: SWord8 = s5097 >>> 1
+  s5099 :: SWord8 = s14 | s5098
+  s5100 :: SWord8 = s16 & s5098
+  s5101 :: SWord8 = if s5094 then s5099 else s5100
+  s5102 :: SWord 1 = choose [0:0] s1884
+  s5103 :: SBool = s10 /= s5102
+  s5104 :: SWord8 = if s5103 then s5099 else s5100
+  s5105 :: SWord8 = if s1846 then s5101 else s5104
+  s5106 :: SWord8 = if s1824 then s5092 else s5105
+  s5107 :: SWord 1 = choose [0:0] s1905
+  s5108 :: SBool = s10 /= s5107
+  s5109 :: SWord 1 = choose [0:0] s1901
+  s5110 :: SBool = s10 /= s5109
+  s5111 :: SWord 1 = choose [0:0] s1894
+  s5112 :: SBool = s10 /= s5111
+  s5113 :: SWord8 = if s5112 then s5078 else s5079
+  s5114 :: SWord8 = s5113 >>> 1
+  s5115 :: SWord8 = s14 | s5114
+  s5116 :: SWord8 = s16 & s5114
+  s5117 :: SWord8 = if s5110 then s5115 else s5116
+  s5118 :: SWord8 = s5117 >>> 1
+  s5119 :: SWord8 = s14 | s5118
+  s5120 :: SWord8 = s16 & s5118
+  s5121 :: SWord8 = if s5108 then s5119 else s5120
+  s5122 :: SWord 1 = choose [0:0] s1910
+  s5123 :: SBool = s10 /= s5122
+  s5124 :: SWord8 = if s5123 then s5119 else s5120
+  s5125 :: SWord8 = if s1846 then s5121 else s5124
+  s5126 :: SWord 1 = choose [0:0] s1926
+  s5127 :: SBool = s10 /= s5126
+  s5128 :: SWord 1 = choose [0:0] s1919
+  s5129 :: SBool = s10 /= s5128
+  s5130 :: SWord8 = if s5129 then s5115 else s5116
+  s5131 :: SWord8 = s5130 >>> 1
+  s5132 :: SWord8 = s14 | s5131
+  s5133 :: SWord8 = s16 & s5131
+  s5134 :: SWord8 = if s5127 then s5132 else s5133
+  s5135 :: SWord 1 = choose [0:0] s1931
+  s5136 :: SBool = s10 /= s5135
+  s5137 :: SWord8 = if s5136 then s5132 else s5133
+  s5138 :: SWord8 = if s1846 then s5134 else s5137
+  s5139 :: SWord8 = if s1824 then s5125 else s5138
+  s5140 :: SWord8 = if s1569 then s5106 else s5139
+  s5141 :: SWord 1 = choose [0:0] s1966
+  s5142 :: SBool = s10 /= s5141
+  s5143 :: SWord 1 = choose [0:0] s1962
+  s5144 :: SBool = s10 /= s5143
+  s5145 :: SWord 1 = choose [0:0] s1958
+  s5146 :: SBool = s10 /= s5145
+  s5147 :: SWord8 = s1945 >>> 1
+  s5148 :: SWord8 = s14 | s5147
+  s5149 :: SWord8 = s16 & s5147
+  s5150 :: SWord8 = if s5146 then s5148 else s5149
+  s5151 :: SWord8 = s5150 >>> 1
+  s5152 :: SWord8 = s14 | s5151
+  s5153 :: SWord8 = s16 & s5151
+  s5154 :: SWord8 = if s5144 then s5152 else s5153
+  s5155 :: SWord8 = s5154 >>> 1
+  s5156 :: SWord8 = s14 | s5155
+  s5157 :: SWord8 = s16 & s5155
+  s5158 :: SWord8 = if s5142 then s5156 else s5157
+  s5159 :: SWord 1 = choose [0:0] s1971
+  s5160 :: SBool = s10 /= s5159
+  s5161 :: SWord8 = if s5160 then s5156 else s5157
+  s5162 :: SWord8 = if s1951 then s5158 else s5161
+  s5163 :: SWord 1 = choose [0:0] s1987
+  s5164 :: SBool = s10 /= s5163
+  s5165 :: SWord 1 = choose [0:0] s1980
+  s5166 :: SBool = s10 /= s5165
+  s5167 :: SWord8 = if s5166 then s5152 else s5153
+  s5168 :: SWord8 = s5167 >>> 1
+  s5169 :: SWord8 = s14 | s5168
+  s5170 :: SWord8 = s16 & s5168
+  s5171 :: SWord8 = if s5164 then s5169 else s5170
+  s5172 :: SWord 1 = choose [0:0] s1992
+  s5173 :: SBool = s10 /= s5172
+  s5174 :: SWord8 = if s5173 then s5169 else s5170
+  s5175 :: SWord8 = if s1951 then s5171 else s5174
+  s5176 :: SWord8 = if s1824 then s5162 else s5175
+  s5177 :: SWord 1 = choose [0:0] s2013
+  s5178 :: SBool = s10 /= s5177
+  s5179 :: SWord 1 = choose [0:0] s2009
+  s5180 :: SBool = s10 /= s5179
+  s5181 :: SWord 1 = choose [0:0] s2002
+  s5182 :: SBool = s10 /= s5181
+  s5183 :: SWord8 = if s5182 then s5148 else s5149
+  s5184 :: SWord8 = s5183 >>> 1
+  s5185 :: SWord8 = s14 | s5184
+  s5186 :: SWord8 = s16 & s5184
+  s5187 :: SWord8 = if s5180 then s5185 else s5186
+  s5188 :: SWord8 = s5187 >>> 1
+  s5189 :: SWord8 = s14 | s5188
+  s5190 :: SWord8 = s16 & s5188
+  s5191 :: SWord8 = if s5178 then s5189 else s5190
+  s5192 :: SWord 1 = choose [0:0] s2018
+  s5193 :: SBool = s10 /= s5192
+  s5194 :: SWord8 = if s5193 then s5189 else s5190
+  s5195 :: SWord8 = if s1951 then s5191 else s5194
+  s5196 :: SWord 1 = choose [0:0] s2034
+  s5197 :: SBool = s10 /= s5196
+  s5198 :: SWord 1 = choose [0:0] s2027
+  s5199 :: SBool = s10 /= s5198
+  s5200 :: SWord8 = if s5199 then s5185 else s5186
+  s5201 :: SWord8 = s5200 >>> 1
+  s5202 :: SWord8 = s14 | s5201
+  s5203 :: SWord8 = s16 & s5201
+  s5204 :: SWord8 = if s5197 then s5202 else s5203
+  s5205 :: SWord 1 = choose [0:0] s2039
+  s5206 :: SBool = s10 /= s5205
+  s5207 :: SWord8 = if s5206 then s5202 else s5203
+  s5208 :: SWord8 = if s1951 then s5204 else s5207
+  s5209 :: SWord8 = if s1824 then s5195 else s5208
+  s5210 :: SWord8 = if s1569 then s5176 else s5209
+  s5211 :: SWord8 = if s1058 then s5140 else s5210
+  s5212 :: SWord8 = if s41 then s5070 else s5211
+  s5213 :: SWord8 = if s30 then s4929 else s5212
+  s5214 :: SWord8 = if s21 then s4646 else s5213
+  s5215 :: SWord 1 = choose [0:0] s2149
+  s5216 :: SBool = s10 /= s5215
+  s5217 :: SWord 1 = choose [0:0] s2145
+  s5218 :: SBool = s10 /= s5217
+  s5219 :: SWord 1 = choose [0:0] s2141
+  s5220 :: SBool = s10 /= s5219
+  s5221 :: SWord8 = s2128 >>> 1
+  s5222 :: SWord8 = s14 | s5221
+  s5223 :: SWord8 = s16 & s5221
+  s5224 :: SWord8 = if s5220 then s5222 else s5223
+  s5225 :: SWord8 = s5224 >>> 1
+  s5226 :: SWord8 = s14 | s5225
+  s5227 :: SWord8 = s16 & s5225
+  s5228 :: SWord8 = if s5218 then s5226 else s5227
+  s5229 :: SWord8 = s5228 >>> 1
+  s5230 :: SWord8 = s14 | s5229
+  s5231 :: SWord8 = s16 & s5229
+  s5232 :: SWord8 = if s5216 then s5230 else s5231
+  s5233 :: SWord 1 = choose [0:0] s2154
+  s5234 :: SBool = s10 /= s5233
+  s5235 :: SWord8 = if s5234 then s5230 else s5231
+  s5236 :: SWord8 = if s2137 then s5232 else s5235
+  s5237 :: SWord 1 = choose [0:0] s2170
+  s5238 :: SBool = s10 /= s5237
+  s5239 :: SWord 1 = choose [0:0] s2163
+  s5240 :: SBool = s10 /= s5239
+  s5241 :: SWord8 = if s5240 then s5226 else s5227
+  s5242 :: SWord8 = s5241 >>> 1
+  s5243 :: SWord8 = s14 | s5242
+  s5244 :: SWord8 = s16 & s5242
+  s5245 :: SWord8 = if s5238 then s5243 else s5244
+  s5246 :: SWord 1 = choose [0:0] s2175
+  s5247 :: SBool = s10 /= s5246
+  s5248 :: SWord8 = if s5247 then s5243 else s5244
+  s5249 :: SWord8 = if s2137 then s5245 else s5248
+  s5250 :: SWord8 = if s2118 then s5236 else s5249
+  s5251 :: SWord 1 = choose [0:0] s2196
+  s5252 :: SBool = s10 /= s5251
+  s5253 :: SWord 1 = choose [0:0] s2192
+  s5254 :: SBool = s10 /= s5253
+  s5255 :: SWord 1 = choose [0:0] s2185
+  s5256 :: SBool = s10 /= s5255
+  s5257 :: SWord8 = if s5256 then s5222 else s5223
+  s5258 :: SWord8 = s5257 >>> 1
+  s5259 :: SWord8 = s14 | s5258
+  s5260 :: SWord8 = s16 & s5258
+  s5261 :: SWord8 = if s5254 then s5259 else s5260
+  s5262 :: SWord8 = s5261 >>> 1
+  s5263 :: SWord8 = s14 | s5262
+  s5264 :: SWord8 = s16 & s5262
+  s5265 :: SWord8 = if s5252 then s5263 else s5264
+  s5266 :: SWord 1 = choose [0:0] s2201
+  s5267 :: SBool = s10 /= s5266
+  s5268 :: SWord8 = if s5267 then s5263 else s5264
+  s5269 :: SWord8 = if s2137 then s5265 else s5268
+  s5270 :: SWord 1 = choose [0:0] s2217
+  s5271 :: SBool = s10 /= s5270
+  s5272 :: SWord 1 = choose [0:0] s2210
+  s5273 :: SBool = s10 /= s5272
+  s5274 :: SWord8 = if s5273 then s5259 else s5260
+  s5275 :: SWord8 = s5274 >>> 1
+  s5276 :: SWord8 = s14 | s5275
+  s5277 :: SWord8 = s16 & s5275
+  s5278 :: SWord8 = if s5271 then s5276 else s5277
+  s5279 :: SWord 1 = choose [0:0] s2222
+  s5280 :: SBool = s10 /= s5279
+  s5281 :: SWord8 = if s5280 then s5276 else s5277
+  s5282 :: SWord8 = if s2137 then s5278 else s5281
+  s5283 :: SWord8 = if s2118 then s5269 else s5282
+  s5284 :: SWord8 = if s2099 then s5250 else s5283
+  s5285 :: SWord 1 = choose [0:0] s2257
+  s5286 :: SBool = s10 /= s5285
+  s5287 :: SWord 1 = choose [0:0] s2253
+  s5288 :: SBool = s10 /= s5287
+  s5289 :: SWord 1 = choose [0:0] s2249
+  s5290 :: SBool = s10 /= s5289
+  s5291 :: SWord8 = s2236 >>> 1
+  s5292 :: SWord8 = s14 | s5291
+  s5293 :: SWord8 = s16 & s5291
+  s5294 :: SWord8 = if s5290 then s5292 else s5293
+  s5295 :: SWord8 = s5294 >>> 1
+  s5296 :: SWord8 = s14 | s5295
+  s5297 :: SWord8 = s16 & s5295
+  s5298 :: SWord8 = if s5288 then s5296 else s5297
+  s5299 :: SWord8 = s5298 >>> 1
+  s5300 :: SWord8 = s14 | s5299
+  s5301 :: SWord8 = s16 & s5299
+  s5302 :: SWord8 = if s5286 then s5300 else s5301
+  s5303 :: SWord 1 = choose [0:0] s2262
+  s5304 :: SBool = s10 /= s5303
+  s5305 :: SWord8 = if s5304 then s5300 else s5301
+  s5306 :: SWord8 = if s2242 then s5302 else s5305
+  s5307 :: SWord 1 = choose [0:0] s2278
+  s5308 :: SBool = s10 /= s5307
+  s5309 :: SWord 1 = choose [0:0] s2271
+  s5310 :: SBool = s10 /= s5309
+  s5311 :: SWord8 = if s5310 then s5296 else s5297
+  s5312 :: SWord8 = s5311 >>> 1
+  s5313 :: SWord8 = s14 | s5312
+  s5314 :: SWord8 = s16 & s5312
+  s5315 :: SWord8 = if s5308 then s5313 else s5314
+  s5316 :: SWord 1 = choose [0:0] s2283
+  s5317 :: SBool = s10 /= s5316
+  s5318 :: SWord8 = if s5317 then s5313 else s5314
+  s5319 :: SWord8 = if s2242 then s5315 else s5318
+  s5320 :: SWord8 = if s2118 then s5306 else s5319
+  s5321 :: SWord 1 = choose [0:0] s2304
+  s5322 :: SBool = s10 /= s5321
+  s5323 :: SWord 1 = choose [0:0] s2300
+  s5324 :: SBool = s10 /= s5323
+  s5325 :: SWord 1 = choose [0:0] s2293
+  s5326 :: SBool = s10 /= s5325
+  s5327 :: SWord8 = if s5326 then s5292 else s5293
+  s5328 :: SWord8 = s5327 >>> 1
+  s5329 :: SWord8 = s14 | s5328
+  s5330 :: SWord8 = s16 & s5328
+  s5331 :: SWord8 = if s5324 then s5329 else s5330
+  s5332 :: SWord8 = s5331 >>> 1
+  s5333 :: SWord8 = s14 | s5332
+  s5334 :: SWord8 = s16 & s5332
+  s5335 :: SWord8 = if s5322 then s5333 else s5334
+  s5336 :: SWord 1 = choose [0:0] s2309
+  s5337 :: SBool = s10 /= s5336
+  s5338 :: SWord8 = if s5337 then s5333 else s5334
+  s5339 :: SWord8 = if s2242 then s5335 else s5338
+  s5340 :: SWord 1 = choose [0:0] s2325
+  s5341 :: SBool = s10 /= s5340
+  s5342 :: SWord 1 = choose [0:0] s2318
+  s5343 :: SBool = s10 /= s5342
+  s5344 :: SWord8 = if s5343 then s5329 else s5330
+  s5345 :: SWord8 = s5344 >>> 1
+  s5346 :: SWord8 = s14 | s5345
+  s5347 :: SWord8 = s16 & s5345
+  s5348 :: SWord8 = if s5341 then s5346 else s5347
+  s5349 :: SWord 1 = choose [0:0] s2330
+  s5350 :: SBool = s10 /= s5349
+  s5351 :: SWord8 = if s5350 then s5346 else s5347
+  s5352 :: SWord8 = if s2242 then s5348 else s5351
+  s5353 :: SWord8 = if s2118 then s5339 else s5352
+  s5354 :: SWord8 = if s2099 then s5320 else s5353
+  s5355 :: SWord8 = if s2080 then s5284 else s5354
+  s5356 :: SWord 1 = choose [0:0] s2385
+  s5357 :: SBool = s10 /= s5356
+  s5358 :: SWord 1 = choose [0:0] s2381
+  s5359 :: SBool = s10 /= s5358
+  s5360 :: SWord 1 = choose [0:0] s2377
+  s5361 :: SBool = s10 /= s5360
+  s5362 :: SWord8 = s2364 >>> 1
+  s5363 :: SWord8 = s14 | s5362
+  s5364 :: SWord8 = s16 & s5362
+  s5365 :: SWord8 = if s5361 then s5363 else s5364
+  s5366 :: SWord8 = s5365 >>> 1
+  s5367 :: SWord8 = s14 | s5366
+  s5368 :: SWord8 = s16 & s5366
+  s5369 :: SWord8 = if s5359 then s5367 else s5368
+  s5370 :: SWord8 = s5369 >>> 1
+  s5371 :: SWord8 = s14 | s5370
+  s5372 :: SWord8 = s16 & s5370
+  s5373 :: SWord8 = if s5357 then s5371 else s5372
+  s5374 :: SWord 1 = choose [0:0] s2390
+  s5375 :: SBool = s10 /= s5374
+  s5376 :: SWord8 = if s5375 then s5371 else s5372
+  s5377 :: SWord8 = if s2373 then s5373 else s5376
+  s5378 :: SWord 1 = choose [0:0] s2406
+  s5379 :: SBool = s10 /= s5378
+  s5380 :: SWord 1 = choose [0:0] s2399
+  s5381 :: SBool = s10 /= s5380
+  s5382 :: SWord8 = if s5381 then s5367 else s5368
+  s5383 :: SWord8 = s5382 >>> 1
+  s5384 :: SWord8 = s14 | s5383
+  s5385 :: SWord8 = s16 & s5383
+  s5386 :: SWord8 = if s5379 then s5384 else s5385
+  s5387 :: SWord 1 = choose [0:0] s2411
+  s5388 :: SBool = s10 /= s5387
+  s5389 :: SWord8 = if s5388 then s5384 else s5385
+  s5390 :: SWord8 = if s2373 then s5386 else s5389
+  s5391 :: SWord8 = if s2351 then s5377 else s5390
+  s5392 :: SWord 1 = choose [0:0] s2432
+  s5393 :: SBool = s10 /= s5392
+  s5394 :: SWord 1 = choose [0:0] s2428
+  s5395 :: SBool = s10 /= s5394
+  s5396 :: SWord 1 = choose [0:0] s2421
+  s5397 :: SBool = s10 /= s5396
+  s5398 :: SWord8 = if s5397 then s5363 else s5364
+  s5399 :: SWord8 = s5398 >>> 1
+  s5400 :: SWord8 = s14 | s5399
+  s5401 :: SWord8 = s16 & s5399
+  s5402 :: SWord8 = if s5395 then s5400 else s5401
+  s5403 :: SWord8 = s5402 >>> 1
+  s5404 :: SWord8 = s14 | s5403
+  s5405 :: SWord8 = s16 & s5403
+  s5406 :: SWord8 = if s5393 then s5404 else s5405
+  s5407 :: SWord 1 = choose [0:0] s2437
+  s5408 :: SBool = s10 /= s5407
+  s5409 :: SWord8 = if s5408 then s5404 else s5405
+  s5410 :: SWord8 = if s2373 then s5406 else s5409
+  s5411 :: SWord 1 = choose [0:0] s2453
+  s5412 :: SBool = s10 /= s5411
+  s5413 :: SWord 1 = choose [0:0] s2446
+  s5414 :: SBool = s10 /= s5413
+  s5415 :: SWord8 = if s5414 then s5400 else s5401
+  s5416 :: SWord8 = s5415 >>> 1
+  s5417 :: SWord8 = s14 | s5416
+  s5418 :: SWord8 = s16 & s5416
+  s5419 :: SWord8 = if s5412 then s5417 else s5418
+  s5420 :: SWord 1 = choose [0:0] s2458
+  s5421 :: SBool = s10 /= s5420
+  s5422 :: SWord8 = if s5421 then s5417 else s5418
+  s5423 :: SWord8 = if s2373 then s5419 else s5422
+  s5424 :: SWord8 = if s2351 then s5410 else s5423
+  s5425 :: SWord8 = if s2099 then s5391 else s5424
+  s5426 :: SWord 1 = choose [0:0] s2493
+  s5427 :: SBool = s10 /= s5426
+  s5428 :: SWord 1 = choose [0:0] s2489
+  s5429 :: SBool = s10 /= s5428
+  s5430 :: SWord 1 = choose [0:0] s2485
+  s5431 :: SBool = s10 /= s5430
+  s5432 :: SWord8 = s2472 >>> 1
+  s5433 :: SWord8 = s14 | s5432
+  s5434 :: SWord8 = s16 & s5432
+  s5435 :: SWord8 = if s5431 then s5433 else s5434
+  s5436 :: SWord8 = s5435 >>> 1
+  s5437 :: SWord8 = s14 | s5436
+  s5438 :: SWord8 = s16 & s5436
+  s5439 :: SWord8 = if s5429 then s5437 else s5438
+  s5440 :: SWord8 = s5439 >>> 1
+  s5441 :: SWord8 = s14 | s5440
+  s5442 :: SWord8 = s16 & s5440
+  s5443 :: SWord8 = if s5427 then s5441 else s5442
+  s5444 :: SWord 1 = choose [0:0] s2498
+  s5445 :: SBool = s10 /= s5444
+  s5446 :: SWord8 = if s5445 then s5441 else s5442
+  s5447 :: SWord8 = if s2478 then s5443 else s5446
+  s5448 :: SWord 1 = choose [0:0] s2514
+  s5449 :: SBool = s10 /= s5448
+  s5450 :: SWord 1 = choose [0:0] s2507
+  s5451 :: SBool = s10 /= s5450
+  s5452 :: SWord8 = if s5451 then s5437 else s5438
+  s5453 :: SWord8 = s5452 >>> 1
+  s5454 :: SWord8 = s14 | s5453
+  s5455 :: SWord8 = s16 & s5453
+  s5456 :: SWord8 = if s5449 then s5454 else s5455
+  s5457 :: SWord 1 = choose [0:0] s2519
+  s5458 :: SBool = s10 /= s5457
+  s5459 :: SWord8 = if s5458 then s5454 else s5455
+  s5460 :: SWord8 = if s2478 then s5456 else s5459
+  s5461 :: SWord8 = if s2351 then s5447 else s5460
+  s5462 :: SWord 1 = choose [0:0] s2540
+  s5463 :: SBool = s10 /= s5462
+  s5464 :: SWord 1 = choose [0:0] s2536
+  s5465 :: SBool = s10 /= s5464
+  s5466 :: SWord 1 = choose [0:0] s2529
+  s5467 :: SBool = s10 /= s5466
+  s5468 :: SWord8 = if s5467 then s5433 else s5434
+  s5469 :: SWord8 = s5468 >>> 1
+  s5470 :: SWord8 = s14 | s5469
+  s5471 :: SWord8 = s16 & s5469
+  s5472 :: SWord8 = if s5465 then s5470 else s5471
+  s5473 :: SWord8 = s5472 >>> 1
+  s5474 :: SWord8 = s14 | s5473
+  s5475 :: SWord8 = s16 & s5473
+  s5476 :: SWord8 = if s5463 then s5474 else s5475
+  s5477 :: SWord 1 = choose [0:0] s2545
+  s5478 :: SBool = s10 /= s5477
+  s5479 :: SWord8 = if s5478 then s5474 else s5475
+  s5480 :: SWord8 = if s2478 then s5476 else s5479
+  s5481 :: SWord 1 = choose [0:0] s2561
+  s5482 :: SBool = s10 /= s5481
+  s5483 :: SWord 1 = choose [0:0] s2554
+  s5484 :: SBool = s10 /= s5483
+  s5485 :: SWord8 = if s5484 then s5470 else s5471
+  s5486 :: SWord8 = s5485 >>> 1
+  s5487 :: SWord8 = s14 | s5486
+  s5488 :: SWord8 = s16 & s5486
+  s5489 :: SWord8 = if s5482 then s5487 else s5488
+  s5490 :: SWord 1 = choose [0:0] s2566
+  s5491 :: SBool = s10 /= s5490
+  s5492 :: SWord8 = if s5491 then s5487 else s5488
+  s5493 :: SWord8 = if s2478 then s5489 else s5492
+  s5494 :: SWord8 = if s2351 then s5480 else s5493
+  s5495 :: SWord8 = if s2099 then s5461 else s5494
+  s5496 :: SWord8 = if s2080 then s5425 else s5495
+  s5497 :: SWord8 = if s2063 then s5355 else s5496
+  s5498 :: SWord 1 = choose [0:0] s2641
+  s5499 :: SBool = s10 /= s5498
+  s5500 :: SWord 1 = choose [0:0] s2637
+  s5501 :: SBool = s10 /= s5500
+  s5502 :: SWord 1 = choose [0:0] s2633
+  s5503 :: SBool = s10 /= s5502
+  s5504 :: SWord8 = s2620 >>> 1
+  s5505 :: SWord8 = s14 | s5504
+  s5506 :: SWord8 = s16 & s5504
+  s5507 :: SWord8 = if s5503 then s5505 else s5506
+  s5508 :: SWord8 = s5507 >>> 1
+  s5509 :: SWord8 = s14 | s5508
+  s5510 :: SWord8 = s16 & s5508
+  s5511 :: SWord8 = if s5501 then s5509 else s5510
+  s5512 :: SWord8 = s5511 >>> 1
+  s5513 :: SWord8 = s14 | s5512
+  s5514 :: SWord8 = s16 & s5512
+  s5515 :: SWord8 = if s5499 then s5513 else s5514
+  s5516 :: SWord 1 = choose [0:0] s2646
+  s5517 :: SBool = s10 /= s5516
+  s5518 :: SWord8 = if s5517 then s5513 else s5514
+  s5519 :: SWord8 = if s2629 then s5515 else s5518
+  s5520 :: SWord 1 = choose [0:0] s2662
+  s5521 :: SBool = s10 /= s5520
+  s5522 :: SWord 1 = choose [0:0] s2655
+  s5523 :: SBool = s10 /= s5522
+  s5524 :: SWord8 = if s5523 then s5509 else s5510
+  s5525 :: SWord8 = s5524 >>> 1
+  s5526 :: SWord8 = s14 | s5525
+  s5527 :: SWord8 = s16 & s5525
+  s5528 :: SWord8 = if s5521 then s5526 else s5527
+  s5529 :: SWord 1 = choose [0:0] s2667
+  s5530 :: SBool = s10 /= s5529
+  s5531 :: SWord8 = if s5530 then s5526 else s5527
+  s5532 :: SWord8 = if s2629 then s5528 else s5531
+  s5533 :: SWord8 = if s2610 then s5519 else s5532
+  s5534 :: SWord 1 = choose [0:0] s2688
+  s5535 :: SBool = s10 /= s5534
+  s5536 :: SWord 1 = choose [0:0] s2684
+  s5537 :: SBool = s10 /= s5536
+  s5538 :: SWord 1 = choose [0:0] s2677
+  s5539 :: SBool = s10 /= s5538
+  s5540 :: SWord8 = if s5539 then s5505 else s5506
+  s5541 :: SWord8 = s5540 >>> 1
+  s5542 :: SWord8 = s14 | s5541
+  s5543 :: SWord8 = s16 & s5541
+  s5544 :: SWord8 = if s5537 then s5542 else s5543
+  s5545 :: SWord8 = s5544 >>> 1
+  s5546 :: SWord8 = s14 | s5545
+  s5547 :: SWord8 = s16 & s5545
+  s5548 :: SWord8 = if s5535 then s5546 else s5547
+  s5549 :: SWord 1 = choose [0:0] s2693
+  s5550 :: SBool = s10 /= s5549
+  s5551 :: SWord8 = if s5550 then s5546 else s5547
+  s5552 :: SWord8 = if s2629 then s5548 else s5551
+  s5553 :: SWord 1 = choose [0:0] s2709
+  s5554 :: SBool = s10 /= s5553
+  s5555 :: SWord 1 = choose [0:0] s2702
+  s5556 :: SBool = s10 /= s5555
+  s5557 :: SWord8 = if s5556 then s5542 else s5543
+  s5558 :: SWord8 = s5557 >>> 1
+  s5559 :: SWord8 = s14 | s5558
+  s5560 :: SWord8 = s16 & s5558
+  s5561 :: SWord8 = if s5554 then s5559 else s5560
+  s5562 :: SWord 1 = choose [0:0] s2714
+  s5563 :: SBool = s10 /= s5562
+  s5564 :: SWord8 = if s5563 then s5559 else s5560
+  s5565 :: SWord8 = if s2629 then s5561 else s5564
+  s5566 :: SWord8 = if s2610 then s5552 else s5565
+  s5567 :: SWord8 = if s2588 then s5533 else s5566
+  s5568 :: SWord 1 = choose [0:0] s2749
+  s5569 :: SBool = s10 /= s5568
+  s5570 :: SWord 1 = choose [0:0] s2745
+  s5571 :: SBool = s10 /= s5570
+  s5572 :: SWord 1 = choose [0:0] s2741
+  s5573 :: SBool = s10 /= s5572
+  s5574 :: SWord8 = s2728 >>> 1
+  s5575 :: SWord8 = s14 | s5574
+  s5576 :: SWord8 = s16 & s5574
+  s5577 :: SWord8 = if s5573 then s5575 else s5576
+  s5578 :: SWord8 = s5577 >>> 1
+  s5579 :: SWord8 = s14 | s5578
+  s5580 :: SWord8 = s16 & s5578
+  s5581 :: SWord8 = if s5571 then s5579 else s5580
+  s5582 :: SWord8 = s5581 >>> 1
+  s5583 :: SWord8 = s14 | s5582
+  s5584 :: SWord8 = s16 & s5582
+  s5585 :: SWord8 = if s5569 then s5583 else s5584
+  s5586 :: SWord 1 = choose [0:0] s2754
+  s5587 :: SBool = s10 /= s5586
+  s5588 :: SWord8 = if s5587 then s5583 else s5584
+  s5589 :: SWord8 = if s2734 then s5585 else s5588
+  s5590 :: SWord 1 = choose [0:0] s2770
+  s5591 :: SBool = s10 /= s5590
+  s5592 :: SWord 1 = choose [0:0] s2763
+  s5593 :: SBool = s10 /= s5592
+  s5594 :: SWord8 = if s5593 then s5579 else s5580
+  s5595 :: SWord8 = s5594 >>> 1
+  s5596 :: SWord8 = s14 | s5595
+  s5597 :: SWord8 = s16 & s5595
+  s5598 :: SWord8 = if s5591 then s5596 else s5597
+  s5599 :: SWord 1 = choose [0:0] s2775
+  s5600 :: SBool = s10 /= s5599
+  s5601 :: SWord8 = if s5600 then s5596 else s5597
+  s5602 :: SWord8 = if s2734 then s5598 else s5601
+  s5603 :: SWord8 = if s2610 then s5589 else s5602
+  s5604 :: SWord 1 = choose [0:0] s2796
+  s5605 :: SBool = s10 /= s5604
+  s5606 :: SWord 1 = choose [0:0] s2792
+  s5607 :: SBool = s10 /= s5606
+  s5608 :: SWord 1 = choose [0:0] s2785
+  s5609 :: SBool = s10 /= s5608
+  s5610 :: SWord8 = if s5609 then s5575 else s5576
+  s5611 :: SWord8 = s5610 >>> 1
+  s5612 :: SWord8 = s14 | s5611
+  s5613 :: SWord8 = s16 & s5611
+  s5614 :: SWord8 = if s5607 then s5612 else s5613
+  s5615 :: SWord8 = s5614 >>> 1
+  s5616 :: SWord8 = s14 | s5615
+  s5617 :: SWord8 = s16 & s5615
+  s5618 :: SWord8 = if s5605 then s5616 else s5617
+  s5619 :: SWord 1 = choose [0:0] s2801
+  s5620 :: SBool = s10 /= s5619
+  s5621 :: SWord8 = if s5620 then s5616 else s5617
+  s5622 :: SWord8 = if s2734 then s5618 else s5621
+  s5623 :: SWord 1 = choose [0:0] s2817
+  s5624 :: SBool = s10 /= s5623
+  s5625 :: SWord 1 = choose [0:0] s2810
+  s5626 :: SBool = s10 /= s5625
+  s5627 :: SWord8 = if s5626 then s5612 else s5613
+  s5628 :: SWord8 = s5627 >>> 1
+  s5629 :: SWord8 = s14 | s5628
+  s5630 :: SWord8 = s16 & s5628
+  s5631 :: SWord8 = if s5624 then s5629 else s5630
+  s5632 :: SWord 1 = choose [0:0] s2822
+  s5633 :: SBool = s10 /= s5632
+  s5634 :: SWord8 = if s5633 then s5629 else s5630
+  s5635 :: SWord8 = if s2734 then s5631 else s5634
+  s5636 :: SWord8 = if s2610 then s5622 else s5635
+  s5637 :: SWord8 = if s2588 then s5603 else s5636
+  s5638 :: SWord8 = if s2080 then s5567 else s5637
+  s5639 :: SWord 1 = choose [0:0] s2877
+  s5640 :: SBool = s10 /= s5639
+  s5641 :: SWord 1 = choose [0:0] s2873
+  s5642 :: SBool = s10 /= s5641
+  s5643 :: SWord 1 = choose [0:0] s2869
+  s5644 :: SBool = s10 /= s5643
+  s5645 :: SWord8 = s2856 >>> 1
+  s5646 :: SWord8 = s14 | s5645
+  s5647 :: SWord8 = s16 & s5645
+  s5648 :: SWord8 = if s5644 then s5646 else s5647
+  s5649 :: SWord8 = s5648 >>> 1
+  s5650 :: SWord8 = s14 | s5649
+  s5651 :: SWord8 = s16 & s5649
+  s5652 :: SWord8 = if s5642 then s5650 else s5651
+  s5653 :: SWord8 = s5652 >>> 1
+  s5654 :: SWord8 = s14 | s5653
+  s5655 :: SWord8 = s16 & s5653
+  s5656 :: SWord8 = if s5640 then s5654 else s5655
+  s5657 :: SWord 1 = choose [0:0] s2882
+  s5658 :: SBool = s10 /= s5657
+  s5659 :: SWord8 = if s5658 then s5654 else s5655
+  s5660 :: SWord8 = if s2865 then s5656 else s5659
+  s5661 :: SWord 1 = choose [0:0] s2898
+  s5662 :: SBool = s10 /= s5661
+  s5663 :: SWord 1 = choose [0:0] s2891
+  s5664 :: SBool = s10 /= s5663
+  s5665 :: SWord8 = if s5664 then s5650 else s5651
+  s5666 :: SWord8 = s5665 >>> 1
+  s5667 :: SWord8 = s14 | s5666
+  s5668 :: SWord8 = s16 & s5666
+  s5669 :: SWord8 = if s5662 then s5667 else s5668
+  s5670 :: SWord 1 = choose [0:0] s2903
+  s5671 :: SBool = s10 /= s5670
+  s5672 :: SWord8 = if s5671 then s5667 else s5668
+  s5673 :: SWord8 = if s2865 then s5669 else s5672
+  s5674 :: SWord8 = if s2843 then s5660 else s5673
+  s5675 :: SWord 1 = choose [0:0] s2924
+  s5676 :: SBool = s10 /= s5675
+  s5677 :: SWord 1 = choose [0:0] s2920
+  s5678 :: SBool = s10 /= s5677
+  s5679 :: SWord 1 = choose [0:0] s2913
+  s5680 :: SBool = s10 /= s5679
+  s5681 :: SWord8 = if s5680 then s5646 else s5647
+  s5682 :: SWord8 = s5681 >>> 1
+  s5683 :: SWord8 = s14 | s5682
+  s5684 :: SWord8 = s16 & s5682
+  s5685 :: SWord8 = if s5678 then s5683 else s5684
+  s5686 :: SWord8 = s5685 >>> 1
+  s5687 :: SWord8 = s14 | s5686
+  s5688 :: SWord8 = s16 & s5686
+  s5689 :: SWord8 = if s5676 then s5687 else s5688
+  s5690 :: SWord 1 = choose [0:0] s2929
+  s5691 :: SBool = s10 /= s5690
+  s5692 :: SWord8 = if s5691 then s5687 else s5688
+  s5693 :: SWord8 = if s2865 then s5689 else s5692
+  s5694 :: SWord 1 = choose [0:0] s2945
+  s5695 :: SBool = s10 /= s5694
+  s5696 :: SWord 1 = choose [0:0] s2938
+  s5697 :: SBool = s10 /= s5696
+  s5698 :: SWord8 = if s5697 then s5683 else s5684
+  s5699 :: SWord8 = s5698 >>> 1
+  s5700 :: SWord8 = s14 | s5699
+  s5701 :: SWord8 = s16 & s5699
+  s5702 :: SWord8 = if s5695 then s5700 else s5701
+  s5703 :: SWord 1 = choose [0:0] s2950
+  s5704 :: SBool = s10 /= s5703
+  s5705 :: SWord8 = if s5704 then s5700 else s5701
+  s5706 :: SWord8 = if s2865 then s5702 else s5705
+  s5707 :: SWord8 = if s2843 then s5693 else s5706
+  s5708 :: SWord8 = if s2588 then s5674 else s5707
+  s5709 :: SWord 1 = choose [0:0] s2985
+  s5710 :: SBool = s10 /= s5709
+  s5711 :: SWord 1 = choose [0:0] s2981
+  s5712 :: SBool = s10 /= s5711
+  s5713 :: SWord 1 = choose [0:0] s2977
+  s5714 :: SBool = s10 /= s5713
+  s5715 :: SWord8 = s2964 >>> 1
+  s5716 :: SWord8 = s14 | s5715
+  s5717 :: SWord8 = s16 & s5715
+  s5718 :: SWord8 = if s5714 then s5716 else s5717
+  s5719 :: SWord8 = s5718 >>> 1
+  s5720 :: SWord8 = s14 | s5719
+  s5721 :: SWord8 = s16 & s5719
+  s5722 :: SWord8 = if s5712 then s5720 else s5721
+  s5723 :: SWord8 = s5722 >>> 1
+  s5724 :: SWord8 = s14 | s5723
+  s5725 :: SWord8 = s16 & s5723
+  s5726 :: SWord8 = if s5710 then s5724 else s5725
+  s5727 :: SWord 1 = choose [0:0] s2990
+  s5728 :: SBool = s10 /= s5727
+  s5729 :: SWord8 = if s5728 then s5724 else s5725
+  s5730 :: SWord8 = if s2970 then s5726 else s5729
+  s5731 :: SWord 1 = choose [0:0] s3006
+  s5732 :: SBool = s10 /= s5731
+  s5733 :: SWord 1 = choose [0:0] s2999
+  s5734 :: SBool = s10 /= s5733
+  s5735 :: SWord8 = if s5734 then s5720 else s5721
+  s5736 :: SWord8 = s5735 >>> 1
+  s5737 :: SWord8 = s14 | s5736
+  s5738 :: SWord8 = s16 & s5736
+  s5739 :: SWord8 = if s5732 then s5737 else s5738
+  s5740 :: SWord 1 = choose [0:0] s3011
+  s5741 :: SBool = s10 /= s5740
+  s5742 :: SWord8 = if s5741 then s5737 else s5738
+  s5743 :: SWord8 = if s2970 then s5739 else s5742
+  s5744 :: SWord8 = if s2843 then s5730 else s5743
+  s5745 :: SWord 1 = choose [0:0] s3032
+  s5746 :: SBool = s10 /= s5745
+  s5747 :: SWord 1 = choose [0:0] s3028
+  s5748 :: SBool = s10 /= s5747
+  s5749 :: SWord 1 = choose [0:0] s3021
+  s5750 :: SBool = s10 /= s5749
+  s5751 :: SWord8 = if s5750 then s5716 else s5717
+  s5752 :: SWord8 = s5751 >>> 1
+  s5753 :: SWord8 = s14 | s5752
+  s5754 :: SWord8 = s16 & s5752
+  s5755 :: SWord8 = if s5748 then s5753 else s5754
+  s5756 :: SWord8 = s5755 >>> 1
+  s5757 :: SWord8 = s14 | s5756
+  s5758 :: SWord8 = s16 & s5756
+  s5759 :: SWord8 = if s5746 then s5757 else s5758
+  s5760 :: SWord 1 = choose [0:0] s3037
+  s5761 :: SBool = s10 /= s5760
+  s5762 :: SWord8 = if s5761 then s5757 else s5758
+  s5763 :: SWord8 = if s2970 then s5759 else s5762
+  s5764 :: SWord 1 = choose [0:0] s3053
+  s5765 :: SBool = s10 /= s5764
+  s5766 :: SWord 1 = choose [0:0] s3046
+  s5767 :: SBool = s10 /= s5766
+  s5768 :: SWord8 = if s5767 then s5753 else s5754
+  s5769 :: SWord8 = s5768 >>> 1
+  s5770 :: SWord8 = s14 | s5769
+  s5771 :: SWord8 = s16 & s5769
+  s5772 :: SWord8 = if s5765 then s5770 else s5771
+  s5773 :: SWord 1 = choose [0:0] s3058
+  s5774 :: SBool = s10 /= s5773
+  s5775 :: SWord8 = if s5774 then s5770 else s5771
+  s5776 :: SWord8 = if s2970 then s5772 else s5775
+  s5777 :: SWord8 = if s2843 then s5763 else s5776
+  s5778 :: SWord8 = if s2588 then s5744 else s5777
+  s5779 :: SWord8 = if s2080 then s5708 else s5778
+  s5780 :: SWord8 = if s2063 then s5638 else s5779
+  s5781 :: SWord8 = if s30 then s5497 else s5780
+  s5782 :: SWord 1 = choose [0:0] s3153
+  s5783 :: SBool = s10 /= s5782
+  s5784 :: SWord 1 = choose [0:0] s3149
+  s5785 :: SBool = s10 /= s5784
+  s5786 :: SWord 1 = choose [0:0] s3145
+  s5787 :: SBool = s10 /= s5786
+  s5788 :: SWord8 = s3132 >>> 1
+  s5789 :: SWord8 = s14 | s5788
+  s5790 :: SWord8 = s16 & s5788
+  s5791 :: SWord8 = if s5787 then s5789 else s5790
+  s5792 :: SWord8 = s5791 >>> 1
+  s5793 :: SWord8 = s14 | s5792
+  s5794 :: SWord8 = s16 & s5792
+  s5795 :: SWord8 = if s5785 then s5793 else s5794
+  s5796 :: SWord8 = s5795 >>> 1
+  s5797 :: SWord8 = s14 | s5796
+  s5798 :: SWord8 = s16 & s5796
+  s5799 :: SWord8 = if s5783 then s5797 else s5798
+  s5800 :: SWord 1 = choose [0:0] s3158
+  s5801 :: SBool = s10 /= s5800
+  s5802 :: SWord8 = if s5801 then s5797 else s5798
+  s5803 :: SWord8 = if s3141 then s5799 else s5802
+  s5804 :: SWord 1 = choose [0:0] s3174
+  s5805 :: SBool = s10 /= s5804
+  s5806 :: SWord 1 = choose [0:0] s3167
+  s5807 :: SBool = s10 /= s5806
+  s5808 :: SWord8 = if s5807 then s5793 else s5794
+  s5809 :: SWord8 = s5808 >>> 1
+  s5810 :: SWord8 = s14 | s5809
+  s5811 :: SWord8 = s16 & s5809
+  s5812 :: SWord8 = if s5805 then s5810 else s5811
+  s5813 :: SWord 1 = choose [0:0] s3179
+  s5814 :: SBool = s10 /= s5813
+  s5815 :: SWord8 = if s5814 then s5810 else s5811
+  s5816 :: SWord8 = if s3141 then s5812 else s5815
+  s5817 :: SWord8 = if s3122 then s5803 else s5816
+  s5818 :: SWord 1 = choose [0:0] s3200
+  s5819 :: SBool = s10 /= s5818
+  s5820 :: SWord 1 = choose [0:0] s3196
+  s5821 :: SBool = s10 /= s5820
+  s5822 :: SWord 1 = choose [0:0] s3189
+  s5823 :: SBool = s10 /= s5822
+  s5824 :: SWord8 = if s5823 then s5789 else s5790
+  s5825 :: SWord8 = s5824 >>> 1
+  s5826 :: SWord8 = s14 | s5825
+  s5827 :: SWord8 = s16 & s5825
+  s5828 :: SWord8 = if s5821 then s5826 else s5827
+  s5829 :: SWord8 = s5828 >>> 1
+  s5830 :: SWord8 = s14 | s5829
+  s5831 :: SWord8 = s16 & s5829
+  s5832 :: SWord8 = if s5819 then s5830 else s5831
+  s5833 :: SWord 1 = choose [0:0] s3205
+  s5834 :: SBool = s10 /= s5833
+  s5835 :: SWord8 = if s5834 then s5830 else s5831
+  s5836 :: SWord8 = if s3141 then s5832 else s5835
+  s5837 :: SWord 1 = choose [0:0] s3221
+  s5838 :: SBool = s10 /= s5837
+  s5839 :: SWord 1 = choose [0:0] s3214
+  s5840 :: SBool = s10 /= s5839
+  s5841 :: SWord8 = if s5840 then s5826 else s5827
+  s5842 :: SWord8 = s5841 >>> 1
+  s5843 :: SWord8 = s14 | s5842
+  s5844 :: SWord8 = s16 & s5842
+  s5845 :: SWord8 = if s5838 then s5843 else s5844
+  s5846 :: SWord 1 = choose [0:0] s3226
+  s5847 :: SBool = s10 /= s5846
+  s5848 :: SWord8 = if s5847 then s5843 else s5844
+  s5849 :: SWord8 = if s3141 then s5845 else s5848
+  s5850 :: SWord8 = if s3122 then s5836 else s5849
+  s5851 :: SWord8 = if s3103 then s5817 else s5850
+  s5852 :: SWord 1 = choose [0:0] s3261
+  s5853 :: SBool = s10 /= s5852
+  s5854 :: SWord 1 = choose [0:0] s3257
+  s5855 :: SBool = s10 /= s5854
+  s5856 :: SWord 1 = choose [0:0] s3253
+  s5857 :: SBool = s10 /= s5856
+  s5858 :: SWord8 = s3240 >>> 1
+  s5859 :: SWord8 = s14 | s5858
+  s5860 :: SWord8 = s16 & s5858
+  s5861 :: SWord8 = if s5857 then s5859 else s5860
+  s5862 :: SWord8 = s5861 >>> 1
+  s5863 :: SWord8 = s14 | s5862
+  s5864 :: SWord8 = s16 & s5862
+  s5865 :: SWord8 = if s5855 then s5863 else s5864
+  s5866 :: SWord8 = s5865 >>> 1
+  s5867 :: SWord8 = s14 | s5866
+  s5868 :: SWord8 = s16 & s5866
+  s5869 :: SWord8 = if s5853 then s5867 else s5868
+  s5870 :: SWord 1 = choose [0:0] s3266
+  s5871 :: SBool = s10 /= s5870
+  s5872 :: SWord8 = if s5871 then s5867 else s5868
+  s5873 :: SWord8 = if s3246 then s5869 else s5872
+  s5874 :: SWord 1 = choose [0:0] s3282
+  s5875 :: SBool = s10 /= s5874
+  s5876 :: SWord 1 = choose [0:0] s3275
+  s5877 :: SBool = s10 /= s5876
+  s5878 :: SWord8 = if s5877 then s5863 else s5864
+  s5879 :: SWord8 = s5878 >>> 1
+  s5880 :: SWord8 = s14 | s5879
+  s5881 :: SWord8 = s16 & s5879
+  s5882 :: SWord8 = if s5875 then s5880 else s5881
+  s5883 :: SWord 1 = choose [0:0] s3287
+  s5884 :: SBool = s10 /= s5883
+  s5885 :: SWord8 = if s5884 then s5880 else s5881
+  s5886 :: SWord8 = if s3246 then s5882 else s5885
+  s5887 :: SWord8 = if s3122 then s5873 else s5886
+  s5888 :: SWord 1 = choose [0:0] s3308
+  s5889 :: SBool = s10 /= s5888
+  s5890 :: SWord 1 = choose [0:0] s3304
+  s5891 :: SBool = s10 /= s5890
+  s5892 :: SWord 1 = choose [0:0] s3297
+  s5893 :: SBool = s10 /= s5892
+  s5894 :: SWord8 = if s5893 then s5859 else s5860
+  s5895 :: SWord8 = s5894 >>> 1
+  s5896 :: SWord8 = s14 | s5895
+  s5897 :: SWord8 = s16 & s5895
+  s5898 :: SWord8 = if s5891 then s5896 else s5897
+  s5899 :: SWord8 = s5898 >>> 1
+  s5900 :: SWord8 = s14 | s5899
+  s5901 :: SWord8 = s16 & s5899
+  s5902 :: SWord8 = if s5889 then s5900 else s5901
+  s5903 :: SWord 1 = choose [0:0] s3313
+  s5904 :: SBool = s10 /= s5903
+  s5905 :: SWord8 = if s5904 then s5900 else s5901
+  s5906 :: SWord8 = if s3246 then s5902 else s5905
+  s5907 :: SWord 1 = choose [0:0] s3329
+  s5908 :: SBool = s10 /= s5907
+  s5909 :: SWord 1 = choose [0:0] s3322
+  s5910 :: SBool = s10 /= s5909
+  s5911 :: SWord8 = if s5910 then s5896 else s5897
+  s5912 :: SWord8 = s5911 >>> 1
+  s5913 :: SWord8 = s14 | s5912
+  s5914 :: SWord8 = s16 & s5912
+  s5915 :: SWord8 = if s5908 then s5913 else s5914
+  s5916 :: SWord 1 = choose [0:0] s3334
+  s5917 :: SBool = s10 /= s5916
+  s5918 :: SWord8 = if s5917 then s5913 else s5914
+  s5919 :: SWord8 = if s3246 then s5915 else s5918
+  s5920 :: SWord8 = if s3122 then s5906 else s5919
+  s5921 :: SWord8 = if s3103 then s5887 else s5920
+  s5922 :: SWord8 = if s3081 then s5851 else s5921
+  s5923 :: SWord 1 = choose [0:0] s3389
+  s5924 :: SBool = s10 /= s5923
+  s5925 :: SWord 1 = choose [0:0] s3385
+  s5926 :: SBool = s10 /= s5925
+  s5927 :: SWord 1 = choose [0:0] s3381
+  s5928 :: SBool = s10 /= s5927
+  s5929 :: SWord8 = s3368 >>> 1
+  s5930 :: SWord8 = s14 | s5929
+  s5931 :: SWord8 = s16 & s5929
+  s5932 :: SWord8 = if s5928 then s5930 else s5931
+  s5933 :: SWord8 = s5932 >>> 1
+  s5934 :: SWord8 = s14 | s5933
+  s5935 :: SWord8 = s16 & s5933
+  s5936 :: SWord8 = if s5926 then s5934 else s5935
+  s5937 :: SWord8 = s5936 >>> 1
+  s5938 :: SWord8 = s14 | s5937
+  s5939 :: SWord8 = s16 & s5937
+  s5940 :: SWord8 = if s5924 then s5938 else s5939
+  s5941 :: SWord 1 = choose [0:0] s3394
+  s5942 :: SBool = s10 /= s5941
+  s5943 :: SWord8 = if s5942 then s5938 else s5939
+  s5944 :: SWord8 = if s3377 then s5940 else s5943
+  s5945 :: SWord 1 = choose [0:0] s3410
+  s5946 :: SBool = s10 /= s5945
+  s5947 :: SWord 1 = choose [0:0] s3403
+  s5948 :: SBool = s10 /= s5947
+  s5949 :: SWord8 = if s5948 then s5934 else s5935
+  s5950 :: SWord8 = s5949 >>> 1
+  s5951 :: SWord8 = s14 | s5950
+  s5952 :: SWord8 = s16 & s5950
+  s5953 :: SWord8 = if s5946 then s5951 else s5952
+  s5954 :: SWord 1 = choose [0:0] s3415
+  s5955 :: SBool = s10 /= s5954
+  s5956 :: SWord8 = if s5955 then s5951 else s5952
+  s5957 :: SWord8 = if s3377 then s5953 else s5956
+  s5958 :: SWord8 = if s3355 then s5944 else s5957
+  s5959 :: SWord 1 = choose [0:0] s3436
+  s5960 :: SBool = s10 /= s5959
+  s5961 :: SWord 1 = choose [0:0] s3432
+  s5962 :: SBool = s10 /= s5961
+  s5963 :: SWord 1 = choose [0:0] s3425
+  s5964 :: SBool = s10 /= s5963
+  s5965 :: SWord8 = if s5964 then s5930 else s5931
+  s5966 :: SWord8 = s5965 >>> 1
+  s5967 :: SWord8 = s14 | s5966
+  s5968 :: SWord8 = s16 & s5966
+  s5969 :: SWord8 = if s5962 then s5967 else s5968
+  s5970 :: SWord8 = s5969 >>> 1
+  s5971 :: SWord8 = s14 | s5970
+  s5972 :: SWord8 = s16 & s5970
+  s5973 :: SWord8 = if s5960 then s5971 else s5972
+  s5974 :: SWord 1 = choose [0:0] s3441
+  s5975 :: SBool = s10 /= s5974
+  s5976 :: SWord8 = if s5975 then s5971 else s5972
+  s5977 :: SWord8 = if s3377 then s5973 else s5976
+  s5978 :: SWord 1 = choose [0:0] s3457
+  s5979 :: SBool = s10 /= s5978
+  s5980 :: SWord 1 = choose [0:0] s3450
+  s5981 :: SBool = s10 /= s5980
+  s5982 :: SWord8 = if s5981 then s5967 else s5968
+  s5983 :: SWord8 = s5982 >>> 1
+  s5984 :: SWord8 = s14 | s5983
+  s5985 :: SWord8 = s16 & s5983
+  s5986 :: SWord8 = if s5979 then s5984 else s5985
+  s5987 :: SWord 1 = choose [0:0] s3462
+  s5988 :: SBool = s10 /= s5987
+  s5989 :: SWord8 = if s5988 then s5984 else s5985
+  s5990 :: SWord8 = if s3377 then s5986 else s5989
+  s5991 :: SWord8 = if s3355 then s5977 else s5990
+  s5992 :: SWord8 = if s3103 then s5958 else s5991
+  s5993 :: SWord 1 = choose [0:0] s3497
+  s5994 :: SBool = s10 /= s5993
+  s5995 :: SWord 1 = choose [0:0] s3493
+  s5996 :: SBool = s10 /= s5995
+  s5997 :: SWord 1 = choose [0:0] s3489
+  s5998 :: SBool = s10 /= s5997
+  s5999 :: SWord8 = s3476 >>> 1
+  s6000 :: SWord8 = s14 | s5999
+  s6001 :: SWord8 = s16 & s5999
+  s6002 :: SWord8 = if s5998 then s6000 else s6001
+  s6003 :: SWord8 = s6002 >>> 1
+  s6004 :: SWord8 = s14 | s6003
+  s6005 :: SWord8 = s16 & s6003
+  s6006 :: SWord8 = if s5996 then s6004 else s6005
+  s6007 :: SWord8 = s6006 >>> 1
+  s6008 :: SWord8 = s14 | s6007
+  s6009 :: SWord8 = s16 & s6007
+  s6010 :: SWord8 = if s5994 then s6008 else s6009
+  s6011 :: SWord 1 = choose [0:0] s3502
+  s6012 :: SBool = s10 /= s6011
+  s6013 :: SWord8 = if s6012 then s6008 else s6009
+  s6014 :: SWord8 = if s3482 then s6010 else s6013
+  s6015 :: SWord 1 = choose [0:0] s3518
+  s6016 :: SBool = s10 /= s6015
+  s6017 :: SWord 1 = choose [0:0] s3511
+  s6018 :: SBool = s10 /= s6017
+  s6019 :: SWord8 = if s6018 then s6004 else s6005
+  s6020 :: SWord8 = s6019 >>> 1
+  s6021 :: SWord8 = s14 | s6020
+  s6022 :: SWord8 = s16 & s6020
+  s6023 :: SWord8 = if s6016 then s6021 else s6022
+  s6024 :: SWord 1 = choose [0:0] s3523
+  s6025 :: SBool = s10 /= s6024
+  s6026 :: SWord8 = if s6025 then s6021 else s6022
+  s6027 :: SWord8 = if s3482 then s6023 else s6026
+  s6028 :: SWord8 = if s3355 then s6014 else s6027
+  s6029 :: SWord 1 = choose [0:0] s3544
+  s6030 :: SBool = s10 /= s6029
+  s6031 :: SWord 1 = choose [0:0] s3540
+  s6032 :: SBool = s10 /= s6031
+  s6033 :: SWord 1 = choose [0:0] s3533
+  s6034 :: SBool = s10 /= s6033
+  s6035 :: SWord8 = if s6034 then s6000 else s6001
+  s6036 :: SWord8 = s6035 >>> 1
+  s6037 :: SWord8 = s14 | s6036
+  s6038 :: SWord8 = s16 & s6036
+  s6039 :: SWord8 = if s6032 then s6037 else s6038
+  s6040 :: SWord8 = s6039 >>> 1
+  s6041 :: SWord8 = s14 | s6040
+  s6042 :: SWord8 = s16 & s6040
+  s6043 :: SWord8 = if s6030 then s6041 else s6042
+  s6044 :: SWord 1 = choose [0:0] s3549
+  s6045 :: SBool = s10 /= s6044
+  s6046 :: SWord8 = if s6045 then s6041 else s6042
+  s6047 :: SWord8 = if s3482 then s6043 else s6046
+  s6048 :: SWord 1 = choose [0:0] s3565
+  s6049 :: SBool = s10 /= s6048
+  s6050 :: SWord 1 = choose [0:0] s3558
+  s6051 :: SBool = s10 /= s6050
+  s6052 :: SWord8 = if s6051 then s6037 else s6038
+  s6053 :: SWord8 = s6052 >>> 1
+  s6054 :: SWord8 = s14 | s6053
+  s6055 :: SWord8 = s16 & s6053
+  s6056 :: SWord8 = if s6049 then s6054 else s6055
+  s6057 :: SWord 1 = choose [0:0] s3570
+  s6058 :: SBool = s10 /= s6057
+  s6059 :: SWord8 = if s6058 then s6054 else s6055
+  s6060 :: SWord8 = if s3482 then s6056 else s6059
+  s6061 :: SWord8 = if s3355 then s6047 else s6060
+  s6062 :: SWord8 = if s3103 then s6028 else s6061
+  s6063 :: SWord8 = if s3081 then s5992 else s6062
+  s6064 :: SWord8 = if s2063 then s5922 else s6063
+  s6065 :: SWord 1 = choose [0:0] s3645
+  s6066 :: SBool = s10 /= s6065
+  s6067 :: SWord 1 = choose [0:0] s3641
+  s6068 :: SBool = s10 /= s6067
+  s6069 :: SWord 1 = choose [0:0] s3637
+  s6070 :: SBool = s10 /= s6069
+  s6071 :: SWord8 = s3624 >>> 1
+  s6072 :: SWord8 = s14 | s6071
+  s6073 :: SWord8 = s16 & s6071
+  s6074 :: SWord8 = if s6070 then s6072 else s6073
+  s6075 :: SWord8 = s6074 >>> 1
+  s6076 :: SWord8 = s14 | s6075
+  s6077 :: SWord8 = s16 & s6075
+  s6078 :: SWord8 = if s6068 then s6076 else s6077
+  s6079 :: SWord8 = s6078 >>> 1
+  s6080 :: SWord8 = s14 | s6079
+  s6081 :: SWord8 = s16 & s6079
+  s6082 :: SWord8 = if s6066 then s6080 else s6081
+  s6083 :: SWord 1 = choose [0:0] s3650
+  s6084 :: SBool = s10 /= s6083
+  s6085 :: SWord8 = if s6084 then s6080 else s6081
+  s6086 :: SWord8 = if s3633 then s6082 else s6085
+  s6087 :: SWord 1 = choose [0:0] s3666
+  s6088 :: SBool = s10 /= s6087
+  s6089 :: SWord 1 = choose [0:0] s3659
+  s6090 :: SBool = s10 /= s6089
+  s6091 :: SWord8 = if s6090 then s6076 else s6077
+  s6092 :: SWord8 = s6091 >>> 1
+  s6093 :: SWord8 = s14 | s6092
+  s6094 :: SWord8 = s16 & s6092
+  s6095 :: SWord8 = if s6088 then s6093 else s6094
+  s6096 :: SWord 1 = choose [0:0] s3671
+  s6097 :: SBool = s10 /= s6096
+  s6098 :: SWord8 = if s6097 then s6093 else s6094
+  s6099 :: SWord8 = if s3633 then s6095 else s6098
+  s6100 :: SWord8 = if s3614 then s6086 else s6099
+  s6101 :: SWord 1 = choose [0:0] s3692
+  s6102 :: SBool = s10 /= s6101
+  s6103 :: SWord 1 = choose [0:0] s3688
+  s6104 :: SBool = s10 /= s6103
+  s6105 :: SWord 1 = choose [0:0] s3681
+  s6106 :: SBool = s10 /= s6105
+  s6107 :: SWord8 = if s6106 then s6072 else s6073
+  s6108 :: SWord8 = s6107 >>> 1
+  s6109 :: SWord8 = s14 | s6108
+  s6110 :: SWord8 = s16 & s6108
+  s6111 :: SWord8 = if s6104 then s6109 else s6110
+  s6112 :: SWord8 = s6111 >>> 1
+  s6113 :: SWord8 = s14 | s6112
+  s6114 :: SWord8 = s16 & s6112
+  s6115 :: SWord8 = if s6102 then s6113 else s6114
+  s6116 :: SWord 1 = choose [0:0] s3697
+  s6117 :: SBool = s10 /= s6116
+  s6118 :: SWord8 = if s6117 then s6113 else s6114
+  s6119 :: SWord8 = if s3633 then s6115 else s6118
+  s6120 :: SWord 1 = choose [0:0] s3713
+  s6121 :: SBool = s10 /= s6120
+  s6122 :: SWord 1 = choose [0:0] s3706
+  s6123 :: SBool = s10 /= s6122
+  s6124 :: SWord8 = if s6123 then s6109 else s6110
+  s6125 :: SWord8 = s6124 >>> 1
+  s6126 :: SWord8 = s14 | s6125
+  s6127 :: SWord8 = s16 & s6125
+  s6128 :: SWord8 = if s6121 then s6126 else s6127
+  s6129 :: SWord 1 = choose [0:0] s3718
+  s6130 :: SBool = s10 /= s6129
+  s6131 :: SWord8 = if s6130 then s6126 else s6127
+  s6132 :: SWord8 = if s3633 then s6128 else s6131
+  s6133 :: SWord8 = if s3614 then s6119 else s6132
+  s6134 :: SWord8 = if s3592 then s6100 else s6133
+  s6135 :: SWord 1 = choose [0:0] s3753
+  s6136 :: SBool = s10 /= s6135
+  s6137 :: SWord 1 = choose [0:0] s3749
+  s6138 :: SBool = s10 /= s6137
+  s6139 :: SWord 1 = choose [0:0] s3745
+  s6140 :: SBool = s10 /= s6139
+  s6141 :: SWord8 = s3732 >>> 1
+  s6142 :: SWord8 = s14 | s6141
+  s6143 :: SWord8 = s16 & s6141
+  s6144 :: SWord8 = if s6140 then s6142 else s6143
+  s6145 :: SWord8 = s6144 >>> 1
+  s6146 :: SWord8 = s14 | s6145
+  s6147 :: SWord8 = s16 & s6145
+  s6148 :: SWord8 = if s6138 then s6146 else s6147
+  s6149 :: SWord8 = s6148 >>> 1
+  s6150 :: SWord8 = s14 | s6149
+  s6151 :: SWord8 = s16 & s6149
+  s6152 :: SWord8 = if s6136 then s6150 else s6151
+  s6153 :: SWord 1 = choose [0:0] s3758
+  s6154 :: SBool = s10 /= s6153
+  s6155 :: SWord8 = if s6154 then s6150 else s6151
+  s6156 :: SWord8 = if s3738 then s6152 else s6155
+  s6157 :: SWord 1 = choose [0:0] s3774
+  s6158 :: SBool = s10 /= s6157
+  s6159 :: SWord 1 = choose [0:0] s3767
+  s6160 :: SBool = s10 /= s6159
+  s6161 :: SWord8 = if s6160 then s6146 else s6147
+  s6162 :: SWord8 = s6161 >>> 1
+  s6163 :: SWord8 = s14 | s6162
+  s6164 :: SWord8 = s16 & s6162
+  s6165 :: SWord8 = if s6158 then s6163 else s6164
+  s6166 :: SWord 1 = choose [0:0] s3779
+  s6167 :: SBool = s10 /= s6166
+  s6168 :: SWord8 = if s6167 then s6163 else s6164
+  s6169 :: SWord8 = if s3738 then s6165 else s6168
+  s6170 :: SWord8 = if s3614 then s6156 else s6169
+  s6171 :: SWord 1 = choose [0:0] s3800
+  s6172 :: SBool = s10 /= s6171
+  s6173 :: SWord 1 = choose [0:0] s3796
+  s6174 :: SBool = s10 /= s6173
+  s6175 :: SWord 1 = choose [0:0] s3789
+  s6176 :: SBool = s10 /= s6175
+  s6177 :: SWord8 = if s6176 then s6142 else s6143
+  s6178 :: SWord8 = s6177 >>> 1
+  s6179 :: SWord8 = s14 | s6178
+  s6180 :: SWord8 = s16 & s6178
+  s6181 :: SWord8 = if s6174 then s6179 else s6180
+  s6182 :: SWord8 = s6181 >>> 1
+  s6183 :: SWord8 = s14 | s6182
+  s6184 :: SWord8 = s16 & s6182
+  s6185 :: SWord8 = if s6172 then s6183 else s6184
+  s6186 :: SWord 1 = choose [0:0] s3805
+  s6187 :: SBool = s10 /= s6186
+  s6188 :: SWord8 = if s6187 then s6183 else s6184
+  s6189 :: SWord8 = if s3738 then s6185 else s6188
+  s6190 :: SWord 1 = choose [0:0] s3821
+  s6191 :: SBool = s10 /= s6190
+  s6192 :: SWord 1 = choose [0:0] s3814
+  s6193 :: SBool = s10 /= s6192
+  s6194 :: SWord8 = if s6193 then s6179 else s6180
+  s6195 :: SWord8 = s6194 >>> 1
+  s6196 :: SWord8 = s14 | s6195
+  s6197 :: SWord8 = s16 & s6195
+  s6198 :: SWord8 = if s6191 then s6196 else s6197
+  s6199 :: SWord 1 = choose [0:0] s3826
+  s6200 :: SBool = s10 /= s6199
+  s6201 :: SWord8 = if s6200 then s6196 else s6197
+  s6202 :: SWord8 = if s3738 then s6198 else s6201
+  s6203 :: SWord8 = if s3614 then s6189 else s6202
+  s6204 :: SWord8 = if s3592 then s6170 else s6203
+  s6205 :: SWord8 = if s3081 then s6134 else s6204
+  s6206 :: SWord 1 = choose [0:0] s3881
+  s6207 :: SBool = s10 /= s6206
+  s6208 :: SWord 1 = choose [0:0] s3877
+  s6209 :: SBool = s10 /= s6208
+  s6210 :: SWord 1 = choose [0:0] s3873
+  s6211 :: SBool = s10 /= s6210
+  s6212 :: SWord8 = s3860 >>> 1
+  s6213 :: SWord8 = s14 | s6212
+  s6214 :: SWord8 = s16 & s6212
+  s6215 :: SWord8 = if s6211 then s6213 else s6214
+  s6216 :: SWord8 = s6215 >>> 1
+  s6217 :: SWord8 = s14 | s6216
+  s6218 :: SWord8 = s16 & s6216
+  s6219 :: SWord8 = if s6209 then s6217 else s6218
+  s6220 :: SWord8 = s6219 >>> 1
+  s6221 :: SWord8 = s14 | s6220
+  s6222 :: SWord8 = s16 & s6220
+  s6223 :: SWord8 = if s6207 then s6221 else s6222
+  s6224 :: SWord 1 = choose [0:0] s3886
+  s6225 :: SBool = s10 /= s6224
+  s6226 :: SWord8 = if s6225 then s6221 else s6222
+  s6227 :: SWord8 = if s3869 then s6223 else s6226
+  s6228 :: SWord 1 = choose [0:0] s3902
+  s6229 :: SBool = s10 /= s6228
+  s6230 :: SWord 1 = choose [0:0] s3895
+  s6231 :: SBool = s10 /= s6230
+  s6232 :: SWord8 = if s6231 then s6217 else s6218
+  s6233 :: SWord8 = s6232 >>> 1
+  s6234 :: SWord8 = s14 | s6233
+  s6235 :: SWord8 = s16 & s6233
+  s6236 :: SWord8 = if s6229 then s6234 else s6235
+  s6237 :: SWord 1 = choose [0:0] s3907
+  s6238 :: SBool = s10 /= s6237
+  s6239 :: SWord8 = if s6238 then s6234 else s6235
+  s6240 :: SWord8 = if s3869 then s6236 else s6239
+  s6241 :: SWord8 = if s3847 then s6227 else s6240
+  s6242 :: SWord 1 = choose [0:0] s3928
+  s6243 :: SBool = s10 /= s6242
+  s6244 :: SWord 1 = choose [0:0] s3924
+  s6245 :: SBool = s10 /= s6244
+  s6246 :: SWord 1 = choose [0:0] s3917
+  s6247 :: SBool = s10 /= s6246
+  s6248 :: SWord8 = if s6247 then s6213 else s6214
+  s6249 :: SWord8 = s6248 >>> 1
+  s6250 :: SWord8 = s14 | s6249
+  s6251 :: SWord8 = s16 & s6249
+  s6252 :: SWord8 = if s6245 then s6250 else s6251
+  s6253 :: SWord8 = s6252 >>> 1
+  s6254 :: SWord8 = s14 | s6253
+  s6255 :: SWord8 = s16 & s6253
+  s6256 :: SWord8 = if s6243 then s6254 else s6255
+  s6257 :: SWord 1 = choose [0:0] s3933
+  s6258 :: SBool = s10 /= s6257
+  s6259 :: SWord8 = if s6258 then s6254 else s6255
+  s6260 :: SWord8 = if s3869 then s6256 else s6259
+  s6261 :: SWord 1 = choose [0:0] s3949
+  s6262 :: SBool = s10 /= s6261
+  s6263 :: SWord 1 = choose [0:0] s3942
+  s6264 :: SBool = s10 /= s6263
+  s6265 :: SWord8 = if s6264 then s6250 else s6251
+  s6266 :: SWord8 = s6265 >>> 1
+  s6267 :: SWord8 = s14 | s6266
+  s6268 :: SWord8 = s16 & s6266
+  s6269 :: SWord8 = if s6262 then s6267 else s6268
+  s6270 :: SWord 1 = choose [0:0] s3954
+  s6271 :: SBool = s10 /= s6270
+  s6272 :: SWord8 = if s6271 then s6267 else s6268
+  s6273 :: SWord8 = if s3869 then s6269 else s6272
+  s6274 :: SWord8 = if s3847 then s6260 else s6273
+  s6275 :: SWord8 = if s3592 then s6241 else s6274
+  s6276 :: SWord 1 = choose [0:0] s3989
+  s6277 :: SBool = s10 /= s6276
+  s6278 :: SWord 1 = choose [0:0] s3985
+  s6279 :: SBool = s10 /= s6278
+  s6280 :: SWord 1 = choose [0:0] s3981
+  s6281 :: SBool = s10 /= s6280
+  s6282 :: SWord8 = s3968 >>> 1
+  s6283 :: SWord8 = s14 | s6282
+  s6284 :: SWord8 = s16 & s6282
+  s6285 :: SWord8 = if s6281 then s6283 else s6284
+  s6286 :: SWord8 = s6285 >>> 1
+  s6287 :: SWord8 = s14 | s6286
+  s6288 :: SWord8 = s16 & s6286
+  s6289 :: SWord8 = if s6279 then s6287 else s6288
+  s6290 :: SWord8 = s6289 >>> 1
+  s6291 :: SWord8 = s14 | s6290
+  s6292 :: SWord8 = s16 & s6290
+  s6293 :: SWord8 = if s6277 then s6291 else s6292
+  s6294 :: SWord 1 = choose [0:0] s3994
+  s6295 :: SBool = s10 /= s6294
+  s6296 :: SWord8 = if s6295 then s6291 else s6292
+  s6297 :: SWord8 = if s3974 then s6293 else s6296
+  s6298 :: SWord 1 = choose [0:0] s4010
+  s6299 :: SBool = s10 /= s6298
+  s6300 :: SWord 1 = choose [0:0] s4003
+  s6301 :: SBool = s10 /= s6300
+  s6302 :: SWord8 = if s6301 then s6287 else s6288
+  s6303 :: SWord8 = s6302 >>> 1
+  s6304 :: SWord8 = s14 | s6303
+  s6305 :: SWord8 = s16 & s6303
+  s6306 :: SWord8 = if s6299 then s6304 else s6305
+  s6307 :: SWord 1 = choose [0:0] s4015
+  s6308 :: SBool = s10 /= s6307
+  s6309 :: SWord8 = if s6308 then s6304 else s6305
+  s6310 :: SWord8 = if s3974 then s6306 else s6309
+  s6311 :: SWord8 = if s3847 then s6297 else s6310
+  s6312 :: SWord 1 = choose [0:0] s4036
+  s6313 :: SBool = s10 /= s6312
+  s6314 :: SWord 1 = choose [0:0] s4032
+  s6315 :: SBool = s10 /= s6314
+  s6316 :: SWord 1 = choose [0:0] s4025
+  s6317 :: SBool = s10 /= s6316
+  s6318 :: SWord8 = if s6317 then s6283 else s6284
+  s6319 :: SWord8 = s6318 >>> 1
+  s6320 :: SWord8 = s14 | s6319
+  s6321 :: SWord8 = s16 & s6319
+  s6322 :: SWord8 = if s6315 then s6320 else s6321
+  s6323 :: SWord8 = s6322 >>> 1
+  s6324 :: SWord8 = s14 | s6323
+  s6325 :: SWord8 = s16 & s6323
+  s6326 :: SWord8 = if s6313 then s6324 else s6325
+  s6327 :: SWord 1 = choose [0:0] s4041
+  s6328 :: SBool = s10 /= s6327
+  s6329 :: SWord8 = if s6328 then s6324 else s6325
+  s6330 :: SWord8 = if s3974 then s6326 else s6329
+  s6331 :: SWord 1 = choose [0:0] s4057
+  s6332 :: SBool = s10 /= s6331
+  s6333 :: SWord 1 = choose [0:0] s4050
+  s6334 :: SBool = s10 /= s6333
+  s6335 :: SWord8 = if s6334 then s6320 else s6321
+  s6336 :: SWord8 = s6335 >>> 1
+  s6337 :: SWord8 = s14 | s6336
+  s6338 :: SWord8 = s16 & s6336
+  s6339 :: SWord8 = if s6332 then s6337 else s6338
+  s6340 :: SWord 1 = choose [0:0] s4062
+  s6341 :: SBool = s10 /= s6340
+  s6342 :: SWord8 = if s6341 then s6337 else s6338
+  s6343 :: SWord8 = if s3974 then s6339 else s6342
+  s6344 :: SWord8 = if s3847 then s6330 else s6343
+  s6345 :: SWord8 = if s3592 then s6311 else s6344
+  s6346 :: SWord8 = if s3081 then s6275 else s6345
+  s6347 :: SWord8 = if s2063 then s6205 else s6346
+  s6348 :: SWord8 = if s30 then s6064 else s6347
+  s6349 :: SWord8 = if s21 then s5781 else s6348
+  s6350 :: SWord8 = if s12 then s5214 else s6349
+  s6351 :: SWord16 = s8 # s6350
+  s6352 :: SWord16 = s4079 + s6351
+  s6353 :: SWord16 = s8 # s0
+  s6354 :: SWord16 = s8 # s1
+  s6355 :: SWord16 = s6353 * s6354
+  s6356 :: SBool = s6352 == s6355
+CONSTRAINTS
+ASSERTIONS
+OUTPUTS
+  s6356
diff --git a/SBVTestSuite/GoldFiles/legato_c.gold b/SBVTestSuite/GoldFiles/legato_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/legato_c.gold
@@ -0,0 +1,6425 @@
+== BEGIN: "Makefile" ================
+# Makefile for legatoMult. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: legatoMult_driver
+
+legatoMult.o: legatoMult.c legatoMult.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+legatoMult_driver.o: legatoMult_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+legatoMult_driver: legatoMult.o legatoMult_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f legatoMult_driver
+== END: "Makefile" ==================
+== BEGIN: "legatoMult.h" ================
+/* Header file for legatoMult. Automatically generated by SBV. Do not edit! */
+
+#ifndef __legatoMult__HEADER_INCLUDED__
+#define __legatoMult__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void legatoMult(const SWord8 x, const SWord8 y, SWord8 *hi,
+                SWord8 *lo);
+
+#endif /* __legatoMult__HEADER_INCLUDED__ */
+== END: "legatoMult.h" ==================
+== BEGIN: "legatoMult_driver.c" ================
+/* Example driver program for legatoMult. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "legatoMult.h"
+
+int main(void)
+{
+  SWord8 hi;
+  SWord8 lo;
+
+  legatoMult(87, 92, &hi, &lo);
+
+  printf("legatoMult(87, 92, &hi, &lo) ->\n");
+  printf("  hi = %"PRIu8"\n", hi);
+  printf("  lo = %"PRIu8"\n", lo);
+
+  return 0;
+}
+== END: "legatoMult_driver.c" ==================
+== BEGIN: "legatoMult.c" ================
+/* File: "legatoMult.c". Automatically generated by SBV. Do not edit! */
+
+#include "legatoMult.h"
+
+void legatoMult(const SWord8 x, const SWord8 y, SWord8 *hi,
+                SWord8 *lo)
+{
+  const SWord8 s0 = x;
+  const SWord8 s1 = y;
+  const SBool  s2 = (SBool) (s0 & 1);
+  const SBool  s4 = s2 != false;
+  const SBool  s5 = !s4;
+  const SWord8 s6 = (s0 >> 1) | (s0 << 7);
+  const SWord8 s8 = s6 & 127;
+  const SBool  s9 = (SBool) (s8 & 1);
+  const SBool  s10 = false != s9;
+  const SBool  s11 = !s10;
+  const SWord8 s12 = (s8 >> 1) | (s8 << 7);
+  const SWord8 s13 = 127 & s12;
+  const SBool  s14 = (SBool) (s13 & 1);
+  const SBool  s15 = false != s14;
+  const SBool  s16 = !s15;
+  const SWord8 s17 = (s13 >> 1) | (s13 << 7);
+  const SWord8 s18 = 127 & s17;
+  const SBool  s19 = (SBool) (s18 & 1);
+  const SBool  s20 = false != s19;
+  const SBool  s21 = !s20;
+  const SWord8 s24 = s4 ? 128 : 0;
+  const SBool  s25 = (SBool) (s24 & 1);
+  const SBool  s26 = false != s25;
+  const SWord8 s27 = s26 ? 128 : 0;
+  const SBool  s28 = (SBool) (s27 & 1);
+  const SBool  s29 = false != s28;
+  const SWord8 s30 = (s18 >> 1) | (s18 << 7);
+  const SWord8 s31 = 128 | s30;
+  const SWord8 s32 = 127 & s30;
+  const SWord8 s33 = s29 ? s31 : s32;
+  const SBool  s34 = (SBool) (s33 & 1);
+  const SBool  s35 = false != s34;
+  const SBool  s36 = !s35;
+  const SWord8 s37 = (s24 >> 1) | (s24 << 7);
+  const SWord8 s38 = 128 | s37;
+  const SWord8 s39 = 127 & s37;
+  const SWord8 s40 = s10 ? s38 : s39;
+  const SBool  s41 = (SBool) (s40 & 1);
+  const SBool  s42 = false != s41;
+  const SWord8 s43 = (s27 >> 1) | (s27 << 7);
+  const SWord8 s44 = 128 | s43;
+  const SWord8 s45 = 127 & s43;
+  const SWord8 s46 = s42 ? s44 : s45;
+  const SBool  s47 = (SBool) (s46 & 1);
+  const SBool  s48 = false != s47;
+  const SWord8 s49 = (s33 >> 1) | (s33 << 7);
+  const SWord8 s50 = 128 | s49;
+  const SWord8 s51 = 127 & s49;
+  const SWord8 s52 = s48 ? s50 : s51;
+  const SBool  s53 = (SBool) (s52 & 1);
+  const SBool  s54 = false != s53;
+  const SBool  s55 = !s54;
+  const SWord8 s56 = (s40 >> 1) | (s40 << 7);
+  const SWord8 s57 = 128 | s56;
+  const SWord8 s58 = 127 & s56;
+  const SWord8 s59 = s15 ? s57 : s58;
+  const SBool  s60 = (SBool) (s59 & 1);
+  const SBool  s61 = false != s60;
+  const SWord8 s62 = (s46 >> 1) | (s46 << 7);
+  const SWord8 s63 = 128 | s62;
+  const SWord8 s64 = 127 & s62;
+  const SWord8 s65 = s61 ? s63 : s64;
+  const SBool  s66 = (SBool) (s65 & 1);
+  const SBool  s67 = false != s66;
+  const SWord8 s68 = (s52 >> 1) | (s52 << 7);
+  const SWord8 s69 = 128 | s68;
+  const SWord8 s70 = 127 & s68;
+  const SWord8 s71 = s67 ? s69 : s70;
+  const SBool  s72 = (SBool) (s71 & 1);
+  const SBool  s73 = false != s72;
+  const SBool  s74 = !s73;
+  const SWord8 s75 = (s59 >> 1) | (s59 << 7);
+  const SWord8 s76 = 128 | s75;
+  const SWord8 s77 = 127 & s75;
+  const SWord8 s78 = s20 ? s76 : s77;
+  const SBool  s79 = (SBool) (s78 & 1);
+  const SBool  s80 = false != s79;
+  const SWord8 s81 = (s65 >> 1) | (s65 << 7);
+  const SWord8 s82 = 128 | s81;
+  const SWord8 s83 = 127 & s81;
+  const SWord8 s84 = s80 ? s82 : s83;
+  const SBool  s85 = (SBool) (s84 & 1);
+  const SBool  s86 = false != s85;
+  const SWord8 s87 = (s71 >> 1) | (s71 << 7);
+  const SWord8 s88 = 128 | s87;
+  const SWord8 s89 = 127 & s87;
+  const SWord8 s90 = s86 ? s88 : s89;
+  const SBool  s91 = (SBool) (s90 & 1);
+  const SBool  s92 = false != s91;
+  const SBool  s93 = !s92;
+  const SWord8 s94 = (s78 >> 1) | (s78 << 7);
+  const SWord8 s95 = 128 | s94;
+  const SWord8 s96 = 127 & s94;
+  const SWord8 s97 = s35 ? s95 : s96;
+  const SWord8 s98 = (s97 >> 1) | (s97 << 7);
+  const SWord8 s99 = 128 | s98;
+  const SWord8 s100 = 127 & s98;
+  const SWord8 s101 = s54 ? s99 : s100;
+  const SWord8 s102 = (s101 >> 1) | (s101 << 7);
+  const SWord8 s103 = 128 | s102;
+  const SWord8 s104 = 127 & s102;
+  const SWord8 s105 = s73 ? s103 : s104;
+  const SWord8 s106 = (s105 >> 1) | (s105 << 7);
+  const SWord8 s107 = 128 | s106;
+  const SWord8 s108 = 127 & s106;
+  const SWord8 s109 = s92 ? s107 : s108;
+  const SWord8 s110 = s1 + s105;
+  const SBool  s111 = s110 < s1;
+  const SBool  s112 = s110 < s105;
+  const SBool  s113 = s111 || s112;
+  const SWord8 s114 = (s110 >> 1) | (s110 << 7);
+  const SWord8 s115 = 128 | s114;
+  const SWord8 s116 = 127 & s114;
+  const SWord8 s117 = s113 ? s115 : s116;
+  const SWord8 s118 = s93 ? s109 : s117;
+  const SWord8 s119 = s1 + s101;
+  const SBool  s120 = s119 < s1;
+  const SBool  s121 = s119 < s101;
+  const SBool  s122 = s120 || s121;
+  const SWord8 s123 = (s119 >> 1) | (s119 << 7);
+  const SWord8 s124 = 128 | s123;
+  const SWord8 s125 = 127 & s123;
+  const SWord8 s126 = s122 ? s124 : s125;
+  const SWord8 s127 = (s126 >> 1) | (s126 << 7);
+  const SWord8 s128 = 128 | s127;
+  const SWord8 s129 = 127 & s127;
+  const SWord8 s130 = s92 ? s128 : s129;
+  const SWord8 s131 = s1 + s126;
+  const SBool  s132 = s131 < s1;
+  const SBool  s133 = s131 < s126;
+  const SBool  s134 = s132 || s133;
+  const SWord8 s135 = (s131 >> 1) | (s131 << 7);
+  const SWord8 s136 = 128 | s135;
+  const SWord8 s137 = 127 & s135;
+  const SWord8 s138 = s134 ? s136 : s137;
+  const SWord8 s139 = s93 ? s130 : s138;
+  const SWord8 s140 = s74 ? s118 : s139;
+  const SWord8 s141 = s1 + s97;
+  const SBool  s142 = s141 < s1;
+  const SBool  s143 = s141 < s97;
+  const SBool  s144 = s142 || s143;
+  const SWord8 s145 = (s141 >> 1) | (s141 << 7);
+  const SWord8 s146 = 128 | s145;
+  const SWord8 s147 = 127 & s145;
+  const SWord8 s148 = s144 ? s146 : s147;
+  const SWord8 s149 = (s148 >> 1) | (s148 << 7);
+  const SWord8 s150 = 128 | s149;
+  const SWord8 s151 = 127 & s149;
+  const SWord8 s152 = s73 ? s150 : s151;
+  const SWord8 s153 = (s152 >> 1) | (s152 << 7);
+  const SWord8 s154 = 128 | s153;
+  const SWord8 s155 = 127 & s153;
+  const SWord8 s156 = s92 ? s154 : s155;
+  const SWord8 s157 = s1 + s152;
+  const SBool  s158 = s157 < s1;
+  const SBool  s159 = s157 < s152;
+  const SBool  s160 = s158 || s159;
+  const SWord8 s161 = (s157 >> 1) | (s157 << 7);
+  const SWord8 s162 = 128 | s161;
+  const SWord8 s163 = 127 & s161;
+  const SWord8 s164 = s160 ? s162 : s163;
+  const SWord8 s165 = s93 ? s156 : s164;
+  const SWord8 s166 = s1 + s148;
+  const SBool  s167 = s166 < s1;
+  const SBool  s168 = s166 < s148;
+  const SBool  s169 = s167 || s168;
+  const SWord8 s170 = (s166 >> 1) | (s166 << 7);
+  const SWord8 s171 = 128 | s170;
+  const SWord8 s172 = 127 & s170;
+  const SWord8 s173 = s169 ? s171 : s172;
+  const SWord8 s174 = (s173 >> 1) | (s173 << 7);
+  const SWord8 s175 = 128 | s174;
+  const SWord8 s176 = 127 & s174;
+  const SWord8 s177 = s92 ? s175 : s176;
+  const SWord8 s178 = s1 + s173;
+  const SBool  s179 = s178 < s1;
+  const SBool  s180 = s178 < s173;
+  const SBool  s181 = s179 || s180;
+  const SWord8 s182 = (s178 >> 1) | (s178 << 7);
+  const SWord8 s183 = 128 | s182;
+  const SWord8 s184 = 127 & s182;
+  const SWord8 s185 = s181 ? s183 : s184;
+  const SWord8 s186 = s93 ? s177 : s185;
+  const SWord8 s187 = s74 ? s165 : s186;
+  const SWord8 s188 = s55 ? s140 : s187;
+  const SWord8 s189 = s1 + s78;
+  const SBool  s190 = (SBool) (s189 & 1);
+  const SBool  s191 = false != s190;
+  const SWord8 s192 = s191 ? s82 : s83;
+  const SBool  s193 = (SBool) (s192 & 1);
+  const SBool  s194 = false != s193;
+  const SWord8 s195 = s194 ? s88 : s89;
+  const SBool  s196 = (SBool) (s195 & 1);
+  const SBool  s197 = false != s196;
+  const SBool  s198 = !s197;
+  const SBool  s199 = s189 < s1;
+  const SBool  s200 = s189 < s78;
+  const SBool  s201 = s199 || s200;
+  const SWord8 s202 = (s189 >> 1) | (s189 << 7);
+  const SWord8 s203 = 128 | s202;
+  const SWord8 s204 = 127 & s202;
+  const SWord8 s205 = s201 ? s203 : s204;
+  const SWord8 s206 = (s205 >> 1) | (s205 << 7);
+  const SWord8 s207 = 128 | s206;
+  const SWord8 s208 = 127 & s206;
+  const SWord8 s209 = s54 ? s207 : s208;
+  const SWord8 s210 = (s209 >> 1) | (s209 << 7);
+  const SWord8 s211 = 128 | s210;
+  const SWord8 s212 = 127 & s210;
+  const SWord8 s213 = s73 ? s211 : s212;
+  const SWord8 s214 = (s213 >> 1) | (s213 << 7);
+  const SWord8 s215 = 128 | s214;
+  const SWord8 s216 = 127 & s214;
+  const SWord8 s217 = s197 ? s215 : s216;
+  const SWord8 s218 = s1 + s213;
+  const SBool  s219 = s218 < s1;
+  const SBool  s220 = s218 < s213;
+  const SBool  s221 = s219 || s220;
+  const SWord8 s222 = (s218 >> 1) | (s218 << 7);
+  const SWord8 s223 = 128 | s222;
+  const SWord8 s224 = 127 & s222;
+  const SWord8 s225 = s221 ? s223 : s224;
+  const SWord8 s226 = s198 ? s217 : s225;
+  const SWord8 s227 = s1 + s209;
+  const SBool  s228 = s227 < s1;
+  const SBool  s229 = s227 < s209;
+  const SBool  s230 = s228 || s229;
+  const SWord8 s231 = (s227 >> 1) | (s227 << 7);
+  const SWord8 s232 = 128 | s231;
+  const SWord8 s233 = 127 & s231;
+  const SWord8 s234 = s230 ? s232 : s233;
+  const SWord8 s235 = (s234 >> 1) | (s234 << 7);
+  const SWord8 s236 = 128 | s235;
+  const SWord8 s237 = 127 & s235;
+  const SWord8 s238 = s197 ? s236 : s237;
+  const SWord8 s239 = s1 + s234;
+  const SBool  s240 = s239 < s1;
+  const SBool  s241 = s239 < s234;
+  const SBool  s242 = s240 || s241;
+  const SWord8 s243 = (s239 >> 1) | (s239 << 7);
+  const SWord8 s244 = 128 | s243;
+  const SWord8 s245 = 127 & s243;
+  const SWord8 s246 = s242 ? s244 : s245;
+  const SWord8 s247 = s198 ? s238 : s246;
+  const SWord8 s248 = s74 ? s226 : s247;
+  const SWord8 s249 = s1 + s205;
+  const SBool  s250 = s249 < s1;
+  const SBool  s251 = s249 < s205;
+  const SBool  s252 = s250 || s251;
+  const SWord8 s253 = (s249 >> 1) | (s249 << 7);
+  const SWord8 s254 = 128 | s253;
+  const SWord8 s255 = 127 & s253;
+  const SWord8 s256 = s252 ? s254 : s255;
+  const SWord8 s257 = (s256 >> 1) | (s256 << 7);
+  const SWord8 s258 = 128 | s257;
+  const SWord8 s259 = 127 & s257;
+  const SWord8 s260 = s73 ? s258 : s259;
+  const SWord8 s261 = (s260 >> 1) | (s260 << 7);
+  const SWord8 s262 = 128 | s261;
+  const SWord8 s263 = 127 & s261;
+  const SWord8 s264 = s197 ? s262 : s263;
+  const SWord8 s265 = s1 + s260;
+  const SBool  s266 = s265 < s1;
+  const SBool  s267 = s265 < s260;
+  const SBool  s268 = s266 || s267;
+  const SWord8 s269 = (s265 >> 1) | (s265 << 7);
+  const SWord8 s270 = 128 | s269;
+  const SWord8 s271 = 127 & s269;
+  const SWord8 s272 = s268 ? s270 : s271;
+  const SWord8 s273 = s198 ? s264 : s272;
+  const SWord8 s274 = s1 + s256;
+  const SBool  s275 = s274 < s1;
+  const SBool  s276 = s274 < s256;
+  const SBool  s277 = s275 || s276;
+  const SWord8 s278 = (s274 >> 1) | (s274 << 7);
+  const SWord8 s279 = 128 | s278;
+  const SWord8 s280 = 127 & s278;
+  const SWord8 s281 = s277 ? s279 : s280;
+  const SWord8 s282 = (s281 >> 1) | (s281 << 7);
+  const SWord8 s283 = 128 | s282;
+  const SWord8 s284 = 127 & s282;
+  const SWord8 s285 = s197 ? s283 : s284;
+  const SWord8 s286 = s1 + s281;
+  const SBool  s287 = s286 < s1;
+  const SBool  s288 = s286 < s281;
+  const SBool  s289 = s287 || s288;
+  const SWord8 s290 = (s286 >> 1) | (s286 << 7);
+  const SWord8 s291 = 128 | s290;
+  const SWord8 s292 = 127 & s290;
+  const SWord8 s293 = s289 ? s291 : s292;
+  const SWord8 s294 = s198 ? s285 : s293;
+  const SWord8 s295 = s74 ? s273 : s294;
+  const SWord8 s296 = s55 ? s248 : s295;
+  const SWord8 s297 = s36 ? s188 : s296;
+  const SWord8 s298 = s1 + s59;
+  const SBool  s299 = (SBool) (s298 & 1);
+  const SBool  s300 = false != s299;
+  const SWord8 s301 = s300 ? s63 : s64;
+  const SBool  s302 = (SBool) (s301 & 1);
+  const SBool  s303 = false != s302;
+  const SWord8 s304 = s303 ? s69 : s70;
+  const SBool  s305 = (SBool) (s304 & 1);
+  const SBool  s306 = false != s305;
+  const SBool  s307 = !s306;
+  const SBool  s308 = s298 < s1;
+  const SBool  s309 = s298 < s59;
+  const SBool  s310 = s308 || s309;
+  const SWord8 s311 = (s298 >> 1) | (s298 << 7);
+  const SWord8 s312 = 128 | s311;
+  const SWord8 s313 = 127 & s311;
+  const SWord8 s314 = s310 ? s312 : s313;
+  const SBool  s315 = (SBool) (s314 & 1);
+  const SBool  s316 = false != s315;
+  const SWord8 s317 = (s301 >> 1) | (s301 << 7);
+  const SWord8 s318 = 128 | s317;
+  const SWord8 s319 = 127 & s317;
+  const SWord8 s320 = s316 ? s318 : s319;
+  const SBool  s321 = (SBool) (s320 & 1);
+  const SBool  s322 = false != s321;
+  const SWord8 s323 = (s304 >> 1) | (s304 << 7);
+  const SWord8 s324 = 128 | s323;
+  const SWord8 s325 = 127 & s323;
+  const SWord8 s326 = s322 ? s324 : s325;
+  const SBool  s327 = (SBool) (s326 & 1);
+  const SBool  s328 = false != s327;
+  const SBool  s329 = !s328;
+  const SWord8 s330 = (s314 >> 1) | (s314 << 7);
+  const SWord8 s331 = 128 | s330;
+  const SWord8 s332 = 127 & s330;
+  const SWord8 s333 = s35 ? s331 : s332;
+  const SWord8 s334 = (s333 >> 1) | (s333 << 7);
+  const SWord8 s335 = 128 | s334;
+  const SWord8 s336 = 127 & s334;
+  const SWord8 s337 = s54 ? s335 : s336;
+  const SWord8 s338 = (s337 >> 1) | (s337 << 7);
+  const SWord8 s339 = 128 | s338;
+  const SWord8 s340 = 127 & s338;
+  const SWord8 s341 = s306 ? s339 : s340;
+  const SWord8 s342 = (s341 >> 1) | (s341 << 7);
+  const SWord8 s343 = 128 | s342;
+  const SWord8 s344 = 127 & s342;
+  const SWord8 s345 = s328 ? s343 : s344;
+  const SWord8 s346 = s1 + s341;
+  const SBool  s347 = s346 < s1;
+  const SBool  s348 = s346 < s341;
+  const SBool  s349 = s347 || s348;
+  const SWord8 s350 = (s346 >> 1) | (s346 << 7);
+  const SWord8 s351 = 128 | s350;
+  const SWord8 s352 = 127 & s350;
+  const SWord8 s353 = s349 ? s351 : s352;
+  const SWord8 s354 = s329 ? s345 : s353;
+  const SWord8 s355 = s1 + s337;
+  const SBool  s356 = s355 < s1;
+  const SBool  s357 = s355 < s337;
+  const SBool  s358 = s356 || s357;
+  const SWord8 s359 = (s355 >> 1) | (s355 << 7);
+  const SWord8 s360 = 128 | s359;
+  const SWord8 s361 = 127 & s359;
+  const SWord8 s362 = s358 ? s360 : s361;
+  const SWord8 s363 = (s362 >> 1) | (s362 << 7);
+  const SWord8 s364 = 128 | s363;
+  const SWord8 s365 = 127 & s363;
+  const SWord8 s366 = s328 ? s364 : s365;
+  const SWord8 s367 = s1 + s362;
+  const SBool  s368 = s367 < s1;
+  const SBool  s369 = s367 < s362;
+  const SBool  s370 = s368 || s369;
+  const SWord8 s371 = (s367 >> 1) | (s367 << 7);
+  const SWord8 s372 = 128 | s371;
+  const SWord8 s373 = 127 & s371;
+  const SWord8 s374 = s370 ? s372 : s373;
+  const SWord8 s375 = s329 ? s366 : s374;
+  const SWord8 s376 = s307 ? s354 : s375;
+  const SWord8 s377 = s1 + s333;
+  const SBool  s378 = s377 < s1;
+  const SBool  s379 = s377 < s333;
+  const SBool  s380 = s378 || s379;
+  const SWord8 s381 = (s377 >> 1) | (s377 << 7);
+  const SWord8 s382 = 128 | s381;
+  const SWord8 s383 = 127 & s381;
+  const SWord8 s384 = s380 ? s382 : s383;
+  const SWord8 s385 = (s384 >> 1) | (s384 << 7);
+  const SWord8 s386 = 128 | s385;
+  const SWord8 s387 = 127 & s385;
+  const SWord8 s388 = s306 ? s386 : s387;
+  const SWord8 s389 = (s388 >> 1) | (s388 << 7);
+  const SWord8 s390 = 128 | s389;
+  const SWord8 s391 = 127 & s389;
+  const SWord8 s392 = s328 ? s390 : s391;
+  const SWord8 s393 = s1 + s388;
+  const SBool  s394 = s393 < s1;
+  const SBool  s395 = s393 < s388;
+  const SBool  s396 = s394 || s395;
+  const SWord8 s397 = (s393 >> 1) | (s393 << 7);
+  const SWord8 s398 = 128 | s397;
+  const SWord8 s399 = 127 & s397;
+  const SWord8 s400 = s396 ? s398 : s399;
+  const SWord8 s401 = s329 ? s392 : s400;
+  const SWord8 s402 = s1 + s384;
+  const SBool  s403 = s402 < s1;
+  const SBool  s404 = s402 < s384;
+  const SBool  s405 = s403 || s404;
+  const SWord8 s406 = (s402 >> 1) | (s402 << 7);
+  const SWord8 s407 = 128 | s406;
+  const SWord8 s408 = 127 & s406;
+  const SWord8 s409 = s405 ? s407 : s408;
+  const SWord8 s410 = (s409 >> 1) | (s409 << 7);
+  const SWord8 s411 = 128 | s410;
+  const SWord8 s412 = 127 & s410;
+  const SWord8 s413 = s328 ? s411 : s412;
+  const SWord8 s414 = s1 + s409;
+  const SBool  s415 = s414 < s1;
+  const SBool  s416 = s414 < s409;
+  const SBool  s417 = s415 || s416;
+  const SWord8 s418 = (s414 >> 1) | (s414 << 7);
+  const SWord8 s419 = 128 | s418;
+  const SWord8 s420 = 127 & s418;
+  const SWord8 s421 = s417 ? s419 : s420;
+  const SWord8 s422 = s329 ? s413 : s421;
+  const SWord8 s423 = s307 ? s401 : s422;
+  const SWord8 s424 = s55 ? s376 : s423;
+  const SWord8 s425 = s1 + s314;
+  const SBool  s426 = (SBool) (s425 & 1);
+  const SBool  s427 = false != s426;
+  const SWord8 s428 = s427 ? s318 : s319;
+  const SBool  s429 = (SBool) (s428 & 1);
+  const SBool  s430 = false != s429;
+  const SWord8 s431 = s430 ? s324 : s325;
+  const SBool  s432 = (SBool) (s431 & 1);
+  const SBool  s433 = false != s432;
+  const SBool  s434 = !s433;
+  const SBool  s435 = s425 < s1;
+  const SBool  s436 = s425 < s314;
+  const SBool  s437 = s435 || s436;
+  const SWord8 s438 = (s425 >> 1) | (s425 << 7);
+  const SWord8 s439 = 128 | s438;
+  const SWord8 s440 = 127 & s438;
+  const SWord8 s441 = s437 ? s439 : s440;
+  const SWord8 s442 = (s441 >> 1) | (s441 << 7);
+  const SWord8 s443 = 128 | s442;
+  const SWord8 s444 = 127 & s442;
+  const SWord8 s445 = s54 ? s443 : s444;
+  const SWord8 s446 = (s445 >> 1) | (s445 << 7);
+  const SWord8 s447 = 128 | s446;
+  const SWord8 s448 = 127 & s446;
+  const SWord8 s449 = s306 ? s447 : s448;
+  const SWord8 s450 = (s449 >> 1) | (s449 << 7);
+  const SWord8 s451 = 128 | s450;
+  const SWord8 s452 = 127 & s450;
+  const SWord8 s453 = s433 ? s451 : s452;
+  const SWord8 s454 = s1 + s449;
+  const SBool  s455 = s454 < s1;
+  const SBool  s456 = s454 < s449;
+  const SBool  s457 = s455 || s456;
+  const SWord8 s458 = (s454 >> 1) | (s454 << 7);
+  const SWord8 s459 = 128 | s458;
+  const SWord8 s460 = 127 & s458;
+  const SWord8 s461 = s457 ? s459 : s460;
+  const SWord8 s462 = s434 ? s453 : s461;
+  const SWord8 s463 = s1 + s445;
+  const SBool  s464 = s463 < s1;
+  const SBool  s465 = s463 < s445;
+  const SBool  s466 = s464 || s465;
+  const SWord8 s467 = (s463 >> 1) | (s463 << 7);
+  const SWord8 s468 = 128 | s467;
+  const SWord8 s469 = 127 & s467;
+  const SWord8 s470 = s466 ? s468 : s469;
+  const SWord8 s471 = (s470 >> 1) | (s470 << 7);
+  const SWord8 s472 = 128 | s471;
+  const SWord8 s473 = 127 & s471;
+  const SWord8 s474 = s433 ? s472 : s473;
+  const SWord8 s475 = s1 + s470;
+  const SBool  s476 = s475 < s1;
+  const SBool  s477 = s475 < s470;
+  const SBool  s478 = s476 || s477;
+  const SWord8 s479 = (s475 >> 1) | (s475 << 7);
+  const SWord8 s480 = 128 | s479;
+  const SWord8 s481 = 127 & s479;
+  const SWord8 s482 = s478 ? s480 : s481;
+  const SWord8 s483 = s434 ? s474 : s482;
+  const SWord8 s484 = s307 ? s462 : s483;
+  const SWord8 s485 = s1 + s441;
+  const SBool  s486 = s485 < s1;
+  const SBool  s487 = s485 < s441;
+  const SBool  s488 = s486 || s487;
+  const SWord8 s489 = (s485 >> 1) | (s485 << 7);
+  const SWord8 s490 = 128 | s489;
+  const SWord8 s491 = 127 & s489;
+  const SWord8 s492 = s488 ? s490 : s491;
+  const SWord8 s493 = (s492 >> 1) | (s492 << 7);
+  const SWord8 s494 = 128 | s493;
+  const SWord8 s495 = 127 & s493;
+  const SWord8 s496 = s306 ? s494 : s495;
+  const SWord8 s497 = (s496 >> 1) | (s496 << 7);
+  const SWord8 s498 = 128 | s497;
+  const SWord8 s499 = 127 & s497;
+  const SWord8 s500 = s433 ? s498 : s499;
+  const SWord8 s501 = s1 + s496;
+  const SBool  s502 = s501 < s1;
+  const SBool  s503 = s501 < s496;
+  const SBool  s504 = s502 || s503;
+  const SWord8 s505 = (s501 >> 1) | (s501 << 7);
+  const SWord8 s506 = 128 | s505;
+  const SWord8 s507 = 127 & s505;
+  const SWord8 s508 = s504 ? s506 : s507;
+  const SWord8 s509 = s434 ? s500 : s508;
+  const SWord8 s510 = s1 + s492;
+  const SBool  s511 = s510 < s1;
+  const SBool  s512 = s510 < s492;
+  const SBool  s513 = s511 || s512;
+  const SWord8 s514 = (s510 >> 1) | (s510 << 7);
+  const SWord8 s515 = 128 | s514;
+  const SWord8 s516 = 127 & s514;
+  const SWord8 s517 = s513 ? s515 : s516;
+  const SWord8 s518 = (s517 >> 1) | (s517 << 7);
+  const SWord8 s519 = 128 | s518;
+  const SWord8 s520 = 127 & s518;
+  const SWord8 s521 = s433 ? s519 : s520;
+  const SWord8 s522 = s1 + s517;
+  const SBool  s523 = s522 < s1;
+  const SBool  s524 = s522 < s517;
+  const SBool  s525 = s523 || s524;
+  const SWord8 s526 = (s522 >> 1) | (s522 << 7);
+  const SWord8 s527 = 128 | s526;
+  const SWord8 s528 = 127 & s526;
+  const SWord8 s529 = s525 ? s527 : s528;
+  const SWord8 s530 = s434 ? s521 : s529;
+  const SWord8 s531 = s307 ? s509 : s530;
+  const SWord8 s532 = s55 ? s484 : s531;
+  const SWord8 s533 = s36 ? s424 : s532;
+  const SWord8 s534 = s21 ? s297 : s533;
+  const SWord8 s535 = s1 + s40;
+  const SBool  s536 = (SBool) (s535 & 1);
+  const SBool  s537 = false != s536;
+  const SWord8 s538 = s537 ? s44 : s45;
+  const SBool  s539 = (SBool) (s538 & 1);
+  const SBool  s540 = false != s539;
+  const SWord8 s541 = s540 ? s50 : s51;
+  const SBool  s542 = (SBool) (s541 & 1);
+  const SBool  s543 = false != s542;
+  const SBool  s544 = !s543;
+  const SBool  s545 = s535 < s1;
+  const SBool  s546 = s535 < s40;
+  const SBool  s547 = s545 || s546;
+  const SWord8 s548 = (s535 >> 1) | (s535 << 7);
+  const SWord8 s549 = 128 | s548;
+  const SWord8 s550 = 127 & s548;
+  const SWord8 s551 = s547 ? s549 : s550;
+  const SBool  s552 = (SBool) (s551 & 1);
+  const SBool  s553 = false != s552;
+  const SWord8 s554 = (s538 >> 1) | (s538 << 7);
+  const SWord8 s555 = 128 | s554;
+  const SWord8 s556 = 127 & s554;
+  const SWord8 s557 = s553 ? s555 : s556;
+  const SBool  s558 = (SBool) (s557 & 1);
+  const SBool  s559 = false != s558;
+  const SWord8 s560 = (s541 >> 1) | (s541 << 7);
+  const SWord8 s561 = 128 | s560;
+  const SWord8 s562 = 127 & s560;
+  const SWord8 s563 = s559 ? s561 : s562;
+  const SBool  s564 = (SBool) (s563 & 1);
+  const SBool  s565 = false != s564;
+  const SBool  s566 = !s565;
+  const SWord8 s567 = (s551 >> 1) | (s551 << 7);
+  const SWord8 s568 = 128 | s567;
+  const SWord8 s569 = 127 & s567;
+  const SWord8 s570 = s20 ? s568 : s569;
+  const SBool  s571 = (SBool) (s570 & 1);
+  const SBool  s572 = false != s571;
+  const SWord8 s573 = (s557 >> 1) | (s557 << 7);
+  const SWord8 s574 = 128 | s573;
+  const SWord8 s575 = 127 & s573;
+  const SWord8 s576 = s572 ? s574 : s575;
+  const SBool  s577 = (SBool) (s576 & 1);
+  const SBool  s578 = false != s577;
+  const SWord8 s579 = (s563 >> 1) | (s563 << 7);
+  const SWord8 s580 = 128 | s579;
+  const SWord8 s581 = 127 & s579;
+  const SWord8 s582 = s578 ? s580 : s581;
+  const SBool  s583 = (SBool) (s582 & 1);
+  const SBool  s584 = false != s583;
+  const SBool  s585 = !s584;
+  const SWord8 s586 = (s570 >> 1) | (s570 << 7);
+  const SWord8 s587 = 128 | s586;
+  const SWord8 s588 = 127 & s586;
+  const SWord8 s589 = s35 ? s587 : s588;
+  const SWord8 s590 = (s589 >> 1) | (s589 << 7);
+  const SWord8 s591 = 128 | s590;
+  const SWord8 s592 = 127 & s590;
+  const SWord8 s593 = s543 ? s591 : s592;
+  const SWord8 s594 = (s593 >> 1) | (s593 << 7);
+  const SWord8 s595 = 128 | s594;
+  const SWord8 s596 = 127 & s594;
+  const SWord8 s597 = s565 ? s595 : s596;
+  const SWord8 s598 = (s597 >> 1) | (s597 << 7);
+  const SWord8 s599 = 128 | s598;
+  const SWord8 s600 = 127 & s598;
+  const SWord8 s601 = s584 ? s599 : s600;
+  const SWord8 s602 = s1 + s597;
+  const SBool  s603 = s602 < s1;
+  const SBool  s604 = s602 < s597;
+  const SBool  s605 = s603 || s604;
+  const SWord8 s606 = (s602 >> 1) | (s602 << 7);
+  const SWord8 s607 = 128 | s606;
+  const SWord8 s608 = 127 & s606;
+  const SWord8 s609 = s605 ? s607 : s608;
+  const SWord8 s610 = s585 ? s601 : s609;
+  const SWord8 s611 = s1 + s593;
+  const SBool  s612 = s611 < s1;
+  const SBool  s613 = s611 < s593;
+  const SBool  s614 = s612 || s613;
+  const SWord8 s615 = (s611 >> 1) | (s611 << 7);
+  const SWord8 s616 = 128 | s615;
+  const SWord8 s617 = 127 & s615;
+  const SWord8 s618 = s614 ? s616 : s617;
+  const SWord8 s619 = (s618 >> 1) | (s618 << 7);
+  const SWord8 s620 = 128 | s619;
+  const SWord8 s621 = 127 & s619;
+  const SWord8 s622 = s584 ? s620 : s621;
+  const SWord8 s623 = s1 + s618;
+  const SBool  s624 = s623 < s1;
+  const SBool  s625 = s623 < s618;
+  const SBool  s626 = s624 || s625;
+  const SWord8 s627 = (s623 >> 1) | (s623 << 7);
+  const SWord8 s628 = 128 | s627;
+  const SWord8 s629 = 127 & s627;
+  const SWord8 s630 = s626 ? s628 : s629;
+  const SWord8 s631 = s585 ? s622 : s630;
+  const SWord8 s632 = s566 ? s610 : s631;
+  const SWord8 s633 = s1 + s589;
+  const SBool  s634 = s633 < s1;
+  const SBool  s635 = s633 < s589;
+  const SBool  s636 = s634 || s635;
+  const SWord8 s637 = (s633 >> 1) | (s633 << 7);
+  const SWord8 s638 = 128 | s637;
+  const SWord8 s639 = 127 & s637;
+  const SWord8 s640 = s636 ? s638 : s639;
+  const SWord8 s641 = (s640 >> 1) | (s640 << 7);
+  const SWord8 s642 = 128 | s641;
+  const SWord8 s643 = 127 & s641;
+  const SWord8 s644 = s565 ? s642 : s643;
+  const SWord8 s645 = (s644 >> 1) | (s644 << 7);
+  const SWord8 s646 = 128 | s645;
+  const SWord8 s647 = 127 & s645;
+  const SWord8 s648 = s584 ? s646 : s647;
+  const SWord8 s649 = s1 + s644;
+  const SBool  s650 = s649 < s1;
+  const SBool  s651 = s649 < s644;
+  const SBool  s652 = s650 || s651;
+  const SWord8 s653 = (s649 >> 1) | (s649 << 7);
+  const SWord8 s654 = 128 | s653;
+  const SWord8 s655 = 127 & s653;
+  const SWord8 s656 = s652 ? s654 : s655;
+  const SWord8 s657 = s585 ? s648 : s656;
+  const SWord8 s658 = s1 + s640;
+  const SBool  s659 = s658 < s1;
+  const SBool  s660 = s658 < s640;
+  const SBool  s661 = s659 || s660;
+  const SWord8 s662 = (s658 >> 1) | (s658 << 7);
+  const SWord8 s663 = 128 | s662;
+  const SWord8 s664 = 127 & s662;
+  const SWord8 s665 = s661 ? s663 : s664;
+  const SWord8 s666 = (s665 >> 1) | (s665 << 7);
+  const SWord8 s667 = 128 | s666;
+  const SWord8 s668 = 127 & s666;
+  const SWord8 s669 = s584 ? s667 : s668;
+  const SWord8 s670 = s1 + s665;
+  const SBool  s671 = s670 < s1;
+  const SBool  s672 = s670 < s665;
+  const SBool  s673 = s671 || s672;
+  const SWord8 s674 = (s670 >> 1) | (s670 << 7);
+  const SWord8 s675 = 128 | s674;
+  const SWord8 s676 = 127 & s674;
+  const SWord8 s677 = s673 ? s675 : s676;
+  const SWord8 s678 = s585 ? s669 : s677;
+  const SWord8 s679 = s566 ? s657 : s678;
+  const SWord8 s680 = s544 ? s632 : s679;
+  const SWord8 s681 = s1 + s570;
+  const SBool  s682 = (SBool) (s681 & 1);
+  const SBool  s683 = false != s682;
+  const SWord8 s684 = s683 ? s574 : s575;
+  const SBool  s685 = (SBool) (s684 & 1);
+  const SBool  s686 = false != s685;
+  const SWord8 s687 = s686 ? s580 : s581;
+  const SBool  s688 = (SBool) (s687 & 1);
+  const SBool  s689 = false != s688;
+  const SBool  s690 = !s689;
+  const SBool  s691 = s681 < s1;
+  const SBool  s692 = s681 < s570;
+  const SBool  s693 = s691 || s692;
+  const SWord8 s694 = (s681 >> 1) | (s681 << 7);
+  const SWord8 s695 = 128 | s694;
+  const SWord8 s696 = 127 & s694;
+  const SWord8 s697 = s693 ? s695 : s696;
+  const SWord8 s698 = (s697 >> 1) | (s697 << 7);
+  const SWord8 s699 = 128 | s698;
+  const SWord8 s700 = 127 & s698;
+  const SWord8 s701 = s543 ? s699 : s700;
+  const SWord8 s702 = (s701 >> 1) | (s701 << 7);
+  const SWord8 s703 = 128 | s702;
+  const SWord8 s704 = 127 & s702;
+  const SWord8 s705 = s565 ? s703 : s704;
+  const SWord8 s706 = (s705 >> 1) | (s705 << 7);
+  const SWord8 s707 = 128 | s706;
+  const SWord8 s708 = 127 & s706;
+  const SWord8 s709 = s689 ? s707 : s708;
+  const SWord8 s710 = s1 + s705;
+  const SBool  s711 = s710 < s1;
+  const SBool  s712 = s710 < s705;
+  const SBool  s713 = s711 || s712;
+  const SWord8 s714 = (s710 >> 1) | (s710 << 7);
+  const SWord8 s715 = 128 | s714;
+  const SWord8 s716 = 127 & s714;
+  const SWord8 s717 = s713 ? s715 : s716;
+  const SWord8 s718 = s690 ? s709 : s717;
+  const SWord8 s719 = s1 + s701;
+  const SBool  s720 = s719 < s1;
+  const SBool  s721 = s719 < s701;
+  const SBool  s722 = s720 || s721;
+  const SWord8 s723 = (s719 >> 1) | (s719 << 7);
+  const SWord8 s724 = 128 | s723;
+  const SWord8 s725 = 127 & s723;
+  const SWord8 s726 = s722 ? s724 : s725;
+  const SWord8 s727 = (s726 >> 1) | (s726 << 7);
+  const SWord8 s728 = 128 | s727;
+  const SWord8 s729 = 127 & s727;
+  const SWord8 s730 = s689 ? s728 : s729;
+  const SWord8 s731 = s1 + s726;
+  const SBool  s732 = s731 < s1;
+  const SBool  s733 = s731 < s726;
+  const SBool  s734 = s732 || s733;
+  const SWord8 s735 = (s731 >> 1) | (s731 << 7);
+  const SWord8 s736 = 128 | s735;
+  const SWord8 s737 = 127 & s735;
+  const SWord8 s738 = s734 ? s736 : s737;
+  const SWord8 s739 = s690 ? s730 : s738;
+  const SWord8 s740 = s566 ? s718 : s739;
+  const SWord8 s741 = s1 + s697;
+  const SBool  s742 = s741 < s1;
+  const SBool  s743 = s741 < s697;
+  const SBool  s744 = s742 || s743;
+  const SWord8 s745 = (s741 >> 1) | (s741 << 7);
+  const SWord8 s746 = 128 | s745;
+  const SWord8 s747 = 127 & s745;
+  const SWord8 s748 = s744 ? s746 : s747;
+  const SWord8 s749 = (s748 >> 1) | (s748 << 7);
+  const SWord8 s750 = 128 | s749;
+  const SWord8 s751 = 127 & s749;
+  const SWord8 s752 = s565 ? s750 : s751;
+  const SWord8 s753 = (s752 >> 1) | (s752 << 7);
+  const SWord8 s754 = 128 | s753;
+  const SWord8 s755 = 127 & s753;
+  const SWord8 s756 = s689 ? s754 : s755;
+  const SWord8 s757 = s1 + s752;
+  const SBool  s758 = s757 < s1;
+  const SBool  s759 = s757 < s752;
+  const SBool  s760 = s758 || s759;
+  const SWord8 s761 = (s757 >> 1) | (s757 << 7);
+  const SWord8 s762 = 128 | s761;
+  const SWord8 s763 = 127 & s761;
+  const SWord8 s764 = s760 ? s762 : s763;
+  const SWord8 s765 = s690 ? s756 : s764;
+  const SWord8 s766 = s1 + s748;
+  const SBool  s767 = s766 < s1;
+  const SBool  s768 = s766 < s748;
+  const SBool  s769 = s767 || s768;
+  const SWord8 s770 = (s766 >> 1) | (s766 << 7);
+  const SWord8 s771 = 128 | s770;
+  const SWord8 s772 = 127 & s770;
+  const SWord8 s773 = s769 ? s771 : s772;
+  const SWord8 s774 = (s773 >> 1) | (s773 << 7);
+  const SWord8 s775 = 128 | s774;
+  const SWord8 s776 = 127 & s774;
+  const SWord8 s777 = s689 ? s775 : s776;
+  const SWord8 s778 = s1 + s773;
+  const SBool  s779 = s778 < s1;
+  const SBool  s780 = s778 < s773;
+  const SBool  s781 = s779 || s780;
+  const SWord8 s782 = (s778 >> 1) | (s778 << 7);
+  const SWord8 s783 = 128 | s782;
+  const SWord8 s784 = 127 & s782;
+  const SWord8 s785 = s781 ? s783 : s784;
+  const SWord8 s786 = s690 ? s777 : s785;
+  const SWord8 s787 = s566 ? s765 : s786;
+  const SWord8 s788 = s544 ? s740 : s787;
+  const SWord8 s789 = s36 ? s680 : s788;
+  const SWord8 s790 = s1 + s551;
+  const SBool  s791 = (SBool) (s790 & 1);
+  const SBool  s792 = false != s791;
+  const SWord8 s793 = s792 ? s555 : s556;
+  const SBool  s794 = (SBool) (s793 & 1);
+  const SBool  s795 = false != s794;
+  const SWord8 s796 = s795 ? s561 : s562;
+  const SBool  s797 = (SBool) (s796 & 1);
+  const SBool  s798 = false != s797;
+  const SBool  s799 = !s798;
+  const SBool  s800 = s790 < s1;
+  const SBool  s801 = s790 < s551;
+  const SBool  s802 = s800 || s801;
+  const SWord8 s803 = (s790 >> 1) | (s790 << 7);
+  const SWord8 s804 = 128 | s803;
+  const SWord8 s805 = 127 & s803;
+  const SWord8 s806 = s802 ? s804 : s805;
+  const SBool  s807 = (SBool) (s806 & 1);
+  const SBool  s808 = false != s807;
+  const SWord8 s809 = (s793 >> 1) | (s793 << 7);
+  const SWord8 s810 = 128 | s809;
+  const SWord8 s811 = 127 & s809;
+  const SWord8 s812 = s808 ? s810 : s811;
+  const SBool  s813 = (SBool) (s812 & 1);
+  const SBool  s814 = false != s813;
+  const SWord8 s815 = (s796 >> 1) | (s796 << 7);
+  const SWord8 s816 = 128 | s815;
+  const SWord8 s817 = 127 & s815;
+  const SWord8 s818 = s814 ? s816 : s817;
+  const SBool  s819 = (SBool) (s818 & 1);
+  const SBool  s820 = false != s819;
+  const SBool  s821 = !s820;
+  const SWord8 s822 = (s806 >> 1) | (s806 << 7);
+  const SWord8 s823 = 128 | s822;
+  const SWord8 s824 = 127 & s822;
+  const SWord8 s825 = s35 ? s823 : s824;
+  const SWord8 s826 = (s825 >> 1) | (s825 << 7);
+  const SWord8 s827 = 128 | s826;
+  const SWord8 s828 = 127 & s826;
+  const SWord8 s829 = s543 ? s827 : s828;
+  const SWord8 s830 = (s829 >> 1) | (s829 << 7);
+  const SWord8 s831 = 128 | s830;
+  const SWord8 s832 = 127 & s830;
+  const SWord8 s833 = s798 ? s831 : s832;
+  const SWord8 s834 = (s833 >> 1) | (s833 << 7);
+  const SWord8 s835 = 128 | s834;
+  const SWord8 s836 = 127 & s834;
+  const SWord8 s837 = s820 ? s835 : s836;
+  const SWord8 s838 = s1 + s833;
+  const SBool  s839 = s838 < s1;
+  const SBool  s840 = s838 < s833;
+  const SBool  s841 = s839 || s840;
+  const SWord8 s842 = (s838 >> 1) | (s838 << 7);
+  const SWord8 s843 = 128 | s842;
+  const SWord8 s844 = 127 & s842;
+  const SWord8 s845 = s841 ? s843 : s844;
+  const SWord8 s846 = s821 ? s837 : s845;
+  const SWord8 s847 = s1 + s829;
+  const SBool  s848 = s847 < s1;
+  const SBool  s849 = s847 < s829;
+  const SBool  s850 = s848 || s849;
+  const SWord8 s851 = (s847 >> 1) | (s847 << 7);
+  const SWord8 s852 = 128 | s851;
+  const SWord8 s853 = 127 & s851;
+  const SWord8 s854 = s850 ? s852 : s853;
+  const SWord8 s855 = (s854 >> 1) | (s854 << 7);
+  const SWord8 s856 = 128 | s855;
+  const SWord8 s857 = 127 & s855;
+  const SWord8 s858 = s820 ? s856 : s857;
+  const SWord8 s859 = s1 + s854;
+  const SBool  s860 = s859 < s1;
+  const SBool  s861 = s859 < s854;
+  const SBool  s862 = s860 || s861;
+  const SWord8 s863 = (s859 >> 1) | (s859 << 7);
+  const SWord8 s864 = 128 | s863;
+  const SWord8 s865 = 127 & s863;
+  const SWord8 s866 = s862 ? s864 : s865;
+  const SWord8 s867 = s821 ? s858 : s866;
+  const SWord8 s868 = s799 ? s846 : s867;
+  const SWord8 s869 = s1 + s825;
+  const SBool  s870 = s869 < s1;
+  const SBool  s871 = s869 < s825;
+  const SBool  s872 = s870 || s871;
+  const SWord8 s873 = (s869 >> 1) | (s869 << 7);
+  const SWord8 s874 = 128 | s873;
+  const SWord8 s875 = 127 & s873;
+  const SWord8 s876 = s872 ? s874 : s875;
+  const SWord8 s877 = (s876 >> 1) | (s876 << 7);
+  const SWord8 s878 = 128 | s877;
+  const SWord8 s879 = 127 & s877;
+  const SWord8 s880 = s798 ? s878 : s879;
+  const SWord8 s881 = (s880 >> 1) | (s880 << 7);
+  const SWord8 s882 = 128 | s881;
+  const SWord8 s883 = 127 & s881;
+  const SWord8 s884 = s820 ? s882 : s883;
+  const SWord8 s885 = s1 + s880;
+  const SBool  s886 = s885 < s1;
+  const SBool  s887 = s885 < s880;
+  const SBool  s888 = s886 || s887;
+  const SWord8 s889 = (s885 >> 1) | (s885 << 7);
+  const SWord8 s890 = 128 | s889;
+  const SWord8 s891 = 127 & s889;
+  const SWord8 s892 = s888 ? s890 : s891;
+  const SWord8 s893 = s821 ? s884 : s892;
+  const SWord8 s894 = s1 + s876;
+  const SBool  s895 = s894 < s1;
+  const SBool  s896 = s894 < s876;
+  const SBool  s897 = s895 || s896;
+  const SWord8 s898 = (s894 >> 1) | (s894 << 7);
+  const SWord8 s899 = 128 | s898;
+  const SWord8 s900 = 127 & s898;
+  const SWord8 s901 = s897 ? s899 : s900;
+  const SWord8 s902 = (s901 >> 1) | (s901 << 7);
+  const SWord8 s903 = 128 | s902;
+  const SWord8 s904 = 127 & s902;
+  const SWord8 s905 = s820 ? s903 : s904;
+  const SWord8 s906 = s1 + s901;
+  const SBool  s907 = s906 < s1;
+  const SBool  s908 = s906 < s901;
+  const SBool  s909 = s907 || s908;
+  const SWord8 s910 = (s906 >> 1) | (s906 << 7);
+  const SWord8 s911 = 128 | s910;
+  const SWord8 s912 = 127 & s910;
+  const SWord8 s913 = s909 ? s911 : s912;
+  const SWord8 s914 = s821 ? s905 : s913;
+  const SWord8 s915 = s799 ? s893 : s914;
+  const SWord8 s916 = s544 ? s868 : s915;
+  const SWord8 s917 = s1 + s806;
+  const SBool  s918 = (SBool) (s917 & 1);
+  const SBool  s919 = false != s918;
+  const SWord8 s920 = s919 ? s810 : s811;
+  const SBool  s921 = (SBool) (s920 & 1);
+  const SBool  s922 = false != s921;
+  const SWord8 s923 = s922 ? s816 : s817;
+  const SBool  s924 = (SBool) (s923 & 1);
+  const SBool  s925 = false != s924;
+  const SBool  s926 = !s925;
+  const SBool  s927 = s917 < s1;
+  const SBool  s928 = s917 < s806;
+  const SBool  s929 = s927 || s928;
+  const SWord8 s930 = (s917 >> 1) | (s917 << 7);
+  const SWord8 s931 = 128 | s930;
+  const SWord8 s932 = 127 & s930;
+  const SWord8 s933 = s929 ? s931 : s932;
+  const SWord8 s934 = (s933 >> 1) | (s933 << 7);
+  const SWord8 s935 = 128 | s934;
+  const SWord8 s936 = 127 & s934;
+  const SWord8 s937 = s543 ? s935 : s936;
+  const SWord8 s938 = (s937 >> 1) | (s937 << 7);
+  const SWord8 s939 = 128 | s938;
+  const SWord8 s940 = 127 & s938;
+  const SWord8 s941 = s798 ? s939 : s940;
+  const SWord8 s942 = (s941 >> 1) | (s941 << 7);
+  const SWord8 s943 = 128 | s942;
+  const SWord8 s944 = 127 & s942;
+  const SWord8 s945 = s925 ? s943 : s944;
+  const SWord8 s946 = s1 + s941;
+  const SBool  s947 = s946 < s1;
+  const SBool  s948 = s946 < s941;
+  const SBool  s949 = s947 || s948;
+  const SWord8 s950 = (s946 >> 1) | (s946 << 7);
+  const SWord8 s951 = 128 | s950;
+  const SWord8 s952 = 127 & s950;
+  const SWord8 s953 = s949 ? s951 : s952;
+  const SWord8 s954 = s926 ? s945 : s953;
+  const SWord8 s955 = s1 + s937;
+  const SBool  s956 = s955 < s1;
+  const SBool  s957 = s955 < s937;
+  const SBool  s958 = s956 || s957;
+  const SWord8 s959 = (s955 >> 1) | (s955 << 7);
+  const SWord8 s960 = 128 | s959;
+  const SWord8 s961 = 127 & s959;
+  const SWord8 s962 = s958 ? s960 : s961;
+  const SWord8 s963 = (s962 >> 1) | (s962 << 7);
+  const SWord8 s964 = 128 | s963;
+  const SWord8 s965 = 127 & s963;
+  const SWord8 s966 = s925 ? s964 : s965;
+  const SWord8 s967 = s1 + s962;
+  const SBool  s968 = s967 < s1;
+  const SBool  s969 = s967 < s962;
+  const SBool  s970 = s968 || s969;
+  const SWord8 s971 = (s967 >> 1) | (s967 << 7);
+  const SWord8 s972 = 128 | s971;
+  const SWord8 s973 = 127 & s971;
+  const SWord8 s974 = s970 ? s972 : s973;
+  const SWord8 s975 = s926 ? s966 : s974;
+  const SWord8 s976 = s799 ? s954 : s975;
+  const SWord8 s977 = s1 + s933;
+  const SBool  s978 = s977 < s1;
+  const SBool  s979 = s977 < s933;
+  const SBool  s980 = s978 || s979;
+  const SWord8 s981 = (s977 >> 1) | (s977 << 7);
+  const SWord8 s982 = 128 | s981;
+  const SWord8 s983 = 127 & s981;
+  const SWord8 s984 = s980 ? s982 : s983;
+  const SWord8 s985 = (s984 >> 1) | (s984 << 7);
+  const SWord8 s986 = 128 | s985;
+  const SWord8 s987 = 127 & s985;
+  const SWord8 s988 = s798 ? s986 : s987;
+  const SWord8 s989 = (s988 >> 1) | (s988 << 7);
+  const SWord8 s990 = 128 | s989;
+  const SWord8 s991 = 127 & s989;
+  const SWord8 s992 = s925 ? s990 : s991;
+  const SWord8 s993 = s1 + s988;
+  const SBool  s994 = s993 < s1;
+  const SBool  s995 = s993 < s988;
+  const SBool  s996 = s994 || s995;
+  const SWord8 s997 = (s993 >> 1) | (s993 << 7);
+  const SWord8 s998 = 128 | s997;
+  const SWord8 s999 = 127 & s997;
+  const SWord8 s1000 = s996 ? s998 : s999;
+  const SWord8 s1001 = s926 ? s992 : s1000;
+  const SWord8 s1002 = s1 + s984;
+  const SBool  s1003 = s1002 < s1;
+  const SBool  s1004 = s1002 < s984;
+  const SBool  s1005 = s1003 || s1004;
+  const SWord8 s1006 = (s1002 >> 1) | (s1002 << 7);
+  const SWord8 s1007 = 128 | s1006;
+  const SWord8 s1008 = 127 & s1006;
+  const SWord8 s1009 = s1005 ? s1007 : s1008;
+  const SWord8 s1010 = (s1009 >> 1) | (s1009 << 7);
+  const SWord8 s1011 = 128 | s1010;
+  const SWord8 s1012 = 127 & s1010;
+  const SWord8 s1013 = s925 ? s1011 : s1012;
+  const SWord8 s1014 = s1 + s1009;
+  const SBool  s1015 = s1014 < s1;
+  const SBool  s1016 = s1014 < s1009;
+  const SBool  s1017 = s1015 || s1016;
+  const SWord8 s1018 = (s1014 >> 1) | (s1014 << 7);
+  const SWord8 s1019 = 128 | s1018;
+  const SWord8 s1020 = 127 & s1018;
+  const SWord8 s1021 = s1017 ? s1019 : s1020;
+  const SWord8 s1022 = s926 ? s1013 : s1021;
+  const SWord8 s1023 = s799 ? s1001 : s1022;
+  const SWord8 s1024 = s544 ? s976 : s1023;
+  const SWord8 s1025 = s36 ? s916 : s1024;
+  const SWord8 s1026 = s21 ? s789 : s1025;
+  const SWord8 s1027 = s16 ? s534 : s1026;
+  const SWord8 s1028 = s1 + s24;
+  const SBool  s1029 = (SBool) (s1028 & 1);
+  const SBool  s1030 = false != s1029;
+  const SWord8 s1031 = s1030 ? 128 : 0;
+  const SBool  s1032 = (SBool) (s1031 & 1);
+  const SBool  s1033 = false != s1032;
+  const SWord8 s1034 = s1033 ? s31 : s32;
+  const SBool  s1035 = (SBool) (s1034 & 1);
+  const SBool  s1036 = false != s1035;
+  const SBool  s1037 = !s1036;
+  const SBool  s1038 = s1028 < s1;
+  const SBool  s1039 = s1028 < s24;
+  const SBool  s1040 = s1038 || s1039;
+  const SWord8 s1041 = (s1028 >> 1) | (s1028 << 7);
+  const SWord8 s1042 = 128 | s1041;
+  const SWord8 s1043 = 127 & s1041;
+  const SWord8 s1044 = s1040 ? s1042 : s1043;
+  const SBool  s1045 = (SBool) (s1044 & 1);
+  const SBool  s1046 = false != s1045;
+  const SWord8 s1047 = (s1031 >> 1) | (s1031 << 7);
+  const SWord8 s1048 = 128 | s1047;
+  const SWord8 s1049 = 127 & s1047;
+  const SWord8 s1050 = s1046 ? s1048 : s1049;
+  const SBool  s1051 = (SBool) (s1050 & 1);
+  const SBool  s1052 = false != s1051;
+  const SWord8 s1053 = (s1034 >> 1) | (s1034 << 7);
+  const SWord8 s1054 = 128 | s1053;
+  const SWord8 s1055 = 127 & s1053;
+  const SWord8 s1056 = s1052 ? s1054 : s1055;
+  const SBool  s1057 = (SBool) (s1056 & 1);
+  const SBool  s1058 = false != s1057;
+  const SBool  s1059 = !s1058;
+  const SWord8 s1060 = (s1044 >> 1) | (s1044 << 7);
+  const SWord8 s1061 = 128 | s1060;
+  const SWord8 s1062 = 127 & s1060;
+  const SWord8 s1063 = s15 ? s1061 : s1062;
+  const SBool  s1064 = (SBool) (s1063 & 1);
+  const SBool  s1065 = false != s1064;
+  const SWord8 s1066 = (s1050 >> 1) | (s1050 << 7);
+  const SWord8 s1067 = 128 | s1066;
+  const SWord8 s1068 = 127 & s1066;
+  const SWord8 s1069 = s1065 ? s1067 : s1068;
+  const SBool  s1070 = (SBool) (s1069 & 1);
+  const SBool  s1071 = false != s1070;
+  const SWord8 s1072 = (s1056 >> 1) | (s1056 << 7);
+  const SWord8 s1073 = 128 | s1072;
+  const SWord8 s1074 = 127 & s1072;
+  const SWord8 s1075 = s1071 ? s1073 : s1074;
+  const SBool  s1076 = (SBool) (s1075 & 1);
+  const SBool  s1077 = false != s1076;
+  const SBool  s1078 = !s1077;
+  const SWord8 s1079 = (s1063 >> 1) | (s1063 << 7);
+  const SWord8 s1080 = 128 | s1079;
+  const SWord8 s1081 = 127 & s1079;
+  const SWord8 s1082 = s20 ? s1080 : s1081;
+  const SBool  s1083 = (SBool) (s1082 & 1);
+  const SBool  s1084 = false != s1083;
+  const SWord8 s1085 = (s1069 >> 1) | (s1069 << 7);
+  const SWord8 s1086 = 128 | s1085;
+  const SWord8 s1087 = 127 & s1085;
+  const SWord8 s1088 = s1084 ? s1086 : s1087;
+  const SBool  s1089 = (SBool) (s1088 & 1);
+  const SBool  s1090 = false != s1089;
+  const SWord8 s1091 = (s1075 >> 1) | (s1075 << 7);
+  const SWord8 s1092 = 128 | s1091;
+  const SWord8 s1093 = 127 & s1091;
+  const SWord8 s1094 = s1090 ? s1092 : s1093;
+  const SBool  s1095 = (SBool) (s1094 & 1);
+  const SBool  s1096 = false != s1095;
+  const SBool  s1097 = !s1096;
+  const SWord8 s1098 = (s1082 >> 1) | (s1082 << 7);
+  const SWord8 s1099 = 128 | s1098;
+  const SWord8 s1100 = 127 & s1098;
+  const SWord8 s1101 = s1036 ? s1099 : s1100;
+  const SWord8 s1102 = (s1101 >> 1) | (s1101 << 7);
+  const SWord8 s1103 = 128 | s1102;
+  const SWord8 s1104 = 127 & s1102;
+  const SWord8 s1105 = s1058 ? s1103 : s1104;
+  const SWord8 s1106 = (s1105 >> 1) | (s1105 << 7);
+  const SWord8 s1107 = 128 | s1106;
+  const SWord8 s1108 = 127 & s1106;
+  const SWord8 s1109 = s1077 ? s1107 : s1108;
+  const SWord8 s1110 = (s1109 >> 1) | (s1109 << 7);
+  const SWord8 s1111 = 128 | s1110;
+  const SWord8 s1112 = 127 & s1110;
+  const SWord8 s1113 = s1096 ? s1111 : s1112;
+  const SWord8 s1114 = s1 + s1109;
+  const SBool  s1115 = s1114 < s1;
+  const SBool  s1116 = s1114 < s1109;
+  const SBool  s1117 = s1115 || s1116;
+  const SWord8 s1118 = (s1114 >> 1) | (s1114 << 7);
+  const SWord8 s1119 = 128 | s1118;
+  const SWord8 s1120 = 127 & s1118;
+  const SWord8 s1121 = s1117 ? s1119 : s1120;
+  const SWord8 s1122 = s1097 ? s1113 : s1121;
+  const SWord8 s1123 = s1 + s1105;
+  const SBool  s1124 = s1123 < s1;
+  const SBool  s1125 = s1123 < s1105;
+  const SBool  s1126 = s1124 || s1125;
+  const SWord8 s1127 = (s1123 >> 1) | (s1123 << 7);
+  const SWord8 s1128 = 128 | s1127;
+  const SWord8 s1129 = 127 & s1127;
+  const SWord8 s1130 = s1126 ? s1128 : s1129;
+  const SWord8 s1131 = (s1130 >> 1) | (s1130 << 7);
+  const SWord8 s1132 = 128 | s1131;
+  const SWord8 s1133 = 127 & s1131;
+  const SWord8 s1134 = s1096 ? s1132 : s1133;
+  const SWord8 s1135 = s1 + s1130;
+  const SBool  s1136 = s1135 < s1;
+  const SBool  s1137 = s1135 < s1130;
+  const SBool  s1138 = s1136 || s1137;
+  const SWord8 s1139 = (s1135 >> 1) | (s1135 << 7);
+  const SWord8 s1140 = 128 | s1139;
+  const SWord8 s1141 = 127 & s1139;
+  const SWord8 s1142 = s1138 ? s1140 : s1141;
+  const SWord8 s1143 = s1097 ? s1134 : s1142;
+  const SWord8 s1144 = s1078 ? s1122 : s1143;
+  const SWord8 s1145 = s1 + s1101;
+  const SBool  s1146 = s1145 < s1;
+  const SBool  s1147 = s1145 < s1101;
+  const SBool  s1148 = s1146 || s1147;
+  const SWord8 s1149 = (s1145 >> 1) | (s1145 << 7);
+  const SWord8 s1150 = 128 | s1149;
+  const SWord8 s1151 = 127 & s1149;
+  const SWord8 s1152 = s1148 ? s1150 : s1151;
+  const SWord8 s1153 = (s1152 >> 1) | (s1152 << 7);
+  const SWord8 s1154 = 128 | s1153;
+  const SWord8 s1155 = 127 & s1153;
+  const SWord8 s1156 = s1077 ? s1154 : s1155;
+  const SWord8 s1157 = (s1156 >> 1) | (s1156 << 7);
+  const SWord8 s1158 = 128 | s1157;
+  const SWord8 s1159 = 127 & s1157;
+  const SWord8 s1160 = s1096 ? s1158 : s1159;
+  const SWord8 s1161 = s1 + s1156;
+  const SBool  s1162 = s1161 < s1;
+  const SBool  s1163 = s1161 < s1156;
+  const SBool  s1164 = s1162 || s1163;
+  const SWord8 s1165 = (s1161 >> 1) | (s1161 << 7);
+  const SWord8 s1166 = 128 | s1165;
+  const SWord8 s1167 = 127 & s1165;
+  const SWord8 s1168 = s1164 ? s1166 : s1167;
+  const SWord8 s1169 = s1097 ? s1160 : s1168;
+  const SWord8 s1170 = s1 + s1152;
+  const SBool  s1171 = s1170 < s1;
+  const SBool  s1172 = s1170 < s1152;
+  const SBool  s1173 = s1171 || s1172;
+  const SWord8 s1174 = (s1170 >> 1) | (s1170 << 7);
+  const SWord8 s1175 = 128 | s1174;
+  const SWord8 s1176 = 127 & s1174;
+  const SWord8 s1177 = s1173 ? s1175 : s1176;
+  const SWord8 s1178 = (s1177 >> 1) | (s1177 << 7);
+  const SWord8 s1179 = 128 | s1178;
+  const SWord8 s1180 = 127 & s1178;
+  const SWord8 s1181 = s1096 ? s1179 : s1180;
+  const SWord8 s1182 = s1 + s1177;
+  const SBool  s1183 = s1182 < s1;
+  const SBool  s1184 = s1182 < s1177;
+  const SBool  s1185 = s1183 || s1184;
+  const SWord8 s1186 = (s1182 >> 1) | (s1182 << 7);
+  const SWord8 s1187 = 128 | s1186;
+  const SWord8 s1188 = 127 & s1186;
+  const SWord8 s1189 = s1185 ? s1187 : s1188;
+  const SWord8 s1190 = s1097 ? s1181 : s1189;
+  const SWord8 s1191 = s1078 ? s1169 : s1190;
+  const SWord8 s1192 = s1059 ? s1144 : s1191;
+  const SWord8 s1193 = s1 + s1082;
+  const SBool  s1194 = (SBool) (s1193 & 1);
+  const SBool  s1195 = false != s1194;
+  const SWord8 s1196 = s1195 ? s1086 : s1087;
+  const SBool  s1197 = (SBool) (s1196 & 1);
+  const SBool  s1198 = false != s1197;
+  const SWord8 s1199 = s1198 ? s1092 : s1093;
+  const SBool  s1200 = (SBool) (s1199 & 1);
+  const SBool  s1201 = false != s1200;
+  const SBool  s1202 = !s1201;
+  const SBool  s1203 = s1193 < s1;
+  const SBool  s1204 = s1193 < s1082;
+  const SBool  s1205 = s1203 || s1204;
+  const SWord8 s1206 = (s1193 >> 1) | (s1193 << 7);
+  const SWord8 s1207 = 128 | s1206;
+  const SWord8 s1208 = 127 & s1206;
+  const SWord8 s1209 = s1205 ? s1207 : s1208;
+  const SWord8 s1210 = (s1209 >> 1) | (s1209 << 7);
+  const SWord8 s1211 = 128 | s1210;
+  const SWord8 s1212 = 127 & s1210;
+  const SWord8 s1213 = s1058 ? s1211 : s1212;
+  const SWord8 s1214 = (s1213 >> 1) | (s1213 << 7);
+  const SWord8 s1215 = 128 | s1214;
+  const SWord8 s1216 = 127 & s1214;
+  const SWord8 s1217 = s1077 ? s1215 : s1216;
+  const SWord8 s1218 = (s1217 >> 1) | (s1217 << 7);
+  const SWord8 s1219 = 128 | s1218;
+  const SWord8 s1220 = 127 & s1218;
+  const SWord8 s1221 = s1201 ? s1219 : s1220;
+  const SWord8 s1222 = s1 + s1217;
+  const SBool  s1223 = s1222 < s1;
+  const SBool  s1224 = s1222 < s1217;
+  const SBool  s1225 = s1223 || s1224;
+  const SWord8 s1226 = (s1222 >> 1) | (s1222 << 7);
+  const SWord8 s1227 = 128 | s1226;
+  const SWord8 s1228 = 127 & s1226;
+  const SWord8 s1229 = s1225 ? s1227 : s1228;
+  const SWord8 s1230 = s1202 ? s1221 : s1229;
+  const SWord8 s1231 = s1 + s1213;
+  const SBool  s1232 = s1231 < s1;
+  const SBool  s1233 = s1231 < s1213;
+  const SBool  s1234 = s1232 || s1233;
+  const SWord8 s1235 = (s1231 >> 1) | (s1231 << 7);
+  const SWord8 s1236 = 128 | s1235;
+  const SWord8 s1237 = 127 & s1235;
+  const SWord8 s1238 = s1234 ? s1236 : s1237;
+  const SWord8 s1239 = (s1238 >> 1) | (s1238 << 7);
+  const SWord8 s1240 = 128 | s1239;
+  const SWord8 s1241 = 127 & s1239;
+  const SWord8 s1242 = s1201 ? s1240 : s1241;
+  const SWord8 s1243 = s1 + s1238;
+  const SBool  s1244 = s1243 < s1;
+  const SBool  s1245 = s1243 < s1238;
+  const SBool  s1246 = s1244 || s1245;
+  const SWord8 s1247 = (s1243 >> 1) | (s1243 << 7);
+  const SWord8 s1248 = 128 | s1247;
+  const SWord8 s1249 = 127 & s1247;
+  const SWord8 s1250 = s1246 ? s1248 : s1249;
+  const SWord8 s1251 = s1202 ? s1242 : s1250;
+  const SWord8 s1252 = s1078 ? s1230 : s1251;
+  const SWord8 s1253 = s1 + s1209;
+  const SBool  s1254 = s1253 < s1;
+  const SBool  s1255 = s1253 < s1209;
+  const SBool  s1256 = s1254 || s1255;
+  const SWord8 s1257 = (s1253 >> 1) | (s1253 << 7);
+  const SWord8 s1258 = 128 | s1257;
+  const SWord8 s1259 = 127 & s1257;
+  const SWord8 s1260 = s1256 ? s1258 : s1259;
+  const SWord8 s1261 = (s1260 >> 1) | (s1260 << 7);
+  const SWord8 s1262 = 128 | s1261;
+  const SWord8 s1263 = 127 & s1261;
+  const SWord8 s1264 = s1077 ? s1262 : s1263;
+  const SWord8 s1265 = (s1264 >> 1) | (s1264 << 7);
+  const SWord8 s1266 = 128 | s1265;
+  const SWord8 s1267 = 127 & s1265;
+  const SWord8 s1268 = s1201 ? s1266 : s1267;
+  const SWord8 s1269 = s1 + s1264;
+  const SBool  s1270 = s1269 < s1;
+  const SBool  s1271 = s1269 < s1264;
+  const SBool  s1272 = s1270 || s1271;
+  const SWord8 s1273 = (s1269 >> 1) | (s1269 << 7);
+  const SWord8 s1274 = 128 | s1273;
+  const SWord8 s1275 = 127 & s1273;
+  const SWord8 s1276 = s1272 ? s1274 : s1275;
+  const SWord8 s1277 = s1202 ? s1268 : s1276;
+  const SWord8 s1278 = s1 + s1260;
+  const SBool  s1279 = s1278 < s1;
+  const SBool  s1280 = s1278 < s1260;
+  const SBool  s1281 = s1279 || s1280;
+  const SWord8 s1282 = (s1278 >> 1) | (s1278 << 7);
+  const SWord8 s1283 = 128 | s1282;
+  const SWord8 s1284 = 127 & s1282;
+  const SWord8 s1285 = s1281 ? s1283 : s1284;
+  const SWord8 s1286 = (s1285 >> 1) | (s1285 << 7);
+  const SWord8 s1287 = 128 | s1286;
+  const SWord8 s1288 = 127 & s1286;
+  const SWord8 s1289 = s1201 ? s1287 : s1288;
+  const SWord8 s1290 = s1 + s1285;
+  const SBool  s1291 = s1290 < s1;
+  const SBool  s1292 = s1290 < s1285;
+  const SBool  s1293 = s1291 || s1292;
+  const SWord8 s1294 = (s1290 >> 1) | (s1290 << 7);
+  const SWord8 s1295 = 128 | s1294;
+  const SWord8 s1296 = 127 & s1294;
+  const SWord8 s1297 = s1293 ? s1295 : s1296;
+  const SWord8 s1298 = s1202 ? s1289 : s1297;
+  const SWord8 s1299 = s1078 ? s1277 : s1298;
+  const SWord8 s1300 = s1059 ? s1252 : s1299;
+  const SWord8 s1301 = s1037 ? s1192 : s1300;
+  const SWord8 s1302 = s1 + s1063;
+  const SBool  s1303 = (SBool) (s1302 & 1);
+  const SBool  s1304 = false != s1303;
+  const SWord8 s1305 = s1304 ? s1067 : s1068;
+  const SBool  s1306 = (SBool) (s1305 & 1);
+  const SBool  s1307 = false != s1306;
+  const SWord8 s1308 = s1307 ? s1073 : s1074;
+  const SBool  s1309 = (SBool) (s1308 & 1);
+  const SBool  s1310 = false != s1309;
+  const SBool  s1311 = !s1310;
+  const SBool  s1312 = s1302 < s1;
+  const SBool  s1313 = s1302 < s1063;
+  const SBool  s1314 = s1312 || s1313;
+  const SWord8 s1315 = (s1302 >> 1) | (s1302 << 7);
+  const SWord8 s1316 = 128 | s1315;
+  const SWord8 s1317 = 127 & s1315;
+  const SWord8 s1318 = s1314 ? s1316 : s1317;
+  const SBool  s1319 = (SBool) (s1318 & 1);
+  const SBool  s1320 = false != s1319;
+  const SWord8 s1321 = (s1305 >> 1) | (s1305 << 7);
+  const SWord8 s1322 = 128 | s1321;
+  const SWord8 s1323 = 127 & s1321;
+  const SWord8 s1324 = s1320 ? s1322 : s1323;
+  const SBool  s1325 = (SBool) (s1324 & 1);
+  const SBool  s1326 = false != s1325;
+  const SWord8 s1327 = (s1308 >> 1) | (s1308 << 7);
+  const SWord8 s1328 = 128 | s1327;
+  const SWord8 s1329 = 127 & s1327;
+  const SWord8 s1330 = s1326 ? s1328 : s1329;
+  const SBool  s1331 = (SBool) (s1330 & 1);
+  const SBool  s1332 = false != s1331;
+  const SBool  s1333 = !s1332;
+  const SWord8 s1334 = (s1318 >> 1) | (s1318 << 7);
+  const SWord8 s1335 = 128 | s1334;
+  const SWord8 s1336 = 127 & s1334;
+  const SWord8 s1337 = s1036 ? s1335 : s1336;
+  const SWord8 s1338 = (s1337 >> 1) | (s1337 << 7);
+  const SWord8 s1339 = 128 | s1338;
+  const SWord8 s1340 = 127 & s1338;
+  const SWord8 s1341 = s1058 ? s1339 : s1340;
+  const SWord8 s1342 = (s1341 >> 1) | (s1341 << 7);
+  const SWord8 s1343 = 128 | s1342;
+  const SWord8 s1344 = 127 & s1342;
+  const SWord8 s1345 = s1310 ? s1343 : s1344;
+  const SWord8 s1346 = (s1345 >> 1) | (s1345 << 7);
+  const SWord8 s1347 = 128 | s1346;
+  const SWord8 s1348 = 127 & s1346;
+  const SWord8 s1349 = s1332 ? s1347 : s1348;
+  const SWord8 s1350 = s1 + s1345;
+  const SBool  s1351 = s1350 < s1;
+  const SBool  s1352 = s1350 < s1345;
+  const SBool  s1353 = s1351 || s1352;
+  const SWord8 s1354 = (s1350 >> 1) | (s1350 << 7);
+  const SWord8 s1355 = 128 | s1354;
+  const SWord8 s1356 = 127 & s1354;
+  const SWord8 s1357 = s1353 ? s1355 : s1356;
+  const SWord8 s1358 = s1333 ? s1349 : s1357;
+  const SWord8 s1359 = s1 + s1341;
+  const SBool  s1360 = s1359 < s1;
+  const SBool  s1361 = s1359 < s1341;
+  const SBool  s1362 = s1360 || s1361;
+  const SWord8 s1363 = (s1359 >> 1) | (s1359 << 7);
+  const SWord8 s1364 = 128 | s1363;
+  const SWord8 s1365 = 127 & s1363;
+  const SWord8 s1366 = s1362 ? s1364 : s1365;
+  const SWord8 s1367 = (s1366 >> 1) | (s1366 << 7);
+  const SWord8 s1368 = 128 | s1367;
+  const SWord8 s1369 = 127 & s1367;
+  const SWord8 s1370 = s1332 ? s1368 : s1369;
+  const SWord8 s1371 = s1 + s1366;
+  const SBool  s1372 = s1371 < s1;
+  const SBool  s1373 = s1371 < s1366;
+  const SBool  s1374 = s1372 || s1373;
+  const SWord8 s1375 = (s1371 >> 1) | (s1371 << 7);
+  const SWord8 s1376 = 128 | s1375;
+  const SWord8 s1377 = 127 & s1375;
+  const SWord8 s1378 = s1374 ? s1376 : s1377;
+  const SWord8 s1379 = s1333 ? s1370 : s1378;
+  const SWord8 s1380 = s1311 ? s1358 : s1379;
+  const SWord8 s1381 = s1 + s1337;
+  const SBool  s1382 = s1381 < s1;
+  const SBool  s1383 = s1381 < s1337;
+  const SBool  s1384 = s1382 || s1383;
+  const SWord8 s1385 = (s1381 >> 1) | (s1381 << 7);
+  const SWord8 s1386 = 128 | s1385;
+  const SWord8 s1387 = 127 & s1385;
+  const SWord8 s1388 = s1384 ? s1386 : s1387;
+  const SWord8 s1389 = (s1388 >> 1) | (s1388 << 7);
+  const SWord8 s1390 = 128 | s1389;
+  const SWord8 s1391 = 127 & s1389;
+  const SWord8 s1392 = s1310 ? s1390 : s1391;
+  const SWord8 s1393 = (s1392 >> 1) | (s1392 << 7);
+  const SWord8 s1394 = 128 | s1393;
+  const SWord8 s1395 = 127 & s1393;
+  const SWord8 s1396 = s1332 ? s1394 : s1395;
+  const SWord8 s1397 = s1 + s1392;
+  const SBool  s1398 = s1397 < s1;
+  const SBool  s1399 = s1397 < s1392;
+  const SBool  s1400 = s1398 || s1399;
+  const SWord8 s1401 = (s1397 >> 1) | (s1397 << 7);
+  const SWord8 s1402 = 128 | s1401;
+  const SWord8 s1403 = 127 & s1401;
+  const SWord8 s1404 = s1400 ? s1402 : s1403;
+  const SWord8 s1405 = s1333 ? s1396 : s1404;
+  const SWord8 s1406 = s1 + s1388;
+  const SBool  s1407 = s1406 < s1;
+  const SBool  s1408 = s1406 < s1388;
+  const SBool  s1409 = s1407 || s1408;
+  const SWord8 s1410 = (s1406 >> 1) | (s1406 << 7);
+  const SWord8 s1411 = 128 | s1410;
+  const SWord8 s1412 = 127 & s1410;
+  const SWord8 s1413 = s1409 ? s1411 : s1412;
+  const SWord8 s1414 = (s1413 >> 1) | (s1413 << 7);
+  const SWord8 s1415 = 128 | s1414;
+  const SWord8 s1416 = 127 & s1414;
+  const SWord8 s1417 = s1332 ? s1415 : s1416;
+  const SWord8 s1418 = s1 + s1413;
+  const SBool  s1419 = s1418 < s1;
+  const SBool  s1420 = s1418 < s1413;
+  const SBool  s1421 = s1419 || s1420;
+  const SWord8 s1422 = (s1418 >> 1) | (s1418 << 7);
+  const SWord8 s1423 = 128 | s1422;
+  const SWord8 s1424 = 127 & s1422;
+  const SWord8 s1425 = s1421 ? s1423 : s1424;
+  const SWord8 s1426 = s1333 ? s1417 : s1425;
+  const SWord8 s1427 = s1311 ? s1405 : s1426;
+  const SWord8 s1428 = s1059 ? s1380 : s1427;
+  const SWord8 s1429 = s1 + s1318;
+  const SBool  s1430 = (SBool) (s1429 & 1);
+  const SBool  s1431 = false != s1430;
+  const SWord8 s1432 = s1431 ? s1322 : s1323;
+  const SBool  s1433 = (SBool) (s1432 & 1);
+  const SBool  s1434 = false != s1433;
+  const SWord8 s1435 = s1434 ? s1328 : s1329;
+  const SBool  s1436 = (SBool) (s1435 & 1);
+  const SBool  s1437 = false != s1436;
+  const SBool  s1438 = !s1437;
+  const SBool  s1439 = s1429 < s1;
+  const SBool  s1440 = s1429 < s1318;
+  const SBool  s1441 = s1439 || s1440;
+  const SWord8 s1442 = (s1429 >> 1) | (s1429 << 7);
+  const SWord8 s1443 = 128 | s1442;
+  const SWord8 s1444 = 127 & s1442;
+  const SWord8 s1445 = s1441 ? s1443 : s1444;
+  const SWord8 s1446 = (s1445 >> 1) | (s1445 << 7);
+  const SWord8 s1447 = 128 | s1446;
+  const SWord8 s1448 = 127 & s1446;
+  const SWord8 s1449 = s1058 ? s1447 : s1448;
+  const SWord8 s1450 = (s1449 >> 1) | (s1449 << 7);
+  const SWord8 s1451 = 128 | s1450;
+  const SWord8 s1452 = 127 & s1450;
+  const SWord8 s1453 = s1310 ? s1451 : s1452;
+  const SWord8 s1454 = (s1453 >> 1) | (s1453 << 7);
+  const SWord8 s1455 = 128 | s1454;
+  const SWord8 s1456 = 127 & s1454;
+  const SWord8 s1457 = s1437 ? s1455 : s1456;
+  const SWord8 s1458 = s1 + s1453;
+  const SBool  s1459 = s1458 < s1;
+  const SBool  s1460 = s1458 < s1453;
+  const SBool  s1461 = s1459 || s1460;
+  const SWord8 s1462 = (s1458 >> 1) | (s1458 << 7);
+  const SWord8 s1463 = 128 | s1462;
+  const SWord8 s1464 = 127 & s1462;
+  const SWord8 s1465 = s1461 ? s1463 : s1464;
+  const SWord8 s1466 = s1438 ? s1457 : s1465;
+  const SWord8 s1467 = s1 + s1449;
+  const SBool  s1468 = s1467 < s1;
+  const SBool  s1469 = s1467 < s1449;
+  const SBool  s1470 = s1468 || s1469;
+  const SWord8 s1471 = (s1467 >> 1) | (s1467 << 7);
+  const SWord8 s1472 = 128 | s1471;
+  const SWord8 s1473 = 127 & s1471;
+  const SWord8 s1474 = s1470 ? s1472 : s1473;
+  const SWord8 s1475 = (s1474 >> 1) | (s1474 << 7);
+  const SWord8 s1476 = 128 | s1475;
+  const SWord8 s1477 = 127 & s1475;
+  const SWord8 s1478 = s1437 ? s1476 : s1477;
+  const SWord8 s1479 = s1 + s1474;
+  const SBool  s1480 = s1479 < s1;
+  const SBool  s1481 = s1479 < s1474;
+  const SBool  s1482 = s1480 || s1481;
+  const SWord8 s1483 = (s1479 >> 1) | (s1479 << 7);
+  const SWord8 s1484 = 128 | s1483;
+  const SWord8 s1485 = 127 & s1483;
+  const SWord8 s1486 = s1482 ? s1484 : s1485;
+  const SWord8 s1487 = s1438 ? s1478 : s1486;
+  const SWord8 s1488 = s1311 ? s1466 : s1487;
+  const SWord8 s1489 = s1 + s1445;
+  const SBool  s1490 = s1489 < s1;
+  const SBool  s1491 = s1489 < s1445;
+  const SBool  s1492 = s1490 || s1491;
+  const SWord8 s1493 = (s1489 >> 1) | (s1489 << 7);
+  const SWord8 s1494 = 128 | s1493;
+  const SWord8 s1495 = 127 & s1493;
+  const SWord8 s1496 = s1492 ? s1494 : s1495;
+  const SWord8 s1497 = (s1496 >> 1) | (s1496 << 7);
+  const SWord8 s1498 = 128 | s1497;
+  const SWord8 s1499 = 127 & s1497;
+  const SWord8 s1500 = s1310 ? s1498 : s1499;
+  const SWord8 s1501 = (s1500 >> 1) | (s1500 << 7);
+  const SWord8 s1502 = 128 | s1501;
+  const SWord8 s1503 = 127 & s1501;
+  const SWord8 s1504 = s1437 ? s1502 : s1503;
+  const SWord8 s1505 = s1 + s1500;
+  const SBool  s1506 = s1505 < s1;
+  const SBool  s1507 = s1505 < s1500;
+  const SBool  s1508 = s1506 || s1507;
+  const SWord8 s1509 = (s1505 >> 1) | (s1505 << 7);
+  const SWord8 s1510 = 128 | s1509;
+  const SWord8 s1511 = 127 & s1509;
+  const SWord8 s1512 = s1508 ? s1510 : s1511;
+  const SWord8 s1513 = s1438 ? s1504 : s1512;
+  const SWord8 s1514 = s1 + s1496;
+  const SBool  s1515 = s1514 < s1;
+  const SBool  s1516 = s1514 < s1496;
+  const SBool  s1517 = s1515 || s1516;
+  const SWord8 s1518 = (s1514 >> 1) | (s1514 << 7);
+  const SWord8 s1519 = 128 | s1518;
+  const SWord8 s1520 = 127 & s1518;
+  const SWord8 s1521 = s1517 ? s1519 : s1520;
+  const SWord8 s1522 = (s1521 >> 1) | (s1521 << 7);
+  const SWord8 s1523 = 128 | s1522;
+  const SWord8 s1524 = 127 & s1522;
+  const SWord8 s1525 = s1437 ? s1523 : s1524;
+  const SWord8 s1526 = s1 + s1521;
+  const SBool  s1527 = s1526 < s1;
+  const SBool  s1528 = s1526 < s1521;
+  const SBool  s1529 = s1527 || s1528;
+  const SWord8 s1530 = (s1526 >> 1) | (s1526 << 7);
+  const SWord8 s1531 = 128 | s1530;
+  const SWord8 s1532 = 127 & s1530;
+  const SWord8 s1533 = s1529 ? s1531 : s1532;
+  const SWord8 s1534 = s1438 ? s1525 : s1533;
+  const SWord8 s1535 = s1311 ? s1513 : s1534;
+  const SWord8 s1536 = s1059 ? s1488 : s1535;
+  const SWord8 s1537 = s1037 ? s1428 : s1536;
+  const SWord8 s1538 = s21 ? s1301 : s1537;
+  const SWord8 s1539 = s1 + s1044;
+  const SBool  s1540 = (SBool) (s1539 & 1);
+  const SBool  s1541 = false != s1540;
+  const SWord8 s1542 = s1541 ? s1048 : s1049;
+  const SBool  s1543 = (SBool) (s1542 & 1);
+  const SBool  s1544 = false != s1543;
+  const SWord8 s1545 = s1544 ? s1054 : s1055;
+  const SBool  s1546 = (SBool) (s1545 & 1);
+  const SBool  s1547 = false != s1546;
+  const SBool  s1548 = !s1547;
+  const SBool  s1549 = s1539 < s1;
+  const SBool  s1550 = s1539 < s1044;
+  const SBool  s1551 = s1549 || s1550;
+  const SWord8 s1552 = (s1539 >> 1) | (s1539 << 7);
+  const SWord8 s1553 = 128 | s1552;
+  const SWord8 s1554 = 127 & s1552;
+  const SWord8 s1555 = s1551 ? s1553 : s1554;
+  const SBool  s1556 = (SBool) (s1555 & 1);
+  const SBool  s1557 = false != s1556;
+  const SWord8 s1558 = (s1542 >> 1) | (s1542 << 7);
+  const SWord8 s1559 = 128 | s1558;
+  const SWord8 s1560 = 127 & s1558;
+  const SWord8 s1561 = s1557 ? s1559 : s1560;
+  const SBool  s1562 = (SBool) (s1561 & 1);
+  const SBool  s1563 = false != s1562;
+  const SWord8 s1564 = (s1545 >> 1) | (s1545 << 7);
+  const SWord8 s1565 = 128 | s1564;
+  const SWord8 s1566 = 127 & s1564;
+  const SWord8 s1567 = s1563 ? s1565 : s1566;
+  const SBool  s1568 = (SBool) (s1567 & 1);
+  const SBool  s1569 = false != s1568;
+  const SBool  s1570 = !s1569;
+  const SWord8 s1571 = (s1555 >> 1) | (s1555 << 7);
+  const SWord8 s1572 = 128 | s1571;
+  const SWord8 s1573 = 127 & s1571;
+  const SWord8 s1574 = s20 ? s1572 : s1573;
+  const SBool  s1575 = (SBool) (s1574 & 1);
+  const SBool  s1576 = false != s1575;
+  const SWord8 s1577 = (s1561 >> 1) | (s1561 << 7);
+  const SWord8 s1578 = 128 | s1577;
+  const SWord8 s1579 = 127 & s1577;
+  const SWord8 s1580 = s1576 ? s1578 : s1579;
+  const SBool  s1581 = (SBool) (s1580 & 1);
+  const SBool  s1582 = false != s1581;
+  const SWord8 s1583 = (s1567 >> 1) | (s1567 << 7);
+  const SWord8 s1584 = 128 | s1583;
+  const SWord8 s1585 = 127 & s1583;
+  const SWord8 s1586 = s1582 ? s1584 : s1585;
+  const SBool  s1587 = (SBool) (s1586 & 1);
+  const SBool  s1588 = false != s1587;
+  const SBool  s1589 = !s1588;
+  const SWord8 s1590 = (s1574 >> 1) | (s1574 << 7);
+  const SWord8 s1591 = 128 | s1590;
+  const SWord8 s1592 = 127 & s1590;
+  const SWord8 s1593 = s1036 ? s1591 : s1592;
+  const SWord8 s1594 = (s1593 >> 1) | (s1593 << 7);
+  const SWord8 s1595 = 128 | s1594;
+  const SWord8 s1596 = 127 & s1594;
+  const SWord8 s1597 = s1547 ? s1595 : s1596;
+  const SWord8 s1598 = (s1597 >> 1) | (s1597 << 7);
+  const SWord8 s1599 = 128 | s1598;
+  const SWord8 s1600 = 127 & s1598;
+  const SWord8 s1601 = s1569 ? s1599 : s1600;
+  const SWord8 s1602 = (s1601 >> 1) | (s1601 << 7);
+  const SWord8 s1603 = 128 | s1602;
+  const SWord8 s1604 = 127 & s1602;
+  const SWord8 s1605 = s1588 ? s1603 : s1604;
+  const SWord8 s1606 = s1 + s1601;
+  const SBool  s1607 = s1606 < s1;
+  const SBool  s1608 = s1606 < s1601;
+  const SBool  s1609 = s1607 || s1608;
+  const SWord8 s1610 = (s1606 >> 1) | (s1606 << 7);
+  const SWord8 s1611 = 128 | s1610;
+  const SWord8 s1612 = 127 & s1610;
+  const SWord8 s1613 = s1609 ? s1611 : s1612;
+  const SWord8 s1614 = s1589 ? s1605 : s1613;
+  const SWord8 s1615 = s1 + s1597;
+  const SBool  s1616 = s1615 < s1;
+  const SBool  s1617 = s1615 < s1597;
+  const SBool  s1618 = s1616 || s1617;
+  const SWord8 s1619 = (s1615 >> 1) | (s1615 << 7);
+  const SWord8 s1620 = 128 | s1619;
+  const SWord8 s1621 = 127 & s1619;
+  const SWord8 s1622 = s1618 ? s1620 : s1621;
+  const SWord8 s1623 = (s1622 >> 1) | (s1622 << 7);
+  const SWord8 s1624 = 128 | s1623;
+  const SWord8 s1625 = 127 & s1623;
+  const SWord8 s1626 = s1588 ? s1624 : s1625;
+  const SWord8 s1627 = s1 + s1622;
+  const SBool  s1628 = s1627 < s1;
+  const SBool  s1629 = s1627 < s1622;
+  const SBool  s1630 = s1628 || s1629;
+  const SWord8 s1631 = (s1627 >> 1) | (s1627 << 7);
+  const SWord8 s1632 = 128 | s1631;
+  const SWord8 s1633 = 127 & s1631;
+  const SWord8 s1634 = s1630 ? s1632 : s1633;
+  const SWord8 s1635 = s1589 ? s1626 : s1634;
+  const SWord8 s1636 = s1570 ? s1614 : s1635;
+  const SWord8 s1637 = s1 + s1593;
+  const SBool  s1638 = s1637 < s1;
+  const SBool  s1639 = s1637 < s1593;
+  const SBool  s1640 = s1638 || s1639;
+  const SWord8 s1641 = (s1637 >> 1) | (s1637 << 7);
+  const SWord8 s1642 = 128 | s1641;
+  const SWord8 s1643 = 127 & s1641;
+  const SWord8 s1644 = s1640 ? s1642 : s1643;
+  const SWord8 s1645 = (s1644 >> 1) | (s1644 << 7);
+  const SWord8 s1646 = 128 | s1645;
+  const SWord8 s1647 = 127 & s1645;
+  const SWord8 s1648 = s1569 ? s1646 : s1647;
+  const SWord8 s1649 = (s1648 >> 1) | (s1648 << 7);
+  const SWord8 s1650 = 128 | s1649;
+  const SWord8 s1651 = 127 & s1649;
+  const SWord8 s1652 = s1588 ? s1650 : s1651;
+  const SWord8 s1653 = s1 + s1648;
+  const SBool  s1654 = s1653 < s1;
+  const SBool  s1655 = s1653 < s1648;
+  const SBool  s1656 = s1654 || s1655;
+  const SWord8 s1657 = (s1653 >> 1) | (s1653 << 7);
+  const SWord8 s1658 = 128 | s1657;
+  const SWord8 s1659 = 127 & s1657;
+  const SWord8 s1660 = s1656 ? s1658 : s1659;
+  const SWord8 s1661 = s1589 ? s1652 : s1660;
+  const SWord8 s1662 = s1 + s1644;
+  const SBool  s1663 = s1662 < s1;
+  const SBool  s1664 = s1662 < s1644;
+  const SBool  s1665 = s1663 || s1664;
+  const SWord8 s1666 = (s1662 >> 1) | (s1662 << 7);
+  const SWord8 s1667 = 128 | s1666;
+  const SWord8 s1668 = 127 & s1666;
+  const SWord8 s1669 = s1665 ? s1667 : s1668;
+  const SWord8 s1670 = (s1669 >> 1) | (s1669 << 7);
+  const SWord8 s1671 = 128 | s1670;
+  const SWord8 s1672 = 127 & s1670;
+  const SWord8 s1673 = s1588 ? s1671 : s1672;
+  const SWord8 s1674 = s1 + s1669;
+  const SBool  s1675 = s1674 < s1;
+  const SBool  s1676 = s1674 < s1669;
+  const SBool  s1677 = s1675 || s1676;
+  const SWord8 s1678 = (s1674 >> 1) | (s1674 << 7);
+  const SWord8 s1679 = 128 | s1678;
+  const SWord8 s1680 = 127 & s1678;
+  const SWord8 s1681 = s1677 ? s1679 : s1680;
+  const SWord8 s1682 = s1589 ? s1673 : s1681;
+  const SWord8 s1683 = s1570 ? s1661 : s1682;
+  const SWord8 s1684 = s1548 ? s1636 : s1683;
+  const SWord8 s1685 = s1 + s1574;
+  const SBool  s1686 = (SBool) (s1685 & 1);
+  const SBool  s1687 = false != s1686;
+  const SWord8 s1688 = s1687 ? s1578 : s1579;
+  const SBool  s1689 = (SBool) (s1688 & 1);
+  const SBool  s1690 = false != s1689;
+  const SWord8 s1691 = s1690 ? s1584 : s1585;
+  const SBool  s1692 = (SBool) (s1691 & 1);
+  const SBool  s1693 = false != s1692;
+  const SBool  s1694 = !s1693;
+  const SBool  s1695 = s1685 < s1;
+  const SBool  s1696 = s1685 < s1574;
+  const SBool  s1697 = s1695 || s1696;
+  const SWord8 s1698 = (s1685 >> 1) | (s1685 << 7);
+  const SWord8 s1699 = 128 | s1698;
+  const SWord8 s1700 = 127 & s1698;
+  const SWord8 s1701 = s1697 ? s1699 : s1700;
+  const SWord8 s1702 = (s1701 >> 1) | (s1701 << 7);
+  const SWord8 s1703 = 128 | s1702;
+  const SWord8 s1704 = 127 & s1702;
+  const SWord8 s1705 = s1547 ? s1703 : s1704;
+  const SWord8 s1706 = (s1705 >> 1) | (s1705 << 7);
+  const SWord8 s1707 = 128 | s1706;
+  const SWord8 s1708 = 127 & s1706;
+  const SWord8 s1709 = s1569 ? s1707 : s1708;
+  const SWord8 s1710 = (s1709 >> 1) | (s1709 << 7);
+  const SWord8 s1711 = 128 | s1710;
+  const SWord8 s1712 = 127 & s1710;
+  const SWord8 s1713 = s1693 ? s1711 : s1712;
+  const SWord8 s1714 = s1 + s1709;
+  const SBool  s1715 = s1714 < s1;
+  const SBool  s1716 = s1714 < s1709;
+  const SBool  s1717 = s1715 || s1716;
+  const SWord8 s1718 = (s1714 >> 1) | (s1714 << 7);
+  const SWord8 s1719 = 128 | s1718;
+  const SWord8 s1720 = 127 & s1718;
+  const SWord8 s1721 = s1717 ? s1719 : s1720;
+  const SWord8 s1722 = s1694 ? s1713 : s1721;
+  const SWord8 s1723 = s1 + s1705;
+  const SBool  s1724 = s1723 < s1;
+  const SBool  s1725 = s1723 < s1705;
+  const SBool  s1726 = s1724 || s1725;
+  const SWord8 s1727 = (s1723 >> 1) | (s1723 << 7);
+  const SWord8 s1728 = 128 | s1727;
+  const SWord8 s1729 = 127 & s1727;
+  const SWord8 s1730 = s1726 ? s1728 : s1729;
+  const SWord8 s1731 = (s1730 >> 1) | (s1730 << 7);
+  const SWord8 s1732 = 128 | s1731;
+  const SWord8 s1733 = 127 & s1731;
+  const SWord8 s1734 = s1693 ? s1732 : s1733;
+  const SWord8 s1735 = s1 + s1730;
+  const SBool  s1736 = s1735 < s1;
+  const SBool  s1737 = s1735 < s1730;
+  const SBool  s1738 = s1736 || s1737;
+  const SWord8 s1739 = (s1735 >> 1) | (s1735 << 7);
+  const SWord8 s1740 = 128 | s1739;
+  const SWord8 s1741 = 127 & s1739;
+  const SWord8 s1742 = s1738 ? s1740 : s1741;
+  const SWord8 s1743 = s1694 ? s1734 : s1742;
+  const SWord8 s1744 = s1570 ? s1722 : s1743;
+  const SWord8 s1745 = s1 + s1701;
+  const SBool  s1746 = s1745 < s1;
+  const SBool  s1747 = s1745 < s1701;
+  const SBool  s1748 = s1746 || s1747;
+  const SWord8 s1749 = (s1745 >> 1) | (s1745 << 7);
+  const SWord8 s1750 = 128 | s1749;
+  const SWord8 s1751 = 127 & s1749;
+  const SWord8 s1752 = s1748 ? s1750 : s1751;
+  const SWord8 s1753 = (s1752 >> 1) | (s1752 << 7);
+  const SWord8 s1754 = 128 | s1753;
+  const SWord8 s1755 = 127 & s1753;
+  const SWord8 s1756 = s1569 ? s1754 : s1755;
+  const SWord8 s1757 = (s1756 >> 1) | (s1756 << 7);
+  const SWord8 s1758 = 128 | s1757;
+  const SWord8 s1759 = 127 & s1757;
+  const SWord8 s1760 = s1693 ? s1758 : s1759;
+  const SWord8 s1761 = s1 + s1756;
+  const SBool  s1762 = s1761 < s1;
+  const SBool  s1763 = s1761 < s1756;
+  const SBool  s1764 = s1762 || s1763;
+  const SWord8 s1765 = (s1761 >> 1) | (s1761 << 7);
+  const SWord8 s1766 = 128 | s1765;
+  const SWord8 s1767 = 127 & s1765;
+  const SWord8 s1768 = s1764 ? s1766 : s1767;
+  const SWord8 s1769 = s1694 ? s1760 : s1768;
+  const SWord8 s1770 = s1 + s1752;
+  const SBool  s1771 = s1770 < s1;
+  const SBool  s1772 = s1770 < s1752;
+  const SBool  s1773 = s1771 || s1772;
+  const SWord8 s1774 = (s1770 >> 1) | (s1770 << 7);
+  const SWord8 s1775 = 128 | s1774;
+  const SWord8 s1776 = 127 & s1774;
+  const SWord8 s1777 = s1773 ? s1775 : s1776;
+  const SWord8 s1778 = (s1777 >> 1) | (s1777 << 7);
+  const SWord8 s1779 = 128 | s1778;
+  const SWord8 s1780 = 127 & s1778;
+  const SWord8 s1781 = s1693 ? s1779 : s1780;
+  const SWord8 s1782 = s1 + s1777;
+  const SBool  s1783 = s1782 < s1;
+  const SBool  s1784 = s1782 < s1777;
+  const SBool  s1785 = s1783 || s1784;
+  const SWord8 s1786 = (s1782 >> 1) | (s1782 << 7);
+  const SWord8 s1787 = 128 | s1786;
+  const SWord8 s1788 = 127 & s1786;
+  const SWord8 s1789 = s1785 ? s1787 : s1788;
+  const SWord8 s1790 = s1694 ? s1781 : s1789;
+  const SWord8 s1791 = s1570 ? s1769 : s1790;
+  const SWord8 s1792 = s1548 ? s1744 : s1791;
+  const SWord8 s1793 = s1037 ? s1684 : s1792;
+  const SWord8 s1794 = s1 + s1555;
+  const SBool  s1795 = (SBool) (s1794 & 1);
+  const SBool  s1796 = false != s1795;
+  const SWord8 s1797 = s1796 ? s1559 : s1560;
+  const SBool  s1798 = (SBool) (s1797 & 1);
+  const SBool  s1799 = false != s1798;
+  const SWord8 s1800 = s1799 ? s1565 : s1566;
+  const SBool  s1801 = (SBool) (s1800 & 1);
+  const SBool  s1802 = false != s1801;
+  const SBool  s1803 = !s1802;
+  const SBool  s1804 = s1794 < s1;
+  const SBool  s1805 = s1794 < s1555;
+  const SBool  s1806 = s1804 || s1805;
+  const SWord8 s1807 = (s1794 >> 1) | (s1794 << 7);
+  const SWord8 s1808 = 128 | s1807;
+  const SWord8 s1809 = 127 & s1807;
+  const SWord8 s1810 = s1806 ? s1808 : s1809;
+  const SBool  s1811 = (SBool) (s1810 & 1);
+  const SBool  s1812 = false != s1811;
+  const SWord8 s1813 = (s1797 >> 1) | (s1797 << 7);
+  const SWord8 s1814 = 128 | s1813;
+  const SWord8 s1815 = 127 & s1813;
+  const SWord8 s1816 = s1812 ? s1814 : s1815;
+  const SBool  s1817 = (SBool) (s1816 & 1);
+  const SBool  s1818 = false != s1817;
+  const SWord8 s1819 = (s1800 >> 1) | (s1800 << 7);
+  const SWord8 s1820 = 128 | s1819;
+  const SWord8 s1821 = 127 & s1819;
+  const SWord8 s1822 = s1818 ? s1820 : s1821;
+  const SBool  s1823 = (SBool) (s1822 & 1);
+  const SBool  s1824 = false != s1823;
+  const SBool  s1825 = !s1824;
+  const SWord8 s1826 = (s1810 >> 1) | (s1810 << 7);
+  const SWord8 s1827 = 128 | s1826;
+  const SWord8 s1828 = 127 & s1826;
+  const SWord8 s1829 = s1036 ? s1827 : s1828;
+  const SWord8 s1830 = (s1829 >> 1) | (s1829 << 7);
+  const SWord8 s1831 = 128 | s1830;
+  const SWord8 s1832 = 127 & s1830;
+  const SWord8 s1833 = s1547 ? s1831 : s1832;
+  const SWord8 s1834 = (s1833 >> 1) | (s1833 << 7);
+  const SWord8 s1835 = 128 | s1834;
+  const SWord8 s1836 = 127 & s1834;
+  const SWord8 s1837 = s1802 ? s1835 : s1836;
+  const SWord8 s1838 = (s1837 >> 1) | (s1837 << 7);
+  const SWord8 s1839 = 128 | s1838;
+  const SWord8 s1840 = 127 & s1838;
+  const SWord8 s1841 = s1824 ? s1839 : s1840;
+  const SWord8 s1842 = s1 + s1837;
+  const SBool  s1843 = s1842 < s1;
+  const SBool  s1844 = s1842 < s1837;
+  const SBool  s1845 = s1843 || s1844;
+  const SWord8 s1846 = (s1842 >> 1) | (s1842 << 7);
+  const SWord8 s1847 = 128 | s1846;
+  const SWord8 s1848 = 127 & s1846;
+  const SWord8 s1849 = s1845 ? s1847 : s1848;
+  const SWord8 s1850 = s1825 ? s1841 : s1849;
+  const SWord8 s1851 = s1 + s1833;
+  const SBool  s1852 = s1851 < s1;
+  const SBool  s1853 = s1851 < s1833;
+  const SBool  s1854 = s1852 || s1853;
+  const SWord8 s1855 = (s1851 >> 1) | (s1851 << 7);
+  const SWord8 s1856 = 128 | s1855;
+  const SWord8 s1857 = 127 & s1855;
+  const SWord8 s1858 = s1854 ? s1856 : s1857;
+  const SWord8 s1859 = (s1858 >> 1) | (s1858 << 7);
+  const SWord8 s1860 = 128 | s1859;
+  const SWord8 s1861 = 127 & s1859;
+  const SWord8 s1862 = s1824 ? s1860 : s1861;
+  const SWord8 s1863 = s1 + s1858;
+  const SBool  s1864 = s1863 < s1;
+  const SBool  s1865 = s1863 < s1858;
+  const SBool  s1866 = s1864 || s1865;
+  const SWord8 s1867 = (s1863 >> 1) | (s1863 << 7);
+  const SWord8 s1868 = 128 | s1867;
+  const SWord8 s1869 = 127 & s1867;
+  const SWord8 s1870 = s1866 ? s1868 : s1869;
+  const SWord8 s1871 = s1825 ? s1862 : s1870;
+  const SWord8 s1872 = s1803 ? s1850 : s1871;
+  const SWord8 s1873 = s1 + s1829;
+  const SBool  s1874 = s1873 < s1;
+  const SBool  s1875 = s1873 < s1829;
+  const SBool  s1876 = s1874 || s1875;
+  const SWord8 s1877 = (s1873 >> 1) | (s1873 << 7);
+  const SWord8 s1878 = 128 | s1877;
+  const SWord8 s1879 = 127 & s1877;
+  const SWord8 s1880 = s1876 ? s1878 : s1879;
+  const SWord8 s1881 = (s1880 >> 1) | (s1880 << 7);
+  const SWord8 s1882 = 128 | s1881;
+  const SWord8 s1883 = 127 & s1881;
+  const SWord8 s1884 = s1802 ? s1882 : s1883;
+  const SWord8 s1885 = (s1884 >> 1) | (s1884 << 7);
+  const SWord8 s1886 = 128 | s1885;
+  const SWord8 s1887 = 127 & s1885;
+  const SWord8 s1888 = s1824 ? s1886 : s1887;
+  const SWord8 s1889 = s1 + s1884;
+  const SBool  s1890 = s1889 < s1;
+  const SBool  s1891 = s1889 < s1884;
+  const SBool  s1892 = s1890 || s1891;
+  const SWord8 s1893 = (s1889 >> 1) | (s1889 << 7);
+  const SWord8 s1894 = 128 | s1893;
+  const SWord8 s1895 = 127 & s1893;
+  const SWord8 s1896 = s1892 ? s1894 : s1895;
+  const SWord8 s1897 = s1825 ? s1888 : s1896;
+  const SWord8 s1898 = s1 + s1880;
+  const SBool  s1899 = s1898 < s1;
+  const SBool  s1900 = s1898 < s1880;
+  const SBool  s1901 = s1899 || s1900;
+  const SWord8 s1902 = (s1898 >> 1) | (s1898 << 7);
+  const SWord8 s1903 = 128 | s1902;
+  const SWord8 s1904 = 127 & s1902;
+  const SWord8 s1905 = s1901 ? s1903 : s1904;
+  const SWord8 s1906 = (s1905 >> 1) | (s1905 << 7);
+  const SWord8 s1907 = 128 | s1906;
+  const SWord8 s1908 = 127 & s1906;
+  const SWord8 s1909 = s1824 ? s1907 : s1908;
+  const SWord8 s1910 = s1 + s1905;
+  const SBool  s1911 = s1910 < s1;
+  const SBool  s1912 = s1910 < s1905;
+  const SBool  s1913 = s1911 || s1912;
+  const SWord8 s1914 = (s1910 >> 1) | (s1910 << 7);
+  const SWord8 s1915 = 128 | s1914;
+  const SWord8 s1916 = 127 & s1914;
+  const SWord8 s1917 = s1913 ? s1915 : s1916;
+  const SWord8 s1918 = s1825 ? s1909 : s1917;
+  const SWord8 s1919 = s1803 ? s1897 : s1918;
+  const SWord8 s1920 = s1548 ? s1872 : s1919;
+  const SWord8 s1921 = s1 + s1810;
+  const SBool  s1922 = (SBool) (s1921 & 1);
+  const SBool  s1923 = false != s1922;
+  const SWord8 s1924 = s1923 ? s1814 : s1815;
+  const SBool  s1925 = (SBool) (s1924 & 1);
+  const SBool  s1926 = false != s1925;
+  const SWord8 s1927 = s1926 ? s1820 : s1821;
+  const SBool  s1928 = (SBool) (s1927 & 1);
+  const SBool  s1929 = false != s1928;
+  const SBool  s1930 = !s1929;
+  const SBool  s1931 = s1921 < s1;
+  const SBool  s1932 = s1921 < s1810;
+  const SBool  s1933 = s1931 || s1932;
+  const SWord8 s1934 = (s1921 >> 1) | (s1921 << 7);
+  const SWord8 s1935 = 128 | s1934;
+  const SWord8 s1936 = 127 & s1934;
+  const SWord8 s1937 = s1933 ? s1935 : s1936;
+  const SWord8 s1938 = (s1937 >> 1) | (s1937 << 7);
+  const SWord8 s1939 = 128 | s1938;
+  const SWord8 s1940 = 127 & s1938;
+  const SWord8 s1941 = s1547 ? s1939 : s1940;
+  const SWord8 s1942 = (s1941 >> 1) | (s1941 << 7);
+  const SWord8 s1943 = 128 | s1942;
+  const SWord8 s1944 = 127 & s1942;
+  const SWord8 s1945 = s1802 ? s1943 : s1944;
+  const SWord8 s1946 = (s1945 >> 1) | (s1945 << 7);
+  const SWord8 s1947 = 128 | s1946;
+  const SWord8 s1948 = 127 & s1946;
+  const SWord8 s1949 = s1929 ? s1947 : s1948;
+  const SWord8 s1950 = s1 + s1945;
+  const SBool  s1951 = s1950 < s1;
+  const SBool  s1952 = s1950 < s1945;
+  const SBool  s1953 = s1951 || s1952;
+  const SWord8 s1954 = (s1950 >> 1) | (s1950 << 7);
+  const SWord8 s1955 = 128 | s1954;
+  const SWord8 s1956 = 127 & s1954;
+  const SWord8 s1957 = s1953 ? s1955 : s1956;
+  const SWord8 s1958 = s1930 ? s1949 : s1957;
+  const SWord8 s1959 = s1 + s1941;
+  const SBool  s1960 = s1959 < s1;
+  const SBool  s1961 = s1959 < s1941;
+  const SBool  s1962 = s1960 || s1961;
+  const SWord8 s1963 = (s1959 >> 1) | (s1959 << 7);
+  const SWord8 s1964 = 128 | s1963;
+  const SWord8 s1965 = 127 & s1963;
+  const SWord8 s1966 = s1962 ? s1964 : s1965;
+  const SWord8 s1967 = (s1966 >> 1) | (s1966 << 7);
+  const SWord8 s1968 = 128 | s1967;
+  const SWord8 s1969 = 127 & s1967;
+  const SWord8 s1970 = s1929 ? s1968 : s1969;
+  const SWord8 s1971 = s1 + s1966;
+  const SBool  s1972 = s1971 < s1;
+  const SBool  s1973 = s1971 < s1966;
+  const SBool  s1974 = s1972 || s1973;
+  const SWord8 s1975 = (s1971 >> 1) | (s1971 << 7);
+  const SWord8 s1976 = 128 | s1975;
+  const SWord8 s1977 = 127 & s1975;
+  const SWord8 s1978 = s1974 ? s1976 : s1977;
+  const SWord8 s1979 = s1930 ? s1970 : s1978;
+  const SWord8 s1980 = s1803 ? s1958 : s1979;
+  const SWord8 s1981 = s1 + s1937;
+  const SBool  s1982 = s1981 < s1;
+  const SBool  s1983 = s1981 < s1937;
+  const SBool  s1984 = s1982 || s1983;
+  const SWord8 s1985 = (s1981 >> 1) | (s1981 << 7);
+  const SWord8 s1986 = 128 | s1985;
+  const SWord8 s1987 = 127 & s1985;
+  const SWord8 s1988 = s1984 ? s1986 : s1987;
+  const SWord8 s1989 = (s1988 >> 1) | (s1988 << 7);
+  const SWord8 s1990 = 128 | s1989;
+  const SWord8 s1991 = 127 & s1989;
+  const SWord8 s1992 = s1802 ? s1990 : s1991;
+  const SWord8 s1993 = (s1992 >> 1) | (s1992 << 7);
+  const SWord8 s1994 = 128 | s1993;
+  const SWord8 s1995 = 127 & s1993;
+  const SWord8 s1996 = s1929 ? s1994 : s1995;
+  const SWord8 s1997 = s1 + s1992;
+  const SBool  s1998 = s1997 < s1;
+  const SBool  s1999 = s1997 < s1992;
+  const SBool  s2000 = s1998 || s1999;
+  const SWord8 s2001 = (s1997 >> 1) | (s1997 << 7);
+  const SWord8 s2002 = 128 | s2001;
+  const SWord8 s2003 = 127 & s2001;
+  const SWord8 s2004 = s2000 ? s2002 : s2003;
+  const SWord8 s2005 = s1930 ? s1996 : s2004;
+  const SWord8 s2006 = s1 + s1988;
+  const SBool  s2007 = s2006 < s1;
+  const SBool  s2008 = s2006 < s1988;
+  const SBool  s2009 = s2007 || s2008;
+  const SWord8 s2010 = (s2006 >> 1) | (s2006 << 7);
+  const SWord8 s2011 = 128 | s2010;
+  const SWord8 s2012 = 127 & s2010;
+  const SWord8 s2013 = s2009 ? s2011 : s2012;
+  const SWord8 s2014 = (s2013 >> 1) | (s2013 << 7);
+  const SWord8 s2015 = 128 | s2014;
+  const SWord8 s2016 = 127 & s2014;
+  const SWord8 s2017 = s1929 ? s2015 : s2016;
+  const SWord8 s2018 = s1 + s2013;
+  const SBool  s2019 = s2018 < s1;
+  const SBool  s2020 = s2018 < s2013;
+  const SBool  s2021 = s2019 || s2020;
+  const SWord8 s2022 = (s2018 >> 1) | (s2018 << 7);
+  const SWord8 s2023 = 128 | s2022;
+  const SWord8 s2024 = 127 & s2022;
+  const SWord8 s2025 = s2021 ? s2023 : s2024;
+  const SWord8 s2026 = s1930 ? s2017 : s2025;
+  const SWord8 s2027 = s1803 ? s2005 : s2026;
+  const SWord8 s2028 = s1548 ? s1980 : s2027;
+  const SWord8 s2029 = s1037 ? s1920 : s2028;
+  const SWord8 s2030 = s21 ? s1793 : s2029;
+  const SWord8 s2031 = s16 ? s1538 : s2030;
+  const SWord8 s2032 = s11 ? s1027 : s2031;
+  const SBool  s2033 = (SBool) (s1 & 1);
+  const SBool  s2034 = false != s2033;
+  const SWord8 s2035 = s2034 ? 128 : 0;
+  const SBool  s2036 = (SBool) (s2035 & 1);
+  const SBool  s2037 = false != s2036;
+  const SWord8 s2038 = s17 | 128;
+  const SWord8 s2039 = s2037 ? s2038 : s18;
+  const SBool  s2040 = (SBool) (s2039 & 1);
+  const SBool  s2041 = false != s2040;
+  const SBool  s2042 = !s2041;
+  const SWord8 s2043 = (s1 >> 1) | (s1 << 7);
+  const SWord8 s2044 = 127 & s2043;
+  const SBool  s2045 = (SBool) (s2044 & 1);
+  const SBool  s2046 = false != s2045;
+  const SWord8 s2047 = (s2035 >> 1) | (s2035 << 7);
+  const SWord8 s2048 = 128 | s2047;
+  const SWord8 s2049 = 127 & s2047;
+  const SWord8 s2050 = s2046 ? s2048 : s2049;
+  const SBool  s2051 = (SBool) (s2050 & 1);
+  const SBool  s2052 = false != s2051;
+  const SWord8 s2053 = (s2039 >> 1) | (s2039 << 7);
+  const SWord8 s2054 = 128 | s2053;
+  const SWord8 s2055 = 127 & s2053;
+  const SWord8 s2056 = s2052 ? s2054 : s2055;
+  const SBool  s2057 = (SBool) (s2056 & 1);
+  const SBool  s2058 = false != s2057;
+  const SBool  s2059 = !s2058;
+  const SWord8 s2060 = (s2044 >> 1) | (s2044 << 7);
+  const SWord8 s2061 = 128 | s2060;
+  const SWord8 s2062 = 127 & s2060;
+  const SWord8 s2063 = s10 ? s2061 : s2062;
+  const SBool  s2064 = (SBool) (s2063 & 1);
+  const SBool  s2065 = false != s2064;
+  const SWord8 s2066 = (s2050 >> 1) | (s2050 << 7);
+  const SWord8 s2067 = 128 | s2066;
+  const SWord8 s2068 = 127 & s2066;
+  const SWord8 s2069 = s2065 ? s2067 : s2068;
+  const SBool  s2070 = (SBool) (s2069 & 1);
+  const SBool  s2071 = false != s2070;
+  const SWord8 s2072 = (s2056 >> 1) | (s2056 << 7);
+  const SWord8 s2073 = 128 | s2072;
+  const SWord8 s2074 = 127 & s2072;
+  const SWord8 s2075 = s2071 ? s2073 : s2074;
+  const SBool  s2076 = (SBool) (s2075 & 1);
+  const SBool  s2077 = false != s2076;
+  const SBool  s2078 = !s2077;
+  const SWord8 s2079 = (s2063 >> 1) | (s2063 << 7);
+  const SWord8 s2080 = 128 | s2079;
+  const SWord8 s2081 = 127 & s2079;
+  const SWord8 s2082 = s15 ? s2080 : s2081;
+  const SBool  s2083 = (SBool) (s2082 & 1);
+  const SBool  s2084 = false != s2083;
+  const SWord8 s2085 = (s2069 >> 1) | (s2069 << 7);
+  const SWord8 s2086 = 128 | s2085;
+  const SWord8 s2087 = 127 & s2085;
+  const SWord8 s2088 = s2084 ? s2086 : s2087;
+  const SBool  s2089 = (SBool) (s2088 & 1);
+  const SBool  s2090 = false != s2089;
+  const SWord8 s2091 = (s2075 >> 1) | (s2075 << 7);
+  const SWord8 s2092 = 128 | s2091;
+  const SWord8 s2093 = 127 & s2091;
+  const SWord8 s2094 = s2090 ? s2092 : s2093;
+  const SBool  s2095 = (SBool) (s2094 & 1);
+  const SBool  s2096 = false != s2095;
+  const SBool  s2097 = !s2096;
+  const SWord8 s2098 = (s2082 >> 1) | (s2082 << 7);
+  const SWord8 s2099 = 128 | s2098;
+  const SWord8 s2100 = 127 & s2098;
+  const SWord8 s2101 = s2041 ? s2099 : s2100;
+  const SBool  s2102 = (SBool) (s2101 & 1);
+  const SBool  s2103 = false != s2102;
+  const SWord8 s2104 = (s2088 >> 1) | (s2088 << 7);
+  const SWord8 s2105 = 128 | s2104;
+  const SWord8 s2106 = 127 & s2104;
+  const SWord8 s2107 = s2103 ? s2105 : s2106;
+  const SBool  s2108 = (SBool) (s2107 & 1);
+  const SBool  s2109 = false != s2108;
+  const SWord8 s2110 = (s2094 >> 1) | (s2094 << 7);
+  const SWord8 s2111 = 128 | s2110;
+  const SWord8 s2112 = 127 & s2110;
+  const SWord8 s2113 = s2109 ? s2111 : s2112;
+  const SBool  s2114 = (SBool) (s2113 & 1);
+  const SBool  s2115 = false != s2114;
+  const SBool  s2116 = !s2115;
+  const SWord8 s2117 = (s2101 >> 1) | (s2101 << 7);
+  const SWord8 s2118 = 128 | s2117;
+  const SWord8 s2119 = 127 & s2117;
+  const SWord8 s2120 = s2058 ? s2118 : s2119;
+  const SWord8 s2121 = (s2120 >> 1) | (s2120 << 7);
+  const SWord8 s2122 = 128 | s2121;
+  const SWord8 s2123 = 127 & s2121;
+  const SWord8 s2124 = s2077 ? s2122 : s2123;
+  const SWord8 s2125 = (s2124 >> 1) | (s2124 << 7);
+  const SWord8 s2126 = 128 | s2125;
+  const SWord8 s2127 = 127 & s2125;
+  const SWord8 s2128 = s2096 ? s2126 : s2127;
+  const SWord8 s2129 = (s2128 >> 1) | (s2128 << 7);
+  const SWord8 s2130 = 128 | s2129;
+  const SWord8 s2131 = 127 & s2129;
+  const SWord8 s2132 = s2115 ? s2130 : s2131;
+  const SWord8 s2133 = s1 + s2128;
+  const SBool  s2134 = s2133 < s1;
+  const SBool  s2135 = s2133 < s2128;
+  const SBool  s2136 = s2134 || s2135;
+  const SWord8 s2137 = (s2133 >> 1) | (s2133 << 7);
+  const SWord8 s2138 = 128 | s2137;
+  const SWord8 s2139 = 127 & s2137;
+  const SWord8 s2140 = s2136 ? s2138 : s2139;
+  const SWord8 s2141 = s2116 ? s2132 : s2140;
+  const SWord8 s2142 = s1 + s2124;
+  const SBool  s2143 = s2142 < s1;
+  const SBool  s2144 = s2142 < s2124;
+  const SBool  s2145 = s2143 || s2144;
+  const SWord8 s2146 = (s2142 >> 1) | (s2142 << 7);
+  const SWord8 s2147 = 128 | s2146;
+  const SWord8 s2148 = 127 & s2146;
+  const SWord8 s2149 = s2145 ? s2147 : s2148;
+  const SWord8 s2150 = (s2149 >> 1) | (s2149 << 7);
+  const SWord8 s2151 = 128 | s2150;
+  const SWord8 s2152 = 127 & s2150;
+  const SWord8 s2153 = s2115 ? s2151 : s2152;
+  const SWord8 s2154 = s1 + s2149;
+  const SBool  s2155 = s2154 < s1;
+  const SBool  s2156 = s2154 < s2149;
+  const SBool  s2157 = s2155 || s2156;
+  const SWord8 s2158 = (s2154 >> 1) | (s2154 << 7);
+  const SWord8 s2159 = 128 | s2158;
+  const SWord8 s2160 = 127 & s2158;
+  const SWord8 s2161 = s2157 ? s2159 : s2160;
+  const SWord8 s2162 = s2116 ? s2153 : s2161;
+  const SWord8 s2163 = s2097 ? s2141 : s2162;
+  const SWord8 s2164 = s1 + s2120;
+  const SBool  s2165 = s2164 < s1;
+  const SBool  s2166 = s2164 < s2120;
+  const SBool  s2167 = s2165 || s2166;
+  const SWord8 s2168 = (s2164 >> 1) | (s2164 << 7);
+  const SWord8 s2169 = 128 | s2168;
+  const SWord8 s2170 = 127 & s2168;
+  const SWord8 s2171 = s2167 ? s2169 : s2170;
+  const SWord8 s2172 = (s2171 >> 1) | (s2171 << 7);
+  const SWord8 s2173 = 128 | s2172;
+  const SWord8 s2174 = 127 & s2172;
+  const SWord8 s2175 = s2096 ? s2173 : s2174;
+  const SWord8 s2176 = (s2175 >> 1) | (s2175 << 7);
+  const SWord8 s2177 = 128 | s2176;
+  const SWord8 s2178 = 127 & s2176;
+  const SWord8 s2179 = s2115 ? s2177 : s2178;
+  const SWord8 s2180 = s1 + s2175;
+  const SBool  s2181 = s2180 < s1;
+  const SBool  s2182 = s2180 < s2175;
+  const SBool  s2183 = s2181 || s2182;
+  const SWord8 s2184 = (s2180 >> 1) | (s2180 << 7);
+  const SWord8 s2185 = 128 | s2184;
+  const SWord8 s2186 = 127 & s2184;
+  const SWord8 s2187 = s2183 ? s2185 : s2186;
+  const SWord8 s2188 = s2116 ? s2179 : s2187;
+  const SWord8 s2189 = s1 + s2171;
+  const SBool  s2190 = s2189 < s1;
+  const SBool  s2191 = s2189 < s2171;
+  const SBool  s2192 = s2190 || s2191;
+  const SWord8 s2193 = (s2189 >> 1) | (s2189 << 7);
+  const SWord8 s2194 = 128 | s2193;
+  const SWord8 s2195 = 127 & s2193;
+  const SWord8 s2196 = s2192 ? s2194 : s2195;
+  const SWord8 s2197 = (s2196 >> 1) | (s2196 << 7);
+  const SWord8 s2198 = 128 | s2197;
+  const SWord8 s2199 = 127 & s2197;
+  const SWord8 s2200 = s2115 ? s2198 : s2199;
+  const SWord8 s2201 = s1 + s2196;
+  const SBool  s2202 = s2201 < s1;
+  const SBool  s2203 = s2201 < s2196;
+  const SBool  s2204 = s2202 || s2203;
+  const SWord8 s2205 = (s2201 >> 1) | (s2201 << 7);
+  const SWord8 s2206 = 128 | s2205;
+  const SWord8 s2207 = 127 & s2205;
+  const SWord8 s2208 = s2204 ? s2206 : s2207;
+  const SWord8 s2209 = s2116 ? s2200 : s2208;
+  const SWord8 s2210 = s2097 ? s2188 : s2209;
+  const SWord8 s2211 = s2078 ? s2163 : s2210;
+  const SWord8 s2212 = s1 + s2101;
+  const SBool  s2213 = (SBool) (s2212 & 1);
+  const SBool  s2214 = false != s2213;
+  const SWord8 s2215 = s2214 ? s2105 : s2106;
+  const SBool  s2216 = (SBool) (s2215 & 1);
+  const SBool  s2217 = false != s2216;
+  const SWord8 s2218 = s2217 ? s2111 : s2112;
+  const SBool  s2219 = (SBool) (s2218 & 1);
+  const SBool  s2220 = false != s2219;
+  const SBool  s2221 = !s2220;
+  const SBool  s2222 = s2212 < s1;
+  const SBool  s2223 = s2212 < s2101;
+  const SBool  s2224 = s2222 || s2223;
+  const SWord8 s2225 = (s2212 >> 1) | (s2212 << 7);
+  const SWord8 s2226 = 128 | s2225;
+  const SWord8 s2227 = 127 & s2225;
+  const SWord8 s2228 = s2224 ? s2226 : s2227;
+  const SWord8 s2229 = (s2228 >> 1) | (s2228 << 7);
+  const SWord8 s2230 = 128 | s2229;
+  const SWord8 s2231 = 127 & s2229;
+  const SWord8 s2232 = s2077 ? s2230 : s2231;
+  const SWord8 s2233 = (s2232 >> 1) | (s2232 << 7);
+  const SWord8 s2234 = 128 | s2233;
+  const SWord8 s2235 = 127 & s2233;
+  const SWord8 s2236 = s2096 ? s2234 : s2235;
+  const SWord8 s2237 = (s2236 >> 1) | (s2236 << 7);
+  const SWord8 s2238 = 128 | s2237;
+  const SWord8 s2239 = 127 & s2237;
+  const SWord8 s2240 = s2220 ? s2238 : s2239;
+  const SWord8 s2241 = s1 + s2236;
+  const SBool  s2242 = s2241 < s1;
+  const SBool  s2243 = s2241 < s2236;
+  const SBool  s2244 = s2242 || s2243;
+  const SWord8 s2245 = (s2241 >> 1) | (s2241 << 7);
+  const SWord8 s2246 = 128 | s2245;
+  const SWord8 s2247 = 127 & s2245;
+  const SWord8 s2248 = s2244 ? s2246 : s2247;
+  const SWord8 s2249 = s2221 ? s2240 : s2248;
+  const SWord8 s2250 = s1 + s2232;
+  const SBool  s2251 = s2250 < s1;
+  const SBool  s2252 = s2250 < s2232;
+  const SBool  s2253 = s2251 || s2252;
+  const SWord8 s2254 = (s2250 >> 1) | (s2250 << 7);
+  const SWord8 s2255 = 128 | s2254;
+  const SWord8 s2256 = 127 & s2254;
+  const SWord8 s2257 = s2253 ? s2255 : s2256;
+  const SWord8 s2258 = (s2257 >> 1) | (s2257 << 7);
+  const SWord8 s2259 = 128 | s2258;
+  const SWord8 s2260 = 127 & s2258;
+  const SWord8 s2261 = s2220 ? s2259 : s2260;
+  const SWord8 s2262 = s1 + s2257;
+  const SBool  s2263 = s2262 < s1;
+  const SBool  s2264 = s2262 < s2257;
+  const SBool  s2265 = s2263 || s2264;
+  const SWord8 s2266 = (s2262 >> 1) | (s2262 << 7);
+  const SWord8 s2267 = 128 | s2266;
+  const SWord8 s2268 = 127 & s2266;
+  const SWord8 s2269 = s2265 ? s2267 : s2268;
+  const SWord8 s2270 = s2221 ? s2261 : s2269;
+  const SWord8 s2271 = s2097 ? s2249 : s2270;
+  const SWord8 s2272 = s1 + s2228;
+  const SBool  s2273 = s2272 < s1;
+  const SBool  s2274 = s2272 < s2228;
+  const SBool  s2275 = s2273 || s2274;
+  const SWord8 s2276 = (s2272 >> 1) | (s2272 << 7);
+  const SWord8 s2277 = 128 | s2276;
+  const SWord8 s2278 = 127 & s2276;
+  const SWord8 s2279 = s2275 ? s2277 : s2278;
+  const SWord8 s2280 = (s2279 >> 1) | (s2279 << 7);
+  const SWord8 s2281 = 128 | s2280;
+  const SWord8 s2282 = 127 & s2280;
+  const SWord8 s2283 = s2096 ? s2281 : s2282;
+  const SWord8 s2284 = (s2283 >> 1) | (s2283 << 7);
+  const SWord8 s2285 = 128 | s2284;
+  const SWord8 s2286 = 127 & s2284;
+  const SWord8 s2287 = s2220 ? s2285 : s2286;
+  const SWord8 s2288 = s1 + s2283;
+  const SBool  s2289 = s2288 < s1;
+  const SBool  s2290 = s2288 < s2283;
+  const SBool  s2291 = s2289 || s2290;
+  const SWord8 s2292 = (s2288 >> 1) | (s2288 << 7);
+  const SWord8 s2293 = 128 | s2292;
+  const SWord8 s2294 = 127 & s2292;
+  const SWord8 s2295 = s2291 ? s2293 : s2294;
+  const SWord8 s2296 = s2221 ? s2287 : s2295;
+  const SWord8 s2297 = s1 + s2279;
+  const SBool  s2298 = s2297 < s1;
+  const SBool  s2299 = s2297 < s2279;
+  const SBool  s2300 = s2298 || s2299;
+  const SWord8 s2301 = (s2297 >> 1) | (s2297 << 7);
+  const SWord8 s2302 = 128 | s2301;
+  const SWord8 s2303 = 127 & s2301;
+  const SWord8 s2304 = s2300 ? s2302 : s2303;
+  const SWord8 s2305 = (s2304 >> 1) | (s2304 << 7);
+  const SWord8 s2306 = 128 | s2305;
+  const SWord8 s2307 = 127 & s2305;
+  const SWord8 s2308 = s2220 ? s2306 : s2307;
+  const SWord8 s2309 = s1 + s2304;
+  const SBool  s2310 = s2309 < s1;
+  const SBool  s2311 = s2309 < s2304;
+  const SBool  s2312 = s2310 || s2311;
+  const SWord8 s2313 = (s2309 >> 1) | (s2309 << 7);
+  const SWord8 s2314 = 128 | s2313;
+  const SWord8 s2315 = 127 & s2313;
+  const SWord8 s2316 = s2312 ? s2314 : s2315;
+  const SWord8 s2317 = s2221 ? s2308 : s2316;
+  const SWord8 s2318 = s2097 ? s2296 : s2317;
+  const SWord8 s2319 = s2078 ? s2271 : s2318;
+  const SWord8 s2320 = s2059 ? s2211 : s2319;
+  const SWord8 s2321 = s1 + s2082;
+  const SBool  s2322 = (SBool) (s2321 & 1);
+  const SBool  s2323 = false != s2322;
+  const SWord8 s2324 = s2323 ? s2086 : s2087;
+  const SBool  s2325 = (SBool) (s2324 & 1);
+  const SBool  s2326 = false != s2325;
+  const SWord8 s2327 = s2326 ? s2092 : s2093;
+  const SBool  s2328 = (SBool) (s2327 & 1);
+  const SBool  s2329 = false != s2328;
+  const SBool  s2330 = !s2329;
+  const SBool  s2331 = s2321 < s1;
+  const SBool  s2332 = s2321 < s2082;
+  const SBool  s2333 = s2331 || s2332;
+  const SWord8 s2334 = (s2321 >> 1) | (s2321 << 7);
+  const SWord8 s2335 = 128 | s2334;
+  const SWord8 s2336 = 127 & s2334;
+  const SWord8 s2337 = s2333 ? s2335 : s2336;
+  const SBool  s2338 = (SBool) (s2337 & 1);
+  const SBool  s2339 = false != s2338;
+  const SWord8 s2340 = (s2324 >> 1) | (s2324 << 7);
+  const SWord8 s2341 = 128 | s2340;
+  const SWord8 s2342 = 127 & s2340;
+  const SWord8 s2343 = s2339 ? s2341 : s2342;
+  const SBool  s2344 = (SBool) (s2343 & 1);
+  const SBool  s2345 = false != s2344;
+  const SWord8 s2346 = (s2327 >> 1) | (s2327 << 7);
+  const SWord8 s2347 = 128 | s2346;
+  const SWord8 s2348 = 127 & s2346;
+  const SWord8 s2349 = s2345 ? s2347 : s2348;
+  const SBool  s2350 = (SBool) (s2349 & 1);
+  const SBool  s2351 = false != s2350;
+  const SBool  s2352 = !s2351;
+  const SWord8 s2353 = (s2337 >> 1) | (s2337 << 7);
+  const SWord8 s2354 = 128 | s2353;
+  const SWord8 s2355 = 127 & s2353;
+  const SWord8 s2356 = s2058 ? s2354 : s2355;
+  const SWord8 s2357 = (s2356 >> 1) | (s2356 << 7);
+  const SWord8 s2358 = 128 | s2357;
+  const SWord8 s2359 = 127 & s2357;
+  const SWord8 s2360 = s2077 ? s2358 : s2359;
+  const SWord8 s2361 = (s2360 >> 1) | (s2360 << 7);
+  const SWord8 s2362 = 128 | s2361;
+  const SWord8 s2363 = 127 & s2361;
+  const SWord8 s2364 = s2329 ? s2362 : s2363;
+  const SWord8 s2365 = (s2364 >> 1) | (s2364 << 7);
+  const SWord8 s2366 = 128 | s2365;
+  const SWord8 s2367 = 127 & s2365;
+  const SWord8 s2368 = s2351 ? s2366 : s2367;
+  const SWord8 s2369 = s1 + s2364;
+  const SBool  s2370 = s2369 < s1;
+  const SBool  s2371 = s2369 < s2364;
+  const SBool  s2372 = s2370 || s2371;
+  const SWord8 s2373 = (s2369 >> 1) | (s2369 << 7);
+  const SWord8 s2374 = 128 | s2373;
+  const SWord8 s2375 = 127 & s2373;
+  const SWord8 s2376 = s2372 ? s2374 : s2375;
+  const SWord8 s2377 = s2352 ? s2368 : s2376;
+  const SWord8 s2378 = s1 + s2360;
+  const SBool  s2379 = s2378 < s1;
+  const SBool  s2380 = s2378 < s2360;
+  const SBool  s2381 = s2379 || s2380;
+  const SWord8 s2382 = (s2378 >> 1) | (s2378 << 7);
+  const SWord8 s2383 = 128 | s2382;
+  const SWord8 s2384 = 127 & s2382;
+  const SWord8 s2385 = s2381 ? s2383 : s2384;
+  const SWord8 s2386 = (s2385 >> 1) | (s2385 << 7);
+  const SWord8 s2387 = 128 | s2386;
+  const SWord8 s2388 = 127 & s2386;
+  const SWord8 s2389 = s2351 ? s2387 : s2388;
+  const SWord8 s2390 = s1 + s2385;
+  const SBool  s2391 = s2390 < s1;
+  const SBool  s2392 = s2390 < s2385;
+  const SBool  s2393 = s2391 || s2392;
+  const SWord8 s2394 = (s2390 >> 1) | (s2390 << 7);
+  const SWord8 s2395 = 128 | s2394;
+  const SWord8 s2396 = 127 & s2394;
+  const SWord8 s2397 = s2393 ? s2395 : s2396;
+  const SWord8 s2398 = s2352 ? s2389 : s2397;
+  const SWord8 s2399 = s2330 ? s2377 : s2398;
+  const SWord8 s2400 = s1 + s2356;
+  const SBool  s2401 = s2400 < s1;
+  const SBool  s2402 = s2400 < s2356;
+  const SBool  s2403 = s2401 || s2402;
+  const SWord8 s2404 = (s2400 >> 1) | (s2400 << 7);
+  const SWord8 s2405 = 128 | s2404;
+  const SWord8 s2406 = 127 & s2404;
+  const SWord8 s2407 = s2403 ? s2405 : s2406;
+  const SWord8 s2408 = (s2407 >> 1) | (s2407 << 7);
+  const SWord8 s2409 = 128 | s2408;
+  const SWord8 s2410 = 127 & s2408;
+  const SWord8 s2411 = s2329 ? s2409 : s2410;
+  const SWord8 s2412 = (s2411 >> 1) | (s2411 << 7);
+  const SWord8 s2413 = 128 | s2412;
+  const SWord8 s2414 = 127 & s2412;
+  const SWord8 s2415 = s2351 ? s2413 : s2414;
+  const SWord8 s2416 = s1 + s2411;
+  const SBool  s2417 = s2416 < s1;
+  const SBool  s2418 = s2416 < s2411;
+  const SBool  s2419 = s2417 || s2418;
+  const SWord8 s2420 = (s2416 >> 1) | (s2416 << 7);
+  const SWord8 s2421 = 128 | s2420;
+  const SWord8 s2422 = 127 & s2420;
+  const SWord8 s2423 = s2419 ? s2421 : s2422;
+  const SWord8 s2424 = s2352 ? s2415 : s2423;
+  const SWord8 s2425 = s1 + s2407;
+  const SBool  s2426 = s2425 < s1;
+  const SBool  s2427 = s2425 < s2407;
+  const SBool  s2428 = s2426 || s2427;
+  const SWord8 s2429 = (s2425 >> 1) | (s2425 << 7);
+  const SWord8 s2430 = 128 | s2429;
+  const SWord8 s2431 = 127 & s2429;
+  const SWord8 s2432 = s2428 ? s2430 : s2431;
+  const SWord8 s2433 = (s2432 >> 1) | (s2432 << 7);
+  const SWord8 s2434 = 128 | s2433;
+  const SWord8 s2435 = 127 & s2433;
+  const SWord8 s2436 = s2351 ? s2434 : s2435;
+  const SWord8 s2437 = s1 + s2432;
+  const SBool  s2438 = s2437 < s1;
+  const SBool  s2439 = s2437 < s2432;
+  const SBool  s2440 = s2438 || s2439;
+  const SWord8 s2441 = (s2437 >> 1) | (s2437 << 7);
+  const SWord8 s2442 = 128 | s2441;
+  const SWord8 s2443 = 127 & s2441;
+  const SWord8 s2444 = s2440 ? s2442 : s2443;
+  const SWord8 s2445 = s2352 ? s2436 : s2444;
+  const SWord8 s2446 = s2330 ? s2424 : s2445;
+  const SWord8 s2447 = s2078 ? s2399 : s2446;
+  const SWord8 s2448 = s1 + s2337;
+  const SBool  s2449 = (SBool) (s2448 & 1);
+  const SBool  s2450 = false != s2449;
+  const SWord8 s2451 = s2450 ? s2341 : s2342;
+  const SBool  s2452 = (SBool) (s2451 & 1);
+  const SBool  s2453 = false != s2452;
+  const SWord8 s2454 = s2453 ? s2347 : s2348;
+  const SBool  s2455 = (SBool) (s2454 & 1);
+  const SBool  s2456 = false != s2455;
+  const SBool  s2457 = !s2456;
+  const SBool  s2458 = s2448 < s1;
+  const SBool  s2459 = s2448 < s2337;
+  const SBool  s2460 = s2458 || s2459;
+  const SWord8 s2461 = (s2448 >> 1) | (s2448 << 7);
+  const SWord8 s2462 = 128 | s2461;
+  const SWord8 s2463 = 127 & s2461;
+  const SWord8 s2464 = s2460 ? s2462 : s2463;
+  const SWord8 s2465 = (s2464 >> 1) | (s2464 << 7);
+  const SWord8 s2466 = 128 | s2465;
+  const SWord8 s2467 = 127 & s2465;
+  const SWord8 s2468 = s2077 ? s2466 : s2467;
+  const SWord8 s2469 = (s2468 >> 1) | (s2468 << 7);
+  const SWord8 s2470 = 128 | s2469;
+  const SWord8 s2471 = 127 & s2469;
+  const SWord8 s2472 = s2329 ? s2470 : s2471;
+  const SWord8 s2473 = (s2472 >> 1) | (s2472 << 7);
+  const SWord8 s2474 = 128 | s2473;
+  const SWord8 s2475 = 127 & s2473;
+  const SWord8 s2476 = s2456 ? s2474 : s2475;
+  const SWord8 s2477 = s1 + s2472;
+  const SBool  s2478 = s2477 < s1;
+  const SBool  s2479 = s2477 < s2472;
+  const SBool  s2480 = s2478 || s2479;
+  const SWord8 s2481 = (s2477 >> 1) | (s2477 << 7);
+  const SWord8 s2482 = 128 | s2481;
+  const SWord8 s2483 = 127 & s2481;
+  const SWord8 s2484 = s2480 ? s2482 : s2483;
+  const SWord8 s2485 = s2457 ? s2476 : s2484;
+  const SWord8 s2486 = s1 + s2468;
+  const SBool  s2487 = s2486 < s1;
+  const SBool  s2488 = s2486 < s2468;
+  const SBool  s2489 = s2487 || s2488;
+  const SWord8 s2490 = (s2486 >> 1) | (s2486 << 7);
+  const SWord8 s2491 = 128 | s2490;
+  const SWord8 s2492 = 127 & s2490;
+  const SWord8 s2493 = s2489 ? s2491 : s2492;
+  const SWord8 s2494 = (s2493 >> 1) | (s2493 << 7);
+  const SWord8 s2495 = 128 | s2494;
+  const SWord8 s2496 = 127 & s2494;
+  const SWord8 s2497 = s2456 ? s2495 : s2496;
+  const SWord8 s2498 = s1 + s2493;
+  const SBool  s2499 = s2498 < s1;
+  const SBool  s2500 = s2498 < s2493;
+  const SBool  s2501 = s2499 || s2500;
+  const SWord8 s2502 = (s2498 >> 1) | (s2498 << 7);
+  const SWord8 s2503 = 128 | s2502;
+  const SWord8 s2504 = 127 & s2502;
+  const SWord8 s2505 = s2501 ? s2503 : s2504;
+  const SWord8 s2506 = s2457 ? s2497 : s2505;
+  const SWord8 s2507 = s2330 ? s2485 : s2506;
+  const SWord8 s2508 = s1 + s2464;
+  const SBool  s2509 = s2508 < s1;
+  const SBool  s2510 = s2508 < s2464;
+  const SBool  s2511 = s2509 || s2510;
+  const SWord8 s2512 = (s2508 >> 1) | (s2508 << 7);
+  const SWord8 s2513 = 128 | s2512;
+  const SWord8 s2514 = 127 & s2512;
+  const SWord8 s2515 = s2511 ? s2513 : s2514;
+  const SWord8 s2516 = (s2515 >> 1) | (s2515 << 7);
+  const SWord8 s2517 = 128 | s2516;
+  const SWord8 s2518 = 127 & s2516;
+  const SWord8 s2519 = s2329 ? s2517 : s2518;
+  const SWord8 s2520 = (s2519 >> 1) | (s2519 << 7);
+  const SWord8 s2521 = 128 | s2520;
+  const SWord8 s2522 = 127 & s2520;
+  const SWord8 s2523 = s2456 ? s2521 : s2522;
+  const SWord8 s2524 = s1 + s2519;
+  const SBool  s2525 = s2524 < s1;
+  const SBool  s2526 = s2524 < s2519;
+  const SBool  s2527 = s2525 || s2526;
+  const SWord8 s2528 = (s2524 >> 1) | (s2524 << 7);
+  const SWord8 s2529 = 128 | s2528;
+  const SWord8 s2530 = 127 & s2528;
+  const SWord8 s2531 = s2527 ? s2529 : s2530;
+  const SWord8 s2532 = s2457 ? s2523 : s2531;
+  const SWord8 s2533 = s1 + s2515;
+  const SBool  s2534 = s2533 < s1;
+  const SBool  s2535 = s2533 < s2515;
+  const SBool  s2536 = s2534 || s2535;
+  const SWord8 s2537 = (s2533 >> 1) | (s2533 << 7);
+  const SWord8 s2538 = 128 | s2537;
+  const SWord8 s2539 = 127 & s2537;
+  const SWord8 s2540 = s2536 ? s2538 : s2539;
+  const SWord8 s2541 = (s2540 >> 1) | (s2540 << 7);
+  const SWord8 s2542 = 128 | s2541;
+  const SWord8 s2543 = 127 & s2541;
+  const SWord8 s2544 = s2456 ? s2542 : s2543;
+  const SWord8 s2545 = s1 + s2540;
+  const SBool  s2546 = s2545 < s1;
+  const SBool  s2547 = s2545 < s2540;
+  const SBool  s2548 = s2546 || s2547;
+  const SWord8 s2549 = (s2545 >> 1) | (s2545 << 7);
+  const SWord8 s2550 = 128 | s2549;
+  const SWord8 s2551 = 127 & s2549;
+  const SWord8 s2552 = s2548 ? s2550 : s2551;
+  const SWord8 s2553 = s2457 ? s2544 : s2552;
+  const SWord8 s2554 = s2330 ? s2532 : s2553;
+  const SWord8 s2555 = s2078 ? s2507 : s2554;
+  const SWord8 s2556 = s2059 ? s2447 : s2555;
+  const SWord8 s2557 = s2042 ? s2320 : s2556;
+  const SWord8 s2558 = s1 + s2063;
+  const SBool  s2559 = (SBool) (s2558 & 1);
+  const SBool  s2560 = false != s2559;
+  const SWord8 s2561 = s2560 ? s2067 : s2068;
+  const SBool  s2562 = (SBool) (s2561 & 1);
+  const SBool  s2563 = false != s2562;
+  const SWord8 s2564 = s2563 ? s2073 : s2074;
+  const SBool  s2565 = (SBool) (s2564 & 1);
+  const SBool  s2566 = false != s2565;
+  const SBool  s2567 = !s2566;
+  const SBool  s2568 = s2558 < s1;
+  const SBool  s2569 = s2558 < s2063;
+  const SBool  s2570 = s2568 || s2569;
+  const SWord8 s2571 = (s2558 >> 1) | (s2558 << 7);
+  const SWord8 s2572 = 128 | s2571;
+  const SWord8 s2573 = 127 & s2571;
+  const SWord8 s2574 = s2570 ? s2572 : s2573;
+  const SBool  s2575 = (SBool) (s2574 & 1);
+  const SBool  s2576 = false != s2575;
+  const SWord8 s2577 = (s2561 >> 1) | (s2561 << 7);
+  const SWord8 s2578 = 128 | s2577;
+  const SWord8 s2579 = 127 & s2577;
+  const SWord8 s2580 = s2576 ? s2578 : s2579;
+  const SBool  s2581 = (SBool) (s2580 & 1);
+  const SBool  s2582 = false != s2581;
+  const SWord8 s2583 = (s2564 >> 1) | (s2564 << 7);
+  const SWord8 s2584 = 128 | s2583;
+  const SWord8 s2585 = 127 & s2583;
+  const SWord8 s2586 = s2582 ? s2584 : s2585;
+  const SBool  s2587 = (SBool) (s2586 & 1);
+  const SBool  s2588 = false != s2587;
+  const SBool  s2589 = !s2588;
+  const SWord8 s2590 = (s2574 >> 1) | (s2574 << 7);
+  const SWord8 s2591 = 128 | s2590;
+  const SWord8 s2592 = 127 & s2590;
+  const SWord8 s2593 = s2041 ? s2591 : s2592;
+  const SBool  s2594 = (SBool) (s2593 & 1);
+  const SBool  s2595 = false != s2594;
+  const SWord8 s2596 = (s2580 >> 1) | (s2580 << 7);
+  const SWord8 s2597 = 128 | s2596;
+  const SWord8 s2598 = 127 & s2596;
+  const SWord8 s2599 = s2595 ? s2597 : s2598;
+  const SBool  s2600 = (SBool) (s2599 & 1);
+  const SBool  s2601 = false != s2600;
+  const SWord8 s2602 = (s2586 >> 1) | (s2586 << 7);
+  const SWord8 s2603 = 128 | s2602;
+  const SWord8 s2604 = 127 & s2602;
+  const SWord8 s2605 = s2601 ? s2603 : s2604;
+  const SBool  s2606 = (SBool) (s2605 & 1);
+  const SBool  s2607 = false != s2606;
+  const SBool  s2608 = !s2607;
+  const SWord8 s2609 = (s2593 >> 1) | (s2593 << 7);
+  const SWord8 s2610 = 128 | s2609;
+  const SWord8 s2611 = 127 & s2609;
+  const SWord8 s2612 = s2058 ? s2610 : s2611;
+  const SWord8 s2613 = (s2612 >> 1) | (s2612 << 7);
+  const SWord8 s2614 = 128 | s2613;
+  const SWord8 s2615 = 127 & s2613;
+  const SWord8 s2616 = s2566 ? s2614 : s2615;
+  const SWord8 s2617 = (s2616 >> 1) | (s2616 << 7);
+  const SWord8 s2618 = 128 | s2617;
+  const SWord8 s2619 = 127 & s2617;
+  const SWord8 s2620 = s2588 ? s2618 : s2619;
+  const SWord8 s2621 = (s2620 >> 1) | (s2620 << 7);
+  const SWord8 s2622 = 128 | s2621;
+  const SWord8 s2623 = 127 & s2621;
+  const SWord8 s2624 = s2607 ? s2622 : s2623;
+  const SWord8 s2625 = s1 + s2620;
+  const SBool  s2626 = s2625 < s1;
+  const SBool  s2627 = s2625 < s2620;
+  const SBool  s2628 = s2626 || s2627;
+  const SWord8 s2629 = (s2625 >> 1) | (s2625 << 7);
+  const SWord8 s2630 = 128 | s2629;
+  const SWord8 s2631 = 127 & s2629;
+  const SWord8 s2632 = s2628 ? s2630 : s2631;
+  const SWord8 s2633 = s2608 ? s2624 : s2632;
+  const SWord8 s2634 = s1 + s2616;
+  const SBool  s2635 = s2634 < s1;
+  const SBool  s2636 = s2634 < s2616;
+  const SBool  s2637 = s2635 || s2636;
+  const SWord8 s2638 = (s2634 >> 1) | (s2634 << 7);
+  const SWord8 s2639 = 128 | s2638;
+  const SWord8 s2640 = 127 & s2638;
+  const SWord8 s2641 = s2637 ? s2639 : s2640;
+  const SWord8 s2642 = (s2641 >> 1) | (s2641 << 7);
+  const SWord8 s2643 = 128 | s2642;
+  const SWord8 s2644 = 127 & s2642;
+  const SWord8 s2645 = s2607 ? s2643 : s2644;
+  const SWord8 s2646 = s1 + s2641;
+  const SBool  s2647 = s2646 < s1;
+  const SBool  s2648 = s2646 < s2641;
+  const SBool  s2649 = s2647 || s2648;
+  const SWord8 s2650 = (s2646 >> 1) | (s2646 << 7);
+  const SWord8 s2651 = 128 | s2650;
+  const SWord8 s2652 = 127 & s2650;
+  const SWord8 s2653 = s2649 ? s2651 : s2652;
+  const SWord8 s2654 = s2608 ? s2645 : s2653;
+  const SWord8 s2655 = s2589 ? s2633 : s2654;
+  const SWord8 s2656 = s1 + s2612;
+  const SBool  s2657 = s2656 < s1;
+  const SBool  s2658 = s2656 < s2612;
+  const SBool  s2659 = s2657 || s2658;
+  const SWord8 s2660 = (s2656 >> 1) | (s2656 << 7);
+  const SWord8 s2661 = 128 | s2660;
+  const SWord8 s2662 = 127 & s2660;
+  const SWord8 s2663 = s2659 ? s2661 : s2662;
+  const SWord8 s2664 = (s2663 >> 1) | (s2663 << 7);
+  const SWord8 s2665 = 128 | s2664;
+  const SWord8 s2666 = 127 & s2664;
+  const SWord8 s2667 = s2588 ? s2665 : s2666;
+  const SWord8 s2668 = (s2667 >> 1) | (s2667 << 7);
+  const SWord8 s2669 = 128 | s2668;
+  const SWord8 s2670 = 127 & s2668;
+  const SWord8 s2671 = s2607 ? s2669 : s2670;
+  const SWord8 s2672 = s1 + s2667;
+  const SBool  s2673 = s2672 < s1;
+  const SBool  s2674 = s2672 < s2667;
+  const SBool  s2675 = s2673 || s2674;
+  const SWord8 s2676 = (s2672 >> 1) | (s2672 << 7);
+  const SWord8 s2677 = 128 | s2676;
+  const SWord8 s2678 = 127 & s2676;
+  const SWord8 s2679 = s2675 ? s2677 : s2678;
+  const SWord8 s2680 = s2608 ? s2671 : s2679;
+  const SWord8 s2681 = s1 + s2663;
+  const SBool  s2682 = s2681 < s1;
+  const SBool  s2683 = s2681 < s2663;
+  const SBool  s2684 = s2682 || s2683;
+  const SWord8 s2685 = (s2681 >> 1) | (s2681 << 7);
+  const SWord8 s2686 = 128 | s2685;
+  const SWord8 s2687 = 127 & s2685;
+  const SWord8 s2688 = s2684 ? s2686 : s2687;
+  const SWord8 s2689 = (s2688 >> 1) | (s2688 << 7);
+  const SWord8 s2690 = 128 | s2689;
+  const SWord8 s2691 = 127 & s2689;
+  const SWord8 s2692 = s2607 ? s2690 : s2691;
+  const SWord8 s2693 = s1 + s2688;
+  const SBool  s2694 = s2693 < s1;
+  const SBool  s2695 = s2693 < s2688;
+  const SBool  s2696 = s2694 || s2695;
+  const SWord8 s2697 = (s2693 >> 1) | (s2693 << 7);
+  const SWord8 s2698 = 128 | s2697;
+  const SWord8 s2699 = 127 & s2697;
+  const SWord8 s2700 = s2696 ? s2698 : s2699;
+  const SWord8 s2701 = s2608 ? s2692 : s2700;
+  const SWord8 s2702 = s2589 ? s2680 : s2701;
+  const SWord8 s2703 = s2567 ? s2655 : s2702;
+  const SWord8 s2704 = s1 + s2593;
+  const SBool  s2705 = (SBool) (s2704 & 1);
+  const SBool  s2706 = false != s2705;
+  const SWord8 s2707 = s2706 ? s2597 : s2598;
+  const SBool  s2708 = (SBool) (s2707 & 1);
+  const SBool  s2709 = false != s2708;
+  const SWord8 s2710 = s2709 ? s2603 : s2604;
+  const SBool  s2711 = (SBool) (s2710 & 1);
+  const SBool  s2712 = false != s2711;
+  const SBool  s2713 = !s2712;
+  const SBool  s2714 = s2704 < s1;
+  const SBool  s2715 = s2704 < s2593;
+  const SBool  s2716 = s2714 || s2715;
+  const SWord8 s2717 = (s2704 >> 1) | (s2704 << 7);
+  const SWord8 s2718 = 128 | s2717;
+  const SWord8 s2719 = 127 & s2717;
+  const SWord8 s2720 = s2716 ? s2718 : s2719;
+  const SWord8 s2721 = (s2720 >> 1) | (s2720 << 7);
+  const SWord8 s2722 = 128 | s2721;
+  const SWord8 s2723 = 127 & s2721;
+  const SWord8 s2724 = s2566 ? s2722 : s2723;
+  const SWord8 s2725 = (s2724 >> 1) | (s2724 << 7);
+  const SWord8 s2726 = 128 | s2725;
+  const SWord8 s2727 = 127 & s2725;
+  const SWord8 s2728 = s2588 ? s2726 : s2727;
+  const SWord8 s2729 = (s2728 >> 1) | (s2728 << 7);
+  const SWord8 s2730 = 128 | s2729;
+  const SWord8 s2731 = 127 & s2729;
+  const SWord8 s2732 = s2712 ? s2730 : s2731;
+  const SWord8 s2733 = s1 + s2728;
+  const SBool  s2734 = s2733 < s1;
+  const SBool  s2735 = s2733 < s2728;
+  const SBool  s2736 = s2734 || s2735;
+  const SWord8 s2737 = (s2733 >> 1) | (s2733 << 7);
+  const SWord8 s2738 = 128 | s2737;
+  const SWord8 s2739 = 127 & s2737;
+  const SWord8 s2740 = s2736 ? s2738 : s2739;
+  const SWord8 s2741 = s2713 ? s2732 : s2740;
+  const SWord8 s2742 = s1 + s2724;
+  const SBool  s2743 = s2742 < s1;
+  const SBool  s2744 = s2742 < s2724;
+  const SBool  s2745 = s2743 || s2744;
+  const SWord8 s2746 = (s2742 >> 1) | (s2742 << 7);
+  const SWord8 s2747 = 128 | s2746;
+  const SWord8 s2748 = 127 & s2746;
+  const SWord8 s2749 = s2745 ? s2747 : s2748;
+  const SWord8 s2750 = (s2749 >> 1) | (s2749 << 7);
+  const SWord8 s2751 = 128 | s2750;
+  const SWord8 s2752 = 127 & s2750;
+  const SWord8 s2753 = s2712 ? s2751 : s2752;
+  const SWord8 s2754 = s1 + s2749;
+  const SBool  s2755 = s2754 < s1;
+  const SBool  s2756 = s2754 < s2749;
+  const SBool  s2757 = s2755 || s2756;
+  const SWord8 s2758 = (s2754 >> 1) | (s2754 << 7);
+  const SWord8 s2759 = 128 | s2758;
+  const SWord8 s2760 = 127 & s2758;
+  const SWord8 s2761 = s2757 ? s2759 : s2760;
+  const SWord8 s2762 = s2713 ? s2753 : s2761;
+  const SWord8 s2763 = s2589 ? s2741 : s2762;
+  const SWord8 s2764 = s1 + s2720;
+  const SBool  s2765 = s2764 < s1;
+  const SBool  s2766 = s2764 < s2720;
+  const SBool  s2767 = s2765 || s2766;
+  const SWord8 s2768 = (s2764 >> 1) | (s2764 << 7);
+  const SWord8 s2769 = 128 | s2768;
+  const SWord8 s2770 = 127 & s2768;
+  const SWord8 s2771 = s2767 ? s2769 : s2770;
+  const SWord8 s2772 = (s2771 >> 1) | (s2771 << 7);
+  const SWord8 s2773 = 128 | s2772;
+  const SWord8 s2774 = 127 & s2772;
+  const SWord8 s2775 = s2588 ? s2773 : s2774;
+  const SWord8 s2776 = (s2775 >> 1) | (s2775 << 7);
+  const SWord8 s2777 = 128 | s2776;
+  const SWord8 s2778 = 127 & s2776;
+  const SWord8 s2779 = s2712 ? s2777 : s2778;
+  const SWord8 s2780 = s1 + s2775;
+  const SBool  s2781 = s2780 < s1;
+  const SBool  s2782 = s2780 < s2775;
+  const SBool  s2783 = s2781 || s2782;
+  const SWord8 s2784 = (s2780 >> 1) | (s2780 << 7);
+  const SWord8 s2785 = 128 | s2784;
+  const SWord8 s2786 = 127 & s2784;
+  const SWord8 s2787 = s2783 ? s2785 : s2786;
+  const SWord8 s2788 = s2713 ? s2779 : s2787;
+  const SWord8 s2789 = s1 + s2771;
+  const SBool  s2790 = s2789 < s1;
+  const SBool  s2791 = s2789 < s2771;
+  const SBool  s2792 = s2790 || s2791;
+  const SWord8 s2793 = (s2789 >> 1) | (s2789 << 7);
+  const SWord8 s2794 = 128 | s2793;
+  const SWord8 s2795 = 127 & s2793;
+  const SWord8 s2796 = s2792 ? s2794 : s2795;
+  const SWord8 s2797 = (s2796 >> 1) | (s2796 << 7);
+  const SWord8 s2798 = 128 | s2797;
+  const SWord8 s2799 = 127 & s2797;
+  const SWord8 s2800 = s2712 ? s2798 : s2799;
+  const SWord8 s2801 = s1 + s2796;
+  const SBool  s2802 = s2801 < s1;
+  const SBool  s2803 = s2801 < s2796;
+  const SBool  s2804 = s2802 || s2803;
+  const SWord8 s2805 = (s2801 >> 1) | (s2801 << 7);
+  const SWord8 s2806 = 128 | s2805;
+  const SWord8 s2807 = 127 & s2805;
+  const SWord8 s2808 = s2804 ? s2806 : s2807;
+  const SWord8 s2809 = s2713 ? s2800 : s2808;
+  const SWord8 s2810 = s2589 ? s2788 : s2809;
+  const SWord8 s2811 = s2567 ? s2763 : s2810;
+  const SWord8 s2812 = s2059 ? s2703 : s2811;
+  const SWord8 s2813 = s1 + s2574;
+  const SBool  s2814 = (SBool) (s2813 & 1);
+  const SBool  s2815 = false != s2814;
+  const SWord8 s2816 = s2815 ? s2578 : s2579;
+  const SBool  s2817 = (SBool) (s2816 & 1);
+  const SBool  s2818 = false != s2817;
+  const SWord8 s2819 = s2818 ? s2584 : s2585;
+  const SBool  s2820 = (SBool) (s2819 & 1);
+  const SBool  s2821 = false != s2820;
+  const SBool  s2822 = !s2821;
+  const SBool  s2823 = s2813 < s1;
+  const SBool  s2824 = s2813 < s2574;
+  const SBool  s2825 = s2823 || s2824;
+  const SWord8 s2826 = (s2813 >> 1) | (s2813 << 7);
+  const SWord8 s2827 = 128 | s2826;
+  const SWord8 s2828 = 127 & s2826;
+  const SWord8 s2829 = s2825 ? s2827 : s2828;
+  const SBool  s2830 = (SBool) (s2829 & 1);
+  const SBool  s2831 = false != s2830;
+  const SWord8 s2832 = (s2816 >> 1) | (s2816 << 7);
+  const SWord8 s2833 = 128 | s2832;
+  const SWord8 s2834 = 127 & s2832;
+  const SWord8 s2835 = s2831 ? s2833 : s2834;
+  const SBool  s2836 = (SBool) (s2835 & 1);
+  const SBool  s2837 = false != s2836;
+  const SWord8 s2838 = (s2819 >> 1) | (s2819 << 7);
+  const SWord8 s2839 = 128 | s2838;
+  const SWord8 s2840 = 127 & s2838;
+  const SWord8 s2841 = s2837 ? s2839 : s2840;
+  const SBool  s2842 = (SBool) (s2841 & 1);
+  const SBool  s2843 = false != s2842;
+  const SBool  s2844 = !s2843;
+  const SWord8 s2845 = (s2829 >> 1) | (s2829 << 7);
+  const SWord8 s2846 = 128 | s2845;
+  const SWord8 s2847 = 127 & s2845;
+  const SWord8 s2848 = s2058 ? s2846 : s2847;
+  const SWord8 s2849 = (s2848 >> 1) | (s2848 << 7);
+  const SWord8 s2850 = 128 | s2849;
+  const SWord8 s2851 = 127 & s2849;
+  const SWord8 s2852 = s2566 ? s2850 : s2851;
+  const SWord8 s2853 = (s2852 >> 1) | (s2852 << 7);
+  const SWord8 s2854 = 128 | s2853;
+  const SWord8 s2855 = 127 & s2853;
+  const SWord8 s2856 = s2821 ? s2854 : s2855;
+  const SWord8 s2857 = (s2856 >> 1) | (s2856 << 7);
+  const SWord8 s2858 = 128 | s2857;
+  const SWord8 s2859 = 127 & s2857;
+  const SWord8 s2860 = s2843 ? s2858 : s2859;
+  const SWord8 s2861 = s1 + s2856;
+  const SBool  s2862 = s2861 < s1;
+  const SBool  s2863 = s2861 < s2856;
+  const SBool  s2864 = s2862 || s2863;
+  const SWord8 s2865 = (s2861 >> 1) | (s2861 << 7);
+  const SWord8 s2866 = 128 | s2865;
+  const SWord8 s2867 = 127 & s2865;
+  const SWord8 s2868 = s2864 ? s2866 : s2867;
+  const SWord8 s2869 = s2844 ? s2860 : s2868;
+  const SWord8 s2870 = s1 + s2852;
+  const SBool  s2871 = s2870 < s1;
+  const SBool  s2872 = s2870 < s2852;
+  const SBool  s2873 = s2871 || s2872;
+  const SWord8 s2874 = (s2870 >> 1) | (s2870 << 7);
+  const SWord8 s2875 = 128 | s2874;
+  const SWord8 s2876 = 127 & s2874;
+  const SWord8 s2877 = s2873 ? s2875 : s2876;
+  const SWord8 s2878 = (s2877 >> 1) | (s2877 << 7);
+  const SWord8 s2879 = 128 | s2878;
+  const SWord8 s2880 = 127 & s2878;
+  const SWord8 s2881 = s2843 ? s2879 : s2880;
+  const SWord8 s2882 = s1 + s2877;
+  const SBool  s2883 = s2882 < s1;
+  const SBool  s2884 = s2882 < s2877;
+  const SBool  s2885 = s2883 || s2884;
+  const SWord8 s2886 = (s2882 >> 1) | (s2882 << 7);
+  const SWord8 s2887 = 128 | s2886;
+  const SWord8 s2888 = 127 & s2886;
+  const SWord8 s2889 = s2885 ? s2887 : s2888;
+  const SWord8 s2890 = s2844 ? s2881 : s2889;
+  const SWord8 s2891 = s2822 ? s2869 : s2890;
+  const SWord8 s2892 = s1 + s2848;
+  const SBool  s2893 = s2892 < s1;
+  const SBool  s2894 = s2892 < s2848;
+  const SBool  s2895 = s2893 || s2894;
+  const SWord8 s2896 = (s2892 >> 1) | (s2892 << 7);
+  const SWord8 s2897 = 128 | s2896;
+  const SWord8 s2898 = 127 & s2896;
+  const SWord8 s2899 = s2895 ? s2897 : s2898;
+  const SWord8 s2900 = (s2899 >> 1) | (s2899 << 7);
+  const SWord8 s2901 = 128 | s2900;
+  const SWord8 s2902 = 127 & s2900;
+  const SWord8 s2903 = s2821 ? s2901 : s2902;
+  const SWord8 s2904 = (s2903 >> 1) | (s2903 << 7);
+  const SWord8 s2905 = 128 | s2904;
+  const SWord8 s2906 = 127 & s2904;
+  const SWord8 s2907 = s2843 ? s2905 : s2906;
+  const SWord8 s2908 = s1 + s2903;
+  const SBool  s2909 = s2908 < s1;
+  const SBool  s2910 = s2908 < s2903;
+  const SBool  s2911 = s2909 || s2910;
+  const SWord8 s2912 = (s2908 >> 1) | (s2908 << 7);
+  const SWord8 s2913 = 128 | s2912;
+  const SWord8 s2914 = 127 & s2912;
+  const SWord8 s2915 = s2911 ? s2913 : s2914;
+  const SWord8 s2916 = s2844 ? s2907 : s2915;
+  const SWord8 s2917 = s1 + s2899;
+  const SBool  s2918 = s2917 < s1;
+  const SBool  s2919 = s2917 < s2899;
+  const SBool  s2920 = s2918 || s2919;
+  const SWord8 s2921 = (s2917 >> 1) | (s2917 << 7);
+  const SWord8 s2922 = 128 | s2921;
+  const SWord8 s2923 = 127 & s2921;
+  const SWord8 s2924 = s2920 ? s2922 : s2923;
+  const SWord8 s2925 = (s2924 >> 1) | (s2924 << 7);
+  const SWord8 s2926 = 128 | s2925;
+  const SWord8 s2927 = 127 & s2925;
+  const SWord8 s2928 = s2843 ? s2926 : s2927;
+  const SWord8 s2929 = s1 + s2924;
+  const SBool  s2930 = s2929 < s1;
+  const SBool  s2931 = s2929 < s2924;
+  const SBool  s2932 = s2930 || s2931;
+  const SWord8 s2933 = (s2929 >> 1) | (s2929 << 7);
+  const SWord8 s2934 = 128 | s2933;
+  const SWord8 s2935 = 127 & s2933;
+  const SWord8 s2936 = s2932 ? s2934 : s2935;
+  const SWord8 s2937 = s2844 ? s2928 : s2936;
+  const SWord8 s2938 = s2822 ? s2916 : s2937;
+  const SWord8 s2939 = s2567 ? s2891 : s2938;
+  const SWord8 s2940 = s1 + s2829;
+  const SBool  s2941 = (SBool) (s2940 & 1);
+  const SBool  s2942 = false != s2941;
+  const SWord8 s2943 = s2942 ? s2833 : s2834;
+  const SBool  s2944 = (SBool) (s2943 & 1);
+  const SBool  s2945 = false != s2944;
+  const SWord8 s2946 = s2945 ? s2839 : s2840;
+  const SBool  s2947 = (SBool) (s2946 & 1);
+  const SBool  s2948 = false != s2947;
+  const SBool  s2949 = !s2948;
+  const SBool  s2950 = s2940 < s1;
+  const SBool  s2951 = s2940 < s2829;
+  const SBool  s2952 = s2950 || s2951;
+  const SWord8 s2953 = (s2940 >> 1) | (s2940 << 7);
+  const SWord8 s2954 = 128 | s2953;
+  const SWord8 s2955 = 127 & s2953;
+  const SWord8 s2956 = s2952 ? s2954 : s2955;
+  const SWord8 s2957 = (s2956 >> 1) | (s2956 << 7);
+  const SWord8 s2958 = 128 | s2957;
+  const SWord8 s2959 = 127 & s2957;
+  const SWord8 s2960 = s2566 ? s2958 : s2959;
+  const SWord8 s2961 = (s2960 >> 1) | (s2960 << 7);
+  const SWord8 s2962 = 128 | s2961;
+  const SWord8 s2963 = 127 & s2961;
+  const SWord8 s2964 = s2821 ? s2962 : s2963;
+  const SWord8 s2965 = (s2964 >> 1) | (s2964 << 7);
+  const SWord8 s2966 = 128 | s2965;
+  const SWord8 s2967 = 127 & s2965;
+  const SWord8 s2968 = s2948 ? s2966 : s2967;
+  const SWord8 s2969 = s1 + s2964;
+  const SBool  s2970 = s2969 < s1;
+  const SBool  s2971 = s2969 < s2964;
+  const SBool  s2972 = s2970 || s2971;
+  const SWord8 s2973 = (s2969 >> 1) | (s2969 << 7);
+  const SWord8 s2974 = 128 | s2973;
+  const SWord8 s2975 = 127 & s2973;
+  const SWord8 s2976 = s2972 ? s2974 : s2975;
+  const SWord8 s2977 = s2949 ? s2968 : s2976;
+  const SWord8 s2978 = s1 + s2960;
+  const SBool  s2979 = s2978 < s1;
+  const SBool  s2980 = s2978 < s2960;
+  const SBool  s2981 = s2979 || s2980;
+  const SWord8 s2982 = (s2978 >> 1) | (s2978 << 7);
+  const SWord8 s2983 = 128 | s2982;
+  const SWord8 s2984 = 127 & s2982;
+  const SWord8 s2985 = s2981 ? s2983 : s2984;
+  const SWord8 s2986 = (s2985 >> 1) | (s2985 << 7);
+  const SWord8 s2987 = 128 | s2986;
+  const SWord8 s2988 = 127 & s2986;
+  const SWord8 s2989 = s2948 ? s2987 : s2988;
+  const SWord8 s2990 = s1 + s2985;
+  const SBool  s2991 = s2990 < s1;
+  const SBool  s2992 = s2990 < s2985;
+  const SBool  s2993 = s2991 || s2992;
+  const SWord8 s2994 = (s2990 >> 1) | (s2990 << 7);
+  const SWord8 s2995 = 128 | s2994;
+  const SWord8 s2996 = 127 & s2994;
+  const SWord8 s2997 = s2993 ? s2995 : s2996;
+  const SWord8 s2998 = s2949 ? s2989 : s2997;
+  const SWord8 s2999 = s2822 ? s2977 : s2998;
+  const SWord8 s3000 = s1 + s2956;
+  const SBool  s3001 = s3000 < s1;
+  const SBool  s3002 = s3000 < s2956;
+  const SBool  s3003 = s3001 || s3002;
+  const SWord8 s3004 = (s3000 >> 1) | (s3000 << 7);
+  const SWord8 s3005 = 128 | s3004;
+  const SWord8 s3006 = 127 & s3004;
+  const SWord8 s3007 = s3003 ? s3005 : s3006;
+  const SWord8 s3008 = (s3007 >> 1) | (s3007 << 7);
+  const SWord8 s3009 = 128 | s3008;
+  const SWord8 s3010 = 127 & s3008;
+  const SWord8 s3011 = s2821 ? s3009 : s3010;
+  const SWord8 s3012 = (s3011 >> 1) | (s3011 << 7);
+  const SWord8 s3013 = 128 | s3012;
+  const SWord8 s3014 = 127 & s3012;
+  const SWord8 s3015 = s2948 ? s3013 : s3014;
+  const SWord8 s3016 = s1 + s3011;
+  const SBool  s3017 = s3016 < s1;
+  const SBool  s3018 = s3016 < s3011;
+  const SBool  s3019 = s3017 || s3018;
+  const SWord8 s3020 = (s3016 >> 1) | (s3016 << 7);
+  const SWord8 s3021 = 128 | s3020;
+  const SWord8 s3022 = 127 & s3020;
+  const SWord8 s3023 = s3019 ? s3021 : s3022;
+  const SWord8 s3024 = s2949 ? s3015 : s3023;
+  const SWord8 s3025 = s1 + s3007;
+  const SBool  s3026 = s3025 < s1;
+  const SBool  s3027 = s3025 < s3007;
+  const SBool  s3028 = s3026 || s3027;
+  const SWord8 s3029 = (s3025 >> 1) | (s3025 << 7);
+  const SWord8 s3030 = 128 | s3029;
+  const SWord8 s3031 = 127 & s3029;
+  const SWord8 s3032 = s3028 ? s3030 : s3031;
+  const SWord8 s3033 = (s3032 >> 1) | (s3032 << 7);
+  const SWord8 s3034 = 128 | s3033;
+  const SWord8 s3035 = 127 & s3033;
+  const SWord8 s3036 = s2948 ? s3034 : s3035;
+  const SWord8 s3037 = s1 + s3032;
+  const SBool  s3038 = s3037 < s1;
+  const SBool  s3039 = s3037 < s3032;
+  const SBool  s3040 = s3038 || s3039;
+  const SWord8 s3041 = (s3037 >> 1) | (s3037 << 7);
+  const SWord8 s3042 = 128 | s3041;
+  const SWord8 s3043 = 127 & s3041;
+  const SWord8 s3044 = s3040 ? s3042 : s3043;
+  const SWord8 s3045 = s2949 ? s3036 : s3044;
+  const SWord8 s3046 = s2822 ? s3024 : s3045;
+  const SWord8 s3047 = s2567 ? s2999 : s3046;
+  const SWord8 s3048 = s2059 ? s2939 : s3047;
+  const SWord8 s3049 = s2042 ? s2812 : s3048;
+  const SWord8 s3050 = s16 ? s2557 : s3049;
+  const SWord8 s3051 = s1 + s2044;
+  const SBool  s3052 = (SBool) (s3051 & 1);
+  const SBool  s3053 = false != s3052;
+  const SWord8 s3054 = s3053 ? s2048 : s2049;
+  const SBool  s3055 = (SBool) (s3054 & 1);
+  const SBool  s3056 = false != s3055;
+  const SWord8 s3057 = s3056 ? s2054 : s2055;
+  const SBool  s3058 = (SBool) (s3057 & 1);
+  const SBool  s3059 = false != s3058;
+  const SBool  s3060 = !s3059;
+  const SBool  s3061 = s3051 < s1;
+  const SBool  s3062 = s3051 < s2044;
+  const SBool  s3063 = s3061 || s3062;
+  const SWord8 s3064 = (s3051 >> 1) | (s3051 << 7);
+  const SWord8 s3065 = 128 | s3064;
+  const SWord8 s3066 = 127 & s3064;
+  const SWord8 s3067 = s3063 ? s3065 : s3066;
+  const SBool  s3068 = (SBool) (s3067 & 1);
+  const SBool  s3069 = false != s3068;
+  const SWord8 s3070 = (s3054 >> 1) | (s3054 << 7);
+  const SWord8 s3071 = 128 | s3070;
+  const SWord8 s3072 = 127 & s3070;
+  const SWord8 s3073 = s3069 ? s3071 : s3072;
+  const SBool  s3074 = (SBool) (s3073 & 1);
+  const SBool  s3075 = false != s3074;
+  const SWord8 s3076 = (s3057 >> 1) | (s3057 << 7);
+  const SWord8 s3077 = 128 | s3076;
+  const SWord8 s3078 = 127 & s3076;
+  const SWord8 s3079 = s3075 ? s3077 : s3078;
+  const SBool  s3080 = (SBool) (s3079 & 1);
+  const SBool  s3081 = false != s3080;
+  const SBool  s3082 = !s3081;
+  const SWord8 s3083 = (s3067 >> 1) | (s3067 << 7);
+  const SWord8 s3084 = 128 | s3083;
+  const SWord8 s3085 = 127 & s3083;
+  const SWord8 s3086 = s15 ? s3084 : s3085;
+  const SBool  s3087 = (SBool) (s3086 & 1);
+  const SBool  s3088 = false != s3087;
+  const SWord8 s3089 = (s3073 >> 1) | (s3073 << 7);
+  const SWord8 s3090 = 128 | s3089;
+  const SWord8 s3091 = 127 & s3089;
+  const SWord8 s3092 = s3088 ? s3090 : s3091;
+  const SBool  s3093 = (SBool) (s3092 & 1);
+  const SBool  s3094 = false != s3093;
+  const SWord8 s3095 = (s3079 >> 1) | (s3079 << 7);
+  const SWord8 s3096 = 128 | s3095;
+  const SWord8 s3097 = 127 & s3095;
+  const SWord8 s3098 = s3094 ? s3096 : s3097;
+  const SBool  s3099 = (SBool) (s3098 & 1);
+  const SBool  s3100 = false != s3099;
+  const SBool  s3101 = !s3100;
+  const SWord8 s3102 = (s3086 >> 1) | (s3086 << 7);
+  const SWord8 s3103 = 128 | s3102;
+  const SWord8 s3104 = 127 & s3102;
+  const SWord8 s3105 = s2041 ? s3103 : s3104;
+  const SBool  s3106 = (SBool) (s3105 & 1);
+  const SBool  s3107 = false != s3106;
+  const SWord8 s3108 = (s3092 >> 1) | (s3092 << 7);
+  const SWord8 s3109 = 128 | s3108;
+  const SWord8 s3110 = 127 & s3108;
+  const SWord8 s3111 = s3107 ? s3109 : s3110;
+  const SBool  s3112 = (SBool) (s3111 & 1);
+  const SBool  s3113 = false != s3112;
+  const SWord8 s3114 = (s3098 >> 1) | (s3098 << 7);
+  const SWord8 s3115 = 128 | s3114;
+  const SWord8 s3116 = 127 & s3114;
+  const SWord8 s3117 = s3113 ? s3115 : s3116;
+  const SBool  s3118 = (SBool) (s3117 & 1);
+  const SBool  s3119 = false != s3118;
+  const SBool  s3120 = !s3119;
+  const SWord8 s3121 = (s3105 >> 1) | (s3105 << 7);
+  const SWord8 s3122 = 128 | s3121;
+  const SWord8 s3123 = 127 & s3121;
+  const SWord8 s3124 = s3059 ? s3122 : s3123;
+  const SWord8 s3125 = (s3124 >> 1) | (s3124 << 7);
+  const SWord8 s3126 = 128 | s3125;
+  const SWord8 s3127 = 127 & s3125;
+  const SWord8 s3128 = s3081 ? s3126 : s3127;
+  const SWord8 s3129 = (s3128 >> 1) | (s3128 << 7);
+  const SWord8 s3130 = 128 | s3129;
+  const SWord8 s3131 = 127 & s3129;
+  const SWord8 s3132 = s3100 ? s3130 : s3131;
+  const SWord8 s3133 = (s3132 >> 1) | (s3132 << 7);
+  const SWord8 s3134 = 128 | s3133;
+  const SWord8 s3135 = 127 & s3133;
+  const SWord8 s3136 = s3119 ? s3134 : s3135;
+  const SWord8 s3137 = s1 + s3132;
+  const SBool  s3138 = s3137 < s1;
+  const SBool  s3139 = s3137 < s3132;
+  const SBool  s3140 = s3138 || s3139;
+  const SWord8 s3141 = (s3137 >> 1) | (s3137 << 7);
+  const SWord8 s3142 = 128 | s3141;
+  const SWord8 s3143 = 127 & s3141;
+  const SWord8 s3144 = s3140 ? s3142 : s3143;
+  const SWord8 s3145 = s3120 ? s3136 : s3144;
+  const SWord8 s3146 = s1 + s3128;
+  const SBool  s3147 = s3146 < s1;
+  const SBool  s3148 = s3146 < s3128;
+  const SBool  s3149 = s3147 || s3148;
+  const SWord8 s3150 = (s3146 >> 1) | (s3146 << 7);
+  const SWord8 s3151 = 128 | s3150;
+  const SWord8 s3152 = 127 & s3150;
+  const SWord8 s3153 = s3149 ? s3151 : s3152;
+  const SWord8 s3154 = (s3153 >> 1) | (s3153 << 7);
+  const SWord8 s3155 = 128 | s3154;
+  const SWord8 s3156 = 127 & s3154;
+  const SWord8 s3157 = s3119 ? s3155 : s3156;
+  const SWord8 s3158 = s1 + s3153;
+  const SBool  s3159 = s3158 < s1;
+  const SBool  s3160 = s3158 < s3153;
+  const SBool  s3161 = s3159 || s3160;
+  const SWord8 s3162 = (s3158 >> 1) | (s3158 << 7);
+  const SWord8 s3163 = 128 | s3162;
+  const SWord8 s3164 = 127 & s3162;
+  const SWord8 s3165 = s3161 ? s3163 : s3164;
+  const SWord8 s3166 = s3120 ? s3157 : s3165;
+  const SWord8 s3167 = s3101 ? s3145 : s3166;
+  const SWord8 s3168 = s1 + s3124;
+  const SBool  s3169 = s3168 < s1;
+  const SBool  s3170 = s3168 < s3124;
+  const SBool  s3171 = s3169 || s3170;
+  const SWord8 s3172 = (s3168 >> 1) | (s3168 << 7);
+  const SWord8 s3173 = 128 | s3172;
+  const SWord8 s3174 = 127 & s3172;
+  const SWord8 s3175 = s3171 ? s3173 : s3174;
+  const SWord8 s3176 = (s3175 >> 1) | (s3175 << 7);
+  const SWord8 s3177 = 128 | s3176;
+  const SWord8 s3178 = 127 & s3176;
+  const SWord8 s3179 = s3100 ? s3177 : s3178;
+  const SWord8 s3180 = (s3179 >> 1) | (s3179 << 7);
+  const SWord8 s3181 = 128 | s3180;
+  const SWord8 s3182 = 127 & s3180;
+  const SWord8 s3183 = s3119 ? s3181 : s3182;
+  const SWord8 s3184 = s1 + s3179;
+  const SBool  s3185 = s3184 < s1;
+  const SBool  s3186 = s3184 < s3179;
+  const SBool  s3187 = s3185 || s3186;
+  const SWord8 s3188 = (s3184 >> 1) | (s3184 << 7);
+  const SWord8 s3189 = 128 | s3188;
+  const SWord8 s3190 = 127 & s3188;
+  const SWord8 s3191 = s3187 ? s3189 : s3190;
+  const SWord8 s3192 = s3120 ? s3183 : s3191;
+  const SWord8 s3193 = s1 + s3175;
+  const SBool  s3194 = s3193 < s1;
+  const SBool  s3195 = s3193 < s3175;
+  const SBool  s3196 = s3194 || s3195;
+  const SWord8 s3197 = (s3193 >> 1) | (s3193 << 7);
+  const SWord8 s3198 = 128 | s3197;
+  const SWord8 s3199 = 127 & s3197;
+  const SWord8 s3200 = s3196 ? s3198 : s3199;
+  const SWord8 s3201 = (s3200 >> 1) | (s3200 << 7);
+  const SWord8 s3202 = 128 | s3201;
+  const SWord8 s3203 = 127 & s3201;
+  const SWord8 s3204 = s3119 ? s3202 : s3203;
+  const SWord8 s3205 = s1 + s3200;
+  const SBool  s3206 = s3205 < s1;
+  const SBool  s3207 = s3205 < s3200;
+  const SBool  s3208 = s3206 || s3207;
+  const SWord8 s3209 = (s3205 >> 1) | (s3205 << 7);
+  const SWord8 s3210 = 128 | s3209;
+  const SWord8 s3211 = 127 & s3209;
+  const SWord8 s3212 = s3208 ? s3210 : s3211;
+  const SWord8 s3213 = s3120 ? s3204 : s3212;
+  const SWord8 s3214 = s3101 ? s3192 : s3213;
+  const SWord8 s3215 = s3082 ? s3167 : s3214;
+  const SWord8 s3216 = s1 + s3105;
+  const SBool  s3217 = (SBool) (s3216 & 1);
+  const SBool  s3218 = false != s3217;
+  const SWord8 s3219 = s3218 ? s3109 : s3110;
+  const SBool  s3220 = (SBool) (s3219 & 1);
+  const SBool  s3221 = false != s3220;
+  const SWord8 s3222 = s3221 ? s3115 : s3116;
+  const SBool  s3223 = (SBool) (s3222 & 1);
+  const SBool  s3224 = false != s3223;
+  const SBool  s3225 = !s3224;
+  const SBool  s3226 = s3216 < s1;
+  const SBool  s3227 = s3216 < s3105;
+  const SBool  s3228 = s3226 || s3227;
+  const SWord8 s3229 = (s3216 >> 1) | (s3216 << 7);
+  const SWord8 s3230 = 128 | s3229;
+  const SWord8 s3231 = 127 & s3229;
+  const SWord8 s3232 = s3228 ? s3230 : s3231;
+  const SWord8 s3233 = (s3232 >> 1) | (s3232 << 7);
+  const SWord8 s3234 = 128 | s3233;
+  const SWord8 s3235 = 127 & s3233;
+  const SWord8 s3236 = s3081 ? s3234 : s3235;
+  const SWord8 s3237 = (s3236 >> 1) | (s3236 << 7);
+  const SWord8 s3238 = 128 | s3237;
+  const SWord8 s3239 = 127 & s3237;
+  const SWord8 s3240 = s3100 ? s3238 : s3239;
+  const SWord8 s3241 = (s3240 >> 1) | (s3240 << 7);
+  const SWord8 s3242 = 128 | s3241;
+  const SWord8 s3243 = 127 & s3241;
+  const SWord8 s3244 = s3224 ? s3242 : s3243;
+  const SWord8 s3245 = s1 + s3240;
+  const SBool  s3246 = s3245 < s1;
+  const SBool  s3247 = s3245 < s3240;
+  const SBool  s3248 = s3246 || s3247;
+  const SWord8 s3249 = (s3245 >> 1) | (s3245 << 7);
+  const SWord8 s3250 = 128 | s3249;
+  const SWord8 s3251 = 127 & s3249;
+  const SWord8 s3252 = s3248 ? s3250 : s3251;
+  const SWord8 s3253 = s3225 ? s3244 : s3252;
+  const SWord8 s3254 = s1 + s3236;
+  const SBool  s3255 = s3254 < s1;
+  const SBool  s3256 = s3254 < s3236;
+  const SBool  s3257 = s3255 || s3256;
+  const SWord8 s3258 = (s3254 >> 1) | (s3254 << 7);
+  const SWord8 s3259 = 128 | s3258;
+  const SWord8 s3260 = 127 & s3258;
+  const SWord8 s3261 = s3257 ? s3259 : s3260;
+  const SWord8 s3262 = (s3261 >> 1) | (s3261 << 7);
+  const SWord8 s3263 = 128 | s3262;
+  const SWord8 s3264 = 127 & s3262;
+  const SWord8 s3265 = s3224 ? s3263 : s3264;
+  const SWord8 s3266 = s1 + s3261;
+  const SBool  s3267 = s3266 < s1;
+  const SBool  s3268 = s3266 < s3261;
+  const SBool  s3269 = s3267 || s3268;
+  const SWord8 s3270 = (s3266 >> 1) | (s3266 << 7);
+  const SWord8 s3271 = 128 | s3270;
+  const SWord8 s3272 = 127 & s3270;
+  const SWord8 s3273 = s3269 ? s3271 : s3272;
+  const SWord8 s3274 = s3225 ? s3265 : s3273;
+  const SWord8 s3275 = s3101 ? s3253 : s3274;
+  const SWord8 s3276 = s1 + s3232;
+  const SBool  s3277 = s3276 < s1;
+  const SBool  s3278 = s3276 < s3232;
+  const SBool  s3279 = s3277 || s3278;
+  const SWord8 s3280 = (s3276 >> 1) | (s3276 << 7);
+  const SWord8 s3281 = 128 | s3280;
+  const SWord8 s3282 = 127 & s3280;
+  const SWord8 s3283 = s3279 ? s3281 : s3282;
+  const SWord8 s3284 = (s3283 >> 1) | (s3283 << 7);
+  const SWord8 s3285 = 128 | s3284;
+  const SWord8 s3286 = 127 & s3284;
+  const SWord8 s3287 = s3100 ? s3285 : s3286;
+  const SWord8 s3288 = (s3287 >> 1) | (s3287 << 7);
+  const SWord8 s3289 = 128 | s3288;
+  const SWord8 s3290 = 127 & s3288;
+  const SWord8 s3291 = s3224 ? s3289 : s3290;
+  const SWord8 s3292 = s1 + s3287;
+  const SBool  s3293 = s3292 < s1;
+  const SBool  s3294 = s3292 < s3287;
+  const SBool  s3295 = s3293 || s3294;
+  const SWord8 s3296 = (s3292 >> 1) | (s3292 << 7);
+  const SWord8 s3297 = 128 | s3296;
+  const SWord8 s3298 = 127 & s3296;
+  const SWord8 s3299 = s3295 ? s3297 : s3298;
+  const SWord8 s3300 = s3225 ? s3291 : s3299;
+  const SWord8 s3301 = s1 + s3283;
+  const SBool  s3302 = s3301 < s1;
+  const SBool  s3303 = s3301 < s3283;
+  const SBool  s3304 = s3302 || s3303;
+  const SWord8 s3305 = (s3301 >> 1) | (s3301 << 7);
+  const SWord8 s3306 = 128 | s3305;
+  const SWord8 s3307 = 127 & s3305;
+  const SWord8 s3308 = s3304 ? s3306 : s3307;
+  const SWord8 s3309 = (s3308 >> 1) | (s3308 << 7);
+  const SWord8 s3310 = 128 | s3309;
+  const SWord8 s3311 = 127 & s3309;
+  const SWord8 s3312 = s3224 ? s3310 : s3311;
+  const SWord8 s3313 = s1 + s3308;
+  const SBool  s3314 = s3313 < s1;
+  const SBool  s3315 = s3313 < s3308;
+  const SBool  s3316 = s3314 || s3315;
+  const SWord8 s3317 = (s3313 >> 1) | (s3313 << 7);
+  const SWord8 s3318 = 128 | s3317;
+  const SWord8 s3319 = 127 & s3317;
+  const SWord8 s3320 = s3316 ? s3318 : s3319;
+  const SWord8 s3321 = s3225 ? s3312 : s3320;
+  const SWord8 s3322 = s3101 ? s3300 : s3321;
+  const SWord8 s3323 = s3082 ? s3275 : s3322;
+  const SWord8 s3324 = s3060 ? s3215 : s3323;
+  const SWord8 s3325 = s1 + s3086;
+  const SBool  s3326 = (SBool) (s3325 & 1);
+  const SBool  s3327 = false != s3326;
+  const SWord8 s3328 = s3327 ? s3090 : s3091;
+  const SBool  s3329 = (SBool) (s3328 & 1);
+  const SBool  s3330 = false != s3329;
+  const SWord8 s3331 = s3330 ? s3096 : s3097;
+  const SBool  s3332 = (SBool) (s3331 & 1);
+  const SBool  s3333 = false != s3332;
+  const SBool  s3334 = !s3333;
+  const SBool  s3335 = s3325 < s1;
+  const SBool  s3336 = s3325 < s3086;
+  const SBool  s3337 = s3335 || s3336;
+  const SWord8 s3338 = (s3325 >> 1) | (s3325 << 7);
+  const SWord8 s3339 = 128 | s3338;
+  const SWord8 s3340 = 127 & s3338;
+  const SWord8 s3341 = s3337 ? s3339 : s3340;
+  const SBool  s3342 = (SBool) (s3341 & 1);
+  const SBool  s3343 = false != s3342;
+  const SWord8 s3344 = (s3328 >> 1) | (s3328 << 7);
+  const SWord8 s3345 = 128 | s3344;
+  const SWord8 s3346 = 127 & s3344;
+  const SWord8 s3347 = s3343 ? s3345 : s3346;
+  const SBool  s3348 = (SBool) (s3347 & 1);
+  const SBool  s3349 = false != s3348;
+  const SWord8 s3350 = (s3331 >> 1) | (s3331 << 7);
+  const SWord8 s3351 = 128 | s3350;
+  const SWord8 s3352 = 127 & s3350;
+  const SWord8 s3353 = s3349 ? s3351 : s3352;
+  const SBool  s3354 = (SBool) (s3353 & 1);
+  const SBool  s3355 = false != s3354;
+  const SBool  s3356 = !s3355;
+  const SWord8 s3357 = (s3341 >> 1) | (s3341 << 7);
+  const SWord8 s3358 = 128 | s3357;
+  const SWord8 s3359 = 127 & s3357;
+  const SWord8 s3360 = s3059 ? s3358 : s3359;
+  const SWord8 s3361 = (s3360 >> 1) | (s3360 << 7);
+  const SWord8 s3362 = 128 | s3361;
+  const SWord8 s3363 = 127 & s3361;
+  const SWord8 s3364 = s3081 ? s3362 : s3363;
+  const SWord8 s3365 = (s3364 >> 1) | (s3364 << 7);
+  const SWord8 s3366 = 128 | s3365;
+  const SWord8 s3367 = 127 & s3365;
+  const SWord8 s3368 = s3333 ? s3366 : s3367;
+  const SWord8 s3369 = (s3368 >> 1) | (s3368 << 7);
+  const SWord8 s3370 = 128 | s3369;
+  const SWord8 s3371 = 127 & s3369;
+  const SWord8 s3372 = s3355 ? s3370 : s3371;
+  const SWord8 s3373 = s1 + s3368;
+  const SBool  s3374 = s3373 < s1;
+  const SBool  s3375 = s3373 < s3368;
+  const SBool  s3376 = s3374 || s3375;
+  const SWord8 s3377 = (s3373 >> 1) | (s3373 << 7);
+  const SWord8 s3378 = 128 | s3377;
+  const SWord8 s3379 = 127 & s3377;
+  const SWord8 s3380 = s3376 ? s3378 : s3379;
+  const SWord8 s3381 = s3356 ? s3372 : s3380;
+  const SWord8 s3382 = s1 + s3364;
+  const SBool  s3383 = s3382 < s1;
+  const SBool  s3384 = s3382 < s3364;
+  const SBool  s3385 = s3383 || s3384;
+  const SWord8 s3386 = (s3382 >> 1) | (s3382 << 7);
+  const SWord8 s3387 = 128 | s3386;
+  const SWord8 s3388 = 127 & s3386;
+  const SWord8 s3389 = s3385 ? s3387 : s3388;
+  const SWord8 s3390 = (s3389 >> 1) | (s3389 << 7);
+  const SWord8 s3391 = 128 | s3390;
+  const SWord8 s3392 = 127 & s3390;
+  const SWord8 s3393 = s3355 ? s3391 : s3392;
+  const SWord8 s3394 = s1 + s3389;
+  const SBool  s3395 = s3394 < s1;
+  const SBool  s3396 = s3394 < s3389;
+  const SBool  s3397 = s3395 || s3396;
+  const SWord8 s3398 = (s3394 >> 1) | (s3394 << 7);
+  const SWord8 s3399 = 128 | s3398;
+  const SWord8 s3400 = 127 & s3398;
+  const SWord8 s3401 = s3397 ? s3399 : s3400;
+  const SWord8 s3402 = s3356 ? s3393 : s3401;
+  const SWord8 s3403 = s3334 ? s3381 : s3402;
+  const SWord8 s3404 = s1 + s3360;
+  const SBool  s3405 = s3404 < s1;
+  const SBool  s3406 = s3404 < s3360;
+  const SBool  s3407 = s3405 || s3406;
+  const SWord8 s3408 = (s3404 >> 1) | (s3404 << 7);
+  const SWord8 s3409 = 128 | s3408;
+  const SWord8 s3410 = 127 & s3408;
+  const SWord8 s3411 = s3407 ? s3409 : s3410;
+  const SWord8 s3412 = (s3411 >> 1) | (s3411 << 7);
+  const SWord8 s3413 = 128 | s3412;
+  const SWord8 s3414 = 127 & s3412;
+  const SWord8 s3415 = s3333 ? s3413 : s3414;
+  const SWord8 s3416 = (s3415 >> 1) | (s3415 << 7);
+  const SWord8 s3417 = 128 | s3416;
+  const SWord8 s3418 = 127 & s3416;
+  const SWord8 s3419 = s3355 ? s3417 : s3418;
+  const SWord8 s3420 = s1 + s3415;
+  const SBool  s3421 = s3420 < s1;
+  const SBool  s3422 = s3420 < s3415;
+  const SBool  s3423 = s3421 || s3422;
+  const SWord8 s3424 = (s3420 >> 1) | (s3420 << 7);
+  const SWord8 s3425 = 128 | s3424;
+  const SWord8 s3426 = 127 & s3424;
+  const SWord8 s3427 = s3423 ? s3425 : s3426;
+  const SWord8 s3428 = s3356 ? s3419 : s3427;
+  const SWord8 s3429 = s1 + s3411;
+  const SBool  s3430 = s3429 < s1;
+  const SBool  s3431 = s3429 < s3411;
+  const SBool  s3432 = s3430 || s3431;
+  const SWord8 s3433 = (s3429 >> 1) | (s3429 << 7);
+  const SWord8 s3434 = 128 | s3433;
+  const SWord8 s3435 = 127 & s3433;
+  const SWord8 s3436 = s3432 ? s3434 : s3435;
+  const SWord8 s3437 = (s3436 >> 1) | (s3436 << 7);
+  const SWord8 s3438 = 128 | s3437;
+  const SWord8 s3439 = 127 & s3437;
+  const SWord8 s3440 = s3355 ? s3438 : s3439;
+  const SWord8 s3441 = s1 + s3436;
+  const SBool  s3442 = s3441 < s1;
+  const SBool  s3443 = s3441 < s3436;
+  const SBool  s3444 = s3442 || s3443;
+  const SWord8 s3445 = (s3441 >> 1) | (s3441 << 7);
+  const SWord8 s3446 = 128 | s3445;
+  const SWord8 s3447 = 127 & s3445;
+  const SWord8 s3448 = s3444 ? s3446 : s3447;
+  const SWord8 s3449 = s3356 ? s3440 : s3448;
+  const SWord8 s3450 = s3334 ? s3428 : s3449;
+  const SWord8 s3451 = s3082 ? s3403 : s3450;
+  const SWord8 s3452 = s1 + s3341;
+  const SBool  s3453 = (SBool) (s3452 & 1);
+  const SBool  s3454 = false != s3453;
+  const SWord8 s3455 = s3454 ? s3345 : s3346;
+  const SBool  s3456 = (SBool) (s3455 & 1);
+  const SBool  s3457 = false != s3456;
+  const SWord8 s3458 = s3457 ? s3351 : s3352;
+  const SBool  s3459 = (SBool) (s3458 & 1);
+  const SBool  s3460 = false != s3459;
+  const SBool  s3461 = !s3460;
+  const SBool  s3462 = s3452 < s1;
+  const SBool  s3463 = s3452 < s3341;
+  const SBool  s3464 = s3462 || s3463;
+  const SWord8 s3465 = (s3452 >> 1) | (s3452 << 7);
+  const SWord8 s3466 = 128 | s3465;
+  const SWord8 s3467 = 127 & s3465;
+  const SWord8 s3468 = s3464 ? s3466 : s3467;
+  const SWord8 s3469 = (s3468 >> 1) | (s3468 << 7);
+  const SWord8 s3470 = 128 | s3469;
+  const SWord8 s3471 = 127 & s3469;
+  const SWord8 s3472 = s3081 ? s3470 : s3471;
+  const SWord8 s3473 = (s3472 >> 1) | (s3472 << 7);
+  const SWord8 s3474 = 128 | s3473;
+  const SWord8 s3475 = 127 & s3473;
+  const SWord8 s3476 = s3333 ? s3474 : s3475;
+  const SWord8 s3477 = (s3476 >> 1) | (s3476 << 7);
+  const SWord8 s3478 = 128 | s3477;
+  const SWord8 s3479 = 127 & s3477;
+  const SWord8 s3480 = s3460 ? s3478 : s3479;
+  const SWord8 s3481 = s1 + s3476;
+  const SBool  s3482 = s3481 < s1;
+  const SBool  s3483 = s3481 < s3476;
+  const SBool  s3484 = s3482 || s3483;
+  const SWord8 s3485 = (s3481 >> 1) | (s3481 << 7);
+  const SWord8 s3486 = 128 | s3485;
+  const SWord8 s3487 = 127 & s3485;
+  const SWord8 s3488 = s3484 ? s3486 : s3487;
+  const SWord8 s3489 = s3461 ? s3480 : s3488;
+  const SWord8 s3490 = s1 + s3472;
+  const SBool  s3491 = s3490 < s1;
+  const SBool  s3492 = s3490 < s3472;
+  const SBool  s3493 = s3491 || s3492;
+  const SWord8 s3494 = (s3490 >> 1) | (s3490 << 7);
+  const SWord8 s3495 = 128 | s3494;
+  const SWord8 s3496 = 127 & s3494;
+  const SWord8 s3497 = s3493 ? s3495 : s3496;
+  const SWord8 s3498 = (s3497 >> 1) | (s3497 << 7);
+  const SWord8 s3499 = 128 | s3498;
+  const SWord8 s3500 = 127 & s3498;
+  const SWord8 s3501 = s3460 ? s3499 : s3500;
+  const SWord8 s3502 = s1 + s3497;
+  const SBool  s3503 = s3502 < s1;
+  const SBool  s3504 = s3502 < s3497;
+  const SBool  s3505 = s3503 || s3504;
+  const SWord8 s3506 = (s3502 >> 1) | (s3502 << 7);
+  const SWord8 s3507 = 128 | s3506;
+  const SWord8 s3508 = 127 & s3506;
+  const SWord8 s3509 = s3505 ? s3507 : s3508;
+  const SWord8 s3510 = s3461 ? s3501 : s3509;
+  const SWord8 s3511 = s3334 ? s3489 : s3510;
+  const SWord8 s3512 = s1 + s3468;
+  const SBool  s3513 = s3512 < s1;
+  const SBool  s3514 = s3512 < s3468;
+  const SBool  s3515 = s3513 || s3514;
+  const SWord8 s3516 = (s3512 >> 1) | (s3512 << 7);
+  const SWord8 s3517 = 128 | s3516;
+  const SWord8 s3518 = 127 & s3516;
+  const SWord8 s3519 = s3515 ? s3517 : s3518;
+  const SWord8 s3520 = (s3519 >> 1) | (s3519 << 7);
+  const SWord8 s3521 = 128 | s3520;
+  const SWord8 s3522 = 127 & s3520;
+  const SWord8 s3523 = s3333 ? s3521 : s3522;
+  const SWord8 s3524 = (s3523 >> 1) | (s3523 << 7);
+  const SWord8 s3525 = 128 | s3524;
+  const SWord8 s3526 = 127 & s3524;
+  const SWord8 s3527 = s3460 ? s3525 : s3526;
+  const SWord8 s3528 = s1 + s3523;
+  const SBool  s3529 = s3528 < s1;
+  const SBool  s3530 = s3528 < s3523;
+  const SBool  s3531 = s3529 || s3530;
+  const SWord8 s3532 = (s3528 >> 1) | (s3528 << 7);
+  const SWord8 s3533 = 128 | s3532;
+  const SWord8 s3534 = 127 & s3532;
+  const SWord8 s3535 = s3531 ? s3533 : s3534;
+  const SWord8 s3536 = s3461 ? s3527 : s3535;
+  const SWord8 s3537 = s1 + s3519;
+  const SBool  s3538 = s3537 < s1;
+  const SBool  s3539 = s3537 < s3519;
+  const SBool  s3540 = s3538 || s3539;
+  const SWord8 s3541 = (s3537 >> 1) | (s3537 << 7);
+  const SWord8 s3542 = 128 | s3541;
+  const SWord8 s3543 = 127 & s3541;
+  const SWord8 s3544 = s3540 ? s3542 : s3543;
+  const SWord8 s3545 = (s3544 >> 1) | (s3544 << 7);
+  const SWord8 s3546 = 128 | s3545;
+  const SWord8 s3547 = 127 & s3545;
+  const SWord8 s3548 = s3460 ? s3546 : s3547;
+  const SWord8 s3549 = s1 + s3544;
+  const SBool  s3550 = s3549 < s1;
+  const SBool  s3551 = s3549 < s3544;
+  const SBool  s3552 = s3550 || s3551;
+  const SWord8 s3553 = (s3549 >> 1) | (s3549 << 7);
+  const SWord8 s3554 = 128 | s3553;
+  const SWord8 s3555 = 127 & s3553;
+  const SWord8 s3556 = s3552 ? s3554 : s3555;
+  const SWord8 s3557 = s3461 ? s3548 : s3556;
+  const SWord8 s3558 = s3334 ? s3536 : s3557;
+  const SWord8 s3559 = s3082 ? s3511 : s3558;
+  const SWord8 s3560 = s3060 ? s3451 : s3559;
+  const SWord8 s3561 = s2042 ? s3324 : s3560;
+  const SWord8 s3562 = s1 + s3067;
+  const SBool  s3563 = (SBool) (s3562 & 1);
+  const SBool  s3564 = false != s3563;
+  const SWord8 s3565 = s3564 ? s3071 : s3072;
+  const SBool  s3566 = (SBool) (s3565 & 1);
+  const SBool  s3567 = false != s3566;
+  const SWord8 s3568 = s3567 ? s3077 : s3078;
+  const SBool  s3569 = (SBool) (s3568 & 1);
+  const SBool  s3570 = false != s3569;
+  const SBool  s3571 = !s3570;
+  const SBool  s3572 = s3562 < s1;
+  const SBool  s3573 = s3562 < s3067;
+  const SBool  s3574 = s3572 || s3573;
+  const SWord8 s3575 = (s3562 >> 1) | (s3562 << 7);
+  const SWord8 s3576 = 128 | s3575;
+  const SWord8 s3577 = 127 & s3575;
+  const SWord8 s3578 = s3574 ? s3576 : s3577;
+  const SBool  s3579 = (SBool) (s3578 & 1);
+  const SBool  s3580 = false != s3579;
+  const SWord8 s3581 = (s3565 >> 1) | (s3565 << 7);
+  const SWord8 s3582 = 128 | s3581;
+  const SWord8 s3583 = 127 & s3581;
+  const SWord8 s3584 = s3580 ? s3582 : s3583;
+  const SBool  s3585 = (SBool) (s3584 & 1);
+  const SBool  s3586 = false != s3585;
+  const SWord8 s3587 = (s3568 >> 1) | (s3568 << 7);
+  const SWord8 s3588 = 128 | s3587;
+  const SWord8 s3589 = 127 & s3587;
+  const SWord8 s3590 = s3586 ? s3588 : s3589;
+  const SBool  s3591 = (SBool) (s3590 & 1);
+  const SBool  s3592 = false != s3591;
+  const SBool  s3593 = !s3592;
+  const SWord8 s3594 = (s3578 >> 1) | (s3578 << 7);
+  const SWord8 s3595 = 128 | s3594;
+  const SWord8 s3596 = 127 & s3594;
+  const SWord8 s3597 = s2041 ? s3595 : s3596;
+  const SBool  s3598 = (SBool) (s3597 & 1);
+  const SBool  s3599 = false != s3598;
+  const SWord8 s3600 = (s3584 >> 1) | (s3584 << 7);
+  const SWord8 s3601 = 128 | s3600;
+  const SWord8 s3602 = 127 & s3600;
+  const SWord8 s3603 = s3599 ? s3601 : s3602;
+  const SBool  s3604 = (SBool) (s3603 & 1);
+  const SBool  s3605 = false != s3604;
+  const SWord8 s3606 = (s3590 >> 1) | (s3590 << 7);
+  const SWord8 s3607 = 128 | s3606;
+  const SWord8 s3608 = 127 & s3606;
+  const SWord8 s3609 = s3605 ? s3607 : s3608;
+  const SBool  s3610 = (SBool) (s3609 & 1);
+  const SBool  s3611 = false != s3610;
+  const SBool  s3612 = !s3611;
+  const SWord8 s3613 = (s3597 >> 1) | (s3597 << 7);
+  const SWord8 s3614 = 128 | s3613;
+  const SWord8 s3615 = 127 & s3613;
+  const SWord8 s3616 = s3059 ? s3614 : s3615;
+  const SWord8 s3617 = (s3616 >> 1) | (s3616 << 7);
+  const SWord8 s3618 = 128 | s3617;
+  const SWord8 s3619 = 127 & s3617;
+  const SWord8 s3620 = s3570 ? s3618 : s3619;
+  const SWord8 s3621 = (s3620 >> 1) | (s3620 << 7);
+  const SWord8 s3622 = 128 | s3621;
+  const SWord8 s3623 = 127 & s3621;
+  const SWord8 s3624 = s3592 ? s3622 : s3623;
+  const SWord8 s3625 = (s3624 >> 1) | (s3624 << 7);
+  const SWord8 s3626 = 128 | s3625;
+  const SWord8 s3627 = 127 & s3625;
+  const SWord8 s3628 = s3611 ? s3626 : s3627;
+  const SWord8 s3629 = s1 + s3624;
+  const SBool  s3630 = s3629 < s1;
+  const SBool  s3631 = s3629 < s3624;
+  const SBool  s3632 = s3630 || s3631;
+  const SWord8 s3633 = (s3629 >> 1) | (s3629 << 7);
+  const SWord8 s3634 = 128 | s3633;
+  const SWord8 s3635 = 127 & s3633;
+  const SWord8 s3636 = s3632 ? s3634 : s3635;
+  const SWord8 s3637 = s3612 ? s3628 : s3636;
+  const SWord8 s3638 = s1 + s3620;
+  const SBool  s3639 = s3638 < s1;
+  const SBool  s3640 = s3638 < s3620;
+  const SBool  s3641 = s3639 || s3640;
+  const SWord8 s3642 = (s3638 >> 1) | (s3638 << 7);
+  const SWord8 s3643 = 128 | s3642;
+  const SWord8 s3644 = 127 & s3642;
+  const SWord8 s3645 = s3641 ? s3643 : s3644;
+  const SWord8 s3646 = (s3645 >> 1) | (s3645 << 7);
+  const SWord8 s3647 = 128 | s3646;
+  const SWord8 s3648 = 127 & s3646;
+  const SWord8 s3649 = s3611 ? s3647 : s3648;
+  const SWord8 s3650 = s1 + s3645;
+  const SBool  s3651 = s3650 < s1;
+  const SBool  s3652 = s3650 < s3645;
+  const SBool  s3653 = s3651 || s3652;
+  const SWord8 s3654 = (s3650 >> 1) | (s3650 << 7);
+  const SWord8 s3655 = 128 | s3654;
+  const SWord8 s3656 = 127 & s3654;
+  const SWord8 s3657 = s3653 ? s3655 : s3656;
+  const SWord8 s3658 = s3612 ? s3649 : s3657;
+  const SWord8 s3659 = s3593 ? s3637 : s3658;
+  const SWord8 s3660 = s1 + s3616;
+  const SBool  s3661 = s3660 < s1;
+  const SBool  s3662 = s3660 < s3616;
+  const SBool  s3663 = s3661 || s3662;
+  const SWord8 s3664 = (s3660 >> 1) | (s3660 << 7);
+  const SWord8 s3665 = 128 | s3664;
+  const SWord8 s3666 = 127 & s3664;
+  const SWord8 s3667 = s3663 ? s3665 : s3666;
+  const SWord8 s3668 = (s3667 >> 1) | (s3667 << 7);
+  const SWord8 s3669 = 128 | s3668;
+  const SWord8 s3670 = 127 & s3668;
+  const SWord8 s3671 = s3592 ? s3669 : s3670;
+  const SWord8 s3672 = (s3671 >> 1) | (s3671 << 7);
+  const SWord8 s3673 = 128 | s3672;
+  const SWord8 s3674 = 127 & s3672;
+  const SWord8 s3675 = s3611 ? s3673 : s3674;
+  const SWord8 s3676 = s1 + s3671;
+  const SBool  s3677 = s3676 < s1;
+  const SBool  s3678 = s3676 < s3671;
+  const SBool  s3679 = s3677 || s3678;
+  const SWord8 s3680 = (s3676 >> 1) | (s3676 << 7);
+  const SWord8 s3681 = 128 | s3680;
+  const SWord8 s3682 = 127 & s3680;
+  const SWord8 s3683 = s3679 ? s3681 : s3682;
+  const SWord8 s3684 = s3612 ? s3675 : s3683;
+  const SWord8 s3685 = s1 + s3667;
+  const SBool  s3686 = s3685 < s1;
+  const SBool  s3687 = s3685 < s3667;
+  const SBool  s3688 = s3686 || s3687;
+  const SWord8 s3689 = (s3685 >> 1) | (s3685 << 7);
+  const SWord8 s3690 = 128 | s3689;
+  const SWord8 s3691 = 127 & s3689;
+  const SWord8 s3692 = s3688 ? s3690 : s3691;
+  const SWord8 s3693 = (s3692 >> 1) | (s3692 << 7);
+  const SWord8 s3694 = 128 | s3693;
+  const SWord8 s3695 = 127 & s3693;
+  const SWord8 s3696 = s3611 ? s3694 : s3695;
+  const SWord8 s3697 = s1 + s3692;
+  const SBool  s3698 = s3697 < s1;
+  const SBool  s3699 = s3697 < s3692;
+  const SBool  s3700 = s3698 || s3699;
+  const SWord8 s3701 = (s3697 >> 1) | (s3697 << 7);
+  const SWord8 s3702 = 128 | s3701;
+  const SWord8 s3703 = 127 & s3701;
+  const SWord8 s3704 = s3700 ? s3702 : s3703;
+  const SWord8 s3705 = s3612 ? s3696 : s3704;
+  const SWord8 s3706 = s3593 ? s3684 : s3705;
+  const SWord8 s3707 = s3571 ? s3659 : s3706;
+  const SWord8 s3708 = s1 + s3597;
+  const SBool  s3709 = (SBool) (s3708 & 1);
+  const SBool  s3710 = false != s3709;
+  const SWord8 s3711 = s3710 ? s3601 : s3602;
+  const SBool  s3712 = (SBool) (s3711 & 1);
+  const SBool  s3713 = false != s3712;
+  const SWord8 s3714 = s3713 ? s3607 : s3608;
+  const SBool  s3715 = (SBool) (s3714 & 1);
+  const SBool  s3716 = false != s3715;
+  const SBool  s3717 = !s3716;
+  const SBool  s3718 = s3708 < s1;
+  const SBool  s3719 = s3708 < s3597;
+  const SBool  s3720 = s3718 || s3719;
+  const SWord8 s3721 = (s3708 >> 1) | (s3708 << 7);
+  const SWord8 s3722 = 128 | s3721;
+  const SWord8 s3723 = 127 & s3721;
+  const SWord8 s3724 = s3720 ? s3722 : s3723;
+  const SWord8 s3725 = (s3724 >> 1) | (s3724 << 7);
+  const SWord8 s3726 = 128 | s3725;
+  const SWord8 s3727 = 127 & s3725;
+  const SWord8 s3728 = s3570 ? s3726 : s3727;
+  const SWord8 s3729 = (s3728 >> 1) | (s3728 << 7);
+  const SWord8 s3730 = 128 | s3729;
+  const SWord8 s3731 = 127 & s3729;
+  const SWord8 s3732 = s3592 ? s3730 : s3731;
+  const SWord8 s3733 = (s3732 >> 1) | (s3732 << 7);
+  const SWord8 s3734 = 128 | s3733;
+  const SWord8 s3735 = 127 & s3733;
+  const SWord8 s3736 = s3716 ? s3734 : s3735;
+  const SWord8 s3737 = s1 + s3732;
+  const SBool  s3738 = s3737 < s1;
+  const SBool  s3739 = s3737 < s3732;
+  const SBool  s3740 = s3738 || s3739;
+  const SWord8 s3741 = (s3737 >> 1) | (s3737 << 7);
+  const SWord8 s3742 = 128 | s3741;
+  const SWord8 s3743 = 127 & s3741;
+  const SWord8 s3744 = s3740 ? s3742 : s3743;
+  const SWord8 s3745 = s3717 ? s3736 : s3744;
+  const SWord8 s3746 = s1 + s3728;
+  const SBool  s3747 = s3746 < s1;
+  const SBool  s3748 = s3746 < s3728;
+  const SBool  s3749 = s3747 || s3748;
+  const SWord8 s3750 = (s3746 >> 1) | (s3746 << 7);
+  const SWord8 s3751 = 128 | s3750;
+  const SWord8 s3752 = 127 & s3750;
+  const SWord8 s3753 = s3749 ? s3751 : s3752;
+  const SWord8 s3754 = (s3753 >> 1) | (s3753 << 7);
+  const SWord8 s3755 = 128 | s3754;
+  const SWord8 s3756 = 127 & s3754;
+  const SWord8 s3757 = s3716 ? s3755 : s3756;
+  const SWord8 s3758 = s1 + s3753;
+  const SBool  s3759 = s3758 < s1;
+  const SBool  s3760 = s3758 < s3753;
+  const SBool  s3761 = s3759 || s3760;
+  const SWord8 s3762 = (s3758 >> 1) | (s3758 << 7);
+  const SWord8 s3763 = 128 | s3762;
+  const SWord8 s3764 = 127 & s3762;
+  const SWord8 s3765 = s3761 ? s3763 : s3764;
+  const SWord8 s3766 = s3717 ? s3757 : s3765;
+  const SWord8 s3767 = s3593 ? s3745 : s3766;
+  const SWord8 s3768 = s1 + s3724;
+  const SBool  s3769 = s3768 < s1;
+  const SBool  s3770 = s3768 < s3724;
+  const SBool  s3771 = s3769 || s3770;
+  const SWord8 s3772 = (s3768 >> 1) | (s3768 << 7);
+  const SWord8 s3773 = 128 | s3772;
+  const SWord8 s3774 = 127 & s3772;
+  const SWord8 s3775 = s3771 ? s3773 : s3774;
+  const SWord8 s3776 = (s3775 >> 1) | (s3775 << 7);
+  const SWord8 s3777 = 128 | s3776;
+  const SWord8 s3778 = 127 & s3776;
+  const SWord8 s3779 = s3592 ? s3777 : s3778;
+  const SWord8 s3780 = (s3779 >> 1) | (s3779 << 7);
+  const SWord8 s3781 = 128 | s3780;
+  const SWord8 s3782 = 127 & s3780;
+  const SWord8 s3783 = s3716 ? s3781 : s3782;
+  const SWord8 s3784 = s1 + s3779;
+  const SBool  s3785 = s3784 < s1;
+  const SBool  s3786 = s3784 < s3779;
+  const SBool  s3787 = s3785 || s3786;
+  const SWord8 s3788 = (s3784 >> 1) | (s3784 << 7);
+  const SWord8 s3789 = 128 | s3788;
+  const SWord8 s3790 = 127 & s3788;
+  const SWord8 s3791 = s3787 ? s3789 : s3790;
+  const SWord8 s3792 = s3717 ? s3783 : s3791;
+  const SWord8 s3793 = s1 + s3775;
+  const SBool  s3794 = s3793 < s1;
+  const SBool  s3795 = s3793 < s3775;
+  const SBool  s3796 = s3794 || s3795;
+  const SWord8 s3797 = (s3793 >> 1) | (s3793 << 7);
+  const SWord8 s3798 = 128 | s3797;
+  const SWord8 s3799 = 127 & s3797;
+  const SWord8 s3800 = s3796 ? s3798 : s3799;
+  const SWord8 s3801 = (s3800 >> 1) | (s3800 << 7);
+  const SWord8 s3802 = 128 | s3801;
+  const SWord8 s3803 = 127 & s3801;
+  const SWord8 s3804 = s3716 ? s3802 : s3803;
+  const SWord8 s3805 = s1 + s3800;
+  const SBool  s3806 = s3805 < s1;
+  const SBool  s3807 = s3805 < s3800;
+  const SBool  s3808 = s3806 || s3807;
+  const SWord8 s3809 = (s3805 >> 1) | (s3805 << 7);
+  const SWord8 s3810 = 128 | s3809;
+  const SWord8 s3811 = 127 & s3809;
+  const SWord8 s3812 = s3808 ? s3810 : s3811;
+  const SWord8 s3813 = s3717 ? s3804 : s3812;
+  const SWord8 s3814 = s3593 ? s3792 : s3813;
+  const SWord8 s3815 = s3571 ? s3767 : s3814;
+  const SWord8 s3816 = s3060 ? s3707 : s3815;
+  const SWord8 s3817 = s1 + s3578;
+  const SBool  s3818 = (SBool) (s3817 & 1);
+  const SBool  s3819 = false != s3818;
+  const SWord8 s3820 = s3819 ? s3582 : s3583;
+  const SBool  s3821 = (SBool) (s3820 & 1);
+  const SBool  s3822 = false != s3821;
+  const SWord8 s3823 = s3822 ? s3588 : s3589;
+  const SBool  s3824 = (SBool) (s3823 & 1);
+  const SBool  s3825 = false != s3824;
+  const SBool  s3826 = !s3825;
+  const SBool  s3827 = s3817 < s1;
+  const SBool  s3828 = s3817 < s3578;
+  const SBool  s3829 = s3827 || s3828;
+  const SWord8 s3830 = (s3817 >> 1) | (s3817 << 7);
+  const SWord8 s3831 = 128 | s3830;
+  const SWord8 s3832 = 127 & s3830;
+  const SWord8 s3833 = s3829 ? s3831 : s3832;
+  const SBool  s3834 = (SBool) (s3833 & 1);
+  const SBool  s3835 = false != s3834;
+  const SWord8 s3836 = (s3820 >> 1) | (s3820 << 7);
+  const SWord8 s3837 = 128 | s3836;
+  const SWord8 s3838 = 127 & s3836;
+  const SWord8 s3839 = s3835 ? s3837 : s3838;
+  const SBool  s3840 = (SBool) (s3839 & 1);
+  const SBool  s3841 = false != s3840;
+  const SWord8 s3842 = (s3823 >> 1) | (s3823 << 7);
+  const SWord8 s3843 = 128 | s3842;
+  const SWord8 s3844 = 127 & s3842;
+  const SWord8 s3845 = s3841 ? s3843 : s3844;
+  const SBool  s3846 = (SBool) (s3845 & 1);
+  const SBool  s3847 = false != s3846;
+  const SBool  s3848 = !s3847;
+  const SWord8 s3849 = (s3833 >> 1) | (s3833 << 7);
+  const SWord8 s3850 = 128 | s3849;
+  const SWord8 s3851 = 127 & s3849;
+  const SWord8 s3852 = s3059 ? s3850 : s3851;
+  const SWord8 s3853 = (s3852 >> 1) | (s3852 << 7);
+  const SWord8 s3854 = 128 | s3853;
+  const SWord8 s3855 = 127 & s3853;
+  const SWord8 s3856 = s3570 ? s3854 : s3855;
+  const SWord8 s3857 = (s3856 >> 1) | (s3856 << 7);
+  const SWord8 s3858 = 128 | s3857;
+  const SWord8 s3859 = 127 & s3857;
+  const SWord8 s3860 = s3825 ? s3858 : s3859;
+  const SWord8 s3861 = (s3860 >> 1) | (s3860 << 7);
+  const SWord8 s3862 = 128 | s3861;
+  const SWord8 s3863 = 127 & s3861;
+  const SWord8 s3864 = s3847 ? s3862 : s3863;
+  const SWord8 s3865 = s1 + s3860;
+  const SBool  s3866 = s3865 < s1;
+  const SBool  s3867 = s3865 < s3860;
+  const SBool  s3868 = s3866 || s3867;
+  const SWord8 s3869 = (s3865 >> 1) | (s3865 << 7);
+  const SWord8 s3870 = 128 | s3869;
+  const SWord8 s3871 = 127 & s3869;
+  const SWord8 s3872 = s3868 ? s3870 : s3871;
+  const SWord8 s3873 = s3848 ? s3864 : s3872;
+  const SWord8 s3874 = s1 + s3856;
+  const SBool  s3875 = s3874 < s1;
+  const SBool  s3876 = s3874 < s3856;
+  const SBool  s3877 = s3875 || s3876;
+  const SWord8 s3878 = (s3874 >> 1) | (s3874 << 7);
+  const SWord8 s3879 = 128 | s3878;
+  const SWord8 s3880 = 127 & s3878;
+  const SWord8 s3881 = s3877 ? s3879 : s3880;
+  const SWord8 s3882 = (s3881 >> 1) | (s3881 << 7);
+  const SWord8 s3883 = 128 | s3882;
+  const SWord8 s3884 = 127 & s3882;
+  const SWord8 s3885 = s3847 ? s3883 : s3884;
+  const SWord8 s3886 = s1 + s3881;
+  const SBool  s3887 = s3886 < s1;
+  const SBool  s3888 = s3886 < s3881;
+  const SBool  s3889 = s3887 || s3888;
+  const SWord8 s3890 = (s3886 >> 1) | (s3886 << 7);
+  const SWord8 s3891 = 128 | s3890;
+  const SWord8 s3892 = 127 & s3890;
+  const SWord8 s3893 = s3889 ? s3891 : s3892;
+  const SWord8 s3894 = s3848 ? s3885 : s3893;
+  const SWord8 s3895 = s3826 ? s3873 : s3894;
+  const SWord8 s3896 = s1 + s3852;
+  const SBool  s3897 = s3896 < s1;
+  const SBool  s3898 = s3896 < s3852;
+  const SBool  s3899 = s3897 || s3898;
+  const SWord8 s3900 = (s3896 >> 1) | (s3896 << 7);
+  const SWord8 s3901 = 128 | s3900;
+  const SWord8 s3902 = 127 & s3900;
+  const SWord8 s3903 = s3899 ? s3901 : s3902;
+  const SWord8 s3904 = (s3903 >> 1) | (s3903 << 7);
+  const SWord8 s3905 = 128 | s3904;
+  const SWord8 s3906 = 127 & s3904;
+  const SWord8 s3907 = s3825 ? s3905 : s3906;
+  const SWord8 s3908 = (s3907 >> 1) | (s3907 << 7);
+  const SWord8 s3909 = 128 | s3908;
+  const SWord8 s3910 = 127 & s3908;
+  const SWord8 s3911 = s3847 ? s3909 : s3910;
+  const SWord8 s3912 = s1 + s3907;
+  const SBool  s3913 = s3912 < s1;
+  const SBool  s3914 = s3912 < s3907;
+  const SBool  s3915 = s3913 || s3914;
+  const SWord8 s3916 = (s3912 >> 1) | (s3912 << 7);
+  const SWord8 s3917 = 128 | s3916;
+  const SWord8 s3918 = 127 & s3916;
+  const SWord8 s3919 = s3915 ? s3917 : s3918;
+  const SWord8 s3920 = s3848 ? s3911 : s3919;
+  const SWord8 s3921 = s1 + s3903;
+  const SBool  s3922 = s3921 < s1;
+  const SBool  s3923 = s3921 < s3903;
+  const SBool  s3924 = s3922 || s3923;
+  const SWord8 s3925 = (s3921 >> 1) | (s3921 << 7);
+  const SWord8 s3926 = 128 | s3925;
+  const SWord8 s3927 = 127 & s3925;
+  const SWord8 s3928 = s3924 ? s3926 : s3927;
+  const SWord8 s3929 = (s3928 >> 1) | (s3928 << 7);
+  const SWord8 s3930 = 128 | s3929;
+  const SWord8 s3931 = 127 & s3929;
+  const SWord8 s3932 = s3847 ? s3930 : s3931;
+  const SWord8 s3933 = s1 + s3928;
+  const SBool  s3934 = s3933 < s1;
+  const SBool  s3935 = s3933 < s3928;
+  const SBool  s3936 = s3934 || s3935;
+  const SWord8 s3937 = (s3933 >> 1) | (s3933 << 7);
+  const SWord8 s3938 = 128 | s3937;
+  const SWord8 s3939 = 127 & s3937;
+  const SWord8 s3940 = s3936 ? s3938 : s3939;
+  const SWord8 s3941 = s3848 ? s3932 : s3940;
+  const SWord8 s3942 = s3826 ? s3920 : s3941;
+  const SWord8 s3943 = s3571 ? s3895 : s3942;
+  const SWord8 s3944 = s1 + s3833;
+  const SBool  s3945 = (SBool) (s3944 & 1);
+  const SBool  s3946 = false != s3945;
+  const SWord8 s3947 = s3946 ? s3837 : s3838;
+  const SBool  s3948 = (SBool) (s3947 & 1);
+  const SBool  s3949 = false != s3948;
+  const SWord8 s3950 = s3949 ? s3843 : s3844;
+  const SBool  s3951 = (SBool) (s3950 & 1);
+  const SBool  s3952 = false != s3951;
+  const SBool  s3953 = !s3952;
+  const SBool  s3954 = s3944 < s1;
+  const SBool  s3955 = s3944 < s3833;
+  const SBool  s3956 = s3954 || s3955;
+  const SWord8 s3957 = (s3944 >> 1) | (s3944 << 7);
+  const SWord8 s3958 = 128 | s3957;
+  const SWord8 s3959 = 127 & s3957;
+  const SWord8 s3960 = s3956 ? s3958 : s3959;
+  const SWord8 s3961 = (s3960 >> 1) | (s3960 << 7);
+  const SWord8 s3962 = 128 | s3961;
+  const SWord8 s3963 = 127 & s3961;
+  const SWord8 s3964 = s3570 ? s3962 : s3963;
+  const SWord8 s3965 = (s3964 >> 1) | (s3964 << 7);
+  const SWord8 s3966 = 128 | s3965;
+  const SWord8 s3967 = 127 & s3965;
+  const SWord8 s3968 = s3825 ? s3966 : s3967;
+  const SWord8 s3969 = (s3968 >> 1) | (s3968 << 7);
+  const SWord8 s3970 = 128 | s3969;
+  const SWord8 s3971 = 127 & s3969;
+  const SWord8 s3972 = s3952 ? s3970 : s3971;
+  const SWord8 s3973 = s1 + s3968;
+  const SBool  s3974 = s3973 < s1;
+  const SBool  s3975 = s3973 < s3968;
+  const SBool  s3976 = s3974 || s3975;
+  const SWord8 s3977 = (s3973 >> 1) | (s3973 << 7);
+  const SWord8 s3978 = 128 | s3977;
+  const SWord8 s3979 = 127 & s3977;
+  const SWord8 s3980 = s3976 ? s3978 : s3979;
+  const SWord8 s3981 = s3953 ? s3972 : s3980;
+  const SWord8 s3982 = s1 + s3964;
+  const SBool  s3983 = s3982 < s1;
+  const SBool  s3984 = s3982 < s3964;
+  const SBool  s3985 = s3983 || s3984;
+  const SWord8 s3986 = (s3982 >> 1) | (s3982 << 7);
+  const SWord8 s3987 = 128 | s3986;
+  const SWord8 s3988 = 127 & s3986;
+  const SWord8 s3989 = s3985 ? s3987 : s3988;
+  const SWord8 s3990 = (s3989 >> 1) | (s3989 << 7);
+  const SWord8 s3991 = 128 | s3990;
+  const SWord8 s3992 = 127 & s3990;
+  const SWord8 s3993 = s3952 ? s3991 : s3992;
+  const SWord8 s3994 = s1 + s3989;
+  const SBool  s3995 = s3994 < s1;
+  const SBool  s3996 = s3994 < s3989;
+  const SBool  s3997 = s3995 || s3996;
+  const SWord8 s3998 = (s3994 >> 1) | (s3994 << 7);
+  const SWord8 s3999 = 128 | s3998;
+  const SWord8 s4000 = 127 & s3998;
+  const SWord8 s4001 = s3997 ? s3999 : s4000;
+  const SWord8 s4002 = s3953 ? s3993 : s4001;
+  const SWord8 s4003 = s3826 ? s3981 : s4002;
+  const SWord8 s4004 = s1 + s3960;
+  const SBool  s4005 = s4004 < s1;
+  const SBool  s4006 = s4004 < s3960;
+  const SBool  s4007 = s4005 || s4006;
+  const SWord8 s4008 = (s4004 >> 1) | (s4004 << 7);
+  const SWord8 s4009 = 128 | s4008;
+  const SWord8 s4010 = 127 & s4008;
+  const SWord8 s4011 = s4007 ? s4009 : s4010;
+  const SWord8 s4012 = (s4011 >> 1) | (s4011 << 7);
+  const SWord8 s4013 = 128 | s4012;
+  const SWord8 s4014 = 127 & s4012;
+  const SWord8 s4015 = s3825 ? s4013 : s4014;
+  const SWord8 s4016 = (s4015 >> 1) | (s4015 << 7);
+  const SWord8 s4017 = 128 | s4016;
+  const SWord8 s4018 = 127 & s4016;
+  const SWord8 s4019 = s3952 ? s4017 : s4018;
+  const SWord8 s4020 = s1 + s4015;
+  const SBool  s4021 = s4020 < s1;
+  const SBool  s4022 = s4020 < s4015;
+  const SBool  s4023 = s4021 || s4022;
+  const SWord8 s4024 = (s4020 >> 1) | (s4020 << 7);
+  const SWord8 s4025 = 128 | s4024;
+  const SWord8 s4026 = 127 & s4024;
+  const SWord8 s4027 = s4023 ? s4025 : s4026;
+  const SWord8 s4028 = s3953 ? s4019 : s4027;
+  const SWord8 s4029 = s1 + s4011;
+  const SBool  s4030 = s4029 < s1;
+  const SBool  s4031 = s4029 < s4011;
+  const SBool  s4032 = s4030 || s4031;
+  const SWord8 s4033 = (s4029 >> 1) | (s4029 << 7);
+  const SWord8 s4034 = 128 | s4033;
+  const SWord8 s4035 = 127 & s4033;
+  const SWord8 s4036 = s4032 ? s4034 : s4035;
+  const SWord8 s4037 = (s4036 >> 1) | (s4036 << 7);
+  const SWord8 s4038 = 128 | s4037;
+  const SWord8 s4039 = 127 & s4037;
+  const SWord8 s4040 = s3952 ? s4038 : s4039;
+  const SWord8 s4041 = s1 + s4036;
+  const SBool  s4042 = s4041 < s1;
+  const SBool  s4043 = s4041 < s4036;
+  const SBool  s4044 = s4042 || s4043;
+  const SWord8 s4045 = (s4041 >> 1) | (s4041 << 7);
+  const SWord8 s4046 = 128 | s4045;
+  const SWord8 s4047 = 127 & s4045;
+  const SWord8 s4048 = s4044 ? s4046 : s4047;
+  const SWord8 s4049 = s3953 ? s4040 : s4048;
+  const SWord8 s4050 = s3826 ? s4028 : s4049;
+  const SWord8 s4051 = s3571 ? s4003 : s4050;
+  const SWord8 s4052 = s3060 ? s3943 : s4051;
+  const SWord8 s4053 = s2042 ? s3816 : s4052;
+  const SWord8 s4054 = s16 ? s3561 : s4053;
+  const SWord8 s4055 = s11 ? s3050 : s4054;
+  const SWord8 s4056 = s5 ? s2032 : s4055;
+  const SBool  s4057 = (SBool) (s105 & 1);
+  const SBool  s4058 = false != s4057;
+  const SBool  s4059 = (SBool) (s101 & 1);
+  const SBool  s4060 = false != s4059;
+  const SBool  s4061 = (SBool) (s97 & 1);
+  const SBool  s4062 = false != s4061;
+  const SWord8 s4063 = (s84 >> 1) | (s84 << 7);
+  const SWord8 s4064 = 128 | s4063;
+  const SWord8 s4065 = 127 & s4063;
+  const SWord8 s4066 = s4062 ? s4064 : s4065;
+  const SWord8 s4067 = (s4066 >> 1) | (s4066 << 7);
+  const SWord8 s4068 = 128 | s4067;
+  const SWord8 s4069 = 127 & s4067;
+  const SWord8 s4070 = s4060 ? s4068 : s4069;
+  const SWord8 s4071 = (s4070 >> 1) | (s4070 << 7);
+  const SWord8 s4072 = 128 | s4071;
+  const SWord8 s4073 = 127 & s4071;
+  const SWord8 s4074 = s4058 ? s4072 : s4073;
+  const SBool  s4075 = (SBool) (s110 & 1);
+  const SBool  s4076 = false != s4075;
+  const SWord8 s4077 = s4076 ? s4072 : s4073;
+  const SWord8 s4078 = s93 ? s4074 : s4077;
+  const SBool  s4079 = (SBool) (s126 & 1);
+  const SBool  s4080 = false != s4079;
+  const SBool  s4081 = (SBool) (s119 & 1);
+  const SBool  s4082 = false != s4081;
+  const SWord8 s4083 = s4082 ? s4068 : s4069;
+  const SWord8 s4084 = (s4083 >> 1) | (s4083 << 7);
+  const SWord8 s4085 = 128 | s4084;
+  const SWord8 s4086 = 127 & s4084;
+  const SWord8 s4087 = s4080 ? s4085 : s4086;
+  const SBool  s4088 = (SBool) (s131 & 1);
+  const SBool  s4089 = false != s4088;
+  const SWord8 s4090 = s4089 ? s4085 : s4086;
+  const SWord8 s4091 = s93 ? s4087 : s4090;
+  const SWord8 s4092 = s74 ? s4078 : s4091;
+  const SBool  s4093 = (SBool) (s152 & 1);
+  const SBool  s4094 = false != s4093;
+  const SBool  s4095 = (SBool) (s148 & 1);
+  const SBool  s4096 = false != s4095;
+  const SBool  s4097 = (SBool) (s141 & 1);
+  const SBool  s4098 = false != s4097;
+  const SWord8 s4099 = s4098 ? s4064 : s4065;
+  const SWord8 s4100 = (s4099 >> 1) | (s4099 << 7);
+  const SWord8 s4101 = 128 | s4100;
+  const SWord8 s4102 = 127 & s4100;
+  const SWord8 s4103 = s4096 ? s4101 : s4102;
+  const SWord8 s4104 = (s4103 >> 1) | (s4103 << 7);
+  const SWord8 s4105 = 128 | s4104;
+  const SWord8 s4106 = 127 & s4104;
+  const SWord8 s4107 = s4094 ? s4105 : s4106;
+  const SBool  s4108 = (SBool) (s157 & 1);
+  const SBool  s4109 = false != s4108;
+  const SWord8 s4110 = s4109 ? s4105 : s4106;
+  const SWord8 s4111 = s93 ? s4107 : s4110;
+  const SBool  s4112 = (SBool) (s173 & 1);
+  const SBool  s4113 = false != s4112;
+  const SBool  s4114 = (SBool) (s166 & 1);
+  const SBool  s4115 = false != s4114;
+  const SWord8 s4116 = s4115 ? s4101 : s4102;
+  const SWord8 s4117 = (s4116 >> 1) | (s4116 << 7);
+  const SWord8 s4118 = 128 | s4117;
+  const SWord8 s4119 = 127 & s4117;
+  const SWord8 s4120 = s4113 ? s4118 : s4119;
+  const SBool  s4121 = (SBool) (s178 & 1);
+  const SBool  s4122 = false != s4121;
+  const SWord8 s4123 = s4122 ? s4118 : s4119;
+  const SWord8 s4124 = s93 ? s4120 : s4123;
+  const SWord8 s4125 = s74 ? s4111 : s4124;
+  const SWord8 s4126 = s55 ? s4092 : s4125;
+  const SBool  s4127 = (SBool) (s213 & 1);
+  const SBool  s4128 = false != s4127;
+  const SBool  s4129 = (SBool) (s209 & 1);
+  const SBool  s4130 = false != s4129;
+  const SBool  s4131 = (SBool) (s205 & 1);
+  const SBool  s4132 = false != s4131;
+  const SWord8 s4133 = (s192 >> 1) | (s192 << 7);
+  const SWord8 s4134 = 128 | s4133;
+  const SWord8 s4135 = 127 & s4133;
+  const SWord8 s4136 = s4132 ? s4134 : s4135;
+  const SWord8 s4137 = (s4136 >> 1) | (s4136 << 7);
+  const SWord8 s4138 = 128 | s4137;
+  const SWord8 s4139 = 127 & s4137;
+  const SWord8 s4140 = s4130 ? s4138 : s4139;
+  const SWord8 s4141 = (s4140 >> 1) | (s4140 << 7);
+  const SWord8 s4142 = 128 | s4141;
+  const SWord8 s4143 = 127 & s4141;
+  const SWord8 s4144 = s4128 ? s4142 : s4143;
+  const SBool  s4145 = (SBool) (s218 & 1);
+  const SBool  s4146 = false != s4145;
+  const SWord8 s4147 = s4146 ? s4142 : s4143;
+  const SWord8 s4148 = s198 ? s4144 : s4147;
+  const SBool  s4149 = (SBool) (s234 & 1);
+  const SBool  s4150 = false != s4149;
+  const SBool  s4151 = (SBool) (s227 & 1);
+  const SBool  s4152 = false != s4151;
+  const SWord8 s4153 = s4152 ? s4138 : s4139;
+  const SWord8 s4154 = (s4153 >> 1) | (s4153 << 7);
+  const SWord8 s4155 = 128 | s4154;
+  const SWord8 s4156 = 127 & s4154;
+  const SWord8 s4157 = s4150 ? s4155 : s4156;
+  const SBool  s4158 = (SBool) (s239 & 1);
+  const SBool  s4159 = false != s4158;
+  const SWord8 s4160 = s4159 ? s4155 : s4156;
+  const SWord8 s4161 = s198 ? s4157 : s4160;
+  const SWord8 s4162 = s74 ? s4148 : s4161;
+  const SBool  s4163 = (SBool) (s260 & 1);
+  const SBool  s4164 = false != s4163;
+  const SBool  s4165 = (SBool) (s256 & 1);
+  const SBool  s4166 = false != s4165;
+  const SBool  s4167 = (SBool) (s249 & 1);
+  const SBool  s4168 = false != s4167;
+  const SWord8 s4169 = s4168 ? s4134 : s4135;
+  const SWord8 s4170 = (s4169 >> 1) | (s4169 << 7);
+  const SWord8 s4171 = 128 | s4170;
+  const SWord8 s4172 = 127 & s4170;
+  const SWord8 s4173 = s4166 ? s4171 : s4172;
+  const SWord8 s4174 = (s4173 >> 1) | (s4173 << 7);
+  const SWord8 s4175 = 128 | s4174;
+  const SWord8 s4176 = 127 & s4174;
+  const SWord8 s4177 = s4164 ? s4175 : s4176;
+  const SBool  s4178 = (SBool) (s265 & 1);
+  const SBool  s4179 = false != s4178;
+  const SWord8 s4180 = s4179 ? s4175 : s4176;
+  const SWord8 s4181 = s198 ? s4177 : s4180;
+  const SBool  s4182 = (SBool) (s281 & 1);
+  const SBool  s4183 = false != s4182;
+  const SBool  s4184 = (SBool) (s274 & 1);
+  const SBool  s4185 = false != s4184;
+  const SWord8 s4186 = s4185 ? s4171 : s4172;
+  const SWord8 s4187 = (s4186 >> 1) | (s4186 << 7);
+  const SWord8 s4188 = 128 | s4187;
+  const SWord8 s4189 = 127 & s4187;
+  const SWord8 s4190 = s4183 ? s4188 : s4189;
+  const SBool  s4191 = (SBool) (s286 & 1);
+  const SBool  s4192 = false != s4191;
+  const SWord8 s4193 = s4192 ? s4188 : s4189;
+  const SWord8 s4194 = s198 ? s4190 : s4193;
+  const SWord8 s4195 = s74 ? s4181 : s4194;
+  const SWord8 s4196 = s55 ? s4162 : s4195;
+  const SWord8 s4197 = s36 ? s4126 : s4196;
+  const SBool  s4198 = (SBool) (s341 & 1);
+  const SBool  s4199 = false != s4198;
+  const SBool  s4200 = (SBool) (s337 & 1);
+  const SBool  s4201 = false != s4200;
+  const SBool  s4202 = (SBool) (s333 & 1);
+  const SBool  s4203 = false != s4202;
+  const SWord8 s4204 = (s320 >> 1) | (s320 << 7);
+  const SWord8 s4205 = 128 | s4204;
+  const SWord8 s4206 = 127 & s4204;
+  const SWord8 s4207 = s4203 ? s4205 : s4206;
+  const SWord8 s4208 = (s4207 >> 1) | (s4207 << 7);
+  const SWord8 s4209 = 128 | s4208;
+  const SWord8 s4210 = 127 & s4208;
+  const SWord8 s4211 = s4201 ? s4209 : s4210;
+  const SWord8 s4212 = (s4211 >> 1) | (s4211 << 7);
+  const SWord8 s4213 = 128 | s4212;
+  const SWord8 s4214 = 127 & s4212;
+  const SWord8 s4215 = s4199 ? s4213 : s4214;
+  const SBool  s4216 = (SBool) (s346 & 1);
+  const SBool  s4217 = false != s4216;
+  const SWord8 s4218 = s4217 ? s4213 : s4214;
+  const SWord8 s4219 = s329 ? s4215 : s4218;
+  const SBool  s4220 = (SBool) (s362 & 1);
+  const SBool  s4221 = false != s4220;
+  const SBool  s4222 = (SBool) (s355 & 1);
+  const SBool  s4223 = false != s4222;
+  const SWord8 s4224 = s4223 ? s4209 : s4210;
+  const SWord8 s4225 = (s4224 >> 1) | (s4224 << 7);
+  const SWord8 s4226 = 128 | s4225;
+  const SWord8 s4227 = 127 & s4225;
+  const SWord8 s4228 = s4221 ? s4226 : s4227;
+  const SBool  s4229 = (SBool) (s367 & 1);
+  const SBool  s4230 = false != s4229;
+  const SWord8 s4231 = s4230 ? s4226 : s4227;
+  const SWord8 s4232 = s329 ? s4228 : s4231;
+  const SWord8 s4233 = s307 ? s4219 : s4232;
+  const SBool  s4234 = (SBool) (s388 & 1);
+  const SBool  s4235 = false != s4234;
+  const SBool  s4236 = (SBool) (s384 & 1);
+  const SBool  s4237 = false != s4236;
+  const SBool  s4238 = (SBool) (s377 & 1);
+  const SBool  s4239 = false != s4238;
+  const SWord8 s4240 = s4239 ? s4205 : s4206;
+  const SWord8 s4241 = (s4240 >> 1) | (s4240 << 7);
+  const SWord8 s4242 = 128 | s4241;
+  const SWord8 s4243 = 127 & s4241;
+  const SWord8 s4244 = s4237 ? s4242 : s4243;
+  const SWord8 s4245 = (s4244 >> 1) | (s4244 << 7);
+  const SWord8 s4246 = 128 | s4245;
+  const SWord8 s4247 = 127 & s4245;
+  const SWord8 s4248 = s4235 ? s4246 : s4247;
+  const SBool  s4249 = (SBool) (s393 & 1);
+  const SBool  s4250 = false != s4249;
+  const SWord8 s4251 = s4250 ? s4246 : s4247;
+  const SWord8 s4252 = s329 ? s4248 : s4251;
+  const SBool  s4253 = (SBool) (s409 & 1);
+  const SBool  s4254 = false != s4253;
+  const SBool  s4255 = (SBool) (s402 & 1);
+  const SBool  s4256 = false != s4255;
+  const SWord8 s4257 = s4256 ? s4242 : s4243;
+  const SWord8 s4258 = (s4257 >> 1) | (s4257 << 7);
+  const SWord8 s4259 = 128 | s4258;
+  const SWord8 s4260 = 127 & s4258;
+  const SWord8 s4261 = s4254 ? s4259 : s4260;
+  const SBool  s4262 = (SBool) (s414 & 1);
+  const SBool  s4263 = false != s4262;
+  const SWord8 s4264 = s4263 ? s4259 : s4260;
+  const SWord8 s4265 = s329 ? s4261 : s4264;
+  const SWord8 s4266 = s307 ? s4252 : s4265;
+  const SWord8 s4267 = s55 ? s4233 : s4266;
+  const SBool  s4268 = (SBool) (s449 & 1);
+  const SBool  s4269 = false != s4268;
+  const SBool  s4270 = (SBool) (s445 & 1);
+  const SBool  s4271 = false != s4270;
+  const SBool  s4272 = (SBool) (s441 & 1);
+  const SBool  s4273 = false != s4272;
+  const SWord8 s4274 = (s428 >> 1) | (s428 << 7);
+  const SWord8 s4275 = 128 | s4274;
+  const SWord8 s4276 = 127 & s4274;
+  const SWord8 s4277 = s4273 ? s4275 : s4276;
+  const SWord8 s4278 = (s4277 >> 1) | (s4277 << 7);
+  const SWord8 s4279 = 128 | s4278;
+  const SWord8 s4280 = 127 & s4278;
+  const SWord8 s4281 = s4271 ? s4279 : s4280;
+  const SWord8 s4282 = (s4281 >> 1) | (s4281 << 7);
+  const SWord8 s4283 = 128 | s4282;
+  const SWord8 s4284 = 127 & s4282;
+  const SWord8 s4285 = s4269 ? s4283 : s4284;
+  const SBool  s4286 = (SBool) (s454 & 1);
+  const SBool  s4287 = false != s4286;
+  const SWord8 s4288 = s4287 ? s4283 : s4284;
+  const SWord8 s4289 = s434 ? s4285 : s4288;
+  const SBool  s4290 = (SBool) (s470 & 1);
+  const SBool  s4291 = false != s4290;
+  const SBool  s4292 = (SBool) (s463 & 1);
+  const SBool  s4293 = false != s4292;
+  const SWord8 s4294 = s4293 ? s4279 : s4280;
+  const SWord8 s4295 = (s4294 >> 1) | (s4294 << 7);
+  const SWord8 s4296 = 128 | s4295;
+  const SWord8 s4297 = 127 & s4295;
+  const SWord8 s4298 = s4291 ? s4296 : s4297;
+  const SBool  s4299 = (SBool) (s475 & 1);
+  const SBool  s4300 = false != s4299;
+  const SWord8 s4301 = s4300 ? s4296 : s4297;
+  const SWord8 s4302 = s434 ? s4298 : s4301;
+  const SWord8 s4303 = s307 ? s4289 : s4302;
+  const SBool  s4304 = (SBool) (s496 & 1);
+  const SBool  s4305 = false != s4304;
+  const SBool  s4306 = (SBool) (s492 & 1);
+  const SBool  s4307 = false != s4306;
+  const SBool  s4308 = (SBool) (s485 & 1);
+  const SBool  s4309 = false != s4308;
+  const SWord8 s4310 = s4309 ? s4275 : s4276;
+  const SWord8 s4311 = (s4310 >> 1) | (s4310 << 7);
+  const SWord8 s4312 = 128 | s4311;
+  const SWord8 s4313 = 127 & s4311;
+  const SWord8 s4314 = s4307 ? s4312 : s4313;
+  const SWord8 s4315 = (s4314 >> 1) | (s4314 << 7);
+  const SWord8 s4316 = 128 | s4315;
+  const SWord8 s4317 = 127 & s4315;
+  const SWord8 s4318 = s4305 ? s4316 : s4317;
+  const SBool  s4319 = (SBool) (s501 & 1);
+  const SBool  s4320 = false != s4319;
+  const SWord8 s4321 = s4320 ? s4316 : s4317;
+  const SWord8 s4322 = s434 ? s4318 : s4321;
+  const SBool  s4323 = (SBool) (s517 & 1);
+  const SBool  s4324 = false != s4323;
+  const SBool  s4325 = (SBool) (s510 & 1);
+  const SBool  s4326 = false != s4325;
+  const SWord8 s4327 = s4326 ? s4312 : s4313;
+  const SWord8 s4328 = (s4327 >> 1) | (s4327 << 7);
+  const SWord8 s4329 = 128 | s4328;
+  const SWord8 s4330 = 127 & s4328;
+  const SWord8 s4331 = s4324 ? s4329 : s4330;
+  const SBool  s4332 = (SBool) (s522 & 1);
+  const SBool  s4333 = false != s4332;
+  const SWord8 s4334 = s4333 ? s4329 : s4330;
+  const SWord8 s4335 = s434 ? s4331 : s4334;
+  const SWord8 s4336 = s307 ? s4322 : s4335;
+  const SWord8 s4337 = s55 ? s4303 : s4336;
+  const SWord8 s4338 = s36 ? s4267 : s4337;
+  const SWord8 s4339 = s21 ? s4197 : s4338;
+  const SBool  s4340 = (SBool) (s597 & 1);
+  const SBool  s4341 = false != s4340;
+  const SBool  s4342 = (SBool) (s593 & 1);
+  const SBool  s4343 = false != s4342;
+  const SBool  s4344 = (SBool) (s589 & 1);
+  const SBool  s4345 = false != s4344;
+  const SWord8 s4346 = (s576 >> 1) | (s576 << 7);
+  const SWord8 s4347 = 128 | s4346;
+  const SWord8 s4348 = 127 & s4346;
+  const SWord8 s4349 = s4345 ? s4347 : s4348;
+  const SWord8 s4350 = (s4349 >> 1) | (s4349 << 7);
+  const SWord8 s4351 = 128 | s4350;
+  const SWord8 s4352 = 127 & s4350;
+  const SWord8 s4353 = s4343 ? s4351 : s4352;
+  const SWord8 s4354 = (s4353 >> 1) | (s4353 << 7);
+  const SWord8 s4355 = 128 | s4354;
+  const SWord8 s4356 = 127 & s4354;
+  const SWord8 s4357 = s4341 ? s4355 : s4356;
+  const SBool  s4358 = (SBool) (s602 & 1);
+  const SBool  s4359 = false != s4358;
+  const SWord8 s4360 = s4359 ? s4355 : s4356;
+  const SWord8 s4361 = s585 ? s4357 : s4360;
+  const SBool  s4362 = (SBool) (s618 & 1);
+  const SBool  s4363 = false != s4362;
+  const SBool  s4364 = (SBool) (s611 & 1);
+  const SBool  s4365 = false != s4364;
+  const SWord8 s4366 = s4365 ? s4351 : s4352;
+  const SWord8 s4367 = (s4366 >> 1) | (s4366 << 7);
+  const SWord8 s4368 = 128 | s4367;
+  const SWord8 s4369 = 127 & s4367;
+  const SWord8 s4370 = s4363 ? s4368 : s4369;
+  const SBool  s4371 = (SBool) (s623 & 1);
+  const SBool  s4372 = false != s4371;
+  const SWord8 s4373 = s4372 ? s4368 : s4369;
+  const SWord8 s4374 = s585 ? s4370 : s4373;
+  const SWord8 s4375 = s566 ? s4361 : s4374;
+  const SBool  s4376 = (SBool) (s644 & 1);
+  const SBool  s4377 = false != s4376;
+  const SBool  s4378 = (SBool) (s640 & 1);
+  const SBool  s4379 = false != s4378;
+  const SBool  s4380 = (SBool) (s633 & 1);
+  const SBool  s4381 = false != s4380;
+  const SWord8 s4382 = s4381 ? s4347 : s4348;
+  const SWord8 s4383 = (s4382 >> 1) | (s4382 << 7);
+  const SWord8 s4384 = 128 | s4383;
+  const SWord8 s4385 = 127 & s4383;
+  const SWord8 s4386 = s4379 ? s4384 : s4385;
+  const SWord8 s4387 = (s4386 >> 1) | (s4386 << 7);
+  const SWord8 s4388 = 128 | s4387;
+  const SWord8 s4389 = 127 & s4387;
+  const SWord8 s4390 = s4377 ? s4388 : s4389;
+  const SBool  s4391 = (SBool) (s649 & 1);
+  const SBool  s4392 = false != s4391;
+  const SWord8 s4393 = s4392 ? s4388 : s4389;
+  const SWord8 s4394 = s585 ? s4390 : s4393;
+  const SBool  s4395 = (SBool) (s665 & 1);
+  const SBool  s4396 = false != s4395;
+  const SBool  s4397 = (SBool) (s658 & 1);
+  const SBool  s4398 = false != s4397;
+  const SWord8 s4399 = s4398 ? s4384 : s4385;
+  const SWord8 s4400 = (s4399 >> 1) | (s4399 << 7);
+  const SWord8 s4401 = 128 | s4400;
+  const SWord8 s4402 = 127 & s4400;
+  const SWord8 s4403 = s4396 ? s4401 : s4402;
+  const SBool  s4404 = (SBool) (s670 & 1);
+  const SBool  s4405 = false != s4404;
+  const SWord8 s4406 = s4405 ? s4401 : s4402;
+  const SWord8 s4407 = s585 ? s4403 : s4406;
+  const SWord8 s4408 = s566 ? s4394 : s4407;
+  const SWord8 s4409 = s544 ? s4375 : s4408;
+  const SBool  s4410 = (SBool) (s705 & 1);
+  const SBool  s4411 = false != s4410;
+  const SBool  s4412 = (SBool) (s701 & 1);
+  const SBool  s4413 = false != s4412;
+  const SBool  s4414 = (SBool) (s697 & 1);
+  const SBool  s4415 = false != s4414;
+  const SWord8 s4416 = (s684 >> 1) | (s684 << 7);
+  const SWord8 s4417 = 128 | s4416;
+  const SWord8 s4418 = 127 & s4416;
+  const SWord8 s4419 = s4415 ? s4417 : s4418;
+  const SWord8 s4420 = (s4419 >> 1) | (s4419 << 7);
+  const SWord8 s4421 = 128 | s4420;
+  const SWord8 s4422 = 127 & s4420;
+  const SWord8 s4423 = s4413 ? s4421 : s4422;
+  const SWord8 s4424 = (s4423 >> 1) | (s4423 << 7);
+  const SWord8 s4425 = 128 | s4424;
+  const SWord8 s4426 = 127 & s4424;
+  const SWord8 s4427 = s4411 ? s4425 : s4426;
+  const SBool  s4428 = (SBool) (s710 & 1);
+  const SBool  s4429 = false != s4428;
+  const SWord8 s4430 = s4429 ? s4425 : s4426;
+  const SWord8 s4431 = s690 ? s4427 : s4430;
+  const SBool  s4432 = (SBool) (s726 & 1);
+  const SBool  s4433 = false != s4432;
+  const SBool  s4434 = (SBool) (s719 & 1);
+  const SBool  s4435 = false != s4434;
+  const SWord8 s4436 = s4435 ? s4421 : s4422;
+  const SWord8 s4437 = (s4436 >> 1) | (s4436 << 7);
+  const SWord8 s4438 = 128 | s4437;
+  const SWord8 s4439 = 127 & s4437;
+  const SWord8 s4440 = s4433 ? s4438 : s4439;
+  const SBool  s4441 = (SBool) (s731 & 1);
+  const SBool  s4442 = false != s4441;
+  const SWord8 s4443 = s4442 ? s4438 : s4439;
+  const SWord8 s4444 = s690 ? s4440 : s4443;
+  const SWord8 s4445 = s566 ? s4431 : s4444;
+  const SBool  s4446 = (SBool) (s752 & 1);
+  const SBool  s4447 = false != s4446;
+  const SBool  s4448 = (SBool) (s748 & 1);
+  const SBool  s4449 = false != s4448;
+  const SBool  s4450 = (SBool) (s741 & 1);
+  const SBool  s4451 = false != s4450;
+  const SWord8 s4452 = s4451 ? s4417 : s4418;
+  const SWord8 s4453 = (s4452 >> 1) | (s4452 << 7);
+  const SWord8 s4454 = 128 | s4453;
+  const SWord8 s4455 = 127 & s4453;
+  const SWord8 s4456 = s4449 ? s4454 : s4455;
+  const SWord8 s4457 = (s4456 >> 1) | (s4456 << 7);
+  const SWord8 s4458 = 128 | s4457;
+  const SWord8 s4459 = 127 & s4457;
+  const SWord8 s4460 = s4447 ? s4458 : s4459;
+  const SBool  s4461 = (SBool) (s757 & 1);
+  const SBool  s4462 = false != s4461;
+  const SWord8 s4463 = s4462 ? s4458 : s4459;
+  const SWord8 s4464 = s690 ? s4460 : s4463;
+  const SBool  s4465 = (SBool) (s773 & 1);
+  const SBool  s4466 = false != s4465;
+  const SBool  s4467 = (SBool) (s766 & 1);
+  const SBool  s4468 = false != s4467;
+  const SWord8 s4469 = s4468 ? s4454 : s4455;
+  const SWord8 s4470 = (s4469 >> 1) | (s4469 << 7);
+  const SWord8 s4471 = 128 | s4470;
+  const SWord8 s4472 = 127 & s4470;
+  const SWord8 s4473 = s4466 ? s4471 : s4472;
+  const SBool  s4474 = (SBool) (s778 & 1);
+  const SBool  s4475 = false != s4474;
+  const SWord8 s4476 = s4475 ? s4471 : s4472;
+  const SWord8 s4477 = s690 ? s4473 : s4476;
+  const SWord8 s4478 = s566 ? s4464 : s4477;
+  const SWord8 s4479 = s544 ? s4445 : s4478;
+  const SWord8 s4480 = s36 ? s4409 : s4479;
+  const SBool  s4481 = (SBool) (s833 & 1);
+  const SBool  s4482 = false != s4481;
+  const SBool  s4483 = (SBool) (s829 & 1);
+  const SBool  s4484 = false != s4483;
+  const SBool  s4485 = (SBool) (s825 & 1);
+  const SBool  s4486 = false != s4485;
+  const SWord8 s4487 = (s812 >> 1) | (s812 << 7);
+  const SWord8 s4488 = 128 | s4487;
+  const SWord8 s4489 = 127 & s4487;
+  const SWord8 s4490 = s4486 ? s4488 : s4489;
+  const SWord8 s4491 = (s4490 >> 1) | (s4490 << 7);
+  const SWord8 s4492 = 128 | s4491;
+  const SWord8 s4493 = 127 & s4491;
+  const SWord8 s4494 = s4484 ? s4492 : s4493;
+  const SWord8 s4495 = (s4494 >> 1) | (s4494 << 7);
+  const SWord8 s4496 = 128 | s4495;
+  const SWord8 s4497 = 127 & s4495;
+  const SWord8 s4498 = s4482 ? s4496 : s4497;
+  const SBool  s4499 = (SBool) (s838 & 1);
+  const SBool  s4500 = false != s4499;
+  const SWord8 s4501 = s4500 ? s4496 : s4497;
+  const SWord8 s4502 = s821 ? s4498 : s4501;
+  const SBool  s4503 = (SBool) (s854 & 1);
+  const SBool  s4504 = false != s4503;
+  const SBool  s4505 = (SBool) (s847 & 1);
+  const SBool  s4506 = false != s4505;
+  const SWord8 s4507 = s4506 ? s4492 : s4493;
+  const SWord8 s4508 = (s4507 >> 1) | (s4507 << 7);
+  const SWord8 s4509 = 128 | s4508;
+  const SWord8 s4510 = 127 & s4508;
+  const SWord8 s4511 = s4504 ? s4509 : s4510;
+  const SBool  s4512 = (SBool) (s859 & 1);
+  const SBool  s4513 = false != s4512;
+  const SWord8 s4514 = s4513 ? s4509 : s4510;
+  const SWord8 s4515 = s821 ? s4511 : s4514;
+  const SWord8 s4516 = s799 ? s4502 : s4515;
+  const SBool  s4517 = (SBool) (s880 & 1);
+  const SBool  s4518 = false != s4517;
+  const SBool  s4519 = (SBool) (s876 & 1);
+  const SBool  s4520 = false != s4519;
+  const SBool  s4521 = (SBool) (s869 & 1);
+  const SBool  s4522 = false != s4521;
+  const SWord8 s4523 = s4522 ? s4488 : s4489;
+  const SWord8 s4524 = (s4523 >> 1) | (s4523 << 7);
+  const SWord8 s4525 = 128 | s4524;
+  const SWord8 s4526 = 127 & s4524;
+  const SWord8 s4527 = s4520 ? s4525 : s4526;
+  const SWord8 s4528 = (s4527 >> 1) | (s4527 << 7);
+  const SWord8 s4529 = 128 | s4528;
+  const SWord8 s4530 = 127 & s4528;
+  const SWord8 s4531 = s4518 ? s4529 : s4530;
+  const SBool  s4532 = (SBool) (s885 & 1);
+  const SBool  s4533 = false != s4532;
+  const SWord8 s4534 = s4533 ? s4529 : s4530;
+  const SWord8 s4535 = s821 ? s4531 : s4534;
+  const SBool  s4536 = (SBool) (s901 & 1);
+  const SBool  s4537 = false != s4536;
+  const SBool  s4538 = (SBool) (s894 & 1);
+  const SBool  s4539 = false != s4538;
+  const SWord8 s4540 = s4539 ? s4525 : s4526;
+  const SWord8 s4541 = (s4540 >> 1) | (s4540 << 7);
+  const SWord8 s4542 = 128 | s4541;
+  const SWord8 s4543 = 127 & s4541;
+  const SWord8 s4544 = s4537 ? s4542 : s4543;
+  const SBool  s4545 = (SBool) (s906 & 1);
+  const SBool  s4546 = false != s4545;
+  const SWord8 s4547 = s4546 ? s4542 : s4543;
+  const SWord8 s4548 = s821 ? s4544 : s4547;
+  const SWord8 s4549 = s799 ? s4535 : s4548;
+  const SWord8 s4550 = s544 ? s4516 : s4549;
+  const SBool  s4551 = (SBool) (s941 & 1);
+  const SBool  s4552 = false != s4551;
+  const SBool  s4553 = (SBool) (s937 & 1);
+  const SBool  s4554 = false != s4553;
+  const SBool  s4555 = (SBool) (s933 & 1);
+  const SBool  s4556 = false != s4555;
+  const SWord8 s4557 = (s920 >> 1) | (s920 << 7);
+  const SWord8 s4558 = 128 | s4557;
+  const SWord8 s4559 = 127 & s4557;
+  const SWord8 s4560 = s4556 ? s4558 : s4559;
+  const SWord8 s4561 = (s4560 >> 1) | (s4560 << 7);
+  const SWord8 s4562 = 128 | s4561;
+  const SWord8 s4563 = 127 & s4561;
+  const SWord8 s4564 = s4554 ? s4562 : s4563;
+  const SWord8 s4565 = (s4564 >> 1) | (s4564 << 7);
+  const SWord8 s4566 = 128 | s4565;
+  const SWord8 s4567 = 127 & s4565;
+  const SWord8 s4568 = s4552 ? s4566 : s4567;
+  const SBool  s4569 = (SBool) (s946 & 1);
+  const SBool  s4570 = false != s4569;
+  const SWord8 s4571 = s4570 ? s4566 : s4567;
+  const SWord8 s4572 = s926 ? s4568 : s4571;
+  const SBool  s4573 = (SBool) (s962 & 1);
+  const SBool  s4574 = false != s4573;
+  const SBool  s4575 = (SBool) (s955 & 1);
+  const SBool  s4576 = false != s4575;
+  const SWord8 s4577 = s4576 ? s4562 : s4563;
+  const SWord8 s4578 = (s4577 >> 1) | (s4577 << 7);
+  const SWord8 s4579 = 128 | s4578;
+  const SWord8 s4580 = 127 & s4578;
+  const SWord8 s4581 = s4574 ? s4579 : s4580;
+  const SBool  s4582 = (SBool) (s967 & 1);
+  const SBool  s4583 = false != s4582;
+  const SWord8 s4584 = s4583 ? s4579 : s4580;
+  const SWord8 s4585 = s926 ? s4581 : s4584;
+  const SWord8 s4586 = s799 ? s4572 : s4585;
+  const SBool  s4587 = (SBool) (s988 & 1);
+  const SBool  s4588 = false != s4587;
+  const SBool  s4589 = (SBool) (s984 & 1);
+  const SBool  s4590 = false != s4589;
+  const SBool  s4591 = (SBool) (s977 & 1);
+  const SBool  s4592 = false != s4591;
+  const SWord8 s4593 = s4592 ? s4558 : s4559;
+  const SWord8 s4594 = (s4593 >> 1) | (s4593 << 7);
+  const SWord8 s4595 = 128 | s4594;
+  const SWord8 s4596 = 127 & s4594;
+  const SWord8 s4597 = s4590 ? s4595 : s4596;
+  const SWord8 s4598 = (s4597 >> 1) | (s4597 << 7);
+  const SWord8 s4599 = 128 | s4598;
+  const SWord8 s4600 = 127 & s4598;
+  const SWord8 s4601 = s4588 ? s4599 : s4600;
+  const SBool  s4602 = (SBool) (s993 & 1);
+  const SBool  s4603 = false != s4602;
+  const SWord8 s4604 = s4603 ? s4599 : s4600;
+  const SWord8 s4605 = s926 ? s4601 : s4604;
+  const SBool  s4606 = (SBool) (s1009 & 1);
+  const SBool  s4607 = false != s4606;
+  const SBool  s4608 = (SBool) (s1002 & 1);
+  const SBool  s4609 = false != s4608;
+  const SWord8 s4610 = s4609 ? s4595 : s4596;
+  const SWord8 s4611 = (s4610 >> 1) | (s4610 << 7);
+  const SWord8 s4612 = 128 | s4611;
+  const SWord8 s4613 = 127 & s4611;
+  const SWord8 s4614 = s4607 ? s4612 : s4613;
+  const SBool  s4615 = (SBool) (s1014 & 1);
+  const SBool  s4616 = false != s4615;
+  const SWord8 s4617 = s4616 ? s4612 : s4613;
+  const SWord8 s4618 = s926 ? s4614 : s4617;
+  const SWord8 s4619 = s799 ? s4605 : s4618;
+  const SWord8 s4620 = s544 ? s4586 : s4619;
+  const SWord8 s4621 = s36 ? s4550 : s4620;
+  const SWord8 s4622 = s21 ? s4480 : s4621;
+  const SWord8 s4623 = s16 ? s4339 : s4622;
+  const SBool  s4624 = (SBool) (s1109 & 1);
+  const SBool  s4625 = false != s4624;
+  const SBool  s4626 = (SBool) (s1105 & 1);
+  const SBool  s4627 = false != s4626;
+  const SBool  s4628 = (SBool) (s1101 & 1);
+  const SBool  s4629 = false != s4628;
+  const SWord8 s4630 = (s1088 >> 1) | (s1088 << 7);
+  const SWord8 s4631 = 128 | s4630;
+  const SWord8 s4632 = 127 & s4630;
+  const SWord8 s4633 = s4629 ? s4631 : s4632;
+  const SWord8 s4634 = (s4633 >> 1) | (s4633 << 7);
+  const SWord8 s4635 = 128 | s4634;
+  const SWord8 s4636 = 127 & s4634;
+  const SWord8 s4637 = s4627 ? s4635 : s4636;
+  const SWord8 s4638 = (s4637 >> 1) | (s4637 << 7);
+  const SWord8 s4639 = 128 | s4638;
+  const SWord8 s4640 = 127 & s4638;
+  const SWord8 s4641 = s4625 ? s4639 : s4640;
+  const SBool  s4642 = (SBool) (s1114 & 1);
+  const SBool  s4643 = false != s4642;
+  const SWord8 s4644 = s4643 ? s4639 : s4640;
+  const SWord8 s4645 = s1097 ? s4641 : s4644;
+  const SBool  s4646 = (SBool) (s1130 & 1);
+  const SBool  s4647 = false != s4646;
+  const SBool  s4648 = (SBool) (s1123 & 1);
+  const SBool  s4649 = false != s4648;
+  const SWord8 s4650 = s4649 ? s4635 : s4636;
+  const SWord8 s4651 = (s4650 >> 1) | (s4650 << 7);
+  const SWord8 s4652 = 128 | s4651;
+  const SWord8 s4653 = 127 & s4651;
+  const SWord8 s4654 = s4647 ? s4652 : s4653;
+  const SBool  s4655 = (SBool) (s1135 & 1);
+  const SBool  s4656 = false != s4655;
+  const SWord8 s4657 = s4656 ? s4652 : s4653;
+  const SWord8 s4658 = s1097 ? s4654 : s4657;
+  const SWord8 s4659 = s1078 ? s4645 : s4658;
+  const SBool  s4660 = (SBool) (s1156 & 1);
+  const SBool  s4661 = false != s4660;
+  const SBool  s4662 = (SBool) (s1152 & 1);
+  const SBool  s4663 = false != s4662;
+  const SBool  s4664 = (SBool) (s1145 & 1);
+  const SBool  s4665 = false != s4664;
+  const SWord8 s4666 = s4665 ? s4631 : s4632;
+  const SWord8 s4667 = (s4666 >> 1) | (s4666 << 7);
+  const SWord8 s4668 = 128 | s4667;
+  const SWord8 s4669 = 127 & s4667;
+  const SWord8 s4670 = s4663 ? s4668 : s4669;
+  const SWord8 s4671 = (s4670 >> 1) | (s4670 << 7);
+  const SWord8 s4672 = 128 | s4671;
+  const SWord8 s4673 = 127 & s4671;
+  const SWord8 s4674 = s4661 ? s4672 : s4673;
+  const SBool  s4675 = (SBool) (s1161 & 1);
+  const SBool  s4676 = false != s4675;
+  const SWord8 s4677 = s4676 ? s4672 : s4673;
+  const SWord8 s4678 = s1097 ? s4674 : s4677;
+  const SBool  s4679 = (SBool) (s1177 & 1);
+  const SBool  s4680 = false != s4679;
+  const SBool  s4681 = (SBool) (s1170 & 1);
+  const SBool  s4682 = false != s4681;
+  const SWord8 s4683 = s4682 ? s4668 : s4669;
+  const SWord8 s4684 = (s4683 >> 1) | (s4683 << 7);
+  const SWord8 s4685 = 128 | s4684;
+  const SWord8 s4686 = 127 & s4684;
+  const SWord8 s4687 = s4680 ? s4685 : s4686;
+  const SBool  s4688 = (SBool) (s1182 & 1);
+  const SBool  s4689 = false != s4688;
+  const SWord8 s4690 = s4689 ? s4685 : s4686;
+  const SWord8 s4691 = s1097 ? s4687 : s4690;
+  const SWord8 s4692 = s1078 ? s4678 : s4691;
+  const SWord8 s4693 = s1059 ? s4659 : s4692;
+  const SBool  s4694 = (SBool) (s1217 & 1);
+  const SBool  s4695 = false != s4694;
+  const SBool  s4696 = (SBool) (s1213 & 1);
+  const SBool  s4697 = false != s4696;
+  const SBool  s4698 = (SBool) (s1209 & 1);
+  const SBool  s4699 = false != s4698;
+  const SWord8 s4700 = (s1196 >> 1) | (s1196 << 7);
+  const SWord8 s4701 = 128 | s4700;
+  const SWord8 s4702 = 127 & s4700;
+  const SWord8 s4703 = s4699 ? s4701 : s4702;
+  const SWord8 s4704 = (s4703 >> 1) | (s4703 << 7);
+  const SWord8 s4705 = 128 | s4704;
+  const SWord8 s4706 = 127 & s4704;
+  const SWord8 s4707 = s4697 ? s4705 : s4706;
+  const SWord8 s4708 = (s4707 >> 1) | (s4707 << 7);
+  const SWord8 s4709 = 128 | s4708;
+  const SWord8 s4710 = 127 & s4708;
+  const SWord8 s4711 = s4695 ? s4709 : s4710;
+  const SBool  s4712 = (SBool) (s1222 & 1);
+  const SBool  s4713 = false != s4712;
+  const SWord8 s4714 = s4713 ? s4709 : s4710;
+  const SWord8 s4715 = s1202 ? s4711 : s4714;
+  const SBool  s4716 = (SBool) (s1238 & 1);
+  const SBool  s4717 = false != s4716;
+  const SBool  s4718 = (SBool) (s1231 & 1);
+  const SBool  s4719 = false != s4718;
+  const SWord8 s4720 = s4719 ? s4705 : s4706;
+  const SWord8 s4721 = (s4720 >> 1) | (s4720 << 7);
+  const SWord8 s4722 = 128 | s4721;
+  const SWord8 s4723 = 127 & s4721;
+  const SWord8 s4724 = s4717 ? s4722 : s4723;
+  const SBool  s4725 = (SBool) (s1243 & 1);
+  const SBool  s4726 = false != s4725;
+  const SWord8 s4727 = s4726 ? s4722 : s4723;
+  const SWord8 s4728 = s1202 ? s4724 : s4727;
+  const SWord8 s4729 = s1078 ? s4715 : s4728;
+  const SBool  s4730 = (SBool) (s1264 & 1);
+  const SBool  s4731 = false != s4730;
+  const SBool  s4732 = (SBool) (s1260 & 1);
+  const SBool  s4733 = false != s4732;
+  const SBool  s4734 = (SBool) (s1253 & 1);
+  const SBool  s4735 = false != s4734;
+  const SWord8 s4736 = s4735 ? s4701 : s4702;
+  const SWord8 s4737 = (s4736 >> 1) | (s4736 << 7);
+  const SWord8 s4738 = 128 | s4737;
+  const SWord8 s4739 = 127 & s4737;
+  const SWord8 s4740 = s4733 ? s4738 : s4739;
+  const SWord8 s4741 = (s4740 >> 1) | (s4740 << 7);
+  const SWord8 s4742 = 128 | s4741;
+  const SWord8 s4743 = 127 & s4741;
+  const SWord8 s4744 = s4731 ? s4742 : s4743;
+  const SBool  s4745 = (SBool) (s1269 & 1);
+  const SBool  s4746 = false != s4745;
+  const SWord8 s4747 = s4746 ? s4742 : s4743;
+  const SWord8 s4748 = s1202 ? s4744 : s4747;
+  const SBool  s4749 = (SBool) (s1285 & 1);
+  const SBool  s4750 = false != s4749;
+  const SBool  s4751 = (SBool) (s1278 & 1);
+  const SBool  s4752 = false != s4751;
+  const SWord8 s4753 = s4752 ? s4738 : s4739;
+  const SWord8 s4754 = (s4753 >> 1) | (s4753 << 7);
+  const SWord8 s4755 = 128 | s4754;
+  const SWord8 s4756 = 127 & s4754;
+  const SWord8 s4757 = s4750 ? s4755 : s4756;
+  const SBool  s4758 = (SBool) (s1290 & 1);
+  const SBool  s4759 = false != s4758;
+  const SWord8 s4760 = s4759 ? s4755 : s4756;
+  const SWord8 s4761 = s1202 ? s4757 : s4760;
+  const SWord8 s4762 = s1078 ? s4748 : s4761;
+  const SWord8 s4763 = s1059 ? s4729 : s4762;
+  const SWord8 s4764 = s1037 ? s4693 : s4763;
+  const SBool  s4765 = (SBool) (s1345 & 1);
+  const SBool  s4766 = false != s4765;
+  const SBool  s4767 = (SBool) (s1341 & 1);
+  const SBool  s4768 = false != s4767;
+  const SBool  s4769 = (SBool) (s1337 & 1);
+  const SBool  s4770 = false != s4769;
+  const SWord8 s4771 = (s1324 >> 1) | (s1324 << 7);
+  const SWord8 s4772 = 128 | s4771;
+  const SWord8 s4773 = 127 & s4771;
+  const SWord8 s4774 = s4770 ? s4772 : s4773;
+  const SWord8 s4775 = (s4774 >> 1) | (s4774 << 7);
+  const SWord8 s4776 = 128 | s4775;
+  const SWord8 s4777 = 127 & s4775;
+  const SWord8 s4778 = s4768 ? s4776 : s4777;
+  const SWord8 s4779 = (s4778 >> 1) | (s4778 << 7);
+  const SWord8 s4780 = 128 | s4779;
+  const SWord8 s4781 = 127 & s4779;
+  const SWord8 s4782 = s4766 ? s4780 : s4781;
+  const SBool  s4783 = (SBool) (s1350 & 1);
+  const SBool  s4784 = false != s4783;
+  const SWord8 s4785 = s4784 ? s4780 : s4781;
+  const SWord8 s4786 = s1333 ? s4782 : s4785;
+  const SBool  s4787 = (SBool) (s1366 & 1);
+  const SBool  s4788 = false != s4787;
+  const SBool  s4789 = (SBool) (s1359 & 1);
+  const SBool  s4790 = false != s4789;
+  const SWord8 s4791 = s4790 ? s4776 : s4777;
+  const SWord8 s4792 = (s4791 >> 1) | (s4791 << 7);
+  const SWord8 s4793 = 128 | s4792;
+  const SWord8 s4794 = 127 & s4792;
+  const SWord8 s4795 = s4788 ? s4793 : s4794;
+  const SBool  s4796 = (SBool) (s1371 & 1);
+  const SBool  s4797 = false != s4796;
+  const SWord8 s4798 = s4797 ? s4793 : s4794;
+  const SWord8 s4799 = s1333 ? s4795 : s4798;
+  const SWord8 s4800 = s1311 ? s4786 : s4799;
+  const SBool  s4801 = (SBool) (s1392 & 1);
+  const SBool  s4802 = false != s4801;
+  const SBool  s4803 = (SBool) (s1388 & 1);
+  const SBool  s4804 = false != s4803;
+  const SBool  s4805 = (SBool) (s1381 & 1);
+  const SBool  s4806 = false != s4805;
+  const SWord8 s4807 = s4806 ? s4772 : s4773;
+  const SWord8 s4808 = (s4807 >> 1) | (s4807 << 7);
+  const SWord8 s4809 = 128 | s4808;
+  const SWord8 s4810 = 127 & s4808;
+  const SWord8 s4811 = s4804 ? s4809 : s4810;
+  const SWord8 s4812 = (s4811 >> 1) | (s4811 << 7);
+  const SWord8 s4813 = 128 | s4812;
+  const SWord8 s4814 = 127 & s4812;
+  const SWord8 s4815 = s4802 ? s4813 : s4814;
+  const SBool  s4816 = (SBool) (s1397 & 1);
+  const SBool  s4817 = false != s4816;
+  const SWord8 s4818 = s4817 ? s4813 : s4814;
+  const SWord8 s4819 = s1333 ? s4815 : s4818;
+  const SBool  s4820 = (SBool) (s1413 & 1);
+  const SBool  s4821 = false != s4820;
+  const SBool  s4822 = (SBool) (s1406 & 1);
+  const SBool  s4823 = false != s4822;
+  const SWord8 s4824 = s4823 ? s4809 : s4810;
+  const SWord8 s4825 = (s4824 >> 1) | (s4824 << 7);
+  const SWord8 s4826 = 128 | s4825;
+  const SWord8 s4827 = 127 & s4825;
+  const SWord8 s4828 = s4821 ? s4826 : s4827;
+  const SBool  s4829 = (SBool) (s1418 & 1);
+  const SBool  s4830 = false != s4829;
+  const SWord8 s4831 = s4830 ? s4826 : s4827;
+  const SWord8 s4832 = s1333 ? s4828 : s4831;
+  const SWord8 s4833 = s1311 ? s4819 : s4832;
+  const SWord8 s4834 = s1059 ? s4800 : s4833;
+  const SBool  s4835 = (SBool) (s1453 & 1);
+  const SBool  s4836 = false != s4835;
+  const SBool  s4837 = (SBool) (s1449 & 1);
+  const SBool  s4838 = false != s4837;
+  const SBool  s4839 = (SBool) (s1445 & 1);
+  const SBool  s4840 = false != s4839;
+  const SWord8 s4841 = (s1432 >> 1) | (s1432 << 7);
+  const SWord8 s4842 = 128 | s4841;
+  const SWord8 s4843 = 127 & s4841;
+  const SWord8 s4844 = s4840 ? s4842 : s4843;
+  const SWord8 s4845 = (s4844 >> 1) | (s4844 << 7);
+  const SWord8 s4846 = 128 | s4845;
+  const SWord8 s4847 = 127 & s4845;
+  const SWord8 s4848 = s4838 ? s4846 : s4847;
+  const SWord8 s4849 = (s4848 >> 1) | (s4848 << 7);
+  const SWord8 s4850 = 128 | s4849;
+  const SWord8 s4851 = 127 & s4849;
+  const SWord8 s4852 = s4836 ? s4850 : s4851;
+  const SBool  s4853 = (SBool) (s1458 & 1);
+  const SBool  s4854 = false != s4853;
+  const SWord8 s4855 = s4854 ? s4850 : s4851;
+  const SWord8 s4856 = s1438 ? s4852 : s4855;
+  const SBool  s4857 = (SBool) (s1474 & 1);
+  const SBool  s4858 = false != s4857;
+  const SBool  s4859 = (SBool) (s1467 & 1);
+  const SBool  s4860 = false != s4859;
+  const SWord8 s4861 = s4860 ? s4846 : s4847;
+  const SWord8 s4862 = (s4861 >> 1) | (s4861 << 7);
+  const SWord8 s4863 = 128 | s4862;
+  const SWord8 s4864 = 127 & s4862;
+  const SWord8 s4865 = s4858 ? s4863 : s4864;
+  const SBool  s4866 = (SBool) (s1479 & 1);
+  const SBool  s4867 = false != s4866;
+  const SWord8 s4868 = s4867 ? s4863 : s4864;
+  const SWord8 s4869 = s1438 ? s4865 : s4868;
+  const SWord8 s4870 = s1311 ? s4856 : s4869;
+  const SBool  s4871 = (SBool) (s1500 & 1);
+  const SBool  s4872 = false != s4871;
+  const SBool  s4873 = (SBool) (s1496 & 1);
+  const SBool  s4874 = false != s4873;
+  const SBool  s4875 = (SBool) (s1489 & 1);
+  const SBool  s4876 = false != s4875;
+  const SWord8 s4877 = s4876 ? s4842 : s4843;
+  const SWord8 s4878 = (s4877 >> 1) | (s4877 << 7);
+  const SWord8 s4879 = 128 | s4878;
+  const SWord8 s4880 = 127 & s4878;
+  const SWord8 s4881 = s4874 ? s4879 : s4880;
+  const SWord8 s4882 = (s4881 >> 1) | (s4881 << 7);
+  const SWord8 s4883 = 128 | s4882;
+  const SWord8 s4884 = 127 & s4882;
+  const SWord8 s4885 = s4872 ? s4883 : s4884;
+  const SBool  s4886 = (SBool) (s1505 & 1);
+  const SBool  s4887 = false != s4886;
+  const SWord8 s4888 = s4887 ? s4883 : s4884;
+  const SWord8 s4889 = s1438 ? s4885 : s4888;
+  const SBool  s4890 = (SBool) (s1521 & 1);
+  const SBool  s4891 = false != s4890;
+  const SBool  s4892 = (SBool) (s1514 & 1);
+  const SBool  s4893 = false != s4892;
+  const SWord8 s4894 = s4893 ? s4879 : s4880;
+  const SWord8 s4895 = (s4894 >> 1) | (s4894 << 7);
+  const SWord8 s4896 = 128 | s4895;
+  const SWord8 s4897 = 127 & s4895;
+  const SWord8 s4898 = s4891 ? s4896 : s4897;
+  const SBool  s4899 = (SBool) (s1526 & 1);
+  const SBool  s4900 = false != s4899;
+  const SWord8 s4901 = s4900 ? s4896 : s4897;
+  const SWord8 s4902 = s1438 ? s4898 : s4901;
+  const SWord8 s4903 = s1311 ? s4889 : s4902;
+  const SWord8 s4904 = s1059 ? s4870 : s4903;
+  const SWord8 s4905 = s1037 ? s4834 : s4904;
+  const SWord8 s4906 = s21 ? s4764 : s4905;
+  const SBool  s4907 = (SBool) (s1601 & 1);
+  const SBool  s4908 = false != s4907;
+  const SBool  s4909 = (SBool) (s1597 & 1);
+  const SBool  s4910 = false != s4909;
+  const SBool  s4911 = (SBool) (s1593 & 1);
+  const SBool  s4912 = false != s4911;
+  const SWord8 s4913 = (s1580 >> 1) | (s1580 << 7);
+  const SWord8 s4914 = 128 | s4913;
+  const SWord8 s4915 = 127 & s4913;
+  const SWord8 s4916 = s4912 ? s4914 : s4915;
+  const SWord8 s4917 = (s4916 >> 1) | (s4916 << 7);
+  const SWord8 s4918 = 128 | s4917;
+  const SWord8 s4919 = 127 & s4917;
+  const SWord8 s4920 = s4910 ? s4918 : s4919;
+  const SWord8 s4921 = (s4920 >> 1) | (s4920 << 7);
+  const SWord8 s4922 = 128 | s4921;
+  const SWord8 s4923 = 127 & s4921;
+  const SWord8 s4924 = s4908 ? s4922 : s4923;
+  const SBool  s4925 = (SBool) (s1606 & 1);
+  const SBool  s4926 = false != s4925;
+  const SWord8 s4927 = s4926 ? s4922 : s4923;
+  const SWord8 s4928 = s1589 ? s4924 : s4927;
+  const SBool  s4929 = (SBool) (s1622 & 1);
+  const SBool  s4930 = false != s4929;
+  const SBool  s4931 = (SBool) (s1615 & 1);
+  const SBool  s4932 = false != s4931;
+  const SWord8 s4933 = s4932 ? s4918 : s4919;
+  const SWord8 s4934 = (s4933 >> 1) | (s4933 << 7);
+  const SWord8 s4935 = 128 | s4934;
+  const SWord8 s4936 = 127 & s4934;
+  const SWord8 s4937 = s4930 ? s4935 : s4936;
+  const SBool  s4938 = (SBool) (s1627 & 1);
+  const SBool  s4939 = false != s4938;
+  const SWord8 s4940 = s4939 ? s4935 : s4936;
+  const SWord8 s4941 = s1589 ? s4937 : s4940;
+  const SWord8 s4942 = s1570 ? s4928 : s4941;
+  const SBool  s4943 = (SBool) (s1648 & 1);
+  const SBool  s4944 = false != s4943;
+  const SBool  s4945 = (SBool) (s1644 & 1);
+  const SBool  s4946 = false != s4945;
+  const SBool  s4947 = (SBool) (s1637 & 1);
+  const SBool  s4948 = false != s4947;
+  const SWord8 s4949 = s4948 ? s4914 : s4915;
+  const SWord8 s4950 = (s4949 >> 1) | (s4949 << 7);
+  const SWord8 s4951 = 128 | s4950;
+  const SWord8 s4952 = 127 & s4950;
+  const SWord8 s4953 = s4946 ? s4951 : s4952;
+  const SWord8 s4954 = (s4953 >> 1) | (s4953 << 7);
+  const SWord8 s4955 = 128 | s4954;
+  const SWord8 s4956 = 127 & s4954;
+  const SWord8 s4957 = s4944 ? s4955 : s4956;
+  const SBool  s4958 = (SBool) (s1653 & 1);
+  const SBool  s4959 = false != s4958;
+  const SWord8 s4960 = s4959 ? s4955 : s4956;
+  const SWord8 s4961 = s1589 ? s4957 : s4960;
+  const SBool  s4962 = (SBool) (s1669 & 1);
+  const SBool  s4963 = false != s4962;
+  const SBool  s4964 = (SBool) (s1662 & 1);
+  const SBool  s4965 = false != s4964;
+  const SWord8 s4966 = s4965 ? s4951 : s4952;
+  const SWord8 s4967 = (s4966 >> 1) | (s4966 << 7);
+  const SWord8 s4968 = 128 | s4967;
+  const SWord8 s4969 = 127 & s4967;
+  const SWord8 s4970 = s4963 ? s4968 : s4969;
+  const SBool  s4971 = (SBool) (s1674 & 1);
+  const SBool  s4972 = false != s4971;
+  const SWord8 s4973 = s4972 ? s4968 : s4969;
+  const SWord8 s4974 = s1589 ? s4970 : s4973;
+  const SWord8 s4975 = s1570 ? s4961 : s4974;
+  const SWord8 s4976 = s1548 ? s4942 : s4975;
+  const SBool  s4977 = (SBool) (s1709 & 1);
+  const SBool  s4978 = false != s4977;
+  const SBool  s4979 = (SBool) (s1705 & 1);
+  const SBool  s4980 = false != s4979;
+  const SBool  s4981 = (SBool) (s1701 & 1);
+  const SBool  s4982 = false != s4981;
+  const SWord8 s4983 = (s1688 >> 1) | (s1688 << 7);
+  const SWord8 s4984 = 128 | s4983;
+  const SWord8 s4985 = 127 & s4983;
+  const SWord8 s4986 = s4982 ? s4984 : s4985;
+  const SWord8 s4987 = (s4986 >> 1) | (s4986 << 7);
+  const SWord8 s4988 = 128 | s4987;
+  const SWord8 s4989 = 127 & s4987;
+  const SWord8 s4990 = s4980 ? s4988 : s4989;
+  const SWord8 s4991 = (s4990 >> 1) | (s4990 << 7);
+  const SWord8 s4992 = 128 | s4991;
+  const SWord8 s4993 = 127 & s4991;
+  const SWord8 s4994 = s4978 ? s4992 : s4993;
+  const SBool  s4995 = (SBool) (s1714 & 1);
+  const SBool  s4996 = false != s4995;
+  const SWord8 s4997 = s4996 ? s4992 : s4993;
+  const SWord8 s4998 = s1694 ? s4994 : s4997;
+  const SBool  s4999 = (SBool) (s1730 & 1);
+  const SBool  s5000 = false != s4999;
+  const SBool  s5001 = (SBool) (s1723 & 1);
+  const SBool  s5002 = false != s5001;
+  const SWord8 s5003 = s5002 ? s4988 : s4989;
+  const SWord8 s5004 = (s5003 >> 1) | (s5003 << 7);
+  const SWord8 s5005 = 128 | s5004;
+  const SWord8 s5006 = 127 & s5004;
+  const SWord8 s5007 = s5000 ? s5005 : s5006;
+  const SBool  s5008 = (SBool) (s1735 & 1);
+  const SBool  s5009 = false != s5008;
+  const SWord8 s5010 = s5009 ? s5005 : s5006;
+  const SWord8 s5011 = s1694 ? s5007 : s5010;
+  const SWord8 s5012 = s1570 ? s4998 : s5011;
+  const SBool  s5013 = (SBool) (s1756 & 1);
+  const SBool  s5014 = false != s5013;
+  const SBool  s5015 = (SBool) (s1752 & 1);
+  const SBool  s5016 = false != s5015;
+  const SBool  s5017 = (SBool) (s1745 & 1);
+  const SBool  s5018 = false != s5017;
+  const SWord8 s5019 = s5018 ? s4984 : s4985;
+  const SWord8 s5020 = (s5019 >> 1) | (s5019 << 7);
+  const SWord8 s5021 = 128 | s5020;
+  const SWord8 s5022 = 127 & s5020;
+  const SWord8 s5023 = s5016 ? s5021 : s5022;
+  const SWord8 s5024 = (s5023 >> 1) | (s5023 << 7);
+  const SWord8 s5025 = 128 | s5024;
+  const SWord8 s5026 = 127 & s5024;
+  const SWord8 s5027 = s5014 ? s5025 : s5026;
+  const SBool  s5028 = (SBool) (s1761 & 1);
+  const SBool  s5029 = false != s5028;
+  const SWord8 s5030 = s5029 ? s5025 : s5026;
+  const SWord8 s5031 = s1694 ? s5027 : s5030;
+  const SBool  s5032 = (SBool) (s1777 & 1);
+  const SBool  s5033 = false != s5032;
+  const SBool  s5034 = (SBool) (s1770 & 1);
+  const SBool  s5035 = false != s5034;
+  const SWord8 s5036 = s5035 ? s5021 : s5022;
+  const SWord8 s5037 = (s5036 >> 1) | (s5036 << 7);
+  const SWord8 s5038 = 128 | s5037;
+  const SWord8 s5039 = 127 & s5037;
+  const SWord8 s5040 = s5033 ? s5038 : s5039;
+  const SBool  s5041 = (SBool) (s1782 & 1);
+  const SBool  s5042 = false != s5041;
+  const SWord8 s5043 = s5042 ? s5038 : s5039;
+  const SWord8 s5044 = s1694 ? s5040 : s5043;
+  const SWord8 s5045 = s1570 ? s5031 : s5044;
+  const SWord8 s5046 = s1548 ? s5012 : s5045;
+  const SWord8 s5047 = s1037 ? s4976 : s5046;
+  const SBool  s5048 = (SBool) (s1837 & 1);
+  const SBool  s5049 = false != s5048;
+  const SBool  s5050 = (SBool) (s1833 & 1);
+  const SBool  s5051 = false != s5050;
+  const SBool  s5052 = (SBool) (s1829 & 1);
+  const SBool  s5053 = false != s5052;
+  const SWord8 s5054 = (s1816 >> 1) | (s1816 << 7);
+  const SWord8 s5055 = 128 | s5054;
+  const SWord8 s5056 = 127 & s5054;
+  const SWord8 s5057 = s5053 ? s5055 : s5056;
+  const SWord8 s5058 = (s5057 >> 1) | (s5057 << 7);
+  const SWord8 s5059 = 128 | s5058;
+  const SWord8 s5060 = 127 & s5058;
+  const SWord8 s5061 = s5051 ? s5059 : s5060;
+  const SWord8 s5062 = (s5061 >> 1) | (s5061 << 7);
+  const SWord8 s5063 = 128 | s5062;
+  const SWord8 s5064 = 127 & s5062;
+  const SWord8 s5065 = s5049 ? s5063 : s5064;
+  const SBool  s5066 = (SBool) (s1842 & 1);
+  const SBool  s5067 = false != s5066;
+  const SWord8 s5068 = s5067 ? s5063 : s5064;
+  const SWord8 s5069 = s1825 ? s5065 : s5068;
+  const SBool  s5070 = (SBool) (s1858 & 1);
+  const SBool  s5071 = false != s5070;
+  const SBool  s5072 = (SBool) (s1851 & 1);
+  const SBool  s5073 = false != s5072;
+  const SWord8 s5074 = s5073 ? s5059 : s5060;
+  const SWord8 s5075 = (s5074 >> 1) | (s5074 << 7);
+  const SWord8 s5076 = 128 | s5075;
+  const SWord8 s5077 = 127 & s5075;
+  const SWord8 s5078 = s5071 ? s5076 : s5077;
+  const SBool  s5079 = (SBool) (s1863 & 1);
+  const SBool  s5080 = false != s5079;
+  const SWord8 s5081 = s5080 ? s5076 : s5077;
+  const SWord8 s5082 = s1825 ? s5078 : s5081;
+  const SWord8 s5083 = s1803 ? s5069 : s5082;
+  const SBool  s5084 = (SBool) (s1884 & 1);
+  const SBool  s5085 = false != s5084;
+  const SBool  s5086 = (SBool) (s1880 & 1);
+  const SBool  s5087 = false != s5086;
+  const SBool  s5088 = (SBool) (s1873 & 1);
+  const SBool  s5089 = false != s5088;
+  const SWord8 s5090 = s5089 ? s5055 : s5056;
+  const SWord8 s5091 = (s5090 >> 1) | (s5090 << 7);
+  const SWord8 s5092 = 128 | s5091;
+  const SWord8 s5093 = 127 & s5091;
+  const SWord8 s5094 = s5087 ? s5092 : s5093;
+  const SWord8 s5095 = (s5094 >> 1) | (s5094 << 7);
+  const SWord8 s5096 = 128 | s5095;
+  const SWord8 s5097 = 127 & s5095;
+  const SWord8 s5098 = s5085 ? s5096 : s5097;
+  const SBool  s5099 = (SBool) (s1889 & 1);
+  const SBool  s5100 = false != s5099;
+  const SWord8 s5101 = s5100 ? s5096 : s5097;
+  const SWord8 s5102 = s1825 ? s5098 : s5101;
+  const SBool  s5103 = (SBool) (s1905 & 1);
+  const SBool  s5104 = false != s5103;
+  const SBool  s5105 = (SBool) (s1898 & 1);
+  const SBool  s5106 = false != s5105;
+  const SWord8 s5107 = s5106 ? s5092 : s5093;
+  const SWord8 s5108 = (s5107 >> 1) | (s5107 << 7);
+  const SWord8 s5109 = 128 | s5108;
+  const SWord8 s5110 = 127 & s5108;
+  const SWord8 s5111 = s5104 ? s5109 : s5110;
+  const SBool  s5112 = (SBool) (s1910 & 1);
+  const SBool  s5113 = false != s5112;
+  const SWord8 s5114 = s5113 ? s5109 : s5110;
+  const SWord8 s5115 = s1825 ? s5111 : s5114;
+  const SWord8 s5116 = s1803 ? s5102 : s5115;
+  const SWord8 s5117 = s1548 ? s5083 : s5116;
+  const SBool  s5118 = (SBool) (s1945 & 1);
+  const SBool  s5119 = false != s5118;
+  const SBool  s5120 = (SBool) (s1941 & 1);
+  const SBool  s5121 = false != s5120;
+  const SBool  s5122 = (SBool) (s1937 & 1);
+  const SBool  s5123 = false != s5122;
+  const SWord8 s5124 = (s1924 >> 1) | (s1924 << 7);
+  const SWord8 s5125 = 128 | s5124;
+  const SWord8 s5126 = 127 & s5124;
+  const SWord8 s5127 = s5123 ? s5125 : s5126;
+  const SWord8 s5128 = (s5127 >> 1) | (s5127 << 7);
+  const SWord8 s5129 = 128 | s5128;
+  const SWord8 s5130 = 127 & s5128;
+  const SWord8 s5131 = s5121 ? s5129 : s5130;
+  const SWord8 s5132 = (s5131 >> 1) | (s5131 << 7);
+  const SWord8 s5133 = 128 | s5132;
+  const SWord8 s5134 = 127 & s5132;
+  const SWord8 s5135 = s5119 ? s5133 : s5134;
+  const SBool  s5136 = (SBool) (s1950 & 1);
+  const SBool  s5137 = false != s5136;
+  const SWord8 s5138 = s5137 ? s5133 : s5134;
+  const SWord8 s5139 = s1930 ? s5135 : s5138;
+  const SBool  s5140 = (SBool) (s1966 & 1);
+  const SBool  s5141 = false != s5140;
+  const SBool  s5142 = (SBool) (s1959 & 1);
+  const SBool  s5143 = false != s5142;
+  const SWord8 s5144 = s5143 ? s5129 : s5130;
+  const SWord8 s5145 = (s5144 >> 1) | (s5144 << 7);
+  const SWord8 s5146 = 128 | s5145;
+  const SWord8 s5147 = 127 & s5145;
+  const SWord8 s5148 = s5141 ? s5146 : s5147;
+  const SBool  s5149 = (SBool) (s1971 & 1);
+  const SBool  s5150 = false != s5149;
+  const SWord8 s5151 = s5150 ? s5146 : s5147;
+  const SWord8 s5152 = s1930 ? s5148 : s5151;
+  const SWord8 s5153 = s1803 ? s5139 : s5152;
+  const SBool  s5154 = (SBool) (s1992 & 1);
+  const SBool  s5155 = false != s5154;
+  const SBool  s5156 = (SBool) (s1988 & 1);
+  const SBool  s5157 = false != s5156;
+  const SBool  s5158 = (SBool) (s1981 & 1);
+  const SBool  s5159 = false != s5158;
+  const SWord8 s5160 = s5159 ? s5125 : s5126;
+  const SWord8 s5161 = (s5160 >> 1) | (s5160 << 7);
+  const SWord8 s5162 = 128 | s5161;
+  const SWord8 s5163 = 127 & s5161;
+  const SWord8 s5164 = s5157 ? s5162 : s5163;
+  const SWord8 s5165 = (s5164 >> 1) | (s5164 << 7);
+  const SWord8 s5166 = 128 | s5165;
+  const SWord8 s5167 = 127 & s5165;
+  const SWord8 s5168 = s5155 ? s5166 : s5167;
+  const SBool  s5169 = (SBool) (s1997 & 1);
+  const SBool  s5170 = false != s5169;
+  const SWord8 s5171 = s5170 ? s5166 : s5167;
+  const SWord8 s5172 = s1930 ? s5168 : s5171;
+  const SBool  s5173 = (SBool) (s2013 & 1);
+  const SBool  s5174 = false != s5173;
+  const SBool  s5175 = (SBool) (s2006 & 1);
+  const SBool  s5176 = false != s5175;
+  const SWord8 s5177 = s5176 ? s5162 : s5163;
+  const SWord8 s5178 = (s5177 >> 1) | (s5177 << 7);
+  const SWord8 s5179 = 128 | s5178;
+  const SWord8 s5180 = 127 & s5178;
+  const SWord8 s5181 = s5174 ? s5179 : s5180;
+  const SBool  s5182 = (SBool) (s2018 & 1);
+  const SBool  s5183 = false != s5182;
+  const SWord8 s5184 = s5183 ? s5179 : s5180;
+  const SWord8 s5185 = s1930 ? s5181 : s5184;
+  const SWord8 s5186 = s1803 ? s5172 : s5185;
+  const SWord8 s5187 = s1548 ? s5153 : s5186;
+  const SWord8 s5188 = s1037 ? s5117 : s5187;
+  const SWord8 s5189 = s21 ? s5047 : s5188;
+  const SWord8 s5190 = s16 ? s4906 : s5189;
+  const SWord8 s5191 = s11 ? s4623 : s5190;
+  const SBool  s5192 = (SBool) (s2128 & 1);
+  const SBool  s5193 = false != s5192;
+  const SBool  s5194 = (SBool) (s2124 & 1);
+  const SBool  s5195 = false != s5194;
+  const SBool  s5196 = (SBool) (s2120 & 1);
+  const SBool  s5197 = false != s5196;
+  const SWord8 s5198 = (s2107 >> 1) | (s2107 << 7);
+  const SWord8 s5199 = 128 | s5198;
+  const SWord8 s5200 = 127 & s5198;
+  const SWord8 s5201 = s5197 ? s5199 : s5200;
+  const SWord8 s5202 = (s5201 >> 1) | (s5201 << 7);
+  const SWord8 s5203 = 128 | s5202;
+  const SWord8 s5204 = 127 & s5202;
+  const SWord8 s5205 = s5195 ? s5203 : s5204;
+  const SWord8 s5206 = (s5205 >> 1) | (s5205 << 7);
+  const SWord8 s5207 = 128 | s5206;
+  const SWord8 s5208 = 127 & s5206;
+  const SWord8 s5209 = s5193 ? s5207 : s5208;
+  const SBool  s5210 = (SBool) (s2133 & 1);
+  const SBool  s5211 = false != s5210;
+  const SWord8 s5212 = s5211 ? s5207 : s5208;
+  const SWord8 s5213 = s2116 ? s5209 : s5212;
+  const SBool  s5214 = (SBool) (s2149 & 1);
+  const SBool  s5215 = false != s5214;
+  const SBool  s5216 = (SBool) (s2142 & 1);
+  const SBool  s5217 = false != s5216;
+  const SWord8 s5218 = s5217 ? s5203 : s5204;
+  const SWord8 s5219 = (s5218 >> 1) | (s5218 << 7);
+  const SWord8 s5220 = 128 | s5219;
+  const SWord8 s5221 = 127 & s5219;
+  const SWord8 s5222 = s5215 ? s5220 : s5221;
+  const SBool  s5223 = (SBool) (s2154 & 1);
+  const SBool  s5224 = false != s5223;
+  const SWord8 s5225 = s5224 ? s5220 : s5221;
+  const SWord8 s5226 = s2116 ? s5222 : s5225;
+  const SWord8 s5227 = s2097 ? s5213 : s5226;
+  const SBool  s5228 = (SBool) (s2175 & 1);
+  const SBool  s5229 = false != s5228;
+  const SBool  s5230 = (SBool) (s2171 & 1);
+  const SBool  s5231 = false != s5230;
+  const SBool  s5232 = (SBool) (s2164 & 1);
+  const SBool  s5233 = false != s5232;
+  const SWord8 s5234 = s5233 ? s5199 : s5200;
+  const SWord8 s5235 = (s5234 >> 1) | (s5234 << 7);
+  const SWord8 s5236 = 128 | s5235;
+  const SWord8 s5237 = 127 & s5235;
+  const SWord8 s5238 = s5231 ? s5236 : s5237;
+  const SWord8 s5239 = (s5238 >> 1) | (s5238 << 7);
+  const SWord8 s5240 = 128 | s5239;
+  const SWord8 s5241 = 127 & s5239;
+  const SWord8 s5242 = s5229 ? s5240 : s5241;
+  const SBool  s5243 = (SBool) (s2180 & 1);
+  const SBool  s5244 = false != s5243;
+  const SWord8 s5245 = s5244 ? s5240 : s5241;
+  const SWord8 s5246 = s2116 ? s5242 : s5245;
+  const SBool  s5247 = (SBool) (s2196 & 1);
+  const SBool  s5248 = false != s5247;
+  const SBool  s5249 = (SBool) (s2189 & 1);
+  const SBool  s5250 = false != s5249;
+  const SWord8 s5251 = s5250 ? s5236 : s5237;
+  const SWord8 s5252 = (s5251 >> 1) | (s5251 << 7);
+  const SWord8 s5253 = 128 | s5252;
+  const SWord8 s5254 = 127 & s5252;
+  const SWord8 s5255 = s5248 ? s5253 : s5254;
+  const SBool  s5256 = (SBool) (s2201 & 1);
+  const SBool  s5257 = false != s5256;
+  const SWord8 s5258 = s5257 ? s5253 : s5254;
+  const SWord8 s5259 = s2116 ? s5255 : s5258;
+  const SWord8 s5260 = s2097 ? s5246 : s5259;
+  const SWord8 s5261 = s2078 ? s5227 : s5260;
+  const SBool  s5262 = (SBool) (s2236 & 1);
+  const SBool  s5263 = false != s5262;
+  const SBool  s5264 = (SBool) (s2232 & 1);
+  const SBool  s5265 = false != s5264;
+  const SBool  s5266 = (SBool) (s2228 & 1);
+  const SBool  s5267 = false != s5266;
+  const SWord8 s5268 = (s2215 >> 1) | (s2215 << 7);
+  const SWord8 s5269 = 128 | s5268;
+  const SWord8 s5270 = 127 & s5268;
+  const SWord8 s5271 = s5267 ? s5269 : s5270;
+  const SWord8 s5272 = (s5271 >> 1) | (s5271 << 7);
+  const SWord8 s5273 = 128 | s5272;
+  const SWord8 s5274 = 127 & s5272;
+  const SWord8 s5275 = s5265 ? s5273 : s5274;
+  const SWord8 s5276 = (s5275 >> 1) | (s5275 << 7);
+  const SWord8 s5277 = 128 | s5276;
+  const SWord8 s5278 = 127 & s5276;
+  const SWord8 s5279 = s5263 ? s5277 : s5278;
+  const SBool  s5280 = (SBool) (s2241 & 1);
+  const SBool  s5281 = false != s5280;
+  const SWord8 s5282 = s5281 ? s5277 : s5278;
+  const SWord8 s5283 = s2221 ? s5279 : s5282;
+  const SBool  s5284 = (SBool) (s2257 & 1);
+  const SBool  s5285 = false != s5284;
+  const SBool  s5286 = (SBool) (s2250 & 1);
+  const SBool  s5287 = false != s5286;
+  const SWord8 s5288 = s5287 ? s5273 : s5274;
+  const SWord8 s5289 = (s5288 >> 1) | (s5288 << 7);
+  const SWord8 s5290 = 128 | s5289;
+  const SWord8 s5291 = 127 & s5289;
+  const SWord8 s5292 = s5285 ? s5290 : s5291;
+  const SBool  s5293 = (SBool) (s2262 & 1);
+  const SBool  s5294 = false != s5293;
+  const SWord8 s5295 = s5294 ? s5290 : s5291;
+  const SWord8 s5296 = s2221 ? s5292 : s5295;
+  const SWord8 s5297 = s2097 ? s5283 : s5296;
+  const SBool  s5298 = (SBool) (s2283 & 1);
+  const SBool  s5299 = false != s5298;
+  const SBool  s5300 = (SBool) (s2279 & 1);
+  const SBool  s5301 = false != s5300;
+  const SBool  s5302 = (SBool) (s2272 & 1);
+  const SBool  s5303 = false != s5302;
+  const SWord8 s5304 = s5303 ? s5269 : s5270;
+  const SWord8 s5305 = (s5304 >> 1) | (s5304 << 7);
+  const SWord8 s5306 = 128 | s5305;
+  const SWord8 s5307 = 127 & s5305;
+  const SWord8 s5308 = s5301 ? s5306 : s5307;
+  const SWord8 s5309 = (s5308 >> 1) | (s5308 << 7);
+  const SWord8 s5310 = 128 | s5309;
+  const SWord8 s5311 = 127 & s5309;
+  const SWord8 s5312 = s5299 ? s5310 : s5311;
+  const SBool  s5313 = (SBool) (s2288 & 1);
+  const SBool  s5314 = false != s5313;
+  const SWord8 s5315 = s5314 ? s5310 : s5311;
+  const SWord8 s5316 = s2221 ? s5312 : s5315;
+  const SBool  s5317 = (SBool) (s2304 & 1);
+  const SBool  s5318 = false != s5317;
+  const SBool  s5319 = (SBool) (s2297 & 1);
+  const SBool  s5320 = false != s5319;
+  const SWord8 s5321 = s5320 ? s5306 : s5307;
+  const SWord8 s5322 = (s5321 >> 1) | (s5321 << 7);
+  const SWord8 s5323 = 128 | s5322;
+  const SWord8 s5324 = 127 & s5322;
+  const SWord8 s5325 = s5318 ? s5323 : s5324;
+  const SBool  s5326 = (SBool) (s2309 & 1);
+  const SBool  s5327 = false != s5326;
+  const SWord8 s5328 = s5327 ? s5323 : s5324;
+  const SWord8 s5329 = s2221 ? s5325 : s5328;
+  const SWord8 s5330 = s2097 ? s5316 : s5329;
+  const SWord8 s5331 = s2078 ? s5297 : s5330;
+  const SWord8 s5332 = s2059 ? s5261 : s5331;
+  const SBool  s5333 = (SBool) (s2364 & 1);
+  const SBool  s5334 = false != s5333;
+  const SBool  s5335 = (SBool) (s2360 & 1);
+  const SBool  s5336 = false != s5335;
+  const SBool  s5337 = (SBool) (s2356 & 1);
+  const SBool  s5338 = false != s5337;
+  const SWord8 s5339 = (s2343 >> 1) | (s2343 << 7);
+  const SWord8 s5340 = 128 | s5339;
+  const SWord8 s5341 = 127 & s5339;
+  const SWord8 s5342 = s5338 ? s5340 : s5341;
+  const SWord8 s5343 = (s5342 >> 1) | (s5342 << 7);
+  const SWord8 s5344 = 128 | s5343;
+  const SWord8 s5345 = 127 & s5343;
+  const SWord8 s5346 = s5336 ? s5344 : s5345;
+  const SWord8 s5347 = (s5346 >> 1) | (s5346 << 7);
+  const SWord8 s5348 = 128 | s5347;
+  const SWord8 s5349 = 127 & s5347;
+  const SWord8 s5350 = s5334 ? s5348 : s5349;
+  const SBool  s5351 = (SBool) (s2369 & 1);
+  const SBool  s5352 = false != s5351;
+  const SWord8 s5353 = s5352 ? s5348 : s5349;
+  const SWord8 s5354 = s2352 ? s5350 : s5353;
+  const SBool  s5355 = (SBool) (s2385 & 1);
+  const SBool  s5356 = false != s5355;
+  const SBool  s5357 = (SBool) (s2378 & 1);
+  const SBool  s5358 = false != s5357;
+  const SWord8 s5359 = s5358 ? s5344 : s5345;
+  const SWord8 s5360 = (s5359 >> 1) | (s5359 << 7);
+  const SWord8 s5361 = 128 | s5360;
+  const SWord8 s5362 = 127 & s5360;
+  const SWord8 s5363 = s5356 ? s5361 : s5362;
+  const SBool  s5364 = (SBool) (s2390 & 1);
+  const SBool  s5365 = false != s5364;
+  const SWord8 s5366 = s5365 ? s5361 : s5362;
+  const SWord8 s5367 = s2352 ? s5363 : s5366;
+  const SWord8 s5368 = s2330 ? s5354 : s5367;
+  const SBool  s5369 = (SBool) (s2411 & 1);
+  const SBool  s5370 = false != s5369;
+  const SBool  s5371 = (SBool) (s2407 & 1);
+  const SBool  s5372 = false != s5371;
+  const SBool  s5373 = (SBool) (s2400 & 1);
+  const SBool  s5374 = false != s5373;
+  const SWord8 s5375 = s5374 ? s5340 : s5341;
+  const SWord8 s5376 = (s5375 >> 1) | (s5375 << 7);
+  const SWord8 s5377 = 128 | s5376;
+  const SWord8 s5378 = 127 & s5376;
+  const SWord8 s5379 = s5372 ? s5377 : s5378;
+  const SWord8 s5380 = (s5379 >> 1) | (s5379 << 7);
+  const SWord8 s5381 = 128 | s5380;
+  const SWord8 s5382 = 127 & s5380;
+  const SWord8 s5383 = s5370 ? s5381 : s5382;
+  const SBool  s5384 = (SBool) (s2416 & 1);
+  const SBool  s5385 = false != s5384;
+  const SWord8 s5386 = s5385 ? s5381 : s5382;
+  const SWord8 s5387 = s2352 ? s5383 : s5386;
+  const SBool  s5388 = (SBool) (s2432 & 1);
+  const SBool  s5389 = false != s5388;
+  const SBool  s5390 = (SBool) (s2425 & 1);
+  const SBool  s5391 = false != s5390;
+  const SWord8 s5392 = s5391 ? s5377 : s5378;
+  const SWord8 s5393 = (s5392 >> 1) | (s5392 << 7);
+  const SWord8 s5394 = 128 | s5393;
+  const SWord8 s5395 = 127 & s5393;
+  const SWord8 s5396 = s5389 ? s5394 : s5395;
+  const SBool  s5397 = (SBool) (s2437 & 1);
+  const SBool  s5398 = false != s5397;
+  const SWord8 s5399 = s5398 ? s5394 : s5395;
+  const SWord8 s5400 = s2352 ? s5396 : s5399;
+  const SWord8 s5401 = s2330 ? s5387 : s5400;
+  const SWord8 s5402 = s2078 ? s5368 : s5401;
+  const SBool  s5403 = (SBool) (s2472 & 1);
+  const SBool  s5404 = false != s5403;
+  const SBool  s5405 = (SBool) (s2468 & 1);
+  const SBool  s5406 = false != s5405;
+  const SBool  s5407 = (SBool) (s2464 & 1);
+  const SBool  s5408 = false != s5407;
+  const SWord8 s5409 = (s2451 >> 1) | (s2451 << 7);
+  const SWord8 s5410 = 128 | s5409;
+  const SWord8 s5411 = 127 & s5409;
+  const SWord8 s5412 = s5408 ? s5410 : s5411;
+  const SWord8 s5413 = (s5412 >> 1) | (s5412 << 7);
+  const SWord8 s5414 = 128 | s5413;
+  const SWord8 s5415 = 127 & s5413;
+  const SWord8 s5416 = s5406 ? s5414 : s5415;
+  const SWord8 s5417 = (s5416 >> 1) | (s5416 << 7);
+  const SWord8 s5418 = 128 | s5417;
+  const SWord8 s5419 = 127 & s5417;
+  const SWord8 s5420 = s5404 ? s5418 : s5419;
+  const SBool  s5421 = (SBool) (s2477 & 1);
+  const SBool  s5422 = false != s5421;
+  const SWord8 s5423 = s5422 ? s5418 : s5419;
+  const SWord8 s5424 = s2457 ? s5420 : s5423;
+  const SBool  s5425 = (SBool) (s2493 & 1);
+  const SBool  s5426 = false != s5425;
+  const SBool  s5427 = (SBool) (s2486 & 1);
+  const SBool  s5428 = false != s5427;
+  const SWord8 s5429 = s5428 ? s5414 : s5415;
+  const SWord8 s5430 = (s5429 >> 1) | (s5429 << 7);
+  const SWord8 s5431 = 128 | s5430;
+  const SWord8 s5432 = 127 & s5430;
+  const SWord8 s5433 = s5426 ? s5431 : s5432;
+  const SBool  s5434 = (SBool) (s2498 & 1);
+  const SBool  s5435 = false != s5434;
+  const SWord8 s5436 = s5435 ? s5431 : s5432;
+  const SWord8 s5437 = s2457 ? s5433 : s5436;
+  const SWord8 s5438 = s2330 ? s5424 : s5437;
+  const SBool  s5439 = (SBool) (s2519 & 1);
+  const SBool  s5440 = false != s5439;
+  const SBool  s5441 = (SBool) (s2515 & 1);
+  const SBool  s5442 = false != s5441;
+  const SBool  s5443 = (SBool) (s2508 & 1);
+  const SBool  s5444 = false != s5443;
+  const SWord8 s5445 = s5444 ? s5410 : s5411;
+  const SWord8 s5446 = (s5445 >> 1) | (s5445 << 7);
+  const SWord8 s5447 = 128 | s5446;
+  const SWord8 s5448 = 127 & s5446;
+  const SWord8 s5449 = s5442 ? s5447 : s5448;
+  const SWord8 s5450 = (s5449 >> 1) | (s5449 << 7);
+  const SWord8 s5451 = 128 | s5450;
+  const SWord8 s5452 = 127 & s5450;
+  const SWord8 s5453 = s5440 ? s5451 : s5452;
+  const SBool  s5454 = (SBool) (s2524 & 1);
+  const SBool  s5455 = false != s5454;
+  const SWord8 s5456 = s5455 ? s5451 : s5452;
+  const SWord8 s5457 = s2457 ? s5453 : s5456;
+  const SBool  s5458 = (SBool) (s2540 & 1);
+  const SBool  s5459 = false != s5458;
+  const SBool  s5460 = (SBool) (s2533 & 1);
+  const SBool  s5461 = false != s5460;
+  const SWord8 s5462 = s5461 ? s5447 : s5448;
+  const SWord8 s5463 = (s5462 >> 1) | (s5462 << 7);
+  const SWord8 s5464 = 128 | s5463;
+  const SWord8 s5465 = 127 & s5463;
+  const SWord8 s5466 = s5459 ? s5464 : s5465;
+  const SBool  s5467 = (SBool) (s2545 & 1);
+  const SBool  s5468 = false != s5467;
+  const SWord8 s5469 = s5468 ? s5464 : s5465;
+  const SWord8 s5470 = s2457 ? s5466 : s5469;
+  const SWord8 s5471 = s2330 ? s5457 : s5470;
+  const SWord8 s5472 = s2078 ? s5438 : s5471;
+  const SWord8 s5473 = s2059 ? s5402 : s5472;
+  const SWord8 s5474 = s2042 ? s5332 : s5473;
+  const SBool  s5475 = (SBool) (s2620 & 1);
+  const SBool  s5476 = false != s5475;
+  const SBool  s5477 = (SBool) (s2616 & 1);
+  const SBool  s5478 = false != s5477;
+  const SBool  s5479 = (SBool) (s2612 & 1);
+  const SBool  s5480 = false != s5479;
+  const SWord8 s5481 = (s2599 >> 1) | (s2599 << 7);
+  const SWord8 s5482 = 128 | s5481;
+  const SWord8 s5483 = 127 & s5481;
+  const SWord8 s5484 = s5480 ? s5482 : s5483;
+  const SWord8 s5485 = (s5484 >> 1) | (s5484 << 7);
+  const SWord8 s5486 = 128 | s5485;
+  const SWord8 s5487 = 127 & s5485;
+  const SWord8 s5488 = s5478 ? s5486 : s5487;
+  const SWord8 s5489 = (s5488 >> 1) | (s5488 << 7);
+  const SWord8 s5490 = 128 | s5489;
+  const SWord8 s5491 = 127 & s5489;
+  const SWord8 s5492 = s5476 ? s5490 : s5491;
+  const SBool  s5493 = (SBool) (s2625 & 1);
+  const SBool  s5494 = false != s5493;
+  const SWord8 s5495 = s5494 ? s5490 : s5491;
+  const SWord8 s5496 = s2608 ? s5492 : s5495;
+  const SBool  s5497 = (SBool) (s2641 & 1);
+  const SBool  s5498 = false != s5497;
+  const SBool  s5499 = (SBool) (s2634 & 1);
+  const SBool  s5500 = false != s5499;
+  const SWord8 s5501 = s5500 ? s5486 : s5487;
+  const SWord8 s5502 = (s5501 >> 1) | (s5501 << 7);
+  const SWord8 s5503 = 128 | s5502;
+  const SWord8 s5504 = 127 & s5502;
+  const SWord8 s5505 = s5498 ? s5503 : s5504;
+  const SBool  s5506 = (SBool) (s2646 & 1);
+  const SBool  s5507 = false != s5506;
+  const SWord8 s5508 = s5507 ? s5503 : s5504;
+  const SWord8 s5509 = s2608 ? s5505 : s5508;
+  const SWord8 s5510 = s2589 ? s5496 : s5509;
+  const SBool  s5511 = (SBool) (s2667 & 1);
+  const SBool  s5512 = false != s5511;
+  const SBool  s5513 = (SBool) (s2663 & 1);
+  const SBool  s5514 = false != s5513;
+  const SBool  s5515 = (SBool) (s2656 & 1);
+  const SBool  s5516 = false != s5515;
+  const SWord8 s5517 = s5516 ? s5482 : s5483;
+  const SWord8 s5518 = (s5517 >> 1) | (s5517 << 7);
+  const SWord8 s5519 = 128 | s5518;
+  const SWord8 s5520 = 127 & s5518;
+  const SWord8 s5521 = s5514 ? s5519 : s5520;
+  const SWord8 s5522 = (s5521 >> 1) | (s5521 << 7);
+  const SWord8 s5523 = 128 | s5522;
+  const SWord8 s5524 = 127 & s5522;
+  const SWord8 s5525 = s5512 ? s5523 : s5524;
+  const SBool  s5526 = (SBool) (s2672 & 1);
+  const SBool  s5527 = false != s5526;
+  const SWord8 s5528 = s5527 ? s5523 : s5524;
+  const SWord8 s5529 = s2608 ? s5525 : s5528;
+  const SBool  s5530 = (SBool) (s2688 & 1);
+  const SBool  s5531 = false != s5530;
+  const SBool  s5532 = (SBool) (s2681 & 1);
+  const SBool  s5533 = false != s5532;
+  const SWord8 s5534 = s5533 ? s5519 : s5520;
+  const SWord8 s5535 = (s5534 >> 1) | (s5534 << 7);
+  const SWord8 s5536 = 128 | s5535;
+  const SWord8 s5537 = 127 & s5535;
+  const SWord8 s5538 = s5531 ? s5536 : s5537;
+  const SBool  s5539 = (SBool) (s2693 & 1);
+  const SBool  s5540 = false != s5539;
+  const SWord8 s5541 = s5540 ? s5536 : s5537;
+  const SWord8 s5542 = s2608 ? s5538 : s5541;
+  const SWord8 s5543 = s2589 ? s5529 : s5542;
+  const SWord8 s5544 = s2567 ? s5510 : s5543;
+  const SBool  s5545 = (SBool) (s2728 & 1);
+  const SBool  s5546 = false != s5545;
+  const SBool  s5547 = (SBool) (s2724 & 1);
+  const SBool  s5548 = false != s5547;
+  const SBool  s5549 = (SBool) (s2720 & 1);
+  const SBool  s5550 = false != s5549;
+  const SWord8 s5551 = (s2707 >> 1) | (s2707 << 7);
+  const SWord8 s5552 = 128 | s5551;
+  const SWord8 s5553 = 127 & s5551;
+  const SWord8 s5554 = s5550 ? s5552 : s5553;
+  const SWord8 s5555 = (s5554 >> 1) | (s5554 << 7);
+  const SWord8 s5556 = 128 | s5555;
+  const SWord8 s5557 = 127 & s5555;
+  const SWord8 s5558 = s5548 ? s5556 : s5557;
+  const SWord8 s5559 = (s5558 >> 1) | (s5558 << 7);
+  const SWord8 s5560 = 128 | s5559;
+  const SWord8 s5561 = 127 & s5559;
+  const SWord8 s5562 = s5546 ? s5560 : s5561;
+  const SBool  s5563 = (SBool) (s2733 & 1);
+  const SBool  s5564 = false != s5563;
+  const SWord8 s5565 = s5564 ? s5560 : s5561;
+  const SWord8 s5566 = s2713 ? s5562 : s5565;
+  const SBool  s5567 = (SBool) (s2749 & 1);
+  const SBool  s5568 = false != s5567;
+  const SBool  s5569 = (SBool) (s2742 & 1);
+  const SBool  s5570 = false != s5569;
+  const SWord8 s5571 = s5570 ? s5556 : s5557;
+  const SWord8 s5572 = (s5571 >> 1) | (s5571 << 7);
+  const SWord8 s5573 = 128 | s5572;
+  const SWord8 s5574 = 127 & s5572;
+  const SWord8 s5575 = s5568 ? s5573 : s5574;
+  const SBool  s5576 = (SBool) (s2754 & 1);
+  const SBool  s5577 = false != s5576;
+  const SWord8 s5578 = s5577 ? s5573 : s5574;
+  const SWord8 s5579 = s2713 ? s5575 : s5578;
+  const SWord8 s5580 = s2589 ? s5566 : s5579;
+  const SBool  s5581 = (SBool) (s2775 & 1);
+  const SBool  s5582 = false != s5581;
+  const SBool  s5583 = (SBool) (s2771 & 1);
+  const SBool  s5584 = false != s5583;
+  const SBool  s5585 = (SBool) (s2764 & 1);
+  const SBool  s5586 = false != s5585;
+  const SWord8 s5587 = s5586 ? s5552 : s5553;
+  const SWord8 s5588 = (s5587 >> 1) | (s5587 << 7);
+  const SWord8 s5589 = 128 | s5588;
+  const SWord8 s5590 = 127 & s5588;
+  const SWord8 s5591 = s5584 ? s5589 : s5590;
+  const SWord8 s5592 = (s5591 >> 1) | (s5591 << 7);
+  const SWord8 s5593 = 128 | s5592;
+  const SWord8 s5594 = 127 & s5592;
+  const SWord8 s5595 = s5582 ? s5593 : s5594;
+  const SBool  s5596 = (SBool) (s2780 & 1);
+  const SBool  s5597 = false != s5596;
+  const SWord8 s5598 = s5597 ? s5593 : s5594;
+  const SWord8 s5599 = s2713 ? s5595 : s5598;
+  const SBool  s5600 = (SBool) (s2796 & 1);
+  const SBool  s5601 = false != s5600;
+  const SBool  s5602 = (SBool) (s2789 & 1);
+  const SBool  s5603 = false != s5602;
+  const SWord8 s5604 = s5603 ? s5589 : s5590;
+  const SWord8 s5605 = (s5604 >> 1) | (s5604 << 7);
+  const SWord8 s5606 = 128 | s5605;
+  const SWord8 s5607 = 127 & s5605;
+  const SWord8 s5608 = s5601 ? s5606 : s5607;
+  const SBool  s5609 = (SBool) (s2801 & 1);
+  const SBool  s5610 = false != s5609;
+  const SWord8 s5611 = s5610 ? s5606 : s5607;
+  const SWord8 s5612 = s2713 ? s5608 : s5611;
+  const SWord8 s5613 = s2589 ? s5599 : s5612;
+  const SWord8 s5614 = s2567 ? s5580 : s5613;
+  const SWord8 s5615 = s2059 ? s5544 : s5614;
+  const SBool  s5616 = (SBool) (s2856 & 1);
+  const SBool  s5617 = false != s5616;
+  const SBool  s5618 = (SBool) (s2852 & 1);
+  const SBool  s5619 = false != s5618;
+  const SBool  s5620 = (SBool) (s2848 & 1);
+  const SBool  s5621 = false != s5620;
+  const SWord8 s5622 = (s2835 >> 1) | (s2835 << 7);
+  const SWord8 s5623 = 128 | s5622;
+  const SWord8 s5624 = 127 & s5622;
+  const SWord8 s5625 = s5621 ? s5623 : s5624;
+  const SWord8 s5626 = (s5625 >> 1) | (s5625 << 7);
+  const SWord8 s5627 = 128 | s5626;
+  const SWord8 s5628 = 127 & s5626;
+  const SWord8 s5629 = s5619 ? s5627 : s5628;
+  const SWord8 s5630 = (s5629 >> 1) | (s5629 << 7);
+  const SWord8 s5631 = 128 | s5630;
+  const SWord8 s5632 = 127 & s5630;
+  const SWord8 s5633 = s5617 ? s5631 : s5632;
+  const SBool  s5634 = (SBool) (s2861 & 1);
+  const SBool  s5635 = false != s5634;
+  const SWord8 s5636 = s5635 ? s5631 : s5632;
+  const SWord8 s5637 = s2844 ? s5633 : s5636;
+  const SBool  s5638 = (SBool) (s2877 & 1);
+  const SBool  s5639 = false != s5638;
+  const SBool  s5640 = (SBool) (s2870 & 1);
+  const SBool  s5641 = false != s5640;
+  const SWord8 s5642 = s5641 ? s5627 : s5628;
+  const SWord8 s5643 = (s5642 >> 1) | (s5642 << 7);
+  const SWord8 s5644 = 128 | s5643;
+  const SWord8 s5645 = 127 & s5643;
+  const SWord8 s5646 = s5639 ? s5644 : s5645;
+  const SBool  s5647 = (SBool) (s2882 & 1);
+  const SBool  s5648 = false != s5647;
+  const SWord8 s5649 = s5648 ? s5644 : s5645;
+  const SWord8 s5650 = s2844 ? s5646 : s5649;
+  const SWord8 s5651 = s2822 ? s5637 : s5650;
+  const SBool  s5652 = (SBool) (s2903 & 1);
+  const SBool  s5653 = false != s5652;
+  const SBool  s5654 = (SBool) (s2899 & 1);
+  const SBool  s5655 = false != s5654;
+  const SBool  s5656 = (SBool) (s2892 & 1);
+  const SBool  s5657 = false != s5656;
+  const SWord8 s5658 = s5657 ? s5623 : s5624;
+  const SWord8 s5659 = (s5658 >> 1) | (s5658 << 7);
+  const SWord8 s5660 = 128 | s5659;
+  const SWord8 s5661 = 127 & s5659;
+  const SWord8 s5662 = s5655 ? s5660 : s5661;
+  const SWord8 s5663 = (s5662 >> 1) | (s5662 << 7);
+  const SWord8 s5664 = 128 | s5663;
+  const SWord8 s5665 = 127 & s5663;
+  const SWord8 s5666 = s5653 ? s5664 : s5665;
+  const SBool  s5667 = (SBool) (s2908 & 1);
+  const SBool  s5668 = false != s5667;
+  const SWord8 s5669 = s5668 ? s5664 : s5665;
+  const SWord8 s5670 = s2844 ? s5666 : s5669;
+  const SBool  s5671 = (SBool) (s2924 & 1);
+  const SBool  s5672 = false != s5671;
+  const SBool  s5673 = (SBool) (s2917 & 1);
+  const SBool  s5674 = false != s5673;
+  const SWord8 s5675 = s5674 ? s5660 : s5661;
+  const SWord8 s5676 = (s5675 >> 1) | (s5675 << 7);
+  const SWord8 s5677 = 128 | s5676;
+  const SWord8 s5678 = 127 & s5676;
+  const SWord8 s5679 = s5672 ? s5677 : s5678;
+  const SBool  s5680 = (SBool) (s2929 & 1);
+  const SBool  s5681 = false != s5680;
+  const SWord8 s5682 = s5681 ? s5677 : s5678;
+  const SWord8 s5683 = s2844 ? s5679 : s5682;
+  const SWord8 s5684 = s2822 ? s5670 : s5683;
+  const SWord8 s5685 = s2567 ? s5651 : s5684;
+  const SBool  s5686 = (SBool) (s2964 & 1);
+  const SBool  s5687 = false != s5686;
+  const SBool  s5688 = (SBool) (s2960 & 1);
+  const SBool  s5689 = false != s5688;
+  const SBool  s5690 = (SBool) (s2956 & 1);
+  const SBool  s5691 = false != s5690;
+  const SWord8 s5692 = (s2943 >> 1) | (s2943 << 7);
+  const SWord8 s5693 = 128 | s5692;
+  const SWord8 s5694 = 127 & s5692;
+  const SWord8 s5695 = s5691 ? s5693 : s5694;
+  const SWord8 s5696 = (s5695 >> 1) | (s5695 << 7);
+  const SWord8 s5697 = 128 | s5696;
+  const SWord8 s5698 = 127 & s5696;
+  const SWord8 s5699 = s5689 ? s5697 : s5698;
+  const SWord8 s5700 = (s5699 >> 1) | (s5699 << 7);
+  const SWord8 s5701 = 128 | s5700;
+  const SWord8 s5702 = 127 & s5700;
+  const SWord8 s5703 = s5687 ? s5701 : s5702;
+  const SBool  s5704 = (SBool) (s2969 & 1);
+  const SBool  s5705 = false != s5704;
+  const SWord8 s5706 = s5705 ? s5701 : s5702;
+  const SWord8 s5707 = s2949 ? s5703 : s5706;
+  const SBool  s5708 = (SBool) (s2985 & 1);
+  const SBool  s5709 = false != s5708;
+  const SBool  s5710 = (SBool) (s2978 & 1);
+  const SBool  s5711 = false != s5710;
+  const SWord8 s5712 = s5711 ? s5697 : s5698;
+  const SWord8 s5713 = (s5712 >> 1) | (s5712 << 7);
+  const SWord8 s5714 = 128 | s5713;
+  const SWord8 s5715 = 127 & s5713;
+  const SWord8 s5716 = s5709 ? s5714 : s5715;
+  const SBool  s5717 = (SBool) (s2990 & 1);
+  const SBool  s5718 = false != s5717;
+  const SWord8 s5719 = s5718 ? s5714 : s5715;
+  const SWord8 s5720 = s2949 ? s5716 : s5719;
+  const SWord8 s5721 = s2822 ? s5707 : s5720;
+  const SBool  s5722 = (SBool) (s3011 & 1);
+  const SBool  s5723 = false != s5722;
+  const SBool  s5724 = (SBool) (s3007 & 1);
+  const SBool  s5725 = false != s5724;
+  const SBool  s5726 = (SBool) (s3000 & 1);
+  const SBool  s5727 = false != s5726;
+  const SWord8 s5728 = s5727 ? s5693 : s5694;
+  const SWord8 s5729 = (s5728 >> 1) | (s5728 << 7);
+  const SWord8 s5730 = 128 | s5729;
+  const SWord8 s5731 = 127 & s5729;
+  const SWord8 s5732 = s5725 ? s5730 : s5731;
+  const SWord8 s5733 = (s5732 >> 1) | (s5732 << 7);
+  const SWord8 s5734 = 128 | s5733;
+  const SWord8 s5735 = 127 & s5733;
+  const SWord8 s5736 = s5723 ? s5734 : s5735;
+  const SBool  s5737 = (SBool) (s3016 & 1);
+  const SBool  s5738 = false != s5737;
+  const SWord8 s5739 = s5738 ? s5734 : s5735;
+  const SWord8 s5740 = s2949 ? s5736 : s5739;
+  const SBool  s5741 = (SBool) (s3032 & 1);
+  const SBool  s5742 = false != s5741;
+  const SBool  s5743 = (SBool) (s3025 & 1);
+  const SBool  s5744 = false != s5743;
+  const SWord8 s5745 = s5744 ? s5730 : s5731;
+  const SWord8 s5746 = (s5745 >> 1) | (s5745 << 7);
+  const SWord8 s5747 = 128 | s5746;
+  const SWord8 s5748 = 127 & s5746;
+  const SWord8 s5749 = s5742 ? s5747 : s5748;
+  const SBool  s5750 = (SBool) (s3037 & 1);
+  const SBool  s5751 = false != s5750;
+  const SWord8 s5752 = s5751 ? s5747 : s5748;
+  const SWord8 s5753 = s2949 ? s5749 : s5752;
+  const SWord8 s5754 = s2822 ? s5740 : s5753;
+  const SWord8 s5755 = s2567 ? s5721 : s5754;
+  const SWord8 s5756 = s2059 ? s5685 : s5755;
+  const SWord8 s5757 = s2042 ? s5615 : s5756;
+  const SWord8 s5758 = s16 ? s5474 : s5757;
+  const SBool  s5759 = (SBool) (s3132 & 1);
+  const SBool  s5760 = false != s5759;
+  const SBool  s5761 = (SBool) (s3128 & 1);
+  const SBool  s5762 = false != s5761;
+  const SBool  s5763 = (SBool) (s3124 & 1);
+  const SBool  s5764 = false != s5763;
+  const SWord8 s5765 = (s3111 >> 1) | (s3111 << 7);
+  const SWord8 s5766 = 128 | s5765;
+  const SWord8 s5767 = 127 & s5765;
+  const SWord8 s5768 = s5764 ? s5766 : s5767;
+  const SWord8 s5769 = (s5768 >> 1) | (s5768 << 7);
+  const SWord8 s5770 = 128 | s5769;
+  const SWord8 s5771 = 127 & s5769;
+  const SWord8 s5772 = s5762 ? s5770 : s5771;
+  const SWord8 s5773 = (s5772 >> 1) | (s5772 << 7);
+  const SWord8 s5774 = 128 | s5773;
+  const SWord8 s5775 = 127 & s5773;
+  const SWord8 s5776 = s5760 ? s5774 : s5775;
+  const SBool  s5777 = (SBool) (s3137 & 1);
+  const SBool  s5778 = false != s5777;
+  const SWord8 s5779 = s5778 ? s5774 : s5775;
+  const SWord8 s5780 = s3120 ? s5776 : s5779;
+  const SBool  s5781 = (SBool) (s3153 & 1);
+  const SBool  s5782 = false != s5781;
+  const SBool  s5783 = (SBool) (s3146 & 1);
+  const SBool  s5784 = false != s5783;
+  const SWord8 s5785 = s5784 ? s5770 : s5771;
+  const SWord8 s5786 = (s5785 >> 1) | (s5785 << 7);
+  const SWord8 s5787 = 128 | s5786;
+  const SWord8 s5788 = 127 & s5786;
+  const SWord8 s5789 = s5782 ? s5787 : s5788;
+  const SBool  s5790 = (SBool) (s3158 & 1);
+  const SBool  s5791 = false != s5790;
+  const SWord8 s5792 = s5791 ? s5787 : s5788;
+  const SWord8 s5793 = s3120 ? s5789 : s5792;
+  const SWord8 s5794 = s3101 ? s5780 : s5793;
+  const SBool  s5795 = (SBool) (s3179 & 1);
+  const SBool  s5796 = false != s5795;
+  const SBool  s5797 = (SBool) (s3175 & 1);
+  const SBool  s5798 = false != s5797;
+  const SBool  s5799 = (SBool) (s3168 & 1);
+  const SBool  s5800 = false != s5799;
+  const SWord8 s5801 = s5800 ? s5766 : s5767;
+  const SWord8 s5802 = (s5801 >> 1) | (s5801 << 7);
+  const SWord8 s5803 = 128 | s5802;
+  const SWord8 s5804 = 127 & s5802;
+  const SWord8 s5805 = s5798 ? s5803 : s5804;
+  const SWord8 s5806 = (s5805 >> 1) | (s5805 << 7);
+  const SWord8 s5807 = 128 | s5806;
+  const SWord8 s5808 = 127 & s5806;
+  const SWord8 s5809 = s5796 ? s5807 : s5808;
+  const SBool  s5810 = (SBool) (s3184 & 1);
+  const SBool  s5811 = false != s5810;
+  const SWord8 s5812 = s5811 ? s5807 : s5808;
+  const SWord8 s5813 = s3120 ? s5809 : s5812;
+  const SBool  s5814 = (SBool) (s3200 & 1);
+  const SBool  s5815 = false != s5814;
+  const SBool  s5816 = (SBool) (s3193 & 1);
+  const SBool  s5817 = false != s5816;
+  const SWord8 s5818 = s5817 ? s5803 : s5804;
+  const SWord8 s5819 = (s5818 >> 1) | (s5818 << 7);
+  const SWord8 s5820 = 128 | s5819;
+  const SWord8 s5821 = 127 & s5819;
+  const SWord8 s5822 = s5815 ? s5820 : s5821;
+  const SBool  s5823 = (SBool) (s3205 & 1);
+  const SBool  s5824 = false != s5823;
+  const SWord8 s5825 = s5824 ? s5820 : s5821;
+  const SWord8 s5826 = s3120 ? s5822 : s5825;
+  const SWord8 s5827 = s3101 ? s5813 : s5826;
+  const SWord8 s5828 = s3082 ? s5794 : s5827;
+  const SBool  s5829 = (SBool) (s3240 & 1);
+  const SBool  s5830 = false != s5829;
+  const SBool  s5831 = (SBool) (s3236 & 1);
+  const SBool  s5832 = false != s5831;
+  const SBool  s5833 = (SBool) (s3232 & 1);
+  const SBool  s5834 = false != s5833;
+  const SWord8 s5835 = (s3219 >> 1) | (s3219 << 7);
+  const SWord8 s5836 = 128 | s5835;
+  const SWord8 s5837 = 127 & s5835;
+  const SWord8 s5838 = s5834 ? s5836 : s5837;
+  const SWord8 s5839 = (s5838 >> 1) | (s5838 << 7);
+  const SWord8 s5840 = 128 | s5839;
+  const SWord8 s5841 = 127 & s5839;
+  const SWord8 s5842 = s5832 ? s5840 : s5841;
+  const SWord8 s5843 = (s5842 >> 1) | (s5842 << 7);
+  const SWord8 s5844 = 128 | s5843;
+  const SWord8 s5845 = 127 & s5843;
+  const SWord8 s5846 = s5830 ? s5844 : s5845;
+  const SBool  s5847 = (SBool) (s3245 & 1);
+  const SBool  s5848 = false != s5847;
+  const SWord8 s5849 = s5848 ? s5844 : s5845;
+  const SWord8 s5850 = s3225 ? s5846 : s5849;
+  const SBool  s5851 = (SBool) (s3261 & 1);
+  const SBool  s5852 = false != s5851;
+  const SBool  s5853 = (SBool) (s3254 & 1);
+  const SBool  s5854 = false != s5853;
+  const SWord8 s5855 = s5854 ? s5840 : s5841;
+  const SWord8 s5856 = (s5855 >> 1) | (s5855 << 7);
+  const SWord8 s5857 = 128 | s5856;
+  const SWord8 s5858 = 127 & s5856;
+  const SWord8 s5859 = s5852 ? s5857 : s5858;
+  const SBool  s5860 = (SBool) (s3266 & 1);
+  const SBool  s5861 = false != s5860;
+  const SWord8 s5862 = s5861 ? s5857 : s5858;
+  const SWord8 s5863 = s3225 ? s5859 : s5862;
+  const SWord8 s5864 = s3101 ? s5850 : s5863;
+  const SBool  s5865 = (SBool) (s3287 & 1);
+  const SBool  s5866 = false != s5865;
+  const SBool  s5867 = (SBool) (s3283 & 1);
+  const SBool  s5868 = false != s5867;
+  const SBool  s5869 = (SBool) (s3276 & 1);
+  const SBool  s5870 = false != s5869;
+  const SWord8 s5871 = s5870 ? s5836 : s5837;
+  const SWord8 s5872 = (s5871 >> 1) | (s5871 << 7);
+  const SWord8 s5873 = 128 | s5872;
+  const SWord8 s5874 = 127 & s5872;
+  const SWord8 s5875 = s5868 ? s5873 : s5874;
+  const SWord8 s5876 = (s5875 >> 1) | (s5875 << 7);
+  const SWord8 s5877 = 128 | s5876;
+  const SWord8 s5878 = 127 & s5876;
+  const SWord8 s5879 = s5866 ? s5877 : s5878;
+  const SBool  s5880 = (SBool) (s3292 & 1);
+  const SBool  s5881 = false != s5880;
+  const SWord8 s5882 = s5881 ? s5877 : s5878;
+  const SWord8 s5883 = s3225 ? s5879 : s5882;
+  const SBool  s5884 = (SBool) (s3308 & 1);
+  const SBool  s5885 = false != s5884;
+  const SBool  s5886 = (SBool) (s3301 & 1);
+  const SBool  s5887 = false != s5886;
+  const SWord8 s5888 = s5887 ? s5873 : s5874;
+  const SWord8 s5889 = (s5888 >> 1) | (s5888 << 7);
+  const SWord8 s5890 = 128 | s5889;
+  const SWord8 s5891 = 127 & s5889;
+  const SWord8 s5892 = s5885 ? s5890 : s5891;
+  const SBool  s5893 = (SBool) (s3313 & 1);
+  const SBool  s5894 = false != s5893;
+  const SWord8 s5895 = s5894 ? s5890 : s5891;
+  const SWord8 s5896 = s3225 ? s5892 : s5895;
+  const SWord8 s5897 = s3101 ? s5883 : s5896;
+  const SWord8 s5898 = s3082 ? s5864 : s5897;
+  const SWord8 s5899 = s3060 ? s5828 : s5898;
+  const SBool  s5900 = (SBool) (s3368 & 1);
+  const SBool  s5901 = false != s5900;
+  const SBool  s5902 = (SBool) (s3364 & 1);
+  const SBool  s5903 = false != s5902;
+  const SBool  s5904 = (SBool) (s3360 & 1);
+  const SBool  s5905 = false != s5904;
+  const SWord8 s5906 = (s3347 >> 1) | (s3347 << 7);
+  const SWord8 s5907 = 128 | s5906;
+  const SWord8 s5908 = 127 & s5906;
+  const SWord8 s5909 = s5905 ? s5907 : s5908;
+  const SWord8 s5910 = (s5909 >> 1) | (s5909 << 7);
+  const SWord8 s5911 = 128 | s5910;
+  const SWord8 s5912 = 127 & s5910;
+  const SWord8 s5913 = s5903 ? s5911 : s5912;
+  const SWord8 s5914 = (s5913 >> 1) | (s5913 << 7);
+  const SWord8 s5915 = 128 | s5914;
+  const SWord8 s5916 = 127 & s5914;
+  const SWord8 s5917 = s5901 ? s5915 : s5916;
+  const SBool  s5918 = (SBool) (s3373 & 1);
+  const SBool  s5919 = false != s5918;
+  const SWord8 s5920 = s5919 ? s5915 : s5916;
+  const SWord8 s5921 = s3356 ? s5917 : s5920;
+  const SBool  s5922 = (SBool) (s3389 & 1);
+  const SBool  s5923 = false != s5922;
+  const SBool  s5924 = (SBool) (s3382 & 1);
+  const SBool  s5925 = false != s5924;
+  const SWord8 s5926 = s5925 ? s5911 : s5912;
+  const SWord8 s5927 = (s5926 >> 1) | (s5926 << 7);
+  const SWord8 s5928 = 128 | s5927;
+  const SWord8 s5929 = 127 & s5927;
+  const SWord8 s5930 = s5923 ? s5928 : s5929;
+  const SBool  s5931 = (SBool) (s3394 & 1);
+  const SBool  s5932 = false != s5931;
+  const SWord8 s5933 = s5932 ? s5928 : s5929;
+  const SWord8 s5934 = s3356 ? s5930 : s5933;
+  const SWord8 s5935 = s3334 ? s5921 : s5934;
+  const SBool  s5936 = (SBool) (s3415 & 1);
+  const SBool  s5937 = false != s5936;
+  const SBool  s5938 = (SBool) (s3411 & 1);
+  const SBool  s5939 = false != s5938;
+  const SBool  s5940 = (SBool) (s3404 & 1);
+  const SBool  s5941 = false != s5940;
+  const SWord8 s5942 = s5941 ? s5907 : s5908;
+  const SWord8 s5943 = (s5942 >> 1) | (s5942 << 7);
+  const SWord8 s5944 = 128 | s5943;
+  const SWord8 s5945 = 127 & s5943;
+  const SWord8 s5946 = s5939 ? s5944 : s5945;
+  const SWord8 s5947 = (s5946 >> 1) | (s5946 << 7);
+  const SWord8 s5948 = 128 | s5947;
+  const SWord8 s5949 = 127 & s5947;
+  const SWord8 s5950 = s5937 ? s5948 : s5949;
+  const SBool  s5951 = (SBool) (s3420 & 1);
+  const SBool  s5952 = false != s5951;
+  const SWord8 s5953 = s5952 ? s5948 : s5949;
+  const SWord8 s5954 = s3356 ? s5950 : s5953;
+  const SBool  s5955 = (SBool) (s3436 & 1);
+  const SBool  s5956 = false != s5955;
+  const SBool  s5957 = (SBool) (s3429 & 1);
+  const SBool  s5958 = false != s5957;
+  const SWord8 s5959 = s5958 ? s5944 : s5945;
+  const SWord8 s5960 = (s5959 >> 1) | (s5959 << 7);
+  const SWord8 s5961 = 128 | s5960;
+  const SWord8 s5962 = 127 & s5960;
+  const SWord8 s5963 = s5956 ? s5961 : s5962;
+  const SBool  s5964 = (SBool) (s3441 & 1);
+  const SBool  s5965 = false != s5964;
+  const SWord8 s5966 = s5965 ? s5961 : s5962;
+  const SWord8 s5967 = s3356 ? s5963 : s5966;
+  const SWord8 s5968 = s3334 ? s5954 : s5967;
+  const SWord8 s5969 = s3082 ? s5935 : s5968;
+  const SBool  s5970 = (SBool) (s3476 & 1);
+  const SBool  s5971 = false != s5970;
+  const SBool  s5972 = (SBool) (s3472 & 1);
+  const SBool  s5973 = false != s5972;
+  const SBool  s5974 = (SBool) (s3468 & 1);
+  const SBool  s5975 = false != s5974;
+  const SWord8 s5976 = (s3455 >> 1) | (s3455 << 7);
+  const SWord8 s5977 = 128 | s5976;
+  const SWord8 s5978 = 127 & s5976;
+  const SWord8 s5979 = s5975 ? s5977 : s5978;
+  const SWord8 s5980 = (s5979 >> 1) | (s5979 << 7);
+  const SWord8 s5981 = 128 | s5980;
+  const SWord8 s5982 = 127 & s5980;
+  const SWord8 s5983 = s5973 ? s5981 : s5982;
+  const SWord8 s5984 = (s5983 >> 1) | (s5983 << 7);
+  const SWord8 s5985 = 128 | s5984;
+  const SWord8 s5986 = 127 & s5984;
+  const SWord8 s5987 = s5971 ? s5985 : s5986;
+  const SBool  s5988 = (SBool) (s3481 & 1);
+  const SBool  s5989 = false != s5988;
+  const SWord8 s5990 = s5989 ? s5985 : s5986;
+  const SWord8 s5991 = s3461 ? s5987 : s5990;
+  const SBool  s5992 = (SBool) (s3497 & 1);
+  const SBool  s5993 = false != s5992;
+  const SBool  s5994 = (SBool) (s3490 & 1);
+  const SBool  s5995 = false != s5994;
+  const SWord8 s5996 = s5995 ? s5981 : s5982;
+  const SWord8 s5997 = (s5996 >> 1) | (s5996 << 7);
+  const SWord8 s5998 = 128 | s5997;
+  const SWord8 s5999 = 127 & s5997;
+  const SWord8 s6000 = s5993 ? s5998 : s5999;
+  const SBool  s6001 = (SBool) (s3502 & 1);
+  const SBool  s6002 = false != s6001;
+  const SWord8 s6003 = s6002 ? s5998 : s5999;
+  const SWord8 s6004 = s3461 ? s6000 : s6003;
+  const SWord8 s6005 = s3334 ? s5991 : s6004;
+  const SBool  s6006 = (SBool) (s3523 & 1);
+  const SBool  s6007 = false != s6006;
+  const SBool  s6008 = (SBool) (s3519 & 1);
+  const SBool  s6009 = false != s6008;
+  const SBool  s6010 = (SBool) (s3512 & 1);
+  const SBool  s6011 = false != s6010;
+  const SWord8 s6012 = s6011 ? s5977 : s5978;
+  const SWord8 s6013 = (s6012 >> 1) | (s6012 << 7);
+  const SWord8 s6014 = 128 | s6013;
+  const SWord8 s6015 = 127 & s6013;
+  const SWord8 s6016 = s6009 ? s6014 : s6015;
+  const SWord8 s6017 = (s6016 >> 1) | (s6016 << 7);
+  const SWord8 s6018 = 128 | s6017;
+  const SWord8 s6019 = 127 & s6017;
+  const SWord8 s6020 = s6007 ? s6018 : s6019;
+  const SBool  s6021 = (SBool) (s3528 & 1);
+  const SBool  s6022 = false != s6021;
+  const SWord8 s6023 = s6022 ? s6018 : s6019;
+  const SWord8 s6024 = s3461 ? s6020 : s6023;
+  const SBool  s6025 = (SBool) (s3544 & 1);
+  const SBool  s6026 = false != s6025;
+  const SBool  s6027 = (SBool) (s3537 & 1);
+  const SBool  s6028 = false != s6027;
+  const SWord8 s6029 = s6028 ? s6014 : s6015;
+  const SWord8 s6030 = (s6029 >> 1) | (s6029 << 7);
+  const SWord8 s6031 = 128 | s6030;
+  const SWord8 s6032 = 127 & s6030;
+  const SWord8 s6033 = s6026 ? s6031 : s6032;
+  const SBool  s6034 = (SBool) (s3549 & 1);
+  const SBool  s6035 = false != s6034;
+  const SWord8 s6036 = s6035 ? s6031 : s6032;
+  const SWord8 s6037 = s3461 ? s6033 : s6036;
+  const SWord8 s6038 = s3334 ? s6024 : s6037;
+  const SWord8 s6039 = s3082 ? s6005 : s6038;
+  const SWord8 s6040 = s3060 ? s5969 : s6039;
+  const SWord8 s6041 = s2042 ? s5899 : s6040;
+  const SBool  s6042 = (SBool) (s3624 & 1);
+  const SBool  s6043 = false != s6042;
+  const SBool  s6044 = (SBool) (s3620 & 1);
+  const SBool  s6045 = false != s6044;
+  const SBool  s6046 = (SBool) (s3616 & 1);
+  const SBool  s6047 = false != s6046;
+  const SWord8 s6048 = (s3603 >> 1) | (s3603 << 7);
+  const SWord8 s6049 = 128 | s6048;
+  const SWord8 s6050 = 127 & s6048;
+  const SWord8 s6051 = s6047 ? s6049 : s6050;
+  const SWord8 s6052 = (s6051 >> 1) | (s6051 << 7);
+  const SWord8 s6053 = 128 | s6052;
+  const SWord8 s6054 = 127 & s6052;
+  const SWord8 s6055 = s6045 ? s6053 : s6054;
+  const SWord8 s6056 = (s6055 >> 1) | (s6055 << 7);
+  const SWord8 s6057 = 128 | s6056;
+  const SWord8 s6058 = 127 & s6056;
+  const SWord8 s6059 = s6043 ? s6057 : s6058;
+  const SBool  s6060 = (SBool) (s3629 & 1);
+  const SBool  s6061 = false != s6060;
+  const SWord8 s6062 = s6061 ? s6057 : s6058;
+  const SWord8 s6063 = s3612 ? s6059 : s6062;
+  const SBool  s6064 = (SBool) (s3645 & 1);
+  const SBool  s6065 = false != s6064;
+  const SBool  s6066 = (SBool) (s3638 & 1);
+  const SBool  s6067 = false != s6066;
+  const SWord8 s6068 = s6067 ? s6053 : s6054;
+  const SWord8 s6069 = (s6068 >> 1) | (s6068 << 7);
+  const SWord8 s6070 = 128 | s6069;
+  const SWord8 s6071 = 127 & s6069;
+  const SWord8 s6072 = s6065 ? s6070 : s6071;
+  const SBool  s6073 = (SBool) (s3650 & 1);
+  const SBool  s6074 = false != s6073;
+  const SWord8 s6075 = s6074 ? s6070 : s6071;
+  const SWord8 s6076 = s3612 ? s6072 : s6075;
+  const SWord8 s6077 = s3593 ? s6063 : s6076;
+  const SBool  s6078 = (SBool) (s3671 & 1);
+  const SBool  s6079 = false != s6078;
+  const SBool  s6080 = (SBool) (s3667 & 1);
+  const SBool  s6081 = false != s6080;
+  const SBool  s6082 = (SBool) (s3660 & 1);
+  const SBool  s6083 = false != s6082;
+  const SWord8 s6084 = s6083 ? s6049 : s6050;
+  const SWord8 s6085 = (s6084 >> 1) | (s6084 << 7);
+  const SWord8 s6086 = 128 | s6085;
+  const SWord8 s6087 = 127 & s6085;
+  const SWord8 s6088 = s6081 ? s6086 : s6087;
+  const SWord8 s6089 = (s6088 >> 1) | (s6088 << 7);
+  const SWord8 s6090 = 128 | s6089;
+  const SWord8 s6091 = 127 & s6089;
+  const SWord8 s6092 = s6079 ? s6090 : s6091;
+  const SBool  s6093 = (SBool) (s3676 & 1);
+  const SBool  s6094 = false != s6093;
+  const SWord8 s6095 = s6094 ? s6090 : s6091;
+  const SWord8 s6096 = s3612 ? s6092 : s6095;
+  const SBool  s6097 = (SBool) (s3692 & 1);
+  const SBool  s6098 = false != s6097;
+  const SBool  s6099 = (SBool) (s3685 & 1);
+  const SBool  s6100 = false != s6099;
+  const SWord8 s6101 = s6100 ? s6086 : s6087;
+  const SWord8 s6102 = (s6101 >> 1) | (s6101 << 7);
+  const SWord8 s6103 = 128 | s6102;
+  const SWord8 s6104 = 127 & s6102;
+  const SWord8 s6105 = s6098 ? s6103 : s6104;
+  const SBool  s6106 = (SBool) (s3697 & 1);
+  const SBool  s6107 = false != s6106;
+  const SWord8 s6108 = s6107 ? s6103 : s6104;
+  const SWord8 s6109 = s3612 ? s6105 : s6108;
+  const SWord8 s6110 = s3593 ? s6096 : s6109;
+  const SWord8 s6111 = s3571 ? s6077 : s6110;
+  const SBool  s6112 = (SBool) (s3732 & 1);
+  const SBool  s6113 = false != s6112;
+  const SBool  s6114 = (SBool) (s3728 & 1);
+  const SBool  s6115 = false != s6114;
+  const SBool  s6116 = (SBool) (s3724 & 1);
+  const SBool  s6117 = false != s6116;
+  const SWord8 s6118 = (s3711 >> 1) | (s3711 << 7);
+  const SWord8 s6119 = 128 | s6118;
+  const SWord8 s6120 = 127 & s6118;
+  const SWord8 s6121 = s6117 ? s6119 : s6120;
+  const SWord8 s6122 = (s6121 >> 1) | (s6121 << 7);
+  const SWord8 s6123 = 128 | s6122;
+  const SWord8 s6124 = 127 & s6122;
+  const SWord8 s6125 = s6115 ? s6123 : s6124;
+  const SWord8 s6126 = (s6125 >> 1) | (s6125 << 7);
+  const SWord8 s6127 = 128 | s6126;
+  const SWord8 s6128 = 127 & s6126;
+  const SWord8 s6129 = s6113 ? s6127 : s6128;
+  const SBool  s6130 = (SBool) (s3737 & 1);
+  const SBool  s6131 = false != s6130;
+  const SWord8 s6132 = s6131 ? s6127 : s6128;
+  const SWord8 s6133 = s3717 ? s6129 : s6132;
+  const SBool  s6134 = (SBool) (s3753 & 1);
+  const SBool  s6135 = false != s6134;
+  const SBool  s6136 = (SBool) (s3746 & 1);
+  const SBool  s6137 = false != s6136;
+  const SWord8 s6138 = s6137 ? s6123 : s6124;
+  const SWord8 s6139 = (s6138 >> 1) | (s6138 << 7);
+  const SWord8 s6140 = 128 | s6139;
+  const SWord8 s6141 = 127 & s6139;
+  const SWord8 s6142 = s6135 ? s6140 : s6141;
+  const SBool  s6143 = (SBool) (s3758 & 1);
+  const SBool  s6144 = false != s6143;
+  const SWord8 s6145 = s6144 ? s6140 : s6141;
+  const SWord8 s6146 = s3717 ? s6142 : s6145;
+  const SWord8 s6147 = s3593 ? s6133 : s6146;
+  const SBool  s6148 = (SBool) (s3779 & 1);
+  const SBool  s6149 = false != s6148;
+  const SBool  s6150 = (SBool) (s3775 & 1);
+  const SBool  s6151 = false != s6150;
+  const SBool  s6152 = (SBool) (s3768 & 1);
+  const SBool  s6153 = false != s6152;
+  const SWord8 s6154 = s6153 ? s6119 : s6120;
+  const SWord8 s6155 = (s6154 >> 1) | (s6154 << 7);
+  const SWord8 s6156 = 128 | s6155;
+  const SWord8 s6157 = 127 & s6155;
+  const SWord8 s6158 = s6151 ? s6156 : s6157;
+  const SWord8 s6159 = (s6158 >> 1) | (s6158 << 7);
+  const SWord8 s6160 = 128 | s6159;
+  const SWord8 s6161 = 127 & s6159;
+  const SWord8 s6162 = s6149 ? s6160 : s6161;
+  const SBool  s6163 = (SBool) (s3784 & 1);
+  const SBool  s6164 = false != s6163;
+  const SWord8 s6165 = s6164 ? s6160 : s6161;
+  const SWord8 s6166 = s3717 ? s6162 : s6165;
+  const SBool  s6167 = (SBool) (s3800 & 1);
+  const SBool  s6168 = false != s6167;
+  const SBool  s6169 = (SBool) (s3793 & 1);
+  const SBool  s6170 = false != s6169;
+  const SWord8 s6171 = s6170 ? s6156 : s6157;
+  const SWord8 s6172 = (s6171 >> 1) | (s6171 << 7);
+  const SWord8 s6173 = 128 | s6172;
+  const SWord8 s6174 = 127 & s6172;
+  const SWord8 s6175 = s6168 ? s6173 : s6174;
+  const SBool  s6176 = (SBool) (s3805 & 1);
+  const SBool  s6177 = false != s6176;
+  const SWord8 s6178 = s6177 ? s6173 : s6174;
+  const SWord8 s6179 = s3717 ? s6175 : s6178;
+  const SWord8 s6180 = s3593 ? s6166 : s6179;
+  const SWord8 s6181 = s3571 ? s6147 : s6180;
+  const SWord8 s6182 = s3060 ? s6111 : s6181;
+  const SBool  s6183 = (SBool) (s3860 & 1);
+  const SBool  s6184 = false != s6183;
+  const SBool  s6185 = (SBool) (s3856 & 1);
+  const SBool  s6186 = false != s6185;
+  const SBool  s6187 = (SBool) (s3852 & 1);
+  const SBool  s6188 = false != s6187;
+  const SWord8 s6189 = (s3839 >> 1) | (s3839 << 7);
+  const SWord8 s6190 = 128 | s6189;
+  const SWord8 s6191 = 127 & s6189;
+  const SWord8 s6192 = s6188 ? s6190 : s6191;
+  const SWord8 s6193 = (s6192 >> 1) | (s6192 << 7);
+  const SWord8 s6194 = 128 | s6193;
+  const SWord8 s6195 = 127 & s6193;
+  const SWord8 s6196 = s6186 ? s6194 : s6195;
+  const SWord8 s6197 = (s6196 >> 1) | (s6196 << 7);
+  const SWord8 s6198 = 128 | s6197;
+  const SWord8 s6199 = 127 & s6197;
+  const SWord8 s6200 = s6184 ? s6198 : s6199;
+  const SBool  s6201 = (SBool) (s3865 & 1);
+  const SBool  s6202 = false != s6201;
+  const SWord8 s6203 = s6202 ? s6198 : s6199;
+  const SWord8 s6204 = s3848 ? s6200 : s6203;
+  const SBool  s6205 = (SBool) (s3881 & 1);
+  const SBool  s6206 = false != s6205;
+  const SBool  s6207 = (SBool) (s3874 & 1);
+  const SBool  s6208 = false != s6207;
+  const SWord8 s6209 = s6208 ? s6194 : s6195;
+  const SWord8 s6210 = (s6209 >> 1) | (s6209 << 7);
+  const SWord8 s6211 = 128 | s6210;
+  const SWord8 s6212 = 127 & s6210;
+  const SWord8 s6213 = s6206 ? s6211 : s6212;
+  const SBool  s6214 = (SBool) (s3886 & 1);
+  const SBool  s6215 = false != s6214;
+  const SWord8 s6216 = s6215 ? s6211 : s6212;
+  const SWord8 s6217 = s3848 ? s6213 : s6216;
+  const SWord8 s6218 = s3826 ? s6204 : s6217;
+  const SBool  s6219 = (SBool) (s3907 & 1);
+  const SBool  s6220 = false != s6219;
+  const SBool  s6221 = (SBool) (s3903 & 1);
+  const SBool  s6222 = false != s6221;
+  const SBool  s6223 = (SBool) (s3896 & 1);
+  const SBool  s6224 = false != s6223;
+  const SWord8 s6225 = s6224 ? s6190 : s6191;
+  const SWord8 s6226 = (s6225 >> 1) | (s6225 << 7);
+  const SWord8 s6227 = 128 | s6226;
+  const SWord8 s6228 = 127 & s6226;
+  const SWord8 s6229 = s6222 ? s6227 : s6228;
+  const SWord8 s6230 = (s6229 >> 1) | (s6229 << 7);
+  const SWord8 s6231 = 128 | s6230;
+  const SWord8 s6232 = 127 & s6230;
+  const SWord8 s6233 = s6220 ? s6231 : s6232;
+  const SBool  s6234 = (SBool) (s3912 & 1);
+  const SBool  s6235 = false != s6234;
+  const SWord8 s6236 = s6235 ? s6231 : s6232;
+  const SWord8 s6237 = s3848 ? s6233 : s6236;
+  const SBool  s6238 = (SBool) (s3928 & 1);
+  const SBool  s6239 = false != s6238;
+  const SBool  s6240 = (SBool) (s3921 & 1);
+  const SBool  s6241 = false != s6240;
+  const SWord8 s6242 = s6241 ? s6227 : s6228;
+  const SWord8 s6243 = (s6242 >> 1) | (s6242 << 7);
+  const SWord8 s6244 = 128 | s6243;
+  const SWord8 s6245 = 127 & s6243;
+  const SWord8 s6246 = s6239 ? s6244 : s6245;
+  const SBool  s6247 = (SBool) (s3933 & 1);
+  const SBool  s6248 = false != s6247;
+  const SWord8 s6249 = s6248 ? s6244 : s6245;
+  const SWord8 s6250 = s3848 ? s6246 : s6249;
+  const SWord8 s6251 = s3826 ? s6237 : s6250;
+  const SWord8 s6252 = s3571 ? s6218 : s6251;
+  const SBool  s6253 = (SBool) (s3968 & 1);
+  const SBool  s6254 = false != s6253;
+  const SBool  s6255 = (SBool) (s3964 & 1);
+  const SBool  s6256 = false != s6255;
+  const SBool  s6257 = (SBool) (s3960 & 1);
+  const SBool  s6258 = false != s6257;
+  const SWord8 s6259 = (s3947 >> 1) | (s3947 << 7);
+  const SWord8 s6260 = 128 | s6259;
+  const SWord8 s6261 = 127 & s6259;
+  const SWord8 s6262 = s6258 ? s6260 : s6261;
+  const SWord8 s6263 = (s6262 >> 1) | (s6262 << 7);
+  const SWord8 s6264 = 128 | s6263;
+  const SWord8 s6265 = 127 & s6263;
+  const SWord8 s6266 = s6256 ? s6264 : s6265;
+  const SWord8 s6267 = (s6266 >> 1) | (s6266 << 7);
+  const SWord8 s6268 = 128 | s6267;
+  const SWord8 s6269 = 127 & s6267;
+  const SWord8 s6270 = s6254 ? s6268 : s6269;
+  const SBool  s6271 = (SBool) (s3973 & 1);
+  const SBool  s6272 = false != s6271;
+  const SWord8 s6273 = s6272 ? s6268 : s6269;
+  const SWord8 s6274 = s3953 ? s6270 : s6273;
+  const SBool  s6275 = (SBool) (s3989 & 1);
+  const SBool  s6276 = false != s6275;
+  const SBool  s6277 = (SBool) (s3982 & 1);
+  const SBool  s6278 = false != s6277;
+  const SWord8 s6279 = s6278 ? s6264 : s6265;
+  const SWord8 s6280 = (s6279 >> 1) | (s6279 << 7);
+  const SWord8 s6281 = 128 | s6280;
+  const SWord8 s6282 = 127 & s6280;
+  const SWord8 s6283 = s6276 ? s6281 : s6282;
+  const SBool  s6284 = (SBool) (s3994 & 1);
+  const SBool  s6285 = false != s6284;
+  const SWord8 s6286 = s6285 ? s6281 : s6282;
+  const SWord8 s6287 = s3953 ? s6283 : s6286;
+  const SWord8 s6288 = s3826 ? s6274 : s6287;
+  const SBool  s6289 = (SBool) (s4015 & 1);
+  const SBool  s6290 = false != s6289;
+  const SBool  s6291 = (SBool) (s4011 & 1);
+  const SBool  s6292 = false != s6291;
+  const SBool  s6293 = (SBool) (s4004 & 1);
+  const SBool  s6294 = false != s6293;
+  const SWord8 s6295 = s6294 ? s6260 : s6261;
+  const SWord8 s6296 = (s6295 >> 1) | (s6295 << 7);
+  const SWord8 s6297 = 128 | s6296;
+  const SWord8 s6298 = 127 & s6296;
+  const SWord8 s6299 = s6292 ? s6297 : s6298;
+  const SWord8 s6300 = (s6299 >> 1) | (s6299 << 7);
+  const SWord8 s6301 = 128 | s6300;
+  const SWord8 s6302 = 127 & s6300;
+  const SWord8 s6303 = s6290 ? s6301 : s6302;
+  const SBool  s6304 = (SBool) (s4020 & 1);
+  const SBool  s6305 = false != s6304;
+  const SWord8 s6306 = s6305 ? s6301 : s6302;
+  const SWord8 s6307 = s3953 ? s6303 : s6306;
+  const SBool  s6308 = (SBool) (s4036 & 1);
+  const SBool  s6309 = false != s6308;
+  const SBool  s6310 = (SBool) (s4029 & 1);
+  const SBool  s6311 = false != s6310;
+  const SWord8 s6312 = s6311 ? s6297 : s6298;
+  const SWord8 s6313 = (s6312 >> 1) | (s6312 << 7);
+  const SWord8 s6314 = 128 | s6313;
+  const SWord8 s6315 = 127 & s6313;
+  const SWord8 s6316 = s6309 ? s6314 : s6315;
+  const SBool  s6317 = (SBool) (s4041 & 1);
+  const SBool  s6318 = false != s6317;
+  const SWord8 s6319 = s6318 ? s6314 : s6315;
+  const SWord8 s6320 = s3953 ? s6316 : s6319;
+  const SWord8 s6321 = s3826 ? s6307 : s6320;
+  const SWord8 s6322 = s3571 ? s6288 : s6321;
+  const SWord8 s6323 = s3060 ? s6252 : s6322;
+  const SWord8 s6324 = s2042 ? s6182 : s6323;
+  const SWord8 s6325 = s16 ? s6041 : s6324;
+  const SWord8 s6326 = s11 ? s5758 : s6325;
+  const SWord8 s6327 = s5 ? s5191 : s6326;
+
+  *hi = s4056;
+  *lo = s6327;
+}
+== END: "legatoMult.c" ==================
diff --git a/SBVTestSuite/GoldFiles/listFloat1.gold b/SBVTestSuite/GoldFiles/listFloat1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/listFloat1.gold
@@ -0,0 +1,18 @@
+
+EXCEPTION:
+
+*** Data.SBV: Unsupported complicated comparison:
+***
+***   Op  : ==
+***   Type: [SFloat]
+***
+*** Due to the presence of NaN, comparisons over this type require
+*** special support in SMTLib. And in general this can lead to
+*** performance issues since the comparison is no longer a natively
+*** supported operation in the logic.
+***
+*** NB. If you want the semantics NaN == NaN, and +0 /= -0, then you can use .=== instead.
+***
+*** For this case, please use: Data.SBV.List.listEq
+*** but beware of performance/decidability implications.
+
diff --git a/SBVTestSuite/GoldFiles/listFloat2.gold b/SBVTestSuite/GoldFiles/listFloat2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/listFloat2.gold
@@ -0,0 +1,168 @@
+[MEASURE] Verifying termination measures for: listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)
+[MEASURE] Checking: listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)
+[MEASURE] listEq @(SBV [Float] -> SBV [Float] -> SBV Bool): barified = "|listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)|"
+[MEASURE] listEq @(SBV [Float] -> SBV [Float] -> SBV Bool): Uninterpreted ops in DAG: [("|listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)|",2)]
+[MEASURE] listEq @(SBV [Float] -> SBV [Float] -> SBV Bool): recursive calls found = 1
+[MEASURE] listEq @(SBV [Float] -> SBV [Float] -> SBV Bool): trying length arg1
+[MEASURE] replayDAG {listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ FloatingPoint  8 24))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq (_ FloatingPoint  8 24))) ; tracks user variable "arg1"
+[GOOD] (declare-fun s15 () Bool) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Int (seq.len s1))
+[GOOD] (define-fun s7 () Bool (= s2 s6))
+[GOOD] (define-fun s8 () (_ FloatingPoint  8 24) (seq.nth s0 s2))
+[GOOD] (define-fun s9 () (_ FloatingPoint  8 24) (seq.nth s1 s2))
+[GOOD] (define-fun s10 () Bool (fp.eq s8 s9))
+[GOOD] (define-fun s11 () Int (- s4 s3))
+[GOOD] (define-fun s12 () (Seq (_ FloatingPoint  8 24)) (seq.extract s0 s3 s11))
+[GOOD] (define-fun s13 () Int (- s6 s3))
+[GOOD] (define-fun s14 () (Seq (_ FloatingPoint  8 24)) (seq.extract s1 s3 s13))
+[GOOD] (define-fun s16 () Bool (and s10 s15))
+[GOOD] (define-fun s17 () Bool (not s7))
+[GOOD] (define-fun s18 () Bool (and s16 s17))
+[GOOD] (define-fun s19 () Bool (ite s5 s7 s18))
+[GOOD] (define-fun s20 () Bool (>= s4 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s20))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)}: replaying 16 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (_ FloatingPoint  8 24))) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () (Seq (_ FloatingPoint  8 24))) ; tracks user variable "arg1"
+[GOOD] (declare-fun s15 () Bool) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Int (seq.len s1))
+[GOOD] (define-fun s7 () Bool (= s2 s6))
+[GOOD] (define-fun s8 () (_ FloatingPoint  8 24) (seq.nth s0 s2))
+[GOOD] (define-fun s9 () (_ FloatingPoint  8 24) (seq.nth s1 s2))
+[GOOD] (define-fun s10 () Bool (fp.eq s8 s9))
+[GOOD] (define-fun s11 () Int (- s4 s3))
+[GOOD] (define-fun s12 () (Seq (_ FloatingPoint  8 24)) (seq.extract s0 s3 s11))
+[GOOD] (define-fun s13 () Int (- s6 s3))
+[GOOD] (define-fun s14 () (Seq (_ FloatingPoint  8 24)) (seq.extract s1 s3 s13))
+[GOOD] (define-fun s16 () Bool (and s10 s15))
+[GOOD] (define-fun s17 () Bool (not s7))
+[GOOD] (define-fun s18 () Bool (and s16 s17))
+[GOOD] (define-fun s19 () Bool (ite s5 s7 s18))
+[GOOD] (define-fun s20 () Int (seq.len s12))
+[GOOD] (define-fun s21 () Bool (not s5))
+[GOOD] (define-fun s22 () Bool (and s17 s21))
+[GOOD] (define-fun s23 () Bool (and s10 s22))
+[GOOD] (define-fun s24 () Bool (> s4 s20))
+[GOOD] (define-fun s25 () Bool (=> s23 s24))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] listEq @(SBV [Float] -> SBV [Float] -> SBV Bool): length arg1 -> OK
+[MEASURE] Passed (terminating): listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)| :: [SFloat] -> [SFloat] -> SBool [Recursive]
+[GOOD] (define-fun-rec |listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)| ((l1_s0 (Seq (_ FloatingPoint  8 24))) (l1_s1 (Seq (_ FloatingPoint  8 24)))) Bool
+                                 (let ((l1_s3 0))
+                                 (let ((l1_s10 1))
+                                 (let ((l1_s2 (seq.len l1_s0)))
+                                 (let ((l1_s4 (= l1_s2 l1_s3)))
+                                 (let ((l1_s5 (seq.len l1_s1)))
+                                 (let ((l1_s6 (= l1_s3 l1_s5)))
+                                 (let ((l1_s7 (seq.nth l1_s0 l1_s3)))
+                                 (let ((l1_s8 (seq.nth l1_s1 l1_s3)))
+                                 (let ((l1_s9 (fp.eq l1_s7 l1_s8)))
+                                 (let ((l1_s11 (- l1_s2 l1_s10)))
+                                 (let ((l1_s12 (seq.extract l1_s0 l1_s10 l1_s11)))
+                                 (let ((l1_s13 (- l1_s5 l1_s10)))
+                                 (let ((l1_s14 (seq.extract l1_s1 l1_s10 l1_s13)))
+                                 (let ((l1_s15 (|listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)| l1_s12 l1_s14)))
+                                 (let ((l1_s16 (and l1_s9 l1_s15)))
+                                 (let ((l1_s17 (not l1_s6)))
+                                 (let ((l1_s18 (and l1_s16 l1_s17)))
+                                 (let ((l1_s19 (ite l1_s4 l1_s6 l1_s18)))
+                                 l1_s19)))))))))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq (_ FloatingPoint  8 24)) (seq.unit s0))
+[GOOD] (define-fun s2 () Bool (|listEq @(SBV [Float] -> SBV [Float] -> SBV Bool)| s1 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s2))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (_ NaN 8 24)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Falsifiable. Counter-example:
+  x = NaN :: Float
diff --git a/SBVTestSuite/GoldFiles/listFloat3.gold b/SBVTestSuite/GoldFiles/listFloat3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/listFloat3.gold
@@ -0,0 +1,33 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has lists, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq (_ FloatingPoint  8 24)) (seq.unit s0))
+[GOOD] (define-fun s2 () Bool (= s1 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s2))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/merge.gold b/SBVTestSuite/GoldFiles/merge.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/merge.gold
@@ -0,0 +1,156 @@
+== BEGIN: "Makefile" ================
+# Makefile for merge. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: merge_driver
+
+merge.o: merge.c merge.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+merge_driver.o: merge_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+merge_driver: merge.o merge_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f merge_driver
+== END: "Makefile" ==================
+== BEGIN: "merge.h" ================
+/* Header file for merge. Automatically generated by SBV. Do not edit! */
+
+#ifndef __merge__HEADER_INCLUDED__
+#define __merge__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void merge(const SWord8 *xs, SWord8 *ys);
+
+#endif /* __merge__HEADER_INCLUDED__ */
+== END: "merge.h" ==================
+== BEGIN: "merge_driver.c" ================
+/* Example driver program for merge. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "merge.h"
+
+int main(void)
+{
+  const SWord8 xs[5] = {
+      10,  6,  4, 82, 71
+  };
+
+  printf("Contents of input array xs:\n");
+  int xs_ctr;
+  for(xs_ctr = 0; xs_ctr < 5 ; ++xs_ctr)
+    printf("  xs[%1d] = %"PRIu8"\n", xs_ctr ,xs[xs_ctr]);
+
+  SWord8 ys[5];
+
+  merge(xs, ys);
+
+  printf("merge(xs, ys) ->\n");
+  int ys_ctr;
+  for(ys_ctr = 0; ys_ctr < 5 ; ++ys_ctr)
+    printf("  ys[%1d] = %"PRIu8"\n", ys_ctr ,ys[ys_ctr]);
+
+  return 0;
+}
+== END: "merge_driver.c" ==================
+== BEGIN: "merge.c" ================
+/* File: "merge.c". Automatically generated by SBV. Do not edit! */
+
+#include "merge.h"
+
+void merge(const SWord8 *xs, SWord8 *ys)
+{
+  const SWord8 s0 = xs[0];
+  const SWord8 s1 = xs[1];
+  const SWord8 s2 = xs[2];
+  const SWord8 s3 = xs[3];
+  const SWord8 s4 = xs[4];
+  const SBool  s5 = s0 < s1;
+  const SWord8 s6 = s5 ? s0 : s1;
+  const SBool  s7 = s3 < s4;
+  const SWord8 s8 = s7 ? s3 : s4;
+  const SBool  s9 = s2 < s8;
+  const SWord8 s10 = s9 ? s2 : s8;
+  const SBool  s11 = s6 < s10;
+  const SWord8 s12 = s11 ? s6 : s10;
+  const SWord8 s13 = s5 ? s1 : s0;
+  const SBool  s14 = s13 < s10;
+  const SWord8 s15 = s14 ? s13 : s10;
+  const SWord8 s16 = s7 ? s4 : s3;
+  const SBool  s17 = s2 < s16;
+  const SWord8 s18 = s17 ? s2 : s16;
+  const SWord8 s19 = s9 ? s8 : s18;
+  const SBool  s20 = s6 < s19;
+  const SWord8 s21 = s20 ? s6 : s19;
+  const SWord8 s22 = s11 ? s15 : s21;
+  const SBool  s23 = s13 < s19;
+  const SWord8 s24 = s23 ? s13 : s19;
+  const SWord8 s25 = s14 ? s10 : s24;
+  const SWord8 s26 = s17 ? s16 : s2;
+  const SWord8 s27 = s9 ? s16 : s26;
+  const SBool  s28 = s6 < s27;
+  const SWord8 s29 = s28 ? s6 : s27;
+  const SWord8 s30 = s20 ? s24 : s29;
+  const SWord8 s31 = s11 ? s25 : s30;
+  const SBool  s32 = s13 < s27;
+  const SWord8 s33 = s32 ? s13 : s27;
+  const SWord8 s34 = s23 ? s19 : s33;
+  const SWord8 s35 = s14 ? s19 : s34;
+  const SWord8 s36 = s28 ? s33 : s6;
+  const SWord8 s37 = s20 ? s34 : s36;
+  const SWord8 s38 = s11 ? s35 : s37;
+  const SWord8 s39 = s32 ? s27 : s13;
+  const SWord8 s40 = s23 ? s27 : s39;
+  const SWord8 s41 = s14 ? s27 : s40;
+  const SWord8 s42 = s28 ? s39 : s13;
+  const SWord8 s43 = s20 ? s40 : s42;
+  const SWord8 s44 = s11 ? s41 : s43;
+
+  ys[0] = s12;
+  ys[1] = s22;
+  ys[2] = s31;
+  ys[3] = s38;
+  ys[4] = s44;
+}
+== END: "merge.c" ==================
diff --git a/SBVTestSuite/GoldFiles/nested1.gold b/SBVTestSuite/GoldFiles/nested1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nested1.gold
@@ -0,0 +1,8 @@
+CAUGHT EXCEPTION
+
+Data.SBV: Mismatched contexts detected.
+***
+*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
+*** while another one is in execution, or use results from one such call in another.
+*** Please avoid such nested calls, all interactions should be from the same context.
+*** See https://github.com/LeventErkok/sbv/issues/71 for several examples.
diff --git a/SBVTestSuite/GoldFiles/nested2.gold b/SBVTestSuite/GoldFiles/nested2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nested2.gold
@@ -0,0 +1,8 @@
+CAUGHT EXCEPTION
+
+Data.SBV: Mismatched contexts detected.
+***
+*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
+*** while another one is in execution, or use results from one such call in another.
+*** Please avoid such nested calls, all interactions should be from the same context.
+*** See https://github.com/LeventErkok/sbv/issues/71 for several examples.
diff --git a/SBVTestSuite/GoldFiles/nested3.gold b/SBVTestSuite/GoldFiles/nested3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nested3.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+CAUGHT EXCEPTION
+
+Data.SBV: Mismatched contexts detected.
+***
+*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
+*** while another one is in execution, or use results from one such call in another.
+*** Please avoid such nested calls, all interactions should be from the same context.
+*** See https://github.com/LeventErkok/sbv/issues/71 for several examples.
diff --git a/SBVTestSuite/GoldFiles/nested4.gold b/SBVTestSuite/GoldFiles/nested4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nested4.gold
@@ -0,0 +1,8 @@
+CAUGHT EXCEPTION
+
+Data.SBV: Mismatched contexts detected.
+***
+*** This happens if you call a proof-function (prove/sat/runSMT/isSatisfiable) etc.
+*** while another one is in execution, or use results from one such call in another.
+*** Please avoid such nested calls, all interactions should be from the same context.
+*** See https://github.com/LeventErkok/sbv/issues/71 for several examples.
diff --git a/SBVTestSuite/GoldFiles/noOpt1.gold b/SBVTestSuite/GoldFiles/noOpt1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/noOpt1.gold
@@ -0,0 +1,27 @@
+** 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_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Solver   : Z3
+*** Exit code: ExitFailure (-15)
+
+
+
+*** Data.SBV: Unsupported call to optimize when no objectives are present.
+*** Use "sat" for plain satisfaction
diff --git a/SBVTestSuite/GoldFiles/noOpt2.gold b/SBVTestSuite/GoldFiles/noOpt2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/noOpt2.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 QF_BV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] ; --- optimization tracker variables ---
+[GOOD] (declare-fun s1 () (_ BitVec 8)) ; tracks mx
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Solver   : Z3
+*** Exit code: ExitFailure (-15)
+
+
+
+*** Data.SBV: Unsupported call sat/prove when optimization objectives are present.
+*** Use "optimize"/"optimizeWith" to calculate optimal satisfaction!
diff --git a/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold b/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nonlinear_cvc4.gold
@@ -0,0 +1,35 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt --model-witness-value
+[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 ALL) ; has algebraic reals, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Real (/ 2.0 1.0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Real)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Real (* s0 s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (witness ((BOUND_VARIABLE_840 Real)) (or (= BOUND_VARIABLE_840 (/ (- 2965827) 2097152)) (and (>= BOUND_VARIABLE_840 (/ (- 1482917) 1048576)) (>= (* (- 1.0) BOUND_VARIABLE_840) (/ 741455 524288)))))))
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Satisfiable. Model:
+  s0 = -1.414216518402099609375... :: Real
+DONE!
diff --git a/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold b/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nonlinear_cvc5.gold
@@ -0,0 +1,34 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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 HO_ALL) ; has algebraic reals, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Real (/ 2.0 1.0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Real)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Real (* s0 s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (_ real_algebraic_number <1*x^2 + (-2), (-3/2, -5/4)>)))
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
+
+FINAL:
+Satisfiable. Model:
+  s0 = ((-3) % 2, (-5) % 4) :: Real
+DONE!
diff --git a/SBVTestSuite/GoldFiles/nonlinear_z3.gold b/SBVTestSuite/GoldFiles/nonlinear_z3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/nonlinear_z3.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-logic ALL) ; has algebraic reals, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Real (/ 2.0 1.0))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Real)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Real (* s0 s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.decimal false)
+[SEND] (get-value (s0))
+[RECV] ((s0 (root-obj (+ (^ x 2) (- 2)) 1)))
+[GOOD] (set-option :pp.decimal true)
+[GOOD] (set-option :pp.decimal_precision 16)
+[SEND] (get-value (s0))
+[RECV] ((s0 (- 1.4142135623730950?)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+Satisfiable. Model:
+  s0 = root(1, x^2 = 2) = -1.414213562373095... :: Real
+DONE!
diff --git a/SBVTestSuite/GoldFiles/optBasics1.gold b/SBVTestSuite/GoldFiles/optBasics1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasics1.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x        = 1 :: Integer
+  y        = 1 :: Integer
+  x_plus_y = 2 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optBasics2.gold b/SBVTestSuite/GoldFiles/optBasics2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasics2.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x        = 2 :: Integer
+  y        = 2 :: Integer
+  x_plus_y = 4 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = 127 :: Int8
+  toMetricSpace(m) = 255 :: Word8
+  m                = 127 :: Int8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = -128 :: Int8
+  toMetricSpace(m) =    0 :: Word8
+  m                = -128 :: Int8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_max.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 255 :: Word8
+  m = 255 :: Word8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_unsigned_min.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 0 :: Word8
+  m = 0 :: Word8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = 32767 :: Int16
+  toMetricSpace(m) = 65535 :: Word16
+  m                = 32767 :: Int16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = -32768 :: Int16
+  toMetricSpace(m) =      0 :: Word16
+  m                = -32768 :: Int16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_max.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 65535 :: Word16
+  m = 65535 :: Word16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_unsigned_min.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 0 :: Word16
+  m = 0 :: Word16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = 2147483647 :: Int32
+  toMetricSpace(m) = 4294967295 :: Word32
+  m                = 2147483647 :: Int32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = -2147483648 :: Int32
+  toMetricSpace(m) =           0 :: Word32
+  m                = -2147483648 :: Int32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_max.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 4294967295 :: Word32
+  m = 4294967295 :: Word32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_unsigned_min.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 0 :: Word32
+  m = 0 :: Word32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                =  9223372036854775807 :: Int64
+  toMetricSpace(m) = 18446744073709551615 :: Word64
+  m                =  9223372036854775807 :: Int64
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x                = -9223372036854775808 :: Int64
+  toMetricSpace(m) =                    0 :: Word64
+  m                = -9223372036854775808 :: Int64
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_max.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_max.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 18446744073709551615 :: Word64
+  m = 18446744073709551615 :: Word64
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_min.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_unsigned_min.gold
@@ -0,0 +1,3 @@
+Optimal model:
+  x = 0 :: Word64
+  m = 0 :: Word64
diff --git a/SBVTestSuite/GoldFiles/optExtField1.gold b/SBVTestSuite/GoldFiles/optExtField1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optExtField1.gold
@@ -0,0 +1,2 @@
+Optimal in an extension field:
+  x_plus_y = oo :: Integer
diff --git a/SBVTestSuite/GoldFiles/optExtField2.gold b/SBVTestSuite/GoldFiles/optExtField2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optExtField2.gold
@@ -0,0 +1,2 @@
+Optimal in an extension field:
+  x_plus_y = -oo :: Integer
diff --git a/SBVTestSuite/GoldFiles/optExtField3.gold b/SBVTestSuite/GoldFiles/optExtField3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optExtField3.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  x        = 4.0 :: Real
+  y        = 5.0 :: Real
+  x_plus_y = 9.0 :: Real
diff --git a/SBVTestSuite/GoldFiles/optFloat1a.gold b/SBVTestSuite/GoldFiles/optFloat1a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat1a.gold
@@ -0,0 +1,39 @@
+Optimal model:
+  x                    = -3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 1 11111110 11111111111111111111111
+      Hex layout: FF7F FFFF
+       Precision: Single
+            Sign: Negative
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: -0b1.11111111111111111111111p+127
+           Octal: -0o3.77777774p+126
+         Decimal: -3.4028235e38
+             Hex: -0xf.fffffp+124
+  toMetricSpace(min-x) =       8388608 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 0000 0000 1000 0000 0000 0000 0000 0000
+      Hex layout: 0080 0000
+            Type: Unsigned 32-bit word
+          Binary: 0b100000000000000000000000
+           Octal: 0o40000000
+         Decimal: 8388608
+             Hex: 0x800000
+  min-x                = -3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 1 11111110 11111111111111111111111
+      Hex layout: FF7F FFFF
+       Precision: Single
+            Sign: Negative
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: -0b1.11111111111111111111111p+127
+           Octal: -0o3.77777774p+126
+         Decimal: -3.4028235e38
+             Hex: -0xf.fffffp+124
diff --git a/SBVTestSuite/GoldFiles/optFloat1b.gold b/SBVTestSuite/GoldFiles/optFloat1b.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat1b.gold
@@ -0,0 +1,33 @@
+Optimal model:
+  x                    = -Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 1 11111111 00000000000000000000000
+      Hex layout: FF80 0000
+       Precision: Single
+            Sign: Negative
+        Exponent: 128 (Stored: 255, Bias: 127)
+  Classification: FP_INFINITE
+           Value: -Infinity
+  toMetricSpace(min-x) =   8388607 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 0000 0000 0111 1111 1111 1111 1111 1111
+      Hex layout: 007F FFFF
+            Type: Unsigned 32-bit word
+          Binary: 0b11111111111111111111111
+           Octal: 0o37777777
+         Decimal: 8388607
+             Hex: 0x7fffff
+  min-x                = -Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 1 11111111 00000000000000000000000
+      Hex layout: FF80 0000
+       Precision: Single
+            Sign: Negative
+        Exponent: 128 (Stored: 255, Bias: 127)
+  Classification: FP_INFINITE
+           Value: -Infinity
diff --git a/SBVTestSuite/GoldFiles/optFloat1c.gold b/SBVTestSuite/GoldFiles/optFloat1c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat1c.gold
@@ -0,0 +1,39 @@
+Optimal model:
+  x                    = 3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111110 11111111111111111111111
+      Hex layout: 7F7F FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+127
+           Octal: 0o3.77777774p+126
+         Decimal: 3.4028235e38
+             Hex: 0xf.fffffp+124
+  toMetricSpace(max-x) =   4286578687 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1111 1111 0111 1111 1111 1111 1111 1111
+      Hex layout: FF7F FFFF
+            Type: Unsigned 32-bit word
+          Binary: 0b11111111011111111111111111111111
+           Octal: 0o37737777777
+         Decimal: 4286578687
+             Hex: 0xff7fffff
+  max-x                = 3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111110 11111111111111111111111
+      Hex layout: 7F7F FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+127
+           Octal: 0o3.77777774p+126
+         Decimal: 3.4028235e38
+             Hex: 0xf.fffffp+124
diff --git a/SBVTestSuite/GoldFiles/optFloat1d.gold b/SBVTestSuite/GoldFiles/optFloat1d.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat1d.gold
@@ -0,0 +1,33 @@
+Optimal model:
+  x                    =   Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111111 00000000000000000000000
+      Hex layout: 7F80 0000
+       Precision: Single
+            Sign: Positive
+        Exponent: 128 (Stored: 255, Bias: 127)
+  Classification: FP_INFINITE
+           Value: Infinity
+  toMetricSpace(max-y) = 4286578688 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1111 1111 1000 0000 0000 0000 0000 0000
+      Hex layout: FF80 0000
+            Type: Unsigned 32-bit word
+          Binary: 0b11111111100000000000000000000000
+           Octal: 0o37740000000
+         Decimal: 4286578688
+             Hex: 0xff800000
+  max-y                =   Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111111 00000000000000000000000
+      Hex layout: 7F80 0000
+       Precision: Single
+            Sign: Positive
+        Exponent: 128 (Stored: 255, Bias: 127)
+  Classification: FP_INFINITE
+           Value: Infinity
diff --git a/SBVTestSuite/GoldFiles/optFloat2a.gold b/SBVTestSuite/GoldFiles/optFloat2a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat2a.gold
@@ -0,0 +1,39 @@
+Optimal model:
+  x                    = -1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 1 11111111110 1111111111111111111111111111111111111111111111111111
+      Hex layout: FFEF FFFF FFFF FFFF
+       Precision: Double
+            Sign: Negative
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+  Classification: FP_NORMAL
+          Binary: -0b1.1111111111111111111111111111111111111111111111111111p+1023
+           Octal: -0o1.777777777777777774p+1023
+         Decimal: -1.7976931348623157e308
+             Hex: -0xf.ffffffffffff8p+1020
+  toMetricSpace(min-x) =        4503599627370496 :: Word64
+                  6    5           4            3           2            1           0
+                  3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 0000 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+      Hex layout: 0010 0000 0000 0000
+            Type: Unsigned 64-bit word
+          Binary: 0b10000000000000000000000000000000000000000000000000000
+           Octal: 0o200000000000000000
+         Decimal: 4503599627370496
+             Hex: 0x10000000000000
+  min-x                = -1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 1 11111111110 1111111111111111111111111111111111111111111111111111
+      Hex layout: FFEF FFFF FFFF FFFF
+       Precision: Double
+            Sign: Negative
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+  Classification: FP_NORMAL
+          Binary: -0b1.1111111111111111111111111111111111111111111111111111p+1023
+           Octal: -0o1.777777777777777774p+1023
+         Decimal: -1.7976931348623157e308
+             Hex: -0xf.ffffffffffff8p+1020
diff --git a/SBVTestSuite/GoldFiles/optFloat2b.gold b/SBVTestSuite/GoldFiles/optFloat2b.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat2b.gold
@@ -0,0 +1,33 @@
+Optimal model:
+  x                    =        -Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 1 11111111111 0000000000000000000000000000000000000000000000000000
+      Hex layout: FFF0 0000 0000 0000
+       Precision: Double
+            Sign: Negative
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+  Classification: FP_INFINITE
+           Value: -Infinity
+  toMetricSpace(min-x) = 4503599627370495 :: Word64
+                  6    5           4            3           2            1           0
+                  3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 0000 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
+      Hex layout: 000F FFFF FFFF FFFF
+            Type: Unsigned 64-bit word
+          Binary: 0b1111111111111111111111111111111111111111111111111111
+           Octal: 0o177777777777777777
+         Decimal: 4503599627370495
+             Hex: 0xfffffffffffff
+  min-x                =        -Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 1 11111111111 0000000000000000000000000000000000000000000000000000
+      Hex layout: FFF0 0000 0000 0000
+       Precision: Double
+            Sign: Negative
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+  Classification: FP_INFINITE
+           Value: -Infinity
diff --git a/SBVTestSuite/GoldFiles/optFloat2c.gold b/SBVTestSuite/GoldFiles/optFloat2c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat2c.gold
@@ -0,0 +1,39 @@
+Optimal model:
+  x                    = 1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 0 11111111110 1111111111111111111111111111111111111111111111111111
+      Hex layout: 7FEF FFFF FFFF FFFF
+       Precision: Double
+            Sign: Positive
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+  Classification: FP_NORMAL
+          Binary: 0b1.1111111111111111111111111111111111111111111111111111p+1023
+           Octal: 0o1.777777777777777774p+1023
+         Decimal: 1.7976931348623157e308
+             Hex: 0xf.ffffffffffff8p+1020
+  toMetricSpace(max-x) =   18442240474082181119 :: Word64
+                  6    5           4            3           2            1           0
+                  3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1111 1111 1110 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
+      Hex layout: FFEF FFFF FFFF FFFF
+            Type: Unsigned 64-bit word
+          Binary: 0b1111111111101111111111111111111111111111111111111111111111111111
+           Octal: 0o1777577777777777777777
+         Decimal: 18442240474082181119
+             Hex: 0xffefffffffffffff
+  max-x                = 1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 0 11111111110 1111111111111111111111111111111111111111111111111111
+      Hex layout: 7FEF FFFF FFFF FFFF
+       Precision: Double
+            Sign: Positive
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+  Classification: FP_NORMAL
+          Binary: 0b1.1111111111111111111111111111111111111111111111111111p+1023
+           Octal: 0o1.777777777777777774p+1023
+         Decimal: 1.7976931348623157e308
+             Hex: 0xf.ffffffffffff8p+1020
diff --git a/SBVTestSuite/GoldFiles/optFloat2d.gold b/SBVTestSuite/GoldFiles/optFloat2d.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat2d.gold
@@ -0,0 +1,33 @@
+Optimal model:
+  x                    =             Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 0 11111111111 0000000000000000000000000000000000000000000000000000
+      Hex layout: 7FF0 0000 0000 0000
+       Precision: Double
+            Sign: Positive
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+  Classification: FP_INFINITE
+           Value: Infinity
+  toMetricSpace(max-y) = 18442240474082181120 :: Word64
+                  6    5           4            3           2            1           0
+                  3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+      Hex layout: FFF0 0000 0000 0000
+            Type: Unsigned 64-bit word
+          Binary: 0b1111111111110000000000000000000000000000000000000000000000000000
+           Octal: 0o1777600000000000000000
+         Decimal: 18442240474082181120
+             Hex: 0xfff0000000000000
+  max-y                =             Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------S52-------------------------
+   Binary layout: 0 11111111111 0000000000000000000000000000000000000000000000000000
+      Hex layout: 7FF0 0000 0000 0000
+       Precision: Double
+            Sign: Positive
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+  Classification: FP_INFINITE
+           Value: Infinity
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,67 @@
+Optimal model:
+  x                             = 1.7014117e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111101 11111111111111111111111
+      Hex layout: 7EFF FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 126 (Stored: 253, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+126
+           Octal: 0o1.77777776p+126
+         Decimal: 1.7014117e38
+             Hex: 0x7.fffff8p+124
+  y                             = 1.7014117e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111101 11111111111111111111111
+      Hex layout: 7EFF FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 126 (Stored: 253, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+126
+           Octal: 0o1.77777776p+126
+         Decimal: 1.7014117e38
+             Hex: 0x7.fffff8p+124
+  toMetricSpace(metric-max-x+y) =   4286578687 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1111 1111 0111 1111 1111 1111 1111 1111
+      Hex layout: FF7F FFFF
+            Type: Unsigned 32-bit word
+          Binary: 0b11111111011111111111111111111111
+           Octal: 0o37737777777
+         Decimal: 4286578687
+             Hex: 0xff7fffff
+  max-x+y                       = 3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111110 11111111111111111111111
+      Hex layout: 7F7F FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+127
+           Octal: 0o3.77777774p+126
+         Decimal: 3.4028235e38
+             Hex: 0xf.fffffp+124
+  metric-max-x+y                = 3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 11111110 11111111111111111111111
+      Hex layout: 7F7F FFFF
+       Precision: Single
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+  Classification: FP_NORMAL
+          Binary: 0b1.11111111111111111111111p+127
+           Octal: 0o3.77777774p+126
+         Decimal: 3.4028235e38
+             Hex: 0xf.fffffp+124
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,67 @@
+Optimal model:
+  x                             =    1.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 00000000 00000000000000000000001
+      Hex layout: 0000 0001
+       Precision: Single
+            Sign: Positive
+        Exponent: -126 (Subnormal, with fixed exponent value. Stored: 0, Bias: 127)
+  Classification: FP_SUBNORMAL
+          Binary: 0b1p-149
+           Octal: 0o2p-150
+         Decimal: 1.0e-45
+             Hex: 0x8p-152
+  y                             =    1.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 00000000 00000000000000000000001
+      Hex layout: 0000 0001
+       Precision: Single
+            Sign: Positive
+        Exponent: -126 (Subnormal, with fixed exponent value. Stored: 0, Bias: 127)
+  Classification: FP_SUBNORMAL
+          Binary: 0b1p-149
+           Octal: 0o2p-150
+         Decimal: 1.0e-45
+             Hex: 0x8p-152
+  toMetricSpace(metric-min-x+y) = 2147483650 :: Word32
+                  3 2            1           0
+                  1098 7654 3210 9876 5432 1098 7654 3210
+   Binary layout: 1000 0000 0000 0000 0000 0000 0000 0010
+      Hex layout: 8000 0002
+            Type: Unsigned 32-bit word
+          Binary: 0b10000000000000000000000000000010
+           Octal: 0o20000000002
+         Decimal: 2147483650
+             Hex: 0x80000002
+  metric-min-x+y                =    3.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 00000000 00000000000000000000010
+      Hex layout: 0000 0002
+       Precision: Single
+            Sign: Positive
+        Exponent: -126 (Subnormal, with fixed exponent value. Stored: 0, Bias: 127)
+  Classification: FP_SUBNORMAL
+          Binary: 0b1p-148
+           Octal: 0o4p-150
+         Decimal: 3.0e-45
+             Hex: 0x1p-148
+  min-x+y                       =    3.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------S23----------
+   Binary layout: 0 00000000 00000000000000000000010
+      Hex layout: 0000 0002
+       Precision: Single
+            Sign: Positive
+        Exponent: -126 (Subnormal, with fixed exponent value. Stored: 0, Bias: 127)
+  Classification: FP_SUBNORMAL
+          Binary: 0b1p-148
+           Octal: 0o4p-150
+         Decimal: 3.0e-45
+             Hex: 0x1p-148
diff --git a/SBVTestSuite/GoldFiles/optQuant1.gold b/SBVTestSuite/GoldFiles/optQuant1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optQuant1.gold
@@ -0,0 +1,5 @@
+Optimal model:
+  a    = 0 :: Integer
+  b1   = 1 :: Integer
+  b2   = 1 :: Integer
+  goal = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optQuant2.gold b/SBVTestSuite/GoldFiles/optQuant2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optQuant2.gold
@@ -0,0 +1,5 @@
+Optimal model:
+  a    = 0 :: Integer
+  b1   = 1 :: Integer
+  b2   = 1 :: Integer
+  goal = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optQuant3.gold b/SBVTestSuite/GoldFiles/optQuant3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optQuant3.gold
@@ -0,0 +1,5 @@
+Optimal model:
+  a    = 0 :: Integer
+  b1   = 1 :: Integer
+  b2   = 1 :: Integer
+  goal = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optQuant4.gold b/SBVTestSuite/GoldFiles/optQuant4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optQuant4.gold
@@ -0,0 +1,5 @@
+Optimal model:
+  a    = 0 :: Integer
+  b1   = 1 :: Integer
+  b2   = 1 :: Integer
+  goal = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optQuant5.gold b/SBVTestSuite/GoldFiles/optQuant5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optQuant5.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  a    = 0 :: Integer
+  b    = 0 :: Integer
+  goal = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/optReal1.gold b/SBVTestSuite/GoldFiles/optReal1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optReal1.gold
@@ -0,0 +1,6 @@
+Optimal model:
+  x =  10.0 :: Real
+  y =  10.0 :: Real
+  z =   0.0 :: Real
+  w =  20.0 :: Real
+  p = 115.0 :: Real
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/pareto1.gold b/SBVTestSuite/GoldFiles/pareto1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pareto1.gold
@@ -0,0 +1,180 @@
+Pareto front #1: Optimal model:
+  x            = 1 :: Integer
+  y            = 1 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_y = 2 :: Integer
+  min_y        = 1 :: Integer
+Pareto front #2: Optimal model:
+  x            = 2 :: Integer
+  y            = 2 :: Integer
+  min_x        = 2 :: Integer
+  max_x_plus_y = 4 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #3: Optimal model:
+  x            = 3 :: Integer
+  y            = 3 :: Integer
+  min_x        = 3 :: Integer
+  max_x_plus_y = 6 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #4: Optimal model:
+  x            = 4 :: Integer
+  y            = 1 :: Integer
+  min_x        = 4 :: Integer
+  max_x_plus_y = 5 :: Integer
+  min_y        = 1 :: Integer
+Pareto front #5: Optimal model:
+  x            = 3 :: Integer
+  y            = 2 :: Integer
+  min_x        = 3 :: Integer
+  max_x_plus_y = 5 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #6: Optimal model:
+  x            = 5 :: Integer
+  y            = 1 :: Integer
+  min_x        = 5 :: Integer
+  max_x_plus_y = 6 :: Integer
+  min_y        = 1 :: Integer
+Pareto front #7: Optimal model:
+  x            = 5 :: Integer
+  y            = 0 :: Integer
+  min_x        = 5 :: Integer
+  max_x_plus_y = 5 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #8: Optimal model:
+  x            = 2 :: Integer
+  y            = 4 :: Integer
+  min_x        = 2 :: Integer
+  max_x_plus_y = 6 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #9: Optimal model:
+  x            = 4 :: Integer
+  y            = 3 :: Integer
+  min_x        = 4 :: Integer
+  max_x_plus_y = 7 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #10: Optimal model:
+  x            = 5 :: Integer
+  y            = 2 :: Integer
+  min_x        = 5 :: Integer
+  max_x_plus_y = 7 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #11: Optimal model:
+  x            = 5 :: Integer
+  y            = 3 :: Integer
+  min_x        = 5 :: Integer
+  max_x_plus_y = 8 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #12: Optimal model:
+  x            = 3 :: Integer
+  y            = 4 :: Integer
+  min_x        = 3 :: Integer
+  max_x_plus_y = 7 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #13: Optimal model:
+  x            = 4 :: Integer
+  y            = 2 :: Integer
+  min_x        = 4 :: Integer
+  max_x_plus_y = 6 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #14: Optimal model:
+  x            = 4 :: Integer
+  y            = 4 :: Integer
+  min_x        = 4 :: Integer
+  max_x_plus_y = 8 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #15: Optimal model:
+  x            = 5 :: Integer
+  y            = 4 :: Integer
+  min_x        = 5 :: Integer
+  max_x_plus_y = 9 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #16: Optimal model:
+  x            = 1 :: Integer
+  y            = 0 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_y = 1 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #17: Optimal model:
+  x            = 0 :: Integer
+  y            = 0 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_y = 0 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #18: Optimal model:
+  x            = 2 :: Integer
+  y            = 0 :: Integer
+  min_x        = 2 :: Integer
+  max_x_plus_y = 2 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #19: Optimal model:
+  x            = 0 :: Integer
+  y            = 1 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_y = 1 :: Integer
+  min_y        = 1 :: Integer
+Pareto front #20: Optimal model:
+  x            = 2 :: Integer
+  y            = 1 :: Integer
+  min_x        = 2 :: Integer
+  max_x_plus_y = 3 :: Integer
+  min_y        = 1 :: Integer
+Pareto front #21: Optimal model:
+  x            = 1 :: Integer
+  y            = 2 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_y = 3 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #22: Optimal model:
+  x            = 0 :: Integer
+  y            = 2 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_y = 2 :: Integer
+  min_y        = 2 :: Integer
+Pareto front #23: Optimal model:
+  x            = 0 :: Integer
+  y            = 3 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_y = 3 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #24: Optimal model:
+  x            = 1 :: Integer
+  y            = 3 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_y = 4 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #25: Optimal model:
+  x            = 0 :: Integer
+  y            = 4 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_y = 4 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #26: Optimal model:
+  x            = 1 :: Integer
+  y            = 4 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_y = 5 :: Integer
+  min_y        = 4 :: Integer
+Pareto front #27: Optimal model:
+  x            = 2 :: Integer
+  y            = 3 :: Integer
+  min_x        = 2 :: Integer
+  max_x_plus_y = 5 :: Integer
+  min_y        = 3 :: Integer
+Pareto front #28: Optimal model:
+  x            = 3 :: Integer
+  y            = 0 :: Integer
+  min_x        = 3 :: Integer
+  max_x_plus_y = 3 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #29: Optimal model:
+  x            = 4 :: Integer
+  y            = 0 :: Integer
+  min_x        = 4 :: Integer
+  max_x_plus_y = 4 :: Integer
+  min_y        = 0 :: Integer
+Pareto front #30: Optimal model:
+  x            = 3 :: Integer
+  y            = 1 :: Integer
+  min_x        = 3 :: Integer
+  max_x_plus_y = 4 :: Integer
+  min_y        = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/pareto2.gold b/SBVTestSuite/GoldFiles/pareto2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pareto2.gold
@@ -0,0 +1,182 @@
+Pareto front #1: Optimal model:
+  x            = 0 :: Integer
+  y            = 1 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 1 :: Integer
+  max_x_plus_y = 1 :: Integer
+Pareto front #2: Optimal model:
+  x            = 0 :: Integer
+  y            = 2 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 2 :: Integer
+  max_x_plus_y = 2 :: Integer
+Pareto front #3: Optimal model:
+  x            = 0 :: Integer
+  y            = 3 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 3 :: Integer
+  max_x_plus_y = 3 :: Integer
+Pareto front #4: Optimal model:
+  x            = 0 :: Integer
+  y            = 5 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 5 :: Integer
+  max_x_plus_y = 5 :: Integer
+Pareto front #5: Optimal model:
+  x            = 0 :: Integer
+  y            = 6 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 6 :: Integer
+  max_x_plus_y = 6 :: Integer
+Pareto front #6: Optimal model:
+  x            = 0 :: Integer
+  y            = 7 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 7 :: Integer
+  max_x_plus_y = 7 :: Integer
+Pareto front #7: Optimal model:
+  x            = 0 :: Integer
+  y            = 9 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 9 :: Integer
+  max_x_plus_y = 9 :: Integer
+Pareto front #8: Optimal model:
+  x            = 0 :: Integer
+  y            = 8 :: Integer
+  min_x        = 0 :: Integer
+  max_y        = 8 :: Integer
+  max_x_plus_y = 8 :: Integer
+Pareto front #9: Optimal model:
+  x            =  0 :: Integer
+  y            = 11 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 11 :: Integer
+  max_x_plus_y = 11 :: Integer
+Pareto front #10: Optimal model:
+  x            =  0 :: Integer
+  y            = 13 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 13 :: Integer
+  max_x_plus_y = 13 :: Integer
+Pareto front #11: Optimal model:
+  x            =  0 :: Integer
+  y            = 14 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 14 :: Integer
+  max_x_plus_y = 14 :: Integer
+Pareto front #12: Optimal model:
+  x            =  0 :: Integer
+  y            = 15 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 15 :: Integer
+  max_x_plus_y = 15 :: Integer
+Pareto front #13: Optimal model:
+  x            =  0 :: Integer
+  y            = 17 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 17 :: Integer
+  max_x_plus_y = 17 :: Integer
+Pareto front #14: Optimal model:
+  x            =  0 :: Integer
+  y            = 19 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 19 :: Integer
+  max_x_plus_y = 19 :: Integer
+Pareto front #15: Optimal model:
+  x            =  0 :: Integer
+  y            = 21 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 21 :: Integer
+  max_x_plus_y = 21 :: Integer
+Pareto front #16: Optimal model:
+  x            =  0 :: Integer
+  y            = 22 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 22 :: Integer
+  max_x_plus_y = 22 :: Integer
+Pareto front #17: Optimal model:
+  x            =  0 :: Integer
+  y            = 23 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 23 :: Integer
+  max_x_plus_y = 23 :: Integer
+Pareto front #18: Optimal model:
+  x            =  0 :: Integer
+  y            = 25 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 25 :: Integer
+  max_x_plus_y = 25 :: Integer
+Pareto front #19: Optimal model:
+  x            =  0 :: Integer
+  y            = 26 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 26 :: Integer
+  max_x_plus_y = 26 :: Integer
+Pareto front #20: Optimal model:
+  x            =  0 :: Integer
+  y            = 28 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 28 :: Integer
+  max_x_plus_y = 28 :: Integer
+Pareto front #21: Optimal model:
+  x            =  0 :: Integer
+  y            = 30 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 30 :: Integer
+  max_x_plus_y = 30 :: Integer
+Pareto front #22: Optimal model:
+  x            =  0 :: Integer
+  y            = 32 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 32 :: Integer
+  max_x_plus_y = 32 :: Integer
+Pareto front #23: Optimal model:
+  x            =  0 :: Integer
+  y            = 34 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 34 :: Integer
+  max_x_plus_y = 34 :: Integer
+Pareto front #24: Optimal model:
+  x            =  0 :: Integer
+  y            = 36 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 36 :: Integer
+  max_x_plus_y = 36 :: Integer
+Pareto front #25: Optimal model:
+  x            =  0 :: Integer
+  y            = 37 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 37 :: Integer
+  max_x_plus_y = 37 :: Integer
+Pareto front #26: Optimal model:
+  x            =  0 :: Integer
+  y            = 39 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 39 :: Integer
+  max_x_plus_y = 39 :: Integer
+Pareto front #27: Optimal model:
+  x            =  0 :: Integer
+  y            = 40 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 40 :: Integer
+  max_x_plus_y = 40 :: Integer
+Pareto front #28: Optimal model:
+  x            =  0 :: Integer
+  y            = 41 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 41 :: Integer
+  max_x_plus_y = 41 :: Integer
+Pareto front #29: Optimal model:
+  x            =  0 :: Integer
+  y            = 43 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 43 :: Integer
+  max_x_plus_y = 43 :: Integer
+Pareto front #30: Optimal model:
+  x            =  0 :: Integer
+  y            = 44 :: Integer
+  min_x        =  0 :: Integer
+  max_y        = 44 :: Integer
+  max_x_plus_y = 44 :: Integer
+*** Note: Pareto-front extraction was terminated as requested by the user.
+***       There might be many other results!
diff --git a/SBVTestSuite/GoldFiles/pareto3.gold b/SBVTestSuite/GoldFiles/pareto3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pareto3.gold
@@ -0,0 +1,8 @@
+Pareto front #1: Optimal model:
+  x            = 1 :: Integer
+  min_x        = 1 :: Integer
+  max_x_plus_x = 2 :: Integer
+Pareto front #2: Optimal model:
+  x            = 0 :: Integer
+  min_x        = 0 :: Integer
+  max_x_plus_x = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/pbAtLeast.gold b/SBVTestSuite/GoldFiles/pbAtLeast.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbAtLeast.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
+[GOOD] (define-fun s32 () (_ BitVec 32) #x00000005)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ at-least 5) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () (_ BitVec 32) (ite s0 s11 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (ite s1 s11 s12))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvadd s13 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s2 s11 s12))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvadd s15 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s3 s11 s12))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvadd s17 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s4 s11 s12))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvadd s19 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s5 s11 s12))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvadd s21 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s11 s12))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvadd s23 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (ite s7 s11 s12))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvadd s25 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (ite s8 s11 s12))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvadd s27 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (ite s9 s11 s12))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvadd s29 s30))
+[GOOD] (define-fun s33 () Bool (bvuge s31 s32))
+[GOOD] (define-fun s34 () Bool (= s10 s33))
+[GOOD] (define-fun s35 () Bool (not s34))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s35)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbAtMost.gold b/SBVTestSuite/GoldFiles/pbAtMost.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbAtMost.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
+[GOOD] (define-fun s32 () (_ BitVec 32) #x00000008)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ at-most 8) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () (_ BitVec 32) (ite s0 s11 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (ite s1 s11 s12))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvadd s13 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s2 s11 s12))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvadd s15 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s3 s11 s12))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvadd s17 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s4 s11 s12))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvadd s19 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s5 s11 s12))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvadd s21 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s11 s12))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvadd s23 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (ite s7 s11 s12))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvadd s25 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (ite s8 s11 s12))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvadd s27 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (ite s9 s11 s12))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvadd s29 s30))
+[GOOD] (define-fun s33 () Bool (bvule s31 s32))
+[GOOD] (define-fun s34 () Bool (= s10 s33))
+[GOOD] (define-fun s35 () Bool (not s34))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s35)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbEq.gold b/SBVTestSuite/GoldFiles/pbEq.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbEq.gold
@@ -0,0 +1,68 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () Int 1)
+[GOOD] (define-fun s12 () Int 0)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 3)
+[GOOD] (define-fun s20 () Int 4)
+[GOOD] (define-fun s23 () Int 5)
+[GOOD] (define-fun s26 () Int 6)
+[GOOD] (define-fun s29 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s35 () Int 9)
+[GOOD] (define-fun s38 () Int 10)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pbeq 7 1 2 3 4 5 6 7 8 9 10) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () Int (ite s0 s11 s12))
+[GOOD] (define-fun s15 () Int (ite s1 s14 s12))
+[GOOD] (define-fun s16 () Int (+ s13 s15))
+[GOOD] (define-fun s18 () Int (ite s2 s17 s12))
+[GOOD] (define-fun s19 () Int (+ s16 s18))
+[GOOD] (define-fun s21 () Int (ite s3 s20 s12))
+[GOOD] (define-fun s22 () Int (+ s19 s21))
+[GOOD] (define-fun s24 () Int (ite s4 s23 s12))
+[GOOD] (define-fun s25 () Int (+ s22 s24))
+[GOOD] (define-fun s27 () Int (ite s5 s26 s12))
+[GOOD] (define-fun s28 () Int (+ s25 s27))
+[GOOD] (define-fun s30 () Int (ite s6 s29 s12))
+[GOOD] (define-fun s31 () Int (+ s28 s30))
+[GOOD] (define-fun s33 () Int (ite s7 s32 s12))
+[GOOD] (define-fun s34 () Int (+ s31 s33))
+[GOOD] (define-fun s36 () Int (ite s8 s35 s12))
+[GOOD] (define-fun s37 () Int (+ s34 s36))
+[GOOD] (define-fun s39 () Int (ite s9 s38 s12))
+[GOOD] (define-fun s40 () Int (+ s37 s39))
+[GOOD] (define-fun s41 () Bool (= s29 s40))
+[GOOD] (define-fun s42 () Bool (= s10 s41))
+[GOOD] (define-fun s43 () Bool (not s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbEq2.gold b/SBVTestSuite/GoldFiles/pbEq2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbEq2.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pbeq 3 1 1) s1 s2))
+[GOOD] (define-fun s11 () Bool ((_ pbeq 1 1 1) s1 s2))
+[GOOD] (define-fun s12 () Bool (ite s0 s10 s11))
+[GOOD] (define-fun s13 () Bool ((_ pbeq 3 1 1 1) s0 s3 s4))
+[GOOD] (define-fun s14 () Bool ((_ pbeq 1 1 1 1) s0 s3 s4))
+[GOOD] (define-fun s15 () Bool (ite s2 s13 s14))
+[GOOD] (define-fun s16 () Bool (and s12 s15))
+[GOOD] (define-fun s17 () Bool (not s0))
+[GOOD] (define-fun s18 () Bool (not s2))
+[GOOD] (define-fun s19 () Bool (not s4))
+[GOOD] (define-fun s20 () Bool (and s3 s19))
+[GOOD] (define-fun s21 () Bool (and s18 s20))
+[GOOD] (define-fun s22 () Bool (and s1 s21))
+[GOOD] (define-fun s23 () Bool (and s17 s22))
+[GOOD] (define-fun s24 () Bool (not s3))
+[GOOD] (define-fun s25 () Bool (and s4 s24))
+[GOOD] (define-fun s26 () Bool (and s18 s25))
+[GOOD] (define-fun s27 () Bool (and s1 s26))
+[GOOD] (define-fun s28 () Bool (and s17 s27))
+[GOOD] (define-fun s29 () Bool (or s23 s28))
+[GOOD] (define-fun s30 () Bool (=> s16 s29))
+[GOOD] (define-fun s31 () Bool (not s30))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s31)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbExactly.gold b/SBVTestSuite/GoldFiles/pbExactly.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbExactly.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
+[GOOD] (define-fun s32 () (_ BitVec 32) #x00000005)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pbeq 5 1 1 1 1 1 1 1 1 1 1) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () (_ BitVec 32) (ite s0 s11 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (ite s1 s11 s12))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvadd s13 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s2 s11 s12))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvadd s15 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s3 s11 s12))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvadd s17 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s4 s11 s12))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvadd s19 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s5 s11 s12))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvadd s21 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s11 s12))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvadd s23 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (ite s7 s11 s12))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvadd s25 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (ite s8 s11 s12))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvadd s27 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (ite s9 s11 s12))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvadd s29 s30))
+[GOOD] (define-fun s33 () Bool (= s31 s32))
+[GOOD] (define-fun s34 () Bool (= s10 s33))
+[GOOD] (define-fun s35 () Bool (not s34))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s35)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbGe.gold b/SBVTestSuite/GoldFiles/pbGe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbGe.gold
@@ -0,0 +1,68 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () Int 1)
+[GOOD] (define-fun s12 () Int 0)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 3)
+[GOOD] (define-fun s20 () Int 4)
+[GOOD] (define-fun s23 () Int 5)
+[GOOD] (define-fun s26 () Int 6)
+[GOOD] (define-fun s29 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s35 () Int 9)
+[GOOD] (define-fun s38 () Int 10)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pbge 7 1 2 3 4 5 6 7 8 9 10) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () Int (ite s0 s11 s12))
+[GOOD] (define-fun s15 () Int (ite s1 s14 s12))
+[GOOD] (define-fun s16 () Int (+ s13 s15))
+[GOOD] (define-fun s18 () Int (ite s2 s17 s12))
+[GOOD] (define-fun s19 () Int (+ s16 s18))
+[GOOD] (define-fun s21 () Int (ite s3 s20 s12))
+[GOOD] (define-fun s22 () Int (+ s19 s21))
+[GOOD] (define-fun s24 () Int (ite s4 s23 s12))
+[GOOD] (define-fun s25 () Int (+ s22 s24))
+[GOOD] (define-fun s27 () Int (ite s5 s26 s12))
+[GOOD] (define-fun s28 () Int (+ s25 s27))
+[GOOD] (define-fun s30 () Int (ite s6 s29 s12))
+[GOOD] (define-fun s31 () Int (+ s28 s30))
+[GOOD] (define-fun s33 () Int (ite s7 s32 s12))
+[GOOD] (define-fun s34 () Int (+ s31 s33))
+[GOOD] (define-fun s36 () Int (ite s8 s35 s12))
+[GOOD] (define-fun s37 () Int (+ s34 s36))
+[GOOD] (define-fun s39 () Int (ite s9 s38 s12))
+[GOOD] (define-fun s40 () Int (+ s37 s39))
+[GOOD] (define-fun s41 () Bool (>= s40 s29))
+[GOOD] (define-fun s42 () Bool (= s10 s41))
+[GOOD] (define-fun s43 () Bool (not s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbLe.gold b/SBVTestSuite/GoldFiles/pbLe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbLe.gold
@@ -0,0 +1,68 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () Int 1)
+[GOOD] (define-fun s12 () Int 0)
+[GOOD] (define-fun s14 () Int 2)
+[GOOD] (define-fun s17 () Int 3)
+[GOOD] (define-fun s20 () Int 4)
+[GOOD] (define-fun s23 () Int 5)
+[GOOD] (define-fun s26 () Int 6)
+[GOOD] (define-fun s29 () Int 7)
+[GOOD] (define-fun s32 () Int 8)
+[GOOD] (define-fun s35 () Int 9)
+[GOOD] (define-fun s38 () Int 10)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pble 7 1 2 3 4 5 6 7 8 9 10) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () Int (ite s0 s11 s12))
+[GOOD] (define-fun s15 () Int (ite s1 s14 s12))
+[GOOD] (define-fun s16 () Int (+ s13 s15))
+[GOOD] (define-fun s18 () Int (ite s2 s17 s12))
+[GOOD] (define-fun s19 () Int (+ s16 s18))
+[GOOD] (define-fun s21 () Int (ite s3 s20 s12))
+[GOOD] (define-fun s22 () Int (+ s19 s21))
+[GOOD] (define-fun s24 () Int (ite s4 s23 s12))
+[GOOD] (define-fun s25 () Int (+ s22 s24))
+[GOOD] (define-fun s27 () Int (ite s5 s26 s12))
+[GOOD] (define-fun s28 () Int (+ s25 s27))
+[GOOD] (define-fun s30 () Int (ite s6 s29 s12))
+[GOOD] (define-fun s31 () Int (+ s28 s30))
+[GOOD] (define-fun s33 () Int (ite s7 s32 s12))
+[GOOD] (define-fun s34 () Int (+ s31 s33))
+[GOOD] (define-fun s36 () Int (ite s8 s35 s12))
+[GOOD] (define-fun s37 () Int (+ s34 s36))
+[GOOD] (define-fun s39 () Int (ite s9 s38 s12))
+[GOOD] (define-fun s40 () Int (+ s37 s39))
+[GOOD] (define-fun s41 () Bool (<= s40 s29))
+[GOOD] (define-fun s42 () Bool (= s10 s41))
+[GOOD] (define-fun s43 () Bool (not s42))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s43)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbMutexed.gold b/SBVTestSuite/GoldFiles/pbMutexed.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbMutexed.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ at-most 1) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () (_ BitVec 32) (ite s0 s11 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (ite s1 s11 s12))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvadd s13 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s2 s11 s12))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvadd s15 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s3 s11 s12))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvadd s17 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s4 s11 s12))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvadd s19 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s5 s11 s12))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvadd s21 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s11 s12))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvadd s23 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (ite s7 s11 s12))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvadd s25 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (ite s8 s11 s12))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvadd s27 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (ite s9 s11 s12))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvadd s29 s30))
+[GOOD] (define-fun s32 () Bool (bvule s31 s11))
+[GOOD] (define-fun s33 () Bool (= s10 s32))
+[GOOD] (define-fun s34 () Bool (not s33))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s34)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold b/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/pbStronglyMutexed.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "b1"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "b2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "b3"
+[GOOD] (declare-fun s4 () Bool) ; tracks user variable "b4"
+[GOOD] (declare-fun s5 () Bool) ; tracks user variable "b5"
+[GOOD] (declare-fun s6 () Bool) ; tracks user variable "b6"
+[GOOD] (declare-fun s7 () Bool) ; tracks user variable "b7"
+[GOOD] (declare-fun s8 () Bool) ; tracks user variable "b8"
+[GOOD] (declare-fun s9 () Bool) ; tracks user variable "b9"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s10 () Bool ((_ pbeq 1 1 1 1 1 1 1 1 1 1 1) s0 s1 s2 s3 s4 s5 s6 s7 s8 s9))
+[GOOD] (define-fun s13 () (_ BitVec 32) (ite s0 s11 s12))
+[GOOD] (define-fun s14 () (_ BitVec 32) (ite s1 s11 s12))
+[GOOD] (define-fun s15 () (_ BitVec 32) (bvadd s13 s14))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s2 s11 s12))
+[GOOD] (define-fun s17 () (_ BitVec 32) (bvadd s15 s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s3 s11 s12))
+[GOOD] (define-fun s19 () (_ BitVec 32) (bvadd s17 s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s4 s11 s12))
+[GOOD] (define-fun s21 () (_ BitVec 32) (bvadd s19 s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s5 s11 s12))
+[GOOD] (define-fun s23 () (_ BitVec 32) (bvadd s21 s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s11 s12))
+[GOOD] (define-fun s25 () (_ BitVec 32) (bvadd s23 s24))
+[GOOD] (define-fun s26 () (_ BitVec 32) (ite s7 s11 s12))
+[GOOD] (define-fun s27 () (_ BitVec 32) (bvadd s25 s26))
+[GOOD] (define-fun s28 () (_ BitVec 32) (ite s8 s11 s12))
+[GOOD] (define-fun s29 () (_ BitVec 32) (bvadd s27 s28))
+[GOOD] (define-fun s30 () (_ BitVec 32) (ite s9 s11 s12))
+[GOOD] (define-fun s31 () (_ BitVec 32) (bvadd s29 s30))
+[GOOD] (define-fun s32 () Bool (= s11 s31))
+[GOOD] (define-fun s33 () Bool (= s10 s32))
+[GOOD] (define-fun s34 () Bool (not s33))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s34)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/popCount1.gold b/SBVTestSuite/GoldFiles/popCount1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/popCount1.gold
@@ -0,0 +1,138 @@
+== BEGIN: "Makefile" ================
+# Makefile for popCount. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: popCount_driver
+
+popCount.o: popCount.c popCount.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+popCount_driver.o: popCount_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+popCount_driver: popCount.o popCount_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f popCount_driver
+== END: "Makefile" ==================
+== BEGIN: "popCount.h" ================
+/* Header file for popCount. Automatically generated by SBV. Do not edit! */
+
+#ifndef __popCount__HEADER_INCLUDED__
+#define __popCount__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord8 popCount(const SWord64 x);
+
+#endif /* __popCount__HEADER_INCLUDED__ */
+== END: "popCount.h" ==================
+== BEGIN: "popCount_driver.c" ================
+/* Example driver program for popCount. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "popCount.h"
+
+int main(void)
+{
+  const SWord8 __result = popCount(0x0123456789abcdefULL);
+
+  printf("popCount(0x0123456789abcdefULL) = %"PRIu8"\n", __result);
+
+  return 0;
+}
+== END: "popCount_driver.c" ==================
+== BEGIN: "popCount.c" ================
+/* File: "popCount.c". Automatically generated by SBV. Do not edit! */
+
+#include "popCount.h"
+
+SWord8 popCount(const SWord64 x)
+{
+  const SWord64 s0 = x;
+  static const SWord8 table0[] = {
+      0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
+      3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
+      3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
+      2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
+      3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
+      5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
+      2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
+      4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+      3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
+      4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
+      5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
+      5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+  };
+  const SWord64 s11 = s0 & 0x00000000000000ffULL;
+  const SWord8  s12 = table0[s11];
+  const SWord64 s14 = s0 >> 8;
+  const SWord64 s15 = 0x00000000000000ffULL & s14;
+  const SWord8  s16 = table0[s15];
+  const SWord8  s17 = s12 + s16;
+  const SWord64 s18 = s14 >> 8;
+  const SWord64 s19 = 0x00000000000000ffULL & s18;
+  const SWord8  s20 = table0[s19];
+  const SWord8  s21 = s17 + s20;
+  const SWord64 s22 = s18 >> 8;
+  const SWord64 s23 = 0x00000000000000ffULL & s22;
+  const SWord8  s24 = table0[s23];
+  const SWord8  s25 = s21 + s24;
+  const SWord64 s26 = s22 >> 8;
+  const SWord64 s27 = 0x00000000000000ffULL & s26;
+  const SWord8  s28 = table0[s27];
+  const SWord8  s29 = s25 + s28;
+  const SWord64 s30 = s26 >> 8;
+  const SWord64 s31 = 0x00000000000000ffULL & s30;
+  const SWord8  s32 = table0[s31];
+  const SWord8  s33 = s29 + s32;
+  const SWord64 s34 = s30 >> 8;
+  const SWord64 s35 = 0x00000000000000ffULL & s34;
+  const SWord8  s36 = table0[s35];
+  const SWord8  s37 = s33 + s36;
+  const SWord64 s38 = s34 >> 8;
+  const SWord64 s39 = 0x00000000000000ffULL & s38;
+  const SWord8  s40 = table0[s39];
+  const SWord8  s41 = s37 + s40;
+
+  return s41;
+}
+== END: "popCount.c" ==================
diff --git a/SBVTestSuite/GoldFiles/popCount2.gold b/SBVTestSuite/GoldFiles/popCount2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/popCount2.gold
@@ -0,0 +1,138 @@
+== BEGIN: "Makefile" ================
+# Makefile for popCount. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: popCount_driver
+
+popCount.o: popCount.c popCount.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+popCount_driver.o: popCount_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+popCount_driver: popCount.o popCount_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f popCount_driver
+== END: "Makefile" ==================
+== BEGIN: "popCount.h" ================
+/* Header file for popCount. Automatically generated by SBV. Do not edit! */
+
+#ifndef __popCount__HEADER_INCLUDED__
+#define __popCount__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord8 popCount(const SWord64 x);
+
+#endif /* __popCount__HEADER_INCLUDED__ */
+== END: "popCount.h" ==================
+== BEGIN: "popCount_driver.c" ================
+/* Example driver program for popCount. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "popCount.h"
+
+int main(void)
+{
+  const SWord8 __result = popCount(0x0123456789abcdefULL);
+
+  printf("popCount(0x0123456789abcdefULL) = %"PRIu8"\n", __result);
+
+  return 0;
+}
+== END: "popCount_driver.c" ==================
+== BEGIN: "popCount.c" ================
+/* File: "popCount.c". Automatically generated by SBV. Do not edit! */
+
+#include "popCount.h"
+
+SWord8 popCount(const SWord64 x)
+{
+  const SWord64 s0 = x;
+  static const SWord8 table0[] = {
+      0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
+      3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
+      3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
+      2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
+      3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
+      5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
+      2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
+      4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+      3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
+      4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
+      5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
+      5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+  };
+  const SWord64 s11 = s0 & 0x00000000000000ffULL;
+  const SWord8  s12 = s11 >= 256 ? 0 : table0[s11];
+  const SWord64 s14 = s0 >> 8;
+  const SWord64 s15 = 0x00000000000000ffULL & s14;
+  const SWord8  s16 = s15 >= 256 ? 0 : table0[s15];
+  const SWord8  s17 = s12 + s16;
+  const SWord64 s18 = s14 >> 8;
+  const SWord64 s19 = 0x00000000000000ffULL & s18;
+  const SWord8  s20 = s19 >= 256 ? 0 : table0[s19];
+  const SWord8  s21 = s17 + s20;
+  const SWord64 s22 = s18 >> 8;
+  const SWord64 s23 = 0x00000000000000ffULL & s22;
+  const SWord8  s24 = s23 >= 256 ? 0 : table0[s23];
+  const SWord8  s25 = s21 + s24;
+  const SWord64 s26 = s22 >> 8;
+  const SWord64 s27 = 0x00000000000000ffULL & s26;
+  const SWord8  s28 = s27 >= 256 ? 0 : table0[s27];
+  const SWord8  s29 = s25 + s28;
+  const SWord64 s30 = s26 >> 8;
+  const SWord64 s31 = 0x00000000000000ffULL & s30;
+  const SWord8  s32 = s31 >= 256 ? 0 : table0[s31];
+  const SWord8  s33 = s29 + s32;
+  const SWord64 s34 = s30 >> 8;
+  const SWord64 s35 = 0x00000000000000ffULL & s34;
+  const SWord8  s36 = s35 >= 256 ? 0 : table0[s35];
+  const SWord8  s37 = s33 + s36;
+  const SWord64 s38 = s34 >> 8;
+  const SWord64 s39 = 0x00000000000000ffULL & s38;
+  const SWord8  s40 = s39 >= 256 ? 0 : table0[s39];
+  const SWord8  s41 = s37 + s40;
+
+  return s41;
+}
+== END: "popCount.c" ==================
diff --git a/SBVTestSuite/GoldFiles/qEnum1.gold b/SBVTestSuite/GoldFiles/qEnum1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/qEnum1.gold
@@ -0,0 +1,65 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: BinOp
+[GOOD] (declare-datatype BinOp (
+           (Plus)
+           (Minus)
+           (Times)
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () BinOp (as Plus BinOp))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] (define-fun s6 () BinOp (as Minus BinOp))
+[GOOD] (define-fun s8 () Int 1)
+[GOOD] (define-fun s9 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () BinOp) ; tracks user variable "p"
+[GOOD] (declare-fun s1 () BinOp) ; tracks user variable "m"
+[GOOD] (declare-fun s2 () BinOp) ; tracks user variable "t"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s7 () Bool (= s0 s6))
+[GOOD] (define-fun s10 () Int (ite s7 s8 s9))
+[GOOD] (define-fun s11 () Int (ite s4 s5 s10))
+[GOOD] (define-fun s12 () Bool (= s1 s3))
+[GOOD] (define-fun s13 () Bool (= s1 s6))
+[GOOD] (define-fun s14 () Int (ite s13 s8 s9))
+[GOOD] (define-fun s15 () Int (ite s12 s5 s14))
+[GOOD] (define-fun s16 () Bool (<= s11 s15))
+[GOOD] (define-fun s17 () Bool (= s2 s3))
+[GOOD] (define-fun s18 () Bool (= s2 s6))
+[GOOD] (define-fun s19 () Int (ite s18 s8 s9))
+[GOOD] (define-fun s20 () Int (ite s17 s5 s19))
+[GOOD] (define-fun s21 () Bool (<= s15 s20))
+[GOOD] (define-fun s22 () Bool (distinct s0 s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s16)
+[GOOD] (assert s21)
+[GOOD] (assert s22)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 Plus))
+[SEND] (get-value (s1))
+[RECV] ((s1 Minus))
+[SEND] (get-value (s2))
+[RECV] ((s2 Times))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/qOpt_1.gold b/SBVTestSuite/GoldFiles/qOpt_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/qOpt_1.gold
@@ -0,0 +1,109 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x1"
+[GOOD] (declare-fun s4 () Int) ; tracks user variable "x2"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "x3"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "x4"
+[GOOD] (declare-fun s13 () Int) ; tracks user variable "x5"
+[GOOD] ; --- optimization tracker variables ---
+[GOOD] (declare-fun s3 () Int) ; tracks goal1
+[GOOD] (declare-fun s6 () Int) ; tracks goal2
+[GOOD] (declare-fun s9 () Int) ; tracks goal3
+[GOOD] (declare-fun s12 () Int) ; tracks goal4
+[GOOD] (declare-fun s15 () Int) ; tracks goal5
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (<= s1 s0))
+[GOOD] (define-fun s5 () Bool (<= s1 s4))
+[GOOD] (define-fun s8 () Bool (<= s1 s7))
+[GOOD] (define-fun s11 () Bool (<= s1 s10))
+[GOOD] (define-fun s14 () Bool (<= s1 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s5)
+[GOOD] (assert s8)
+[GOOD] (assert s11)
+[GOOD] (assert s14)
+[GOOD] (assert (= s0 s3))
+[GOOD] (maximize s3)
+[GOOD] (assert (= s4 s6))
+[GOOD] (maximize s6)
+[GOOD] (assert (= s7 s9))
+[GOOD] (maximize s9)
+[GOOD] (assert (= s10 s12))
+[GOOD] (maximize s12)
+[GOOD] (assert (= s13 s15))
+[GOOD] (maximize s15)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s3 oo)
+        (s6  (interval (* (- 1) oo) oo))
+        (s9  (interval (* (- 1) oo) oo))
+        (s12  (interval (* (- 1) oo) oo))
+        (s15  (interval (* (- 1) oo) oo))
+       )
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s4))
+[RECV] ((s4 1))
+[SEND] (get-value (s7))
+[RECV] ((s7 1))
+[SEND] (get-value (s10))
+[RECV] ((s10 1))
+[SEND] (get-value (s13))
+[RECV] ((s13 1))
+[SEND] (get-value (s3))
+[RECV] ((s3 1))
+[SEND] (get-value (s6))
+[RECV] ((s6 1))
+[SEND] (get-value (s9))
+[RECV] ((s9 1))
+[SEND] (get-value (s12))
+[RECV] ((s12 1))
+[SEND] (get-value (s15))
+[RECV] ((s15 1))
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s3 oo)
+        (s6  (interval (* (- 1) oo) oo))
+        (s9  (interval (* (- 1) oo) oo))
+        (s12  (interval (* (- 1) oo) oo))
+        (s15  (interval (* (- 1) oo) oo))
+       )
+*** Solver   : Z3
+*** Exit code: ExitFailure (-15)
+
+EXCEPTION CAUGHT:
+
+*** Data.SBV.getValue: The current solver state is satisfiable in an extension field.
+*** That is, the optimized values assume epsilon/infinity values.
+***
+*** Calls to getValue is not supported in this context. Instead, use the 'optimize' method
+*** directly and inspect the objective values explicitly.
+***
+*** The current model is:
+***
+***     Optimal in an extension field:
+***       goal1 =          oo :: Integer
+***       goal2 = [-oo .. oo] :: [Integer]
+***       goal3 = [-oo .. oo] :: [Integer]
+***       goal4 = [-oo .. oo] :: [Integer]
+***       goal5 = [-oo .. oo] :: [Integer]
+
diff --git a/SBVTestSuite/GoldFiles/qOpt_2.gold b/SBVTestSuite/GoldFiles/qOpt_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/qOpt_2.gold
@@ -0,0 +1,119 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s3 () Int 10)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x1"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "x2"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "x3"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "x4"
+[GOOD] (declare-fun s18 () Int) ; tracks user variable "x5"
+[GOOD] ; --- optimization tracker variables ---
+[GOOD] (declare-fun s5 () Int) ; tracks goal1
+[GOOD] (declare-fun s9 () Int) ; tracks goal2
+[GOOD] (declare-fun s13 () Int) ; tracks goal3
+[GOOD] (declare-fun s17 () Int) ; tracks goal4
+[GOOD] (declare-fun s21 () Int) ; tracks goal5
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (<= s1 s0))
+[GOOD] (define-fun s4 () Bool (< s0 s3))
+[GOOD] (define-fun s7 () Bool (<= s1 s6))
+[GOOD] (define-fun s8 () Bool (< s6 s3))
+[GOOD] (define-fun s11 () Bool (<= s1 s10))
+[GOOD] (define-fun s12 () Bool (< s10 s3))
+[GOOD] (define-fun s15 () Bool (<= s1 s14))
+[GOOD] (define-fun s16 () Bool (< s14 s3))
+[GOOD] (define-fun s19 () Bool (<= s1 s18))
+[GOOD] (define-fun s20 () Bool (< s18 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s4)
+[GOOD] (assert s7)
+[GOOD] (assert s8)
+[GOOD] (assert s11)
+[GOOD] (assert s12)
+[GOOD] (assert s15)
+[GOOD] (assert s16)
+[GOOD] (assert s19)
+[GOOD] (assert s20)
+[GOOD] (assert (= s0 s5))
+[GOOD] (maximize s5)
+[GOOD] (assert (= s6 s9))
+[GOOD] (maximize s9)
+[GOOD] (assert (= s10 s13))
+[GOOD] (maximize s13)
+[GOOD] (assert (= s14 s17))
+[GOOD] (maximize s17)
+[GOOD] (assert (= s18 s21))
+[GOOD] (maximize s21)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s5 9)
+        (s9 9)
+        (s13 9)
+        (s17 9)
+        (s21 9)
+       )
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s5 9)
+        (s9 9)
+        (s13 9)
+        (s17 9)
+        (s21 9)
+       )
+[SEND] (get-value (s6))
+[RECV] ((s6 9))
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s5 9)
+        (s9 9)
+        (s13 9)
+        (s17 9)
+        (s21 9)
+       )
+[SEND] (get-value (s10))
+[RECV] ((s10 9))
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s5 9)
+        (s9 9)
+        (s13 9)
+        (s17 9)
+        (s21 9)
+       )
+[SEND] (get-value (s14))
+[RECV] ((s14 9))
+[SEND] (get-objectives)
+[RECV] (objectives
+        (s5 9)
+        (s9 9)
+        (s13 9)
+        (s17 9)
+        (s21 9)
+       )
+[SEND] (get-value (s18))
+[RECV] ((s18 9))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:[9,9,9,9,9]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/qUninterp1.gold b/SBVTestSuite/GoldFiles/qUninterp1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/qUninterp1.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: L
+[GOOD] (declare-datatype L (
+           (A)
+           (B)
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () L)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 A))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:A
+DONE!
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_0.gold b/SBVTestSuite/GoldFiles/quantifiedB_0.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_0.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) ; has quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8)))
+                                 (let ((l1_s4 #x14))
+                                 (let ((l1_s12 #x01))
+                                 (let ((l1_s17 #x00))
+                                 (let ((l1_s5 (bvult l1_s0 l1_s4)))
+                                 (let ((l1_s6 (bvult l1_s1 l1_s4)))
+                                 (let ((l1_s7 (bvult l1_s2 l1_s4)))
+                                 (let ((l1_s8 (bvult l1_s3 l1_s4)))
+                                 (let ((l1_s9 (and l1_s7 l1_s8)))
+                                 (let ((l1_s10 (and l1_s6 l1_s9)))
+                                 (let ((l1_s11 (and l1_s5 l1_s10)))
+                                 (let ((l1_s13 (bvadd l1_s0 l1_s12)))
+                                 (let ((l1_s14 (bvadd l1_s1 l1_s13)))
+                                 (let ((l1_s15 (bvadd l1_s2 l1_s14)))
+                                 (let ((l1_s16 (bvadd l1_s3 l1_s15)))
+                                 (let ((l1_s18 (= l1_s16 l1_s17)))
+                                 (let ((l1_s19 (and l1_s11 l1_s18)))
+                                 l1_s19))))))))))))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_1.gold b/SBVTestSuite/GoldFiles/quantifiedB_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_1.gold
@@ -0,0 +1,33 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8)))
+                                 (let ((l1_s7 #x00))
+                                 (let ((l1_s4 (bvadd l1_s0 l1_s1)))
+                                 (let ((l1_s5 (bvadd l1_s2 l1_s4)))
+                                 (let ((l1_s6 (bvadd l1_s3 l1_s5)))
+                                 (let ((l1_s8 (= l1_s6 l1_s7)))
+                                 l1_s8)))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_2.gold b/SBVTestSuite/GoldFiles/quantifiedB_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_2.gold
@@ -0,0 +1,33 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8)))
+                                 (let ((l1_s4 (bvadd l1_s0 l1_s1)))
+                                 (let ((l1_s5 (bvadd l1_s2 l1_s4)))
+                                 (let ((l1_s6 (bvadd l1_s3 l1_s5)))
+                                 (let ((l1_s7 (= s0 l1_s6)))
+                                 l1_s7))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_3.gold b/SBVTestSuite/GoldFiles/quantifiedB_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_3.gold
@@ -0,0 +1,36 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8)))
+                                 (let ((l1_s4 (bvadd l1_s0 l1_s1)))
+                                 (let ((l1_s5 (bvadd l1_s2 l1_s4)))
+                                 (let ((l1_s6 (bvadd l1_s3 l1_s5)))
+                                 (let ((l1_s7 (= s0 l1_s6)))
+                                 l1_s7))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x01))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable. Model:
+  s0 = 1 :: Word8
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_4.gold b/SBVTestSuite/GoldFiles/quantifiedB_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_4.gold
@@ -0,0 +1,32 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8)) (l1_s4 (_ BitVec 8)))
+                                 (let ((l1_s5 (bvadd l1_s0 l1_s1)))
+                                 (let ((l1_s6 (bvadd l1_s2 l1_s5)))
+                                 (let ((l1_s7 (bvadd l1_s3 l1_s6)))
+                                 (let ((l1_s8 (= l1_s4 l1_s7)))
+                                 l1_s8))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_5.gold b/SBVTestSuite/GoldFiles/quantifiedB_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_5.gold
@@ -0,0 +1,32 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)) (l1_s2 (_ BitVec 8)) (l1_s3 (_ BitVec 8))) (forall ((l1_s4 (_ BitVec 8)))
+                                 (let ((l1_s5 (bvadd l1_s0 l1_s1)))
+                                 (let ((l1_s6 (bvadd l1_s2 l1_s5)))
+                                 (let ((l1_s7 (bvadd l1_s3 l1_s6)))
+                                 (let ((l1_s8 (= l1_s4 l1_s7)))
+                                 l1_s8)))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_6.gold b/SBVTestSuite/GoldFiles/quantifiedB_6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_6.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 Bool))
+                                 l1_s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_7.gold b/SBVTestSuite/GoldFiles/quantifiedB_7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_7.gold
@@ -0,0 +1,30 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 Bool))
+                                 (let ((l1_s1 (exists ((l2_s0 Bool))
+         (or l1_s0 l2_s0))))
+                                 l1_s1)))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_8.gold b/SBVTestSuite/GoldFiles/quantifiedB_8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_8.gold
@@ -0,0 +1,30 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 Bool))
+                                 (let ((l1_s1 (exists ((l2_s0 Bool))
+         (or l1_s0 l2_s0))))
+                                 l1_s1)))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_9.gold b/SBVTestSuite/GoldFiles/quantifiedB_9.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_9.gold
@@ -0,0 +1,30 @@
+** 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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 Bool))
+                                 (let ((l1_s1 (exists ((l2_s0 Bool))
+         (or l1_s0 l2_s0))))
+                                 l1_s1)))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_A.gold b/SBVTestSuite/GoldFiles/quantifiedB_A.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_A.gold
@@ -0,0 +1,33 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 Int)) (forall ((l1_s1 Int)) (exists ((l1_s2 Int)) (forall ((l1_s3 Int))
+                                 (let ((l1_s7 0))
+                                 (let ((l1_s4 (+ l1_s0 l1_s1)))
+                                 (let ((l1_s5 (+ l1_s2 l1_s4)))
+                                 (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                 (let ((l1_s8 (= l1_s6 l1_s7)))
+                                 l1_s8))))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/quantifiedB_B.gold b/SBVTestSuite/GoldFiles/quantifiedB_B.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantifiedB_B.gold
@@ -0,0 +1,33 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int)) (exists ((l1_s1 Int)) (forall ((l1_s2 Int)) (exists ((l1_s3 Int))
+                                 (let ((l1_s7 0))
+                                 (let ((l1_s4 (+ l1_s0 l1_s1)))
+                                 (let ((l1_s5 (+ l1_s2 l1_s4)))
+                                 (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                 (let ((l1_s8 (= l1_s6 l1_s7)))
+                                 l1_s8))))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Satisfiable
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s0))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (exists ((l1_s0 (_ BitVec 8))) (forall ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8))) (exists ((l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s1)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 #x01))
+                                 (let ((l1_s3 (bvadd l1_s1 l1_s2)))
+                                 (let ((l1_s4 (= l1_s0 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.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 quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 (_ BitVec 8)) (l1_s1 (_ BitVec 8)))
+                                 (let ((l1_s2 (bvsub l1_s1 l1_s0)))
+                                 (let ((l1_s3 (bvadd l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4)))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query1.gold b/SBVTestSuite/GoldFiles/query1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query1.gold
@@ -0,0 +1,205 @@
+** 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-unsat-cores true)
+[GOOD] (set-option :produce-unsat-assumptions true)
+[GOOD] (set-option :produce-proofs true)
+[GOOD] (set-option :random-seed 123)
+[GOOD] (set-option :produce-assertions true)
+[GOOD] (set-option :smt.mbqi true)
+[GOOD] (set-option :produce-assignments true)
+[GOOD] (set-info :status sat)
+[GOOD] (set-info :bad what)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (_ FloatingPoint  8 24)) ; tracks user variable "c"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "d"
+[GOOD] (declare-fun s4 () Real) ; tracks user variable "e"
+[GOOD] (declare-fun s5 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s7 () Bool (> s0 s6))
+[GOOD] (define-fun s8 () Bool (> s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s7 :named |a > 0|))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () Int 2)
+[GOOD] (define-fun s11 () Int 5)
+[GOOD] (define-fun s10 () Int (+ s0 s9))
+[GOOD] (define-fun s12 () Bool (>= s10 s11))
+[GOOD] (assert s12)
+[GOOD] (define-fun s14 () Int 12)
+[GOOD] (define-fun s13 () Int (+ s0 s1))
+[GOOD] (define-fun s15 () Bool (< s13 s14))
+[GOOD] (assert (! s15 :named |a+b_<_12|))
+[SEND] (get-option :diagnostic-output-channel)
+[RECV] stdout
+[SEND] (get-option :produce-assertions)
+[RECV] true
+[SEND] (get-option :produce-assignments)
+[RECV] true
+[SEND] (get-option :produce-proofs)
+[RECV] true
+[SEND] (get-option :produce-unsat-assumptions)
+[RECV] true
+[SEND] (get-option :produce-unsat-cores)
+[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: 43 position: 0
+[RECV] 0
+[SEND] (get-option :smt.mbqi)
+[RECV] true
+[SEND] (get-option :smt.mbqi)
+[RECV] true
+[SEND] (get-info :reason-unknown)
+[RECV] (:reason-unknown "state of the most recent check-sat command is not known")
+[SEND] (get-info :version)
+[RECV] (:version "4.17.0")
+[SEND] (get-info :status)
+[RECV] (:status sat)
+[GOOD] (define-fun s16 () Int 4)
+[GOOD] (define-fun s17 () Bool (> s0 s16))
+[GOOD] (assert (! s17 :named |later, a > 4|))
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-info :status unknown)
+[GOOD] (define-fun s18 () Bool (> s0 s9))
+[GOOD] (declare-const __assumption_proxy_s18_19 Bool)
+[GOOD] (assert (= __assumption_proxy_s18_19 s18))
+[SEND] (check-sat-assuming (__assumption_proxy_s18_19))
+[RECV] sat
+[GOOD] (declare-const __assumption_proxy_s18_20 Bool)
+[GOOD] (assert (= __assumption_proxy_s18_20 s18))
+[SEND] (check-sat-assuming (__assumption_proxy_s18_20))
+[RECV] sat
+[SEND] (get-assignment)
+[RECV] ((s7 true) (|a > 0| true) (s15 true) (s8 true) (s17 true) (a+b_<_12 true) (|later, a > 4| true) (s18 true) (s12 true))
+[SEND] (get-info :assertion-stack-levels)
+[RECV] (:assertion-stack-levels 0)
+[SEND] (get-info :authors)
+[RECV] (:authors "Leonardo de Moura, Nikolaj Bjorner, Lev Nachmanson and Christoph Wintersteiger")
+[SEND] (get-info :error-behavior)
+[RECV] (:error-behavior continued-execution)
+[SEND] (get-info :name)
+[RECV] (:name "Z3")
+[SEND] (get-info :reason-unknown)
+[RECV] (:reason-unknown "unknown")
+[SEND] (get-info :version)
+[RECV] (:version "4.17.0")
+[SEND] (get-info :memory)
+[RECV] unsupported
+[SEND] (get-info :time)
+[SKIP] ; :memory line: 69 position: 0
+[SKIP] ; Suppported get-info parameters:
+[SKIP] ; (get-info :reason-unknown)
+[SKIP] ; (get-info :status)
+[SKIP] ; (get-info :version)
+[SKIP] ; (get-info :authors)
+[SKIP] ; (get-info :error-behavior)
+[SKIP] ; (get-info :parameters)
+[SKIP] ; (get-info :rlimit)
+[SKIP] ; (get-info :assertion-stack-levels)
+[RECV] unsupported
+[SEND] (get-value (s0))
+[SKIP] ; :time line: 70 position: 0
+[SKIP] ; Suppported get-info parameters:
+[SKIP] ; (get-info :reason-unknown)
+[SKIP] ; (get-info :status)
+[SKIP] ; (get-info :version)
+[SKIP] ; (get-info :authors)
+[SKIP] ; (get-info :error-behavior)
+[SKIP] ; (get-info :parameters)
+[SKIP] ; (get-info :rlimit)
+[SKIP] ; (get-info :assertion-stack-levels)
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[GOOD] (define-fun s21 () Int 100)
+[GOOD] (define-fun s23 () Int 9)
+[GOOD] (define-fun s22 () Bool (> s0 s21))
+[GOOD] (define-fun s24 () Bool (> s0 s23))
+[GOOD] (declare-const __assumption_proxy_s22_25 Bool)
+[GOOD] (assert (= __assumption_proxy_s22_25 s22))
+[GOOD] (declare-const __assumption_proxy_s24_26 Bool)
+[GOOD] (assert (= __assumption_proxy_s24_26 s24))
+[SEND] (check-sat-assuming (__assumption_proxy_s22_25 __assumption_proxy_s24_26))
+[RECV] unsat
+[SEND] (get-unsat-assumptions)
+[RECV] (a+b_<_12 __assumption_proxy_s22_25)
+*** In call to 'getUnsatAssumptions'
+***
+***    Unexpected assumption named: "a+b_<_12"
+***    Was expecting one of       : ["s22","s24"]
+***
+*** This can happen if unsat-cores are also enabled. Ignoring.
+[GOOD] (push 5)
+[GOOD] (pop 3)
+[GOOD] (define-fun s27 () Int 6)
+[GOOD] (define-fun s28 () Bool (> s0 s27))
+[GOOD] (assert (! s28 :named |bey|))
+[GOOD] (define-fun s29 () Bool (< s0 s27))
+[GOOD] (assert (! s29 :named |hey|))
+[SEND] (check-sat)
+[RECV] unsat
+[SEND, TimeOut: 80000ms] (get-unsat-core)
+[RECV] (bey hey)
+[SEND] (get-proof)
+[RECV] ((set-logic ALL)
+       (proof
+       (let (($x268 (<= s0 6)))
+       (let (($x269 (not $x268)))
+       (let (($x276 (or (not bey) $x269)))
+       (let ((@x274 (monotonicity (rewrite (= (> s0 6) $x269)) (= (=> bey (> s0 6)) (=> bey $x269)))))
+       (let ((@x280 (trans @x274 (rewrite (= (=> bey $x269) $x276)) (= (=> bey (> s0 6)) $x276))))
+       (let ((@x281 (mp (asserted (=> bey (> s0 6))) @x280 $x276)))
+       (let (($x293 (>= s0 6)))
+       (let (($x292 (not $x293)))
+       (let (($x300 (or (not hey) $x292)))
+       (let ((@x291 (trans (rewrite (= (< s0 6) (not (<= 6 s0)))) (rewrite (= (not (<= 6 s0)) $x292)) (= (< s0 6) $x292))))
+       (let ((@x304 (trans (monotonicity @x291 (= (=> hey (< s0 6)) (=> hey $x292))) (rewrite (= (=> hey $x292) $x300)) (= (=> hey (< s0 6)) $x300))))
+       (let ((@x305 (mp (asserted (=> hey (< s0 6))) @x304 $x300)))
+       (unit-resolution ((_ th-lemma arith farkas 1 1) (or $x293 $x268)) (unit-resolution @x305 (asserted hey) $x292) (unit-resolution @x281 (asserted bey) $x269) false)))))))))))))))
+[SEND, TimeOut: 90000ms] (get-assertions)
+
+[RECV] ((! s7 :named |a > 0|)
+        s8
+        s12
+        (! s15 :named |a+b_<_12|)
+        (! s17 :named |later, a > 4|)
+        (= __assumption_proxy_s18_19 s18)
+        (= __assumption_proxy_s18_20 s18)
+        (= __assumption_proxy_s22_25 s22)
+        (= __assumption_proxy_s24_26 s24)
+        (! s28 :named |bey|)
+        (! s29 :named |hey|))
+[SEND] (echo "there we go")
+[RECV] "there we go"
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Satisfiable. Model:
+  a  =  332 :: Integer
+  b  =    3 :: Integer
+  c  =  2.3 :: Float
+  d  = True :: Bool
+  e  = 3.12 :: Real
+  s5 =  -12 :: Int8
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays1.gold b/SBVTestSuite/GoldFiles/queryArrays1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays1.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) (_ BitVec 8))) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 8)) ; tracks user variable "a1"
+[GOOD] (declare-fun s2 () (_ BitVec 8)) ; tracks user variable "a2"
+[GOOD] (declare-fun s4 () (_ BitVec 8)) ; tracks user variable "v1"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) (_ BitVec 8)) (store s0 s1 s4))
+[GOOD] (define-fun s6 () (_ BitVec 8) (select s5 s1))
+[GOOD] (define-fun s7 () Bool (= s4 s6))
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 #xff))
+[SEND] (get-value (s2))
+[RECV] ((s2 #x00))
+[SEND] (get-value (s4))
+[RECV] ((s4 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:(255,0,0)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays10.gold b/SBVTestSuite/GoldFiles/queryArrays10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays10.gold
@@ -0,0 +1,36 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int String)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 Int)) (= 1 (str.len (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int 5)
+[GOOD] (define-fun s3 () String (_ char #x61))
+[GOOD] (define-fun s2 () String (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays11.gold b/SBVTestSuite/GoldFiles/queryArrays11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays11.gold
@@ -0,0 +1,36 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has non-bitvector arrays, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array String String)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 String)) (= 1 (str.len (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () String (_ char #x61))
+[GOOD] (define-fun s3 () String (_ char #x62))
+[GOOD] (define-fun s2 () String (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays12.gold b/SBVTestSuite/GoldFiles/queryArrays12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays12.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array SBVRational Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () SBVRational (SBV.Rational 5 3))
+[GOOD] (define-fun s3 () Int 5)
+[GOOD] (define-fun s2 () Int (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays13.gold b/SBVTestSuite/GoldFiles/queryArrays13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays13.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int SBVRational)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 Int)) (< 0 (sbv.rat.denominator (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int 5)
+[GOOD] (define-fun s3 () SBVRational (SBV.Rational 5 3))
+[GOOD] (define-fun s2 () SBVRational (select s0 s1))
+[GOOD] (define-fun s4 () Bool (sbv.rat.eq s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays14.gold b/SBVTestSuite/GoldFiles/queryArrays14.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays14.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array SBVRational SBVRational)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 SBVRational)) (< 0 (sbv.rat.denominator (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () SBVRational (SBV.Rational 5 3))
+[GOOD] (define-fun s3 () SBVRational (SBV.Rational 9 8))
+[GOOD] (define-fun s2 () SBVRational (select s0 s1))
+[GOOD] (define-fun s4 () Bool (sbv.rat.eq s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays15.gold b/SBVTestSuite/GoldFiles/queryArrays15.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays15.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array SBVRational String)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 SBVRational)) (= 1 (str.len (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () SBVRational (SBV.Rational 5 3))
+[GOOD] (define-fun s3 () String (_ char #x7a))
+[GOOD] (define-fun s2 () String (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays16.gold b/SBVTestSuite/GoldFiles/queryArrays16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays16.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array String SBVRational)) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 String)) (< 0 (sbv.rat.denominator (select s0 array0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () String (_ char #x7a))
+[GOOD] (define-fun s3 () SBVRational (SBV.Rational 5 3))
+[GOOD] (define-fun s2 () SBVRational (select s0 s1))
+[GOOD] (define-fun s4 () Bool (sbv.rat.eq s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays17.gold b/SBVTestSuite/GoldFiles/queryArrays17.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays17.gold
@@ -0,0 +1,49 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has rational values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatype SBVRational ((SBV.Rational (sbv.rat.numerator Int) (sbv.rat.denominator Int))))
+
+[GOOD] (define-fun sbv.rat.eq ((x SBVRational) (y SBVRational)) Bool
+          (= (* (sbv.rat.numerator   x) (sbv.rat.denominator y))
+             (* (sbv.rat.denominator x) (sbv.rat.numerator   y)))
+       )
+
+[GOOD] (define-fun sbv.rat.notEq ((x SBVRational) (y SBVRational)) Bool
+          (not (sbv.rat.eq x y))
+       )
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (SBVTuple2 String SBVRational) (SBVTuple2 SBVRational String))) ; tracks user variable "x"
+[GOOD] (assert (forall ((array0 (SBVTuple2 String SBVRational))) (and (< 0 (sbv.rat.denominator (proj_1_SBVTuple2 (select s0 array0)))) (= 1 (str.len (proj_2_SBVTuple2 (select s0 array0)))))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () (SBVTuple2 String SBVRational) (mkSBVTuple2 (_ char #x7a) (SBV.Rational 5 3)))
+[GOOD] (define-fun s3 () (SBVTuple2 SBVRational String) (mkSBVTuple2 (SBV.Rational 5 3) (_ char #x7a)))
+[GOOD] (define-fun s2 () (SBVTuple2 SBVRational String) (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays2.gold b/SBVTestSuite/GoldFiles/queryArrays2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays2.gold
@@ -0,0 +1,547 @@
+** 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_UFBV) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x02)
+[GOOD] (define-fun s4 () (_ BitVec 8) #x03)
+[GOOD] (define-fun s5 () (_ BitVec 8) #x04)
+[GOOD] (define-fun s6 () (_ BitVec 8) #x05)
+[GOOD] (define-fun s7 () (_ BitVec 8) #x06)
+[GOOD] (define-fun s8 () (_ BitVec 8) #x07)
+[GOOD] (define-fun s9 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s10 () (_ BitVec 8) #x09)
+[GOOD] (define-fun s11 () (_ BitVec 8) #x0a)
+[GOOD] (define-fun s12 () (_ BitVec 8) #x0b)
+[GOOD] (define-fun s13 () (_ BitVec 8) #x0c)
+[GOOD] (define-fun s14 () (_ BitVec 8) #x0d)
+[GOOD] (define-fun s15 () (_ BitVec 8) #x0e)
+[GOOD] (define-fun s16 () (_ BitVec 8) #x0f)
+[GOOD] (define-fun s17 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s18 () (_ BitVec 8) #x11)
+[GOOD] (define-fun s19 () (_ BitVec 8) #x12)
+[GOOD] (define-fun s20 () (_ BitVec 8) #x13)
+[GOOD] (define-fun s21 () (_ BitVec 8) #x14)
+[GOOD] (define-fun s22 () (_ BitVec 8) #x15)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x16)
+[GOOD] (define-fun s24 () (_ BitVec 8) #x17)
+[GOOD] (define-fun s25 () (_ BitVec 8) #x18)
+[GOOD] (define-fun s26 () (_ BitVec 8) #x19)
+[GOOD] (define-fun s27 () (_ BitVec 8) #x1a)
+[GOOD] (define-fun s28 () (_ BitVec 8) #x1b)
+[GOOD] (define-fun s29 () (_ BitVec 8) #x1c)
+[GOOD] (define-fun s30 () (_ BitVec 8) #x1d)
+[GOOD] (define-fun s31 () (_ BitVec 8) #x1e)
+[GOOD] (define-fun s32 () (_ BitVec 8) #x1f)
+[GOOD] (define-fun s33 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s34 () (_ BitVec 8) #x21)
+[GOOD] (define-fun s35 () (_ BitVec 8) #x22)
+[GOOD] (define-fun s36 () (_ BitVec 8) #x23)
+[GOOD] (define-fun s37 () (_ BitVec 8) #x24)
+[GOOD] (define-fun s38 () (_ BitVec 8) #x25)
+[GOOD] (define-fun s39 () (_ BitVec 8) #x26)
+[GOOD] (define-fun s40 () (_ BitVec 8) #x27)
+[GOOD] (define-fun s41 () (_ BitVec 8) #x28)
+[GOOD] (define-fun s42 () (_ BitVec 8) #x29)
+[GOOD] (define-fun s43 () (_ BitVec 8) #x2a)
+[GOOD] (define-fun s44 () (_ BitVec 8) #x2b)
+[GOOD] (define-fun s45 () (_ BitVec 8) #x2c)
+[GOOD] (define-fun s46 () (_ BitVec 8) #x2d)
+[GOOD] (define-fun s47 () (_ BitVec 8) #x2e)
+[GOOD] (define-fun s48 () (_ BitVec 8) #x2f)
+[GOOD] (define-fun s49 () (_ BitVec 8) #x30)
+[GOOD] (define-fun s50 () (_ BitVec 8) #x31)
+[GOOD] (define-fun s51 () (_ BitVec 8) #x32)
+[GOOD] (define-fun s52 () (_ BitVec 8) #x33)
+[GOOD] (define-fun s53 () (_ BitVec 8) #x34)
+[GOOD] (define-fun s54 () (_ BitVec 8) #x35)
+[GOOD] (define-fun s55 () (_ BitVec 8) #x36)
+[GOOD] (define-fun s56 () (_ BitVec 8) #x37)
+[GOOD] (define-fun s57 () (_ BitVec 8) #x38)
+[GOOD] (define-fun s58 () (_ BitVec 8) #x39)
+[GOOD] (define-fun s59 () (_ BitVec 8) #x3a)
+[GOOD] (define-fun s60 () (_ BitVec 8) #x3b)
+[GOOD] (define-fun s61 () (_ BitVec 8) #x3c)
+[GOOD] (define-fun s62 () (_ BitVec 8) #x3d)
+[GOOD] (define-fun s63 () (_ BitVec 8) #x3e)
+[GOOD] (define-fun s64 () (_ BitVec 8) #x3f)
+[GOOD] (define-fun s65 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s66 () (_ BitVec 8) #x41)
+[GOOD] (define-fun s67 () (_ BitVec 8) #x42)
+[GOOD] (define-fun s68 () (_ BitVec 8) #x43)
+[GOOD] (define-fun s69 () (_ BitVec 8) #x44)
+[GOOD] (define-fun s70 () (_ BitVec 8) #x45)
+[GOOD] (define-fun s71 () (_ BitVec 8) #x46)
+[GOOD] (define-fun s72 () (_ BitVec 8) #x47)
+[GOOD] (define-fun s73 () (_ BitVec 8) #x48)
+[GOOD] (define-fun s74 () (_ BitVec 8) #x49)
+[GOOD] (define-fun s75 () (_ BitVec 8) #x4a)
+[GOOD] (define-fun s76 () (_ BitVec 8) #x4b)
+[GOOD] (define-fun s77 () (_ BitVec 8) #x4c)
+[GOOD] (define-fun s78 () (_ BitVec 8) #x4d)
+[GOOD] (define-fun s79 () (_ BitVec 8) #x4e)
+[GOOD] (define-fun s80 () (_ BitVec 8) #x4f)
+[GOOD] (define-fun s81 () (_ BitVec 8) #x50)
+[GOOD] (define-fun s82 () (_ BitVec 8) #x51)
+[GOOD] (define-fun s83 () (_ BitVec 8) #x52)
+[GOOD] (define-fun s84 () (_ BitVec 8) #x53)
+[GOOD] (define-fun s85 () (_ BitVec 8) #x54)
+[GOOD] (define-fun s86 () (_ BitVec 8) #x55)
+[GOOD] (define-fun s87 () (_ BitVec 8) #x56)
+[GOOD] (define-fun s88 () (_ BitVec 8) #x57)
+[GOOD] (define-fun s89 () (_ BitVec 8) #x58)
+[GOOD] (define-fun s90 () (_ BitVec 8) #x59)
+[GOOD] (define-fun s91 () (_ BitVec 8) #x5a)
+[GOOD] (define-fun s92 () (_ BitVec 8) #x5b)
+[GOOD] (define-fun s93 () (_ BitVec 8) #x5c)
+[GOOD] (define-fun s94 () (_ BitVec 8) #x5d)
+[GOOD] (define-fun s95 () (_ BitVec 8) #x5e)
+[GOOD] (define-fun s96 () (_ BitVec 8) #x5f)
+[GOOD] (define-fun s97 () (_ BitVec 8) #x60)
+[GOOD] (define-fun s98 () (_ BitVec 8) #x61)
+[GOOD] (define-fun s99 () (_ BitVec 8) #x62)
+[GOOD] (define-fun s100 () (_ BitVec 8) #x63)
+[GOOD] (define-fun s101 () (_ BitVec 8) #x64)
+[GOOD] (define-fun s102 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s103 () (_ BitVec 8) #x66)
+[GOOD] (define-fun s104 () (_ BitVec 8) #x67)
+[GOOD] (define-fun s105 () (_ BitVec 8) #x68)
+[GOOD] (define-fun s106 () (_ BitVec 8) #x69)
+[GOOD] (define-fun s107 () (_ BitVec 8) #x6a)
+[GOOD] (define-fun s108 () (_ BitVec 8) #x6b)
+[GOOD] (define-fun s109 () (_ BitVec 8) #x6c)
+[GOOD] (define-fun s110 () (_ BitVec 8) #x6d)
+[GOOD] (define-fun s111 () (_ BitVec 8) #x6e)
+[GOOD] (define-fun s112 () (_ BitVec 8) #x6f)
+[GOOD] (define-fun s113 () (_ BitVec 8) #x70)
+[GOOD] (define-fun s114 () (_ BitVec 8) #x71)
+[GOOD] (define-fun s115 () (_ BitVec 8) #x72)
+[GOOD] (define-fun s116 () (_ BitVec 8) #x73)
+[GOOD] (define-fun s117 () (_ BitVec 8) #x74)
+[GOOD] (define-fun s118 () (_ BitVec 8) #x75)
+[GOOD] (define-fun s119 () (_ BitVec 8) #x76)
+[GOOD] (define-fun s120 () (_ BitVec 8) #x77)
+[GOOD] (define-fun s121 () (_ BitVec 8) #x78)
+[GOOD] (define-fun s122 () (_ BitVec 8) #x79)
+[GOOD] (define-fun s123 () (_ BitVec 8) #x7a)
+[GOOD] (define-fun s124 () (_ BitVec 8) #x7b)
+[GOOD] (define-fun s125 () (_ BitVec 8) #x7c)
+[GOOD] (define-fun s126 () (_ BitVec 8) #x7d)
+[GOOD] (define-fun s127 () (_ BitVec 8) #x7e)
+[GOOD] (define-fun s128 () (_ BitVec 8) #x7f)
+[GOOD] (define-fun s129 () (_ BitVec 8) #x80)
+[GOOD] (define-fun s130 () (_ BitVec 8) #x81)
+[GOOD] (define-fun s131 () (_ BitVec 8) #x82)
+[GOOD] (define-fun s132 () (_ BitVec 8) #x83)
+[GOOD] (define-fun s133 () (_ BitVec 8) #x84)
+[GOOD] (define-fun s134 () (_ BitVec 8) #x85)
+[GOOD] (define-fun s135 () (_ BitVec 8) #x86)
+[GOOD] (define-fun s136 () (_ BitVec 8) #x87)
+[GOOD] (define-fun s137 () (_ BitVec 8) #x88)
+[GOOD] (define-fun s138 () (_ BitVec 8) #x89)
+[GOOD] (define-fun s139 () (_ BitVec 8) #x8a)
+[GOOD] (define-fun s140 () (_ BitVec 8) #x8b)
+[GOOD] (define-fun s141 () (_ BitVec 8) #x8c)
+[GOOD] (define-fun s142 () (_ BitVec 8) #x8d)
+[GOOD] (define-fun s143 () (_ BitVec 8) #x8e)
+[GOOD] (define-fun s144 () (_ BitVec 8) #x8f)
+[GOOD] (define-fun s145 () (_ BitVec 8) #x90)
+[GOOD] (define-fun s146 () (_ BitVec 8) #x91)
+[GOOD] (define-fun s147 () (_ BitVec 8) #x92)
+[GOOD] (define-fun s148 () (_ BitVec 8) #x93)
+[GOOD] (define-fun s149 () (_ BitVec 8) #x94)
+[GOOD] (define-fun s150 () (_ BitVec 8) #x95)
+[GOOD] (define-fun s151 () (_ BitVec 8) #x96)
+[GOOD] (define-fun s152 () (_ BitVec 8) #x97)
+[GOOD] (define-fun s153 () (_ BitVec 8) #x98)
+[GOOD] (define-fun s154 () (_ BitVec 8) #x99)
+[GOOD] (define-fun s155 () (_ BitVec 8) #x9a)
+[GOOD] (define-fun s156 () (_ BitVec 8) #x9b)
+[GOOD] (define-fun s157 () (_ BitVec 8) #x9c)
+[GOOD] (define-fun s158 () (_ BitVec 8) #x9d)
+[GOOD] (define-fun s159 () (_ BitVec 8) #x9e)
+[GOOD] (define-fun s160 () (_ BitVec 8) #x9f)
+[GOOD] (define-fun s161 () (_ BitVec 8) #xa0)
+[GOOD] (define-fun s162 () (_ BitVec 8) #xa1)
+[GOOD] (define-fun s163 () (_ BitVec 8) #xa2)
+[GOOD] (define-fun s164 () (_ BitVec 8) #xa3)
+[GOOD] (define-fun s165 () (_ BitVec 8) #xa4)
+[GOOD] (define-fun s166 () (_ BitVec 8) #xa5)
+[GOOD] (define-fun s167 () (_ BitVec 8) #xa6)
+[GOOD] (define-fun s168 () (_ BitVec 8) #xa7)
+[GOOD] (define-fun s169 () (_ BitVec 8) #xa8)
+[GOOD] (define-fun s170 () (_ BitVec 8) #xa9)
+[GOOD] (define-fun s171 () (_ BitVec 8) #xaa)
+[GOOD] (define-fun s172 () (_ BitVec 8) #xab)
+[GOOD] (define-fun s173 () (_ BitVec 8) #xac)
+[GOOD] (define-fun s174 () (_ BitVec 8) #xad)
+[GOOD] (define-fun s175 () (_ BitVec 8) #xae)
+[GOOD] (define-fun s176 () (_ BitVec 8) #xaf)
+[GOOD] (define-fun s177 () (_ BitVec 8) #xb0)
+[GOOD] (define-fun s178 () (_ BitVec 8) #xb1)
+[GOOD] (define-fun s179 () (_ BitVec 8) #xb2)
+[GOOD] (define-fun s180 () (_ BitVec 8) #xb3)
+[GOOD] (define-fun s181 () (_ BitVec 8) #xb4)
+[GOOD] (define-fun s182 () (_ BitVec 8) #xb5)
+[GOOD] (define-fun s183 () (_ BitVec 8) #xb6)
+[GOOD] (define-fun s184 () (_ BitVec 8) #xb7)
+[GOOD] (define-fun s185 () (_ BitVec 8) #xb8)
+[GOOD] (define-fun s186 () (_ BitVec 8) #xb9)
+[GOOD] (define-fun s187 () (_ BitVec 8) #xba)
+[GOOD] (define-fun s188 () (_ BitVec 8) #xbb)
+[GOOD] (define-fun s189 () (_ BitVec 8) #xbc)
+[GOOD] (define-fun s190 () (_ BitVec 8) #xbd)
+[GOOD] (define-fun s191 () (_ BitVec 8) #xbe)
+[GOOD] (define-fun s192 () (_ BitVec 8) #xbf)
+[GOOD] (define-fun s193 () (_ BitVec 8) #xc0)
+[GOOD] (define-fun s194 () (_ BitVec 8) #xc1)
+[GOOD] (define-fun s195 () (_ BitVec 8) #xc2)
+[GOOD] (define-fun s196 () (_ BitVec 8) #xc3)
+[GOOD] (define-fun s197 () (_ BitVec 8) #xc4)
+[GOOD] (define-fun s198 () (_ BitVec 8) #xc5)
+[GOOD] (define-fun s199 () (_ BitVec 8) #xc6)
+[GOOD] (define-fun s200 () (_ BitVec 8) #xc7)
+[GOOD] (define-fun s201 () (_ BitVec 8) #xc8)
+[GOOD] (define-fun s202 () (_ BitVec 8) #xc9)
+[GOOD] (define-fun s203 () (_ BitVec 8) #xca)
+[GOOD] (define-fun s204 () (_ BitVec 8) #xcb)
+[GOOD] (define-fun s205 () (_ BitVec 8) #xcc)
+[GOOD] (define-fun s206 () (_ BitVec 8) #xcd)
+[GOOD] (define-fun s207 () (_ BitVec 8) #xce)
+[GOOD] (define-fun s208 () (_ BitVec 8) #xcf)
+[GOOD] (define-fun s209 () (_ BitVec 8) #xd0)
+[GOOD] (define-fun s210 () (_ BitVec 8) #xd1)
+[GOOD] (define-fun s211 () (_ BitVec 8) #xd2)
+[GOOD] (define-fun s212 () (_ BitVec 8) #xd3)
+[GOOD] (define-fun s213 () (_ BitVec 8) #xd4)
+[GOOD] (define-fun s214 () (_ BitVec 8) #xd5)
+[GOOD] (define-fun s215 () (_ BitVec 8) #xd6)
+[GOOD] (define-fun s216 () (_ BitVec 8) #xd7)
+[GOOD] (define-fun s217 () (_ BitVec 8) #xd8)
+[GOOD] (define-fun s218 () (_ BitVec 8) #xd9)
+[GOOD] (define-fun s219 () (_ BitVec 8) #xda)
+[GOOD] (define-fun s220 () (_ BitVec 8) #xdb)
+[GOOD] (define-fun s221 () (_ BitVec 8) #xdc)
+[GOOD] (define-fun s222 () (_ BitVec 8) #xdd)
+[GOOD] (define-fun s223 () (_ BitVec 8) #xde)
+[GOOD] (define-fun s224 () (_ BitVec 8) #xdf)
+[GOOD] (define-fun s225 () (_ BitVec 8) #xe0)
+[GOOD] (define-fun s226 () (_ BitVec 8) #xe1)
+[GOOD] (define-fun s227 () (_ BitVec 8) #xe2)
+[GOOD] (define-fun s228 () (_ BitVec 8) #xe3)
+[GOOD] (define-fun s229 () (_ BitVec 8) #xe4)
+[GOOD] (define-fun s230 () (_ BitVec 8) #xe5)
+[GOOD] (define-fun s231 () (_ BitVec 8) #xe6)
+[GOOD] (define-fun s232 () (_ BitVec 8) #xe7)
+[GOOD] (define-fun s233 () (_ BitVec 8) #xe8)
+[GOOD] (define-fun s234 () (_ BitVec 8) #xe9)
+[GOOD] (define-fun s235 () (_ BitVec 8) #xea)
+[GOOD] (define-fun s236 () (_ BitVec 8) #xeb)
+[GOOD] (define-fun s237 () (_ BitVec 8) #xec)
+[GOOD] (define-fun s238 () (_ BitVec 8) #xed)
+[GOOD] (define-fun s239 () (_ BitVec 8) #xee)
+[GOOD] (define-fun s240 () (_ BitVec 8) #xef)
+[GOOD] (define-fun s241 () (_ BitVec 8) #xf0)
+[GOOD] (define-fun s242 () (_ BitVec 8) #xf1)
+[GOOD] (define-fun s243 () (_ BitVec 8) #xf2)
+[GOOD] (define-fun s244 () (_ BitVec 8) #xf3)
+[GOOD] (define-fun s245 () (_ BitVec 8) #xf4)
+[GOOD] (define-fun s246 () (_ BitVec 8) #xf5)
+[GOOD] (define-fun s247 () (_ BitVec 8) #xf6)
+[GOOD] (define-fun s248 () (_ BitVec 8) #xf7)
+[GOOD] (define-fun s249 () (_ BitVec 8) #xf8)
+[GOOD] (define-fun s250 () (_ BitVec 8) #xf9)
+[GOOD] (define-fun s251 () (_ BitVec 8) #xfa)
+[GOOD] (define-fun s252 () (_ BitVec 8) #xfb)
+[GOOD] (define-fun s253 () (_ BitVec 8) #xfc)
+[GOOD] (define-fun s254 () (_ BitVec 8) #xfd)
+[GOOD] (define-fun s255 () (_ BitVec 8) #xfe)
+[GOOD] (define-fun s256 () (_ BitVec 8) #xff)
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] (define-fun s257 () (_ BitVec 8) (table0 s0))
+[GOOD] (define-fun s258 () Bool (= s0 s257))
+[GOOD] (define-fun table0_initializer_0 () Bool (= (table0 #x00) s1))
+[GOOD] (define-fun table0_initializer_1 () Bool (= (table0 #x01) s2))
+[GOOD] (define-fun table0_initializer_2 () Bool (= (table0 #x02) s3))
+[GOOD] (define-fun table0_initializer_3 () Bool (= (table0 #x03) s4))
+[GOOD] (define-fun table0_initializer_4 () Bool (= (table0 #x04) s5))
+[GOOD] (define-fun table0_initializer_5 () Bool (= (table0 #x05) s6))
+[GOOD] (define-fun table0_initializer_6 () Bool (= (table0 #x06) s7))
+[GOOD] (define-fun table0_initializer_7 () Bool (= (table0 #x07) s8))
+[GOOD] (define-fun table0_initializer_8 () Bool (= (table0 #x08) s9))
+[GOOD] (define-fun table0_initializer_9 () Bool (= (table0 #x09) s10))
+[GOOD] (define-fun table0_initializer_10 () Bool (= (table0 #x0a) s11))
+[GOOD] (define-fun table0_initializer_11 () Bool (= (table0 #x0b) s12))
+[GOOD] (define-fun table0_initializer_12 () Bool (= (table0 #x0c) s13))
+[GOOD] (define-fun table0_initializer_13 () Bool (= (table0 #x0d) s14))
+[GOOD] (define-fun table0_initializer_14 () Bool (= (table0 #x0e) s15))
+[GOOD] (define-fun table0_initializer_15 () Bool (= (table0 #x0f) s16))
+[GOOD] (define-fun table0_initializer_16 () Bool (= (table0 #x10) s17))
+[GOOD] (define-fun table0_initializer_17 () Bool (= (table0 #x11) s18))
+[GOOD] (define-fun table0_initializer_18 () Bool (= (table0 #x12) s19))
+[GOOD] (define-fun table0_initializer_19 () Bool (= (table0 #x13) s20))
+[GOOD] (define-fun table0_initializer_20 () Bool (= (table0 #x14) s21))
+[GOOD] (define-fun table0_initializer_21 () Bool (= (table0 #x15) s22))
+[GOOD] (define-fun table0_initializer_22 () Bool (= (table0 #x16) s23))
+[GOOD] (define-fun table0_initializer_23 () Bool (= (table0 #x17) s24))
+[GOOD] (define-fun table0_initializer_24 () Bool (= (table0 #x18) s25))
+[GOOD] (define-fun table0_initializer_25 () Bool (= (table0 #x19) s26))
+[GOOD] (define-fun table0_initializer_26 () Bool (= (table0 #x1a) s27))
+[GOOD] (define-fun table0_initializer_27 () Bool (= (table0 #x1b) s28))
+[GOOD] (define-fun table0_initializer_28 () Bool (= (table0 #x1c) s29))
+[GOOD] (define-fun table0_initializer_29 () Bool (= (table0 #x1d) s30))
+[GOOD] (define-fun table0_initializer_30 () Bool (= (table0 #x1e) s31))
+[GOOD] (define-fun table0_initializer_31 () Bool (= (table0 #x1f) s32))
+[GOOD] (define-fun table0_initializer_32 () Bool (= (table0 #x20) s33))
+[GOOD] (define-fun table0_initializer_33 () Bool (= (table0 #x21) s34))
+[GOOD] (define-fun table0_initializer_34 () Bool (= (table0 #x22) s35))
+[GOOD] (define-fun table0_initializer_35 () Bool (= (table0 #x23) s36))
+[GOOD] (define-fun table0_initializer_36 () Bool (= (table0 #x24) s37))
+[GOOD] (define-fun table0_initializer_37 () Bool (= (table0 #x25) s38))
+[GOOD] (define-fun table0_initializer_38 () Bool (= (table0 #x26) s39))
+[GOOD] (define-fun table0_initializer_39 () Bool (= (table0 #x27) s40))
+[GOOD] (define-fun table0_initializer_40 () Bool (= (table0 #x28) s41))
+[GOOD] (define-fun table0_initializer_41 () Bool (= (table0 #x29) s42))
+[GOOD] (define-fun table0_initializer_42 () Bool (= (table0 #x2a) s43))
+[GOOD] (define-fun table0_initializer_43 () Bool (= (table0 #x2b) s44))
+[GOOD] (define-fun table0_initializer_44 () Bool (= (table0 #x2c) s45))
+[GOOD] (define-fun table0_initializer_45 () Bool (= (table0 #x2d) s46))
+[GOOD] (define-fun table0_initializer_46 () Bool (= (table0 #x2e) s47))
+[GOOD] (define-fun table0_initializer_47 () Bool (= (table0 #x2f) s48))
+[GOOD] (define-fun table0_initializer_48 () Bool (= (table0 #x30) s49))
+[GOOD] (define-fun table0_initializer_49 () Bool (= (table0 #x31) s50))
+[GOOD] (define-fun table0_initializer_50 () Bool (= (table0 #x32) s51))
+[GOOD] (define-fun table0_initializer_51 () Bool (= (table0 #x33) s52))
+[GOOD] (define-fun table0_initializer_52 () Bool (= (table0 #x34) s53))
+[GOOD] (define-fun table0_initializer_53 () Bool (= (table0 #x35) s54))
+[GOOD] (define-fun table0_initializer_54 () Bool (= (table0 #x36) s55))
+[GOOD] (define-fun table0_initializer_55 () Bool (= (table0 #x37) s56))
+[GOOD] (define-fun table0_initializer_56 () Bool (= (table0 #x38) s57))
+[GOOD] (define-fun table0_initializer_57 () Bool (= (table0 #x39) s58))
+[GOOD] (define-fun table0_initializer_58 () Bool (= (table0 #x3a) s59))
+[GOOD] (define-fun table0_initializer_59 () Bool (= (table0 #x3b) s60))
+[GOOD] (define-fun table0_initializer_60 () Bool (= (table0 #x3c) s61))
+[GOOD] (define-fun table0_initializer_61 () Bool (= (table0 #x3d) s62))
+[GOOD] (define-fun table0_initializer_62 () Bool (= (table0 #x3e) s63))
+[GOOD] (define-fun table0_initializer_63 () Bool (= (table0 #x3f) s64))
+[GOOD] (define-fun table0_initializer_64 () Bool (= (table0 #x40) s65))
+[GOOD] (define-fun table0_initializer_65 () Bool (= (table0 #x41) s66))
+[GOOD] (define-fun table0_initializer_66 () Bool (= (table0 #x42) s67))
+[GOOD] (define-fun table0_initializer_67 () Bool (= (table0 #x43) s68))
+[GOOD] (define-fun table0_initializer_68 () Bool (= (table0 #x44) s69))
+[GOOD] (define-fun table0_initializer_69 () Bool (= (table0 #x45) s70))
+[GOOD] (define-fun table0_initializer_70 () Bool (= (table0 #x46) s71))
+[GOOD] (define-fun table0_initializer_71 () Bool (= (table0 #x47) s72))
+[GOOD] (define-fun table0_initializer_72 () Bool (= (table0 #x48) s73))
+[GOOD] (define-fun table0_initializer_73 () Bool (= (table0 #x49) s74))
+[GOOD] (define-fun table0_initializer_74 () Bool (= (table0 #x4a) s75))
+[GOOD] (define-fun table0_initializer_75 () Bool (= (table0 #x4b) s76))
+[GOOD] (define-fun table0_initializer_76 () Bool (= (table0 #x4c) s77))
+[GOOD] (define-fun table0_initializer_77 () Bool (= (table0 #x4d) s78))
+[GOOD] (define-fun table0_initializer_78 () Bool (= (table0 #x4e) s79))
+[GOOD] (define-fun table0_initializer_79 () Bool (= (table0 #x4f) s80))
+[GOOD] (define-fun table0_initializer_80 () Bool (= (table0 #x50) s81))
+[GOOD] (define-fun table0_initializer_81 () Bool (= (table0 #x51) s82))
+[GOOD] (define-fun table0_initializer_82 () Bool (= (table0 #x52) s83))
+[GOOD] (define-fun table0_initializer_83 () Bool (= (table0 #x53) s84))
+[GOOD] (define-fun table0_initializer_84 () Bool (= (table0 #x54) s85))
+[GOOD] (define-fun table0_initializer_85 () Bool (= (table0 #x55) s86))
+[GOOD] (define-fun table0_initializer_86 () Bool (= (table0 #x56) s87))
+[GOOD] (define-fun table0_initializer_87 () Bool (= (table0 #x57) s88))
+[GOOD] (define-fun table0_initializer_88 () Bool (= (table0 #x58) s89))
+[GOOD] (define-fun table0_initializer_89 () Bool (= (table0 #x59) s90))
+[GOOD] (define-fun table0_initializer_90 () Bool (= (table0 #x5a) s91))
+[GOOD] (define-fun table0_initializer_91 () Bool (= (table0 #x5b) s92))
+[GOOD] (define-fun table0_initializer_92 () Bool (= (table0 #x5c) s93))
+[GOOD] (define-fun table0_initializer_93 () Bool (= (table0 #x5d) s94))
+[GOOD] (define-fun table0_initializer_94 () Bool (= (table0 #x5e) s95))
+[GOOD] (define-fun table0_initializer_95 () Bool (= (table0 #x5f) s96))
+[GOOD] (define-fun table0_initializer_96 () Bool (= (table0 #x60) s97))
+[GOOD] (define-fun table0_initializer_97 () Bool (= (table0 #x61) s98))
+[GOOD] (define-fun table0_initializer_98 () Bool (= (table0 #x62) s99))
+[GOOD] (define-fun table0_initializer_99 () Bool (= (table0 #x63) s100))
+[GOOD] (define-fun table0_initializer_100 () Bool (= (table0 #x64) s101))
+[GOOD] (define-fun table0_initializer_101 () Bool (= (table0 #x65) s102))
+[GOOD] (define-fun table0_initializer_102 () Bool (= (table0 #x66) s103))
+[GOOD] (define-fun table0_initializer_103 () Bool (= (table0 #x67) s104))
+[GOOD] (define-fun table0_initializer_104 () Bool (= (table0 #x68) s105))
+[GOOD] (define-fun table0_initializer_105 () Bool (= (table0 #x69) s106))
+[GOOD] (define-fun table0_initializer_106 () Bool (= (table0 #x6a) s107))
+[GOOD] (define-fun table0_initializer_107 () Bool (= (table0 #x6b) s108))
+[GOOD] (define-fun table0_initializer_108 () Bool (= (table0 #x6c) s109))
+[GOOD] (define-fun table0_initializer_109 () Bool (= (table0 #x6d) s110))
+[GOOD] (define-fun table0_initializer_110 () Bool (= (table0 #x6e) s111))
+[GOOD] (define-fun table0_initializer_111 () Bool (= (table0 #x6f) s112))
+[GOOD] (define-fun table0_initializer_112 () Bool (= (table0 #x70) s113))
+[GOOD] (define-fun table0_initializer_113 () Bool (= (table0 #x71) s114))
+[GOOD] (define-fun table0_initializer_114 () Bool (= (table0 #x72) s115))
+[GOOD] (define-fun table0_initializer_115 () Bool (= (table0 #x73) s116))
+[GOOD] (define-fun table0_initializer_116 () Bool (= (table0 #x74) s117))
+[GOOD] (define-fun table0_initializer_117 () Bool (= (table0 #x75) s118))
+[GOOD] (define-fun table0_initializer_118 () Bool (= (table0 #x76) s119))
+[GOOD] (define-fun table0_initializer_119 () Bool (= (table0 #x77) s120))
+[GOOD] (define-fun table0_initializer_120 () Bool (= (table0 #x78) s121))
+[GOOD] (define-fun table0_initializer_121 () Bool (= (table0 #x79) s122))
+[GOOD] (define-fun table0_initializer_122 () Bool (= (table0 #x7a) s123))
+[GOOD] (define-fun table0_initializer_123 () Bool (= (table0 #x7b) s124))
+[GOOD] (define-fun table0_initializer_124 () Bool (= (table0 #x7c) s125))
+[GOOD] (define-fun table0_initializer_125 () Bool (= (table0 #x7d) s126))
+[GOOD] (define-fun table0_initializer_126 () Bool (= (table0 #x7e) s127))
+[GOOD] (define-fun table0_initializer_127 () Bool (= (table0 #x7f) s128))
+[GOOD] (define-fun table0_initializer_128 () Bool (= (table0 #x80) s129))
+[GOOD] (define-fun table0_initializer_129 () Bool (= (table0 #x81) s130))
+[GOOD] (define-fun table0_initializer_130 () Bool (= (table0 #x82) s131))
+[GOOD] (define-fun table0_initializer_131 () Bool (= (table0 #x83) s132))
+[GOOD] (define-fun table0_initializer_132 () Bool (= (table0 #x84) s133))
+[GOOD] (define-fun table0_initializer_133 () Bool (= (table0 #x85) s134))
+[GOOD] (define-fun table0_initializer_134 () Bool (= (table0 #x86) s135))
+[GOOD] (define-fun table0_initializer_135 () Bool (= (table0 #x87) s136))
+[GOOD] (define-fun table0_initializer_136 () Bool (= (table0 #x88) s137))
+[GOOD] (define-fun table0_initializer_137 () Bool (= (table0 #x89) s138))
+[GOOD] (define-fun table0_initializer_138 () Bool (= (table0 #x8a) s139))
+[GOOD] (define-fun table0_initializer_139 () Bool (= (table0 #x8b) s140))
+[GOOD] (define-fun table0_initializer_140 () Bool (= (table0 #x8c) s141))
+[GOOD] (define-fun table0_initializer_141 () Bool (= (table0 #x8d) s142))
+[GOOD] (define-fun table0_initializer_142 () Bool (= (table0 #x8e) s143))
+[GOOD] (define-fun table0_initializer_143 () Bool (= (table0 #x8f) s144))
+[GOOD] (define-fun table0_initializer_144 () Bool (= (table0 #x90) s145))
+[GOOD] (define-fun table0_initializer_145 () Bool (= (table0 #x91) s146))
+[GOOD] (define-fun table0_initializer_146 () Bool (= (table0 #x92) s147))
+[GOOD] (define-fun table0_initializer_147 () Bool (= (table0 #x93) s148))
+[GOOD] (define-fun table0_initializer_148 () Bool (= (table0 #x94) s149))
+[GOOD] (define-fun table0_initializer_149 () Bool (= (table0 #x95) s150))
+[GOOD] (define-fun table0_initializer_150 () Bool (= (table0 #x96) s151))
+[GOOD] (define-fun table0_initializer_151 () Bool (= (table0 #x97) s152))
+[GOOD] (define-fun table0_initializer_152 () Bool (= (table0 #x98) s153))
+[GOOD] (define-fun table0_initializer_153 () Bool (= (table0 #x99) s154))
+[GOOD] (define-fun table0_initializer_154 () Bool (= (table0 #x9a) s155))
+[GOOD] (define-fun table0_initializer_155 () Bool (= (table0 #x9b) s156))
+[GOOD] (define-fun table0_initializer_156 () Bool (= (table0 #x9c) s157))
+[GOOD] (define-fun table0_initializer_157 () Bool (= (table0 #x9d) s158))
+[GOOD] (define-fun table0_initializer_158 () Bool (= (table0 #x9e) s159))
+[GOOD] (define-fun table0_initializer_159 () Bool (= (table0 #x9f) s160))
+[GOOD] (define-fun table0_initializer_160 () Bool (= (table0 #xa0) s161))
+[GOOD] (define-fun table0_initializer_161 () Bool (= (table0 #xa1) s162))
+[GOOD] (define-fun table0_initializer_162 () Bool (= (table0 #xa2) s163))
+[GOOD] (define-fun table0_initializer_163 () Bool (= (table0 #xa3) s164))
+[GOOD] (define-fun table0_initializer_164 () Bool (= (table0 #xa4) s165))
+[GOOD] (define-fun table0_initializer_165 () Bool (= (table0 #xa5) s166))
+[GOOD] (define-fun table0_initializer_166 () Bool (= (table0 #xa6) s167))
+[GOOD] (define-fun table0_initializer_167 () Bool (= (table0 #xa7) s168))
+[GOOD] (define-fun table0_initializer_168 () Bool (= (table0 #xa8) s169))
+[GOOD] (define-fun table0_initializer_169 () Bool (= (table0 #xa9) s170))
+[GOOD] (define-fun table0_initializer_170 () Bool (= (table0 #xaa) s171))
+[GOOD] (define-fun table0_initializer_171 () Bool (= (table0 #xab) s172))
+[GOOD] (define-fun table0_initializer_172 () Bool (= (table0 #xac) s173))
+[GOOD] (define-fun table0_initializer_173 () Bool (= (table0 #xad) s174))
+[GOOD] (define-fun table0_initializer_174 () Bool (= (table0 #xae) s175))
+[GOOD] (define-fun table0_initializer_175 () Bool (= (table0 #xaf) s176))
+[GOOD] (define-fun table0_initializer_176 () Bool (= (table0 #xb0) s177))
+[GOOD] (define-fun table0_initializer_177 () Bool (= (table0 #xb1) s178))
+[GOOD] (define-fun table0_initializer_178 () Bool (= (table0 #xb2) s179))
+[GOOD] (define-fun table0_initializer_179 () Bool (= (table0 #xb3) s180))
+[GOOD] (define-fun table0_initializer_180 () Bool (= (table0 #xb4) s181))
+[GOOD] (define-fun table0_initializer_181 () Bool (= (table0 #xb5) s182))
+[GOOD] (define-fun table0_initializer_182 () Bool (= (table0 #xb6) s183))
+[GOOD] (define-fun table0_initializer_183 () Bool (= (table0 #xb7) s184))
+[GOOD] (define-fun table0_initializer_184 () Bool (= (table0 #xb8) s185))
+[GOOD] (define-fun table0_initializer_185 () Bool (= (table0 #xb9) s186))
+[GOOD] (define-fun table0_initializer_186 () Bool (= (table0 #xba) s187))
+[GOOD] (define-fun table0_initializer_187 () Bool (= (table0 #xbb) s188))
+[GOOD] (define-fun table0_initializer_188 () Bool (= (table0 #xbc) s189))
+[GOOD] (define-fun table0_initializer_189 () Bool (= (table0 #xbd) s190))
+[GOOD] (define-fun table0_initializer_190 () Bool (= (table0 #xbe) s191))
+[GOOD] (define-fun table0_initializer_191 () Bool (= (table0 #xbf) s192))
+[GOOD] (define-fun table0_initializer_192 () Bool (= (table0 #xc0) s193))
+[GOOD] (define-fun table0_initializer_193 () Bool (= (table0 #xc1) s194))
+[GOOD] (define-fun table0_initializer_194 () Bool (= (table0 #xc2) s195))
+[GOOD] (define-fun table0_initializer_195 () Bool (= (table0 #xc3) s196))
+[GOOD] (define-fun table0_initializer_196 () Bool (= (table0 #xc4) s197))
+[GOOD] (define-fun table0_initializer_197 () Bool (= (table0 #xc5) s198))
+[GOOD] (define-fun table0_initializer_198 () Bool (= (table0 #xc6) s199))
+[GOOD] (define-fun table0_initializer_199 () Bool (= (table0 #xc7) s200))
+[GOOD] (define-fun table0_initializer_200 () Bool (= (table0 #xc8) s201))
+[GOOD] (define-fun table0_initializer_201 () Bool (= (table0 #xc9) s202))
+[GOOD] (define-fun table0_initializer_202 () Bool (= (table0 #xca) s203))
+[GOOD] (define-fun table0_initializer_203 () Bool (= (table0 #xcb) s204))
+[GOOD] (define-fun table0_initializer_204 () Bool (= (table0 #xcc) s205))
+[GOOD] (define-fun table0_initializer_205 () Bool (= (table0 #xcd) s206))
+[GOOD] (define-fun table0_initializer_206 () Bool (= (table0 #xce) s207))
+[GOOD] (define-fun table0_initializer_207 () Bool (= (table0 #xcf) s208))
+[GOOD] (define-fun table0_initializer_208 () Bool (= (table0 #xd0) s209))
+[GOOD] (define-fun table0_initializer_209 () Bool (= (table0 #xd1) s210))
+[GOOD] (define-fun table0_initializer_210 () Bool (= (table0 #xd2) s211))
+[GOOD] (define-fun table0_initializer_211 () Bool (= (table0 #xd3) s212))
+[GOOD] (define-fun table0_initializer_212 () Bool (= (table0 #xd4) s213))
+[GOOD] (define-fun table0_initializer_213 () Bool (= (table0 #xd5) s214))
+[GOOD] (define-fun table0_initializer_214 () Bool (= (table0 #xd6) s215))
+[GOOD] (define-fun table0_initializer_215 () Bool (= (table0 #xd7) s216))
+[GOOD] (define-fun table0_initializer_216 () Bool (= (table0 #xd8) s217))
+[GOOD] (define-fun table0_initializer_217 () Bool (= (table0 #xd9) s218))
+[GOOD] (define-fun table0_initializer_218 () Bool (= (table0 #xda) s219))
+[GOOD] (define-fun table0_initializer_219 () Bool (= (table0 #xdb) s220))
+[GOOD] (define-fun table0_initializer_220 () Bool (= (table0 #xdc) s221))
+[GOOD] (define-fun table0_initializer_221 () Bool (= (table0 #xdd) s222))
+[GOOD] (define-fun table0_initializer_222 () Bool (= (table0 #xde) s223))
+[GOOD] (define-fun table0_initializer_223 () Bool (= (table0 #xdf) s224))
+[GOOD] (define-fun table0_initializer_224 () Bool (= (table0 #xe0) s225))
+[GOOD] (define-fun table0_initializer_225 () Bool (= (table0 #xe1) s226))
+[GOOD] (define-fun table0_initializer_226 () Bool (= (table0 #xe2) s227))
+[GOOD] (define-fun table0_initializer_227 () Bool (= (table0 #xe3) s228))
+[GOOD] (define-fun table0_initializer_228 () Bool (= (table0 #xe4) s229))
+[GOOD] (define-fun table0_initializer_229 () Bool (= (table0 #xe5) s230))
+[GOOD] (define-fun table0_initializer_230 () Bool (= (table0 #xe6) s231))
+[GOOD] (define-fun table0_initializer_231 () Bool (= (table0 #xe7) s232))
+[GOOD] (define-fun table0_initializer_232 () Bool (= (table0 #xe8) s233))
+[GOOD] (define-fun table0_initializer_233 () Bool (= (table0 #xe9) s234))
+[GOOD] (define-fun table0_initializer_234 () Bool (= (table0 #xea) s235))
+[GOOD] (define-fun table0_initializer_235 () Bool (= (table0 #xeb) s236))
+[GOOD] (define-fun table0_initializer_236 () Bool (= (table0 #xec) s237))
+[GOOD] (define-fun table0_initializer_237 () Bool (= (table0 #xed) s238))
+[GOOD] (define-fun table0_initializer_238 () Bool (= (table0 #xee) s239))
+[GOOD] (define-fun table0_initializer_239 () Bool (= (table0 #xef) s240))
+[GOOD] (define-fun table0_initializer_240 () Bool (= (table0 #xf0) s241))
+[GOOD] (define-fun table0_initializer_241 () Bool (= (table0 #xf1) s242))
+[GOOD] (define-fun table0_initializer_242 () Bool (= (table0 #xf2) s243))
+[GOOD] (define-fun table0_initializer_243 () Bool (= (table0 #xf3) s244))
+[GOOD] (define-fun table0_initializer_244 () Bool (= (table0 #xf4) s245))
+[GOOD] (define-fun table0_initializer_245 () Bool (= (table0 #xf5) s246))
+[GOOD] (define-fun table0_initializer_246 () Bool (= (table0 #xf6) s247))
+[GOOD] (define-fun table0_initializer_247 () Bool (= (table0 #xf7) s248))
+[GOOD] (define-fun table0_initializer_248 () Bool (= (table0 #xf8) s249))
+[GOOD] (define-fun table0_initializer_249 () Bool (= (table0 #xf9) s250))
+[GOOD] (define-fun table0_initializer_250 () Bool (= (table0 #xfa) s251))
+[GOOD] (define-fun table0_initializer_251 () Bool (= (table0 #xfb) s252))
+[GOOD] (define-fun table0_initializer_252 () Bool (= (table0 #xfc) s253))
+[GOOD] (define-fun table0_initializer_253 () Bool (= (table0 #xfd) s254))
+[GOOD] (define-fun table0_initializer_254 () Bool (= (table0 #xfe) s255))
+[GOOD] (define-fun table0_initializer_255 () Bool (= (table0 #xff) s256))
+[GOOD] (define-fun table0_initializer () Bool (and table0_initializer_0 table0_initializer_1 table0_initializer_2 table0_initializer_3 table0_initializer_4 table0_initializer_5 table0_initializer_6 table0_initializer_7 table0_initializer_8 table0_initializer_9 table0_initializer_10 table0_initializer_11 table0_initializer_12 table0_initializer_13 table0_initializer_14 table0_initializer_15 table0_initializer_16 table0_initializer_17 table0_initializer_18 table0_initializer_19 table0_initializer_20 table0_initializer_21 table0_initializer_22 table0_initializer_23 table0_initializer_24 table0_initializer_25 table0_initializer_26 table0_initializer_27 table0_initializer_28 table0_initializer_29 table0_initializer_30 table0_initializer_31 table0_initializer_32 table0_initializer_33 table0_initializer_34 table0_initializer_35 table0_initializer_36 table0_initializer_37 table0_initializer_38 table0_initializer_39 table0_initializer_40 table0_initializer_41 table0_initializer_42 table0_initializer_43 table0_initializer_44 table0_initializer_45 table0_initializer_46 table0_initializer_47 table0_initializer_48 table0_initializer_49 table0_initializer_50 table0_initializer_51 table0_initializer_52 table0_initializer_53 table0_initializer_54 table0_initializer_55 table0_initializer_56 table0_initializer_57 table0_initializer_58 table0_initializer_59 table0_initializer_60 table0_initializer_61 table0_initializer_62 table0_initializer_63 table0_initializer_64 table0_initializer_65 table0_initializer_66 table0_initializer_67 table0_initializer_68 table0_initializer_69 table0_initializer_70 table0_initializer_71 table0_initializer_72 table0_initializer_73 table0_initializer_74 table0_initializer_75 table0_initializer_76 table0_initializer_77 table0_initializer_78 table0_initializer_79 table0_initializer_80 table0_initializer_81 table0_initializer_82 table0_initializer_83 table0_initializer_84 table0_initializer_85 table0_initializer_86 table0_initializer_87 table0_initializer_88 table0_initializer_89 table0_initializer_90 table0_initializer_91 table0_initializer_92 table0_initializer_93 table0_initializer_94 table0_initializer_95 table0_initializer_96 table0_initializer_97 table0_initializer_98 table0_initializer_99 table0_initializer_100 table0_initializer_101 table0_initializer_102 table0_initializer_103 table0_initializer_104 table0_initializer_105 table0_initializer_106 table0_initializer_107 table0_initializer_108 table0_initializer_109 table0_initializer_110 table0_initializer_111 table0_initializer_112 table0_initializer_113 table0_initializer_114 table0_initializer_115 table0_initializer_116 table0_initializer_117 table0_initializer_118 table0_initializer_119 table0_initializer_120 table0_initializer_121 table0_initializer_122 table0_initializer_123 table0_initializer_124 table0_initializer_125 table0_initializer_126 table0_initializer_127 table0_initializer_128 table0_initializer_129 table0_initializer_130 table0_initializer_131 table0_initializer_132 table0_initializer_133 table0_initializer_134 table0_initializer_135 table0_initializer_136 table0_initializer_137 table0_initializer_138 table0_initializer_139 table0_initializer_140 table0_initializer_141 table0_initializer_142 table0_initializer_143 table0_initializer_144 table0_initializer_145 table0_initializer_146 table0_initializer_147 table0_initializer_148 table0_initializer_149 table0_initializer_150 table0_initializer_151 table0_initializer_152 table0_initializer_153 table0_initializer_154 table0_initializer_155 table0_initializer_156 table0_initializer_157 table0_initializer_158 table0_initializer_159 table0_initializer_160 table0_initializer_161 table0_initializer_162 table0_initializer_163 table0_initializer_164 table0_initializer_165 table0_initializer_166 table0_initializer_167 table0_initializer_168 table0_initializer_169 table0_initializer_170 table0_initializer_171 table0_initializer_172 table0_initializer_173 table0_initializer_174 table0_initializer_175 table0_initializer_176 table0_initializer_177 table0_initializer_178 table0_initializer_179 table0_initializer_180 table0_initializer_181 table0_initializer_182 table0_initializer_183 table0_initializer_184 table0_initializer_185 table0_initializer_186 table0_initializer_187 table0_initializer_188 table0_initializer_189 table0_initializer_190 table0_initializer_191 table0_initializer_192 table0_initializer_193 table0_initializer_194 table0_initializer_195 table0_initializer_196 table0_initializer_197 table0_initializer_198 table0_initializer_199 table0_initializer_200 table0_initializer_201 table0_initializer_202 table0_initializer_203 table0_initializer_204 table0_initializer_205 table0_initializer_206 table0_initializer_207 table0_initializer_208 table0_initializer_209 table0_initializer_210 table0_initializer_211 table0_initializer_212 table0_initializer_213 table0_initializer_214 table0_initializer_215 table0_initializer_216 table0_initializer_217 table0_initializer_218 table0_initializer_219 table0_initializer_220 table0_initializer_221 table0_initializer_222 table0_initializer_223 table0_initializer_224 table0_initializer_225 table0_initializer_226 table0_initializer_227 table0_initializer_228 table0_initializer_229 table0_initializer_230 table0_initializer_231 table0_initializer_232 table0_initializer_233 table0_initializer_234 table0_initializer_235 table0_initializer_236 table0_initializer_237 table0_initializer_238 table0_initializer_239 table0_initializer_240 table0_initializer_241 table0_initializer_242 table0_initializer_243 table0_initializer_244 table0_initializer_245 table0_initializer_246 table0_initializer_247 table0_initializer_248 table0_initializer_249 table0_initializer_250 table0_initializer_251 table0_initializer_252 table0_initializer_253 table0_initializer_254 table0_initializer_255))
+[GOOD] (assert table0_initializer)
+[GOOD] (assert s258)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:0
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays3.gold b/SBVTestSuite/GoldFiles/queryArrays3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays3.gold
@@ -0,0 +1,292 @@
+** 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_UFBV) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () (_ BitVec 8) #x00)
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] (define-fun s2 () (_ BitVec 8) (table0 s0))
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun table0_initializer_0 () Bool (= (table0 #x00) s0))
+[GOOD] (define-fun table0_initializer_1 () Bool (= (table0 #x01) s0))
+[GOOD] (define-fun table0_initializer_2 () Bool (= (table0 #x02) s0))
+[GOOD] (define-fun table0_initializer_3 () Bool (= (table0 #x03) s0))
+[GOOD] (define-fun table0_initializer_4 () Bool (= (table0 #x04) s0))
+[GOOD] (define-fun table0_initializer_5 () Bool (= (table0 #x05) s0))
+[GOOD] (define-fun table0_initializer_6 () Bool (= (table0 #x06) s0))
+[GOOD] (define-fun table0_initializer_7 () Bool (= (table0 #x07) s0))
+[GOOD] (define-fun table0_initializer_8 () Bool (= (table0 #x08) s0))
+[GOOD] (define-fun table0_initializer_9 () Bool (= (table0 #x09) s0))
+[GOOD] (define-fun table0_initializer_10 () Bool (= (table0 #x0a) s0))
+[GOOD] (define-fun table0_initializer_11 () Bool (= (table0 #x0b) s0))
+[GOOD] (define-fun table0_initializer_12 () Bool (= (table0 #x0c) s0))
+[GOOD] (define-fun table0_initializer_13 () Bool (= (table0 #x0d) s0))
+[GOOD] (define-fun table0_initializer_14 () Bool (= (table0 #x0e) s0))
+[GOOD] (define-fun table0_initializer_15 () Bool (= (table0 #x0f) s0))
+[GOOD] (define-fun table0_initializer_16 () Bool (= (table0 #x10) s0))
+[GOOD] (define-fun table0_initializer_17 () Bool (= (table0 #x11) s0))
+[GOOD] (define-fun table0_initializer_18 () Bool (= (table0 #x12) s0))
+[GOOD] (define-fun table0_initializer_19 () Bool (= (table0 #x13) s0))
+[GOOD] (define-fun table0_initializer_20 () Bool (= (table0 #x14) s0))
+[GOOD] (define-fun table0_initializer_21 () Bool (= (table0 #x15) s0))
+[GOOD] (define-fun table0_initializer_22 () Bool (= (table0 #x16) s0))
+[GOOD] (define-fun table0_initializer_23 () Bool (= (table0 #x17) s0))
+[GOOD] (define-fun table0_initializer_24 () Bool (= (table0 #x18) s0))
+[GOOD] (define-fun table0_initializer_25 () Bool (= (table0 #x19) s0))
+[GOOD] (define-fun table0_initializer_26 () Bool (= (table0 #x1a) s0))
+[GOOD] (define-fun table0_initializer_27 () Bool (= (table0 #x1b) s0))
+[GOOD] (define-fun table0_initializer_28 () Bool (= (table0 #x1c) s0))
+[GOOD] (define-fun table0_initializer_29 () Bool (= (table0 #x1d) s0))
+[GOOD] (define-fun table0_initializer_30 () Bool (= (table0 #x1e) s0))
+[GOOD] (define-fun table0_initializer_31 () Bool (= (table0 #x1f) s0))
+[GOOD] (define-fun table0_initializer_32 () Bool (= (table0 #x20) s0))
+[GOOD] (define-fun table0_initializer_33 () Bool (= (table0 #x21) s0))
+[GOOD] (define-fun table0_initializer_34 () Bool (= (table0 #x22) s0))
+[GOOD] (define-fun table0_initializer_35 () Bool (= (table0 #x23) s0))
+[GOOD] (define-fun table0_initializer_36 () Bool (= (table0 #x24) s0))
+[GOOD] (define-fun table0_initializer_37 () Bool (= (table0 #x25) s0))
+[GOOD] (define-fun table0_initializer_38 () Bool (= (table0 #x26) s0))
+[GOOD] (define-fun table0_initializer_39 () Bool (= (table0 #x27) s0))
+[GOOD] (define-fun table0_initializer_40 () Bool (= (table0 #x28) s0))
+[GOOD] (define-fun table0_initializer_41 () Bool (= (table0 #x29) s0))
+[GOOD] (define-fun table0_initializer_42 () Bool (= (table0 #x2a) s0))
+[GOOD] (define-fun table0_initializer_43 () Bool (= (table0 #x2b) s0))
+[GOOD] (define-fun table0_initializer_44 () Bool (= (table0 #x2c) s0))
+[GOOD] (define-fun table0_initializer_45 () Bool (= (table0 #x2d) s0))
+[GOOD] (define-fun table0_initializer_46 () Bool (= (table0 #x2e) s0))
+[GOOD] (define-fun table0_initializer_47 () Bool (= (table0 #x2f) s0))
+[GOOD] (define-fun table0_initializer_48 () Bool (= (table0 #x30) s0))
+[GOOD] (define-fun table0_initializer_49 () Bool (= (table0 #x31) s0))
+[GOOD] (define-fun table0_initializer_50 () Bool (= (table0 #x32) s0))
+[GOOD] (define-fun table0_initializer_51 () Bool (= (table0 #x33) s0))
+[GOOD] (define-fun table0_initializer_52 () Bool (= (table0 #x34) s0))
+[GOOD] (define-fun table0_initializer_53 () Bool (= (table0 #x35) s0))
+[GOOD] (define-fun table0_initializer_54 () Bool (= (table0 #x36) s0))
+[GOOD] (define-fun table0_initializer_55 () Bool (= (table0 #x37) s0))
+[GOOD] (define-fun table0_initializer_56 () Bool (= (table0 #x38) s0))
+[GOOD] (define-fun table0_initializer_57 () Bool (= (table0 #x39) s0))
+[GOOD] (define-fun table0_initializer_58 () Bool (= (table0 #x3a) s0))
+[GOOD] (define-fun table0_initializer_59 () Bool (= (table0 #x3b) s0))
+[GOOD] (define-fun table0_initializer_60 () Bool (= (table0 #x3c) s0))
+[GOOD] (define-fun table0_initializer_61 () Bool (= (table0 #x3d) s0))
+[GOOD] (define-fun table0_initializer_62 () Bool (= (table0 #x3e) s0))
+[GOOD] (define-fun table0_initializer_63 () Bool (= (table0 #x3f) s0))
+[GOOD] (define-fun table0_initializer_64 () Bool (= (table0 #x40) s0))
+[GOOD] (define-fun table0_initializer_65 () Bool (= (table0 #x41) s0))
+[GOOD] (define-fun table0_initializer_66 () Bool (= (table0 #x42) s0))
+[GOOD] (define-fun table0_initializer_67 () Bool (= (table0 #x43) s0))
+[GOOD] (define-fun table0_initializer_68 () Bool (= (table0 #x44) s0))
+[GOOD] (define-fun table0_initializer_69 () Bool (= (table0 #x45) s0))
+[GOOD] (define-fun table0_initializer_70 () Bool (= (table0 #x46) s0))
+[GOOD] (define-fun table0_initializer_71 () Bool (= (table0 #x47) s0))
+[GOOD] (define-fun table0_initializer_72 () Bool (= (table0 #x48) s0))
+[GOOD] (define-fun table0_initializer_73 () Bool (= (table0 #x49) s0))
+[GOOD] (define-fun table0_initializer_74 () Bool (= (table0 #x4a) s0))
+[GOOD] (define-fun table0_initializer_75 () Bool (= (table0 #x4b) s0))
+[GOOD] (define-fun table0_initializer_76 () Bool (= (table0 #x4c) s0))
+[GOOD] (define-fun table0_initializer_77 () Bool (= (table0 #x4d) s0))
+[GOOD] (define-fun table0_initializer_78 () Bool (= (table0 #x4e) s0))
+[GOOD] (define-fun table0_initializer_79 () Bool (= (table0 #x4f) s0))
+[GOOD] (define-fun table0_initializer_80 () Bool (= (table0 #x50) s0))
+[GOOD] (define-fun table0_initializer_81 () Bool (= (table0 #x51) s0))
+[GOOD] (define-fun table0_initializer_82 () Bool (= (table0 #x52) s0))
+[GOOD] (define-fun table0_initializer_83 () Bool (= (table0 #x53) s0))
+[GOOD] (define-fun table0_initializer_84 () Bool (= (table0 #x54) s0))
+[GOOD] (define-fun table0_initializer_85 () Bool (= (table0 #x55) s0))
+[GOOD] (define-fun table0_initializer_86 () Bool (= (table0 #x56) s0))
+[GOOD] (define-fun table0_initializer_87 () Bool (= (table0 #x57) s0))
+[GOOD] (define-fun table0_initializer_88 () Bool (= (table0 #x58) s0))
+[GOOD] (define-fun table0_initializer_89 () Bool (= (table0 #x59) s0))
+[GOOD] (define-fun table0_initializer_90 () Bool (= (table0 #x5a) s0))
+[GOOD] (define-fun table0_initializer_91 () Bool (= (table0 #x5b) s0))
+[GOOD] (define-fun table0_initializer_92 () Bool (= (table0 #x5c) s0))
+[GOOD] (define-fun table0_initializer_93 () Bool (= (table0 #x5d) s0))
+[GOOD] (define-fun table0_initializer_94 () Bool (= (table0 #x5e) s0))
+[GOOD] (define-fun table0_initializer_95 () Bool (= (table0 #x5f) s0))
+[GOOD] (define-fun table0_initializer_96 () Bool (= (table0 #x60) s0))
+[GOOD] (define-fun table0_initializer_97 () Bool (= (table0 #x61) s0))
+[GOOD] (define-fun table0_initializer_98 () Bool (= (table0 #x62) s0))
+[GOOD] (define-fun table0_initializer_99 () Bool (= (table0 #x63) s0))
+[GOOD] (define-fun table0_initializer_100 () Bool (= (table0 #x64) s0))
+[GOOD] (define-fun table0_initializer_101 () Bool (= (table0 #x65) s0))
+[GOOD] (define-fun table0_initializer_102 () Bool (= (table0 #x66) s0))
+[GOOD] (define-fun table0_initializer_103 () Bool (= (table0 #x67) s0))
+[GOOD] (define-fun table0_initializer_104 () Bool (= (table0 #x68) s0))
+[GOOD] (define-fun table0_initializer_105 () Bool (= (table0 #x69) s0))
+[GOOD] (define-fun table0_initializer_106 () Bool (= (table0 #x6a) s0))
+[GOOD] (define-fun table0_initializer_107 () Bool (= (table0 #x6b) s0))
+[GOOD] (define-fun table0_initializer_108 () Bool (= (table0 #x6c) s0))
+[GOOD] (define-fun table0_initializer_109 () Bool (= (table0 #x6d) s0))
+[GOOD] (define-fun table0_initializer_110 () Bool (= (table0 #x6e) s0))
+[GOOD] (define-fun table0_initializer_111 () Bool (= (table0 #x6f) s0))
+[GOOD] (define-fun table0_initializer_112 () Bool (= (table0 #x70) s0))
+[GOOD] (define-fun table0_initializer_113 () Bool (= (table0 #x71) s0))
+[GOOD] (define-fun table0_initializer_114 () Bool (= (table0 #x72) s0))
+[GOOD] (define-fun table0_initializer_115 () Bool (= (table0 #x73) s0))
+[GOOD] (define-fun table0_initializer_116 () Bool (= (table0 #x74) s0))
+[GOOD] (define-fun table0_initializer_117 () Bool (= (table0 #x75) s0))
+[GOOD] (define-fun table0_initializer_118 () Bool (= (table0 #x76) s0))
+[GOOD] (define-fun table0_initializer_119 () Bool (= (table0 #x77) s0))
+[GOOD] (define-fun table0_initializer_120 () Bool (= (table0 #x78) s0))
+[GOOD] (define-fun table0_initializer_121 () Bool (= (table0 #x79) s0))
+[GOOD] (define-fun table0_initializer_122 () Bool (= (table0 #x7a) s0))
+[GOOD] (define-fun table0_initializer_123 () Bool (= (table0 #x7b) s0))
+[GOOD] (define-fun table0_initializer_124 () Bool (= (table0 #x7c) s0))
+[GOOD] (define-fun table0_initializer_125 () Bool (= (table0 #x7d) s0))
+[GOOD] (define-fun table0_initializer_126 () Bool (= (table0 #x7e) s0))
+[GOOD] (define-fun table0_initializer_127 () Bool (= (table0 #x7f) s0))
+[GOOD] (define-fun table0_initializer_128 () Bool (= (table0 #x80) s0))
+[GOOD] (define-fun table0_initializer_129 () Bool (= (table0 #x81) s0))
+[GOOD] (define-fun table0_initializer_130 () Bool (= (table0 #x82) s0))
+[GOOD] (define-fun table0_initializer_131 () Bool (= (table0 #x83) s0))
+[GOOD] (define-fun table0_initializer_132 () Bool (= (table0 #x84) s0))
+[GOOD] (define-fun table0_initializer_133 () Bool (= (table0 #x85) s0))
+[GOOD] (define-fun table0_initializer_134 () Bool (= (table0 #x86) s0))
+[GOOD] (define-fun table0_initializer_135 () Bool (= (table0 #x87) s0))
+[GOOD] (define-fun table0_initializer_136 () Bool (= (table0 #x88) s0))
+[GOOD] (define-fun table0_initializer_137 () Bool (= (table0 #x89) s0))
+[GOOD] (define-fun table0_initializer_138 () Bool (= (table0 #x8a) s0))
+[GOOD] (define-fun table0_initializer_139 () Bool (= (table0 #x8b) s0))
+[GOOD] (define-fun table0_initializer_140 () Bool (= (table0 #x8c) s0))
+[GOOD] (define-fun table0_initializer_141 () Bool (= (table0 #x8d) s0))
+[GOOD] (define-fun table0_initializer_142 () Bool (= (table0 #x8e) s0))
+[GOOD] (define-fun table0_initializer_143 () Bool (= (table0 #x8f) s0))
+[GOOD] (define-fun table0_initializer_144 () Bool (= (table0 #x90) s0))
+[GOOD] (define-fun table0_initializer_145 () Bool (= (table0 #x91) s0))
+[GOOD] (define-fun table0_initializer_146 () Bool (= (table0 #x92) s0))
+[GOOD] (define-fun table0_initializer_147 () Bool (= (table0 #x93) s0))
+[GOOD] (define-fun table0_initializer_148 () Bool (= (table0 #x94) s0))
+[GOOD] (define-fun table0_initializer_149 () Bool (= (table0 #x95) s0))
+[GOOD] (define-fun table0_initializer_150 () Bool (= (table0 #x96) s0))
+[GOOD] (define-fun table0_initializer_151 () Bool (= (table0 #x97) s0))
+[GOOD] (define-fun table0_initializer_152 () Bool (= (table0 #x98) s0))
+[GOOD] (define-fun table0_initializer_153 () Bool (= (table0 #x99) s0))
+[GOOD] (define-fun table0_initializer_154 () Bool (= (table0 #x9a) s0))
+[GOOD] (define-fun table0_initializer_155 () Bool (= (table0 #x9b) s0))
+[GOOD] (define-fun table0_initializer_156 () Bool (= (table0 #x9c) s0))
+[GOOD] (define-fun table0_initializer_157 () Bool (= (table0 #x9d) s0))
+[GOOD] (define-fun table0_initializer_158 () Bool (= (table0 #x9e) s0))
+[GOOD] (define-fun table0_initializer_159 () Bool (= (table0 #x9f) s0))
+[GOOD] (define-fun table0_initializer_160 () Bool (= (table0 #xa0) s0))
+[GOOD] (define-fun table0_initializer_161 () Bool (= (table0 #xa1) s0))
+[GOOD] (define-fun table0_initializer_162 () Bool (= (table0 #xa2) s0))
+[GOOD] (define-fun table0_initializer_163 () Bool (= (table0 #xa3) s0))
+[GOOD] (define-fun table0_initializer_164 () Bool (= (table0 #xa4) s0))
+[GOOD] (define-fun table0_initializer_165 () Bool (= (table0 #xa5) s0))
+[GOOD] (define-fun table0_initializer_166 () Bool (= (table0 #xa6) s0))
+[GOOD] (define-fun table0_initializer_167 () Bool (= (table0 #xa7) s0))
+[GOOD] (define-fun table0_initializer_168 () Bool (= (table0 #xa8) s0))
+[GOOD] (define-fun table0_initializer_169 () Bool (= (table0 #xa9) s0))
+[GOOD] (define-fun table0_initializer_170 () Bool (= (table0 #xaa) s0))
+[GOOD] (define-fun table0_initializer_171 () Bool (= (table0 #xab) s0))
+[GOOD] (define-fun table0_initializer_172 () Bool (= (table0 #xac) s0))
+[GOOD] (define-fun table0_initializer_173 () Bool (= (table0 #xad) s0))
+[GOOD] (define-fun table0_initializer_174 () Bool (= (table0 #xae) s0))
+[GOOD] (define-fun table0_initializer_175 () Bool (= (table0 #xaf) s0))
+[GOOD] (define-fun table0_initializer_176 () Bool (= (table0 #xb0) s0))
+[GOOD] (define-fun table0_initializer_177 () Bool (= (table0 #xb1) s0))
+[GOOD] (define-fun table0_initializer_178 () Bool (= (table0 #xb2) s0))
+[GOOD] (define-fun table0_initializer_179 () Bool (= (table0 #xb3) s0))
+[GOOD] (define-fun table0_initializer_180 () Bool (= (table0 #xb4) s0))
+[GOOD] (define-fun table0_initializer_181 () Bool (= (table0 #xb5) s0))
+[GOOD] (define-fun table0_initializer_182 () Bool (= (table0 #xb6) s0))
+[GOOD] (define-fun table0_initializer_183 () Bool (= (table0 #xb7) s0))
+[GOOD] (define-fun table0_initializer_184 () Bool (= (table0 #xb8) s0))
+[GOOD] (define-fun table0_initializer_185 () Bool (= (table0 #xb9) s0))
+[GOOD] (define-fun table0_initializer_186 () Bool (= (table0 #xba) s0))
+[GOOD] (define-fun table0_initializer_187 () Bool (= (table0 #xbb) s0))
+[GOOD] (define-fun table0_initializer_188 () Bool (= (table0 #xbc) s0))
+[GOOD] (define-fun table0_initializer_189 () Bool (= (table0 #xbd) s0))
+[GOOD] (define-fun table0_initializer_190 () Bool (= (table0 #xbe) s0))
+[GOOD] (define-fun table0_initializer_191 () Bool (= (table0 #xbf) s0))
+[GOOD] (define-fun table0_initializer_192 () Bool (= (table0 #xc0) s0))
+[GOOD] (define-fun table0_initializer_193 () Bool (= (table0 #xc1) s0))
+[GOOD] (define-fun table0_initializer_194 () Bool (= (table0 #xc2) s0))
+[GOOD] (define-fun table0_initializer_195 () Bool (= (table0 #xc3) s0))
+[GOOD] (define-fun table0_initializer_196 () Bool (= (table0 #xc4) s0))
+[GOOD] (define-fun table0_initializer_197 () Bool (= (table0 #xc5) s0))
+[GOOD] (define-fun table0_initializer_198 () Bool (= (table0 #xc6) s0))
+[GOOD] (define-fun table0_initializer_199 () Bool (= (table0 #xc7) s0))
+[GOOD] (define-fun table0_initializer_200 () Bool (= (table0 #xc8) s0))
+[GOOD] (define-fun table0_initializer_201 () Bool (= (table0 #xc9) s0))
+[GOOD] (define-fun table0_initializer_202 () Bool (= (table0 #xca) s0))
+[GOOD] (define-fun table0_initializer_203 () Bool (= (table0 #xcb) s0))
+[GOOD] (define-fun table0_initializer_204 () Bool (= (table0 #xcc) s0))
+[GOOD] (define-fun table0_initializer_205 () Bool (= (table0 #xcd) s0))
+[GOOD] (define-fun table0_initializer_206 () Bool (= (table0 #xce) s0))
+[GOOD] (define-fun table0_initializer_207 () Bool (= (table0 #xcf) s0))
+[GOOD] (define-fun table0_initializer_208 () Bool (= (table0 #xd0) s0))
+[GOOD] (define-fun table0_initializer_209 () Bool (= (table0 #xd1) s0))
+[GOOD] (define-fun table0_initializer_210 () Bool (= (table0 #xd2) s0))
+[GOOD] (define-fun table0_initializer_211 () Bool (= (table0 #xd3) s0))
+[GOOD] (define-fun table0_initializer_212 () Bool (= (table0 #xd4) s0))
+[GOOD] (define-fun table0_initializer_213 () Bool (= (table0 #xd5) s0))
+[GOOD] (define-fun table0_initializer_214 () Bool (= (table0 #xd6) s0))
+[GOOD] (define-fun table0_initializer_215 () Bool (= (table0 #xd7) s0))
+[GOOD] (define-fun table0_initializer_216 () Bool (= (table0 #xd8) s0))
+[GOOD] (define-fun table0_initializer_217 () Bool (= (table0 #xd9) s0))
+[GOOD] (define-fun table0_initializer_218 () Bool (= (table0 #xda) s0))
+[GOOD] (define-fun table0_initializer_219 () Bool (= (table0 #xdb) s0))
+[GOOD] (define-fun table0_initializer_220 () Bool (= (table0 #xdc) s0))
+[GOOD] (define-fun table0_initializer_221 () Bool (= (table0 #xdd) s0))
+[GOOD] (define-fun table0_initializer_222 () Bool (= (table0 #xde) s0))
+[GOOD] (define-fun table0_initializer_223 () Bool (= (table0 #xdf) s0))
+[GOOD] (define-fun table0_initializer_224 () Bool (= (table0 #xe0) s0))
+[GOOD] (define-fun table0_initializer_225 () Bool (= (table0 #xe1) s0))
+[GOOD] (define-fun table0_initializer_226 () Bool (= (table0 #xe2) s0))
+[GOOD] (define-fun table0_initializer_227 () Bool (= (table0 #xe3) s0))
+[GOOD] (define-fun table0_initializer_228 () Bool (= (table0 #xe4) s0))
+[GOOD] (define-fun table0_initializer_229 () Bool (= (table0 #xe5) s0))
+[GOOD] (define-fun table0_initializer_230 () Bool (= (table0 #xe6) s0))
+[GOOD] (define-fun table0_initializer_231 () Bool (= (table0 #xe7) s0))
+[GOOD] (define-fun table0_initializer_232 () Bool (= (table0 #xe8) s0))
+[GOOD] (define-fun table0_initializer_233 () Bool (= (table0 #xe9) s0))
+[GOOD] (define-fun table0_initializer_234 () Bool (= (table0 #xea) s0))
+[GOOD] (define-fun table0_initializer_235 () Bool (= (table0 #xeb) s0))
+[GOOD] (define-fun table0_initializer_236 () Bool (= (table0 #xec) s0))
+[GOOD] (define-fun table0_initializer_237 () Bool (= (table0 #xed) s0))
+[GOOD] (define-fun table0_initializer_238 () Bool (= (table0 #xee) s0))
+[GOOD] (define-fun table0_initializer_239 () Bool (= (table0 #xef) s0))
+[GOOD] (define-fun table0_initializer_240 () Bool (= (table0 #xf0) s0))
+[GOOD] (define-fun table0_initializer_241 () Bool (= (table0 #xf1) s0))
+[GOOD] (define-fun table0_initializer_242 () Bool (= (table0 #xf2) s0))
+[GOOD] (define-fun table0_initializer_243 () Bool (= (table0 #xf3) s0))
+[GOOD] (define-fun table0_initializer_244 () Bool (= (table0 #xf4) s0))
+[GOOD] (define-fun table0_initializer_245 () Bool (= (table0 #xf5) s0))
+[GOOD] (define-fun table0_initializer_246 () Bool (= (table0 #xf6) s0))
+[GOOD] (define-fun table0_initializer_247 () Bool (= (table0 #xf7) s0))
+[GOOD] (define-fun table0_initializer_248 () Bool (= (table0 #xf8) s0))
+[GOOD] (define-fun table0_initializer_249 () Bool (= (table0 #xf9) s0))
+[GOOD] (define-fun table0_initializer_250 () Bool (= (table0 #xfa) s0))
+[GOOD] (define-fun table0_initializer_251 () Bool (= (table0 #xfb) s0))
+[GOOD] (define-fun table0_initializer_252 () Bool (= (table0 #xfc) s0))
+[GOOD] (define-fun table0_initializer_253 () Bool (= (table0 #xfd) s0))
+[GOOD] (define-fun table0_initializer_254 () Bool (= (table0 #xfe) s0))
+[GOOD] (define-fun table0_initializer_255 () Bool (= (table0 #xff) s0))
+[GOOD] (define-fun table0_initializer () Bool (and table0_initializer_0 table0_initializer_1 table0_initializer_2 table0_initializer_3 table0_initializer_4 table0_initializer_5 table0_initializer_6 table0_initializer_7 table0_initializer_8 table0_initializer_9 table0_initializer_10 table0_initializer_11 table0_initializer_12 table0_initializer_13 table0_initializer_14 table0_initializer_15 table0_initializer_16 table0_initializer_17 table0_initializer_18 table0_initializer_19 table0_initializer_20 table0_initializer_21 table0_initializer_22 table0_initializer_23 table0_initializer_24 table0_initializer_25 table0_initializer_26 table0_initializer_27 table0_initializer_28 table0_initializer_29 table0_initializer_30 table0_initializer_31 table0_initializer_32 table0_initializer_33 table0_initializer_34 table0_initializer_35 table0_initializer_36 table0_initializer_37 table0_initializer_38 table0_initializer_39 table0_initializer_40 table0_initializer_41 table0_initializer_42 table0_initializer_43 table0_initializer_44 table0_initializer_45 table0_initializer_46 table0_initializer_47 table0_initializer_48 table0_initializer_49 table0_initializer_50 table0_initializer_51 table0_initializer_52 table0_initializer_53 table0_initializer_54 table0_initializer_55 table0_initializer_56 table0_initializer_57 table0_initializer_58 table0_initializer_59 table0_initializer_60 table0_initializer_61 table0_initializer_62 table0_initializer_63 table0_initializer_64 table0_initializer_65 table0_initializer_66 table0_initializer_67 table0_initializer_68 table0_initializer_69 table0_initializer_70 table0_initializer_71 table0_initializer_72 table0_initializer_73 table0_initializer_74 table0_initializer_75 table0_initializer_76 table0_initializer_77 table0_initializer_78 table0_initializer_79 table0_initializer_80 table0_initializer_81 table0_initializer_82 table0_initializer_83 table0_initializer_84 table0_initializer_85 table0_initializer_86 table0_initializer_87 table0_initializer_88 table0_initializer_89 table0_initializer_90 table0_initializer_91 table0_initializer_92 table0_initializer_93 table0_initializer_94 table0_initializer_95 table0_initializer_96 table0_initializer_97 table0_initializer_98 table0_initializer_99 table0_initializer_100 table0_initializer_101 table0_initializer_102 table0_initializer_103 table0_initializer_104 table0_initializer_105 table0_initializer_106 table0_initializer_107 table0_initializer_108 table0_initializer_109 table0_initializer_110 table0_initializer_111 table0_initializer_112 table0_initializer_113 table0_initializer_114 table0_initializer_115 table0_initializer_116 table0_initializer_117 table0_initializer_118 table0_initializer_119 table0_initializer_120 table0_initializer_121 table0_initializer_122 table0_initializer_123 table0_initializer_124 table0_initializer_125 table0_initializer_126 table0_initializer_127 table0_initializer_128 table0_initializer_129 table0_initializer_130 table0_initializer_131 table0_initializer_132 table0_initializer_133 table0_initializer_134 table0_initializer_135 table0_initializer_136 table0_initializer_137 table0_initializer_138 table0_initializer_139 table0_initializer_140 table0_initializer_141 table0_initializer_142 table0_initializer_143 table0_initializer_144 table0_initializer_145 table0_initializer_146 table0_initializer_147 table0_initializer_148 table0_initializer_149 table0_initializer_150 table0_initializer_151 table0_initializer_152 table0_initializer_153 table0_initializer_154 table0_initializer_155 table0_initializer_156 table0_initializer_157 table0_initializer_158 table0_initializer_159 table0_initializer_160 table0_initializer_161 table0_initializer_162 table0_initializer_163 table0_initializer_164 table0_initializer_165 table0_initializer_166 table0_initializer_167 table0_initializer_168 table0_initializer_169 table0_initializer_170 table0_initializer_171 table0_initializer_172 table0_initializer_173 table0_initializer_174 table0_initializer_175 table0_initializer_176 table0_initializer_177 table0_initializer_178 table0_initializer_179 table0_initializer_180 table0_initializer_181 table0_initializer_182 table0_initializer_183 table0_initializer_184 table0_initializer_185 table0_initializer_186 table0_initializer_187 table0_initializer_188 table0_initializer_189 table0_initializer_190 table0_initializer_191 table0_initializer_192 table0_initializer_193 table0_initializer_194 table0_initializer_195 table0_initializer_196 table0_initializer_197 table0_initializer_198 table0_initializer_199 table0_initializer_200 table0_initializer_201 table0_initializer_202 table0_initializer_203 table0_initializer_204 table0_initializer_205 table0_initializer_206 table0_initializer_207 table0_initializer_208 table0_initializer_209 table0_initializer_210 table0_initializer_211 table0_initializer_212 table0_initializer_213 table0_initializer_214 table0_initializer_215 table0_initializer_216 table0_initializer_217 table0_initializer_218 table0_initializer_219 table0_initializer_220 table0_initializer_221 table0_initializer_222 table0_initializer_223 table0_initializer_224 table0_initializer_225 table0_initializer_226 table0_initializer_227 table0_initializer_228 table0_initializer_229 table0_initializer_230 table0_initializer_231 table0_initializer_232 table0_initializer_233 table0_initializer_234 table0_initializer_235 table0_initializer_236 table0_initializer_237 table0_initializer_238 table0_initializer_239 table0_initializer_240 table0_initializer_241 table0_initializer_242 table0_initializer_243 table0_initializer_244 table0_initializer_245 table0_initializer_246 table0_initializer_247 table0_initializer_248 table0_initializer_249 table0_initializer_250 table0_initializer_251 table0_initializer_252 table0_initializer_253 table0_initializer_254 table0_initializer_255))
+[GOOD] (assert table0_initializer)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:0
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays4.gold b/SBVTestSuite/GoldFiles/queryArrays4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays4.gold
@@ -0,0 +1,560 @@
+** 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_UFBV) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
+[GOOD] (declare-fun s1 () (_ BitVec 8)) ; tracks user variable "j"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s3 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s4 () (_ BitVec 8) #x02)
+[GOOD] (define-fun s5 () (_ BitVec 8) #x03)
+[GOOD] (define-fun s6 () (_ BitVec 8) #x04)
+[GOOD] (define-fun s7 () (_ BitVec 8) #x05)
+[GOOD] (define-fun s8 () (_ BitVec 8) #x06)
+[GOOD] (define-fun s9 () (_ BitVec 8) #x07)
+[GOOD] (define-fun s10 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s11 () (_ BitVec 8) #x09)
+[GOOD] (define-fun s12 () (_ BitVec 8) #x0a)
+[GOOD] (define-fun s13 () (_ BitVec 8) #x0b)
+[GOOD] (define-fun s14 () (_ BitVec 8) #x0c)
+[GOOD] (define-fun s15 () (_ BitVec 8) #x0d)
+[GOOD] (define-fun s16 () (_ BitVec 8) #x0e)
+[GOOD] (define-fun s17 () (_ BitVec 8) #x0f)
+[GOOD] (define-fun s18 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s19 () (_ BitVec 8) #x11)
+[GOOD] (define-fun s20 () (_ BitVec 8) #x12)
+[GOOD] (define-fun s21 () (_ BitVec 8) #x13)
+[GOOD] (define-fun s22 () (_ BitVec 8) #x14)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x15)
+[GOOD] (define-fun s24 () (_ BitVec 8) #x16)
+[GOOD] (define-fun s25 () (_ BitVec 8) #x17)
+[GOOD] (define-fun s26 () (_ BitVec 8) #x18)
+[GOOD] (define-fun s27 () (_ BitVec 8) #x19)
+[GOOD] (define-fun s28 () (_ BitVec 8) #x1a)
+[GOOD] (define-fun s29 () (_ BitVec 8) #x1b)
+[GOOD] (define-fun s30 () (_ BitVec 8) #x1c)
+[GOOD] (define-fun s31 () (_ BitVec 8) #x1d)
+[GOOD] (define-fun s32 () (_ BitVec 8) #x1e)
+[GOOD] (define-fun s33 () (_ BitVec 8) #x1f)
+[GOOD] (define-fun s34 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s35 () (_ BitVec 8) #x21)
+[GOOD] (define-fun s36 () (_ BitVec 8) #x22)
+[GOOD] (define-fun s37 () (_ BitVec 8) #x23)
+[GOOD] (define-fun s38 () (_ BitVec 8) #x24)
+[GOOD] (define-fun s39 () (_ BitVec 8) #x25)
+[GOOD] (define-fun s40 () (_ BitVec 8) #x26)
+[GOOD] (define-fun s41 () (_ BitVec 8) #x27)
+[GOOD] (define-fun s42 () (_ BitVec 8) #x28)
+[GOOD] (define-fun s43 () (_ BitVec 8) #x29)
+[GOOD] (define-fun s44 () (_ BitVec 8) #x2a)
+[GOOD] (define-fun s45 () (_ BitVec 8) #x2b)
+[GOOD] (define-fun s46 () (_ BitVec 8) #x2c)
+[GOOD] (define-fun s47 () (_ BitVec 8) #x2d)
+[GOOD] (define-fun s48 () (_ BitVec 8) #x2e)
+[GOOD] (define-fun s49 () (_ BitVec 8) #x2f)
+[GOOD] (define-fun s50 () (_ BitVec 8) #x30)
+[GOOD] (define-fun s51 () (_ BitVec 8) #x31)
+[GOOD] (define-fun s52 () (_ BitVec 8) #x32)
+[GOOD] (define-fun s53 () (_ BitVec 8) #x33)
+[GOOD] (define-fun s54 () (_ BitVec 8) #x34)
+[GOOD] (define-fun s55 () (_ BitVec 8) #x35)
+[GOOD] (define-fun s56 () (_ BitVec 8) #x36)
+[GOOD] (define-fun s57 () (_ BitVec 8) #x37)
+[GOOD] (define-fun s58 () (_ BitVec 8) #x38)
+[GOOD] (define-fun s59 () (_ BitVec 8) #x39)
+[GOOD] (define-fun s60 () (_ BitVec 8) #x3a)
+[GOOD] (define-fun s61 () (_ BitVec 8) #x3b)
+[GOOD] (define-fun s62 () (_ BitVec 8) #x3c)
+[GOOD] (define-fun s63 () (_ BitVec 8) #x3d)
+[GOOD] (define-fun s64 () (_ BitVec 8) #x3e)
+[GOOD] (define-fun s65 () (_ BitVec 8) #x3f)
+[GOOD] (define-fun s66 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s67 () (_ BitVec 8) #x41)
+[GOOD] (define-fun s68 () (_ BitVec 8) #x42)
+[GOOD] (define-fun s69 () (_ BitVec 8) #x43)
+[GOOD] (define-fun s70 () (_ BitVec 8) #x44)
+[GOOD] (define-fun s71 () (_ BitVec 8) #x45)
+[GOOD] (define-fun s72 () (_ BitVec 8) #x46)
+[GOOD] (define-fun s73 () (_ BitVec 8) #x47)
+[GOOD] (define-fun s74 () (_ BitVec 8) #x48)
+[GOOD] (define-fun s75 () (_ BitVec 8) #x49)
+[GOOD] (define-fun s76 () (_ BitVec 8) #x4a)
+[GOOD] (define-fun s77 () (_ BitVec 8) #x4b)
+[GOOD] (define-fun s78 () (_ BitVec 8) #x4c)
+[GOOD] (define-fun s79 () (_ BitVec 8) #x4d)
+[GOOD] (define-fun s80 () (_ BitVec 8) #x4e)
+[GOOD] (define-fun s81 () (_ BitVec 8) #x4f)
+[GOOD] (define-fun s82 () (_ BitVec 8) #x50)
+[GOOD] (define-fun s83 () (_ BitVec 8) #x51)
+[GOOD] (define-fun s84 () (_ BitVec 8) #x52)
+[GOOD] (define-fun s85 () (_ BitVec 8) #x53)
+[GOOD] (define-fun s86 () (_ BitVec 8) #x54)
+[GOOD] (define-fun s87 () (_ BitVec 8) #x55)
+[GOOD] (define-fun s88 () (_ BitVec 8) #x56)
+[GOOD] (define-fun s89 () (_ BitVec 8) #x57)
+[GOOD] (define-fun s90 () (_ BitVec 8) #x58)
+[GOOD] (define-fun s91 () (_ BitVec 8) #x59)
+[GOOD] (define-fun s92 () (_ BitVec 8) #x5a)
+[GOOD] (define-fun s93 () (_ BitVec 8) #x5b)
+[GOOD] (define-fun s94 () (_ BitVec 8) #x5c)
+[GOOD] (define-fun s95 () (_ BitVec 8) #x5d)
+[GOOD] (define-fun s96 () (_ BitVec 8) #x5e)
+[GOOD] (define-fun s97 () (_ BitVec 8) #x5f)
+[GOOD] (define-fun s98 () (_ BitVec 8) #x60)
+[GOOD] (define-fun s99 () (_ BitVec 8) #x61)
+[GOOD] (define-fun s100 () (_ BitVec 8) #x62)
+[GOOD] (define-fun s101 () (_ BitVec 8) #x63)
+[GOOD] (define-fun s102 () (_ BitVec 8) #x64)
+[GOOD] (define-fun s103 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s104 () (_ BitVec 8) #x66)
+[GOOD] (define-fun s105 () (_ BitVec 8) #x67)
+[GOOD] (define-fun s106 () (_ BitVec 8) #x68)
+[GOOD] (define-fun s107 () (_ BitVec 8) #x69)
+[GOOD] (define-fun s108 () (_ BitVec 8) #x6a)
+[GOOD] (define-fun s109 () (_ BitVec 8) #x6b)
+[GOOD] (define-fun s110 () (_ BitVec 8) #x6c)
+[GOOD] (define-fun s111 () (_ BitVec 8) #x6d)
+[GOOD] (define-fun s112 () (_ BitVec 8) #x6e)
+[GOOD] (define-fun s113 () (_ BitVec 8) #x6f)
+[GOOD] (define-fun s114 () (_ BitVec 8) #x70)
+[GOOD] (define-fun s115 () (_ BitVec 8) #x71)
+[GOOD] (define-fun s116 () (_ BitVec 8) #x72)
+[GOOD] (define-fun s117 () (_ BitVec 8) #x73)
+[GOOD] (define-fun s118 () (_ BitVec 8) #x74)
+[GOOD] (define-fun s119 () (_ BitVec 8) #x75)
+[GOOD] (define-fun s120 () (_ BitVec 8) #x76)
+[GOOD] (define-fun s121 () (_ BitVec 8) #x77)
+[GOOD] (define-fun s122 () (_ BitVec 8) #x78)
+[GOOD] (define-fun s123 () (_ BitVec 8) #x79)
+[GOOD] (define-fun s124 () (_ BitVec 8) #x7a)
+[GOOD] (define-fun s125 () (_ BitVec 8) #x7b)
+[GOOD] (define-fun s126 () (_ BitVec 8) #x7c)
+[GOOD] (define-fun s127 () (_ BitVec 8) #x7d)
+[GOOD] (define-fun s128 () (_ BitVec 8) #x7e)
+[GOOD] (define-fun s129 () (_ BitVec 8) #x7f)
+[GOOD] (define-fun s130 () (_ BitVec 8) #x80)
+[GOOD] (define-fun s131 () (_ BitVec 8) #x81)
+[GOOD] (define-fun s132 () (_ BitVec 8) #x82)
+[GOOD] (define-fun s133 () (_ BitVec 8) #x83)
+[GOOD] (define-fun s134 () (_ BitVec 8) #x84)
+[GOOD] (define-fun s135 () (_ BitVec 8) #x85)
+[GOOD] (define-fun s136 () (_ BitVec 8) #x86)
+[GOOD] (define-fun s137 () (_ BitVec 8) #x87)
+[GOOD] (define-fun s138 () (_ BitVec 8) #x88)
+[GOOD] (define-fun s139 () (_ BitVec 8) #x89)
+[GOOD] (define-fun s140 () (_ BitVec 8) #x8a)
+[GOOD] (define-fun s141 () (_ BitVec 8) #x8b)
+[GOOD] (define-fun s142 () (_ BitVec 8) #x8c)
+[GOOD] (define-fun s143 () (_ BitVec 8) #x8d)
+[GOOD] (define-fun s144 () (_ BitVec 8) #x8e)
+[GOOD] (define-fun s145 () (_ BitVec 8) #x8f)
+[GOOD] (define-fun s146 () (_ BitVec 8) #x90)
+[GOOD] (define-fun s147 () (_ BitVec 8) #x91)
+[GOOD] (define-fun s148 () (_ BitVec 8) #x92)
+[GOOD] (define-fun s149 () (_ BitVec 8) #x93)
+[GOOD] (define-fun s150 () (_ BitVec 8) #x94)
+[GOOD] (define-fun s151 () (_ BitVec 8) #x95)
+[GOOD] (define-fun s152 () (_ BitVec 8) #x96)
+[GOOD] (define-fun s153 () (_ BitVec 8) #x97)
+[GOOD] (define-fun s154 () (_ BitVec 8) #x98)
+[GOOD] (define-fun s155 () (_ BitVec 8) #x99)
+[GOOD] (define-fun s156 () (_ BitVec 8) #x9a)
+[GOOD] (define-fun s157 () (_ BitVec 8) #x9b)
+[GOOD] (define-fun s158 () (_ BitVec 8) #x9c)
+[GOOD] (define-fun s159 () (_ BitVec 8) #x9d)
+[GOOD] (define-fun s160 () (_ BitVec 8) #x9e)
+[GOOD] (define-fun s161 () (_ BitVec 8) #x9f)
+[GOOD] (define-fun s162 () (_ BitVec 8) #xa0)
+[GOOD] (define-fun s163 () (_ BitVec 8) #xa1)
+[GOOD] (define-fun s164 () (_ BitVec 8) #xa2)
+[GOOD] (define-fun s165 () (_ BitVec 8) #xa3)
+[GOOD] (define-fun s166 () (_ BitVec 8) #xa4)
+[GOOD] (define-fun s167 () (_ BitVec 8) #xa5)
+[GOOD] (define-fun s168 () (_ BitVec 8) #xa6)
+[GOOD] (define-fun s169 () (_ BitVec 8) #xa7)
+[GOOD] (define-fun s170 () (_ BitVec 8) #xa8)
+[GOOD] (define-fun s171 () (_ BitVec 8) #xa9)
+[GOOD] (define-fun s172 () (_ BitVec 8) #xaa)
+[GOOD] (define-fun s173 () (_ BitVec 8) #xab)
+[GOOD] (define-fun s174 () (_ BitVec 8) #xac)
+[GOOD] (define-fun s175 () (_ BitVec 8) #xad)
+[GOOD] (define-fun s176 () (_ BitVec 8) #xae)
+[GOOD] (define-fun s177 () (_ BitVec 8) #xaf)
+[GOOD] (define-fun s178 () (_ BitVec 8) #xb0)
+[GOOD] (define-fun s179 () (_ BitVec 8) #xb1)
+[GOOD] (define-fun s180 () (_ BitVec 8) #xb2)
+[GOOD] (define-fun s181 () (_ BitVec 8) #xb3)
+[GOOD] (define-fun s182 () (_ BitVec 8) #xb4)
+[GOOD] (define-fun s183 () (_ BitVec 8) #xb5)
+[GOOD] (define-fun s184 () (_ BitVec 8) #xb6)
+[GOOD] (define-fun s185 () (_ BitVec 8) #xb7)
+[GOOD] (define-fun s186 () (_ BitVec 8) #xb8)
+[GOOD] (define-fun s187 () (_ BitVec 8) #xb9)
+[GOOD] (define-fun s188 () (_ BitVec 8) #xba)
+[GOOD] (define-fun s189 () (_ BitVec 8) #xbb)
+[GOOD] (define-fun s190 () (_ BitVec 8) #xbc)
+[GOOD] (define-fun s191 () (_ BitVec 8) #xbd)
+[GOOD] (define-fun s192 () (_ BitVec 8) #xbe)
+[GOOD] (define-fun s193 () (_ BitVec 8) #xbf)
+[GOOD] (define-fun s194 () (_ BitVec 8) #xc0)
+[GOOD] (define-fun s195 () (_ BitVec 8) #xc1)
+[GOOD] (define-fun s196 () (_ BitVec 8) #xc2)
+[GOOD] (define-fun s197 () (_ BitVec 8) #xc3)
+[GOOD] (define-fun s198 () (_ BitVec 8) #xc4)
+[GOOD] (define-fun s199 () (_ BitVec 8) #xc5)
+[GOOD] (define-fun s200 () (_ BitVec 8) #xc6)
+[GOOD] (define-fun s201 () (_ BitVec 8) #xc7)
+[GOOD] (define-fun s202 () (_ BitVec 8) #xc8)
+[GOOD] (define-fun s203 () (_ BitVec 8) #xc9)
+[GOOD] (define-fun s204 () (_ BitVec 8) #xca)
+[GOOD] (define-fun s205 () (_ BitVec 8) #xcb)
+[GOOD] (define-fun s206 () (_ BitVec 8) #xcc)
+[GOOD] (define-fun s207 () (_ BitVec 8) #xcd)
+[GOOD] (define-fun s208 () (_ BitVec 8) #xce)
+[GOOD] (define-fun s209 () (_ BitVec 8) #xcf)
+[GOOD] (define-fun s210 () (_ BitVec 8) #xd0)
+[GOOD] (define-fun s211 () (_ BitVec 8) #xd1)
+[GOOD] (define-fun s212 () (_ BitVec 8) #xd2)
+[GOOD] (define-fun s213 () (_ BitVec 8) #xd3)
+[GOOD] (define-fun s214 () (_ BitVec 8) #xd4)
+[GOOD] (define-fun s215 () (_ BitVec 8) #xd5)
+[GOOD] (define-fun s216 () (_ BitVec 8) #xd6)
+[GOOD] (define-fun s217 () (_ BitVec 8) #xd7)
+[GOOD] (define-fun s218 () (_ BitVec 8) #xd8)
+[GOOD] (define-fun s219 () (_ BitVec 8) #xd9)
+[GOOD] (define-fun s220 () (_ BitVec 8) #xda)
+[GOOD] (define-fun s221 () (_ BitVec 8) #xdb)
+[GOOD] (define-fun s222 () (_ BitVec 8) #xdc)
+[GOOD] (define-fun s223 () (_ BitVec 8) #xdd)
+[GOOD] (define-fun s224 () (_ BitVec 8) #xde)
+[GOOD] (define-fun s225 () (_ BitVec 8) #xdf)
+[GOOD] (define-fun s226 () (_ BitVec 8) #xe0)
+[GOOD] (define-fun s227 () (_ BitVec 8) #xe1)
+[GOOD] (define-fun s228 () (_ BitVec 8) #xe2)
+[GOOD] (define-fun s229 () (_ BitVec 8) #xe3)
+[GOOD] (define-fun s230 () (_ BitVec 8) #xe4)
+[GOOD] (define-fun s231 () (_ BitVec 8) #xe5)
+[GOOD] (define-fun s232 () (_ BitVec 8) #xe6)
+[GOOD] (define-fun s233 () (_ BitVec 8) #xe7)
+[GOOD] (define-fun s234 () (_ BitVec 8) #xe8)
+[GOOD] (define-fun s235 () (_ BitVec 8) #xe9)
+[GOOD] (define-fun s236 () (_ BitVec 8) #xea)
+[GOOD] (define-fun s237 () (_ BitVec 8) #xeb)
+[GOOD] (define-fun s238 () (_ BitVec 8) #xec)
+[GOOD] (define-fun s239 () (_ BitVec 8) #xed)
+[GOOD] (define-fun s240 () (_ BitVec 8) #xee)
+[GOOD] (define-fun s241 () (_ BitVec 8) #xef)
+[GOOD] (define-fun s242 () (_ BitVec 8) #xf0)
+[GOOD] (define-fun s243 () (_ BitVec 8) #xf1)
+[GOOD] (define-fun s244 () (_ BitVec 8) #xf2)
+[GOOD] (define-fun s245 () (_ BitVec 8) #xf3)
+[GOOD] (define-fun s246 () (_ BitVec 8) #xf4)
+[GOOD] (define-fun s247 () (_ BitVec 8) #xf5)
+[GOOD] (define-fun s248 () (_ BitVec 8) #xf6)
+[GOOD] (define-fun s249 () (_ BitVec 8) #xf7)
+[GOOD] (define-fun s250 () (_ BitVec 8) #xf8)
+[GOOD] (define-fun s251 () (_ BitVec 8) #xf9)
+[GOOD] (define-fun s252 () (_ BitVec 8) #xfa)
+[GOOD] (define-fun s253 () (_ BitVec 8) #xfb)
+[GOOD] (define-fun s254 () (_ BitVec 8) #xfc)
+[GOOD] (define-fun s255 () (_ BitVec 8) #xfd)
+[GOOD] (define-fun s256 () (_ BitVec 8) #xfe)
+[GOOD] (define-fun s257 () (_ BitVec 8) #xff)
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] (define-fun s258 () (_ BitVec 8) (table0 s0))
+[GOOD] (define-fun s259 () Bool (= s0 s258))
+[GOOD] (define-fun table0_initializer_0 () Bool (= (table0 #x00) s2))
+[GOOD] (define-fun table0_initializer_1 () Bool (= (table0 #x01) s3))
+[GOOD] (define-fun table0_initializer_2 () Bool (= (table0 #x02) s4))
+[GOOD] (define-fun table0_initializer_3 () Bool (= (table0 #x03) s5))
+[GOOD] (define-fun table0_initializer_4 () Bool (= (table0 #x04) s6))
+[GOOD] (define-fun table0_initializer_5 () Bool (= (table0 #x05) s7))
+[GOOD] (define-fun table0_initializer_6 () Bool (= (table0 #x06) s8))
+[GOOD] (define-fun table0_initializer_7 () Bool (= (table0 #x07) s9))
+[GOOD] (define-fun table0_initializer_8 () Bool (= (table0 #x08) s10))
+[GOOD] (define-fun table0_initializer_9 () Bool (= (table0 #x09) s11))
+[GOOD] (define-fun table0_initializer_10 () Bool (= (table0 #x0a) s12))
+[GOOD] (define-fun table0_initializer_11 () Bool (= (table0 #x0b) s13))
+[GOOD] (define-fun table0_initializer_12 () Bool (= (table0 #x0c) s14))
+[GOOD] (define-fun table0_initializer_13 () Bool (= (table0 #x0d) s15))
+[GOOD] (define-fun table0_initializer_14 () Bool (= (table0 #x0e) s16))
+[GOOD] (define-fun table0_initializer_15 () Bool (= (table0 #x0f) s17))
+[GOOD] (define-fun table0_initializer_16 () Bool (= (table0 #x10) s18))
+[GOOD] (define-fun table0_initializer_17 () Bool (= (table0 #x11) s19))
+[GOOD] (define-fun table0_initializer_18 () Bool (= (table0 #x12) s20))
+[GOOD] (define-fun table0_initializer_19 () Bool (= (table0 #x13) s21))
+[GOOD] (define-fun table0_initializer_20 () Bool (= (table0 #x14) s22))
+[GOOD] (define-fun table0_initializer_21 () Bool (= (table0 #x15) s23))
+[GOOD] (define-fun table0_initializer_22 () Bool (= (table0 #x16) s24))
+[GOOD] (define-fun table0_initializer_23 () Bool (= (table0 #x17) s25))
+[GOOD] (define-fun table0_initializer_24 () Bool (= (table0 #x18) s26))
+[GOOD] (define-fun table0_initializer_25 () Bool (= (table0 #x19) s27))
+[GOOD] (define-fun table0_initializer_26 () Bool (= (table0 #x1a) s28))
+[GOOD] (define-fun table0_initializer_27 () Bool (= (table0 #x1b) s29))
+[GOOD] (define-fun table0_initializer_28 () Bool (= (table0 #x1c) s30))
+[GOOD] (define-fun table0_initializer_29 () Bool (= (table0 #x1d) s31))
+[GOOD] (define-fun table0_initializer_30 () Bool (= (table0 #x1e) s32))
+[GOOD] (define-fun table0_initializer_31 () Bool (= (table0 #x1f) s33))
+[GOOD] (define-fun table0_initializer_32 () Bool (= (table0 #x20) s34))
+[GOOD] (define-fun table0_initializer_33 () Bool (= (table0 #x21) s35))
+[GOOD] (define-fun table0_initializer_34 () Bool (= (table0 #x22) s36))
+[GOOD] (define-fun table0_initializer_35 () Bool (= (table0 #x23) s37))
+[GOOD] (define-fun table0_initializer_36 () Bool (= (table0 #x24) s38))
+[GOOD] (define-fun table0_initializer_37 () Bool (= (table0 #x25) s39))
+[GOOD] (define-fun table0_initializer_38 () Bool (= (table0 #x26) s40))
+[GOOD] (define-fun table0_initializer_39 () Bool (= (table0 #x27) s41))
+[GOOD] (define-fun table0_initializer_40 () Bool (= (table0 #x28) s42))
+[GOOD] (define-fun table0_initializer_41 () Bool (= (table0 #x29) s43))
+[GOOD] (define-fun table0_initializer_42 () Bool (= (table0 #x2a) s44))
+[GOOD] (define-fun table0_initializer_43 () Bool (= (table0 #x2b) s45))
+[GOOD] (define-fun table0_initializer_44 () Bool (= (table0 #x2c) s46))
+[GOOD] (define-fun table0_initializer_45 () Bool (= (table0 #x2d) s47))
+[GOOD] (define-fun table0_initializer_46 () Bool (= (table0 #x2e) s48))
+[GOOD] (define-fun table0_initializer_47 () Bool (= (table0 #x2f) s49))
+[GOOD] (define-fun table0_initializer_48 () Bool (= (table0 #x30) s50))
+[GOOD] (define-fun table0_initializer_49 () Bool (= (table0 #x31) s51))
+[GOOD] (define-fun table0_initializer_50 () Bool (= (table0 #x32) s52))
+[GOOD] (define-fun table0_initializer_51 () Bool (= (table0 #x33) s53))
+[GOOD] (define-fun table0_initializer_52 () Bool (= (table0 #x34) s54))
+[GOOD] (define-fun table0_initializer_53 () Bool (= (table0 #x35) s55))
+[GOOD] (define-fun table0_initializer_54 () Bool (= (table0 #x36) s56))
+[GOOD] (define-fun table0_initializer_55 () Bool (= (table0 #x37) s57))
+[GOOD] (define-fun table0_initializer_56 () Bool (= (table0 #x38) s58))
+[GOOD] (define-fun table0_initializer_57 () Bool (= (table0 #x39) s59))
+[GOOD] (define-fun table0_initializer_58 () Bool (= (table0 #x3a) s60))
+[GOOD] (define-fun table0_initializer_59 () Bool (= (table0 #x3b) s61))
+[GOOD] (define-fun table0_initializer_60 () Bool (= (table0 #x3c) s62))
+[GOOD] (define-fun table0_initializer_61 () Bool (= (table0 #x3d) s63))
+[GOOD] (define-fun table0_initializer_62 () Bool (= (table0 #x3e) s64))
+[GOOD] (define-fun table0_initializer_63 () Bool (= (table0 #x3f) s65))
+[GOOD] (define-fun table0_initializer_64 () Bool (= (table0 #x40) s66))
+[GOOD] (define-fun table0_initializer_65 () Bool (= (table0 #x41) s67))
+[GOOD] (define-fun table0_initializer_66 () Bool (= (table0 #x42) s68))
+[GOOD] (define-fun table0_initializer_67 () Bool (= (table0 #x43) s69))
+[GOOD] (define-fun table0_initializer_68 () Bool (= (table0 #x44) s70))
+[GOOD] (define-fun table0_initializer_69 () Bool (= (table0 #x45) s71))
+[GOOD] (define-fun table0_initializer_70 () Bool (= (table0 #x46) s72))
+[GOOD] (define-fun table0_initializer_71 () Bool (= (table0 #x47) s73))
+[GOOD] (define-fun table0_initializer_72 () Bool (= (table0 #x48) s74))
+[GOOD] (define-fun table0_initializer_73 () Bool (= (table0 #x49) s75))
+[GOOD] (define-fun table0_initializer_74 () Bool (= (table0 #x4a) s76))
+[GOOD] (define-fun table0_initializer_75 () Bool (= (table0 #x4b) s77))
+[GOOD] (define-fun table0_initializer_76 () Bool (= (table0 #x4c) s78))
+[GOOD] (define-fun table0_initializer_77 () Bool (= (table0 #x4d) s79))
+[GOOD] (define-fun table0_initializer_78 () Bool (= (table0 #x4e) s80))
+[GOOD] (define-fun table0_initializer_79 () Bool (= (table0 #x4f) s81))
+[GOOD] (define-fun table0_initializer_80 () Bool (= (table0 #x50) s82))
+[GOOD] (define-fun table0_initializer_81 () Bool (= (table0 #x51) s83))
+[GOOD] (define-fun table0_initializer_82 () Bool (= (table0 #x52) s84))
+[GOOD] (define-fun table0_initializer_83 () Bool (= (table0 #x53) s85))
+[GOOD] (define-fun table0_initializer_84 () Bool (= (table0 #x54) s86))
+[GOOD] (define-fun table0_initializer_85 () Bool (= (table0 #x55) s87))
+[GOOD] (define-fun table0_initializer_86 () Bool (= (table0 #x56) s88))
+[GOOD] (define-fun table0_initializer_87 () Bool (= (table0 #x57) s89))
+[GOOD] (define-fun table0_initializer_88 () Bool (= (table0 #x58) s90))
+[GOOD] (define-fun table0_initializer_89 () Bool (= (table0 #x59) s91))
+[GOOD] (define-fun table0_initializer_90 () Bool (= (table0 #x5a) s92))
+[GOOD] (define-fun table0_initializer_91 () Bool (= (table0 #x5b) s93))
+[GOOD] (define-fun table0_initializer_92 () Bool (= (table0 #x5c) s94))
+[GOOD] (define-fun table0_initializer_93 () Bool (= (table0 #x5d) s95))
+[GOOD] (define-fun table0_initializer_94 () Bool (= (table0 #x5e) s96))
+[GOOD] (define-fun table0_initializer_95 () Bool (= (table0 #x5f) s97))
+[GOOD] (define-fun table0_initializer_96 () Bool (= (table0 #x60) s98))
+[GOOD] (define-fun table0_initializer_97 () Bool (= (table0 #x61) s99))
+[GOOD] (define-fun table0_initializer_98 () Bool (= (table0 #x62) s100))
+[GOOD] (define-fun table0_initializer_99 () Bool (= (table0 #x63) s101))
+[GOOD] (define-fun table0_initializer_100 () Bool (= (table0 #x64) s102))
+[GOOD] (define-fun table0_initializer_101 () Bool (= (table0 #x65) s103))
+[GOOD] (define-fun table0_initializer_102 () Bool (= (table0 #x66) s104))
+[GOOD] (define-fun table0_initializer_103 () Bool (= (table0 #x67) s105))
+[GOOD] (define-fun table0_initializer_104 () Bool (= (table0 #x68) s106))
+[GOOD] (define-fun table0_initializer_105 () Bool (= (table0 #x69) s107))
+[GOOD] (define-fun table0_initializer_106 () Bool (= (table0 #x6a) s108))
+[GOOD] (define-fun table0_initializer_107 () Bool (= (table0 #x6b) s109))
+[GOOD] (define-fun table0_initializer_108 () Bool (= (table0 #x6c) s110))
+[GOOD] (define-fun table0_initializer_109 () Bool (= (table0 #x6d) s111))
+[GOOD] (define-fun table0_initializer_110 () Bool (= (table0 #x6e) s112))
+[GOOD] (define-fun table0_initializer_111 () Bool (= (table0 #x6f) s113))
+[GOOD] (define-fun table0_initializer_112 () Bool (= (table0 #x70) s114))
+[GOOD] (define-fun table0_initializer_113 () Bool (= (table0 #x71) s115))
+[GOOD] (define-fun table0_initializer_114 () Bool (= (table0 #x72) s116))
+[GOOD] (define-fun table0_initializer_115 () Bool (= (table0 #x73) s117))
+[GOOD] (define-fun table0_initializer_116 () Bool (= (table0 #x74) s118))
+[GOOD] (define-fun table0_initializer_117 () Bool (= (table0 #x75) s119))
+[GOOD] (define-fun table0_initializer_118 () Bool (= (table0 #x76) s120))
+[GOOD] (define-fun table0_initializer_119 () Bool (= (table0 #x77) s121))
+[GOOD] (define-fun table0_initializer_120 () Bool (= (table0 #x78) s122))
+[GOOD] (define-fun table0_initializer_121 () Bool (= (table0 #x79) s123))
+[GOOD] (define-fun table0_initializer_122 () Bool (= (table0 #x7a) s124))
+[GOOD] (define-fun table0_initializer_123 () Bool (= (table0 #x7b) s125))
+[GOOD] (define-fun table0_initializer_124 () Bool (= (table0 #x7c) s126))
+[GOOD] (define-fun table0_initializer_125 () Bool (= (table0 #x7d) s127))
+[GOOD] (define-fun table0_initializer_126 () Bool (= (table0 #x7e) s128))
+[GOOD] (define-fun table0_initializer_127 () Bool (= (table0 #x7f) s129))
+[GOOD] (define-fun table0_initializer_128 () Bool (= (table0 #x80) s130))
+[GOOD] (define-fun table0_initializer_129 () Bool (= (table0 #x81) s131))
+[GOOD] (define-fun table0_initializer_130 () Bool (= (table0 #x82) s132))
+[GOOD] (define-fun table0_initializer_131 () Bool (= (table0 #x83) s133))
+[GOOD] (define-fun table0_initializer_132 () Bool (= (table0 #x84) s134))
+[GOOD] (define-fun table0_initializer_133 () Bool (= (table0 #x85) s135))
+[GOOD] (define-fun table0_initializer_134 () Bool (= (table0 #x86) s136))
+[GOOD] (define-fun table0_initializer_135 () Bool (= (table0 #x87) s137))
+[GOOD] (define-fun table0_initializer_136 () Bool (= (table0 #x88) s138))
+[GOOD] (define-fun table0_initializer_137 () Bool (= (table0 #x89) s139))
+[GOOD] (define-fun table0_initializer_138 () Bool (= (table0 #x8a) s140))
+[GOOD] (define-fun table0_initializer_139 () Bool (= (table0 #x8b) s141))
+[GOOD] (define-fun table0_initializer_140 () Bool (= (table0 #x8c) s142))
+[GOOD] (define-fun table0_initializer_141 () Bool (= (table0 #x8d) s143))
+[GOOD] (define-fun table0_initializer_142 () Bool (= (table0 #x8e) s144))
+[GOOD] (define-fun table0_initializer_143 () Bool (= (table0 #x8f) s145))
+[GOOD] (define-fun table0_initializer_144 () Bool (= (table0 #x90) s146))
+[GOOD] (define-fun table0_initializer_145 () Bool (= (table0 #x91) s147))
+[GOOD] (define-fun table0_initializer_146 () Bool (= (table0 #x92) s148))
+[GOOD] (define-fun table0_initializer_147 () Bool (= (table0 #x93) s149))
+[GOOD] (define-fun table0_initializer_148 () Bool (= (table0 #x94) s150))
+[GOOD] (define-fun table0_initializer_149 () Bool (= (table0 #x95) s151))
+[GOOD] (define-fun table0_initializer_150 () Bool (= (table0 #x96) s152))
+[GOOD] (define-fun table0_initializer_151 () Bool (= (table0 #x97) s153))
+[GOOD] (define-fun table0_initializer_152 () Bool (= (table0 #x98) s154))
+[GOOD] (define-fun table0_initializer_153 () Bool (= (table0 #x99) s155))
+[GOOD] (define-fun table0_initializer_154 () Bool (= (table0 #x9a) s156))
+[GOOD] (define-fun table0_initializer_155 () Bool (= (table0 #x9b) s157))
+[GOOD] (define-fun table0_initializer_156 () Bool (= (table0 #x9c) s158))
+[GOOD] (define-fun table0_initializer_157 () Bool (= (table0 #x9d) s159))
+[GOOD] (define-fun table0_initializer_158 () Bool (= (table0 #x9e) s160))
+[GOOD] (define-fun table0_initializer_159 () Bool (= (table0 #x9f) s161))
+[GOOD] (define-fun table0_initializer_160 () Bool (= (table0 #xa0) s162))
+[GOOD] (define-fun table0_initializer_161 () Bool (= (table0 #xa1) s163))
+[GOOD] (define-fun table0_initializer_162 () Bool (= (table0 #xa2) s164))
+[GOOD] (define-fun table0_initializer_163 () Bool (= (table0 #xa3) s165))
+[GOOD] (define-fun table0_initializer_164 () Bool (= (table0 #xa4) s166))
+[GOOD] (define-fun table0_initializer_165 () Bool (= (table0 #xa5) s167))
+[GOOD] (define-fun table0_initializer_166 () Bool (= (table0 #xa6) s168))
+[GOOD] (define-fun table0_initializer_167 () Bool (= (table0 #xa7) s169))
+[GOOD] (define-fun table0_initializer_168 () Bool (= (table0 #xa8) s170))
+[GOOD] (define-fun table0_initializer_169 () Bool (= (table0 #xa9) s171))
+[GOOD] (define-fun table0_initializer_170 () Bool (= (table0 #xaa) s172))
+[GOOD] (define-fun table0_initializer_171 () Bool (= (table0 #xab) s173))
+[GOOD] (define-fun table0_initializer_172 () Bool (= (table0 #xac) s174))
+[GOOD] (define-fun table0_initializer_173 () Bool (= (table0 #xad) s175))
+[GOOD] (define-fun table0_initializer_174 () Bool (= (table0 #xae) s176))
+[GOOD] (define-fun table0_initializer_175 () Bool (= (table0 #xaf) s177))
+[GOOD] (define-fun table0_initializer_176 () Bool (= (table0 #xb0) s178))
+[GOOD] (define-fun table0_initializer_177 () Bool (= (table0 #xb1) s179))
+[GOOD] (define-fun table0_initializer_178 () Bool (= (table0 #xb2) s180))
+[GOOD] (define-fun table0_initializer_179 () Bool (= (table0 #xb3) s181))
+[GOOD] (define-fun table0_initializer_180 () Bool (= (table0 #xb4) s182))
+[GOOD] (define-fun table0_initializer_181 () Bool (= (table0 #xb5) s183))
+[GOOD] (define-fun table0_initializer_182 () Bool (= (table0 #xb6) s184))
+[GOOD] (define-fun table0_initializer_183 () Bool (= (table0 #xb7) s185))
+[GOOD] (define-fun table0_initializer_184 () Bool (= (table0 #xb8) s186))
+[GOOD] (define-fun table0_initializer_185 () Bool (= (table0 #xb9) s187))
+[GOOD] (define-fun table0_initializer_186 () Bool (= (table0 #xba) s188))
+[GOOD] (define-fun table0_initializer_187 () Bool (= (table0 #xbb) s189))
+[GOOD] (define-fun table0_initializer_188 () Bool (= (table0 #xbc) s190))
+[GOOD] (define-fun table0_initializer_189 () Bool (= (table0 #xbd) s191))
+[GOOD] (define-fun table0_initializer_190 () Bool (= (table0 #xbe) s192))
+[GOOD] (define-fun table0_initializer_191 () Bool (= (table0 #xbf) s193))
+[GOOD] (define-fun table0_initializer_192 () Bool (= (table0 #xc0) s194))
+[GOOD] (define-fun table0_initializer_193 () Bool (= (table0 #xc1) s195))
+[GOOD] (define-fun table0_initializer_194 () Bool (= (table0 #xc2) s196))
+[GOOD] (define-fun table0_initializer_195 () Bool (= (table0 #xc3) s197))
+[GOOD] (define-fun table0_initializer_196 () Bool (= (table0 #xc4) s198))
+[GOOD] (define-fun table0_initializer_197 () Bool (= (table0 #xc5) s199))
+[GOOD] (define-fun table0_initializer_198 () Bool (= (table0 #xc6) s200))
+[GOOD] (define-fun table0_initializer_199 () Bool (= (table0 #xc7) s201))
+[GOOD] (define-fun table0_initializer_200 () Bool (= (table0 #xc8) s202))
+[GOOD] (define-fun table0_initializer_201 () Bool (= (table0 #xc9) s203))
+[GOOD] (define-fun table0_initializer_202 () Bool (= (table0 #xca) s204))
+[GOOD] (define-fun table0_initializer_203 () Bool (= (table0 #xcb) s205))
+[GOOD] (define-fun table0_initializer_204 () Bool (= (table0 #xcc) s206))
+[GOOD] (define-fun table0_initializer_205 () Bool (= (table0 #xcd) s207))
+[GOOD] (define-fun table0_initializer_206 () Bool (= (table0 #xce) s208))
+[GOOD] (define-fun table0_initializer_207 () Bool (= (table0 #xcf) s209))
+[GOOD] (define-fun table0_initializer_208 () Bool (= (table0 #xd0) s210))
+[GOOD] (define-fun table0_initializer_209 () Bool (= (table0 #xd1) s211))
+[GOOD] (define-fun table0_initializer_210 () Bool (= (table0 #xd2) s212))
+[GOOD] (define-fun table0_initializer_211 () Bool (= (table0 #xd3) s213))
+[GOOD] (define-fun table0_initializer_212 () Bool (= (table0 #xd4) s214))
+[GOOD] (define-fun table0_initializer_213 () Bool (= (table0 #xd5) s215))
+[GOOD] (define-fun table0_initializer_214 () Bool (= (table0 #xd6) s216))
+[GOOD] (define-fun table0_initializer_215 () Bool (= (table0 #xd7) s217))
+[GOOD] (define-fun table0_initializer_216 () Bool (= (table0 #xd8) s218))
+[GOOD] (define-fun table0_initializer_217 () Bool (= (table0 #xd9) s219))
+[GOOD] (define-fun table0_initializer_218 () Bool (= (table0 #xda) s220))
+[GOOD] (define-fun table0_initializer_219 () Bool (= (table0 #xdb) s221))
+[GOOD] (define-fun table0_initializer_220 () Bool (= (table0 #xdc) s222))
+[GOOD] (define-fun table0_initializer_221 () Bool (= (table0 #xdd) s223))
+[GOOD] (define-fun table0_initializer_222 () Bool (= (table0 #xde) s224))
+[GOOD] (define-fun table0_initializer_223 () Bool (= (table0 #xdf) s225))
+[GOOD] (define-fun table0_initializer_224 () Bool (= (table0 #xe0) s226))
+[GOOD] (define-fun table0_initializer_225 () Bool (= (table0 #xe1) s227))
+[GOOD] (define-fun table0_initializer_226 () Bool (= (table0 #xe2) s228))
+[GOOD] (define-fun table0_initializer_227 () Bool (= (table0 #xe3) s229))
+[GOOD] (define-fun table0_initializer_228 () Bool (= (table0 #xe4) s230))
+[GOOD] (define-fun table0_initializer_229 () Bool (= (table0 #xe5) s231))
+[GOOD] (define-fun table0_initializer_230 () Bool (= (table0 #xe6) s232))
+[GOOD] (define-fun table0_initializer_231 () Bool (= (table0 #xe7) s233))
+[GOOD] (define-fun table0_initializer_232 () Bool (= (table0 #xe8) s234))
+[GOOD] (define-fun table0_initializer_233 () Bool (= (table0 #xe9) s235))
+[GOOD] (define-fun table0_initializer_234 () Bool (= (table0 #xea) s236))
+[GOOD] (define-fun table0_initializer_235 () Bool (= (table0 #xeb) s237))
+[GOOD] (define-fun table0_initializer_236 () Bool (= (table0 #xec) s238))
+[GOOD] (define-fun table0_initializer_237 () Bool (= (table0 #xed) s239))
+[GOOD] (define-fun table0_initializer_238 () Bool (= (table0 #xee) s240))
+[GOOD] (define-fun table0_initializer_239 () Bool (= (table0 #xef) s241))
+[GOOD] (define-fun table0_initializer_240 () Bool (= (table0 #xf0) s242))
+[GOOD] (define-fun table0_initializer_241 () Bool (= (table0 #xf1) s243))
+[GOOD] (define-fun table0_initializer_242 () Bool (= (table0 #xf2) s244))
+[GOOD] (define-fun table0_initializer_243 () Bool (= (table0 #xf3) s245))
+[GOOD] (define-fun table0_initializer_244 () Bool (= (table0 #xf4) s246))
+[GOOD] (define-fun table0_initializer_245 () Bool (= (table0 #xf5) s247))
+[GOOD] (define-fun table0_initializer_246 () Bool (= (table0 #xf6) s248))
+[GOOD] (define-fun table0_initializer_247 () Bool (= (table0 #xf7) s249))
+[GOOD] (define-fun table0_initializer_248 () Bool (= (table0 #xf8) s250))
+[GOOD] (define-fun table0_initializer_249 () Bool (= (table0 #xf9) s251))
+[GOOD] (define-fun table0_initializer_250 () Bool (= (table0 #xfa) s252))
+[GOOD] (define-fun table0_initializer_251 () Bool (= (table0 #xfb) s253))
+[GOOD] (define-fun table0_initializer_252 () Bool (= (table0 #xfc) s254))
+[GOOD] (define-fun table0_initializer_253 () Bool (= (table0 #xfd) s255))
+[GOOD] (define-fun table0_initializer_254 () Bool (= (table0 #xfe) s256))
+[GOOD] (define-fun table0_initializer_255 () Bool (= (table0 #xff) s257))
+[GOOD] (define-fun table0_initializer () Bool (and table0_initializer_0 table0_initializer_1 table0_initializer_2 table0_initializer_3 table0_initializer_4 table0_initializer_5 table0_initializer_6 table0_initializer_7 table0_initializer_8 table0_initializer_9 table0_initializer_10 table0_initializer_11 table0_initializer_12 table0_initializer_13 table0_initializer_14 table0_initializer_15 table0_initializer_16 table0_initializer_17 table0_initializer_18 table0_initializer_19 table0_initializer_20 table0_initializer_21 table0_initializer_22 table0_initializer_23 table0_initializer_24 table0_initializer_25 table0_initializer_26 table0_initializer_27 table0_initializer_28 table0_initializer_29 table0_initializer_30 table0_initializer_31 table0_initializer_32 table0_initializer_33 table0_initializer_34 table0_initializer_35 table0_initializer_36 table0_initializer_37 table0_initializer_38 table0_initializer_39 table0_initializer_40 table0_initializer_41 table0_initializer_42 table0_initializer_43 table0_initializer_44 table0_initializer_45 table0_initializer_46 table0_initializer_47 table0_initializer_48 table0_initializer_49 table0_initializer_50 table0_initializer_51 table0_initializer_52 table0_initializer_53 table0_initializer_54 table0_initializer_55 table0_initializer_56 table0_initializer_57 table0_initializer_58 table0_initializer_59 table0_initializer_60 table0_initializer_61 table0_initializer_62 table0_initializer_63 table0_initializer_64 table0_initializer_65 table0_initializer_66 table0_initializer_67 table0_initializer_68 table0_initializer_69 table0_initializer_70 table0_initializer_71 table0_initializer_72 table0_initializer_73 table0_initializer_74 table0_initializer_75 table0_initializer_76 table0_initializer_77 table0_initializer_78 table0_initializer_79 table0_initializer_80 table0_initializer_81 table0_initializer_82 table0_initializer_83 table0_initializer_84 table0_initializer_85 table0_initializer_86 table0_initializer_87 table0_initializer_88 table0_initializer_89 table0_initializer_90 table0_initializer_91 table0_initializer_92 table0_initializer_93 table0_initializer_94 table0_initializer_95 table0_initializer_96 table0_initializer_97 table0_initializer_98 table0_initializer_99 table0_initializer_100 table0_initializer_101 table0_initializer_102 table0_initializer_103 table0_initializer_104 table0_initializer_105 table0_initializer_106 table0_initializer_107 table0_initializer_108 table0_initializer_109 table0_initializer_110 table0_initializer_111 table0_initializer_112 table0_initializer_113 table0_initializer_114 table0_initializer_115 table0_initializer_116 table0_initializer_117 table0_initializer_118 table0_initializer_119 table0_initializer_120 table0_initializer_121 table0_initializer_122 table0_initializer_123 table0_initializer_124 table0_initializer_125 table0_initializer_126 table0_initializer_127 table0_initializer_128 table0_initializer_129 table0_initializer_130 table0_initializer_131 table0_initializer_132 table0_initializer_133 table0_initializer_134 table0_initializer_135 table0_initializer_136 table0_initializer_137 table0_initializer_138 table0_initializer_139 table0_initializer_140 table0_initializer_141 table0_initializer_142 table0_initializer_143 table0_initializer_144 table0_initializer_145 table0_initializer_146 table0_initializer_147 table0_initializer_148 table0_initializer_149 table0_initializer_150 table0_initializer_151 table0_initializer_152 table0_initializer_153 table0_initializer_154 table0_initializer_155 table0_initializer_156 table0_initializer_157 table0_initializer_158 table0_initializer_159 table0_initializer_160 table0_initializer_161 table0_initializer_162 table0_initializer_163 table0_initializer_164 table0_initializer_165 table0_initializer_166 table0_initializer_167 table0_initializer_168 table0_initializer_169 table0_initializer_170 table0_initializer_171 table0_initializer_172 table0_initializer_173 table0_initializer_174 table0_initializer_175 table0_initializer_176 table0_initializer_177 table0_initializer_178 table0_initializer_179 table0_initializer_180 table0_initializer_181 table0_initializer_182 table0_initializer_183 table0_initializer_184 table0_initializer_185 table0_initializer_186 table0_initializer_187 table0_initializer_188 table0_initializer_189 table0_initializer_190 table0_initializer_191 table0_initializer_192 table0_initializer_193 table0_initializer_194 table0_initializer_195 table0_initializer_196 table0_initializer_197 table0_initializer_198 table0_initializer_199 table0_initializer_200 table0_initializer_201 table0_initializer_202 table0_initializer_203 table0_initializer_204 table0_initializer_205 table0_initializer_206 table0_initializer_207 table0_initializer_208 table0_initializer_209 table0_initializer_210 table0_initializer_211 table0_initializer_212 table0_initializer_213 table0_initializer_214 table0_initializer_215 table0_initializer_216 table0_initializer_217 table0_initializer_218 table0_initializer_219 table0_initializer_220 table0_initializer_221 table0_initializer_222 table0_initializer_223 table0_initializer_224 table0_initializer_225 table0_initializer_226 table0_initializer_227 table0_initializer_228 table0_initializer_229 table0_initializer_230 table0_initializer_231 table0_initializer_232 table0_initializer_233 table0_initializer_234 table0_initializer_235 table0_initializer_236 table0_initializer_237 table0_initializer_238 table0_initializer_239 table0_initializer_240 table0_initializer_241 table0_initializer_242 table0_initializer_243 table0_initializer_244 table0_initializer_245 table0_initializer_246 table0_initializer_247 table0_initializer_248 table0_initializer_249 table0_initializer_250 table0_initializer_251 table0_initializer_252 table0_initializer_253 table0_initializer_254 table0_initializer_255))
+[GOOD] (assert table0_initializer)
+[GOOD] (assert s259)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00))
+[GOOD] (define-fun s260 () (_ BitVec 8) (table0 s1))
+[GOOD] (define-fun s261 () Bool (= s1 s260))
+[GOOD] (assert s261)
+[GOOD] (define-fun s262 () Bool (= s0 s2))
+[GOOD] (assert s262)
+[GOOD] (define-fun s263 () (_ BitVec 8) (bvadd s0 s3))
+[GOOD] (define-fun s264 () Bool (= s1 s263))
+[GOOD] (assert s264)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s1))
+[RECV] ((s1 #x01))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:(0,1)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays5.gold b/SBVTestSuite/GoldFiles/queryArrays5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays5.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) (_ BitVec 8))) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 8)) ; tracks user variable "a_0"
+[GOOD] (declare-fun s2 () (_ BitVec 8)) ; tracks user variable "v"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s6 () (_ BitVec 8) #x01)
+[GOOD] (define-fun s4 () (_ BitVec 8) (bvadd s2 s3))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) (_ BitVec 8)) (store s0 s1 s2))
+[GOOD] (define-fun s7 () (_ BitVec 8) (bvadd s1 s6))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) (_ BitVec 8)) (store s5 s7 s4))
+[GOOD] (define-fun s9 () (_ BitVec 8) (select s8 s7))
+[GOOD] (define-fun s10 () Bool (distinct s4 s9))
+[GOOD] (assert s10)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Nothing
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays6.gold b/SBVTestSuite/GoldFiles/queryArrays6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays6.gold
@@ -0,0 +1,70 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (push 1)
+[GOOD] (define-fun s1 () Int 1)
+[GOOD] (define-fun s4 () Int 5)
+[GOOD] (define-fun s2 () (Array Int Int) (store s0 s1 s1))
+[GOOD] (define-fun s3 () Int (select s2 s1))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (declare-fun s6 () Int)
+[GOOD] (define-fun s8 () Int 3)
+[GOOD] (define-fun s7 () Bool (>= s6 s1))
+[GOOD] (define-fun s9 () Bool (< s6 s8))
+[GOOD] (define-fun s10 () Bool (and s7 s9))
+[GOOD] (assert s10)
+[GOOD] (push 1)
+[GOOD] (define-fun s11 () Int (+ s3 s6))
+[GOOD] (define-fun s12 () (Array Int Int) (store s2 s1 s11))
+[GOOD] (define-fun s13 () Int (select s12 s1))
+[GOOD] (define-fun s14 () Bool (= s4 s13))
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (declare-fun s15 () Int)
+[GOOD] (define-fun s16 () Bool (>= s15 s1))
+[GOOD] (define-fun s17 () Bool (< s15 s8))
+[GOOD] (define-fun s18 () Bool (and s16 s17))
+[GOOD] (assert s18)
+[GOOD] (push 1)
+[GOOD] (define-fun s19 () Int (+ s13 s15))
+[GOOD] (define-fun s20 () (Array Int Int) (store s12 s1 s19))
+[GOOD] (define-fun s21 () Int (select s20 s1))
+[GOOD] (define-fun s22 () Bool (= s4 s21))
+[GOOD] (assert s22)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s6))
+[RECV] ((s6 2))
+[SEND] (get-value (s15))
+[RECV] ((s15 2))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:[2,2]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays7.gold b/SBVTestSuite/GoldFiles/queryArrays7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays7.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s5 () Int 2)
+[GOOD] (define-fun s3 () (Array Int Int) (store s0 s1 s2))
+[GOOD] (define-fun s4 () Int (select s3 s1))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (reset-assertions)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:(Unsat,Unsat)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays8.gold b/SBVTestSuite/GoldFiles/queryArrays8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays8.gold
@@ -0,0 +1,38 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (declare-fun s0 () (Array Int Int))
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] (define-fun s5 () Int 2)
+[GOOD] (define-fun s3 () (Array Int Int) (store s0 s1 s2))
+[GOOD] (define-fun s4 () Int (select s3 s1))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (reset-assertions)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:(Unsat,Unsat)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryArrays9.gold b/SBVTestSuite/GoldFiles/queryArrays9.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryArrays9.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array String Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () String (_ char #x61))
+[GOOD] (define-fun s3 () Int 5)
+[GOOD] (define-fun s2 () Int (select s0 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Sat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/queryTables.gold b/SBVTestSuite/GoldFiles/queryTables.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/queryTables.gold
@@ -0,0 +1,141 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (define-fun s1 () (_ BitVec 16) #x0000)
+[GOOD] (define-fun s3 () (_ BitVec 16) #x0001)
+[GOOD] (define-fun s2 () Bool (bvsle s1 s0))
+[GOOD] (define-fun s4 () Bool (bvslt s0 s3))
+[GOOD] (define-fun s5 () Bool (and s2 s4))
+[GOOD] (assert s5)
+[GOOD] (declare-fun s6 () (_ BitVec 16))
+[GOOD] (define-fun s7 () Bool (bvsle s1 s6))
+[GOOD] (define-fun s8 () Bool (bvslt s6 s3))
+[GOOD] (define-fun s9 () Bool (and s7 s8))
+[GOOD] (assert s9)
+[GOOD] (push 1)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] (define-fun s13 () (_ BitVec 16) #x000a)
+[GOOD] (define-fun s15 () (_ BitVec 16) (bvneg #x0001))
+[GOOD] (define-fun s17 () (_ BitVec 16) #x0007)
+[GOOD] (define-fun s19 () (Maybe (_ BitVec 16)) ((as Just (Maybe (_ BitVec 16))) #x0000))
+[GOOD] (define-fun s20 () (Maybe (_ BitVec 16)) (as Nothing (Maybe (_ BitVec 16))))
+[GOOD] (define-fun s28 () (_ BitVec 16) #x00ff)
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] (define-fun s10 () (SBVTuple2 (_ BitVec 16) (_ BitVec 16)) ((as mkSBVTuple2 (SBVTuple2 (_ BitVec 16) (_ BitVec 16))) s0 s6))
+[GOOD] (define-fun s11 () (_ BitVec 16) (proj_1_SBVTuple2 s10))
+[GOOD] (define-fun s12 () Bool (= s3 s11))
+[GOOD] (define-fun s14 () Bool (= s11 s13))
+[GOOD] (define-fun s16 () (_ BitVec 16) (proj_2_SBVTuple2 s10))
+[GOOD] (define-fun s18 () Bool (= s16 s17))
+[GOOD] (define-fun s21 () (Maybe (_ BitVec 16)) (ite s18 s19 s20))
+[GOOD] (define-fun s22 () Bool ((as is-Nothing Bool) s21))
+[GOOD] (define-fun s23 () (_ BitVec 16) (getJust_1 s21))
+[GOOD] (define-fun s24 () (_ BitVec 16) (ite s22 s15 s23))
+[GOOD] (define-fun s25 () (_ BitVec 16) (ite (or (bvslt s24 #x0000) (bvsle #x0001 s24)) s15 (table0 s24)))
+[GOOD] (define-fun s26 () Bool (= s1 s25))
+[GOOD] (define-fun s27 () Bool (= s1 s24))
+[GOOD] (define-fun s29 () (_ BitVec 16) (ite s27 s28 s3))
+[GOOD] (define-fun s30 () (_ BitVec 16) (ite s26 s29 s3))
+[GOOD] (define-fun s31 () (_ BitVec 16) (ite s14 s30 s3))
+[GOOD] (define-fun s32 () (_ BitVec 16) (ite s12 s3 s31))
+[GOOD] (define-fun s33 () Bool (= s3 s32))
+[GOOD] (define-fun s34 () Bool ((_ pbeq 1 1) s33))
+[GOOD] (define-fun table0_initializer_0 () Bool (= (table0 #x0000) s3))
+[GOOD] (define-fun table0_initializer () Bool table0_initializer_0)
+[GOOD] (assert table0_initializer)
+[GOOD] (assert s34)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (pop 1)
+[GOOD] (assert table0_initializer)
+[GOOD] (declare-fun s35 () (_ BitVec 16))
+[GOOD] (define-fun s36 () Bool (bvsle s1 s35))
+[GOOD] (define-fun s37 () Bool (bvslt s35 s3))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (assert s38)
+[GOOD] (declare-fun s39 () (_ BitVec 16))
+[GOOD] (define-fun s40 () Bool (bvsle s1 s39))
+[GOOD] (define-fun s41 () Bool (bvslt s39 s3))
+[GOOD] (define-fun s42 () Bool (and s40 s41))
+[GOOD] (assert s42)
+[GOOD] (push 1)
+[GOOD] (define-fun s48 () (_ BitVec 16) #x0006)
+[GOOD] (define-fun s56 () (_ BitVec 16) #x0002)
+[GOOD] (declare-fun table1 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] (declare-fun table2 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] (define-fun s43 () (SBVTuple2 (_ BitVec 16) (_ BitVec 16)) ((as mkSBVTuple2 (SBVTuple2 (_ BitVec 16) (_ BitVec 16))) s35 s39))
+[GOOD] (define-fun s44 () (_ BitVec 16) (proj_1_SBVTuple2 s43))
+[GOOD] (define-fun s45 () Bool (= s3 s44))
+[GOOD] (define-fun s46 () (_ BitVec 16) (proj_2_SBVTuple2 s43))
+[GOOD] (define-fun s47 () Bool (bvsle s3 s46))
+[GOOD] (define-fun s49 () Bool (bvsle s46 s48))
+[GOOD] (define-fun s50 () Bool (and s47 s49))
+[GOOD] (define-fun s51 () Bool (bvsle s3 s16))
+[GOOD] (define-fun s52 () Bool (bvsle s16 s48))
+[GOOD] (define-fun s53 () Bool (and s51 s52))
+[GOOD] (define-fun s54 () (_ BitVec 16) (bvsub s1 s3))
+[GOOD] (define-fun s55 () Bool (= s1 s54))
+[GOOD] (define-fun s57 () (_ BitVec 16) (ite s55 s56 s1))
+[GOOD] (define-fun s58 () (_ BitVec 16) (bvsub s46 s3))
+[GOOD] (define-fun s59 () (_ BitVec 16) (ite (or (bvslt s58 #x0000) (bvsle #x0001 s58)) s1 (table1 s58)))
+[GOOD] (define-fun s60 () Bool (= s1 s59))
+[GOOD] (define-fun s61 () Bool (= s13 s44))
+[GOOD] (define-fun s62 () Bool (= s17 s46))
+[GOOD] (define-fun s63 () (Maybe (_ BitVec 16)) (ite s62 s19 s20))
+[GOOD] (define-fun s64 () Bool ((as is-Nothing Bool) s63))
+[GOOD] (define-fun s65 () (_ BitVec 16) (getJust_1 s63))
+[GOOD] (define-fun s66 () (_ BitVec 16) (ite s64 s15 s65))
+[GOOD] (define-fun s67 () (_ BitVec 16) (ite (or (bvslt s66 #x0000) (bvsle #x0001 s66)) s15 (table2 s66)))
+[GOOD] (define-fun s68 () Bool (= s1 s67))
+[GOOD] (define-fun s69 () Bool (= s1 s66))
+[GOOD] (define-fun s70 () (_ BitVec 16) (ite s69 s28 s32))
+[GOOD] (define-fun s71 () (_ BitVec 16) (ite s68 s70 s32))
+[GOOD] (define-fun s72 () (_ BitVec 16) (ite s61 s71 s32))
+[GOOD] (define-fun s73 () (_ BitVec 16) (ite s45 s32 s72))
+[GOOD] (define-fun s74 () Bool (= s3 s73))
+[GOOD] (define-fun s75 () Bool ((_ pbeq 1 1) s74))
+[GOOD] (define-fun table1_initializer_0 () Bool (= (table1 #x0000) s57))
+[GOOD] (define-fun table1_initializer () Bool table1_initializer_0)
+[GOOD] (assert table1_initializer)
+[GOOD] (define-fun table2_initializer_0 () Bool (= (table2 #x0000) s32))
+[GOOD] (define-fun table2_initializer () Bool table2_initializer_0)
+[GOOD] (assert table2_initializer)
+[GOOD] (assert s75)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s10))
+[RECV] ((s10 (mkSBVTuple2 #x0000 #x0000)))
+[SEND] (get-value (s43))
+[RECV] ((s43 (mkSBVTuple2 #x0000 #x0000)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:[(0,0),(0,0)]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/query_Chars1.gold b/SBVTestSuite/GoldFiles/query_Chars1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Chars1.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 65)
+[GOOD] (define-fun s4 () Int 66)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (assert (= 1 (str.len s0)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (str.to_code s0))
+[GOOD] (define-fun s3 () Bool (>= s1 s2))
+[GOOD] (define-fun s5 () Bool (< s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 "A"))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+'A'
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant1.gold b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
@@ -0,0 +1,41 @@
+** Calling: mathsat -input=smt2 -theory.fp.minmax_zero_mode=4
+[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-interpolants true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[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] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () Bool (= s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] (define-fun s7 () Bool (= s1 s3))
+[GOOD] (define-fun s8 () Bool (= s2 s3))
+[GOOD] (define-fun s9 () Bool (not s8))
+[GOOD] (define-fun s10 () Bool (and s7 s9))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s6 :interpolation-group |c1|))
+[GOOD] (assert (! s10 :interpolation-group |c2|))
+[SEND] (check-sat)
+[RECV] unsat
+[SEND] (get-interpolant (|c1|))
+[RECV] (= s1 s2)
+*** Solver   : MathSAT
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+"(= s1 s2)"
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant2.gold b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
@@ -0,0 +1,46 @@
+** Calling: mathsat -input=smt2 -theory.fp.minmax_zero_mode=4
+[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-interpolants true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[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] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun f (Int) Int)
+[GOOD] (declare-fun g (Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Int (f s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Int (f s1))
+[GOOD] (define-fun s7 () Bool (= s3 s6))
+[GOOD] (define-fun s8 () Bool (and s5 s7))
+[GOOD] (define-fun s9 () Bool (= s0 s1))
+[GOOD] (define-fun s10 () Int (g s2))
+[GOOD] (define-fun s11 () Int (g s3))
+[GOOD] (define-fun s12 () Bool (distinct s10 s11))
+[GOOD] (define-fun s13 () Bool (and s9 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s8 :interpolation-group |c1|))
+[GOOD] (assert (! s13 :interpolation-group |c2|))
+[SEND] (check-sat)
+[RECV] unsat
+[SEND] (get-interpolant (|c1|))
+[RECV] (not (and (= s0 s1) (not (= s2 s3))))
+*** Solver   : MathSAT
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+"(not (and (= s0 s1) (not (= s2 s3))))"
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant3.gold b/SBVTestSuite/GoldFiles/query_Interpolant3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Interpolant3.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[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] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s4 () Bool (= s0 s1))
+[GOOD] (define-fun s5 () Bool (= s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] (define-fun s7 () Bool (= s1 s3))
+[GOOD] (define-fun s8 () Bool (= s2 s3))
+[GOOD] (define-fun s9 () Bool (not s8))
+[GOOD] (define-fun s10 () Bool (and s7 s9))
+[SEND] (get-interpolant s6 s10)
+[RECV] (= s2 s1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+"(= s2 s1)"
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant4.gold b/SBVTestSuite/GoldFiles/query_Interpolant4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Interpolant4.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) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[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] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (declare-fun f (Int) Int)
+[GOOD] (define-fun s4 () Int (f s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] (define-fun s6 () Int (f s1))
+[GOOD] (define-fun s7 () Bool (= s3 s6))
+[GOOD] (define-fun s8 () Bool (and s5 s7))
+[GOOD] (declare-fun g (Int) Int)
+[GOOD] (define-fun s9 () Bool (= s0 s1))
+[GOOD] (define-fun s10 () Int (g s2))
+[GOOD] (define-fun s11 () Int (g s3))
+[GOOD] (define-fun s12 () Bool (distinct s10 s11))
+[GOOD] (define-fun s13 () Bool (and s9 s12))
+[SEND] (get-interpolant s8 s13)
+[RECV] (or (and (= s1 s2) (= s1 s3))
+           (<= (+ (* (- 1) s1) s0) (- 1))
+           (<= (+ s1 (* (- 1) s0)) (- 1))
+           (= s2 s3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+"(or (and (= s1 s2) (= s1 s3)) (<= (+ (* (- 1) s1) s0) (- 1)) (<= (+ s1 (* (- 1) s0)) (- 1)) (= s2 s3))"
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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Maybe String))) ; tracks user variable "lst"
+[GOOD] (assert (forall ((seq0 Int)) (=> (and (>= seq0 0) (< seq0 (seq.len s0))) (= 1 (str.len (getJust_1 (seq.nth s0 seq0)))))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Maybe String) (seq.nth s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s2))
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Int (- s5 s4))
+[GOOD] (define-fun s7 () (Seq (Maybe String)) (seq.extract s0 s4 s6))
+[GOOD] (define-fun s8 () (Maybe String) (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool ((as is-Nothing Bool) s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.unit (Just "A"))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+[Just 'A']
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,49 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (Either Int Int))) ; tracks user variable "lst"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Either Int Int) (seq.nth s0 s1))
+[GOOD] (define-fun s3 () Bool ((as is-Left Bool) s2))
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Int (- s5 s4))
+[GOOD] (define-fun s7 () (Seq (Either Int Int)) (seq.extract s0 s4 s6))
+[GOOD] (define-fun s8 () (Either Int Int) (seq.nth s7 s1))
+[GOOD] (define-fun s9 () Bool ((as is-Right Bool) s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.unit (Left 3))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+[Left 3]
diff --git a/SBVTestSuite/GoldFiles/query_Lists1.gold b/SBVTestSuite/GoldFiles/query_Lists1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Lists1.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+[1,2,3,4,5]
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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Maybe Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Nothing Bool) s0))
+[GOOD] (define-fun s2 () Int (getJust_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (not s1))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Just 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Just 1
diff --git a/SBVTestSuite/GoldFiles/query_Strings1.gold b/SBVTestSuite/GoldFiles/query_Strings1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Strings1.gold
@@ -0,0 +1,31 @@
+** 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 strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 5 5) (str.to_re "xyz"))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 "xyzxyzxyzxyzxyz"))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+["xyzxyzxyzxyzxyz"]
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,52 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Int))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (define-fun s2 () Bool ((as is-Left Bool) s0))
+[GOOD] (assert s2)
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s1))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Just 3)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Left 2,Just 3)
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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int String)) ; tracks user variable "a"
+[GOOD] (assert (= 1 (str.len (getRight_1 s0))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Bool (and s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Left 1
diff --git a/SBVTestSuite/GoldFiles/query_Tuples1.gold b/SBVTestSuite/GoldFiles/query_Tuples1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Tuples1.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int String)) ; tracks user variable "a"
+[GOOD] (assert (= 1 (str.len (proj_2_SBVTuple2 s0))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 1 "A")))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(1,'A')
diff --git a/SBVTestSuite/GoldFiles/query_Tuples2.gold b/SBVTestSuite/GoldFiles/query_Tuples2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Tuples2.gold
@@ -0,0 +1,42 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[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 () String (_ char #x63))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int (SBVTuple2 String SBVTuple0))) ; tracks user variable "a"
+[GOOD] (assert (= 1 (str.len (proj_1_SBVTuple2 (proj_2_SBVTuple2 s0)))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (SBVTuple2 String SBVTuple0) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s2 () String (proj_1_SBVTuple2 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 0 (mkSBVTuple2 "c" mkSBVTuple0))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(0,('c',()))
diff --git a/SBVTestSuite/GoldFiles/query_abc.gold b/SBVTestSuite/GoldFiles/query_abc.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_abc.gold
@@ -0,0 +1,49 @@
+** 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 ALL) ; external query, using all logics.
+[ISSUE] ; --- tuples ---
+[ISSUE] ; --- sums ---
+[ISSUE] ; --- literal constants ---
+[ISSUE] (define-fun s2 () (_ BitVec 32) #x00000000)
+[ISSUE] ; --- top level inputs ---
+[ISSUE] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[ISSUE] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[ISSUE] ; --- constant tables ---
+[ISSUE] ; --- non-constant tables ---
+[ISSUE] ; --- uninterpreted constants ---
+[ISSUE] ; --- user defined functions ---
+[ISSUE] ; --- assignments ---
+[ISSUE] (define-fun s3 () Bool (bvsgt s0 s2))
+[ISSUE] (define-fun s4 () Bool (bvsgt s1 s2))
+[ISSUE] ; --- delayedEqualities ---
+[ISSUE] ; --- formula ---
+[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))
+[RECV] ((s0 #x1))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x1))
+*** Solver   : ABC
+*** Exit code: ExitSuccess
+*** Std-err  : Cmd warning: redefining '%graft'
diff --git a/SBVTestSuite/GoldFiles/query_badOption.gold b/SBVTestSuite/GoldFiles/query_badOption.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_badOption.gold
@@ -0,0 +1,47 @@
+** 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")
+[FAIL] (set-option :there-is-no-such-option bad argument)
+
+
+*** Data.SBV: Unexpected non-success response from Z3:
+***
+***    Sent      : (set-option :there-is-no-such-option bad argument)
+***    Expected  : success
+***    Received  : (error "line 5 column 37: unknown parameter 'there_is_no_such_option'
+***                Legal parameters are:
+***                  auto_config (bool) (default: true)
+***                  ctrl_c (bool) (default: true)
+***                  debug_ref_count (bool) (default: false)
+***                  dot_proof_file (string) (default: proof.dot)
+***                  dump_models (bool) (default: false)
+***                  encoding (string) (default: unicode)
+***                  memory_high_watermark (unsigned int) (default: 0)
+***                  memory_high_watermark_mb (unsigned int) (default: 0)
+***                  memory_max_alloc_count (unsigned int) (default: 0)
+***                  memory_max_size (unsigned int) (default: 0)
+***                  model (bool) (default: true)
+***                  model_validate (bool) (default: false)
+***                  proof (bool) (default: false)
+***                  rlimit (unsigned int) (default: 0)
+***                  smtlib2_compliant (bool) (default: false)
+***                  stats (bool) (default: false)
+***                  timeout (unsigned int) (default: 4294967295)
+***                  trace (bool) (default: false)
+***                  trace_file_name (string) (default: z3.log)
+***                  type_check (bool) (default: true)
+***                  unsat_core (bool) (default: false)
+***                  verbose (unsigned int) (default: 0)
+***                  warning (bool) (default: true)
+***                  well_sorted_check (bool) (default: false)")
+***
+***    Exit code : ExitFailure (-15)
+***    Executable: /usr/local/bin/z3
+***    Options   : -nw -in -smt2
+***
+***    Reason    : Backend solver reports it does not support this option.
+***                Check the spelling, and if correct please report this as a
+***                bug/feature request with the solver!
diff --git a/SBVTestSuite/GoldFiles/query_bitwuzla.gold b/SBVTestSuite/GoldFiles/query_bitwuzla.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_bitwuzla.gold
@@ -0,0 +1,53 @@
+** Calling: bitwuzla --produce-models
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert s14)
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsge s0 s16))
+[GOOD] (assert s17)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000001))
+[SEND] (get-value (s1))
+[RECV] ((s1 #b00000000000000000000000000000001))
+*** Solver   : Bitwuzla
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query_boolector.gold b/SBVTestSuite/GoldFiles/query_boolector.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_boolector.gold
@@ -0,0 +1,57 @@
+** Calling: boolector --smt2 -m --output-format=smt2 --no-exit-codes --incremental
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert s14)
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsge s0 s16))
+[GOOD] (assert s17)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000001))
+[SEND] (get-value (s1))
+[RECV] ((s1 #b00000000000000000000000000000001))
+*** Solver   : Boolector
+*** Exit code: ExitSuccess
+*** Std-out  : (
+             (define-fun s0 () (_ BitVec 32) #b00000000000000000000000000000001)
+             (define-fun s1 () (_ BitVec 32) #b00000000000000000000000000000001)
+           )
diff --git a/SBVTestSuite/GoldFiles/query_cvc4.gold b/SBVTestSuite/GoldFiles/query_cvc4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_cvc4.gold
@@ -0,0 +1,60 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt --model-witness-value
+[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 ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s3 :named |a > 0|))
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert (! s14 :named |a+b_<_12|))
+[GOOD] (push 1)
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000001))
+[GOOD] (pop 1)
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsgt s0 s16))
+[GOOD] (assert (! s17 :named |extra|))
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000010))
+[SEND] (get-value (s1))
+[RECV] ((s1 #b00000000000000000000000000000001))
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
diff --git a/SBVTestSuite/GoldFiles/query_cvc5.gold b/SBVTestSuite/GoldFiles/query_cvc5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_cvc5.gold
@@ -0,0 +1,59 @@
+** Calling: cvc5 --lang smt --incremental --nl-cov
+[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 HO_ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s3 :named |a > 0|))
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert (! s14 :named |a+b_<_12|))
+[GOOD] (push 1)
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000001))
+[GOOD] (pop 1)
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsgt s0 s16))
+[GOOD] (assert (! s17 :named |extra|))
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000010))
+[SEND] (get-value (s1))
+[RECV] ((s1 #b00000000000000000000000000000001))
+*** Solver   : CVC5
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query_mathsat.gold b/SBVTestSuite/GoldFiles/query_mathsat.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_mathsat.gold
@@ -0,0 +1,54 @@
+** Calling: mathsat -input=smt2 -theory.fp.minmax_zero_mode=4
+[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 ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s3 :named |a > 0|))
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert (! s14 :named |a+b_<_12|))
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsge s0 s16))
+[GOOD] (assert (! s17 :named |extra|))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ( (s0 (_ bv1 32)) )
+[SEND] (get-value (s1))
+[RECV] ( (s1 (_ bv1 32)) )
+*** Solver   : MathSAT
+*** Exit code: ExitSuccess
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,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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Left Bool) s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Left 2)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Left 2,Left 2,False)
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,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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Right Bool) s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Right false)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Right false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Right False,Right False,False)
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,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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Nothing Bool) s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 Nothing))
+[SEND] (get-value (s1))
+[RECV] ((s1 Nothing))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Nothing,Nothing,False)
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,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) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Just Bool) s3))
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Just 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Just 2)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Just 2,Just 2,False)
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,36 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (q1 false))
+[GOOD] (define-fun s1 () Bool (not s0))
+[GOOD] (define-fun s2 () Bool (q1 true))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("q1",(True,SBool -> SBool,Right ([([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,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-logic ALL) ; NB. User specified.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (q2 false true))
+[GOOD] (define-fun s1 () Bool (not s0))
+[GOOD] (define-fun s2 () Bool (q2 true true))
+[GOOD] (define-fun s3 () Bool (q2 true false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) true true true)
+              true
+              false
+              true)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("q2",(True,SBool -> SBool -> SBool,Right ([([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,195 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s21 () Int 5)
+[GOOD] (define-fun s23 () Int 7)
+[GOOD] (define-fun s25 () Int 6)
+[GOOD] (define-fun s29 () (_ FloatingPoint  8 24) (fp #b0 #b10000010 #b00010011001100110011010))
+[GOOD] (define-fun s32 () (_ FloatingPoint  8 24) (fp #b0 #b10000010 #b00110011001100110011010))
+[GOOD] (define-fun s33 () Int 121)
+[GOOD] (define-fun s38 () Int 8)
+[GOOD] (define-fun s40 () (_ FloatingPoint  8 24) (_ +oo 8 24))
+[GOOD] (define-fun s42 () String (_ char #x63))
+[GOOD] (define-fun s43 () String "hey")
+[GOOD] (define-fun s45 () (_ FloatingPoint  8 24) (fp #b0 #b10000101 #b00111000000000000000000))
+[GOOD] (define-fun s47 () String "tey")
+[GOOD] (define-fun s49 () (_ FloatingPoint  8 24) (fp #b0 #b10000101 #b01110000000000000000000))
+[GOOD] (define-fun s51 () String (_ char #x72))
+[GOOD] (define-fun s52 () String "foo")
+[GOOD] (define-fun s54 () (_ FloatingPoint  8 24) (fp #b0 #b10000000 #b11000000000000000000000))
+[GOOD] (define-fun s56 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s57 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (fp #b0 #b10000000 #b10000000000000000000000))))
+[GOOD] (define-fun s60 () (Seq Int) (seq.++ (seq.unit 9) (seq.unit 5)))
+[GOOD] (define-fun s61 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (fp #b0 #b10000010 #b00100000000000000000000))))
+[GOOD] (define-fun s63 () Int 21)
+[GOOD] (define-fun s65 () (Seq Int) (seq.unit 5))
+[GOOD] (define-fun s66 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (_ +zero 8 24))))
+[GOOD] (define-fun s68 () Int 210)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s17 () Bool) ; tracks user variable "__internal_sbv_s17"
+[GOOD] (declare-fun s18 () Int) ; tracks user variable "__internal_sbv_s18"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[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 (String String) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q5 ((Seq Int) (Seq (_ FloatingPoint  8 24))) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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 s19 () Int (q2 s17 s18))
+[GOOD] (define-fun s20 () Int (q2 true s5))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s24 () Int (q2 false s23))
+[GOOD] (define-fun s26 () Bool (= s24 s25))
+[GOOD] (define-fun s27 () Int (q2 false s3))
+[GOOD] (define-fun s28 () Bool (= s5 s27))
+[GOOD] (define-fun s30 () (_ FloatingPoint  8 24) (q3 s29 true s3))
+[GOOD] (define-fun s31 () Bool (fp.eq s29 s30))
+[GOOD] (define-fun s34 () (_ FloatingPoint  8 24) (q3 s32 true s33))
+[GOOD] (define-fun s35 () Bool (fp.isZero s34))
+[GOOD] (define-fun s36 () Bool (fp.isNegative s34))
+[GOOD] (define-fun s37 () Bool (and s35 s36))
+[GOOD] (define-fun s39 () (_ FloatingPoint  8 24) (q3 s32 false s38))
+[GOOD] (define-fun s41 () Bool (fp.eq s39 s40))
+[GOOD] (define-fun s44 () (_ FloatingPoint  8 24) (q4 s42 s43))
+[GOOD] (define-fun s46 () Bool (fp.eq s44 s45))
+[GOOD] (define-fun s48 () (_ FloatingPoint  8 24) (q4 s42 s47))
+[GOOD] (define-fun s50 () Bool (fp.eq s48 s49))
+[GOOD] (define-fun s53 () (_ FloatingPoint  8 24) (q4 s51 s52))
+[GOOD] (define-fun s55 () Bool (fp.eq s53 s54))
+[GOOD] (define-fun s58 () Int (q5 s56 s57))
+[GOOD] (define-fun s59 () Bool (= s23 s58))
+[GOOD] (define-fun s62 () Int (q5 s60 s61))
+[GOOD] (define-fun s64 () Bool (= s62 s63))
+[GOOD] (define-fun s67 () Int (q5 s65 s66))
+[GOOD] (define-fun s69 () Bool (= s67 s68))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s8)
+[GOOD] (assert s12)
+[GOOD] (assert s16)
+[GOOD] (assert s22)
+[GOOD] (assert s26)
+[GOOD] (assert s28)
+[GOOD] (assert s31)
+[GOOD] (assert s37)
+[GOOD] (assert s41)
+[GOOD] (assert s46)
+[GOOD] (assert s50)
+[GOOD] (assert s55)
+[GOOD] (assert s59)
+[GOOD] (assert s64)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s17))
+[RECV] ((s17 false))
+[SEND] (get-value (s18))
+[RECV] ((s18 0))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (q1))
+[RECV] ((q1 (store (store (store ((as const (Array Int Int)) 12) 3 75) (- 3) 9) 0 1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Int Int)) 5) false 7 6) false 12 3)))
+[SEND] (get-value (q3))
+[RECV] ((q3 (store (store ((as const
+                          (Array (_ FloatingPoint 8 24)
+                                 Bool
+                                 Int
+                                 (_ FloatingPoint 8 24)))
+                       (fp #b0 #x82 #b00010011001100110011010))
+                     (fp #b0 #x82 #b00110011001100110011010)
+                     true
+                     121
+                     (_ -zero 8 24))
+              (fp #b0 #x82 #b00110011001100110011010)
+              false
+              8
+              (_ +oo 8 24))))
+[SEND] (get-value (q4))
+[RECV] ((q4 (store (store ((as const (Array String String (_ FloatingPoint 8 24)))
+                       (fp #b0 #x85 #b00111000000000000000000))
+                     "c"
+                     "tey"
+                     (fp #b0 #x85 #b01110000000000000000000))
+              "r"
+              "foo"
+              (fp #b0 #x80 #b11000000000000000000000))))
+[SEND] (get-value (q5))
+[RECV] ((q5 (store (store ((as const (Array (Seq Int) (Seq (_ FloatingPoint 8 24)) Int)) 7)
+                     (seq.++ (seq.unit 9) (seq.unit 5))
+                     (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                             (seq.unit (fp #b0 #x82 #b00100000000000000000000)))
+                     21)
+              (seq.unit 5)
+              (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                      (seq.unit (_ +zero 8 24)))
+              210)))
+*** 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,164 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s21 () Int 5)
+[GOOD] (define-fun s23 () Int 7)
+[GOOD] (define-fun s25 () Int 6)
+[GOOD] (define-fun s29 () (_ FloatingPoint  8 24) (fp #b0 #b10000010 #b00010011001100110011010))
+[GOOD] (define-fun s32 () (_ FloatingPoint  8 24) (fp #b0 #b10000010 #b00110011001100110011010))
+[GOOD] (define-fun s33 () Int 121)
+[GOOD] (define-fun s38 () Int 8)
+[GOOD] (define-fun s40 () (_ FloatingPoint  8 24) (_ +oo 8 24))
+[GOOD] (define-fun s42 () String (_ char #x63))
+[GOOD] (define-fun s43 () String "hey")
+[GOOD] (define-fun s45 () (_ FloatingPoint  8 24) (fp #b0 #b10000101 #b00111000000000000000000))
+[GOOD] (define-fun s47 () String "tey")
+[GOOD] (define-fun s49 () (_ FloatingPoint  8 24) (fp #b0 #b10000101 #b01110000000000000000000))
+[GOOD] (define-fun s51 () String (_ char #x72))
+[GOOD] (define-fun s52 () String "foo")
+[GOOD] (define-fun s54 () (_ FloatingPoint  8 24) (fp #b0 #b10000000 #b11000000000000000000000))
+[GOOD] (define-fun s56 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s57 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (fp #b0 #b10000000 #b10000000000000000000000))))
+[GOOD] (define-fun s60 () (Seq Int) (seq.++ (seq.unit 9) (seq.unit 5)))
+[GOOD] (define-fun s61 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (fp #b0 #b10000010 #b00100000000000000000000))))
+[GOOD] (define-fun s63 () Int 21)
+[GOOD] (define-fun s65 () (Seq Int) (seq.unit 5))
+[GOOD] (define-fun s66 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit (fp #b0 #b10000010 #b00000110011001100110011)) (seq.unit (_ +zero 8 24))))
+[GOOD] (define-fun s68 () Int 210)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s17 () Bool) ; tracks user variable "__internal_sbv_s17"
+[GOOD] (declare-fun s18 () Int) ; tracks user variable "__internal_sbv_s18"
+[GOOD] (declare-fun s70 () Int) ; tracks user variable "__internal_sbv_s70"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[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 (String String) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q5 ((Seq Int) (Seq (_ FloatingPoint  8 24))) Int)
+[GOOD] (declare-fun q6 (Int) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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 s19 () Int (q2 s17 s18))
+[GOOD] (define-fun s20 () Int (q2 true s5))
+[GOOD] (define-fun s22 () Bool (= s20 s21))
+[GOOD] (define-fun s24 () Int (q2 false s23))
+[GOOD] (define-fun s26 () Bool (= s24 s25))
+[GOOD] (define-fun s27 () Int (q2 false s3))
+[GOOD] (define-fun s28 () Bool (= s5 s27))
+[GOOD] (define-fun s30 () (_ FloatingPoint  8 24) (q3 s29 true s3))
+[GOOD] (define-fun s31 () Bool (fp.eq s29 s30))
+[GOOD] (define-fun s34 () (_ FloatingPoint  8 24) (q3 s32 true s33))
+[GOOD] (define-fun s35 () Bool (fp.isZero s34))
+[GOOD] (define-fun s36 () Bool (fp.isNegative s34))
+[GOOD] (define-fun s37 () Bool (and s35 s36))
+[GOOD] (define-fun s39 () (_ FloatingPoint  8 24) (q3 s32 false s38))
+[GOOD] (define-fun s41 () Bool (fp.eq s39 s40))
+[GOOD] (define-fun s44 () (_ FloatingPoint  8 24) (q4 s42 s43))
+[GOOD] (define-fun s46 () Bool (fp.eq s44 s45))
+[GOOD] (define-fun s48 () (_ FloatingPoint  8 24) (q4 s42 s47))
+[GOOD] (define-fun s50 () Bool (fp.eq s48 s49))
+[GOOD] (define-fun s53 () (_ FloatingPoint  8 24) (q4 s51 s52))
+[GOOD] (define-fun s55 () Bool (fp.eq s53 s54))
+[GOOD] (define-fun s58 () Int (q5 s56 s57))
+[GOOD] (define-fun s59 () Bool (= s23 s58))
+[GOOD] (define-fun s62 () Int (q5 s60 s61))
+[GOOD] (define-fun s64 () Bool (= s62 s63))
+[GOOD] (define-fun s67 () Int (q5 s65 s66))
+[GOOD] (define-fun s69 () Bool (= s67 s68))
+[GOOD] (define-fun s71 () Bool (q6 s70))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s8)
+[GOOD] (assert s12)
+[GOOD] (assert s16)
+[GOOD] (assert s22)
+[GOOD] (assert s26)
+[GOOD] (assert s28)
+[GOOD] (assert s31)
+[GOOD] (assert s37)
+[GOOD] (assert s41)
+[GOOD] (assert s46)
+[GOOD] (assert s50)
+[GOOD] (assert s55)
+[GOOD] (assert s59)
+[GOOD] (assert s64)
+[GOOD] (assert s69)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (store (store (store ((as const (Array Int Int)) 12) 3 75) (- 3) 9) 0 1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Int Int)) 5) false 7 6) false 12 3)))
+[SEND] (get-value (q3))
+[RECV] ((q3 (store (store ((as const
+                          (Array (_ FloatingPoint 8 24)
+                                 Bool
+                                 Int
+                                 (_ FloatingPoint 8 24)))
+                       (fp #b0 #x82 #b00010011001100110011010))
+                     (fp #b0 #x82 #b00110011001100110011010)
+                     true
+                     121
+                     (_ -zero 8 24))
+              (fp #b0 #x82 #b00110011001100110011010)
+              false
+              8
+              (_ +oo 8 24))))
+[SEND] (get-value (q4))
+[RECV] ((q4 (store (store ((as const (Array String String (_ FloatingPoint 8 24)))
+                       (fp #b0 #x85 #b00111000000000000000000))
+                     "c"
+                     "tey"
+                     (fp #b0 #x85 #b01110000000000000000000))
+              "r"
+              "foo"
+              (fp #b0 #x80 #b11000000000000000000000))))
+[SEND] (get-value (q5))
+[RECV] ((q5 (store (store ((as const (Array (Seq Int) (Seq (_ FloatingPoint 8 24)) Int)) 7)
+                     (seq.++ (seq.unit 9) (seq.unit 5))
+                     (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                             (seq.unit (fp #b0 #x82 #b00100000000000000000000)))
+                     21)
+              (seq.unit 5)
+              (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                      (seq.unit (_ +zero 8 24)))
+              210)))
+[SEND] (get-value (q6))
+[RECV] ((q6 (_ as-array q6)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:
+(Right ([(0,1),(-3,9),(3,75)],12),Right ([((False,12),3),((False,7),6)],5),Right ([((9.6,False,8),Infinity),((9.6,True,121),-0.0)],8.6),Right ([(('r',"foo"),3.5),(('c',"tey"),92.0)],78.0),Right ([(([5],[8.2,0.0]),210),(([9,5],[8.2,9.0]),21)],7),Right ([],False))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/query_uisatex3.gold b/SBVTestSuite/GoldFiles/query_uisatex3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_uisatex3.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun y (Int) Int)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s2 3))
+                                 (let ((l1_s1 (y l1_s0)))
+                                 (let ((l1_s3 (* l1_s0 l1_s2)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 l1_s4))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (y))
+[RECV] ((y (lambda ((x!1 Int)) (* 3 x!1))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:
+("y x = 3 * x",(True,Just ["x"],EApp [ECon "lambda",EApp [EApp [ECon "x!1",ECon "Int"]],EApp [ECon "*",ENum (3,Nothing,False),ECon "x!1"]]))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/query_yices.gold b/SBVTestSuite/GoldFiles/query_yices.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_yices.gold
@@ -0,0 +1,53 @@
+** Calling: yices-smt2 --incremental
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s3 :named |a > 0|))
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert (! s14 :named |a+b_<_12|))
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsge s0 s16))
+[GOOD] (assert (! s17 :named |extra|))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #b00000000000000000000000000000001))
+[SEND] (get-value (s1))
+[RECV] ((s1 #b00000000000000000000000000000001))
+*** Solver   : Yices
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query_z3.gold b/SBVTestSuite/GoldFiles/query_z3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_z3.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-logic ALL) ; external query, using all logics.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 32)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (_ BitVec 32)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (bvsgt s0 s2))
+[GOOD] (define-fun s4 () Bool (bvsgt s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (! s3 :named |a > 0|))
+[GOOD] (assert s4)
+[GOOD] (define-fun s5 () (_ BitVec 32) #x00000002)
+[GOOD] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[GOOD] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[GOOD] (define-fun s8 () Bool (bvsle s6 s7))
+[GOOD] (assert s8)
+[GOOD] (define-fun s9 () (_ BitVec 32) #x00000003)
+[GOOD] (define-fun s10 () Bool (bvslt s0 s9))
+[GOOD] (assert s10)
+[GOOD] (define-fun s11 () Bool (bvslt s1 s5))
+[GOOD] (assert s11)
+[GOOD] (define-fun s13 () (_ BitVec 32) #x0000000c)
+[GOOD] (define-fun s12 () (_ BitVec 32) (bvadd s0 s1))
+[GOOD] (define-fun s14 () Bool (bvslt s12 s13))
+[GOOD] (assert (! s14 :named |a+b_<_12|))
+[GOOD] (push 1)
+[GOOD] (define-fun s15 () Bool (bvslt s0 s5))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00000001))
+[GOOD] (pop 1)
+[GOOD] (define-fun s16 () (_ BitVec 32) #x00000001)
+[GOOD] (define-fun s17 () Bool (bvsgt s0 s16))
+[GOOD] (assert (! s17 :named |extra|))
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00000002))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x00000001))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/recursive10_mutual.gold b/SBVTestSuite/GoldFiles/recursive10_mutual.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive10_mutual.gold
@@ -0,0 +1,212 @@
+[MEASURE] Verifying termination measures for: mf @(SBV Integer -> SBV Integer), mg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: mf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {mf :: SBV Integer -> SBV Integer, mg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {mf @(SBV Integer -> SBV Integer), mg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mf @(SBV Integer -> SBV Integer), mg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for mf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {mf @(SBV Integer -> SBV Integer), mg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mf @(SBV Integer -> SBV Integer), mg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for mg @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure abs arg1 works for all members
+[MEASURE] Passed (terminating): mf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: mg @(SBV Integer -> SBV Integer)
+[MEASURE] mg @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): mg @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |mf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |mg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|mf @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|mg @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |mf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |mg @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|mg @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |mg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |mf @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|mf @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|mf @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive11_chain.gold b/SBVTestSuite/GoldFiles/recursive11_chain.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive11_chain.gold
@@ -0,0 +1,299 @@
+[MEASURE] Verifying termination measures for: ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: ca @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {ca :: SBV Integer -> SBV Integer, cb :: SBV Integer -> SBV Integer, cc :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for ca @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for cb @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ca @(SBV Integer -> SBV Integer), cb @(SBV Integer -> SBV Integer), cc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for cc @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure abs arg1 works for all members
+[MEASURE] Passed (terminating): ca @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: cb @(SBV Integer -> SBV Integer)
+[MEASURE] cb @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): cb @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: cc @(SBV Integer -> SBV Integer)
+[MEASURE] cc @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): cc @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |ca @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |cb @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |cc @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|ca @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|cb @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int)
+          (|cc @(SBV Integer -> SBV Integer)| ((l3_s0 Int)) Int))
+         (; Definition of: |ca @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |cb @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|cb @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |cb @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |cc @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|cc @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))
+          ; Definition of: |cc @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |ca @(SBV Integer -> SBV Integer)|]
+                                                                  (let ((l3_s1 0))
+                                                                  (let ((l3_s3 1))
+                                                                  (let ((l3_s2 (<= l3_s0 l3_s1)))
+                                                                  (let ((l3_s4 (- l3_s0 l3_s3)))
+                                                                  (let ((l3_s5 (|ca @(SBV Integer -> SBV Integer)| l3_s4)))
+                                                                  (let ((l3_s6 (+ l3_s3 l3_s5)))
+                                                                  (let ((l3_s7 (ite l3_s2 l3_s1 l3_s6)))
+                                                                  l3_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|ca @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive12_badMutual.gold b/SBVTestSuite/GoldFiles/recursive12_badMutual.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive12_badMutual.gold
@@ -0,0 +1,526 @@
+[MEASURE] Verifying termination measures for: bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {bf :: SBV Integer -> SBV Integer, bg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 1))
+[SEND] (get-value (s9))
+[RECV] ((s9 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 2 :: Integer
+[MEASURE] Mutual group: measure abs arg1 failed, trying next
+[MEASURE] Mutual group: trying measure smax 0 arg1 for all members
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (<= s1 s4))
+[GOOD] (define-fun s11 () Int (ite s10 s4 s1))
+[GOOD] (define-fun s12 () Bool (not s3))
+[GOOD] (define-fun s13 () Bool (> s9 s11))
+[GOOD] (define-fun s14 () Bool (=> s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s9))
+[RECV] ((s9 1))
+[SEND] (get-value (s11))
+[RECV] ((s11 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 2 :: Integer
+[MEASURE] Mutual group: measure smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure abs arg1 + smax 0 arg1 for all members
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Bool (>= s11 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () Int (+ s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Bool (> s11 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 2))
+[SEND] (get-value (s15))
+[RECV] ((s15 4))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 2 :: Integer
+  then   = 4 :: Integer
+[MEASURE] Mutual group: measure abs arg1 + smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure (abs arg1, smax 0 arg1) for all members
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s15))
+[RECV] ((s15 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     1 :: Integer
+  before = (1,1) :: (Integer, Integer)
+  then   = (2,2) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (abs arg1, smax 0 arg1) failed, trying next
+[MEASURE] Mutual group: trying measure (smax 0 arg1, abs arg1) for all members
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf @(SBV Integer -> SBV Integer), bg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s4))
+[GOOD] (define-fun s13 () Int (ite s12 s4 s1))
+[GOOD] (define-fun s14 () Int (abs s4))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s13 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s15))
+[RECV] ((s15 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     1 :: Integer
+  before = (1,1) :: (Integer, Integer)
+  then   = (2,2) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (smax 0 arg1, abs arg1) failed, trying next
+
+EXCEPTION:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     bf  :: SBV Integer -> SBV Integer
+***     bg  :: SBV Integer -> SBV Integer
+***
+*** Please use 'smtFunctionWithMeasure' to provide explicit measures.
+
diff --git a/SBVTestSuite/GoldFiles/recursive13_mutualMeasure.gold b/SBVTestSuite/GoldFiles/recursive13_mutualMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive13_mutualMeasure.gold
@@ -0,0 +1,212 @@
+[MEASURE] Verifying termination measures for: ef @(SBV Integer -> SBV Integer), eg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: ef @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {ef :: SBV Integer -> SBV Integer, eg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {ef @(SBV Integer -> SBV Integer), eg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ef @(SBV Integer -> SBV Integer), eg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for ef @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {ef @(SBV Integer -> SBV Integer), eg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ef @(SBV Integer -> SBV Integer), eg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for eg @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: user-provided measure works for all members
+[MEASURE] Passed (terminating): ef @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: eg @(SBV Integer -> SBV Integer)
+[MEASURE] eg @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): eg @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |ef @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |eg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|ef @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|eg @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |ef @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |eg @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|eg @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |eg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |ef @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|ef @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|ef @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive14_badMutualMeasure.gold b/SBVTestSuite/GoldFiles/recursive14_badMutualMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive14_badMutualMeasure.gold
@@ -0,0 +1,294 @@
+[MEASURE] Verifying termination measures for: hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: hf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {hf :: SBV Integer -> SBV Integer, hg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (not s3))
+[GOOD] (define-fun s9 () Bool (=> s8 false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for hf @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 1 :: Integer
+[MEASURE] Mutual group: user-provided measure failed, falling back to auto-guess
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for hf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {hf @(SBV Integer -> SBV Integer), hg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for hg @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure abs arg1 works for all members
+[MEASURE] Passed (terminating): hf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: hg @(SBV Integer -> SBV Integer)
+[MEASURE] hg @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): hg @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |hf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |hg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|hf @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|hg @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |hf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |hg @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|hg @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |hg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |hf @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|hf @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|hf @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive15_mixedMutualMeasure.gold b/SBVTestSuite/GoldFiles/recursive15_mixedMutualMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive15_mixedMutualMeasure.gold
@@ -0,0 +1,212 @@
+[MEASURE] Verifying termination measures for: xf @(SBV Integer -> SBV Integer), xg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: xf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {xf :: SBV Integer -> SBV Integer, xg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {xf @(SBV Integer -> SBV Integer), xg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {xf @(SBV Integer -> SBV Integer), xg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for xf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {xf @(SBV Integer -> SBV Integer), xg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {xf @(SBV Integer -> SBV Integer), xg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for xg @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: user-provided measure works for all members
+[MEASURE] Passed (terminating): xf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: xg @(SBV Integer -> SBV Integer)
+[MEASURE] xg @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): xg @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |xf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |xg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|xf @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|xg @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |xf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |xg @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|xg @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |xg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |xf @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|xf @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|xf @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive16_badMixedMutualMeasure.gold b/SBVTestSuite/GoldFiles/recursive16_badMixedMutualMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive16_badMixedMutualMeasure.gold
@@ -0,0 +1,1135 @@
+[MEASURE] Verifying termination measures for: yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: yf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {yf :: SBV Integer -> SBV Integer, yg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 1))
+[SEND] (get-value (s9))
+[RECV] ((s9 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 2 :: Integer
+[MEASURE] Mutual group: user-provided measure failed, falling back to auto-guess
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s8))
+[RECV] ((s8 1))
+[SEND] (get-value (s9))
+[RECV] ((s9 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 2 :: Integer
+[MEASURE] Mutual group: measure abs arg1 failed, trying next
+[MEASURE] Mutual group: trying measure smax 0 arg1 for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (<= s1 s4))
+[GOOD] (define-fun s11 () Int (ite s10 s4 s1))
+[GOOD] (define-fun s12 () Bool (not s3))
+[GOOD] (define-fun s13 () Bool (> s9 s11))
+[GOOD] (define-fun s14 () Bool (=> s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Bool (<= s1 s4))
+[GOOD] (define-fun s11 () Int (ite s10 s4 s1))
+[GOOD] (define-fun s12 () Bool (not s3))
+[GOOD] (define-fun s13 () Bool (> s9 s11))
+[GOOD] (define-fun s14 () Bool (=> s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s9))
+[RECV] ((s9 1))
+[SEND] (get-value (s11))
+[RECV] ((s11 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 1 :: Integer
+  then   = 2 :: Integer
+[MEASURE] Mutual group: measure smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure abs arg1 + smax 0 arg1 for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Bool (>= s11 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () Int (+ s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Bool (> s11 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Bool (>= s11 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () Int (+ s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () Int (+ s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Bool (> s11 s15))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 2))
+[SEND] (get-value (s15))
+[RECV] ((s15 4))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    = 1 :: Integer
+  before = 2 :: Integer
+  then   = 4 :: Integer
+[MEASURE] Mutual group: measure abs arg1 + smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure (abs arg1, smax 0 arg1) for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (<= s1 s0))
+[GOOD] (define-fun s10 () Int (ite s9 s0 s1))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s8 s10))
+[GOOD] (define-fun s12 () Int (abs s4))
+[GOOD] (define-fun s13 () Bool (<= s1 s4))
+[GOOD] (define-fun s14 () Int (ite s13 s4 s1))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s12 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s15))
+[RECV] ((s15 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     1 :: Integer
+  before = (1,1) :: (Integer, Integer)
+  then   = (2,2) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (abs arg1, smax 0 arg1) failed, trying next
+[MEASURE] Mutual group: trying measure (smax 0 arg1, abs arg1) for all members
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s4))
+[GOOD] (define-fun s13 () Int (ite s12 s4 s1))
+[GOOD] (define-fun s14 () Int (abs s4))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s13 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for yf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s13 () Bool (>= s12 s1))
+[GOOD] (define-fun s14 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Bool (and s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {yf @(SBV Integer -> SBV Integer), yg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (+ s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (<= s1 s0))
+[GOOD] (define-fun s9 () Int (ite s8 s0 s1))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s9 s10))
+[GOOD] (define-fun s12 () Bool (<= s1 s4))
+[GOOD] (define-fun s13 () Int (ite s12 s4 s1))
+[GOOD] (define-fun s14 () Int (abs s4))
+[GOOD] (define-fun s15 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s13 s14))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s15))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s11))
+[GOOD] (define-fun s19 () Bool (< s17 s18))
+[GOOD] (define-fun s20 () Bool (= s17 s18))
+[GOOD] (define-fun s21 () Int (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () Int (proj_2_SBVTuple2 s11))
+[GOOD] (define-fun s23 () Bool (< s21 s22))
+[GOOD] (define-fun s24 () Bool (and s20 s23))
+[GOOD] (define-fun s25 () Bool (or s19 s24))
+[GOOD] (define-fun s26 () Bool (=> s16 s25))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s26))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s15))
+[RECV] ((s15 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for yg @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg    =     1 :: Integer
+  before = (1,1) :: (Integer, Integer)
+  then   = (2,2) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (smax 0 arg1, abs arg1) failed, trying next
+
+EXCEPTION:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     yf  :: SBV Integer -> SBV Integer
+***     yg  :: SBV Integer -> SBV Integer
+***
+*** The user-provided measure did not work, and auto-guessing also failed.
+
diff --git a/SBVTestSuite/GoldFiles/recursive17_chainMeasure.gold b/SBVTestSuite/GoldFiles/recursive17_chainMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive17_chainMeasure.gold
@@ -0,0 +1,299 @@
+[MEASURE] Verifying termination measures for: da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: da @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {da :: SBV Integer -> SBV Integer, db :: SBV Integer -> SBV Integer, dc :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for da @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for db @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {da @(SBV Integer -> SBV Integer), db @(SBV Integer -> SBV Integer), dc @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for dc @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: user-provided measure works for all members
+[MEASURE] Passed (terminating): da @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: db @(SBV Integer -> SBV Integer)
+[MEASURE] db @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): db @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: dc @(SBV Integer -> SBV Integer)
+[MEASURE] dc @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): dc @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |da @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |db @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |dc @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|da @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|db @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int)
+          (|dc @(SBV Integer -> SBV Integer)| ((l3_s0 Int)) Int))
+         (; Definition of: |da @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |db @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|db @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |db @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |dc @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|dc @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))
+          ; Definition of: |dc @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |da @(SBV Integer -> SBV Integer)|]
+                                                                  (let ((l3_s1 0))
+                                                                  (let ((l3_s3 1))
+                                                                  (let ((l3_s2 (<= l3_s0 l3_s1)))
+                                                                  (let ((l3_s4 (- l3_s0 l3_s3)))
+                                                                  (let ((l3_s5 (|da @(SBV Integer -> SBV Integer)| l3_s4)))
+                                                                  (let ((l3_s6 (+ l3_s3 l3_s5)))
+                                                                  (let ((l3_s7 (ite l3_s2 l3_s1 l3_s6)))
+                                                                  l3_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|da @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive19_selfAndMutual.gold b/SBVTestSuite/GoldFiles/recursive19_selfAndMutual.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive19_selfAndMutual.gold
@@ -0,0 +1,297 @@
+[MEASURE] Verifying termination measures for: sf @(SBV Integer -> SBV Integer), sf @(SBV Integer -> SBV Integer), sg @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: sf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {sf :: SBV Integer -> SBV Integer, sg :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer), sg @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer), sg @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for sf @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer), sg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer), sg @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for sg @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure abs arg1 works for all members
+[MEASURE] Passed (terminating): sf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: sf @(SBV Integer -> SBV Integer)
+[MEASURE] sf @(SBV Integer -> SBV Integer): barified = "|sf @(SBV Integer -> SBV Integer)|"
+[MEASURE] sf @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|sf @(SBV Integer -> SBV Integer)|",1),("|sg @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] sf @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] sf @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {sf @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] sf @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): sf @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: sg @(SBV Integer -> SBV Integer)
+[MEASURE] sg @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): sg @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |sf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |sg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|sf @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|sg @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |sf @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |sf @(SBV Integer -> SBV Integer)|, |sg @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|sf @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (|sg @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                  (let ((l1_s8 (ite l1_s2 l1_s1 l1_s7)))
+                                  l1_s8))))))))
+          ; Definition of: |sg @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |sf @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|sf @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|sf @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive1_ack.gold b/SBVTestSuite/GoldFiles/recursive1_ack.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive1_ack.gold
@@ -0,0 +1,1003 @@
+[MEASURE] Verifying termination measures for: ack @(SBV Integer -> SBV Integer -> SBV Integer)
+[MEASURE] Checking: ack @(SBV Integer -> SBV Integer -> SBV Integer)
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): barified = "|ack @(SBV Integer -> SBV Integer -> SBV Integer)|"
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|ack @(SBV Integer -> SBV Integer -> SBV Integer)|",2),("|ack @(SBV Integer -> SBV Integer -> SBV Integer)|",2),("|ack @(SBV Integer -> SBV Integer -> SBV Integer)|",2)]
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): recursive calls found = 3
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Bool (>= s14 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Int (abs s7))
+[GOOD] (define-fun s16 () Bool (not s4))
+[GOOD] (define-fun s17 () Bool (and s6 s16))
+[GOOD] (define-fun s18 () Bool (> s14 s15))
+[GOOD] (define-fun s19 () Bool (=> s17 s18))
+[GOOD] (define-fun s20 () Bool (not s6))
+[GOOD] (define-fun s21 () Bool (and s16 s20))
+[GOOD] (define-fun s22 () Bool (=> s21 false))
+[GOOD] (define-fun s23 () Bool (=> s21 s18))
+[GOOD] (define-fun s24 () Bool (and s22 s23))
+[GOOD] (define-fun s25 () Bool (and s19 s24))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 2))
+[SEND] (get-value (s15))
+[RECV] ((s15 1))
+[SEND] (get-value (s14))
+[RECV] ((s14 2))
+[SEND] (get-value (s15))
+[RECV] ((s15 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 0))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): abs arg1 failed strict decrease: Falsifiable. Counter-example:
+  arg0    = 2 :: Integer
+  arg1    = 1 :: Integer
+  before  = 2 :: Integer
+  then[1] = 1 :: Integer
+  then[2] = 2 :: Integer
+  then[3] = 1 :: Integer
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying smax 0 arg1
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Bool (<= s2 s0))
+[GOOD] (define-fun s15 () Int (ite s14 s0 s2))
+[GOOD] (define-fun s16 () Bool (>= s15 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Bool (<= s2 s0))
+[GOOD] (define-fun s15 () Int (ite s14 s0 s2))
+[GOOD] (define-fun s16 () Bool (<= s2 s7))
+[GOOD] (define-fun s17 () Int (ite s16 s7 s2))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s15 s17))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] (define-fun s22 () Bool (not s6))
+[GOOD] (define-fun s23 () Bool (and s18 s22))
+[GOOD] (define-fun s24 () Bool (=> s23 false))
+[GOOD] (define-fun s25 () Bool (=> s23 s20))
+[GOOD] (define-fun s26 () Bool (and s24 s25))
+[GOOD] (define-fun s27 () Bool (and s21 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s27))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s15))
+[RECV] ((s15 2))
+[SEND] (get-value (s17))
+[RECV] ((s17 1))
+[SEND] (get-value (s15))
+[RECV] ((s15 2))
+[SEND] (get-value (s17))
+[RECV] ((s17 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 0))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): smax 0 arg1 failed strict decrease: Falsifiable. Counter-example:
+  arg0    = 2 :: Integer
+  arg1    = 1 :: Integer
+  before  = 2 :: Integer
+  then[1] = 1 :: Integer
+  then[2] = 2 :: Integer
+  then[3] = 1 :: Integer
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying abs arg2
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s1))
+[GOOD] (define-fun s15 () Bool (>= s14 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s1))
+[GOOD] (define-fun s15 () Int (abs s3))
+[GOOD] (define-fun s16 () Int (abs s9))
+[GOOD] (define-fun s17 () Int (abs s10))
+[GOOD] (define-fun s18 () Bool (not s4))
+[GOOD] (define-fun s19 () Bool (and s6 s18))
+[GOOD] (define-fun s20 () Bool (> s14 s15))
+[GOOD] (define-fun s21 () Bool (=> s19 s20))
+[GOOD] (define-fun s22 () Bool (not s6))
+[GOOD] (define-fun s23 () Bool (and s18 s22))
+[GOOD] (define-fun s24 () Bool (> s14 s16))
+[GOOD] (define-fun s25 () Bool (=> s23 s24))
+[GOOD] (define-fun s26 () Bool (> s14 s17))
+[GOOD] (define-fun s27 () Bool (=> s23 s26))
+[GOOD] (define-fun s28 () Bool (and s25 s27))
+[GOOD] (define-fun s29 () Bool (and s21 s28))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s29))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s14))
+[RECV] ((s14 1))
+[SEND] (get-value (s15))
+[RECV] ((s15 1))
+[SEND] (get-value (s16))
+[RECV] ((s16 2))
+[SEND] (get-value (s17))
+[RECV] ((s17 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 (- 1)))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 (- 1)))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): abs arg2 failed strict decrease: Falsifiable. Counter-example:
+  arg0    =  1 :: Integer
+  arg1    = -1 :: Integer
+  before  =  1 :: Integer
+  then[1] =  1 :: Integer
+  then[2] =  2 :: Integer
+  then[3] =  1 :: Integer
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying smax 0 arg2
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Bool (<= s2 s1))
+[GOOD] (define-fun s15 () Int (ite s14 s1 s2))
+[GOOD] (define-fun s16 () Bool (>= s15 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s16))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Bool (<= s2 s1))
+[GOOD] (define-fun s15 () Int (ite s14 s1 s2))
+[GOOD] (define-fun s16 () Bool (<= s2 s3))
+[GOOD] (define-fun s17 () Int (ite s16 s3 s2))
+[GOOD] (define-fun s18 () Bool (<= s2 s9))
+[GOOD] (define-fun s19 () Int (ite s18 s9 s2))
+[GOOD] (define-fun s20 () Bool (<= s2 s10))
+[GOOD] (define-fun s21 () Int (ite s20 s10 s2))
+[GOOD] (define-fun s22 () Bool (not s4))
+[GOOD] (define-fun s23 () Bool (and s6 s22))
+[GOOD] (define-fun s24 () Bool (> s15 s17))
+[GOOD] (define-fun s25 () Bool (=> s23 s24))
+[GOOD] (define-fun s26 () Bool (not s6))
+[GOOD] (define-fun s27 () Bool (and s22 s26))
+[GOOD] (define-fun s28 () Bool (> s15 s19))
+[GOOD] (define-fun s29 () Bool (=> s27 s28))
+[GOOD] (define-fun s30 () Bool (> s15 s21))
+[GOOD] (define-fun s31 () Bool (=> s27 s30))
+[GOOD] (define-fun s32 () Bool (and s29 s31))
+[GOOD] (define-fun s33 () Bool (and s25 s32))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s33))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s15))
+[RECV] ((s15 2))
+[SEND] (get-value (s17))
+[RECV] ((s17 1))
+[SEND] (get-value (s19))
+[RECV] ((s19 1))
+[SEND] (get-value (s21))
+[RECV] ((s21 2))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 2))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): smax 0 arg2 failed strict decrease: Falsifiable. Counter-example:
+  arg0    = 1 :: Integer
+  arg1    = 2 :: Integer
+  before  = 2 :: Integer
+  then[1] = 1 :: Integer
+  then[2] = 1 :: Integer
+  then[3] = 2 :: Integer
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying abs arg1 + smax 0 arg1 + abs arg2 + smax 0 arg2
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Bool (<= s2 s0))
+[GOOD] (define-fun s16 () Int (ite s15 s0 s2))
+[GOOD] (define-fun s17 () Int (+ s14 s16))
+[GOOD] (define-fun s18 () Int (abs s1))
+[GOOD] (define-fun s19 () Int (+ s17 s18))
+[GOOD] (define-fun s20 () Bool (<= s2 s1))
+[GOOD] (define-fun s21 () Int (ite s20 s1 s2))
+[GOOD] (define-fun s22 () Int (+ s19 s21))
+[GOOD] (define-fun s23 () Bool (>= s22 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s23))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Bool (<= s2 s0))
+[GOOD] (define-fun s16 () Int (ite s15 s0 s2))
+[GOOD] (define-fun s17 () Int (+ s14 s16))
+[GOOD] (define-fun s18 () Int (abs s1))
+[GOOD] (define-fun s19 () Int (+ s17 s18))
+[GOOD] (define-fun s20 () Bool (<= s2 s1))
+[GOOD] (define-fun s21 () Int (ite s20 s1 s2))
+[GOOD] (define-fun s22 () Int (+ s19 s21))
+[GOOD] (define-fun s23 () Int (abs s7))
+[GOOD] (define-fun s24 () Bool (<= s2 s7))
+[GOOD] (define-fun s25 () Int (ite s24 s7 s2))
+[GOOD] (define-fun s26 () Int (+ s23 s25))
+[GOOD] (define-fun s27 () Int (abs s3))
+[GOOD] (define-fun s28 () Int (+ s26 s27))
+[GOOD] (define-fun s29 () Bool (<= s2 s3))
+[GOOD] (define-fun s30 () Int (ite s29 s3 s2))
+[GOOD] (define-fun s31 () Int (+ s28 s30))
+[GOOD] (define-fun s32 () Int (abs s9))
+[GOOD] (define-fun s33 () Int (+ s17 s32))
+[GOOD] (define-fun s34 () Bool (<= s2 s9))
+[GOOD] (define-fun s35 () Int (ite s34 s9 s2))
+[GOOD] (define-fun s36 () Int (+ s33 s35))
+[GOOD] (define-fun s37 () Int (abs s10))
+[GOOD] (define-fun s38 () Int (+ s26 s37))
+[GOOD] (define-fun s39 () Bool (<= s2 s10))
+[GOOD] (define-fun s40 () Int (ite s39 s10 s2))
+[GOOD] (define-fun s41 () Int (+ s38 s40))
+[GOOD] (define-fun s42 () Bool (not s4))
+[GOOD] (define-fun s43 () Bool (and s6 s42))
+[GOOD] (define-fun s44 () Bool (> s22 s31))
+[GOOD] (define-fun s45 () Bool (=> s43 s44))
+[GOOD] (define-fun s46 () Bool (not s6))
+[GOOD] (define-fun s47 () Bool (and s42 s46))
+[GOOD] (define-fun s48 () Bool (> s22 s36))
+[GOOD] (define-fun s49 () Bool (=> s47 s48))
+[GOOD] (define-fun s50 () Bool (> s22 s41))
+[GOOD] (define-fun s51 () Bool (=> s47 s50))
+[GOOD] (define-fun s52 () Bool (and s49 s51))
+[GOOD] (define-fun s53 () Bool (and s45 s52))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s53))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s22))
+[RECV] ((s22 8))
+[SEND] (get-value (s31))
+[RECV] ((s31 4))
+[SEND] (get-value (s36))
+[RECV] ((s36 6))
+[SEND] (get-value (s41))
+[RECV] ((s41 8))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 2))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 (- 6)))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): abs arg1 + smax 0 arg1 + abs arg2 + smax 0 arg2 failed strict decrease: Falsifiable. Counter-example:
+  arg0    = 2 :: Integer
+  arg1    = 2 :: Integer
+  before  = 8 :: Integer
+  then[1] = 4 :: Integer
+  then[2] = 6 :: Integer
+  then[3] = 8 :: Integer
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying (abs arg1, smax 0 arg1)
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Bool (<= s2 s0))
+[GOOD] (define-fun s16 () Int (ite s15 s0 s2))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s16))
+[GOOD] (define-fun s18 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s19 () Bool (>= s18 s2))
+[GOOD] (define-fun s20 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s21 () Bool (>= s20 s2))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s22))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Bool (<= s2 s0))
+[GOOD] (define-fun s16 () Int (ite s15 s0 s2))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s16))
+[GOOD] (define-fun s18 () Int (abs s7))
+[GOOD] (define-fun s19 () Bool (<= s2 s7))
+[GOOD] (define-fun s20 () Int (ite s19 s7 s2))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Bool (not s4))
+[GOOD] (define-fun s23 () Bool (and s6 s22))
+[GOOD] (define-fun s24 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s25 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s26 () Bool (< s24 s25))
+[GOOD] (define-fun s27 () Bool (= s24 s25))
+[GOOD] (define-fun s28 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s29 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s30 () Bool (< s28 s29))
+[GOOD] (define-fun s31 () Bool (and s27 s30))
+[GOOD] (define-fun s32 () Bool (or s26 s31))
+[GOOD] (define-fun s33 () Bool (=> s23 s32))
+[GOOD] (define-fun s34 () Bool (not s6))
+[GOOD] (define-fun s35 () Bool (and s22 s34))
+[GOOD] (define-fun s36 () Bool (=> s35 false))
+[GOOD] (define-fun s37 () Bool (=> s35 s32))
+[GOOD] (define-fun s38 () Bool (and s36 s37))
+[GOOD] (define-fun s39 () Bool (and s33 s38))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s39))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s17))
+[RECV] ((s17 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s21))
+[RECV] ((s21 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s17))
+[RECV] ((s17 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s21))
+[RECV] ((s21 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 1))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s10))
+[RECV] ((s10 0))
+[SEND] (get-value (s11))
+[RECV] ((s11 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): (abs arg1, smax 0 arg1) failed strict decrease: Falsifiable. Counter-example:
+  arg0    =     2 :: Integer
+  arg1    =     1 :: Integer
+  before  = (2,2) :: (Integer, Integer)
+  then[1] = (1,1) :: (Integer, Integer)
+  then[2] = (2,2) :: (Integer, Integer)
+  then[3] = (1,1) :: (Integer, Integer)
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying next candidate..
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): trying (abs arg1, abs arg2)
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Int (abs s1))
+[GOOD] (define-fun s16 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s15))
+[GOOD] (define-fun s17 () Int (proj_1_SBVTuple2 s16))
+[GOOD] (define-fun s18 () Bool (>= s17 s2))
+[GOOD] (define-fun s19 () Int (proj_2_SBVTuple2 s16))
+[GOOD] (define-fun s20 () Bool (>= s19 s2))
+[GOOD] (define-fun s21 () Bool (and s18 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {ack @(SBV Integer -> SBV Integer -> SBV Integer)}: replaying 10 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 0)
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
+[GOOD] (declare-fun s11 () Int) ; tracks user variable "__internal_sbv_s11"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (<= s0 s2))
+[GOOD] (define-fun s5 () Int (+ s1 s3))
+[GOOD] (define-fun s6 () Bool (<= s1 s2))
+[GOOD] (define-fun s7 () Int (- s0 s3))
+[GOOD] (define-fun s9 () Int (- s1 s3))
+[GOOD] (define-fun s12 () Int (ite s6 s8 s11))
+[GOOD] (define-fun s13 () Int (ite s4 s5 s12))
+[GOOD] (define-fun s14 () Int (abs s0))
+[GOOD] (define-fun s15 () Int (abs s1))
+[GOOD] (define-fun s16 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s15))
+[GOOD] (define-fun s17 () Int (abs s7))
+[GOOD] (define-fun s18 () Int (abs s3))
+[GOOD] (define-fun s19 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s17 s18))
+[GOOD] (define-fun s20 () Int (abs s9))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s20))
+[GOOD] (define-fun s22 () Int (abs s10))
+[GOOD] (define-fun s23 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s17 s22))
+[GOOD] (define-fun s24 () Bool (not s4))
+[GOOD] (define-fun s25 () Bool (and s6 s24))
+[GOOD] (define-fun s26 () Int (proj_1_SBVTuple2 s19))
+[GOOD] (define-fun s27 () Int (proj_1_SBVTuple2 s16))
+[GOOD] (define-fun s28 () Bool (< s26 s27))
+[GOOD] (define-fun s29 () Bool (= s26 s27))
+[GOOD] (define-fun s30 () Int (proj_2_SBVTuple2 s19))
+[GOOD] (define-fun s31 () Int (proj_2_SBVTuple2 s16))
+[GOOD] (define-fun s32 () Bool (< s30 s31))
+[GOOD] (define-fun s33 () Bool (and s29 s32))
+[GOOD] (define-fun s34 () Bool (or s28 s33))
+[GOOD] (define-fun s35 () Bool (=> s25 s34))
+[GOOD] (define-fun s36 () Bool (not s6))
+[GOOD] (define-fun s37 () Bool (and s24 s36))
+[GOOD] (define-fun s38 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s39 () Bool (< s38 s27))
+[GOOD] (define-fun s40 () Bool (= s27 s38))
+[GOOD] (define-fun s41 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s42 () Bool (< s41 s31))
+[GOOD] (define-fun s43 () Bool (and s40 s42))
+[GOOD] (define-fun s44 () Bool (or s39 s43))
+[GOOD] (define-fun s45 () Bool (=> s37 s44))
+[GOOD] (define-fun s46 () Int (proj_1_SBVTuple2 s23))
+[GOOD] (define-fun s47 () Bool (< s46 s27))
+[GOOD] (define-fun s48 () Bool (= s27 s46))
+[GOOD] (define-fun s49 () Int (proj_2_SBVTuple2 s23))
+[GOOD] (define-fun s50 () Bool (< s49 s31))
+[GOOD] (define-fun s51 () Bool (and s48 s50))
+[GOOD] (define-fun s52 () Bool (or s47 s51))
+[GOOD] (define-fun s53 () Bool (=> s37 s52))
+[GOOD] (define-fun s54 () Bool (and s45 s53))
+[GOOD] (define-fun s55 () Bool (and s35 s54))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s55))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] ack @(SBV Integer -> SBV Integer -> SBV Integer): (abs arg1, abs arg2) -> OK
+[MEASURE] Passed (terminating): ack @(SBV Integer -> SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 5)
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] (declare-fun s1 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |ack @(SBV Integer -> SBV Integer -> SBV Integer)| :: SInteger -> SInteger -> SInteger [Recursive]
+[GOOD] (define-fun-rec |ack @(SBV Integer -> SBV Integer -> SBV Integer)| ((l1_s0 Int) (l1_s1 Int)) Int
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 1))
+                                 (let ((l1_s3 (<= l1_s0 l1_s2)))
+                                 (let ((l1_s5 (+ l1_s1 l1_s4)))
+                                 (let ((l1_s6 (<= l1_s1 l1_s2)))
+                                 (let ((l1_s7 (- l1_s0 l1_s4)))
+                                 (let ((l1_s8 (|ack @(SBV Integer -> SBV Integer -> SBV Integer)| l1_s7 l1_s4)))
+                                 (let ((l1_s9 (- l1_s1 l1_s4)))
+                                 (let ((l1_s10 (|ack @(SBV Integer -> SBV Integer -> SBV Integer)| l1_s0 l1_s9)))
+                                 (let ((l1_s11 (|ack @(SBV Integer -> SBV Integer -> SBV Integer)| l1_s7 l1_s10)))
+                                 (let ((l1_s12 (ite l1_s6 l1_s8 l1_s11)))
+                                 (let ((l1_s13 (ite l1_s3 l1_s5 l1_s12)))
+                                 l1_s13)))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Int (|ack @(SBV Integer -> SBV Integer -> SBV Integer)| s4 s0))
+[GOOD] (define-fun s6 () Bool (= s1 s5))
+[GOOD] (define-fun s7 () Bool (and s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 5))
+[SEND] (get-value (s1))
+[RECV] ((s1 7))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 5 :: Integer
+  s1 = 7 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive20_mutualTP.gold b/SBVTestSuite/GoldFiles/recursive20_mutualTP.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive20_mutualTP.gold
@@ -0,0 +1,221 @@
+[MEASURE] checkNewMeasures: 2 to verify
+[MEASURE] checkNewMeasures: verifying mf_tp @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {mf_tp :: SBV Integer -> SBV Integer, mg_tp :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {mf_tp @(SBV Integer -> SBV Integer), mg_tp @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mf_tp @(SBV Integer -> SBV Integer), mg_tp @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for mf_tp @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {mf_tp @(SBV Integer -> SBV Integer), mg_tp @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mf_tp @(SBV Integer -> SBV Integer), mg_tp @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for mg_tp @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: measure abs arg1 works for all members
+[MEASURE] checkNewMeasures: mf_tp @(SBV Integer -> SBV Integer) verified
+[MEASURE] checkNewMeasures: verifying mg_tp @(SBV Integer -> SBV Integer)
+[MEASURE] mg_tp @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] checkNewMeasures: mg_tp @(SBV Integer -> SBV Integer) verified
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "__internal_sbv_s0"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |mf_tp @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |mg_tp @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|mf_tp @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|mg_tp @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |mf_tp @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |mg_tp @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|mg_tp @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                  (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                  l1_s7)))))))
+          ; Definition of: |mg_tp @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |mf_tp @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|mf_tp @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (+ l2_s3 l2_s5)))
+                                                  (let ((l2_s7 (ite l2_s2 l2_s1 l2_s6)))
+                                                  l2_s7)))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Int (|mf_tp @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (define-fun s5 () Bool (=> s2 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+; smtProofStep: No context value to push.
+Lemma: mutual_at_0
+[GOOD] (define-fun s6 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (|mf_tp @(SBV Integer -> SBV Integer)| l1_s0)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 (let ((l1_s5 (=> l1_s2 l1_s4)))
+                                 l1_s5)))))))
+[GOOD] (define-fun s7 () Bool (not s6))
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] unsat
+    Q.E.D.
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+Functions proven terminating: mf_tp, mg_tp
diff --git a/SBVTestSuite/GoldFiles/recursive21_allSelfBadCross.gold b/SBVTestSuite/GoldFiles/recursive21_allSelfBadCross.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive21_allSelfBadCross.gold
@@ -0,0 +1,613 @@
+[MEASURE] Verifying termination measures for: bf21 @(SBV Integer -> SBV Integer), bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bf21 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {bf21 :: SBV Integer -> SBV Integer, bg21 :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying measure abs arg1 for all members
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Bool (>= s10 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s11))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Int (abs s4))
+[GOOD] (define-fun s12 () Int (abs s6))
+[GOOD] (define-fun s13 () Bool (not s3))
+[GOOD] (define-fun s14 () Bool (> s10 s11))
+[GOOD] (define-fun s15 () Bool (=> s13 s14))
+[GOOD] (define-fun s16 () Bool (> s10 s12))
+[GOOD] (define-fun s17 () Bool (=> s13 s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s10))
+[RECV] ((s10 2))
+[SEND] (get-value (s11))
+[RECV] ((s11 1))
+[SEND] (get-value (s12))
+[RECV] ((s12 3))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf21 @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     = 2 :: Integer
+  before  = 2 :: Integer
+  then[1] = 1 :: Integer
+  then[2] = 3 :: Integer
+[MEASURE] Mutual group: measure abs arg1 failed, trying next
+[MEASURE] Mutual group: trying measure smax 0 arg1 for all members
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s0))
+[GOOD] (define-fun s11 () Int (ite s10 s0 s1))
+[GOOD] (define-fun s12 () Bool (>= s11 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s0))
+[GOOD] (define-fun s11 () Int (ite s10 s0 s1))
+[GOOD] (define-fun s12 () Bool (<= s1 s4))
+[GOOD] (define-fun s13 () Int (ite s12 s4 s1))
+[GOOD] (define-fun s14 () Bool (<= s1 s6))
+[GOOD] (define-fun s15 () Int (ite s14 s6 s1))
+[GOOD] (define-fun s16 () Bool (not s3))
+[GOOD] (define-fun s17 () Bool (> s11 s13))
+[GOOD] (define-fun s18 () Bool (=> s16 s17))
+[GOOD] (define-fun s19 () Bool (> s11 s15))
+[GOOD] (define-fun s20 () Bool (=> s16 s19))
+[GOOD] (define-fun s21 () Bool (and s18 s20))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s21))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s11))
+[RECV] ((s11 2))
+[SEND] (get-value (s13))
+[RECV] ((s13 1))
+[SEND] (get-value (s15))
+[RECV] ((s15 3))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf21 @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     = 2 :: Integer
+  before  = 2 :: Integer
+  then[1] = 1 :: Integer
+  then[2] = 3 :: Integer
+[MEASURE] Mutual group: measure smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure abs arg1 + smax 0 arg1 for all members
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Bool (<= s1 s0))
+[GOOD] (define-fun s12 () Int (ite s11 s0 s1))
+[GOOD] (define-fun s13 () Int (+ s10 s12))
+[GOOD] (define-fun s14 () Bool (>= s13 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s14))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Bool (<= s1 s0))
+[GOOD] (define-fun s12 () Int (ite s11 s0 s1))
+[GOOD] (define-fun s13 () Int (+ s10 s12))
+[GOOD] (define-fun s14 () Int (abs s4))
+[GOOD] (define-fun s15 () Bool (<= s1 s4))
+[GOOD] (define-fun s16 () Int (ite s15 s4 s1))
+[GOOD] (define-fun s17 () Int (+ s14 s16))
+[GOOD] (define-fun s18 () Int (abs s6))
+[GOOD] (define-fun s19 () Bool (<= s1 s6))
+[GOOD] (define-fun s20 () Int (ite s19 s6 s1))
+[GOOD] (define-fun s21 () Int (+ s18 s20))
+[GOOD] (define-fun s22 () Bool (not s3))
+[GOOD] (define-fun s23 () Bool (> s13 s17))
+[GOOD] (define-fun s24 () Bool (=> s22 s23))
+[GOOD] (define-fun s25 () Bool (> s13 s21))
+[GOOD] (define-fun s26 () Bool (=> s22 s25))
+[GOOD] (define-fun s27 () Bool (and s24 s26))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s27))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s13))
+[RECV] ((s13 4))
+[SEND] (get-value (s17))
+[RECV] ((s17 2))
+[SEND] (get-value (s21))
+[RECV] ((s21 6))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf21 @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     = 2 :: Integer
+  before  = 4 :: Integer
+  then[1] = 2 :: Integer
+  then[2] = 6 :: Integer
+[MEASURE] Mutual group: measure abs arg1 + smax 0 arg1 failed, trying next
+[MEASURE] Mutual group: trying measure (abs arg1, smax 0 arg1) for all members
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Bool (<= s1 s0))
+[GOOD] (define-fun s12 () Int (ite s11 s0 s1))
+[GOOD] (define-fun s13 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s10 s12))
+[GOOD] (define-fun s14 () Int (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Int (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () Bool (>= s16 s1))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Int (abs s0))
+[GOOD] (define-fun s11 () Bool (<= s1 s0))
+[GOOD] (define-fun s12 () Int (ite s11 s0 s1))
+[GOOD] (define-fun s13 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s10 s12))
+[GOOD] (define-fun s14 () Int (abs s4))
+[GOOD] (define-fun s15 () Bool (<= s1 s4))
+[GOOD] (define-fun s16 () Int (ite s15 s4 s1))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s14 s16))
+[GOOD] (define-fun s18 () Int (abs s6))
+[GOOD] (define-fun s19 () Bool (<= s1 s6))
+[GOOD] (define-fun s20 () Int (ite s19 s6 s1))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s18 s20))
+[GOOD] (define-fun s22 () Bool (not s3))
+[GOOD] (define-fun s23 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s24 () Int (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s25 () Bool (< s23 s24))
+[GOOD] (define-fun s26 () Bool (= s23 s24))
+[GOOD] (define-fun s27 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Int (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s29 () Bool (< s27 s28))
+[GOOD] (define-fun s30 () Bool (and s26 s29))
+[GOOD] (define-fun s31 () Bool (or s25 s30))
+[GOOD] (define-fun s32 () Bool (=> s22 s31))
+[GOOD] (define-fun s33 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s34 () Bool (< s33 s24))
+[GOOD] (define-fun s35 () Bool (= s24 s33))
+[GOOD] (define-fun s36 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s37 () Bool (< s36 s28))
+[GOOD] (define-fun s38 () Bool (and s35 s37))
+[GOOD] (define-fun s39 () Bool (or s34 s38))
+[GOOD] (define-fun s40 () Bool (=> s22 s39))
+[GOOD] (define-fun s41 () Bool (and s32 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s41))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s13))
+[RECV] ((s13 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s17))
+[RECV] ((s17 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s21))
+[RECV] ((s21 (mkSBVTuple2 3 3)))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf21 @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     =     2 :: Integer
+  before  = (2,2) :: (Integer, Integer)
+  then[1] = (1,1) :: (Integer, Integer)
+  then[2] = (3,3) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (abs arg1, smax 0 arg1) failed, trying next
+[MEASURE] Mutual group: trying measure (smax 0 arg1, abs arg1) for all members
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s0))
+[GOOD] (define-fun s11 () Int (ite s10 s0 s1))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s11 s12))
+[GOOD] (define-fun s14 () Int (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s15 () Bool (>= s14 s1))
+[GOOD] (define-fun s16 () Int (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s17 () Bool (>= s16 s1))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf21 @(SBV Integer -> SBV Integer), bg21 @(SBV Integer -> SBV Integer)}: replaying 7 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s8 () Int (+ s5 s7))
+[GOOD] (define-fun s9 () Int (ite s3 s1 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s0))
+[GOOD] (define-fun s11 () Int (ite s10 s0 s1))
+[GOOD] (define-fun s12 () Int (abs s0))
+[GOOD] (define-fun s13 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s11 s12))
+[GOOD] (define-fun s14 () Bool (<= s1 s4))
+[GOOD] (define-fun s15 () Int (ite s14 s4 s1))
+[GOOD] (define-fun s16 () Int (abs s4))
+[GOOD] (define-fun s17 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s15 s16))
+[GOOD] (define-fun s18 () Bool (<= s1 s6))
+[GOOD] (define-fun s19 () Int (ite s18 s6 s1))
+[GOOD] (define-fun s20 () Int (abs s6))
+[GOOD] (define-fun s21 () (SBVTuple2 Int Int) ((as mkSBVTuple2 (SBVTuple2 Int Int)) s19 s20))
+[GOOD] (define-fun s22 () Bool (not s3))
+[GOOD] (define-fun s23 () Int (proj_1_SBVTuple2 s17))
+[GOOD] (define-fun s24 () Int (proj_1_SBVTuple2 s13))
+[GOOD] (define-fun s25 () Bool (< s23 s24))
+[GOOD] (define-fun s26 () Bool (= s23 s24))
+[GOOD] (define-fun s27 () Int (proj_2_SBVTuple2 s17))
+[GOOD] (define-fun s28 () Int (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s29 () Bool (< s27 s28))
+[GOOD] (define-fun s30 () Bool (and s26 s29))
+[GOOD] (define-fun s31 () Bool (or s25 s30))
+[GOOD] (define-fun s32 () Bool (=> s22 s31))
+[GOOD] (define-fun s33 () Int (proj_1_SBVTuple2 s21))
+[GOOD] (define-fun s34 () Bool (< s33 s24))
+[GOOD] (define-fun s35 () Bool (= s24 s33))
+[GOOD] (define-fun s36 () Int (proj_2_SBVTuple2 s21))
+[GOOD] (define-fun s37 () Bool (< s36 s28))
+[GOOD] (define-fun s38 () Bool (and s35 s37))
+[GOOD] (define-fun s39 () Bool (or s34 s38))
+[GOOD] (define-fun s40 () Bool (=> s22 s39))
+[GOOD] (define-fun s41 () Bool (and s32 s40))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s41))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s13))
+[RECV] ((s13 (mkSBVTuple2 2 2)))
+[SEND] (get-value (s17))
+[RECV] ((s17 (mkSBVTuple2 1 1)))
+[SEND] (get-value (s21))
+[RECV] ((s21 (mkSBVTuple2 3 3)))
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease failed for bf21 @(SBV Integer -> SBV Integer): Falsifiable. Counter-example:
+  arg     =     2 :: Integer
+  before  = (2,2) :: (Integer, Integer)
+  then[1] = (1,1) :: (Integer, Integer)
+  then[2] = (3,3) :: (Integer, Integer)
+[MEASURE] Mutual group: measure (smax 0 arg1, abs arg1) failed, trying next
+
+EXCEPTION:
+
+*** Data.SBV: Cannot determine a termination measure for mutual recursion group.
+***
+***     bf21  :: SBV Integer -> SBV Integer
+***     bg21  :: SBV Integer -> SBV Integer
+***
+*** Please use 'smtFunctionWithMeasure' to provide explicit measures.
+
diff --git a/SBVTestSuite/GoldFiles/recursive22_allSelfGoodCross.gold b/SBVTestSuite/GoldFiles/recursive22_allSelfGoodCross.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive22_allSelfGoodCross.gold
@@ -0,0 +1,376 @@
+[MEASURE] Verifying termination measures for: bf22 @(SBV Integer -> SBV Integer), bf22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bf22 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking mutual recursion group: {bf22 :: SBV Integer -> SBV Integer, bg22 :: SBV Integer -> SBV Integer}
+[MEASURE] Mutual group: trying user-provided measure for all members
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for bf22 @(SBV Integer -> SBV Integer)
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer), bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Mutual group: decrease verified for bg22 @(SBV Integer -> SBV Integer)
+[MEASURE] Mutual group: user-provided measure works for all members
+[MEASURE] Passed (terminating): bf22 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bf22 @(SBV Integer -> SBV Integer)
+[MEASURE] bf22 @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] bf22 @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bf22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): bf22 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bg22 @(SBV Integer -> SBV Integer)
+[MEASURE] bg22 @(SBV Integer -> SBV Integer): mutual group already verified, skipping
+[MEASURE] Passed (terminating): bg22 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bg22 @(SBV Integer -> SBV Integer)
+[MEASURE] bg22 @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] bg22 @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Bool (>= s9 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s10))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {bg22 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s6 () Int) ; tracks user variable "__internal_sbv_s6"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s7 () Int (+ s5 s6))
+[GOOD] (define-fun s8 () Int (ite s3 s1 s7))
+[GOOD] (define-fun s9 () Int (abs s0))
+[GOOD] (define-fun s10 () Int (abs s4))
+[GOOD] (define-fun s11 () Bool (not s3))
+[GOOD] (define-fun s12 () Bool (> s9 s10))
+[GOOD] (define-fun s13 () Bool (=> s11 s12))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s13))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): bg22 @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |bf22 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger, |bg22 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-funs-rec
+         ((|bf22 @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int)
+          (|bg22 @(SBV Integer -> SBV Integer)| ((l2_s0 Int)) Int))
+         (; Definition of: |bf22 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |bf22 @(SBV Integer -> SBV Integer)|, |bg22 @(SBV Integer -> SBV Integer)|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (- l1_s0 l1_s3)))
+                                  (let ((l1_s5 (|bf22 @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s6 (|bg22 @(SBV Integer -> SBV Integer)| l1_s4)))
+                                  (let ((l1_s7 (+ l1_s5 l1_s6)))
+                                  (let ((l1_s8 (ite l1_s2 l1_s1 l1_s7)))
+                                  l1_s8))))))))
+          ; Definition of: |bg22 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger. [Refers to: |bf22 @(SBV Integer -> SBV Integer)|, |bg22 @(SBV Integer -> SBV Integer)|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (- l2_s0 l2_s3)))
+                                                  (let ((l2_s5 (|bg22 @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s6 (|bf22 @(SBV Integer -> SBV Integer)| l2_s4)))
+                                                  (let ((l2_s7 (+ l2_s5 l2_s6)))
+                                                  (let ((l2_s8 (ite l2_s2 l2_s1 l2_s7)))
+                                                  l2_s8))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|bf22 @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive23_mutualProductive.gold b/SBVTestSuite/GoldFiles/recursive23_mutualProductive.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive23_mutualProductive.gold
@@ -0,0 +1,74 @@
+[MEASURE] Verifying termination measures for: pf23 @(SBV Integer -> SBV [Integer]), pg23 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: pf23 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking mutual productive group: {pf23 :: SBV Integer -> SBV [Integer], pg23 :: SBV Integer -> SBV [Integer]}
+[MEASURE] Mutual productive group: all members are guarded
+[MEASURE] Passed (productive): pf23 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: pg23 @(SBV Integer -> SBV [Integer])
+[MEASURE] pg23 @(SBV Integer -> SBV [Integer]): mutual productive group already verified, skipping
+[MEASURE] Passed (productive): pg23 @(SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |pf23 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger], |pg23 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]
+[GOOD] (define-funs-rec
+         ((|pf23 @(SBV Integer -> SBV [Integer])| ((l1_s0 Int)) (Seq Int))
+          (|pg23 @(SBV Integer -> SBV [Integer])| ((l2_s0 Int)) (Seq Int)))
+         (; Definition of: |pf23 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |pg23 @(SBV Integer -> SBV [Integer])|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 (seq.unit 0)))
+                                  (let ((l1_s5 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (seq.unit l1_s0)))
+                                  (let ((l1_s6 (- l1_s0 l1_s5)))
+                                  (let ((l1_s7 (|pg23 @(SBV Integer -> SBV [Integer])| l1_s6)))
+                                  (let ((l1_s8 (seq.++ l1_s4 l1_s7)))
+                                  (let ((l1_s9 (ite l1_s2 l1_s3 l1_s8)))
+                                  l1_s9)))))))))
+          ; Definition of: |pg23 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |pf23 @(SBV Integer -> SBV [Integer])|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 (seq.unit 0)))
+                                                  (let ((l2_s5 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (seq.unit l2_s0)))
+                                                  (let ((l2_s6 (- l2_s0 l2_s5)))
+                                                  (let ((l2_s7 (|pf23 @(SBV Integer -> SBV [Integer])| l2_s6)))
+                                                  (let ((l2_s8 (seq.++ l2_s4 l2_s7)))
+                                                  (let ((l2_s9 (ite l2_s2 l2_s3 l2_s8)))
+                                                  l2_s9)))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq Int) (|pf23 @(SBV Integer -> SBV [Integer])| s0))
+[GOOD] (define-fun s3 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s5 () Bool (> s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive24_badMutualProductive.gold b/SBVTestSuite/GoldFiles/recursive24_badMutualProductive.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive24_badMutualProductive.gold
@@ -0,0 +1,15 @@
+[MEASURE] Verifying termination measures for: bad_pf @(SBV Integer -> SBV [Integer]), bad_pg @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: bad_pf @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking mutual productive group: {bad_pf :: SBV Integer -> SBV [Integer], bad_pg :: SBV Integer -> SBV [Integer]}
+
+EXCEPTION:
+
+*** Data.SBV: Mutual productive group has unguarded recursive calls.
+***
+***     bad_pf  :: SBV Integer -> SBV [Integer]
+***     bad_pg  :: SBV Integer -> SBV [Integer]
+***   Unguarded: bad_pg :: SBV Integer -> SBV [Integer]
+***
+*** Every recursive call (self or cross) must be a direct argument to a data constructor.
+
+
diff --git a/SBVTestSuite/GoldFiles/recursive25_contractMutualRejected.gold b/SBVTestSuite/GoldFiles/recursive25_contractMutualRejected.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive25_contractMutualRejected.gold
@@ -0,0 +1,16 @@
+[MEASURE] Verifying termination measures for: cf_mut @(SBV Integer -> SBV Integer), cf_mut @(SBV Integer -> SBV Integer), cg_mut @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: cf_mut @(SBV Integer -> SBV Integer)
+[MEASURE] cf_mut @(SBV Integer -> SBV Integer) (contract): verifying with 0 helper(s)
+[MEASURE] cf_mut @(SBV Integer -> SBV Integer) (contract): 0 helper axiom(s) collected, checking measure+contract
+[MEASURE] Passed (terminating): cf_mut @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: cf_mut @(SBV Integer -> SBV Integer)
+
+EXCEPTION:
+
+*** Data.SBV: smtFunctionWithContract does not support mutual recursion.
+***
+***   Function: cf_mut :: SBV Integer -> SBV Integer
+***
+*** Please use smtFunction or smtFunctionWithMeasure for mutual recursion groups.
+
+
diff --git a/SBVTestSuite/GoldFiles/recursive26_selfAndMutualProductive.gold b/SBVTestSuite/GoldFiles/recursive26_selfAndMutualProductive.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive26_selfAndMutualProductive.gold
@@ -0,0 +1,83 @@
+[MEASURE] Verifying termination measures for: spf26 @(SBV Integer -> SBV [Integer]), spf26 @(SBV Integer -> SBV [Integer]), spg26 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: spf26 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking mutual productive group: {spf26 :: SBV Integer -> SBV [Integer], spg26 :: SBV Integer -> SBV [Integer]}
+[MEASURE] Mutual productive group: all members are guarded
+[MEASURE] Passed (productive): spf26 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: spf26 @(SBV Integer -> SBV [Integer])
+[MEASURE] spf26 @(SBV Integer -> SBV [Integer]): productive (all recursive calls are guarded by constructors)
+[MEASURE] Passed (productive): spf26 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: spg26 @(SBV Integer -> SBV [Integer])
+[MEASURE] spg26 @(SBV Integer -> SBV [Integer]): mutual productive group already verified, skipping
+[MEASURE] Passed (productive): spg26 @(SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |spf26 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger], |spg26 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]
+[GOOD] (define-funs-rec
+         ((|spf26 @(SBV Integer -> SBV [Integer])| ((l1_s0 Int)) (Seq Int))
+          (|spg26 @(SBV Integer -> SBV [Integer])| ((l2_s0 Int)) (Seq Int)))
+         (; Definition of: |spf26 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |spf26 @(SBV Integer -> SBV [Integer])|, |spg26 @(SBV Integer -> SBV [Integer])|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 (seq.unit 0)))
+                                  (let ((l1_s4 2))
+                                  (let ((l1_s8 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s5 (mod l1_s0 l1_s4)))
+                                  (let ((l1_s6 (= l1_s1 l1_s5)))
+                                  (let ((l1_s7 (seq.unit l1_s0)))
+                                  (let ((l1_s9 (- l1_s0 l1_s8)))
+                                  (let ((l1_s10 (|spf26 @(SBV Integer -> SBV [Integer])| l1_s9)))
+                                  (let ((l1_s11 (seq.++ l1_s7 l1_s10)))
+                                  (let ((l1_s12 (|spg26 @(SBV Integer -> SBV [Integer])| l1_s9)))
+                                  (let ((l1_s13 (seq.++ l1_s7 l1_s12)))
+                                  (let ((l1_s14 (ite l1_s6 l1_s11 l1_s13)))
+                                  (let ((l1_s15 (ite l1_s2 l1_s3 l1_s14)))
+                                  l1_s15)))))))))))))))
+          ; Definition of: |spg26 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |spf26 @(SBV Integer -> SBV [Integer])|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 (seq.unit 0)))
+                                                  (let ((l2_s5 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s4 (seq.unit l2_s0)))
+                                                  (let ((l2_s6 (- l2_s0 l2_s5)))
+                                                  (let ((l2_s7 (|spf26 @(SBV Integer -> SBV [Integer])| l2_s6)))
+                                                  (let ((l2_s8 (seq.++ l2_s4 l2_s7)))
+                                                  (let ((l2_s9 (ite l2_s2 l2_s3 l2_s8)))
+                                                  l2_s9)))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq Int) (|spf26 @(SBV Integer -> SBV [Integer])| s0))
+[GOOD] (define-fun s3 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s5 () Bool (> s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive27_mutualProductive3.gold b/SBVTestSuite/GoldFiles/recursive27_mutualProductive3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive27_mutualProductive3.gold
@@ -0,0 +1,93 @@
+[MEASURE] Verifying termination measures for: pa27 @(SBV Integer -> SBV [Integer]), pb27 @(SBV Integer -> SBV [Integer]), pc27 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: pa27 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking mutual productive group: {pa27 :: SBV Integer -> SBV [Integer], pb27 :: SBV Integer -> SBV [Integer], pc27 :: SBV Integer -> SBV [Integer]}
+[MEASURE] Mutual productive group: all members are guarded
+[MEASURE] Passed (productive): pa27 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: pb27 @(SBV Integer -> SBV [Integer])
+[MEASURE] pb27 @(SBV Integer -> SBV [Integer]): mutual productive group already verified, skipping
+[MEASURE] Passed (productive): pb27 @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: pc27 @(SBV Integer -> SBV [Integer])
+[MEASURE] pc27 @(SBV Integer -> SBV [Integer]): mutual productive group already verified, skipping
+[MEASURE] Passed (productive): pc27 @(SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |pa27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger], |pb27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger], |pc27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]
+[GOOD] (define-funs-rec
+         ((|pa27 @(SBV Integer -> SBV [Integer])| ((l1_s0 Int)) (Seq Int))
+          (|pb27 @(SBV Integer -> SBV [Integer])| ((l2_s0 Int)) (Seq Int))
+          (|pc27 @(SBV Integer -> SBV [Integer])| ((l3_s0 Int)) (Seq Int)))
+         (; Definition of: |pa27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |pb27 @(SBV Integer -> SBV [Integer])|]
+                                  (let ((l1_s1 0))
+                                  (let ((l1_s3 (seq.unit 0)))
+                                  (let ((l1_s5 1))
+                                  (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                  (let ((l1_s4 (seq.unit l1_s0)))
+                                  (let ((l1_s6 (- l1_s0 l1_s5)))
+                                  (let ((l1_s7 (|pb27 @(SBV Integer -> SBV [Integer])| l1_s6)))
+                                  (let ((l1_s8 (seq.++ l1_s4 l1_s7)))
+                                  (let ((l1_s9 (ite l1_s2 l1_s3 l1_s8)))
+                                  l1_s9)))))))))
+          ; Definition of: |pb27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |pc27 @(SBV Integer -> SBV [Integer])|]
+                                                  (let ((l2_s1 0))
+                                                  (let ((l2_s3 (seq.unit 0)))
+                                                  (let ((l2_s4 10))
+                                                  (let ((l2_s7 1))
+                                                  (let ((l2_s2 (<= l2_s0 l2_s1)))
+                                                  (let ((l2_s5 (* l2_s0 l2_s4)))
+                                                  (let ((l2_s6 (seq.unit l2_s5)))
+                                                  (let ((l2_s8 (- l2_s0 l2_s7)))
+                                                  (let ((l2_s9 (|pc27 @(SBV Integer -> SBV [Integer])| l2_s8)))
+                                                  (let ((l2_s10 (seq.++ l2_s6 l2_s9)))
+                                                  (let ((l2_s11 (ite l2_s2 l2_s3 l2_s10)))
+                                                  l2_s11)))))))))))
+          ; Definition of: |pc27 @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger]. [Refers to: |pa27 @(SBV Integer -> SBV [Integer])|]
+                                                                  (let ((l3_s1 0))
+                                                                  (let ((l3_s3 (seq.unit 0)))
+                                                                  (let ((l3_s4 100))
+                                                                  (let ((l3_s7 1))
+                                                                  (let ((l3_s2 (<= l3_s0 l3_s1)))
+                                                                  (let ((l3_s5 (* l3_s0 l3_s4)))
+                                                                  (let ((l3_s6 (seq.unit l3_s5)))
+                                                                  (let ((l3_s8 (- l3_s0 l3_s7)))
+                                                                  (let ((l3_s9 (|pa27 @(SBV Integer -> SBV [Integer])| l3_s8)))
+                                                                  (let ((l3_s10 (seq.++ l3_s6 l3_s9)))
+                                                                  (let ((l3_s11 (ite l3_s2 l3_s3 l3_s10)))
+                                                                  l3_s11)))))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq Int) (|pa27 @(SBV Integer -> SBV [Integer])| s0))
+[GOOD] (define-fun s3 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s5 () Bool (> s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive28_noTermCheck.gold b/SBVTestSuite/GoldFiles/recursive28_noTermCheck.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive28_noTermCheck.gold
@@ -0,0 +1,53 @@
+[MEASURE] ntc28 @(SBV Integer -> SBV Integer): no termination check (smtFunctionNoTermination)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 5)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "__internal_sbv_s0"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |ntc28 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+[GOOD] (define-fun-rec |ntc28 @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s3 1))
+                                 (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                 (let ((l1_s4 (- l1_s0 l1_s3)))
+                                 (let ((l1_s5 (|ntc28 @(SBV Integer -> SBV Integer)| l1_s4)))
+                                 (let ((l1_s6 (+ l1_s3 l1_s5)))
+                                 (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                 l1_s7))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Int (|ntc28 @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] (define-fun s5 () Bool (=> s2 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+; smtProofStep: No context value to push.
+Lemma: ntc_at_5
+[GOOD] (define-fun s6 () Bool (forall ((l1_s0 Int))
+                                 (let ((l1_s1 5))
+                                 (let ((l1_s2 (= l1_s0 l1_s1)))
+                                 (let ((l1_s3 (|ntc28 @(SBV Integer -> SBV Integer)| l1_s0)))
+                                 (let ((l1_s4 (= l1_s1 l1_s3)))
+                                 (let ((l1_s5 (=> l1_s2 l1_s4)))
+                                 l1_s5)))))))
+[GOOD] (define-fun s7 () Bool (not s6))
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] unsat
+     Q.E.D. [Modulo: ntc28 termination]
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[Modulo: ntc28 termination] ntc_at_5 :: Ɐn ∷ Integer → Bool
diff --git a/SBVTestSuite/GoldFiles/recursive2_enum.gold b/SBVTestSuite/GoldFiles/recursive2_enum.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive2_enum.gold
@@ -0,0 +1,158 @@
+[MEASURE] Verifying termination measures for: EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])
+[MEASURE] Checking: EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])
+[MEASURE] EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer]): verifying with 0 helper(s)
+[MEASURE] EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer]): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])}: replaying 8 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s14 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "arg2"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Bool (< s0 s2))
+[GOOD] (define-fun s6 () Bool (>= s1 s3))
+[GOOD] (define-fun s7 () Bool (or s5 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s0))
+[GOOD] (define-fun s9 () Int (+ s0 s1))
+[GOOD] (define-fun s11 () (Seq Int) (seq.++ s8 s10))
+[GOOD] (define-fun s12 () (Seq Int) (ite s7 s4 s11))
+[GOOD] (define-fun s13 () Int (- s0 s2))
+[GOOD] (define-fun s15 () Int (+ s13 s14))
+[GOOD] (define-fun s16 () Bool (<= s3 s15))
+[GOOD] (define-fun s17 () Int (ite s16 s15 s3))
+[GOOD] (define-fun s18 () Bool (>= s17 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s18))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])}: replaying 8 node(s)
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s14 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg0"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "arg1"
+[GOOD] (declare-fun s2 () Int) ; tracks user variable "arg2"
+[GOOD] (declare-fun s10 () (Seq Int)) ; tracks user variable "__internal_sbv_s10"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s5 () Bool (< s0 s2))
+[GOOD] (define-fun s6 () Bool (>= s1 s3))
+[GOOD] (define-fun s7 () Bool (or s5 s6))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s0))
+[GOOD] (define-fun s9 () Int (+ s0 s1))
+[GOOD] (define-fun s11 () (Seq Int) (seq.++ s8 s10))
+[GOOD] (define-fun s12 () (Seq Int) (ite s7 s4 s11))
+[GOOD] (define-fun s13 () Int (- s0 s2))
+[GOOD] (define-fun s15 () Int (+ s13 s14))
+[GOOD] (define-fun s16 () Bool (<= s3 s15))
+[GOOD] (define-fun s17 () Int (ite s16 s15 s3))
+[GOOD] (define-fun s18 () Int (- s9 s2))
+[GOOD] (define-fun s19 () Int (+ s14 s18))
+[GOOD] (define-fun s20 () Bool (<= s3 s19))
+[GOOD] (define-fun s21 () Int (ite s20 s19 s3))
+[GOOD] (define-fun s22 () Bool (not s7))
+[GOOD] (define-fun s23 () Bool (> s17 s21))
+[GOOD] (define-fun s24 () Bool (=> s22 s23))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s24))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 5)
+[GOOD] (define-fun s2 () Int (- 1))
+[GOOD] (define-fun s5 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])| :: SInteger -> SInteger -> SInteger -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])| ((l1_s0 Int) (l1_s1 Int) (l1_s2 Int)) (Seq Int)
+                                 (let ((l1_s4 0))
+                                 (let ((l1_s7 (as seq.empty (Seq Int))))
+                                 (let ((l1_s3 (< l1_s0 l1_s2)))
+                                 (let ((l1_s5 (>= l1_s1 l1_s4)))
+                                 (let ((l1_s6 (or l1_s3 l1_s5)))
+                                 (let ((l1_s8 (seq.unit l1_s0)))
+                                 (let ((l1_s9 (+ l1_s0 l1_s1)))
+                                 (let ((l1_s10 (|EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])| l1_s9 l1_s1 l1_s2)))
+                                 (let ((l1_s11 (seq.++ l1_s8 l1_s10)))
+                                 (let ((l1_s12 (ite l1_s6 l1_s7 l1_s11)))
+                                 l1_s12)))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (|EnumSymbolic.Integer.enumFromThenTo.down @(SBV Integer -> SBV Integer -> SBV Integer -> SBV [Integer])| s1 s2 s0))
+[GOOD] (define-fun s4 () Int (seq.len s3))
+[GOOD] (define-fun s6 () Bool (>= s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 6))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 6 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive3_badMeasure.gold b/SBVTestSuite/GoldFiles/recursive3_badMeasure.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive3_badMeasure.gold
@@ -0,0 +1,94 @@
+[MEASURE] Verifying termination measures for: badSum @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: badSum @(SBV Integer -> SBV Integer)
+[MEASURE] badSum @(SBV Integer -> SBV Integer): verifying with 0 helper(s)
+[MEASURE] badSum @(SBV Integer -> SBV Integer): 0 helper axiom(s) collected, checking measure
+[MEASURE] replayDAG {badSum @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {badSum @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Bool (not s3))
+[GOOD] (define-fun s9 () Bool (=> s8 false))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[SEND] (get-value (s2))
+[RECV] ((s2 1))
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+[SEND] (get-value (s5))
+[RECV] ((s5 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+EXCEPTION:
+
+*** Data.SBV: Termination measure does not strictly decrease at a recursive call site.
+***
+***   Function: badSum :: SBV Integer -> SBV Integer
+***
+***   Falsifiable. Counter-example:
+***     arg    = 1 :: Integer
+***     before = 1 :: Integer
+***     then   = 1 :: Integer
+***
+*** The measure must strictly decrease at every recursive call.
+
diff --git a/SBVTestSuite/GoldFiles/recursive4_mcCarthy91.gold b/SBVTestSuite/GoldFiles/recursive4_mcCarthy91.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive4_mcCarthy91.gold
@@ -0,0 +1,175 @@
+[MEASURE] Verifying termination measures for: mcCarthy91 @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: mcCarthy91 @(SBV Integer -> SBV Integer)
+[MEASURE] mcCarthy91 @(SBV Integer -> SBV Integer) (contract): verifying with 0 helper(s)
+[MEASURE] mcCarthy91 @(SBV Integer -> SBV Integer) (contract): 0 helper axiom(s) collected, checking measure+contract
+[MEASURE] replayDAG {mcCarthy91 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s10 () Int 0)
+[GOOD] (define-fun s11 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s12 () Int (- s11 s0))
+[GOOD] (define-fun s13 () Bool (<= s10 s12))
+[GOOD] (define-fun s14 () Int (ite s13 s12 s10))
+[GOOD] (define-fun s15 () Bool (>= s14 s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mcCarthy91 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mcCarthy91 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mcCarthy91 @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s25 () Int 91)
+[GOOD] (define-fun s31 () Int 0)
+[GOOD] (define-fun s32 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s13 () Int) ; tracks user variable "__internal_sbv_s13"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] (declare-fun s20 () Int) ; tracks user variable "__internal_sbv_s20"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s10 () Bool (> s6 s3))
+[GOOD] (define-fun s11 () Int (- s6 s1))
+[GOOD] (define-fun s12 () Int (+ s2 s6))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Bool (= s7 s15))
+[GOOD] (define-fun s17 () Bool (> s7 s3))
+[GOOD] (define-fun s18 () Int (- s7 s1))
+[GOOD] (define-fun s19 () Int (+ s2 s7))
+[GOOD] (define-fun s22 () Int (ite s17 s18 s21))
+[GOOD] (define-fun s23 () Bool (= s8 s22))
+[GOOD] (define-fun s24 () Bool (<= s6 s3))
+[GOOD] (define-fun s26 () Bool (= s7 s25))
+[GOOD] (define-fun s27 () Bool (=> s24 s26))
+[GOOD] (define-fun s28 () Bool (<= s7 s3))
+[GOOD] (define-fun s29 () Bool (= s8 s25))
+[GOOD] (define-fun s30 () Bool (=> s28 s29))
+[GOOD] (define-fun s33 () Int (- s32 s0))
+[GOOD] (define-fun s34 () Bool (<= s31 s33))
+[GOOD] (define-fun s35 () Int (ite s34 s33 s31))
+[GOOD] (define-fun s36 () Int (- s32 s6))
+[GOOD] (define-fun s37 () Bool (<= s31 s36))
+[GOOD] (define-fun s38 () Int (ite s37 s36 s31))
+[GOOD] (define-fun s39 () Int (- s32 s7))
+[GOOD] (define-fun s40 () Bool (<= s31 s39))
+[GOOD] (define-fun s41 () Int (ite s40 s39 s31))
+[GOOD] (define-fun s42 () Bool (not s4))
+[GOOD] (define-fun s43 () Bool (> s35 s38))
+[GOOD] (define-fun s44 () Bool (=> s42 s43))
+[GOOD] (define-fun s45 () Bool (> s35 s41))
+[GOOD] (define-fun s46 () Bool (=> s42 s45))
+[GOOD] (define-fun s47 () Bool (and s44 s46))
+[GOOD] (define-fun s48 () Bool (<= s0 s3))
+[GOOD] (define-fun s49 () Bool (= s9 s25))
+[GOOD] (define-fun s50 () Bool (=> s48 s49))
+[GOOD] (define-fun s51 () Bool (and s47 s50))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s16)
+[GOOD] (assert s23)
+[GOOD] (assert s27)
+[GOOD] (assert s30)
+[GOOD] (assert (not s51))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] Passed (terminating): mcCarthy91 @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 91)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |mcCarthy91 @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+[GOOD] (define-fun-rec |mcCarthy91 @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 100))
+                                 (let ((l1_s3 10))
+                                 (let ((l1_s5 11))
+                                 (let ((l1_s2 (> l1_s0 l1_s1)))
+                                 (let ((l1_s4 (- l1_s0 l1_s3)))
+                                 (let ((l1_s6 (+ l1_s0 l1_s5)))
+                                 (let ((l1_s7 (|mcCarthy91 @(SBV Integer -> SBV Integer)| l1_s6)))
+                                 (let ((l1_s8 (|mcCarthy91 @(SBV Integer -> SBV Integer)| l1_s7)))
+                                 (let ((l1_s9 (ite l1_s2 l1_s4 l1_s8)))
+                                 l1_s9))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|mcCarthy91 @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 101))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 101 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive5_badContract.gold b/SBVTestSuite/GoldFiles/recursive5_badContract.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive5_badContract.gold
@@ -0,0 +1,159 @@
+[MEASURE] Verifying termination measures for: mc91bad @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: mc91bad @(SBV Integer -> SBV Integer)
+[MEASURE] mc91bad @(SBV Integer -> SBV Integer) (contract): verifying with 0 helper(s)
+[MEASURE] mc91bad @(SBV Integer -> SBV Integer) (contract): 0 helper axiom(s) collected, checking measure+contract
+[MEASURE] replayDAG {mc91bad @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s10 () Int 0)
+[GOOD] (define-fun s11 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s12 () Int (- s11 s0))
+[GOOD] (define-fun s13 () Bool (<= s10 s12))
+[GOOD] (define-fun s14 () Int (ite s13 s12 s10))
+[GOOD] (define-fun s15 () Bool (>= s14 s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mc91bad @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mc91bad @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mc91bad @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s24 () Int 0)
+[GOOD] (define-fun s27 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s13 () Int) ; tracks user variable "__internal_sbv_s13"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] (declare-fun s20 () Int) ; tracks user variable "__internal_sbv_s20"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s10 () Bool (> s6 s3))
+[GOOD] (define-fun s11 () Int (- s6 s1))
+[GOOD] (define-fun s12 () Int (+ s2 s6))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Bool (= s7 s15))
+[GOOD] (define-fun s17 () Bool (> s7 s3))
+[GOOD] (define-fun s18 () Int (- s7 s1))
+[GOOD] (define-fun s19 () Int (+ s2 s7))
+[GOOD] (define-fun s22 () Int (ite s17 s18 s21))
+[GOOD] (define-fun s23 () Bool (= s8 s22))
+[GOOD] (define-fun s25 () Bool (= s7 s24))
+[GOOD] (define-fun s26 () Bool (= s8 s24))
+[GOOD] (define-fun s28 () Int (- s27 s0))
+[GOOD] (define-fun s29 () Bool (<= s24 s28))
+[GOOD] (define-fun s30 () Int (ite s29 s28 s24))
+[GOOD] (define-fun s31 () Int (- s27 s6))
+[GOOD] (define-fun s32 () Bool (<= s24 s31))
+[GOOD] (define-fun s33 () Int (ite s32 s31 s24))
+[GOOD] (define-fun s34 () Int (- s27 s7))
+[GOOD] (define-fun s35 () Bool (<= s24 s34))
+[GOOD] (define-fun s36 () Int (ite s35 s34 s24))
+[GOOD] (define-fun s37 () Bool (not s4))
+[GOOD] (define-fun s38 () Bool (> s30 s33))
+[GOOD] (define-fun s39 () Bool (=> s37 s38))
+[GOOD] (define-fun s40 () Bool (> s30 s36))
+[GOOD] (define-fun s41 () Bool (=> s37 s40))
+[GOOD] (define-fun s42 () Bool (and s39 s41))
+[GOOD] (define-fun s43 () Bool (= s9 s24))
+[GOOD] (define-fun s44 () Bool (and s42 s43))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s16)
+[GOOD] (assert s23)
+[GOOD] (assert s25)
+[GOOD] (assert s26)
+[GOOD] (assert (not s44))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s30))
+[RECV] ((s30 92))
+[SEND] (get-value (s33))
+[RECV] ((s33 81))
+[SEND] (get-value (s36))
+[RECV] ((s36 101))
+[SEND] (get-value (s0))
+[RECV] ((s0 9))
+[SEND] (get-value (s7))
+[RECV] ((s7 0))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 0))
+[SEND] (get-value (s20))
+[RECV] ((s20 0))
+[SEND] (get-value (s21))
+[RECV] ((s21 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+EXCEPTION:
+
+*** Data.SBV: Measure+contract verification failed.
+***
+***   Function: mc91bad :: SBV Integer -> SBV Integer
+***
+***   Falsifiable. Counter-example:
+***     arg     =   9 :: Integer
+***     before  =  92 :: Integer
+***     then[1] =  81 :: Integer
+***     then[2] = 101 :: Integer
+***
+*** The measure must strictly decrease at every recursive call,
+*** and the contract must hold for the function's output.
+*** The inductive hypothesis provides the contract on recursive call
+*** results for inputs with strictly smaller measure.
+
diff --git a/SBVTestSuite/GoldFiles/recursive6_uselessContract.gold b/SBVTestSuite/GoldFiles/recursive6_uselessContract.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive6_uselessContract.gold
@@ -0,0 +1,153 @@
+[MEASURE] Verifying termination measures for: mc91triv @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: mc91triv @(SBV Integer -> SBV Integer)
+[MEASURE] mc91triv @(SBV Integer -> SBV Integer) (contract): verifying with 0 helper(s)
+[MEASURE] mc91triv @(SBV Integer -> SBV Integer) (contract): 0 helper axiom(s) collected, checking measure+contract
+[MEASURE] replayDAG {mc91triv @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s10 () Int 0)
+[GOOD] (define-fun s11 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s12 () Int (- s11 s0))
+[GOOD] (define-fun s13 () Bool (<= s10 s12))
+[GOOD] (define-fun s14 () Int (ite s13 s12 s10))
+[GOOD] (define-fun s15 () Bool (>= s14 s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s15))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {mc91triv @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mc91triv @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+[MEASURE] replayDAG {mc91triv @(SBV Integer -> SBV Integer)}: replaying 6 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 10)
+[GOOD] (define-fun s2 () Int 11)
+[GOOD] (define-fun s3 () Int 100)
+[GOOD] (define-fun s24 () Int 0)
+[GOOD] (define-fun s25 () Int 101)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
+[GOOD] (declare-fun s8 () Int) ; tracks user variable "__internal_sbv_s8"
+[GOOD] (declare-fun s13 () Int) ; tracks user variable "__internal_sbv_s13"
+[GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
+[GOOD] (declare-fun s20 () Int) ; tracks user variable "__internal_sbv_s20"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Int (- s0 s1))
+[GOOD] (define-fun s6 () Int (+ s0 s2))
+[GOOD] (define-fun s9 () Int (ite s4 s5 s8))
+[GOOD] (define-fun s10 () Bool (> s6 s3))
+[GOOD] (define-fun s11 () Int (- s6 s1))
+[GOOD] (define-fun s12 () Int (+ s2 s6))
+[GOOD] (define-fun s15 () Int (ite s10 s11 s14))
+[GOOD] (define-fun s16 () Bool (= s7 s15))
+[GOOD] (define-fun s17 () Bool (> s7 s3))
+[GOOD] (define-fun s18 () Int (- s7 s1))
+[GOOD] (define-fun s19 () Int (+ s2 s7))
+[GOOD] (define-fun s22 () Int (ite s17 s18 s21))
+[GOOD] (define-fun s23 () Bool (= s8 s22))
+[GOOD] (define-fun s26 () Int (- s25 s0))
+[GOOD] (define-fun s27 () Bool (<= s24 s26))
+[GOOD] (define-fun s28 () Int (ite s27 s26 s24))
+[GOOD] (define-fun s29 () Int (- s25 s6))
+[GOOD] (define-fun s30 () Bool (<= s24 s29))
+[GOOD] (define-fun s31 () Int (ite s30 s29 s24))
+[GOOD] (define-fun s32 () Int (- s25 s7))
+[GOOD] (define-fun s33 () Bool (<= s24 s32))
+[GOOD] (define-fun s34 () Int (ite s33 s32 s24))
+[GOOD] (define-fun s35 () Bool (not s4))
+[GOOD] (define-fun s36 () Bool (> s28 s31))
+[GOOD] (define-fun s37 () Bool (=> s35 s36))
+[GOOD] (define-fun s38 () Bool (> s28 s34))
+[GOOD] (define-fun s39 () Bool (=> s35 s38))
+[GOOD] (define-fun s40 () Bool (and s37 s39))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s16)
+[GOOD] (assert s23)
+[GOOD] (assert (not s40))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s28))
+[RECV] ((s28 12))
+[SEND] (get-value (s31))
+[RECV] ((s31 1))
+[SEND] (get-value (s34))
+[RECV] ((s34 12))
+[SEND] (get-value (s0))
+[RECV] ((s0 89))
+[SEND] (get-value (s7))
+[RECV] ((s7 89))
+[SEND] (get-value (s8))
+[RECV] ((s8 0))
+[SEND] (get-value (s13))
+[RECV] ((s13 0))
+[SEND] (get-value (s14))
+[RECV] ((s14 89))
+[SEND] (get-value (s20))
+[RECV] ((s20 0))
+[SEND] (get-value (s21))
+[RECV] ((s21 0))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+EXCEPTION:
+
+*** Data.SBV: Measure+contract verification failed.
+***
+***   Function: mc91triv :: SBV Integer -> SBV Integer
+***
+***   Falsifiable. Counter-example:
+***     arg     = 89 :: Integer
+***     before  = 12 :: Integer
+***     then[1] =  1 :: Integer
+***     then[2] = 12 :: Integer
+***
+*** The measure must strictly decrease at every recursive call,
+*** and the contract must hold for the function's output.
+*** The inductive hypothesis provides the contract on recursive call
+*** results for inputs with strictly smaller measure.
+
diff --git a/SBVTestSuite/GoldFiles/recursive7_productive.gold b/SBVTestSuite/GoldFiles/recursive7_productive.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive7_productive.gold
@@ -0,0 +1,54 @@
+[MEASURE] Verifying termination measures for: rep @(SBV Integer -> SBV Integer -> SBV [Integer])
+[MEASURE] Checking: rep @(SBV Integer -> SBV Integer -> SBV [Integer])
+[MEASURE] rep @(SBV Integer -> SBV Integer -> SBV [Integer]): productive (all recursive calls are guarded by constructors)
+[MEASURE] Passed (productive): rep @(SBV Integer -> SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |rep @(SBV Integer -> SBV Integer -> SBV [Integer])| :: SInteger -> SInteger -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |rep @(SBV Integer -> SBV Integer -> SBV [Integer])| ((l1_s0 Int) (l1_s1 Int)) (Seq Int)
+                                 (let ((l1_s2 0))
+                                 (let ((l1_s4 (as seq.empty (Seq Int))))
+                                 (let ((l1_s6 1))
+                                 (let ((l1_s3 (<= l1_s0 l1_s2)))
+                                 (let ((l1_s5 (seq.unit l1_s1)))
+                                 (let ((l1_s7 (- l1_s0 l1_s6)))
+                                 (let ((l1_s8 (|rep @(SBV Integer -> SBV Integer -> SBV [Integer])| l1_s7 l1_s1)))
+                                 (let ((l1_s9 (seq.++ l1_s5 l1_s8)))
+                                 (let ((l1_s10 (ite l1_s3 l1_s4 l1_s9)))
+                                 l1_s10))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Seq Int) (|rep @(SBV Integer -> SBV Integer -> SBV [Integer])| s1 s0))
+[GOOD] (define-fun s3 () Int (seq.len s2))
+[GOOD] (define-fun s4 () Bool (= s1 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 4))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 4 :: Integer
diff --git a/SBVTestSuite/GoldFiles/recursive8_badProductive.gold b/SBVTestSuite/GoldFiles/recursive8_badProductive.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive8_badProductive.gold
@@ -0,0 +1,12 @@
+[MEASURE] Verifying termination measures for: bad @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: bad @(SBV Integer -> SBV Integer)
+
+EXCEPTION:
+
+*** Data.SBV: Function marked as productive is not guarded-recursive.
+***
+***   Function: bad :: SBV Integer -> SBV Integer
+***
+*** Every recursive call must be a direct argument to a data constructor
+*** (list cons, ADT constructor, etc.) to ensure productivity.
+
diff --git a/SBVTestSuite/GoldFiles/recursive9_productive2.gold b/SBVTestSuite/GoldFiles/recursive9_productive2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/recursive9_productive2.gold
@@ -0,0 +1,56 @@
+[MEASURE] Verifying termination measures for: countdown @(SBV Integer -> SBV [Integer])
+[MEASURE] Checking: countdown @(SBV Integer -> SBV [Integer])
+[MEASURE] countdown @(SBV Integer -> SBV [Integer]): productive (all recursive calls are guarded by constructors)
+[MEASURE] Passed (productive): countdown @(SBV Integer -> SBV [Integer])
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |countdown @(SBV Integer -> SBV [Integer])| :: SInteger -> [SInteger] [Recursive]
+[GOOD] (define-fun-rec |countdown @(SBV Integer -> SBV [Integer])| ((l1_s0 Int)) (Seq Int)
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s3 (seq.unit 0)))
+                                 (let ((l1_s5 1))
+                                 (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                 (let ((l1_s4 (seq.unit l1_s0)))
+                                 (let ((l1_s6 (- l1_s0 l1_s5)))
+                                 (let ((l1_s7 (|countdown @(SBV Integer -> SBV [Integer])| l1_s6)))
+                                 (let ((l1_s8 (seq.++ l1_s4 l1_s7)))
+                                 (let ((l1_s9 (ite l1_s2 l1_s3 l1_s8)))
+                                 l1_s9))))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Seq Int) (|countdown @(SBV Integer -> SBV [Integer])| s0))
+[GOOD] (define-fun s3 () Int (seq.nth s1 s2))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[GOOD] (define-fun s5 () Bool (> s0 s2))
+[GOOD] (define-fun s6 () Bool (and s4 s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/safe1.gold b/SBVTestSuite/GoldFiles/safe1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/safe1.gold
@@ -0,0 +1,38 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 12)
+[GOOD] (define-fun s3 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s5 () Bool (not s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (push 1)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: [safe1: Violated. Model:
+  s0 = 0 :: Integer]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/safe2.gold b/SBVTestSuite/GoldFiles/safe2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/safe2.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 12)
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (> s0 s2))
+[GOOD] (define-fun s4 () Bool (not s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (push 1)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: [safe2: Violated. Model:
+  s0 = 0 :: Integer]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/selChecked.gold b/SBVTestSuite/GoldFiles/selChecked.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/selChecked.gold
@@ -0,0 +1,99 @@
+== BEGIN: "Makefile" ================
+# Makefile for selChecked. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: selChecked_driver
+
+selChecked.o: selChecked.c selChecked.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+selChecked_driver.o: selChecked_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+selChecked_driver: selChecked.o selChecked_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f selChecked_driver
+== END: "Makefile" ==================
+== BEGIN: "selChecked.h" ================
+/* Header file for selChecked. Automatically generated by SBV. Do not edit! */
+
+#ifndef __selChecked__HEADER_INCLUDED__
+#define __selChecked__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord8 selChecked(const SWord8 x);
+
+#endif /* __selChecked__HEADER_INCLUDED__ */
+== END: "selChecked.h" ==================
+== BEGIN: "selChecked_driver.c" ================
+/* Example driver program for selChecked. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "selChecked.h"
+
+int main(void)
+{
+  const SWord8 __result = selChecked(65);
+
+  printf("selChecked(65) = %"PRIu8"\n", __result);
+
+  return 0;
+}
+== END: "selChecked_driver.c" ==================
+== BEGIN: "selChecked.c" ================
+/* File: "selChecked.c". Automatically generated by SBV. Do not edit! */
+
+#include "selChecked.h"
+
+SWord8 selChecked(const SWord8 x)
+{
+  const SWord8 s0 = x;
+  const SWord8 s3 = s0 + 2;
+  const SWord8 table0[] = {
+       1, s3
+  };
+  const SWord8 s5 = s0 >= 2 ? 3 : table0[s0];
+
+  return s5;
+}
+== END: "selChecked.c" ==================
diff --git a/SBVTestSuite/GoldFiles/selUnchecked.gold b/SBVTestSuite/GoldFiles/selUnchecked.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/selUnchecked.gold
@@ -0,0 +1,99 @@
+== BEGIN: "Makefile" ================
+# Makefile for selUnChecked. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: selUnChecked_driver
+
+selUnChecked.o: selUnChecked.c selUnChecked.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+selUnChecked_driver.o: selUnChecked_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+selUnChecked_driver: selUnChecked.o selUnChecked_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f selUnChecked_driver
+== END: "Makefile" ==================
+== BEGIN: "selUnChecked.h" ================
+/* Header file for selUnChecked. Automatically generated by SBV. Do not edit! */
+
+#ifndef __selUnChecked__HEADER_INCLUDED__
+#define __selUnChecked__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+SWord8 selUnChecked(const SWord8 x);
+
+#endif /* __selUnChecked__HEADER_INCLUDED__ */
+== END: "selUnChecked.h" ==================
+== BEGIN: "selUnChecked_driver.c" ================
+/* Example driver program for selUnChecked. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "selUnChecked.h"
+
+int main(void)
+{
+  const SWord8 __result = selUnChecked(65);
+
+  printf("selUnChecked(65) = %"PRIu8"\n", __result);
+
+  return 0;
+}
+== END: "selUnChecked_driver.c" ==================
+== BEGIN: "selUnChecked.c" ================
+/* File: "selUnChecked.c". Automatically generated by SBV. Do not edit! */
+
+#include "selUnChecked.h"
+
+SWord8 selUnChecked(const SWord8 x)
+{
+  const SWord8 s0 = x;
+  const SWord8 s3 = s0 + 2;
+  const SWord8 table0[] = {
+       1, s3
+  };
+  const SWord8 s5 = table0[s0];
+
+  return s5;
+}
+== END: "selUnChecked.c" ==================
diff --git a/SBVTestSuite/GoldFiles/seqConcat.gold b/SBVTestSuite/GoldFiles/seqConcat.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqConcat.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqConcatBad.gold b/SBVTestSuite/GoldFiles/seqConcatBad.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqConcatBad.gold
@@ -0,0 +1,24 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples1.gold b/SBVTestSuite/GoldFiles/seqExamples1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples1.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples2.gold b/SBVTestSuite/GoldFiles/seqExamples2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples2.gold
@@ -0,0 +1,33 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ s0 s1))
+[GOOD] (define-fun s4 () (Seq Int) (seq.++ s3 s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples3.gold b/SBVTestSuite/GoldFiles/seqExamples3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples3.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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)))
+[GOOD] (define-fun s9 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (Seq Int)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (seq.++ s0 s1))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s6 () (Seq Int) (seq.++ s1 s2))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Bool (not s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s8)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples4.gold b/SBVTestSuite/GoldFiles/seqExamples4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples4.gold
@@ -0,0 +1,38 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s4 () (Seq Int) (seq.++ (seq.unit 3) (seq.unit 4) (seq.unit 5)))
+[GOOD] (define-fun s8 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Seq Int) (seq.++ s2 s0))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ s1 s4))
+[GOOD] (define-fun s6 () Bool (= s3 s5))
+[GOOD] (define-fun s7 () Int (seq.len s0))
+[GOOD] (define-fun s9 () Bool (<= s7 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples5.gold b/SBVTestSuite/GoldFiles/seqExamples5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples5.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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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)))
+[GOOD] (define-fun s12 () (Seq Int) (seq.unit 1))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (Seq Int)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () (Seq Int) (seq.++ s3 s1))
+[GOOD] (define-fun s5 () (Seq Int) (seq.++ s0 s4))
+[GOOD] (define-fun s7 () (Seq Int) (seq.++ s6 s2))
+[GOOD] (define-fun s8 () (Seq Int) (seq.++ s1 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.++ s0 s1))
+[GOOD] (define-fun s11 () Bool (= s2 s10))
+[GOOD] (define-fun s13 () (Seq Int) (seq.++ s0 s12))
+[GOOD] (define-fun s14 () (Seq Int) (seq.++ s12 s0))
+[GOOD] (define-fun s15 () Bool (= s13 s14))
+[GOOD] (define-fun s16 () Bool (not s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[GOOD] (assert s16)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples6.gold b/SBVTestSuite/GoldFiles/seqExamples6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples6.gold
@@ -0,0 +1,36 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (Seq Int)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (seq.contains s0 s1))
+[GOOD] (define-fun s4 () Bool (seq.contains s1 s2))
+[GOOD] (define-fun s5 () Bool (seq.contains s0 s2))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples7.gold b/SBVTestSuite/GoldFiles/seqExamples7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples7.gold
@@ -0,0 +1,39 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (Seq Int)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (seq.contains s0 s1))
+[GOOD] (define-fun s4 () Bool (seq.contains s0 s2))
+[GOOD] (define-fun s5 () Bool (seq.contains s1 s2))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () Bool (seq.contains s2 s1))
+[GOOD] (define-fun s8 () Bool (not s7))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s8)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqExamples8.gold b/SBVTestSuite/GoldFiles/seqExamples8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqExamples8.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Seq Int)) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () (Seq Int)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (seq.prefixof s1 s0))
+[GOOD] (define-fun s4 () Bool (seq.suffixof s2 s0))
+[GOOD] (define-fun s5 () Int (seq.len s0))
+[GOOD] (define-fun s6 () Int (seq.len s1))
+[GOOD] (define-fun s7 () Int (seq.len s2))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () (Seq Int) (seq.++ s1 s2))
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqIndexOf.gold b/SBVTestSuite/GoldFiles/seqIndexOf.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqIndexOf.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/seqIndexOfBad.gold b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
@@ -0,0 +1,24 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s3 () (Array Int Bool) (complement s0))
+[SEND] (get-value (s3))
+[RECV] ((s3 (store (store (store (store ((as const (Array Int Bool)) true) 4 false) 3 false)
+                     2
+                     false)
+              1
+              false)))
+[GOOD] (define-fun s4 () (Array Int Bool) (complement s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s5 () (Array Int Bool) (intersection s3 s0))
+[SEND] (get-value (s5))
+[RECV] ((s5 ((as const (Array Int Bool)) false)))
+[GOOD] (define-fun s6 () (Array Int Bool) (union s3 s0))
+[SEND] (get-value (s6))
+[RECV] ((s6 ((as const (Array Int Bool)) true)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({1,2,3,4},U - {1,2,3,4},{1,2,3,4},{},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,61 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s4 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s6 () (Array Int Bool) (store s1 s0 false))
+[SEND] (get-value (s6))
+[RECV] ((s6 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     1
+                     true)
+              2
+              false)))
+[GOOD] (define-fun s7 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s8 () (Array Int Bool) (store s7 s0 false))
+[SEND] (get-value (s8))
+[RECV] ((s8 (store (store (store (store ((as const (Array Int Bool)) true) 4 false) 3 false)
+                     1
+                     false)
+              2
+              false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+(2,{1,2,3,4},{1,3,4},U - {1,2,3,4})
+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,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s5 () (Array Int Bool) (setminus s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 ((as const (Array Int Bool)) false)))
+[GOOD] (define-fun s6 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s7 () (Array Int Bool) (setminus s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s9 () (Array Int Bool) (setminus s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 (store ((as const (Array Int Bool)) true) 0 false)))
+[GOOD] (define-fun s10 () (Array Int Bool) (setminus s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 ((as const (Array Int Bool)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({0},{0},{},{0},U - {0},{})
+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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s6 () (Array Int Bool) ((as const (Array Int Bool)) false))
+[GOOD] (define-fun s5 () (Array Int Bool) (intersection s0 s1))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s9 () (Array Int Bool) (intersection s0 s8))
+[GOOD] (define-fun s10 () Bool (= s6 s9))
+[SEND] (get-value (s10))
+[RECV] ((s10 true))
+[GOOD] (define-fun s11 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s12 () (Array Int Bool) (intersection s11 s1))
+[GOOD] (define-fun s13 () Bool (= s6 s12))
+[SEND] (get-value (s13))
+[RECV] ((s13 true))
+[GOOD] (define-fun s14 () (Array Int Bool) (intersection s11 s8))
+[GOOD] (define-fun s15 () Bool (= s6 s14))
+[SEND] (get-value (s15))
+[RECV] ((s15 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({0},{0},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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s3 () (Array Int Bool) ((as const (Array Int Bool)) false))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 false))
+[GOOD] (define-fun s5 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s6 () Bool (= s3 s5))
+[SEND] (get-value (s6))
+[RECV] ((s6 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({1,2,3,4},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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s3 () (Array Int Bool) ((as const (Array Int Bool)) true))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 false))
+[GOOD] (define-fun s5 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s6 () Bool (= s3 s5))
+[SEND] (get-value (s6))
+[RECV] ((s6 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({1,2,3,4},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,61 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s4 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s6 () (Array Int Bool) (store s1 s0 true))
+[SEND] (get-value (s6))
+[RECV] ((s6 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     1
+                     true)
+              2
+              true)))
+[GOOD] (define-fun s7 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s8 () (Array Int Bool) (store s7 s0 true))
+[SEND] (get-value (s8))
+[RECV] ((s8 (store (store (store (store ((as const (Array Int Bool)) true) 4 false) 3 false)
+                     1
+                     false)
+              2
+              true)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+(2,{1,2,3,4},{1,2,3,4},U - {1,3,4})
+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,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s5 () (Array Int Bool) (intersection s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s6 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s7 () (Array Int Bool) (intersection s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 ((as const (Array Int Bool)) false)))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s9 () (Array Int Bool) (intersection s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 ((as const (Array Int Bool)) false)))
+[GOOD] (define-fun s10 () (Array Int Bool) (intersection s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 (store ((as const (Array Int Bool)) true) 0 false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({0},{0},{0},{},{},U - {0})
+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,53 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s4 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              true)))
+[GOOD] (define-fun s6 () Bool (select s1 s0))
+[SEND] (get-value (s6))
+[RECV] ((s6 true))
+[GOOD] (define-fun s7 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s8 () Bool (select s7 s0))
+[SEND] (get-value (s8))
+[RECV] ((s8 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+(2,{1,2,3,4},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,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s4 () (Array Int Bool) (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true) 2 true) 1 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 2))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array Int Bool)) false) 4 true) 3 true)
+                     2
+                     true)
+              1
+              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 Int Bool) (complement 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:
+(2,{1,2,3,4},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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s5 () Bool (subset s0 s1))
+[GOOD] (define-fun s6 () Bool (distinct s0 s1))
+[GOOD] (define-fun s7 () Bool (and s5 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s9 () Bool (subset s0 s8))
+[GOOD] (define-fun s10 () Bool (distinct s0 s8))
+[GOOD] (define-fun s11 () Bool (and s9 s10))
+[SEND] (get-value (s11))
+[RECV] ((s11 false))
+[GOOD] (define-fun s12 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s13 () Bool (subset s12 s1))
+[GOOD] (define-fun s14 () Bool (distinct s1 s12))
+[GOOD] (define-fun s15 () Bool (and s13 s14))
+[SEND] (get-value (s15))
+[RECV] ((s15 false))
+[GOOD] (define-fun s16 () Bool (subset s12 s8))
+[GOOD] (define-fun s17 () Bool (distinct s8 s12))
+[GOOD] (define-fun s18 () Bool (and s16 s17))
+[SEND] (get-value (s18))
+[RECV] ((s18 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({0},{0},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,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s5 () Bool (subset s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 true))
+[GOOD] (define-fun s6 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s7 () Bool (subset s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement 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:
+({0},{0},True,False,False,True)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_tupleSet.gold b/SBVTestSuite/GoldFiles/set_tupleSet.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_tupleSet.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has tuples, using catch-all.
+[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 s1 () (SBVTuple2 (Array Bool Bool) (Array Bool Bool)) (mkSBVTuple2 ((as const (Array Bool Bool)) false) ((as const (Array Bool Bool)) false)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (Array Bool Bool) (Array Bool Bool)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 (lambda ((x!1 Bool)) x!1)
+                    (store ((as const (Array Bool Bool)) false) false true))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+Satisfiable. Model:
+  s0 = ({True},{False}) :: ({Bool}, {Bool})
+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,136 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array E Bool))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array E Bool)) false)))
+[GOOD] (push 1)
+[GOOD] (define-fun s1 () (Array E Bool) ((as const (Array E Bool)) false))
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] (assert s2)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) C true)))
+[GOOD] (push 1)
+[GOOD] (define-fun s3 () (Array E Bool) (store ((as const (Array E Bool)) false) (as C E) true))
+[GOOD] (define-fun s4 () Bool (distinct s0 s3))
+[GOOD] (assert s4)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) A true)))
+[GOOD] (push 1)
+[GOOD] (define-fun s5 () (Array E Bool) (store ((as const (Array E Bool)) false) (as A E) true))
+[GOOD] (define-fun s6 () Bool (distinct s0 s5))
+[GOOD] (assert s6)
+Fast allSat, Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) false) B true) A true)))
+[GOOD] (push 1)
+[GOOD] (define-fun s7 () (Array E Bool) (store (store ((as const (Array E Bool)) false) (as B E) true) (as A E) true))
+[GOOD] (define-fun s8 () Bool (distinct s0 s7))
+[GOOD] (assert s8)
+Fast allSat, Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) true) C false) A false)))
+[GOOD] (push 1)
+[GOOD] (define-fun s9 () (Array E Bool) (store (store ((as const (Array E Bool)) true) (as C E) false) (as A E) false))
+[GOOD] (define-fun s10 () Bool (distinct s0 s9))
+[GOOD] (assert s10)
+Fast allSat, Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) true) B false)))
+[GOOD] (push 1)
+[GOOD] (define-fun s11 () (Array E Bool) (store ((as const (Array E Bool)) true) (as B E) false))
+[GOOD] (define-fun s12 () Bool (distinct s0 s11))
+[GOOD] (assert s12)
+Fast allSat, 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) B true)))
+[GOOD] (push 1)
+[GOOD] (define-fun s13 () (Array E Bool) (store (store ((as const (Array E Bool)) false) (as C E) true) (as B E) true))
+[GOOD] (define-fun s14 () Bool (distinct s0 s13))
+[GOOD] (assert s14)
+Fast allSat, Looking for solution 8
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array E Bool)) true)))
+[GOOD] (push 1)
+[GOOD] (define-fun s15 () (Array E Bool) ((as const (Array E Bool)) true))
+[GOOD] (define-fun s16 () Bool (distinct s0 s15))
+[GOOD] (assert s16)
+Fast allSat, Looking for solution 9
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+Solution #1:
+  s0 = U :: {E}
+Solution #2:
+  s0 = {B,C} :: {E}
+Solution #3:
+  s0 = U - {B} :: {E}
+Solution #4:
+  s0 = U - {A,C} :: {E}
+Solution #5:
+  s0 = {A,B} :: {E}
+Solution #6:
+  s0 = {A} :: {E}
+Solution #7:
+  s0 = {C} :: {E}
+Solution #8:
+  s0 = {} :: {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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[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] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) C true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 ((as const (Array E Bool)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({C},{})
+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,55 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array Int Bool) (store ((as const (Array Int Bool)) false) 0 true))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Array Int Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array Int Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array Int Bool)) false) 0 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s5 () (Array Int Bool) (union s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 (store ((as const (Array Int Bool)) false) 0 true)))
+[GOOD] (define-fun s6 () (Array Int Bool) (complement s1))
+[GOOD] (define-fun s7 () (Array Int Bool) (union s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 ((as const (Array Int Bool)) true)))
+[GOOD] (define-fun s8 () (Array Int Bool) (complement s0))
+[GOOD] (define-fun s9 () (Array Int Bool) (union s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 ((as const (Array Int Bool)) true)))
+[GOOD] (define-fun s10 () (Array Int Bool) (union s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 (store ((as const (Array Int Bool)) true) 0 false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({0},{0},{0},U,U,U - {0})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/sha256HashBlock.gold b/SBVTestSuite/GoldFiles/sha256HashBlock.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sha256HashBlock.gold
@@ -0,0 +1,2589 @@
+== BEGIN: "Makefile" ================
+# Makefile for sha256HashBlock. Automatically generated by SBV. Do not edit!
+
+# include any user-defined .mk file in the current directory.
+-include *.mk
+
+CC?=gcc
+CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
+
+all: sha256HashBlock_driver
+
+sha256HashBlock.o: sha256HashBlock.c sha256HashBlock.h
+	${CC} ${CCFLAGS} -c $< -o $@
+
+sha256HashBlock_driver.o: sha256HashBlock_driver.c
+	${CC} ${CCFLAGS} -c $< -o $@
+
+sha256HashBlock_driver: sha256HashBlock.o sha256HashBlock_driver.o
+	${CC} ${CCFLAGS} $^ -o $@
+
+clean:
+	rm -f *.o
+
+veryclean: clean
+	rm -f sha256HashBlock_driver
+== END: "Makefile" ==================
+== BEGIN: "sha256HashBlock.h" ================
+/* Header file for sha256HashBlock. Automatically generated by SBV. Do not edit! */
+
+#ifndef __sha256HashBlock__HEADER_INCLUDED__
+#define __sha256HashBlock__HEADER_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+/* Entry point prototype: */
+void sha256HashBlock(const SWord8 *hIn, const SWord8 *block,
+                     SWord8 *hash);
+
+#endif /* __sha256HashBlock__HEADER_INCLUDED__ */
+== END: "sha256HashBlock.h" ==================
+== BEGIN: "sha256HashBlock_driver.c" ================
+/* Example driver program for sha256HashBlock. */
+/* Automatically generated by SBV. Edit as you see fit! */
+
+#include <stdio.h>
+#include "sha256HashBlock.h"
+
+int main(void)
+{
+  const SWord8 hIn[32] = {
+      0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3,
+      0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05,
+      0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19
+  };
+
+  printf("Contents of input array hIn:\n");
+  int hIn_ctr;
+  for(hIn_ctr = 0; hIn_ctr < 32 ; ++hIn_ctr)
+    printf("  hIn[%2d] = 0x%02"PRIx8"\n", hIn_ctr ,hIn[hIn_ctr]);
+
+  const SWord8 block[64] = {
+      0x53, 0x42, 0x56, 0x20, 0x67, 0x6f, 0x65, 0x73, 0x20, 0x53, 0x48,
+      0x41, 0x32, 0x35, 0x36, 0x21, 0x21, 0x80, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88
+  };
+
+  printf("Contents of input array block:\n");
+  int block_ctr;
+  for(block_ctr = 0; block_ctr < 64 ; ++block_ctr)
+    printf("  block[%2d] = 0x%02"PRIx8"\n", block_ctr ,block[block_ctr]);
+
+  SWord8 hash[32];
+
+  sha256HashBlock(hIn, block, hash);
+
+  printf("sha256HashBlock(hIn, block, hash) ->\n");
+  int hash_ctr;
+  for(hash_ctr = 0; hash_ctr < 32 ; ++hash_ctr)
+    printf("  hash[%2d] = 0x%02"PRIx8"\n", hash_ctr ,hash[hash_ctr]);
+
+  return 0;
+}
+== END: "sha256HashBlock_driver.c" ==================
+== BEGIN: "sha256HashBlock.c" ================
+/* File: "sha256HashBlock.c". Automatically generated by SBV. Do not edit! */
+
+#include "sha256HashBlock.h"
+
+void sha256HashBlock(const SWord8 *hIn, const SWord8 *block,
+                     SWord8 *hash)
+{
+  const SWord8  s0 = hIn[0];
+  const SWord8  s1 = hIn[1];
+  const SWord8  s2 = hIn[2];
+  const SWord8  s3 = hIn[3];
+  const SWord8  s4 = hIn[4];
+  const SWord8  s5 = hIn[5];
+  const SWord8  s6 = hIn[6];
+  const SWord8  s7 = hIn[7];
+  const SWord8  s8 = hIn[8];
+  const SWord8  s9 = hIn[9];
+  const SWord8  s10 = hIn[10];
+  const SWord8  s11 = hIn[11];
+  const SWord8  s12 = hIn[12];
+  const SWord8  s13 = hIn[13];
+  const SWord8  s14 = hIn[14];
+  const SWord8  s15 = hIn[15];
+  const SWord8  s16 = hIn[16];
+  const SWord8  s17 = hIn[17];
+  const SWord8  s18 = hIn[18];
+  const SWord8  s19 = hIn[19];
+  const SWord8  s20 = hIn[20];
+  const SWord8  s21 = hIn[21];
+  const SWord8  s22 = hIn[22];
+  const SWord8  s23 = hIn[23];
+  const SWord8  s24 = hIn[24];
+  const SWord8  s25 = hIn[25];
+  const SWord8  s26 = hIn[26];
+  const SWord8  s27 = hIn[27];
+  const SWord8  s28 = hIn[28];
+  const SWord8  s29 = hIn[29];
+  const SWord8  s30 = hIn[30];
+  const SWord8  s31 = hIn[31];
+  const SWord8  s32 = block[0];
+  const SWord8  s33 = block[1];
+  const SWord8  s34 = block[2];
+  const SWord8  s35 = block[3];
+  const SWord8  s36 = block[4];
+  const SWord8  s37 = block[5];
+  const SWord8  s38 = block[6];
+  const SWord8  s39 = block[7];
+  const SWord8  s40 = block[8];
+  const SWord8  s41 = block[9];
+  const SWord8  s42 = block[10];
+  const SWord8  s43 = block[11];
+  const SWord8  s44 = block[12];
+  const SWord8  s45 = block[13];
+  const SWord8  s46 = block[14];
+  const SWord8  s47 = block[15];
+  const SWord8  s48 = block[16];
+  const SWord8  s49 = block[17];
+  const SWord8  s50 = block[18];
+  const SWord8  s51 = block[19];
+  const SWord8  s52 = block[20];
+  const SWord8  s53 = block[21];
+  const SWord8  s54 = block[22];
+  const SWord8  s55 = block[23];
+  const SWord8  s56 = block[24];
+  const SWord8  s57 = block[25];
+  const SWord8  s58 = block[26];
+  const SWord8  s59 = block[27];
+  const SWord8  s60 = block[28];
+  const SWord8  s61 = block[29];
+  const SWord8  s62 = block[30];
+  const SWord8  s63 = block[31];
+  const SWord8  s64 = block[32];
+  const SWord8  s65 = block[33];
+  const SWord8  s66 = block[34];
+  const SWord8  s67 = block[35];
+  const SWord8  s68 = block[36];
+  const SWord8  s69 = block[37];
+  const SWord8  s70 = block[38];
+  const SWord8  s71 = block[39];
+  const SWord8  s72 = block[40];
+  const SWord8  s73 = block[41];
+  const SWord8  s74 = block[42];
+  const SWord8  s75 = block[43];
+  const SWord8  s76 = block[44];
+  const SWord8  s77 = block[45];
+  const SWord8  s78 = block[46];
+  const SWord8  s79 = block[47];
+  const SWord8  s80 = block[48];
+  const SWord8  s81 = block[49];
+  const SWord8  s82 = block[50];
+  const SWord8  s83 = block[51];
+  const SWord8  s84 = block[52];
+  const SWord8  s85 = block[53];
+  const SWord8  s86 = block[54];
+  const SWord8  s87 = block[55];
+  const SWord8  s88 = block[56];
+  const SWord8  s89 = block[57];
+  const SWord8  s90 = block[58];
+  const SWord8  s91 = block[59];
+  const SWord8  s92 = block[60];
+  const SWord8  s93 = block[61];
+  const SWord8  s94 = block[62];
+  const SWord8  s95 = block[63];
+  const SWord16 s96 = (((SWord16) s0) << 8) | ((SWord16) s1);
+  const SWord16 s97 = (((SWord16) s2) << 8) | ((SWord16) s3);
+  const SWord32 s98 = (((SWord32) s96) << 16) | ((SWord32) s97);
+  const SWord16 s99 = (((SWord16) s16) << 8) | ((SWord16) s17);
+  const SWord16 s100 = (((SWord16) s18) << 8) | ((SWord16) s19);
+  const SWord32 s101 = (((SWord32) s99) << 16) | ((SWord32) s100);
+  const SWord16 s102 = (((SWord16) s4) << 8) | ((SWord16) s5);
+  const SWord16 s103 = (((SWord16) s6) << 8) | ((SWord16) s7);
+  const SWord32 s104 = (((SWord32) s102) << 16) | ((SWord32) s103);
+  const SWord16 s105 = (((SWord16) s20) << 8) | ((SWord16) s21);
+  const SWord16 s106 = (((SWord16) s22) << 8) | ((SWord16) s23);
+  const SWord32 s107 = (((SWord32) s105) << 16) | ((SWord32) s106);
+  const SWord16 s108 = (((SWord16) s8) << 8) | ((SWord16) s9);
+  const SWord16 s109 = (((SWord16) s10) << 8) | ((SWord16) s11);
+  const SWord32 s110 = (((SWord32) s108) << 16) | ((SWord32) s109);
+  const SWord16 s111 = (((SWord16) s24) << 8) | ((SWord16) s25);
+  const SWord16 s112 = (((SWord16) s26) << 8) | ((SWord16) s27);
+  const SWord32 s113 = (((SWord32) s111) << 16) | ((SWord32) s112);
+  const SWord16 s114 = (((SWord16) s12) << 8) | ((SWord16) s13);
+  const SWord16 s115 = (((SWord16) s14) << 8) | ((SWord16) s15);
+  const SWord32 s116 = (((SWord32) s114) << 16) | ((SWord32) s115);
+  const SWord16 s117 = (((SWord16) s28) << 8) | ((SWord16) s29);
+  const SWord16 s118 = (((SWord16) s30) << 8) | ((SWord16) s31);
+  const SWord32 s119 = (((SWord32) s117) << 16) | ((SWord32) s118);
+  const SWord32 s120 = (s101 >> 6) | (s101 << 26);
+  const SWord32 s121 = (s101 >> 11) | (s101 << 21);
+  const SWord32 s122 = s120 ^ s121;
+  const SWord32 s123 = (s101 >> 25) | (s101 << 7);
+  const SWord32 s124 = s122 ^ s123;
+  const SWord32 s125 = s119 + s124;
+  const SWord32 s126 = s101 & s107;
+  const SWord32 s127 = ~s101;
+  const SWord32 s128 = s113 & s127;
+  const SWord32 s129 = s126 ^ s128;
+  const SWord32 s130 = s125 + s129;
+  const SWord32 s132 = s130 + 0x428a2f98UL;
+  const SWord16 s133 = (((SWord16) s32) << 8) | ((SWord16) s33);
+  const SWord16 s134 = (((SWord16) s34) << 8) | ((SWord16) s35);
+  const SWord32 s135 = (((SWord32) s133) << 16) | ((SWord32) s134);
+  const SWord32 s136 = s132 + s135;
+  const SWord32 s137 = s116 + s136;
+  const SWord32 s138 = (s137 >> 6) | (s137 << 26);
+  const SWord32 s139 = (s137 >> 11) | (s137 << 21);
+  const SWord32 s140 = s138 ^ s139;
+  const SWord32 s141 = (s137 >> 25) | (s137 << 7);
+  const SWord32 s142 = s140 ^ s141;
+  const SWord32 s143 = s113 + s142;
+  const SWord32 s144 = s101 & s137;
+  const SWord32 s145 = ~s137;
+  const SWord32 s146 = s107 & s145;
+  const SWord32 s147 = s144 ^ s146;
+  const SWord32 s148 = s143 + s147;
+  const SWord32 s150 = s148 + 0x71374491UL;
+  const SWord16 s151 = (((SWord16) s36) << 8) | ((SWord16) s37);
+  const SWord16 s152 = (((SWord16) s38) << 8) | ((SWord16) s39);
+  const SWord32 s153 = (((SWord32) s151) << 16) | ((SWord32) s152);
+  const SWord32 s154 = s150 + s153;
+  const SWord32 s155 = s110 + s154;
+  const SWord32 s156 = (s155 >> 6) | (s155 << 26);
+  const SWord32 s157 = (s155 >> 11) | (s155 << 21);
+  const SWord32 s158 = s156 ^ s157;
+  const SWord32 s159 = (s155 >> 25) | (s155 << 7);
+  const SWord32 s160 = s158 ^ s159;
+  const SWord32 s161 = s107 + s160;
+  const SWord32 s162 = s137 & s155;
+  const SWord32 s163 = ~s155;
+  const SWord32 s164 = s101 & s163;
+  const SWord32 s165 = s162 ^ s164;
+  const SWord32 s166 = s161 + s165;
+  const SWord32 s168 = s166 + 0xb5c0fbcfUL;
+  const SWord16 s169 = (((SWord16) s40) << 8) | ((SWord16) s41);
+  const SWord16 s170 = (((SWord16) s42) << 8) | ((SWord16) s43);
+  const SWord32 s171 = (((SWord32) s169) << 16) | ((SWord32) s170);
+  const SWord32 s172 = s168 + s171;
+  const SWord32 s173 = s104 + s172;
+  const SWord32 s174 = (s173 >> 6) | (s173 << 26);
+  const SWord32 s175 = (s173 >> 11) | (s173 << 21);
+  const SWord32 s176 = s174 ^ s175;
+  const SWord32 s177 = (s173 >> 25) | (s173 << 7);
+  const SWord32 s178 = s176 ^ s177;
+  const SWord32 s179 = s101 + s178;
+  const SWord32 s180 = s155 & s173;
+  const SWord32 s181 = ~s173;
+  const SWord32 s182 = s137 & s181;
+  const SWord32 s183 = s180 ^ s182;
+  const SWord32 s184 = s179 + s183;
+  const SWord32 s186 = s184 + 0xe9b5dba5UL;
+  const SWord16 s187 = (((SWord16) s44) << 8) | ((SWord16) s45);
+  const SWord16 s188 = (((SWord16) s46) << 8) | ((SWord16) s47);
+  const SWord32 s189 = (((SWord32) s187) << 16) | ((SWord32) s188);
+  const SWord32 s190 = s186 + s189;
+  const SWord32 s191 = s98 + s190;
+  const SWord32 s192 = (s98 >> 2) | (s98 << 30);
+  const SWord32 s193 = (s98 >> 13) | (s98 << 19);
+  const SWord32 s194 = s192 ^ s193;
+  const SWord32 s195 = (s98 >> 22) | (s98 << 10);
+  const SWord32 s196 = s194 ^ s195;
+  const SWord32 s197 = s98 & s104;
+  const SWord32 s198 = s98 & s110;
+  const SWord32 s199 = s197 ^ s198;
+  const SWord32 s200 = s104 & s110;
+  const SWord32 s201 = s199 ^ s200;
+  const SWord32 s202 = s196 + s201;
+  const SWord32 s203 = s136 + s202;
+  const SWord32 s204 = (s203 >> 2) | (s203 << 30);
+  const SWord32 s205 = (s203 >> 13) | (s203 << 19);
+  const SWord32 s206 = s204 ^ s205;
+  const SWord32 s207 = (s203 >> 22) | (s203 << 10);
+  const SWord32 s208 = s206 ^ s207;
+  const SWord32 s209 = s98 & s203;
+  const SWord32 s210 = s104 & s203;
+  const SWord32 s211 = s209 ^ s210;
+  const SWord32 s212 = s197 ^ s211;
+  const SWord32 s213 = s208 + s212;
+  const SWord32 s214 = s154 + s213;
+  const SWord32 s215 = (s214 >> 2) | (s214 << 30);
+  const SWord32 s216 = (s214 >> 13) | (s214 << 19);
+  const SWord32 s217 = s215 ^ s216;
+  const SWord32 s218 = (s214 >> 22) | (s214 << 10);
+  const SWord32 s219 = s217 ^ s218;
+  const SWord32 s220 = s203 & s214;
+  const SWord32 s221 = s98 & s214;
+  const SWord32 s222 = s220 ^ s221;
+  const SWord32 s223 = s209 ^ s222;
+  const SWord32 s224 = s219 + s223;
+  const SWord32 s225 = s172 + s224;
+  const SWord32 s226 = (s191 >> 6) | (s191 << 26);
+  const SWord32 s227 = (s191 >> 11) | (s191 << 21);
+  const SWord32 s228 = s226 ^ s227;
+  const SWord32 s229 = (s191 >> 25) | (s191 << 7);
+  const SWord32 s230 = s228 ^ s229;
+  const SWord32 s231 = s137 + s230;
+  const SWord32 s232 = s173 & s191;
+  const SWord32 s233 = ~s191;
+  const SWord32 s234 = s155 & s233;
+  const SWord32 s235 = s232 ^ s234;
+  const SWord32 s236 = s231 + s235;
+  const SWord32 s238 = s236 + 0x3956c25bUL;
+  const SWord16 s239 = (((SWord16) s48) << 8) | ((SWord16) s49);
+  const SWord16 s240 = (((SWord16) s50) << 8) | ((SWord16) s51);
+  const SWord32 s241 = (((SWord32) s239) << 16) | ((SWord32) s240);
+  const SWord32 s242 = s238 + s241;
+  const SWord32 s243 = s203 + s242;
+  const SWord32 s244 = (s243 >> 6) | (s243 << 26);
+  const SWord32 s245 = (s243 >> 11) | (s243 << 21);
+  const SWord32 s246 = s244 ^ s245;
+  const SWord32 s247 = (s243 >> 25) | (s243 << 7);
+  const SWord32 s248 = s246 ^ s247;
+  const SWord32 s249 = s155 + s248;
+  const SWord32 s250 = s191 & s243;
+  const SWord32 s251 = ~s243;
+  const SWord32 s252 = s173 & s251;
+  const SWord32 s253 = s250 ^ s252;
+  const SWord32 s254 = s249 + s253;
+  const SWord32 s256 = s254 + 0x59f111f1UL;
+  const SWord16 s257 = (((SWord16) s52) << 8) | ((SWord16) s53);
+  const SWord16 s258 = (((SWord16) s54) << 8) | ((SWord16) s55);
+  const SWord32 s259 = (((SWord32) s257) << 16) | ((SWord32) s258);
+  const SWord32 s260 = s256 + s259;
+  const SWord32 s261 = s214 + s260;
+  const SWord32 s262 = (s261 >> 6) | (s261 << 26);
+  const SWord32 s263 = (s261 >> 11) | (s261 << 21);
+  const SWord32 s264 = s262 ^ s263;
+  const SWord32 s265 = (s261 >> 25) | (s261 << 7);
+  const SWord32 s266 = s264 ^ s265;
+  const SWord32 s267 = s173 + s266;
+  const SWord32 s268 = s243 & s261;
+  const SWord32 s269 = ~s261;
+  const SWord32 s270 = s191 & s269;
+  const SWord32 s271 = s268 ^ s270;
+  const SWord32 s272 = s267 + s271;
+  const SWord32 s274 = s272 + 0x923f82a4UL;
+  const SWord16 s275 = (((SWord16) s56) << 8) | ((SWord16) s57);
+  const SWord16 s276 = (((SWord16) s58) << 8) | ((SWord16) s59);
+  const SWord32 s277 = (((SWord32) s275) << 16) | ((SWord32) s276);
+  const SWord32 s278 = s274 + s277;
+  const SWord32 s279 = s225 + s278;
+  const SWord32 s280 = (s279 >> 6) | (s279 << 26);
+  const SWord32 s281 = (s279 >> 11) | (s279 << 21);
+  const SWord32 s282 = s280 ^ s281;
+  const SWord32 s283 = (s279 >> 25) | (s279 << 7);
+  const SWord32 s284 = s282 ^ s283;
+  const SWord32 s285 = s191 + s284;
+  const SWord32 s286 = s261 & s279;
+  const SWord32 s287 = ~s279;
+  const SWord32 s288 = s243 & s287;
+  const SWord32 s289 = s286 ^ s288;
+  const SWord32 s290 = s285 + s289;
+  const SWord32 s292 = s290 + 0xab1c5ed5UL;
+  const SWord16 s293 = (((SWord16) s60) << 8) | ((SWord16) s61);
+  const SWord16 s294 = (((SWord16) s62) << 8) | ((SWord16) s63);
+  const SWord32 s295 = (((SWord32) s293) << 16) | ((SWord32) s294);
+  const SWord32 s296 = s292 + s295;
+  const SWord32 s297 = (s225 >> 2) | (s225 << 30);
+  const SWord32 s298 = (s225 >> 13) | (s225 << 19);
+  const SWord32 s299 = s297 ^ s298;
+  const SWord32 s300 = (s225 >> 22) | (s225 << 10);
+  const SWord32 s301 = s299 ^ s300;
+  const SWord32 s302 = s214 & s225;
+  const SWord32 s303 = s203 & s225;
+  const SWord32 s304 = s302 ^ s303;
+  const SWord32 s305 = s220 ^ s304;
+  const SWord32 s306 = s301 + s305;
+  const SWord32 s307 = s190 + s306;
+  const SWord32 s308 = (s307 >> 2) | (s307 << 30);
+  const SWord32 s309 = (s307 >> 13) | (s307 << 19);
+  const SWord32 s310 = s308 ^ s309;
+  const SWord32 s311 = (s307 >> 22) | (s307 << 10);
+  const SWord32 s312 = s310 ^ s311;
+  const SWord32 s313 = s225 & s307;
+  const SWord32 s314 = s214 & s307;
+  const SWord32 s315 = s313 ^ s314;
+  const SWord32 s316 = s302 ^ s315;
+  const SWord32 s317 = s312 + s316;
+  const SWord32 s318 = s242 + s317;
+  const SWord32 s319 = (s318 >> 2) | (s318 << 30);
+  const SWord32 s320 = (s318 >> 13) | (s318 << 19);
+  const SWord32 s321 = s319 ^ s320;
+  const SWord32 s322 = (s318 >> 22) | (s318 << 10);
+  const SWord32 s323 = s321 ^ s322;
+  const SWord32 s324 = s307 & s318;
+  const SWord32 s325 = s225 & s318;
+  const SWord32 s326 = s324 ^ s325;
+  const SWord32 s327 = s313 ^ s326;
+  const SWord32 s328 = s323 + s327;
+  const SWord32 s329 = s260 + s328;
+  const SWord32 s330 = (s329 >> 2) | (s329 << 30);
+  const SWord32 s331 = (s329 >> 13) | (s329 << 19);
+  const SWord32 s332 = s330 ^ s331;
+  const SWord32 s333 = (s329 >> 22) | (s329 << 10);
+  const SWord32 s334 = s332 ^ s333;
+  const SWord32 s335 = s318 & s329;
+  const SWord32 s336 = s307 & s329;
+  const SWord32 s337 = s335 ^ s336;
+  const SWord32 s338 = s324 ^ s337;
+  const SWord32 s339 = s334 + s338;
+  const SWord32 s340 = s278 + s339;
+  const SWord32 s341 = (s340 >> 2) | (s340 << 30);
+  const SWord32 s342 = (s340 >> 13) | (s340 << 19);
+  const SWord32 s343 = s341 ^ s342;
+  const SWord32 s344 = (s340 >> 22) | (s340 << 10);
+  const SWord32 s345 = s343 ^ s344;
+  const SWord32 s346 = s329 & s340;
+  const SWord32 s347 = s318 & s340;
+  const SWord32 s348 = s346 ^ s347;
+  const SWord32 s349 = s335 ^ s348;
+  const SWord32 s350 = s345 + s349;
+  const SWord32 s351 = s296 + s350;
+  const SWord32 s352 = s296 + s307;
+  const SWord32 s353 = (s352 >> 6) | (s352 << 26);
+  const SWord32 s354 = (s352 >> 11) | (s352 << 21);
+  const SWord32 s355 = s353 ^ s354;
+  const SWord32 s356 = (s352 >> 25) | (s352 << 7);
+  const SWord32 s357 = s355 ^ s356;
+  const SWord32 s358 = s243 + s357;
+  const SWord32 s359 = s279 & s352;
+  const SWord32 s360 = ~s352;
+  const SWord32 s361 = s261 & s360;
+  const SWord32 s362 = s359 ^ s361;
+  const SWord32 s363 = s358 + s362;
+  const SWord32 s365 = s363 + 0xd807aa98UL;
+  const SWord16 s366 = (((SWord16) s64) << 8) | ((SWord16) s65);
+  const SWord16 s367 = (((SWord16) s66) << 8) | ((SWord16) s67);
+  const SWord32 s368 = (((SWord32) s366) << 16) | ((SWord32) s367);
+  const SWord32 s369 = s365 + s368;
+  const SWord32 s370 = s318 + s369;
+  const SWord32 s371 = (s370 >> 6) | (s370 << 26);
+  const SWord32 s372 = (s370 >> 11) | (s370 << 21);
+  const SWord32 s373 = s371 ^ s372;
+  const SWord32 s374 = (s370 >> 25) | (s370 << 7);
+  const SWord32 s375 = s373 ^ s374;
+  const SWord32 s376 = s261 + s375;
+  const SWord32 s377 = s352 & s370;
+  const SWord32 s378 = ~s370;
+  const SWord32 s379 = s279 & s378;
+  const SWord32 s380 = s377 ^ s379;
+  const SWord32 s381 = s376 + s380;
+  const SWord32 s383 = s381 + 0x12835b01UL;
+  const SWord16 s384 = (((SWord16) s68) << 8) | ((SWord16) s69);
+  const SWord16 s385 = (((SWord16) s70) << 8) | ((SWord16) s71);
+  const SWord32 s386 = (((SWord32) s384) << 16) | ((SWord32) s385);
+  const SWord32 s387 = s383 + s386;
+  const SWord32 s388 = s329 + s387;
+  const SWord32 s389 = (s388 >> 6) | (s388 << 26);
+  const SWord32 s390 = (s388 >> 11) | (s388 << 21);
+  const SWord32 s391 = s389 ^ s390;
+  const SWord32 s392 = (s388 >> 25) | (s388 << 7);
+  const SWord32 s393 = s391 ^ s392;
+  const SWord32 s394 = s279 + s393;
+  const SWord32 s395 = s370 & s388;
+  const SWord32 s396 = ~s388;
+  const SWord32 s397 = s352 & s396;
+  const SWord32 s398 = s395 ^ s397;
+  const SWord32 s399 = s394 + s398;
+  const SWord32 s401 = s399 + 0x243185beUL;
+  const SWord16 s402 = (((SWord16) s72) << 8) | ((SWord16) s73);
+  const SWord16 s403 = (((SWord16) s74) << 8) | ((SWord16) s75);
+  const SWord32 s404 = (((SWord32) s402) << 16) | ((SWord32) s403);
+  const SWord32 s405 = s401 + s404;
+  const SWord32 s406 = s340 + s405;
+  const SWord32 s407 = (s406 >> 6) | (s406 << 26);
+  const SWord32 s408 = (s406 >> 11) | (s406 << 21);
+  const SWord32 s409 = s407 ^ s408;
+  const SWord32 s410 = (s406 >> 25) | (s406 << 7);
+  const SWord32 s411 = s409 ^ s410;
+  const SWord32 s412 = s352 + s411;
+  const SWord32 s413 = s388 & s406;
+  const SWord32 s414 = ~s406;
+  const SWord32 s415 = s370 & s414;
+  const SWord32 s416 = s413 ^ s415;
+  const SWord32 s417 = s412 + s416;
+  const SWord32 s419 = s417 + 0x550c7dc3UL;
+  const SWord16 s420 = (((SWord16) s76) << 8) | ((SWord16) s77);
+  const SWord16 s421 = (((SWord16) s78) << 8) | ((SWord16) s79);
+  const SWord32 s422 = (((SWord32) s420) << 16) | ((SWord32) s421);
+  const SWord32 s423 = s419 + s422;
+  const SWord32 s424 = s351 + s423;
+  const SWord32 s425 = (s351 >> 2) | (s351 << 30);
+  const SWord32 s426 = (s351 >> 13) | (s351 << 19);
+  const SWord32 s427 = s425 ^ s426;
+  const SWord32 s428 = (s351 >> 22) | (s351 << 10);
+  const SWord32 s429 = s427 ^ s428;
+  const SWord32 s430 = s340 & s351;
+  const SWord32 s431 = s329 & s351;
+  const SWord32 s432 = s430 ^ s431;
+  const SWord32 s433 = s346 ^ s432;
+  const SWord32 s434 = s429 + s433;
+  const SWord32 s435 = s369 + s434;
+  const SWord32 s436 = (s435 >> 2) | (s435 << 30);
+  const SWord32 s437 = (s435 >> 13) | (s435 << 19);
+  const SWord32 s438 = s436 ^ s437;
+  const SWord32 s439 = (s435 >> 22) | (s435 << 10);
+  const SWord32 s440 = s438 ^ s439;
+  const SWord32 s441 = s351 & s435;
+  const SWord32 s442 = s340 & s435;
+  const SWord32 s443 = s441 ^ s442;
+  const SWord32 s444 = s430 ^ s443;
+  const SWord32 s445 = s440 + s444;
+  const SWord32 s446 = s387 + s445;
+  const SWord32 s447 = (s446 >> 2) | (s446 << 30);
+  const SWord32 s448 = (s446 >> 13) | (s446 << 19);
+  const SWord32 s449 = s447 ^ s448;
+  const SWord32 s450 = (s446 >> 22) | (s446 << 10);
+  const SWord32 s451 = s449 ^ s450;
+  const SWord32 s452 = s435 & s446;
+  const SWord32 s453 = s351 & s446;
+  const SWord32 s454 = s452 ^ s453;
+  const SWord32 s455 = s441 ^ s454;
+  const SWord32 s456 = s451 + s455;
+  const SWord32 s457 = s405 + s456;
+  const SWord32 s458 = (s424 >> 6) | (s424 << 26);
+  const SWord32 s459 = (s424 >> 11) | (s424 << 21);
+  const SWord32 s460 = s458 ^ s459;
+  const SWord32 s461 = (s424 >> 25) | (s424 << 7);
+  const SWord32 s462 = s460 ^ s461;
+  const SWord32 s463 = s370 + s462;
+  const SWord32 s464 = s406 & s424;
+  const SWord32 s465 = ~s424;
+  const SWord32 s466 = s388 & s465;
+  const SWord32 s467 = s464 ^ s466;
+  const SWord32 s468 = s463 + s467;
+  const SWord32 s470 = s468 + 0x72be5d74UL;
+  const SWord16 s471 = (((SWord16) s80) << 8) | ((SWord16) s81);
+  const SWord16 s472 = (((SWord16) s82) << 8) | ((SWord16) s83);
+  const SWord32 s473 = (((SWord32) s471) << 16) | ((SWord32) s472);
+  const SWord32 s474 = s470 + s473;
+  const SWord32 s475 = s435 + s474;
+  const SWord32 s476 = (s475 >> 6) | (s475 << 26);
+  const SWord32 s477 = (s475 >> 11) | (s475 << 21);
+  const SWord32 s478 = s476 ^ s477;
+  const SWord32 s479 = (s475 >> 25) | (s475 << 7);
+  const SWord32 s480 = s478 ^ s479;
+  const SWord32 s481 = s388 + s480;
+  const SWord32 s482 = s424 & s475;
+  const SWord32 s483 = ~s475;
+  const SWord32 s484 = s406 & s483;
+  const SWord32 s485 = s482 ^ s484;
+  const SWord32 s486 = s481 + s485;
+  const SWord32 s488 = s486 + 0x80deb1feUL;
+  const SWord16 s489 = (((SWord16) s84) << 8) | ((SWord16) s85);
+  const SWord16 s490 = (((SWord16) s86) << 8) | ((SWord16) s87);
+  const SWord32 s491 = (((SWord32) s489) << 16) | ((SWord32) s490);
+  const SWord32 s492 = s488 + s491;
+  const SWord32 s493 = s446 + s492;
+  const SWord32 s494 = (s493 >> 6) | (s493 << 26);
+  const SWord32 s495 = (s493 >> 11) | (s493 << 21);
+  const SWord32 s496 = s494 ^ s495;
+  const SWord32 s497 = (s493 >> 25) | (s493 << 7);
+  const SWord32 s498 = s496 ^ s497;
+  const SWord32 s499 = s406 + s498;
+  const SWord32 s500 = s475 & s493;
+  const SWord32 s501 = ~s493;
+  const SWord32 s502 = s424 & s501;
+  const SWord32 s503 = s500 ^ s502;
+  const SWord32 s504 = s499 + s503;
+  const SWord32 s506 = s504 + 0x9bdc06a7UL;
+  const SWord16 s507 = (((SWord16) s88) << 8) | ((SWord16) s89);
+  const SWord16 s508 = (((SWord16) s90) << 8) | ((SWord16) s91);
+  const SWord32 s509 = (((SWord32) s507) << 16) | ((SWord32) s508);
+  const SWord32 s510 = s506 + s509;
+  const SWord32 s511 = s457 + s510;
+  const SWord32 s512 = (s511 >> 6) | (s511 << 26);
+  const SWord32 s513 = (s511 >> 11) | (s511 << 21);
+  const SWord32 s514 = s512 ^ s513;
+  const SWord32 s515 = (s511 >> 25) | (s511 << 7);
+  const SWord32 s516 = s514 ^ s515;
+  const SWord32 s517 = s424 + s516;
+  const SWord32 s518 = s493 & s511;
+  const SWord32 s519 = ~s511;
+  const SWord32 s520 = s475 & s519;
+  const SWord32 s521 = s518 ^ s520;
+  const SWord32 s522 = s517 + s521;
+  const SWord32 s524 = s522 + 0xc19bf174UL;
+  const SWord16 s525 = (((SWord16) s92) << 8) | ((SWord16) s93);
+  const SWord16 s526 = (((SWord16) s94) << 8) | ((SWord16) s95);
+  const SWord32 s527 = (((SWord32) s525) << 16) | ((SWord32) s526);
+  const SWord32 s528 = s524 + s527;
+  const SWord32 s529 = (s457 >> 2) | (s457 << 30);
+  const SWord32 s530 = (s457 >> 13) | (s457 << 19);
+  const SWord32 s531 = s529 ^ s530;
+  const SWord32 s532 = (s457 >> 22) | (s457 << 10);
+  const SWord32 s533 = s531 ^ s532;
+  const SWord32 s534 = s446 & s457;
+  const SWord32 s535 = s435 & s457;
+  const SWord32 s536 = s534 ^ s535;
+  const SWord32 s537 = s452 ^ s536;
+  const SWord32 s538 = s533 + s537;
+  const SWord32 s539 = s423 + s538;
+  const SWord32 s540 = (s539 >> 2) | (s539 << 30);
+  const SWord32 s541 = (s539 >> 13) | (s539 << 19);
+  const SWord32 s542 = s540 ^ s541;
+  const SWord32 s543 = (s539 >> 22) | (s539 << 10);
+  const SWord32 s544 = s542 ^ s543;
+  const SWord32 s545 = s457 & s539;
+  const SWord32 s546 = s446 & s539;
+  const SWord32 s547 = s545 ^ s546;
+  const SWord32 s548 = s534 ^ s547;
+  const SWord32 s549 = s544 + s548;
+  const SWord32 s550 = s474 + s549;
+  const SWord32 s551 = (s550 >> 2) | (s550 << 30);
+  const SWord32 s552 = (s550 >> 13) | (s550 << 19);
+  const SWord32 s553 = s551 ^ s552;
+  const SWord32 s554 = (s550 >> 22) | (s550 << 10);
+  const SWord32 s555 = s553 ^ s554;
+  const SWord32 s556 = s539 & s550;
+  const SWord32 s557 = s457 & s550;
+  const SWord32 s558 = s556 ^ s557;
+  const SWord32 s559 = s545 ^ s558;
+  const SWord32 s560 = s555 + s559;
+  const SWord32 s561 = s492 + s560;
+  const SWord32 s562 = (s561 >> 2) | (s561 << 30);
+  const SWord32 s563 = (s561 >> 13) | (s561 << 19);
+  const SWord32 s564 = s562 ^ s563;
+  const SWord32 s565 = (s561 >> 22) | (s561 << 10);
+  const SWord32 s566 = s564 ^ s565;
+  const SWord32 s567 = s550 & s561;
+  const SWord32 s568 = s539 & s561;
+  const SWord32 s569 = s567 ^ s568;
+  const SWord32 s570 = s556 ^ s569;
+  const SWord32 s571 = s566 + s570;
+  const SWord32 s572 = s510 + s571;
+  const SWord32 s573 = (s572 >> 2) | (s572 << 30);
+  const SWord32 s574 = (s572 >> 13) | (s572 << 19);
+  const SWord32 s575 = s573 ^ s574;
+  const SWord32 s576 = (s572 >> 22) | (s572 << 10);
+  const SWord32 s577 = s575 ^ s576;
+  const SWord32 s578 = s561 & s572;
+  const SWord32 s579 = s550 & s572;
+  const SWord32 s580 = s578 ^ s579;
+  const SWord32 s581 = s567 ^ s580;
+  const SWord32 s582 = s577 + s581;
+  const SWord32 s583 = s528 + s582;
+  const SWord32 s584 = s528 + s539;
+  const SWord32 s585 = (s584 >> 6) | (s584 << 26);
+  const SWord32 s586 = (s584 >> 11) | (s584 << 21);
+  const SWord32 s587 = s585 ^ s586;
+  const SWord32 s588 = (s584 >> 25) | (s584 << 7);
+  const SWord32 s589 = s587 ^ s588;
+  const SWord32 s590 = s475 + s589;
+  const SWord32 s591 = s511 & s584;
+  const SWord32 s592 = ~s584;
+  const SWord32 s593 = s493 & s592;
+  const SWord32 s594 = s591 ^ s593;
+  const SWord32 s595 = s590 + s594;
+  const SWord32 s597 = s595 + 0xe49b69c1UL;
+  const SWord32 s598 = (s509 >> 17) | (s509 << 15);
+  const SWord32 s599 = (s509 >> 19) | (s509 << 13);
+  const SWord32 s600 = s598 ^ s599;
+  const SWord32 s602 = s509 >> 10;
+  const SWord32 s603 = s600 ^ s602;
+  const SWord32 s604 = s386 + s603;
+  const SWord32 s605 = (s153 >> 7) | (s153 << 25);
+  const SWord32 s606 = (s153 >> 18) | (s153 << 14);
+  const SWord32 s607 = s605 ^ s606;
+  const SWord32 s609 = s153 >> 3;
+  const SWord32 s610 = s607 ^ s609;
+  const SWord32 s611 = s604 + s610;
+  const SWord32 s612 = s135 + s611;
+  const SWord32 s613 = s597 + s612;
+  const SWord32 s614 = s550 + s613;
+  const SWord32 s615 = (s614 >> 6) | (s614 << 26);
+  const SWord32 s616 = (s614 >> 11) | (s614 << 21);
+  const SWord32 s617 = s615 ^ s616;
+  const SWord32 s618 = (s614 >> 25) | (s614 << 7);
+  const SWord32 s619 = s617 ^ s618;
+  const SWord32 s620 = s493 + s619;
+  const SWord32 s621 = s584 & s614;
+  const SWord32 s622 = ~s614;
+  const SWord32 s623 = s511 & s622;
+  const SWord32 s624 = s621 ^ s623;
+  const SWord32 s625 = s620 + s624;
+  const SWord32 s627 = s625 + 0xefbe4786UL;
+  const SWord32 s628 = (s527 >> 17) | (s527 << 15);
+  const SWord32 s629 = (s527 >> 19) | (s527 << 13);
+  const SWord32 s630 = s628 ^ s629;
+  const SWord32 s631 = s527 >> 10;
+  const SWord32 s632 = s630 ^ s631;
+  const SWord32 s633 = s404 + s632;
+  const SWord32 s634 = (s171 >> 7) | (s171 << 25);
+  const SWord32 s635 = (s171 >> 18) | (s171 << 14);
+  const SWord32 s636 = s634 ^ s635;
+  const SWord32 s637 = s171 >> 3;
+  const SWord32 s638 = s636 ^ s637;
+  const SWord32 s639 = s633 + s638;
+  const SWord32 s640 = s153 + s639;
+  const SWord32 s641 = s627 + s640;
+  const SWord32 s642 = s561 + s641;
+  const SWord32 s643 = (s642 >> 6) | (s642 << 26);
+  const SWord32 s644 = (s642 >> 11) | (s642 << 21);
+  const SWord32 s645 = s643 ^ s644;
+  const SWord32 s646 = (s642 >> 25) | (s642 << 7);
+  const SWord32 s647 = s645 ^ s646;
+  const SWord32 s648 = s511 + s647;
+  const SWord32 s649 = s614 & s642;
+  const SWord32 s650 = ~s642;
+  const SWord32 s651 = s584 & s650;
+  const SWord32 s652 = s649 ^ s651;
+  const SWord32 s653 = s648 + s652;
+  const SWord32 s655 = s653 + 0x0fc19dc6UL;
+  const SWord32 s656 = (s612 >> 17) | (s612 << 15);
+  const SWord32 s657 = (s612 >> 19) | (s612 << 13);
+  const SWord32 s658 = s656 ^ s657;
+  const SWord32 s659 = s612 >> 10;
+  const SWord32 s660 = s658 ^ s659;
+  const SWord32 s661 = s422 + s660;
+  const SWord32 s662 = (s189 >> 7) | (s189 << 25);
+  const SWord32 s663 = (s189 >> 18) | (s189 << 14);
+  const SWord32 s664 = s662 ^ s663;
+  const SWord32 s665 = s189 >> 3;
+  const SWord32 s666 = s664 ^ s665;
+  const SWord32 s667 = s661 + s666;
+  const SWord32 s668 = s171 + s667;
+  const SWord32 s669 = s655 + s668;
+  const SWord32 s670 = s572 + s669;
+  const SWord32 s671 = (s670 >> 6) | (s670 << 26);
+  const SWord32 s672 = (s670 >> 11) | (s670 << 21);
+  const SWord32 s673 = s671 ^ s672;
+  const SWord32 s674 = (s670 >> 25) | (s670 << 7);
+  const SWord32 s675 = s673 ^ s674;
+  const SWord32 s676 = s584 + s675;
+  const SWord32 s677 = s642 & s670;
+  const SWord32 s678 = ~s670;
+  const SWord32 s679 = s614 & s678;
+  const SWord32 s680 = s677 ^ s679;
+  const SWord32 s681 = s676 + s680;
+  const SWord32 s683 = s681 + 0x240ca1ccUL;
+  const SWord32 s684 = (s640 >> 17) | (s640 << 15);
+  const SWord32 s685 = (s640 >> 19) | (s640 << 13);
+  const SWord32 s686 = s684 ^ s685;
+  const SWord32 s687 = s640 >> 10;
+  const SWord32 s688 = s686 ^ s687;
+  const SWord32 s689 = s473 + s688;
+  const SWord32 s690 = (s241 >> 7) | (s241 << 25);
+  const SWord32 s691 = (s241 >> 18) | (s241 << 14);
+  const SWord32 s692 = s690 ^ s691;
+  const SWord32 s693 = s241 >> 3;
+  const SWord32 s694 = s692 ^ s693;
+  const SWord32 s695 = s689 + s694;
+  const SWord32 s696 = s189 + s695;
+  const SWord32 s697 = s683 + s696;
+  const SWord32 s698 = s583 + s697;
+  const SWord32 s699 = (s583 >> 2) | (s583 << 30);
+  const SWord32 s700 = (s583 >> 13) | (s583 << 19);
+  const SWord32 s701 = s699 ^ s700;
+  const SWord32 s702 = (s583 >> 22) | (s583 << 10);
+  const SWord32 s703 = s701 ^ s702;
+  const SWord32 s704 = s572 & s583;
+  const SWord32 s705 = s561 & s583;
+  const SWord32 s706 = s704 ^ s705;
+  const SWord32 s707 = s578 ^ s706;
+  const SWord32 s708 = s703 + s707;
+  const SWord32 s709 = s613 + s708;
+  const SWord32 s710 = (s709 >> 2) | (s709 << 30);
+  const SWord32 s711 = (s709 >> 13) | (s709 << 19);
+  const SWord32 s712 = s710 ^ s711;
+  const SWord32 s713 = (s709 >> 22) | (s709 << 10);
+  const SWord32 s714 = s712 ^ s713;
+  const SWord32 s715 = s583 & s709;
+  const SWord32 s716 = s572 & s709;
+  const SWord32 s717 = s715 ^ s716;
+  const SWord32 s718 = s704 ^ s717;
+  const SWord32 s719 = s714 + s718;
+  const SWord32 s720 = s641 + s719;
+  const SWord32 s721 = (s720 >> 2) | (s720 << 30);
+  const SWord32 s722 = (s720 >> 13) | (s720 << 19);
+  const SWord32 s723 = s721 ^ s722;
+  const SWord32 s724 = (s720 >> 22) | (s720 << 10);
+  const SWord32 s725 = s723 ^ s724;
+  const SWord32 s726 = s709 & s720;
+  const SWord32 s727 = s583 & s720;
+  const SWord32 s728 = s726 ^ s727;
+  const SWord32 s729 = s715 ^ s728;
+  const SWord32 s730 = s725 + s729;
+  const SWord32 s731 = s669 + s730;
+  const SWord32 s732 = (s698 >> 6) | (s698 << 26);
+  const SWord32 s733 = (s698 >> 11) | (s698 << 21);
+  const SWord32 s734 = s732 ^ s733;
+  const SWord32 s735 = (s698 >> 25) | (s698 << 7);
+  const SWord32 s736 = s734 ^ s735;
+  const SWord32 s737 = s614 + s736;
+  const SWord32 s738 = s670 & s698;
+  const SWord32 s739 = ~s698;
+  const SWord32 s740 = s642 & s739;
+  const SWord32 s741 = s738 ^ s740;
+  const SWord32 s742 = s737 + s741;
+  const SWord32 s744 = s742 + 0x2de92c6fUL;
+  const SWord32 s745 = (s668 >> 17) | (s668 << 15);
+  const SWord32 s746 = (s668 >> 19) | (s668 << 13);
+  const SWord32 s747 = s745 ^ s746;
+  const SWord32 s748 = s668 >> 10;
+  const SWord32 s749 = s747 ^ s748;
+  const SWord32 s750 = s491 + s749;
+  const SWord32 s751 = (s259 >> 7) | (s259 << 25);
+  const SWord32 s752 = (s259 >> 18) | (s259 << 14);
+  const SWord32 s753 = s751 ^ s752;
+  const SWord32 s754 = s259 >> 3;
+  const SWord32 s755 = s753 ^ s754;
+  const SWord32 s756 = s750 + s755;
+  const SWord32 s757 = s241 + s756;
+  const SWord32 s758 = s744 + s757;
+  const SWord32 s759 = s709 + s758;
+  const SWord32 s760 = (s759 >> 6) | (s759 << 26);
+  const SWord32 s761 = (s759 >> 11) | (s759 << 21);
+  const SWord32 s762 = s760 ^ s761;
+  const SWord32 s763 = (s759 >> 25) | (s759 << 7);
+  const SWord32 s764 = s762 ^ s763;
+  const SWord32 s765 = s642 + s764;
+  const SWord32 s766 = s698 & s759;
+  const SWord32 s767 = ~s759;
+  const SWord32 s768 = s670 & s767;
+  const SWord32 s769 = s766 ^ s768;
+  const SWord32 s770 = s765 + s769;
+  const SWord32 s772 = s770 + 0x4a7484aaUL;
+  const SWord32 s773 = (s696 >> 17) | (s696 << 15);
+  const SWord32 s774 = (s696 >> 19) | (s696 << 13);
+  const SWord32 s775 = s773 ^ s774;
+  const SWord32 s776 = s696 >> 10;
+  const SWord32 s777 = s775 ^ s776;
+  const SWord32 s778 = s509 + s777;
+  const SWord32 s779 = (s277 >> 7) | (s277 << 25);
+  const SWord32 s780 = (s277 >> 18) | (s277 << 14);
+  const SWord32 s781 = s779 ^ s780;
+  const SWord32 s782 = s277 >> 3;
+  const SWord32 s783 = s781 ^ s782;
+  const SWord32 s784 = s778 + s783;
+  const SWord32 s785 = s259 + s784;
+  const SWord32 s786 = s772 + s785;
+  const SWord32 s787 = s720 + s786;
+  const SWord32 s788 = (s787 >> 6) | (s787 << 26);
+  const SWord32 s789 = (s787 >> 11) | (s787 << 21);
+  const SWord32 s790 = s788 ^ s789;
+  const SWord32 s791 = (s787 >> 25) | (s787 << 7);
+  const SWord32 s792 = s790 ^ s791;
+  const SWord32 s793 = s670 + s792;
+  const SWord32 s794 = s759 & s787;
+  const SWord32 s795 = ~s787;
+  const SWord32 s796 = s698 & s795;
+  const SWord32 s797 = s794 ^ s796;
+  const SWord32 s798 = s793 + s797;
+  const SWord32 s800 = s798 + 0x5cb0a9dcUL;
+  const SWord32 s801 = (s757 >> 17) | (s757 << 15);
+  const SWord32 s802 = (s757 >> 19) | (s757 << 13);
+  const SWord32 s803 = s801 ^ s802;
+  const SWord32 s804 = s757 >> 10;
+  const SWord32 s805 = s803 ^ s804;
+  const SWord32 s806 = s527 + s805;
+  const SWord32 s807 = (s295 >> 7) | (s295 << 25);
+  const SWord32 s808 = (s295 >> 18) | (s295 << 14);
+  const SWord32 s809 = s807 ^ s808;
+  const SWord32 s810 = s295 >> 3;
+  const SWord32 s811 = s809 ^ s810;
+  const SWord32 s812 = s806 + s811;
+  const SWord32 s813 = s277 + s812;
+  const SWord32 s814 = s800 + s813;
+  const SWord32 s815 = s731 + s814;
+  const SWord32 s816 = (s815 >> 6) | (s815 << 26);
+  const SWord32 s817 = (s815 >> 11) | (s815 << 21);
+  const SWord32 s818 = s816 ^ s817;
+  const SWord32 s819 = (s815 >> 25) | (s815 << 7);
+  const SWord32 s820 = s818 ^ s819;
+  const SWord32 s821 = s698 + s820;
+  const SWord32 s822 = s787 & s815;
+  const SWord32 s823 = ~s815;
+  const SWord32 s824 = s759 & s823;
+  const SWord32 s825 = s822 ^ s824;
+  const SWord32 s826 = s821 + s825;
+  const SWord32 s828 = s826 + 0x76f988daUL;
+  const SWord32 s829 = (s785 >> 17) | (s785 << 15);
+  const SWord32 s830 = (s785 >> 19) | (s785 << 13);
+  const SWord32 s831 = s829 ^ s830;
+  const SWord32 s832 = s785 >> 10;
+  const SWord32 s833 = s831 ^ s832;
+  const SWord32 s834 = s612 + s833;
+  const SWord32 s835 = (s368 >> 7) | (s368 << 25);
+  const SWord32 s836 = (s368 >> 18) | (s368 << 14);
+  const SWord32 s837 = s835 ^ s836;
+  const SWord32 s838 = s368 >> 3;
+  const SWord32 s839 = s837 ^ s838;
+  const SWord32 s840 = s834 + s839;
+  const SWord32 s841 = s295 + s840;
+  const SWord32 s842 = s828 + s841;
+  const SWord32 s843 = (s731 >> 2) | (s731 << 30);
+  const SWord32 s844 = (s731 >> 13) | (s731 << 19);
+  const SWord32 s845 = s843 ^ s844;
+  const SWord32 s846 = (s731 >> 22) | (s731 << 10);
+  const SWord32 s847 = s845 ^ s846;
+  const SWord32 s848 = s720 & s731;
+  const SWord32 s849 = s709 & s731;
+  const SWord32 s850 = s848 ^ s849;
+  const SWord32 s851 = s726 ^ s850;
+  const SWord32 s852 = s847 + s851;
+  const SWord32 s853 = s697 + s852;
+  const SWord32 s854 = (s853 >> 2) | (s853 << 30);
+  const SWord32 s855 = (s853 >> 13) | (s853 << 19);
+  const SWord32 s856 = s854 ^ s855;
+  const SWord32 s857 = (s853 >> 22) | (s853 << 10);
+  const SWord32 s858 = s856 ^ s857;
+  const SWord32 s859 = s731 & s853;
+  const SWord32 s860 = s720 & s853;
+  const SWord32 s861 = s859 ^ s860;
+  const SWord32 s862 = s848 ^ s861;
+  const SWord32 s863 = s858 + s862;
+  const SWord32 s864 = s758 + s863;
+  const SWord32 s865 = (s864 >> 2) | (s864 << 30);
+  const SWord32 s866 = (s864 >> 13) | (s864 << 19);
+  const SWord32 s867 = s865 ^ s866;
+  const SWord32 s868 = (s864 >> 22) | (s864 << 10);
+  const SWord32 s869 = s867 ^ s868;
+  const SWord32 s870 = s853 & s864;
+  const SWord32 s871 = s731 & s864;
+  const SWord32 s872 = s870 ^ s871;
+  const SWord32 s873 = s859 ^ s872;
+  const SWord32 s874 = s869 + s873;
+  const SWord32 s875 = s786 + s874;
+  const SWord32 s876 = (s875 >> 2) | (s875 << 30);
+  const SWord32 s877 = (s875 >> 13) | (s875 << 19);
+  const SWord32 s878 = s876 ^ s877;
+  const SWord32 s879 = (s875 >> 22) | (s875 << 10);
+  const SWord32 s880 = s878 ^ s879;
+  const SWord32 s881 = s864 & s875;
+  const SWord32 s882 = s853 & s875;
+  const SWord32 s883 = s881 ^ s882;
+  const SWord32 s884 = s870 ^ s883;
+  const SWord32 s885 = s880 + s884;
+  const SWord32 s886 = s814 + s885;
+  const SWord32 s887 = (s886 >> 2) | (s886 << 30);
+  const SWord32 s888 = (s886 >> 13) | (s886 << 19);
+  const SWord32 s889 = s887 ^ s888;
+  const SWord32 s890 = (s886 >> 22) | (s886 << 10);
+  const SWord32 s891 = s889 ^ s890;
+  const SWord32 s892 = s875 & s886;
+  const SWord32 s893 = s864 & s886;
+  const SWord32 s894 = s892 ^ s893;
+  const SWord32 s895 = s881 ^ s894;
+  const SWord32 s896 = s891 + s895;
+  const SWord32 s897 = s842 + s896;
+  const SWord32 s898 = s842 + s853;
+  const SWord32 s899 = (s898 >> 6) | (s898 << 26);
+  const SWord32 s900 = (s898 >> 11) | (s898 << 21);
+  const SWord32 s901 = s899 ^ s900;
+  const SWord32 s902 = (s898 >> 25) | (s898 << 7);
+  const SWord32 s903 = s901 ^ s902;
+  const SWord32 s904 = s759 + s903;
+  const SWord32 s905 = s815 & s898;
+  const SWord32 s906 = ~s898;
+  const SWord32 s907 = s787 & s906;
+  const SWord32 s908 = s905 ^ s907;
+  const SWord32 s909 = s904 + s908;
+  const SWord32 s911 = s909 + 0x983e5152UL;
+  const SWord32 s912 = (s813 >> 17) | (s813 << 15);
+  const SWord32 s913 = (s813 >> 19) | (s813 << 13);
+  const SWord32 s914 = s912 ^ s913;
+  const SWord32 s915 = s813 >> 10;
+  const SWord32 s916 = s914 ^ s915;
+  const SWord32 s917 = s640 + s916;
+  const SWord32 s918 = (s386 >> 7) | (s386 << 25);
+  const SWord32 s919 = (s386 >> 18) | (s386 << 14);
+  const SWord32 s920 = s918 ^ s919;
+  const SWord32 s921 = s386 >> 3;
+  const SWord32 s922 = s920 ^ s921;
+  const SWord32 s923 = s917 + s922;
+  const SWord32 s924 = s368 + s923;
+  const SWord32 s925 = s911 + s924;
+  const SWord32 s926 = s864 + s925;
+  const SWord32 s927 = (s926 >> 6) | (s926 << 26);
+  const SWord32 s928 = (s926 >> 11) | (s926 << 21);
+  const SWord32 s929 = s927 ^ s928;
+  const SWord32 s930 = (s926 >> 25) | (s926 << 7);
+  const SWord32 s931 = s929 ^ s930;
+  const SWord32 s932 = s787 + s931;
+  const SWord32 s933 = s898 & s926;
+  const SWord32 s934 = ~s926;
+  const SWord32 s935 = s815 & s934;
+  const SWord32 s936 = s933 ^ s935;
+  const SWord32 s937 = s932 + s936;
+  const SWord32 s939 = s937 + 0xa831c66dUL;
+  const SWord32 s940 = (s841 >> 17) | (s841 << 15);
+  const SWord32 s941 = (s841 >> 19) | (s841 << 13);
+  const SWord32 s942 = s940 ^ s941;
+  const SWord32 s943 = s841 >> 10;
+  const SWord32 s944 = s942 ^ s943;
+  const SWord32 s945 = s668 + s944;
+  const SWord32 s946 = (s404 >> 7) | (s404 << 25);
+  const SWord32 s947 = (s404 >> 18) | (s404 << 14);
+  const SWord32 s948 = s946 ^ s947;
+  const SWord32 s949 = s404 >> 3;
+  const SWord32 s950 = s948 ^ s949;
+  const SWord32 s951 = s945 + s950;
+  const SWord32 s952 = s386 + s951;
+  const SWord32 s953 = s939 + s952;
+  const SWord32 s954 = s875 + s953;
+  const SWord32 s955 = (s954 >> 6) | (s954 << 26);
+  const SWord32 s956 = (s954 >> 11) | (s954 << 21);
+  const SWord32 s957 = s955 ^ s956;
+  const SWord32 s958 = (s954 >> 25) | (s954 << 7);
+  const SWord32 s959 = s957 ^ s958;
+  const SWord32 s960 = s815 + s959;
+  const SWord32 s961 = s926 & s954;
+  const SWord32 s962 = ~s954;
+  const SWord32 s963 = s898 & s962;
+  const SWord32 s964 = s961 ^ s963;
+  const SWord32 s965 = s960 + s964;
+  const SWord32 s967 = s965 + 0xb00327c8UL;
+  const SWord32 s968 = (s924 >> 17) | (s924 << 15);
+  const SWord32 s969 = (s924 >> 19) | (s924 << 13);
+  const SWord32 s970 = s968 ^ s969;
+  const SWord32 s971 = s924 >> 10;
+  const SWord32 s972 = s970 ^ s971;
+  const SWord32 s973 = s696 + s972;
+  const SWord32 s974 = (s422 >> 7) | (s422 << 25);
+  const SWord32 s975 = (s422 >> 18) | (s422 << 14);
+  const SWord32 s976 = s974 ^ s975;
+  const SWord32 s977 = s422 >> 3;
+  const SWord32 s978 = s976 ^ s977;
+  const SWord32 s979 = s973 + s978;
+  const SWord32 s980 = s404 + s979;
+  const SWord32 s981 = s967 + s980;
+  const SWord32 s982 = s886 + s981;
+  const SWord32 s983 = (s982 >> 6) | (s982 << 26);
+  const SWord32 s984 = (s982 >> 11) | (s982 << 21);
+  const SWord32 s985 = s983 ^ s984;
+  const SWord32 s986 = (s982 >> 25) | (s982 << 7);
+  const SWord32 s987 = s985 ^ s986;
+  const SWord32 s988 = s898 + s987;
+  const SWord32 s989 = s954 & s982;
+  const SWord32 s990 = ~s982;
+  const SWord32 s991 = s926 & s990;
+  const SWord32 s992 = s989 ^ s991;
+  const SWord32 s993 = s988 + s992;
+  const SWord32 s995 = s993 + 0xbf597fc7UL;
+  const SWord32 s996 = (s952 >> 17) | (s952 << 15);
+  const SWord32 s997 = (s952 >> 19) | (s952 << 13);
+  const SWord32 s998 = s996 ^ s997;
+  const SWord32 s999 = s952 >> 10;
+  const SWord32 s1000 = s998 ^ s999;
+  const SWord32 s1001 = s757 + s1000;
+  const SWord32 s1002 = (s473 >> 7) | (s473 << 25);
+  const SWord32 s1003 = (s473 >> 18) | (s473 << 14);
+  const SWord32 s1004 = s1002 ^ s1003;
+  const SWord32 s1005 = s473 >> 3;
+  const SWord32 s1006 = s1004 ^ s1005;
+  const SWord32 s1007 = s1001 + s1006;
+  const SWord32 s1008 = s422 + s1007;
+  const SWord32 s1009 = s995 + s1008;
+  const SWord32 s1010 = s897 + s1009;
+  const SWord32 s1011 = (s897 >> 2) | (s897 << 30);
+  const SWord32 s1012 = (s897 >> 13) | (s897 << 19);
+  const SWord32 s1013 = s1011 ^ s1012;
+  const SWord32 s1014 = (s897 >> 22) | (s897 << 10);
+  const SWord32 s1015 = s1013 ^ s1014;
+  const SWord32 s1016 = s886 & s897;
+  const SWord32 s1017 = s875 & s897;
+  const SWord32 s1018 = s1016 ^ s1017;
+  const SWord32 s1019 = s892 ^ s1018;
+  const SWord32 s1020 = s1015 + s1019;
+  const SWord32 s1021 = s925 + s1020;
+  const SWord32 s1022 = (s1021 >> 2) | (s1021 << 30);
+  const SWord32 s1023 = (s1021 >> 13) | (s1021 << 19);
+  const SWord32 s1024 = s1022 ^ s1023;
+  const SWord32 s1025 = (s1021 >> 22) | (s1021 << 10);
+  const SWord32 s1026 = s1024 ^ s1025;
+  const SWord32 s1027 = s897 & s1021;
+  const SWord32 s1028 = s886 & s1021;
+  const SWord32 s1029 = s1027 ^ s1028;
+  const SWord32 s1030 = s1016 ^ s1029;
+  const SWord32 s1031 = s1026 + s1030;
+  const SWord32 s1032 = s953 + s1031;
+  const SWord32 s1033 = (s1032 >> 2) | (s1032 << 30);
+  const SWord32 s1034 = (s1032 >> 13) | (s1032 << 19);
+  const SWord32 s1035 = s1033 ^ s1034;
+  const SWord32 s1036 = (s1032 >> 22) | (s1032 << 10);
+  const SWord32 s1037 = s1035 ^ s1036;
+  const SWord32 s1038 = s1021 & s1032;
+  const SWord32 s1039 = s897 & s1032;
+  const SWord32 s1040 = s1038 ^ s1039;
+  const SWord32 s1041 = s1027 ^ s1040;
+  const SWord32 s1042 = s1037 + s1041;
+  const SWord32 s1043 = s981 + s1042;
+  const SWord32 s1044 = (s1010 >> 6) | (s1010 << 26);
+  const SWord32 s1045 = (s1010 >> 11) | (s1010 << 21);
+  const SWord32 s1046 = s1044 ^ s1045;
+  const SWord32 s1047 = (s1010 >> 25) | (s1010 << 7);
+  const SWord32 s1048 = s1046 ^ s1047;
+  const SWord32 s1049 = s926 + s1048;
+  const SWord32 s1050 = s982 & s1010;
+  const SWord32 s1051 = ~s1010;
+  const SWord32 s1052 = s954 & s1051;
+  const SWord32 s1053 = s1050 ^ s1052;
+  const SWord32 s1054 = s1049 + s1053;
+  const SWord32 s1056 = s1054 + 0xc6e00bf3UL;
+  const SWord32 s1057 = (s980 >> 17) | (s980 << 15);
+  const SWord32 s1058 = (s980 >> 19) | (s980 << 13);
+  const SWord32 s1059 = s1057 ^ s1058;
+  const SWord32 s1060 = s980 >> 10;
+  const SWord32 s1061 = s1059 ^ s1060;
+  const SWord32 s1062 = s785 + s1061;
+  const SWord32 s1063 = (s491 >> 7) | (s491 << 25);
+  const SWord32 s1064 = (s491 >> 18) | (s491 << 14);
+  const SWord32 s1065 = s1063 ^ s1064;
+  const SWord32 s1066 = s491 >> 3;
+  const SWord32 s1067 = s1065 ^ s1066;
+  const SWord32 s1068 = s1062 + s1067;
+  const SWord32 s1069 = s473 + s1068;
+  const SWord32 s1070 = s1056 + s1069;
+  const SWord32 s1071 = s1021 + s1070;
+  const SWord32 s1072 = (s1071 >> 6) | (s1071 << 26);
+  const SWord32 s1073 = (s1071 >> 11) | (s1071 << 21);
+  const SWord32 s1074 = s1072 ^ s1073;
+  const SWord32 s1075 = (s1071 >> 25) | (s1071 << 7);
+  const SWord32 s1076 = s1074 ^ s1075;
+  const SWord32 s1077 = s954 + s1076;
+  const SWord32 s1078 = s1010 & s1071;
+  const SWord32 s1079 = ~s1071;
+  const SWord32 s1080 = s982 & s1079;
+  const SWord32 s1081 = s1078 ^ s1080;
+  const SWord32 s1082 = s1077 + s1081;
+  const SWord32 s1084 = s1082 + 0xd5a79147UL;
+  const SWord32 s1085 = (s1008 >> 17) | (s1008 << 15);
+  const SWord32 s1086 = (s1008 >> 19) | (s1008 << 13);
+  const SWord32 s1087 = s1085 ^ s1086;
+  const SWord32 s1088 = s1008 >> 10;
+  const SWord32 s1089 = s1087 ^ s1088;
+  const SWord32 s1090 = s813 + s1089;
+  const SWord32 s1091 = (s509 >> 7) | (s509 << 25);
+  const SWord32 s1092 = (s509 >> 18) | (s509 << 14);
+  const SWord32 s1093 = s1091 ^ s1092;
+  const SWord32 s1094 = s509 >> 3;
+  const SWord32 s1095 = s1093 ^ s1094;
+  const SWord32 s1096 = s1090 + s1095;
+  const SWord32 s1097 = s491 + s1096;
+  const SWord32 s1098 = s1084 + s1097;
+  const SWord32 s1099 = s1032 + s1098;
+  const SWord32 s1100 = (s1099 >> 6) | (s1099 << 26);
+  const SWord32 s1101 = (s1099 >> 11) | (s1099 << 21);
+  const SWord32 s1102 = s1100 ^ s1101;
+  const SWord32 s1103 = (s1099 >> 25) | (s1099 << 7);
+  const SWord32 s1104 = s1102 ^ s1103;
+  const SWord32 s1105 = s982 + s1104;
+  const SWord32 s1106 = s1071 & s1099;
+  const SWord32 s1107 = ~s1099;
+  const SWord32 s1108 = s1010 & s1107;
+  const SWord32 s1109 = s1106 ^ s1108;
+  const SWord32 s1110 = s1105 + s1109;
+  const SWord32 s1112 = s1110 + 0x06ca6351UL;
+  const SWord32 s1113 = (s1069 >> 17) | (s1069 << 15);
+  const SWord32 s1114 = (s1069 >> 19) | (s1069 << 13);
+  const SWord32 s1115 = s1113 ^ s1114;
+  const SWord32 s1116 = s1069 >> 10;
+  const SWord32 s1117 = s1115 ^ s1116;
+  const SWord32 s1118 = s841 + s1117;
+  const SWord32 s1119 = (s527 >> 7) | (s527 << 25);
+  const SWord32 s1120 = (s527 >> 18) | (s527 << 14);
+  const SWord32 s1121 = s1119 ^ s1120;
+  const SWord32 s1122 = s527 >> 3;
+  const SWord32 s1123 = s1121 ^ s1122;
+  const SWord32 s1124 = s1118 + s1123;
+  const SWord32 s1125 = s509 + s1124;
+  const SWord32 s1126 = s1112 + s1125;
+  const SWord32 s1127 = s1043 + s1126;
+  const SWord32 s1128 = (s1127 >> 6) | (s1127 << 26);
+  const SWord32 s1129 = (s1127 >> 11) | (s1127 << 21);
+  const SWord32 s1130 = s1128 ^ s1129;
+  const SWord32 s1131 = (s1127 >> 25) | (s1127 << 7);
+  const SWord32 s1132 = s1130 ^ s1131;
+  const SWord32 s1133 = s1010 + s1132;
+  const SWord32 s1134 = s1099 & s1127;
+  const SWord32 s1135 = ~s1127;
+  const SWord32 s1136 = s1071 & s1135;
+  const SWord32 s1137 = s1134 ^ s1136;
+  const SWord32 s1138 = s1133 + s1137;
+  const SWord32 s1140 = s1138 + 0x14292967UL;
+  const SWord32 s1141 = (s1097 >> 17) | (s1097 << 15);
+  const SWord32 s1142 = (s1097 >> 19) | (s1097 << 13);
+  const SWord32 s1143 = s1141 ^ s1142;
+  const SWord32 s1144 = s1097 >> 10;
+  const SWord32 s1145 = s1143 ^ s1144;
+  const SWord32 s1146 = s924 + s1145;
+  const SWord32 s1147 = (s612 >> 7) | (s612 << 25);
+  const SWord32 s1148 = (s612 >> 18) | (s612 << 14);
+  const SWord32 s1149 = s1147 ^ s1148;
+  const SWord32 s1150 = s612 >> 3;
+  const SWord32 s1151 = s1149 ^ s1150;
+  const SWord32 s1152 = s1146 + s1151;
+  const SWord32 s1153 = s527 + s1152;
+  const SWord32 s1154 = s1140 + s1153;
+  const SWord32 s1155 = (s1043 >> 2) | (s1043 << 30);
+  const SWord32 s1156 = (s1043 >> 13) | (s1043 << 19);
+  const SWord32 s1157 = s1155 ^ s1156;
+  const SWord32 s1158 = (s1043 >> 22) | (s1043 << 10);
+  const SWord32 s1159 = s1157 ^ s1158;
+  const SWord32 s1160 = s1032 & s1043;
+  const SWord32 s1161 = s1021 & s1043;
+  const SWord32 s1162 = s1160 ^ s1161;
+  const SWord32 s1163 = s1038 ^ s1162;
+  const SWord32 s1164 = s1159 + s1163;
+  const SWord32 s1165 = s1009 + s1164;
+  const SWord32 s1166 = (s1165 >> 2) | (s1165 << 30);
+  const SWord32 s1167 = (s1165 >> 13) | (s1165 << 19);
+  const SWord32 s1168 = s1166 ^ s1167;
+  const SWord32 s1169 = (s1165 >> 22) | (s1165 << 10);
+  const SWord32 s1170 = s1168 ^ s1169;
+  const SWord32 s1171 = s1043 & s1165;
+  const SWord32 s1172 = s1032 & s1165;
+  const SWord32 s1173 = s1171 ^ s1172;
+  const SWord32 s1174 = s1160 ^ s1173;
+  const SWord32 s1175 = s1170 + s1174;
+  const SWord32 s1176 = s1070 + s1175;
+  const SWord32 s1177 = (s1176 >> 2) | (s1176 << 30);
+  const SWord32 s1178 = (s1176 >> 13) | (s1176 << 19);
+  const SWord32 s1179 = s1177 ^ s1178;
+  const SWord32 s1180 = (s1176 >> 22) | (s1176 << 10);
+  const SWord32 s1181 = s1179 ^ s1180;
+  const SWord32 s1182 = s1165 & s1176;
+  const SWord32 s1183 = s1043 & s1176;
+  const SWord32 s1184 = s1182 ^ s1183;
+  const SWord32 s1185 = s1171 ^ s1184;
+  const SWord32 s1186 = s1181 + s1185;
+  const SWord32 s1187 = s1098 + s1186;
+  const SWord32 s1188 = (s1187 >> 2) | (s1187 << 30);
+  const SWord32 s1189 = (s1187 >> 13) | (s1187 << 19);
+  const SWord32 s1190 = s1188 ^ s1189;
+  const SWord32 s1191 = (s1187 >> 22) | (s1187 << 10);
+  const SWord32 s1192 = s1190 ^ s1191;
+  const SWord32 s1193 = s1176 & s1187;
+  const SWord32 s1194 = s1165 & s1187;
+  const SWord32 s1195 = s1193 ^ s1194;
+  const SWord32 s1196 = s1182 ^ s1195;
+  const SWord32 s1197 = s1192 + s1196;
+  const SWord32 s1198 = s1126 + s1197;
+  const SWord32 s1199 = (s1198 >> 2) | (s1198 << 30);
+  const SWord32 s1200 = (s1198 >> 13) | (s1198 << 19);
+  const SWord32 s1201 = s1199 ^ s1200;
+  const SWord32 s1202 = (s1198 >> 22) | (s1198 << 10);
+  const SWord32 s1203 = s1201 ^ s1202;
+  const SWord32 s1204 = s1187 & s1198;
+  const SWord32 s1205 = s1176 & s1198;
+  const SWord32 s1206 = s1204 ^ s1205;
+  const SWord32 s1207 = s1193 ^ s1206;
+  const SWord32 s1208 = s1203 + s1207;
+  const SWord32 s1209 = s1154 + s1208;
+  const SWord32 s1210 = s1154 + s1165;
+  const SWord32 s1211 = (s1210 >> 6) | (s1210 << 26);
+  const SWord32 s1212 = (s1210 >> 11) | (s1210 << 21);
+  const SWord32 s1213 = s1211 ^ s1212;
+  const SWord32 s1214 = (s1210 >> 25) | (s1210 << 7);
+  const SWord32 s1215 = s1213 ^ s1214;
+  const SWord32 s1216 = s1071 + s1215;
+  const SWord32 s1217 = s1127 & s1210;
+  const SWord32 s1218 = ~s1210;
+  const SWord32 s1219 = s1099 & s1218;
+  const SWord32 s1220 = s1217 ^ s1219;
+  const SWord32 s1221 = s1216 + s1220;
+  const SWord32 s1223 = s1221 + 0x27b70a85UL;
+  const SWord32 s1224 = (s1125 >> 17) | (s1125 << 15);
+  const SWord32 s1225 = (s1125 >> 19) | (s1125 << 13);
+  const SWord32 s1226 = s1224 ^ s1225;
+  const SWord32 s1227 = s1125 >> 10;
+  const SWord32 s1228 = s1226 ^ s1227;
+  const SWord32 s1229 = s952 + s1228;
+  const SWord32 s1230 = (s640 >> 7) | (s640 << 25);
+  const SWord32 s1231 = (s640 >> 18) | (s640 << 14);
+  const SWord32 s1232 = s1230 ^ s1231;
+  const SWord32 s1233 = s640 >> 3;
+  const SWord32 s1234 = s1232 ^ s1233;
+  const SWord32 s1235 = s1229 + s1234;
+  const SWord32 s1236 = s612 + s1235;
+  const SWord32 s1237 = s1223 + s1236;
+  const SWord32 s1238 = s1176 + s1237;
+  const SWord32 s1239 = (s1238 >> 6) | (s1238 << 26);
+  const SWord32 s1240 = (s1238 >> 11) | (s1238 << 21);
+  const SWord32 s1241 = s1239 ^ s1240;
+  const SWord32 s1242 = (s1238 >> 25) | (s1238 << 7);
+  const SWord32 s1243 = s1241 ^ s1242;
+  const SWord32 s1244 = s1099 + s1243;
+  const SWord32 s1245 = s1210 & s1238;
+  const SWord32 s1246 = ~s1238;
+  const SWord32 s1247 = s1127 & s1246;
+  const SWord32 s1248 = s1245 ^ s1247;
+  const SWord32 s1249 = s1244 + s1248;
+  const SWord32 s1251 = s1249 + 0x2e1b2138UL;
+  const SWord32 s1252 = (s1153 >> 17) | (s1153 << 15);
+  const SWord32 s1253 = (s1153 >> 19) | (s1153 << 13);
+  const SWord32 s1254 = s1252 ^ s1253;
+  const SWord32 s1255 = s1153 >> 10;
+  const SWord32 s1256 = s1254 ^ s1255;
+  const SWord32 s1257 = s980 + s1256;
+  const SWord32 s1258 = (s668 >> 7) | (s668 << 25);
+  const SWord32 s1259 = (s668 >> 18) | (s668 << 14);
+  const SWord32 s1260 = s1258 ^ s1259;
+  const SWord32 s1261 = s668 >> 3;
+  const SWord32 s1262 = s1260 ^ s1261;
+  const SWord32 s1263 = s1257 + s1262;
+  const SWord32 s1264 = s640 + s1263;
+  const SWord32 s1265 = s1251 + s1264;
+  const SWord32 s1266 = s1187 + s1265;
+  const SWord32 s1267 = (s1266 >> 6) | (s1266 << 26);
+  const SWord32 s1268 = (s1266 >> 11) | (s1266 << 21);
+  const SWord32 s1269 = s1267 ^ s1268;
+  const SWord32 s1270 = (s1266 >> 25) | (s1266 << 7);
+  const SWord32 s1271 = s1269 ^ s1270;
+  const SWord32 s1272 = s1127 + s1271;
+  const SWord32 s1273 = s1238 & s1266;
+  const SWord32 s1274 = ~s1266;
+  const SWord32 s1275 = s1210 & s1274;
+  const SWord32 s1276 = s1273 ^ s1275;
+  const SWord32 s1277 = s1272 + s1276;
+  const SWord32 s1279 = s1277 + 0x4d2c6dfcUL;
+  const SWord32 s1280 = (s1236 >> 17) | (s1236 << 15);
+  const SWord32 s1281 = (s1236 >> 19) | (s1236 << 13);
+  const SWord32 s1282 = s1280 ^ s1281;
+  const SWord32 s1283 = s1236 >> 10;
+  const SWord32 s1284 = s1282 ^ s1283;
+  const SWord32 s1285 = s1008 + s1284;
+  const SWord32 s1286 = (s696 >> 7) | (s696 << 25);
+  const SWord32 s1287 = (s696 >> 18) | (s696 << 14);
+  const SWord32 s1288 = s1286 ^ s1287;
+  const SWord32 s1289 = s696 >> 3;
+  const SWord32 s1290 = s1288 ^ s1289;
+  const SWord32 s1291 = s1285 + s1290;
+  const SWord32 s1292 = s668 + s1291;
+  const SWord32 s1293 = s1279 + s1292;
+  const SWord32 s1294 = s1198 + s1293;
+  const SWord32 s1295 = (s1294 >> 6) | (s1294 << 26);
+  const SWord32 s1296 = (s1294 >> 11) | (s1294 << 21);
+  const SWord32 s1297 = s1295 ^ s1296;
+  const SWord32 s1298 = (s1294 >> 25) | (s1294 << 7);
+  const SWord32 s1299 = s1297 ^ s1298;
+  const SWord32 s1300 = s1210 + s1299;
+  const SWord32 s1301 = s1266 & s1294;
+  const SWord32 s1302 = ~s1294;
+  const SWord32 s1303 = s1238 & s1302;
+  const SWord32 s1304 = s1301 ^ s1303;
+  const SWord32 s1305 = s1300 + s1304;
+  const SWord32 s1307 = s1305 + 0x53380d13UL;
+  const SWord32 s1308 = (s1264 >> 17) | (s1264 << 15);
+  const SWord32 s1309 = (s1264 >> 19) | (s1264 << 13);
+  const SWord32 s1310 = s1308 ^ s1309;
+  const SWord32 s1311 = s1264 >> 10;
+  const SWord32 s1312 = s1310 ^ s1311;
+  const SWord32 s1313 = s1069 + s1312;
+  const SWord32 s1314 = (s757 >> 7) | (s757 << 25);
+  const SWord32 s1315 = (s757 >> 18) | (s757 << 14);
+  const SWord32 s1316 = s1314 ^ s1315;
+  const SWord32 s1317 = s757 >> 3;
+  const SWord32 s1318 = s1316 ^ s1317;
+  const SWord32 s1319 = s1313 + s1318;
+  const SWord32 s1320 = s696 + s1319;
+  const SWord32 s1321 = s1307 + s1320;
+  const SWord32 s1322 = s1209 + s1321;
+  const SWord32 s1323 = (s1209 >> 2) | (s1209 << 30);
+  const SWord32 s1324 = (s1209 >> 13) | (s1209 << 19);
+  const SWord32 s1325 = s1323 ^ s1324;
+  const SWord32 s1326 = (s1209 >> 22) | (s1209 << 10);
+  const SWord32 s1327 = s1325 ^ s1326;
+  const SWord32 s1328 = s1198 & s1209;
+  const SWord32 s1329 = s1187 & s1209;
+  const SWord32 s1330 = s1328 ^ s1329;
+  const SWord32 s1331 = s1204 ^ s1330;
+  const SWord32 s1332 = s1327 + s1331;
+  const SWord32 s1333 = s1237 + s1332;
+  const SWord32 s1334 = (s1333 >> 2) | (s1333 << 30);
+  const SWord32 s1335 = (s1333 >> 13) | (s1333 << 19);
+  const SWord32 s1336 = s1334 ^ s1335;
+  const SWord32 s1337 = (s1333 >> 22) | (s1333 << 10);
+  const SWord32 s1338 = s1336 ^ s1337;
+  const SWord32 s1339 = s1209 & s1333;
+  const SWord32 s1340 = s1198 & s1333;
+  const SWord32 s1341 = s1339 ^ s1340;
+  const SWord32 s1342 = s1328 ^ s1341;
+  const SWord32 s1343 = s1338 + s1342;
+  const SWord32 s1344 = s1265 + s1343;
+  const SWord32 s1345 = (s1344 >> 2) | (s1344 << 30);
+  const SWord32 s1346 = (s1344 >> 13) | (s1344 << 19);
+  const SWord32 s1347 = s1345 ^ s1346;
+  const SWord32 s1348 = (s1344 >> 22) | (s1344 << 10);
+  const SWord32 s1349 = s1347 ^ s1348;
+  const SWord32 s1350 = s1333 & s1344;
+  const SWord32 s1351 = s1209 & s1344;
+  const SWord32 s1352 = s1350 ^ s1351;
+  const SWord32 s1353 = s1339 ^ s1352;
+  const SWord32 s1354 = s1349 + s1353;
+  const SWord32 s1355 = s1293 + s1354;
+  const SWord32 s1356 = (s1322 >> 6) | (s1322 << 26);
+  const SWord32 s1357 = (s1322 >> 11) | (s1322 << 21);
+  const SWord32 s1358 = s1356 ^ s1357;
+  const SWord32 s1359 = (s1322 >> 25) | (s1322 << 7);
+  const SWord32 s1360 = s1358 ^ s1359;
+  const SWord32 s1361 = s1238 + s1360;
+  const SWord32 s1362 = s1294 & s1322;
+  const SWord32 s1363 = ~s1322;
+  const SWord32 s1364 = s1266 & s1363;
+  const SWord32 s1365 = s1362 ^ s1364;
+  const SWord32 s1366 = s1361 + s1365;
+  const SWord32 s1368 = s1366 + 0x650a7354UL;
+  const SWord32 s1369 = (s1292 >> 17) | (s1292 << 15);
+  const SWord32 s1370 = (s1292 >> 19) | (s1292 << 13);
+  const SWord32 s1371 = s1369 ^ s1370;
+  const SWord32 s1372 = s1292 >> 10;
+  const SWord32 s1373 = s1371 ^ s1372;
+  const SWord32 s1374 = s1097 + s1373;
+  const SWord32 s1375 = (s785 >> 7) | (s785 << 25);
+  const SWord32 s1376 = (s785 >> 18) | (s785 << 14);
+  const SWord32 s1377 = s1375 ^ s1376;
+  const SWord32 s1378 = s785 >> 3;
+  const SWord32 s1379 = s1377 ^ s1378;
+  const SWord32 s1380 = s1374 + s1379;
+  const SWord32 s1381 = s757 + s1380;
+  const SWord32 s1382 = s1368 + s1381;
+  const SWord32 s1383 = s1333 + s1382;
+  const SWord32 s1384 = (s1383 >> 6) | (s1383 << 26);
+  const SWord32 s1385 = (s1383 >> 11) | (s1383 << 21);
+  const SWord32 s1386 = s1384 ^ s1385;
+  const SWord32 s1387 = (s1383 >> 25) | (s1383 << 7);
+  const SWord32 s1388 = s1386 ^ s1387;
+  const SWord32 s1389 = s1266 + s1388;
+  const SWord32 s1390 = s1322 & s1383;
+  const SWord32 s1391 = ~s1383;
+  const SWord32 s1392 = s1294 & s1391;
+  const SWord32 s1393 = s1390 ^ s1392;
+  const SWord32 s1394 = s1389 + s1393;
+  const SWord32 s1396 = s1394 + 0x766a0abbUL;
+  const SWord32 s1397 = (s1320 >> 17) | (s1320 << 15);
+  const SWord32 s1398 = (s1320 >> 19) | (s1320 << 13);
+  const SWord32 s1399 = s1397 ^ s1398;
+  const SWord32 s1400 = s1320 >> 10;
+  const SWord32 s1401 = s1399 ^ s1400;
+  const SWord32 s1402 = s1125 + s1401;
+  const SWord32 s1403 = (s813 >> 7) | (s813 << 25);
+  const SWord32 s1404 = (s813 >> 18) | (s813 << 14);
+  const SWord32 s1405 = s1403 ^ s1404;
+  const SWord32 s1406 = s813 >> 3;
+  const SWord32 s1407 = s1405 ^ s1406;
+  const SWord32 s1408 = s1402 + s1407;
+  const SWord32 s1409 = s785 + s1408;
+  const SWord32 s1410 = s1396 + s1409;
+  const SWord32 s1411 = s1344 + s1410;
+  const SWord32 s1412 = (s1411 >> 6) | (s1411 << 26);
+  const SWord32 s1413 = (s1411 >> 11) | (s1411 << 21);
+  const SWord32 s1414 = s1412 ^ s1413;
+  const SWord32 s1415 = (s1411 >> 25) | (s1411 << 7);
+  const SWord32 s1416 = s1414 ^ s1415;
+  const SWord32 s1417 = s1294 + s1416;
+  const SWord32 s1418 = s1383 & s1411;
+  const SWord32 s1419 = ~s1411;
+  const SWord32 s1420 = s1322 & s1419;
+  const SWord32 s1421 = s1418 ^ s1420;
+  const SWord32 s1422 = s1417 + s1421;
+  const SWord32 s1424 = s1422 + 0x81c2c92eUL;
+  const SWord32 s1425 = (s1381 >> 17) | (s1381 << 15);
+  const SWord32 s1426 = (s1381 >> 19) | (s1381 << 13);
+  const SWord32 s1427 = s1425 ^ s1426;
+  const SWord32 s1428 = s1381 >> 10;
+  const SWord32 s1429 = s1427 ^ s1428;
+  const SWord32 s1430 = s1153 + s1429;
+  const SWord32 s1431 = (s841 >> 7) | (s841 << 25);
+  const SWord32 s1432 = (s841 >> 18) | (s841 << 14);
+  const SWord32 s1433 = s1431 ^ s1432;
+  const SWord32 s1434 = s841 >> 3;
+  const SWord32 s1435 = s1433 ^ s1434;
+  const SWord32 s1436 = s1430 + s1435;
+  const SWord32 s1437 = s813 + s1436;
+  const SWord32 s1438 = s1424 + s1437;
+  const SWord32 s1439 = s1355 + s1438;
+  const SWord32 s1440 = (s1439 >> 6) | (s1439 << 26);
+  const SWord32 s1441 = (s1439 >> 11) | (s1439 << 21);
+  const SWord32 s1442 = s1440 ^ s1441;
+  const SWord32 s1443 = (s1439 >> 25) | (s1439 << 7);
+  const SWord32 s1444 = s1442 ^ s1443;
+  const SWord32 s1445 = s1322 + s1444;
+  const SWord32 s1446 = s1411 & s1439;
+  const SWord32 s1447 = ~s1439;
+  const SWord32 s1448 = s1383 & s1447;
+  const SWord32 s1449 = s1446 ^ s1448;
+  const SWord32 s1450 = s1445 + s1449;
+  const SWord32 s1452 = s1450 + 0x92722c85UL;
+  const SWord32 s1453 = (s1409 >> 17) | (s1409 << 15);
+  const SWord32 s1454 = (s1409 >> 19) | (s1409 << 13);
+  const SWord32 s1455 = s1453 ^ s1454;
+  const SWord32 s1456 = s1409 >> 10;
+  const SWord32 s1457 = s1455 ^ s1456;
+  const SWord32 s1458 = s1236 + s1457;
+  const SWord32 s1459 = (s924 >> 7) | (s924 << 25);
+  const SWord32 s1460 = (s924 >> 18) | (s924 << 14);
+  const SWord32 s1461 = s1459 ^ s1460;
+  const SWord32 s1462 = s924 >> 3;
+  const SWord32 s1463 = s1461 ^ s1462;
+  const SWord32 s1464 = s1458 + s1463;
+  const SWord32 s1465 = s841 + s1464;
+  const SWord32 s1466 = s1452 + s1465;
+  const SWord32 s1467 = (s1355 >> 2) | (s1355 << 30);
+  const SWord32 s1468 = (s1355 >> 13) | (s1355 << 19);
+  const SWord32 s1469 = s1467 ^ s1468;
+  const SWord32 s1470 = (s1355 >> 22) | (s1355 << 10);
+  const SWord32 s1471 = s1469 ^ s1470;
+  const SWord32 s1472 = s1344 & s1355;
+  const SWord32 s1473 = s1333 & s1355;
+  const SWord32 s1474 = s1472 ^ s1473;
+  const SWord32 s1475 = s1350 ^ s1474;
+  const SWord32 s1476 = s1471 + s1475;
+  const SWord32 s1477 = s1321 + s1476;
+  const SWord32 s1478 = (s1477 >> 2) | (s1477 << 30);
+  const SWord32 s1479 = (s1477 >> 13) | (s1477 << 19);
+  const SWord32 s1480 = s1478 ^ s1479;
+  const SWord32 s1481 = (s1477 >> 22) | (s1477 << 10);
+  const SWord32 s1482 = s1480 ^ s1481;
+  const SWord32 s1483 = s1355 & s1477;
+  const SWord32 s1484 = s1344 & s1477;
+  const SWord32 s1485 = s1483 ^ s1484;
+  const SWord32 s1486 = s1472 ^ s1485;
+  const SWord32 s1487 = s1482 + s1486;
+  const SWord32 s1488 = s1382 + s1487;
+  const SWord32 s1489 = (s1488 >> 2) | (s1488 << 30);
+  const SWord32 s1490 = (s1488 >> 13) | (s1488 << 19);
+  const SWord32 s1491 = s1489 ^ s1490;
+  const SWord32 s1492 = (s1488 >> 22) | (s1488 << 10);
+  const SWord32 s1493 = s1491 ^ s1492;
+  const SWord32 s1494 = s1477 & s1488;
+  const SWord32 s1495 = s1355 & s1488;
+  const SWord32 s1496 = s1494 ^ s1495;
+  const SWord32 s1497 = s1483 ^ s1496;
+  const SWord32 s1498 = s1493 + s1497;
+  const SWord32 s1499 = s1410 + s1498;
+  const SWord32 s1500 = (s1499 >> 2) | (s1499 << 30);
+  const SWord32 s1501 = (s1499 >> 13) | (s1499 << 19);
+  const SWord32 s1502 = s1500 ^ s1501;
+  const SWord32 s1503 = (s1499 >> 22) | (s1499 << 10);
+  const SWord32 s1504 = s1502 ^ s1503;
+  const SWord32 s1505 = s1488 & s1499;
+  const SWord32 s1506 = s1477 & s1499;
+  const SWord32 s1507 = s1505 ^ s1506;
+  const SWord32 s1508 = s1494 ^ s1507;
+  const SWord32 s1509 = s1504 + s1508;
+  const SWord32 s1510 = s1438 + s1509;
+  const SWord32 s1511 = (s1510 >> 2) | (s1510 << 30);
+  const SWord32 s1512 = (s1510 >> 13) | (s1510 << 19);
+  const SWord32 s1513 = s1511 ^ s1512;
+  const SWord32 s1514 = (s1510 >> 22) | (s1510 << 10);
+  const SWord32 s1515 = s1513 ^ s1514;
+  const SWord32 s1516 = s1499 & s1510;
+  const SWord32 s1517 = s1488 & s1510;
+  const SWord32 s1518 = s1516 ^ s1517;
+  const SWord32 s1519 = s1505 ^ s1518;
+  const SWord32 s1520 = s1515 + s1519;
+  const SWord32 s1521 = s1466 + s1520;
+  const SWord32 s1522 = s1466 + s1477;
+  const SWord32 s1523 = (s1522 >> 6) | (s1522 << 26);
+  const SWord32 s1524 = (s1522 >> 11) | (s1522 << 21);
+  const SWord32 s1525 = s1523 ^ s1524;
+  const SWord32 s1526 = (s1522 >> 25) | (s1522 << 7);
+  const SWord32 s1527 = s1525 ^ s1526;
+  const SWord32 s1528 = s1383 + s1527;
+  const SWord32 s1529 = s1439 & s1522;
+  const SWord32 s1530 = ~s1522;
+  const SWord32 s1531 = s1411 & s1530;
+  const SWord32 s1532 = s1529 ^ s1531;
+  const SWord32 s1533 = s1528 + s1532;
+  const SWord32 s1535 = s1533 + 0xa2bfe8a1UL;
+  const SWord32 s1536 = (s1437 >> 17) | (s1437 << 15);
+  const SWord32 s1537 = (s1437 >> 19) | (s1437 << 13);
+  const SWord32 s1538 = s1536 ^ s1537;
+  const SWord32 s1539 = s1437 >> 10;
+  const SWord32 s1540 = s1538 ^ s1539;
+  const SWord32 s1541 = s1264 + s1540;
+  const SWord32 s1542 = (s952 >> 7) | (s952 << 25);
+  const SWord32 s1543 = (s952 >> 18) | (s952 << 14);
+  const SWord32 s1544 = s1542 ^ s1543;
+  const SWord32 s1545 = s952 >> 3;
+  const SWord32 s1546 = s1544 ^ s1545;
+  const SWord32 s1547 = s1541 + s1546;
+  const SWord32 s1548 = s924 + s1547;
+  const SWord32 s1549 = s1535 + s1548;
+  const SWord32 s1550 = s1488 + s1549;
+  const SWord32 s1551 = (s1550 >> 6) | (s1550 << 26);
+  const SWord32 s1552 = (s1550 >> 11) | (s1550 << 21);
+  const SWord32 s1553 = s1551 ^ s1552;
+  const SWord32 s1554 = (s1550 >> 25) | (s1550 << 7);
+  const SWord32 s1555 = s1553 ^ s1554;
+  const SWord32 s1556 = s1411 + s1555;
+  const SWord32 s1557 = s1522 & s1550;
+  const SWord32 s1558 = ~s1550;
+  const SWord32 s1559 = s1439 & s1558;
+  const SWord32 s1560 = s1557 ^ s1559;
+  const SWord32 s1561 = s1556 + s1560;
+  const SWord32 s1563 = s1561 + 0xa81a664bUL;
+  const SWord32 s1564 = (s1465 >> 17) | (s1465 << 15);
+  const SWord32 s1565 = (s1465 >> 19) | (s1465 << 13);
+  const SWord32 s1566 = s1564 ^ s1565;
+  const SWord32 s1567 = s1465 >> 10;
+  const SWord32 s1568 = s1566 ^ s1567;
+  const SWord32 s1569 = s1292 + s1568;
+  const SWord32 s1570 = (s980 >> 7) | (s980 << 25);
+  const SWord32 s1571 = (s980 >> 18) | (s980 << 14);
+  const SWord32 s1572 = s1570 ^ s1571;
+  const SWord32 s1573 = s980 >> 3;
+  const SWord32 s1574 = s1572 ^ s1573;
+  const SWord32 s1575 = s1569 + s1574;
+  const SWord32 s1576 = s952 + s1575;
+  const SWord32 s1577 = s1563 + s1576;
+  const SWord32 s1578 = s1499 + s1577;
+  const SWord32 s1579 = (s1578 >> 6) | (s1578 << 26);
+  const SWord32 s1580 = (s1578 >> 11) | (s1578 << 21);
+  const SWord32 s1581 = s1579 ^ s1580;
+  const SWord32 s1582 = (s1578 >> 25) | (s1578 << 7);
+  const SWord32 s1583 = s1581 ^ s1582;
+  const SWord32 s1584 = s1439 + s1583;
+  const SWord32 s1585 = s1550 & s1578;
+  const SWord32 s1586 = ~s1578;
+  const SWord32 s1587 = s1522 & s1586;
+  const SWord32 s1588 = s1585 ^ s1587;
+  const SWord32 s1589 = s1584 + s1588;
+  const SWord32 s1591 = s1589 + 0xc24b8b70UL;
+  const SWord32 s1592 = (s1548 >> 17) | (s1548 << 15);
+  const SWord32 s1593 = (s1548 >> 19) | (s1548 << 13);
+  const SWord32 s1594 = s1592 ^ s1593;
+  const SWord32 s1595 = s1548 >> 10;
+  const SWord32 s1596 = s1594 ^ s1595;
+  const SWord32 s1597 = s1320 + s1596;
+  const SWord32 s1598 = (s1008 >> 7) | (s1008 << 25);
+  const SWord32 s1599 = (s1008 >> 18) | (s1008 << 14);
+  const SWord32 s1600 = s1598 ^ s1599;
+  const SWord32 s1601 = s1008 >> 3;
+  const SWord32 s1602 = s1600 ^ s1601;
+  const SWord32 s1603 = s1597 + s1602;
+  const SWord32 s1604 = s980 + s1603;
+  const SWord32 s1605 = s1591 + s1604;
+  const SWord32 s1606 = s1510 + s1605;
+  const SWord32 s1607 = (s1606 >> 6) | (s1606 << 26);
+  const SWord32 s1608 = (s1606 >> 11) | (s1606 << 21);
+  const SWord32 s1609 = s1607 ^ s1608;
+  const SWord32 s1610 = (s1606 >> 25) | (s1606 << 7);
+  const SWord32 s1611 = s1609 ^ s1610;
+  const SWord32 s1612 = s1522 + s1611;
+  const SWord32 s1613 = s1578 & s1606;
+  const SWord32 s1614 = ~s1606;
+  const SWord32 s1615 = s1550 & s1614;
+  const SWord32 s1616 = s1613 ^ s1615;
+  const SWord32 s1617 = s1612 + s1616;
+  const SWord32 s1619 = s1617 + 0xc76c51a3UL;
+  const SWord32 s1620 = (s1576 >> 17) | (s1576 << 15);
+  const SWord32 s1621 = (s1576 >> 19) | (s1576 << 13);
+  const SWord32 s1622 = s1620 ^ s1621;
+  const SWord32 s1623 = s1576 >> 10;
+  const SWord32 s1624 = s1622 ^ s1623;
+  const SWord32 s1625 = s1381 + s1624;
+  const SWord32 s1626 = (s1069 >> 7) | (s1069 << 25);
+  const SWord32 s1627 = (s1069 >> 18) | (s1069 << 14);
+  const SWord32 s1628 = s1626 ^ s1627;
+  const SWord32 s1629 = s1069 >> 3;
+  const SWord32 s1630 = s1628 ^ s1629;
+  const SWord32 s1631 = s1625 + s1630;
+  const SWord32 s1632 = s1008 + s1631;
+  const SWord32 s1633 = s1619 + s1632;
+  const SWord32 s1634 = s1521 + s1633;
+  const SWord32 s1635 = (s1521 >> 2) | (s1521 << 30);
+  const SWord32 s1636 = (s1521 >> 13) | (s1521 << 19);
+  const SWord32 s1637 = s1635 ^ s1636;
+  const SWord32 s1638 = (s1521 >> 22) | (s1521 << 10);
+  const SWord32 s1639 = s1637 ^ s1638;
+  const SWord32 s1640 = s1510 & s1521;
+  const SWord32 s1641 = s1499 & s1521;
+  const SWord32 s1642 = s1640 ^ s1641;
+  const SWord32 s1643 = s1516 ^ s1642;
+  const SWord32 s1644 = s1639 + s1643;
+  const SWord32 s1645 = s1549 + s1644;
+  const SWord32 s1646 = (s1645 >> 2) | (s1645 << 30);
+  const SWord32 s1647 = (s1645 >> 13) | (s1645 << 19);
+  const SWord32 s1648 = s1646 ^ s1647;
+  const SWord32 s1649 = (s1645 >> 22) | (s1645 << 10);
+  const SWord32 s1650 = s1648 ^ s1649;
+  const SWord32 s1651 = s1521 & s1645;
+  const SWord32 s1652 = s1510 & s1645;
+  const SWord32 s1653 = s1651 ^ s1652;
+  const SWord32 s1654 = s1640 ^ s1653;
+  const SWord32 s1655 = s1650 + s1654;
+  const SWord32 s1656 = s1577 + s1655;
+  const SWord32 s1657 = (s1656 >> 2) | (s1656 << 30);
+  const SWord32 s1658 = (s1656 >> 13) | (s1656 << 19);
+  const SWord32 s1659 = s1657 ^ s1658;
+  const SWord32 s1660 = (s1656 >> 22) | (s1656 << 10);
+  const SWord32 s1661 = s1659 ^ s1660;
+  const SWord32 s1662 = s1645 & s1656;
+  const SWord32 s1663 = s1521 & s1656;
+  const SWord32 s1664 = s1662 ^ s1663;
+  const SWord32 s1665 = s1651 ^ s1664;
+  const SWord32 s1666 = s1661 + s1665;
+  const SWord32 s1667 = s1605 + s1666;
+  const SWord32 s1668 = (s1634 >> 6) | (s1634 << 26);
+  const SWord32 s1669 = (s1634 >> 11) | (s1634 << 21);
+  const SWord32 s1670 = s1668 ^ s1669;
+  const SWord32 s1671 = (s1634 >> 25) | (s1634 << 7);
+  const SWord32 s1672 = s1670 ^ s1671;
+  const SWord32 s1673 = s1550 + s1672;
+  const SWord32 s1674 = s1606 & s1634;
+  const SWord32 s1675 = ~s1634;
+  const SWord32 s1676 = s1578 & s1675;
+  const SWord32 s1677 = s1674 ^ s1676;
+  const SWord32 s1678 = s1673 + s1677;
+  const SWord32 s1680 = s1678 + 0xd192e819UL;
+  const SWord32 s1681 = (s1604 >> 17) | (s1604 << 15);
+  const SWord32 s1682 = (s1604 >> 19) | (s1604 << 13);
+  const SWord32 s1683 = s1681 ^ s1682;
+  const SWord32 s1684 = s1604 >> 10;
+  const SWord32 s1685 = s1683 ^ s1684;
+  const SWord32 s1686 = s1409 + s1685;
+  const SWord32 s1687 = (s1097 >> 7) | (s1097 << 25);
+  const SWord32 s1688 = (s1097 >> 18) | (s1097 << 14);
+  const SWord32 s1689 = s1687 ^ s1688;
+  const SWord32 s1690 = s1097 >> 3;
+  const SWord32 s1691 = s1689 ^ s1690;
+  const SWord32 s1692 = s1686 + s1691;
+  const SWord32 s1693 = s1069 + s1692;
+  const SWord32 s1694 = s1680 + s1693;
+  const SWord32 s1695 = s1645 + s1694;
+  const SWord32 s1696 = (s1695 >> 6) | (s1695 << 26);
+  const SWord32 s1697 = (s1695 >> 11) | (s1695 << 21);
+  const SWord32 s1698 = s1696 ^ s1697;
+  const SWord32 s1699 = (s1695 >> 25) | (s1695 << 7);
+  const SWord32 s1700 = s1698 ^ s1699;
+  const SWord32 s1701 = s1578 + s1700;
+  const SWord32 s1702 = s1634 & s1695;
+  const SWord32 s1703 = ~s1695;
+  const SWord32 s1704 = s1606 & s1703;
+  const SWord32 s1705 = s1702 ^ s1704;
+  const SWord32 s1706 = s1701 + s1705;
+  const SWord32 s1708 = s1706 + 0xd6990624UL;
+  const SWord32 s1709 = (s1632 >> 17) | (s1632 << 15);
+  const SWord32 s1710 = (s1632 >> 19) | (s1632 << 13);
+  const SWord32 s1711 = s1709 ^ s1710;
+  const SWord32 s1712 = s1632 >> 10;
+  const SWord32 s1713 = s1711 ^ s1712;
+  const SWord32 s1714 = s1437 + s1713;
+  const SWord32 s1715 = (s1125 >> 7) | (s1125 << 25);
+  const SWord32 s1716 = (s1125 >> 18) | (s1125 << 14);
+  const SWord32 s1717 = s1715 ^ s1716;
+  const SWord32 s1718 = s1125 >> 3;
+  const SWord32 s1719 = s1717 ^ s1718;
+  const SWord32 s1720 = s1714 + s1719;
+  const SWord32 s1721 = s1097 + s1720;
+  const SWord32 s1722 = s1708 + s1721;
+  const SWord32 s1723 = s1656 + s1722;
+  const SWord32 s1724 = (s1723 >> 6) | (s1723 << 26);
+  const SWord32 s1725 = (s1723 >> 11) | (s1723 << 21);
+  const SWord32 s1726 = s1724 ^ s1725;
+  const SWord32 s1727 = (s1723 >> 25) | (s1723 << 7);
+  const SWord32 s1728 = s1726 ^ s1727;
+  const SWord32 s1729 = s1606 + s1728;
+  const SWord32 s1730 = s1695 & s1723;
+  const SWord32 s1731 = ~s1723;
+  const SWord32 s1732 = s1634 & s1731;
+  const SWord32 s1733 = s1730 ^ s1732;
+  const SWord32 s1734 = s1729 + s1733;
+  const SWord32 s1736 = s1734 + 0xf40e3585UL;
+  const SWord32 s1737 = (s1693 >> 17) | (s1693 << 15);
+  const SWord32 s1738 = (s1693 >> 19) | (s1693 << 13);
+  const SWord32 s1739 = s1737 ^ s1738;
+  const SWord32 s1740 = s1693 >> 10;
+  const SWord32 s1741 = s1739 ^ s1740;
+  const SWord32 s1742 = s1465 + s1741;
+  const SWord32 s1743 = (s1153 >> 7) | (s1153 << 25);
+  const SWord32 s1744 = (s1153 >> 18) | (s1153 << 14);
+  const SWord32 s1745 = s1743 ^ s1744;
+  const SWord32 s1746 = s1153 >> 3;
+  const SWord32 s1747 = s1745 ^ s1746;
+  const SWord32 s1748 = s1742 + s1747;
+  const SWord32 s1749 = s1125 + s1748;
+  const SWord32 s1750 = s1736 + s1749;
+  const SWord32 s1751 = s1667 + s1750;
+  const SWord32 s1752 = (s1751 >> 6) | (s1751 << 26);
+  const SWord32 s1753 = (s1751 >> 11) | (s1751 << 21);
+  const SWord32 s1754 = s1752 ^ s1753;
+  const SWord32 s1755 = (s1751 >> 25) | (s1751 << 7);
+  const SWord32 s1756 = s1754 ^ s1755;
+  const SWord32 s1757 = s1634 + s1756;
+  const SWord32 s1758 = s1723 & s1751;
+  const SWord32 s1759 = ~s1751;
+  const SWord32 s1760 = s1695 & s1759;
+  const SWord32 s1761 = s1758 ^ s1760;
+  const SWord32 s1762 = s1757 + s1761;
+  const SWord32 s1764 = s1762 + 0x106aa070UL;
+  const SWord32 s1765 = (s1721 >> 17) | (s1721 << 15);
+  const SWord32 s1766 = (s1721 >> 19) | (s1721 << 13);
+  const SWord32 s1767 = s1765 ^ s1766;
+  const SWord32 s1768 = s1721 >> 10;
+  const SWord32 s1769 = s1767 ^ s1768;
+  const SWord32 s1770 = s1548 + s1769;
+  const SWord32 s1771 = (s1236 >> 7) | (s1236 << 25);
+  const SWord32 s1772 = (s1236 >> 18) | (s1236 << 14);
+  const SWord32 s1773 = s1771 ^ s1772;
+  const SWord32 s1774 = s1236 >> 3;
+  const SWord32 s1775 = s1773 ^ s1774;
+  const SWord32 s1776 = s1770 + s1775;
+  const SWord32 s1777 = s1153 + s1776;
+  const SWord32 s1778 = s1764 + s1777;
+  const SWord32 s1779 = (s1667 >> 2) | (s1667 << 30);
+  const SWord32 s1780 = (s1667 >> 13) | (s1667 << 19);
+  const SWord32 s1781 = s1779 ^ s1780;
+  const SWord32 s1782 = (s1667 >> 22) | (s1667 << 10);
+  const SWord32 s1783 = s1781 ^ s1782;
+  const SWord32 s1784 = s1656 & s1667;
+  const SWord32 s1785 = s1645 & s1667;
+  const SWord32 s1786 = s1784 ^ s1785;
+  const SWord32 s1787 = s1662 ^ s1786;
+  const SWord32 s1788 = s1783 + s1787;
+  const SWord32 s1789 = s1633 + s1788;
+  const SWord32 s1790 = (s1789 >> 2) | (s1789 << 30);
+  const SWord32 s1791 = (s1789 >> 13) | (s1789 << 19);
+  const SWord32 s1792 = s1790 ^ s1791;
+  const SWord32 s1793 = (s1789 >> 22) | (s1789 << 10);
+  const SWord32 s1794 = s1792 ^ s1793;
+  const SWord32 s1795 = s1667 & s1789;
+  const SWord32 s1796 = s1656 & s1789;
+  const SWord32 s1797 = s1795 ^ s1796;
+  const SWord32 s1798 = s1784 ^ s1797;
+  const SWord32 s1799 = s1794 + s1798;
+  const SWord32 s1800 = s1694 + s1799;
+  const SWord32 s1801 = (s1800 >> 2) | (s1800 << 30);
+  const SWord32 s1802 = (s1800 >> 13) | (s1800 << 19);
+  const SWord32 s1803 = s1801 ^ s1802;
+  const SWord32 s1804 = (s1800 >> 22) | (s1800 << 10);
+  const SWord32 s1805 = s1803 ^ s1804;
+  const SWord32 s1806 = s1789 & s1800;
+  const SWord32 s1807 = s1667 & s1800;
+  const SWord32 s1808 = s1806 ^ s1807;
+  const SWord32 s1809 = s1795 ^ s1808;
+  const SWord32 s1810 = s1805 + s1809;
+  const SWord32 s1811 = s1722 + s1810;
+  const SWord32 s1812 = (s1811 >> 2) | (s1811 << 30);
+  const SWord32 s1813 = (s1811 >> 13) | (s1811 << 19);
+  const SWord32 s1814 = s1812 ^ s1813;
+  const SWord32 s1815 = (s1811 >> 22) | (s1811 << 10);
+  const SWord32 s1816 = s1814 ^ s1815;
+  const SWord32 s1817 = s1800 & s1811;
+  const SWord32 s1818 = s1789 & s1811;
+  const SWord32 s1819 = s1817 ^ s1818;
+  const SWord32 s1820 = s1806 ^ s1819;
+  const SWord32 s1821 = s1816 + s1820;
+  const SWord32 s1822 = s1750 + s1821;
+  const SWord32 s1823 = (s1822 >> 2) | (s1822 << 30);
+  const SWord32 s1824 = (s1822 >> 13) | (s1822 << 19);
+  const SWord32 s1825 = s1823 ^ s1824;
+  const SWord32 s1826 = (s1822 >> 22) | (s1822 << 10);
+  const SWord32 s1827 = s1825 ^ s1826;
+  const SWord32 s1828 = s1811 & s1822;
+  const SWord32 s1829 = s1800 & s1822;
+  const SWord32 s1830 = s1828 ^ s1829;
+  const SWord32 s1831 = s1817 ^ s1830;
+  const SWord32 s1832 = s1827 + s1831;
+  const SWord32 s1833 = s1778 + s1832;
+  const SWord32 s1834 = s1778 + s1789;
+  const SWord32 s1835 = (s1834 >> 6) | (s1834 << 26);
+  const SWord32 s1836 = (s1834 >> 11) | (s1834 << 21);
+  const SWord32 s1837 = s1835 ^ s1836;
+  const SWord32 s1838 = (s1834 >> 25) | (s1834 << 7);
+  const SWord32 s1839 = s1837 ^ s1838;
+  const SWord32 s1840 = s1695 + s1839;
+  const SWord32 s1841 = s1751 & s1834;
+  const SWord32 s1842 = ~s1834;
+  const SWord32 s1843 = s1723 & s1842;
+  const SWord32 s1844 = s1841 ^ s1843;
+  const SWord32 s1845 = s1840 + s1844;
+  const SWord32 s1847 = s1845 + 0x19a4c116UL;
+  const SWord32 s1848 = (s1749 >> 17) | (s1749 << 15);
+  const SWord32 s1849 = (s1749 >> 19) | (s1749 << 13);
+  const SWord32 s1850 = s1848 ^ s1849;
+  const SWord32 s1851 = s1749 >> 10;
+  const SWord32 s1852 = s1850 ^ s1851;
+  const SWord32 s1853 = s1576 + s1852;
+  const SWord32 s1854 = (s1264 >> 7) | (s1264 << 25);
+  const SWord32 s1855 = (s1264 >> 18) | (s1264 << 14);
+  const SWord32 s1856 = s1854 ^ s1855;
+  const SWord32 s1857 = s1264 >> 3;
+  const SWord32 s1858 = s1856 ^ s1857;
+  const SWord32 s1859 = s1853 + s1858;
+  const SWord32 s1860 = s1236 + s1859;
+  const SWord32 s1861 = s1847 + s1860;
+  const SWord32 s1862 = s1800 + s1861;
+  const SWord32 s1863 = (s1862 >> 6) | (s1862 << 26);
+  const SWord32 s1864 = (s1862 >> 11) | (s1862 << 21);
+  const SWord32 s1865 = s1863 ^ s1864;
+  const SWord32 s1866 = (s1862 >> 25) | (s1862 << 7);
+  const SWord32 s1867 = s1865 ^ s1866;
+  const SWord32 s1868 = s1723 + s1867;
+  const SWord32 s1869 = s1834 & s1862;
+  const SWord32 s1870 = ~s1862;
+  const SWord32 s1871 = s1751 & s1870;
+  const SWord32 s1872 = s1869 ^ s1871;
+  const SWord32 s1873 = s1868 + s1872;
+  const SWord32 s1875 = s1873 + 0x1e376c08UL;
+  const SWord32 s1876 = (s1777 >> 17) | (s1777 << 15);
+  const SWord32 s1877 = (s1777 >> 19) | (s1777 << 13);
+  const SWord32 s1878 = s1876 ^ s1877;
+  const SWord32 s1879 = s1777 >> 10;
+  const SWord32 s1880 = s1878 ^ s1879;
+  const SWord32 s1881 = s1604 + s1880;
+  const SWord32 s1882 = (s1292 >> 7) | (s1292 << 25);
+  const SWord32 s1883 = (s1292 >> 18) | (s1292 << 14);
+  const SWord32 s1884 = s1882 ^ s1883;
+  const SWord32 s1885 = s1292 >> 3;
+  const SWord32 s1886 = s1884 ^ s1885;
+  const SWord32 s1887 = s1881 + s1886;
+  const SWord32 s1888 = s1264 + s1887;
+  const SWord32 s1889 = s1875 + s1888;
+  const SWord32 s1890 = s1811 + s1889;
+  const SWord32 s1891 = (s1890 >> 6) | (s1890 << 26);
+  const SWord32 s1892 = (s1890 >> 11) | (s1890 << 21);
+  const SWord32 s1893 = s1891 ^ s1892;
+  const SWord32 s1894 = (s1890 >> 25) | (s1890 << 7);
+  const SWord32 s1895 = s1893 ^ s1894;
+  const SWord32 s1896 = s1751 + s1895;
+  const SWord32 s1897 = s1862 & s1890;
+  const SWord32 s1898 = ~s1890;
+  const SWord32 s1899 = s1834 & s1898;
+  const SWord32 s1900 = s1897 ^ s1899;
+  const SWord32 s1901 = s1896 + s1900;
+  const SWord32 s1903 = s1901 + 0x2748774cUL;
+  const SWord32 s1904 = (s1860 >> 17) | (s1860 << 15);
+  const SWord32 s1905 = (s1860 >> 19) | (s1860 << 13);
+  const SWord32 s1906 = s1904 ^ s1905;
+  const SWord32 s1907 = s1860 >> 10;
+  const SWord32 s1908 = s1906 ^ s1907;
+  const SWord32 s1909 = s1632 + s1908;
+  const SWord32 s1910 = (s1320 >> 7) | (s1320 << 25);
+  const SWord32 s1911 = (s1320 >> 18) | (s1320 << 14);
+  const SWord32 s1912 = s1910 ^ s1911;
+  const SWord32 s1913 = s1320 >> 3;
+  const SWord32 s1914 = s1912 ^ s1913;
+  const SWord32 s1915 = s1909 + s1914;
+  const SWord32 s1916 = s1292 + s1915;
+  const SWord32 s1917 = s1903 + s1916;
+  const SWord32 s1918 = s1822 + s1917;
+  const SWord32 s1919 = (s1918 >> 6) | (s1918 << 26);
+  const SWord32 s1920 = (s1918 >> 11) | (s1918 << 21);
+  const SWord32 s1921 = s1919 ^ s1920;
+  const SWord32 s1922 = (s1918 >> 25) | (s1918 << 7);
+  const SWord32 s1923 = s1921 ^ s1922;
+  const SWord32 s1924 = s1834 + s1923;
+  const SWord32 s1925 = s1890 & s1918;
+  const SWord32 s1926 = ~s1918;
+  const SWord32 s1927 = s1862 & s1926;
+  const SWord32 s1928 = s1925 ^ s1927;
+  const SWord32 s1929 = s1924 + s1928;
+  const SWord32 s1931 = s1929 + 0x34b0bcb5UL;
+  const SWord32 s1932 = (s1888 >> 17) | (s1888 << 15);
+  const SWord32 s1933 = (s1888 >> 19) | (s1888 << 13);
+  const SWord32 s1934 = s1932 ^ s1933;
+  const SWord32 s1935 = s1888 >> 10;
+  const SWord32 s1936 = s1934 ^ s1935;
+  const SWord32 s1937 = s1693 + s1936;
+  const SWord32 s1938 = (s1381 >> 7) | (s1381 << 25);
+  const SWord32 s1939 = (s1381 >> 18) | (s1381 << 14);
+  const SWord32 s1940 = s1938 ^ s1939;
+  const SWord32 s1941 = s1381 >> 3;
+  const SWord32 s1942 = s1940 ^ s1941;
+  const SWord32 s1943 = s1937 + s1942;
+  const SWord32 s1944 = s1320 + s1943;
+  const SWord32 s1945 = s1931 + s1944;
+  const SWord32 s1946 = s1833 + s1945;
+  const SWord32 s1947 = (s1833 >> 2) | (s1833 << 30);
+  const SWord32 s1948 = (s1833 >> 13) | (s1833 << 19);
+  const SWord32 s1949 = s1947 ^ s1948;
+  const SWord32 s1950 = (s1833 >> 22) | (s1833 << 10);
+  const SWord32 s1951 = s1949 ^ s1950;
+  const SWord32 s1952 = s1822 & s1833;
+  const SWord32 s1953 = s1811 & s1833;
+  const SWord32 s1954 = s1952 ^ s1953;
+  const SWord32 s1955 = s1828 ^ s1954;
+  const SWord32 s1956 = s1951 + s1955;
+  const SWord32 s1957 = s1861 + s1956;
+  const SWord32 s1958 = (s1957 >> 2) | (s1957 << 30);
+  const SWord32 s1959 = (s1957 >> 13) | (s1957 << 19);
+  const SWord32 s1960 = s1958 ^ s1959;
+  const SWord32 s1961 = (s1957 >> 22) | (s1957 << 10);
+  const SWord32 s1962 = s1960 ^ s1961;
+  const SWord32 s1963 = s1833 & s1957;
+  const SWord32 s1964 = s1822 & s1957;
+  const SWord32 s1965 = s1963 ^ s1964;
+  const SWord32 s1966 = s1952 ^ s1965;
+  const SWord32 s1967 = s1962 + s1966;
+  const SWord32 s1968 = s1889 + s1967;
+  const SWord32 s1969 = (s1968 >> 2) | (s1968 << 30);
+  const SWord32 s1970 = (s1968 >> 13) | (s1968 << 19);
+  const SWord32 s1971 = s1969 ^ s1970;
+  const SWord32 s1972 = (s1968 >> 22) | (s1968 << 10);
+  const SWord32 s1973 = s1971 ^ s1972;
+  const SWord32 s1974 = s1957 & s1968;
+  const SWord32 s1975 = s1833 & s1968;
+  const SWord32 s1976 = s1974 ^ s1975;
+  const SWord32 s1977 = s1963 ^ s1976;
+  const SWord32 s1978 = s1973 + s1977;
+  const SWord32 s1979 = s1917 + s1978;
+  const SWord32 s1980 = (s1946 >> 6) | (s1946 << 26);
+  const SWord32 s1981 = (s1946 >> 11) | (s1946 << 21);
+  const SWord32 s1982 = s1980 ^ s1981;
+  const SWord32 s1983 = (s1946 >> 25) | (s1946 << 7);
+  const SWord32 s1984 = s1982 ^ s1983;
+  const SWord32 s1985 = s1862 + s1984;
+  const SWord32 s1986 = s1918 & s1946;
+  const SWord32 s1987 = ~s1946;
+  const SWord32 s1988 = s1890 & s1987;
+  const SWord32 s1989 = s1986 ^ s1988;
+  const SWord32 s1990 = s1985 + s1989;
+  const SWord32 s1992 = s1990 + 0x391c0cb3UL;
+  const SWord32 s1993 = (s1916 >> 17) | (s1916 << 15);
+  const SWord32 s1994 = (s1916 >> 19) | (s1916 << 13);
+  const SWord32 s1995 = s1993 ^ s1994;
+  const SWord32 s1996 = s1916 >> 10;
+  const SWord32 s1997 = s1995 ^ s1996;
+  const SWord32 s1998 = s1721 + s1997;
+  const SWord32 s1999 = (s1409 >> 7) | (s1409 << 25);
+  const SWord32 s2000 = (s1409 >> 18) | (s1409 << 14);
+  const SWord32 s2001 = s1999 ^ s2000;
+  const SWord32 s2002 = s1409 >> 3;
+  const SWord32 s2003 = s2001 ^ s2002;
+  const SWord32 s2004 = s1998 + s2003;
+  const SWord32 s2005 = s1381 + s2004;
+  const SWord32 s2006 = s1992 + s2005;
+  const SWord32 s2007 = s1957 + s2006;
+  const SWord32 s2008 = (s2007 >> 6) | (s2007 << 26);
+  const SWord32 s2009 = (s2007 >> 11) | (s2007 << 21);
+  const SWord32 s2010 = s2008 ^ s2009;
+  const SWord32 s2011 = (s2007 >> 25) | (s2007 << 7);
+  const SWord32 s2012 = s2010 ^ s2011;
+  const SWord32 s2013 = s1890 + s2012;
+  const SWord32 s2014 = s1946 & s2007;
+  const SWord32 s2015 = ~s2007;
+  const SWord32 s2016 = s1918 & s2015;
+  const SWord32 s2017 = s2014 ^ s2016;
+  const SWord32 s2018 = s2013 + s2017;
+  const SWord32 s2020 = s2018 + 0x4ed8aa4aUL;
+  const SWord32 s2021 = (s1944 >> 17) | (s1944 << 15);
+  const SWord32 s2022 = (s1944 >> 19) | (s1944 << 13);
+  const SWord32 s2023 = s2021 ^ s2022;
+  const SWord32 s2024 = s1944 >> 10;
+  const SWord32 s2025 = s2023 ^ s2024;
+  const SWord32 s2026 = s1749 + s2025;
+  const SWord32 s2027 = (s1437 >> 7) | (s1437 << 25);
+  const SWord32 s2028 = (s1437 >> 18) | (s1437 << 14);
+  const SWord32 s2029 = s2027 ^ s2028;
+  const SWord32 s2030 = s1437 >> 3;
+  const SWord32 s2031 = s2029 ^ s2030;
+  const SWord32 s2032 = s2026 + s2031;
+  const SWord32 s2033 = s1409 + s2032;
+  const SWord32 s2034 = s2020 + s2033;
+  const SWord32 s2035 = s1968 + s2034;
+  const SWord32 s2036 = (s2035 >> 6) | (s2035 << 26);
+  const SWord32 s2037 = (s2035 >> 11) | (s2035 << 21);
+  const SWord32 s2038 = s2036 ^ s2037;
+  const SWord32 s2039 = (s2035 >> 25) | (s2035 << 7);
+  const SWord32 s2040 = s2038 ^ s2039;
+  const SWord32 s2041 = s1918 + s2040;
+  const SWord32 s2042 = s2007 & s2035;
+  const SWord32 s2043 = ~s2035;
+  const SWord32 s2044 = s1946 & s2043;
+  const SWord32 s2045 = s2042 ^ s2044;
+  const SWord32 s2046 = s2041 + s2045;
+  const SWord32 s2048 = s2046 + 0x5b9cca4fUL;
+  const SWord32 s2049 = (s2005 >> 17) | (s2005 << 15);
+  const SWord32 s2050 = (s2005 >> 19) | (s2005 << 13);
+  const SWord32 s2051 = s2049 ^ s2050;
+  const SWord32 s2052 = s2005 >> 10;
+  const SWord32 s2053 = s2051 ^ s2052;
+  const SWord32 s2054 = s1777 + s2053;
+  const SWord32 s2055 = (s1465 >> 7) | (s1465 << 25);
+  const SWord32 s2056 = (s1465 >> 18) | (s1465 << 14);
+  const SWord32 s2057 = s2055 ^ s2056;
+  const SWord32 s2058 = s1465 >> 3;
+  const SWord32 s2059 = s2057 ^ s2058;
+  const SWord32 s2060 = s2054 + s2059;
+  const SWord32 s2061 = s1437 + s2060;
+  const SWord32 s2062 = s2048 + s2061;
+  const SWord32 s2063 = s1979 + s2062;
+  const SWord32 s2064 = (s2063 >> 6) | (s2063 << 26);
+  const SWord32 s2065 = (s2063 >> 11) | (s2063 << 21);
+  const SWord32 s2066 = s2064 ^ s2065;
+  const SWord32 s2067 = (s2063 >> 25) | (s2063 << 7);
+  const SWord32 s2068 = s2066 ^ s2067;
+  const SWord32 s2069 = s1946 + s2068;
+  const SWord32 s2070 = s2035 & s2063;
+  const SWord32 s2071 = ~s2063;
+  const SWord32 s2072 = s2007 & s2071;
+  const SWord32 s2073 = s2070 ^ s2072;
+  const SWord32 s2074 = s2069 + s2073;
+  const SWord32 s2076 = s2074 + 0x682e6ff3UL;
+  const SWord32 s2077 = (s2033 >> 17) | (s2033 << 15);
+  const SWord32 s2078 = (s2033 >> 19) | (s2033 << 13);
+  const SWord32 s2079 = s2077 ^ s2078;
+  const SWord32 s2080 = s2033 >> 10;
+  const SWord32 s2081 = s2079 ^ s2080;
+  const SWord32 s2082 = s1860 + s2081;
+  const SWord32 s2083 = (s1548 >> 7) | (s1548 << 25);
+  const SWord32 s2084 = (s1548 >> 18) | (s1548 << 14);
+  const SWord32 s2085 = s2083 ^ s2084;
+  const SWord32 s2086 = s1548 >> 3;
+  const SWord32 s2087 = s2085 ^ s2086;
+  const SWord32 s2088 = s2082 + s2087;
+  const SWord32 s2089 = s1465 + s2088;
+  const SWord32 s2090 = s2076 + s2089;
+  const SWord32 s2091 = (s1979 >> 2) | (s1979 << 30);
+  const SWord32 s2092 = (s1979 >> 13) | (s1979 << 19);
+  const SWord32 s2093 = s2091 ^ s2092;
+  const SWord32 s2094 = (s1979 >> 22) | (s1979 << 10);
+  const SWord32 s2095 = s2093 ^ s2094;
+  const SWord32 s2096 = s1968 & s1979;
+  const SWord32 s2097 = s1957 & s1979;
+  const SWord32 s2098 = s2096 ^ s2097;
+  const SWord32 s2099 = s1974 ^ s2098;
+  const SWord32 s2100 = s2095 + s2099;
+  const SWord32 s2101 = s1945 + s2100;
+  const SWord32 s2102 = (s2101 >> 2) | (s2101 << 30);
+  const SWord32 s2103 = (s2101 >> 13) | (s2101 << 19);
+  const SWord32 s2104 = s2102 ^ s2103;
+  const SWord32 s2105 = (s2101 >> 22) | (s2101 << 10);
+  const SWord32 s2106 = s2104 ^ s2105;
+  const SWord32 s2107 = s1979 & s2101;
+  const SWord32 s2108 = s1968 & s2101;
+  const SWord32 s2109 = s2107 ^ s2108;
+  const SWord32 s2110 = s2096 ^ s2109;
+  const SWord32 s2111 = s2106 + s2110;
+  const SWord32 s2112 = s2006 + s2111;
+  const SWord32 s2113 = (s2112 >> 2) | (s2112 << 30);
+  const SWord32 s2114 = (s2112 >> 13) | (s2112 << 19);
+  const SWord32 s2115 = s2113 ^ s2114;
+  const SWord32 s2116 = (s2112 >> 22) | (s2112 << 10);
+  const SWord32 s2117 = s2115 ^ s2116;
+  const SWord32 s2118 = s2101 & s2112;
+  const SWord32 s2119 = s1979 & s2112;
+  const SWord32 s2120 = s2118 ^ s2119;
+  const SWord32 s2121 = s2107 ^ s2120;
+  const SWord32 s2122 = s2117 + s2121;
+  const SWord32 s2123 = s2034 + s2122;
+  const SWord32 s2124 = (s2123 >> 2) | (s2123 << 30);
+  const SWord32 s2125 = (s2123 >> 13) | (s2123 << 19);
+  const SWord32 s2126 = s2124 ^ s2125;
+  const SWord32 s2127 = (s2123 >> 22) | (s2123 << 10);
+  const SWord32 s2128 = s2126 ^ s2127;
+  const SWord32 s2129 = s2112 & s2123;
+  const SWord32 s2130 = s2101 & s2123;
+  const SWord32 s2131 = s2129 ^ s2130;
+  const SWord32 s2132 = s2118 ^ s2131;
+  const SWord32 s2133 = s2128 + s2132;
+  const SWord32 s2134 = s2062 + s2133;
+  const SWord32 s2135 = (s2134 >> 2) | (s2134 << 30);
+  const SWord32 s2136 = (s2134 >> 13) | (s2134 << 19);
+  const SWord32 s2137 = s2135 ^ s2136;
+  const SWord32 s2138 = (s2134 >> 22) | (s2134 << 10);
+  const SWord32 s2139 = s2137 ^ s2138;
+  const SWord32 s2140 = s2123 & s2134;
+  const SWord32 s2141 = s2112 & s2134;
+  const SWord32 s2142 = s2140 ^ s2141;
+  const SWord32 s2143 = s2129 ^ s2142;
+  const SWord32 s2144 = s2139 + s2143;
+  const SWord32 s2145 = s2090 + s2144;
+  const SWord32 s2146 = s2090 + s2101;
+  const SWord32 s2147 = (s2146 >> 6) | (s2146 << 26);
+  const SWord32 s2148 = (s2146 >> 11) | (s2146 << 21);
+  const SWord32 s2149 = s2147 ^ s2148;
+  const SWord32 s2150 = (s2146 >> 25) | (s2146 << 7);
+  const SWord32 s2151 = s2149 ^ s2150;
+  const SWord32 s2152 = s2007 + s2151;
+  const SWord32 s2153 = s2063 & s2146;
+  const SWord32 s2154 = ~s2146;
+  const SWord32 s2155 = s2035 & s2154;
+  const SWord32 s2156 = s2153 ^ s2155;
+  const SWord32 s2157 = s2152 + s2156;
+  const SWord32 s2159 = s2157 + 0x748f82eeUL;
+  const SWord32 s2160 = (s2061 >> 17) | (s2061 << 15);
+  const SWord32 s2161 = (s2061 >> 19) | (s2061 << 13);
+  const SWord32 s2162 = s2160 ^ s2161;
+  const SWord32 s2163 = s2061 >> 10;
+  const SWord32 s2164 = s2162 ^ s2163;
+  const SWord32 s2165 = s1888 + s2164;
+  const SWord32 s2166 = (s1576 >> 7) | (s1576 << 25);
+  const SWord32 s2167 = (s1576 >> 18) | (s1576 << 14);
+  const SWord32 s2168 = s2166 ^ s2167;
+  const SWord32 s2169 = s1576 >> 3;
+  const SWord32 s2170 = s2168 ^ s2169;
+  const SWord32 s2171 = s2165 + s2170;
+  const SWord32 s2172 = s1548 + s2171;
+  const SWord32 s2173 = s2159 + s2172;
+  const SWord32 s2174 = s2112 + s2173;
+  const SWord32 s2175 = (s2174 >> 6) | (s2174 << 26);
+  const SWord32 s2176 = (s2174 >> 11) | (s2174 << 21);
+  const SWord32 s2177 = s2175 ^ s2176;
+  const SWord32 s2178 = (s2174 >> 25) | (s2174 << 7);
+  const SWord32 s2179 = s2177 ^ s2178;
+  const SWord32 s2180 = s2035 + s2179;
+  const SWord32 s2181 = s2146 & s2174;
+  const SWord32 s2182 = ~s2174;
+  const SWord32 s2183 = s2063 & s2182;
+  const SWord32 s2184 = s2181 ^ s2183;
+  const SWord32 s2185 = s2180 + s2184;
+  const SWord32 s2187 = s2185 + 0x78a5636fUL;
+  const SWord32 s2188 = (s2089 >> 17) | (s2089 << 15);
+  const SWord32 s2189 = (s2089 >> 19) | (s2089 << 13);
+  const SWord32 s2190 = s2188 ^ s2189;
+  const SWord32 s2191 = s2089 >> 10;
+  const SWord32 s2192 = s2190 ^ s2191;
+  const SWord32 s2193 = s1916 + s2192;
+  const SWord32 s2194 = (s1604 >> 7) | (s1604 << 25);
+  const SWord32 s2195 = (s1604 >> 18) | (s1604 << 14);
+  const SWord32 s2196 = s2194 ^ s2195;
+  const SWord32 s2197 = s1604 >> 3;
+  const SWord32 s2198 = s2196 ^ s2197;
+  const SWord32 s2199 = s2193 + s2198;
+  const SWord32 s2200 = s1576 + s2199;
+  const SWord32 s2201 = s2187 + s2200;
+  const SWord32 s2202 = s2123 + s2201;
+  const SWord32 s2203 = (s2202 >> 6) | (s2202 << 26);
+  const SWord32 s2204 = (s2202 >> 11) | (s2202 << 21);
+  const SWord32 s2205 = s2203 ^ s2204;
+  const SWord32 s2206 = (s2202 >> 25) | (s2202 << 7);
+  const SWord32 s2207 = s2205 ^ s2206;
+  const SWord32 s2208 = s2063 + s2207;
+  const SWord32 s2209 = s2174 & s2202;
+  const SWord32 s2210 = ~s2202;
+  const SWord32 s2211 = s2146 & s2210;
+  const SWord32 s2212 = s2209 ^ s2211;
+  const SWord32 s2213 = s2208 + s2212;
+  const SWord32 s2215 = s2213 + 0x84c87814UL;
+  const SWord32 s2216 = (s2172 >> 17) | (s2172 << 15);
+  const SWord32 s2217 = (s2172 >> 19) | (s2172 << 13);
+  const SWord32 s2218 = s2216 ^ s2217;
+  const SWord32 s2219 = s2172 >> 10;
+  const SWord32 s2220 = s2218 ^ s2219;
+  const SWord32 s2221 = s1944 + s2220;
+  const SWord32 s2222 = (s1632 >> 7) | (s1632 << 25);
+  const SWord32 s2223 = (s1632 >> 18) | (s1632 << 14);
+  const SWord32 s2224 = s2222 ^ s2223;
+  const SWord32 s2225 = s1632 >> 3;
+  const SWord32 s2226 = s2224 ^ s2225;
+  const SWord32 s2227 = s2221 + s2226;
+  const SWord32 s2228 = s1604 + s2227;
+  const SWord32 s2229 = s2215 + s2228;
+  const SWord32 s2230 = s2134 + s2229;
+  const SWord32 s2231 = (s2230 >> 6) | (s2230 << 26);
+  const SWord32 s2232 = (s2230 >> 11) | (s2230 << 21);
+  const SWord32 s2233 = s2231 ^ s2232;
+  const SWord32 s2234 = (s2230 >> 25) | (s2230 << 7);
+  const SWord32 s2235 = s2233 ^ s2234;
+  const SWord32 s2236 = s2146 + s2235;
+  const SWord32 s2237 = s2202 & s2230;
+  const SWord32 s2238 = ~s2230;
+  const SWord32 s2239 = s2174 & s2238;
+  const SWord32 s2240 = s2237 ^ s2239;
+  const SWord32 s2241 = s2236 + s2240;
+  const SWord32 s2243 = s2241 + 0x8cc70208UL;
+  const SWord32 s2244 = (s2200 >> 17) | (s2200 << 15);
+  const SWord32 s2245 = (s2200 >> 19) | (s2200 << 13);
+  const SWord32 s2246 = s2244 ^ s2245;
+  const SWord32 s2247 = s2200 >> 10;
+  const SWord32 s2248 = s2246 ^ s2247;
+  const SWord32 s2249 = s2005 + s2248;
+  const SWord32 s2250 = (s1693 >> 7) | (s1693 << 25);
+  const SWord32 s2251 = (s1693 >> 18) | (s1693 << 14);
+  const SWord32 s2252 = s2250 ^ s2251;
+  const SWord32 s2253 = s1693 >> 3;
+  const SWord32 s2254 = s2252 ^ s2253;
+  const SWord32 s2255 = s2249 + s2254;
+  const SWord32 s2256 = s1632 + s2255;
+  const SWord32 s2257 = s2243 + s2256;
+  const SWord32 s2258 = s2145 + s2257;
+  const SWord32 s2259 = (s2145 >> 2) | (s2145 << 30);
+  const SWord32 s2260 = (s2145 >> 13) | (s2145 << 19);
+  const SWord32 s2261 = s2259 ^ s2260;
+  const SWord32 s2262 = (s2145 >> 22) | (s2145 << 10);
+  const SWord32 s2263 = s2261 ^ s2262;
+  const SWord32 s2264 = s2134 & s2145;
+  const SWord32 s2265 = s2123 & s2145;
+  const SWord32 s2266 = s2264 ^ s2265;
+  const SWord32 s2267 = s2140 ^ s2266;
+  const SWord32 s2268 = s2263 + s2267;
+  const SWord32 s2269 = s2173 + s2268;
+  const SWord32 s2270 = (s2269 >> 2) | (s2269 << 30);
+  const SWord32 s2271 = (s2269 >> 13) | (s2269 << 19);
+  const SWord32 s2272 = s2270 ^ s2271;
+  const SWord32 s2273 = (s2269 >> 22) | (s2269 << 10);
+  const SWord32 s2274 = s2272 ^ s2273;
+  const SWord32 s2275 = s2145 & s2269;
+  const SWord32 s2276 = s2134 & s2269;
+  const SWord32 s2277 = s2275 ^ s2276;
+  const SWord32 s2278 = s2264 ^ s2277;
+  const SWord32 s2279 = s2274 + s2278;
+  const SWord32 s2280 = s2201 + s2279;
+  const SWord32 s2281 = (s2280 >> 2) | (s2280 << 30);
+  const SWord32 s2282 = (s2280 >> 13) | (s2280 << 19);
+  const SWord32 s2283 = s2281 ^ s2282;
+  const SWord32 s2284 = (s2280 >> 22) | (s2280 << 10);
+  const SWord32 s2285 = s2283 ^ s2284;
+  const SWord32 s2286 = s2269 & s2280;
+  const SWord32 s2287 = s2145 & s2280;
+  const SWord32 s2288 = s2286 ^ s2287;
+  const SWord32 s2289 = s2275 ^ s2288;
+  const SWord32 s2290 = s2285 + s2289;
+  const SWord32 s2291 = s2229 + s2290;
+  const SWord32 s2292 = (s2258 >> 6) | (s2258 << 26);
+  const SWord32 s2293 = (s2258 >> 11) | (s2258 << 21);
+  const SWord32 s2294 = s2292 ^ s2293;
+  const SWord32 s2295 = (s2258 >> 25) | (s2258 << 7);
+  const SWord32 s2296 = s2294 ^ s2295;
+  const SWord32 s2297 = s2174 + s2296;
+  const SWord32 s2298 = s2230 & s2258;
+  const SWord32 s2299 = ~s2258;
+  const SWord32 s2300 = s2202 & s2299;
+  const SWord32 s2301 = s2298 ^ s2300;
+  const SWord32 s2302 = s2297 + s2301;
+  const SWord32 s2304 = s2302 + 0x90befffaUL;
+  const SWord32 s2305 = (s2228 >> 17) | (s2228 << 15);
+  const SWord32 s2306 = (s2228 >> 19) | (s2228 << 13);
+  const SWord32 s2307 = s2305 ^ s2306;
+  const SWord32 s2308 = s2228 >> 10;
+  const SWord32 s2309 = s2307 ^ s2308;
+  const SWord32 s2310 = s2033 + s2309;
+  const SWord32 s2311 = (s1721 >> 7) | (s1721 << 25);
+  const SWord32 s2312 = (s1721 >> 18) | (s1721 << 14);
+  const SWord32 s2313 = s2311 ^ s2312;
+  const SWord32 s2314 = s1721 >> 3;
+  const SWord32 s2315 = s2313 ^ s2314;
+  const SWord32 s2316 = s2310 + s2315;
+  const SWord32 s2317 = s1693 + s2316;
+  const SWord32 s2318 = s2304 + s2317;
+  const SWord32 s2319 = s2269 + s2318;
+  const SWord32 s2320 = (s2319 >> 6) | (s2319 << 26);
+  const SWord32 s2321 = (s2319 >> 11) | (s2319 << 21);
+  const SWord32 s2322 = s2320 ^ s2321;
+  const SWord32 s2323 = (s2319 >> 25) | (s2319 << 7);
+  const SWord32 s2324 = s2322 ^ s2323;
+  const SWord32 s2325 = s2202 + s2324;
+  const SWord32 s2326 = s2258 & s2319;
+  const SWord32 s2327 = ~s2319;
+  const SWord32 s2328 = s2230 & s2327;
+  const SWord32 s2329 = s2326 ^ s2328;
+  const SWord32 s2330 = s2325 + s2329;
+  const SWord32 s2332 = s2330 + 0xa4506cebUL;
+  const SWord32 s2333 = (s2256 >> 17) | (s2256 << 15);
+  const SWord32 s2334 = (s2256 >> 19) | (s2256 << 13);
+  const SWord32 s2335 = s2333 ^ s2334;
+  const SWord32 s2336 = s2256 >> 10;
+  const SWord32 s2337 = s2335 ^ s2336;
+  const SWord32 s2338 = s2061 + s2337;
+  const SWord32 s2339 = (s1749 >> 7) | (s1749 << 25);
+  const SWord32 s2340 = (s1749 >> 18) | (s1749 << 14);
+  const SWord32 s2341 = s2339 ^ s2340;
+  const SWord32 s2342 = s1749 >> 3;
+  const SWord32 s2343 = s2341 ^ s2342;
+  const SWord32 s2344 = s2338 + s2343;
+  const SWord32 s2345 = s1721 + s2344;
+  const SWord32 s2346 = s2332 + s2345;
+  const SWord32 s2347 = s2280 + s2346;
+  const SWord32 s2348 = (s2347 >> 6) | (s2347 << 26);
+  const SWord32 s2349 = (s2347 >> 11) | (s2347 << 21);
+  const SWord32 s2350 = s2348 ^ s2349;
+  const SWord32 s2351 = (s2347 >> 25) | (s2347 << 7);
+  const SWord32 s2352 = s2350 ^ s2351;
+  const SWord32 s2353 = s2230 + s2352;
+  const SWord32 s2354 = s2319 & s2347;
+  const SWord32 s2355 = ~s2347;
+  const SWord32 s2356 = s2258 & s2355;
+  const SWord32 s2357 = s2354 ^ s2356;
+  const SWord32 s2358 = s2353 + s2357;
+  const SWord32 s2360 = s2358 + 0xbef9a3f7UL;
+  const SWord32 s2361 = (s2317 >> 17) | (s2317 << 15);
+  const SWord32 s2362 = (s2317 >> 19) | (s2317 << 13);
+  const SWord32 s2363 = s2361 ^ s2362;
+  const SWord32 s2364 = s2317 >> 10;
+  const SWord32 s2365 = s2363 ^ s2364;
+  const SWord32 s2366 = s2089 + s2365;
+  const SWord32 s2367 = (s1777 >> 7) | (s1777 << 25);
+  const SWord32 s2368 = (s1777 >> 18) | (s1777 << 14);
+  const SWord32 s2369 = s2367 ^ s2368;
+  const SWord32 s2370 = s1777 >> 3;
+  const SWord32 s2371 = s2369 ^ s2370;
+  const SWord32 s2372 = s2366 + s2371;
+  const SWord32 s2373 = s1749 + s2372;
+  const SWord32 s2374 = s2360 + s2373;
+  const SWord32 s2375 = s2291 + s2374;
+  const SWord32 s2376 = (s2375 >> 6) | (s2375 << 26);
+  const SWord32 s2377 = (s2375 >> 11) | (s2375 << 21);
+  const SWord32 s2378 = s2376 ^ s2377;
+  const SWord32 s2379 = (s2375 >> 25) | (s2375 << 7);
+  const SWord32 s2380 = s2378 ^ s2379;
+  const SWord32 s2381 = s2258 + s2380;
+  const SWord32 s2382 = s2347 & s2375;
+  const SWord32 s2383 = ~s2375;
+  const SWord32 s2384 = s2319 & s2383;
+  const SWord32 s2385 = s2382 ^ s2384;
+  const SWord32 s2386 = s2381 + s2385;
+  const SWord32 s2388 = s2386 + 0xc67178f2UL;
+  const SWord32 s2389 = (s2345 >> 17) | (s2345 << 15);
+  const SWord32 s2390 = (s2345 >> 19) | (s2345 << 13);
+  const SWord32 s2391 = s2389 ^ s2390;
+  const SWord32 s2392 = s2345 >> 10;
+  const SWord32 s2393 = s2391 ^ s2392;
+  const SWord32 s2394 = s2172 + s2393;
+  const SWord32 s2395 = (s1860 >> 7) | (s1860 << 25);
+  const SWord32 s2396 = (s1860 >> 18) | (s1860 << 14);
+  const SWord32 s2397 = s2395 ^ s2396;
+  const SWord32 s2398 = s1860 >> 3;
+  const SWord32 s2399 = s2397 ^ s2398;
+  const SWord32 s2400 = s2394 + s2399;
+  const SWord32 s2401 = s1777 + s2400;
+  const SWord32 s2402 = s2388 + s2401;
+  const SWord32 s2403 = (s2291 >> 2) | (s2291 << 30);
+  const SWord32 s2404 = (s2291 >> 13) | (s2291 << 19);
+  const SWord32 s2405 = s2403 ^ s2404;
+  const SWord32 s2406 = (s2291 >> 22) | (s2291 << 10);
+  const SWord32 s2407 = s2405 ^ s2406;
+  const SWord32 s2408 = s2280 & s2291;
+  const SWord32 s2409 = s2269 & s2291;
+  const SWord32 s2410 = s2408 ^ s2409;
+  const SWord32 s2411 = s2286 ^ s2410;
+  const SWord32 s2412 = s2407 + s2411;
+  const SWord32 s2413 = s2257 + s2412;
+  const SWord32 s2414 = (s2413 >> 2) | (s2413 << 30);
+  const SWord32 s2415 = (s2413 >> 13) | (s2413 << 19);
+  const SWord32 s2416 = s2414 ^ s2415;
+  const SWord32 s2417 = (s2413 >> 22) | (s2413 << 10);
+  const SWord32 s2418 = s2416 ^ s2417;
+  const SWord32 s2419 = s2291 & s2413;
+  const SWord32 s2420 = s2280 & s2413;
+  const SWord32 s2421 = s2419 ^ s2420;
+  const SWord32 s2422 = s2408 ^ s2421;
+  const SWord32 s2423 = s2418 + s2422;
+  const SWord32 s2424 = s2318 + s2423;
+  const SWord32 s2425 = (s2424 >> 2) | (s2424 << 30);
+  const SWord32 s2426 = (s2424 >> 13) | (s2424 << 19);
+  const SWord32 s2427 = s2425 ^ s2426;
+  const SWord32 s2428 = (s2424 >> 22) | (s2424 << 10);
+  const SWord32 s2429 = s2427 ^ s2428;
+  const SWord32 s2430 = s2413 & s2424;
+  const SWord32 s2431 = s2291 & s2424;
+  const SWord32 s2432 = s2430 ^ s2431;
+  const SWord32 s2433 = s2419 ^ s2432;
+  const SWord32 s2434 = s2429 + s2433;
+  const SWord32 s2435 = s2346 + s2434;
+  const SWord32 s2436 = (s2435 >> 2) | (s2435 << 30);
+  const SWord32 s2437 = (s2435 >> 13) | (s2435 << 19);
+  const SWord32 s2438 = s2436 ^ s2437;
+  const SWord32 s2439 = (s2435 >> 22) | (s2435 << 10);
+  const SWord32 s2440 = s2438 ^ s2439;
+  const SWord32 s2441 = s2424 & s2435;
+  const SWord32 s2442 = s2413 & s2435;
+  const SWord32 s2443 = s2441 ^ s2442;
+  const SWord32 s2444 = s2430 ^ s2443;
+  const SWord32 s2445 = s2440 + s2444;
+  const SWord32 s2446 = s2374 + s2445;
+  const SWord32 s2447 = (s2446 >> 2) | (s2446 << 30);
+  const SWord32 s2448 = (s2446 >> 13) | (s2446 << 19);
+  const SWord32 s2449 = s2447 ^ s2448;
+  const SWord32 s2450 = (s2446 >> 22) | (s2446 << 10);
+  const SWord32 s2451 = s2449 ^ s2450;
+  const SWord32 s2452 = s2435 & s2446;
+  const SWord32 s2453 = s2424 & s2446;
+  const SWord32 s2454 = s2452 ^ s2453;
+  const SWord32 s2455 = s2441 ^ s2454;
+  const SWord32 s2456 = s2451 + s2455;
+  const SWord32 s2457 = s2402 + s2456;
+  const SWord32 s2458 = s98 + s2457;
+  const SWord8  s2459 = (SWord8) (s2458 >> 24);
+  const SWord8  s2460 = (SWord8) (s2458 >> 16);
+  const SWord8  s2461 = (SWord8) (s2458 >> 8);
+  const SWord8  s2462 = (SWord8) s2458;
+  const SWord32 s2463 = s104 + s2446;
+  const SWord8  s2464 = (SWord8) (s2463 >> 24);
+  const SWord8  s2465 = (SWord8) (s2463 >> 16);
+  const SWord8  s2466 = (SWord8) (s2463 >> 8);
+  const SWord8  s2467 = (SWord8) s2463;
+  const SWord32 s2468 = s110 + s2435;
+  const SWord8  s2469 = (SWord8) (s2468 >> 24);
+  const SWord8  s2470 = (SWord8) (s2468 >> 16);
+  const SWord8  s2471 = (SWord8) (s2468 >> 8);
+  const SWord8  s2472 = (SWord8) s2468;
+  const SWord32 s2473 = s116 + s2424;
+  const SWord8  s2474 = (SWord8) (s2473 >> 24);
+  const SWord8  s2475 = (SWord8) (s2473 >> 16);
+  const SWord8  s2476 = (SWord8) (s2473 >> 8);
+  const SWord8  s2477 = (SWord8) s2473;
+  const SWord32 s2478 = s2402 + s2413;
+  const SWord32 s2479 = s101 + s2478;
+  const SWord8  s2480 = (SWord8) (s2479 >> 24);
+  const SWord8  s2481 = (SWord8) (s2479 >> 16);
+  const SWord8  s2482 = (SWord8) (s2479 >> 8);
+  const SWord8  s2483 = (SWord8) s2479;
+  const SWord32 s2484 = s107 + s2375;
+  const SWord8  s2485 = (SWord8) (s2484 >> 24);
+  const SWord8  s2486 = (SWord8) (s2484 >> 16);
+  const SWord8  s2487 = (SWord8) (s2484 >> 8);
+  const SWord8  s2488 = (SWord8) s2484;
+  const SWord32 s2489 = s113 + s2347;
+  const SWord8  s2490 = (SWord8) (s2489 >> 24);
+  const SWord8  s2491 = (SWord8) (s2489 >> 16);
+  const SWord8  s2492 = (SWord8) (s2489 >> 8);
+  const SWord8  s2493 = (SWord8) s2489;
+  const SWord32 s2494 = s119 + s2319;
+  const SWord8  s2495 = (SWord8) (s2494 >> 24);
+  const SWord8  s2496 = (SWord8) (s2494 >> 16);
+  const SWord8  s2497 = (SWord8) (s2494 >> 8);
+  const SWord8  s2498 = (SWord8) s2494;
+
+  hash[0] = s2459;
+  hash[1] = s2460;
+  hash[2] = s2461;
+  hash[3] = s2462;
+  hash[4] = s2464;
+  hash[5] = s2465;
+  hash[6] = s2466;
+  hash[7] = s2467;
+  hash[8] = s2469;
+  hash[9] = s2470;
+  hash[10] = s2471;
+  hash[11] = s2472;
+  hash[12] = s2474;
+  hash[13] = s2475;
+  hash[14] = s2476;
+  hash[15] = s2477;
+  hash[16] = s2480;
+  hash[17] = s2481;
+  hash[18] = s2482;
+  hash[19] = s2483;
+  hash[20] = s2485;
+  hash[21] = s2486;
+  hash[22] = s2487;
+  hash[23] = s2488;
+  hash[24] = s2490;
+  hash[25] = s2491;
+  hash[26] = s2492;
+  hash[27] = s2493;
+  hash[28] = s2495;
+  hash[29] = s2496;
+  hash[30] = s2497;
+  hash[31] = s2498;
+}
+== END: "sha256HashBlock.c" ==================
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_captureConflict.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_captureConflict.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_captureConflict.gold
@@ -0,0 +1,9 @@
+
+*** Data.SBV: Function 'bar @(SBV Integer -> SBV Integer)' defined with conflicting bodies.
+***
+*** Two calls to smtFunction (or related) used the name 'bar @(SBV Integer -> SBV Integer)'
+*** but with different definitions. This would generate conflicting
+*** SMTLib define-fun-rec declarations.
+***
+*** Please use a unique name for each distinct function.
+
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_captureTagged.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_captureTagged.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_captureTagged.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s4 () Int 10)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |bar_two @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |bar_two @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 2))
+                                 (let ((l1_s2 (+ l1_s0 l1_s1)))
+                                 l1_s2)))
+[GOOD] ; |bar_three @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |bar_three @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 3))
+                                 (let ((l1_s2 (+ l1_s0 l1_s1)))
+                                 l1_s2)))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|bar_two @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Int (|bar_three @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_conflict.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_conflict.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_conflict.gold
@@ -0,0 +1,9 @@
+
+*** Data.SBV: Function 'f @(SBV Integer -> SBV Integer)' defined with conflicting bodies.
+***
+*** Two calls to smtFunction (or related) used the name 'f @(SBV Integer -> SBV Integer)'
+*** but with different definitions. This would generate conflicting
+*** SMTLib define-fun-rec declarations.
+***
+*** Please use a unique name for each distinct function.
+
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveConflict.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveConflict.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveConflict.gold
@@ -0,0 +1,9 @@
+
+*** Data.SBV: Function 'f @(SBV Integer -> SBV Integer)' defined with conflicting bodies.
+***
+*** Two calls to smtFunction (or related) used the name 'f @(SBV Integer -> SBV Integer)'
+*** but with different definitions. This would generate conflicting
+*** SMTLib define-fun-rec declarations.
+***
+*** Please use a unique name for each distinct function.
+
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveOk.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveOk.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_recursiveOk.gold
@@ -0,0 +1,131 @@
+[MEASURE] Verifying termination measures for: f @(SBV Integer -> SBV Integer)
+[MEASURE] Checking: f @(SBV Integer -> SBV Integer)
+[MEASURE] f @(SBV Integer -> SBV Integer): barified = "|f @(SBV Integer -> SBV Integer)|"
+[MEASURE] f @(SBV Integer -> SBV Integer): Uninterpreted ops in DAG: [("|f @(SBV Integer -> SBV Integer)|",1)]
+[MEASURE] f @(SBV Integer -> SBV Integer): recursive calls found = 1
+[MEASURE] f @(SBV Integer -> SBV Integer): trying abs arg1
+[MEASURE] replayDAG {f @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Bool (>= s8 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] replayDAG {f @(SBV Integer -> SBV Integer)}: replaying 5 node(s)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "arg"
+[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (<= s0 s1))
+[GOOD] (define-fun s4 () Int (- s0 s2))
+[GOOD] (define-fun s6 () Int (+ s0 s5))
+[GOOD] (define-fun s7 () Int (ite s3 s1 s6))
+[GOOD] (define-fun s8 () Int (abs s0))
+[GOOD] (define-fun s9 () Int (abs s4))
+[GOOD] (define-fun s10 () Bool (not s3))
+[GOOD] (define-fun s11 () Bool (> s8 s9))
+[GOOD] (define-fun s12 () Bool (=> s10 s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (not s12))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[MEASURE] f @(SBV Integer -> SBV Integer): abs arg1 -> OK
+[MEASURE] Passed (terminating): f @(SBV Integer -> SBV Integer)
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 0)
+[GOOD] (define-fun s3 () Int 3)
+[GOOD] (define-fun s6 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |f @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger [Recursive]
+[GOOD] (define-fun-rec |f @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 0))
+                                 (let ((l1_s3 1))
+                                 (let ((l1_s2 (<= l1_s0 l1_s1)))
+                                 (let ((l1_s4 (- l1_s0 l1_s3)))
+                                 (let ((l1_s5 (|f @(SBV Integer -> SBV Integer)| l1_s4)))
+                                 (let ((l1_s6 (+ l1_s0 l1_s5)))
+                                 (let ((l1_s7 (ite l1_s2 l1_s1 l1_s6)))
+                                 l1_s7))))))))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (>= s0 s1))
+[GOOD] (define-fun s4 () Bool (<= s0 s3))
+[GOOD] (define-fun s5 () Int (|f @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s8 () Bool (and s4 s7))
+[GOOD] (define-fun s9 () Bool (and s2 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 3))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 3 :: Integer
diff --git a/SBVTestSuite/GoldFiles/smtFuncUniq_sameOk.gold b/SBVTestSuite/GoldFiles/smtFuncUniq_sameOk.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/smtFuncUniq_sameOk.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 4)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; |f @(SBV Integer -> SBV Integer)| :: SInteger -> SInteger
+[GOOD] (define-fun |f @(SBV Integer -> SBV Integer)| ((l1_s0 Int)) Int
+                                 (let ((l1_s1 1))
+                                 (let ((l1_s2 (+ l1_s0 l1_s1)))
+                                 l1_s2)))
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Int (|f @(SBV Integer -> SBV Integer)| s0))
+[GOOD] (define-fun s2 () Int (+ s1 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT:
+Satisfiable. Model:
+  s0 = 1 :: Integer
diff --git a/SBVTestSuite/GoldFiles/squashReals1.gold b/SBVTestSuite/GoldFiles/squashReals1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/squashReals1.gold
@@ -0,0 +1,2 @@
+Satisfiable. Model:
+  s0 = root(2, x^2 = 59) = 7.6811457478686081... :: Real
diff --git a/SBVTestSuite/GoldFiles/squashReals2.gold b/SBVTestSuite/GoldFiles/squashReals2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/squashReals2.gold
@@ -0,0 +1,2 @@
+Satisfiable. Model:
+  s0 = 4.0 :: Real
diff --git a/SBVTestSuite/GoldFiles/squashReals3.gold b/SBVTestSuite/GoldFiles/squashReals3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/squashReals3.gold
@@ -0,0 +1,2 @@
+Satisfiable. Model:
+  s0 = root(2, x^2 = 59) = 7.68114574786860817576968702173137247... :: Real
diff --git a/SBVTestSuite/GoldFiles/squashReals4.gold b/SBVTestSuite/GoldFiles/squashReals4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/squashReals4.gold
@@ -0,0 +1,2 @@
+Satisfiable. Model:
+  s0 = 4.0 :: Real
diff --git a/SBVTestSuite/GoldFiles/strConcat.gold b/SBVTestSuite/GoldFiles/strConcat.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strConcat.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strConcatBad.gold b/SBVTestSuite/GoldFiles/strConcatBad.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strConcatBad.gold
@@ -0,0 +1,24 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples1.gold b/SBVTestSuite/GoldFiles/strExamples1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples1.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples10.gold b/SBVTestSuite/GoldFiles/strExamples10.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples10.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 1 3) (str.to_re "ab"))))
+[GOOD] (define-fun s2 () Int (str.len s0))
+[GOOD] (define-fun s4 () Bool (> s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples11.gold b/SBVTestSuite/GoldFiles/strExamples11.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples11.gold
@@ -0,0 +1,32 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 11)
+[GOOD] (define-fun s4 () String "11")
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () String (int.to.str s0))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples12.gold b/SBVTestSuite/GoldFiles/strExamples12.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples12.gold
@@ -0,0 +1,32 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int (- 2))
+[GOOD] (define-fun s4 () String "")
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () String (int.to.str s0))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples13.gold b/SBVTestSuite/GoldFiles/strExamples13.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples13.gold
@@ -0,0 +1,32 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () String "13")
+[GOOD] (define-fun s4 () Int 13)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "s"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Int (str.to.int s0))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples2.gold b/SBVTestSuite/GoldFiles/strExamples2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples2.gold
@@ -0,0 +1,30 @@
+** 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 strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () String "b")
+[GOOD] (define-fun s3 () String "a")
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () String (str.++ s0 s1))
+[GOOD] (define-fun s4 () String (str.++ s3 s0))
+[GOOD] (define-fun s5 () Bool (= s2 s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples3.gold b/SBVTestSuite/GoldFiles/strExamples3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples3.gold
@@ -0,0 +1,38 @@
+** 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 strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s4 () String "abcd")
+[GOOD] (define-fun s7 () String "cdef")
+[GOOD] (define-fun s9 () String "")
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () String) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () String (str.++ s0 s1))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s6 () String (str.++ s1 s2))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s10 () Bool (= s1 s9))
+[GOOD] (define-fun s11 () Bool (not s10))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s8)
+[GOOD] (assert s11)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples4.gold b/SBVTestSuite/GoldFiles/strExamples4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples4.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) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () String "abc")
+[GOOD] (define-fun s4 () String "cef")
+[GOOD] (define-fun s8 () Int 2)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () String (str.++ s2 s0))
+[GOOD] (define-fun s5 () String (str.++ s1 s4))
+[GOOD] (define-fun s6 () Bool (= s3 s5))
+[GOOD] (define-fun s7 () Int (str.len s0))
+[GOOD] (define-fun s9 () Bool (<= s7 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s6)
+[GOOD] (assert s9)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples5.gold b/SBVTestSuite/GoldFiles/strExamples5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples5.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-logic ALL) ; has strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () String "ab")
+[GOOD] (define-fun s6 () String "ba")
+[GOOD] (define-fun s12 () String "a")
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () String) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s4 () String (str.++ s3 s1))
+[GOOD] (define-fun s5 () String (str.++ s0 s4))
+[GOOD] (define-fun s7 () String (str.++ s6 s2))
+[GOOD] (define-fun s8 () String (str.++ s1 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () String (str.++ s0 s1))
+[GOOD] (define-fun s11 () Bool (= s2 s10))
+[GOOD] (define-fun s13 () String (str.++ s0 s12))
+[GOOD] (define-fun s14 () String (str.++ s12 s0))
+[GOOD] (define-fun s15 () Bool (= s13 s14))
+[GOOD] (define-fun s16 () Bool (not s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[GOOD] (assert s16)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples6.gold b/SBVTestSuite/GoldFiles/strExamples6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples6.gold
@@ -0,0 +1,33 @@
+** 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 strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () String) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (str.contains s0 s1))
+[GOOD] (define-fun s4 () Bool (str.contains s1 s2))
+[GOOD] (define-fun s5 () Bool (str.contains s0 s2))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples7.gold b/SBVTestSuite/GoldFiles/strExamples7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples7.gold
@@ -0,0 +1,36 @@
+** 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 strings, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () String) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (str.contains s0 s1))
+[GOOD] (define-fun s4 () Bool (str.contains s0 s2))
+[GOOD] (define-fun s5 () Bool (str.contains s1 s2))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () Bool (str.contains s2 s1))
+[GOOD] (define-fun s8 () Bool (not s7))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s6)
+[GOOD] (assert s8)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples8.gold b/SBVTestSuite/GoldFiles/strExamples8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples8.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-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "b"
+[GOOD] (declare-fun s2 () String) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (str.prefixof s1 s0))
+[GOOD] (define-fun s4 () Bool (str.suffixof s2 s0))
+[GOOD] (define-fun s5 () Int (str.len s0))
+[GOOD] (define-fun s6 () Int (str.len s1))
+[GOOD] (define-fun s7 () Int (str.len s2))
+[GOOD] (define-fun s8 () Int (+ s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () String (str.++ s1 s2))
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strExamples9.gold b/SBVTestSuite/GoldFiles/strExamples9.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strExamples9.gold
@@ -0,0 +1,30 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 6)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () String) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (str.in_re s0 ((_ re.loop 1 3) (str.to_re "ab"))))
+[GOOD] (define-fun s2 () Int (str.len s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strIndexOf.gold b/SBVTestSuite/GoldFiles/strIndexOf.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strIndexOf.gold
@@ -0,0 +1,23 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/strIndexOfBad.gold b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
@@ -0,0 +1,24 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Int (+ s2 s3))
+[GOOD] (define-fun s5 () (Either Int Int) ((as Left (Either Int Int)) s4))
+[GOOD] (define-fun s6 () Int (getRight_1 s0))
+[GOOD] (define-fun s7 () Int (+ s3 s6))
+[GOOD] (define-fun s8 () (Either Int Int) ((as Right (Either Int Int)) s7))
+[GOOD] (define-fun s9 () (Either Int Int) (ite s1 s5 s8))
+[GOOD] (define-fun s10 () Bool ((as is-Left Bool) s9))
+[GOOD] (define-fun s11 () Int (getLeft_1 s9))
+[GOOD] (define-fun s12 () Int (getRight_1 s9))
+[GOOD] (define-fun s13 () Int (ite s10 s11 s12))
+[GOOD] (define-fun s14 () Int (ite s1 s2 s6))
+[GOOD] (define-fun s15 () Int (+ s3 s14))
+[GOOD] (define-fun s16 () Bool (= s13 s15))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s16)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left (- 1))))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left (-1) :: 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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int Bool)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s2 () Int (getLeft_1 s0))
+[GOOD] (define-fun s4 () Bool (> s2 s3))
+[GOOD] (define-fun s5 () Bool (getRight_1 s0))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (define-fun s7 () Bool (ite s1 s4 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Right 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,47 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] (declare-fun s1 () String) ; tracks user variable "c"
+[GOOD] (assert (= 1 (str.len s1)))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (Either Int String) ((as Left (Either Int String)) s0))
+[GOOD] (define-fun s3 () Bool ((as is-Left Bool) s2))
+[GOOD] (define-fun s4 () (Either Int String) ((as Right (Either Int String)) s1))
+[GOOD] (define-fun s5 () Bool ((as is-Right Bool) s4))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s1))
+[RECV] ((s1 "A"))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("i",0 :: Integer),("c",'A' :: 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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Maybe Int) (as Nothing (Maybe Int)))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (Maybe Int) ((as Just (Maybe Int)) s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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,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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Maybe Int) (as Nothing (Maybe Int)))
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] (define-fun s13 () Int 0)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Maybe Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool ((as is-Nothing Bool) s0))
+[GOOD] (define-fun s3 () Int (getJust_1 s0))
+[GOOD] (define-fun s5 () Int (+ s3 s4))
+[GOOD] (define-fun s6 () (Maybe Int) ((as Just (Maybe Int)) s5))
+[GOOD] (define-fun s7 () (Maybe Int) (ite s1 s2 s6))
+[GOOD] (define-fun s8 () Bool ((as is-Nothing Bool) s7))
+[GOOD] (define-fun s9 () Bool (= s1 s8))
+[GOOD] (define-fun s10 () Bool ((as is-Just Bool) s0))
+[GOOD] (define-fun s11 () Bool ((as is-Just Bool) s7))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s14 () Int (ite s1 s13 s3))
+[GOOD] (define-fun s15 () Int (getJust_1 s7))
+[GOOD] (define-fun s16 () Int (ite s8 s13 s15))
+[GOOD] (define-fun s17 () Int (- s16 s4))
+[GOOD] (define-fun s18 () Bool (= s14 s17))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[GOOD] (assert s18)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Just 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,49 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool ((as is-Left Bool) s0))
+[GOOD] (define-fun s3 () Bool ((as is-Just Bool) s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Just 3)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Left 2 :: Either Integer Integer),("s1",Just 3 :: 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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Left Bool) s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Left 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Left 2)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Left 2 :: Either Integer Bool),("s1",Left 2 :: Either Integer Bool),("s2",False :: 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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Either
+[GOOD] (declare-datatype Either (par (a b) (
+           (Left (getLeft_1 a))
+           (Right (getRight_1 b))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Either Int Bool))
+[GOOD] (declare-fun s1 () (Either Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Either Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Right Bool) s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Right false)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Right false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Right False :: Either Integer Bool),("s1",Right False :: Either Integer Bool),("s2",False :: 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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Nothing Bool) s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 Nothing))
+[SEND] (get-value (s1))
+[RECV] ((s1 Nothing))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Nothing :: Maybe Integer),("s1",Nothing :: Maybe Integer),("s2",False :: 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,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-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: Maybe
+[GOOD] (declare-datatype Maybe (par (a) (
+           (Nothing)
+           (Just (getJust_1 a))
+       )))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Maybe Int))
+[GOOD] (declare-fun s1 () (Maybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () (Maybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((as is-Just Bool) s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (Just 2)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (Just 2)))
+[SEND] (get-value (s2))
+[RECV] ((s2 false))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Just 2 :: Maybe Integer),("s1",Just 2 :: Maybe Integer),("s2",False :: Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/temperature.gold b/SBVTestSuite/GoldFiles/temperature.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/temperature.gold
@@ -0,0 +1,1 @@
+[("s0",16 :: Integer),("s0",28 :: Integer)]
diff --git a/SBVTestSuite/GoldFiles/tgen_c.gold b/SBVTestSuite/GoldFiles/tgen_c.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tgen_c.gold
@@ -0,0 +1,73 @@
+/* Automatically generated by SBV. Do not edit! */
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+
+/* The boolean type */
+typedef bool SBool;
+
+/* The float type */
+typedef float SFloat;
+
+/* The double type */
+typedef double SDouble;
+
+/* Unsigned bit-vectors */
+typedef uint8_t  SWord8;
+typedef uint16_t SWord16;
+typedef uint32_t SWord32;
+typedef uint64_t SWord64;
+
+/* Signed bit-vectors */
+typedef int8_t  SInt8;
+typedef int16_t SInt16;
+typedef int32_t SInt32;
+typedef int64_t SInt64;
+
+typedef struct {
+  struct {
+    SWord32 i0;
+    SWord32 i1;
+  } input;
+  struct {
+    SWord32 o0;
+    SWord32 o1;
+    SWord32 o2;
+  } output;
+} CTestTestVector;
+
+CTestTestVector CTest[] = {
+      {{0x96962508UL, 0xf3dc6f98UL}, {0x8a7294a0UL, 0xa2b9b570UL, 0xee1474c0UL}}
+    , {{0xb4538396UL, 0x8f338d9cUL}, {0x43871132UL, 0x251ff5faUL, 0xe33fcd68UL}}
+    , {{0xe017f69fUL, 0xe7510cb7UL}, {0xc7690356UL, 0xf8c6e9e8UL, 0xd1ffbfa9UL}}
+    , {{0x9847fd68UL, 0x1e671b39UL}, {0xb6af18a1UL, 0x79e0e22fUL, 0xa4996428UL}}
+    , {{0xb9a2eb19UL, 0x6eedc674UL}, {0x2890b18dUL, 0x4ab524a5UL, 0x83ccdd54UL}}
+    , {{0x4f576647UL, 0x0058226eUL}, {0x4faf88b5UL, 0x4eff43d9UL, 0xdb8b6082UL}}
+    , {{0x24ff2cd8UL, 0x466eb767UL}, {0x6b6de43fUL, 0xde907571UL, 0xa08972e8UL}}
+    , {{0x08363d14UL, 0xdcfe4253UL}, {0xe5347f67UL, 0x2b37fac1UL, 0x6f2cf57cUL}}
+    , {{0xeefac975UL, 0x45b9cecdUL}, {0x34b49842UL, 0xa940faa8UL, 0x4b7c78b1UL}}
+    , {{0x2ee34d81UL, 0xdabd0994UL}, {0x09a05715UL, 0x542643edUL, 0x2b5f5794UL}}
+};
+
+int CTestLength = 10;
+
+/* Stub driver showing the test values, replace with code that uses the test vectors. */
+int main(void)
+{
+  int i;
+  for(i = 0; i < CTestLength; ++i)
+  {
+    printf("%*d. 0x%08"PRIx32"UL 0x%08"PRIx32"UL -> 0x%08"PRIx32"UL 0x%08"PRIx32"UL 0x%08"PRIx32"UL\n", 1, i
+           , CTest[i].input.i0
+           , CTest[i].input.i1
+           , CTest[i].output.o0
+           , CTest[i].output.o1
+           , CTest[i].output.o2);
+  }
+
+  return 0;
+}
diff --git a/SBVTestSuite/GoldFiles/tgen_forte.gold b/SBVTestSuite/GoldFiles/tgen_forte.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tgen_forte.gold
@@ -0,0 +1,14 @@
+// Automatically generated by SBV. Do not edit!
+let ForteTest =
+   let c s = val [_, r] = str_split s "'" in map (\s. s == "1") (explode (string_tl r))
+   in [ ((c "32'b10010110100101100010010100001000", c "32'b11110011110111000110111110011000"), (c "32'b10001010011100101001010010100000", c "32'b10100010101110011011010101110000", c "32'b11101110000101000111010011000000"))
+      , ((c "32'b10110100010100111000001110010110", c "32'b10001111001100111000110110011100"), (c "32'b01000011100001110001000100110010", c "32'b00100101000111111111010111111010", c "32'b11100011001111111100110101101000"))
+      , ((c "32'b11100000000101111111011010011111", c "32'b11100111010100010000110010110111"), (c "32'b11000111011010010000001101010110", c "32'b11111000110001101110100111101000", c "32'b11010001111111111011111110101001"))
+      , ((c "32'b10011000010001111111110101101000", c "32'b00011110011001110001101100111001"), (c "32'b10110110101011110001100010100001", c "32'b01111001111000001110001000101111", c "32'b10100100100110010110010000101000"))
+      , ((c "32'b10111001101000101110101100011001", c "32'b01101110111011011100011001110100"), (c "32'b00101000100100001011000110001101", c "32'b01001010101101010010010010100101", c "32'b10000011110011001101110101010100"))
+      , ((c "32'b01001111010101110110011001000111", c "32'b00000000010110000010001001101110"), (c "32'b01001111101011111000100010110101", c "32'b01001110111111110100001111011001", c "32'b11011011100010110110000010000010"))
+      , ((c "32'b00100100111111110010110011011000", c "32'b01000110011011101011011101100111"), (c "32'b01101011011011011110010000111111", c "32'b11011110100100000111010101110001", c "32'b10100000100010010111001011101000"))
+      , ((c "32'b00001000001101100011110100010100", c "32'b11011100111111100100001001010011"), (c "32'b11100101001101000111111101100111", c "32'b00101011001101111111101011000001", c "32'b01101111001011001111010101111100"))
+      , ((c "32'b11101110111110101100100101110101", c "32'b01000101101110011100111011001101"), (c "32'b00110100101101001001100001000010", c "32'b10101001010000001111101010101000", c "32'b01001011011111000111100010110001"))
+      , ((c "32'b00101110111000110100110110000001", c "32'b11011010101111010000100110010100"), (c "32'b00001001101000000101011100010101", c "32'b01010100001001100100001111101101", c "32'b00101011010111110101011110010100"))
+      ];
diff --git a/SBVTestSuite/GoldFiles/tgen_haskell.gold b/SBVTestSuite/GoldFiles/tgen_haskell.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tgen_haskell.gold
@@ -0,0 +1,18 @@
+-- Automatically generated by SBV. Do not edit!
+
+module HaskTest(haskTest) where
+
+import Data.Word
+
+haskTest :: [([Word32], [Word32])]
+haskTest = [ ([0x96962508, 0xf3dc6f98], [0x8a7294a0, 0xa2b9b570, 0xee1474c0])
+           , ([0xb4538396, 0x8f338d9c], [0x43871132, 0x251ff5fa, 0xe33fcd68])
+           , ([0xe017f69f, 0xe7510cb7], [0xc7690356, 0xf8c6e9e8, 0xd1ffbfa9])
+           , ([0x9847fd68, 0x1e671b39], [0xb6af18a1, 0x79e0e22f, 0xa4996428])
+           , ([0xb9a2eb19, 0x6eedc674], [0x2890b18d, 0x4ab524a5, 0x83ccdd54])
+           , ([0x4f576647, 0x0058226e], [0x4faf88b5, 0x4eff43d9, 0xdb8b6082])
+           , ([0x24ff2cd8, 0x466eb767], [0x6b6de43f, 0xde907571, 0xa08972e8])
+           , ([0x08363d14, 0xdcfe4253], [0xe5347f67, 0x2b37fac1, 0x6f2cf57c])
+           , ([0xeefac975, 0x45b9cecd], [0x34b49842, 0xa940faa8, 0x4b7c78b1])
+           , ([0x2ee34d81, 0xdabd0994], [0x09a05715, 0x542643ed, 0x2b5f5794])
+           ]
diff --git a/SBVTestSuite/GoldFiles/timeout1.gold b/SBVTestSuite/GoldFiles/timeout1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/timeout1.gold
@@ -0,0 +1,2 @@
+Unknown.
+  Reason: timeout
diff --git a/SBVTestSuite/GoldFiles/tpCache_alias.gold b/SBVTestSuite/GoldFiles/tpCache_alias.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_alias.gold
@@ -0,0 +1,3 @@
+Lemma: nameA        Q.E.D.
+Lemma: nameB        Q.E.D.
+Lemma: nameC        Q.E.D. [Cached] (a.k.a. nameA, nameB)
diff --git a/SBVTestSuite/GoldFiles/tpCache_barFail.gold b/SBVTestSuite/GoldFiles/tpCache_barFail.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_barFail.gold
@@ -0,0 +1,4 @@
+Lemma: foo
+*** Failed to prove foo.
+Falsifiable. Counter-example:
+  x = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/tpCache_calcCollapse.gold b/SBVTestSuite/GoldFiles/tpCache_calcCollapse.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_calcCollapse.gold
@@ -0,0 +1,4 @@
+Lemma: addZero
+  Step: 1           Q.E.D.
+  Result:           Q.E.D.
+Lemma: addZero      Q.E.D. [Cached]
diff --git a/SBVTestSuite/GoldFiles/tpCache_fooFail.gold b/SBVTestSuite/GoldFiles/tpCache_fooFail.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_fooFail.gold
@@ -0,0 +1,4 @@
+Lemma: foo
+*** Failed to prove foo.
+Falsifiable. Counter-example:
+  x = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/tpCache_hit.gold b/SBVTestSuite/GoldFiles/tpCache_hit.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_hit.gold
@@ -0,0 +1,2 @@
+Lemma: fact         Q.E.D.
+Lemma: fact         Q.E.D. [Cached]
diff --git a/SBVTestSuite/GoldFiles/tpCache_miss.gold b/SBVTestSuite/GoldFiles/tpCache_miss.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_miss.gold
@@ -0,0 +1,1 @@
+Lemma: fact         Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/tpCache_nested.gold b/SBVTestSuite/GoldFiles/tpCache_nested.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_nested.gold
@@ -0,0 +1,3 @@
+Lemma: inner        Q.E.D.
+Lemma: outer        Q.E.D.
+Lemma: outer        Q.E.D. [Cached] (a.k.a. inner)
diff --git a/SBVTestSuite/GoldFiles/tpCache_recallFail.gold b/SBVTestSuite/GoldFiles/tpCache_recallFail.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_recallFail.gold
@@ -0,0 +1,4 @@
+Lemma: bad
+*** Failed to prove bad.
+Falsifiable. Counter-example:
+  x = 0 :: Integer
diff --git a/SBVTestSuite/GoldFiles/tpCache_statsHit.gold b/SBVTestSuite/GoldFiles/tpCache_statsHit.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_statsHit.gold
@@ -0,0 +1,4 @@
+Lemma: addZero
+  Step: 1           Q.E.D.
+  Result:           Q.E.D.
+Lemma: addZero      Q.E.D. [Cached]
diff --git a/SBVTestSuite/GoldFiles/tpCache_statsMiss.gold b/SBVTestSuite/GoldFiles/tpCache_statsMiss.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_statsMiss.gold
@@ -0,0 +1,3 @@
+Lemma: addZero
+  Step: 1           Q.E.D.
+  Result:           Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/tpCache_statsNested.gold b/SBVTestSuite/GoldFiles/tpCache_statsNested.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tpCache_statsNested.gold
@@ -0,0 +1,4 @@
+Lemma: inner        Q.E.D.
+Lemma: outer        Q.E.D.
+Lemma: inner        Q.E.D. [Cached] (a.k.a. outer)
+Lemma: outer        Q.E.D. [Cached] (a.k.a. inner)
diff --git a/SBVTestSuite/GoldFiles/tuple_enum.gold b/SBVTestSuite/GoldFiles/tuple_enum.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_enum.gold
@@ -0,0 +1,95 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
+                                           ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
+                                                         (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] ; User defined ADT: E
+[GOOD] (declare-datatype E (
+           (A)
+           (B)
+           (C)
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 1)
+[GOOD] (define-fun s11 () Int 3)
+[GOOD] (define-fun s13 () Int 2)
+[GOOD] (define-fun s16 () E (as C E))
+[GOOD] (define-fun s20 () Int 6)
+[GOOD] (define-fun s22 () Int 4)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 E (Seq Bool)))) ; tracks user variable "v1"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "q"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (not s1))
+[GOOD] (define-fun s4 () (SBVTuple2 E (Seq Bool)) (seq.nth s0 s3))
+[GOOD] (define-fun s5 () (Seq Bool) (proj_2_SBVTuple2 s4))
+[GOOD] (define-fun s6 () (Seq Bool) (seq.unit true))
+[GOOD] (define-fun s7 () (Seq Bool) (seq.unit s1))
+[GOOD] (define-fun s8 () (Seq Bool) (seq.++ s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () Int (seq.len s0))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s14 () (SBVTuple2 E (Seq Bool)) (seq.nth s0 s13))
+[GOOD] (define-fun s15 () E (proj_1_SBVTuple2 s14))
+[GOOD] (define-fun s17 () Bool (= s15 s16))
+[GOOD] (define-fun s18 () (Seq Bool) (proj_2_SBVTuple2 s14))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s23 () Bool (seq.nth s18 s22))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[GOOD] (assert s17)
+[GOOD] (assert s21)
+[GOOD] (assert s23)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[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 s24 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E String Int)))
+[GOOD] (assert (= 1 (str.len (proj_2_SBVTuple3 (proj_2_SBVTuple2 s24)))))
+[GOOD] (define-fun s25 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E String Int)) (mkSBVTuple2 #x05 (mkSBVTuple3 (as C E) (_ char #x41) 812)))
+[GOOD] (define-fun s26 () Bool (= s24 s25))
+[GOOD] (assert s26)
+[GOOD] (define-fun s27 () (Seq (SBVTuple2 E (Seq Bool))) (seq.++ (seq.unit (mkSBVTuple2 (as B E) (as seq.empty (Seq Bool)))) (seq.unit (mkSBVTuple2 (as A E) (seq.++ (seq.unit true) (seq.unit false)))) (seq.unit (mkSBVTuple2 (as C E) (seq.++ (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit true) (seq.unit false))))))
+[GOOD] (define-fun s28 () Bool (= s0 s27))
+[GOOD] (assert s28)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (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.++ (seq.unit true) (seq.unit false))))))))
+[SEND] (get-value (s24))
+[RECV] ((s24 (mkSBVTuple2 #x05 (mkSBVTuple3 C "A" 812))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: ([(B,[]),(A,[True,False]),(C,[False,False,False,False,True,False])],(5,(C,'A',812)))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_list.gold b/SBVTestSuite/GoldFiles/tuple_list.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_list.gold
@@ -0,0 +1,75 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s1 () Int 0)
+[GOOD] (define-fun s4 () Int 2)
+[GOOD] (define-fun s6 () Int 1)
+[GOOD] (define-fun s11 () String "foo")
+[GOOD] (define-fun s14 () Int 4)
+[GOOD] (define-fun s17 () Int 5)
+[GOOD] (define-fun s23 () (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] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String))))) ; tracks user variable "lst"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (SBVTuple2 Int (Seq (SBVTuple2 Int String))) (seq.nth s0 s1))
+[GOOD] (define-fun s3 () Int (proj_1_SBVTuple2 s2))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s7 () (SBVTuple2 Int (Seq (SBVTuple2 Int String))) (seq.nth s0 s6))
+[GOOD] (define-fun s8 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s7))
+[GOOD] (define-fun s9 () (SBVTuple2 Int String) (seq.nth s8 s1))
+[GOOD] (define-fun s10 () String (proj_2_SBVTuple2 s9))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s13 () Int (seq.len s0))
+[GOOD] (define-fun s15 () Bool (= s13 s14))
+[GOOD] (define-fun s16 () Int (seq.len s8))
+[GOOD] (define-fun s18 () Bool (= s16 s17))
+[GOOD] (define-fun s19 () (SBVTuple2 Int (Seq (SBVTuple2 Int String))) (seq.nth s0 s4))
+[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s19))
+[GOOD] (define-fun s21 () Int (seq.len s20))
+[GOOD] (define-fun s22 () Bool (= s1 s21))
+[GOOD] (define-fun s24 () Bool (= s0 s23))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s5)
+[GOOD] (assert s12)
+[GOOD] (assert s15)
+[GOOD] (assert s18)
+[GOOD] (assert s22)
+[GOOD] (assert s24)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (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))))))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: [(2,[]),(1,[(3,"foo"),(0,"bar"),(-1,"baz"),(-2,"quux"),(-3,"enough")]),(-4,[]),(-5,[])]
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_makePair.gold b/SBVTestSuite/GoldFiles/tuple_makePair.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_makePair.gold
@@ -0,0 +1,3 @@
+
+ FINAL: ()
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_nested.gold b/SBVTestSuite/GoldFiles/tuple_nested.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_nested.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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 s7 () String "foo")
+[GOOD] (define-fun s10 () String (_ char #x63))
+[GOOD] (define-fun s13 () (_ BitVec 8) #x00)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 (SBVTuple2 Int (SBVTuple2 String String)) (_ BitVec 8))) ; tracks user variable "abcd"
+[GOOD] (assert (= 1 (str.len (proj_2_SBVTuple2 (proj_2_SBVTuple2 (proj_1_SBVTuple2 s0))))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () (SBVTuple2 Int (SBVTuple2 String String)) (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s2 () Int (proj_1_SBVTuple2 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () (SBVTuple2 String String) (proj_2_SBVTuple2 s1))
+[GOOD] (define-fun s6 () String (proj_1_SBVTuple2 s5))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s9 () String (proj_2_SBVTuple2 s5))
+[GOOD] (define-fun s11 () Bool (= s9 s10))
+[GOOD] (define-fun s12 () (_ BitVec 8) (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s14 () Bool (= s12 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s8)
+[GOOD] (assert s11)
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 (mkSBVTuple2 1 (mkSBVTuple2 "foo" "c")) #x00)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: ((1,("foo",'c')),0)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_swap.gold b/SBVTestSuite/GoldFiles/tuple_swap.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_swap.gold
@@ -0,0 +1,61 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
+                                           ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
+                                                         (proj_2_SBVTuple3 T2)
+                                                         (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s8 () Int 1)
+[GOOD] (define-fun s10 () Int 2)
+[GOOD] (define-fun s13 () Int 3)
+[GOOD] (define-fun s16 () Int 4)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple3 Int Int Int)) ; tracks user variable "abx"
+[GOOD] (declare-fun s1 () (SBVTuple3 Int Int Int)) ; tracks user variable "bay"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (proj_1_SBVTuple3 s0))
+[GOOD] (define-fun s3 () Int (proj_2_SBVTuple3 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () Int (proj_2_SBVTuple3 s0))
+[GOOD] (define-fun s6 () Int (proj_1_SBVTuple3 s1))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
+[GOOD] (define-fun s11 () Bool (= s5 s10))
+[GOOD] (define-fun s12 () Int (proj_3_SBVTuple3 s0))
+[GOOD] (define-fun s14 () Bool (= s12 s13))
+[GOOD] (define-fun s15 () Int (proj_3_SBVTuple3 s1))
+[GOOD] (define-fun s17 () Bool (= s15 s16))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s7)
+[GOOD] (assert s9)
+[GOOD] (assert s11)
+[GOOD] (assert s14)
+[GOOD] (assert s17)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple3 1 2 3)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple3 2 1 4)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: ((1,2,3),(2,1,4))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_twoTwo.gold b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
@@ -0,0 +1,47 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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 () String (_ char #x63))
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int String)) ; tracks user variable "ab"
+[GOOD] (declare-fun s1 () (SBVTuple2 String (_ BitVec 8))) ; tracks user variable "cd"
+[GOOD] (assert (= 1 (str.len (proj_1_SBVTuple2 s1))))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s5 () String (proj_1_SBVTuple2 s1))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s4)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (mkSBVTuple2 1 "")))
+[SEND] (get-value (s1))
+[RECV] ((s1 (mkSBVTuple2 "c" #x00)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: ((1,""),('c',0))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_unequal.gold b/SBVTestSuite/GoldFiles/tuple_unequal.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_unequal.gold
@@ -0,0 +1,49 @@
+** 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-option :model.inline_def  true      )
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[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] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (SBVTuple2 Int Int))
+[GOOD] (declare-fun s1 () (SBVTuple2 Int Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Int (proj_1_SBVTuple2 s0))
+[GOOD] (define-fun s3 () Int (proj_1_SBVTuple2 s1))
+[GOOD] (define-fun s4 () Bool (< s2 s3))
+[GOOD] (define-fun s5 () Bool (= s2 s3))
+[GOOD] (define-fun s6 () Int (proj_2_SBVTuple2 s0))
+[GOOD] (define-fun s7 () Int (proj_2_SBVTuple2 s1))
+[GOOD] (define-fun s8 () Bool (< s6 s7))
+[GOOD] (define-fun s9 () Bool (and s5 s8))
+[GOOD] (define-fun s10 () Bool (or s4 s9))
+[GOOD] (define-fun s11 () Bool (< s3 s2))
+[GOOD] (define-fun s12 () Bool (< s7 s6))
+[GOOD] (define-fun s13 () Bool (and s5 s12))
+[GOOD] (define-fun s14 () Bool (or s11 s13))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s10)
+[GOOD] (assert s14)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL: ()
+DONE!
diff --git a/SBVTestSuite/GoldFiles/tuple_unit.gold b/SBVTestSuite/GoldFiles/tuple_unit.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/tuple_unit.gold
@@ -0,0 +1,3 @@
+
+ FINAL: ()
+DONE!
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,105 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "__internal_sbv_s0"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (q1 s0))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (_ as-array q1)))
+[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 ((as const (Array Bool 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 (store ((as const (Array Bool Bool)) true) true false)))
+[GOOD] (define-fun q1_model3 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 True = True
+  q1 _    = False
+Solution #2:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+Solution #3:
+  q1 :: Bool -> Bool
+  q1 _ = True
+Solution #4:
+  q1 :: Bool -> Bool
+  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,364 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "__internal_sbv_s0"
+[GOOD] (declare-fun s1 () Bool) ; tracks user variable "__internal_sbv_s1"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () Bool (q2 s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (_ as-array q2)))
+[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 ((as const (Array Bool Bool 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 (store ((as const (Array Bool Bool Bool)) true) false false false)))
+[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 (store ((as const (Array Bool Bool Bool)) false) false true true)))
+[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 (store (store ((as const (Array Bool Bool Bool)) false) false true true)
+              true
+              false
+              true)))
+[GOOD] (define-fun q2_model5 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 false) (= 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 (store (store ((as const (Array Bool Bool Bool)) false) true false true)
+              true
+              true
+              true)))
+[GOOD] (define-fun q2_model6 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          (ite (and (= x!0 true) (= 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 q2_model6_reject)
+[GOOD] (assert uiFunRejector_model_6)
+Looking for solution 7
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false true false)))
+[GOOD] (define-fun q2_model7 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[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 (store (store ((as const (Array Bool Bool Bool)) true) false true false)
+              true
+              true
+              false)))
+[GOOD] (define-fun q2_model8 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          (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 q2_model8_reject)
+[GOOD] (assert uiFunRejector_model_8)
+Looking for solution 9
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true true false)))
+[GOOD] (define-fun q2_model9 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= 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 q2_model9_reject)
+[GOOD] (assert uiFunRejector_model_9)
+Looking for solution 10
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true false false)))
+[GOOD] (define-fun q2_model10 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[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 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              true
+              true
+              false)))
+[GOOD] (define-fun q2_model11 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          (ite (and (= x!0 true) (= x!1 false)) 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 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q2_model12 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true))
+       )
+[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 (store ((as const (Array Bool Bool Bool)) false) false false true)))
+[GOOD] (define-fun q2_model13 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= 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 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              false
+              false)))
+[GOOD] (define-fun q2_model14 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          (ite (and (= x!0 true) (= x!1 false)) 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 q2_model14_reject)
+[GOOD] (assert uiFunRejector_model_14)
+Looking for solution 15
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true true true)))
+[GOOD] (define-fun q2_model15 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[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 (store ((as const (Array Bool Bool Bool)) false) true false true)))
+[GOOD] (define-fun q2_model16 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[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 True False = True
+  q2 _    _     = False
+Solution #2:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True
+  q2 _    _    = False
+Solution #3:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #4:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 _     _     = False
+Solution #5:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #6:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True  = False
+  q2 True False = False
+  q2 _    _     = True
+Solution #7:
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True
+Solution #8:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True
+Solution #9:
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True = False
+  q2 False True = False
+  q2 _     _    = True
+Solution #10:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True
+Solution #11:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True  = True
+  q2 True False = True
+  q2 _    _     = False
+Solution #12:
+  q2 :: Bool -> Bool -> Bool
+  q2 True  False = True
+  q2 False True  = True
+  q2 _     _     = False
+Solution #13:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 _     _    = False
+Solution #14:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True
+Solution #15:
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #16:
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+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,2381 @@
+** 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Bool) ; tracks user variable "__internal_sbv_s0"
+[GOOD] (declare-fun s2 () Bool) ; tracks user variable "__internal_sbv_s2"
+[GOOD] (declare-fun s3 () Bool) ; tracks user variable "__internal_sbv_s3"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (q1 s0))
+[GOOD] (define-fun s4 () Bool (q2 s2 s3))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (_ as-array q1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (_ as-array q2)))
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (_ as-array q2)))
+[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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 ((as const (Array Bool Bool 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false true false)))
+[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 false) (= x!1 true)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false false true)))
+[GOOD] (define-fun q1_model5 ((x!0 Bool)) Bool
+          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 false) (= x!1 false)) 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 
+               (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 (store ((as const (Array Bool Bool Bool)) false) false false true)))
+[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 (store ((as const (Array Bool Bool Bool)) true) false true false)))
+[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 true)) false
+          true)
+       )
+[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 (store (store ((as const (Array Bool Bool Bool)) true) false true false)
+              true
+              true
+              false)))
+[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 true) (= x!1 true)) false
+          (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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true true false)))
+[GOOD] (define-fun q1_model9 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          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 true) (= 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 ((as const (Array Bool Bool Bool)) true)))
+[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
+          true
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true false false)))
+[GOOD] (define-fun q1_model11 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          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 true) (= x!1 false)) 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 
+               (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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model12 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) 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 true)) false
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              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 true)) false
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true false false)))
+[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 true) (= x!1 false)) 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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model15 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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
+          (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 
+               (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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model16 ((x!0 Bool)) Bool
+          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 false) (= x!1 true)) false
+          (ite (and (= x!0 true) (= x!1 false)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true false false)))
+[GOOD] (define-fun q1_model17 ((x!0 Bool)) Bool
+          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 false)) 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 (store ((as const (Array Bool Bool)) false) false true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true false false)))
+[GOOD] (define-fun q1_model18 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) 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
+          (ite (and (= x!0 true) (= x!1 false)) false
+          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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false true false)))
+[GOOD] (define-fun q1_model19 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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
+          (ite (and (= x!0 false) (= x!1 true)) false
+          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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 ((as const (Array Bool Bool Bool)) true)))
+[GOOD] (define-fun q1_model20 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 ((as const (Array Bool Bool Bool)) true)))
+[GOOD] (define-fun q1_model21 ((x!0 Bool)) Bool
+          true
+       )
+[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
+          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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false 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 false) (= 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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 ((as const (Array Bool Bool Bool)) false)))
+[GOOD] (define-fun q1_model23 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          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
+          false
+       )
+[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 (store ((as const (Array Bool Bool Bool)) false) true false true)))
+[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
+          (ite (and (= x!0 true) (= x!1 false)) true
+          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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true false true)))
+[GOOD] (define-fun q1_model25 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 ((as const (Array Bool Bool Bool)) false)))
+[GOOD] (define-fun q1_model26 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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
+          false
+       )
+[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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false true true)))
+[GOOD] (define-fun q1_model27 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 false) (= 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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false false false)))
+[GOOD] (define-fun q1_model28 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 false)) false
+          true)
+       )
+[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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              true
+              true
+              false)))
+[GOOD] (define-fun q1_model29 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model30 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 false) (= x!1 true)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model31 ((x!0 Bool)) Bool
+          true
+       )
+[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)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true false true)))
+[GOOD] (define-fun q1_model32 ((x!0 Bool)) Bool
+          true
+       )
+[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 true) (= x!1 false)) 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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) true false true)
+              false
+              true
+              true)))
+[GOOD] (define-fun q1_model33 ((x!0 Bool)) Bool
+          true
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false false false)))
+[GOOD] (define-fun q1_model34 ((x!0 Bool)) Bool
+          true
+       )
+[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 false) (= x!1 false)) false
+          true)
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) false true true)
+              true
+              true
+              true)))
+[GOOD] (define-fun q1_model35 ((x!0 Bool)) Bool
+          true
+       )
+[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 true)) true
+          (ite (and (= x!0 false) (= 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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false true true)))
+[GOOD] (define-fun q1_model36 ((x!0 Bool)) Bool
+          true
+       )
+[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
+          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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) false true true)
+              true
+              true
+              true)))
+[GOOD] (define-fun q1_model37 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 true) (= x!1 true)) true
+          (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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true true false)))
+[GOOD] (define-fun q1_model38 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          true)
+       )
+[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 true) (= x!1 true)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true true false)))
+[GOOD] (define-fun q1_model39 ((x!0 Bool)) Bool
+          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 true) (= x!1 true)) false
+          true)
+       )
+[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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true true false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model40 ((x!0 Bool)) Bool
+          false
+       )
+[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)) false
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true true false)
+              false
+              true
+              false)))
+[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 true)) false
+          (ite (and (= x!0 true) (= x!1 true)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true true true)))
+[GOOD] (define-fun q1_model42 ((x!0 Bool)) Bool
+          false
+       )
+[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 true) (= 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true false true)))
+[GOOD] (define-fun q1_model43 ((x!0 Bool)) Bool
+          false
+       )
+[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 true) (= x!1 false)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false true true)))
+[GOOD] (define-fun q1_model44 ((x!0 Bool)) Bool
+          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
+          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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false true true)))
+[GOOD] (define-fun q1_model45 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) 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 false) (= x!1 true)) true
+          false)
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true true true)))
+[GOOD] (define-fun q1_model46 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[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 true)) true
+          false)
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) true true true)
+              false
+              true
+              true)))
+[GOOD] (define-fun q1_model47 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[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 true)) true
+          (ite (and (= x!0 true) (= 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) true true true)
+              false
+              true
+              true)))
+[GOOD] (define-fun q1_model48 ((x!0 Bool)) Bool
+          false
+       )
+[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 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model49 ((x!0 Bool)) Bool
+          false
+       )
+[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 true)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false false false)))
+[GOOD] (define-fun q1_model50 ((x!0 Bool)) Bool
+          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)) false
+          true)
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) false false false)))
+[GOOD] (define-fun q1_model51 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) 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)) false
+          true)
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              true
+              true
+              false)))
+[GOOD] (define-fun q1_model52 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) 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 true) (= x!1 true)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              true
+              true
+              false)))
+[GOOD] (define-fun q1_model53 ((x!0 Bool)) Bool
+          false
+       )
+[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)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) false false false)
+              false
+              true
+              false)))
+[GOOD] (define-fun q1_model54 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          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)) false
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true))
+       )
+[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 (store ((as const (Array Bool Bool)) false) false true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true true true)))
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) true) true true false)))
+[GOOD] (define-fun q1_model56 ((x!0 Bool)) Bool
+          true
+       )
+[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 true)) false
+          true)
+       )
+[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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) true false true)
+              false
+              false
+              true)))
+[GOOD] (define-fun q1_model57 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          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 false) (= x!1 false)) true
+          (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 (store ((as const (Array Bool Bool)) true) true false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false false true)))
+[GOOD] (define-fun q1_model58 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) false
+          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 false) (= x!1 false)) 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 ((as const (Array Bool Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true true false)
+              true
+              false
+              false)))
+[GOOD] (define-fun q1_model59 ((x!0 Bool)) Bool
+          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)) false
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true))
+       )
+[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)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) true) true true false)
+              true
+              false
+              false)))
+[GOOD] (define-fun q1_model60 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) 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
+          (ite (and (= x!0 true) (= x!1 false)) false
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true))
+       )
+[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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) false true true)
+              false
+              false
+              true)))
+[GOOD] (define-fun q1_model61 ((x!0 Bool)) Bool
+          true
+       )
+[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
+          (ite (and (= x!0 false) (= x!1 true)) 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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) false false true)))
+[GOOD] (define-fun q1_model62 ((x!0 Bool)) Bool
+          true
+       )
+[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
+          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 ((as const (Array Bool Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store ((as const (Array Bool Bool Bool)) false) true true true)))
+[GOOD] (define-fun q1_model63 ((x!0 Bool)) Bool
+          true
+       )
+[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 true) (= 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 (store ((as const (Array Bool Bool)) false) false true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (store (store ((as const (Array Bool Bool Bool)) false) false true true)
+              false
+              false
+              true)))
+[GOOD] (define-fun q1_model64 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          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 false) (= 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 = True
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 False True  = True
+  q2 _     _     = False
+Solution #2:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True
+  q2 _    _    = False
+Solution #3:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 _     _     = False
+Solution #4:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 False True  = True
+  q2 _     _     = False
+Solution #5:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 True True  = False
+  q2 _    _     = True
+Solution #6:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 True True  = False
+  q2 _    _     = True
+Solution #7:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 _     _     = False
+Solution #8:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 True  False = True
+  q2 _     _     = False
+Solution #9:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True
+Solution #10:
+  q1 :: Bool -> Bool
+  q1 False = True
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True
+  q2 _    _    = False
+Solution #11:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #12:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #13:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #14:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True
+Solution #15:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True
+Solution #16:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #17:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 True  True = True
+  q2 _     _    = False
+Solution #18:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 True  True = True
+  q2 _     _    = False
+Solution #19:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True
+  q2 _    _    = False
+Solution #20:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 _     _    = False
+Solution #21:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 _     _    = False
+Solution #22:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True
+  q2 _    _     = False
+Solution #23:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True
+  q2 _    _    = False
+Solution #24:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 True  True = False
+  q2 _     _    = True
+Solution #25:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 True  True = False
+  q2 _     _    = True
+Solution #26:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True
+Solution #27:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True
+Solution #28:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True = True
+  q2 False True = True
+  q2 _     _    = False
+Solution #29:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 _     _    = False
+Solution #30:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True = True
+  q2 False True = True
+  q2 _     _    = False
+Solution #31:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True
+Solution #32:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True
+  q2 True  False = True
+  q2 _     _     = False
+Solution #33:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True
+  q2 _    _     = False
+Solution #34:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #35:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #36:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True  = False
+  q2 False False = False
+  q2 _     _     = True
+Solution #37:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True
+Solution #38:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True
+  q2 _     _    = False
+Solution #39:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #40:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True
+  q2 _    _     = False
+Solution #41:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True
+  q2 _    _     = False
+Solution #42:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #43:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True
+Solution #44:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #45:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #46:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True
+Solution #47:
+  q1 :: Bool -> Bool
+  q1 False = True
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True
+Solution #48:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True
+Solution #49:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #50:
+  q1 :: Bool -> Bool
+  q1 True = False
+  q1 _    = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #51:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True
+Solution #52:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #53:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = False
+  q2 True  False = False
+  q2 _     _     = True
+Solution #54:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True
+Solution #55:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #56:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True
+Solution #57:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True  True = False
+  q2 False True = False
+  q2 _     _    = True
+Solution #58:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True
+Solution #59:
+  q1 :: Bool -> Bool
+  q1 True = True
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 _     _     = False
+Solution #60:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True
+  q2 _     _     = False
+Solution #61:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True
+Solution #62:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #63:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #64:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Found 64 different solutions.
diff --git a/SBVTestSuite/GoldFiles/unint-axioms-empty.gold b/SBVTestSuite/GoldFiles/unint-axioms-empty.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/unint-axioms-empty.gold
@@ -0,0 +1,47 @@
+** 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 user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Thing 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s2 () Thing) ; tracks user variable "__internal_sbv_s2"
+[GOOD] (declare-fun s3 () Thing) ; tracks user variable "__internal_sbv_s3"
+[GOOD] (declare-fun s5 () Thing)
+[GOOD] (declare-fun s6 () Thing)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun thingCompare (Thing Thing) Bool)
+[GOOD] (declare-fun thingMerge (Thing Thing) Thing)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Thing))
+         (thingCompare l1_s0 l1_s0)))
+[GOOD] (define-fun s1 () Bool (forall ((l1_s0 Thing) (l1_s1 Thing))
+                                 (let ((l1_s2 (thingMerge l1_s0 l1_s1)))
+                                 (let ((l1_s3 (distinct l1_s0 l1_s2)))
+                                 l1_s3))))
+[GOOD] (define-fun s4 () Thing (thingMerge s2 s3))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[GOOD] (define-fun s8 () Bool (thingCompare s5 s6))
+[GOOD] (define-fun s9 () Bool (=> s7 s8))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert s1)
+[GOOD] (assert (not s9))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:True
+DONE!
diff --git a/SBVTestSuite/GoldFiles/unint-axioms-query.gold b/SBVTestSuite/GoldFiles/unint-axioms-query.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/unint-axioms-query.gold
@@ -0,0 +1,69 @@
+** 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 user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort B 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () B) ; tracks user variable "p"
+[GOOD] (declare-fun s1 () B) ; tracks user variable "q"
+[GOOD] (declare-fun s2 () B) ; tracks user variable "r"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (declare-fun AND (B B) B)
+[GOOD] (declare-fun NOT (B) B)
+[GOOD] (declare-fun OR (B B) B)
+[GOOD] (define-fun s3 () B (AND s1 s2))
+[GOOD] (define-fun s4 () B (OR s0 s3))
+[GOOD] (define-fun s5 () B (NOT s4))
+[GOOD] (define-fun s6 () B (NOT s0))
+[GOOD] (define-fun s7 () B (NOT s1))
+[GOOD] (define-fun s8 () B (AND s6 s7))
+[GOOD] (define-fun s9 () B (NOT s2))
+[GOOD] (define-fun s10 () B (AND s6 s9))
+[GOOD] (define-fun s11 () B (OR s8 s10))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (assert s12)
+[GOOD] (define-fun s13 () Bool (forall ((l1_s0 B) (l1_s1 B) (l1_s2 B))
+                                 (let ((l1_s3 (OR l1_s0 l1_s1)))
+                                 (let ((l1_s4 (OR l1_s0 l1_s2)))
+                                 (let ((l1_s5 (AND l1_s3 l1_s4)))
+                                 (let ((l1_s6 (AND l1_s1 l1_s2)))
+                                 (let ((l1_s7 (OR l1_s0 l1_s6)))
+                                 (let ((l1_s8 (= l1_s5 l1_s7)))
+                                 l1_s8))))))))
+[GOOD] (assert s13)
+[GOOD] (define-fun s14 () Bool (forall ((l1_s0 B) (l1_s1 B))
+                                 (let ((l1_s2 (OR l1_s0 l1_s1)))
+                                 (let ((l1_s3 (NOT l1_s2)))
+                                 (let ((l1_s4 (NOT l1_s0)))
+                                 (let ((l1_s5 (NOT l1_s1)))
+                                 (let ((l1_s6 (AND l1_s4 l1_s5)))
+                                 (let ((l1_s7 (= l1_s3 l1_s6)))
+                                 l1_s7))))))))
+[GOOD] (assert s14)
+[GOOD] (define-fun s15 () Bool (forall ((l1_s0 B))
+                                 (let ((l1_s1 (NOT l1_s0)))
+                                 (let ((l1_s2 (NOT l1_s1)))
+                                 (let ((l1_s3 (= l1_s0 l1_s2)))
+                                 l1_s3)))))
+[GOOD] (assert s15)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Unsat
+DONE!
diff --git a/SBVTestSuite/GoldFiles/unint-axioms.gold b/SBVTestSuite/GoldFiles/unint-axioms.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/unint-axioms.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) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Bitstring 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s1 () Bitstring) ; tracks user variable "p"
+[GOOD] (declare-fun s2 () Bitstring) ; tracks user variable "k"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun a (Bitstring) Bool)
+[GOOD] (declare-fun e (Bitstring Bitstring) Bitstring)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool (forall ((l1_s0 Bitstring) (l1_s1 Bitstring))
+                                 (let ((l1_s2 (a l1_s1)))
+                                 (let ((l1_s3 (a l1_s0)))
+                                 (let ((l1_s4 (and l1_s2 l1_s3)))
+                                 (let ((l1_s5 (e l1_s1 l1_s0)))
+                                 (let ((l1_s6 (a l1_s5)))
+                                 (let ((l1_s7 (=> l1_s4 l1_s6)))
+                                 l1_s7))))))))
+[GOOD] (define-fun s3 () Bool (a s1))
+[GOOD] (define-fun s4 () Bool (a s2))
+[GOOD] (define-fun s5 () Bitstring (e s2 s1))
+[GOOD] (define-fun s6 () Bool (a s5))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s0)
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[GOOD] (assert (not s6))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:True
+DONE!
diff --git a/SBVTestSuite/GoldFiles/unint-sort01.gold b/SBVTestSuite/GoldFiles/unint-sort01.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/unint-sort01.gold
@@ -0,0 +1,37 @@
+Solution #1:
+  l  = L_1 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   1 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #2:
+  l  = L_0 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   0 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #3:
+  l  = L_1 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   0 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Solution #4:
+  l  = L_0 :: L
+  l0 = L_0 :: L
+  l1 = L_1 :: L
+  x  =   1 :: Integer
+
+  len :: L -> Integer
+  len L_1 = 1
+  len _   = 0
+Found 4 different solutions.
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-1a.gold b/SBVTestSuite/GoldFiles/uninterpreted-1a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uninterpreted-1a.gold
@@ -0,0 +1,53 @@
+** 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_UFBV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] (declare-fun s2 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun g ((_ BitVec 8) (_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 32) (g s0 s1))
+[GOOD] (define-fun s5 () (_ BitVec 32) (g s0 s2))
+[GOOD] (define-fun s6 () Bool (= s4 s5))
+[GOOD] (define-fun s7 () Bool (=> s3 s6))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x00))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x0000))
+[SEND] (get-value (s2))
+[RECV] ((s2 #x0000))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-option :model.inline_def  true      )
+[SEND] (get-value (g))
+[RECV] ((g ((as const (Array (_ BitVec 8) (_ BitVec 16) (_ BitVec 32))) #x00000000)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Satisfiable. Model:
+  s0 = 0 :: Int8
+  s1 = 0 :: Word16
+  s2 = 0 :: Word16
+
+  g :: (Int8, Word16) -> Word32
+  g (_, _) = 0
+DONE!
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-3.gold b/SBVTestSuite/GoldFiles/uninterpreted-3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uninterpreted-3.gold
@@ -0,0 +1,38 @@
+** 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_UFBV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun p () Bool)
+[GOOD] (declare-fun q () Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool p)
+[GOOD] (define-fun s1 () Bool q)
+[GOOD] (define-fun s2 () Bool (or s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (p))
+[RECV] ((p true))
+[SEND] (get-value (q))
+[RECV] ((q false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Satisfiable. Model:
+  p =  True :: Bool
+  q = False :: Bool
+DONE!
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-3a.gold b/SBVTestSuite/GoldFiles/uninterpreted-3a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uninterpreted-3a.gold
@@ -0,0 +1,89 @@
+** 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_UFBV)
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun p () Bool)
+[GOOD] (declare-fun q () Bool)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Bool p)
+[GOOD] (define-fun s1 () Bool q)
+[GOOD] (define-fun s2 () Bool (or s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+*** Checking Satisfiability, all solutions..
+Fast allSat, Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 true))
+[SEND] (get-value (s1))
+[RECV] ((s1 false))
+[GOOD] (push 1)
+[GOOD] (define-fun s3 () Bool (not s0))
+[GOOD] (assert s3)
+Fast allSat, Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 false))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[GOOD] (push 1)
+[GOOD] (assert s0)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (define-fun s4 () Bool (not s1))
+[GOOD] (assert s4)
+[GOOD] (assert s3)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+[GOOD] (push 1)
+[GOOD] (assert s1)
+[GOOD] (assert s0)
+Fast allSat, Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 true))
+[SEND] (get-value (s1))
+[RECV] ((s1 true))
+[GOOD] (push 1)
+[GOOD] (assert s4)
+Fast allSat, Looking for solution 4
+[SEND] (check-sat)
+[RECV] unsat
+[GOOD] (pop 1)
+[GOOD] (pop 1)
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Solution #1:
+  p = True :: Bool
+  q = True :: Bool
+Solution #2:
+  p = False :: Bool
+  q =  True :: Bool
+Solution #3:
+  p =  True :: Bool
+  q = False :: Bool
+Found 3 different solutions.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-4.gold b/SBVTestSuite/GoldFiles/uninterpreted-4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uninterpreted-4.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-logic ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Q 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun c () Q)
+[GOOD] (declare-fun d () Q)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Q c)
+[GOOD] (define-fun s1 () Q d)
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (c))
+[RECV] ((c Q!val!0))
+[SEND] (get-value (d))
+[RECV] ((d Q!val!1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Satisfiable. Model:
+  c = Q_0 :: Q
+  d = Q_1 :: Q
+DONE!
diff --git a/SBVTestSuite/GoldFiles/uninterpreted-4a.gold b/SBVTestSuite/GoldFiles/uninterpreted-4a.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uninterpreted-4a.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 ALL) ; has user-defined data-types, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- ADTs  --- 
+[GOOD] (declare-sort Q 0) ; N.B. Uninterpreted sort.
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun c () Q)
+[GOOD] (declare-fun d () Q)
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s0 () Q c)
+[GOOD] (define-fun s1 () Q d)
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s2)
+*** Checking Satisfiability, all solutions..
+*** SBV.allSat: Uninterpreted function: c :: Q
+*** Will *not* be used in allSat considerations since its type
+*** has uninterpreted sorts present.
+*** SBV.allSat: Uninterpreted function: d :: Q
+*** Will *not* be used in allSat considerations since its type
+*** has uninterpreted sorts present.
+*** SBV.allSat: Uninterpreted sorts present: Q
+***             SBV will use equivalence classes to generate all-satisfying instances.
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (c))
+[RECV] ((c Q!val!0))
+[SEND] (get-value (d))
+[RECV] ((d Q!val!1))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:Solution #1:
+  c = Q_0 :: Q
+  d = Q_1 :: Q
+This is the only solution.
+DONE!
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,39 @@
+** 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] ; --- tuples ---
+[ISSUE] ; --- sums ---
+[ISSUE] ; --- literal constants ---
+[ISSUE] (define-fun s1 () (_ BitVec 8) #x0a)
+[ISSUE] ; --- top level inputs ---
+[ISSUE] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
+[ISSUE] ; --- constant tables ---
+[ISSUE] ; --- non-constant tables ---
+[ISSUE] ; --- uninterpreted constants ---
+[ISSUE] ; --- user defined functions ---
+[ISSUE] ; --- assignments ---
+[ISSUE] (define-fun s2 () Bool (bvult s0 s1))
+[ISSUE] ; --- delayedEqualities ---
+[ISSUE] ; --- formula ---
+[ISSUE] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x0))
+*** Solver   : ABC
+*** Exit code: ExitSuccess
+*** Std-err  : Cmd warning: redefining '%graft'
+[VALIDATE] Validating the model. Assignment:
+[VALIDATE]       x = 0 :: Word8
+[VALIDATE] There are no constraints to check.
+[VALIDATE] Validating outputs.
+[VALIDATE] All outputs are satisfied. Validation complete.
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  x = 0 :: 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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () RoundingMode roundTowardZero)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (fp.add s1 s0 s0))
+[GOOD] (define-fun s3 () Bool (fp.eq s0 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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. Assignment:
+[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.
+*** 
+*** Assignment:
+*** 
+***       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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () RoundingMode roundNearestTiesToEven)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (fp.fma s1 s0 s0 s0))
+[GOOD] (define-fun s3 () Bool (fp.eq s0 s2))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (fp #b0 #x00 #b00000000000000011001101)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model. Assignment:
+[VALIDATE]       x = 2.87e-43 :: 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.
+*** 
+*** Assignment:
+*** 
+***       x = 2.87e-43 :: 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 = 2.87e-43 :: 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,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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[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,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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "y"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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. Assignment:
+[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] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "y"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[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] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[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. Assignment:
+[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,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-logic ALL) ; has quantified booleans, using catch-all.
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- top level inputs ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- non-constant tables ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user defined functions ---
+[GOOD] ; --- assignments ---
+[GOOD] (define-fun s1 () Bool (forall ((l1_s0 (_ FloatingPoint  8 24)))
+                                 (let ((l1_s1 (fp.isNaN l1_s0)))
+                                 (let ((l1_s2 (fp.isInfinite l1_s0)))
+                                 (let ((l1_s3 (or l1_s1 l1_s2)))
+                                 (let ((l1_s4 (not l1_s3)))
+                                 (let ((l1_s5 (fp.leq s0 l1_s0)))
+                                 (let ((l1_s6 (=> l1_s4 l1_s5)))
+                                 l1_s6))))))))
+[GOOD] ; --- delayedEqualities ---
+[GOOD] ; --- formula ---
+[GOOD] (assert s1)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (_ -oo 8 24)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model. Assignment:
+[VALIDATE]       x = -Infinity :: Float
+[VALIDATE] There are no constraints to check.
+[VALIDATE] Validating outputs.
+
+FINAL OUTPUT:
+*** Data.SBV: Cannot validate the model, since s1 is not concretely computable.
+*** 
+*** Assignment:
+*** 
+***       x = -Infinity :: Float
+*** 
+*** The value depends on a quantified variable.
+*** 
+*** 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 = -Infinity :: Float
diff --git a/SBVTestSuite/SBVConnectionTest.hs b/SBVTestSuite/SBVConnectionTest.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/SBVConnectionTest.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Main (main) where
+
+import Data.SBV
+import Data.List
+import Control.Monad
+import System.Exit
+import System.Environment
+
+-- Known solvers with bugs! Should really be empty!
+badSolvers :: [SMTConfig]
+badSolvers = []
+
+solverName :: SMTConfig -> String
+solverName = show . name . solver
+
+main :: IO ()
+main = do let allSolvers = map ((\s -> (solverName s, s)) . defaultSolverConfig) [minBound .. maxBound]
+
+          args <- getArgs
+
+          let chosenSolvers = case args of
+                               [] -> allSolvers
+                               _  -> let walk []     = []
+                                         walk (c:cs) = case c `lookup` allSolvers of
+                                                         Nothing -> error $ "Unknown chosen solver: " ++ show c
+                                                         Just s  -> (c, s) : walk cs
+                                     in walk args
+
+              (requiredBad, requiredPresent) = partition (\(n, _) -> n `elem` map solverName badSolvers) chosenSolvers
+
+              pickTest s = case name (solver s) of
+                             DReal   -> testI s
+                             OpenSMT -> testO s
+                             _       -> test  s
+
+          mapM_ (pickTest . snd) requiredPresent
+
+          let tested   = sort $ map fst requiredPresent
+              allKnown = sort $ map fst allSolvers
+
+              skipped  = filter (`notElem` tested) allKnown
+
+
+          putStrLn $ "Tested OK basic connection to: " ++ intercalate ", " (map fst requiredPresent)
+          unless (null requiredBad) $ putStrLn $ "*** NB: The following solvers are declared bad: " ++ intercalate ", " (map (\(n, s)-> show (n, solverName s)) requiredBad)
+          unless (null skipped)     $ putStrLn $ "*** NB: The following solvers are skipped: "      ++ intercalate ", " skipped
+
+test :: SMTConfig -> IO ()
+test s = do check  s "t0" t0 not
+            check  s "t1" t1 id
+            models "t2" t2 (== ([2,62,66,126,130,190,194,254]::[Word8]))
+            models "t3" t3 (== ([]::[Word8]))
+            models "t4" t4 (== [4::Word8])
+  where models m p f = allSat p >>= (decide s m f . sort) . extractModels
+        t0 x = x   .== x+(1::SWord8)
+        t1 x = x*2 .== x+(x::SWord8)
+        t2 x = x*x .== (4::SWord8)
+        t3 x = x*x .== (3::SWord8)
+        t4 x = x*3 .== (12::SWord8)
+
+-- for dreal
+testI :: SMTConfig -> IO ()
+testI s = do check s "t0" t0 id
+             check s "t1" t1 not
+  where t0 x = x .== (x :: SReal)
+        t1 x = x .== (2 :: SReal) .&& (x .== 3)
+
+-- for openSMT
+testO :: SMTConfig -> IO ()
+testO s = do check s "t0" t0 id
+             check s "t1" t1 not
+  where t0 = do {setLogic QF_RDL; x <- free "x"; pure (x .== (x :: SReal))}
+        t1 = do {setLogic QF_RDL; x <- free "x"; pure (x .== (2 :: SReal) .&& (x .== 3))}
+
+check :: Provable a => SMTConfig -> String -> a -> (Bool -> Bool) -> IO ()
+check s m p f = isTheoremWith s p >>= decide s m f
+
+decide :: Show a => SMTConfig -> String -> (a -> Bool) -> a -> IO ()
+decide s m f r
+  | f r  = return ()
+  | True = do putStrLn $ m ++ "[" ++ solverName s ++ "] FAIL. Got: " ++ show r
+              exitFailure
diff --git a/SBVTestSuite/SBVDocTest.hs b/SBVTestSuite/SBVDocTest.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/SBVDocTest.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : SBVDocTest
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Doctest interface for SBV testsuite
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall #-}
+
+module Main (main) where
+
+import System.Environment(getArgs)
+import System.Exit(exitWith)
+
+import System.Process
+
+-- This "fake" import creates a dependency to sbv,
+-- thus allowing cabal to recognize it has to compile
+-- sbv first before running the doctests. Otherwise it plays no role.
+import Data.SBV ()
+
+main :: IO ()
+main = do args <- getArgs
+          exitWith =<< rawSystem "cabal-docspec" args
diff --git a/SBVTestSuite/SBVHLint.hs b/SBVTestSuite/SBVHLint.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/SBVHLint.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : SBVHLint
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- HLint interface for SBV testsuite
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Main (main) where
+
+import System.Exit (exitWith)
+import System.Process
+
+arguments :: [String]
+arguments =
+    [ "Data"
+    , "SBVTestSuite"
+    , "Documentation"
+    , "-i", "Use otherwise"
+    ]
+
+main :: IO ()
+main = exitWith =<< rawSystem "hlint" arguments
diff --git a/SBVTestSuite/SBVTest.hs b/SBVTestSuite/SBVTest.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/SBVTest.hs
@@ -0,0 +1,261 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : SBVTest
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Main entry point to the test suite
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Main(main) where
+
+import Test.Tasty
+
+import qualified TestSuite.ADT.ADT
+import qualified TestSuite.ADT.Expr
+import qualified TestSuite.ADT.MutRec
+import qualified TestSuite.ADT.PExpr
+import qualified TestSuite.Arrays.InitVals
+import qualified TestSuite.Arrays.Memory
+import qualified TestSuite.Arrays.Query
+import qualified TestSuite.Arrays.Caching
+import qualified TestSuite.Basics.AllSat
+import qualified TestSuite.Basics.ArbFloats
+import qualified TestSuite.Basics.ArithNoSolver
+import qualified TestSuite.Basics.ArithNoSolver2
+import qualified TestSuite.Basics.ArithSolver
+import qualified TestSuite.Basics.Assert
+import qualified TestSuite.Basics.BasicTests
+import qualified TestSuite.Basics.BarrelRotate
+import qualified TestSuite.Basics.DynSign
+import qualified TestSuite.Basics.Exceptions
+import qualified TestSuite.Basics.EqSym
+import qualified TestSuite.Basics.GenBenchmark
+import qualified TestSuite.Basics.Higher
+import qualified TestSuite.Basics.Index
+import qualified TestSuite.Basics.IteTest
+import qualified TestSuite.Basics.Lambda
+import qualified TestSuite.Basics.List
+import qualified TestSuite.Basics.ModelValidate
+import qualified TestSuite.Basics.Nonlinear
+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.TPCaching
+import qualified TestSuite.Basics.Set
+import qualified TestSuite.Basics.SmtFunctionUnique
+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
+import qualified TestSuite.BitPrecise.PrefixSum
+import qualified TestSuite.CantTypeCheck.Misc
+import qualified TestSuite.Char.Char
+import qualified TestSuite.CodeGeneration.AddSub
+import qualified TestSuite.CodeGeneration.CgTests
+import qualified TestSuite.CodeGeneration.CRC_USB5
+import qualified TestSuite.CodeGeneration.Fibonacci
+import qualified TestSuite.CodeGeneration.Floats
+import qualified TestSuite.CodeGeneration.GCD
+import qualified TestSuite.CodeGeneration.PopulationCount
+import qualified TestSuite.CodeGeneration.Uninterpreted
+import qualified TestSuite.CRC.CCITT
+import qualified TestSuite.CRC.CCITT_Unidir
+import qualified TestSuite.CRC.GenPoly
+import qualified TestSuite.CRC.Parity
+import qualified TestSuite.CRC.USB5
+import qualified TestSuite.Crypto.AES
+import qualified TestSuite.Crypto.RC4
+import qualified TestSuite.Crypto.SHA
+import qualified TestSuite.GenTest.GenTests
+import qualified TestSuite.Optimization.AssertWithPenalty
+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.Tuples
+import qualified TestSuite.Overflows.Arithmetic
+import qualified TestSuite.Overflows.Casts
+import qualified TestSuite.Polynomials.Polynomials
+import qualified TestSuite.Puzzles.Coins
+import qualified TestSuite.Puzzles.Counts
+import qualified TestSuite.Puzzles.DogCatMouse
+import qualified TestSuite.Puzzles.Euler185
+import qualified TestSuite.Puzzles.MagicSquare
+import qualified TestSuite.Puzzles.NQueens
+import qualified TestSuite.Puzzles.PowerSet
+import qualified TestSuite.Puzzles.Sudoku
+import qualified TestSuite.Puzzles.Temperature
+import qualified TestSuite.Puzzles.U2Bridge
+import qualified TestSuite.Queries.ArrayGetVal
+import qualified TestSuite.Queries.BasicQuery
+import qualified TestSuite.Queries.BadOption
+import qualified TestSuite.Queries.DSat
+import qualified TestSuite.Queries.Enums
+import qualified TestSuite.Queries.FreshVars
+import qualified TestSuite.Queries.Int_ABC
+import qualified TestSuite.Queries.Int_Boolector
+import qualified TestSuite.Queries.Int_CVC4
+import qualified TestSuite.Queries.Int_Mathsat
+import qualified TestSuite.Queries.Int_Yices
+import qualified TestSuite.Queries.Int_Z3
+import qualified TestSuite.Queries.Interpolants
+import qualified TestSuite.Queries.Lists
+import qualified TestSuite.Queries.Strings
+import qualified TestSuite.Queries.Sums
+import qualified TestSuite.Queries.Tables
+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.CompileTests.SCase
+import qualified TestSuite.CompileTests.PCase
+import qualified TestSuite.Transformers.SymbolicEval
+import qualified TestSuite.Uninterpreted.AUF
+import qualified TestSuite.Uninterpreted.Axioms
+import qualified TestSuite.Uninterpreted.EUFLogic
+import qualified TestSuite.Uninterpreted.Function
+import qualified TestSuite.Uninterpreted.Sort
+import qualified TestSuite.Uninterpreted.Uninterpreted
+
+main :: IO ()
+main = do sCaseTests <- TestSuite.CompileTests.SCase.tests
+          pCaseTests <- TestSuite.CompileTests.PCase.tests
+          defaultMain $ testGroup "SBV" [
+                        TestSuite.ADT.ADT.tests
+                      , TestSuite.ADT.Expr.tests
+                      , TestSuite.ADT.MutRec.tests
+                      , TestSuite.ADT.PExpr.tests
+                      , TestSuite.Arrays.InitVals.tests
+                      , TestSuite.Arrays.Memory.tests
+                      , TestSuite.Arrays.Query.tests
+                      , TestSuite.Arrays.Caching.tests
+                      , TestSuite.Basics.AllSat.tests
+                      , TestSuite.Basics.ArbFloats.tests
+                      , TestSuite.Basics.ArithNoSolver.tests
+                      , TestSuite.Basics.ArithNoSolver2.tests
+                      , TestSuite.Basics.ArithSolver.tests
+                      , TestSuite.Basics.Assert.tests
+                      , TestSuite.Basics.BarrelRotate.tests
+                      , TestSuite.Basics.BasicTests.tests
+                      , TestSuite.Basics.DynSign.tests
+                      , TestSuite.Basics.EqSym.tests
+                      , TestSuite.Basics.Exceptions.testsLocal
+                      , TestSuite.Basics.Exceptions.testsRemote
+                      , TestSuite.Basics.GenBenchmark.tests
+                      , TestSuite.Basics.Higher.tests
+                      , TestSuite.Basics.Index.tests
+                      , TestSuite.Basics.IteTest.tests
+                      , TestSuite.Basics.Lambda.tests
+                      , TestSuite.Basics.List.tests
+                      , TestSuite.Basics.ModelValidate.tests
+                      , TestSuite.Basics.ModelValidate.testsABC
+                      , TestSuite.Basics.Nonlinear.tests
+                      , TestSuite.Basics.ProofTests.tests
+                      , TestSuite.Basics.PseudoBoolean.tests
+                      , TestSuite.Basics.QRem.tests
+                      , TestSuite.Basics.Quantifiers.tests
+                      , TestSuite.Basics.Recursive.tests
+                      , TestSuite.Basics.TPCaching.tests
+                      , TestSuite.Basics.Set.tests
+                      , TestSuite.Basics.SmtFunctionUnique.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
+                      , TestSuite.BitPrecise.PrefixSum.tests
+                      , TestSuite.CantTypeCheck.Misc.tests
+                      , TestSuite.Char.Char.tests
+                      , TestSuite.CodeGeneration.AddSub.tests
+                      , TestSuite.CodeGeneration.CgTests.tests
+                      , TestSuite.CodeGeneration.CRC_USB5.tests
+                      , TestSuite.CodeGeneration.Fibonacci.tests
+                      , TestSuite.CodeGeneration.Floats.tests
+                      , TestSuite.CodeGeneration.GCD.tests
+                      , TestSuite.CodeGeneration.PopulationCount.tests
+                      , TestSuite.CodeGeneration.Uninterpreted.tests
+                      , TestSuite.CRC.CCITT.tests
+                      , TestSuite.CRC.CCITT_Unidir.tests
+                      , TestSuite.CRC.GenPoly.tests
+                      , TestSuite.CRC.Parity.tests
+                      , TestSuite.CRC.USB5.tests
+                      , TestSuite.Crypto.AES.tests
+                      , TestSuite.Crypto.RC4.tests
+                      , TestSuite.Crypto.SHA.tests
+                      , TestSuite.GenTest.GenTests.tests
+                      , TestSuite.Optimization.AssertWithPenalty.tests
+                      , 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.Overflows.Arithmetic.tests
+                      , TestSuite.Overflows.Casts.tests
+                      , TestSuite.Polynomials.Polynomials.tests
+                      , TestSuite.Puzzles.Coins.tests
+                      , TestSuite.Puzzles.Counts.tests
+                      , TestSuite.Puzzles.DogCatMouse.tests
+                      , TestSuite.Puzzles.Euler185.tests
+                      , TestSuite.Puzzles.MagicSquare.tests
+                      , TestSuite.Puzzles.NQueens.tests
+                      , TestSuite.Puzzles.PowerSet.tests
+                      , TestSuite.Puzzles.Sudoku.tests
+                      , TestSuite.Puzzles.Temperature.tests
+                      , TestSuite.Puzzles.U2Bridge.tests
+                      , TestSuite.Queries.BadOption.tests
+                      , TestSuite.Queries.ArrayGetVal.tests
+                      , TestSuite.Queries.BasicQuery.tests
+                      , TestSuite.Queries.DSat.tests
+                      , TestSuite.Queries.Interpolants.tests
+                      , TestSuite.Queries.Enums.tests
+                      , TestSuite.Queries.FreshVars.tests
+                      , TestSuite.Queries.Int_Z3.tests
+                      , TestSuite.Queries.Int_ABC.tests
+                      , TestSuite.Queries.Int_Boolector.tests
+                      , TestSuite.Queries.Int_CVC4.tests
+                      , TestSuite.Queries.Int_Mathsat.tests
+                      , TestSuite.Queries.Int_Yices.tests
+                      , TestSuite.Queries.Lists.tests
+                      , TestSuite.Queries.Strings.tests
+                      , TestSuite.Queries.Sums.tests
+                      , TestSuite.Queries.Tables.tests
+                      , TestSuite.Queries.Tuples.tests
+                      , TestSuite.Queries.UISat.tests
+                      , TestSuite.Queries.UISatEx.tests
+                      , TestSuite.Queries.Uninterpreted.tests
+                      , TestSuite.QuickCheck.QC.tests
+                      , TestSuite.Transformers.SymbolicEval.tests
+                      , TestSuite.Uninterpreted.AUF.tests
+                      , TestSuite.Uninterpreted.Axioms.tests
+                      , TestSuite.Uninterpreted.Function.tests
+                      , TestSuite.Uninterpreted.Sort.tests
+                      , TestSuite.Uninterpreted.Uninterpreted.tests
+                      , TestSuite.Uninterpreted.EUFLogic.tests
+                      , sCaseTests
+                      , pCaseTests
+                      ]
diff --git a/SBVTestSuite/TestSuite/ADT/ADT.hs b/SBVTestSuite/TestSuite/ADT/ADT.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/ADT.hs
@@ -0,0 +1,131 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.ADT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-unused-top-binds #-}
+
+module TestSuite.ADT.ADT(tests) where
+
+import Utils.SBVTestFramework
+import Data.SBV.Control
+import Data.SBV.Maybe
+
+data ADT  = AEmpty
+          | ABool     Bool
+          | AInteger  Integer
+          | AWord8    Word8
+          | AWord16   Word16
+          | AWord32   Word32
+          | AWord64   Word64
+          | AInt8     Int8
+          | AInt16    Int16
+          | AInt32    Int32
+          | AInt64    Int64
+          | AWord1    (WordN  1)
+          | AWord5    (WordN  5)
+          | AWord30   (WordN 30)
+          | AInt1     (IntN   1)
+          | AInt5     (IntN   5)
+          | AInt30    (IntN  30)
+          | AReal     AlgReal
+          | AFloat    Float
+          | ADouble   Double
+          | AFP       (FloatingPoint 5 12)
+          | AString   String
+          | AList     [Integer]
+          | ATuple    (Double, [(WordN 5, [Float])])
+          | AMaybe    (Maybe (AlgReal, Float, (Either Integer Float, [Bool])))
+          | AEither   (Either (Maybe Integer, Bool) [Integer])
+          | APair     ADT ADT
+          | KChar     Char
+          | KRational Rational
+          {-
+          | KADT      String (Maybe [(String, [Kind])])
+          | KSet  Kind
+          | KArray  Kind Kind
+          -}
+          deriving Show
+
+mkSymbolic [''ADT]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt00" $ checkWith t00
+    , goldenCapturedIO "adt01" $ checkWith t01
+    , goldenCapturedIO "adt02" $ checkWith t02
+    , goldenCapturedIO "adt03" $ checkWith t03
+    , goldenCapturedIO "adt04" t04
+    , goldenCapturedIO "adt05" t05
+    , goldenCapturedIO "adt06" t06
+    ]
+
+checkWith :: Symbolic () -> FilePath -> IO ()
+checkWith props rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+        _ <- props
+        query $ do cs <- checkSat
+                   case cs of
+                     Unsat  -> io $ appendFile rf "\nUNSAT"
+                     DSat{} -> io $ appendFile rf "\nDSAT"
+                     Sat{}  -> getModel         >>= \m -> io $ appendFile rf $ "\nMODEL: "   ++ show m ++ "\nDONE."
+                     Unk    -> getUnknownReason >>= \r -> io $ appendFile rf $ "\nUNKNOWN: " ++ show r ++ "\nDONE."
+
+t00 :: Symbolic ()
+t00 = do a :: SADT <- free "e"
+         constrain $ a ./== a
+
+t01 :: Symbolic ()
+t01 = do a :: SADT <- free "e"
+         constrain $ a .=== literal (APair (AInt64 4) (AMaybe (Just (0, 12, (Left 3, [False, True])))))
+
+t02 :: Symbolic ()
+t02 = do a :: SADT <- free "e"
+         constrain $ isAList a
+
+t03 :: Symbolic ()
+t03 = do a :: SADT <- free "e"
+         constrain $ isAList a .&& isAFP a
+
+t04 :: FilePath -> IO ()
+t04 rf = do AllSatResult _ _ _ ms <- allSatWith z3{verbose=True, redirectVerbose = Just rf} t
+            let sh m = appendFile rf $ "\nMODEL:" ++ show (SatResult m)
+            mapM_ sh ms
+  where t = do a :: SADT <- free "a"
+               constrain $ isAInteger a
+               constrain $ getAInteger_1 a .>= 0
+               constrain $ getAInteger_1 a .<= 5
+
+-- z3 is buggy on this. So we use cvc5. See: https://github.com/Z3Prover/z3/issues/7842
+t05 :: FilePath -> IO ()
+t05 rf = do AllSatResult _ _ _ ms <- allSatWith cvc5{verbose=True, redirectVerbose = Just rf, allSatMaxModelCount=Just 10} t
+            let sh m = appendFile rf $ "\nMODEL:" ++ show (SatResult m)
+            mapM_ sh ms
+  where t = do a :: SADT <- free "a"
+               b :: SADT <- free "b"
+               constrain $ isAFloat a .&& getAFloat_1 a .== 4
+               constrain $ isAFloat b .&& fpIsNaN (getAFloat_1 b)
+
+t06 :: FilePath -> IO ()
+t06 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+             a :: SADT <- free "a"
+             constrain $ isAMaybe a
+             constrain $ isJust (getAMaybe_1 a)
+             query $ do cs <- checkSat
+                        case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\ngetValue: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error ("BAD RESULT: " ++ show cs)
diff --git a/SBVTestSuite/TestSuite/ADT/Expr.hs b/SBVTestSuite/TestSuite/ADT/Expr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/Expr.hs
@@ -0,0 +1,419 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.Expr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, expressions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.ADT.Expr(tests) where
+
+import Control.Monad (void)
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Documentation.SBV.Examples.ADT.Expr
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Word8
+       | C A A
+       deriving Show
+
+mkSymbolic [''A]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt_expr00c" $ evalCheck  (eval e00,  3)
+    , goldenCapturedIO "adt_expr00"  $ evalCheckS eval (e00,  3)
+
+    , goldenCapturedIO "adt_expr01c" $ evalCheck  (eval e01,  7)
+    , goldenCapturedIO "adt_expr01"  $ evalCheckS eval (e01,  7)
+
+    , goldenCapturedIO "adt_expr02c" $ evalCheck  (eval e02, 21)
+    , goldenCapturedIO "adt_expr02"  $ evalCheckS eval (e02, 21)
+
+    , goldenCapturedIO "adt_expr03c" $ evalCheck  (eval e03, 28)
+    , goldenCapturedIO "adt_expr03"  $ evalCheckS eval (e03, 28)
+
+    , goldenCapturedIO "adt_expr04" $ evalTest  (eval e04)
+    , goldenCapturedIO "adt_expr05" $ evalTest  (eval e05)
+
+    , goldenCapturedIO "adt_expr06c" $ evalCheck  (f (sVar (literal "a")), 0)
+    , goldenCapturedIO "adt_expr06"  $ evalCheckS f  (sVar (literal "a") , 0)
+
+    , goldenCapturedIO "adt_expr07c" $ evalCheck  (f (sVar (literal "b")), 1)
+    , goldenCapturedIO "adt_expr07"  $ evalCheckS f  (sVar (literal "b") , 1)
+
+    , goldenCapturedIO "adt_expr08c" $ evalCheck  (f (sVar (literal "c")), 1)
+    , goldenCapturedIO "adt_expr08"  $ evalCheckS f  (sVar (literal "c") , 1)
+
+    , goldenCapturedIO "adt_expr09c" $ evalCheck  (f (sVar (literal "d")), 2)
+    , goldenCapturedIO "adt_expr09"  $ evalCheckS f  (sVar (literal "d") , 2)
+
+    , goldenCapturedIO "adt_expr10c" $ evalCheck   (sum (map (f . sVal . literal)      [-5 .. 9]),  45)
+    , goldenCapturedIO "adt_expr10"  $ evalCheckSL (sum . map f) (map (sVal . literal) [-5 .. 9],   45)
+
+    , goldenCapturedIO "adt_expr11c" $ evalCheck   (sum (map (f . sVal . literal)      [10, 10]),    8)
+    , goldenCapturedIO "adt_expr11"  $ evalCheckSL (sum . map f) (map (sVal . literal) [10, 10],     8)
+
+    , goldenCapturedIO "adt_expr12c" $ evalCheck   (sum (map (f . sVal . literal)      [11 .. 20]), 50)
+    , goldenCapturedIO "adt_expr12"  $ evalCheckSL (sum . map f) (map (sVal . literal) [11 .. 20],  50)
+
+    , goldenCapturedIO "adt_expr13c" $ evalCheck  (f e00, 3)
+    , goldenCapturedIO "adt_expr13"  $ evalCheckS f (e00, 3)
+
+    , goldenCapturedIO "adt_expr14c" $ evalCheck  (f e01, 6)
+    , goldenCapturedIO "adt_expr14"  $ evalCheckS f (e01, 6)
+
+    , goldenCapturedIO "adt_expr15c" $ evalCheck  (f e02, 6)
+    , goldenCapturedIO "adt_expr15"  $ evalCheckS f (e02, 6)
+
+    , goldenCapturedIO "adt_expr16c" $ evalCheck  (f e03, 6)
+    , goldenCapturedIO "adt_expr16"  $ evalCheckS f (e03, 6)
+
+    , goldenCapturedIO "adt_expr17c" $ evalCheck  (f e04, 6)
+    , goldenCapturedIO "adt_expr17"  $ evalCheckS f (e04, 6)
+
+    , goldenCapturedIO "adt_expr18c" $ evalCheck  (f e05, 6)
+    , goldenCapturedIO "adt_expr18"  $ evalCheckS f (e05, 6)
+
+    , goldenCapturedIO "adt_gen00"  t00
+    , goldenCapturedIO "adt_gen01"  $ tSat (-1)
+    , goldenCapturedIO "adt_gen02"  $ tSat 0
+    , goldenCapturedIO "adt_gen03"  $ tSat 1
+    , goldenCapturedIO "adt_gen04"  $ tSat 2
+    , goldenCapturedIO "adt_gen05"  $ tSat 3
+    , goldenCapturedIO "adt_gen06"  $ tSat 4
+    , goldenCapturedIO "adt_gen07"  $ tSat 5
+    , goldenCapturedIO "adt_gen08"  $ tSat 6
+    , goldenCapturedIO "adt_gen09"  $ tSat 7
+    , goldenCapturedIO "adt_gen10"  $ tSat 8
+    , goldenCapturedIO "adt_gen11"  $ tSat 9
+    , goldenCapturedIO "adt_gen12"  $ tSat 100
+    , goldenCapturedIO "adt_chk01"  $ evalTest (t (sA 12))
+
+    -- Nested pattern tests: h is a simplifier using nested patterns
+    -- Add (Val 0) e => e
+    , goldenCapturedIO "adt_nested00c" $ evalCheck (h (sAdd (sVal 0) (sVal 5)),  sVal 5)
+    , goldenCapturedIO "adt_nested00"  $ evalCheckS h (sAdd (sVal 0) (sVal 5),   sVal 5)
+    -- Add e (Val 0) => e
+    , goldenCapturedIO "adt_nested01c" $ evalCheck (h (sAdd (sVal 7) (sVal 0)),  sVal 7)
+    , goldenCapturedIO "adt_nested01"  $ evalCheckS h (sAdd (sVal 7) (sVal 0),   sVal 7)
+    -- Mul (Val 1) e => e
+    , goldenCapturedIO "adt_nested02c" $ evalCheck (h (sMul (sVal 1) (sVal 9)),  sVal 9)
+    , goldenCapturedIO "adt_nested02"  $ evalCheckS h (sMul (sVal 1) (sVal 9),   sVal 9)
+    -- Mul e (Val 1) => e
+    , goldenCapturedIO "adt_nested03c" $ evalCheck (h (sMul (sVal 4) (sVal 1)),  sVal 4)
+    , goldenCapturedIO "adt_nested03"  $ evalCheckS h (sMul (sVal 4) (sVal 1),   sVal 4)
+    -- Mul (Val 0) _ => 0
+    , goldenCapturedIO "adt_nested04c" $ evalCheck (h (sMul (sVal 0) (sVal 99)), sVal 0)
+    , goldenCapturedIO "adt_nested04"  $ evalCheckS h (sMul (sVal 0) (sVal 99),  sVal 0)
+    -- No simplification applies: Add (Val 3) (Val 4) stays as-is
+    , goldenCapturedIO "adt_nested05c" $ evalCheck (h (sAdd (sVal 3) (sVal 4)),  sAdd (sVal 3) (sVal 4))
+    , goldenCapturedIO "adt_nested05"  $ evalCheckS h (sAdd (sVal 3) (sVal 4),   sAdd (sVal 3) (sVal 4))
+    -- Guard miss: Add (Val 1) e, i /= 0, falls through to _
+    , goldenCapturedIO "adt_nested06c" $ evalCheck (h (sAdd (sVal 1) (sVal 5)),  sAdd (sVal 1) (sVal 5))
+    , goldenCapturedIO "adt_nested06"  $ evalCheckS h (sAdd (sVal 1) (sVal 5),   sAdd (sVal 1) (sVal 5))
+    -- Pattern ordering: Add (Val 0) (Val 0) => Val 0 (first rule fires, not second)
+    , goldenCapturedIO "adt_nested07c" $ evalCheck (h (sAdd (sVal 0) (sVal 0)),  sVal 0)
+    , goldenCapturedIO "adt_nested07"  $ evalCheckS h (sAdd (sVal 0) (sVal 0),   sVal 0)
+    -- Mul (Val 1) e where e is compound: result is the compound expression
+    , goldenCapturedIO "adt_nested08c" $ evalCheck (h (sMul (sVal 1) (sAdd (sVal 3) (sVal 4))),  sAdd (sVal 3) (sVal 4))
+    , goldenCapturedIO "adt_nested08"  $ evalCheckS h (sMul (sVal 1) (sAdd (sVal 3) (sVal 4)),   sAdd (sVal 3) (sVal 4))
+    -- Mul (Val 0) e where e is compound: result is Val 0 regardless of right side
+    , goldenCapturedIO "adt_nested09c" $ evalCheck (h (sMul (sVal 0) (sAdd (sVal 3) (sVal 4))),  sVal 0)
+    , goldenCapturedIO "adt_nested09"  $ evalCheckS h (sMul (sVal 0) (sAdd (sVal 3) (sVal 4)),   sVal 0)
+    -- Non-Add/Mul constructor: Var falls through to _
+    , goldenCapturedIO "adt_nested10c" $ evalCheck (h (sVar (literal "x")),  sVar (literal "x"))
+    , goldenCapturedIO "adt_nested10"  $ evalCheckS h (sVar (literal "x"),   sVar (literal "x"))
+    -- Non-Add/Mul constructor: Val falls through to _
+    , goldenCapturedIO "adt_nested11c" $ evalCheck (h (sVal 42),  sVal 42)
+    , goldenCapturedIO "adt_nested11"  $ evalCheckS h (sVal 42,   sVal 42)
+    -- Let falls through to _
+    , goldenCapturedIO "adt_nested12c" $ evalCheck (h (sLet (literal "x") (sVal 1) (sVar (literal "x"))),  sLet (literal "x") (sVal 1) (sVar (literal "x")))
+    , goldenCapturedIO "adt_nested12"  $ evalCheckS h (sLet (literal "x") (sVal 1) (sVar (literal "x")),   sLet (literal "x") (sVal 1) (sVar (literal "x")))
+    -- Mul (Val 0) with a non-Val right side (Var): result is Val 0, wildcard ignores it
+    , goldenCapturedIO "adt_nested13c" $ evalCheck (h (sMul (sVal 0) (sVar (literal "x"))),  sVal 0)
+    , goldenCapturedIO "adt_nested13"  $ evalCheckS h (sMul (sVal 0) (sVar (literal "x")),   sVal 0)
+    -- Add (Val 0) with a compound right side (Add)
+    , goldenCapturedIO "adt_nested14c" $ evalCheck (h (sAdd (sVal 0) (sMul (sVal 2) (sVal 3))),  sMul (sVal 2) (sVal 3))
+    , goldenCapturedIO "adt_nested14"  $ evalCheckS h (sAdd (sVal 0) (sMul (sVal 2) (sVal 3)),   sMul (sVal 2) (sVal 3))
+    -- Idempotency: h (h e) == h e (using a simplifiable input)
+    , goldenCapturedIO "adt_nested15c" $ evalCheck (h (h (sAdd (sVal 0) (sVal 5))),  sVal 5)
+    , goldenCapturedIO "adt_nested15"  $ evalCheckS (h . h) (sAdd (sVal 0) (sVal 5),  sVal 5)
+    -- Idempotency: h (h e) == h e (using a non-simplifiable input)
+    , goldenCapturedIO "adt_nested16c" $ evalCheck (h (h (sAdd (sVal 3) (sVal 4))),  sAdd (sVal 3) (sVal 4))
+    , goldenCapturedIO "adt_nested16"  $ evalCheckS (h . h) (sAdd (sVal 3) (sVal 4),  sAdd (sVal 3) (sVal 4))
+    -- Two-step simplification: h (h (Mul (Val 1) (Add (Val 0) (Val 5)))) => Val 5
+    -- First h: Mul (Val 1) (Add (Val 0) (Val 5)) => Add (Val 0) (Val 5)
+    -- Second h: Add (Val 0) (Val 5)              => Val 5
+    , goldenCapturedIO "adt_nested17c" $ evalCheck (h (h (sMul (sVal 1) (sAdd (sVal 0) (sVal 5)))),  sVal 5)
+    , goldenCapturedIO "adt_nested17"  $ evalCheckS (h . h) (sMul (sVal 1) (sAdd (sVal 0) (sVal 5)),  sVal 5)
+    -- Semantics preservation: eval (h e) == eval e for all closed e
+    , goldenCapturedIO "adt_nested18"  hPreservesEval
+    -- Mul rule ordering: Mul (Val 1) (Val 1) => Val 1 (first Mul rule fires, not second)
+    , goldenCapturedIO "adt_nested19c" $ evalCheck (h (sMul (sVal 1) (sVal 1)),  sVal 1)
+    , goldenCapturedIO "adt_nested19"  $ evalCheckS h (sMul (sVal 1) (sVal 1),   sVal 1)
+    -- Guard miss on both Mul rules: Mul (Val 2) (Val 3) falls through to _
+    , goldenCapturedIO "adt_nested20c" $ evalCheck (h (sMul (sVal 2) (sVal 3)),  sMul (sVal 2) (sVal 3))
+    , goldenCapturedIO "adt_nested20"  $ evalCheckS h (sMul (sVal 2) (sVal 3),   sMul (sVal 2) (sVal 3))
+    -- Mul (Val 1) (Var "x") => Var "x": Mul rule returns a non-Val expression
+    , goldenCapturedIO "adt_nested21c" $ evalCheck (h (sMul (sVal 1) (sVar (literal "x"))),  sVar (literal "x"))
+    , goldenCapturedIO "adt_nested21"  $ evalCheckS h (sMul (sVal 1) (sVar (literal "x")),   sVar (literal "x"))
+    -- Add (Val 0) (Var "x") => Var "x": Add rule returns a non-Val expression
+    , goldenCapturedIO "adt_nested22c" $ evalCheck (h (sAdd (sVal 0) (sVar (literal "x"))),  sVar (literal "x"))
+    , goldenCapturedIO "adt_nested22"  $ evalCheckS h (sAdd (sVal 0) (sVar (literal "x")),   sVar (literal "x"))
+    -- Focused proof: h preserves eval for Add expressions specifically
+    , goldenCapturedIO "adt_nested23"  hPreservesEvalAdd
+    -- Focused proof: h preserves eval for Mul expressions specifically
+    , goldenCapturedIO "adt_nested24"  hPreservesEvalMul
+
+    -- Deep nesting: cfold constant-folds Add (Mul (Val a) (Val b)) (Mul (Val c) (Val d)) => Val (a*b + c*d)
+    -- 4-level deep nested pattern on all branches simultaneously
+    -- Fires: Add (Mul (Val 2) (Val 3)) (Mul (Val 4) (Val 5)) => Val 26
+    , goldenCapturedIO "adt_nested25c" $ evalCheck (cfold (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5))),  sVal 26)
+    , goldenCapturedIO "adt_nested25"  $ evalCheckS cfold (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5)),   sVal 26)
+    -- Fires: Add (Mul (Val 0) (Val 99)) (Mul (Val 1) (Val 1)) => Val 1
+    , goldenCapturedIO "adt_nested26c" $ evalCheck (cfold (sAdd (sMul (sVal 0) (sVal 99)) (sMul (sVal 1) (sVal 1))),  sVal 1)
+    , goldenCapturedIO "adt_nested26"  $ evalCheckS cfold (sAdd (sMul (sVal 0) (sVal 99)) (sMul (sVal 1) (sVal 1)),   sVal 1)
+    -- No match: right branch is Var, not Mul (Val _) (Val _)
+    , goldenCapturedIO "adt_nested27c" $ evalCheck (cfold (sAdd (sMul (sVal 2) (sVal 3)) (sVar (literal "x"))),  sAdd (sMul (sVal 2) (sVal 3)) (sVar (literal "x")))
+    , goldenCapturedIO "adt_nested27"  $ evalCheckS cfold (sAdd (sMul (sVal 2) (sVal 3)) (sVar (literal "x")),   sAdd (sMul (sVal 2) (sVal 3)) (sVar (literal "x")))
+    -- No match: outer constructor is Mul, not Add
+    , goldenCapturedIO "adt_nested28c" $ evalCheck (cfold (sMul (sVal 2) (sVal 3)),  sMul (sVal 2) (sVal 3))
+    , goldenCapturedIO "adt_nested28"  $ evalCheckS cfold (sMul (sVal 2) (sVal 3),   sMul (sVal 2) (sVal 3))
+    -- Semantics preservation: eval (cfold e) == eval e for all e
+    , goldenCapturedIO "adt_nested29"  cfoldPreservesEval
+
+    -- Pipeline tests: cfold (h e) — first simplify with h, then constant-fold with cfold
+    -- Neither h nor cfold fires: Add (Mul (Val 2) (Val 3)) (Mul (Val 4) (Val 5)) passes through h unchanged, cfold folds to Val 26
+    , goldenCapturedIO "adt_nested30c" $ evalCheck (cfold (h (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5)))),  sVal 26)
+    , goldenCapturedIO "adt_nested30"  $ evalCheckS (cfold . h) (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5)),  sVal 26)
+    -- h leaves outer Add unchanged; cfold still sees Add (Mul (Val 1) (Val 2)) (Mul (Val 0) (Val 4)) and folds to Val 2
+    , goldenCapturedIO "adt_nested31c" $ evalCheck (cfold (h (sAdd (sMul (sVal 1) (sVal 2)) (sMul (sVal 0) (sVal 4)))),  sVal 2)
+    , goldenCapturedIO "adt_nested31"  $ evalCheckS (cfold . h) (sAdd (sMul (sVal 1) (sVal 2)) (sMul (sVal 0) (sVal 4)),  sVal 2)
+    -- h fires (Mul (Val 1) r => r), exposing a cfold-able expression; cfold then folds to Val 26
+    , goldenCapturedIO "adt_nested32c" $ evalCheck (cfold (h (sMul (sVal 1) (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5))))),  sVal 26)
+    , goldenCapturedIO "adt_nested32"  $ evalCheckS (cfold . h) (sMul (sVal 1) (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5))),  sVal 26)
+    -- h fires (Add (Val 0) r => r), exposing a cfold-able expression; cfold then folds to Val 26
+    , goldenCapturedIO "adt_nested33c" $ evalCheck (cfold (h (sAdd (sVal 0) (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5))))),  sVal 26)
+    , goldenCapturedIO "adt_nested33"  $ evalCheckS (cfold . h) (sAdd (sVal 0) (sAdd (sMul (sVal 2) (sVal 3)) (sMul (sVal 4) (sVal 5))),  sVal 26)
+
+    -- Literal pattern tests: p uses integer and string literal patterns
+    -- Top-level literal fires: Val 0 => 100
+    , goldenCapturedIO "adt_lit00c" $ evalCheck (p (sVal 0),  100)
+    , goldenCapturedIO "adt_lit00"  $ evalCheckS p (sVal 0,   100)
+    -- Top-level literal fires: Val 1 => 200
+    , goldenCapturedIO "adt_lit01c" $ evalCheck (p (sVal 1),  200)
+    , goldenCapturedIO "adt_lit01"  $ evalCheckS p (sVal 1,   200)
+    -- Top-level literal misses: Val 2 falls through to eval e = 2
+    , goldenCapturedIO "adt_lit02c" $ evalCheck (p (sVal 2),  2)
+    , goldenCapturedIO "adt_lit02"  $ evalCheckS p (sVal 2,   2)
+    -- Nested literal fires: Add (Val 0) (Val 5) => eval (Val 5) = 5
+    , goldenCapturedIO "adt_lit03c" $ evalCheck (p (sAdd (sVal 0) (sVal 5)),  5)
+    , goldenCapturedIO "adt_lit03"  $ evalCheckS p (sAdd (sVal 0) (sVal 5),   5)
+    -- Nested literal misses: Add (Val 1) (Val 5) => eval e = 6
+    , goldenCapturedIO "adt_lit04c" $ evalCheck (p (sAdd (sVal 1) (sVal 5)),  6)
+    , goldenCapturedIO "adt_lit04"  $ evalCheckS p (sAdd (sVal 1) (sVal 5),   6)
+    -- Var falls through to eval e (= 0 for unbound var)
+    , goldenCapturedIO "adt_lit05c" $ evalCheck (p (sVar (literal "x")),  0)
+    , goldenCapturedIO "adt_lit05"  $ evalCheckS p (sVar (literal "x"),   0)
+    ]
+    where a = literal "a"
+          b = literal "a"
+
+          e00 = 3                                -- 3
+          e01 = 3 + 4                            -- 7
+          e02 = e00 * e01                        -- 21
+          e03 = sLet a e02 (sVar a + e01)        -- 28
+          e04 = e03 + sLet a e03 (sVar a + e01)  -- 28 + 28 + 7 = 63
+          e05 = sLet b e04 (sVar b * sVar b)     -- 63 * 63 = 3969
+
+evalCheck :: SymVal a => (SBV a, SBV a) -> FilePath -> IO ()
+evalCheck (sv, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        constrain $ sv ./= v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckS :: SymVal b => (SExpr -> SBV b) -> (SExpr, SBV b) -> FilePath -> IO ()
+evalCheckS fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        se :: SExpr <- free_
+                        constrain $ se .== e
+                        constrain $ fun se ./= v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckSL :: ([SExpr] -> SInteger) -> ([SExpr], Integer) -> FilePath -> IO ()
+evalCheckSL fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        ses :: [SExpr] <- mapM (const free_) e
+                        constrain $ ses .== e
+                        constrain $ fun ses ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalTest :: (Show a, SymVal a) => SBV a -> FilePath -> IO ()
+evalTest sv rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                    res <- free "res"
+                    constrain $ sv .== res
+                    query $ do cs <- checkSat
+                               case cs of
+                                 Sat -> do r <- getValue res
+                                           io $ appendFile rf ("Result: " ++ show r ++ "\n")
+                                 _       -> error $ "Unexpected: " ++ show cs
+
+f :: SExpr -> SInteger
+f e = [sCase| e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         _                                                   -> 6
+      |]
+
+-- Create something like:
+--       let a = _
+--    in let b = _
+--    in _ + _
+-- such that it evaluates to 12
+t00 :: FilePath -> IO ()
+t00 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+            a :: SExpr <- free "a"
+            constrain $ isValid a
+            constrain $ eval a .== 12
+
+            constrain $ isLet a
+            constrain $ isLet (getLet_3 a)
+            constrain $ isAdd (getLet_3 (getLet_3 a))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\nGot: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error $ "Unexpected: " ++ show cs
+
+g :: SExpr -> SInteger
+g e = [sCase| e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         Add _ _ -> 6
+         Mul _ _ -> 7
+         Let{}   -> 8
+
+         _ -> 100
+      |]
+
+-- Show that g can never produce anything but 0..8
+tSat :: Integer -> FilePath -> IO ()
+tSat i rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+              a :: SExpr <- free "a"
+              constrain $ g a .== literal i
+
+              query $ do cs <- checkSat
+                         case cs of
+                           Sat{} -> do v <- getValue a
+                                       io $ do appendFile rf $ "\nGot: " ++ show v
+                                               appendFile rf   "\nDONE\n"
+                           Unsat -> io $ do appendFile rf "\nUNSAT\n"
+                           _     -> error $ "Unexpected: " ++ show cs
+
+t :: SA -> SA
+t = smtFunction "t" $ \a ->
+       [sCase| a of
+         A u     -> sA (u+1)
+         B w     -> sB (w+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
+
+-- | A simplifier that uses nested patterns to special-case identity/zero elements.
+-- Add (Val 0) e  => e
+-- Add e (Val 0)  => e
+-- Mul (Val 1) e  => e
+-- Mul e (Val 1)  => e
+-- Mul (Val 0) _  => 0
+-- otherwise      => identity
+h :: SExpr -> SExpr
+h e = [sCase| e of
+         Add (Val i) r | i .== 0 -> r
+         Add l (Val i) | i .== 0 -> l
+         Mul (Val i) r | i .== 1 -> r
+         Mul l (Val i) | i .== 1 -> l
+         Mul (Val i) _ | i .== 0 -> sVal 0
+         _                        -> e
+      |]
+
+-- | Prove that h preserves evaluation semantics: eval (h e) == eval e for all e.
+hPreservesEval :: FilePath -> IO ()
+hPreservesEval rf = void $ proveWith z3{verbose=True, redirectVerbose=Just rf} $ do
+                      e :: SExpr <- free "e"
+                      pure $ eval (h e) .== eval e
+
+-- | Focused proof: h preserves eval specifically when the top-level node is Add.
+hPreservesEvalAdd :: FilePath -> IO ()
+hPreservesEvalAdd rf = void $ proveWith z3{verbose=True, redirectVerbose=Just rf} $ do
+                         e :: SExpr <- free "e"
+                         pure $ isAdd e .=> (eval (h e) .== eval e)
+
+-- | Focused proof: h preserves eval specifically when the top-level node is Mul.
+hPreservesEvalMul :: FilePath -> IO ()
+hPreservesEvalMul rf = void $ proveWith z3{verbose=True, redirectVerbose=Just rf} $ do
+                         e :: SExpr <- free "e"
+                         pure $ isMul e .=> (eval (h e) .== eval e)
+
+-- | A constant-folder using a deeply nested pattern: recognizes Add (Mul (Val a) (Val b)) (Mul (Val c) (Val d))
+-- and folds it to Val (a*b + c*d). All four leaf positions use nested Val patterns simultaneously.
+cfold :: SExpr -> SExpr
+cfold e = [sCase| e of
+             Add (Mul (Val a) (Val b)) (Mul (Val c) (Val d)) -> sVal (a*b + c*d)
+             _                                               -> e
+          |]
+
+-- | Prove that cfold preserves evaluation semantics: eval (cfold e) == eval e for all e.
+cfoldPreservesEval :: FilePath -> IO ()
+cfoldPreservesEval rf = void $ proveWith z3{verbose=True, redirectVerbose=Just rf} $ do
+                          e :: SExpr <- free "e"
+                          pure $ eval (cfold e) .== eval e
+
+-- | A function using literal patterns: dispatches on specific integer/string values directly in the pattern.
+-- Val 0         => 100
+-- Val 1         => 200
+-- Add (Val 0) r => eval r   (nested integer literal)
+-- _             => eval e   (fallthrough)
+p :: SExpr -> SInteger
+p e = [sCase| e of
+         Val 0         -> 100
+         Val 1         -> 200
+         Add (Val 0) r -> eval r
+         _             -> eval e
+      |]
diff --git a/SBVTestSuite/TestSuite/ADT/MutRec.hs b/SBVTestSuite/TestSuite/ADT/MutRec.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/MutRec.hs
@@ -0,0 +1,195 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.MutRec
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, mutual-recursion and other parameterization checks
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-record-selectors #-}
+
+module TestSuite.ADT.MutRec(tests) where
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Data.SBV.RegExp
+import Data.SBV.Tuple
+import Data.SBV.Maybe
+import qualified Data.SBV.List  as SL
+import qualified Data.SBV.Tuple as ST
+
+-- | Expression layer
+data Expr var val = Con { con :: val }
+                  | Var { var :: var }
+                  | Add { add1 :: Expr var val, add2 :: Expr var val }
+                  | Mul { mul1 :: Expr var val, mul2 :: Expr var val }
+
+-- | Statement layer
+data Stmt var val = Assign {lhs  :: var,          rhs  :: Expr var val }
+                  | Seq    {seqH :: Stmt var val, seqT :: Stmt var val }
+
+mkSymbolic [''Expr, ''Stmt]
+
+data A a b = Aa   { aa :: a }
+           | Ab   { ab :: b }
+           | Aab  { aba :: a, abb :: b }
+           | A2   { a2 :: A b String }
+           | A3   { a3 :: A b a }
+           deriving Show
+
+mkSymbolic [''A]
+
+-- | Show instance for 'Expr'.
+instance (Show var, Show val) => Show (Expr var val) where
+  show (Con i)   = show i
+  show (Var a)   = show a
+  show (Add l r) = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r) = "(" ++ show l ++ " * " ++ show r ++ ")"
+
+-- | Show instance for 'Stmt'.
+instance (Show var, Show val) => Show (Stmt var val) where
+  show (Assign v e) = show v ++ " := " ++ show e
+  show (Seq a b)    = show a ++ ";\n" ++ show b
+
+-- | Show instance for 'Expr' specialized when var is string.
+instance {-# OVERLAPPING #-} Show val => Show (Expr String val) where
+  show (Con i)   = show i
+  show (Var a)   = a
+  show (Add l r) = "(" ++ show l ++ " + " ++ show r ++ ")"
+  show (Mul l r) = "(" ++ show l ++ " * " ++ show r ++ ")"
+
+-- | Show instance for 'Stmt' specialized when var is string.
+instance {-# OVERLAPPING #-} Show val => Show (Stmt String val) where
+  show (Assign v e) =      v ++ " := " ++ show e
+  show (Seq a b)    = show a ++ ";\n" ++ show b
+
+-- | Validity: We require each variable appearing to be an identifier (lowercase letter followed by
+-- any number of upper-lower case letters and digits), and all expressions are closed; i.e., any
+-- variable referenced is assigned by a prior assignment expression.
+isValid :: forall val. SymVal val => SStmt String val -> SBool
+isValid = ST.fst . goS []
+  where isId s = s `match` (asciiLower * KStar (asciiLetter + digit))
+
+        goE :: SList String -> SExpr String val -> SBool
+        goE = smtFunction "validE"
+            $ \env expr -> [sCase| expr of
+                               Con _   -> sTrue
+                               Var s   -> isId s .&& s `SL.elem` env
+                               Add l r -> goE env l .&& goE env r
+                               Mul l r -> goE env l .&& goE env r
+                            |]
+
+        goS :: SList String -> SStmt String val -> STuple Bool [String]
+        goS = smtFunction "validS"
+            $ \env stmt -> [sCase| stmt of
+                               Assign v e -> tuple (isId v .&& goE env e, v SL..: env)
+                               Seq    a b -> let (lv, env')  = untuple $ goS env  a
+                                                 (rv, env'') = untuple $ goS env' b
+                                             in tuple (lv .&& rv, env'')
+                            |]
+
+tests :: TestTree
+tests =
+  testGroup "ADT_MR" [
+      goldenCapturedIO "adt_mr00" $ r t00
+    , goldenCapturedIO "adt_mr01" $ r t01
+    , goldenCapturedIO "adt_mr02" $ r t02
+    , goldenCapturedIO "adt_mr03" $ r t03
+    , goldenCapturedIO "adt_mr04" $ r t04
+    ]
+  where r p rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} (p rf)
+
+t00 :: FilePath -> Symbolic ()
+t00 rf = do p :: SStmt String Integer <- free "p"
+
+            -- Make sure there's some structure to the program:
+            constrain $ isSeq    p
+            constrain $ isSeq    (getSeq_2 p)
+            constrain $ isSeq    (getSeq_2 (getSeq_2 p))
+            constrain $ isAssign (getSeq_2 (getSeq_2 (getSeq_2 p)))
+            constrain $ isAdd    (getAssign_2 (getSeq_2 (getSeq_2 (getSeq_2 p))))
+            constrain $ isVar    (getAdd_1    (getAssign_2 (getSeq_2 (getSeq_2 (getSeq_2 p)))))
+
+            -- Would love to have the following. But it creates too big of a problem.
+            -- constrain $ isValid p
+            constrain $ isValid (sAssign (literal "a") (sCon (literal 1)) :: SStmt String Float)
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t01 :: FilePath -> Symbolic ()
+t01 rf = do p :: SStmt String (Maybe (Either Integer Bool)) <- free "p"
+
+            constrain $ isAssign  p
+            constrain $ isAdd     (srhs p)
+            constrain $ isCon     (sadd1 (srhs p))
+            constrain $ isCon     (sadd2 (srhs p))
+            constrain $ isNothing (scon (sadd1 (srhs p)))
+            constrain $ isJust    (scon (sadd2 (srhs p)))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t02 :: FilePath -> Symbolic ()
+t02 rf = do p :: SA Integer Bool <- free "p"
+
+            constrain $ isA2 p
+            constrain $ isA2 (sa2 p)
+            constrain $ isAa (sa2 (sa2 p))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t03 :: FilePath -> Symbolic ()
+t03 rf = do p :: SA Integer Bool <- free "p"
+
+            constrain $ isA3 p
+            constrain $ isAb (sa3 p)
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+t04 :: FilePath -> Symbolic ()
+t04 rf = do p :: SA Integer (A Float Bool) <- free "p"
+
+            constrain $ isA2 p
+            constrain $ isA3 (sa2 p)
+            constrain $ isAab (sa3 (sa2 p))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat -> do r <- getValue p
+                                   io $ do appendFile rf $ "\nGot:\n" ++ show r
+                                           appendFile rf   "\nDONE\n"
+                         _   -> error $ "Unexpected result: " ++ show cs
+
+_unused :: a
+_unused = undefined con var add1 add2 mul1 mul2 lhs rhs seqH seqT
diff --git a/SBVTestSuite/TestSuite/ADT/PExpr.hs b/SBVTestSuite/TestSuite/ADT/PExpr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/ADT/PExpr.hs
@@ -0,0 +1,230 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.ADT.PExpr
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ADTs, parameterized expressions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.ADT.PExpr(tests) where
+
+import Data.SBV
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Documentation.SBV.Examples.ADT.Param
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Word8
+       | C A A
+       deriving Show
+
+mkSymbolic [''A]
+
+tests :: TestTree
+tests =
+  testGroup "ADT" [
+      goldenCapturedIO "adt_pexpr00c" $ evalCheck  (eval e00,  3)
+    , goldenCapturedIO "adt_pexpr00"  $ evalCheckS eval (e00,  3)
+
+    , goldenCapturedIO "adt_pexpr01c" $ evalCheck  (eval e01,  7)
+    , goldenCapturedIO "adt_pexpr01"  $ evalCheckS eval (e01,  7)
+
+    , goldenCapturedIO "adt_pexpr02c" $ evalCheck  (eval e02, 21)
+    , goldenCapturedIO "adt_pexpr02"  $ evalCheckS eval (e02, 21)
+
+    , goldenCapturedIO "adt_pexpr03c" $ evalCheck  (eval e03, 28)
+    , goldenCapturedIO "adt_pexpr03"  $ evalCheckS eval (e03, 28)
+
+    , goldenCapturedIO "adt_pexpr04" $ evalTest  (eval e04)
+    , goldenCapturedIO "adt_pexpr05" $ evalTest  (eval e05)
+
+    , goldenCapturedIO "adt_pexpr06c" $ evalCheck  (f (sVar (literal "a")), 0)
+    , goldenCapturedIO "adt_pexpr06"  $ evalCheckS f  (sVar (literal "a") , 0)
+
+    , goldenCapturedIO "adt_pexpr07c" $ evalCheck  (f (sVar (literal "b")), 1)
+    , goldenCapturedIO "adt_pexpr07"  $ evalCheckS f  (sVar (literal "b") , 1)
+
+    , goldenCapturedIO "adt_pexpr08c" $ evalCheck  (f (sVar (literal "c")), 1)
+    , goldenCapturedIO "adt_pexpr08"  $ evalCheckS f  (sVar (literal "c") , 1)
+
+    , goldenCapturedIO "adt_pexpr09c" $ evalCheck  (f (sVar (literal "d")), 2)
+    , goldenCapturedIO "adt_pexpr09"  $ evalCheckS f  (sVar (literal "d") , 2)
+
+    , goldenCapturedIO "adt_pexpr10c" $ evalCheck   (sum (map (f . sVal . literal)      [-5 .. 9]), 45)
+    , goldenCapturedIO "adt_pexpr10"  $ evalCheckSL (sum . map f) (map (sVal . literal) [-5 .. 9],  45)
+
+    , goldenCapturedIO "adt_pexpr11c" $ evalCheck   (sum (map (f . sVal . literal)      [10, 10]),   8)
+    , goldenCapturedIO "adt_pexpr11"  $ evalCheckSL (sum . map f) (map (sVal . literal) [10, 10],    8)
+
+    , goldenCapturedIO "adt_pexpr12c" $ evalCheck   (sum (map (f . sVal . literal)      [11 .. 20]), 50)
+    , goldenCapturedIO "adt_pexpr12"  $ evalCheckSL (sum . map f) (map (sVal . literal) [11 .. 20],  50)
+
+    , goldenCapturedIO "adt_pexpr13c" $ evalCheck  (f e00, 3)
+    , goldenCapturedIO "adt_pexpr13"  $ evalCheckS f (e00, 3)
+
+    , goldenCapturedIO "adt_pexpr14c" $ evalCheck  (f e01, 6)
+    , goldenCapturedIO "adt_pexpr14"  $ evalCheckS f (e01, 6)
+
+    , goldenCapturedIO "adt_pexpr15c" $ evalCheck  (f e02, 6)
+    , goldenCapturedIO "adt_pexpr15"  $ evalCheckS f (e02, 6)
+
+    , goldenCapturedIO "adt_pexpr16c" $ evalCheck  (f e03, 6)
+    , goldenCapturedIO "adt_pexpr16"  $ evalCheckS f (e03, 6)
+
+    , goldenCapturedIO "adt_pexpr17c" $ evalCheck  (f e04, 6)
+    , goldenCapturedIO "adt_pexpr17"  $ evalCheckS f (e04, 6)
+
+    , goldenCapturedIO "adt_pexpr18c" $ evalCheck  (f e05, 6)
+    , goldenCapturedIO "adt_pexpr18"  $ evalCheckS f (e05, 6)
+
+    , goldenCapturedIO "adt_pgen00"  t00
+    , goldenCapturedIO "adt_pgen01"  $ tSat (-1)
+    , goldenCapturedIO "adt_pgen02"  $ tSat 0
+    , goldenCapturedIO "adt_pgen03"  $ tSat 1
+    , goldenCapturedIO "adt_pgen04"  $ tSat 2
+    , goldenCapturedIO "adt_pgen05"  $ tSat 3
+    , goldenCapturedIO "adt_pgen06"  $ tSat 4
+    , goldenCapturedIO "adt_pgen07"  $ tSat 5
+    , goldenCapturedIO "adt_pgen08"  $ tSat 6
+    , goldenCapturedIO "adt_pgen09"  $ tSat 7
+    , goldenCapturedIO "adt_pgen10"  $ tSat 8
+    , goldenCapturedIO "adt_pgen11"  $ tSat 9
+    , goldenCapturedIO "adt_pgen12"  $ tSat 100
+    , goldenCapturedIO "adt_pchk01"  $ evalTest (t (sA 12))
+    ]
+    where a = literal "a"
+          b = literal "a"
+
+          e00, e01, e02, e03, e04, e05 :: SExpr String Integer
+          e00 = 3                                -- 3
+          e01 = 3 + 4                            -- 7
+          e02 = e00 * e01                        -- 21
+          e03 = sLet a e02 (sVar a + e01)        -- 28
+          e04 = e03 + sLet a e03 (sVar a + e01)  -- 28 + 28 + 7 = 63
+          e05 = sLet b e04 (sVar b * sVar b)     -- 63 * 63 = 3969
+
+evalCheck :: SymVal a => (SBV a, a) -> FilePath -> IO ()
+evalCheck (sv, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        constrain $ sv ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckS :: (SExpr String Integer -> SInteger) -> (SExpr String Integer , Integer) -> FilePath -> IO ()
+evalCheckS fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        se :: SExpr String Integer <- free_
+                        constrain $ se .== e
+                        constrain $ fun se ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalCheckSL :: ([SExpr String Integer] -> SInteger) -> ([SExpr String Integer], Integer) -> FilePath -> IO ()
+evalCheckSL fun (e, v) rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                        ses :: [SExpr String Integer] <- mapM (const free_) e
+                        constrain $ ses .== e
+                        constrain $ fun ses ./= literal v
+                        query $ do cs <- checkSat
+                                   case cs of
+                                     Unsat{} -> io $ appendFile rf "All good.\n"
+                                     _       -> error $ "Unexpected: " ++ show cs
+
+evalTest :: (Show a, SymVal a) => SBV a -> FilePath -> IO ()
+evalTest sv rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+                    res <- free "res"
+                    constrain $ sv .== res
+                    query $ do cs <- checkSat
+                               case cs of
+                                 Sat -> do r <- getValue res
+                                           io $ appendFile rf ("Result: " ++ show r ++ "\n")
+                                 _       -> error $ "Unexpected: " ++ show cs
+
+f :: SExpr String Integer -> SInteger
+f e = [sCase| e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         _                                                   -> 6
+      |]
+
+-- Create something like:
+--       let a = _
+--    in let b = _
+--    in _ + _
+-- such that it evaluates to 12
+t00 :: FilePath -> IO ()
+t00 rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+            a :: SExpr String Integer <- free "a"
+            constrain $ isValid isId a
+            constrain $ eval a .== 12
+
+            constrain $ isLet a
+            constrain $ isLet (getLet_3 a)
+            constrain $ isAdd (getLet_3 (getLet_3 a))
+
+            query $ do cs <- checkSat
+                       case cs of
+                         Sat{} -> do v <- getValue a
+                                     io $ do appendFile rf $ "\nGot: " ++ show v
+                                             appendFile rf   "\nDONE\n"
+                         _     -> error $ "Unexpected: " ++ show cs
+
+g :: (SymVal val, OrdSymbolic (SBV val), Num (SBV val)) => SExpr String val -> SInteger
+g e = [sCase| e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Val i     | i .<  10                                -> 3
+                   | i .== 10                                -> 4
+                   | i .>  10                                -> 5
+
+         Add _ _ -> 6
+         Mul _ _ -> 7
+         Let{}   -> 8
+
+         _ -> 100
+      |]
+
+-- Show that g can never produce anything but 0..8
+tSat :: Integer -> FilePath -> IO ()
+tSat i rf = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+              a :: SExpr String Integer <- free "a"
+              constrain $ g a .== literal i
+
+              query $ do cs <- checkSat
+                         case cs of
+                           Sat{} -> do v <- getValue a
+                                       io $ do appendFile rf $ "\nGot: " ++ show v
+                                               appendFile rf   "\nDONE\n"
+                           Unsat -> io $ do appendFile rf "\nUNSAT\n"
+                           _     -> error $ "Unexpected: " ++ show cs
+
+t :: SA -> SA
+t = smtFunction "t" $ \a ->
+       [sCase| a of
+         A u     -> sA (u+1)
+         B w     -> sB (w+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
diff --git a/SBVTestSuite/TestSuite/Arrays/Caching.hs b/SBVTestSuite/TestSuite/Arrays/Caching.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Arrays/Caching.hs
@@ -0,0 +1,47 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Arrays.Caching
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test case for https://github.com/LeventErkok/sbv/issues/541
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Arrays.Caching (tests)  where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests = testGroup "Arrays.Caching" [
+            goldenCapturedIO "array_caching_01" (run (test True))
+          , goldenCapturedIO "array_caching_02" (run (test False))
+          ]
+   where run :: Symbolic SBool -> FilePath -> IO ()
+         run tst goldFile = do r <- satWith defaultSMTCfg{verbose=True, redirectVerbose = Just goldFile} tst
+                               appendFile goldFile ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+test :: Bool -> Symbolic SBool
+test swap = do
+    let arr :: SArray Integer Integer
+        arr = constArray 0
+
+    x   <- sInteger "x"
+
+    let ys = writeArray arr 0 2
+
+        idx = x + 1
+
+        ys1 = writeArray ys 0   (readArray ys idx)
+        ys2 = writeArray ys idx 1
+
+        v = if swap
+               then ite (x .== 0) (readArray ys1 0) (readArray ys2 0)
+               else ite (x ./= 0) (readArray ys2 0) (readArray ys1 0)
+
+    pure $ v .== 1
diff --git a/SBVTestSuite/TestSuite/Arrays/InitVals.hs b/SBVTestSuite/TestSuite/Arrays/InitVals.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Arrays/InitVals.hs
@@ -0,0 +1,139 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Arrays.InitVals
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing arrays with initializers
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Arrays.InitVals(tests) where
+
+import Data.SBV
+import Utils.SBVTestFramework
+
+readDef :: Predicate
+readDef = do c :: SInteger <- free "c"
+             i :: SInteger <- free "i"
+             j <- free "j"
+             let a = constArray c
+
+             let a' = writeArray a j 32
+
+             return $ ite (i ./= j) (readArray a' i .== c)
+                                    (readArray a' i .== 32)
+
+readNoDef :: Predicate
+readNoDef = do i :: SInteger <- free "i"
+               j :: SInteger <- free "j"
+
+               a <- sArray_
+
+               return $ readArray a i .== j
+
+constArr :: Predicate
+constArr = do i :: SInteger <- sInteger "i"
+              j :: SInteger <- sInteger "j"
+
+              constrain $ i .< j
+              constrain $ i `sElem` [1, 2, 3, 75]
+              pure $ readArray myArray i .== readArray myArray j
+  where myArray = listArray [(1, 12), (2, 5) , (3, 6), (75, 5)] (7 :: Integer)
+
+constArr2 :: Predicate
+constArr2 = do i :: SInteger <- sInteger "i"
+               j :: SInteger <- sInteger "j"
+
+               constrain $ i .< j
+               constrain $ i `sElem` [1, 2, 3, 75]
+               pure $ readArray myArray i .== readArray myArray j
+  where myArray = listArray [(1, 12), (2, 5) , (3, 6), (75, 5)] (2 :: Integer)
+
+tests :: TestTree
+tests = testGroup "Arrays" [
+    testGroup "Arrays.InitVals"
+      [ testCase "readDef_SArray"           $ assertIsThm readDef
+      , testCase "readDef2_SArray2"         $ assertIsSat readNoDef
+      , goldenCapturedIO "constArr_SArray"  $ t satWith constArr
+      , goldenCapturedIO "constArr2_SArray" $ t satWith constArr2
+      ]
+  , testGroup "Arrays.Misc"
+      [ goldenCapturedIO "array_misc_1"  $ t proveWith $ \i -> readArray (listArray [(True,1),(False,0)] 3) i .<= (1::SInteger)
+
+      , goldenCapturedIO "array_misc_2"  $ t satWith   $ \(x :: SArray Integer Integer) i1 i2 i3 ->
+                                                                 readArray x i1 .== 4 .&& readArray x i2 .== 5 .&& readArray x i3 .== 12
+
+      , goldenCapturedIO "array_misc_3"  $ t proveWith $      write (empty False) [(True, True), (False, False)]
+                                                          .== write (empty True)  [(True, True), (False, False)]
+
+      , testCase         "array_misc_4"  $                   (write (empty False) [(True, True), (False, False)]
+                                                          .== write (empty True)  [(True, True), (False, False)]) `showsAs` "True"
+
+      -- Interestingly, z3 says UNKNOWN if the logic below isn't set to ALL.
+      , goldenCapturedIO "array_misc_5"  $ t proveWith $ do setLogic Logic_ALL
+                                                            pure (    write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]
+                                                                  .== write (empty 1) [(i, i) | i <- [0 .. (3 :: WordN 2)]]) :: Symbolic SBool
+
+      , testCase         "array_misc_6"  $                   (write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]
+                                                          .== write (empty 1) [(i, i) | i <- [0 .. (3 :: WordN 2)]]) `showsAs` "<symbolic> :: SBool"
+
+      , goldenCapturedIO "array_misc_7"  $ t proveWith $      write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]
+                                                          .== write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]
+
+      , testCase         "array_misc_8"  $                   (write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]
+                                                          .== write (empty 0) [(i, i) | i <- [0 .. (3 :: WordN 2)]]) `showsAs` "True"
+
+      , goldenCapturedIO "array_misc_9"   $ t proveWith $     write (empty 0) [(i, i+1) | i <- [0 .. (3 :: WordN 2)]]
+                                                          .== write (empty 0) [(i, i)   | i <- [0 .. (3 :: WordN 2)]]
+
+      , testCase         "array_misc_10" $                   (write (empty 0) [(i, i+1) | i <- [0 .. (3 :: WordN 2)]]
+                                                          .== write (empty 0) [(i, i  ) | i <- [0 .. (3 :: WordN 2)]]) `showsAs` "False"
+
+      , goldenCapturedIO "array_misc_11" $ t satWith $ \(a :: SArray (Integer, Integer) Integer) -> readArray a (literal (1, 2)) .== 3
+      , goldenCapturedIO "array_misc_12" $ t satWith $ \(a :: SArray Integer (Integer, Integer)) -> readArray a 3 .== literal (1, 2)
+
+      , goldenCapturedIO "array_misc_13" $ t satWith $ \(a :: SArray (Integer, Integer) (Integer, Integer)) -> readArray a (literal (1, 2)) .== literal (1, 2)
+      , goldenCapturedIO "array_misc_14" $ t satWith $ \(a :: SArray Integer Float)   -> fpIsNaN (readArray a 2)
+      , goldenCapturedIO "array_misc_15" $ t satWith $ \(a :: SArray Float   Integer) -> readArray a (0/0) .== 3
+
+      , goldenCapturedIO "array_misc_16" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray Float                Integer) 0)
+      , goldenCapturedIO "array_misc_17" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray Double               Integer) 0)
+      , goldenCapturedIO "array_misc_18" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray (FloatingPoint 10 4) Integer) (0 :: SFloatingPoint 10 4))
+
+      , goldenCapturedIO "array_misc_19" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray Float                Integer) (-0))
+      , goldenCapturedIO "array_misc_20" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray Double               Integer) (-0))
+      , goldenCapturedIO "array_misc_21" $ t satWith (.== readArray (listArray [(0, 12)] 3 :: SArray (FloatingPoint 10 4) Integer) (-(0 :: SFloatingPoint 10 4)))
+
+      , goldenCapturedIO "array_misc_22" $ t satWith (.== readArray (listArray [(0/0, 12)] 3 :: SArray Float                Integer) (0/0))
+      , goldenCapturedIO "array_misc_23" $ t satWith (.== readArray (listArray [(0/0, 12)] 3 :: SArray Double               Integer) (0/0))
+      , goldenCapturedIO "array_misc_24" $ t satWith (.== readArray (listArray [(0/0, 12)] 3 :: SArray (FloatingPoint 10 4) Integer) (0/0))
+
+      , goldenCapturedIO "array_misc_25" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray Float                Integer) (1/0))
+      , goldenCapturedIO "array_misc_26" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray Double               Integer) (1/0))
+      , goldenCapturedIO "array_misc_27" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray (FloatingPoint 10 4) Integer) (1/0))
+
+      , goldenCapturedIO "array_misc_28" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray Float                Integer) (-(1/0)))
+      , goldenCapturedIO "array_misc_29" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray Double               Integer) (-(1/0)))
+      , goldenCapturedIO "array_misc_30" $ t satWith (.== readArray (listArray [(1/0, 12)] 3 :: SArray (FloatingPoint 10 4) Integer) (-(1/0)))
+
+      , goldenCapturedIO "array_misc_31" $ t proveWith (listArray [(1, 2), (3, 4)] 5 .== listArray [(3 :: Integer, 4), (1, 2)] (5 :: Integer))
+      ]
+  ]
+  where t p f goldFile = do r <- p defaultSMTCfg{verbose=True, redirectVerbose = Just goldFile} f
+                            appendFile goldFile ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+        empty :: (SymVal a, SymVal b) => b -> SArray a b
+        empty = listArray []
+
+        write :: (SymVal a, SymVal b) => SArray a b -> [(a, b)] -> SArray a b
+        write = foldr (\(k, v) a -> writeArray a (literal k) (literal v))
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Arrays/Memory.hs b/SBVTestSuite/TestSuite/Arrays/Memory.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Arrays/Memory.hs
@@ -0,0 +1,108 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Arrays.Memory
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Arrays.Memory
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE RankNTypes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Arrays.Memory(tests) where
+
+import Utils.SBVTestFramework
+
+type AddressBase = Word32
+type ValueBase   = Word64
+type Address     = SBV AddressBase
+type Value       = SBV ValueBase
+type Memory      = SArray AddressBase ValueBase
+
+-- | read-after-write: If you write a value and read it back, you'll get it
+raw :: Address -> Value -> Memory -> SBool
+raw a v m = readArray (writeArray m a v) a .== v
+
+-- | if read from a place you didn't write to, the result doesn't change
+rawd :: Address -> Address -> Value -> Memory -> SBool
+rawd a b v m = a ./= b .=> readArray (writeArray m a v) b .== readArray m b
+
+-- | write-after-write: If you write to the same location twice, then the first one is ignored
+waw :: Address -> Value -> Value -> Memory -> Address -> SBool
+waw a v1 v2 m0 i = readArray m2 i .== readArray m3 i
+  where m1 = writeArray m0 a v1
+        m2 = writeArray m1 a v2
+        m3 = writeArray m0 a v2
+
+-- | Two writes to different locations commute, i.e., can be done in any order
+wcommutesGood :: (Address, Value) -> (Address, Value) -> Memory -> Address -> SBool
+wcommutesGood (a, x) (b, y) m i = a ./= b .=> wcommutesBad (a, x) (b, y) m i
+
+-- | Two writes do not commute if they can be done to the same location
+wcommutesBad :: (Address, Value) -> (Address, Value) -> Memory -> Address -> SBool
+wcommutesBad (a, x) (b, y) m i = readArray m0 i .== readArray m1 i
+   where m0 = writeArray (writeArray m a x) b y
+         m1 = writeArray (writeArray m b y) a x
+
+-- | Extensionality
+extensionality :: Memory -> Memory -> Predicate
+extensionality m1 m2 = pure $ quantifiedBool $ \(Exists i) ->
+                          (readArray m1 i ./= readArray m2 i) .|| m1 .== m2
+
+-- | Extensionality, second variant. Expressible for both kinds of arrays.
+extensionality2 :: Memory -> Memory -> Address -> Predicate
+extensionality2 m1 m2 i = pure $ quantifiedBool $ \(Exists j) ->
+                             (readArray m1 j ./= readArray m2 j) .|| readArray m1 i .== readArray m2 i
+
+-- | Merge, using memory equality to check result
+mergeEq :: SBool -> Memory -> Memory -> SBool
+mergeEq b m1 m2 = ite b m1 m2 .== ite (sNot b) m2 m1
+
+-- | Merge, using extensionality to check result
+mergeExt :: SBool -> Memory -> Memory -> Address -> SBool
+mergeExt b m1 m2 i = readArray (ite b m1 m2) i .== readArray (ite (sNot b) m2 m1) i
+
+-- | Merge semantics
+mergeSem :: SBool -> Memory -> Memory -> Address -> SBool
+mergeSem b m1 m2 i = readArray (ite b m1 m2) i .== ite b (readArray m1 i) (readArray m2 i)
+
+-- | Merge semantics 2, but make sure to populate the array so merge does something interesting
+mergeSem2 :: SBool -> Memory -> Memory -> (Address, Value) -> (Address, Value) -> Address -> SBool
+mergeSem2 b m1 m2 (a1, v1) (a2, v2) i = readArray (ite b m1' m2') i .== ite b (readArray m1' i) (readArray m2' i)
+   where m1' = writeArray (writeArray m1 a1 v1) a2 v2
+         m2' = writeArray (writeArray m2 a1 v1) a2 v2
+
+-- | Merge is done correctly:
+mergeSem3 :: SBool -> Memory -> (Address, Value) -> (Address, Value) -> SBool
+mergeSem3 b m (a1, v1) (a2, v2) = readArray (ite b m1 m2) a1 .== ite b (readArray m1 a1) (readArray m2 a1)
+  where m1 = writeArray m a1 v1
+        m2 = writeArray m a2 v2
+
+-- | Another merge check
+mergeSem4 :: SBool -> Memory -> Address -> Address -> SBool
+mergeSem4 b m a1 a2 = readArray m3 a2 .== ite b (readArray m a2) 3
+  where m1 = writeArray m a1 1
+        m2 = writeArray (writeArray m a1 2) a2 3
+        m3 = ite b m1 m2
+
+tests :: TestTree
+tests =
+  testGroup "Arrays.Memory"
+    [ testCase "raw_SArray"              $ assertIsThm   (raw             :: Address -> Value -> Memory -> SBool)
+    , testCase "rawd_SArray"             $ assertIsThm   (rawd            :: Address -> Address -> Value -> Memory -> SBool)
+    , testCase "waw_SArray"              $ assertIsThm   (waw             :: Address -> Value -> Value -> Memory -> Address -> SBool)
+    , testCase "wcommute-good_SArray"    $ assertIsThm   (wcommutesGood   :: (Address, Value) -> (Address, Value) -> Memory -> Address -> SBool)
+    , testCase "wcommute-bad_SArray"     $ assertIsntThm (wcommutesBad    :: (Address, Value) -> (Address, Value) -> Memory -> Address -> SBool)
+    , testCase "ext_SArray"              $ assertIsThm   (extensionality  :: Memory -> Memory -> Predicate)
+    , testCase "ext2_SArray"             $ assertIsThm   (extensionality2 :: Memory -> Memory -> Address -> Predicate)
+    , testCase "mergeEq_SArray"          $ assertIsThm   (mergeEq         :: SBool -> Memory -> Memory -> SBool)
+    , testCase "mergeExt_SArray"         $ assertIsThm   (mergeExt        :: SBool -> Memory -> Memory -> Address -> SBool)
+    , testCase "mergeSem_SArray"         $ assertIsThm   (mergeSem        :: SBool -> Memory -> Memory -> Address -> SBool)
+    , testCase "mergeSem2_SArray"        $ assertIsThm   (mergeSem2       :: SBool -> Memory -> Memory -> (Address, Value) -> (Address, Value) -> Address -> SBool)
+    , testCase "mergeSem3_SArray"        $ assertIsThm   (mergeSem3       :: SBool -> Memory -> (Address, Value) -> (Address, Value) -> SBool)
+    , testCase "mergeSem4_SArray"        $ assertIsntThm (mergeSem4       :: SBool -> Memory -> Address -> Address -> SBool)
+    ]
diff --git a/SBVTestSuite/TestSuite/Arrays/Query.hs b/SBVTestSuite/TestSuite/Arrays/Query.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Arrays/Query.hs
@@ -0,0 +1,221 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Arrays.Query
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for query mode arrays
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Arrays.Query(tests) where
+
+import Data.SBV.Rational
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Arrays.Query"
+    [ goldenCapturedIO "queryArrays1"  $ t q1
+    , goldenCapturedIO "queryArrays2"  $ t q2
+    , goldenCapturedIO "queryArrays3"  $ t q3
+    , goldenCapturedIO "queryArrays4"  $ t q4
+    , goldenCapturedIO "queryArrays5"  $ t q5
+    , goldenCapturedIO "queryArrays6"  $ t q6
+    , goldenCapturedIO "queryArrays7"  $ t q7
+    , goldenCapturedIO "queryArrays8"  $ t q8
+    , goldenCapturedIO "queryArrays9"  $ t q9
+    , goldenCapturedIO "queryArrays10" $ t q10
+    , goldenCapturedIO "queryArrays11" $ t q11
+    , goldenCapturedIO "queryArrays12" $ t q12
+    , goldenCapturedIO "queryArrays13" $ t q13
+    , goldenCapturedIO "queryArrays14" $ t q14
+    , goldenCapturedIO "queryArrays15" $ t q15
+    , goldenCapturedIO "queryArrays16" $ t q16
+    , goldenCapturedIO "queryArrays17" $ t q17
+    ]
+    where t tc goldFile = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just goldFile} tc
+                             appendFile goldFile ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+
+q1 :: Symbolic (Word8, Word8, Int8)
+q1 = do m  :: SArray Word8 Int8 <- sArray "a"
+
+        a1 <- sWord8 "a1"
+        a2 <- sWord8 "a2"
+
+        constrain $ a1 ./= a2
+
+        v1 <- sInt8 "v1"
+
+        query $ do constrain $ v1 .== readArray (writeArray m a1 v1) a1
+                   _ <- checkSat
+                   va1 <- getValue a1
+                   va2 <- getValue a2
+                   vv1 <- getValue v1
+                   return (va1, va2, vv1)
+
+q2 :: Symbolic Word8
+q2 = do i <- sWord8 "i"
+
+        setLogic QF_UFBV
+
+        query $ do constrain $ i .== select (map literal [0 .. 255]) 0 i
+                   _ <- checkSat
+                   getValue i
+
+q3 :: Symbolic Word8
+q3 = do i <- sWord8 "i"
+
+        setLogic QF_UFBV
+
+        query $ do constrain $ i .== select (replicate 256 i) 0 i
+                   _ <- checkSat
+                   getValue i
+
+q4 :: Symbolic (Word8, Word8)
+q4 = do i <- sWord8 "i"
+        j <- sWord8 "j"
+
+        setLogic QF_UFBV
+
+        query $ do constrain $ i .== select (map literal [0 .. 255]) 0 i
+                   _ <- checkSat
+                   iv <- getValue i
+                   constrain $ j .== select (map literal [0 .. 255]) 0 j
+                   constrain $ i .== literal iv
+                   constrain $ j .== i+1
+                   _ <- checkSat
+                   jv <- getValue j
+                   return (iv, jv)
+
+q5 :: Symbolic (Maybe (Word8, Int8))
+q5 = do m  :: SArray Word8 Int8 <- sArray "a"
+
+        a <- sWord8 "a"
+        v <- sInt8  "v"
+
+        query $ do let m2    = writeArray (writeArray m a v) (a+1) (v+1)
+                       vRead = readArray  m2 (a+1)
+
+                   constrain $ v + 1 ./= vRead
+
+                   cs <- checkSat
+
+                   case cs of
+                     Unsat  -> return Nothing
+                     Unk    -> error "solver returned Unknown!"
+                     DSat{} -> error "solver returned Delta-satisfiable!"
+                     Sat    -> do av <- getValue a
+                                  vv <- getValue v
+                                  return $ Just (av, vv)
+
+q6 :: Symbolic [Integer]
+q6 = do (a :: SArray Integer Integer) <- sArray "a"
+
+        query $ loop (writeArray a 1 1) []
+
+  where loop a sofar = do push 1
+                          constrain $ readArray a 1 .== 5
+                          cs <- checkSat
+                          case cs of
+                            Unk    -> error "Unknown"
+                            Unsat  -> do pop 1
+                                         d <- freshVar $ "d" ++ show (length sofar)
+                                         constrain $ d .>= 1 .&& d .< 3
+                                         loop (writeArray a 1 (readArray a 1 + d)) (sofar ++ [d])
+                            DSat{} -> error "solver returned Delta-satisfiable!"
+                            Sat    -> mapM getValue sofar
+
+
+q7 :: Symbolic (CheckSatResult, CheckSatResult)
+q7 = do x :: SArray Integer Integer <- sArray "x"
+        let y = writeArray x 0 1
+
+        query $ do constrain $ readArray y 0 .== 2
+                   r1 <- checkSat
+
+                   resetAssertions
+
+                   constrain $ readArray y 0 .== 2
+                   r2 <- checkSat
+
+                   pure (r1, r2)
+
+q8 :: Symbolic (CheckSatResult, CheckSatResult)
+q8 = query $ do x :: SArray Integer Integer <- freshVar "x"
+                let y = writeArray x 0 1
+
+                constrain $ readArray y 0 .== 2
+                r1 <- checkSat
+
+                resetAssertions
+
+                constrain $ readArray y 0 .== 2
+                r2 <- checkSat
+
+                pure (r1, r2)
+
+q9 :: Symbolic CheckSatResult
+q9 = do x :: SArray Char Integer <- sArray "x"
+
+        query $ do constrain $ readArray x (literal 'a') .== 5
+                   checkSat
+
+q10 :: Symbolic CheckSatResult
+q10 = do x :: SArray Integer Char <- sArray "x"
+
+         query $ do constrain $ readArray x 5 .== literal 'a'
+                    checkSat
+
+q11 :: Symbolic CheckSatResult
+q11 = do x :: SArray Char Char    <- sArray "x"
+
+         query $ do constrain $ readArray x (literal 'a') .== literal 'b'
+                    checkSat
+
+q12 :: Symbolic CheckSatResult
+q12 = do x :: SArray Rational Integer <- sArray "x"
+
+         query $ do constrain $ readArray x (5 .% 3) .== 5
+                    checkSat
+
+q13 :: Symbolic CheckSatResult
+q13 = do x :: SArray Integer Rational <- sArray "x"
+
+         query $ do constrain $ readArray x 5 .== 5 .% 3
+                    checkSat
+
+q14 :: Symbolic CheckSatResult
+q14 = do x :: SArray Rational Rational    <- sArray "x"
+
+         query $ do constrain $ readArray x (5 .% 3) .== 9 .% 8
+                    checkSat
+
+q15 :: Symbolic CheckSatResult
+q15 = do x :: SArray Rational Char <- sArray "x"
+
+         query $ do constrain $ readArray x (5 .% 3) .== literal 'z'
+                    checkSat
+
+q16 :: Symbolic CheckSatResult
+q16 = do x :: SArray Char Rational <- sArray "x"
+
+         query $ do constrain $ readArray x (literal 'z') .== 5 .% 3
+                    checkSat
+
+q17 :: Symbolic CheckSatResult
+q17 = do x :: SArray (Char, Rational) (Rational, Char) <- sArray "x"
+
+         query $ do constrain $ readArray x (literal ('z', 5 % 3)) .== literal (5 % 3, 'z')
+                    checkSat
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/AllSat.hs b/SBVTestSuite/TestSuite/Basics/AllSat.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/AllSat.hs
@@ -0,0 +1,76 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.AllSat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for basic allsat calls
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.AllSat(tests) where
+
+import Utils.SBVTestFramework
+
+import Control.Monad(void)
+import Data.List (sortOn)
+
+import qualified Control.Exception as C
+
+data Q
+mkSymbolic [''Q]
+
+tests :: TestTree
+tests =
+  testGroup "Basics.AllSat"
+    [ goldenVsStringShow "allSat1" t1
+    , goldenVsStringShow "allSat2" t2
+    , goldenVsStringShow "allSat3" $            allSat $ \x -> x .== (0::SFloat)
+    , goldenVsStringShow "allSat4" $            allSat $ \x -> x .<  (0::SWord8)
+    , goldenVsStringShow "allSat5" $ fmap srt $ allSat $ \x y -> x .< y .&& y .< (4::SWord8)
+    , goldenVsStringShow "allSat6" $            allSat t3
+    , goldenCapturedIO   "allSat7" $ \rf -> void (allSatWith z3{verbose=True, redirectVerbose=Just rf} t4)
+    , goldenCapturedIO   "allSat8" $ \rf -> void (allSatWith z3{verbose=True, redirectVerbose=Just rf} t5)
+                                            `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\nEXCEPTION CAUGHT:\n" ++ show e ++ "\n"))
+    ]
+
+srt :: AllSatResult -> AllSatResult
+srt r@AllSatResult{allSatResults = ms} = r { allSatResults = sortOn (show . SatResult) ms }
+
+t1 :: IO AllSatResult
+t1 = allSat $ do x <- free "x"
+                 y <- free "y"
+                 return $ x .== (y :: SQ)
+
+t2 :: IO AllSatResult
+t2 = allSat $ do x <- free "x"
+                 y <- free "y"
+                 z <- free "z"
+                 return $ x .== (y :: SQ) .&& z .== (z :: SQ)
+
+t3 :: ConstraintSet
+t3 = do x <- free "x"
+        y <- free "y"
+        constrain $ \(Forall z) -> x .< (y::SWord8) .&& y .< 3 .&& z .== (z::SWord8)
+
+t4 :: ConstraintSet
+t4 = do x <- sInteger "x"
+        y <- sInteger "y"
+        z <- sInteger "z"
+
+        let range = (1, 15)
+
+        constrain $ x `inRange` range
+        constrain $ y `inRange` range
+        constrain $ z `inRange` range
+
+        constrain $ distinct [x, y, z]
+
+t5 :: ConstraintSet
+t5 = constrain $ \(Forall x) -> uninterpret "f" x .== x+(1::SInteger)
diff --git a/SBVTestSuite/TestSuite/Basics/ArbFloats.hs b/SBVTestSuite/TestSuite/Basics/ArbFloats.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ArbFloats.hs
@@ -0,0 +1,40 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ArbFloats
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Basic arbitrary float checks
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.ArbFloats(tests) where
+
+import Utils.SBVTestFramework
+
+-- # of inhabitants is 2^sb(2^eb - 1) + 3
+count :: Integer -> Integer -> Integer
+count eb sb = 2^sb * (2^eb - 1) + 3
+
+tests :: TestTree
+tests = testGroup "Basics.ArbFloats"
+  [ testCase "FP_2_2" (assert $ (== fromIntegral (count 2 2)) <$> numberOfModels (const sTrue :: SFloatingPoint 2 2 -> SBool))
+  , testCase "FP_2_3" (assert $ (== fromIntegral (count 2 3)) <$> numberOfModels (const sTrue :: SFloatingPoint 2 3 -> SBool))
+  , testCase "FP_2_4" (assert $ (== fromIntegral (count 2 4)) <$> numberOfModels (const sTrue :: SFloatingPoint 2 4 -> SBool))
+
+  , testCase "FP_3_2" (assert $ (== fromIntegral (count 3 2)) <$> numberOfModels (const sTrue :: SFloatingPoint 3 2 -> SBool))
+  , testCase "FP_3_3" (assert $ (== fromIntegral (count 3 3)) <$> numberOfModels (const sTrue :: SFloatingPoint 3 3 -> SBool))
+  , testCase "FP_3_4" (assert $ (== fromIntegral (count 3 4)) <$> numberOfModels (const sTrue :: SFloatingPoint 3 4 -> SBool))
+
+  , testCase "FP_4_2" (assert $ (== fromIntegral (count 4 2)) <$> numberOfModels (const sTrue :: SFloatingPoint 4 2 -> SBool))
+  , testCase "FP_4_3" (assert $ (== fromIntegral (count 4 3)) <$> numberOfModels (const sTrue :: SFloatingPoint 4 3 -> SBool))
+  , testCase "FP_4_4" (assert $ (== fromIntegral (count 4 4)) <$> numberOfModels (const sTrue :: SFloatingPoint 4 4 -> SBool))
+
+  , goldenVsStringShow "arbFp_opt_1" (optimize Lexicographic $ \x -> do {constrain (fpIsPoint x);  maximize "x" (x::SFPHalf)})
+  ]
diff --git a/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
@@ -0,0 +1,466 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ArithNoSolver
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for basic concrete arithmetic, i.e., testing all
+-- the constant folding based arithmetic implementation in SBV
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE RankNTypes    #-}
+{-# LANGUAGE TupleSections #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
+
+module TestSuite.Basics.ArithNoSolver(tests) where
+
+import Data.SBV.Internals
+import Utils.SBVTestFramework
+
+import Data.Maybe (fromJust, fromMaybe)
+
+import qualified Data.Char as C
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Arith.NoSolver" $
+           genReals
+        ++ genFloats
+        ++ genQRems
+        ++ genBinTest            "+"             (+)
+        ++ genBinTest            "-"             (-)
+        ++ genBinTest            "*"             (*)
+        ++ genUnTest             "negate"        negate
+        ++ genUnTest             "abs"           abs
+        ++ genUnTest             "signum"        signum
+        ++ genBitTest            ".&."           (.&.)
+        ++ genBitTest            ".|."           (.|.)
+        ++ genBoolTest           "<"             (<)  (.<)
+        ++ genBoolTest           "<="            (<=) (.<=)
+        ++ genBoolTest           ">"             (>)  (.>)
+        ++ genBoolTest           ">="            (>=) (.>=)
+        ++ genBoolTest           "=="            (==) (.==)
+        ++ genBoolTest           "/="            (/=) (./=)
+        ++ genBitTest            "xor"           xor
+        ++ genUnTestBit          "complement"    complement
+
+genBinTest :: String -> (forall a. Num a => a -> a -> a) -> [TestTree]
+genBinTest nm op = map mkTest $
+        zipWith pair [(show x, show y, literal (x `op` y)) | x <- w8s,  y <- w8s ] [x `op` y | x <- sw8s,  y <- sw8s ]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w16s, y <- w16s] [x `op` y | x <- sw16s, y <- sw16s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w32s, y <- w32s] [x `op` y | x <- sw32s, y <- sw32s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w64s, y <- w64s] [x `op` y | x <- sw64s, y <- sw64s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i8s,  y <- i8s ] [x `op` y | x <- si8s,  y <- si8s ]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i16s, y <- i16s] [x `op` y | x <- si16s, y <- si16s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i32s, y <- i32s] [x `op` y | x <- si32s, y <- si32s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i64s, y <- i64s] [x `op` y | x <- si64s, y <- si64s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- iUBs, y <- iUBs] [x `op` y | x <- siUBs, y <- siUBs]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- rs,   y <- rs]   [x `op` y | x <- srs,   y <- srs]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- ras,  y <- ras]  [x `op` y | x <- sras,  y <- sras]
+  where pair (x, y, a) b = (x, y, a == b)
+        mkTest (x, y, s) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
+
+genBitTest :: String -> (forall a. (Num a, Bits a) => a -> a -> a) -> [TestTree]
+genBitTest nm op = map mkTest $
+        zipWith pair [(show x, show y, literal (x `op` y)) | x <- w8s,  y <- w8s ] [x `op` y | x <- sw8s,  y <- sw8s ]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w16s, y <- w16s] [x `op` y | x <- sw16s, y <- sw16s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w32s, y <- w32s] [x `op` y | x <- sw32s, y <- sw32s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- w64s, y <- w64s] [x `op` y | x <- sw64s, y <- sw64s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i8s,  y <- i8s ] [x `op` y | x <- si8s,  y <- si8s ]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i16s, y <- i16s] [x `op` y | x <- si16s, y <- si16s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i32s, y <- i32s] [x `op` y | x <- si32s, y <- si32s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- i64s, y <- i64s] [x `op` y | x <- si64s, y <- si64s]
+     ++ zipWith pair [(show x, show y, literal (x `op` y)) | x <- iUBs, y <- iUBs] [x `op` y | x <- siUBs, y <- siUBs]
+  where pair (x, y, a) b = (x, y, a == b)
+        mkTest (x, y, s) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
+
+genBoolTest :: String -> (forall a. Ord a => a -> a -> Bool) -> (forall a. OrdSymbolic a => a -> a -> SBool) -> [TestTree]
+genBoolTest nm op opS = map mkTest $
+        zipWith pair [(show x, show y, x     `op` y)     | x <- w8s,  y <- w8s ] [x `opS` y | x <- sw8s,  y <- sw8s ]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- w16s, y <- w16s] [x `opS` y | x <- sw16s, y <- sw16s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- w32s, y <- w32s] [x `opS` y | x <- sw32s, y <- sw32s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- w64s, y <- w64s] [x `opS` y | x <- sw64s, y <- sw64s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- i8s,  y <- i8s ] [x `opS` y | x <- si8s,  y <- si8s ]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- i16s, y <- i16s] [x `opS` y | x <- si16s, y <- si16s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- i32s, y <- i32s] [x `opS` y | x <- si32s, y <- si32s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- i64s, y <- i64s] [x `opS` y | x <- si64s, y <- si64s]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- iUBs, y <- iUBs] [x `opS` y | x <- siUBs, y <- siUBs]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- iCs,  y <- iCs ] [x `opS` y | x <- siCs,  y <- siCs ]
+     ++ zipWith pair [(show x, show y, x     `op` y)     | x <- ss,   y <- ss  ] [x `opS` y | x <- sss,   y <- sss  ]
+     ++ zipWith pair [(show x, show y, toL x `op` toL y) | x <- ssl,  y <- ssl ] [x `opS` y | x <- ssl,   y <- ssl  ]
+     ++ zipWith pair [(show x, show y, toL x `op` toL y) | x <- ssm,  y <- ssm ] [x `opS` y | x <- ssm,   y <- ssm  ]
+     ++ zipWith pair [(show x, show y, toL x `op` toL y) | x <- sse,  y <- sse ] [x `opS` y | x <- sse,   y <- sse  ]
+     ++ zipWith pair [(show x, show y, toL x `op` toL y) | x <- sst,  y <- sst ] [x `opS` y | x <- sst,   y <- sst  ]
+     ++ zipWith pair [(show x, show y, toL x `op` toL y) | x <- sras, y <- sras] [x `opS` y | x <- sras,  y <- sras ]
+  where pair (x, y, a) b = (x, y, Just a == unliteral b)
+        mkTest (x, y, s) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
+        toL x = fromMaybe (error "genBoolTest: Cannot extract a literal!") (unliteral x)
+
+genUnTest :: String -> (forall a. Num a => a -> a) -> [TestTree]
+genUnTest nm op = map mkTest $
+        zipWith pair [(show x, literal (op x)) | x <- w8s ] [op x | x <- sw8s ]
+     ++ zipWith pair [(show x, literal (op x)) | x <- w16s] [op x | x <- sw16s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- w32s] [op x | x <- sw32s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- w64s] [op x | x <- sw64s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- i8s ] [op x | x <- si8s ]
+     ++ zipWith pair [(show x, literal (op x)) | x <- i16s] [op x | x <- si16s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- i32s] [op x | x <- si32s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- i64s] [op x | x <- si64s]
+     ++ zipWith pair [(show x, literal (op x)) | x <- iUBs] [op x | x <- siUBs]
+     ++ zipWith pair [(show x, literal (op x)) | x <- ras]  [op x | x <- sras]
+  where pair (x, a) b = (x, a == b)
+        mkTest (x, s) = testCase ("arithCF-" ++ nm ++ "." ++ x) (s `showsAs` "True")
+
+genUnTestBit :: String -> (forall a. (Num a, Bits a) => a -> a) -> [TestTree]
+genUnTestBit nm op = map mkTest $
+        zipWith pair [(show x, op x) | x <- w8s ] [op x | x <- sw8s ]
+     ++ zipWith pair [(show x, op x) | x <- w16s] [op x | x <- sw16s]
+     ++ zipWith pair [(show x, op x) | x <- w32s] [op x | x <- sw32s]
+     ++ zipWith pair [(show x, op x) | x <- w64s] [op x | x <- sw64s]
+     ++ zipWith pair [(show x, op x) | x <- i8s ] [op x | x <- si8s ]
+     ++ zipWith pair [(show x, op x) | x <- i16s] [op x | x <- si16s]
+     ++ zipWith pair [(show x, op x) | x <- i32s] [op x | x <- si32s]
+     ++ zipWith pair [(show x, op x) | x <- i64s] [op x | x <- si64s]
+     ++ zipWith pair [(show x, op x) | x <- iUBs] [op x | x <- siUBs]
+  where pair (x, a) b = (x, show (fromIntegral a `asTypeOf` b) == show b)
+        mkTest (x, s) = testCase ("arithCF-" ++ nm ++ "." ++ x) (s `showsAs` "True")
+
+genQRems :: [TestTree]
+genQRems = map mkTest $
+        zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w8s,  y <- w8s ] [x `sDivMod`  y | x <- sw8s,  y <- sw8s ]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w16s, y <- w16s] [x `sDivMod`  y | x <- sw16s, y <- sw16s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w32s, y <- w32s] [x `sDivMod`  y | x <- sw32s, y <- sw32s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w64s, y <- w64s] [x `sDivMod`  y | x <- sw64s, y <- sw64s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i8s,  y <- i8s ] [x `sDivMod`  y | x <- si8s,  y <- si8s ]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i16s, y <- i16s] [x `sDivMod`  y | x <- si16s, y <- si16s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i32s, y <- i32s] [x `sDivMod`  y | x <- si32s, y <- si32s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i64s, y <- i64s] [x `sDivMod`  y | x <- si64s, y <- si64s]
+     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- iUBs, y <- iUBs] [x `sDivMod`  y | x <- siUBs, y <- siUBs]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w8s,  y <- w8s ] [x `sQuotRem` y | x <- sw8s,  y <- sw8s ]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w16s, y <- w16s] [x `sQuotRem` y | x <- sw16s, y <- sw16s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w32s, y <- w32s] [x `sQuotRem` y | x <- sw32s, y <- sw32s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w64s, y <- w64s] [x `sQuotRem` y | x <- sw64s, y <- sw64s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i8s,  y <- i8s ] [x `sQuotRem` y | x <- si8s,  y <- si8s ]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i16s, y <- i16s] [x `sQuotRem` y | x <- si16s, y <- si16s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i32s, y <- i32s] [x `sQuotRem` y | x <- si32s, y <- si32s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i64s, y <- i64s] [x `sQuotRem` y | x <- si64s, y <- si64s]
+     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- iUBs, y <- iUBs] [x `sQuotRem` y | x <- siUBs, y <- siUBs]
+  where pair (nm, x, y, (r1, r2)) (e1, e2)   = (nm, x, y, show (fromIntegral r1 `asTypeOf` e1, fromIntegral r2 `asTypeOf` e2) == show (e1, e2))
+        mkTest (nm, x, y, s) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
+        -- Haskell's divMod and quotRem differs from SBV's in two ways:
+        --     - when y is 0, Haskell throws an exception, SBV sets the result to 0; like in division
+        --     - Haskell overflows if x == minBound and y == -1 for bounded signed types; but SBV returns minBound, 0; which is more meaningful
+        overflow x y = x == minBound && y == -1
+        divMod0  x y = if y == 0       then (0, x) else x `divMod`   y
+        divMod1  x y = if overflow x y then (x, 0) else x `divMod0`  y
+        quotRem0 x y = if y == 0       then (0, x) else x `quotRem`  y
+        quotRem1 x y = if overflow x y then (x, 0) else x `quotRem0` y
+
+genReals :: [TestTree]
+genReals = map mkTest $
+        map ("+",)  (zipWith pair [(show x, show y, x +  y) | x <- rs, y <- rs        ] [x +   y | x <- srs,  y <- srs                       ])
+     ++ map ("-",)  (zipWith pair [(show x, show y, x -  y) | x <- rs, y <- rs        ] [x -   y | x <- srs,  y <- srs                       ])
+     ++ map ("*",)  (zipWith pair [(show x, show y, x *  y) | x <- rs, y <- rs        ] [x *   y | x <- srs,  y <- srs                       ])
+     ++ map ("<",)  (zipWith pair [(show x, show y, x <  y) | x <- rs, y <- rs        ] [x .<  y | x <- srs,  y <- srs                       ])
+     ++ map ("<=",) (zipWith pair [(show x, show y, x <= y) | x <- rs, y <- rs        ] [x .<= y | x <- srs,  y <- srs                       ])
+     ++ map (">",)  (zipWith pair [(show x, show y, x >  y) | x <- rs, y <- rs        ] [x .>  y | x <- srs,  y <- srs                       ])
+     ++ map (">=",) (zipWith pair [(show x, show y, x >= y) | x <- rs, y <- rs        ] [x .>= y | x <- srs,  y <- srs                       ])
+     ++ map ("==",) (zipWith pair [(show x, show y, x == y) | x <- rs, y <- rs        ] [x .== y | x <- srs,  y <- srs                       ])
+     ++ map ("/=",) (zipWith pair [(show x, show y, x /= y) | x <- rs, y <- rs        ] [x ./= y | x <- srs,  y <- srs                       ])
+     ++ map ("/",)  (zipWith pair [(show x, show y, x /  y) | x <- rs, y <- rs, y /= 0] [x / y   | x <- srs,  y <- srs, unliteral y /= Just 0])
+  where pair (x, y, a) b   = (x, y, Just a == unliteral b)
+        mkTest (nm, (x, y, s)) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
+
+genFloats :: [TestTree]
+genFloats = bTests ++ uTests ++ fpTests1 ++ fpTests2 ++ converts
+  where bTests = map mkTest2 $  floatRun2  "+"  (+)  (+)   comb
+                             ++ doubleRun2 "+"  (+)  (+)   comb
+
+                             ++ floatRun2  "-"  (-)  (-)   comb
+                             ++ doubleRun2 "-"  (-)  (-)   comb
+
+                             ++ floatRun2  "*"  (*)  (*)   comb
+                             ++ doubleRun2 "*"  (*)  (*)   comb
+
+                             ++ floatRun2  "/"  (/)  (/)   comb
+                             ++ doubleRun2 "/"  (/)  (/)   comb
+
+                             ++ floatRun2  "<"  (<)  (.<)  combB
+                             ++ doubleRun2 "<"  (<)  (.<)  combB
+
+                             ++ floatRun2  "<=" (<=) (.<=) combB
+                             ++ doubleRun2 "<=" (<=) (.<=) combB
+
+                             ++ floatRun2  ">"  (>)  (.>)  combB
+                             ++ doubleRun2 ">"  (>)  (.>)  combB
+
+                             ++ floatRun2  ">=" (>=) (.>=) combB
+                             ++ doubleRun2 ">=" (>=) (.>=) combB
+
+                             ++ floatRun2  "==" (==) (.==) combB
+                             ++ doubleRun2 "==" (==) (.==) combB
+
+                             ++ floatRun2  "/=" (/=) (./=) combN
+                             ++ doubleRun2 "/=" (/=) (./=) combN
+
+        fpTests1 = map mkTest1 $  floatRun1   "abs"               abs                abs               comb1
+                               ++ floatRun1   "fpAbs"             abs                fpAbs             comb1
+                               ++ doubleRun1  "abs"               abs                abs               comb1
+                               ++ doubleRun1  "fpAbs"             abs                fpAbs             comb1
+
+                               ++ floatRun1   "negate"            negate             negate            comb1
+                               ++ floatRun1   "fpNeg"             negate             fpNeg             comb1
+                               ++ doubleRun1  "negate"            negate             negate            comb1
+                               ++ doubleRun1  "fpNeg"             negate             fpNeg             comb1
+
+                               ++ floatRun1M  "fpSqrt"            sqrt               fpSqrt            comb1
+                               ++ doubleRun1M "fpSqrt"            sqrt               fpSqrt            comb1
+
+                               ++ floatRun1M  "fpRoundToIntegral" fpRoundToIntegralH fpRoundToIntegral comb1
+                               ++ doubleRun1M "fpRoundToIntegral" fpRoundToIntegralH fpRoundToIntegral comb1
+
+                               ++ floatRun1   "signum"            signum             signum            comb1
+                               ++ doubleRun1  "signum"            signum             signum            comb1
+
+        -- TODO. Can't possibly test fma, unless we FFI out to C. Leave it out for the time being
+        fpTests2 = map mkTest2 $  floatRun2M  "fpAdd"           (+)              fpAdd           comb
+                               ++ doubleRun2M "fpAdd"           (+)              fpAdd           comb
+
+                               ++ floatRun2M  "fpSub"           (-)              fpSub           comb
+                               ++ doubleRun2M "fpSub"           (-)              fpSub           comb
+
+                               ++ floatRun2M  "fpMul"           (*)              fpMul           comb
+                               ++ doubleRun2M "fpMul"           (*)              fpMul           comb
+
+                               ++ floatRun2M  "fpDiv"           (/)              fpDiv           comb
+                               ++ doubleRun2M "fpDiv"           (/)              fpDiv           comb
+
+                               ++ floatRunMM  "fpMin"           fpMinH           fpMin           comb
+                               ++ doubleRunMM "fpMin"           fpMinH           fpMin           comb
+
+                               ++ floatRunMM  "fpMax"           fpMaxH           fpMax           comb
+                               ++ doubleRunMM "fpMax"           fpMaxH           fpMax           comb
+
+                               ++ floatRun2   "fpRem"           fpRemH           fpRem           comb
+                               ++ doubleRun2  "fpRem"           fpRemH           fpRem           comb
+
+                               ++ floatRun2   "fpIsEqualObject" fpIsEqualObjectH fpIsEqualObject combE
+                               ++ doubleRun2  "fpIsEqualObject" fpIsEqualObjectH fpIsEqualObject combE
+
+        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  ]
+
+                 ++  [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  ]
+
+                 -- NB. We don't constant fold float/double conversions, so we skip these
+                 --
+                 ++  [cvtTest  ("reinterp_Word32_Float",  show x, sWord32AsSFloat  (literal x), literal (wordToFloat  x)) | x <- w32s]
+                 ++  [cvtTest  ("reinterp_Word64_Double", show x, sWord64AsSDouble (literal x), literal (wordToDouble x)) | x <- w64s]
+
+                 ++  [cvtTestI ("reinterp_Float_Word32",  show x, sFloatAsSWord32  (literal x), floatToWord x)  | x <- fs, not (isNaN x)] -- Not unique for NaN
+                 ++  [cvtTestI ("reinterp_Double_Word64", show x, sDoubleAsSWord64 (literal x), doubleToWord x) | x <- ds, not (isNaN x)] -- Not unique for NaN
+
+        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
+                             ++ concatMap (checkPred ds sds) predicates
+        extract :: SymVal a => SBV a -> a
+        extract = fromJust . unliteral
+
+        comb  (x, y, a, b) = (show x, show y, same a b)
+        combB (x, y, a, b) = (show x, show y, checkNaN f x y a b) where f v w = not (v || w)  -- All comparisons except /=: Both should be False if we have a NaN argument
+        combN (x, y, a, b) = (show x, show y, checkNaN f x y a b) where f v w =      v && w   -- /=: Both should be True
+        combE (x, y, a, b) = (show x, show y, a == b)
+        comb1 (x, a, b)    = (show x, same a b)
+        same a b = (isNaN a && isNaN b) || (a == b)
+        checkNaN f x y a b
+          | isNaN x || isNaN y = f a b
+          | True               = a == b
+
+        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")
+
+        checkPred :: Show a => [a] -> [SBV a] -> (String, SBV a -> SBool, a -> Bool) -> [(String, (String, Bool))]
+        checkPred xs sxs (n, ps, p) = zipWith (chk n) (map (\x -> (x, p x)) xs) (map ps sxs)
+          where chk nm (x, v) sv = (nm, (show x, Just v == unliteral sv))
+
+        predicates :: IEEEFloating a => [(String, SBV a -> SBool, a -> Bool)]
+        predicates = [ ("fpIsNormal",       fpIsNormal,        fpIsNormalizedH)
+                     , ("fpIsSubnormal",    fpIsSubnormal,     isDenormalized)
+                     , ("fpIsZero",         fpIsZero,          (== 0))
+                     , ("fpIsInfinite",     fpIsInfinite,      isInfinite)
+                     , ("fpIsNaN",          fpIsNaN,           isNaN)
+                     , ("fpIsNegative",     fpIsNegative,      \x -> x < 0  ||      isNegativeZero x)
+                     , ("fpIsPositive",     fpIsPositive,      \x -> x >= 0 && not (isNegativeZero x))
+                     , ("fpIsNegativeZero", fpIsNegativeZero,  isNegativeZero)
+                     , ("fpIsPositiveZero", fpIsPositiveZero,  \x -> x == 0 && not (isNegativeZero x))
+                     , ("fpIsPoint",        fpIsPoint,         \x -> not (isNaN x || isInfinite x))
+                     ]
+
+-- Concrete test data
+xsUnsigned :: (Num a, Bounded a) => [a]
+xsUnsigned = take 5 (iterate (1+) minBound) ++ take 5 (iterate (\x -> x-1) maxBound)
+
+xsSigned :: (Num a, Enum a, Bounded a) => [a]
+xsSigned   = xsUnsigned ++ [-5 .. 5]
+
+w8s :: [Word8]
+w8s = xsUnsigned
+
+sw8s :: [SWord8]
+sw8s = map literal xsUnsigned
+
+w16s :: [Word16]
+w16s = xsUnsigned
+
+sw16s :: [SWord16]
+sw16s = map literal xsUnsigned
+
+w32s :: [Word32]
+w32s = xsUnsigned
+
+sw32s :: [SWord32]
+sw32s = map literal xsUnsigned
+
+w64s :: [Word64]
+w64s = xsUnsigned
+
+sw64s :: [SWord64]
+sw64s = map literal xsUnsigned
+
+i8s :: [Int8]
+i8s = xsSigned
+
+si8s :: [SInt8]
+si8s = map literal xsSigned
+
+i16s :: [Int16]
+i16s = xsSigned
+
+si16s :: [SInt16]
+si16s = map literal xsSigned
+
+i32s :: [Int32]
+i32s = xsSigned
+
+si32s :: [SInt32]
+si32s = map literal xsSigned
+
+i64s :: [Int64]
+i64s = xsSigned
+
+si64s :: [SInt64]
+si64s = map literal xsSigned
+
+iUBs :: [Integer]
+iUBs = [-1000000 .. -999995] ++ [-5 .. 5] ++ [999995 ..  1000000]
+
+siUBs :: [SInteger]
+siUBs = map literal iUBs
+
+ras :: [Rational]
+ras = [i % d | i <- nums, d <- dens]
+ where nums = [-1000000 .. -999998] ++ [-2 .. 2] ++ [999998 ..  1000001]
+       dens = [2 .. 5] ++ [98 .. 102] ++ [999998 .. 1000000]
+
+sras :: [SRational]
+sras = map literal ras
+
+rs :: [AlgReal]
+rs = map fromRational ras
+
+srs :: [SReal]
+srs = map literal rs
+
+fs :: [Float]
+fs = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
+ where xs = [nan, infinity, 0, 0.5, 0.68302244, 0.5268265, 0.10283524, 5.8336496e-2, 1.0e-45]
+
+sfs :: [SFloat]
+sfs = map literal fs
+
+ds :: [Double]
+ds = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
+ where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 7.518897767550192e-2, 1.1656043286207285e-2, 5.0e-324]
+
+sds :: [SDouble]
+sds = map literal ds
+
+-- For pair character ops, just take a subset
+iCs :: [Char]
+iCs = map C.chr $ [0..5] ++ [98..102] ++ [250..255]
+
+siCs :: [SChar]
+siCs = map literal iCs
+
+-- Ditto for strings, just a few things
+ss :: [String]
+ss = ["", "palTRY", "teSTing", "SBV", "sTRIngs", "123", "surely", "thIS", "hI", "ly", "0"]
+
+sss :: [SString]
+sss = map literal ss
+
+-- Lists are the worst in coverage!
+sl :: [[Integer]]
+sl = [[], [0], [-1, 1], [-10, 0, 10], [3, 4, 5, 4, 5, 3]]
+
+-- Lists are the worst in coverage!
+ssl :: [SList Integer]
+ssl = map literal sl
+
+-- Very rudimentary maybe, either, and, tuples
+sm :: [Maybe Integer]
+sm = [Nothing, Just (-5), Just 0, Just 5]
+
+ssm :: [SMaybe Integer]
+ssm = map literal sm
+
+se :: [Either Integer Integer]
+se = [Left 3, Right 5]
+
+sse :: [SEither Integer Integer]
+sse = map literal se
+
+st :: [(Integer, Integer)]
+st = [(1, 2), (-1, -5), (0, 9), (5, 5)]
+
+sst :: [STuple Integer Integer]
+sst = map literal st
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs b/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ArithNoSolver2.hs
@@ -0,0 +1,536 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ArithNoSolver2
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Spill over from ArithNoSolver. To aid faster GHC compilation.
+-- the constant folding based arithmetic implementation in SBV
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RankNTypes        #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+{-# LANGUAGE QuasiQuotes       #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
+
+module TestSuite.Basics.ArithNoSolver2(tests) where
+
+import Data.SBV.Internals
+import Utils.SBVTestFramework
+
+import Data.Maybe (isJust)
+
+import Data.List (genericIndex, isInfixOf, isPrefixOf, isSuffixOf, genericTake, genericDrop, genericLength)
+
+import qualified Data.Char       as C
+import qualified Data.SBV.Char   as SC
+import qualified Data.SBV.List   as SL
+
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Show, Eq, Enum, Bounded)
+mkSymbolic  [''Day]
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Arith.NoSolver2" $
+           genIntTest      False "setBit"        setBit
+        ++ genIntTest      False "clearBit"      clearBit
+        ++ genIntTest      False "complementBit" complementBit
+        ++ genIntTest      True  "shift"         shift
+        ++ genIntTest      True  "shiftL"        shiftL
+        ++ genIntTest      True  "shiftR"        shiftR
+        ++ genIntTest      True  "rotate"        rotate
+        ++ genIntTest      True  "rotateL"       rotateL
+        ++ genIntTest      True  "rotateR"       rotateR
+        ++ genShiftRotTest       "shiftL_gen"    sShiftLeft
+        ++ genShiftRotTest       "shiftR_gen"    sShiftRight
+        ++ genShiftRotTest       "rotateL_gen"   sRotateLeft
+        ++ genShiftRotTest       "rotateR_gen"   sRotateRight
+        ++ genShiftMixSize
+        ++ genBlasts
+        ++ genCounts
+        ++ genIntCasts
+        ++ genChars
+        ++ genStrings
+        ++ genLists
+        ++ genEnums
+
+genIntTest :: Bool -> String -> (forall a. (Num a, Bits a) => (a -> Int -> a)) -> [TestTree]
+genIntTest overSized nm op = map mkTest $
+        zipWith pair [("u8",  show x, show y, x `op` y) | x <- w8s,  y <- is (intSizeOf x)] [x `op` y | x <- sw8s,  y <- is (intSizeOf x)]
+     ++ zipWith pair [("u16", show x, show y, x `op` y) | x <- w16s, y <- is (intSizeOf x)] [x `op` y | x <- sw16s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("u32", show x, show y, x `op` y) | x <- w32s, y <- is (intSizeOf x)] [x `op` y | x <- sw32s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("u64", show x, show y, x `op` y) | x <- w64s, y <- is (intSizeOf x)] [x `op` y | x <- sw64s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s8",  show x, show y, x `op` y) | x <- i8s,  y <- is (intSizeOf x)] [x `op` y | x <- si8s,  y <- is (intSizeOf x)]
+     ++ zipWith pair [("s16", show x, show y, x `op` y) | x <- i16s, y <- is (intSizeOf x)] [x `op` y | x <- si16s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s32", show x, show y, x `op` y) | x <- i32s, y <- is (intSizeOf x)] [x `op` y | x <- si32s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s64", show x, show y, x `op` y) | x <- i64s, y <- is (intSizeOf x)] [x `op` y | x <- si64s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("iUB", show x, show y, x `op` y) | x <- iUBs, y <- [0..10]]          [x `op` y | x <- siUBs, y <- [0..10]]
+  where is sz = [0 .. sz - 1] ++ extras
+          where extras
+                 | overSized = map (sz +) ([0 .. 1] ++ [sz, sz+1])
+                 | True      = []
+        pair (t, x, y, a) b       = (t, x, y, show a, show b, show (fromIntegral a `asTypeOf` b) == show b)
+        mkTest (t, x, y, a, b, s) = testCase ("arithCF-" ++ nm ++ "." ++ t ++ "_" ++ x ++ "_" ++ y ++ "_" ++ a ++ "_" ++ b) (s `showsAs` "True")
+
+genShiftRotTest :: String -> (forall a. (SIntegral a, SDivisible (SBV a)) => (SBV a -> SBV a -> SBV a)) -> [TestTree]
+genShiftRotTest nm op = map mkTest $
+        zipWith pair [("u8",  show x, show y, literal x `op` y) | x <- w8s,  y <- is (intSizeOf x)] [x `op` y | x <- sw8s,  y <- is (intSizeOf x)]
+     ++ zipWith pair [("u16", show x, show y, literal x `op` y) | x <- w16s, y <- is (intSizeOf x)] [x `op` y | x <- sw16s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("u32", show x, show y, literal x `op` y) | x <- w32s, y <- is (intSizeOf x)] [x `op` y | x <- sw32s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("u64", show x, show y, literal x `op` y) | x <- w64s, y <- is (intSizeOf x)] [x `op` y | x <- sw64s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s8",  show x, show y, literal x `op` y) | x <- i8s,  y <- is (intSizeOf x)] [x `op` y | x <- si8s,  y <- is (intSizeOf x)]
+     ++ zipWith pair [("s16", show x, show y, literal x `op` y) | x <- i16s, y <- is (intSizeOf x)] [x `op` y | x <- si16s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s32", show x, show y, literal x `op` y) | x <- i32s, y <- is (intSizeOf x)] [x `op` y | x <- si32s, y <- is (intSizeOf x)]
+     ++ zipWith pair [("s64", show x, show y, literal x `op` y) | x <- i64s, y <- is (intSizeOf x)] [x `op` y | x <- si64s, y <- is (intSizeOf x)]
+     -- NB. No generic shift/rotate for SMTLib unbounded integers
+  where is sz = let b :: Word32
+                    b = fromIntegral sz
+                in map (sFromIntegral . literal) $ [0 .. b - 1] ++ [b, b+1, 2*b, 2*b+1]
+        pair (t, x, y, a) b       = (t, x, y, show a, show b, isJust (unliteral a) && isJust (unliteral b) && unliteral a == unliteral b)
+        mkTest (t, x, y, a, b, s) = testCase ("arithCF-" ++ nm ++ "." ++ t ++ "_" ++ x ++ "_" ++ y ++ "_" ++ a ++ "_" ++ b) (s `showsAs` "True")
+
+-- A few tests for mixed-size shifts
+genShiftMixSize :: [TestTree]
+genShiftMixSize = map mkTest $
+           [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")
+
+         yi16s :: [Int16]
+         yi16s = [0, 255, 256, 257, maxBound]
+
+         yw16s :: [Word16]
+         yw16s = [0, 255, 256, 257, maxBound]
+
+
+genBlasts :: [TestTree]
+genBlasts = map mkTest $
+             [(show x, fromBitsLE (blastLE x) .== x) | x <- sw8s ]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw8s ]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si8s ]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si8s ]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw16s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw16s]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si16s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si16s]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw32s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw32s]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si32s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si32s]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw64s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw64s]
+          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si64s]
+          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si64s]
+  where mkTest (x, r) = testCase ("blast-" ++ x) (r `showsAs` "True")
+
+genCounts :: [TestTree]
+genCounts = map mkTest $
+             [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SWord8 )) | x <- sw8s ]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SWord8 )) | x <- sw8s ]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SInt8  )) | x <- si8s ]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SInt8  )) | x <- si8s ]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SWord16)) | x <- sw16s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SWord16)) | x <- sw16s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SInt16 )) | x <- si16s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SInt16 )) | x <- si16s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SWord32)) | x <- sw32s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SWord32)) | x <- sw32s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SInt32 )) | x <- si32s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SInt32 )) | x <- si32s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SWord64)) | x <- sw64s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SWord64)) | x <- sw64s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsBE (blastLE x) :: SInt64 )) | x <- si64s]
+          ++ [(show x, sCountTrailingZeros x .== sCountLeadingZeros (fromBitsLE (blastBE x) :: SInt64 )) | x <- si64s]
+  where mkTest (x, r) = testCase ("count-" ++ x) (r `showsAs` "True")
+
+genIntCasts :: [TestTree]
+genIntCasts = map mkTest $  cast w8s ++ cast w16s ++ cast w32s ++ cast w64s
+                         ++ cast i8s ++ cast i16s ++ cast i32s ++ cast i64s
+                         ++ cast iUBs
+   where mkTest (x, r) = testCase ("intCast-" ++ x) (r `showsAs` "True")
+         lhs x = sFromIntegral (literal x)
+         rhs x = literal (fromIntegral x)
+         cast :: forall a. (Show a, Integral a, SymVal a) => [a] -> [(String, SBool)]
+         cast xs = toWords xs ++ toInts xs
+         toWords xs =  [(show x, lhs x .== (rhs x :: SWord8 ))  | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SWord16))  | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SWord32))  | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SWord64))  | x <- xs]
+         toInts  xs =  [(show x, lhs x .== (rhs x :: SInt8 ))   | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SInt16))   | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SInt32))   | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SInt64))   | x <- xs]
+                    ++ [(show x, lhs x .== (rhs x :: SInteger)) | x <- xs]
+
+genChars :: [TestTree]
+genChars = map mkTest $  [("ord",           show c, check SC.ord             cord            c) | c <- cs]
+                      ++ [("toLower",       show c, check SC.toLowerL1       C.toLower       c) | c <- cs]
+                      ++ [("toUpper",       show c, check SC.toUpperL1       C.toUpper       c) | c <- cs]
+                      ++ [("digitToInt",    show c, check SC.digitToInt      dig2Int         c) | c <- cs, digitToIntRange c]
+                      ++ [("intToDigit",    show c, check SC.intToDigit      int2Dig         c) | c <- [0 .. 15]]
+                      ++ [("isControl",     show c, check SC.isControlL1     C.isControl     c) | c <- cs]
+                      ++ [("isSpace",       show c, check SC.isSpaceL1       C.isSpace       c) | c <- cs]
+                      ++ [("isLower",       show c, check SC.isLowerL1       C.isLower       c) | c <- cs]
+                      ++ [("isUpper",       show c, check SC.isUpperL1       C.isUpper       c) | c <- cs]
+                      ++ [("isAlpha",       show c, check SC.isAlphaL1       C.isAlpha       c) | c <- cs]
+                      ++ [("isAlphaNum",    show c, check SC.isAlphaNumL1    C.isAlphaNum    c) | c <- cs]
+                      ++ [("isPrint",       show c, check SC.isPrintL1       C.isPrint       c) | c <- cs]
+                      ++ [("isDigit",       show c, check SC.isDigit         C.isDigit       c) | c <- cs]
+                      ++ [("isOctDigit",    show c, check SC.isOctDigit      C.isOctDigit    c) | c <- cs]
+                      ++ [("isHexDigit",    show c, check SC.isHexDigit      C.isHexDigit    c) | c <- cs]
+                      ++ [("isLetter",      show c, check SC.isLetterL1      C.isLetter      c) | c <- cs]
+                      ++ [("isMark",        show c, check SC.isMarkL1        C.isMark        c) | c <- cs]
+                      ++ [("isNumber",      show c, check SC.isNumberL1      C.isNumber      c) | c <- cs]
+                      ++ [("isPunctuation", show c, check SC.isPunctuationL1 C.isPunctuation c) | c <- cs]
+                      ++ [("isSymbol",      show c, check SC.isSymbolL1      C.isSymbol      c) | c <- cs]
+                      ++ [("isSeparator",   show c, check SC.isSeparatorL1   C.isSeparator   c) | c <- cs]
+                      ++ [("isAscii",       show c, check SC.isAscii         C.isAscii       c) | c <- cs]
+                      ++ [("isLatin1",      show c, check SC.isLatin1        C.isLatin1      c) | c <- cs]
+                      ++ [("isAsciiUpper",  show c, check SC.isAsciiUpper    C.isAsciiUpper  c) | c <- cs]
+                      ++ [("isAsciiLower",  show c, check SC.isAsciiLower    C.isAsciiLower  c) | c <- cs]
+  where digitToIntRange   = (`elem` "0123456789abcdefABCDEF")
+        cord :: Char -> Integer
+        cord = fromIntegral . C.ord
+        dig2Int :: Char -> Integer
+        dig2Int = fromIntegral . C.digitToInt
+        int2Dig :: Integer -> Char
+        int2Dig = C.intToDigit . fromIntegral
+        mkTest (nm, x, t) = testCase ("genChars-" ++ nm ++ "." ++ x) (assert t)
+        check sop cop arg = case unliteral (sop (literal arg)) of
+                              Nothing -> False
+                              Just x  -> x == cop arg
+
+genStrings :: [TestTree]
+genStrings = map mkTest1 (  [("length",        show s,                   check1 SL.length        strLen        s      ) | s <- ss                                                       ]
+                         ++ [("null",          show s,                   check1 SL.null          null          s      ) | s <- ss                                                       ]
+                         ++ [("head",          show s,                   check1 SL.head          head          s      ) | s <- ss, not (null s)                                         ]
+                         ++ [("tail",          show s,                   check1 SL.tail          tail          s      ) | s <- ss, not (null s)                                         ]
+                         ++ [("singleton",     show c,                   check1 SL.singleton     (: [])        c      ) | c <- cs                                                       ]
+                         ++ [("implode",       show s,                   checkI SL.implode                     s      ) | s <- ss                                                       ]
+                         ++ [("strToNat",      show s,                   check1 SL.strToNat      strToNat      s      ) | s <- ss                                                       ]
+                         ++ [("natToStr",      show i,                   check1 SL.natToStr      natToStr      i      ) | i <- iUBs                                                     ])
+          ++ map mkTest2 (  [("strToCharAt",   show s, show i,           check2 SL.elemAt        strToCharAt   s i    ) | s <- ss, i  <- range s                                        ]
+                         ++ [("concat",        show s, show s1,          check2 (SL.++)          (++)          s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isInfixOf",     show s, show s1,          check2 SL.isInfixOf     isInfixOf     s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isSuffixOf",    show s, show s1,          check2 SL.isSuffixOf    isSuffixOf    s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isPrefixOf",    show s, show s1,          check2 SL.isPrefixOf    isPrefixOf    s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("take",          show s, show i,           check2 SL.take          genericTake   i s    ) | s <- ss, i <- iUBs                                            ]
+                         ++ [("drop",          show s, show i,           check2 SL.drop          genericDrop   i s    ) | s <- ss, i <- iUBs                                            ]
+                         ++ [("indexOf",       show s, show s1,          check2 SL.indexOf       indexOf       s s1   ) | s <- ss, s1 <- ss                                             ])
+          ++ map mkTest3 (  [("subStr",        show s, show  i, show j,  check3 SL.subList       subStr        s i  j ) | s <- ss, i  <- range s, j <- range s, i + j <= genericLength s]
+                         ++ [("replace",       show s, show s1, show s2, check3 SL.replace       replace       s s1 s2) | s <- ss, s1 <- ss, s2 <- ss                                   ]
+                         ++ [("offsetIndexOf", show s, show s1, show i,  check3 SL.offsetIndexOf offsetIndexOf s s1 i ) | s <- ss, s1 <- ss, i <- range s                               ])
+  where strLen :: String -> Integer
+        strLen = fromIntegral . length
+
+        strToNat :: String -> Integer
+        strToNat s
+          | all C.isDigit s && not (null s) = read s
+          | True                            = -1
+
+        natToStr :: Integer -> String
+        natToStr i
+          | i >= 0 = show i
+          | True   = ""
+
+        range :: String -> [Integer]
+        range s = map fromIntegral [0 .. length s - 1]
+
+        indexOf :: String -> String -> Integer
+        indexOf s1 s2 = go 0 s1
+          where go i x
+                 | s2 `isPrefixOf` x = i
+                 | True              = case x of
+                                          "" -> -1
+                                          (_:r) -> go (i+1) r
+
+        strToCharAt :: String -> Integer -> Char
+        s `strToCharAt` i = s `genericIndex` i
+
+        subStr :: String -> Integer -> Integer -> String
+        subStr s i j = genericTake j (genericDrop i s)
+
+        replace :: String -> String -> String -> String
+        replace s "" y = y ++ s
+        replace s x  y = go s
+          where go "" = ""
+                go h@(c:rest) | x `isPrefixOf` h = y ++ drop (length x) h
+                              | True             = c : go rest
+
+        offsetIndexOf :: String -> String -> Integer -> Integer
+        offsetIndexOf x y i = case indexOf (genericDrop i x) y of
+                                -1 -> -1
+                                r  -> r+i
+
+        mkTest1 (nm, x, t)       = testCase ("genStrings-" ++ nm ++ "." ++ x)                         (assert t)
+        mkTest2 (nm, x, y, t)    = testCase ("genStrings-" ++ nm ++ "." ++ x ++ "_" ++ y)             (assert t)
+        mkTest3 (nm, x, y, z, t) = testCase ("genStrings-" ++ nm ++ "." ++ x ++ "_" ++ y ++ "_" ++ z) (assert t)
+
+        checkI sop s = case unliteral (sop (map literal s)) of
+                         Nothing -> False
+                         Just x  -> s == x
+
+        check1 sop cop arg            = case unliteral (sop (literal arg)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg
+        check2 sop cop arg1 arg2      = case unliteral (sop (literal arg1) (literal arg2)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg1 arg2
+        check3 sop cop arg1 arg2 arg3 = case unliteral (sop (literal arg1) (literal arg2) (literal arg3)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg1 arg2 arg3
+
+genLists :: [TestTree]
+genLists = map mkTest1 (   [("length",        show l,                   check1 SL.length        llen          l      ) | l <- sl                                                       ]
+                        ++ [("null",          show l,                   check1 SL.null          null          l      ) | l <- sl                                                       ]
+                        ++ [("head",          show l,                   check1 SL.head          head          l      ) | l <- sl, not (null l)                                         ]
+                        ++ [("tail",          show l,                   check1 SL.tail          tail          l      ) | l <- sl, not (null l)                                         ]
+                        ++ [("singleton",     show i,                   check1 SL.singleton     (: [])        i      ) | i <- iUBs                                                     ]
+                        ++ [("implode",       show l,                   checkI SL.implode       id            l      ) | l <- sl                                                       ]
+                        ++ [("concat",        show l,                   check1 SL.concat        concat        l      ) | l <- sll                                                      ]
+                       )
+        ++ map mkTest2 (   [("listToListAt",  show l, show i,           check2 SL.listToListAt  listToListAt  l i    ) | l <- sl, i  <- range l                                        ]
+                        ++ [("elemAt",        show l, show i,           check2 SL.elemAt        elemAt        l i    ) | l <- sl, i  <- range l                                        ]
+                        ++ [("append",        show l, show l1,          check2 (SL.++)          (++)          l l1   ) | l <- sl, l1 <- sl                                             ]
+                        ++ [("isInfixOf",     show l, show l1,          check2 SL.isInfixOf     isInfixOf     l l1   ) | l <- sl, l1 <- sl                                             ]
+                        ++ [("isSuffixOf",    show l, show l1,          check2 SL.isSuffixOf    isSuffixOf    l l1   ) | l <- sl, l1 <- sl                                             ]
+                        ++ [("isPrefixOf",    show l, show l1,          check2 SL.isPrefixOf    isPrefixOf    l l1   ) | l <- sl, l1 <- sl                                             ]
+                        ++ [("take",          show l, show i,           check2 SL.take          genericTake   i l    ) | l <- sl, i <- iUBs                                            ]
+                        ++ [("drop",          show l, show i,           check2 SL.drop          genericDrop   i l    ) | l <- sl, i <- iUBs                                            ]
+                        ++ [("indexOf",       show l, show l1,          check2 SL.indexOf       indexOf       l l1   ) | l <- sl, l1 <- sl                                             ])
+        ++ map mkTest3 (   [("subList",       show l, show  i, show j,  check3 SL.subList       subList       l i  j ) | l <- sl, i  <- range l, j <- range l, i + j <= genericLength l]
+                        ++ [("replace",       show l, show l1, show l2, check3 SL.replace       replace       l l1 l2) | l <- sl, l1 <- sl, l2 <- sl                                   ]
+                        ++ [("offsetIndexOf", show l, show l1, show i,  check3 SL.offsetIndexOf offsetIndexOf l l1 i ) | l <- sl, l1 <- sl, i <- range l                               ])
+  where llen :: [Integer] -> Integer
+        llen = fromIntegral . length
+
+        range :: [Integer] -> [Integer]
+        range l = map fromIntegral [0 .. length l - 1]
+
+        indexOf :: [Integer] -> [Integer] -> Integer
+        indexOf s1 s2 = go 0 s1
+          where go i x
+                 | s2 `isPrefixOf` x = i
+                 | True              = case x of
+                                          []    -> -1
+                                          (_:r) -> go (i+1) r
+
+        listToListAt :: [Integer] -> Integer -> [Integer]
+        s `listToListAt` i = [s `elemAt` i]
+
+        elemAt :: [Integer] -> Integer -> Integer
+        l `elemAt` i = l `genericIndex` i
+
+        subList :: [Integer] -> Integer -> Integer -> [Integer]
+        subList s i j = genericTake j (genericDrop i s)
+
+        replace :: [Integer] -> [Integer] -> [Integer] -> [Integer]
+        replace s [] y = y ++ s
+        replace s x  y = go s
+          where go [] = []
+                go h@(c:rest) | x `isPrefixOf` h = y ++ drop (length x) h
+                              | True             = c : go rest
+
+        offsetIndexOf :: [Integer] -> [Integer] -> Integer -> Integer
+        offsetIndexOf x y i = case indexOf (genericDrop i x) y of
+                                -1 -> -1
+                                r  -> r+i
+
+        mkTest1 (nm, x, t)       = testCase ("genLists-" ++ nm ++ "." ++ x)                         (assert t)
+        mkTest2 (nm, x, y, t)    = testCase ("genLists-" ++ nm ++ "." ++ x ++ "_" ++ y)             (assert t)
+        mkTest3 (nm, x, y, z, t) = testCase ("genLists-" ++ nm ++ "." ++ x ++ "_" ++ y ++ "_" ++ z) (assert t)
+
+        checkI sop cop arg = case unliteral (sop (map literal arg)) of
+                               Nothing -> False
+                               Just x  -> x == cop arg
+
+        check1 sop cop arg            = case unliteral (sop (literal arg)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg
+
+        check2 sop cop arg1 arg2      = case unliteral (sop (literal arg1) (literal arg2)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg1 arg2
+
+        check3 sop cop arg1 arg2 arg3 = case unliteral (sop (literal arg1) (literal arg2) (literal arg3)) of
+                                          Nothing -> False
+                                          Just x  -> x == cop arg1 arg2 arg3
+
+-- Test these with make test TGT=enum_
+genEnums :: [TestTree]
+genEnums =
+    -- Only bounded for from, otherwise infinite (or too big for chars)
+    [mkTest1 "from"       s     (eq [s..    ] [sEnum|literal s..                    |]) | s <- univ @(WordN 4)]
+ ++ [mkTest1 "from"       s     (eq [s..    ] [sEnum|literal s..                    |]) | s <- univ @(IntN  4)]
+ ++ [mkTest1 "from"       s     (eq [s..    ] [sEnum|literal s..                    |]) | s <- univ @Day]
+ ++ [mkTest1 "from"       s     (eq [s..    ] [sEnum|literal s..                    |]) | s <- w8s]
+ ++ [mkTest1 "from"       s     (eq [s..    ] [sEnum|literal s..                    |]) | s <- i8s]
+
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- univ @(WordN 4), t <- univ @(WordN 4)]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- univ @(IntN  4), t <- univ @(IntN  4)]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- univ @Day      , t <- univ @Day      ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- w8s            , t <- w8s            ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- i8s            , t <- i8s            ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- ints           , t <- ints           ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- floats         , t <- floats         ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- doubles        , t <- doubles        ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- fps            , t <- fps            ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- lcs            , t <- lcs            ]
+ ++ [mkTest2 "fromTo"     s t   (eq [s..t   ] [sEnum|literal s..literal t           |]) | s <- rs             , t <- rs             ]
+
+    -- Only bounded for fromThen, otherwise infinite (or too big for chars)
+ ++ [mkTest2 "fromThen"   s t   (eq [s, t.. ] [sEnum|literal s, literal t..         |]) | s <- univ @(WordN 4), t <- univ @(WordN 4), s /= t]
+ ++ [mkTest2 "fromThen"   s t   (eq [s, t.. ] [sEnum|literal s, literal t..         |]) | s <- univ @(IntN  4), t <- univ @(IntN  4), s /= t]
+ ++ [mkTest2 "fromThen"   s t   (eq [s, t.. ] [sEnum|literal s, literal t..         |]) | s <- univ @Day      , t <- univ @Day      , s /= t]
+ ++ [mkTest2 "fromThen"   s t   (eq [s, t.. ] [sEnum|literal s, literal t..         |]) | s <- w8s            , t <- w8s            , s /= t]
+ ++ [mkTest2 "fromThen"   s t   (eq [s, t.. ] [sEnum|literal s, literal t..         |]) | s <- i8s            , t <- i8s            , s /= t]
+
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- univ @(WordN 4), t <- univ @(WordN 4), s /= t, u <- univ @(WordN 4)]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- univ @(IntN  4), t <- univ @(IntN  4), s /= t, u <- univ @(IntN  4)]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- univ @Day      , t <- univ @Day      , s /= t, u <- univ @Day      ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- w8s            , t <- w8s            , s /= t, u <- w8s            ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- i8s            , t <- i8s            , s /= t, u <- i8s            ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- ints           , t <- ints           , s /= t, u <- ints           ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- floats         , t <- floats         , s /= t, u <- floats         ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- doubles        , t <- doubles        , s /= t, u <- doubles        ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- fps            , t <- fps            , s /= t, u <- fps            ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- lcs            , t <- lcs            , s /= t, u <- lcs            ]
+ ++ [mkTest3 "fromThenTo" s t u (eq [s, t..u] [sEnum|literal s, literal t..literal u|]) | s <- rs             , t <- rs             , s /= t, u <- rs             ]
+
+  where mkTest1 pre a     = testCase ("enum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show a)
+        mkTest2 pre a b   = testCase ("enum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show (a, b))
+        mkTest3 pre a b c = testCase ("enum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show (a, b, c))
+
+        eq c s = assert (Just c == unliteral s)
+
+        univ :: (Enum n, Bounded n) => [n]
+        univ = [minBound .. maxBound]
+
+        ints :: [Integer]
+        ints = [-3 .. 3]
+
+        floats :: [Float]
+        floats = [-3.4, -3.2 .. 3.5]
+
+        doubles :: [Double]
+        doubles = [-3.4, -3.2 .. 3.5]
+
+        -- NB. Precision here is important. If you pick too small of a significand
+        -- size then you can turn this enumeration into an infinite list, busting the tests.
+        fps :: [FloatingPoint 5 8]
+        fps = [-3.4, -3.2 .. 3.5]
+
+        rs :: [AlgReal]
+        rs = [-3.4, -3.2 .. 3.5]
+
+        -- don't add min/max bounds here. causes too big lists.
+        lcs :: [Char]
+        lcs = map C.chr [5, 10, 30, 40, 41, 42, 43, 90, 100]
+
+-- Concrete test data
+xsUnsigned :: (Num a, Bounded a) => [a]
+xsUnsigned = take 5 (iterate (1+) minBound) ++ take 5 (iterate (\x -> x-1) maxBound)
+
+xsSigned :: (Num a, Enum a, Bounded a) => [a]
+xsSigned   = xsUnsigned ++ [-5 .. 5]
+
+w8s :: [Word8]
+w8s = xsUnsigned
+
+sw8s :: [SWord8]
+sw8s = xsUnsigned
+
+w16s :: [Word16]
+w16s = xsUnsigned
+
+sw16s :: [SWord16]
+sw16s = xsUnsigned
+
+w32s :: [Word32]
+w32s = xsUnsigned
+
+sw32s :: [SWord32]
+sw32s = xsUnsigned
+
+w64s :: [Word64]
+w64s = xsUnsigned
+
+sw64s :: [SWord64]
+sw64s = xsUnsigned
+
+i8s :: [Int8]
+i8s = xsSigned
+
+si8s :: [SInt8]
+si8s = map literal xsSigned
+
+i16s :: [Int16]
+i16s = xsSigned
+
+si16s :: [SInt16]
+si16s = map literal xsSigned
+
+i32s :: [Int32]
+i32s = xsSigned
+
+si32s :: [SInt32]
+si32s = map literal xsSigned
+
+i64s :: [Int64]
+i64s = xsSigned
+
+si64s :: [SInt64]
+si64s = map literal xsSigned
+
+iUBs :: [Integer]
+iUBs = [-1000000 .. -999995] ++ [-5 .. 5] ++ [999995 ..  1000000]
+
+siUBs :: [SInteger]
+siUBs = map literal iUBs
+
+-- Currently we test over all latin-1 characters. Maybe we should add some unicode here. Oh well.
+cs :: String
+cs = map C.chr [0..255]
+
+-- Ditto for strings, just a few things
+ss :: [String]
+ss = ["", "palTRY", "teSTing", "SBV", "sTRIngs", "123", "surely", "thIS", "hI", "ly", "0"]
+
+-- Lists are the worst in coverage!
+sl :: [[Integer]]
+sl = [[], [0], [-1, 1], [-10, 0, 10], [3, 4, 5, 4, 5, 3]]
+
+-- Like wise, list of lists
+sll :: [[[Integer]]]
+sll = [[x, x, x] | x <- [[], [0], [-1, 1], [-10, 0, 10], [3, 4, 5, 4, 5, 3]]]
+
+-- Quiet GHC about unused enum elts
+_unused :: SDay
+_unused = undefined  sMon  sTue  sWed  sThu  sFri  sSat  sSun
+                    isMon isTue isWed isThu isFri isSat isSun
+                    (sCaseDay @SInteger)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/ArithSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
@@ -0,0 +1,1043 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ArithSolver
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for basic non-concrete arithmetic, i.e., testing all
+-- basic arithmetic reasoning using an SMT solver without any
+-- constant folding.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns -Wno-x-partial #-}
+
+module TestSuite.Basics.ArithSolver(tests) where
+
+import Data.SBV.Internals hiding (free, free_, (#))
+import Utils.SBVTestFramework
+
+import Data.List (genericIndex, isInfixOf, isPrefixOf, isSuffixOf, genericTake, genericDrop, genericLength)
+
+import qualified Data.Char       as C
+import qualified Data.SBV.Char   as SC
+import qualified Data.SBV.List   as SL
+
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving (Show, Bounded, Enum, Eq)
+mkSymbolic  [''Day]
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.ArithSolver"
+   (    genExtends
+     ++ genConcats
+     ++ genReals
+     ++ genFloats
+     ++ genDoubles
+     ++ genFPConverts
+     ++ genQRems
+     ++ genBinTest       True  "+"                (+)
+     ++ genBinTest       True  "-"                (-)
+     ++ genBinTest       True  "*"                (*)
+     ++ genUnTest        True  "negate"           negate
+     ++ genUnTest        True  "abs"              abs
+     ++ genUnTest        True  "signum"           signum
+     ++ genBitTest       False ".&."              (.&.)
+     ++ genBitTest       False ".|."              (.|.)
+     ++ genBoolTest            "<"                (<)  (.<)
+     ++ genBoolTest            "<="               (<=) (.<=)
+     ++ genBoolTest            ">"                (>)  (.>)
+     ++ genBoolTest            ">="               (>=) (.>=)
+     ++ genBoolTest            "=="               (==) (.==)
+     ++ genBoolTest            "/="               (/=) (./=)
+     ++ genBitTest       False "xor"              xor
+     ++ genUnTestBit     False "complement"       complement
+     ++ genIntTest       False "setBit"           setBit
+     ++ genIntTest       False "clearBit"         clearBit
+     ++ genIntTest       False "complementBit"    complementBit
+     ++ genIntTest       True  "shift"            shift
+     ++ genIntTest       True  "shiftL"           shiftL
+     ++ genIntTest       True  "shiftR"           shiftR
+     ++ genIntTest       True  "rotate"           rotate
+     ++ genIntTest       True  "rotateL"          rotateL
+     ++ genIntTest       True  "rotateR"          rotateR
+     ++ genShiftRotTest        "shiftL_gen"       sShiftLeft
+     ++ genShiftRotTest        "shiftR_gen"       sShiftRight
+     ++ genShiftRotTest        "rotateL_gen"      sRotateLeft
+     ++ genShiftRotTest        "rotateR_gen"      sRotateRight
+     ++ genShiftMixSize
+     ++ genBlasts
+     ++ genCounts
+     ++ genIntCasts
+     ++ genChars
+     ++ genStrings
+     ++ genLists
+     ++ genEnums
+     ++ misc
+     )
+
+genExtends :: [TestTree]
+genExtends = map mkTest $  [("signExtend-word", show x, mkThm signExtend x (signExtend (literal x) :: SWord 16)) | x <- wn8s]
+                        ++ [("signExtend-int",  show x, mkThm signExtend x (signExtend (literal x) :: SInt 16))  | x <- in8s]
+                        ++ [("zeroExtend-word", show x, mkThm zeroExtend x (zeroExtend (literal x) :: SWord 16)) | x <- wn8s]
+                        ++ [("zeroExtend-int",  show x, mkThm zeroExtend x (zeroExtend (literal x) :: SInt 16))  | x <- in8s]
+  where
+    mkTest (nm, x, t) = testCase ("genExtends-" ++ nm ++ "." ++ x) (assert t)
+    mkThm op x sr
+      | Just r <- unliteral sr
+      = isTheorem $ do a <- free "x"
+                       constrain $ a .== literal x
+                       return $ literal r .== op a
+      | True
+      = return False
+
+genConcats :: [TestTree]
+genConcats = map mkTest $  [("word", show x, show y, mkThm2 (#) x y (literal x # literal y)) | x <- wn8s, y <- wn8s]
+                        ++ [("int",  show x, show y, mkThm2 (#) x y (literal x # literal y)) | x <- in8s, y <- in8s]
+  where
+    mkTest (nm, x, y, t) = testCase ("genConcats-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+    mkThm2 op x y sr
+      | Just r <- unliteral sr
+      = isTheorem $ do [a, b] <- mapM free ["a", "b"]
+                       constrain $ a .== literal x
+                       constrain $ b .== literal y
+                       return $ literal r .== a `op` b
+      | True
+      = return False
+
+genBinTest :: Bool -> String -> (forall a. Num a => a -> a -> a) -> [TestTree]
+genBinTest unboundedOK nm op = 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 <- rs,   y <- rs]
+                                          ++ [(show x, show y, mkThm2 x y (x `op` y)) | unboundedOK, x <- iUBs, y <- iUBs]
+  where mkTest (x, y, t) = testCase ("genBinTest.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        mkThm2 x y r = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                                      constrain $ a .== literal x
+                                      constrain $ b .== literal y
+                                      return $ literal r .== a `op` b
+
+genBitTest :: Bool -> String -> (forall a. (Num a, Bits a) => a -> a -> a) -> [TestTree]
+genBitTest unboundedOK nm op = 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)) | unboundedOK, x <- iUBs, y <- iUBs]
+  where mkTest (x, y, t) = testCase ("genBitTest.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        mkThm2 x y r = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                                      constrain $ a .== literal x
+                                      constrain $ b .== literal y
+                                      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 <- fs,        y <- fs       ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                             x <- ds,        y <- ds       ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                             x <- ss,        y <- ss       ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                             x <- rs,        y <- rs       ]
+                                   ++ [(show x, show y, mkThm2L x y (x `op` y)) | nm `elem` allowedListComps, x <- sl,        y <- sl       ]
+                                   ++ [(show x, show y, mkThm2M x y (x `op` y)) |                             x <- sm,        y <- sm       ]
+                                   ++ [(show x, show y, mkThm2E x y (x `op` y)) |                             x <- se,        y <- se       ]
+                                   ++ [(show x, show y, mkThm2T x y (x `op` y)) |                             x <- st,        y <- st       ]
+  where -- Currently Z3 doesn't allow for list comparisons, so only test equals and distinct
+        -- And there's no way for us to desugar this like we do for tuple/maybe etc; since the datatype itself is recursive.
+        allowedListComps = ["==", "/="]
+        mkTest (x, y, t) = testCase ("genBoolTest.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        mkThm2 x y r = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                                      constrain $ a .== literal x
+                                      constrain $ b .== literal y
+                                      return $ literal r .== a `opS` b
+        mkThm2L x y r = isTheorem $ do [a, b :: SList Integer] <- mapM free ["x", "y"]
+                                       constrain $ a .== literal x
+                                       constrain $ b .== literal y
+                                       return $ literal r .== a `opS` b
+        mkThm2M x y r = isTheorem $ do [a, b :: SMaybe Integer] <- mapM free ["x", "y"]
+                                       constrain $ a .== literal x
+                                       constrain $ b .== literal y
+                                       return $ literal r .== a `opS` b
+        mkThm2E x y r = isTheorem $ do [a, b :: SEither Integer Integer] <- mapM free ["x", "y"]
+                                       constrain $ a .== literal x
+                                       constrain $ b .== literal y
+                                       return $ literal r .== a `opS` b
+        mkThm2T x y r = isTheorem $ do [a, b :: STuple Integer Integer] <- mapM free ["x", "y"]
+                                       constrain $ a .== literal x
+                                       constrain $ b .== literal y
+                                       return $ literal r .== a `opS` b
+
+genUnTest :: Bool -> String -> (forall a. Num a => a -> a) -> [TestTree]
+genUnTest unboundedOK nm op = map mkTest $  [(show x, mkThm x (op x)) | x <- w8s ]
+                                         ++ [(show x, mkThm x (op x)) | x <- w16s]
+                                         ++ [(show x, mkThm x (op x)) | x <- w32s]
+                                         ++ [(show x, mkThm x (op x)) | x <- w64s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i8s ]
+                                         ++ [(show x, mkThm x (op x)) | x <- i16s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i32s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i64s]
+                                         ++ [(show x, mkThm x (op x)) | x <- rs  ]
+                                         ++ [(show x, mkThm x (op x)) | unboundedOK, x <- iUBs]
+  where mkTest (x, t) = testCase ("genUnTest.arithmetic-" ++ nm ++ "." ++ x) (assert t)
+        mkThm x r = isTheorem $ do a <- free "x"
+                                   constrain $ a .== literal x
+                                   return $ literal r .== op a
+
+genUnTestBit :: Bool -> String -> (forall a. (Num a, Bits a) => a -> a) -> [TestTree]
+genUnTestBit unboundedOK nm op = map mkTest $  [(show x, mkThm x (op x)) | x <- w8s ]
+                                         ++ [(show x, mkThm x (op x)) | x <- w16s]
+                                         ++ [(show x, mkThm x (op x)) | x <- w32s]
+                                         ++ [(show x, mkThm x (op x)) | x <- w64s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i8s ]
+                                         ++ [(show x, mkThm x (op x)) | x <- i16s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i32s]
+                                         ++ [(show x, mkThm x (op x)) | x <- i64s]
+                                         ++ [(show x, mkThm x (op x)) | unboundedOK, x <- iUBs]
+  where mkTest (x, t) = testCase ("genUnTestBit.arithmetic-" ++ nm ++ "." ++ x) (assert t)
+        mkThm x r = isTheorem $ do a <- free "x"
+                                   constrain $ a .== literal x
+                                   return $ literal r .== op a
+
+genIntTest :: Bool -> String -> (forall a. (Num a, Bits a) => (a -> Int -> a)) -> [TestTree]
+genIntTest overSized nm op = map mkTest $
+        [("u8",  show x, show y, mkThm2 x y (x `op` y)) | x <- w8s,  y <- is (intSizeOf x)]
+     ++ [("u16", show x, show y, mkThm2 x y (x `op` y)) | x <- w16s, y <- is (intSizeOf x)]
+     ++ [("u32", show x, show y, mkThm2 x y (x `op` y)) | x <- w32s, y <- is (intSizeOf x)]
+     ++ [("u64", show x, show y, mkThm2 x y (x `op` y)) | x <- w64s, y <- is (intSizeOf x)]
+     ++ [("s8",  show x, show y, mkThm2 x y (x `op` y)) | x <- i8s,  y <- is (intSizeOf x)]
+     ++ [("s16", show x, show y, mkThm2 x y (x `op` y)) | x <- i16s, y <- is (intSizeOf x)]
+     ++ [("s32", show x, show y, mkThm2 x y (x `op` y)) | x <- i32s, y <- is (intSizeOf x)]
+     ++ [("s64", show x, show y, mkThm2 x y (x `op` y)) | x <- i64s, y <- is (intSizeOf x)]
+     -- No size based tests for unbounded integers
+  where is sz = [0 .. sz - 1] ++ extras
+          where extras
+                 | overSized = map (sz +) ([0 .. 1] ++ [sz, sz+1])
+                 | True      = []
+        mkTest (l, x, y, t) = testCase ("genIntTest.arithmetic-" ++ nm ++ "." ++ l ++ "_" ++ x ++ "_" ++ y) (assert t)
+        mkThm2 x y r = isTheorem $ do a <- free "x"
+                                      constrain $ a .== literal x
+                                      return $ literal r .== a `op` y
+
+genShiftRotTest :: String -> (forall a. (SIntegral a, SDivisible (SBV a)) => (SBV a -> SBV a -> SBV a)) -> [TestTree]
+genShiftRotTest nm op = map mkTest $
+        [("u8",  show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- w8s,  y <- is (intSizeOf x)]
+     ++ [("u16", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- w16s, y <- is (intSizeOf x)]
+     ++ [("u32", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- w32s, y <- is (intSizeOf x)]
+     ++ [("u64", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- w64s, y <- is (intSizeOf x)]
+     ++ [("s8",  show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- i8s,  y <- is (intSizeOf x)]
+     ++ [("s16", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- i16s, y <- is (intSizeOf x)]
+     ++ [("s32", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- i32s, y <- is (intSizeOf x)]
+     ++ [("s64", show x, show y, mkThm2 x (fromIntegral y) (literal x `op` sFromIntegral (literal y))) | x <- i64s, y <- is (intSizeOf x)]
+     -- NB. No generic shift/rotate for SMTLib unbounded integers
+  where is sz = let b :: Word32
+                    b = fromIntegral sz
+                in [0 .. b - 1] ++ [b, b+1, 2*b, 2*b+1]
+        mkTest (l, x, y, t) = testCase ("genShiftRotTest.arithmetic-" ++ nm ++ "." ++ l ++ "_" ++ x ++ "_" ++ y) (assert t)
+        mkThm2 x y sr
+         | Just r <- unliteral sr
+         = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                          constrain $ a .== literal x
+                          constrain $ b .== literal y
+                          return $ literal r .== a `op` b
+         | True
+         = return False
+
+-- A few tests for mixed-size shifts
+genShiftMixSize :: [TestTree]
+genShiftMixSize = map mkTest $  [(show x, show y, "shl_w8_w16", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- w8s,  y <- yw16s]
+                             ++ [(show x, show y, "shr_w8_w16", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- w8s,  y <- yw16s]
+                             ++ [(show x, show y, "shl_w16_w8", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- w16s, y <- w8s]
+                             ++ [(show x, show y, "shr_w16_w8", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- w16s, y <- w8s]
+                             ++ [(show x, show y, "shl_i8_i16", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- i8s,  y <- yi16s]
+                             ++ [(show x, show y, "shr_i8_i16", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- i8s,  y <- yi16s]
+                             ++ [(show x, show y, "shl_i16_i8", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- i16s, y <- i8s, y >= 0]
+                             ++ [(show x, show y, "shr_i16_i8", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- i16s, y <- i8s, y >= 0]
+                             ++ [(show x, show y, "shl_w8_i16", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- w8s,  y <- yi16s]
+                             ++ [(show x, show y, "shr_w8_i16", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- w8s,  y <- yi16s]
+                             ++ [(show x, show y, "shl_w16_i8", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- w16s, y <- i8s, y >= 0]
+                             ++ [(show x, show y, "shr_w16_i8", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- w16s, y <- i8s, y >= 0]
+                             ++ [(show x, show y, "shl_i8_w16", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- i8s,  y <- yw16s]
+                             ++ [(show x, show y, "shr_i8_w16", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- i8s,  y <- yw16s]
+                             ++ [(show x, show y, "shl_i16_w8", mk sShiftLeft  x y (x `shiftL` fromIntegral y)) | x <- i16s, y <- w8s]
+                             ++ [(show x, show y, "shr_i16_w8", mk sShiftRight x y (x `shiftR` fromIntegral y)) | x <- i16s, y <- w8s]
+   where yi16s :: [Int16]
+         yi16s = [0, 255, 256, 257, maxBound]
+
+         yw16s :: [Word16]
+         yw16s = [0, 255, 256, 257, maxBound]
+
+         mkTest (x, y, l, t) = testCase ("genShiftMixSize." ++ l ++ "." ++ x ++ "_" ++ y) (assert t)
+         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"
+                           constrain $ a .== literal x
+                           constrain $ b .== literal y
+                           return $ literal r .== a `o` b
+
+genBlasts :: [TestTree]
+genBlasts = map mkTest $  [(show x, mkThm fromBitsLE blastLE x) | x <- w8s ]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w8s ]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i8s ]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i8s ]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w16s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w16s]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i16s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i16s]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w32s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w32s]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i32s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i32s]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w64s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w64s]
+                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i64s]
+                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i64s]
+  where mkTest (x, t) = testCase ("genBlasts.blast-" ++ show x) (assert t)
+        mkThm from to v = isTheorem $ do a <- free "x"
+                                         constrain $ a .== literal v
+                                         return $ a .== from (to a)
+
+genCounts :: [TestTree]
+genCounts = map mkTest $  [(show x, mkThm (fromBitsLE :: [SBool] -> SWord8 ) blastBE x) | x <- w8s ]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SWord8 ) blastLE x) | x <- w8s ]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SInt8  ) blastBE x) | x <- i8s ]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SInt8  ) blastLE x) | x <- i8s ]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SWord16) blastBE x) | x <- w16s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SWord16) blastLE x) | x <- w16s]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SInt16 ) blastBE x) | x <- i16s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SInt16 ) blastLE x) | x <- i16s]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SWord32) blastBE x) | x <- w32s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SWord32) blastLE x) | x <- w32s]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SInt32 ) blastBE x) | x <- i32s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SInt32 ) blastLE x) | x <- i32s]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SWord64) blastBE x) | x <- w64s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SWord64) blastLE x) | x <- w64s]
+                       ++ [(show x, mkThm (fromBitsLE :: [SBool] -> SInt64 ) blastBE x) | x <- i64s]
+                       ++ [(show x, mkThm (fromBitsBE :: [SBool] -> SInt64 ) blastLE x) | x <- i64s]
+  where mkTest (x, t) = testCase ("genCounts.count-" ++ show x) (assert t)
+        mkThm from to v = isTheorem $ do a <- free "x"
+                                         constrain $ a .== literal v
+                                         return $ sCountTrailingZeros a .== sCountLeadingZeros (from (to a))
+
+genIntCasts :: [TestTree]
+genIntCasts = map mkTest $  cast w8s ++ cast w16s ++ cast w32s ++ cast w64s
+                         ++ cast i8s ++ cast i16s ++ cast i32s ++ cast i64s
+                         ++ cast iUBs
+   where mkTest (x, t) = testCase ("sIntCast-" ++ x) (assert t)
+         cast :: forall a. (Show a, Integral a, SymVal a) => [a] -> [(String, IO Bool)]
+         cast xs = toWords xs ++ toInts xs
+         toWords xs =  [(show x, mkThm x (fromIntegral x :: Word8 ))  | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Word16))  | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Word32))  | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Word64))  | x <- xs]
+         toInts  xs =  [(show x, mkThm x (fromIntegral x :: Int8 ))   | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Int16))   | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Int32))   | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Int64))   | x <- xs]
+                    ++ [(show x, mkThm x (fromIntegral x :: Integer)) | x <- xs]
+         mkThm v res = isTheorem $ do a <- free "x"
+                                      constrain $ a .== literal v
+                                      return $ literal res .== sFromIntegral a
+
+genReals :: [TestTree]
+genReals = map mkTest $  [("+",  show x, show y, mkThm2 (+)   x y (x +  y)) | x <- ars, y <- ars        ]
+                      ++ [("-",  show x, show y, mkThm2 (-)   x y (x -  y)) | x <- ars, y <- ars        ]
+                      ++ [("*",  show x, show y, mkThm2 (*)   x y (x *  y)) | x <- ars, y <- ars        ]
+                      ++ [("/",  show x, show y, mkThm2 (/)   x y (x /  y)) | x <- ars, y <- ars, y /= 0]
+                      ++ [("<",  show x, show y, mkThm2 (.<)  x y (x <  y)) | x <- ars, y <- ars        ]
+                      ++ [("<=", show x, show y, mkThm2 (.<=) x y (x <= y)) | x <- ars, y <- ars        ]
+                      ++ [(">",  show x, show y, mkThm2 (.>)  x y (x >  y)) | x <- ars, y <- ars        ]
+                      ++ [(">=", show x, show y, mkThm2 (.>=) x y (x >= y)) | x <- ars, y <- ars        ]
+                      ++ [("==", show x, show y, mkThm2 (.==) x y (x == y)) | x <- ars, y <- ars        ]
+                      ++ [("/=", show x, show y, mkThm2 (./=) x y (x /= y)) | x <- ars, y <- ars        ]
+  where mkTest (nm, x, y, t) = testCase ("genReals.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        mkThm2 op x y r = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                                         constrain $ a .== literal x
+                                         constrain $ b .== literal y
+                                         return $ literal r .== a `op` b
+
+genFloats :: [TestTree]
+genFloats = genIEEE754 "genFloats" fs
+
+genDoubles :: [TestTree]
+genDoubles = genIEEE754 "genDoubles" ds
+
+genIEEE754 :: (IEEEFloating a, OrdSymbolic (SBV a), Num (SBV a), Show a) => String -> [a] -> [TestTree]
+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]
+               ++ [("fpAbs",             show x, mkThm1 fpAbs                 x  (abs x))                | x <- vs]
+               ++ [("fpNeg",             show x, mkThm1 fpNeg                 x  (negate x))             | x <- vs]
+               ++ [("fpSqrt",            show x, mkThm1 (m fpSqrt)            x  (sqrt   x))             | x <- vs]
+               ++ [("fpRoundToIntegral", show x, mkThm1 (m fpRoundToIntegral) x  (fpRoundToIntegralH x)) | x <- vs]
+
+        bins =    [("+",      show x,  show y, mkThm2        (+)       x y (x +  y))   | x <- vs, y <- vs]
+               ++ [("-",      show x,  show y, mkThm2        (-)       x y (x -  y))   | x <- vs, y <- vs]
+               ++ [("*",      show x,  show y, mkThm2        (*)       x y (x *  y))   | x <- vs, y <- vs]
+               ++ [("/",      show x,  show y, mkThm2        (/)       x y (x /  y))   | x <- vs, y <- vs]
+               ++ [("<",      show x,  show y, mkThm2C False (.<)      x y (x <  y))   | x <- vs, y <- vs]
+               ++ [("<=",     show x,  show y, mkThm2C False (.<=)     x y (x <= y))   | x <- vs, y <- vs]
+               ++ [(">",      show x,  show y, mkThm2C False (.>)      x y (x >  y))   | x <- vs, y <- vs]
+               ++ [(">=",     show x,  show y, mkThm2C False (.>=)     x y (x >= y))   | x <- vs, y <- vs]
+               ++ [("==",     show x,  show y, mkThm2C False (.==)     x y (x == y))   | x <- vs, y <- vs]
+               ++ [("/=",     show x,  show y, mkThm2C True  (./=)     x y (x /= y))   | x <- vs, y <- vs]
+               -- TODO. Can't possibly test fma, unless we FFI out to C. Leave it out for the time being
+               ++ [("fpAdd",           show x, show y, mkThm2  (m fpAdd)        x y ((+)              x y)) | x <- vs, y <- vs]
+               ++ [("fpSub",           show x, show y, mkThm2  (m fpSub)        x y ((-)              x y)) | x <- vs, y <- vs]
+               ++ [("fpMul",           show x, show y, mkThm2  (m fpMul)        x y ((*)              x y)) | x <- vs, y <- vs]
+               ++ [("fpDiv",           show x, show y, mkThm2  (m fpDiv)        x y ((/)              x y)) | x <- vs, y <- vs]
+               ++ [("fpMin",           show x, show y, mkThm2  fpMin            x y (fpMinH           x y)) | x <- vs, y <- vs, not (alt0 x y || alt0 y x)]
+               ++ [("fpMax",           show x, show y, mkThm2  fpMax            x y (fpMaxH           x y)) | x <- vs, y <- vs, not (alt0 x y || alt0 y x)]
+               ++ [("fpIsEqualObject", show x, show y, mkThm2P fpIsEqualObject  x y (fpIsEqualObjectH x y)) | x <- vs, y <- vs]
+               ++ [("fpRem",           show x, show y, mkThm2  fpRem            x y (fpRemH           x y)) | x <- vsFPRem, y <- vsFPRem]
+
+        -- TODO: For doubles fpRem takes too long, so we only do a subset
+        vsFPRem
+          | origin == "genDoubles" = [nan, infinity, 0, 0.5, -infinity, -0, -0.5]
+          | True                   = vs
+
+        -- fpMin/fpMax: skip +0/-0 case as this is underspecified
+        alt0 x y = isNegativeZero x && y == 0 && not (isNegativeZero y)
+
+        m f = f sRNE
+
+        preds =   [(pn, show x, mkThmP ps x (pc x)) | (pn, ps, pc) <- predicates, x <- vs]
+        tst2 (nm, x, y, t) = testCase (origin ++ ".arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        tst1 (nm, x,    t) = testCase (origin ++ ".arithmetic-" ++ nm ++ "." ++ x) (assert t)
+
+        eqF v val
+          | isNaN          val        = constrain $ fpIsNaN v
+          | isNegativeZero val        = constrain $ fpIsNegativeZero v
+          | val == 0                  = constrain $ fpIsPositiveZero v
+          | isInfinite val && val > 0 = constrain $ fpIsInfinite v .&& fpIsPositive v
+          | isInfinite val && val < 0 = constrain $ fpIsInfinite v .&& fpIsNegative v
+          | True                      = constrain $ v .== literal val
+
+        -- Quickly pick which solver to use. Currently z3 or mathSAT supports FP
+        fpProver :: SMTConfig
+        fpProver = z3 -- mathSAT
+
+        fpThm = isTheoremWith fpProver
+
+        mkThmP op x r = fpThm $ do a <- free "x"
+                                   eqF a x
+                                   return $ literal r .== op a
+
+        mkThm2P op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
+                                      eqF a x
+                                      eqF b y
+                                      return $ literal r .== a `op` b
+
+        mkThm1 op x r = fpThm $ do a <- free "x"
+                                   eqF a x
+                                   return $ literal r `fpIsEqualObject` op a
+
+        mkThm2 op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
+                                     eqF a x
+                                     eqF b y
+                                     return $ literal r `fpIsEqualObject` (a `op` b)
+
+        mkThm2C neq op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
+                                          eqF a x
+                                          eqF b y
+                                          return $ if isNaN x || isNaN y
+                                                   then (if neq then a `op` b else sNot (a `op` b))
+                                                   else literal r .== a `op` b
+
+        predicates :: (IEEEFloating a) => [(String, SBV a -> SBool, a -> Bool)]
+        predicates = [ ("fpIsNormal",       fpIsNormal,        fpIsNormalizedH)
+                     , ("fpIsSubnormal",    fpIsSubnormal,     isDenormalized)
+                     , ("fpIsZero",         fpIsZero,          (== 0))
+                     , ("fpIsInfinite",     fpIsInfinite,      isInfinite)
+                     , ("fpIsNaN",          fpIsNaN,           isNaN)
+                     , ("fpIsNegative",     fpIsNegative,      \x -> x < 0  ||      isNegativeZero x)
+                     , ("fpIsPositive",     fpIsPositive,      \x -> x >= 0 && not (isNegativeZero x))
+                     , ("fpIsNegativeZero", fpIsNegativeZero,  isNegativeZero)
+                     , ("fpIsPositiveZero", fpIsPositiveZero,  \x -> x == 0 && not (isNegativeZero x))
+                     , ("fpIsPoint",        fpIsPoint,         \x -> not (isNaN x || isInfinite x))
+                     ]
+
+genFPConverts :: [TestTree]
+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]
+                 ++  [("toFP_Int64_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- i64s]
+                 ++  [("toFP_Word8_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w8s ]
+                 ++  [("toFP_Word16_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w16s]
+                 ++  [("toFP_Word32_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w32s]
+                 ++  [("toFP_Word64_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w64s]
+                 ++  [("toFP_Float_ToFloat",    show x, mkThm1 (m toSFloat) x                           x  ) | x <- fs  ]
+                 ++  [("toFP_Double_ToFloat",   show x, mkThm1 (m toSFloat) x (                   fp2fp x )) | x <- ds  ]
+                 ++  [("toFP_Integer_ToFloat",  show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- iUBs]
+                 ++  [("toFP_Real_ToFloat",     show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- ars ]
+
+                 ++  [("toFP_Int8_ToDouble",    show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i8s ]
+                 ++  [("toFP_Int16_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i16s]
+                 ++  [("toFP_Int32_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i32s]
+                 ++  [("toFP_Int64_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i64s]
+                 ++  [("toFP_Word8_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w8s ]
+                 ++  [("toFP_Word16_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w16s]
+                 ++  [("toFP_Word32_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w32s]
+                 ++  [("toFP_Word64_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w64s]
+                 ++  [("toFP_Float_ToDouble",   show x, mkThm1 (m toSDouble) x (                   fp2fp x )) | x <- fs  ]
+                 ++  [("toFP_Double_ToDouble",  show x, mkThm1 (m toSDouble) x                           x )  | x <- ds  ]
+                 ++  [("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 <- ars ]
+
+                 -- 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_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 (wordToFloat  x)) | x <- w32s]
+                 ++  [("reinterp_Word64_Double", show x, mkThmC sWord64AsSDouble x (wordToDouble x)) | x <- w64s]
+
+                 ++  [("reinterp_Float_Word32",  show x, mkThmP sFloatAsSWord32  x (floatToWord x))  | x <- fs, not (isNaN x)] -- Not unique for NaN
+                 ++  [("reinterp_Double_Word64", show x, mkThmP sDoubleAsSWord64 x (doubleToWord x)) | x <- ds, not (isNaN x)] -- Not unique for NaN
+
+        m f = f sRNE
+
+        tst1 (nm, x, t) = testCase ("fpConverts.arithmetic-" ++ nm ++ "." ++ x) (assert t)
+
+        eqF v val
+          | isNaN          val        = constrain $ fpIsNaN v
+          | isNegativeZero val        = constrain $ fpIsNegativeZero v
+          | val == 0                  = constrain $ fpIsPositiveZero v
+          | isInfinite val && val > 0 = constrain $ fpIsInfinite v .&& fpIsPositive v
+          | isInfinite val && val < 0 = constrain $ fpIsInfinite v .&& fpIsNegative v
+          | True                      = constrain $ v .== literal val
+
+        -- Quickly pick which solver to use. Currently z3 or mathSAT supports FP
+        fpProver :: SMTConfig
+        fpProver = z3 -- mathSAT
+
+        fpThm = isTheoremWith fpProver
+
+        mkThmP op x r = fpThm $ do a <- free "x"
+                                   eqF a x
+                                   return $ literal r .== op a
+
+        mkThm1 op x r = fpThm $ do a <- free "x"
+                                   eqF a x
+                                   return $ literal r `fpIsEqualObject` op a
+
+        mkThmC op x r = fpThm $ do a <- free "x"
+                                   constrain $ a .== literal x
+                                   return $ literal r `fpIsEqualObject` op a
+
+        mkThmC' op x r = fpThm $ do a <- free "x"
+                                    eqF a x
+                                    return $ literal r .== op a
+
+genQRems :: [TestTree]
+genQRems = map mkTest $  [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w8s,  y <- w8s ]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w16s, y <- w16s]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w32s, y <- w32s]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w64s, y <- w64s]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i8s,  y <- i8s , noOverflow x y]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i16s, y <- i16s, noOverflow x y]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i32s, y <- i32s, noOverflow x y]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i64s, y <- i64s, noOverflow x y]
+                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- iUBs, y <- iUBs]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w8s,  y <- w8s ]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w16s, y <- w16s]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w32s, y <- w32s]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w64s, y <- w64s]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i8s,  y <- i8s , noOverflow x y]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i16s, y <- i16s, noOverflow x y]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i32s, y <- i32s, noOverflow x y]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i64s, y <- i64s, noOverflow x y]
+                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- iUBs, y <- iUBs]
+  where divMod'  x y = if y == 0 then (0, x) else x `divMod`  y
+        quotRem' x y = if y == 0 then (0, x) else x `quotRem` y
+        mkTest (nm, x, y, t) = testCase ("genQRems.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y) (assert t)
+        mkThm2 op x y (e1, e2) = isTheorem $ do [a, b] <- mapM free ["x", "y"]
+                                                constrain $ a .== literal x
+                                                constrain $ b .== literal y
+                                                return $ (literal e1, literal e2) .== a `op` b
+        -- Haskell's divMod and quotRem overflows if x == minBound and y == -1 for signed types; so avoid that case
+        noOverflow x y = not (x == minBound && y == -1)
+
+genChars :: [TestTree]
+genChars = [ testCase "solver_genChars" (assert (isTheorem t)) ]
+  where t = do a <- free "a"
+               i <- free "i"
+
+               let chk  sop cop v = (a .== literal v) .=> sop a .== literal (cop v)
+                   chkI sop cop v = (i .== literal v) .=> sop i .== literal (cop v)
+
+               pure $ sAnd $  [chk  SC.ord             cord            c | c <- cs]
+                           ++ [chk  SC.toLowerL1       C.toLower       c | c <- cs]
+                           ++ [chk  SC.toUpperL1       C.toUpper       c | c <- cs]
+                           ++ [chk  SC.digitToInt      dig2Int         c | c <- cs, digitToIntRange c]
+                           ++ [chkI SC.intToDigit      int2Dig         c | c <- [0 .. 15]]
+                           ++ [chk  SC.isControlL1     C.isControl     c | c <- cs]
+                           ++ [chk  SC.isSpaceL1       C.isSpace       c | c <- cs]
+                           ++ [chk  SC.isLowerL1       C.isLower       c | c <- cs]
+                           ++ [chk  SC.isUpperL1       C.isUpper       c | c <- cs]
+                           ++ [chk  SC.isAlphaL1       C.isAlpha       c | c <- cs]
+                           ++ [chk  SC.isAlphaNumL1    C.isAlphaNum    c | c <- cs]
+                           ++ [chk  SC.isPrintL1       C.isPrint       c | c <- cs]
+                           ++ [chk  SC.isDigit         C.isDigit       c | c <- cs]
+                           ++ [chk  SC.isOctDigit      C.isOctDigit    c | c <- cs]
+                           ++ [chk  SC.isHexDigit      C.isHexDigit    c | c <- cs]
+                           ++ [chk  SC.isLetterL1      C.isLetter      c | c <- cs]
+                           ++ [chk  SC.isMarkL1        C.isMark        c | c <- cs]
+                           ++ [chk  SC.isNumberL1      C.isNumber      c | c <- cs]
+                           ++ [chk  SC.isPunctuationL1 C.isPunctuation c | c <- cs]
+                           ++ [chk  SC.isSymbolL1      C.isSymbol      c | c <- cs]
+                           ++ [chk  SC.isSeparatorL1   C.isSeparator   c | c <- cs]
+                           ++ [chk  SC.isAscii         C.isAscii       c | c <- cs]
+                           ++ [chk  SC.isLatin1        C.isLatin1      c | c <- cs]
+                           ++ [chk  SC.isAsciiUpper    C.isAsciiUpper  c | c <- cs]
+                           ++ [chk  SC.isAsciiLower    C.isAsciiLower  c | c <- cs]
+
+        digitToIntRange   = (`elem` "0123456789abcdefABCDEF")
+        cord :: Char -> Integer
+        cord = fromIntegral . C.ord
+        dig2Int :: Char -> Integer
+        dig2Int = fromIntegral . C.digitToInt
+        int2Dig :: Integer -> Char
+        int2Dig = C.intToDigit . fromIntegral
+
+genStrings :: [TestTree]
+genStrings = map mkTest1 (  [("length",        show s,                   mkThm1 SL.length        strLen        s      ) | s <- ss                                                       ]
+                         ++ [("null",          show s,                   mkThm1 SL.null          null          s      ) | s <- ss                                                       ]
+                         ++ [("head",          show s,                   mkThm1 SL.head          head          s      ) | s <- ss, not (null s)                                         ]
+                         ++ [("tail",          show s,                   mkThm1 SL.tail          tail          s      ) | s <- ss, not (null s)                                         ]
+                         ++ [("singleton",     show c,                   mkThm1 SL.singleton     (: [])        c      ) | c <- cs                                                       ]
+                         ++ [("implode",       show s,                   mkThmI SL.implode                     s      ) | s <- ss                                                       ]
+                         ++ [("strToNat",      show s,                   mkThm1 SL.strToNat      strToNat      s      ) | s <- ss                                                       ]
+                         ++ [("natToStr",      show i,                   mkThm1 SL.natToStr      natToStr      i      ) | i <- iUBs                                                     ])
+          ++ map mkTest2 (  [("strToCharAt",   show s, show i,           mkThm2 SL.elemAt        strToCharAt   s i    ) | s <- ss, i  <- range s                                        ]
+                         ++ [("++",            show s, show s1,          mkThm2 (SL.++)          (++)          s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isInfixOf",     show s, show s1,          mkThm2 SL.isInfixOf     isInfixOf     s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isSuffixOf",    show s, show s1,          mkThm2 SL.isSuffixOf    isSuffixOf    s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("isPrefixOf",    show s, show s1,          mkThm2 SL.isPrefixOf    isPrefixOf    s s1   ) | s <- ss, s1 <- ss                                             ]
+                         ++ [("take",          show s, show i,           mkThm2 SL.take          genericTake   i s    ) | s <- ss, i <- iUBs                                            ]
+                         ++ [("drop",          show s, show i,           mkThm2 SL.drop          genericDrop   i s    ) | s <- ss, i <- iUBs                                            ]
+                         ++ [("indexOf",       show s, show s1,          mkThm2 SL.indexOf       indexOf       s s1   ) | s <- ss, s1 <- ss                                             ])
+          ++ map mkTest3 (  [("subStr",        show s, show  i, show j,  mkThm3 SL.subList       subStr        s i  j ) | s <- ss, i  <- range s, j <- range s, i + j <= genericLength s]
+                         ++ [("replace",       show s, show s1, show s2, mkThm3 SL.replace       replace       s s1 s2) | s <- ss, s1 <- ss, s2 <- ss                                   ]
+                         ++ [("offsetIndexOf", show s, show s1, show i,  mkThm3 SL.offsetIndexOf offsetIndexOf s s1 i ) | s <- ss, s1 <- ss, i <- range s                               ])
+  where strLen :: String -> Integer
+        strLen = fromIntegral . length
+
+        strToNat :: String -> Integer
+        strToNat s
+          | all C.isDigit s && not (null s) = read s
+          | True                            = -1
+
+        natToStr :: Integer -> String
+        natToStr i
+          | i >= 0 = show i
+          | True   = ""
+
+        range :: String -> [Integer]
+        range s = map fromIntegral [0 .. length s - 1]
+
+        indexOf :: String -> String -> Integer
+        indexOf s1 s2 = go 0 s1
+          where go i x
+                 | s2 `isPrefixOf` x = i
+                 | True              = case x of
+                                          "" -> -1
+                                          (_:r) -> go (i+1) r
+
+        strToCharAt :: String -> Integer -> Char
+        s `strToCharAt` i = s `genericIndex` i
+
+        subStr :: String -> Integer -> Integer -> String
+        subStr s i j = genericTake j (genericDrop i s)
+
+        replace :: String -> String -> String -> String
+        replace s "" y = y ++ s
+        replace s x  y = go s
+          where go "" = ""
+                go h@(c:rest) | x `isPrefixOf` h = y ++ drop (length x) h
+                              | True             = c : go rest
+
+        offsetIndexOf :: String -> String -> Integer -> Integer
+        offsetIndexOf x y i = case indexOf (genericDrop i x) y of
+                                -1 -> -1
+                                r  -> r+i
+
+        mkTest1 (nm, x, t)       = testCase ("genStrings-" ++ nm ++ "." ++ x)                         (assert t)
+        mkTest2 (nm, x, y, t)    = testCase ("genStrings-" ++ nm ++ "." ++ x ++ "_" ++ y)             (assert t)
+        mkTest3 (nm, x, y, z, t) = testCase ("genStrings-" ++ nm ++ "." ++ x ++ "_" ++ y ++ "_" ++ z) (assert t)
+
+        mkThmI sop s = isTheorem $ do let v c = do sc <- free_
+                                                   constrain $ sc .== literal c
+                                                   return sc
+                                      vs <- mapM v s
+                                      return $ literal s .== sop vs
+
+        mkThm1 sop cop arg            = isTheorem $ do a <- free "a"
+                                                       constrain $ a .== literal arg
+                                                       return $ literal (cop arg) .== sop a
+        mkThm2 sop cop arg1 arg2      = isTheorem $ do a <- free "a"
+                                                       b <- free "b"
+                                                       constrain $ a .== literal arg1
+                                                       constrain $ b .== literal arg2
+                                                       return $ literal (cop arg1 arg2) .== sop a b
+        mkThm3 sop cop arg1 arg2 arg3 = isTheorem $ do a <- free "a"
+                                                       b <- free "b"
+                                                       c <- free "c"
+                                                       constrain $ a .== literal arg1
+                                                       constrain $ b .== literal arg2
+                                                       constrain $ c .== literal arg3
+                                                       return $ literal (cop arg1 arg2 arg3) .== sop a b c
+
+genLists :: [TestTree]
+genLists = map mkTest1 (   [("length",        show l,                   mkThm1 SL.length        llen          l      ) | l <- sl                                                        ]
+                        ++ [("null",          show l,                   mkThm1 SL.null          null          l      ) | l <- sl                                                        ]
+                        ++ [("head",          show l,                   mkThm1 SL.head          head          l      ) | l <- sl, not (null l)                                          ]
+                        ++ [("tail",          show l,                   mkThm1 SL.tail          tail          l      ) | l <- sl, not (null l)                                          ]
+                        ++ [("singleton",     show i,                   mkThm1 SL.singleton     (: [])        i      ) | i <- iUBs                                                      ]
+                        ++ [("implode",       show l,                   mkThmI SL.implode       id            l      ) | l <- sl                                                        ]
+                        ++ [("concat",        show l,                   mkThm1 SL.concat        concat        l      ) | l <- sll                                                       ]
+                       )
+        ++ map mkTest2 (   [("listToListAt",  show l, show i,           mkThm2 SL.listToListAt  listToListAt  l i    ) | l <- sl,  i  <- range l                                        ]
+                        ++ [("elemAt",        show l, show i,           mkThm2 SL.elemAt        elemAt        l i    ) | l <- sl,  i  <- range l                                        ]
+                        ++ [("append",        show l, show l1,          mkThm2 (SL.++)          (++)          l l1   ) | l <- sl,  l1 <- sl                                             ]
+                        ++ [("isInfixOf",     show l, show l1,          mkThm2 SL.isInfixOf     isInfixOf     l l1   ) | l <- sl,  l1 <- sl                                             ]
+                        ++ [("isSuffixOf",    show l, show l1,          mkThm2 SL.isSuffixOf    isSuffixOf    l l1   ) | l <- sl,  l1 <- sl                                             ]
+                        ++ [("isPrefixOf",    show l, show l1,          mkThm2 SL.isPrefixOf    isPrefixOf    l l1   ) | l <- sl,  l1 <- sl                                             ]
+                        ++ [("take",          show l, show i,           mkThm2 SL.take          genericTake   i l    ) | l <- sl,  i <- iUBs                                            ]
+                        ++ [("drop",          show l, show i,           mkThm2 SL.drop          genericDrop   i l    ) | l <- sl,  i <- iUBs                                            ]
+                        ++ [("indexOf",       show l, show l1,          mkThm2 SL.indexOf       indexOf       l l1   ) | l <- sl,  l1 <- sl                                             ]
+                       )
+        ++ map mkTest3 (   [("subList",       show l, show  i, show j,  mkThm3 SL.subList       subList       l i  j ) | l <- sl,  i  <- range l, j <- range l, i + j <= genericLength l]
+                        ++ [("replace",       show l, show l1, show l2, mkThm3 SL.replace       replace       l l1 l2) | l <- sl,  l1 <- sl, l2 <- sl                                   ]
+                        ++ [("offsetIndexOf", show l, show l1, show i,  mkThm3 SL.offsetIndexOf offsetIndexOf l l1 i ) | l <- sl,  l1 <- sl, i <- range l                               ]
+                       )
+  where llen :: [Integer] -> Integer
+        llen = fromIntegral . length
+
+        range :: [Integer] -> [Integer]
+        range l = map fromIntegral [0 .. length l - 1]
+
+        indexOf :: [Integer] -> [Integer] -> Integer
+        indexOf s1 s2 = go 0 s1
+          where go i x
+                 | s2 `isPrefixOf` x = i
+                 | True              = case x of
+                                          []    -> -1
+                                          (_:r) -> go (i+1) r
+
+        listToListAt :: [Integer] -> Integer -> [Integer]
+        s `listToListAt` i = [s `elemAt` i]
+
+        elemAt :: [Integer] -> Integer -> Integer
+        l `elemAt` i = l `genericIndex` i
+
+        subList :: [Integer] -> Integer -> Integer -> [Integer]
+        subList s i j = genericTake j (genericDrop i s)
+
+        replace :: [Integer] -> [Integer] -> [Integer] -> [Integer]
+        replace s [] y = y ++ s
+        replace s x  y = go s
+          where go [] = []
+                go h@(c:rest) | x `isPrefixOf` h = y ++ drop (length x) h
+                              | True             = c : go rest
+
+        offsetIndexOf :: [Integer] -> [Integer] -> Integer -> Integer
+        offsetIndexOf x y i = case indexOf (genericDrop i x) y of
+                                -1 -> -1
+                                r  -> r+i
+
+        mkTest1 (nm, x, t)       = testCase ("genLists-" ++ nm ++ "." ++ x)                         (assert t)
+        mkTest2 (nm, x, y, t)    = testCase ("genLists-" ++ nm ++ "." ++ x ++ "_" ++ y)             (assert t)
+        mkTest3 (nm, x, y, z, t) = testCase ("genLists-" ++ nm ++ "." ++ x ++ "_" ++ y ++ "_" ++ z) (assert t)
+
+        mkThmI sop cop arg = isTheorem $ do let v c = do sc <- free_
+                                                         constrain $ sc .== literal c
+                                                         return sc
+                                            vs <- mapM v arg
+                                            return $ literal (cop arg) .== sop vs
+
+        mkThm1 sop cop arg = isTheorem $ do a <- free "a"
+                                            constrain $ a .== literal arg
+                                            return $ literal (cop arg) .== sop a
+
+        mkThm2 sop cop arg1 arg2 = isTheorem $ do a <- free "a"
+                                                  b <- free "b"
+                                                  constrain $ a .== literal arg1
+                                                  constrain $ b .== literal arg2
+                                                  return $ literal (cop arg1 arg2) .== sop a b
+
+        mkThm3 sop cop arg1 arg2 arg3 = isTheorem $ do a <- free "a"
+                                                       b <- free "b"
+                                                       c <- free "c"
+                                                       constrain $ a .== literal arg1
+                                                       constrain $ b .== literal arg2
+                                                       constrain $ c .== literal arg3
+                                                       return $ literal (cop arg1 arg2 arg3) .== sop a b c
+
+-- Concrete test data
+xsSigned, xsUnsigned :: (Num a, Bounded a) => [a]
+xsUnsigned = [0, 1, maxBound - 1, maxBound]
+xsSigned   = xsUnsigned ++ [minBound, minBound + 1, -1]
+
+w8s :: [Word8]
+w8s = xsUnsigned
+
+w16s :: [Word16]
+w16s = xsUnsigned
+
+w32s :: [Word32]
+w32s = xsUnsigned
+
+w64s :: [Word64]
+w64s = xsUnsigned
+
+i8s :: [Int8]
+i8s = xsSigned
+
+i16s :: [Int16]
+i16s = xsSigned
+
+i32s :: [Int32]
+i32s = xsSigned
+
+i64s :: [Int64]
+i64s = xsSigned
+
+wn8s :: [WordN 8]
+wn8s = xsUnsigned
+
+in8s :: [IntN 8]
+in8s = xsSigned
+
+iUBs :: [Integer]
+iUBs = [-1000000] ++ [-1 .. 1] ++ [1000000]
+
+ars :: [AlgReal]
+ars = map fromRational rs
+
+rs :: [Ratio Integer]
+rs = [i % d | i <- is, d <- dens]
+ where is   = [-1000000] ++ [-1 .. 1] ++ [1000001]
+       dens = [5,100,1000000]
+
+-- Admittedly paltry test-cases for float/double
+fs :: [Float]
+fs = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
+   where xs = [nan, infinity, 0, 0.5, 0.68302244, 0.5268265, 0.10283524, 5.8336496e-2, 1.0e-45]
+
+ds :: [Double]
+ds = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
+  where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 5.0e-324]
+
+-- Currently we test over all latin-1 characters. Maybe we should add some unicode when the
+-- underlying operation is supported. Oh well.
+cs :: String
+cs = map C.chr [0..255]
+
+-- For pair char ops, take a subset.
+reducedCS :: String
+reducedCS = map C.chr $ [0..5] ++ [98..102] ++ [250..255]
+
+-- Ditto for strings, just a few things
+ss :: [String]
+ss = ["", "palTRY", "teSTing", "SBV", "sTRIngs", "123", "surely", "thIS", "hI", "ly", "0"]
+
+-- Lists are the worst in coverage!
+sl :: [[Integer]]
+sl = [[], [0], [-1, 1], [-10, 0, 10], [3, 4, 5, 4, 5, 3]]
+
+-- List of lists are similarly inadequate
+sll :: [[[Integer]]]
+sll = [[x, x, x] | x <- [[], [0], [-1, 1], [-10, 0, 10], [3, 4, 5, 4, 5, 3]]]
+
+-- Ditto for maybe, either and tuple
+sm :: [Maybe Integer]
+sm = [Nothing, Just (-5), Just 0, Just 5]
+
+se :: [Either Integer Integer]
+se = [Left 3, Right 5]
+
+st :: [(Integer, Integer)]
+st = [(1, 2), (-1, -5), (0, 9), (5, 5)]
+
+misc :: [TestTree]
+misc = [ testCase "misc-t1" $ assertIsSat t1
+       ]
+ where -- https://stackoverflow.com/questions/69033969/trivial-rationals-problems-without-variables-in-sbv-solver-in-haskell
+       t1 = do _xs <- sRationals []
+               constrain $ (5.%1:: SRational) .<= (5.%1:: SRational)
+
+-- Test these with make test TGT=sEnum_
+genEnums :: [TestTree]
+genEnums =
+    -- Only bounded for from, otherwise infinite (or too big for chars)
+    [mkTest1 "from"       s     (from [s..    ] s) | s <- univ @(WordN 4)]
+ ++ [mkTest1 "from"       s     (from [s..    ] s) | s <- univ @(IntN  4)]
+ ++ [mkTest1 "from"       s     (from [s..    ] s) | s <- univ @Day]
+ ++ [mkTest1 "from"       s     (from [s..    ] s) | s <- w8s]
+ ++ [mkTest1 "from"       s     (from [s..    ] s) | s <- i8s]
+
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- univ @(WordN 4), t <- univ @(WordN 4)]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- univ @(IntN  4), t <- univ @(IntN  4)]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- univ @Day      , t <- univ @Day      ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- w8s            , t <- w8s            ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- i8s            , t <- i8s            ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- ints           , t <- ints           ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- floats         , t <- floats         ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- doubles        , t <- doubles        ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- fps            , t <- fps            ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- lcs            , t <- lcs            ]
+ ++ [mkTest2 "fromTo"     s t   (fromTo [s..t   ] s t) | s <- rrs            , t <- rrs            ]
+
+    -- Only bounded for fromThen, otherwise infinite (or too big for chars)
+ ++ [mkTest2 "fromThen"   s t   (fromThen [s, t.. ] s t) | s <- univ @(WordN 4), t <- univ @(WordN 4), s /= t]
+ ++ [mkTest2 "fromThen"   s t   (fromThen [s, t.. ] s t) | s <- univ @(IntN  4), t <- univ @(IntN  4), s /= t]
+ ++ [mkTest2 "fromThen"   s t   (fromThen [s, t.. ] s t) | s <- univ @Day      , t <- univ @Day      , s /= t]
+ ++ [mkTest2 "fromThen"   s t   (fromThen [s, t.. ] s t) | s <- w8s            , t <- w8s            , s /= t]
+ ++ [mkTest2 "fromThen"   s t   (fromThen [s, t.. ] s t) | s <- i8s            , t <- i8s            , s /= t]
+
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- univ @(WordN 4), t <- univ @(WordN 4), s /= t, u <- univ @(WordN 4)]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- univ @(IntN  4), t <- univ @(IntN  4), s /= t, u <- univ @(IntN  4)]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- univ @Day      , t <- univ @Day      , s /= t, u <- univ @Day      ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- w8s            , t <- w8s            , s /= t, u <- w8s            ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- i8s            , t <- i8s            , s /= t, u <- i8s            ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- ints           , t <- ints           , s /= t, u <- ints           ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- floats         , t <- floats         , s /= t, u <- floats         ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- doubles        , t <- doubles        , s /= t, u <- doubles        ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- fps            , t <- fps            , s /= t, u <- fps            ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- lcs            , t <- lcs            , s /= t, u <- lcs            ]
+ ++ [mkTest3 "fromThenTo" s t u (fromThenTo [s, t..u] s t u) | s <- rrs            , t <- rrs            , s /= t, u <- rrs            ]
+
+  where mkTest1 pre a     = testCase ("sEnum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show a)
+        mkTest2 pre a b   = testCase ("sEnum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show (a, b))
+        mkTest3 pre a b c = testCase ("sEnum_" ++ pre ++ "_|" ++ show (kindOf a) ++ "|_" ++ show (a, b, c))
+
+        from cr a1 = assert $ isTheorem $ do
+                        sa1 <- free_
+                        constrain $ sa1 .== literal a1
+
+                        pure $ [sEnum|sa1..|] .== literal cr
+
+        fromTo cr a1 a2 = assert $ isTheorem $ do
+                            sa1 <- free_
+                            constrain $ sa1 .== literal a1
+
+                            sa2 <- free_
+                            constrain $ sa2 .== literal a2
+
+                            pure $ [sEnum|sa1..sa2|] .== literal cr
+
+        fromThen cr a1 a2 = assert $ isTheorem $ do
+                              sa1 <- free_
+                              constrain $ sa1 .== literal a1
+
+                              sa2 <- free_
+                              constrain $ sa2 .== literal a2
+
+                              pure $ [sEnum|sa1, sa2 ..|] .== literal cr
+
+        fromThenTo cr a1 a2 a3 = assert $ isTheorem $ do
+                                   sa1 <- free_
+                                   constrain $ sa1 .== literal a1
+
+                                   sa2 <- free_
+                                   constrain $ sa2 .== literal a2
+
+                                   sa3 <- free_
+                                   constrain $ sa3 .== literal a3
+
+                                   pure $ [sEnum|sa1, sa2 .. sa3|] .== literal cr
+
+        univ :: (Enum n, Bounded n) => [n]
+        univ = [minBound .. maxBound]
+
+        ints :: [Integer]
+        ints = [-3 .. 3]
+
+        -- Floats create too big a problem for z3, even though we have ground terms. So, skip
+        floats :: [Float]
+        -- floats = [-3.4, -3.2 .. 3.5]
+        floats = []
+
+        -- Ditto here
+        doubles :: [Double]
+        -- doubles = [-3.4, -3.2 .. 3.5]
+        doubles = []
+
+        -- NB. Precision here is important. If you pick too small of a significand
+        -- size then you can turn this enumeration into an infinite list, busting the tests.
+        fps :: [FloatingPoint 5 8]
+        -- fps = [-3.4, -3.2 .. 3.5]
+        fps = []
+
+        -- This one works, but is way too slow. So we further reduce the range
+        rrs :: [AlgReal]
+        -- rrs = [-3.4, -3.2 .. 3.5]
+        rrs = [-0.4, -0.2 .. 0.4]
+
+        -- don't add min/max bounds here. causes too big lists.
+        lcs :: [Char]
+        lcs = map C.chr [5, 10, 30, 40, 41, 42, 43, 90, 100]
+
+-- Quiet GHC about unused enum elts
+_unused :: SDay
+_unused = undefined  sMon  sTue  sWed  sThu  sFri  sSat  sSun
+                    isMon isTue isWed isThu isFri isSat isSun
+                    (sCaseDay @SInteger)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/Assert.hs b/SBVTestSuite/TestSuite/Basics/Assert.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Assert.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Assert
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the sAssert feature.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Assert(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.Assert"
+   [ goldenCapturedIO "safe1" $ t $ \x -> sAssert Nothing "safe1" (x .> (2::SInteger)) (x .== 12)
+   , goldenCapturedIO "safe2" $ t $ \x -> sAssert Nothing "safe2" (x .> (2::SInteger)) (12::SInteger)
+   ]
+   where t tc goldFile = do r <- safeWith z3{verbose=True, redirectVerbose=Just goldFile} tc
+                            appendFile goldFile ("\n FINAL: " ++ show r ++ "\nDONE!")
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,98 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.BarrelRotate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test barrel rotates.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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 CVC5 for these tests as Z3 is rather slow!
+          check f gf = do r <- proveWith cvc5{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
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/BasicTests.hs
@@ -0,0 +1,139 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.BasicTests
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.BasicTests
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.BasicTests(tests) where
+
+import Data.SBV.Control
+import Data.SBV.Internals hiding (free, output)
+import Utils.SBVTestFramework
+
+import Control.Monad       (void)
+import Control.Monad.Trans (liftIO)
+
+import System.Random
+
+import qualified Control.Exception as C
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.BasicTests"
+   [ testCase "basic-0.1" $ test0 f1 `showsAs` "5"
+   , testCase "basic-0.2" $ test0 f2 `showsAs` "5"
+   , testCase "basic-0.3" $ test0 f3 `showsAs` "25"
+   , testCase "basic-0.4" $ test0 f4 `showsAs` "25"
+   , testCase "basic-0.5" $ test0 f5 `showsAs` "4"
+   , goldenVsStringShow "basic-1_1" $ test1 f1
+   , goldenVsStringShow "basic-1_2" $ test1 f2
+   , goldenVsStringShow "basic-1_3" $ test1 f3
+   , goldenVsStringShow "basic-1_4" $ test1 f4
+   , goldenVsStringShow "basic-1_5" $ test1 f5
+   , goldenVsStringShow "basic-2_1" $ test2 f1
+   , goldenVsStringShow "basic-2_2" $ test2 f2
+   , goldenVsStringShow "basic-2_3" $ test2 f3
+   , goldenVsStringShow "basic-2_4" $ test2 f4
+   , goldenVsStringShow "basic-2_5" $ test2 f5
+   , goldenVsStringShow "basic-3_1" $ test3 f1
+   , goldenVsStringShow "basic-3_2" $ test3 f2
+   , goldenVsStringShow "basic-3_3" $ test3 f3
+   , goldenVsStringShow "basic-3_4" $ test3 f4
+   , goldenVsStringShow "basic-3_5" $ test3 f5
+   , goldenVsStringShow "basic-4_1" $ test4 f1
+   , goldenVsStringShow "basic-4_2" $ test4 f2
+   , goldenVsStringShow "basic-4_3" $ test4 f3
+   , goldenVsStringShow "basic-4_4" $ test4 f4
+   , goldenVsStringShow "basic-4_5" $ test4 f5
+   , goldenVsStringShow "basic-5_1" $ test5 f1
+   , goldenVsStringShow "basic-5_2" $ test5 f2
+   , goldenVsStringShow "basic-5_3" $ test5 f3
+   , goldenVsStringShow "basic-5_4" $ test5 f4
+   , goldenVsStringShow "basic-5_5" $ test5 f5
+   , goldenCapturedIO   "nested1"   $ nested nested1
+   , goldenCapturedIO   "nested2"   $ nested nested2
+   , goldenCapturedIO   "nested3"   $ nested nested3
+   , goldenCapturedIO   "nested4"   $ nested nested4
+   ]
+
+test0 :: (forall a. Num a => (a -> a -> a)) -> Word8
+test0 f = f (3 :: Word8) 2
+
+test1, test2, test3, test4, test5 :: (forall a. Num a => (a -> a -> a)) -> IO Result
+test1 f = runSAT $ do let x = literal (3 :: Word8)
+                          y = literal (2 :: Word8)
+                      pure $ f x y
+test2 f = runSAT $ do let x = literal (3 :: Word8)
+                      y :: SWord8 <- free "y"
+                      pure $ f x y
+test3 f = runSAT $ do x :: SWord8 <- free "x"
+                      y :: SWord8 <- free "y"
+                      pure $ f x y
+test4 f = runSAT $ do x :: SWord8 <- free "x"
+                      pure $ f x x
+test5 f = runSAT $ do x :: SWord8 <- free "x"
+                      let r = f x x
+                      q :: SWord8 <- free "q"
+                      _ <- output q
+                      pure r
+
+f1, f2, f3, f4, f5 :: Num a => a -> a -> a
+f1 x y = (x+y)*(x-y)
+f2 x y = (x*x)-(y*y)
+f3 x y = (x+y)*(x+y)
+f4 x y = let z = x + y in z * z
+f5 x _ = x + 1
+
+-- Nested calls are not OK; make sure we catch these
+nested :: (SMTConfig -> IO a) -> FilePath -> IO ()
+nested t rf = do setStdGen (mkStdGen 0)
+                 void (t z3{verbose=True, redirectVerbose=Just rf})
+                  `C.catch` \(e::C.SomeException) -> do appendFile rf "CAUGHT EXCEPTION\n\n"
+                                                        appendFile rf (show e)
+
+nested1 :: SMTConfig -> IO ThmResult
+nested1 cfg = proveWith cfg $ do
+  x <- free "x"
+  y <- free "y"
+  liftIO $ f x y
+ where f :: SWord32 -> SWord32 -> IO SBool
+       f x y = do
+         res <- isSatisfiable $ x .== y
+         return $ if res then sTrue else sFalse
+
+nested2 :: SMTConfig -> IO ThmResult
+nested2 cfg = proveWith cfg $ do
+  x <- free "x"
+  liftIO $ f x
+ where f :: SWord32 -> IO SBool
+       f x = do
+         res <- isSatisfiable $ x .== 2
+         return $ if res then sTrue else sFalse
+
+nested3 :: SMTConfig -> IO ThmResult
+nested3 cfg = proveWith cfg $ do
+        y <- sBool "y"
+        x <- liftIO leak        -- reach in!
+        return $ y .== x
+  where leak :: IO SBool
+        leak = runSMTWith cfg $ do
+                        x <- sBool "x"
+                        query $ pure x
+
+nested4 :: SMTConfig -> IO Bool
+nested4 cfg = do
+  d1 <- runSMT (sArray_ :: Symbolic (SArray Bool Bool))
+
+  let sboolOfInterest = readArray d1 sTrue
+
+  isSatisfiableWith cfg sboolOfInterest
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,43 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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>
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.DynSign(tests) where
+
+import Utils.SBVTestFramework hiding (proveWith)
+
+import Data.SBV.Dynamic
+import Data.SBV.Internals  (genMkSymVar, unSBV, VarContext(..))
+
+prop :: Symbolic SVal
+prop = do x <- unSBV <$> genMkSymVar w8 (NonQueryVar 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/EqSym.hs b/SBVTestSuite/TestSuite/Basics/EqSym.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/EqSym.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.BasicTests
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.EqSym
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.EqSym(tests) where
+
+import Utils.SBVTestFramework
+
+import Control.Monad (void)
+import GHC.Generics
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.EqSym"
+   [ goldenCapturedIO "check1" $ \rf -> void (isTheoremWith z3{verbose=True, redirectVerbose=Just rf} check1)
+   , goldenCapturedIO "check2" $ \rf -> void (isTheoremWith z3{verbose=True, redirectVerbose=Just rf} check2)
+   ]
+
+data F = A SWord8 SWord16
+       | B SBool
+       deriving (Generic, EqSymbolic)
+
+newF :: Symbolic F
+newF = A <$> free_ <*> free_
+
+check1 :: Predicate
+check1 = do x <- newF
+            y <- newF
+            pure $ x .== y
+
+check2 :: Predicate
+check2 = do x <- newF
+            pure $ x ./= x
diff --git a/SBVTestSuite/TestSuite/Basics/Exceptions.hs b/SBVTestSuite/TestSuite/Basics/Exceptions.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Exceptions.hs
@@ -0,0 +1,68 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Exceptions
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the exception mechanism
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Exceptions(testsLocal, testsRemote)  where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import qualified Control.Exception as C
+
+-- Test suite
+testsLocal :: TestTree
+testsLocal =
+  testGroup "Basics.exceptions.local"
+    [ goldenCapturedIO "exceptionLocal1" yicesExc
+    , goldenCapturedIO "exceptionLocal2" z3Exc1
+    ]
+
+-- Yices throws an exception for this since exponent is too large
+yicesExc :: FilePath -> IO ()
+yicesExc rf = runSMTWith yices{verbose=True, redirectVerbose=Just rf} exc
+                             `C.catch` \(e :: SBVException) -> do appendFile rf "CAUGHT SMT EXCEPTION"
+                                                                  appendFile rf (show e)
+ where exc = do x <- sWord32 "x"
+                constrain $ lsb x .=> (x * (x .^ (-1::SWord32))) .== 1
+                query $ do cs <- checkSat
+                           cs `seq` return ()
+
+testsRemote :: TestTree
+testsRemote =
+  testGroup "Basics.exceptions.remote"
+    [ goldenCapturedIO "exceptionRemote1" z3Exc2
+    ]
+
+-- Create the case where we ask for integer-logic, but use reals
+z3Exc1 :: FilePath -> IO ()
+z3Exc1 rf = runSMTWith z3{verbose=True, redirectVerbose=Just rf} exc
+                `C.catch` \(e :: SBVException) -> do appendFile rf "CAUGHT SMT EXCEPTION"
+                                                     appendFile rf (show e)
+   where exc = do setLogic QF_LIA
+                  x <- sReal "x"
+                  constrain $ x .== 2
+                  query $ do cs <- checkSat
+                             cs `seq` return ()
+
+-- Similar to above, except linear logic, but use non-linear constructs
+z3Exc2 :: FilePath -> IO ()
+z3Exc2 rf = do r <- runSMT z3ExcCatch `C.catch` \(e :: SBVException) -> return ("OK, we got: " ++ sbvExceptionDescription e)
+               appendFile rf ("\nFINAL: " ++ show r ++ "\nDONE!\n")
+  where z3ExcCatch = do setLogic QF_LIA
+                        x <- sInteger "x"
+                        y <- sInteger "y"
+                        query $ do constrain $ x*y .== x*x
+                                   show <$> checkSat
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs b/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.GenBenchmark
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the generateSMTBenchmark function.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.GenBenchmark(tests)  where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.genBenchmark"
+    [ goldenString "genBenchMark1" $ gen generateSMTBenchmarkProof (\x -> x .== (x+1::SWord8))
+    , goldenString "genBenchMark2" $ gen generateSMTBenchmarkSat   (\x -> x .== (x+1::SWord8))
+    ]
+    where gen generator f =
+                -- the first line is time-stamp, get rid of it so test is repeatable
+                unlines . drop 1 . lines <$> generator f
diff --git a/SBVTestSuite/TestSuite/Basics/Higher.hs b/SBVTestSuite/TestSuite/Basics/Higher.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Higher.hs
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Higher
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.Higher
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Higher(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Basics.Higher"
+    [ goldenVsStringShow "higher-1" (f11 === f11)
+    , goldenVsStringShow "higher-2" (f12 === f12)
+    , goldenVsStringShow "higher-3" (f21 === f21)
+    , goldenVsStringShow "higher-4" (f22 === f22)
+    , goldenVsStringShow "higher-5" (f31 === f31)
+    , goldenVsStringShow "higher-6" (f32 === f32)
+    , goldenVsStringShow "higher-7" (f33 === f33)
+    , goldenVsStringShow "higher-8" double
+    , goldenVsStringShow "higher-9" onlyFailsFor128
+    ]
+ where double          = (2*) === (\x -> x+(x::SWord8))
+       onlyFailsFor128 = (2*) === (\x -> ite (x .== 128) 5 (x+(x::SWord8)))
+
+type B = SWord8
+
+f11 :: B -> B
+f11 x = x
+
+f12 :: B -> (B, B)
+f12 x = (x, x)
+
+f21 :: (B, B) -> B
+f21 (x, y) = x + y
+
+f22 :: (B, B) -> (B, B)
+f22 (x, y) = (x, y)
+
+f31 :: B -> B -> B
+f31 x y = x + y
+
+f32 :: B -> B -> (B, B)
+f32 x y = (x, y)
+
+f33 :: B -> B -> B -> (B, B, B)
+f33 x y z = (x, y, z)
diff --git a/SBVTestSuite/TestSuite/Basics/Index.hs b/SBVTestSuite/TestSuite/Basics/Index.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Index.hs
@@ -0,0 +1,78 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Index
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.Index
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Index(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Basics.Index"
+    (zipWith
+      mkTest
+      [f x | f <- [test1, test2, test3], x <- [0..13]]
+      [(0::Int)..])
+
+mkTest :: IO Bool -> Int -> TestTree
+mkTest tst i =
+  testCase ("index-" ++ show i)
+    (assert tst)
+
+-- prove that the "select" primitive is working correctly
+test1 :: Int -> IO Bool
+test1 n = isTheorem $ do
+            elts <- mkFreeVars n
+            err  <- free_
+            ind  <- free_
+            ind2 <- free_
+            let r1 = (select :: [SWord8] -> SWord8 -> SInt8 -> SWord8) elts err ind
+                r2 = (select :: [SWord8] -> SWord8 -> SWord8 -> SWord8) elts err ind2
+                r3 = slowSearch elts err ind
+                r4 = slowSearch elts err ind2
+            return $ r1 .== r3 .&& r2 .== r4
+ where slowSearch elts err i = ite (i .< 0) err (go elts i)
+         where go []     _      = err
+               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
+
+test2 :: Int -> IO Bool
+test2 n = isTheorem $ do
+            elts1 <- mkFreeVars n
+            elts2 <- mkFreeVars n
+            let elts = zip elts1 elts2
+            err1  <- free_
+            err2  <- free_
+            let err = (err1, err2)
+            ind  <- free_
+            ind2 <- free_
+            let r1 = (select :: [(SWord8, SWord8)] -> (SWord8, SWord8) -> SInt8 -> (SWord8, SWord8)) elts err ind
+                r2 = (select :: [(SWord8, SWord8)] -> (SWord8, SWord8) -> SWord8 -> (SWord8, SWord8)) elts err ind2
+                r3 = slowSearch elts err ind
+                r4 = slowSearch elts err ind2
+            return $ r1 .== r3 .&& r2 .== r4
+ where slowSearch elts err i = ite (i .< 0) err (go elts i)
+         where go []     _      = err
+               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
+
+test3 :: Int -> IO Bool
+test3 n = isTheorem $ do
+            eltsI <- mkFreeVars n
+            let elts = map Left eltsI
+            errI  <- free_
+            let err = Left errI
+            ind  <- free_
+            let r1 = (select :: [Either SWord8 SWord8] -> Either SWord8 SWord8 -> SInt8 -> Either SWord8 SWord8) elts err ind
+                r2 = slowSearch elts err ind
+            return $ r1 .== r2
+ where slowSearch elts err i = ite (i .< 0) err (go elts i)
+         where go []     _      = err
+               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
diff --git a/SBVTestSuite/TestSuite/Basics/IteTest.hs b/SBVTestSuite/TestSuite/Basics/IteTest.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/IteTest.hs
@@ -0,0 +1,39 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.IteTest
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test various incarnations of laziness in ite
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.IteTest(tests)  where
+
+import Utils.SBVTestFramework
+
+chk1 :: (SBool -> SBool -> SBool -> SBool) -> SWord8 -> SBool
+chk1 cond x = cond (x .== x) sTrue undefined
+
+chk2 :: (SBool -> [SBool] -> [SBool] -> [SBool]) -> SWord8 -> SBool
+chk2 cond x = case cond (x .== x) [sTrue] [undefined] of
+                [v] -> v
+                _   -> error "chk2: Impossible happened in call to cond!"
+
+chk3 :: (SBool -> (SBool, SBool) -> (SBool, SBool)  -> (SBool, SBool)) -> SWord8 -> SBool
+chk3 cond x = fst (cond (x .== x) (sTrue, undefined::SBool) (undefined, undefined))
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Ite"
+    [ testCase "iteTest1" (chk1 ite 0 `showsAs` "True")
+    , testCase "iteTest2" (chk2 ite 0 `showsAs` "True")
+    , testCase "iteTest3" (chk3 ite 0 `showsAs` "True")
+    , testCase "iteTest4" (assertIsThm (chk1 iteLazy))
+    , testCase "iteTest5" (assertIsThm (chk2 iteLazy))
+    , testCase "iteTest6" (assertIsThm (chk3 iteLazy))
+    ]
diff --git a/SBVTestSuite/TestSuite/Basics/Lambda.hs b/SBVTestSuite/TestSuite/Basics/Lambda.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Lambda.hs
@@ -0,0 +1,489 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Lambda
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test lambda generation
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Lambda(tests)  where
+
+import Prelude hiding((++), map, foldl, foldr, sum, length, zip, zipWith, all, any, concat, filter, head)
+import qualified Prelude as P
+
+import qualified Data.List as P (partition)
+
+import Control.Monad (unless, void)
+import qualified Control.Exception as C
+
+import Data.SBV.Control
+import Data.SBV.Internals hiding(free_)
+
+import Documentation.SBV.Examples.Misc.Definitions
+
+import Data.SBV.List
+import Data.SBV.Tuple hiding (fst, snd)
+
+import Data.Proxy
+
+import Utils.SBVTestFramework
+
+data P
+mkSymbolic [''P]
+
+drinker :: Predicate
+drinker = pure $ quantifiedBool $ \(Exists x) (Forall y) -> d x .=> d y
+  where d :: SP -> SBool
+        d = uninterpret "D"
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Lambda" $ [
+        goldenCapturedIO "lambda01" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInteger)) (2             :: SInteger)
+      , goldenCapturedIO "lambda02" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInteger)) (\x   -> x+1   :: SInteger)
+      , goldenCapturedIO "lambda03" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInteger)) (\x y -> x+y*2 :: SInteger)
+
+      , goldenCapturedIO "lambda04" $ eval1 [1 .. 3 :: Integer] (mapl (const sFalse),  P.map (const False))
+      , goldenCapturedIO "lambda05" $ eval1 [1 .. 5 :: Integer] (mapl (+1) . mapl (+2), P.map (+1) . P.map (+2))
+      , goldenCapturedIO "lambda06" $ eval1 [1 .. 5 :: Integer]
+                                            ( mapl  (\x -> P.sum [x .^ literal i | i <- [1..10 :: Integer]])
+                                            , P.map (\x -> P.sum [x  ^ i         | i <- [1..10 :: Integer]])
+                                            )
+
+      , goldenCapturedIO "lambda07" $ eval1 ([[1..5], [1..10], [1..20]] :: [[Integer]]) (   sum .   map   sum
+                                                                                        , P.sum . P.map P.sum
+                                                                                        )
+
+      , goldenCapturedIO "lambda08" $ eval1 [1 .. 5 :: Int64]   (mapl (+1), P.map (+1))
+      , goldenCapturedIO "lambda09" $ eval1 [1 .. 5 :: Int8]    (mapl (+1), P.map (+1))
+      , goldenCapturedIO "lambda10" $ eval1 [1 .. 5 :: Integer] (mapl (+1), P.map (+1))
+      , goldenCapturedIO "lambda11" $ eval1 [1 .. 5 :: Word8]   (mapl (+1), P.map (+1))
+
+      , goldenCapturedIO "lambda12" $ eval1 [1 .. 3 :: Integer] (map singleton, P.map (: []))
+
+      , goldenCapturedIO "lambda13" $ eval1 [(x, y) | x <- [1..3], y <- [4..6 :: Integer]]
+                                            (map (\t -> t^._1 + t^._2), P.map (P.uncurry (+)))
+
+      , goldenCapturedIO "lambda14" $ eval1 [1 .. 5 :: Integer] (zipWithL (+) [sEnum|10..15|], P.zipWith (+) [10..15])
+
+      , goldenCapturedIO "lambda15" $ eval1 [1 .. 5 :: Integer] (foldlL (+) 0, P.sum)
+      , goldenCapturedIO "lambda16" $ eval1 [1 .. 5 :: Integer] (foldlL (*) 1, P.product)
+      , goldenCapturedIO "lambda17" $ eval1 [1 .. 5 :: Integer]
+                                           (   foldlL (\soFar elt -> singleton elt ++ soFar) []
+                                           , P.foldl  (\soFar elt ->           elt :  soFar) []
+                                           )
+
+      , goldenCapturedIO "lambda18" $ eval1 [1 .. 5 :: Integer]
+                                            (   foldlL (\b t      -> t^._1 + b + t^._2) 0 .   zip [sEnum|10..15|]
+                                            , P.foldl  (\b (i, a) -> i     + b + a)     0 . P.zip [      10..15 ]
+                                            )
+
+      , goldenCapturedIO "lambda19" $ eval1 [1 .. 5 :: Integer] (foldrL (+) 0, P.foldr (+) 0)
+      , goldenCapturedIO "lambda20" $ eval1 [1 .. 5 :: Integer] (foldrL (*) 1, P.foldr (*) 1)
+      , goldenCapturedIO "lambda21" $ eval1 [1 .. 5 :: Integer]
+                                           (   foldrL (\elt soFar -> soFar   ++ singleton elt) []
+                                           , P.foldr  (\elt soFar -> soFar P.++ [elt])         []
+                                           )
+
+      , goldenCapturedIO "lambda22" $ eval2 [1 .. 10 :: Integer] [11..20 :: Integer] (zip, P.zip)
+      , goldenCapturedIO "lambda23" $ eval2 [1 .. 10 :: Integer] [10, 9 .. 1 :: Integer]
+                                            ( \a b ->   foldrL (+) 0 (  map (\t -> t^._1+t^._2::SInteger) (  zip a b))
+                                            , \a b -> P.foldr  (+) 0 (P.map (\t -> fst t+snd t::Integer ) (P.zip a b))
+                                            )
+      , goldenCapturedIO "lambda24" $ eval2 [1 .. 10 :: Integer] [11..20 :: Integer] (zipWithL (+), P.zipWith (+))
+      , goldenCapturedIO "lambda25" $ eval2 [1 .. 10 :: Integer] [10, 9 .. 1 :: Integer]
+                                            ( \a b ->   foldrL (+) 0 (  zipWithL (+) a b)
+                                            , \a b -> P.foldr  (+) 0 (P.zipWith  (+) a b)
+                                            )
+
+      -- Disabled due to z3 bug: https://github.com/LeventErkok/sbv/issues/773
+      -- , goldenCapturedIO "lambda26" $ eval1 ([[1..5], [1..10], [1..20]] :: [[Integer]]) (concat, P.concat)
+
+      , goldenCapturedIO "lambda27" $ eval1 [2, 4, 6,    8, 10 :: Integer] (all (\x -> x `sMod` 2 .== 0), P.all (\x -> x `mod` 2 == 0))
+      , goldenCapturedIO "lambda28" $ eval1 [2, 4, 6, 1, 8, 10 :: Integer] (all (\x -> x `sMod` 2 .== 0), P.all (\x -> x `mod` 2 == 0))
+
+      , goldenCapturedIO "lambda29" $ eval1 [2, 4, 6,    8, 10 :: Integer] (any (\x -> x `sMod` 2 ./= 0), P.any (\x -> x `mod` 2 /= 0))
+      , goldenCapturedIO "lambda30" $ eval1 [2, 4, 6, 1, 8, 10 :: Integer] (any (\x -> x `sMod` 2 .== 0), P.any (\x -> x `mod` 2 == 0))
+
+      , goldenCapturedIO "lambda31" $ eval1 [1 .. 10 :: Integer] (filterL (\x -> x `sMod` 2 .== 0), P.filter (\x -> x `mod` 2 == 0))
+      , goldenCapturedIO "lambda32" $ eval1 [1 .. 10 :: Integer] (filterL (\x -> x `sMod` 2 ./= 0), P.filter (\x -> x `mod` 2 /= 0))
+
+      , goldenCapturedIO "lambda33" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInt8)) (0           :: SInt8)
+      , goldenCapturedIO "lambda34" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInt8)) (\x   -> x+1 :: SInt8)
+      , goldenCapturedIO "lambda35" $ record $ \st -> show <$> lambdaStr st TopLevel (kindOf (Proxy @SInt8)) (\x y -> x+y :: SInt8)
+
+      , goldenCapturedIO "lambda36" $ record $ \st -> constraintStr st $ \(Forall (_ :: SBool))  -> sTrue
+      , goldenCapturedIO "lambda37" $ record $ \st -> constraintStr st $ \(Forall b)             -> sNot b
+      , goldenCapturedIO "lambda38" $ record $ \st -> constraintStr st $ \(Forall x) (Forall y) -> x .== (0 :: SInteger) .|| y
+
+      , goldenCapturedIO "lambda40" $ record $ \st -> show <$> lambdaStr st TopLevel KUnbounded (0           :: SInteger)
+      , goldenCapturedIO "lambda41" $ record $ \st -> show <$> lambdaStr st TopLevel KUnbounded (\x   -> x+1 :: SInteger)
+      , goldenCapturedIO "lambda42" $ record $ \st -> show <$> lambdaStr st TopLevel KUnbounded (\x y -> x+y :: SInteger)
+
+      , goldenCapturedIO "lambda43" $ record $ \st -> show <$> lambdaStr st TopLevel (KBounded False 32) (0           :: SWord32)
+      , goldenCapturedIO "lambda44" $ record $ \st -> show <$> lambdaStr st TopLevel (KBounded False 32) (\x   -> x+1 :: SWord32)
+      , goldenCapturedIO "lambda45" $ record $ \st -> show <$> lambdaStr st TopLevel (KBounded False 32) (\x y -> x+y :: SWord32)
+
+      , goldenCapturedIO "lambda46" $ runSat ((.== 5) . add1)
+
+      , goldenCapturedIO "lambda47"   $ runSat2 (\a r -> a .== 5 .&& sumToN a .== r)
+      , goldenCapturedIO "lambda47_c" $ runSat  (sumToN 5 .==)
+
+      , goldenCapturedIO "lambda48"   $ runSat2 (\a r -> a .== [1,2,3::SInteger] .&& len a .== r)
+      , goldenCapturedIO "lambda48_c" $ runSat  (len [1,2,3::SInteger] .==)
+
+      , goldenCapturedIO "lambda49"   $ runSat2 (\a r -> a .== 20 .&& isEven a .== r)
+      , goldenCapturedIO "lambda49_c" $ runSat  (isEven 20 .==)
+
+      , goldenCapturedIO "lambda50"   $ runSat2 (\a r -> a .== 21 .&& isEven a .== r)
+      , goldenCapturedIO "lambda50_c" $ runSat  (isEven 21 .==)
+
+      , goldenCapturedIO "lambda51"   $ runSat2 (\a r -> a .== 20 .&& isOdd  a .== r)
+      , goldenCapturedIO "lambda51_c" $ runSat  (isOdd  20 .==)
+
+      , goldenCapturedIO "lambda52"   $ runSat2 (\a r -> a .== 21 .&& isOdd  a .== r)
+      , goldenCapturedIO "lambda52_c" $ runSat  (isOdd  21 .==)
+
+      -- make sure we can pass globals
+      , goldenCapturedIO "lambda53" $ runS $ \x -> x .== smtFunction "foo" (+(x::SInteger)) x
+
+      -- Make sure we can handle dependency orders
+      , goldenCapturedIO "lambda54" $ runSat   $ \x -> let foo = smtFunction "foo" (\a -> bar a + 1)
+                                                           bar = smtFunction "bar" (+1)
+                                                       in bar x + foo x .== (x :: SInteger)
+      , goldenCapturedIO "lambda55" $ runSat   $ \x -> let foo = smtFunction "foo" (\a -> bar a + 1)
+                                                           bar = smtFunction "bar" (+1)
+                                                       in foo x + bar x .== (x :: SInteger)
+      , goldenCapturedIO "lambda56" $ runUnsat $ \x -> let foo = smtFunction "foo" (\a -> bar a + 1)
+                                                           bar = smtFunction "bar" (\a -> foo a + 1)
+                                                       in foo x + bar x .== (x :: SInteger)
+      , goldenCapturedIO "lambda57" $ runSat   $ \x -> let f1 = smtFunction "f1" (\a -> ite (a .== 0) 0 (1 + (f1 (a-1) + f2 (a-2))))
+                                                           f2 = smtFunction "f2" (\a -> ite (a .== 0) 0 (1 + (f2 (a-1) + f3 (a-2))))
+                                                           f3 = smtFunction "f3" (\a -> ite (a .== 0) 0 (1 + (f3 (a-1) + f4 (a-2))))
+                                                           f4 = smtFunction "f4" (\a -> ite (a .== 0) 0 (1 + (f4 (a-1) + f1 (a-2))))
+                                                       in f1 x .== (x :: SWord8)
+      , goldenCapturedIO "lambda57a" $ runSat $ \x -> let f1 = smtFunction "f1i" (\a -> ite (a .<= 0) 0 (1 + (f1 (a-1) + f2 (a-2))))
+                                                          f2 = smtFunction "f2i" (\a -> ite (a .<= 0) 0 (1 + (f2 (a-1) + f3 (a-2))))
+                                                          f3 = smtFunction "f3i" (\a -> ite (a .<= 0) 0 (1 + (f3 (a-1) + f4 (a-2))))
+                                                          f4 = smtFunction "f4i" (\a -> ite (a .<= 0) 0 (1 + (f4 (a-1) + f1 (a-2))))
+                                                      in f1 x .== (x :: SInteger)
+      , goldenCapturedIO "lambda57b" $ runSat $ \x -> let m a = 0 `smax` a :: SInteger
+                                                          f1 = smtFunctionWithMeasure "f1m" (m, []) (\a -> ite (a .<= 0) 0 (1 + (f1 (a-1) + f2 (a-2))))
+                                                          f2 = smtFunctionWithMeasure "f2m" (m, []) (\a -> ite (a .<= 0) 0 (1 + (f2 (a-1) + f3 (a-2))))
+                                                          f3 = smtFunctionWithMeasure "f3m" (m, []) (\a -> ite (a .<= 0) 0 (1 + (f3 (a-1) + f4 (a-2))))
+                                                          f4 = smtFunctionWithMeasure "f4m" (m, []) (\a -> ite (a .<= 0) 0 (1 + (f4 (a-1) + f1 (a-2))))
+                                                      in f1 x .== (x :: SInteger)
+      , goldenCapturedIO "lambda57c" $ runSat $ \x -> let m  = sFromIntegral :: SWord8 -> SInteger
+                                                          f1 = smtFunctionWithMeasure "f1w" (m, []) (\a -> ite (a .== 0) 0 (1 + (f1 (a-1) + f2 (a-2))))
+                                                          f2 = smtFunctionWithMeasure "f2w" (m, []) (\a -> ite (a .== 0) 0 (1 + (f2 (a-1) + f3 (a-2))))
+                                                          f3 = smtFunctionWithMeasure "f3w" (m, []) (\a -> ite (a .== 0) 0 (1 + (f3 (a-1) + f4 (a-2))))
+                                                          f4 = smtFunctionWithMeasure "f4w" (m, []) (\a -> ite (a .== 0) 0 (1 + (f4 (a-1) + f1 (a-2))))
+                                                      in f1 x .== (x :: SWord8)
+
+      -- Quantified axioms
+      , goldenCapturedIO "lambda58" $ record $ \st -> constraintStr st $ \(Forall b) (Exists c) -> sNot b .|| c
+      , goldenCapturedIO "lambda59" $ record $ \st -> constraintStr st $ \(Forall x) (Exists y) -> x .== (0 :: SInteger) .|| y
+
+      , goldenCapturedIO "lambda60" $ runAxSat   $ constrain $ \(Forall x) (Exists y) (Exists z) -> y .> (x+z :: SInteger)
+      , goldenCapturedIO "lambda61" $ runAxUnsat $ constrain $ \(Forall x) (Exists y) -> y .> (x :: SWord8)
+
+      -- Quantified booleans
+      , goldenCapturedIO "lambda62" $ \rf -> do m <- proveWith z3{verbose=True, redirectVerbose=Just rf} drinker
+                                                appendFile rf ("\nRESULT:\n" <> show m <> "\n")
+                                                `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\nEXCEPTION CAUGHT:\n" <> show e <> "\n"))
+
+      -- Special relations (kind of lambda related)
+      , goldenCapturedIO "lambda63" $ runP $         quantifiedBool (\(Forall x) -> rel (x, x))
+      , goldenCapturedIO "lambda64" $ runP $ po  .=> quantifiedBool (\(Forall x) -> rel (x, x))
+      , goldenCapturedIO "lambda65" $ runP $ poI .=> quantifiedBool (\(Forall x) -> leq (x, x))
+      , goldenCapturedIO "lambda66" $ runP $ let u   = uninterpret "U" :: Relation Integer
+                                                 tcU = mkTransitiveClosure "tcU" u
+                                             in quantifiedBool (\(Forall x) (Forall y) (Forall z)
+                                                                     -> (u (x, y) .&& u (y, z)) .=> tcU (x, z))
+
+      , goldenCapturedIO "lambda67" $ runP $ let u   = uninterpret "U" :: Relation Word8
+                                                 tcU = mkTransitiveClosure "tcU" u
+                                             in quantifiedBool (\(Forall x) (Forall y) (Forall z)
+                                                                     -> (u (x, y) .&& u (y, z)) .=> tcU (x, z))
+
+      -- Not really lambda related, but kind of fits in here
+      , goldenCapturedIO "lambda68" $ runS $ \(Forall x) -> uninterpret "F" x .== 2*x+(3::SInteger)
+      , goldenCapturedIO "lambda69" $ runS $ \(Forall x) (Forall y) -> uninterpret "F" x y .== 2*x+(3-y::SInteger)
+
+      -- Most skolems are tested inline, here's a fancy one!
+      -- This is satisfiable. A model for this will present two functions, x_eu1 and x_eu2
+      -- If these functions differ on all mappings i.e. forall x. x_eu1 x /= x_eu2 x, then
+      -- it would be a valid model for this problem. Note that these functions can
+      -- be constant functions mapping to different values; or functions that distinguish
+      -- some subset of inputs, so long as they map it to different values. Examples:
+      --    x_eu1 _ = 0      x_eu2 _ = 0
+      -- OR
+      --    x_eu1 1 = 0      x_eu2 1 = 1
+      --    x_eu1 _ = 1      x_eu2 _ = 0
+      --
+      -- are all good.
+      , goldenCapturedIO "lambda70" $
+                let phi :: ExistsUnique "x" Integer -> SBool
+                    phi (ExistsUnique  x) = x .== 0 .|| x .== 1
+
+                    nPhi :: Forall "x" Integer -> Exists "x_eu1" Integer -> Exists "x_eu2" Integer -> SBool
+                    nPhi = qNot phi
+
+                    snPhi :: Forall "x" Integer -> SBool
+                    snPhi = skolemize nPhi
+                in runS snPhi
+
+      , goldenCapturedIO "lambda71" $ \f -> sbv2smt def_foo >>= writeFile f
+      , goldenCapturedIO "lambda72" $ \f -> sbv2smt def_bar >>= writeFile f
+      , goldenCapturedIO "lambda73" $ \f -> sbv2smt def_baz >>= writeFile f
+      , goldenCapturedIO "lambda74" $ \f -> sbv2smt def_e   >>= writeFile f
+      , goldenCapturedIO "lambda75" $ \f -> sbv2smt def_o   >>= writeFile f
+
+      , goldenCapturedIO "lambda76" $ \f -> sbv2smt (2 :: SInteger)                    >>= writeFile f
+      , goldenCapturedIO "lambda77" $ \f -> sbv2smt (literal 'a' :: SChar)             >>= writeFile f
+      , goldenCapturedIO "lambda78" $ \f -> sbv2smt (literal [1,2,3] :: SList Integer) >>= writeFile f
+
+      , goldenCapturedIO "lambda79" $ \f -> sbv2smt def_t1 >>= writeFile f
+      , goldenCapturedIO "lambda80" $ \f -> sbv2smt def_t2 >>= writeFile f
+
+      , goldenCapturedIO "lambda81" $ regularRun filterHead
+
+      , goldenCapturedIO "lambda82" $ eval1 [1 .. 5 :: Integer] (   mapl (\x ->   map (\y -> x + y) (literal [4, 5, 6]))
+                                                                , P.map  (\x -> P.map (\y -> x + y)          [4, 5, 6])
+                                                                )
+
+      , goldenCapturedIO "lambda83" $ errorOut noFreeVars1
+      , goldenCapturedIO "lambda84" $ errorOut noFreeVars2
+
+      , goldenCapturedIO "lambda85" $ eval1 [1 .. 10 :: Integer] (partitionL (\x -> x `sMod` 2 .== 0), P.partition (\x -> x `mod` 2 == 0))
+      , goldenCapturedIO "lambda86" $ eval1 [1 .. 10 :: Integer] (partitionL (\x -> x `sMod` 2 ./= 0), P.partition (\x -> x `mod` 2 /= 0))
+
+      , let cls :: SInteger -> Closure SInteger (SInteger -> SInteger)
+            cls x = Closure { closureEnv = x
+                            , closureFun = \env y -> env + y
+                            }
+        in goldenCapturedIO "lambda87" $ eval2 [1 .. 3 :: Integer] [6 .. 8 :: Integer]
+                                               ( \xs ys ->   map (\x ->   map (cls x)       xs) ys
+                                               , \xs ys -> P.map (\x -> P.map (\y -> x + y) xs) ys
+                                               )
+
+      {- Disabled due to z3 bug: https://github.com/LeventErkok/sbv/issues/773
+      , let cls :: SList Integer -> Closure (SList Integer) (SList Integer -> SList Integer)
+            cls ys = Closure { closureEnv = ys
+                             , closureFun = \env xs -> xs ++ env
+                             }
+        in goldenCapturedIO "lambda88" $ eval2 [[1 .. 3 :: Integer], [4 .. 6 :: Integer]] [7 .. 9 :: Integer]
+                                               ( \xss ys ->   map (cls  ys) xss
+                                               , \xss ys -> P.map (P.++ ys) xss
+                                               )
+      -}
+      ]
+   P.++ qc1 "lambdaQC1" P.sum (foldr ((+) @SInteger) (0::SInteger))
+   P.++ qc2 "lambdaQC2" (+)  (smtFunction "sadd" ((+) :: SInteger -> SInteger -> SInteger))
+   P.++ qc1 "lambdaQC3" (\n -> let pn = abs n in (pn * (pn+1)) `sDiv` 2)
+                        (let ssum = smtFunction "ssum" $ \(n :: SInteger) -> let pn = abs n in ite (pn .== 0) 0 (pn + ssum (pn - 1)) in ssum)
+  where def_foo, def_bar, def_baz, def_e, def_o :: SInteger -> SInteger
+        def_foo = smtFunction "foo" $ \x -> def_bar (x-1)
+        def_bar = smtFunction "bar" $ \x -> def_bar (x-1)
+        def_baz = smtFunction "baz" $ \x -> x+1
+        def_e = smtFunction "e" $ \x -> def_o (x-1)
+        def_o = smtFunction "o" $ \x -> def_e (x-1)
+        def_t1 = smtFunction "foo" (\x -> select [1,2,3]       (0 :: SWord32)  (x::SInteger))
+        def_t2 = smtFunction "foo" (\x -> select [x+1,x+2,x+3] (0 :: SInteger) (x::SInteger))
+
+        mapl :: (SymVal a, SymVal b) => (SBV a -> SBV b) -> SList a -> SList b
+        mapl = map
+
+        foldlL :: (SymVal a, SymVal b) => (SBV b -> SBV a -> SBV b) -> SBV b -> SList a -> SBV b
+        foldlL = foldl
+
+        foldrL :: (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV b) -> SBV b -> SList a -> SBV b
+        foldrL = foldr
+
+        zipWithL :: (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b -> SBV c) -> SList a -> SList b -> SList c
+        zipWithL = zipWith
+
+        filterL :: SymVal a => (SBV a -> SBool) -> SList a -> SList a
+        filterL = filter
+
+        partitionL :: SymVal a => (SBV a -> SBool) -> SList a -> STuple [a] [a]
+        partitionL = partition
+
+        rel, leq :: Relation Integer
+        rel = uninterpret "R"
+        leq = P.uncurry $ smtFunction "leq" (.<=)
+        po  = isPartialOrder "poR" rel
+        poI = isPartialOrder "poI" leq
+
+        regularRun tc goldFile = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just goldFile} tc
+                                    appendFile goldFile ("\n FINAL:" <> show r <> "\nDONE!\n")
+
+        record :: (State -> IO String) -> FilePath -> IO ()
+        record gen rf = do st <- mkNewState defaultSMTCfg (LambdaGen (Just 0))
+                           appendFile rf . (P.++ "\n") =<< gen st
+
+        runP b rf = runGen proveWith b rf
+        runS b rf = runGen satWith   b rf
+        runGen a b rf = do m <- a z3{verbose=True, redirectVerbose=Just rf} b
+                           appendFile rf ("\nRESULT:\n" P.++ show m P.++ "\n")
+
+        runSat   f = runSatExpecting f Sat
+        runUnsat f = runSatExpecting f Unsat
+
+        runAxSat   f = runSatAxExpecting f Sat
+        runAxUnsat f = runSatAxExpecting f Unsat
+
+        runSatAxExpecting f what rf = do m <- runSMTWith z3{verbose=True, redirectVerbose=Just rf} run
+                                         appendFile rf ("\nRESULT:\n" P.++ m P.++ "\n")
+                                         `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\nEXCEPTION CAUGHT:\n" P.++ show e P.++ "\n"))
+           where run = do _ <- f
+                          query $ do cs <- checkSat
+                                     if cs /= what
+                                        then error $ "Unexpected output: " P.++ show cs
+                                        else if cs == Sat
+                                                then showModel z3 <$> getModel
+                                                else pure $ "All good, expecting: " P.++ show cs
+
+        runSatExpecting f what rf = do m <- runSMTWith z3{verbose=True, redirectVerbose=Just rf} run
+                                       appendFile rf ("\nRESULT:\n" P.++ m P.++ "\n")
+                                       `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\nEXCEPTION CAUGHT:\n" P.++ show e P.++ "\n"))
+           where run = do arg <- free_
+                          constrain $ f arg
+                          query $ do arg2 <- freshVar_
+                                     constrain $ f arg2
+                                     cs <- checkSat
+                                     if cs /= what
+                                        then error $ "Unexpected output: " P.++ show cs
+                                        else if cs == Sat
+                                                then showModel z3 <$> getModel
+                                                else pure $ "All good, expecting: " P.++ show cs
+
+        runSat2 f rf = do m <- runSMTWith z3{verbose=True, redirectVerbose=Just rf} run
+                          appendFile rf ("\nRESULT:\n" P.++ showModel z3 m P.++ "\n")
+           where run = do arg1 <- free_
+                          arg2 <- free_
+                          constrain $ f arg1 arg2
+                          query $ do arg3 <- freshVar_
+                                     arg4 <- freshVar_
+                                     constrain $ f arg3 arg4
+                                     cs <- checkSat
+                                     case cs of
+                                       Sat -> getModel
+                                       _   -> error $ "Unexpected output: " P.++ show cs
+
+
+eval1 :: (SymVal a, SymVal b, Show a, Show b, Eq b) => a -> (SBV a -> SBV b, a -> b) -> FilePath -> IO ()
+eval1 cArg sf rf = eval1Gen cArg sf rf z3{verbose=True, redirectVerbose=Just rf}
+
+eval1Gen :: (SymVal a, SymVal b, Show a, Show b, Eq b) => a -> (SBV a -> SBV b, a -> b) -> FilePath -> SMTConfig -> IO ()
+eval1Gen cArg (sFun, cFun) rf cfg = do m <- runSMTWith cfg run
+                                       appendFile rf ("\nRESULT:\n" P.++ showModel z3 m P.++ "\n")
+
+ where run = do arg <- free_
+                res <- free_
+                constrain $ arg .== literal cArg
+                constrain $ res .== sFun arg
+
+                let concResult = cFun cArg
+
+                query $ do
+                  cs <- checkSat
+                  case cs of
+                    Sat -> do resV <- getValue res
+                              unless (resV == concResult) $
+                                  error $ unlines [ "Bad output:"
+                                                  , "  arg      = " P.++ show cArg
+                                                  , "  concrete = " P.++ show concResult
+                                                  , "  symbolic = " P.++ show resV
+                                                  ]
+                              getModel
+                    _ -> error $ "Unexpected output: " P.++ show cs
+
+eval2 :: (SymVal a, SymVal b, SymVal c, Eq c, Show a, Show b, Show c) => a -> b -> (SBV a -> SBV b -> SBV c, a -> b -> c) -> FilePath -> IO ()
+eval2 cArg1 cArg2 (sFun, cFun) rf = do m <- runSMTWith z3{verbose=True, redirectVerbose=Just rf} run
+                                       appendFile rf ("\nRESULT:\n" P.++ showModel z3 m P.++ "\n")
+
+ where run = do arg1 <- free_
+                arg2 <- free_
+                res <- free_
+                constrain $ arg1 .== literal cArg1
+                constrain $ arg2 .== literal cArg2
+                constrain $ res  .== sFun arg1 arg2
+
+                let concResult = cFun cArg1 cArg2
+
+                query $ do
+                  cs <- checkSat
+                  case cs of
+                    Sat -> do resV <- getValue res
+                              unless (resV == concResult) $
+                                  error $ unlines [ "Bad output:"
+                                                  , "  arg1     = " P.++ show cArg1
+                                                  , "  arg2     = " P.++ show cArg2
+                                                  , "  concrete = " P.++ show concResult
+                                                  , "  symbolic = " P.++ show resV
+                                                  ]
+                              getModel
+                    _ -> error $ "Unexpected output: " P.++ show cs
+
+-- Tests that error out
+errorOut :: (SMTConfig -> IO a) -> FilePath -> IO ()
+errorOut t rf = void (t z3{verbose=True, redirectVerbose=Just rf})
+                    `C.catch` \(e::C.SomeException) -> do appendFile rf "CAUGHT EXCEPTION\n\n"
+                                                          appendFile rf (show e)
+
+-- No free vars
+noFreeVars1 :: SMTConfig -> IO SatResult
+noFreeVars1 cfg = satWith cfg $ do
+        zs :: SList [Integer] <- free_
+        xs :: SList Integer   <- free_
+        ys :: SList Integer   <- free_
+        constrain $ xs .== literal [1,2,3::Integer]
+        constrain $ ys .== literal [3,4,5::Integer]
+        pure $ zs .== map (\(x :: SInteger) -> map (\(y :: SInteger) -> x+y) ys) xs
+
+-- No free vars
+noFreeVars2 :: SMTConfig -> IO ThmResult
+noFreeVars2 cfg = proveWith cfg $ do
+   let ae :: SList [Integer] -> SList Integer -> SList [Integer]
+       ae xs ys = map (++ ys) xs
+
+   xs <- free_
+   ys <- free_
+   pure $ map (ae xs) ys .== []
+
+-- This one is ok, because we're using the global xs. (i.e., no free vars)
+filterHead :: Symbolic String
+filterHead = do
+        xs :: SList Integer <- free_
+        constrain $ filter (.> (head xs :: SInteger)) xs ./= filter (.> (4 :: SInteger)) xs
+        query $ do cs <- checkSat
+                   case cs of
+                     Sat -> showModel z3 <$> getModel
+                     _   -> pure $ "Unexpected result: " <> show cs
+
+
+{- HLint ignore module "Use map once"   -}
+{- HLint ignore module "Use sum"        -}
+{- HLint ignore module "Fuse foldr/map" -}
+{- HLint ignore module "Use zipWith"    -}
+{- HLint ignore module "Use uncurry"    -}
+{- HLint ignore module "Use even"       -}
+{- HLint ignore module "Use odd"        -}
+{- HLint ignore module "Use product"    -}
+{- HLint ignore module "Avoid lambda"   -}
+{- HLint ignore module "Eta reduce"     -}
diff --git a/SBVTestSuite/TestSuite/Basics/List.hs b/SBVTestSuite/TestSuite/Basics/List.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/List.hs
@@ -0,0 +1,170 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.List
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the sequence/list functions.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.List(tests)  where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import qualified Control.Exception as C
+
+import           Prelude hiding ((++), (!!))
+import qualified Prelude as P   ((++))
+
+import Data.SBV.List ((!!), (++))
+import qualified Data.SBV.List as L
+
+import Control.Monad (unless)
+import Data.Maybe (catMaybes)
+import Data.List (sort)
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.List" [
+      goldenCapturedIO "seqConcat"     $ \rf -> checkWith z3{redirectVerbose=Just rf} seqConcatSat    Sat
+    , goldenCapturedIO "seqConcatBad"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqConcatUnsat  Unsat
+    , goldenCapturedIO "seqIndexOf"    $ \rf -> checkWith z3{redirectVerbose=Just rf} seqIndexOfSat   Sat
+    , goldenCapturedIO "seqIndexOfBad" $ \rf -> checkWith z3{redirectVerbose=Just rf} seqIndexOfUnsat Unsat
+    , goldenCapturedIO "seqExamples1"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples1    Sat
+    , goldenCapturedIO "seqExamples2"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples2    Unsat
+    , goldenCapturedIO "seqExamples3"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples3    Sat
+    , goldenCapturedIO "seqExamples4"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples4    Sat
+    , goldenCapturedIO "seqExamples5"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples5    Sat
+    , goldenCapturedIO "seqExamples6"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples6    Unsat
+    , goldenCapturedIO "seqExamples7"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples7    Sat
+    , goldenCapturedIO "seqExamples8"  $ \rf -> checkWith z3{redirectVerbose=Just rf} seqExamples8    Unsat
+    , goldenCapturedIO "listFloat1"    $ run listFloat1
+    , goldenCapturedIO "listFloat2"    $ run listFloat2
+    , goldenCapturedIO "listFloat3"    $ run listFloat3
+    , testCase         "seqExamples9"  $ assert seqExamples9
+    ]
+
+checkWith :: SMTConfig -> Symbolic () -> CheckSatResult -> IO ()
+checkWith 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"
+                       DSat{} -> error "Failed! Expected Sat, got delta-sat"
+                       Sat    -> getModel         >>= \r -> error $ "Failed! Expected Unsat, got SAT:\n" P.++ show (SatResult (Satisfiable cfg r))
+                       Unk    -> getUnknownReason >>= \r -> error $ "Failed! Expected Unsat, got UNK:\n" P.++ show r
+
+seqConcatSat :: Symbolic ()
+seqConcatSat = constrain $ [sEnum|1..3|] ++ [sEnum|4..6|] .== ([sEnum|1..6|] :: SList Integer)
+
+seqConcatUnsat :: Symbolic ()
+seqConcatUnsat = constrain $ [sEnum|1..3|] ++ [sEnum|4..6|] .== ([sEnum|1..7|] :: SList Integer)
+
+seqIndexOfSat :: Symbolic ()
+seqIndexOfSat = constrain $ L.indexOf ([1,2,3,1,2,3] :: SList Integer) [1] .== 0
+
+seqIndexOfUnsat :: Symbolic ()
+seqIndexOfUnsat = constrain $ L.indexOf ([1,2,3,1,2,3] :: SList Integer) [1] ./= 0
+
+-- Basic sequence operations
+seqExamples1 :: Symbolic ()
+seqExamples1 = constrain $ sAnd
+  [ L.singleton (([1,2,3] :: SList Integer) !! 1) ++ L.singleton (([1,2,3] :: SList Integer) !! 0) .== [2,1]
+  , ([1,2,3,1,2,3] :: SList Integer) `L.indexOf` [1]                                               .== 0
+  , L.offsetIndexOf ([1,2,3,1,2,3] :: SList Integer) [1] 1                                         .== 3
+  , L.subList ([4,4,1,2,3,5,5] :: SList Integer)     2 3                                           .== [1,2,3]
+  ]
+
+-- A list cannot overlap with two different elements
+seqExamples2 :: Symbolic ()
+seqExamples2 = do
+  a :: SList Integer <- sList "a"
+  constrain $ a ++ [2] .== [1] ++ a
+
+-- Strings a, b, c can have a non-trivial overlap.
+seqExamples3 :: Symbolic ()
+seqExamples3 = do
+  [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
+  constrain $ a ++ b .== [sEnum|1..4|]
+  constrain $ b ++ c .== [sEnum|3..6|]
+  constrain $ sNot $ b .== []
+
+-- There is a solution to a of length at most 2.
+seqExamples4 :: Symbolic ()
+seqExamples4 = do
+  [a, b :: SList Integer] <- sLists ["a", "b"]
+  constrain $ [sEnum|1..3|] ++ a .== b ++ [sEnum|3..5|]
+  constrain $ L.length a .<= 2
+
+-- There is a solution to a that is not a sequence of 1's.
+seqExamples5 :: Symbolic ()
+seqExamples5 = do
+  [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
+  constrain $ a ++ [1,2] ++ b .== b ++ [2,1] ++ c
+  constrain $ c .== a ++ b
+  constrain $ sNot $ a ++ [1] .== [1] ++ a
+
+-- Contains is transitive.
+seqExamples6 :: Symbolic ()
+seqExamples6 = do
+  [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
+  constrain $ b `L.isInfixOf` a
+  constrain $ c `L.isInfixOf` b
+  constrain $ sNot $ c `L.isInfixOf` a
+
+-- But containment is not a linear order.
+seqExamples7 :: Symbolic ()
+seqExamples7 = do
+  [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
+  constrain $ b `L.isInfixOf` a
+  constrain $ c `L.isInfixOf` a
+  constrain $ sNot $ c `L.isInfixOf` b
+  constrain $ sNot $ b `L.isInfixOf` c
+
+-- Any string is equal to the prefix and suffix that add up to its length.
+seqExamples8 :: Symbolic ()
+seqExamples8 = do
+  [a, b, c :: SList Integer] <- sLists ["a", "b", "c"]
+  constrain $ b `L.isPrefixOf` a
+  constrain $ c `L.isSuffixOf` a
+  constrain $ L.length a .== L.length b + L.length c
+  constrain $ sNot $ a .== b ++ c
+
+-- Generate all length one sequences, to enumerate all and making sure we can parse correctly
+seqExamples9 :: IO Bool
+seqExamples9 = do m <- allSat $ do (s :: SList Word8) <- sList "s"
+                                   return $ L.length s .== 1
+
+                  let vals :: [Word8]
+                      vals = sort $ concat (catMaybes (getModelValues "s" m) :: [[Word8]])
+
+                  return $ vals == [0..255]
+
+run :: Provable a => a -> FilePath -> IO ()
+run t gf = do r <- proveWith defaultSMTCfg{verbose=True, redirectVerbose = Just gf} t
+              appendFile gf ("\nFINAL OUTPUT:\n" <> show r <> "\n")
+        `C.catch` (\(e :: C.SomeException) -> appendFile gf ("\nEXCEPTION:\n" <> show e <> "\n"))
+
+listFloat1 :: Symbolic SBool
+listFloat1 = do x :: SFloat <- free "x"
+                pure $ L.singleton x .== L.singleton x
+
+listFloat2 :: Symbolic SBool
+listFloat2 = do x :: SFloat <- free "x"
+                pure $ L.singleton x `L.listEq` L.singleton x
+
+listFloat3 :: Symbolic SBool
+listFloat3 = do x :: SFloat <- free "x"
+                pure $ L.singleton x .=== L.singleton x
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,67 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ModelValidate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Few validate tests
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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" testABC
+           ]
+    where testABC goldFile = do r <- satWith abc{verbose=True, redirectVerbose = Just goldFile, validateModel = True} (free "x" >>= \x -> pure $ 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, t2 :: Predicate
+          t1 = free "x" >>= \x -> pure $ fpAdd sRTZ x x   .== (x::SFloat)
+          t2 = free "x" >>= \x -> pure $ fpFMA sRNE x x x .== (x::SFloat)
+
+          t3 :: Predicate
+          t3 = do x <- sInteger "x"
+                  constrain $ x .> x   -- Constraining with False! i.e., any theorem will follow, and will be trivially unsat
+                  pure sFalse
+
+          t4 :: Predicate
+          t4 = do x <- sInteger "x"
+                  y <- sInteger "y"
+                  constrain $ x .> y
+                  constrain $ x .> 12
+                  return $ x .== y+3
+
+          t5 :: Predicate
+          t5 = do x <- free "x"
+                  pure $ quantifiedBool $ \(Forall y) -> fpIsPoint y .=> x .<= (y::SFloat)
diff --git a/SBVTestSuite/TestSuite/Basics/Nonlinear.hs b/SBVTestSuite/TestSuite/Basics/Nonlinear.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Nonlinear.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Nonlinear
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Some nonlinear tests, z3 and CVC5
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Nonlinear (tests)  where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.Nonlinear" [
+          goldenCapturedIO "nonlinear_z3"   $ check z3
+        , goldenCapturedIO "nonlinear_cvc4" $ check cvc4
+        , goldenCapturedIO "nonlinear_cvc5" $ check cvc5
+        ]
+    where check s gf = do r <- satWith s{verbose = True, redirectVerbose = Just gf} f
+                          appendFile gf ("\nFINAL:\n" ++ show r ++ "\nDONE!\n")
+
+          f :: SReal -> SBool
+          f x = x * x .== 2
diff --git a/SBVTestSuite/TestSuite/Basics/ProofTests.hs b/SBVTestSuite/TestSuite/Basics/ProofTests.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ProofTests.hs
@@ -0,0 +1,53 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ProofTests
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.ProofTests
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.ProofTests(tests)  where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Basics.Proof"
+    [ testCase "proofs-1" (assertIsThm   f1eqf2)
+    , testCase "proofs-2" (assertIsntThm f1eqf3)
+    , testCase "proofs-3" (assertIsThm   f3eqf4)
+    , testCase "proofs-4" (assertIsThm   f1Single)
+    , testCase "proofs-5" (assertIsSat   (f1 `xyEq` f2))
+    , testCase "proofs-6" (assertIsSat   (f1 `xyEq` f3))
+    , testCase "proofs-7" (assertIsntSat (free "x" >>= \x -> return (x .== x + (1 :: SWord16))))
+    , testCase "proofs-8" (assertIsSat   (free "x" >>= \x -> return (x :: SBool)))
+    , testCase "proofs-9" (assertIsSat   (free "x" >>= \x -> return x :: Predicate))
+    ]
+
+xyEq :: (EqSymbolic a, SymVal a1) => (SBV a1 -> SBV Word8 -> a) -> (SBV a1 -> SWord8 -> a) -> Symbolic SBool
+func1 `xyEq` func2 = do x <- free_
+                        y <- free_
+                        return $ func1 x y .== func2 x (y :: SWord8)
+
+f1, f2, f3, f4 :: Num a => a -> a -> a
+f1 x y = (x+y)*(x-y)
+f2 x y = (x*x)-(y*y)
+f3 x y = (x+y)*(x+y)
+f4 x y = x*x + 2*x*y + y*y
+
+f1eqf2 :: Predicate
+f1eqf2 = pure $ quantifiedBool $ \(Forall x) (Forall y) -> f1 x y .== f2 x (y :: SWord8)
+
+f1eqf3 :: Predicate
+f1eqf3 = pure $ quantifiedBool $ \(Forall x) (Forall y) -> f1 x y .== f3 x (y :: SWord8)
+
+f3eqf4 :: Predicate
+f3eqf4 = pure $ quantifiedBool $ \(Forall x) (Forall y) -> f3 x y .== f4 x (y :: SWord8)
+
+f1Single :: Predicate
+f1Single = pure $ quantifiedBool $ \(Forall x) -> f1 x x .== (0 :: SWord16)
diff --git a/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs b/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.PseudoBoolean
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the pseudo-boolean functions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-incomplete-uni-patterns #-}
+
+module TestSuite.Basics.PseudoBoolean(tests)  where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.pseudoBoolean" [
+      goldenCapturedIO "pbAtMost"          $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbAtMost
+    , goldenCapturedIO "pbAtLeast"         $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbAtLeast
+    , goldenCapturedIO "pbExactly"         $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbExactly
+    , goldenCapturedIO "pbLe"              $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbLe
+    , goldenCapturedIO "pbGe"              $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbGe
+    , goldenCapturedIO "pbEq"              $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbEq
+    , goldenCapturedIO "pbEq2"             $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbEq2
+    , goldenCapturedIO "pbMutexed"         $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbMutexed
+    , goldenCapturedIO "pbStronglyMutexed" $ \rf -> checkWith z3{redirectVerbose=Just rf} propPbStronglyMutexed
+    ]
+
+-- to test interactively, use:
+--    checkWith z3 propPbAtLeast
+
+checkWith :: SMTConfig -> ([SBool] -> SBool) -> IO ()
+checkWith cfg spec = runSMTWith cfg{verbose=True} $ do
+        bs <- sBools $ map (\i -> "b" ++ show i) [0..(9::Int)]
+        constrain $ sNot (spec bs)
+        query $ do cs <- checkSat
+                   case cs of
+                     Unsat  -> return ()
+                     DSat{} -> error "Expected Unsat, got delta-sat"
+                     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
+
+propPbAtMost :: [SBool] -> SBool
+propPbAtMost bs = pbAtMost bs 8 .== (sum (map oneIf bs) .<= (8::SWord32))
+
+propPbAtLeast :: [SBool] -> SBool
+propPbAtLeast bs = pbAtLeast bs 5 .== (sum (map oneIf bs) .>= (5::SWord32))
+
+propPbExactly :: [SBool] -> SBool
+propPbExactly bs = pbExactly bs 5 .== (sum (map oneIf bs) .== (5::SWord32))
+
+propPbLe :: [SBool] -> SBool
+propPbLe bs = pbLe ibs 7 .== (sum (map valIf ibs) .<= (7::SInteger))
+  where ibs = zip [1..] bs
+        valIf (i, b) = ite b (literal (fromIntegral i)) 0
+
+propPbGe :: [SBool] -> SBool
+propPbGe bs = pbGe ibs 7 .== (sum (map valIf ibs) .>= (7::SInteger))
+  where ibs = zip [1..] bs
+        valIf (i, b) = ite b (literal (fromIntegral i)) 0
+
+propPbEq :: [SBool] -> SBool
+propPbEq bs = pbEq ibs 7 .== (sum (map valIf ibs) .== (7::SInteger))
+  where ibs = zip [1..] bs
+        valIf (i, b) = ite b (literal (fromIntegral i)) 0
+
+-- Reported here as a bug <http://github.com/Z3Prover/z3/issues/1571>
+-- and SBV didn't catch this. So let's add it as a test case.
+propPbEq2 :: [SBool] -> SBool
+propPbEq2 bs = (c1 .&& c2) .=> (   ([a, b, c, d, e] .== [sFalse, sTrue, sFalse, sTrue, sFalse])
+                               .|| ([a, b, c, d, e] .== [sFalse, sTrue, sFalse, sFalse, sTrue]))
+  where ~(a : b : c : d : e : _) = take 5 bs
+        c1 = ite a (pbEq [(1, b), (1, c)]         3) (pbEq [(1, b), (1, c)]         1)
+        c2 = ite c (pbEq [(1, a), (1, d), (1, e)] 3) (pbEq [(1, a), (1, d), (1, e)] 1)
+
+propPbMutexed :: [SBool] -> SBool
+propPbMutexed bs = pbMutexed bs .== (sum (map oneIf bs) .<= (1::SWord32))
+
+propPbStronglyMutexed :: [SBool] -> SBool
+propPbStronglyMutexed bs = pbStronglyMutexed bs .== (sum (map oneIf bs) .== (1::SWord32))
diff --git a/SBVTestSuite/TestSuite/Basics/QRem.hs b/SBVTestSuite/TestSuite/Basics/QRem.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/QRem.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.QRem
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Basics.QRem
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.QRem(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Basics.QRem"
+    [ testCase "qremW8" (assertIsThm (qrem :: SWord8   -> SWord8   -> SBool))
+    , testCase "qremI8" (assertIsThm (qrem :: SInt8    -> SInt8    -> SBool))
+    , testCase "qremI"  (assertIsThm (qrem :: SInteger -> SInteger -> SBool))
+    ]
+
+-- check: if (a, b) = x `quotRem` y then x = y*a + b
+-- same is also true for divMod
+-- being careful about y = 0. When divisor is 0, then quotient is
+-- defined to be 0 and the remainder is the numerator
+qrem :: (Num a, EqSymbolic a, SDivisible a) => a -> a -> SBool
+qrem x y = ite (y .== 0)
+               ((0, x) .== (q, r) .&& (0, x) .== (d, m))
+               (x .== y * q + r .&& x .== y * d + m)
+  where (q, r) = x `sQuotRem` y
+        (d, m) = x `sDivMod` y
diff --git a/SBVTestSuite/TestSuite/Basics/Quantifiers.hs b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
@@ -0,0 +1,86 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Quantifiers
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Various combinations of quantifiers
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Quantifiers(tests) where
+
+import Control.Monad (void)
+
+import Utils.SBVTestFramework
+
+data Q = E  -- exists
+       | A  -- all
+
+instance Show Q where
+   show E = "exists"
+   show A = "forall"
+
+tests :: TestTree
+tests = testGroup "Basics.Quantifiers" $ concatMap mkGoal goals ++ concatMap mkPred preds ++ others
+   where mkGoal (g, nm) = [ goldenCapturedIO ("quantified_sat"   ++ "_" ++ nm) $ \rf -> void $ satWith   z3{verbose=True, redirectVerbose=Just rf} g
+                          ]
+         mkPred (p, nm) = [ goldenCapturedIO ("quantified_sat"   ++ "_" ++ nm) $ \rf -> void $ satWith   z3{verbose=True, redirectVerbose=Just rf} p
+                          , goldenCapturedIO ("quantified_prove" ++ "_" ++ nm) $ \rf -> void $ proveWith z3{verbose=True, redirectVerbose=Just rf} p
+                          ]
+
+         others = [ goldenCapturedIO "quantifiedB_0" $ check $ \(ExistsN @4 xs)   -> sAll (.< (20 :: SWord8)) xs .&& sum (1 : xs) .== (0::SWord8)
+                  , goldenCapturedIO "quantifiedB_1" $ check $ \(ExistsN @4 xs)   -> sum xs .== (0::SWord8)
+                  , goldenCapturedIO "quantifiedB_2" $ check $ \k (ForallN @4 xs) -> sum xs .== (k::SWord8)
+                  , goldenCapturedIO "quantifiedB_3" $ check $ \k (ExistsN @4 xs) -> sum xs .== (k::SWord8)
+                  , goldenCapturedIO "quantifiedB_4" $ check $ \(ExistsN @4 xs) (Exists k) -> sum xs .== (k::SWord8)
+                  , goldenCapturedIO "quantifiedB_5" $ check $ \(ExistsN @4 xs) (Forall k) -> sum xs .== (k::SWord8)
+                  , goldenCapturedIO "quantifiedB_6" $ check $ quantifiedBool (quantifiedBool (\(Exists (x::SBool)) -> x) )
+                  , goldenCapturedIO "quantifiedB_7" $ check $ \(Exists (x :: SBool)) -> quantifiedBool (quantifiedBool (\(Exists (y::SBool)) -> x .|| y) )
+                  , goldenCapturedIO "quantifiedB_8" $ check $ \(Exists (x :: SBool)) -> quantifiedBool (\(Exists (y::SBool)) -> x .|| y)
+                  , goldenCapturedIO "quantifiedB_9" $ check $ quantifiedBool $ \(Exists (x :: SBool)) -> quantifiedBool (\(Exists (y::SBool)) -> x .|| y)
+                  , goldenCapturedIO "quantifiedB_A" $ check $ \(Exists a) (Forall b) (Exists c) (Forall d) ->  a + b + c + d .== (0::SInteger)
+                  , goldenCapturedIO "quantifiedB_B" $ check $ \(Forall a) (Exists b) (Forall c) (Exists d) ->  a + b + c + d .== (0::SInteger)
+                  ]
+           where check p rf = do res <- satWith z3{verbose=True, redirectVerbose=Just rf} p
+                                 appendFile rf $ "\nRESULT: "  ++ show res ++ "\n"
+
+         qs   = [E, A]
+
+         acts = [ (\x y -> x + (y - x) .== y  , "thm")
+                , (\x y -> x .== y .&& x ./= y, "contradiction")
+                , (\x y -> x .== y + 1        , "satisfiable")
+                ]
+
+         goals = [(t1 q1 q2 a, show q1 ++ show q2 ++ "_" ++ an ++ "_c") | q1      <- qs
+                                                                        , q2      <- qs
+                                                                        , (a, an) <- acts
+                                                                        ]
+
+         preds = [(t2 q1 q2 a, show q1 ++ show q2 ++ "_" ++ an ++ "_p") | q1       <- qs
+                                                                        , q2       <- qs
+                                                                        , (a, an)  <- acts
+                                                                        ]
+
+         t1 :: Q -> Q -> (SWord8 -> SWord8 -> SBool) -> ConstraintSet
+         t1 E E act = constrain $ \(Exists x) (Exists y) -> act x y
+         t1 E A act = constrain $ \(Exists x) (Forall y) -> act x y
+         t1 A E act = constrain $ \(Forall x) (Exists y) -> act x y
+         t1 A A act = constrain $ \(Forall x) (Forall y) -> act x y
+
+         t2 :: Q -> Q -> (SWord8 -> SWord8 -> SBool) -> Predicate
+         t2 E E act = pure $ quantifiedBool $ \(Exists x) (Exists y) -> act x y
+         t2 E A act = pure $ quantifiedBool $ \(Exists x) (Forall y) -> act x y
+         t2 A E act = pure $ quantifiedBool $ \(Forall x) (Exists y) -> act x y
+         t2 A A act = pure $ quantifiedBool $ \(Forall x) (Forall y) -> act x y
+
+{- HLint ignore module "Reduce duplication"     -}
+{- HLint ignore module "Unused LANGUAGE pragma" -}
diff --git a/SBVTestSuite/TestSuite/Basics/Recursive.hs b/SBVTestSuite/TestSuite/Basics/Recursive.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Recursive.hs
@@ -0,0 +1,469 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Recursive
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Some recursive definitions.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Recursive(tests) where
+
+import Utils.SBVTestFramework
+
+import Data.SBV.Internals  (genMkSymVar, unSBV, VarContext(..))
+
+import Data.List (isInfixOf)
+
+import qualified Data.SBV.List as L
+import qualified Data.SBV.Dynamic as D
+import Data.SBV.TP (runTPWith, lemma)
+
+import qualified Control.Exception as C
+
+import Documentation.SBV.Examples.Misc.Definitions (ack)
+import Documentation.SBV.Examples.TP.McCarthy91    (mcCarthy91)
+
+-- This is recursive and can't be symbolically simulated for arbitrary inputs.
+-- But we can still prove a few things about it!
+mgcd :: SWord8 -> SWord8 -> SWord8
+mgcd a b = [sCase| b of
+              _ | b .== 0 -> a
+              _           -> mgcd b (a `sMod` b)
+           |]
+
+-- Same construction, expressed in terms of the dynamic interface
+mgcdDyn :: Int -> IO ThmResult
+mgcdDyn i = D.proveWith z3 $ do
+
+              let var8 :: String -> Symbolic D.SVal
+                  var8 nm = unSBV <$> genMkSymVar word8 (NonQueryVar (Just D.ALL)) (Just nm)
+
+                  word8   = KBounded False 8
+                  zero8   = D.svInteger word8 0
+
+                  gcdDyn a b = D.svIte (b `D.svEqual` zero8) a (gcdDyn b (a `D.svRem` b))
+
+              x <- var8 "x"
+
+              let prop0 = gcdDyn zero8 x `D.svEqual` x
+                  prop1 = gcdDyn x zero8 `D.svEqual` x
+
+              return $  if i == 0 then prop0 else prop1
+
+checkThm :: ThmResult -> Assertion
+checkThm r = assert isThm
+  where isThm = case r of
+                  ThmResult Unsatisfiable{} -> return True :: IO Bool
+                  ThmResult Satisfiable{}   -> return False
+                  _                         -> error "checkThm: Unexpected result!"
+
+-- | Test that auto-guess succeeds for an integer-recursive function (abs measure)
+autoGuessInteger :: Assertion
+autoGuessInteger = assertIsSat $ \(x :: SInteger) -> f x .== x
+  where f :: SInteger -> SInteger
+        f = smtFunction "autoGuessIntF" $ \x -> ite (x .<= 0) 0 (1 + f (x - 1))
+
+-- | Test that auto-guess succeeds for a list-recursive function (length measure)
+autoGuessList :: Assertion
+autoGuessList = assertIsSat $ \(xs :: SList Integer) -> myLen xs .>= 0
+  where myLen :: SList Integer -> SInteger
+        myLen = smtFunction "autoGuessListLen" $ \xs ->
+                  ite (L.null xs) 0 (1 + myLen (L.tail xs))
+
+-- | Test that auto-guess fails when candidates exist but don't work (Ackermann)
+autoGuessFailCandidates :: Assertion
+autoGuessFailCandidates = do
+  r <- C.try $ sat $ \(x :: SInteger) (y :: SInteger) -> ack' x y .== 0
+  case r of
+    Left (e :: C.SomeException) -> if "Cannot determine a termination measure" `isInfixOf` show e
+                                      then pure ()
+                                      else assertFailure $ "Unexpected exception: " ++ show e
+    Right _                     -> assertFailure "Expected error for Ackermann auto-guess"
+  where ack' :: SInteger -> SInteger -> SInteger
+        ack' = smtFunction "ackermann" $ \m n ->
+                ite (m .== 0) (n + 1)
+                    (ite (n .== 0) (ack' (m - 1) 1)
+                                   (ack' (m - 1) (ack' m (n - 1))))
+
+-- | Test that auto-guess fails when no candidates can be derived (non-integer, non-list args)
+autoGuessNoCandidates :: Assertion
+autoGuessNoCandidates = do
+  r <- C.try $ sat $ \(b :: SBool) -> h b .== 0
+  case r of
+    Left (e :: C.SomeException) -> if "No measure candidates" `isInfixOf` show e
+                                      then pure ()
+                                      else assertFailure $ "Unexpected exception: " ++ show e
+    Right _                     -> assertFailure "Expected error for no-candidate auto-guess"
+  where h :: SBool -> SInteger
+        h = smtFunction "noCandidate" $ \b -> ite b (1 + h (sNot b)) 0
+
+-- | Test that a non-recursive smtFunction without a measure is accepted
+nonRecursiveNoMeasure :: Assertion
+nonRecursiveNoMeasure = assertIsSat $ \(x :: SInteger) -> g x .== 4
+  where g :: SInteger -> SInteger
+        g = smtFunction "nonRecG" $ \x -> 2 * x
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.Recursive"
+   [ testCase "recursive1"                $ assertIsThm $ \x -> mgcd    0 x .== x
+   , testCase "recursive2"                $ assertIsThm $ \x -> mgcd    x 0 .== x
+   , testCase "recursiveDyn1"             $ checkThm =<< mgcdDyn 0
+   , testCase "recursiveDyn2"             $ checkThm =<< mgcdDyn 1
+   , testCase "autoGuessInteger"          autoGuessInteger
+   , testCase "autoGuessList"             autoGuessList
+   , testCase "autoGuessFailCandidates"   autoGuessFailCandidates
+   , testCase "autoGuessNoCandidates"     autoGuessNoCandidates
+   , testCase "nonRecursiveNoMeasure"     nonRecursiveNoMeasure
+
+   -- Test that an explicit measure that doesn't decrease is rejected
+   , goldenCapturedIO "recursive3_badMeasure" $ \rf -> do
+        let badSum :: SInteger -> SInteger
+            badSum = smtFunctionWithMeasure "badSum" (\_ -> 1 :: SInteger, [])
+                   $ \x -> ite (x .<= 0) 0 (x + badSum (x - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> badSum x .>= 0
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that lexicographic measure auto-guess works for Ackermann (nested recursion)
+   , goldenCapturedIO "recursive1_ack" $ \rf -> do
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \y r -> y .== (5 :: SInteger) .&& r .== ack 1 y
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that explicit measure works for enumFromThenTo.down (descending enumeration)
+   , goldenCapturedIO "recursive2_enum" $ \rf -> do
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> L.length [sEnum|(5::SInteger), 4 .. x|] .>= 0
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that contract-based measure works for McCarthy91 (nested recursion)
+   , goldenCapturedIO "recursive4_mcCarthy91" $ \rf -> do
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> mcCarthy91 n .== (91 :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that a bad contract is rejected (contract says result is always 0, which is wrong)
+   , goldenCapturedIO "recursive5_badContract" $ \rf -> do
+        let mc91bad :: SInteger -> SInteger
+            mc91bad = smtFunctionWithContract "mc91bad"
+                        ( \n -> 0 `smax` (101 - n)
+                        , \_ r -> r .== 0
+                        , []
+                        )
+                    $ \n -> ite (n .> 100) (n - 10) (mc91bad (mc91bad (n + 11)))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> mc91bad n .>= 0
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that a true-but-useless contract is rejected (contract is trivially True,
+   -- so the IH provides no information about recursive call results, and the measure
+   -- decrease for the outer call can't be proven)
+   , goldenCapturedIO "recursive6_uselessContract" $ \rf -> do
+        let mc91triv :: SInteger -> SInteger
+            mc91triv = smtFunctionWithContract "mc91triv"
+                         ( \n -> 0 `smax` (101 - n)
+                         , \_ _ -> sTrue
+                         , []
+                         )
+                     $ \n -> ite (n .> 100) (n - 10) (mc91triv (mc91triv (n + 11)))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> mc91triv n .>= 0
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that a productive function (guarded recursion) is accepted
+   , goldenCapturedIO "recursive7_productive" $ \rf -> do
+        let rep :: SInteger -> SInteger -> SList Integer
+            rep = smtProductiveFunction "rep" $ \n x ->
+                    ite (n .<= 0) L.nil (x L..: rep (n - 1) x)
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> L.length (rep 3 x) .== 3
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that a non-guarded function marked productive is rejected
+   , goldenCapturedIO "recursive8_badProductive" $ \rf -> do
+        let bad :: SInteger -> SInteger
+            bad = smtProductiveFunction "bad" $ \n -> ite (n .== 0) 0 (1 + bad (n - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> bad n .>= 0
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that a multi-arg productive function (guarded recursion) is accepted
+   , goldenCapturedIO "recursive9_productive2" $ \rf -> do
+        let countdown :: SInteger -> SList Integer
+            countdown = smtProductiveFunction "countdown" $ \n ->
+                          ite (n .<= 0) (L.singleton 0) (n L..: countdown (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> L.head (countdown n) .== (n :: SInteger) .&& n .> 0
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual recursion (2-way): mf calls mg, mg calls mf, neither is self-recursive.
+   -- No measure check should fire. The SMTLib emission should use define-funs-rec.
+   , goldenCapturedIO "recursive10_mutual" $ \rf -> do
+        let mf :: SInteger -> SInteger
+            mf = smtFunction "mf" $ \n -> ite (n .<= 0) 0 (1 + mg (n - 1))
+            mg :: SInteger -> SInteger
+            mg = smtFunction "mg" $ \n -> ite (n .<= 0) 0 (1 + mf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> mf x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test chain recursion (3-way): ca calls cb, cb calls cc, cc calls ca.
+   -- No measure check should fire. The SMTLib emission should use define-funs-rec.
+   , goldenCapturedIO "recursive11_chain" $ \rf -> do
+        let ca :: SInteger -> SInteger
+            ca = smtFunction "ca" $ \n -> ite (n .<= 0) 0 (1 + cb (n - 1))
+            cb :: SInteger -> SInteger
+            cb = smtFunction "cb" $ \n -> ite (n .<= 0) 0 (1 + cc (n - 1))
+            cc :: SInteger -> SInteger
+            cc = smtFunction "cc" $ \n -> ite (n .<= 0) 0 (1 + ca (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> ca x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test bad mutual recursion: bf calls bg with (n+1), so no measure can decrease.
+   , goldenCapturedIO "recursive12_badMutual" $ \rf -> do
+        let bf :: SInteger -> SInteger
+            bf = smtFunction "bf" $ \n -> ite (n .<= 0) 0 (1 + bg (n + 1))
+            bg :: SInteger -> SInteger
+            bg = smtFunction "bg" $ \n -> ite (n .<= 0) 0 (1 + bf (n - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> bf x .== (x :: SInteger)
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual recursion with explicit measures: ef calls eg, eg calls ef, both decreasing.
+   , goldenCapturedIO "recursive13_mutualMeasure" $ \rf -> do
+        let ef :: SInteger -> SInteger
+            ef = smtFunctionWithMeasure "ef" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + eg (n - 1))
+            eg :: SInteger -> SInteger
+            eg = smtFunctionWithMeasure "eg" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + ef (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> ef x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual recursion with explicit measure that fails: constant measure doesn't decrease.
+   , goldenCapturedIO "recursive14_badMutualMeasure" $ \rf -> do
+        let hf :: SInteger -> SInteger
+            hf = smtFunctionWithMeasure "hf" (\_ -> 1 :: SInteger, [])
+               $ \n -> ite (n .<= 0) 0 (1 + hg (n - 1))
+            hg :: SInteger -> SInteger
+            hg = smtFunctionWithMeasure "hg" (\_ -> 1 :: SInteger, [])
+               $ \n -> ite (n .<= 0) 0 (1 + hf (n - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> hf x .== (x :: SInteger)
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mixed mutual recursion: xf has explicit measure, xg uses auto-guess.
+   -- xf's user-provided measure (abs n) is tried first and works for the whole group.
+   , goldenCapturedIO "recursive15_mixedMutualMeasure" $ \rf -> do
+        let xf :: SInteger -> SInteger
+            xf = smtFunctionWithMeasure "xf" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + xg (n - 1))
+            xg :: SInteger -> SInteger
+            xg = smtFunction "xg"
+               $ \n -> ite (n .<= 0) 0 (1 + xf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> xf x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test bad mixed mutual recursion: yf has explicit measure but yg calls yf with (n+1).
+   -- The user-provided measure fails, and auto-guess also fails.
+   , goldenCapturedIO "recursive16_badMixedMutualMeasure" $ \rf -> do
+        let yf :: SInteger -> SInteger
+            yf = smtFunctionWithMeasure "yf" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + yg (n - 1))
+            yg :: SInteger -> SInteger
+            yg = smtFunction "yg"
+               $ \n -> ite (n .<= 0) 0 (1 + yf (n + 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> yf x .== (x :: SInteger)
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test 3-way chain with explicit measures: da calls db, db calls dc, dc calls da, all with abs measure.
+   , goldenCapturedIO "recursive17_chainMeasure" $ \rf -> do
+        let da :: SInteger -> SInteger
+            da = smtFunctionWithMeasure "da" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + db (n - 1))
+            db :: SInteger -> SInteger
+            db = smtFunctionWithMeasure "db" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + dc (n - 1))
+            dc :: SInteger -> SInteger
+            dc = smtFunctionWithMeasure "dc" (abs, [])
+               $ \n -> ite (n .<= 0) 0 (1 + da (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> da x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual recursion with different arg types: tf takes Integer, tg takes a list.
+   -- Auto-guess fails because no single measure applies to both signatures.
+   , testCase "diffTypeMutual" $ do
+        let tf :: SInteger -> SInteger
+            tf = smtFunction "tf" $ \n -> ite (n .<= 0) 0 (1 + tg (L.singleton n))
+            tg :: SList Integer -> SInteger
+            tg = smtFunction "tg" $ \xs -> ite (L.null xs) 0 (tf (L.head xs - 1))
+        r <- C.try $ sat $ \(x :: SInteger) -> tf x .== 0
+        case r of
+          Left (e :: C.SomeException) -> if "Cannot determine a termination measure" `isInfixOf` show e
+                                            then pure ()
+                                            else assertFailure $ "Unexpected exception: " ++ show e
+          Right _                     -> assertFailure "Expected error for different-type mutual recursion"
+
+   -- Test self-recursive + mutual: sf calls itself AND sg. Both paths should be checked.
+   , goldenCapturedIO "recursive19_selfAndMutual" $ \rf -> do
+        let sf :: SInteger -> SInteger
+            sf = smtFunction "sf" $ \n -> ite (n .<= 0) 0 (sf (n - 1) + sg (n - 1))
+            sg :: SInteger -> SInteger
+            sg = smtFunction "sg" $ \n -> ite (n .<= 0) 0 (1 + sf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> sf x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test all-self-recursive mutual group with bad cross-calls:
+   -- bf and bg both self-recurse (n-1), but cross-call with (n+1).
+   -- Self-recursion checks pass, but mutual group check must catch the bad cross-calls.
+   , goldenCapturedIO "recursive21_allSelfBadCross" $ \rf -> do
+        let bf :: SInteger -> SInteger
+            bf = smtFunction "bf21" $ \n -> ite (n .<= 0) 0 (bf (n - 1) + bg (n + 1))
+            bg :: SInteger -> SInteger
+            bg = smtFunction "bg21" $ \n -> ite (n .<= 0) 0 (bg (n - 1) + bf (n + 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> bf x .== (x :: SInteger)
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test all-self-recursive mutual group with good cross-calls and explicit measures:
+   -- Both bf and bg self-recurse and cross-call with (n-1). User-provided abs measure works.
+   , goldenCapturedIO "recursive22_allSelfGoodCross" $ \rf -> do
+        let bf :: SInteger -> SInteger
+            bf = smtFunctionWithMeasure "bf22" (abs, []) $ \n -> ite (n .<= 0) 0 (bf (n - 1) + bg (n - 1))
+            bg :: SInteger -> SInteger
+            bg = smtFunctionWithMeasure "bg22" (abs, []) $ \n -> ite (n .<= 0) 0 (bg (n - 1) + bf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> bf x .== (x :: SInteger)
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual recursion via TP proofs (exercises checkNewMeasures in Kernel.hs)
+   , goldenCapturedIO "recursive20_mutualTP" $ \rf -> do
+        let cfg = z3{verbose=True, redirectVerbose=Just rf}
+            mf :: SInteger -> SInteger
+            mf = smtFunction "mf_tp" $ \n -> ite (n .<= 0) 0 (1 + mg (n - 1))
+            mg :: SInteger -> SInteger
+            mg = smtFunction "mg_tp" $ \n -> ite (n .<= 0) 0 (1 + mf (n - 1))
+        _ <- runTPWith cfg $
+                lemma "mutual_at_0"
+                      (\(Forall @"n" n) -> n .== 0 .=> mf n .== 0)
+                      []
+        pure ()
+
+   -- Test mutual productive functions (guarded cross-calls): pf and pg build lists via each other.
+   , goldenCapturedIO "recursive23_mutualProductive" $ \rf -> do
+        let pf :: SInteger -> SList Integer
+            pf = smtProductiveFunction "pf23" $ \n ->
+                   ite (n .<= 0) (L.singleton 0) (n L..: pg (n - 1))
+            pg :: SInteger -> SList Integer
+            pg = smtProductiveFunction "pg23" $ \n ->
+                   ite (n .<= 0) (L.singleton 0) (n L..: pf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> L.head (pf n) .== (n :: SInteger) .&& n .> 0
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test mutual productive functions with unguarded cross-call: bad_pg calls bad_pf without a constructor guard.
+   , goldenCapturedIO "recursive24_badMutualProductive" $ \rf -> do
+        let bad_pf :: SInteger -> SList Integer
+            bad_pf = smtProductiveFunction "bad_pf" $ \n ->
+                       ite (n .<= 0) (L.singleton 0) (n L..: bad_pg (n - 1))
+            bad_pg :: SInteger -> SList Integer
+            bad_pg = smtProductiveFunction "bad_pg" $ \n ->
+                       ite (n .<= 0) (L.singleton 0) (bad_pf (n - 1))  -- not guarded!
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \(n :: SInteger) -> L.head (bad_pf n) .== n
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test that smtFunctionWithContract in a mutual group is rejected.
+   , goldenCapturedIO "recursive25_contractMutualRejected" $ \rf -> do
+        let cf :: SInteger -> SInteger
+            cf = smtFunctionWithContract "cf_mut"
+                   ( \n -> 0 `smax` (101 - n)
+                   , \_ r -> r .== 91
+                   , []
+                   )
+                 $ \n -> ite (n .> 100) (n - 10) (cg (n + 11))
+            cg :: SInteger -> SInteger
+            cg = smtFunction "cg_mut" $ \n -> ite (n .<= 0) 0 (1 + cf (n - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \(n :: SInteger) -> cf n .== 0
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf ("\nEXCEPTION:\n" ++ show e ++ "\n")
+          Right m                     -> appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test productive function that is both self-recursive and has cross-refs.
+   -- spf calls itself AND spg, both guarded by L..:
+   , goldenCapturedIO "recursive26_selfAndMutualProductive" $ \rf -> do
+        let spf :: SInteger -> SList Integer
+            spf = smtProductiveFunction "spf26" $ \n ->
+                    ite (n .<= 0) (L.singleton 0)
+                        (ite (sMod n 2 .== 0) (n L..: spf (n - 1))
+                                              (n L..: spg (n - 1)))
+            spg :: SInteger -> SList Integer
+            spg = smtProductiveFunction "spg26" $ \n ->
+                    ite (n .<= 0) (L.singleton 0) (n L..: spf (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> L.head (spf n) .== (n :: SInteger) .&& n .> 0
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test 3-way mutually-recursive productive streams.
+   -- pa -> pb -> pc -> pa, all guarded by L..:
+   , goldenCapturedIO "recursive27_mutualProductive3" $ \rf -> do
+        let pa :: SInteger -> SList Integer
+            pa = smtProductiveFunction "pa27" $ \n ->
+                   ite (n .<= 0) (L.singleton 0) (n L..: pb (n - 1))
+            pb :: SInteger -> SList Integer
+            pb = smtProductiveFunction "pb27" $ \n ->
+                   ite (n .<= 0) (L.singleton 0) ((n * 10) L..: pc (n - 1))
+            pc :: SInteger -> SList Integer
+            pc = smtProductiveFunction "pc27" $ \n ->
+                   ite (n .<= 0) (L.singleton 0) ((n * 100) L..: pa (n - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \n -> L.head (pa n) .== (n :: SInteger) .&& n .> 0
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Test smtFunctionNoTermination: proofs show [Modulo: <name> termination]
+   , goldenCapturedIO "recursive28_noTermCheck" $ \rf -> do
+        let f :: SInteger -> SInteger
+            f = smtFunctionNoTermination "ntc28" $ \n -> ite (n .<= 0) 0 (1 + f (n - 1))
+        p <- runTPWith z3{verbose=True, redirectVerbose=Just rf} $
+                lemma "ntc_at_5"
+                      (\(Forall @"n" n) -> n .== 5 .=> f n .== 5)
+                      []
+        appendFile rf (show p ++ "\n")
+   ]
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,167 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Set
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test sets.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Set (tests)  where
+
+import Data.SBV hiding (complement)
+import Data.SBV.Set
+
+import Data.SBV.Control
+
+import Data.SBV.Tuple
+
+import Utils.SBVTestFramework hiding (complement)
+
+data E = A | B | C deriving (Show, Eq, Ord)
+mkSymbolic [''E]
+
+type SC = SSet  Integer
+type RC = RCSet Integer
+
+cSetAL :: SC
+cSetAL = fromList [1,2,3,3,4]
+
+cIntA :: SInteger
+cIntA = literal 2
+
+cSetA :: SC
+cSetA = singleton $ literal 0
+
+-- 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  cIntA  cSetAL insert
+        , goldenCapturedIO "set_delete1"    $ tq $ templateBE  cIntA  cSetAL delete
+        , goldenCapturedIO "set_member1"    $ tq $ templateBEB cIntA  cSetAL member
+        , goldenCapturedIO "set_notMember1" $ tq $ templateBEB cIntA  cSetAL notMember
+        , goldenCapturedIO "set_tupleSet"   $ ta setOfTuples
+        ]
+    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 :: SInteger -> SC -> (SInteger -> SC -> SC) -> Symbolic (Integer, RC, RC, RC)
+templateBE ic is f = do a <- sInteger "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 :: SInteger -> SC -> (SInteger -> SC -> SBool) -> Symbolic (Integer, RC, Bool, Bool)
+templateBEB ic is f = do a <- sInteger "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
+
+setOfTuples :: SMTConfig -> IO SatResult
+setOfTuples cfg = satWith cfg $ do
+    let x = tuple (empty :: SSet Bool, empty :: SSet Bool)
+    y <- free_
+    return $ x ./= y
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/SmallShifts.hs b/SBVTestSuite/TestSuite/Basics/SmallShifts.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/SmallShifts.hs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.SmallShifts
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing small-shift amounts using the dynamic interface. See
+-- http://github.com/LeventErkok/sbv/issues/323 for the genesis.
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.SmallShifts(tests) where
+
+import Utils.SBVTestFramework hiding (proveWith)
+
+import Data.SBV.Dynamic
+import Data.SBV.Internals  (genMkSymVar, unSBV, VarContext(..))
+
+k1, k32, k33 :: Kind
+k1   = KBounded False  1
+k32  = KBounded False 32
+k33  = KBounded False 33
+type SW32 = SVal
+type SW33 = SVal
+type SW1  = SVal
+
+b0 :: SW1
+b0 = svInteger k1 0
+
+b1 :: SW1
+b1 = svInteger k1 1
+
+average33 :: SW32 -> SW32 -> SW32
+average33 x y = svExtract 31 0 (z' `svDivide` svInteger k33 2)
+    where z' :: SW33
+          z' = (b0 `svJoin` x) `svPlus` (b0 `svJoin` y)
+
+average4 :: SW32 -> SW32 -> SW32
+average4 x y =   ((x `svShiftRight` b1) `svPlus` (y `svShiftRight` b1))
+                `svPlus` (x `svAnd` (y `svAnd` svInteger k32 1))
+
+prop :: Symbolic SVal
+prop = do x <- unSBV <$> genMkSymVar k32 (NonQueryVar Nothing) (Just "x")
+          y <- unSBV <$> genMkSymVar k32 (NonQueryVar Nothing) (Just "y")
+          return $ average33 x y `svEqual` average4 x y
+
+checkThm :: ThmResult -> Assertion
+checkThm r = assert isThm
+  where isThm = case r of
+                  ThmResult Unsatisfiable{} -> return True :: IO Bool
+                  ThmResult Satisfiable{}   -> return False
+                  _                         -> error "checkThm: Unexpected result!"
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.SmallShifts"
+   [ testCase "smallShift" $ checkThm =<< proveWith z3 prop
+   ]
diff --git a/SBVTestSuite/TestSuite/Basics/SmtFunctionUnique.hs b/SBVTestSuite/TestSuite/Basics/SmtFunctionUnique.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/SmtFunctionUnique.hs
@@ -0,0 +1,84 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.SmtFunctionUnique
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Tests for smtFunction name uniqueness enforcement.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.SmtFunctionUnique(tests) where
+
+import Utils.SBVTestFramework
+
+import qualified Control.Exception as C
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.SmtFunctionUnique"
+   [
+   -- Same name, same body: should succeed (idempotent re-registration).
+     goldenCapturedIO "smtFuncUniq_sameOk" $ \rf -> do
+        let f :: SInteger -> SInteger
+            f = smtFunction "f" $ \x -> x + 1
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> f x + f x .== 4
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Same name, different body: should error.
+   , goldenCapturedIO "smtFuncUniq_conflict" $ \rf -> do
+        let f :: SInteger -> SInteger
+            f = smtFunction "f" $ \x -> x + 1
+            g :: SInteger -> SInteger
+            g = smtFunction "f" $ \x -> x + 2
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> f x + g x .== 5
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
+          Right m                     -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
+
+   -- Same name, same recursive body: should succeed.
+   , goldenCapturedIO "smtFuncUniq_recursiveOk" $ \rf -> do
+        let f :: SInteger -> SInteger
+            f = smtFunction "f" $ \x -> ite (x .<= 0) 0 (x + f (x - 1))
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> x .>= 0 .&& x .<= 3 .&& f x .== 6
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+
+   -- Same name, different recursive body: should error.
+   , goldenCapturedIO "smtFuncUniq_recursiveConflict" $ \rf -> do
+        let f :: SInteger -> SInteger
+            f = smtFunction "f" $ \x -> ite (x .<= 0) 0 (x + f (x - 1))
+            g :: SInteger -> SInteger
+            g = smtFunction "f" $ \x -> ite (x .<= 0) 1 (x * g (x - 1))
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> f x + g x .== 10
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
+          Right m                     -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
+
+   -- Same name via parameter capture: bar 2 and bar 3 create different closures
+   -- for "bar", which should be detected as a conflict.
+   , goldenCapturedIO "smtFuncUniq_captureConflict" $ \rf -> do
+        let bar :: SInteger -> SInteger -> SInteger
+            bar k = smtFunction "bar" (+ k)
+        r <- C.try $ satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> bar 2 x + bar 3 x .== 10
+        case r of
+          Left (e :: C.SomeException) -> appendFile rf (show e ++ "\n")
+          Right m                     -> appendFile rf ("\nUNEXPECTED SUCCESS:\n" ++ show m ++ "\n")
+
+   -- Fix for the above: use a tag to give each instantiation a unique name.
+   , goldenCapturedIO "smtFuncUniq_captureTagged" $ \rf -> do
+        let bar :: String -> SInteger -> SInteger -> SInteger
+            bar tag k = smtFunction ("bar_" ++ tag) (+ k)
+        m <- satWith z3{verbose=True, redirectVerbose=Just rf} $
+                \x -> bar "two" 2 x + bar "three" 3 x .== 10
+        appendFile rf ("\nRESULT:\n" ++ show m ++ "\n")
+   ]
diff --git a/SBVTestSuite/TestSuite/Basics/SquashReals.hs b/SBVTestSuite/TestSuite/Basics/SquashReals.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/SquashReals.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.SquashReals
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the "squash" reals feature
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.SquashReals(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Reals.Squash"
+    [ goldenVsStringShow "squashReals1" $ sat                            (\x -> x .>= 0 .&& x*x .== (59::SReal))
+    , goldenVsStringShow "squashReals2" $ sat                            (\x -> x .>= 0 .&& x*x .== (16::SReal))
+    , goldenVsStringShow "squashReals3" $ satWith z3{printRealPrec = 35} (\x -> x .>= 0 .&& x*x .== (59::SReal))
+    , goldenVsStringShow "squashReals4" $ satWith z3{printRealPrec = 35} (\x -> x .>= 0 .&& x*x .== (16::SReal))
+    ]
diff --git a/SBVTestSuite/TestSuite/Basics/String.hs b/SBVTestSuite/TestSuite/Basics/String.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/String.hs
@@ -0,0 +1,196 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.String
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the string functions.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.String(tests)  where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Prelude hiding ((!!), (++))
+import qualified Prelude as P ((++))
+
+import Data.SBV.List ((!!), (++))
+import qualified Data.SBV.List   as S
+import qualified Data.SBV.Char   as SC
+import qualified Data.SBV.RegExp as R
+
+import Control.Monad (unless)
+import Data.List (sort)
+
+import qualified Data.Map.Strict as M
+
+import qualified Data.Char as C
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.String" [
+      goldenCapturedIO "strConcat"     $ \rf -> checkWith z3{redirectVerbose=Just rf} strConcatSat    Sat
+    , goldenCapturedIO "strConcatBad"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strConcatUnsat  Unsat
+    , goldenCapturedIO "strIndexOf"    $ \rf -> checkWith z3{redirectVerbose=Just rf} strIndexOfSat   Sat
+    , goldenCapturedIO "strIndexOfBad" $ \rf -> checkWith z3{redirectVerbose=Just rf} strIndexOfUnsat Unsat
+    , goldenCapturedIO "strExamples1"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples1    Sat
+    , goldenCapturedIO "strExamples2"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples2    Unsat
+    , goldenCapturedIO "strExamples3"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples3    Sat
+    , goldenCapturedIO "strExamples4"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples4    Sat
+    , goldenCapturedIO "strExamples5"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples5    Sat
+    , goldenCapturedIO "strExamples6"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples6    Unsat
+    , goldenCapturedIO "strExamples7"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples7    Sat
+    , goldenCapturedIO "strExamples8"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples8    Unsat
+    , goldenCapturedIO "strExamples9"  $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples9    Sat
+    , goldenCapturedIO "strExamples10" $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples10   Unsat
+    , goldenCapturedIO "strExamples11" $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples11   Unsat
+    , goldenCapturedIO "strExamples12" $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples12   Unsat
+    , goldenCapturedIO "strExamples13" $ \rf -> checkWith z3{redirectVerbose=Just rf} strExamples13   Unsat
+    , testCase         "strExamples14" $ assert strExamples14
+    ]
+
+checkWith :: SMTConfig -> Symbolic () -> CheckSatResult -> IO ()
+checkWith 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"
+                       DSat{} -> error "Failed! Expected Sat, got delta-sat"
+                       Sat    -> getModel         >>= \r -> error $ "Failed! Expected Unsat, got SAT:\n" P.++ show (SatResult (Satisfiable cfg r))
+                       Unk    -> getUnknownReason >>= \r -> error $ "Failed! Expected Unsat, got UNK:\n" P.++ show r
+
+strConcatSat :: Symbolic ()
+strConcatSat = constrain $ "abc" ++ "def" .== ("abcdef" :: SString)
+
+strConcatUnsat :: Symbolic ()
+strConcatUnsat = constrain $ "abc" ++ "def" .== ("abcdefg" :: SString)
+
+strIndexOfSat :: Symbolic ()
+strIndexOfSat = constrain $ S.indexOf "abcabc" ("a" :: SString) .== 0
+
+strIndexOfUnsat :: Symbolic ()
+strIndexOfUnsat = constrain $ S.indexOf "abcabc" ("a" :: SString) ./= 0
+
+-- Basic string operations
+strExamples1 :: Symbolic ()
+strExamples1 = constrain $ sAnd
+  [ S.singleton ("abc" !! 1) ++ S.singleton ("abc" !! 0) .== ("ba" :: SString)
+  , "abcabc" `S.indexOf` ("a" :: SString)                .== 0
+  , S.offsetIndexOf "abcabc" ("a" :: SString) 1          .== 3
+  , S.subList "xxabcyy" 2 3                              .== ("abc" :: SString)
+  ]
+
+-- A string cannot overlap with two different characters.
+strExamples2 :: Symbolic ()
+strExamples2 = do
+  a <- sString "a"
+  constrain $ a ++ "b" .== "a" ++ a
+
+-- Strings a, b, c can have a non-trivial overlap.
+strExamples3 :: Symbolic ()
+strExamples3 = do
+  [a, b, c] <- sStrings ["a", "b", "c"]
+  constrain $ a ++ b .== "abcd"
+  constrain $ b ++ c .== "cdef"
+  constrain $ sNot $ b .== ""
+
+-- There is a solution to a of length at most 2.
+strExamples4 :: Symbolic ()
+strExamples4 = do
+  [a, b] <- sStrings ["a", "b"]
+  constrain $ "abc" ++ a .== b ++ "cef"
+  constrain $ S.length a .<= 2
+
+-- There is a solution to a that is not a sequence of "a"'s.
+strExamples5 :: Symbolic ()
+strExamples5 = do
+  [a, b, c] <- sStrings ["a", "b", "c"]
+  constrain $ a ++ "ab" ++ b .== b ++ "ba" ++ c
+  constrain $ c .== a ++ b
+  constrain $ sNot $ a ++ "a" .== "a" ++ a
+
+-- Contains is transitive.
+strExamples6 :: Symbolic ()
+strExamples6 = do
+  [a, b, c] <- sStrings ["a", "b", "c"]
+  constrain $ b `S.isInfixOf` a
+  constrain $ c `S.isInfixOf` b
+  constrain $ sNot $ c `S.isInfixOf` a
+
+-- But containment is not a linear order.
+strExamples7 :: Symbolic ()
+strExamples7 = do
+  [a, b, c] <- sStrings ["a", "b", "c"]
+  constrain $ b `S.isInfixOf` a
+  constrain $ c `S.isInfixOf` a
+  constrain $ sNot $ c `S.isInfixOf` b
+  constrain $ sNot $ b `S.isInfixOf` c
+
+-- Any string is equal to the prefix and suffix that add up to its length.
+strExamples8 :: Symbolic ()
+strExamples8 = do
+  [a, b, c] <- sStrings ["a", "b", "c"]
+  constrain $ b `S.isPrefixOf` a
+  constrain $ c `S.isSuffixOf` a
+  constrain $ S.length a .== S.length b + S.length c
+  constrain $ sNot $ a .== b ++ c
+
+-- The maximal length is 6 for a string of length 2 repeated at most 3 times
+strExamples9 :: Symbolic ()
+strExamples9 = do
+   a <- sString "a"
+   constrain $ R.match a (R.Loop 1 3 "ab")
+   constrain $ S.length a .== 6
+
+-- The maximal length is 6 for a string of length 2 repeated at most 3 times
+strExamples10 :: Symbolic ()
+strExamples10 = do
+   a <- sString "a"
+   constrain $ R.match a (R.Loop 1 3 "ab")
+   constrain $ S.length a .> 6
+
+-- Conversion from nat to string, only ground terms
+strExamples11 :: Symbolic ()
+strExamples11 = do
+   i <- sInteger "i"
+   constrain $ i .== 11
+   constrain $ sNot $ S.natToStr i .== "11"
+
+-- Conversion from nat to string, negative values produce empty string
+strExamples12 :: Symbolic ()
+strExamples12 = do
+   i <- sInteger "i"
+   constrain $ i .== -2
+   constrain $ sNot $ S.natToStr i .== ""
+
+-- Conversion from string to nat, only ground terms
+strExamples13 :: Symbolic ()
+strExamples13 = do
+   s <- sString "s"
+   constrain $ s .== "13"
+   constrain $ sNot $ S.strToNat s .== 13
+
+-- Generate all length one strings consisting of letters A-Z, to enumerate all and making sure we can parse correctly
+strExamples14 :: IO Bool
+strExamples14 = do m <- allSat $ do s <- sString "s"
+                                    let c = SC.ord (S.head s)
+                                    constrain $ c .>= SC.ord (literal 'A')
+                                    constrain $ c .<= SC.ord (literal 'Z')
+                                    return $ S.length s .== 1
+                   let dicts = getModelDictionaries m
+
+                       vals :: [Int]
+                       vals = map C.ord $ concat $ sort $ map (fromCV . snd) (concatMap M.assocs dicts)
+
+                   case length dicts of
+                     26 -> return $ vals == map C.ord ['A' .. 'Z']
+                     _   -> return False
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,145 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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"
+                       DSat{} -> error "Failed! Expected Sat, got delta-sat"
+                       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 <- free "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)          <- free_
+
+   constrain $ isLeft x
+   constrain $ isJust y
+
+sumMergeMaybe1 :: Symbolic ()
+sumMergeMaybe1 = do
+   (x :: SMaybe Integer) <- free_
+   (y :: SMaybe Integer) <- free_
+   b  <- sBool_
+
+   constrain $ isNothing $ ite b x y
+
+sumMergeMaybe2 :: Symbolic ()
+sumMergeMaybe2 = do
+   (x :: SMaybe Integer) <- free_
+   (y :: SMaybe Integer) <- free_
+   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
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Basics/TOut.hs b/SBVTestSuite/TestSuite/Basics/TOut.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/TOut.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.TOut
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the basic timeout mechanism
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.TOut(tests)  where
+
+import Documentation.SBV.Examples.Puzzles.Euler185
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.timeout"
+    [ goldenVsStringShow "timeout1" $ sat $ setTimeOut 1000 >> euler185
+    ]
diff --git a/SBVTestSuite/TestSuite/Basics/TPCaching.hs b/SBVTestSuite/TestSuite/Basics/TPCaching.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/TPCaching.hs
@@ -0,0 +1,178 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.TPCaching
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Tests for the TP proof caching mechanism.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.TPCaching(tests) where
+
+import Utils.SBVTestFramework
+
+import Data.SBV.TP (TP, Proof, runTPWith, lemma, calc, recall, tpStats, (|-), (=:), qed)
+
+import Control.Monad (void)
+import Control.Exception (try, SomeException)
+
+import Data.Char (isSpace)
+import Data.List (isPrefixOf, dropWhileEnd)
+
+import Control.DeepSeq (($!!))
+
+-- | Strip timing info like @[0.05s]@ from the end of output lines.
+-- Only matches brackets whose content looks like a time value (digits, dots, and 's').
+-- Handles multiple consecutive timings like @[0.001s][0.002s]@.
+stripTiming :: String -> String
+stripTiming s = reverse $ go $ reverse $ dropWhileEnd isSpace s
+ where go (']':rest) | (inner, '[':before) <- break (== '[') rest
+                     , all (`elem` ("0123456789.s" :: String)) inner
+                     = go $ dropWhile isSpace before
+       go xs = xs
+
+-- | Filter out the statistics summary line from verbose output.
+isStatsLine :: String -> Bool
+isStatsLine s = "[SBV:" `isPrefixOf` dropWhile isSpace s
+
+-- | Clean captured verbose output: strip timing and stats.
+cleanStatsOutput :: String -> String
+cleanStatsOutput = unlines . map stripTiming . filter (not . isStatsLine) . lines
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.TPCaching"
+   [
+   -- Normal mode: recall when cache is empty (cache miss).
+   -- The proof runs from scratch; recallWith shows "Lemma:" one-liner.
+     goldenCapturedIO "tpCache_miss" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        void $ runTPWith cfg $
+           recall (lemma "fact" sTrue [])
+
+   -- Normal mode: direct proof then recall (cache hit).
+   -- The direct proof shows "Lemma:", the recall shows "Lemma: ... [Cached]".
+   , goldenCapturedIO "tpCache_hit" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           _ <- lemma "fact" sTrue []
+           recall (lemma "fact" sTrue [])
+
+   -- Normal mode: same proposition proved under two names, then recalled (aliases).
+   -- The recall shows "Lemma: ... [Cached]" with "(a.k.a. ...)" listing the other name.
+   , goldenCapturedIO "tpCache_alias" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           _ <- lemma "nameA" sTrue []
+           _ <- lemma "nameB" sTrue []
+           recall (lemma "nameC" sTrue [])
+
+   -- Normal mode: calc proof with steps, then recall (cache hit).
+   -- The direct proof shows each step; the recall collapses to one line.
+   , goldenCapturedIO "tpCache_calcCollapse" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           let addZeroProof = calc "addZero"
+                                   (\(Forall @"x" (x :: SInteger)) -> x + 0 .== x) $
+                                   \x -> [] |- x + 0
+                                            =: (x :: SInteger)
+                                            =: qed
+           _ <- addZeroProof
+           recall addZeroProof
+
+   -- Normal mode: nested recall.
+   -- First run proves inner and outer. Second run (via recall) hits cache for outer.
+   , goldenCapturedIO "tpCache_nested" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           let myProof = do _ <- recall (lemma "inner" sTrue [])
+                            lemma "outer" sTrue []
+           _ <- myProof
+           recall myProof
+
+   -- Stats mode: recall when cache is empty (cache miss).
+   -- In stats mode, recall does NOT suppress inner output, so full proof steps are visible.
+   , goldenCapturedIO "tpCache_statsMiss" $ \rf -> do
+        let cfg = (tpStats z3) { redirectVerbose = Just rf }
+        void $ runTPWith cfg $
+           recall (calc "addZero"
+                        (\(Forall @"x" (x :: SInteger)) -> x + 0 .== x) $
+                        \x -> [] |- x + 0
+                                 =: (x :: SInteger)
+                                 =: qed)
+        contents <- readFile rf
+        writeFile rf $!! cleanStatsOutput contents
+
+   -- Stats mode: direct proof then recall (cache hit).
+   -- Direct proof shows full steps; recall shows "Lemma: ... [Cached]" one-liner.
+   , goldenCapturedIO "tpCache_statsHit" $ \rf -> do
+        let cfg = (tpStats z3) { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           let addZeroProof = calc "addZero"
+                                   (\(Forall @"x" (x :: SInteger)) -> x + 0 .== x) $
+                                   \x -> [] |- x + 0
+                                            =: (x :: SInteger)
+                                            =: qed
+           _ <- addZeroProof
+           recall addZeroProof
+        contents <- readFile rf
+        writeFile rf $!! cleanStatsOutput contents
+
+   -- Stats mode: nested recall showing inner cache dynamics.
+   -- First recall misses (shows full inner proofs). Second recall hits (shows "Lemma: ... [Cached]").
+   , goldenCapturedIO "tpCache_statsNested" $ \rf -> do
+        let cfg = (tpStats z3) { redirectVerbose = Just rf }
+        void $ runTPWith cfg $ do
+           _ <- recall (lemma "inner" sTrue [])
+           _ <- lemma "outer" sTrue []
+           _ <- recall (lemma "inner" sTrue [])
+           recall (lemma "outer" sTrue [])
+        contents <- readFile rf
+        writeFile rf $!! cleanStatsOutput contents
+
+   -- Recall of a failing proof: the lemma is false (x > x), so the proof should fail.
+   , goldenCapturedIO "tpCache_recallFail" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        res <- try $ void $ runTPWith cfg $
+           recall bad
+        case res of
+           Left  (_ :: SomeException) -> pure ()
+           Right _                    -> appendFile rf "Unexpected success\n"
+
+   -- Direct proof of a false lemma.
+   , goldenCapturedIO "tpCache_fooFail" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        res <- try $ void $ runTPWith cfg foo
+        case res of
+           Left  (_ :: SomeException) -> pure ()
+           Right _                    -> appendFile rf "Unexpected success\n"
+
+   -- Recall of a failing lemma inside a larger proof.
+   , goldenCapturedIO "tpCache_barFail" $ \rf -> do
+        let cfg = z3 { redirectVerbose = Just rf }
+        res <- try $ void $ runTPWith cfg bar
+        case res of
+           Left  (_ :: SomeException) -> pure ()
+           Right _                    -> appendFile rf "Unexpected success\n"
+   ]
+
+-- | A trivially false lemma, used to test recall of a failing proof.
+bad :: TP (Proof (Forall "x" Integer -> SBool))
+bad = lemma "bad" (\(Forall @"x" (x :: SInteger)) -> x .> x) []
+
+-- | A false lemma: x == x+1.
+foo :: TP (Proof (Forall "x" Integer -> SBool))
+foo = lemma "foo" (\(Forall @"x" (x :: SInteger)) -> x .== x + 1) []
+
+-- | Recalls foo (which fails), then tries to prove another false lemma.
+bar :: TP (Proof (Forall "x" Integer -> SBool))
+bar = do _f <- recall foo
+         lemma "bar" (\(Forall @"x" (x :: SInteger)) -> x .== x + 2) []
diff --git a/SBVTestSuite/TestSuite/Basics/Tuple.hs b/SBVTestSuite/TestSuite/Basics/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Tuple.hs
@@ -0,0 +1,147 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Tuple
+-- Copyright : (c) Joel Burget
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test tuples.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.Tuple (tests)  where
+
+import Prelude hiding ((!!))
+
+import Data.SBV.Control
+import Data.SBV.List ((!!))
+
+import Data.SBV.Tuple
+
+import qualified Data.SBV.List as L
+
+import Utils.SBVTestFramework
+
+data E = A | B | C deriving Show
+mkSymbolic [''E]
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.Tuple" [
+          goldenCapturedIO "tuple_swap"       $ t tupleSwapSat
+        , goldenCapturedIO "tuple_twoTwo"     $ t twoTwoTuples
+        , goldenCapturedIO "tuple_nested"     $ t nested
+        , goldenCapturedIO "tuple_list"       $ t list
+        , goldenCapturedIO "tuple_enum"       $ t enum
+        , goldenCapturedIO "tuple_unit"       $ t unit
+        , goldenCapturedIO "tuple_makePair"   $ t makePair
+        , goldenCapturedIO "tuple_unequal"    $ t unequal
+        ]
+    where t tc goldFile = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just goldFile} tc
+                             appendFile goldFile ("\n FINAL: " ++ show r ++ "\nDONE!\n")
+
+tupleSwapSat :: Symbolic ((Integer, Integer, Integer), (Integer, Integer, Integer))
+tupleSwapSat = do
+  [abx, bay] <- sTuples @(Integer, Integer, Integer) ["abx", "bay"]
+  constrain $ abx^._1 .== bay^._2
+  constrain $ abx^._2 .== bay^._1
+  constrain $ abx^._1 .== 1
+  constrain $ abx^._2 .== 2
+  constrain $ abx^._3 .== 3
+  constrain $ bay^._3 .== 4
+  query $ do _ <- checkSat
+             (,) <$> getValue abx <*> getValue bay
+
+twoTwoTuples :: Symbolic ((Integer, String), (Char, Word8))
+twoTwoTuples = do
+  ab <- sTuple @(Integer, String) "ab"
+  cd <- sTuple @(Char,    Word8)  "cd"
+  constrain $ ab^._1 .== 1
+  constrain $ cd^._1 .== literal 'c'
+  query $ do _ <- checkSat
+             (,) <$> getValue ab <*> getValue cd
+
+nested :: Symbolic ((Integer, (String, Char)), Word8)
+nested = do
+  abcd <- sTuple @((Integer, (String, Char)), Word8) "abcd"
+  constrain $     abcd^._1^._1 .== 1
+  constrain $ abcd^._1^._2^._1 .== literal "foo"
+  constrain $ abcd^._1^._2^._2 .== literal 'c'
+  constrain $         abcd^._2 .== 0
+  query $ do _ <- checkSat
+             getValue abcd
+
+list :: Symbolic [(Integer, [(Integer, String)])]
+list = do
+  lst <- sList @(Integer, [(Integer, String)]) "lst"
+
+  constrain $ (lst !! 0)^._1 .== 2
+  constrain $ (((lst !! 1)^._2) !! 0)^._2 .== literal "foo"
+  constrain $ L.length lst .== 4
+  constrain $ L.length ((lst !! 1)^._2) .== 5
+  constrain $ L.length ((lst !! 2)^._2) .== 0
+
+  constrain $ lst .== literal [(2,[]), (1,[(3,"foo"), (0,"bar"), (-1,"baz"), (-2,"quux"), (-3,"enough")]), (-4,[]), (-5,[])]
+
+  query $ do _ <- checkSat
+             getValue lst
+
+enum :: Symbolic ([(E, [Bool])], (Word8, (E, Char, Integer)))
+enum = do
+   vTup1 :: SList (E, [Bool]) <- sList "v1"
+   q <- sBool "q"
+   constrain $ sNot q
+   constrain $ (vTup1 !! 1)^._2 .== sTrue .: q .: []
+   constrain $ L.length vTup1 .== 3
+
+   case untuple (vTup1 !! 2)  of
+     (e, b) -> do constrain $ e .== sC
+                  constrain $ L.length b .== 6
+                  constrain $ b !! 4 .== sTrue
+
+   query $ do
+     vTup2 :: STuple Word8 (E, Char, Integer) <- freshVar "v2"
+     constrain $ vTup2 .== literal (5, (C, 'A', 812))
+
+     constrain $ vTup1 .== literal [(B, []), (A, [True, False]), (C, [False, False, False, False, True, False])]
+
+     _ <- checkSat
+     (,) <$> getValue vTup1 <*> getValue vTup2
+
+unit :: Symbolic ()
+unit = do
+  x <- sTuple @() "x"
+  y <- sTuple @() "y"
+  constrain $ x .== y
+
+makePair :: Symbolic ()
+makePair = do
+  [x, y] <- sIntegers ["x", "y"]
+  let xy = tuple (x, y)
+  constrain $ xy^._1 + xy^._2 .== 0
+
+type TI = STuple Integer Integer
+
+unequal :: Symbolic ()
+unequal = do
+   x :: TI <- free_
+   y :: TI <- free_
+   -- force unsat; we're simply testing we can generate the tuple inequality here
+   constrain $ x .< y
+   constrain $ x .> y
+
+   query $ do cs <- checkSat
+              case cs of
+                Unsat -> return ()
+                _     -> error "did not expect this!"
+
+{- HLint ignore module "Use ."        -}
+{- HLint ignore module "Redundant ^." -}
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,57 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.UISat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing UI function sat examples
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Basics.UISat(tests)  where
+
+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 -> ConstraintSet -> 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 :: ConstraintSet
+test1 = do setLogic Logic_ALL
+           registerFunction q1
+
+test2 :: ConstraintSet
+test2 = do setLogic Logic_ALL
+           registerFunction q2
+
+test3 :: ConstraintSet
+test3 = do setLogic Logic_ALL
+           registerFunction q1
+           registerFunction q2
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs b/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.BitPrecise.BitTricks
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.BitPrecise.BitTricks
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.BitPrecise.BitTricks(tests) where
+
+import Documentation.SBV.Examples.BitPrecise.BitTricks
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "BitPrecise.BitTricks"
+    [ testCase "fast min"              $ assertIsThm fastMinCorrect
+    , testCase "fast max"              $ assertIsThm fastMaxCorrect
+    , testCase "opposite signs"        $ assertIsThm oppositeSignsCorrect
+    , testCase "conditional set clear" $ assertIsThm conditionalSetClearCorrect
+    , testCase "power of two"          $ assertIsThm powerOfTwoCorrect
+    ]
diff --git a/SBVTestSuite/TestSuite/BitPrecise/Legato.hs b/SBVTestSuite/TestSuite/BitPrecise/Legato.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/BitPrecise/Legato.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.BitPrecise.Legato
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.BitPrecise.Legato
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.BitPrecise.Legato(tests) where
+
+import Data.SBV.Internals hiding (free, output)
+import Documentation.SBV.Examples.BitPrecise.Legato
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "BitPrecise.Legato" [
+   goldenVsStringShow "legato"   legatoPgm
+ , goldenVsStringShow "legato_c" legatoC
+ ]
+ where legatoPgm = runSAT $ do
+                       x     <- free "x"
+                       y     <- free "y"
+                       lo    <- free "lo"
+                       regX  <- free "regX"
+                       regA  <- free "regA"
+                       flagC <- free "flagC"
+                       flagZ <- free "flagZ"
+                       pure $ legatoIsCorrect (x, y, lo, regX, regA, flagC, flagZ)
+
+       thd (_, _, r) = r
+
+       legatoC = thd <$> compileToC' "legatoMult" (do
+                    cgSetDriverValues [87, 92]
+                    x <- cgInput "x"
+                    y <- cgInput "y"
+                    let (hi, lo) = runLegato (initMachine (x, y, 0, 0, 0, sFalse, sFalse))
+                    cgOutput "hi" hi
+                    cgOutput "lo" lo)
diff --git a/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs b/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.BitPrecise.MergeSort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.BitPrecise.MergeSort
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.BitPrecise.MergeSort(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.BitPrecise.MergeSort
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "BitPrecise.MergeSort" [
+   goldenVsStringShow "merge" mergeC
+ ]
+ where thd (_, _, r) = r
+       mergeC = thd <$> compileToC' "merge" (do
+                   cgSetDriverValues [10, 6, 4, 82, 71]
+                   xs <- cgInputArr 5 "xs"
+                   cgOutputArr "ys" (mergeSort xs))
diff --git a/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs b/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.BitPrecise.PrefixSum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.PrefixSum.PrefixSum
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.BitPrecise.PrefixSum(tests) where
+
+import Documentation.SBV.Examples.BitPrecise.PrefixSum
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "BitPrecise.PrefixSum"
+    [ testCase "prefixSum1" $ assertIsThm $ flIsCorrect  8 (0, (+))
+    , testCase "prefixSum2" $ assertIsThm $ flIsCorrect 16 (0, smax)
+    ]
diff --git a/SBVTestSuite/TestSuite/CRC/CCITT.hs b/SBVTestSuite/TestSuite/CRC/CCITT.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CRC/CCITT.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CRC.CCITT
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.CRC.CCITT
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CRC.CCITT(tests) where
+
+import Data.SBV.Tools.Polynomial
+import Utils.SBVTestFramework
+
+import Data.Proxy
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CRC.CCITT"
+  [ goldenVsStringShow "ccitt" crcPgm
+  , testCase "ccit_good" (assertIsThm crcGood)
+  ]
+  where crcPgm = runSAT $ crcGood <$> free_ <*> free_
+
+extendData :: SWord 48 -> SWord 64
+extendData msg = fromBitsBE $ blastBE msg ++ replicate 16 sFalse
+
+mkFrame :: SWord 48 -> SWord 64
+mkFrame msg = msg # crc_48_16 msg
+
+crc_48_16 :: SWord 48 -> SWord 16
+crc_48_16 msg = res
+  where msg64, divisor :: SWord 64
+        msg64   = extendData msg
+        divisor = polynomial [16, 12, 5, 0]
+        crc64 = pMod msg64 divisor
+        res   = bvExtract (Proxy @15) (Proxy @0) crc64
+
+diffCount :: SWord 64 -> SWord 64 -> SWord8
+diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
+  where count []     = 0
+        count (b:bs) = let r = count bs in ite b r (1+r)
+
+-- Claim: If there is an undetected corruption, it must be at least at 4 bits; i.e. HD is 4
+crcGood :: SWord 48 -> SWord 48 -> SBool
+crcGood sent received =
+     sent ./= received .=> diffCount frameSent frameReceived .> 3
+   where frameSent     = mkFrame sent
+         frameReceived = mkFrame received
diff --git a/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs b/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs
@@ -0,0 +1,63 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CRC.CCITT_Unidir
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.CRC.CCITT_Unidir
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CRC.CCITT_Unidir(tests) where
+
+import Data.SBV.Tools.Polynomial
+import Utils.SBVTestFramework
+
+import Data.Proxy
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "CCITT_Unidir"
+    [   testCase "ccitHDis3" (assertIsThm   (crcUniGood 3))
+      , testCase "ccitHDis4" (assertIsntThm (crcUniGood 4))
+    ]
+
+extendData :: SWord 48 -> SWord 64
+extendData msg = msg # 0
+
+mkFrame :: SWord 48 -> SWord 64
+mkFrame msg = msg # crc_48_16 msg
+
+crc_48_16 :: SWord 48 -> SWord 16
+crc_48_16 msg = res
+  where msg64, divisor :: SWord 64
+        msg64   = extendData msg
+        divisor = polynomial [16, 12, 5, 0]
+        crc64 = pMod msg64 divisor
+        res   = bvExtract (Proxy @15) (Proxy @0) crc64
+
+diffCount :: [SBool] -> [SBool] -> SWord8
+diffCount xs ys = count $ zipWith (.==) xs ys
+  where count []     = 0
+        count (b:bs) = let r = count bs in ite b r (1+r)
+
+-- returns true if there's a 0->1 error (1->0 is ok)
+nonUnidir :: [SBool] -> [SBool] -> SBool
+nonUnidir []     _      = sFalse
+nonUnidir _      []     = sTrue
+nonUnidir (a:as) (b:bs) = (sNot a .&& b) .|| nonUnidir as bs
+
+crcUniGood :: SWord8 -> SWord 48 -> SWord 48 -> SBool
+crcUniGood hd sent received =
+     sent ./= received .=> nonUnidir frameSent frameReceived .|| diffCount frameSent frameReceived .> hd
+   where frameSent     = blastLE $ mkFrame sent
+         frameReceived = blastLE $ mkFrame received
+
+{- HLint ignore crc_48_16 "Use camelCase" -}
diff --git a/SBVTestSuite/TestSuite/CRC/GenPoly.hs b/SBVTestSuite/TestSuite/CRC/GenPoly.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CRC/GenPoly.hs
@@ -0,0 +1,63 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CRC.GenPoly
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.CRC.GenPoly
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds        #-}
+{-# LANGUAGE TypeApplications #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CRC.GenPoly(tests) where
+
+import Data.SBV.Tools.Polynomial
+import Utils.SBVTestFramework
+
+import Data.Proxy
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "CRC.GenPoly"
+    [ testCase "crcGoodE" (assertIsSat crcGoodE)
+    , testCase "crcGood"  (assertIsntThm (crcGood 3 12))
+    ]
+
+crcGoodE :: Symbolic SBool
+crcGoodE = pure $ quantifiedBool $ \(Exists x) (Exists y) -> crcGood 3 0 x y
+
+extendData :: SWord 48 -> SWord 64
+extendData msg = msg # 0
+
+mkFrame :: SWord 64 -> SWord 48 -> SWord 64
+mkFrame poly msg = msg # crc_48_16 msg poly
+
+crc_48_16 :: SWord 48 -> SWord 64 -> SWord 16
+crc_48_16 msg poly = res
+  where msg64 = extendData msg
+        crc64 = pMod msg64 poly
+        res   = bvExtract (Proxy @15) (Proxy @0) crc64
+
+diffCount :: SWord 64 -> SWord 64 -> SWord 8
+diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
+  where count []     = 0
+        count (b:bs) = let r = count bs in ite b r (1+r)
+
+crcGood :: SWord 8 -> SWord 16 -> SWord 48 -> SWord 48 -> SBool
+crcGood hd divisor sent received =
+     sent ./= received .=> diffCount frameSent frameReceived .> hd
+   where frameSent     = mkFrame poly sent
+         frameReceived = mkFrame poly received
+         poly          = mkPoly divisor
+
+mkPoly :: SWord 16 -> SWord 64
+mkPoly d = 1 # d
+
+{- HLint ignore crc_48_16 "Use camelCase" -}
+{- HLint ignore crcGoodE  "Use <$>"       -}
diff --git a/SBVTestSuite/TestSuite/CRC/Parity.hs b/SBVTestSuite/TestSuite/CRC/Parity.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CRC/Parity.hs
@@ -0,0 +1,38 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CRC.Parity
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.CRC.Parity
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CRC.Parity(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "CRC.Parity"
+    [ testCase "parity" (assertIsThm parityOK)
+    ]
+
+parity :: SWord64 -> SBool
+parity x = sNot (isOdd cnt)
+  where cnt :: SWord8
+        cnt = sum $ map oneIf $ blastLE x
+
+isOdd :: SWord8 -> SBool
+isOdd = lsb
+
+-- Example suggested by Lee Pike
+-- If x and y differ in odd-number of bits, then their parities are flipped
+parityOK :: SWord64 -> SWord64 -> SBool
+parityOK x y = isOdd cnt .=> px .== sNot py
+  where cnt = sum $ map oneIf $ zipWith (./=) (blastLE x) (blastLE y)
+        px  = parity x
+        py  = parity y
diff --git a/SBVTestSuite/TestSuite/CRC/USB5.hs b/SBVTestSuite/TestSuite/CRC/USB5.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CRC/USB5.hs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CRC.USB5
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.CRC.USB5
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CRC.USB5(tests) where
+
+import Data.SBV.Tools.Polynomial
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "CRC.USB5"
+    [ testCase "usbGood" (assertIsThm usbGood)
+    ]
+
+newtype SWord11 = S11 SWord16
+
+instance EqSymbolic SWord11 where
+  S11 w .== S11 w' = w .== w'
+
+mkSWord11 :: SWord16 -> SWord11
+mkSWord11 w = S11 (w .&. 0x07FF)
+
+extendData :: SWord11 -> SWord16
+extendData (S11 w) = w `shiftL` 5
+
+mkFrame :: SWord11 -> SWord16
+mkFrame w = extendData w .|. crc_11_16 w
+
+-- crc returns 16 bits, but the first 11 are always 0
+crc_11_16 :: SWord11 -> SWord16
+crc_11_16 msg = crc16 .&. 0x1F -- just get the last 5 bits
+  where divisor :: SWord16
+        divisor = polynomial [5, 2, 0]
+        crc16 = pMod (extendData msg) divisor
+
+diffCount :: SWord16 -> SWord16 -> SWord8
+diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
+  where count []     = 0
+        count (b:bs) = let r = count bs in ite b r (1+r)
+
+-- Claim: If there is an undetected corruption, it must be at least at 3 bits
+usbGood :: SWord16 -> SWord16 -> SBool
+usbGood sent16 received16 =
+    sent ./= received .=> diffCount frameSent frameReceived .>= 3
+   where sent     = mkSWord11 sent16
+         received = mkSWord11 received16
+         frameSent     = mkFrame sent
+         frameReceived = mkFrame received
+
+{- HLint ignore crc_11_16 "Use camelCase" -}
diff --git a/SBVTestSuite/TestSuite/CantTypeCheck/Misc.hs b/SBVTestSuite/TestSuite/CantTypeCheck/Misc.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CantTypeCheck/Misc.hs
@@ -0,0 +1,72 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CantTypeCheck.Misc
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for things that should not type-check
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE FlexibleInstances    #-}
+
+-- Defer type-errors is essential here!
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans -Wno-deferred-type-errors -fdefer-type-errors #-}
+
+module TestSuite.CantTypeCheck.Misc(tests) where
+
+import Control.DeepSeq (NFData(..))
+import Utils.SBVTestFramework
+
+-- Only used safely!
+import System.IO.Unsafe(unsafePerformIO)
+instance NFData (IO Bool) where
+  rnf iob = rnf (unsafePerformIO iob) `seq` ()
+
+type Val = (Integer, Integer)
+
+instance Num Val where
+  (+)         = undefined
+  (*)         = undefined
+  (-)         = undefined
+  signum      = undefined
+  abs         = undefined
+  fromInteger = undefined
+
+tests :: TestTree
+tests = testGroup "CantTypeCheck.Misc" [
+           testCase "noTypeCheckBad01"  $ shouldNotTypeCheck $ isTheorem t1
+         , testCase "noTypeCheckBad02"  $ shouldNotTypeCheck $ isTheorem t2
+         , testCase "noTypeCheckBad03"  $ shouldNotTypeCheck   runSko
+         , testCase "noTypeCheckBad04"  $ shouldNotTypeCheck   runNoNum
+         , testCase "noTypeCheckGood01" $                      assertIsSat t1
+         , testCase "noTypeCheckGood02" $                      assertIsSat t2
+
+         -- Just so we got something other than our stuff..
+         , testCase "noTypeCheck05"     $ shouldNotTypeCheck (1 :: String)
+         ]
+  where t1 :: SInteger -> ConstraintSet
+        t1 x = do { constrain ( x .> (5::SInteger)) }
+
+        t2 :: ConstraintSet
+        t2 = pure ()
+
+        -- shouldn't be able to skolemize like this
+        sko :: Forall "y" Integer -> SInteger
+        sko = skolemize fml
+          where fml :: Exists "x" Integer -> Forall "y" Integer -> SInteger
+                fml (Exists x) (Forall y) = x + y
+
+        -- We have to reduce the above to a IO Bool so the rnf instance does the right thing!
+        -- Oh the horrors of "deferring type errors"
+        runSko :: IO Bool
+        runSko = isSatisfiable $ sko (Forall (literal 3))
+
+        -- can't add SBV Val
+        noNumSBV :: SBV Val -> SBV Val -> SBV Val
+        noNumSBV x y = x + y
+
+        runNoNum :: IO Bool
+        runNoNum = isSatisfiable noNumSBV
diff --git a/SBVTestSuite/TestSuite/Char/Char.hs b/SBVTestSuite/TestSuite/Char/Char.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Char/Char.hs
@@ -0,0 +1,112 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Char.Char
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing SChar constraints (as modeled thru strings in SMTLib)
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Char.Char(tests) where
+
+import Utils.SBVTestFramework
+import Data.SBV.Control
+
+import qualified Data.SBV.Either as E
+import qualified Data.SBV.List   as L
+import qualified Data.SBV.Maybe  as M
+import qualified Data.SBV.Set    as S
+import Data.SBV.Tuple
+
+tests :: TestTree
+tests =
+  testGroup "Char" [
+      goldenCapturedIO "charConstr00" $ \rf -> checkWith rf t00
+    , goldenCapturedIO "charConstr01" $ \rf -> checkWith rf t01
+    , goldenCapturedIO "charConstr02" $ \rf -> checkWith rf t02
+    , goldenCapturedIO "charConstr03" $ \rf -> checkWith rf t03
+    , goldenCapturedIO "charConstr04" $ \rf -> checkWith rf t04
+    , goldenCapturedIO "charConstr05" $ \rf -> checkWith rf t05
+    , goldenCapturedIO "charConstr06" $ \rf -> checkWith rf t06
+    , goldenCapturedIO "charConstr07" $ \rf -> checkWith rf t07
+    , goldenCapturedIO "charConstr08" $ \rf -> checkWith rf t08
+    , goldenCapturedIO "charConstr09" $ \rf -> checkWith rf t09
+    , goldenCapturedIO "charConstr10" $ \rf -> checkWith rf t10
+    , goldenCapturedIO "charConstr11" $ \rf -> checkWith rf t11
+    ]
+
+checkWith :: FilePath -> Symbolic () -> IO ()
+checkWith rf props = runSMTWith z3{verbose=True, redirectVerbose = Just rf} $ do
+        _ <- props
+        query $ do cs <- checkSat
+                   case cs of
+                     Unsat  -> io $ appendFile rf "\nUNSAT"
+                     DSat{} -> io $ appendFile rf "\nDSAT"
+                     Sat{}  -> getModel         >>= \m -> io $ appendFile rf $ "\nMODEL: "   ++ show m ++ "\nDONE."
+                     Unk    -> getUnknownReason >>= \r -> io $ appendFile rf $ "\nUNKNOWN: " ++ show r ++ "\nDONE."
+
+cf :: SInteger -> SChar
+cf  = uninterpret "cf"
+
+cf3 :: SInteger -> STuple3 Char Char Char
+cf3 = uninterpret "cf3"
+
+t00 :: Symbolic ()
+t00 = do x <- sChar "x"
+         constrain $ x ./= literal 'A'
+
+t01 :: Symbolic ()
+t01 = constrain $ cf 4 ./= literal 'A'
+
+t02 :: Symbolic ()
+t02 = constrain $ cf3 4 ./= literal ('A', 'B', 'C')
+
+t03 :: Symbolic ()
+t03 = do x::SEither Char Char <- free "x"
+         constrain $ x ./= E.sLeft (literal 'A')
+
+t04 :: Symbolic ()
+t04 = do x::SEither Integer Char <- free "x"
+         constrain $ x ./= E.sRight (literal 'A')
+
+t05 :: Symbolic ()
+t05 = do x::SEither Char Integer <- free "x"
+         constrain $ x ./= E.sLeft (literal 'A')
+
+t06 :: Symbolic ()
+t06 = do x::SEither Char (Either Char Integer) <- free "x"
+         constrain $ x ./= E.sLeft (literal 'A')
+
+t07 :: Symbolic ()
+t07 = do x::SMaybe Char <- free "x"
+         constrain $ M.isJust x .&& x ./= M.sJust (literal 'A')
+
+t08 :: Symbolic ()
+t08 = do x :: SSet Char <- free "x"
+         constrain $ S.member (literal 'A') x .&& sNot (S.member (literal 'B') x)
+
+t09 :: Symbolic ()
+t09 = do x :: SList ((Char, Char), [Integer]) <- free "x"
+         constrain $ L.length x .== 1
+
+t10 :: Symbolic ()
+t10 = do x :: SList ((Char, Char), [Integer]) <- free "x"
+         constrain $ L.length x .== 1
+         constrain $ (x L.!! 0)^._1^._1 .== literal 'B'
+
+cf4 :: SInteger -> SChar -> SList ((Char, Char), [Integer])
+cf4 = uninterpret "cf4"
+
+t11 :: Symbolic ()
+t11 = do x <- sInteger "x"
+         c <- sChar "c"
+         constrain $ L.length (cf4 x c) .== 1
+
+{- HLint ignore module "Use ."        -}
+{- HLint ignore module "Redundant ^." -}
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs b/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs
@@ -0,0 +1,34 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.AddSub
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.AddSub
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.AddSub(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.AddSub
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGen.addSub" [
+   goldenVsStringShow "addSub" code
+ ]
+ where thd (_, _, r) = r
+       code = thd <$> compileToC' "addSub" (do
+                cgSetDriverValues [76, 92]
+                cgPerformRTCs True
+                x <- cgInput "x"
+                y <- cgInput "y"
+                let (s, d) = addSub x y
+                cgOutput "sum" s
+                cgOutput "dif" d)
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs b/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.CRC_USB5
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.CRC_USB5(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CRC.CodeGen" [
+   goldenVsStringShow "crcUSB5_1" $ genC crcUSB
+ , goldenVsStringShow "crcUSB5_2" $ genC crcUSB'
+ ]
+ where thd (_, _, r) = r
+       genC f = thd <$> compileToC' "crcUSB5" (do
+                   cgSetDriverValues [0xFEDC]
+                   msg <- cgInput "msg"
+                   cgReturn $ f msg)
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs b/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.CgTests
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for code-generation features
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.CgTests(tests) where
+
+import Data.SBV.Internals
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.CgTests" [
+   goldenVsStringShow "selChecked"   $ genSelect True  "selChecked"
+ , goldenVsStringShow "selUnchecked" $ genSelect False "selUnChecked"
+ , goldenVsStringShow "codeGen1"       foo
+ ]
+ where thd (_, _, r) = r
+
+       genSelect b n = thd <$> compileToC' n (do
+                         cgSetDriverValues [65]
+                         cgPerformRTCs b
+                         let sel :: SWord8 -> SWord8
+                             sel x = select [1, x+2] 3 x
+                         x <- cgInput "x"
+                         cgReturn $ sel x)
+       foo = thd <$> compileToC' "foo" (do
+                        cgSetDriverValues $ repeat 0
+                        (x::SInt16)    <- cgInput "x"
+                        (ys::[SInt64]) <- cgInputArr 45 "xArr"
+                        cgOutput "z" (5 :: SWord16)
+                        cgOutputArr "zArr" (replicate 7 (x+1))
+                        cgOutputArr "yArr" ys
+                        cgReturn (x*2))
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs b/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.Fibonacci
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.Fibonacci
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.Fibonacci(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.Fibonacci
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.Fibonacci" [
+   goldenVsStringShow "fib1" $ tst [12] "fib1" (fib1 64)
+ , goldenVsStringShow "fib2" $ tst [20] "fib2" (fib2 64)
+ ]
+ where thd (_, _, r) = r
+       tst vs nm f = thd <$> compileToC' nm (do cgPerformRTCs True
+                                                cgSetDriverValues vs
+                                                n <- cgInput "n"
+                                                cgReturn $ f n)
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs b/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs
@@ -0,0 +1,167 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.Floats
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test-suite for generating floating-point related C code
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.Floats(tests) where
+
+import Data.SBV.Internals
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.Floats" [
+   goldenVsStringShow "floats_cgen" code
+ ]
+ where code  = thd <$> compileToCLib' "floatCodeGen" cases
+
+       thd (_, _, r) = r
+
+       setup = do cgSRealType CgLongDouble
+                  cgIntegerSize 64
+                  cgSetDriverValues [42, 43, 44]
+
+       test1 nm f = (nm, do setup
+                            a <- cgInput "a"
+                            cgReturn (f a))
+
+       test2 nm f = (nm, do setup
+                            a <- cgInput "a"
+                            b <- cgInput "b"
+                            cgReturn (f a b))
+
+       test3 nm f = (nm, do setup
+                            a <- cgInput "a"
+                            b <- cgInput "b"
+                            c <- cgInput "c"
+                            cgReturn (f a b c))
+
+       cases = [
+            test1 "toFP_Int8_ToFloat"       (toSFloat sRoundNearestTiesToEven  :: SInt8    -> SFloat)
+          , test1 "toFP_Int16_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt16   -> SFloat)
+          , test1 "toFP_Int32_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt32   -> SFloat)
+          , test1 "toFP_Int64_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt64   -> SFloat)
+          , test1 "toFP_Word8_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SWord8   -> SFloat)
+          , test1 "toFP_Word16_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord16  -> SFloat)
+          , test1 "toFP_Word32_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord32  -> SFloat)
+          , test1 "toFP_Word64_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord64  -> SFloat)
+          , test1 "toFP_Float_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SFloat   -> SFloat)
+          , test1 "toFP_Double_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SDouble  -> SFloat)
+          , test1 "toFP_Integer_ToFloat"    (toSFloat sRoundNearestTiesToEven  :: SInteger -> SFloat)
+          , test1 "toFP_Real_ToFloat"       (toSFloat sRoundNearestTiesToEven  :: SReal    -> SFloat)
+
+          , test1 "toFP_Int8_ToDouble"      (toSDouble sRoundNearestTiesToEven :: SInt8    -> SDouble)
+          , test1 "toFP_Int16_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt16   -> SDouble)
+          , test1 "toFP_Int32_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt32   -> SDouble)
+          , test1 "toFP_Int64_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt64   -> SDouble)
+          , test1 "toFP_Word8_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SWord8   -> SDouble)
+          , test1 "toFP_Word16_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord16  -> SDouble)
+          , test1 "toFP_Word32_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord32  -> SDouble)
+          , test1 "toFP_Word64_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord64  -> SDouble)
+          , test1 "toFP_Float_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SFloat   -> SDouble)
+          , test1 "toFP_Double_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SDouble  -> SDouble)
+          , test1 "toFP_Integer_ToDouble"   (toSDouble sRoundNearestTiesToEven :: SInteger -> SDouble)
+          , test1 "toFP_Real_ToDouble"      (toSDouble sRoundNearestTiesToEven :: SReal    -> SDouble)
+
+          , test1 "fromFP_Float_ToInt8"     (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt8)
+          , test1 "fromFP_Float_ToInt16"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt16)
+          , test1 "fromFP_Float_ToInt32"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt32)
+          , test1 "fromFP_Float_ToInt64"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt64)
+          , test1 "fromFP_Float_ToWord8"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord8)
+          , test1 "fromFP_Float_ToWord16"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord16)
+          , test1 "fromFP_Float_ToWord32"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord32)
+          , test1 "fromFP_Float_ToWord64"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord64)
+          , test1 "fromFP_Float_ToFloat"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SFloat)
+          , test1 "fromFP_Float_ToDouble"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SDouble)
+          , test1 "fromFP_Float_ToInteger"  (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInteger)
+          , test1 "fromFP_Float_ToReal"     (fromSFloat sRoundNearestTiesToEven :: SFloat -> SReal)
+
+          , test1 "fromFP_DoubleTo_Int8"    (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt8)
+          , test1 "fromFP_DoubleTo_Int16"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt16)
+          , test1 "fromFP_DoubleTo_Int32"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt32)
+          , test1 "fromFP_DoubleTo_Int64"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt64)
+          , test1 "fromFP_DoubleTo_Word8"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord8)
+          , test1 "fromFP_DoubleTo_Word16"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord16)
+          , test1 "fromFP_DoubleTo_Word32"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord32)
+          , test1 "fromFP_DoubleTo_Word64"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord64)
+          , test1 "fromFP_DoubleTo_Float"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SFloat)
+          , test1 "fromFP_DoubleTo_Double"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SDouble)
+          , test1 "fromFP_DoubleTo_Integer" (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInteger)
+          , test1 "fromFP_DoubleTo_Real"    (fromSDouble sRoundNearestTiesToEven :: SDouble -> SReal)
+
+          , test1 "fromFP_SWord32_SFloat"   (sWord32AsSFloat  :: SWord32 -> SFloat)
+          , test1 "fromFP_SWord64_SDouble"  (sWord64AsSDouble :: SWord64 -> SDouble)
+          , test1 "fromFP_SFloat_SWord32"   (sFloatAsSWord32  :: SFloat  -> SWord32)
+          , test1 "fromFP_SDouble_SWord64"  (sDoubleAsSWord64 :: SDouble -> SWord64)
+
+          , test1 "f_FP_Abs"                (abs    :: SFloat -> SFloat)
+          , test1 "d_FP_Abs"                (abs    :: SDouble -> SDouble)
+
+          , test1 "f_FP_Neg"                (negate :: SFloat -> SFloat)
+          , test1 "d_FP_Neg"                (negate :: SDouble -> SDouble)
+
+          , test2 "f_FP_Add"                (fpAdd  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Add"                (fpAdd  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
+
+          , test2 "f_FP_Sub"                (fpSub  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Sub"                (fpSub  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
+
+          , test2 "f_FP_Mul"                (fpMul  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Mul"                (fpMul  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
+
+          , test2 "f_FP_Div"                (fpDiv  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Div"                (fpDiv  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
+
+          , test3 "f_FP_FMA"                (fpFMA  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat  -> SFloat)
+          , test3 "d_FP_FMA"                (fpFMA  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble -> SDouble)
+
+          , test1 "f_FP_Sqrt"               (fpSqrt sRoundNearestTiesToEven :: SFloat  -> SFloat)
+          , test1 "d_FP_Sqrt"               (fpSqrt sRoundNearestTiesToEven :: SDouble -> SDouble)
+
+          , test2 "f_FP_Rem"                (fpRem  :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Rem"                (fpRem  :: SDouble -> SDouble -> SDouble)
+
+          , test1 "f_FP_RoundToIntegral"    (fpRoundToIntegral sRoundNearestTiesToEven :: SFloat  -> SFloat)
+          , test1 "d_FP_RoundToIntegral"    (fpRoundToIntegral sRoundNearestTiesToEven :: SDouble -> SDouble)
+
+          , test2 "f_FP_Min"                (fpMin :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Min"                (fpMin :: SDouble -> SDouble -> SDouble)
+
+          , test2 "f_FP_Max"                (fpMax :: SFloat  -> SFloat  -> SFloat)
+          , test2 "d_FP_Max"                (fpMax :: SDouble -> SDouble -> SDouble)
+
+          , test2 "f_FP_IsEqualObject"      (fpIsEqualObject :: SFloat  -> SFloat  -> SBool)
+          , test2 "d_FP_IsEqualObject"      (fpIsEqualObject :: SDouble -> SDouble -> SBool)
+
+          , test1 "f_FP_IsNormal"           (fpIsNormal :: SFloat  -> SBool)
+          , test1 "d_FP_IsNormal"           (fpIsNormal :: SDouble -> SBool)
+
+          , test1 "f_FP_IsZero"             (fpIsZero :: SFloat  -> SBool)
+          , test1 "d_FP_IsZero"             (fpIsZero :: SDouble -> SBool)
+
+          , test1 "f_FP_IsSubnormal"        (fpIsSubnormal :: SFloat  -> SBool)
+          , test1 "d_FP_IsSubnormal"        (fpIsSubnormal :: SDouble -> SBool)
+
+          , test1 "f_FP_IsInfinite"         (fpIsInfinite :: SFloat  -> SBool)
+          , test1 "d_FP_IsInfinite"         (fpIsInfinite :: SDouble -> SBool)
+
+          , test1 "f_FP_IsNaN"              (fpIsNaN :: SFloat  -> SBool)
+          , test1 "d_FP_IsNaN"              (fpIsNaN :: SDouble -> SBool)
+
+          , test1 "f_FP_IsNegative"         (fpIsNegative :: SFloat  -> SBool)
+          , test1 "d_FP_IsNegative"         (fpIsNegative :: SDouble -> SBool)
+
+          , test1 "f_FP_IsPositive"         (fpIsPositive :: SFloat  -> SBool)
+          , test1 "d_FP_IsPositive"         (fpIsPositive :: SDouble -> SBool)
+          ]
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs b/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.GCD
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.GCD
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.GCD(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.GCD
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.GCD" [
+   goldenVsStringShow "gcd" gcdC
+ ]
+ where thd (_, _, r) = r
+       gcdC = thd <$> compileToC' "sgcd" (do
+                cgSetDriverValues [55,154]
+                x <- cgInput "x"
+                y <- cgInput "y"
+                cgReturn $ sgcd x y)
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs b/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.PopulationCount
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.PopulationCount
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.PopulationCount(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.PopulationCount
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.PopulationCount" [
+   goldenVsStringShow "popCount1" $ thd <$> genC False
+ , goldenVsStringShow "popCount2" $ thd <$> genC True
+ ]
+ where genC b = compileToC' "popCount" $ do
+                  cgSetDriverValues [0x0123456789ABCDEF]
+                  cgPerformRTCs b
+                  x <- cgInput "x"
+                  cgReturn $ popCountFast x
+       thd (_, _, r) = r
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs b/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CodeGeneration.Uninterpreted
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CodeGeneration.Uninterpreted(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "CodeGeneration.Uninterpreted" [
+   goldenVsStringShow "cgUninterpret"  genC
+ ]
+ where genC = thd <$> compileToC' "tstShiftLeft" (do cgSetDriverValues [1, 2, 3]
+                                                     [x, y, z] <- cgInputArr 3 "vs"
+                                                     cgReturn $ tstShiftLeft x y z)
+       thd (_, _, r) = r
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase.hs b/SBVTestSuite/TestSuite/CompileTests/PCase.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase.hs
@@ -0,0 +1,19 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CompileTests.PCase
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing TH messages
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CompileTests.PCase(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: IO TestTree
+tests = testGroup "THTests.PCase" <$> mkCompileTestGlob "SBVTestSuite/TestSuite/CompileTests/PCase/PCase*.hs"
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/Expr.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/Expr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/Expr.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Expr where
+
+import Data.SBV
+
+data Expr = Zero
+          | Num Integer
+          | Var String
+          | Add Expr Expr
+          | Let String Expr Expr
+          deriving Show
+
+mkSymbolic [''Expr]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Parse error: EOF
+t :: SExpr -> Proof SBool
+t _e = [pCase| _e of|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase01.stderr
@@ -0,0 +1,8 @@
+PCase01.hs:13:15: error: [GHC-39584]
+    " PCase01.hs:13:21: Parse error: EOF
+
+    " In the quasi-quotation: [pCase| _e of|]
+   |
+13 | t _e = [pCase| _e of|]
+   |               ^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Bad syntax
+t :: SExpr -> Proof SBool
+t e = [pCase| e + 1|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase02.stderr
@@ -0,0 +1,8 @@
+PCase02.hs:13:14: error: [GHC-39584]
+    " PCase02.hs:13:20: Parse error: EOF
+
+    " In the quasi-quotation: [pCase| e + 1|]
+   |
+13 | t e = [pCase| e + 1|]
+   |              ^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Not usable in declaration context
+[pCase| e of
+        Zero  -> undefined
+        Num _ -> undefined
+      |]
+
+{- HLint ignore module "Unused LANGUAGE pragma" -}
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase03.stderr
@@ -0,0 +1,6 @@
+PCase03.hs:12:8: error: [GHC-39584]
+    pCase: not usable in declaration context
+   |
+12 | [pCase| e of
+   |        ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Unknown constructor
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        FooBar _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase04.stderr
@@ -0,0 +1,14 @@
+PCase04.hs:13:14: error: [GHC-39584]
+    " pCase: Unknown constructor: FooBar
+
+        Cannot find this constructor in scope.
+        Make sure the type is declared and mkSymbolic is called.
+
+    " In the quasi-quotation:
+        [pCase| e of
+        FooBar _ -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Unknown constructor
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero  -> undefined
+        Numb _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase05.stderr
@@ -0,0 +1,11 @@
+PCase05.hs:13:14: error: [GHC-39584]
+    " PCase05.hs:15:9-14: sCase/pCase: Not in scope: data constructor: Numb
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero  -> undefined
+        Numb _ -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Pattern guards not supported
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero        -> undefined
+        Num i | Just 1 <- Just i -> undefined
+        Var _       -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase06.stderr
@@ -0,0 +1,14 @@
+PCase06.hs:13:14: error: [GHC-39584]
+    " sCase/pCase: Pattern guards are not supported: 
+        Just 1 <- Just i
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero        -> undefined
+        Num i | Just 1 <- Just i -> undefined
+        Var _       -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Arity mismatch: Num takes 1 arg, given 2
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero     -> undefined
+        Num _ _  -> undefined
+        Var _    -> undefined
+        Add _ _  -> undefined
+        Let _ _ _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase07.stderr
@@ -0,0 +1,19 @@
+PCase07.hs:13:14: error: [GHC-39584]
+    " PCase07.hs:15:9-15: pCase: Arity mismatch.
+        Type       : Expr
+        Constructor: Num
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero     -> undefined
+        Num _ _  -> undefined
+        Var _    -> undefined
+        Add _ _  -> undefined
+        Let _ _ _ -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: wildcard at the end catches remaining constructors
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero    -> e .== e =: qed
+         Num _   -> e .== e =: qed
+         _       -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase08.stderr
@@ -0,0 +1,12 @@
+PCase08.hs:(18,15)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero    -> e .== e =: qed\n\
+      \         Num _   -> e .== e =: qed\n\
+      \         _       -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (sNot ((.||) (isZero e) (isNum e)) ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Overlapping constructors: unguarded Num after guarded Num
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero         -> undefined
+        Num i        -> undefined
+        Num i | i .> 3 -> undefined
+        Var _        -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase09.stderr
@@ -0,0 +1,17 @@
+PCase09.hs:13:14: error: [GHC-39584]
+    " PCase09.hs:16:9-13: pCase: Overlapping case constructors:
+        Constructor: Num i | i .> 3
+      Overlaps with:
+        PCase09.hs:15:9-13: Num i
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero         -> undefined
+        Num i        -> undefined
+        Num i | i .> 3 -> undefined
+        Var _        -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Arity mismatch in nested pattern: Num takes 1, given 2
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero            -> undefined
+        Num k           -> undefined
+        Var _           -> undefined
+        Add (Num i j) b -> undefined
+        Let _ _ _       -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase10.stderr
@@ -0,0 +1,18 @@
+PCase10.hs:13:14: error: [GHC-39584]
+    " PCase10.hs:17:9-23: sCase/pCase: Arity mismatch in nested pattern.
+        Constructor: Num
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero            -> undefined
+        Num k           -> undefined
+        Var _           -> undefined
+        Add (Num i j) b -> undefined
+        Let _ _ _       -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Unknown constructor in nested pattern
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero           -> undefined
+        Num k          -> undefined
+        Var _          -> undefined
+        Add (Numb i) b -> undefined
+        Let _ _ _      -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase11.stderr
@@ -0,0 +1,14 @@
+PCase11.hs:13:14: error: [GHC-39584]
+    " PCase11.hs:17:9-22: sCase/pCase: Not in scope: data constructor: Numb
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero           -> undefined
+        Num k          -> undefined
+        Var _          -> undefined
+        Add (Numb i) b -> undefined
+        Let _ _ _      -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: all constructors covered, no guards; use matched fields in proof
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num i     -> sNum i .== sNum i =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase12.stderr
@@ -0,0 +1,30 @@
+PCase12.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num i     -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: partial coverage is fine in pCase (no exhaustiveness check)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero  -> e .== e =: qed
+         Num i -> sNum i .== sNum i =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase13.stderr
@@ -0,0 +1,12 @@
+PCase13.hs:(18,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero  -> e .== e =: qed\n\
+      \         Num i -> sNum i .== sNum i =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: guard on one constructor; use matched field in proof
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero           -> e .== e =: qed
+         Num i | i .> 0 -> sNum i .== sNum i =: e .== e =: qed
+         Var s          -> sVar s .== sVar s =: e .== e =: qed
+         Add a b        -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b     -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase14.stderr
@@ -0,0 +1,30 @@
+PCase14.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero           -> e .== e =: qed\n\
+      \         Num i | i .> 0 -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s          -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b        -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b     -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: multi-arm same constructor with guards (guard accumulation)
+-- Second arm gets: isNum e .&& sNot (i .> 0)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero             -> e .== e =: qed
+         Num i | i .> 0   -> sNum i .== sNum i =: e .== e =: qed
+               | sTrue    -> sNum i .== sNum i =: e .== e =: qed
+         Var s            -> sVar s .== sVar s =: e .== e =: qed
+         Add a b          -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b       -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase15.stderr
@@ -0,0 +1,33 @@
+PCase15.hs:(19,15)-(26,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero             -> e .== e =: qed\n\
+      \         Num i | i .> 0   -> sNum i .== sNum i =: e .== e =: qed\n\
+      \               | sTrue    -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s            -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b          -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b       -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 0))
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested pattern; use matched fields including nested ones
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero            -> e .== e =: qed
+         Num k           -> sNum k .== sNum k =: e .== e =: qed
+         Var s           -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num i) _   -> sNum i .== sNum i =: e .== e =: qed
+         Add a       b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b      -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase16.stderr
@@ -0,0 +1,35 @@
+PCase16.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero            -> e .== e =: qed\n\
+      \         Num k           -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s           -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num i) _   -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Add a       b   -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b      -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&) (isAdd e) (isNum (getAdd_1 e))
+          ==>
+            (let i = getNum_1 (getAdd_1 e)
+             in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isAdd e) (sNot (isNum (getAdd_1 e)))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: pCase generates cases [...] which has type TPProofRaw, not Proof SBool;
+-- so using pCase outside a TP proof context is a type error
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+       Zero      -> e .== e =: qed
+       Num _     -> e .== e =: qed
+       Var _     -> e .== e =: qed
+       Add _ _   -> e .== e =: qed
+       Let _ _ _ -> e .== e =: qed
+     |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase17.stderr
@@ -0,0 +1,32 @@
+PCase17.hs:(18,14)-(24,7): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \       Zero      -> e .== e =: qed\n\
+      \       Num _     -> e .== e =: qed\n\
+      \       Var _     -> e .== e =: qed\n\
+      \       Add _ _   -> e .== e =: qed\n\
+      \       Let _ _ _ -> e .== e =: qed\n\
+      \     "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (isVar e ==> (e .== e =: qed)), (isAdd e ==> (e .== e =: qed)),
+       (isLet e ==> (e .== e =: qed))]
+PCase17.hs:18:14: error: [GHC-83865]
+    " Couldn't match expected type: Proof SBool
+                  with actual type: sbv-14.4:Data.SBV.TP.TP.TPProofGen
+                                      (SBV Bool) [sbv-14.4:Data.SBV.TP.TP.Helper] ()
+    " In the expression:
+        cases
+          [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+           (isVar e ==> (e .== e =: qed)), ....]
+      In an equation for t:
+          t e
+            = (cases
+                 [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+                  (isVar e ==> (e .== e =: qed)), ....])
+   |
+18 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: wildcard with args (e.g. _ _ ->)
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero    -> undefined
+        Num _   -> undefined
+        Var _   -> undefined
+        Add _ _ -> undefined
+        _ _     -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase18.stderr
@@ -0,0 +1,15 @@
+PCase18.hs:13:14: error: [GHC-39584]
+    " PCase18.hs:18:17: Parse error in pattern: _
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero    -> undefined
+        Num _   -> undefined
+        Var _   -> undefined
+        Add _ _ -> undefined
+        _ _     -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: overlapping — second group for same constructor after first has sTrue catch-all guard
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero             -> undefined
+        Num i | i .> 3   -> undefined
+              | sTrue    -> undefined
+        Num i | i .> 12  -> undefined
+        Var _            -> undefined
+        Add _ _          -> undefined
+        Let _ _ _        -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase19.stderr
@@ -0,0 +1,20 @@
+PCase19.hs:13:14: error: [GHC-39584]
+    " PCase19.hs:17:9-13: pCase: Overlapping case constructors:
+        Constructor: Num i | i .> 12
+      Overlaps with:
+        PCase19.hs:15:9-13: Num i
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero             -> undefined
+        Num i | i .> 3   -> undefined
+              | sTrue    -> undefined
+        Num i | i .> 12  -> undefined
+        Var _            -> undefined
+        Add _ _          -> undefined
+        Let _ _ _        -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: {} wildcard patterns; use matched field where available
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Num i | i .> 3  -> sNum i .== sNum i =: e .== e =: qed
+               | sTrue   -> sNum i .== sNum i =: e .== e =: qed
+         Zero{}           -> e .== e =: qed
+         Var{}            -> e .== e =: qed
+         Add{}            -> e .== e =: qed
+         Let{}            -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase20.stderr
@@ -0,0 +1,19 @@
+PCase20.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Num i | i .> 3  -> sNum i .== sNum i =: e .== e =: qed\n\
+      \               | sTrue   -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Zero{}           -> e .== e =: qed\n\
+      \         Var{}            -> e .== e =: qed\n\
+      \         Add{}            -> e .== e =: qed\n\
+      \         Let{}            -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&) (isNum e) (let i = getNum_1 e in i .> 3)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 3))
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isZero e ==> (e .== e =: qed)), (isVar e ==> (e .== e =: qed)),
+       (isAdd e ==> (e .== e =: qed)), (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: deeply nested pattern Add (Add (Num _) j) k; use matched fields
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero                  -> e .== e =: qed
+         Num k                 -> sNum k .== sNum k =: e .== e =: qed
+         Var s                 -> sVar s .== sVar s =: e .== e =: qed
+         Add (Add (Num _) j) _ -> sAdd j j .== sAdd j j =: e .== e =: qed
+         Add a b               -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b            -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase21.stderr
@@ -0,0 +1,39 @@
+PCase21.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero                  -> e .== e =: qed\n\
+      \         Num k                 -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s                 -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Add (Num _) j) _ -> sAdd j j .== sAdd j j =: e .== e =: qed\n\
+      \         Add a b               -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b            -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&) (isAdd (getAdd_1 e)) (isNum (getAdd_1 (getAdd_1 e))))
+          ==>
+            (let j = getAdd_2 (getAdd_1 e)
+             in (sAdd j j) .== sAdd j j =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot ((.&&) (isAdd (getAdd_1 e)) (isNum (getAdd_1 (getAdd_1 e)))))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested pattern combined with a guard; use matched fields
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero                    -> e .== e =: qed
+         Num k                   -> sNum k .== sNum k =: e .== e =: qed
+         Var s                   -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num i) _ | i .> 0  -> sNum i .== sNum i =: e .== e =: qed
+         Add a b                 -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b              -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase22.stderr
@@ -0,0 +1,42 @@
+PCase22.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero                    -> e .== e =: qed\n\
+      \         Num k                   -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s                   -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num i) _ | i .> 0  -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Add a b                 -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b              -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&)
+             (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+          ==>
+            (let i = getNum_1 (getAdd_1 e)
+             in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&)
+                (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested patterns on both sides; use matched fields
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero                -> e .== e =: qed
+         Num k               -> sNum k .== sNum k =: e .== e =: qed
+         Var s               -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num i) (Num j) -> sNum (i + j) .== sNum (i + j) =: e .== e =: qed
+         Add a b             -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b          -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase23.stderr
@@ -0,0 +1,38 @@
+PCase23.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero                -> e .== e =: qed\n\
+      \         Num k               -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s               -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num i) (Num j) -> sNum (i + j) .== sNum (i + j) =: e .== e =: qed\n\
+      \         Add a b             -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b          -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&) (isAdd e) ((.&&) (isNum (getAdd_1 e)) (isNum (getAdd_2 e)))
+          ==>
+            (let
+               i = getNum_1 (getAdd_1 e)
+               j = getNum_1 (getAdd_2 e)
+             in (sNum (i + j)) .== sNum (i + j) =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e) (sNot ((.&&) (isNum (getAdd_1 e)) (isNum (getAdd_2 e))))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested pattern with wildcard inside; use matched fields
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero          -> e .== e =: qed
+         Num k         -> sNum k .== sNum k =: e .== e =: qed
+         Var s         -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num _) _ -> e .== e =: qed
+         Add a b       -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase24.stderr
@@ -0,0 +1,32 @@
+PCase24.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero          -> e .== e =: qed\n\
+      \         Num k         -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s         -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num _) _ -> e .== e =: qed\n\
+      \         Add a b       -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&) (isAdd e) (isNum (getAdd_1 e)) ==> (e .== e =: qed)),
+       ((.&&) (isAdd e) (sNot (isNum (getAdd_1 e)))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested pattern using parenthesized constructor; use matched fields
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero              -> e .== e =: qed
+         Num k             -> sNum k .== sNum k =: e .== e =: qed
+         Var s             -> sVar s .== sVar s =: e .== e =: qed
+         Let _ (Num i) _  -> sNum i .== sNum i =: e .== e =: qed
+         Let nm a       b  -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+         Add a b           -> sAdd a b .== sAdd a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase25.stderr
@@ -0,0 +1,35 @@
+PCase25.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero              -> e .== e =: qed\n\
+      \         Num k             -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s             -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Let _ (Num i) _  -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Let nm a       b  -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \         Add a b           -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&) (isLet e) (isNum (getLet_2 e))
+          ==>
+            (let i = getNum_1 (getLet_2 e)
+             in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isLet e) (sNot (isNum (getLet_2 e)))
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: integer literal at top level (Num 1 -> ...)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num 1     -> sNum 1 .== sNum 1 =: e .== e =: qed
+         Num k     -> sNum k .== sNum k =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase26.stderr
@@ -0,0 +1,33 @@
+PCase26.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num 1     -> sNum 1 .== sNum 1 =: e .== e =: qed\n\
+      \         Num k     -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) ((.==) (getNum_1 e) 1)
+          ==> ((sNum 1) .== sNum 1 =: e .== e =: qed)),
+       ((.&&) (isNum e) (sNot ((.==) (getNum_1 e) 1))
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: integer literal in nested position (Add (Num 0) j -> ...)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero          -> e .== e =: qed
+         Num k         -> sNum k .== sNum k =: e .== e =: qed
+         Var s         -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num 0) _ -> sNum 0 .== sNum 0 =: e .== e =: qed
+         Add a b       -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase27.stderr
@@ -0,0 +1,38 @@
+PCase27.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero          -> e .== e =: qed\n\
+      \         Num k         -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s         -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num 0) _ -> sNum 0 .== sNum 0 =: e .== e =: qed\n\
+      \         Add a b       -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 0))
+          ==> ((sNum 0) .== sNum 0 =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 0)))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: string literal in nested position (Var "x" -> ...)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num k     -> sNum k .== sNum k =: e .== e =: qed
+         Var "x"   -> sVar (literal "x") .== sVar (literal "x") =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase28.stderr
@@ -0,0 +1,34 @@
+PCase28.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num k     -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var \"x\"   -> sVar (literal \"x\") .== sVar (literal \"x\") =: e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       ((.&&) (isVar e) ((.==) (getVar_1 e) (literal "x"))
+          ==>
+            ((sVar (literal "x")) .== sVar (literal "x") =: e .== e =: qed)),
+       ((.&&) (isVar e) (sNot ((.==) (getVar_1 e) (literal "x")))
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: integer literals on both sides of nested pattern
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero                -> e .== e =: qed
+         Num k               -> sNum k .== sNum k =: e .== e =: qed
+         Var s               -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num 1) (Num 2) -> sAdd (sNum 1) (sNum 2) .== sAdd (sNum 1) (sNum 2) =: e .== e =: qed
+         Add a b             -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b          -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase29.stderr
@@ -0,0 +1,48 @@
+PCase29.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero                -> e .== e =: qed\n\
+      \         Num k               -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s               -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num 1) (Num 2) -> sAdd (sNum 1) (sNum 2) .== sAdd (sNum 1) (sNum 2) =: e .== e =: qed\n\
+      \         Add a b             -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b          -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&)
+             (isNum (getAdd_1 e))
+             ((.&&)
+                ((.==) (getNum_1 (getAdd_1 e)) 1)
+                ((.&&) (isNum (getAdd_2 e)) ((.==) (getNum_1 (getAdd_2 e)) 2))))
+          ==>
+            ((sAdd (sNum 1) (sNum 2)) .== sAdd (sNum 1) (sNum 2) =: e .== e
+               =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&)
+                (isNum (getAdd_1 e))
+                ((.&&)
+                   ((.==) (getNum_1 (getAdd_1 e)) 1)
+                   ((.&&) (isNum (getAdd_2 e)) ((.==) (getNum_1 (getAdd_2 e)) 2)))))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: Num 1 as only Num arm, no fallback — fine in pCase (no exhaustiveness check)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num 1     -> sNum 1 .== sNum 1 =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add _ _   -> e .== e =: qed
+         Let _ _ _ -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase30.stderr
@@ -0,0 +1,18 @@
+PCase30.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num 1     -> sNum 1 .== sNum 1 =: e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add _ _   -> e .== e =: qed\n\
+      \         Let _ _ _ -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) ((.==) (getNum_1 e) 1)
+          ==> ((sNum 1) .== sNum 1 =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e ==> (e .== e =: qed)), (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: Add (Num 1) j without fallback for Add — fine in pCase (no exhaustiveness check)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero          -> e .== e =: qed
+         Num k         -> sNum k .== sNum k =: e .== e =: qed
+         Var s         -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num 1) _ -> sNum 1 .== sNum 1 =: e .== e =: qed
+         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase31.stderr
@@ -0,0 +1,28 @@
+PCase31.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero          -> e .== e =: qed\n\
+      \         Num k         -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s         -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num 1) _ -> sNum 1 .== sNum 1 =: e .== e =: qed\n\
+      \         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 1))
+          ==> ((sNum 1) .== sNum 1 =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: only 2 of 5 constructors covered, including a guarded one
+-- (sCase would reject this as non-exhaustive; pCase is fine)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero           -> e .== e =: qed
+         Num i | i .> 0 -> sNum i .== sNum i =: e .== e =: qed
+         Var s          -> sVar s .== sVar s =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase32.stderr
@@ -0,0 +1,15 @@
+PCase32.hs:(19,15)-(23,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero           -> e .== e =: qed\n\
+      \         Num i | i .> 0 -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s          -> sVar s .== sVar s =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative in pCase: wildcard mid-list (after two constructors, before more)
+-- Wildcard makes the remaining matches redundant
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero  -> undefined
+        Num _ -> undefined
+        _     -> undefined
+        Var _ -> undefined
+        Add _ _ -> undefined
+        Let _ _ _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase33.stderr
@@ -0,0 +1,19 @@
+PCase33.hs:14:14: error: [GHC-39584]
+    " PCase33.hs:17:9: pCase: Wildcard makes the remaining matches redundant:
+        PCase33.hs:18:9-13: Var _
+        PCase33.hs:19:9-15: Add _ _
+        PCase33.hs:20:9-17: Let _ _ _
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero  -> undefined
+        Num _ -> undefined
+        _     -> undefined
+        Var _ -> undefined
+        Add _ _ -> undefined
+        Let _ _ _ -> undefined
+      |]
+   |
+14 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative in pCase: two wildcards, second is redundant
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero  -> undefined
+        Num _ -> undefined
+        _     -> undefined
+        _     -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase34.stderr
@@ -0,0 +1,15 @@
+PCase34.hs:13:14: error: [GHC-39584]
+    " PCase34.hs:16:9: pCase: Wildcard makes the remaining matches redundant:
+        PCase34.hs:17:9: _
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero  -> undefined
+        Num _ -> undefined
+        _     -> undefined
+        _     -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: single guarded arm with no fallback for that constructor
+-- (sCase rejects this as "guarded match might fail"; pCase is fine)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero           -> e .== e =: qed
+         Num i | i .< 3 -> sNum i .== sNum i =: e .== e =: qed
+         Var s          -> sVar s .== sVar s =: e .== e =: qed
+         Add _ _        -> e .== e =: qed
+         Let _ _ _      -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase35.stderr
@@ -0,0 +1,18 @@
+PCase35.hs:(19,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero           -> e .== e =: qed\n\
+      \         Num i | i .< 3 -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s          -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add _ _        -> e .== e =: qed\n\
+      \         Let _ _ _      -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .< 3)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e ==> (e .== e =: qed)), (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: guarded wildcard at end with ambiguous type in guard (2 .>= 3)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+       Zero           -> e .== e =: qed
+       Num _          -> e .== e =: qed
+       Var _          -> e .== e =: qed
+       Add _ _        -> e .== e =: qed
+       Let _ _ _      -> e .== e =: qed
+       _ | 2 .>= 3   -> e .== e =: qed
+     |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase36.stderr
@@ -0,0 +1,15 @@
+PCase36.hs:18:15: error: [GHC-39584]
+    " PCase36.hs:24:8: pCase: Wildcard match is redundant
+    " In the quasi-quotation:
+        [pCase| e of
+       Zero           -> e .== e =: qed
+       Num _          -> e .== e =: qed
+       Var _          -> e .== e =: qed
+       Add _ _        -> e .== e =: qed
+       Let _ _ _      -> e .== e =: qed
+       _ | 2 .>= 3   -> e .== e =: qed
+     |]
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: all constructors covered + guarded wildcard with ambiguous type in guard (2 .>= 3)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+       Zero           -> e .== e =: qed
+       Num i          -> sNum i .== sNum i =: e .== e =: qed
+       Var _          -> e .== e =: qed
+       Add _ _        -> e .== e =: qed
+       Let _ _ _      -> e .== e =: qed
+       _ | 2 .>= 3   -> e .== e =: qed
+     |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase37.stderr
@@ -0,0 +1,15 @@
+PCase37.hs:18:15: error: [GHC-39584]
+    " PCase37.hs:24:8: pCase: Wildcard match is redundant
+    " In the quasi-quotation:
+        [pCase| e of
+       Zero           -> e .== e =: qed
+       Num i          -> sNum i .== sNum i =: e .== e =: qed
+       Var _          -> e .== e =: qed
+       Add _ _        -> e .== e =: qed
+       Let _ _ _      -> e .== e =: qed
+       _ | 2 .>= 3   -> e .== e =: qed
+     |]
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero      -> undefined
+        Num _     -> undefined
+        Var _     -> undefined
+        Add _ _   -> undefined
+        Let _ _ _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase38.stderr
@@ -0,0 +1,32 @@
+PCase38.hs:(12,14)-(18,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \        Zero      -> undefined\n\
+      \        Num _     -> undefined\n\
+      \        Var _     -> undefined\n\
+      \        Add _ _   -> undefined\n\
+      \        Let _ _ _ -> undefined\n\
+      \      "
+  ======>
+    cases
+      [(isZero e ==> undefined), (isNum e ==> undefined),
+       (isVar e ==> undefined), (isAdd e ==> undefined),
+       (isLet e ==> undefined)]
+PCase38.hs:12:14: error: [GHC-83865]
+    " Couldn't match expected type: Proof SBool
+                  with actual type: sbv-14.4:Data.SBV.TP.TP.TPProofGen
+                                      a0 [sbv-14.4:Data.SBV.TP.TP.Helper] ()
+    " In the expression:
+        cases
+          [(isZero e ==> undefined), (isNum e ==> undefined),
+           (isVar e ==> undefined), ....]
+      In an equation for t:
+          t e
+            = (cases
+                 [(isZero e ==> undefined), (isNum e ==> undefined),
+                  (isVar e ==> undefined), ....])
+   |
+12 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: nested pattern covers only a subset of Add, no fallback
+-- (sCase rejects as non-exhaustive; pCase is fine)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero          -> e .== e =: qed
+         Num k         -> sNum k .== sNum k =: e .== e =: qed
+         Var s         -> sVar s .== sVar s =: e .== e =: qed
+         Add (Num i) _ -> sNum i .== sNum i =: e .== e =: qed
+         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase39.stderr
@@ -0,0 +1,28 @@
+PCase39.hs:(19,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero          -> e .== e =: qed\n\
+      \         Num k         -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s         -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Num i) _ -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Let nm a b    -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&) (isAdd e) (isNum (getAdd_1 e))
+          ==>
+            (let i = getNum_1 (getAdd_1 e)
+             in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: deeply nested pattern, no fallback for outer Add
+-- (sCase rejects as non-exhaustive; pCase is fine)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero                          -> e .== e =: qed
+         Num k                         -> sNum k .== sNum k =: e .== e =: qed
+         Var s                         -> sVar s .== sVar s =: e .== e =: qed
+         Add (Add (Add (Num _) b) c) _ -> sAdd b (sAdd c c) .== e =: qed
+         Let nm a b                    -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase40.stderr
@@ -0,0 +1,36 @@
+PCase40.hs:(19,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero                          -> e .== e =: qed\n\
+      \         Num k                         -> sNum k .== sNum k =: e .== e =: qed\n\
+      \         Var s                         -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add (Add (Add (Num _) b) c) _ -> sAdd b (sAdd c c) .== e =: qed\n\
+      \         Let nm a b                    -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let k = getNum_1 e in (sNum k) .== sNum k =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          ((.&&)
+             (isAdd (getAdd_1 e))
+             ((.&&)
+                (isAdd (getAdd_1 (getAdd_1 e)))
+                (isNum (getAdd_1 (getAdd_1 (getAdd_1 e))))))
+          ==>
+            (let
+               c = getAdd_2 (getAdd_1 e)
+               b = getAdd_2 (getAdd_1 (getAdd_1 e))
+             in (sAdd b (sAdd c c)) .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: parse error (else keyword in wrong position)
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero  -> undefined
+        Var s -> ite (s .== "a") undefined else undefined
+        Num _ -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase41.stderr
@@ -0,0 +1,13 @@
+PCase41.hs:13:14: error: [GHC-39584]
+    " PCase41.hs:15:44: Parse error: else
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero  -> undefined
+        Var s -> ite (s .== "a") undefined else undefined
+        Num _ -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: Num split across two arms — guarded first, unguarded fallback later
+-- (same constructor appearing in two separate groups is fine in pCase)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero           -> e .== e =: qed
+         Num i | i .< 3 -> sNum i .== sNum i =: e .== e =: qed
+         Var s          -> sVar s .== sVar s =: e .== e =: qed
+         Add a b        -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Num i          -> sNum i .== sNum i =: e .== e =: qed
+         Let nm a b     -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase42.stderr
@@ -0,0 +1,33 @@
+PCase42.hs:(19,15)-(26,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero           -> e .== e =: qed\n\
+      \         Num i | i .< 3 -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s          -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b        -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Num i          -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Let nm a b     -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .< 3)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .< 3))
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: guarded constructor without full coverage (exhaustiveness deferred to proof time)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero              -> e .== e =: qed
+         Num _             -> e .== e =: qed
+         Var _             -> e .== e =: qed
+         Add a _ | isZero a -> e .== e =: qed
+         Let _ _ _         -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase43.stderr
@@ -0,0 +1,17 @@
+PCase43.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero              -> e .== e =: qed\n\
+      \         Num _             -> e .== e =: qed\n\
+      \         Var _             -> e .== e =: qed\n\
+      \         Add a _ | isZero a -> e .== e =: qed\n\
+      \         Let _ _ _         -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (isVar e ==> (e .== e =: qed)),
+       ((.&&) (isAdd e) (let a = getAdd_1 e in isZero a)
+          ==> (e .== e =: qed)),
+       (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: wildcard catch-all after multi-arm guarded Var and Num
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Var s | s .== literal "a"                       -> e .== e =: qed
+               | s .== literal "b" .|| s .== literal "c" -> e .== e =: qed
+               | sTrue                                    -> e .== e =: qed
+
+         Num _ | sTrue                                    -> e .== e =: qed
+
+         _                                                -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase44.stderr
@@ -0,0 +1,48 @@
+PCase44.hs:(18,15)-(26,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Var s | s .== literal \"a\"                       -> e .== e =: qed\n\
+      \               | s .== literal \"b\" .|| s .== literal \"c\" -> e .== e =: qed\n\
+      \               | sTrue                                    -> e .== e =: qed\n\
+      \\n\
+      \         Num _ | sTrue                                    -> e .== e =: qed\n\
+      \\n\
+      \         _                                                -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&) (isVar e) (let s = getVar_1 e in s .== literal "a")
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isVar e)
+          ((.&&)
+             (sNot (let s = getVar_1 e in s .== literal "a"))
+             (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c"))
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isVar e)
+          ((.&&)
+             (sNot (let s = getVar_1 e in s .== literal "a"))
+             (sNot
+                (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c")))
+          ==> (e .== e =: qed)),
+       (isNum e ==> (e .== e =: qed)),
+       (sNot
+          ((.||)
+             ((.||)
+                ((.||)
+                   ((.&&) (isVar e) (let s = getVar_1 e in s .== literal "a"))
+                   ((.&&)
+                      (isVar e)
+                      ((.&&)
+                         (sNot (let s = getVar_1 e in s .== literal "a"))
+                         (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c"))))
+                ((.&&)
+                   (isVar e)
+                   ((.&&)
+                      (sNot (let s = getVar_1 e in s .== literal "a"))
+                      (sNot
+                         (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c")))))
+             (isNum e))
+          ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: bound variable i from Num is not used in the RHS
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num i     -> e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase45.stderr
@@ -0,0 +1,35 @@
+PCase45.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num i     -> e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e ==> (let i = getNum_1 e in e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
+PCase45.hs:18:15: error: [GHC-40910] [-Wunused-local-binds, Werror=unused-local-binds]
+    Defined but not used: i
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: bound variables a, b from Add are not used in the RHS
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num i     -> sNum i .== sNum i =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Add a b   -> e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase46.stderr
@@ -0,0 +1,42 @@
+PCase46.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num i     -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s     -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b   -> e .== e =: qed\n\
+      \         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       (isVar e
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in e .== e =: qed)),
+       (isLet e
+          ==>
+            (let
+               nm = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet nm a b) .== sLet nm a b =: e .== e =: qed))]
+PCase46.hs:18:15: error: [GHC-40910] [-Wunused-local-binds, Werror=unused-local-binds]
+    Defined but not used: b
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
+PCase46.hs:18:15: error: [GHC-40910] [-Wunused-local-binds, Werror=unused-local-binds]
+    Defined but not used: a
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: Var s before Var "x" — Var s overlaps with Var "x"
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num k     -> sNum k .== sNum k =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Var "x"   -> sVar (literal "x") .== sVar (literal "x") =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase47.stderr
@@ -0,0 +1,19 @@
+PCase47.hs:18:15: error: [GHC-39584]
+    " PCase47.hs:22:10-16: pCase: Overlapping case constructors:
+        Constructor: Var _ | (Data.SBV.Core.Data..==) (getVar_1 e) (Data.SBV.Core.Data.literal "x")
+      Overlaps with:
+        PCase47.hs:21:10-14: Var s
+
+    " In the quasi-quotation:
+        [pCase| e of
+         Zero      -> e .== e =: qed
+         Num k     -> sNum k .== sNum k =: e .== e =: qed
+         Var s     -> sVar s .== sVar s =: e .== e =: qed
+         Var "x"   -> sVar (literal "x") .== sVar (literal "x") =: e .== e =: qed
+         Add a b   -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let nm a b -> sLet nm a b .== sLet nm a b =: e .== e =: qed
+       |]
+   |
+18 |     |- [pCase| e of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: multi-arm guarded Var and Num, no wildcard catch-all
+-- (sCase would reject as non-exhaustive; pCase is fine)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Var s | s .== literal "a"                       -> e .== e =: qed
+               | s .== literal "b" .|| s .== literal "c" -> e .== e =: qed
+               | sTrue                                    -> e .== e =: qed
+
+         Num _ | sTrue                                    -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase48.stderr
@@ -0,0 +1,28 @@
+PCase48.hs:(19,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Var s | s .== literal \"a\"                       -> e .== e =: qed\n\
+      \               | s .== literal \"b\" .|| s .== literal \"c\" -> e .== e =: qed\n\
+      \               | sTrue                                    -> e .== e =: qed\n\
+      \\n\
+      \         Num _ | sTrue                                    -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&) (isVar e) (let s = getVar_1 e in s .== literal "a")
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isVar e)
+          ((.&&)
+             (sNot (let s = getVar_1 e in s .== literal "a"))
+             (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c"))
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isVar e)
+          ((.&&)
+             (sNot (let s = getVar_1 e in s .== literal "a"))
+             (sNot
+                (let s = getVar_1 e in s .== literal "b" .|| s .== literal "c")))
+          ==> (e .== e =: qed)),
+       (isNum e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: guarded wildcard as last arm after explicit constructors
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero    -> e .== e =: qed
+         Num _   -> e .== e =: qed
+         _ | sTrue -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase49.stderr
@@ -0,0 +1,12 @@
+PCase49.hs:(18,15)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero    -> e .== e =: qed\n\
+      \         Num _   -> e .== e =: qed\n\
+      \         _ | sTrue -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (sNot ((.||) (isZero e) (isNum e)) ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: wildcard-only, no explicit constructors
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         _ -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase50.stderr
@@ -0,0 +1,8 @@
+PCase50.hs:(18,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         _ -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases [(sTrue ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Positive: guarded wildcard only, no explicit constructors
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         _ | isZero e  -> e .== e =: qed
+           | sTrue     -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase51.stderr
@@ -0,0 +1,11 @@
+PCase51.hs:(18,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         _ | isZero e  -> e .== e =: qed\n\
+      \           | sTrue     -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (sNot (isZero e) ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Negative: guarded wildcard before explicit constructor matches
+t :: SExpr -> Proof SBool
+t e = [pCase| e of
+        Zero       -> undefined
+        _ | sTrue  -> undefined
+        Num _      -> undefined
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase52.stderr
@@ -0,0 +1,14 @@
+PCase52.hs:13:14: error: [GHC-39584]
+    " PCase52.hs:15:9: pCase: Wildcard makes the remaining matches redundant:
+        PCase52.hs:16:9-13: Num _
+
+    " In the quasi-quotation:
+        [pCase| e of
+        Zero       -> undefined
+        _ | sTrue  -> undefined
+        Num _      -> undefined
+      |]
+   |
+13 | t e = [pCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: simple unguarded, all constructors
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num _     -> e .== e =: qed
+         Var _     -> e .== e =: qed
+         Add _ _   -> e .== e =: qed
+         Let _ _ _ -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase53.stderr
@@ -0,0 +1,15 @@
+PCase53.hs:(18,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num _     -> e .== e =: qed\n\
+      \         Var _     -> e .== e =: qed\n\
+      \         Add _ _   -> e .== e =: qed\n\
+      \         Let _ _ _ -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (isVar e ==> (e .== e =: qed)), (isAdd e ==> (e .== e =: qed)),
+       (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: multiple guards on same constructor (guard accumulation)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero              -> e .== e =: qed
+         Num i | i .< 3    -> e .== e =: qed
+               | i .< 10   -> e .== e =: qed
+               | sTrue     -> e .== e =: qed
+         Var _             -> e .== e =: qed
+         Add _ _           -> e .== e =: qed
+         Let _ _ _         -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase54.stderr
@@ -0,0 +1,31 @@
+PCase54.hs:(18,15)-(26,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero              -> e .== e =: qed\n\
+      \         Num i | i .< 3    -> e .== e =: qed\n\
+      \               | i .< 10   -> e .== e =: qed\n\
+      \               | sTrue     -> e .== e =: qed\n\
+      \         Var _             -> e .== e =: qed\n\
+      \         Add _ _           -> e .== e =: qed\n\
+      \         Let _ _ _         -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .< 3)
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isNum e)
+          ((.&&)
+             (sNot (let i = getNum_1 e in i .< 3))
+             (let i = getNum_1 e in i .< 10))
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isNum e)
+          ((.&&)
+             (sNot (let i = getNum_1 e in i .< 3))
+             (sNot (let i = getNum_1 e in i .< 10)))
+          ==> (e .== e =: qed)),
+       (isVar e ==> (e .== e =: qed)), (isAdd e ==> (e .== e =: qed)),
+       (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: wildcard after some constructors (De Morgan negation)
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Zero      -> e .== e =: qed
+         Num _     -> e .== e =: qed
+         _         -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase55.stderr
@@ -0,0 +1,12 @@
+PCase55.hs:(18,15)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero      -> e .== e =: qed\n\
+      \         Num _     -> e .== e =: qed\n\
+      \         _         -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (sNot ((.||) (isZero e) (isNum e)) ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: guarded wildcard + nested pattern on a constructor
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Add (Num i) _ | i .> 0  -> e .== e =: qed
+         Add _ _                  -> e .== e =: qed
+         _ | isZero e             -> e .== e =: qed
+           | sTrue                -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase56.stderr
@@ -0,0 +1,62 @@
+PCase56.hs:(18,15)-(23,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Add (Num i) _ | i .> 0  -> e .== e =: qed\n\
+      \         Add _ _                  -> e .== e =: qed\n\
+      \         _ | isZero e             -> e .== e =: qed\n\
+      \           | sTrue                -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&)
+          (isAdd e)
+          ((.&&)
+             (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&)
+                (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+          ==> (e .== e =: qed)),
+       ((.&&)
+          (sNot
+             ((.||)
+                ((.&&)
+                   (isAdd e)
+                   ((.&&)
+                      (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                ((.&&)
+                   (isAdd e)
+                   (sNot
+                      ((.&&)
+                         (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))))))
+          (isZero e)
+          ==> (e .== e =: qed)),
+       (sNot
+          ((.||)
+             ((.||)
+                ((.&&)
+                   (isAdd e)
+                   ((.&&)
+                      (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                ((.&&)
+                   (isAdd e)
+                   (sNot
+                      ((.&&)
+                         (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))))
+             ((.&&)
+                (sNot
+                   ((.||)
+                      ((.&&)
+                         (isAdd e)
+                         ((.&&)
+                            (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                      ((.&&)
+                         (isAdd e)
+                         (sNot
+                            ((.&&)
+                               (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))))))
+                (isZero e)))
+          ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: nested pattern variable used in both guard and RHS
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Add (Num i) _ | i .> 0  -> sNum i .== sNum i =: e .== e =: qed
+         Add _ _                  -> e .== e =: qed
+         _                        -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase57.stderr
@@ -0,0 +1,35 @@
+PCase57.hs:(18,15)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Add (Num i) _ | i .> 0  -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Add _ _                  -> e .== e =: qed\n\
+      \         _                        -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&)
+          (isAdd e)
+          ((.&&)
+             (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+          ==>
+            (let i = getNum_1 (getAdd_1 e)
+             in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&)
+                (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+          ==> (e .== e =: qed)),
+       (sNot
+          ((.||)
+             ((.&&)
+                (isAdd e)
+                ((.&&)
+                   (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+             ((.&&)
+                (isAdd e)
+                (sNot
+                   ((.&&)
+                      (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))))
+          ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: multiple guarded arms on nested pattern, variable in guard + RHS, wildcard
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Let s (Num i) b | i .> 0   -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed
+                          | i .> -5  -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed
+                          | sTrue    -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed
+         Let s a b                   -> sLet s a b .== sLet s a b =: e .== e =: qed
+         Add (Num i) (Num j)         -> sAdd (sNum i) (sNum j) .== sAdd (sNum i) (sNum j) =: e .== e =: qed
+         _                           -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase58.stderr
@@ -0,0 +1,127 @@
+PCase58.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Let s (Num i) b | i .> 0   -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed\n\
+      \                          | i .> -5  -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed\n\
+      \                          | sTrue    -> sLet s (sNum i) b .== sLet s (sNum i) b =: e .== e =: qed\n\
+      \         Let s a b                   -> sLet s a b .== sLet s a b =: e .== e =: qed\n\
+      \         Add (Num i) (Num j)         -> sAdd (sNum i) (sNum j) .== sAdd (sNum i) (sNum j) =: e .== e =: qed\n\
+      \         _                           -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&)
+          (isLet e)
+          ((.&&)
+             (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0))
+          ==>
+            (let
+               s = getLet_1 e
+               b = getLet_3 e in
+             let i = getNum_1 (getLet_2 e)
+             in (sLet s (sNum i) b) .== sLet s (sNum i) b =: e .== e =: qed)),
+       ((.&&)
+          (isLet e)
+          ((.&&)
+             (sNot
+                ((.&&)
+                   (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+             ((.&&)
+                (isNum (getLet_2 e))
+                (let i = getNum_1 (getLet_2 e) in i .> negate 5)))
+          ==>
+            (let
+               s = getLet_1 e
+               b = getLet_3 e in
+             let i = getNum_1 (getLet_2 e)
+             in (sLet s (sNum i) b) .== sLet s (sNum i) b =: e .== e =: qed)),
+       ((.&&)
+          (isLet e)
+          ((.&&)
+             (sNot
+                ((.&&)
+                   (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+             ((.&&)
+                (sNot
+                   ((.&&)
+                      (isNum (getLet_2 e))
+                      (let i = getNum_1 (getLet_2 e) in i .> negate 5)))
+                (isNum (getLet_2 e))))
+          ==>
+            (let
+               s = getLet_1 e
+               b = getLet_3 e in
+             let i = getNum_1 (getLet_2 e)
+             in (sLet s (sNum i) b) .== sLet s (sNum i) b =: e .== e =: qed)),
+       ((.&&)
+          (isLet e)
+          ((.&&)
+             (sNot
+                ((.&&)
+                   (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+             ((.&&)
+                (sNot
+                   ((.&&)
+                      (isNum (getLet_2 e))
+                      (let i = getNum_1 (getLet_2 e) in i .> negate 5)))
+                (sNot (isNum (getLet_2 e)))))
+          ==>
+            (let
+               s = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet s a b) .== sLet s a b =: e .== e =: qed)),
+       ((.&&) (isAdd e) ((.&&) (isNum (getAdd_1 e)) (isNum (getAdd_2 e)))
+          ==>
+            (let
+               i = getNum_1 (getAdd_1 e)
+               j = getNum_1 (getAdd_2 e)
+             in
+               (sAdd (sNum i) (sNum j)) .== sAdd (sNum i) (sNum j) =: e .== e
+                 =: qed)),
+       (sNot
+          ((.||)
+             ((.||)
+                ((.||)
+                   ((.||)
+                      ((.&&)
+                         (isLet e)
+                         ((.&&)
+                            (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+                      ((.&&)
+                         (isLet e)
+                         ((.&&)
+                            (sNot
+                               ((.&&)
+                                  (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+                            ((.&&)
+                               (isNum (getLet_2 e))
+                               (let i = getNum_1 (getLet_2 e) in i .> negate 5)))))
+                   ((.&&)
+                      (isLet e)
+                      ((.&&)
+                         (sNot
+                            ((.&&)
+                               (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+                         ((.&&)
+                            (sNot
+                               ((.&&)
+                                  (isNum (getLet_2 e))
+                                  (let i = getNum_1 (getLet_2 e) in i .> negate 5)))
+                            (isNum (getLet_2 e))))))
+                ((.&&)
+                   (isLet e)
+                   ((.&&)
+                      (sNot
+                         ((.&&)
+                            (isNum (getLet_2 e)) (let i = getNum_1 (getLet_2 e) in i .> 0)))
+                      ((.&&)
+                         (sNot
+                            ((.&&)
+                               (isNum (getLet_2 e))
+                               (let i = getNum_1 (getLet_2 e) in i .> negate 5)))
+                         (sNot (isNum (getLet_2 e)))))))
+             ((.&&)
+                (isAdd e) ((.&&) (isNum (getAdd_1 e)) (isNum (getAdd_2 e)))))
+          ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: interleaved constructors (Let/Add/Let), linear processing
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Let s a b | isZero a -> sLet s a b .== sLet s a b =: e .== e =: qed
+         Add a b              -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Let s a b            -> sLet s a b .== sLet s a b =: e .== e =: qed
+         Zero                 -> e .== e =: qed
+         Num _                -> e .== e =: qed
+         Var _                -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase59.stderr
@@ -0,0 +1,35 @@
+PCase59.hs:(18,15)-(25,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Let s a b | isZero a -> sLet s a b .== sLet s a b =: e .== e =: qed\n\
+      \         Add a b              -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Let s a b            -> sLet s a b .== sLet s a b =: e .== e =: qed\n\
+      \         Zero                 -> e .== e =: qed\n\
+      \         Num _                -> e .== e =: qed\n\
+      \         Var _                -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&) (isLet e) (let a = getLet_2 e in isZero a)
+          ==>
+            (let
+               s = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet s a b) .== sLet s a b =: e .== e =: qed)),
+       (isAdd e
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       ((.&&) (isLet e) (sNot (let a = getLet_2 e in isZero a))
+          ==>
+            (let
+               s = getLet_1 e
+               a = getLet_2 e
+               b = getLet_3 e
+             in (sLet s a b) .== sLet s a b =: e .== e =: qed)),
+       (isZero e ==> (e .== e =: qed)), (isNum e ==> (e .== e =: qed)),
+       (isVar e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions  #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+-- Dump test: linear processing stress test
+--   - Interleaved constructors (Add / Num / Add)
+--   - Nested patterns with guards
+--   - Guard variables used in both guard and RHS
+--   - Var with guard, then unguarded Var later
+--   - Multiple guarded wildcards at the end
+t :: TP (Proof (Forall "e" Expr -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Add (Num i) b | i .> 0  -> sAdd (sNum i) b .== sAdd (sNum i) b =: e .== e =: qed
+         Num i | i .> 0           -> sNum i .== sNum i =: e .== e =: qed
+         Var s | s .== literal "hey" -> sVar s .== sVar s =: e .== e =: qed
+         Add a b                  -> sAdd a b .== sAdd a b =: e .== e =: qed
+         Num i                    -> sNum i .== sNum i =: e .== e =: qed
+         Var s                    -> sVar s .== sVar s =: e .== e =: qed
+         Zero                     -> e .== e =: qed
+         _ | isLet e              -> e .== e =: qed
+         _                        -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase60.stderr
@@ -0,0 +1,120 @@
+PCase60.hs:(23,15)-(33,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Add (Num i) b | i .> 0  -> sAdd (sNum i) b .== sAdd (sNum i) b =: e .== e =: qed\n\
+      \         Num i | i .> 0           -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s | s .== literal \"hey\" -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Add a b                  -> sAdd a b .== sAdd a b =: e .== e =: qed\n\
+      \         Num i                    -> sNum i .== sNum i =: e .== e =: qed\n\
+      \         Var s                    -> sVar s .== sVar s =: e .== e =: qed\n\
+      \         Zero                     -> e .== e =: qed\n\
+      \         _ | isLet e              -> e .== e =: qed\n\
+      \         _                        -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&)
+          (isAdd e)
+          ((.&&)
+             (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+          ==>
+            (let b = getAdd_2 e in
+             let i = getNum_1 (getAdd_1 e)
+             in (sAdd (sNum i) b) .== sAdd (sNum i) b =: e .== e =: qed)),
+       ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isVar e) (let s = getVar_1 e in s .== literal "hey")
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       ((.&&)
+          (isAdd e)
+          (sNot
+             ((.&&)
+                (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+          ==>
+            (let
+               a = getAdd_1 e
+               b = getAdd_2 e
+             in (sAdd a b) .== sAdd a b =: e .== e =: qed)),
+       ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 0))
+          ==> (let i = getNum_1 e in (sNum i) .== sNum i =: e .== e =: qed)),
+       ((.&&) (isVar e) (sNot (let s = getVar_1 e in s .== literal "hey"))
+          ==> (let s = getVar_1 e in (sVar s) .== sVar s =: e .== e =: qed)),
+       (isZero e ==> (e .== e =: qed)),
+       ((.&&)
+          (sNot
+             ((.||)
+                ((.||)
+                   ((.||)
+                      ((.||)
+                         ((.||)
+                            ((.||)
+                               ((.&&)
+                                  (isAdd e)
+                                  ((.&&)
+                                     (isNum (getAdd_1 e))
+                                     (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                               ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)))
+                            ((.&&) (isVar e) (let s = getVar_1 e in s .== literal "hey")))
+                         ((.&&)
+                            (isAdd e)
+                            (sNot
+                               ((.&&)
+                                  (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))))
+                      ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 0))))
+                   ((.&&)
+                      (isVar e) (sNot (let s = getVar_1 e in s .== literal "hey"))))
+                (isZero e)))
+          (isLet e)
+          ==> (e .== e =: qed)),
+       (sNot
+          ((.||)
+             ((.||)
+                ((.||)
+                   ((.||)
+                      ((.||)
+                         ((.||)
+                            ((.||)
+                               ((.&&)
+                                  (isAdd e)
+                                  ((.&&)
+                                     (isNum (getAdd_1 e))
+                                     (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                               ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)))
+                            ((.&&) (isVar e) (let s = getVar_1 e in s .== literal "hey")))
+                         ((.&&)
+                            (isAdd e)
+                            (sNot
+                               ((.&&)
+                                  (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0)))))
+                      ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 0))))
+                   ((.&&)
+                      (isVar e) (sNot (let s = getVar_1 e in s .== literal "hey"))))
+                (isZero e))
+             ((.&&)
+                (sNot
+                   ((.||)
+                      ((.||)
+                         ((.||)
+                            ((.||)
+                               ((.||)
+                                  ((.||)
+                                     ((.&&)
+                                        (isAdd e)
+                                        ((.&&)
+                                           (isNum (getAdd_1 e))
+                                           (let i = getNum_1 (getAdd_1 e) in i .> 0)))
+                                     ((.&&) (isNum e) (let i = getNum_1 e in i .> 0)))
+                                  ((.&&) (isVar e) (let s = getVar_1 e in s .== literal "hey")))
+                               ((.&&)
+                                  (isAdd e)
+                                  (sNot
+                                     ((.&&)
+                                        (isNum (getAdd_1 e))
+                                        (let i = getNum_1 (getAdd_1 e) in i .> 0)))))
+                            ((.&&) (isNum e) (sNot (let i = getNum_1 e in i .> 0))))
+                         ((.&&)
+                            (isVar e) (sNot (let s = getVar_1 e in s .== literal "hey"))))
+                      (isZero e)))
+                (isLet e)))
+          ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Maybe
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "m" (Maybe Integer) -> SBool))
+t = calc "t" (\(Forall @"m" (m :: SMaybe Integer)) -> m .== m) $ \m -> []
+    |- [pCase| m of
+         Nothing -> m .== m =: qed
+         Just _  -> m .== m =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase61.stderr
@@ -0,0 +1,11 @@
+PCase61.hs:(17,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " m of\n\
+      \         Nothing -> m .== m =: qed\n\
+      \         Just _  -> m .== m =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.Maybe.isNothing m ==> (m .== m =: qed)),
+       (Data.SBV.Maybe.isJust m ==> (m .== m =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Either
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "e" (Either Integer Bool) -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SEither Integer Bool)) -> e .== e) $ \e -> []
+    |- [pCase| e of
+         Left _  -> e .== e =: qed
+         Right _ -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase62.stderr
@@ -0,0 +1,11 @@
+PCase62.hs:(17,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Left _  -> e .== e =: qed\n\
+      \         Right _ -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.Either.isLeft e ==> (e .== e =: qed)),
+       (Data.SBV.Either.isRight e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with List
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "xs" [Integer] -> SBool))
+t = calc "t" (\(Forall @"xs" (xs :: SList Integer)) -> xs .== xs) $ \xs -> []
+    |- [pCase| xs of
+         []    -> xs .== xs =: qed
+         _ : _ -> xs .== xs =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase63.stderr
@@ -0,0 +1,14 @@
+PCase63.hs:(19,15)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " xs of\n\
+      \         []    -> xs .== xs =: qed\n\
+      \         _ : _ -> xs .== xs =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.List.null xs ==> (xs .== xs =: qed)),
+       ((.&&)
+          (sNot (Data.SBV.List.null xs))
+          ((.===) xs (Data.SBV.List.head xs .: Data.SBV.List.tail xs))
+          ==> (xs .== xs =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Tuple2
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "p" (Integer, Bool) -> SBool))
+t = calc "t" (\(Forall @"p" (p :: STuple Integer Bool)) -> p .== p) $ \p -> []
+    |- [pCase| p of
+         (_, _) -> p .== p =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase64.stderr
@@ -0,0 +1,8 @@
+PCase64.hs:(17,15)-(19,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " p of\n\
+      \         (_, _) -> p .== p =: qed\n\
+      \       "
+  ======>
+    cases [(sTrue ==> (p .== p =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Maybe, guards on Just
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "m" (Maybe Integer) -> SBool))
+t = calc "t" (\(Forall @"m" (m :: SMaybe Integer)) -> m .== m) $ \m -> []
+    |- [pCase| m of
+         Nothing          -> m .== m =: qed
+         Just x | x .> 0  -> m .== m =: qed
+                | sTrue    -> m .== m =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase65.stderr
@@ -0,0 +1,19 @@
+PCase65.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " m of\n\
+      \         Nothing          -> m .== m =: qed\n\
+      \         Just x | x .> 0  -> m .== m =: qed\n\
+      \                | sTrue    -> m .== m =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.Maybe.isNothing m ==> (m .== m =: qed)),
+       ((.&&)
+          (Data.SBV.Maybe.isJust m)
+          (let x = Data.SBV.Maybe.getJust_1 m in x .> 0)
+          ==> (m .== m =: qed)),
+       ((.&&)
+          (Data.SBV.Maybe.isJust m)
+          (sNot (let x = Data.SBV.Maybe.getJust_1 m in x .> 0))
+          ==> (m .== m =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with List, guards and wildcard
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "xs" [Integer] -> SBool))
+t = calc "t" (\(Forall @"xs" (xs :: SList Integer)) -> xs .== xs) $ \xs -> []
+    |- [pCase| xs of
+         []             -> xs .== xs =: qed
+         y : _ | y .> 0 -> xs .== xs =: qed
+         _              -> xs .== xs =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase66.stderr
@@ -0,0 +1,26 @@
+PCase66.hs:(19,15)-(23,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " xs of\n\
+      \         []             -> xs .== xs =: qed\n\
+      \         y : _ | y .> 0 -> xs .== xs =: qed\n\
+      \         _              -> xs .== xs =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.List.null xs ==> (xs .== xs =: qed)),
+       ((.&&)
+          (sNot (Data.SBV.List.null xs))
+          ((.&&)
+             ((.===) xs (Data.SBV.List.head xs .: Data.SBV.List.tail xs))
+             (let y = Data.SBV.List.head xs in y .> 0))
+          ==> (xs .== xs =: qed)),
+       (sNot
+          ((.||)
+             (Data.SBV.List.null xs)
+             ((.&&)
+                (sNot (Data.SBV.List.null xs))
+                ((.&&)
+                   ((.===) xs (Data.SBV.List.head xs .: Data.SBV.List.tail xs))
+                   (let y = Data.SBV.List.head xs in y .> 0))))
+          ==> (xs .== xs =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with List, nested cons pattern with bindings
+module T where
+
+import Prelude hiding (null, head, tail, length)
+import Data.SBV
+import Data.SBV.List (length)
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "xs" [Integer] -> SBool))
+t = calc "t" (\(Forall @"xs" (xs :: SList Integer)) -> length xs .>= 0) $ \xs -> []
+    |- [pCase| xs of
+         []              -> length xs .>= 0 =: qed
+         _ : (_ : _)     -> length xs .>= 0 =: qed
+         _ : _           -> length xs .>= 0 =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase67.stderr
@@ -0,0 +1,34 @@
+PCase67.hs:(20,15)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " xs of\n\
+      \         []              -> length xs .>= 0 =: qed\n\
+      \         _ : (_ : _)     -> length xs .>= 0 =: qed\n\
+      \         _ : _           -> length xs .>= 0 =: qed\n\
+      \       "
+  ======>
+    cases
+      [(Data.SBV.List.null xs ==> ((length xs) .>= 0 =: qed)),
+       ((.&&)
+          (sNot (Data.SBV.List.null xs))
+          ((.&&)
+             ((.===) xs (Data.SBV.List.head xs .: Data.SBV.List.tail xs))
+             ((.&&)
+                (sNot (Data.SBV.List.null (Data.SBV.List.tail xs)))
+                ((.===)
+                   (Data.SBV.List.tail xs)
+                   (Data.SBV.List.head (Data.SBV.List.tail xs)
+                      .: Data.SBV.List.tail (Data.SBV.List.tail xs)))))
+          ==> ((length xs) .>= 0 =: qed)),
+       ((.&&)
+          (sNot (Data.SBV.List.null xs))
+          ((.&&)
+             ((.===) xs (Data.SBV.List.head xs .: Data.SBV.List.tail xs))
+             (sNot
+                ((.&&)
+                   (sNot (Data.SBV.List.null (Data.SBV.List.tail xs)))
+                   ((.===)
+                      (Data.SBV.List.tail xs)
+                      (Data.SBV.List.head (Data.SBV.List.tail xs)
+                         .: Data.SBV.List.tail (Data.SBV.List.tail xs))))))
+          ==> ((length xs) .>= 0 =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Bool constructor patterns
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "b" Bool -> SBool))
+t = calc "t" (\(Forall @"b" (b :: SBool)) -> b .== b) $ \b -> []
+    |- [pCase| b of
+         True  -> b .== b =: qed
+         False -> b .== b =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase68.stderr
@@ -0,0 +1,9 @@
+PCase68.hs:(17,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " b of\n\
+      \         True  -> b .== b =: qed\n\
+      \         False -> b .== b =: qed\n\
+      \       "
+  ======>
+    cases [(b ==> (b .== b =: qed)), (sNot b ==> (b .== b =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Bool, guard on True
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "b" Bool -> Forall "x" Integer -> SBool))
+t = calc "t" (\(Forall @"b" (b :: SBool)) (Forall @"x" (x :: SInteger)) -> b .|| sNot b) $ \b x -> []
+    |- [pCase| b of
+         True  | x .> 0 -> b .|| sNot b =: qed
+               | sTrue  -> b .|| sNot b =: qed
+         False           -> b .|| sNot b =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase69.stderr
@@ -0,0 +1,19 @@
+PCase69.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " b of\n\
+      \         True  | x .> 0 -> b .|| sNot b =: qed\n\
+      \               | sTrue  -> b .|| sNot b =: qed\n\
+      \         False           -> b .|| sNot b =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.&&) b (x .> 0) ==> (b .|| sNot b =: qed)),
+       ((.&&) b (sNot (x .> 0)) ==> (b .|| sNot b =: qed)),
+       (sNot b ==> (b .|| sNot b =: qed))]
+PCase69.hs:16:57: error: [GHC-40910] [-Wunused-matches, Werror=unused-matches]
+    Defined but not used: x
+   |
+16 | t = calc "t" (\(Forall @"b" (b :: SBool)) (Forall @"x" (x :: SInteger)) -> b .|| sNot b) $ \b x -> []
+   |                                                         ^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Integer literal patterns and wildcard
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "x" Integer -> SBool))
+t = calc "t" (\(Forall @"x" (x :: SInteger)) -> x .== x) $ \x -> []
+    |- [pCase| x of
+         0 -> x .== x =: qed
+         1 -> x .== x =: qed
+         _ -> x .== x =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase70.stderr
@@ -0,0 +1,14 @@
+PCase70.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " x of\n\
+      \         0 -> x .== x =: qed\n\
+      \         1 -> x .== x =: qed\n\
+      \         _ -> x .== x =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.==) x 0 ==> (x .== x =: qed)),
+       ((.&&) (sNot ((.==) x 0)) ((.==) x 1) ==> (x .== x =: qed)),
+       (sNot ((.||) ((.==) x 0) ((.&&) (sNot ((.==) x 0)) ((.==) x 1)))
+          ==> (x .== x =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Char literal patterns and wildcard
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "c" Char -> SBool))
+t = calc "t" (\(Forall @"c" (c :: SChar)) -> c .== c) $ \c -> []
+    |- [pCase| c of
+         'a' -> c .== c =: qed
+         'b' -> c .== c =: qed
+         _   -> c .== c =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase71.stderr
@@ -0,0 +1,18 @@
+PCase71.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " c of\n\
+      \         'a' -> c .== c =: qed\n\
+      \         'b' -> c .== c =: qed\n\
+      \         _   -> c .== c =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.==) c (literal 'a') ==> (c .== c =: qed)),
+       ((.&&) (sNot ((.==) c (literal 'a'))) ((.==) c (literal 'b'))
+          ==> (c .== c =: qed)),
+       (sNot
+          ((.||)
+             ((.==) c (literal 'a'))
+             ((.&&) (sNot ((.==) c (literal 'a'))) ((.==) c (literal 'b'))))
+          ==> (c .== c =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with String literal patterns and wildcard
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "s" String -> SBool))
+t = calc "t" (\(Forall @"s" (s :: SString)) -> s .== s) $ \s -> []
+    |- [pCase| s of
+         "hello" -> s .== s =: qed
+         _       -> s .== s =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase72.stderr
@@ -0,0 +1,11 @@
+PCase72.hs:(17,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " s of\n\
+      \         \"hello\" -> s .== s =: qed\n\
+      \         _       -> s .== s =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.==) s (literal "hello") ==> (s .== s =: qed)),
+       (sNot ((.==) s (literal "hello")) ==> (s .== s =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Integer variable binding and guard
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "x" Integer -> SBool))
+t = calc "t" (\(Forall @"x" (x :: SInteger)) -> x .== x) $ \x -> []
+    |- [pCase| x of
+         0         -> x .== x =: qed
+         n | n .> 0 -> x .== x =: qed
+           | sTrue  -> x .== x =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase73.stderr
@@ -0,0 +1,17 @@
+PCase73.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " x of\n\
+      \         0         -> x .== x =: qed\n\
+      \         n | n .> 0 -> x .== x =: qed\n\
+      \           | sTrue  -> x .== x =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.==) x 0 ==> (x .== x =: qed)),
+       ((.&&) (sNot ((.==) x 0)) (let n = x in n .> 0)
+          ==> (x .== x =: qed)),
+       (sNot
+          ((.||)
+             ((.==) x 0) ((.&&) (sNot ((.==) x 0)) (let n = x in n .> 0)))
+          ==> (x .== x =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Integer, no wildcard (only literals) — should fail with non-exhaustive
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "x" Integer -> SBool))
+t = calc "t" (\(Forall @"x" (x :: SInteger)) -> x .== x) $ \x -> []
+    |- [pCase| x of
+         0 -> x .== x =: qed
+         1 -> x .== x =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase74.stderr
@@ -0,0 +1,14 @@
+PCase74.hs:17:15: error: [GHC-39584]
+    " PCase74.hs:18:10: pCase: Non-exhaustive pattern match.
+        All branches are guarded; add an unguarded wildcard or variable
+        as the last branch to ensure all cases are covered.
+
+    " In the quasi-quotation:
+        [pCase| x of
+         0 -> x .== x =: qed
+         1 -> x .== x =: qed
+       |]
+   |
+17 |     |- [pCase| x of
+   |               ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with Bool non-exhaustive (only True)
+-- (sCase would reject as non-exhaustive; pCase is fine)
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "b" Bool -> SBool))
+t = calc "t" (\(Forall @"b" (b :: SBool)) -> b .== b) $ \b -> []
+    |- [pCase| b of
+         True -> b .== b =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase75.stderr
@@ -0,0 +1,8 @@
+PCase75.hs:(18,15)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " b of\n\
+      \         True -> b .== b =: qed\n\
+      \       "
+  ======>
+    cases [(b ==> (b .== b =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: pCase with negative integer literal
+module T where
+
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "x" Integer -> SBool))
+t = calc "t" (\(Forall @"x" (x :: SInteger)) -> x .== x) $ \x -> []
+    |- [pCase| x of
+         0    -> x .== x =: qed
+         (-1) -> x .== x =: qed
+         _    -> x .== x =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase76.stderr
@@ -0,0 +1,14 @@
+PCase76.hs:(17,15)-(21,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " x of\n\
+      \         0    -> x .== x =: qed\n\
+      \         (-1) -> x .== x =: qed\n\
+      \         _    -> x .== x =: qed\n\
+      \       "
+  ======>
+    cases
+      [((.==) x 0 ==> (x .== x =: qed)),
+       ((.&&) (sNot ((.==) x 0)) ((.==) x (-1)) ==> (x .== x =: qed)),
+       (sNot ((.||) ((.==) x 0) ((.&&) (sNot ((.==) x 0)) ((.==) x (-1))))
+          ==> (x .== x =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.hs b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-name-shadowing -ddump-splices #-}
+
+-- Positive: Scoping regression test for pCase. Pattern var 'k' from 'Num k' is
+-- used in one branch of a nested case on SBool, while a sibling branch shadows
+-- 'k' with a let binding. Old scope-unaware freeVars would drop the accessor
+-- binding for 'k', causing a compilation error. See also SCase107 for the sCase
+-- counterpart.
+module T where
+
+import Expr
+import Data.SBV
+import Data.SBV.TP
+
+t :: TP (Proof (Forall "e" Expr -> Forall "b" Bool -> SBool))
+t = calc "t" (\(Forall @"e" (e :: SExpr)) (Forall @"b" (_ :: SBool)) -> e .== e) $ \e b -> []
+    |- [pCase| e of
+         Zero    -> e .== e =: qed
+         Num k   -> case b of
+                      True  -> let k = (0 :: SInteger) in k .== k =: e .== e =: qed
+                      False -> k .>= 0 .|| e .== e =: sTrue =: qed
+         Var _   -> e .== e =: qed
+         Add _ _ -> e .== e =: qed
+         Let _ _ _ -> e .== e =: qed
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.stderr b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/PCase/PCase77.stderr
@@ -0,0 +1,24 @@
+PCase77.hs:(22,15)-(30,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      pCase
+      " e of\n\
+      \         Zero    -> e .== e =: qed\n\
+      \         Num k   -> case b of\n\
+      \                      True  -> let k = (0 :: SInteger) in k .== k =: e .== e =: qed\n\
+      \                      False -> k .>= 0 .|| e .== e =: sTrue =: qed\n\
+      \         Var _   -> e .== e =: qed\n\
+      \         Add _ _ -> e .== e =: qed\n\
+      \         Let _ _ _ -> e .== e =: qed\n\
+      \       "
+  ======>
+    cases
+      [(isZero e ==> (e .== e =: qed)),
+       (isNum e
+          ==>
+            (let k = getNum_1 e
+             in
+               cases
+                 [(b ==> (let k = (0 :: SInteger) in k .== k =: e .== e =: qed)),
+                  (sNot b ==> (k .>= 0 .|| e .== e =: sTrue =: qed))])),
+       (isVar e ==> (e .== e =: qed)), (isAdd e ==> (e .== e =: qed)),
+       (isLet e ==> (e .== e =: qed))]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase.hs b/SBVTestSuite/TestSuite/CompileTests/SCase.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase.hs
@@ -0,0 +1,19 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.CompileTests.SCase
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing TH messages
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.CompileTests.SCase(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: IO TestTree
+tests = testGroup "THTests.SCase" <$> mkCompileTestGlob "SBVTestSuite/TestSuite/CompileTests/SCase/SCase*.hs"
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/Expr.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Expr where
+
+import Data.SBV
+
+data Expr = Zero
+          | Num Integer
+          | Var String
+          | Add Expr Expr
+          | Let String Expr Expr
+          deriving Show
+
+mkSymbolic [''Expr]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase01.stderr
@@ -0,0 +1,8 @@
+SCase01.hs:11:14: error: [GHC-39584]
+    " SCase01.hs:11:19: Parse error: EOF
+
+    " In the quasi-quotation: [sCase| e of|]
+   |
+11 | t e = [sCase| e of|]
+   |              ^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+        Zero  -> 0
+        Num i -> i
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase02.stderr
@@ -0,0 +1,17 @@
+SCase02.hs:11:14: error: [GHC-39584]
+    " sCase: Pattern match(es) are non-exhaustive.
+        Not matched     : Var
+        Patterns of type: Expr
+        Must match each : Zero, Num, Var, Add, Let
+
+      You can use a '_' to match multiple cases.
+
+    " In the quasi-quotation:
+        [sCase| e of
+        Zero  -> 0
+        Num i -> i
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+        Zero  -> 0
+        Num _ _ -> i
+        Var _ -> 0
+        Add _ _ -> 2
+        Let _ _ _ -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase03.stderr
@@ -0,0 +1,19 @@
+SCase03.hs:11:14: error: [GHC-39584]
+    " SCase03.hs:13:9-15: sCase: Arity mismatch.
+        Type       : Expr
+        Constructor: Num
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [sCase| e of
+        Zero  -> 0
+        Num _ _ -> i
+        Var _ -> 0
+        Add _ _ -> 2
+        Let _ _ _ -> 3
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Rejected at the top level
+[sCase| e of
+        Zero  -> 0
+        Num i -> i
+      |]
+
+{- HLint ignore module "Unused LANGUAGE pragma" -}
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase04.stderr
@@ -0,0 +1,6 @@
+SCase04.hs:11:8: error: [GHC-39584]
+    sCase: not usable in declaration context
+   |
+11 | [sCase| e of
+   |        ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- bad syntax
+t :: SExpr -> SInteger
+t e = [sCase| e + 1|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase05.stderr
@@ -0,0 +1,8 @@
+SCase05.hs:12:14: error: [GHC-39584]
+    " SCase05.hs:12:20: Parse error: EOF
+
+    " In the quasi-quotation: [sCase| e + 1|]
+   |
+12 | t e = [sCase| e + 1|]
+   |              ^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Unknown constructor
+t :: SExpr -> SInteger
+t e = [sCase| e of FooBar _ -> 1|]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase06.stderr
@@ -0,0 +1,11 @@
+SCase06.hs:12:14: error: [GHC-39584]
+    " sCase: Unknown constructor: FooBar
+
+        Cannot find this constructor in scope.
+        Make sure the type is declared and mkSymbolic is called.
+
+    " In the quasi-quotation: [sCase| e of FooBar _ -> 1|]
+   |
+12 | t e = [sCase| e of FooBar _ -> 1|]
+   |              ^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase07.stderr
@@ -0,0 +1,16 @@
+SCase07.hs:11:14: error: [GHC-39584]
+    " sCase/pCase: Pattern guards are not supported: 
+        Just 1 <- Just i
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 else 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase08.stderr
@@ -0,0 +1,15 @@
+SCase08.hs:11:14: error: [GHC-39584]
+    " SCase08.hs:14:50: Parse error: else
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i | Just 1 <- Just i         -> i
+               Var s        -> ite (s .== "a") 1 else 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase09.stderr
@@ -0,0 +1,14 @@
+SCase09.hs:11:14: error: [GHC-39584]
+    " SCase09.hs:14:16-21: sCase/pCase: Not in scope: data constructor: Viar
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Viar s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var s         -> ite (s .== literal "a") 1 2
+               Add (Num i) j -> i + t j
+               Add a b       -> t a + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase10.stderr
@@ -0,0 +1,28 @@
+SCase10.hs:(11,14)-(18,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num k         -> k\n\
+      \               Var s         -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Num i) j -> i + t j\n\
+      \               Add a b       -> t a + t b\n\
+      \               Let _   _a  b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ j -> const (isNum (getAdd_1 e)) j)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ j -> let i = getNum_1 (getAdd_1 e) in i + t j)
+                  (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Top-level as-pattern on Maybe
+module T where
+
+import Data.SBV
+
+t :: SMaybe Integer -> SInteger
+t m = [sCase| m of
+               whole@(Just v) -> v + case whole of
+                                       Just w  -> w
+                                       Nothing -> 0
+               Nothing        -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase100.stderr
@@ -0,0 +1,16 @@
+SCase100.hs:(11,14)-(16,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               whole@(Just v) -> v + case whole of\n\
+      \                                       Just w  -> w\n\
+      \                                       Nothing -> 0\n\
+      \               Nothing        -> 0\n\
+      \      "
+  ======>
+    Data.SBV.Maybe.sCaseMaybe
+      0
+      (\ v
+         -> let whole = m
+            in v + Data.SBV.Maybe.sCaseMaybe 0 (\ w -> w) whole)
+      m
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Nested as-pattern on Either inside Maybe
+module T where
+
+import Data.SBV
+
+t :: SMaybe (Either Integer Bool) -> SInteger
+t m = [sCase| m of
+               Just inner@(Left v)  -> v + case inner of
+                                              Left w  -> w
+                                              Right _ -> 0
+               Just (Right _)       -> 1
+               Nothing              -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase101.stderr
@@ -0,0 +1,31 @@
+SCase101.hs:(11,14)-(17,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               Just inner@(Left v)  -> v + case inner of\n\
+      \                                              Left w  -> w\n\
+      \                                              Right _ -> 0\n\
+      \               Just (Right _)       -> 1\n\
+      \               Nothing              -> 0\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (Data.SBV.Maybe.isJust m)
+         ((\ _ -> Data.SBV.Either.isLeft (Data.SBV.Maybe.getJust_1 m))
+            (Data.SBV.Maybe.getJust_1 m)))
+      ((\ _
+          -> let
+               inner = Data.SBV.Maybe.getJust_1 m
+               v = Data.SBV.Either.getLeft_1 (Data.SBV.Maybe.getJust_1 m)
+             in v + Data.SBV.Either.sCaseEither (\ w -> w) (\ _ -> 0) inner)
+         (Data.SBV.Maybe.getJust_1 m))
+      (ite
+         ((.&&)
+            (Data.SBV.Maybe.isJust m)
+            ((\ _ -> Data.SBV.Either.isRight (Data.SBV.Maybe.getJust_1 m))
+               (Data.SBV.Maybe.getJust_1 m)))
+         ((\ _ -> 1) (Data.SBV.Maybe.getJust_1 m))
+         (ite
+            (Data.SBV.Maybe.isNothing m) 0
+            (symWithKind "unmatched_sCase_Maybe_6989586621679035008")))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: As-pattern on wildcard
+module T where
+
+import Data.SBV
+
+t :: SMaybe Integer -> SInteger
+t m = [sCase| m of
+               x@_ -> case x of
+                         Just v  -> v
+                         Nothing -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase102.stderr
@@ -0,0 +1,10 @@
+SCase102.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               x@_ -> case x of\n\
+      \                         Just v  -> v\n\
+      \                         Nothing -> 0\n\
+      \      "
+  ======>
+    let x = m in Data.SBV.Maybe.sCaseMaybe 0 (\ v -> v) x
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: As-pattern with Expr ADT (recursive use of as-bound name)
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               whole@(Add a _) -> t a + t whole
+               Num k           -> k
+               _               -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase103.stderr
@@ -0,0 +1,12 @@
+SCase103.hs:(12,14)-(16,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               whole@(Add a _) -> t a + t whole\n\
+      \               Num k           -> k\n\
+      \               _               -> 0\n\
+      \      "
+  ======>
+    sCaseExpr
+      0 (\ k -> k) (\ _ -> 0) (\ a _ -> let whole = e in (t a) + t whole)
+      (\ _ _ _ -> 0) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: As-pattern where binding is unused (should be elided)
+module T where
+
+import Data.SBV
+
+t :: SMaybe Integer -> SInteger
+t m = [sCase| m of
+               _unused@(Just v) -> v
+               Nothing          -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase104.stderr
@@ -0,0 +1,9 @@
+SCase104.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               _unused@(Just v) -> v\n\
+      \               Nothing          -> 0\n\
+      \      "
+  ======>
+    Data.SBV.Maybe.sCaseMaybe 0 (\ v -> v) m
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: As-pattern on list cons pattern
+module T where
+
+import Data.SBV
+
+t :: SList Integer -> SInteger
+t xs = [sCase| xs of
+                a : tl@(_ : _) -> a + case tl of
+                                         b : _ -> b
+                                         []    -> 0
+                _ : _           -> 0
+                []              -> 0
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase105.stderr
@@ -0,0 +1,34 @@
+SCase105.hs:(11,15)-(17,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " xs of\n\
+      \                a : tl@(_ : _) -> a + case tl of\n\
+      \                                         b : _ -> b\n\
+      \                                         []    -> 0\n\
+      \                _ : _           -> 0\n\
+      \                []              -> 0\n\
+      \       "
+  ======>
+    ite
+      ((.&&)
+         (sNot (Data.SBV.List.null xs))
+         ((\ a _
+             -> const
+                  ((.&&)
+                     (sNot (Data.SBV.List.null (Data.SBV.List.tail xs)))
+                     ((.===)
+                        (Data.SBV.List.tail xs)
+                        (Data.SBV.List.head (Data.SBV.List.tail xs)
+                           .: Data.SBV.List.tail (Data.SBV.List.tail xs))))
+                  a)
+            (Data.SBV.List.head xs) (Data.SBV.List.tail xs)))
+      ((\ a _
+          -> let tl = Data.SBV.List.tail xs
+             in
+               a + ite
+                     (sNot (Data.SBV.List.null tl))
+                     ((\ b _ -> b) (Data.SBV.List.head tl) (Data.SBV.List.tail tl)) 0)
+         (Data.SBV.List.head xs) (Data.SBV.List.tail xs))
+      (ite
+         (sNot (Data.SBV.List.null xs))
+         ((\ _ _ -> 0) (Data.SBV.List.head xs) (Data.SBV.List.tail xs)) 0)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: As-pattern on tuple
+module T where
+
+import Data.SBV
+
+t :: STuple Integer Bool -> SInteger
+t p = [sCase| p of
+               whole@(v, b) -> ite b v (case whole of
+                                           (w, _) -> negate w)
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase106.stderr
@@ -0,0 +1,16 @@
+SCase106.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " p of\n\
+      \               whole@(v, b) -> ite b v (case whole of\n\
+      \                                           (w, _) -> negate w)\n\
+      \      "
+  ======>
+    (\ v b
+       -> let whole = p
+          in
+            ite
+              b v
+              ((\ w _ -> negate w)
+                 (Data.SBV.Tuple._1 whole) (Data.SBV.Tuple._2 whole)))
+      (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-name-shadowing -ddump-splices #-}
+
+-- Positive: Scoping regression test. Nested pattern var 'k' from 'Add (Num k) _'
+-- is used in one branch of a nested case on SMaybe, while a sibling branch shadows
+-- 'k' with a let binding. Old scope-unaware freeVars would drop the accessor binding
+-- for 'k', causing a compilation error. See also PCase77 for the pCase counterpart.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero          -> 0
+                Num _         -> 0
+                Var _         -> 0
+                Add (Num k) _ -> case m of
+                                   Nothing -> let k = 42 in k
+                                   Just v  -> k + v
+                Add _ _       -> 0
+                Let _ _ _     -> 0
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase107.stderr
@@ -0,0 +1,31 @@
+SCase107.hs:(15,16)-(24,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                Zero          -> 0\n\
+      \                Num _         -> 0\n\
+      \                Var _         -> 0\n\
+      \                Add (Num k) _ -> case m of\n\
+      \                                   Nothing -> let k = 42 in k\n\
+      \                                   Just v  -> k + v\n\
+      \                Add _ _       -> 0\n\
+      \                Let _ _ _     -> 0\n\
+      \       "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ _ -> 0) (getNum_1 e))
+         (ite
+            (isVar e) ((\ _ -> 0) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ _ -> isNum (getAdd_1 e)) (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ _
+                   -> let k = getNum_1 (getAdd_1 e)
+                      in Data.SBV.Maybe.sCaseMaybe (let k = 42 in k) (\ v -> k + v) m)
+                  (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ _ _ -> 0) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ _ -> 0) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase11.stderr
@@ -0,0 +1,19 @@
+SCase11.hs:11:14: error: [GHC-39584]
+    " SCase11.hs:14:16: sCase: Wildcard makes the remaining matches redundant:
+        SCase11.hs:15:16-20: Var s
+        SCase11.hs:16:16-22: Add a b
+        SCase11.hs:17:16-28: Let _ _a b
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               _ -> 5
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase12.stderr
@@ -0,0 +1,15 @@
+SCase12.hs:11:14: error: [GHC-39584]
+    " SCase12.hs:14:16: sCase: Wildcard makes the remaining matches redundant:
+        SCase12.hs:15:16: _
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               _ -> 3
+               _ -> 5
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var {} _      -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase13.stderr
@@ -0,0 +1,15 @@
+SCase13.hs:11:14: error: [GHC-39584]
+    " SCase13.hs:14:30: Parse error in pattern: Var{}
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var {} _      -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var s _       -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase14.stderr
@@ -0,0 +1,19 @@
+SCase14.hs:11:14: error: [GHC-39584]
+    " SCase14.hs:14:16-22: sCase: Arity mismatch.
+        Type       : Expr
+        Constructor: Var
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var s _       -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               Let _   _a  b -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               _ _ -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase15.stderr
@@ -0,0 +1,15 @@
+SCase15.hs:11:14: error: [GHC-39584]
+    " SCase15.hs:16:20: Parse error in pattern: _
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var s         -> ite (s .== "a") 1 2
+               Add a b       -> t e + t b
+               _ _ -> 3
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase16.stderr
@@ -0,0 +1,18 @@
+SCase16.hs:11:14: error: [GHC-39584]
+    " SCase16.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .< 3
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t a + t b
+               Num i          -> i+1
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase17.stderr
@@ -0,0 +1,24 @@
+SCase17.hs:(11,14)-(18,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero           -> 0\n\
+      \               Num i | i .< 3 -> i\n\
+      \               Var s          -> ite (s .== literal \"a\") 1 2\n\
+      \               Add a b        -> t a + t b\n\
+      \               Num i          -> i+1\n\
+      \               Let _   _a  b  -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         ((.&&) (isNum e) ((\ i -> i .< 3) (getNum_1 e)))
+         ((\ i -> i) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isNum e) ((\ i -> i + 1) (getNum_1 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i -> 4
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase18.stderr
@@ -0,0 +1,20 @@
+SCase18.hs:11:14: error: [GHC-39584]
+    " SCase18.hs:14:16-20: sCase: Overlapping case constructors:
+        Type       : Expr
+        Constructor: Num i | i .< 3
+      Overlaps with:
+        SCase18.hs:13:16-20: Num i
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i -> 4
+               Num i | i .< 3 -> i
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3 -> 4
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase19.stderr
@@ -0,0 +1,19 @@
+SCase19.hs:11:14: error: [GHC-39584]
+    " SCase19.hs:17:16: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: _ | 2 .>= 3
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3 -> 4
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ -> 4
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase20.stderr
@@ -0,0 +1,15 @@
+SCase20.hs:11:14: error: [GHC-39584]
+    " SCase20.hs:17:16: sCase: Wildcard match is redundant
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ -> 4
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase21.stderr
@@ -0,0 +1,18 @@
+SCase21.hs:11:14: error: [GHC-39584]
+    " SCase21.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .> 4
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3    -> 5
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase22.stderr
@@ -0,0 +1,19 @@
+SCase22.hs:11:14: error: [GHC-39584]
+    " SCase22.hs:13:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num i | i .> 4
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero           -> 0
+               Num i | i .> 4 -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t e + t b
+               Let _   _a  b  -> t b
+               _ | 2 .>= 3    -> 5
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num i          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b        -> t a + t b
+               Let _   _a  b  -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase23.stderr
@@ -0,0 +1,20 @@
+SCase23.hs:(11,14)-(17,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero           -> 0\n\
+      \               Num i          -> 4\n\
+      \               Var s          -> ite (s .== literal \"a\") 1 2\n\
+      \               Add a b        -> t a + t b\n\
+      \               Let _   _a  b  -> t b\n\
+      \      "
+  ======>
+    sCaseExpr
+      0 (\ i -> 4) (\ s -> ite (s .== literal "a") 1 2)
+      (\ a b -> (t a) + t b) (\ _ _a b -> t b) e
+SCase23.hs:11:14: error: [GHC-40910] [-Wunused-matches, Werror=unused-matches]
+    Defined but not used: i
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero           -> 0
+               Num _          -> 4
+               Var s          -> ite (s .== literal "a") 1 2
+               Add a b | t a .== 4 -> t b
+               Let _   _a  b  -> t b
+               _ -> 2
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase24.stderr
@@ -0,0 +1,26 @@
+SCase24.hs:(11,14)-(18,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero           -> 0\n\
+      \               Num _          -> 4\n\
+      \               Var s          -> ite (s .== literal \"a\") 1 2\n\
+      \               Add a b | t a .== 4 -> t b\n\
+      \               Let _   _a  b  -> t b\n\
+      \               _ -> 2\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ _ -> 4) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ a b -> const ((t a) .== 4) b) (getAdd_1 e) (getAdd_2 e)))
+               ((\ a b -> const (t b) a) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isLet e)
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e)) 2))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+f :: SExpr -> SInteger
+f e = [sCase| e of
+         Var s     | s .== literal "a"                       -> 0
+                   | s .== literal "b" .|| s .== literal "c" -> 1
+                   | sTrue                                   -> 2
+
+         Num i     | sTrue                                   -> 3
+
+         _                                                   -> 6
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase25.stderr
@@ -0,0 +1,30 @@
+SCase25.hs:(11,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \         Var s     | s .== literal \"a\"                       -> 0\n\
+      \                   | s .== literal \"b\" .|| s .== literal \"c\" -> 1\n\
+      \                   | sTrue                                   -> 2\n\
+      \\n\
+      \         Num i     | sTrue                                   -> 3\n\
+      \\n\
+      \         _                                                   -> 6\n\
+      \      "
+  ======>
+    ite
+      ((.&&) (isVar e) ((\ s -> s .== literal "a") (getVar_1 e)))
+      ((\ s -> const 0 s) (getVar_1 e))
+      (ite
+         ((.&&)
+            (isVar e)
+            ((\ s -> s .== literal "b" .|| s .== literal "c") (getVar_1 e)))
+         ((\ s -> const 1 s) (getVar_1 e))
+         (ite
+            (isVar e) ((\ s -> const 2 s) (getVar_1 e))
+            (ite (isNum e) ((\ i -> 3) (getNum_1 e)) 6)))
+SCase25.hs:11:14: error: [GHC-40910] [-Wunused-matches, Werror=unused-matches]
+    Defined but not used: i
+   |
+11 | f e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Data.SBV
+
+data A = A1 { u :: Integer }
+       | B1 { s :: String, k :: Float }
+       | C1
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase26.stderr
@@ -0,0 +1,1 @@
+There was no failure during compilation.
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Data.SBV
+
+-- don't allow multiple accessors
+data A = A1 { u :: Integer }
+       | B1 { u :: Integer, s :: String}
+       | C1
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase27.stderr
@@ -0,0 +1,11 @@
+SCase27.hs:14:1: error: [GHC-39584]
+    mkSymbolic: Unsupported field accessor definition.
+      Multiply used: u
+      
+      SBV does not support cases where accessor fields are replicated.
+      Please use each accessor only once.
+
+   |
+14 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Num i | i .> 3 -> 5
+                     | sTrue  -> 12
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase28.stderr
@@ -0,0 +1,25 @@
+SCase28.hs:(11,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Num i | i .> 3 -> 5\n\
+      \                     | sTrue  -> 12\n\
+      \\n\
+      \               Zero{} -> 0\n\
+      \               Var{}  -> 0\n\
+      \               Add{}  -> 0\n\
+      \               Let{}  -> 0\n\
+      \      "
+  ======>
+    ite
+      ((.&&) (isNum e) ((\ i -> i .> 3) (getNum_1 e)))
+      ((\ i -> const 5 i) (getNum_1 e))
+      (ite
+         (isNum e) ((\ i -> const 12 i) (getNum_1 e))
+         (ite
+            (isZero e) 0
+            (ite
+               (isVar e) ((\ _ -> 0) (getVar_1 e))
+               (ite
+                  (isAdd e) ((\ _ _ -> 0) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ _ -> 0) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Num i | i > 3  -> 5
+                     | sTrue  -> 12
+               Num i | i > 12 -> 7
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase29.stderr
@@ -0,0 +1,22 @@
+SCase29.hs:11:14: error: [GHC-39584]
+    " SCase29.hs:14:16-20: sCase: Overlapping case constructors:
+        Type       : Expr
+        Constructor: Num i | i > 12
+      Overlaps with:
+        SCase29.hs:12:16-20: Num i
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Num i | i > 3  -> 5
+                     | sTrue  -> 12
+               Num i | i > 12 -> 7
+
+               Zero{} -> 0
+               Var{}  -> 0
+               Add{}  -> 0
+               Let{}  -> 0
+      |]
+   |
+11 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TypeApplications  #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing constructor/type name conflct
+data A = A Integer
+       | B Float
+       | C A A
+
+mkSymbolic [''A]
+
+t :: SA -> SA
+t a = [sCase| a of
+         A u     -> sA (u+1)
+         B f     -> sB (f+2)
+         C a1 a2 -> sC (t a1) (t a2)
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase30.stderr
@@ -0,0 +1,12 @@
+SCase30.hs:(20,14)-(24,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " a of\n\
+      \         A u     -> sA (u+1)\n\
+      \         B f     -> sB (f+2)\n\
+      \         C a1 a2 -> sC (t a1) (t a2)\n\
+      \      "
+  ======>
+    sCaseA
+      (\ u -> sA (u + 1)) (\ f -> sB (f + 2))
+      (\ a1 a2 -> sC (t a1) (t a2)) a
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TemplateHaskell   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing bad fields
+data A = F (Integer -> Bool)
+       | I Integer
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase31.stderr
@@ -0,0 +1,12 @@
+SCase31.hs:13:1: error: [GHC-39584]
+    mkSymbolic: Unsupported constructor kind
+      Datatype   : A
+      Constructor: F
+      Kind       : GHC.Internal.Bignum.Integer.Integer -> GHC.Internal.Types.Bool
+      
+      Higher order fields (i.e., function values) are not supported.
+
+   |
+13 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE TemplateHaskell   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Data.SBV
+
+-- Testing bad fields
+data A = F (A -> Bool)
+       | I Integer
+
+mkSymbolic [''A]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase32.stderr
@@ -0,0 +1,12 @@
+SCase32.hs:13:1: error: [GHC-39584]
+    mkSymbolic: Unsupported constructor kind
+      Datatype   : A
+      Constructor: F
+      Kind       : T.A -> GHC.Internal.Types.Bool
+      
+      Higher order fields (i.e., function values) are not supported.
+
+   |
+13 | mkSymbolic [''A]
+   | ^^^^^^^^^^^^^^^^
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: deeply nested pattern Add (Add (Num i) j) k
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero                  -> 0
+               Num k                 -> k
+               Var s                 -> ite (s .== literal "a") 1 2
+               Add (Add (Num i) j) k -> i + t j + t k
+               Add a b               -> t a + t b
+               Let _   _a  b         -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase33.stderr
@@ -0,0 +1,34 @@
+SCase33.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero                  -> 0\n\
+      \               Num k                 -> k\n\
+      \               Var s                 -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Add (Num i) j) k -> i + t j + t k\n\
+      \               Add a b               -> t a + t b\n\
+      \               Let _   _a  b         -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ k
+                      -> const
+                           ((.&&) (isAdd (getAdd_1 e)) (isNum (getAdd_1 (getAdd_1 e)))) k)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ k
+                   -> let
+                        j = getAdd_2 (getAdd_1 e)
+                        i = getNum_1 (getAdd_1 (getAdd_1 e))
+                      in i + t j + t k)
+                  (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: nested pattern combined with a guard
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero                -> 0
+               Num k               -> k
+               Var s               -> ite (s .== literal "a") 1 2
+               Add (Num i) j | i .> 0 -> i + t j
+               Add a b             -> t a + t b
+               Let _   _a  b       -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase34.stderr
@@ -0,0 +1,32 @@
+SCase34.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero                -> 0\n\
+      \               Num k               -> k\n\
+      \               Var s               -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Num i) j | i .> 0 -> i + t j\n\
+      \               Add a b             -> t a + t b\n\
+      \               Let _   _a  b       -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ j
+                      -> const
+                           ((.&&)
+                              (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+                           j)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ j -> let i = getNum_1 (getAdd_1 e) in i + t j)
+                  (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: nested patterns on both sides of Add
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var s             -> ite (s .== literal "a") 1 2
+               Add (Num i) (Num j) -> i + j
+               Add a b           -> t a + t b
+               Let _   _a  b     -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase35.stderr
@@ -0,0 +1,32 @@
+SCase35.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero              -> 0\n\
+      \               Num k             -> k\n\
+      \               Var s             -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Num i) (Num j) -> i + j\n\
+      \               Add a b           -> t a + t b\n\
+      \               Let _   _a  b     -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ _ -> (.&&) (isNum (getAdd_1 e)) (isNum (getAdd_2 e)))
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ _
+                   -> let
+                        i = getNum_1 (getAdd_1 e)
+                        j = getNum_1 (getAdd_2 e)
+                      in i + j)
+                  (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: nested pattern with wildcard inside the nested constructor
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var s         -> ite (s .== literal "a") 1 2
+               Add (Num _) j -> 1 + t j
+               Add a b       -> t a + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase36.stderr
@@ -0,0 +1,27 @@
+SCase36.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num k         -> k\n\
+      \               Var s         -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Num _) j -> 1 + t j\n\
+      \               Add a b       -> t a + t b\n\
+      \               Let _   _a  b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ j -> const (isNum (getAdd_1 e)) j)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ j -> 1 + t j) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: literal pattern inside nested position is not supported
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var s         -> ite (s .== literal "a") 1 2
+               Add (Num 0) j -> t j
+               Add a b       -> t a + t b
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase37.stderr
@@ -0,0 +1,29 @@
+SCase37.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num k         -> k\n\
+      \               Var s         -> ite (s .== literal \"a\") 1 2\n\
+      \               Add (Num 0) j -> t j\n\
+      \               Add a b       -> t a + t b\n\
+      \               Let _   _a  b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ j
+                      -> const
+                           ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 0)) j)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ j -> t j) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _a b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: nested constructor with wrong arity (Num takes 1 arg, given 2)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var s             -> ite (s .== literal "a") 1 2
+               Add (Num i j) b   -> i + t b
+               Add a b           -> t a + t b
+               Let _   _a  b     -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase38.stderr
@@ -0,0 +1,19 @@
+SCase38.hs:12:14: error: [GHC-39584]
+    " SCase38.hs:16:16-30: sCase/pCase: Arity mismatch in nested pattern.
+        Constructor: Num
+        Expected   : 1
+        Given      : 2
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var s             -> ite (s .== literal "a") 1 2
+               Add (Num i j) b   -> i + t b
+               Add a b           -> t a + t b
+               Let _   _a  b     -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: nested constructor that is not in scope
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var s             -> ite (s .== literal "a") 1 2
+               Add (Numb i) b    -> i + t b
+               Add a b           -> t a + t b
+               Let _   _a  b     -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase39.stderr
@@ -0,0 +1,15 @@
+SCase39.hs:12:14: error: [GHC-39584]
+    " SCase39.hs:16:16-29: sCase/pCase: Not in scope: data constructor: Numb
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var s             -> ite (s .== literal "a") 1 2
+               Add (Numb i) b    -> i + t b
+               Add a b           -> t a + t b
+               Let _   _a  b     -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: nested pattern using parenthesized constructor (ParensP)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero                    -> 0
+               Num k                   -> k
+               Var s                   -> ite (s .== literal "a") 1 2
+               Let _ (Num i) b         -> i + t b
+               Let _ a       b         -> t a + t b
+               Add a b                 -> t a + t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase40.stderr
@@ -0,0 +1,29 @@
+SCase40.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero                    -> 0\n\
+      \               Num k                   -> k\n\
+      \               Var s                   -> ite (s .== literal \"a\") 1 2\n\
+      \               Let _ (Num i) b         -> i + t b\n\
+      \               Let _ a       b         -> t a + t b\n\
+      \               Add a b                 -> t a + t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ s -> ite (s .== literal "a") 1 2) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isLet e)
+                  ((\ _ _ b -> const (isNum (getLet_2 e)) b)
+                     (getLet_1 e) (getLet_2 e) (getLet_3 e)))
+               ((\ _ _ b -> let i = getNum_1 (getLet_2 e) in i + t b)
+                  (getLet_1 e) (getLet_2 e) (getLet_3 e))
+               (ite
+                  (isLet e)
+                  ((\ _ a b -> (t a) + t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))
+                  ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: nested pattern covers only a subset of Add; missing fallback for Add _ _
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var s         -> ite (s .== literal "a") 1 2
+               Add (Num i) j -> i + t j
+               Let _   _a  b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase41.stderr
@@ -0,0 +1,18 @@
+SCase41.hs:12:14: error: [GHC-39584]
+    " SCase41.hs:16:16-28: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Add _ j | isNum (getAdd_1 e)
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var s         -> ite (s .== literal "a") 1 2
+               Add (Num i) j -> i + t j
+               Let _   _a  b -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: deeply nested pattern covers only a subset of the outermost Add; missing fallback
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero                          -> 0
+               Num k                         -> k
+               Var s                         -> ite (s .== literal "a") 1 2
+               Add (Add (Add (Num _) b) c) d -> t b + t c + t d
+               Let _   _a  b                 -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase42.stderr
@@ -0,0 +1,18 @@
+SCase42.hs:12:14: error: [GHC-39584]
+    " SCase42.hs:16:16-44: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Add _ d | (Data.SBV.Core.Data..&&) (isAdd (getAdd_1 e)) ((Data.SBV.Core.Data..&&) (isAdd (getAdd_1 (getAdd_1 e))) (isNum (getAdd_1 (getAdd_1 (getAdd_1 e)))))
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero                          -> 0
+               Num k                         -> k
+               Var s                         -> ite (s .== literal "a") 1 2
+               Add (Add (Add (Num _) b) c) d -> t b + t c + t d
+               Let _   _a  b                 -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: integer literal at top level (Num 1 -> ...)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero  -> 0
+               Num 1 -> 100
+               Num k -> k
+               Var _ -> -1
+               Add a b -> t a + t b
+               Let _ _ b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase43.stderr
@@ -0,0 +1,24 @@
+SCase43.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero  -> 0\n\
+      \               Num 1 -> 100\n\
+      \               Num k -> k\n\
+      \               Var _ -> -1\n\
+      \               Add a b -> t a + t b\n\
+      \               Let _ _ b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         ((.&&) (isNum e) ((\ _ -> (.==) (getNum_1 e) 1) (getNum_1 e)))
+         ((\ _ -> 100) (getNum_1 e))
+         (ite
+            (isNum e) ((\ k -> k) (getNum_1 e))
+            (ite
+               (isVar e) ((\ _ -> negate 1) (getVar_1 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: integer literal in nested position (Add (Num 0) j -> ...)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var _         -> -1
+               Add (Num 0) j -> t j
+               Add a       b -> t a + t b
+               Let _ _     b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase44.stderr
@@ -0,0 +1,29 @@
+SCase44.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num k         -> k\n\
+      \               Var _         -> -1\n\
+      \               Add (Num 0) j -> t j\n\
+      \               Add a       b -> t a + t b\n\
+      \               Let _ _     b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ _ -> negate 1) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ j
+                      -> const
+                           ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 0)) j)
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ j -> t j) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: string literal in nested position (Var "x" -> ...)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero      -> 0
+               Num k     -> k
+               Var "x"   -> 42
+               Var _     -> -1
+               Add a b   -> t a + t b
+               Let _ _ b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase45.stderr
@@ -0,0 +1,25 @@
+SCase45.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero      -> 0\n\
+      \               Num k     -> k\n\
+      \               Var \"x\"   -> 42\n\
+      \               Var _     -> -1\n\
+      \               Add a b   -> t a + t b\n\
+      \               Let _ _ b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            ((.&&)
+               (isVar e) ((\ _ -> (.==) (getVar_1 e) (literal "x")) (getVar_1 e)))
+            ((\ _ -> 42) (getVar_1 e))
+            (ite
+               (isVar e) ((\ _ -> negate 1) (getVar_1 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Positive: integer literals on both sides of nested pattern (Add (Num 1) (Num 2) -> ...)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero              -> 0
+               Num k             -> k
+               Var _             -> -1
+               Add (Num 1) (Num 2) -> 99
+               Add a           b -> t a + t b
+               Let _       _   b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase46.stderr
@@ -0,0 +1,32 @@
+SCase46.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero              -> 0\n\
+      \               Num k             -> k\n\
+      \               Var _             -> -1\n\
+      \               Add (Num 1) (Num 2) -> 99\n\
+      \               Add a           b -> t a + t b\n\
+      \               Let _       _   b -> t b\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         (isNum e) ((\ k -> k) (getNum_1 e))
+         (ite
+            (isVar e) ((\ _ -> negate 1) (getVar_1 e))
+            (ite
+               ((.&&)
+                  (isAdd e)
+                  ((\ _ _
+                      -> (.&&)
+                           (isNum (getAdd_1 e))
+                           ((.&&)
+                              ((.==) (getNum_1 (getAdd_1 e)) 1)
+                              ((.&&) (isNum (getAdd_2 e)) ((.==) (getNum_1 (getAdd_2 e)) 2))))
+                     (getAdd_1 e) (getAdd_2 e)))
+               ((\ _ _ -> 99) (getAdd_1 e) (getAdd_2 e))
+               (ite
+                  (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+                  ((\ _ _ b -> t b) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: Num 1 without a fallback for the Num constructor
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero      -> 0
+               Num 1     -> 100
+               Var _     -> -1
+               Add a b   -> t a + t b
+               Let _ _ b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase47.stderr
@@ -0,0 +1,18 @@
+SCase47.hs:12:14: error: [GHC-39584]
+    " SCase47.hs:14:16-20: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Num _ | (Data.SBV.Core.Data..==) (getNum_1 e) 1
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero      -> 0
+               Num 1     -> 100
+               Var _     -> -1
+               Add a b   -> t a + t b
+               Let _ _ b -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Negative: Add (Num 1) j without a fallback for the Add constructor
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var _         -> -1
+               Add (Num 1) j -> 100 + t j
+               Let _ _     b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase48.stderr
@@ -0,0 +1,18 @@
+SCase48.hs:12:14: error: [GHC-39584]
+    " SCase48.hs:16:16-28: sCase: Non-exhaustive match:
+        Type       : Expr
+        Constructor: Add _ j | (Data.SBV.Core.Data..&&) (isNum (getAdd_1 e)) ((Data.SBV.Core.Data..==) (getNum_1 (getAdd_1 e)) 1)
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+               Zero          -> 0
+               Num k         -> k
+               Var _         -> -1
+               Add (Num 1) j -> 100 + t j
+               Let _ _     b -> t b
+      |]
+   |
+12 | t e = [sCase| e of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.hs
@@ -0,0 +1,18 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: simple unguarded, all constructors, no guards/wildcards/nesting
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               Var _         -> 1
+               Add _ _       -> 2
+               Let _ _ _     -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase49.stderr
@@ -0,0 +1,12 @@
+SCase49.hs:(12,14)-(18,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num i         -> i\n\
+      \               Var _         -> 1\n\
+      \               Add _ _       -> 2\n\
+      \               Let _ _ _     -> 3\n\
+      \      "
+  ======>
+    sCaseExpr 0 (\ i -> i) (\ _ -> 1) (\ _ _ -> 2) (\ _ _ _ -> 3) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: multiple guards on same constructor (guard accumulation, ite chain)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero              -> 0
+               Num i | i .< 3    -> i
+                     | i .< 10   -> i + 1
+               Num i             -> i + 2
+               Var _             -> 1
+               Add _ _           -> 2
+               Let _ _ _         -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase50.stderr
@@ -0,0 +1,28 @@
+SCase50.hs:(12,14)-(20,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero              -> 0\n\
+      \               Num i | i .< 3    -> i\n\
+      \                     | i .< 10   -> i + 1\n\
+      \               Num i             -> i + 2\n\
+      \               Var _             -> 1\n\
+      \               Add _ _           -> 2\n\
+      \               Let _ _ _         -> 3\n\
+      \      "
+  ======>
+    ite
+      (isZero e) 0
+      (ite
+         ((.&&) (isNum e) ((\ i -> i .< 3) (getNum_1 e)))
+         ((\ i -> i) (getNum_1 e))
+         (ite
+            ((.&&) (isNum e) ((\ i -> i .< 10) (getNum_1 e)))
+            ((\ i -> i + 1) (getNum_1 e))
+            (ite
+               (isNum e) ((\ i -> i + 2) (getNum_1 e))
+               (ite
+                  (isVar e) ((\ _ -> 1) (getVar_1 e))
+                  (ite
+                     (isAdd e) ((\ _ _ -> 2) (getAdd_1 e) (getAdd_2 e))
+                     ((\ _ _ _ -> 3) (getLet_1 e) (getLet_2 e) (getLet_3 e)))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: wildcard catch-all after some constructors (ite chain with default)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero          -> 0
+               Num i         -> i
+               _             -> 99
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase51.stderr
@@ -0,0 +1,10 @@
+SCase51.hs:(12,14)-(16,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero          -> 0\n\
+      \               Num i         -> i\n\
+      \               _             -> 99\n\
+      \      "
+  ======>
+    sCaseExpr 0 (\ i -> i) (\ _ -> 99) (\ _ _ -> 99) (\ _ _ _ -> 99) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: nested pattern with literal (synthetic guards, accessors, let-bindings)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Add (Num 0) j -> t j
+               Add a b       -> t a + t b
+               Zero          -> 0
+               Num i         -> i
+               Var _         -> 1
+               Let _ _ _     -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase52.stderr
@@ -0,0 +1,29 @@
+SCase52.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Add (Num 0) j -> t j\n\
+      \               Add a b       -> t a + t b\n\
+      \               Zero          -> 0\n\
+      \               Num i         -> i\n\
+      \               Var _         -> 1\n\
+      \               Let _ _ _     -> 3\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (isAdd e)
+         ((\ _ j
+             -> const
+                  ((.&&) (isNum (getAdd_1 e)) ((.==) (getNum_1 (getAdd_1 e)) 0)) j)
+            (getAdd_1 e) (getAdd_2 e)))
+      ((\ _ j -> t j) (getAdd_1 e) (getAdd_2 e))
+      (ite
+         (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+         (ite
+            (isZero e) 0
+            (ite
+               (isNum e) ((\ i -> i) (getNum_1 e))
+               (ite
+                  (isVar e) ((\ _ -> 1) (getVar_1 e))
+                  ((\ _ _ _ -> 3) (getLet_1 e) (getLet_2 e) (getLet_3 e))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: nested pattern with user guard (combines nesting + guard accumulation)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Add (Num i) b | i .> 0   -> i + t b
+                              | i .> -5  -> t b
+               Add a b                   -> t a + t b
+               Zero                      -> 0
+               Num i                     -> i
+               Var _                     -> 1
+               Let _ _ _                 -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase53.stderr
@@ -0,0 +1,44 @@
+SCase53.hs:(12,14)-(20,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Add (Num i) b | i .> 0   -> i + t b\n\
+      \                              | i .> -5  -> t b\n\
+      \               Add a b                   -> t a + t b\n\
+      \               Zero                      -> 0\n\
+      \               Num i                     -> i\n\
+      \               Var _                     -> 1\n\
+      \               Let _ _ _                 -> 3\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (isAdd e)
+         ((\ _ b
+             -> const
+                  ((.&&)
+                     (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+                  b)
+            (getAdd_1 e) (getAdd_2 e)))
+      ((\ _ b -> let i = getNum_1 (getAdd_1 e) in i + t b)
+         (getAdd_1 e) (getAdd_2 e))
+      (ite
+         ((.&&)
+            (isAdd e)
+            ((\ _ b
+                -> const
+                     ((.&&)
+                        (isNum (getAdd_1 e))
+                        (let i = getNum_1 (getAdd_1 e) in i .> negate 5))
+                     b)
+               (getAdd_1 e) (getAdd_2 e)))
+         ((\ _ b -> t b) (getAdd_1 e) (getAdd_2 e))
+         (ite
+            (isAdd e) ((\ a b -> (t a) + t b) (getAdd_1 e) (getAdd_2 e))
+            (ite
+               (isZero e) 0
+               (ite
+                  (isNum e) ((\ i -> i) (getNum_1 e))
+                  (ite
+                     (isVar e) ((\ _ -> 1) (getVar_1 e))
+                     ((\ _ _ _ -> 3) (getLet_1 e) (getLet_2 e) (getLet_3 e)))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Maybe (no guards)
+module T where
+
+import Data.SBV
+
+t :: SMaybe Integer -> SInteger
+t m = [sCase| m of
+               Nothing -> 0
+               Just x  -> x + 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase54.stderr
@@ -0,0 +1,9 @@
+SCase54.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               Nothing -> 0\n\
+      \               Just x  -> x + 1\n\
+      \      "
+  ======>
+    Data.SBV.Maybe.sCaseMaybe 0 (\ x -> x + 1) m
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Either (no guards)
+module T where
+
+import Data.SBV
+
+t :: SEither Integer Bool -> SInteger
+t e = [sCase| e of
+               Left a  -> a
+               Right _ -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase55.stderr
@@ -0,0 +1,9 @@
+SCase55.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Left a  -> a\n\
+      \               Right _ -> 0\n\
+      \      "
+  ======>
+    Data.SBV.Either.sCaseEither (\ a -> a) (\ _ -> 0) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE OverloadedLists #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with List (no guards)
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+
+t :: SList Integer -> SInteger
+t xs = [sCase| xs of
+                []     -> 0
+                y : ys -> y + t ys
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase56.stderr
@@ -0,0 +1,12 @@
+SCase56.hs:(13,15)-(16,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " xs of\n\
+      \                []     -> 0\n\
+      \                y : ys -> y + t ys\n\
+      \       "
+  ======>
+    ite
+      (Data.SBV.List.null xs) 0
+      ((\ y ys -> y + t ys)
+         (Data.SBV.List.head xs) (Data.SBV.List.tail xs))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Tuple2
+module T where
+
+import Data.SBV
+
+t :: STuple Integer Bool -> SInteger
+t p = [sCase| p of
+               (a, _) -> a + 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase57.stderr
@@ -0,0 +1,8 @@
+SCase57.hs:(11,14)-(13,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " p of\n\
+      \               (a, _) -> a + 1\n\
+      \      "
+  ======>
+    (\ a _ -> a + 1) (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE OverloadedLists #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with List, nested cons pattern
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+
+t :: SList Integer -> SInteger
+t xs = [sCase| xs of
+                []          -> 0
+                a : (b : _) -> a + b
+                _ : _       -> 1
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase58.stderr
@@ -0,0 +1,28 @@
+SCase58.hs:(13,15)-(17,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " xs of\n\
+      \                []          -> 0\n\
+      \                a : (b : _) -> a + b\n\
+      \                _ : _       -> 1\n\
+      \       "
+  ======>
+    ite
+      (Data.SBV.List.null xs) 0
+      (ite
+         ((.&&)
+            (sNot (Data.SBV.List.null xs))
+            ((\ a _
+                -> const
+                     ((.&&)
+                        (sNot (Data.SBV.List.null (Data.SBV.List.tail xs)))
+                        ((.===)
+                           (Data.SBV.List.tail xs)
+                           (Data.SBV.List.head (Data.SBV.List.tail xs)
+                              .: Data.SBV.List.tail (Data.SBV.List.tail xs))))
+                     a)
+               (Data.SBV.List.head xs) (Data.SBV.List.tail xs)))
+         ((\ a _
+             -> let b = Data.SBV.List.head (Data.SBV.List.tail xs) in a + b)
+            (Data.SBV.List.head xs) (Data.SBV.List.tail xs))
+         ((\ _ _ -> 1) (Data.SBV.List.head xs) (Data.SBV.List.tail xs)))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Maybe, nested Either pattern
+module T where
+
+import Data.SBV
+
+t :: SMaybe (Either Integer Bool) -> SInteger
+t m = [sCase| m of
+               Nothing          -> 0
+               Just (Left x)    -> x
+               Just (Right _)   -> 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase59.stderr
@@ -0,0 +1,27 @@
+SCase59.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               Nothing          -> 0\n\
+      \               Just (Left x)    -> x\n\
+      \               Just (Right _)   -> 1\n\
+      \      "
+  ======>
+    ite
+      (Data.SBV.Maybe.isNothing m) 0
+      (ite
+         ((.&&)
+            (Data.SBV.Maybe.isJust m)
+            ((\ _ -> Data.SBV.Either.isLeft (Data.SBV.Maybe.getJust_1 m))
+               (Data.SBV.Maybe.getJust_1 m)))
+         ((\ _
+             -> let x = Data.SBV.Either.getLeft_1 (Data.SBV.Maybe.getJust_1 m)
+                in x)
+            (Data.SBV.Maybe.getJust_1 m))
+         (ite
+            ((.&&)
+               (Data.SBV.Maybe.isJust m)
+               ((\ _ -> Data.SBV.Either.isRight (Data.SBV.Maybe.getJust_1 m))
+                  (Data.SBV.Maybe.getJust_1 m)))
+            ((\ _ -> 1) (Data.SBV.Maybe.getJust_1 m))
+            (symWithKind "unmatched_sCase_Maybe_6989586621679035008")))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE OverloadedLists #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with List and guards
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+
+t :: SList Integer -> SInteger
+t xs = [sCase| xs of
+                []         -> 0
+                y : _ | y .== 5 -> 100
+                _ : ys     -> t ys
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase60.stderr
@@ -0,0 +1,19 @@
+SCase60.hs:(13,15)-(17,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " xs of\n\
+      \                []         -> 0\n\
+      \                y : _ | y .== 5 -> 100\n\
+      \                _ : ys     -> t ys\n\
+      \       "
+  ======>
+    ite
+      (Data.SBV.List.null xs) 0
+      (ite
+         ((.&&)
+            (sNot (Data.SBV.List.null xs))
+            ((\ y _ -> y .== 5)
+               (Data.SBV.List.head xs) (Data.SBV.List.tail xs)))
+         ((\ y _ -> const 100 y)
+            (Data.SBV.List.head xs) (Data.SBV.List.tail xs))
+         ((\ _ ys -> t ys) (Data.SBV.List.head xs) (Data.SBV.List.tail xs)))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Maybe, guards on Just
+module T where
+
+import Data.SBV
+
+t :: SMaybe Integer -> SInteger
+t m = [sCase| m of
+               Nothing        -> 0
+               Just x | x .> 5 -> x * 2
+               Just x         -> x
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase61.stderr
@@ -0,0 +1,17 @@
+SCase61.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               Nothing        -> 0\n\
+      \               Just x | x .> 5 -> x * 2\n\
+      \               Just x         -> x\n\
+      \      "
+  ======>
+    ite
+      (Data.SBV.Maybe.isNothing m) 0
+      (ite
+         ((.&&)
+            (Data.SBV.Maybe.isJust m)
+            ((\ x -> x .> 5) (Data.SBV.Maybe.getJust_1 m)))
+         ((\ x -> x * 2) (Data.SBV.Maybe.getJust_1 m))
+         ((\ x -> x) (Data.SBV.Maybe.getJust_1 m)))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Either, guards and wildcard
+module T where
+
+import Data.SBV
+
+t :: SEither Integer Integer -> SInteger
+t e = [sCase| e of
+               Left x | x .> 0 -> x
+               _               -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase62.stderr
@@ -0,0 +1,13 @@
+SCase62.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Left x | x .> 0 -> x\n\
+      \               _               -> 0\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (Data.SBV.Either.isLeft e)
+         ((\ x -> x .> 0) (Data.SBV.Either.getLeft_1 e)))
+      ((\ x -> x) (Data.SBV.Either.getLeft_1 e)) 0
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Tuple3
+module T where
+
+import Data.SBV
+
+t :: STuple3 Integer Integer Bool -> SInteger
+t p = [sCase| p of
+               (a, b, _) -> a + b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase63.stderr
@@ -0,0 +1,9 @@
+SCase63.hs:(11,14)-(13,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " p of\n\
+      \               (a, b, _) -> a + b\n\
+      \      "
+  ======>
+    (\ a b _ -> a + b)
+      (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p) (Data.SBV.Tuple._3 p)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE OverloadedLists #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with List, wildcard only for cons
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+
+t :: SList Integer -> SBool
+t xs = [sCase| xs of
+                []     -> sTrue
+                _ : _  -> sFalse
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase64.stderr
@@ -0,0 +1,11 @@
+SCase64.hs:(13,15)-(16,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " xs of\n\
+      \                []     -> sTrue\n\
+      \                _ : _  -> sFalse\n\
+      \       "
+  ======>
+    ite
+      (Data.SBV.List.null xs) sTrue
+      ((\ _ _ -> sFalse) (Data.SBV.List.head xs) (Data.SBV.List.tail xs))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with nested tuple inside Maybe
+module T where
+
+import Data.SBV
+
+t :: SMaybe (Integer, Bool) -> SInteger
+t m = [sCase| m of
+               Nothing     -> 0
+               Just (a, _) -> a
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase65.stderr
@@ -0,0 +1,13 @@
+SCase65.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " m of\n\
+      \               Nothing     -> 0\n\
+      \               Just (a, _) -> a\n\
+      \      "
+  ======>
+    Data.SBV.Maybe.sCaseMaybe
+      0
+      (\ _
+         -> let a = Data.SBV.Tuple._1 (Data.SBV.Maybe.getJust_1 m) in a)
+      m
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes     #-}
+{-# LANGUAGE OverloadedLists #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with nested list inside Either
+module T where
+
+import Prelude hiding (null, head, tail)
+import Data.SBV
+
+t :: SEither ([] Integer) Bool -> SInteger
+t e = [sCase| e of
+               Left (x : _) -> x
+               Left []      -> 0
+               Right _      -> 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase66.stderr
@@ -0,0 +1,33 @@
+SCase66.hs:(13,14)-(17,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Left (x : _) -> x\n\
+      \               Left []      -> 0\n\
+      \               Right _      -> 1\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (Data.SBV.Either.isLeft e)
+         ((\ _
+             -> (.&&)
+                  (sNot (Data.SBV.List.null (Data.SBV.Either.getLeft_1 e)))
+                  ((.===)
+                     (Data.SBV.Either.getLeft_1 e)
+                     (Data.SBV.List.head (Data.SBV.Either.getLeft_1 e)
+                        .: Data.SBV.List.tail (Data.SBV.Either.getLeft_1 e))))
+            (Data.SBV.Either.getLeft_1 e)))
+      ((\ _
+          -> let x = Data.SBV.List.head (Data.SBV.Either.getLeft_1 e) in x)
+         (Data.SBV.Either.getLeft_1 e))
+      (ite
+         ((.&&)
+            (Data.SBV.Either.isLeft e)
+            ((\ _ -> Data.SBV.List.null (Data.SBV.Either.getLeft_1 e))
+               (Data.SBV.Either.getLeft_1 e)))
+         ((\ _ -> 0) (Data.SBV.Either.getLeft_1 e))
+         (ite
+            (Data.SBV.Either.isRight e)
+            ((\ _ -> 1) (Data.SBV.Either.getRight_1 e))
+            (symWithKind "unmatched_sCase_Either_6989586621679034970")))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Tuple2 with guard
+module T where
+
+import Data.SBV
+
+t :: STuple Integer Integer -> SInteger
+t p = [sCase| p of
+               (a, b) | a .> b -> a
+               (_, b)          -> b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase67.stderr
@@ -0,0 +1,12 @@
+SCase67.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " p of\n\
+      \               (a, b) | a .> b -> a\n\
+      \               (_, b)          -> b\n\
+      \      "
+  ======>
+    ite
+      ((\ a b -> a .> b) (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p))
+      ((\ a b -> const a b) (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p))
+      ((\ _ b -> b) (Data.SBV.Tuple._1 p) (Data.SBV.Tuple._2 p))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with wildcard-only, no guards
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SInteger
+t x = [sCase| x of
+               _ -> x + 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase68.stderr
@@ -0,0 +1,8 @@
+SCase68.hs:(11,14)-(13,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               _ -> x + 1\n\
+      \      "
+  ======>
+    x + 1
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with guarded wildcards only
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SInteger
+t x = [sCase| x of
+               _ | x .> 0 -> x
+                 | sTrue   -> -x
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase69.stderr
@@ -0,0 +1,9 @@
+SCase69.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               _ | x .> 0 -> x\n\
+      \                 | sTrue   -> -x\n\
+      \      "
+  ======>
+    ite (x .> 0) x (negate x)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with integer literal pattern and wildcard
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SBool
+t x = [sCase| x of
+               0 -> sTrue
+               _ -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase70.stderr
@@ -0,0 +1,9 @@
+SCase70.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0 -> sTrue\n\
+      \               _ -> sFalse\n\
+      \      "
+  ======>
+    ite ((.==) x 0) sTrue sFalse
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with multiple integer literals and wildcard
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SInteger
+t x = [sCase| x of
+               0 -> 10
+               1 -> 20
+               2 -> 30
+               _ -> x
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase71.stderr
@@ -0,0 +1,11 @@
+SCase71.hs:(11,14)-(16,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0 -> 10\n\
+      \               1 -> 20\n\
+      \               2 -> 30\n\
+      \               _ -> x\n\
+      \      "
+  ======>
+    ite ((.==) x 0) 10 (ite ((.==) x 1) 20 (ite ((.==) x 2) 30 x))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with integer literal and variable binding
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SInteger
+t x = [sCase| x of
+               0 -> 0
+               n -> n + 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase72.stderr
@@ -0,0 +1,9 @@
+SCase72.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0 -> 0\n\
+      \               n -> n + 1\n\
+      \      "
+  ======>
+    ite ((.==) x 0) 0 (let n = x in n + 1)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with char literal patterns
+module T where
+
+import Data.SBV
+
+t :: SChar -> SBool
+t c = [sCase| c of
+               'a' -> sTrue
+               'b' -> sTrue
+               _   -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase73.stderr
@@ -0,0 +1,12 @@
+SCase73.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " c of\n\
+      \               'a' -> sTrue\n\
+      \               'b' -> sTrue\n\
+      \               _   -> sFalse\n\
+      \      "
+  ======>
+    ite
+      ((.==) c (literal 'a')) sTrue
+      (ite ((.==) c (literal 'b')) sTrue sFalse)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with integer literal and guard
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SInteger -> SInteger
+t x y = [sCase| x of
+                 0         -> y
+                 _ | x .> y -> x
+                   | sTrue  -> y
+        |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase74.stderr
@@ -0,0 +1,10 @@
+SCase74.hs:(11,16)-(15,10): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \                 0         -> y\n\
+      \                 _ | x .> y -> x\n\
+      \                   | sTrue  -> y\n\
+      \        "
+  ======>
+    ite ((.==) x 0) y (ite (x .> y) x y)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with string literal patterns
+module T where
+
+import Data.SBV
+
+t :: SString -> SInteger
+t s = [sCase| s of
+               "hello" -> 1
+               "world" -> 2
+               _       -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase75.stderr
@@ -0,0 +1,11 @@
+SCase75.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " s of\n\
+      \               \"hello\" -> 1\n\
+      \               \"world\" -> 2\n\
+      \               _       -> 0\n\
+      \      "
+  ======>
+    ite
+      ((.==) s (literal "hello")) 1 (ite ((.==) s (literal "world")) 2 0)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with negative integer literal (uses LitP with negative value)
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SBool
+t x = [sCase| x of
+               0    -> sTrue
+               (-1) -> sTrue
+               _    -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase76.stderr
@@ -0,0 +1,10 @@
+SCase76.hs:(11,14)-(15,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0    -> sTrue\n\
+      \               (-1) -> sTrue\n\
+      \               _    -> sFalse\n\
+      \      "
+  ======>
+    ite ((.==) x 0) sTrue (ite ((.==) x (-1)) sTrue sFalse)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with integer literal patterns (no dump, just compilation check)
+-- Tests that the generated code actually type-checks with SBV types
+module T where
+
+import Data.SBV
+
+clamp :: SInteger -> SInteger
+clamp x = [sCase| x of
+                   0 -> 0
+                   1 -> 1
+                   n -> ite (n .> 0) 100 (-100)
+           |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase77.stderr
@@ -0,0 +1,12 @@
+SCase77.hs:(12,18)-(16,13): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \                   0 -> 0\n\
+      \                   1 -> 1\n\
+      \                   n -> ite (n .> 0) 100 (-100)\n\
+      \           "
+  ======>
+    ite
+      ((.==) x 0) 0
+      (ite ((.==) x 1) 1 (let n = x in ite (n .> 0) 100 (negate 100)))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Bool constructor patterns
+module T where
+
+import Data.SBV
+
+t :: SBool -> SBool
+t x = [sCase| x of
+               True  -> sTrue
+               False -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase78.stderr
@@ -0,0 +1,9 @@
+SCase78.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               True  -> sTrue\n\
+      \               False -> sFalse\n\
+      \      "
+  ======>
+    ite x sTrue sFalse
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Bool patterns and guard
+module T where
+
+import Data.SBV
+
+t :: SBool -> SInteger -> SInteger
+t b x = [sCase| b of
+                 True  | x .> 0 -> x
+                 True           -> 0
+                 False          -> -x
+        |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase79.stderr
@@ -0,0 +1,10 @@
+SCase79.hs:(11,16)-(15,10): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " b of\n\
+      \                 True  | x .> 0 -> x\n\
+      \                 True           -> 0\n\
+      \                 False          -> -x\n\
+      \        "
+  ======>
+    ite ((.&&) b (x .> 0)) x (ite b 0 (negate x))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase Bool non-exhaustive (only True, no wildcard) — should fail
+module T where
+
+import Data.SBV
+
+t :: SBool -> SInteger
+t x = [sCase| x of
+               True -> 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase80.stderr
@@ -0,0 +1,16 @@
+SCase80.hs:11:14: error: [GHC-39584]
+    " sCase: Pattern match(es) are non-exhaustive.
+        Not matched     : False
+        Patterns of type: Bool
+        Must match each : True, False
+
+      You can use a '_' to match multiple cases.
+
+    " In the quasi-quotation:
+        [sCase| x of
+               True -> 1
+      |]
+   |
+11 | t x = [sCase| x of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase Bool with wildcard catch-all
+module T where
+
+import Data.SBV
+
+t :: SBool -> SInteger
+t x = [sCase| x of
+               True -> 1
+               _    -> 0
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase81.stderr
@@ -0,0 +1,9 @@
+SCase81.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               True -> 1\n\
+      \               _    -> 0\n\
+      \      "
+  ======>
+    ite x 1 0
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE DataKinds   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Word8 integer literal patterns
+module T where
+
+import Data.SBV
+
+t :: SWord8 -> SWord8
+t x = [sCase| x of
+               0 -> 10
+               1 -> 20
+               _ -> x
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase82.stderr
@@ -0,0 +1,10 @@
+SCase82.hs:(12,14)-(16,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0 -> 10\n\
+      \               1 -> 20\n\
+      \               _ -> x\n\
+      \      "
+  ======>
+    ite ((.==) x 0) 10 (ite ((.==) x 1) 20 x)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE DataKinds   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Int16 integer literals, variable binding, and guard
+module T where
+
+import Data.SBV
+
+t :: SInt16 -> SInt16
+t x = [sCase| x of
+               0          -> 0
+               1          -> 100
+               n | n .> 0 -> n
+                 | sTrue   -> -n
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase83.stderr
@@ -0,0 +1,16 @@
+SCase83.hs:(12,14)-(17,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               0          -> 0\n\
+      \               1          -> 100\n\
+      \               n | n .> 0 -> n\n\
+      \                 | sTrue   -> -n\n\
+      \      "
+  ======>
+    ite
+      ((.==) x 0) 0
+      (ite
+         ((.==) x 1) 100
+         (ite
+            (let n = x in n .> 0) (let n = x in n) (let n = x in negate n)))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase Integer non-exhaustive (all guarded, no catch-all) — should fail
+module T where
+
+import Data.SBV
+
+t :: SInteger -> SBool
+t x = [sCase| x of
+               0 -> sTrue
+               1 -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase84.stderr
@@ -0,0 +1,14 @@
+SCase84.hs:11:14: error: [GHC-39584]
+    " SCase84.hs:12:16: sCase: Non-exhaustive pattern match.
+        All branches are guarded; add an unguarded wildcard or variable
+        as the last branch to ensure all cases are covered.
+
+    " In the quasi-quotation:
+        [sCase| x of
+               0 -> sTrue
+               1 -> sFalse
+      |]
+   |
+11 | t x = [sCase| x of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase Bool reversed order (False first, then True)
+module T where
+
+import Data.SBV
+
+t :: SBool -> SInteger
+t x = [sCase| x of
+               False -> 0
+               True  -> 1
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase85.stderr
@@ -0,0 +1,9 @@
+SCase85.hs:(11,14)-(14,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \               False -> 0\n\
+      \               True  -> 1\n\
+      \      "
+  ======>
+    ite (sNot x) 0 1
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE DataKinds   #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase with Word8 and mixed literal/variable/wildcard
+module T where
+
+import Data.SBV
+
+t :: SWord8 -> SWord8 -> SWord8
+t x y = [sCase| x of
+                 0         -> y
+                 n | n .> y -> n
+                   | sTrue  -> y
+        |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase86.stderr
@@ -0,0 +1,10 @@
+SCase86.hs:(12,16)-(16,10): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " x of\n\
+      \                 0         -> y\n\
+      \                 n | n .> y -> n\n\
+      \                   | sTrue  -> y\n\
+      \        "
+  ======>
+    ite ((.==) x 0) y (ite (let n = x in n .> y) (let n = x in n) y)
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase String non-exhaustive (only literals, no catch-all) — should fail
+module T where
+
+import Data.SBV
+
+t :: SString -> SInteger
+t s = [sCase| s of
+               "hello" -> 1
+               "world" -> 2
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase87.stderr
@@ -0,0 +1,14 @@
+SCase87.hs:11:14: error: [GHC-39584]
+    " SCase87.hs:12:16-22: sCase: Non-exhaustive pattern match.
+        All branches are guarded; add an unguarded wildcard or variable
+        as the last branch to ensure all cases are covered.
+
+    " In the quasi-quotation:
+        [sCase| s of
+               "hello" -> 1
+               "world" -> 2
+      |]
+   |
+11 | t s = [sCase| s of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.hs
@@ -0,0 +1,14 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Test: sCase Char non-exhaustive (only literals, no catch-all) — should fail
+module T where
+
+import Data.SBV
+
+t :: SChar -> SBool
+t c = [sCase| c of
+               'x' -> sTrue
+               'y' -> sFalse
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase88.stderr
@@ -0,0 +1,14 @@
+SCase88.hs:11:14: error: [GHC-39584]
+    " SCase88.hs:12:16-18: sCase: Non-exhaustive pattern match.
+        All branches are guarded; add an unguarded wildcard or variable
+        as the last branch to ensure all cases are covered.
+
+    " In the quasi-quotation:
+        [sCase| c of
+               'x' -> sTrue
+               'y' -> sFalse
+      |]
+   |
+11 | t c = [sCase| c of
+   |              ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+module T where
+
+import Expr
+import Data.SBV
+
+-- Dump test: nested pattern with user guard (combines nesting + guard accumulation)
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Add (Num i) b | i .> 0   -> i + t b
+                              | i .> -5  -> t b
+               Zero                      -> 0
+               Num i                     -> i
+               Var _                     -> 1
+               Let _ _ _                 -> 3
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase89.stderr
@@ -0,0 +1,43 @@
+SCase89.hs:(12,14)-(19,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Add (Num i) b | i .> 0   -> i + t b\n\
+      \                              | i .> -5  -> t b\n\
+      \               Zero                      -> 0\n\
+      \               Num i                     -> i\n\
+      \               Var _                     -> 1\n\
+      \               Let _ _ _                 -> 3\n\
+      \      "
+  ======>
+    ite
+      ((.&&)
+         (isAdd e)
+         ((\ _ b
+             -> const
+                  ((.&&)
+                     (isNum (getAdd_1 e)) (let i = getNum_1 (getAdd_1 e) in i .> 0))
+                  b)
+            (getAdd_1 e) (getAdd_2 e)))
+      ((\ _ b -> let i = getNum_1 (getAdd_1 e) in i + t b)
+         (getAdd_1 e) (getAdd_2 e))
+      (ite
+         ((.&&)
+            (isAdd e)
+            ((\ _ b
+                -> const
+                     ((.&&)
+                        (isNum (getAdd_1 e))
+                        (let i = getNum_1 (getAdd_1 e) in i .> negate 5))
+                     b)
+               (getAdd_1 e) (getAdd_2 e)))
+         ((\ _ b -> t b) (getAdd_1 e) (getAdd_2 e))
+         (ite
+            (isZero e) 0
+            (ite
+               (isNum e) ((\ i -> i) (getNum_1 e))
+               (ite
+                  (isVar e) ((\ _ -> 1) (getVar_1 e))
+                  (ite
+                     (isLet e) ((\ _ _ _ -> 3) (getLet_1 e) (getLet_2 e) (getLet_3 e))
+                     (symWithKind "unmatched_sCase_Expr_6989586621679080570"))))))
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Nested case expressions. Inner case on Maybe inside outer case on Expr.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero      -> case m of
+                               Nothing -> 0
+                               Just v  -> v
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase90.stderr
@@ -0,0 +1,16 @@
+SCase90.hs:(12,16)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                Zero      -> case m of\n\
+      \                               Nothing -> 0\n\
+      \                               Just v  -> v\n\
+      \                Num k     -> k\n\
+      \                Var _     -> -1\n\
+      \                Add a b   -> t a m + t b m\n\
+      \                Let _ _ b -> t b m\n\
+      \       "
+  ======>
+    sCaseExpr
+      (Data.SBV.Maybe.sCaseMaybe 0 (\ v -> v) m) (\ k -> k)
+      (\ _ -> negate 1) (\ a b -> (t a m) + t b m) (\ _ _ b -> t b m) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Same-type nesting. Inner case on Expr inside outer case on Expr.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SInteger
+t e = [sCase| e of
+               Zero      -> 0
+               Num k     -> k
+               Var _     -> -1
+               Add a b   -> case a of
+                              Zero    -> t b
+                              Num k   -> k + t b
+                              Var _   -> t b
+                              Add _ _ -> t a + t b
+                              Let _ _ c -> t c + t b
+               Let _ _ b -> t b
+      |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase91.stderr
@@ -0,0 +1,23 @@
+SCase91.hs:(12,14)-(23,8): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \               Zero      -> 0\n\
+      \               Num k     -> k\n\
+      \               Var _     -> -1\n\
+      \               Add a b   -> case a of\n\
+      \                              Zero    -> t b\n\
+      \                              Num k   -> k + t b\n\
+      \                              Var _   -> t b\n\
+      \                              Add _ _ -> t a + t b\n\
+      \                              Let _ _ c -> t c + t b\n\
+      \               Let _ _ b -> t b\n\
+      \      "
+  ======>
+    sCaseExpr
+      0 (\ k -> k) (\ _ -> negate 1)
+      (\ a b
+         -> sCaseExpr
+              (t b) (\ k -> k + t b) (\ _ -> t b) (\ _ _ -> (t a) + t b)
+              (\ _ _ c -> (t c) + t b) a)
+      (\ _ _ b -> t b) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Deep nesting (3 levels). Outer Expr, inner Maybe, innermost Either.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe (Either Integer Bool) -> SInteger
+t e m = [sCase| e of
+                Zero  -> case m of
+                           Nothing -> 0
+                           Just v  -> case v of
+                                        Left  x -> x
+                                        Right _ -> 1
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase92.stderr
@@ -0,0 +1,20 @@
+SCase92.hs:(12,16)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                Zero  -> case m of\n\
+      \                           Nothing -> 0\n\
+      \                           Just v  -> case v of\n\
+      \                                        Left  x -> x\n\
+      \                                        Right _ -> 1\n\
+      \                Num k     -> k\n\
+      \                Var _     -> -1\n\
+      \                Add a b   -> t a m + t b m\n\
+      \                Let _ _ b -> t b m\n\
+      \       "
+  ======>
+    sCaseExpr
+      (Data.SBV.Maybe.sCaseMaybe
+         0 (\ v -> Data.SBV.Either.sCaseEither (\ x -> x) (\ _ -> 1) v) m)
+      (\ k -> k) (\ _ -> negate 1) (\ a b -> (t a m) + t b m)
+      (\ _ _ b -> t b m) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Nested case in multiple branches of outer case.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SBool -> SInteger
+t e b = [sCase| e of
+                Zero      -> case b of
+                               True  -> 1
+                               False -> 0
+                Num k     -> case b of
+                               True  -> k
+                               False -> -k
+                Var _     -> -1
+                Add a _   -> t a b
+                Let _ _ c -> t c b
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase93.stderr
@@ -0,0 +1,18 @@
+SCase93.hs:(12,16)-(22,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                Zero      -> case b of\n\
+      \                               True  -> 1\n\
+      \                               False -> 0\n\
+      \                Num k     -> case b of\n\
+      \                               True  -> k\n\
+      \                               False -> -k\n\
+      \                Var _     -> -1\n\
+      \                Add a _   -> t a b\n\
+      \                Let _ _ c -> t c b\n\
+      \       "
+  ======>
+    sCaseExpr
+      (ite b 1 0) (\ k -> ite b k (negate k)) (\ _ -> negate 1)
+      (\ a _ -> t a b) (\ _ _ c -> t c b) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Nested case with wildcard in inner case.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero  -> case m of
+                           Just v -> v
+                           _      -> 0
+                Num k     -> k
+                _         -> case m of
+                               Nothing -> -1
+                               _       -> 42
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase94.stderr
@@ -0,0 +1,18 @@
+SCase94.hs:(12,16)-(20,9): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                Zero  -> case m of\n\
+      \                           Just v -> v\n\
+      \                           _      -> 0\n\
+      \                Num k     -> k\n\
+      \                _         -> case m of\n\
+      \                               Nothing -> -1\n\
+      \                               _       -> 42\n\
+      \       "
+  ======>
+    sCaseExpr
+      (Data.SBV.Maybe.sCaseMaybe 0 (\ v -> v) m) (\ k -> k)
+      (\ _ -> Data.SBV.Maybe.sCaseMaybe (negate 1) (\ _ -> 42) m)
+      (\ _ _ -> Data.SBV.Maybe.sCaseMaybe (negate 1) (\ _ -> 42) m)
+      (\ _ _ _ -> Data.SBV.Maybe.sCaseMaybe (negate 1) (\ _ -> 42) m) e
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Negative: Non-exhaustive inner case (missing Nothing).
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero      -> case m of
+                               Just v -> v
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase95.stderr
@@ -0,0 +1,21 @@
+SCase95.hs:12:16: error: [GHC-39584]
+    " sCase: Pattern match(es) are non-exhaustive.
+        Not matched     : Nothing
+        Patterns of type: Maybe
+        Must match each : Nothing, Just
+
+      You can use a '_' to match multiple cases.
+
+    " In the quasi-quotation:
+        [sCase| e of
+                Zero      -> case m of
+                               Just v -> v
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
+   |
+12 | t e m = [sCase| e of
+   |                ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Negative: Overlapping patterns in inner case (duplicate Just).
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero      -> case m of
+                               Nothing -> 0
+                               Just v  -> v
+                               Just _  -> 42
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase96.stderr
@@ -0,0 +1,22 @@
+SCase96.hs:12:16: error: [GHC-39584]
+    " sCase: Overlapping case constructors:
+        Type       : Maybe
+        Constructor: Just _
+      Overlaps with:
+        SCase96.hs:(12,16)-(21,10): Just v
+
+    " In the quasi-quotation:
+        [sCase| e of
+                Zero      -> case m of
+                               Nothing -> 0
+                               Just v  -> v
+                               Just _  -> 42
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
+   |
+12 | t e m = [sCase| e of
+   |                ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Negative: Inner case on ADT without mkSymbolic.
+module T where
+
+import Expr
+import Data.SBV
+
+data Color = Red | Green | Blue
+
+t :: SExpr -> Color -> SInteger
+t e c = [sCase| e of
+                Zero      -> case c of
+                               Red   -> 0
+                               Green -> 1
+                               Blue  -> 2
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a c + t b c
+                Let _ _ b -> t b c
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase97.stderr
@@ -0,0 +1,17 @@
+SCase97.hs:14:16: error: [GHC-79890]
+    " Red is not in the type environment at a reify
+    " In the quasi-quotation:
+        [sCase| e of
+                Zero      -> case c of
+                               Red   -> 0
+                               Green -> 1
+                               Blue  -> 2
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a c + t b c
+                Let _ _ b -> t b c
+       |]
+   |
+14 | t e c = [sCase| e of
+   |                ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Negative: Non-exhaustive guarded inner case (missing Nothing, guard might fail).
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe Integer -> SInteger
+t e m = [sCase| e of
+                Zero      -> case m of
+                               Just v | v .> 0 -> v
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase98.stderr
@@ -0,0 +1,19 @@
+SCase98.hs:12:16: error: [GHC-39584]
+    " sCase: Non-exhaustive match:
+        Type       : Maybe
+        Constructor: Just v | v .> 0
+      NB. Guarded match might fail.
+
+    " In the quasi-quotation:
+        [sCase| e of
+                Zero      -> case m of
+                               Just v | v .> 0 -> v
+                Num k     -> k
+                Var _     -> -1
+                Add a b   -> t a m + t b m
+                Let _ _ b -> t b m
+       |]
+   |
+12 | t e m = [sCase| e of
+   |                ^^^^^...
+
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.hs b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE QuasiQuotes #-}
+
+{-# OPTIONS_GHC -Wall -Werror -ddump-splices #-}
+
+-- Positive: Deep nesting (4 levels). Outer Expr, inner Maybe, inner Either, innermost Bool.
+module T where
+
+import Expr
+import Data.SBV
+
+t :: SExpr -> SMaybe (Either Integer Bool) -> SBool -> SInteger
+t e m b = [sCase| e of
+                  Zero      -> case m of
+                                 Nothing -> 0
+                                 Just v  -> case v of
+                                              Left x  -> case b of
+                                                           True  -> x
+                                                           False -> -x
+                                              Right _ -> 1
+                  Num k     -> k
+                  Var _     -> -1
+                  Add a _   -> t a m b
+                  Let _ _ c -> t c m b
+         |]
diff --git a/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.stderr b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.stderr
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/CompileTests/SCase/SCase99.stderr
@@ -0,0 +1,26 @@
+SCase99.hs:(12,18)-(24,11): Splicing expression
+    ghc-internal:GHC.Internal.TH.Quote.quoteExp
+      sCase
+      " e of\n\
+      \                  Zero      -> case m of\n\
+      \                                 Nothing -> 0\n\
+      \                                 Just v  -> case v of\n\
+      \                                              Left x  -> case b of\n\
+      \                                                           True  -> x\n\
+      \                                                           False -> -x\n\
+      \                                              Right _ -> 1\n\
+      \                  Num k     -> k\n\
+      \                  Var _     -> -1\n\
+      \                  Add a _   -> t a m b\n\
+      \                  Let _ _ c -> t c m b\n\
+      \         "
+  ======>
+    sCaseExpr
+      (Data.SBV.Maybe.sCaseMaybe
+         0
+         (\ v
+            -> Data.SBV.Either.sCaseEither
+                 (\ x -> ite b x (negate x)) (\ _ -> 1) v)
+         m)
+      (\ k -> k) (\ _ -> negate 1) (\ a _ -> t a m b)
+      (\ _ _ c -> t c m b) e
diff --git a/SBVTestSuite/TestSuite/Crypto/AES.hs b/SBVTestSuite/TestSuite/Crypto/AES.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Crypto/AES.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Crypto.AES
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Crypto.AES
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Crypto.AES(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.Crypto.AES
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Crypto.AES" [
+   goldenVsStringShow "aes128Enc" $ thd <$> compileToC'    "aes128Enc" (aes128EncDec True)
+ , goldenVsStringShow "aes128Dec" $ thd <$> compileToC'    "aes128Dec" (aes128EncDec False)
+ , goldenVsStringShow "aes128Lib" $ thd <$> compileToCLib' "aes128Lib" aes128Comps
+ ]
+ where aes128EncDec d = do pt  <- cgInputArr 4 "pt"
+                           key <- cgInputArr 4 "key"
+                           cgSetDriverValues $ repeat 0
+                           let (encKs, decKs) = aesKeySchedule key
+                               res | d    = aesEncrypt pt encKs
+                                   | True = aesDecrypt pt decKs
+                           cgOutputArr "ct" res
+       aes128Comps = [(f, setVals c) | (f, _, c) <- aesLibComponents 128]
+       setVals c = cgSetDriverValues (repeat 0) >> c
+       thd (_, _, r) = r
diff --git a/SBVTestSuite/TestSuite/Crypto/RC4.hs b/SBVTestSuite/TestSuite/Crypto/RC4.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Crypto/RC4.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Crypto.RC4
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Crypto.RC4
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Crypto.RC4(tests) where
+
+import Data.SBV.Tools.STree
+import Documentation.SBV.Examples.Crypto.RC4
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Crypto.RC4"
+    [ testCase "rc4swap" (assertIsThm readWrite)
+    ]
+
+readWrite :: SBV Word8 -> SBV Word8 -> SBV Bool
+readWrite i j = readSTree (writeSTree initS i j) i .== j
diff --git a/SBVTestSuite/TestSuite/Crypto/SHA.hs b/SBVTestSuite/TestSuite/Crypto/SHA.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Crypto/SHA.hs
@@ -0,0 +1,41 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Crypto.SHA
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Crypto.SHA
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Crypto.SHA(tests) where
+
+import Data.SBV.Internals
+import Documentation.SBV.Examples.Crypto.SHA
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Crypto.AES" [
+   goldenVsStringShow "sha256HashBlock" $ (\(_, _, r) -> r) <$> compileToC' "sha256HashBlock" c
+ ]
+ where c = do let algorithm = sha256P
+
+              hInBytes   <- cgInputArr 32 "hIn"
+              blockBytes <- cgInputArr 64 "block"
+
+              let hIn   = chunkBy 4 fromBytes hInBytes
+                  block = chunkBy 4 fromBytes blockBytes
+
+                  result = hashBlock algorithm hIn (Block block)
+
+              cgOutputArr "hash" $ concatMap toBytes result
+
+              -- Use known test values for the empty string input so we get a meaningful driver
+              let msgWords = concat [xs | Block xs <- prepareMessage algorithm "SBV goes SHA256!!"]
+              cgShowU8UsingHex True
+              cgSetDriverValues [fromIntegral x | Just x <- map unliteral (concatMap toBytes (h0 algorithm ++ msgWords))]
diff --git a/SBVTestSuite/TestSuite/GenTest/GenTests.hs b/SBVTestSuite/TestSuite/GenTest/GenTests.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/GenTest/GenTests.hs
@@ -0,0 +1,34 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.GenTest.GenTests
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test-suite for generating tests
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.GenTest.GenTests(tests) where
+
+import Data.SBV.Tools.GenTest
+
+import System.Random
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "GenTest.GenTests"
+   [ goldenCapturedIO "tgen_haskell" $ render (Haskell "haskTest")
+   , goldenCapturedIO "tgen_c"       $ render (C       "CTest")
+   , goldenCapturedIO "tgen_forte"   $ render (Forte   "ForteTest" True ([32,32], [32,32,32]))
+   ]
+ where simple = genTest 10 $ do x <- sWord32 "x"
+                                y <- sWord32 "y"
+                                return (x+y, x-y, x*y)
+       render s f = do setStdGen (mkStdGen 0)  -- make sure we always get the same results!
+                       r <- renderTest s <$> simple
+                       writeFile f r
diff --git a/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs b/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs
@@ -0,0 +1,52 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.AssertWithPenalty
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, soft assertions
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.AssertWithPenalty(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.AssertWithPenalty"
+    [ goldenVsStringShow "assertWithPenalty1" (optimize Lexicographic assertWithPenalty1)
+    , goldenVsStringShow "assertWithPenalty2" (optimize Lexicographic assertWithPenalty2)
+    ]
+
+assertWithPenalty1 :: ConstraintSet
+assertWithPenalty1 = do
+                 x <- sInteger "x"
+                 y <- sInteger "y"
+
+                 let a1 = x .> 0
+                     a2 = x .< y
+                     a3 = x+y .<= 0
+
+                 constrain $ a1 .== a3
+                 constrain $ a3 .|| a2
+
+                 assertWithPenalty "as1" a3        (Penalty  3 Nothing)
+                 assertWithPenalty "as2" (sNot a3) (Penalty  5 Nothing)
+                 assertWithPenalty "as3" (sNot a1) (Penalty 10 Nothing)
+                 assertWithPenalty "as4" (sNot a2) (Penalty  3 Nothing)
+
+assertWithPenalty2 :: ConstraintSet
+assertWithPenalty2 = do
+                 a1 <- sBool "a1"
+                 a2 <- sBool "a2"
+                 a3 <- sBool "a3"
+
+                 assertWithPenalty "as_a1" a1                    (Penalty  0.1 Nothing)
+                 assertWithPenalty "as_a2" a2                    (Penalty  1.0 Nothing)
+                 assertWithPenalty "as_a3" a3                    (Penalty  1   Nothing)
+                 assertWithPenalty "as_a4" (sNot a1 .|| sNot a2) (Penalty 3.2 Nothing)
diff --git a/SBVTestSuite/TestSuite/Optimization/Basics.hs b/SBVTestSuite/TestSuite/Optimization/Basics.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Basics.hs
@@ -0,0 +1,85 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Basics
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.Basics(tests) where
+
+import Utils.SBVTestFramework
+import Data.SBV.Control
+
+import Control.Monad
+
+import qualified Control.Exception as C
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Basics" $
+       [ goldenVsStringShow "optBasics1" (optimize Lexicographic optBasics1)
+       , goldenVsStringShow "optBasics2" (optimize Lexicographic optBasics2)
+       , goldenCapturedIO   "qOpt_1"     (qOpt False)
+       , goldenCapturedIO   "qOpt_2"     (qOpt True)
+       ]
+    ++ [ goldenVsStringShow ("optBasicsRange_" ++ n) (optimize Lexicographic f)
+       | (n, f) <- [ ("08_unsigned_max", sWord8  "x" >>= maximize "m")
+                   , ("08_unsigned_min", sWord8  "x" >>= minimize "m")
+                   , ("16_unsigned_max", sWord16 "x" >>= maximize "m")
+                   , ("16_unsigned_min", sWord16 "x" >>= minimize "m")
+                   , ("32_unsigned_max", sWord32 "x" >>= maximize "m")
+                   , ("32_unsigned_min", sWord32 "x" >>= minimize "m")
+                   , ("64_unsigned_max", sWord64 "x" >>= maximize "m")
+                   , ("64_unsigned_min", sWord64 "x" >>= minimize "m")
+                   , ("08_signed_max",   sInt8   "x" >>= maximize "m")
+                   , ("08_signed_min",   sInt8   "x" >>= minimize "m")
+                   , ("16_signed_max",   sInt16  "x" >>= maximize "m")
+                   , ("16_signed_min",   sInt16  "x" >>= minimize "m")
+                   , ("32_signed_max",   sInt32  "x" >>= maximize "m")
+                   , ("32_signed_min",   sInt32  "x" >>= minimize "m")
+                   , ("64_signed_max",   sInt64  "x" >>= maximize "m")
+                   , ("64_signed_min",   sInt64  "x" >>= minimize "m")
+                   ]
+       ]
+
+optBasics1 :: ConstraintSet
+optBasics1 = do x <- sInteger "x"
+                y <- sInteger "y"
+
+                constrain $ x .< 2
+                constrain $ y - x .< 1
+
+                maximize "x_plus_y" $ x+y
+
+optBasics2 :: ConstraintSet
+optBasics2 = do x <- sInteger "x"
+                y <- sInteger "y"
+
+                constrain $ x .< 4
+                constrain $ y - x .< 1
+                constrain $ y .> 1
+
+                minimize "x_plus_y" $ x+y
+
+qOpt :: Bool -> FilePath -> IO ()
+qOpt mb rf = testQuery $ do
+                vs <- forM [1 .. 5] $ \i -> do x <- sInteger ("x" <> show (i::Int))
+                                               constrain $ 1 .<= x
+                                               when mb $ constrain $ x .< 10
+                                               maximize ("goal" <> show i) x
+                                               pure x
+                query $ do cs <- checkSat
+                           case cs of
+                             Sat -> forM vs getValue
+                             _   -> pure []
+ where testQuery fv = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} fv
+                         appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+                      `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\nEXCEPTION CAUGHT:\n" ++ show e ++ "\n"))
diff --git a/SBVTestSuite/TestSuite/Optimization/Combined.hs b/SBVTestSuite/TestSuite/Optimization/Combined.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Combined.hs
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Combined
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, combined objectives
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.Combined(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Combined"
+    [ goldenVsStringShow "combined1" (optimize Lexicographic      combined1)
+    , goldenVsStringShow "combined2" (optimize Lexicographic      combined2)
+    , goldenVsStringShow "pareto1"   (optimize (Pareto Nothing)   pareto1)
+    , goldenVsStringShow "pareto2"   (optimize (Pareto (Just 30)) pareto2)
+    , goldenVsStringShow "pareto3"   (optimize (Pareto Nothing)   pareto3)
+    ]
+
+combined1 :: ConstraintSet
+combined1 = do x <- sInteger "x"
+               y <- sInteger "y"
+               z <- sInteger "z"
+
+               constrain $ x .< z
+               constrain $ y .< z
+               constrain $ z .< 5
+               constrain $ x ./= y
+
+               maximize "max_x" x
+               maximize "max_y" y
+
+combined2 :: ConstraintSet
+combined2 = do a <- sBool "a"
+               b <- sBool "b"
+               c <- sBool "c"
+
+               assertWithPenalty "soft_a" a (Penalty 1 (Just "A"))
+               assertWithPenalty "soft_b" b (Penalty 2 (Just "B"))
+               assertWithPenalty "soft_c" c (Penalty 3 (Just "A"))
+
+               constrain $ a .== c
+               constrain $ sNot (a .&& b)
+
+pareto1 :: ConstraintSet
+pareto1 = do x <- sInteger "x"
+             y <- sInteger "y"
+
+             constrain $ 5 .>= x
+             constrain $ x .>= 0
+             constrain $ 4 .>= y
+             constrain $ y .>= 0
+
+             minimize "min_x"            x
+             maximize "max_x_plus_y"   $ x + y
+             minimize "min_y"            y
+
+pareto2 :: ConstraintSet
+pareto2 = do x <- sInteger "x"
+             y <- sInteger "y"
+
+             constrain $ 5 .>= x
+             constrain $ x .>= 0
+
+             minimize "min_x"            x
+             maximize "max_y"            y
+             minimize "max_x_plus_y"   $ x + y
+
+pareto3 :: ConstraintSet
+pareto3 = do x <- sInteger "x"
+
+             constrain $ 1 .>= x
+             constrain $ 0 .<= x
+
+             minimize "min_x"            x
+             maximize "max_x_plus_x"   $ x + x
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs b/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs
@@ -0,0 +1,55 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.ExtensionField
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, extension field
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.ExtensionField(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.ExtensionField"
+    [ goldenVsStringShow "optExtField1" (optimize Lexicographic optExtField1)
+    , goldenVsStringShow "optExtField2" (optimize Lexicographic optExtField2)
+    , goldenVsStringShow "optExtField3" (optimize Lexicographic optExtField3)
+    ]
+
+optExtField1 :: ConstraintSet
+optExtField1 = do x <- sInteger "x"
+                  y <- sInteger "y"
+
+                  constrain $ x .< 4
+                  constrain $ y - x .> 1
+
+                  maximize "x_plus_y" $ x+y
+
+optExtField2 :: ConstraintSet
+optExtField2 = do x <- sInteger "x"
+                  y <- sInteger "y"
+
+                  constrain $ x .< 4
+                  constrain $ y - x .< 1
+                  constrain $ y .< 1
+
+                  minimize "x_plus_y" $ x+y
+
+optExtField3 :: ConstraintSet
+optExtField3 = do x <- sReal "x"
+                  y <- sReal "y"
+
+                  constrain $ x .<= 4
+                  constrain $ y .<= 5
+
+                  maximize "x_plus_y" $ x + y
+
+{- HLint ignore module "Reduce duplication" -}
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,74 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Floats
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, floats
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.Floats (tests) where
+
+import Control.Monad (when)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Floats"
+    [ goldenVsStringShow "optFloat1a" $ optimizeWith z3{crackNum=True} Lexicographic (floatMinMax  (minimize "min-x") True)
+    , goldenVsStringShow "optFloat1b" $ optimizeWith z3{crackNum=True} Lexicographic (floatMinMax  (minimize "min-x") False)
+    , goldenVsStringShow "optFloat1c" $ optimizeWith z3{crackNum=True} Lexicographic (floatMinMax  (maximize "max-x") True)
+    , goldenVsStringShow "optFloat1d" $ optimizeWith z3{crackNum=True} Lexicographic (floatMinMax  (maximize "max-y") False)
+    , goldenVsStringShow "optFloat2a" $ optimizeWith z3{crackNum=True} Lexicographic (doubleMinMax (minimize "min-x") True)
+    , goldenVsStringShow "optFloat2b" $ optimizeWith z3{crackNum=True} Lexicographic (doubleMinMax (minimize "min-x") False)
+    , goldenVsStringShow "optFloat2c" $ optimizeWith z3{crackNum=True} Lexicographic (doubleMinMax (maximize "max-x") True)
+    , goldenVsStringShow "optFloat2d" $ optimizeWith z3{crackNum=True} Lexicographic (doubleMinMax (maximize "max-y") False)
+    , goldenVsStringShow "optFloat3"  $ optimizeWith z3{crackNum=True} Lexicographic q
+    , goldenVsStringShow "optFloat4"  $ optimizeWith z3{crackNum=True} Lexicographic r
+    ]
+
+floatMinMax :: (SFloat -> Symbolic ()) -> Bool -> ConstraintSet
+floatMinMax opt reqPoint = do x <- sFloat "x"
+
+                              when reqPoint $ constrain $ fpIsPoint x
+
+                              opt x
+
+doubleMinMax :: (SDouble -> Symbolic ()) -> Bool -> ConstraintSet
+doubleMinMax opt reqPoint = do x <- sDouble "x"
+
+                               when reqPoint $ constrain $ fpIsPoint x
+
+                               opt x
+
+q :: ConstraintSet
+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 :: ConstraintSet
+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)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Optimization/NoOpt.hs b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.NoOpt
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Check that if optimization is done, there must be goals and vice versa
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.NoOpt(tests) where
+
+import qualified Control.Exception as C
+
+import Control.Monad (void)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.NoOpt"
+       [ goldenCapturedIO "noOpt1" $ \rf -> c rf $ optimizeWith z3{verbose=True, redirectVerbose=Just rf} Lexicographic (\x -> x .== (x::SWord8))
+       , goldenCapturedIO "noOpt2" $ \rf -> c rf $ satWith      z3{verbose=True, redirectVerbose=Just rf}               (\x -> maximize "mx" (x::SWord8))
+       ]
+ where c rf cont = void cont `C.catch` (\(e :: C.SomeException) -> appendFile rf ("\n\n" ++ show e))
diff --git a/SBVTestSuite/TestSuite/Optimization/Quantified.hs b/SBVTestSuite/TestSuite/Optimization/Quantified.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Quantified.hs
@@ -0,0 +1,78 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Quantified
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization with quantifiers
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module TestSuite.Optimization.Quantified(tests) where
+
+import Data.List (isPrefixOf)
+
+import Utils.SBVTestFramework
+import qualified Control.Exception as C
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Reals"
+    [ goldenVsStringShow "optQuant1" $ opt  q1
+    , goldenVsStringShow "optQuant2" $ opt  q2
+    , goldenVsStringShow "optQuant3" $ opt  q3
+    , goldenVsStringShow "optQuant4" $ opt  q4
+    , goldenString       "optQuant5" $ optE q5
+    ]
+    where opt    = optimize Lexicographic
+          optE q = (show <$> optimize Lexicographic q) `C.catch` (\(e::C.SomeException) -> return (pick (show e)))
+          pick s = unlines [l | l <- lines s, "***" `isPrefixOf` l]
+
+q1 :: ConstraintSet
+q1 = do a <- sInteger "a"
+        [b1, b2] <- sIntegers ["b1", "b2"]
+        constrain $ \(Forall x) ->     2 * (a * x + b1) .== 2
+                                   .&& 4 * (a * x + b2) .== 4
+        constrain $ a .>= 0
+        minimize "goal" $ 2*a
+
+q2 :: ConstraintSet
+q2 = do a <- sInteger "a"
+        [b1, b2] <- sIntegers ["b1", "b2"]
+        constrain $ \(Forall x) ->     2 * (a * x + b1) .== 2
+                                   .&& 4 * (a * x + b2) .== 4
+                                   .&& a .>= 0
+        minimize "goal" a
+
+q3 :: ConstraintSet
+q3 = do a <- sInteger "a"
+        [b1, b2] <- sIntegers ["b1", "b2"]
+        minimize "goal" a
+        constrain $ \(Forall x) ->     2 * (a * x + b1) .== 2
+                                   .&& 4 * (a * x + b2) .== 4
+        constrain $ a .>= 0
+
+q4 :: ConstraintSet
+q4 = do a <- sInteger "a"
+        [b1, b2] <- sIntegers ["b1", "b2"]
+        minimize "goal" $ 2*a
+        constrain $ \(Forall x) ->     2 * (a * x + b1) .== 2
+                                   .&& 4 * (a * x + b2) .== 4
+        constrain $ a .>= 0
+
+q5 :: ConstraintSet
+q5 = do a <- sInteger "a"
+        constrain $ \(Exists y) -> a .>= (y :: SInteger)
+        constrain $ a .>= 0
+        b <- sInteger "b"
+        constrain $ b .>= 0
+        minimize "goal" $ a+b
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Optimization/Reals.hs b/SBVTestSuite/TestSuite/Optimization/Reals.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Reals.hs
@@ -0,0 +1,40 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Reals
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, reals
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Optimization.Reals(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Reals"
+    [ goldenVsStringShow "optReal1" (optimize Lexicographic p)
+    ]
+
+p :: ConstraintSet
+p = do x <- sReal "x"
+       y <- sReal "y"
+       z <- sReal "z"
+       w <- sReal "w"
+
+       constrain $ x .>= 0
+       constrain $ y .>= 0
+       constrain $ z .>= 0
+       constrain $ w .>= 0
+
+       constrain $ x + y + z + w .<= 40
+       constrain $ 2 * x + y - z - w .>= 10
+       constrain $ w - y .>= 10
+
+       maximize "p" $ 0.5 * x + 3 * y + z + 4 * w
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,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Tuples
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, tuples
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables  #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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 :: ConstraintSet
+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
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Overflows/Arithmetic.hs
@@ -0,0 +1,207 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Overflows.Arithmetic
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for overflow checking
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE TypeOperators       #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Overflows.Arithmetic(tests) where
+
+import Data.SBV
+import Data.SBV.Dynamic
+import Data.SBV.Internals (unSBV, SBV(..), SymVal(minMaxBound))
+
+import Data.SBV.Tools.Overflow
+
+import Data.Proxy
+import GHC.TypeLits
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Overflows" [testGroup "Arithmetic" ts]
+  where ts = [ testGroup "add-ov" [ testCase "w8"  $ assertIsThm $ overflow  svPlus   (bvAddO :: SWord8  -> SWord8  -> SBool)
+                                  , testCase "w16" $ assertIsThm $ overflow  svPlus   (bvAddO :: SWord16 -> SWord16 -> SBool)
+                                  , testCase "w32" $ assertIsThm $ overflow  svPlus   (bvAddO :: SWord32 -> SWord32 -> SBool)
+                                  , testCase "w64" $ assertIsThm $ overflow  svPlus   (bvAddO :: SWord64 -> SWord64 -> SBool)
+                                  , testCase "i8"  $ assertIsThm $ overflow  svPlus   (bvAddO :: SInt8   -> SInt8   -> SBool)
+                                  , testCase "i16" $ assertIsThm $ overflow  svPlus   (bvAddO :: SInt16  -> SInt16  -> SBool)
+                                  , testCase "i32" $ assertIsThm $ overflow  svPlus   (bvAddO :: SInt32  -> SInt32  -> SBool)
+                                  , testCase "i64" $ assertIsThm $ overflow  svPlus   (bvAddO :: SInt64  -> SInt64  -> SBool)
+                                  ]
+
+             , testGroup "sub-ov" [ testCase "w8"  $ assertIsThm $ overflow  svMinus  (bvSubO :: SWord8  -> SWord8  -> SBool)
+                                  , testCase "w16" $ assertIsThm $ overflow  svMinus  (bvSubO :: SWord16 -> SWord16 -> SBool)
+                                  , testCase "w32" $ assertIsThm $ overflow  svMinus  (bvSubO :: SWord32 -> SWord32 -> SBool)
+                                  , testCase "w64" $ assertIsThm $ overflow  svMinus  (bvSubO :: SWord64 -> SWord64 -> SBool)
+                                  , testCase "i8"  $ assertIsThm $ overflow  svMinus  (bvSubO :: SInt8   -> SInt8   -> SBool)
+                                  , testCase "i16" $ assertIsThm $ overflow  svMinus  (bvSubO :: SInt16  -> SInt16  -> SBool)
+                                  , testCase "i32" $ assertIsThm $ overflow  svMinus  (bvSubO :: SInt32  -> SInt32  -> SBool)
+                                  , testCase "i64" $ assertIsThm $ overflow  svMinus  (bvSubO :: SInt64  -> SInt64  -> SBool)
+                                  ]
+
+             -- Multiplication checks are expensive for z3; so only do at a few instances with z3
+             , testGroup "mul-ov" [ testCase "w8"  $ assertIsThm $ overflow  svTimes  (bvMulO :: SWord8  -> SWord8  -> SBool)
+                                  , testCase "w16" $ assertIsThm $ overflow  svTimes  (bvMulO :: SWord16 -> SWord16 -> SBool)
+                                  -- , testCase "w32" $ assertIsThm $ overflow  svTimes  (bvMulO :: SWord32 -> SWord32 -> SBool)
+                                  -- , testCase "w64" $ assertIsThm $ overflow  svTimes  (bvMulO :: SWord64 -> SWord64 -> SBool)
+                                  , testCase "i8"  $ assertIsThm $ overflow  svTimes  (bvMulO :: SInt8   -> SInt8   -> SBool)
+                                  -- , testCase "i16" $ assertIsThm $ overflow  svTimes  (bvMulO :: SInt16  -> SInt16  -> SBool)
+                                  -- , testCase "i32" $ assertIsThm $ overflow  svTimes  (bvMulO :: SInt32  -> SInt32  -> SBool)
+                                  -- , testCase "i64" $ assertIsThm $ overflow  svTimes  (bvMulO :: SInt64  -> SInt64  -> SBool)
+                                  ]
+
+             -- Another group of multiplication overflow tests for signed-multiplication, using bitwuzla
+             , testGroup "mul-special"
+                                 [ testCase "smov1_int"  $ assert $ smulCheck (Proxy @1)  True
+                                 , testCase "smov1_txt"  $ assert $ smulCheck (Proxy @1)  False
+                                 , testCase "smov2_int"  $ assert $ smulCheck (Proxy @2)  True
+                                 , testCase "smov2_txt"  $ assert $ smulCheck (Proxy @2)  False
+                                 , testCase "smov3_int"  $ assert $ smulCheck (Proxy @3)  True
+                                 , testCase "smov3_txt"  $ assert $ smulCheck (Proxy @3)  False
+                                 , testCase "smov4_int"  $ assert $ smulCheck (Proxy @4)  True
+                                 , testCase "smov4_txt"  $ assert $ smulCheck (Proxy @4)  False
+                                 , testCase "smov5_int"  $ assert $ smulCheck (Proxy @5)  True
+                                 , testCase "smov5_txt"  $ assert $ smulCheck (Proxy @5)  False
+                                 , testCase "smov6_int"  $ assert $ smulCheck (Proxy @6)  True
+                                 , testCase "smov6_txt"  $ assert $ smulCheck (Proxy @6)  False
+                                 , testCase "smov7_int"  $ assert $ smulCheck (Proxy @7)  True
+                                 , testCase "smov7_txt"  $ assert $ smulCheck (Proxy @7)  False
+                                 , testCase "smov8_int"  $ assert $ smulCheck (Proxy @8)  True
+                                 , testCase "smov8_txt"  $ assert $ smulCheck (Proxy @8)  False
+                                 -- After this, text-book checks take long; so we just check against internal
+                                 , testCase "smov24_int" $ assert $ smulCheck (Proxy @24) True
+                                 , testCase "smov32_int" $ assert $ smulCheck (Proxy @32) True
+                                 , testCase "smov64_int" $ assert $ smulCheck (Proxy @64) True
+                                 ]
+
+             , testGroup "div-ov" [ testCase "w8"  $ assertIsThm $ never     svDivide (bvDivO :: SWord8  -> SWord8  -> SBool)
+                                  , testCase "w16" $ assertIsThm $ never     svDivide (bvDivO :: SWord16 -> SWord16 -> SBool)
+                                  , testCase "w32" $ assertIsThm $ never     svDivide (bvDivO :: SWord32 -> SWord32 -> SBool)
+                                  , testCase "w64" $ assertIsThm $ never     svDivide (bvDivO :: SWord64 -> SWord64 -> SBool)
+                                  , testCase "i8"  $ assertIsThm $ overflow  svDivide (bvDivO :: SInt8   -> SInt8   -> SBool)
+                                  , testCase "i16" $ assertIsThm $ overflow  svDivide (bvDivO :: SInt16  -> SInt16  -> SBool)
+                                  , testCase "i32" $ assertIsThm $ overflow  svDivide (bvDivO :: SInt32  -> SInt32  -> SBool)
+                                  , testCase "i64" $ assertIsThm $ overflow  svDivide (bvDivO :: SInt64  -> SInt64  -> SBool)
+                                  ]
+
+             , testGroup "neg-ov" [ testCase "w8"  $ assertIsThm $ never1    svNeg0   (bvNegO :: SWord8  -> SBool)
+                                  , testCase "w16" $ assertIsThm $ never1    svNeg0   (bvNegO :: SWord16 -> SBool)
+                                  , testCase "w32" $ assertIsThm $ never1    svNeg0   (bvNegO :: SWord32 -> SBool)
+                                  , testCase "w64" $ assertIsThm $ never1    svNeg0   (bvNegO :: SWord64 -> SBool)
+                                  , testCase "i8"  $ assertIsThm $ overflow1 svNeg0   (bvNegO :: SInt8   -> SBool)
+                                  , testCase "i16" $ assertIsThm $ overflow1 svNeg0   (bvNegO :: SInt16  -> SBool)
+                                  , testCase "i32" $ assertIsThm $ overflow1 svNeg0   (bvNegO :: SInt32  -> SBool)
+                                  , testCase "i64" $ assertIsThm $ overflow1 svNeg0   (bvNegO :: SInt64  -> SBool)
+                                  ]
+             ]
+
+-- 128 bits is large enough to do all these proofs
+large :: Int
+large = 128
+
+type SLarge = SVal
+
+svNeg0 :: SLarge -> SLarge
+svNeg0 v = z `svMinus` v
+  where z = svInteger (KBounded (hasSign v) large) 0
+
+exactlyWhen :: SBool -> SVal -> SBool
+exactlyWhen (SBV a) b = SBV $ (a `svAnd` b) `svOr` (svNot a `svAnd` svNot b)
+
+-- Properly extend to a dynamic signed large vector. This works because we grow to 256 bits, which is high enough.
+toLarge :: HasKind a => SBV a -> SLarge
+toLarge v
+  | extra < 0 = error $ "toLarge: Unexpected size: " ++ show (n, large)
+  | hasSign v =            svSignExtend extra (unSBV v)
+  | True      = mkSigned $ svZeroExtend extra (unSBV v)
+  where n     = intSizeOf v
+        extra = large - n
+
+        mkSigned = svFromIntegral (KBounded True large)
+
+-- For a few cases, we expect them to "never" overflow. The "embedding proofs" are either too expensive (in case of division), or
+-- not possible (in case of negation). We capture these here.
+never :: forall a. (Integral a, Bounded a, SymVal a) => (SLarge -> SLarge -> SLarge) -> (SBV a -> SBV a -> SBool) -> Predicate
+never _op cond = do x  <- free "x"
+                    y  <- free "y"
+
+                    let overFlowHappens = x `cond` y
+
+                    return $ overFlowHappens `exactlyWhen` svFalse
+
+never1 :: forall a. (Integral a, Bounded a, SymVal a) => (SLarge -> SLarge) -> (SBV a -> SBool) -> Predicate
+never1 _op cond = do x  <- free "x"
+
+                     let overflowHappens = cond x
+
+                     return $ overflowHappens `exactlyWhen` svFalse
+
+overflow :: forall a. (Integral a, Bounded a, SymVal a) => (SLarge -> SLarge -> SLarge) -> (SBV a -> SBV a -> SBool) -> Predicate
+overflow op cond = do x  <- free "x"
+                      y  <- free "y"
+
+                      let overflowHappens = x `cond` y
+
+                          extResult :: SLarge
+                          extResult = toLarge x `op` toLarge y
+
+                          minb, maxb :: a
+                          (minb, maxb) = case minMaxBound of
+                                           Nothing -> error "overflow on type that doesn't support bounded"
+                                           Just ab -> ab
+
+                      return $ overflowHappens `exactlyWhen` (      (extResult `svGreaterThan` toLarge (literal maxb))
+                                                             `svOr` (extResult `svLessThan`    toLarge (literal minb))
+                                                             )
+
+overflow1 :: forall a. (Integral a, Bounded a, SymVal a) => (SLarge -> SLarge) -> (SBV a -> SBool) -> Predicate
+overflow1 op cond = do x  <- free "x"
+
+                       let overflowHappens = cond x
+
+                           extResult :: SLarge
+                           extResult = op $ toLarge x
+
+                           minb, maxb :: a
+                           (minb, maxb) = case minMaxBound of
+                                            Nothing -> error "overflow on type that doesn't support bounded"
+                                            Just ab -> ab
+
+                       return $ overflowHappens `exactlyWhen` (       (extResult `svGreaterThan` toLarge (literal maxb))
+                                                               `svOr` (extResult `svLessThan`    toLarge (literal minb)))
+
+-- Custom checker for signedMulOverflow
+smulCheck :: forall proxy n. ( KnownNat n,          BVIsNonZero n
+                             , KnownNat (n+1),      BVIsNonZero (n+1)
+                             , KnownNat (n+n),      BVIsNonZero (n+n)
+                             , KnownNat (2+Log2 n), BVIsNonZero (2+Log2 n)
+                             ) => proxy n -> Bool -> IO Bool
+smulCheck _ builtin = check (if builtin then bvMulO else textbook)
+   where check f = isTheoremWith bitwuzla $ do
+                        x <- sInt "x"
+                        y <- sInt "y"
+                        pure $ f x y .== (signedMulOverflow :: SInt n -> SInt n -> SBool) x y
+
+         textbook x y = prod2N ./= sFromIntegral prodN
+           where prod2N :: SInt (n+n)
+                 prod2N = sFromIntegral x * sFromIntegral y
+
+                 prodN :: SInt n
+                 prodN = x * y
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Overflows/Casts.hs b/SBVTestSuite/TestSuite/Overflows/Casts.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Overflows/Casts.hs
@@ -0,0 +1,136 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Overflows.Casts
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for overflow checking
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Overflows.Casts(tests) where
+
+import Data.SBV
+import Data.SBV.Tools.Overflow
+
+import Utils.SBVTestFramework
+
+type C a b = SBV a -> (SBV b, (SBool, SBool))
+
+getBounds :: (Bounded a, Integral a) => a -> Maybe (Integer, Integer)
+getBounds x = Just (fromIntegral (minBound `asTypeOf` x), fromIntegral (maxBound `asTypeOf` x))
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Overflows" [testGroup "Casts" ts]
+  where ts = [ testGroup "w8"  [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Word8   Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Word8   Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Word8   Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Word8   Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Word8   Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Word8   Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Word8   Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Word8   Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Word8   Integer)
+                               ]
+             , testGroup "w16" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Word16  Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Word16  Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Word16  Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Word16  Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Word16  Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Word16  Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Word16  Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Word16  Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Word16  Integer)
+                               ]
+             , testGroup "w32" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Word32  Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Word32  Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Word32  Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Word32  Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Word32  Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Word32  Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Word32  Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Word32  Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Word32  Integer)
+                               ]
+             , testGroup "w64" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Word64  Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Word64  Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Word64  Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Word64  Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Word64  Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Word64  Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Word64  Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Word64  Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Word64  Integer)
+                               ]
+             , testGroup "i8"  [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Int8    Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Int8    Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Int8    Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Int8    Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Int8    Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Int8    Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Int8    Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Int8    Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Int8    Integer)
+                               ]
+             , testGroup "i16" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Int16   Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Int16   Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Int16   Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Int16   Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Int16   Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Int16   Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Int16   Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Int16   Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Int16   Integer)
+                               ]
+             , testGroup "i32" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Int32   Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Int32   Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Int32   Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Int32   Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Int32   Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Int32   Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Int32   Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Int32   Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Int32   Integer)
+                               ]
+             , testGroup "i64" [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Int64   Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Int64   Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Int64   Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Int64   Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Int64   Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Int64   Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Int64   Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Int64   Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Int64   Integer)
+                               ]
+             , testGroup "i"   [ testCase "w8"  $ assertIsThm $ chk (getBounds (undefined :: Word8 )) (sFromIntegralO :: C Integer Word8)
+                               , testCase "w16" $ assertIsThm $ chk (getBounds (undefined :: Word16)) (sFromIntegralO :: C Integer Word16)
+                               , testCase "w32" $ assertIsThm $ chk (getBounds (undefined :: Word32)) (sFromIntegralO :: C Integer Word32)
+                               , testCase "w64" $ assertIsThm $ chk (getBounds (undefined :: Word64)) (sFromIntegralO :: C Integer Word64)
+                               , testCase "i8"  $ assertIsThm $ chk (getBounds (undefined :: Int8  )) (sFromIntegralO :: C Integer Int8)
+                               , testCase "i16" $ assertIsThm $ chk (getBounds (undefined :: Int16 )) (sFromIntegralO :: C Integer Int16)
+                               , testCase "i32" $ assertIsThm $ chk (getBounds (undefined :: Int32 )) (sFromIntegralO :: C Integer Int32)
+                               , testCase "i64" $ assertIsThm $ chk (getBounds (undefined :: Int64 )) (sFromIntegralO :: C Integer Int64)
+                               , testCase "i"   $ assertIsThm $ chk Nothing                           (sFromIntegralO :: C Integer Integer)
+                               ]
+             ]
+
+chk :: forall a b. (SymVal a, SymVal b, Integral a, Integral b) => Maybe (Integer, Integer) -> (SBV a -> (SBV b, (SBool, SBool))) -> Predicate
+chk mb cvt = do (x :: SBV a) <- free "x"
+
+                let (_ :: SBV b, (uf, ov)) = cvt x
+
+                    ix :: SInteger
+                    ix = sFromIntegral x
+
+                    (ufCorrect, ovCorrect) = case mb of
+                                               Nothing       -> (uf .== sFalse,            ov .== sFalse)
+                                               Just (lb, ub) -> (uf .<=> ix .< literal lb, ov .<=> ix .> literal ub)
+
+                return $ ufCorrect .&& ovCorrect
diff --git a/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs b/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Polynomials.Polynomials
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Polynomials.Polynomials
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Polynomials.Polynomials(tests) where
+
+import Documentation.SBV.Examples.Misc.Polynomials
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Polynomials.Polynomials"
+    [ testCase "polynomial-1" (assertIsThm multUnit)
+    , testCase "polynomial-2" (assertIsThm multComm)
+    , testCase "polynomial-3" (assertIsThm polyDivMod)
+    ]
diff --git a/SBVTestSuite/TestSuite/Puzzles/Coins.hs b/SBVTestSuite/TestSuite/Puzzles/Coins.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/Coins.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.Coins
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.Coins
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.Coins(tests) where
+
+import Documentation.SBV.Examples.Puzzles.Coins
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Puzzles.Coins" [
+  goldenVsStringShow "coins" coinsPgm
+ ]
+ where coinsPgm = runSAT $ do cs <- mapM mkCoin [1..6]
+                              mapM_ constrain [c s | s <- combinations cs, length s >= 2, c <- [c1, c2, c3, c4, c5, c6]]
+                              constrain $ sAnd $ zipWith (.>=) cs (drop 1 cs)
+                              pure $ sum cs .== 115
diff --git a/SBVTestSuite/TestSuite/Puzzles/Counts.hs b/SBVTestSuite/TestSuite/Puzzles/Counts.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/Counts.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.Counts
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.Counts
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.Counts(tests) where
+
+import Documentation.SBV.Examples.Puzzles.Counts
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Puzzles.Counts" [
+  goldenVsStringShow "counts" countPgm
+ ]
+ where countPgm = runSAT $ puzzle <$> mkFreeVars 10
diff --git a/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs b/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.DogCatMouse
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.DogCatMouse
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.DogCatMouse(tests) where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Puzzles.DogCatMouse"
+    [ goldenVsStringShow "dogCatMouse" (allSat p)
+    ]
+ where p = do [dog, cat, mouse] <- sIntegers ["dog", "cat", "mouse"]
+              solve [ dog   .>= 1                                   -- at least one dog
+                    , cat   .>= 1                                   -- at least one cat
+                    , mouse .>= 1                                   -- at least one mouse
+                    , dog + cat + mouse .== 100                     -- buy precisely 100 animals
+                    , 1500 * dog + 100 * cat + 25 * mouse .== 10000 -- spend exactly 100 dollars (use cents since we don't have fractions)
+                    ]
diff --git a/SBVTestSuite/TestSuite/Puzzles/Euler185.hs b/SBVTestSuite/TestSuite/Puzzles/Euler185.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/Euler185.hs
@@ -0,0 +1,25 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.Euler185
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.Euler185
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.Euler185(tests) where
+
+import Documentation.SBV.Examples.Puzzles.Euler185
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Puzzles.Euler185"
+    [ goldenVsStringShow "euler185" (allSat euler185)
+    ]
diff --git a/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs b/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.MagicSquare
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.MagicSquare
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.MagicSquare(tests) where
+
+import Documentation.SBV.Examples.Puzzles.MagicSquare
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Puzzles.MagicSquare"
+    [ testCase "magic 2" (assertIsntSat (mkMagic 2))
+    , testCase "magic 3" (assertIsSat (mkMagic 3))
+    ]
+
+
+mkMagic :: Int -> Symbolic SBool
+mkMagic n = (isMagic . chunk n) `fmap` mkFreeVars (n*n)
diff --git a/SBVTestSuite/TestSuite/Puzzles/NQueens.hs b/SBVTestSuite/TestSuite/Puzzles/NQueens.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/NQueens.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.NQueens
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.NQueens
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.NQueens(tests) where
+
+import Documentation.SBV.Examples.Puzzles.NQueens
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Puzzles.NQueens"
+    -- number of *distinct* solutions is given in http://en.wikipedia.org/wiki/Eight_queens_puzzle
+   [ testCase "nQueens 1" (assert $ (==  1) `fmap` numberOfModels (mkQueens 1))
+   , testCase "nQueens 2" (assert $ (==  0) `fmap` numberOfModels (mkQueens 2))
+   , testCase "nQueens 3" (assert $ (==  0) `fmap` numberOfModels (mkQueens 3))
+   , testCase "nQueens 4" (assert $ (==  2) `fmap` numberOfModels (mkQueens 4))
+   , testCase "nQueens 5" (assert $ (== 10) `fmap` numberOfModels (mkQueens 5))
+   , testCase "nQueens 6" (assert $ (==  4) `fmap` numberOfModels (mkQueens 6))
+   , testCase "nQueens 7" (assert $ (== 40) `fmap` numberOfModels (mkQueens 7))
+   , testCase "nQueens 8" (assert $ (== 92) `fmap` numberOfModels (mkQueens 8))
+   ]
+
+mkQueens :: Int -> Symbolic SBool
+mkQueens n = isValid n `fmap` mkFreeVars n
diff --git a/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs b/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.PowerSet
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Puzzles.PowerSet
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.PowerSet(tests) where
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Puzzles.PowerSet"
+    [ testCase ("powerSet " ++ show i) (assert (pSet i)) | i <- [0 .. 7] ]
+
+pSet :: Int -> IO Bool
+pSet n = do cnt <- numberOfModels $ do mapM_ (\i -> sBool ('e' : show i)) [1..n]
+                                       -- Look ma! No constraints!
+                                       return sTrue
+            return (cnt == 2^n)
diff --git a/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs b/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs
@@ -0,0 +1,29 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.Sudoku
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.Sudoku
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.Sudoku(tests) where
+
+import Documentation.SBV.Examples.Puzzles.Sudoku
+
+import Utils.SBVTestFramework
+
+tests :: TestTree
+tests =
+  testGroup "Puzzles.Sudoku"
+    [ testCase ("sudoku " ++ show n) (assert (checkPuzzle s))
+       | (n, s) <- zip [(0::Int)..] [puzzle1, puzzle2, puzzle3, puzzle4, puzzle5, puzzle6] ]
+
+checkPuzzle :: Puzzle -> IO Bool
+checkPuzzle p = do final <- fillBoard p
+                   let vld = valid (map (map literal) final)
+                   pure $ Just True == unliteral vld
diff --git a/SBVTestSuite/TestSuite/Puzzles/Temperature.hs b/SBVTestSuite/TestSuite/Puzzles/Temperature.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/Temperature.hs
@@ -0,0 +1,41 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.Temperature
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Examples.Puzzles.Temperature
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.Temperature(tests) where
+
+import Utils.SBVTestFramework
+
+import Data.List (sort)
+import qualified Data.Map as M
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Puzzles.Temperature"
+    [ goldenVsStringShow "temperature" result
+    ]
+    where result = (sort . concatMap M.toList . getModelDictionaries) `fmap` allSat (revOf `fmap` free_)
+
+type Temp = SInteger
+
+-- convert celsius to fahrenheit, rounding up/down properly
+-- we have to be careful here to make sure rounding is done properly..
+d2f :: Temp -> Temp
+d2f d = 32 + ite (fr .>= 5) (1+fi) fi
+  where (fi, fr) = (18 * d) `sQuotRem` 10
+
+-- puzzle: What 2 digit fahrenheit/celsius values are reverses of each other?
+revOf :: Temp -> SBool
+revOf c = swap (digits c) .== digits (d2f c)
+  where digits x = x `sQuotRem` 10
+        swap (a, b) = (b, a)
diff --git a/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs b/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Puzzles.U2Bridge
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Puzzles.U2Bridge
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Puzzles.U2Bridge(tests) where
+
+import Documentation.SBV.Examples.Puzzles.U2Bridge
+
+import Data.List(sortOn)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Puzzles.U2Bridge"
+    [ testCase "U2Bridge_cnt1" (assert $ (0 ==) `fmap` count 1)
+    , testCase "U2Bridge_cnt2" (assert $ (0 ==) `fmap` count 2)
+    , testCase "U2Bridge_cnt3" (assert $ (0 ==) `fmap` count 3)
+    , testCase "U2Bridge_cnt4" (assert $ (0 ==) `fmap` count 4)
+    , testCase "U2Bridge_cnt6" (assert $ (0 ==) `fmap` count 6)
+    , goldenVsStringShow "U2Bridge" (slv 5)
+    ]
+ where act     = do b <- free_; p1 <- free_; p2 <- free_; 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 r@AllSatResult{allSatResults = ms} = r { allSatResults = sortOn (show . SatResult) ms }
diff --git a/SBVTestSuite/TestSuite/Queries/ArrayGetVal.hs b/SBVTestSuite/TestSuite/Queries/ArrayGetVal.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/ArrayGetVal.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.ArrayGetVal
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Making sure array get-value works, since we might send extra asserts after
+-- check-sat.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.ArrayGetVal (tests)  where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.ArrayGetVal"
+    [ goldenCapturedIO "arrayGetValTest1" testQuery
+    ]
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} t1
+                  appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+
+t1 :: Symbolic Integer
+t1 = do a :: SArray Integer Integer <- sArray "a"
+        query $ do ensureSat
+                   getValue (readArray (writeArray a 1 2) 1)
diff --git a/SBVTestSuite/TestSuite/Queries/BadOption.hs b/SBVTestSuite/TestSuite/Queries/BadOption.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/BadOption.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.BadOption
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing that a bad option setting is caught properly.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.BadOption (tests)  where
+
+import Data.SBV.Control
+import qualified Control.Exception as C
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_badOption" $ \rf -> runSMTWith z3{verbose=True, redirectVerbose=Just rf} q
+                                                  `C.catch`
+                                                  (\(e::C.SomeException) -> appendFile rf ("\n" ++ show e))
+    ]
+
+q :: Symbolic ()
+q = do _ <- sInteger "x"
+       setOption $ OptionKeyword ":there-is-no-such-option" ["bad", "argument"]
+       query $ return ()
diff --git a/SBVTestSuite/TestSuite/Queries/BasicQuery.hs b/SBVTestSuite/TestSuite/Queries/BasicQuery.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/BasicQuery.hs
@@ -0,0 +1,133 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.BasicQuery
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A hodgepodge of query commands
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.BasicQuery (tests)  where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Query"
+    [ goldenCapturedIO "query1" testQuery
+    ]
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} query1
+                  appendFile rf ("\n FINAL:" ++ show (SatResult r) ++ "\nDONE!\n")
+
+query1 :: Symbolic SMTResult
+query1 = do
+       a <- sInteger "a"
+       b <- sInteger "b"
+
+       c <- sFloat "c"
+       d <- sBool "d"
+
+       e <- sReal "e"
+
+       f :: SInt8 <- free_
+
+       namedConstraint "a > 0" $ a .> 0
+       constrain $ b .> 0
+
+       setOption $ ProduceUnsatCores True
+       setOption $ ProduceUnsatAssumptions True
+       setOption $ ProduceProofs True
+       setOption $ RandomSeed 123
+       setOption $ ProduceAssertions True
+       setOption $ OptionKeyword ":smt.mbqi" ["true"]
+       setOption $ ProduceAssignments True
+
+       setInfo ":status" ["sat"]
+       setInfo ":bad" ["what"]
+
+       query $ do constrain $ a+2 .>= 5
+                  namedConstraint "a+b_<_12" $ a+b .< 12
+
+                  _ <- getOption DiagnosticOutputChannel
+                  _ <- getOption ProduceAssertions
+                  _ <- getOption ProduceAssignments
+                  _ <- getOption ProduceProofs
+                  _ <- getOption ProduceUnsatAssumptions
+                  _ <- getOption ProduceUnsatCores
+                  _ <- getOption RandomSeed
+                  _ <- getOption ReproducibleResourceLimit
+                  _ <- getOption SMTVerbosity
+                  _ <- getOption (OptionKeyword ":smt.mbqi")
+                  _ <- getOption (OptionKeyword ":smt.mbqi")
+
+                  _ <- getInfo ReasonUnknown
+                  _ <- getInfo (InfoKeyword ":version")
+                  _ <- getInfo (InfoKeyword ":status")
+
+                  namedConstraint "later, a > 4" $ a .> 4
+
+                  cs <- checkSat
+
+                  case cs of
+                    Sat -> return ()
+                    Unk -> getInfo ReasonUnknown >>= error . show
+                    r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                  setInfo ":status" ["unknown"]
+
+                  _ <- checkSatAssumingWithUnsatisfiableSet [a .> 2]
+                  _ <- checkSatAssuming [a .> 2]
+                  _ <- getAssignment
+
+                  -- ends up printing different numbers on different machines..
+                  -- _ <- getInfo AllStatistics
+
+                  _ <- getInfo AssertionStackLevels
+                  _ <- getInfo Authors
+                  _ <- getInfo ErrorBehavior
+                  _ <- getInfo Name
+                  _ <- getInfo ReasonUnknown
+                  _ <- getInfo Version
+                  _ <- getInfo (InfoKeyword ":memory")
+                  _ <- getInfo (InfoKeyword ":time")
+
+                  -- Query a/b
+                  av <- getValue a
+                  bv <- getValue b
+
+                  _ <- checkSatAssumingWithUnsatisfiableSet [a .> 100,  a .> 9]
+
+                  push 5
+                  pop 3
+                  _ <- getAssertionStackDepth
+
+                  -- Now assert so that we get even a bigger value..
+                  namedConstraint "bey" $ a .> literal (av + bv)
+                  namedConstraint "hey" $ a .< literal (av + bv)
+                  _ <- checkSat
+                  _ <- timeout 80000 getUnsatCore
+
+                  _ <- getProof
+                  _ <- timeout 90000 getAssertions
+
+                  echo "there we go"
+
+                  -- fake it!
+                  mkSMTResult [ a |-> 332
+                              , b |-> 3
+                              , c |-> 2.3
+                              , d |-> True
+                              , e |-> 3.12
+                              , f |-> (-12)
+                              ]
diff --git a/SBVTestSuite/TestSuite/Queries/DSat.hs b/SBVTestSuite/TestSuite/Queries/DSat.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/DSat.hs
@@ -0,0 +1,69 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.DSat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing dsat value extraction
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.DSat (tests)  where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Query.DSat"
+    [ goldenCapturedIO "dsat01" testQuery
+    ]
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith dReal{verbose=True, redirectVerbose=Just rf} fv
+                  appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+
+fv :: Symbolic (Maybe String, [AlgReal], [RationalCV], [Integer], [Bool])
+fv = do a0 <- sReal    "a0"
+        i0 <- sInteger "i0"
+        b0 <- sBool    "b0"
+
+        constrain $ a0 .> 2
+        constrain $ a0 .<= 5
+
+        query $ do a1 :: SReal    <- freshVar "a1"
+                   i1 :: SInteger <- freshVar "i1"
+                   b1 :: SBool    <- freshVar "b1"
+
+                   constrain $ a1 .> 3
+                   constrain $ a1 .<= 12
+
+                   cs <- checkSat
+
+                   case cs of
+                     DSat p -> do va0 <- getValue a0
+                                  va1 <- getValue a1
+                                  vi0 <- getValue i0
+                                  vi1 <- getValue i1
+                                  vb0 <- getValue b0
+                                  vb1 <- getValue b1
+
+                                  let rva0 = algRealToRational va0
+                                      rva1 = algRealToRational va1
+
+                                      check r = case r of
+                                                  RatInterval lo hi -> if realPoint lo <= realPoint hi
+                                                                       then r
+                                                                       else error $ "Bounds violated for: " ++ show r
+                                                  _                 -> r
+
+                                  pure (p, [va0, va1], map check [rva0, rva1], [vi0, vi1], [vb0, vb1])
+
+                     _   -> error "didn't expect non-DSat here!"
diff --git a/SBVTestSuite/TestSuite/Queries/Enums.hs b/SBVTestSuite/TestSuite/Queries/Enums.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Enums.hs
@@ -0,0 +1,49 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Enums
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Uninterpreted.AUF
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Enums where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+data BinOp  = Plus | Minus | Times
+mkSymbolic [''BinOp]
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Queries.Enums"
+    [ goldenCapturedIO "qEnum1" $ \rf -> runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} test
+    ]
+
+
+test :: Symbolic ()
+test = do p :: SBinOp <- free "p"
+          m :: SBinOp <- free "m"
+          t :: SBinOp <- free "t"
+
+          constrain $ p .<= m
+          constrain $ m .<= t
+          constrain $ distinct [p, m, t]
+
+          query $ do _ <- checkSat
+                     _ <- getValue p
+                     _ <- getValue m
+                     _ <- getValue t
+                     return ()
diff --git a/SBVTestSuite/TestSuite/Queries/FreshVars.hs b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
@@ -0,0 +1,166 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.FreshVars
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing fresh-vars in query mode
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.FreshVars (tests)  where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+data BinOp  = Plus | Minus | Times
+mkSymbolic [''BinOp]
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Query"
+    [ goldenCapturedIO "freshVars" testQuery
+    ]
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} fv
+                  appendFile rf ("\n FINAL:" ++ show (SatResult r) ++ "\nDONE!\n")
+
+fv :: Symbolic SMTResult
+fv = do a <- sInteger "a"
+
+        constrain $ a .== 0
+
+        setOption $ OptionKeyword ":pp.max_depth"      ["4294967295"]
+        setOption $ OptionKeyword ":pp.min_alias_size" ["4294967295"]
+
+        query $ do vBool    :: SBool           <- freshVar  "vBool"
+                   vWord8   :: SWord8          <- freshVar  "vWord8"
+                   vWord16  :: SWord16         <- freshVar_
+                   vWord32  :: SWord32         <- freshVar_
+                   vWord64  :: SWord64         <- freshVar  "vWord64"
+                   vInt8    :: SInt8           <- freshVar  "vInt8"
+                   vInt16   :: SInt16          <- freshVar_
+                   vInt32   :: SInt32          <- freshVar_
+                   vInt64   :: SInt64          <- freshVar  "vInt64"
+                   vFloat   :: SFloat          <- freshVar  "vFloat"
+                   vDouble  :: SDouble         <- freshVar_
+                   vReal    :: SReal           <- freshVar_
+                   vInteger :: SInteger        <- freshVar  "vInteger"
+                   vBinOp   :: SBinOp          <- freshVar  "vBinOp"
+                   vQuad    :: SFPQuad         <- freshVar  "vQuad"
+                   wQuad    :: SFPQuad         <- freshVar  "wQuad"
+
+                   constrain   vBool
+                   constrain $ vWord8   .== 1
+                   constrain $ vWord16  .== 2
+                   constrain $ vWord32  .== 3
+                   constrain $ vWord64  .== 4
+                   constrain $ vInt8    .== 5
+                   constrain $ vInt16   .== 6
+                   constrain $ vInt32   .== 7
+                   constrain $ vInt64   .== 8
+                   constrain $ vFloat   .== 9
+                   constrain $ vDouble  .== 10
+                   constrain $ vReal    .== 11
+                   constrain $ vInteger .== 12
+                   constrain $ vBinOp   .== sPlus
+
+                   constrain $ vQuad .== wQuad
+                   constrain $ sNot $ vQuad `fpIsEqualObject` wQuad
+                   constrain $ fpIsPositive vQuad
+
+                   vSArray  :: SArray    Integer Integer <- freshVar "vSArray"
+                   vi1                                   <- freshVar "i1"
+                   vi2                                   <- freshVar "i2"
+                   constrain $ readArray vSArray vi1 .== 2
+
+                   let viSArray  :: SArray Integer Integer
+                       viSArray = constArray 42
+                   mustBe42                              <- freshVar "mustBe42"
+
+                   constrain $ readArray viSArray 96     .== mustBe42
+                   constrain $ vi1 .== 1
+                   constrain $ sNot vi2
+
+                   vString  :: SString         <- freshVar  "vString"
+                   vList1   :: SList Integer   <- freshVar  "vList1"
+                   vList2   :: SList [Integer] <- freshVar  "vList2"
+                   vList3   :: SList Word8     <- freshVar  "vList3"
+                   vList4   :: SList [Word16]  <- freshVar  "vList4"
+
+                   constrain $ vString  .== "hello"
+                   constrain $ vList1   .== [1,2,3,4]
+                   constrain $ vList2   .== [[1,2,3], [4,5,6,7]]
+                   constrain $ vList3   .== [1,2]
+                   constrain $ vList4   .== [[1,2,3],[],[4,5,6]]
+
+                   cs <- checkSat
+                   case cs of
+                     Sat -> do aVal        <- getValue a
+                               vBoolVal    <- getValue vBool
+                               vWord8Val   <- getValue vWord8
+                               vWord16Val  <- getValue vWord16
+                               vWord32Val  <- getValue vWord32
+                               vWord64Val  <- getValue vWord64
+                               vInt8Val    <- getValue vInt8
+                               vInt16Val   <- getValue vInt16
+                               vInt32Val   <- getValue vInt32
+                               vInt64Val   <- getValue vInt64
+                               vFloatVal   <- getValue vFloat
+                               vDoubleVal  <- getValue vDouble
+                               vRealVal    <- getValue vReal
+                               vIntegerVal <- getValue vInteger
+                               vBinOpVal   <- getValue vBinOp
+                               vSArrayVal  <- getValue vSArray
+                               vi1Val      <- getValue vi1
+                               vi2Val      <- getValue vi2
+                               mustBe42Val <- getValue mustBe42
+                               vStringVal  <- getValue vString
+                               vList1Val   <- getValue vList1
+                               vList2Val   <- getValue vList2
+                               vList3Val   <- getValue vList3
+                               vList4Val   <- getValue vList4
+                               vQuadVal    <- getValue vQuad
+                               wQuadVal    <- getValue wQuad
+
+                               mkSMTResult [ a          |-> aVal
+                                           , vBool      |-> vBoolVal
+                                           , vWord8     |-> vWord8Val
+                                           , vWord16    |-> vWord16Val
+                                           , vWord32    |-> vWord32Val
+                                           , vWord64    |-> vWord64Val
+                                           , vInt8      |-> vInt8Val
+                                           , vInt16     |-> vInt16Val
+                                           , vInt32     |-> vInt32Val
+                                           , vInt64     |-> vInt64Val
+                                           , vFloat     |-> vFloatVal
+                                           , vDouble    |-> vDoubleVal
+                                           , vReal      |-> vRealVal
+                                           , vInteger   |-> vIntegerVal
+                                           , vBinOp     |-> vBinOpVal
+                                           , vSArray    |-> vSArrayVal
+                                           , vi1        |-> vi1Val
+                                           , vi2        |-> vi2Val
+                                           , mustBe42   |-> mustBe42Val
+                                           , vString    |-> vStringVal
+                                           , vList1     |-> vList1Val
+                                           , vList2     |-> vList2Val
+                                           , vList3     |-> vList3Val
+                                           , vList4     |-> vList4Val
+                                           , vQuad      |-> vQuadVal
+                                           , wQuad      |-> wQuadVal
+                                           ]
+                     _   -> error "didn't expect non-Sat here!"
diff --git a/SBVTestSuite/TestSuite/Queries/Int_ABC.hs b/SBVTestSuite/TestSuite/Queries/Int_ABC.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_ABC.hs
@@ -0,0 +1,53 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_ABC
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing ABC specific interactive features.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_ABC (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_abc" $ \rf -> runSMTWith abc{verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       constrain $ a .> 0
+       constrain $ b .> 0
+
+       -- this is severely limited since ABC doesn't like multi check-sat calls, oh well.
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  2
+                  constrain $ b   .<  2
+                  constrain $ a+b .< 12
+
+                  constrain $ a .< 2
+                  cs <- checkSat
+
+                  case cs of
+                    Unk    -> getInfo ReasonUnknown >>= error . show
+                    Unsat  -> error "Got UNSAT!"
+                    DSat{} -> error "Got Delta-satisfiable!"
+                    Sat    -> do -- Query a/b
+                                 res <- (,) <$> getValue a <*> getValue b
+                                 unless (res == (1, 1)) $ error $ "Didn't get (1,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs b/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs
@@ -0,0 +1,57 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_Boolector
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing Boolector specific interactive features.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_Boolector (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_boolector" $ \rf -> runSMTWith boolector{verbose=True, redirectVerbose=Just rf} q
+    , goldenCapturedIO "query_bitwuzla"  $ \rf -> runSMTWith bitwuzla {verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       constrain $ a .> 0
+       constrain $ b .> 0
+
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  3
+                  constrain $ b   .<  2
+                  constrain $ a+b .< 12
+
+                  constrain $ a .< 2
+                  cs <- checkSat
+
+                  case cs of
+                    Sat -> return ()
+                    Unk -> getInfo ReasonUnknown >>= error . show
+                    r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                  -- Now assert so that we get even a bigger value..
+                  constrain $ a .>= 1
+                  _ <- checkSat
+
+                  res <- (,) <$> getValue a <*> getValue b
+                  unless (res == (1, 1)) $ error $ "Didn't get (1,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs b/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs
@@ -0,0 +1,62 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_CVC4
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing CVC4 specific interactive features
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_CVC4 (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_cvc4" $ \rf -> runSMTWith cvc4{verbose=True, redirectVerbose=Just rf} q
+    , goldenCapturedIO "query_cvc5" $ \rf -> runSMTWith cvc5{verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       namedConstraint "a > 0" $ a .> 0
+       constrain $ b .> 0
+
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  3
+                  constrain $ b   .<  2
+                  namedConstraint "a+b_<_12" $ a+b .< 12
+
+                  av <- inNewAssertionStack $ do
+
+                            constrain $ a .< 2
+                            cs <- checkSat
+
+                            case cs of
+                              Sat -> return ()
+                              Unk -> getInfo ReasonUnknown >>= error . show
+                              r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                            getValue a
+
+                  -- Now assert so that we get even a bigger value..
+                  namedConstraint "extra" $ a .> literal av
+                  constrain $ b .< 2
+                  _ <- checkSat
+
+                  res <- (,) <$> getValue a <*> getValue b
+                  unless (res == (2, 1)) $ error $ "Didn't get (2,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs b/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_Mathsat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing MathSAT specific interactive features.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_Mathsat (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_mathsat" $ \rf -> runSMTWith mathSAT{verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       namedConstraint "a > 0" $ a .> 0
+       constrain $ b .> 0
+
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  3
+                  constrain $ b   .<  2
+                  namedConstraint "a+b_<_12" $ a+b .< 12
+
+                  constrain $ a .< 2
+                  cs <- checkSat
+
+                  case cs of
+                    Sat -> return ()
+                    Unk -> getInfo ReasonUnknown >>= error . show
+                    r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                  -- Now assert so that we get even a bigger value..
+                  namedConstraint "extra" $ a .>= 1
+                  _ <- checkSat
+
+                  res <- (,) <$> getValue a <*> getValue b
+                  unless (res == (1, 1)) $ error $ "Didn't get (1,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Yices.hs b/SBVTestSuite/TestSuite/Queries/Int_Yices.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_Yices.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_Yices
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing Yices specific interactive features.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_Yices (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_yices" $ \rf -> runSMTWith yices{verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       namedConstraint "a > 0" $ a .> 0
+       constrain $ b .> 0
+
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  3
+                  constrain $ b   .<  2
+                  namedConstraint "a+b_<_12" $ a+b .< 12
+
+                  constrain $ a .< 2
+                  cs <- checkSat
+
+                  case cs of
+                    Sat -> return ()
+                    Unk -> getInfo ReasonUnknown >>= error . show
+                    r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                  -- Now assert so that we get even a bigger value..
+                  namedConstraint "extra" $ a .>= 1
+                  _ <- checkSat
+
+                  res <- (,) <$> getValue a <*> getValue b
+                  unless (res == (1, 1)) $ error $ "Didn't get (1,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Z3.hs b/SBVTestSuite/TestSuite/Queries/Int_Z3.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Int_Z3.hs
@@ -0,0 +1,63 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Int_Z3
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing Z3 specific interactive features.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Int_Z3 (tests)  where
+
+import Data.SBV.Control
+
+import Control.Monad (unless)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryIndividual"
+    [ goldenCapturedIO "query_z3" $ \rf -> runSMTWith z3{verbose=True, redirectVerbose=Just rf} q
+    ]
+
+q :: Symbolic ()
+q = do a <- sInt32 "a"
+       b <- sInt32 "b"
+
+       namedConstraint "a > 0" $ a .> 0
+       constrain $ b .> 0
+
+       query $ do constrain $ a+2 .<= 15
+                  constrain $ a   .<  3
+                  constrain $ b   .<  2
+                  namedConstraint "a+b_<_12" $ a+b .< 12
+
+                  gv <- inNewAssertionStack $ do
+
+                            constrain $ a .< 2
+                            cs <- checkSat
+
+                            case cs of
+                              Sat -> return ()
+                              Unk -> getInfo ReasonUnknown >>= error . show
+                              r   -> error $ "Something went bad, why not-sat/unk?: " ++ show r
+
+                            -- Query a/b
+                            getValue a
+
+                  -- Now assert so that we get even a bigger value..
+                  namedConstraint "extra" $ a .> literal gv
+                  constrain $ b .< 2
+
+                  _ <- checkSat
+
+                  res <- (,) <$> getValue a <*> getValue b
+                  unless (res == (2, 1)) $ error $ "Didn't get (2,1): " ++ show res
diff --git a/SBVTestSuite/TestSuite/Queries/Interpolants.hs b/SBVTestSuite/TestSuite/Queries/Interpolants.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Interpolants.hs
@@ -0,0 +1,97 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Interpolants
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing a few interpolant computations.
+--
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Interpolants (tests)  where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryInterpolants"
+    [ goldenCapturedIO "query_Interpolant1" $ testQuery mathSAT q1
+    , goldenCapturedIO "query_Interpolant2" $ testQuery mathSAT q2
+    , goldenCapturedIO "query_Interpolant3" $ testQuery z3      q3
+    , goldenCapturedIO "query_Interpolant4" $ testQuery z3      q4
+    ]
+
+testQuery :: Show a => SMTConfig -> Symbolic a -> FilePath -> IO ()
+testQuery s t rf = do r <- runSMTWith s{verbose=True, redirectVerbose=Just rf} t
+                      appendFile rf ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+iConstraint :: String -> SBool -> Symbolic ()
+iConstraint g = constrainWithAttribute [(":interpolation-group", g)]
+
+q1 :: Symbolic String
+q1 = do a <- sInteger "a"
+        b <- sInteger "b"
+        c <- sInteger "c"
+        d <- sInteger "d"
+
+        setOption $ ProduceInterpolants True
+
+        iConstraint "c1" $ a .== b .&& a .== c
+        iConstraint "c2" $ b .== d .&& sNot (c .== d)
+
+        query $ do _ <- checkSat
+                   getInterpolantMathSAT ["c1"]
+
+q2 :: Symbolic String
+q2 = do a <- sInteger "a"
+        b <- sInteger "b"
+        c <- sInteger "c"
+        d <- sInteger "d"
+
+        let f, g :: SInteger -> SInteger
+            f = uninterpret "f"
+            g = uninterpret "g"
+
+        setOption $ ProduceInterpolants True
+
+        iConstraint "c1" $ f a .== c .&& f b .== d
+        iConstraint "c2" $   a .== b .&& g c ./= g d
+
+        query $ do _ <- checkSat
+                   getInterpolantMathSAT ["c1"]
+
+
+q3 :: Symbolic String
+q3 = do a <- sInteger "a"
+        b <- sInteger "b"
+        c <- sInteger "c"
+        d <- sInteger "d"
+
+        query $ getInterpolantZ3 [ a .== b .&& a .== c
+                                 , b .== d .&& sNot (c .== d)
+                                 ]
+
+q4 :: Symbolic String
+q4 = do a <- sInteger "a"
+        b <- sInteger "b"
+        c <- sInteger "c"
+        d <- sInteger "d"
+
+        let f, g :: SInteger -> SInteger
+            f = uninterpret "f"
+            g = uninterpret "g"
+
+        query $ getInterpolantZ3 [ f a .== c .&& f b .== d
+                                 ,   a .== b .&& g c ./= g d
+                                 ]
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Queries/Lists.hs b/SBVTestSuite/TestSuite/Queries/Lists.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Lists.hs
@@ -0,0 +1,47 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Lists
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing a few lists
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE QuasiQuotes         #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Lists (tests)  where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryLists"
+    [ goldenCapturedIO "query_Lists1" $ testQuery queryLists1
+    ]
+
+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")
+
+queryLists1 :: Symbolic [Integer]
+queryLists1 = do a :: SList Integer <- sList "a"
+
+                 constrain $ a .== [sEnum|1..5|]
+
+                 query $ do _ <- checkSat
+
+                            av <- getValue a
+
+                            if av == [1..5]
+                               then return av
+                               else error $ "Didn't expect this: " ++ show av
diff --git a/SBVTestSuite/TestSuite/Queries/Strings.hs b/SBVTestSuite/TestSuite/Queries/Strings.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Strings.hs
@@ -0,0 +1,59 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Strings
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing a few strings
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Strings (tests)  where
+
+import Data.SBV
+import Data.SBV.Control
+
+import qualified Data.SBV.Char   as C
+import qualified Data.SBV.RegExp as R
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryStrings"
+    [ goldenCapturedIO "query_Strings1" $ testQuery queryString1
+    , goldenCapturedIO "query_Chars1"   $ testQuery queryChar1
+    ]
+
+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")
+
+queryString1 :: Symbolic [String]
+queryString1 = do a <- sString "a"
+
+                  constrain $ a `R.match` R.Loop 5 5 "xyz"
+
+                  query $ do _ <- checkSat
+                             s <- getValue a
+                             if s == concat (replicate 5 "xyz")
+                                then return [s]
+                                else error $ "Didn't expect this: " ++ show s
+
+queryChar1 :: Symbolic Char
+queryChar1 = do a <- sChar "a"
+
+                constrain $ C.ord a .>= 65
+                constrain $ C.ord a .<  66
+
+                query $ do _ <- checkSat
+                           s <- getValue a
+                           if s == 'A'
+                              then return s
+                              else error $ "Didn't expect this: " ++ show s
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    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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
+
+-- This one has decidability problems if I force
+-- the list to have two elements. The current model
+-- returned has only one element; which is fine.
+-- (Adding a constraint to set the length to be anything causes unknown)
+queryListOfSum :: Symbolic [Either Integer Integer]
+queryListOfSum = do
+  lst <- sList @(Either Integer Integer) "lst"
+  constrain $ isLeft $ L.head lst
+  constrain $ isRight $ L.head $ L.tail lst
+
+  query $ do
+    ensureSat
+    getValue lst
+
+queryMaybe :: Symbolic (Maybe Integer)
+queryMaybe = do
+  a :: M.SMaybe Integer <- free "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
+
+-- This one has decidability problems if I force
+-- the list to have two elements. The current model
+-- returned has only one element; which is fine.
+-- (Adding a constraint to set the length to be anything causes unknown)
+queryListOfMaybe :: Symbolic [Maybe Char]
+queryListOfMaybe = do
+  lst <- sList @(Maybe Char) "lst"
+  constrain $ isJust (L.head lst)
+  constrain $ isNothing (L.head (L.tail lst))
+
+  query $ do
+    ensureSat
+    getValue lst
+
+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)
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVTestSuite/TestSuite/Queries/Tables.hs b/SBVTestSuite/TestSuite/Queries/Tables.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Tables.hs
@@ -0,0 +1,172 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Tables
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test case for https://github.com/LeventErkok/sbv/issues/539
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE QuantifiedConstraints #-}
+
+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}
+
+module TestSuite.Queries.Tables (tests)  where
+
+import GHC.Generics hiding (S)
+import Control.Monad.Identity
+import Control.Monad.Reader
+import Control.Monad.State
+
+import qualified Data.SBV.Maybe as SBV
+import qualified Data.SBV.Tuple as SBV
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Tables"
+    [ goldenCapturedIO "queryTables" testTables
+    ]
+
+testTables :: FilePath -> IO ()
+testTables rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} tables
+                   appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+
+data S = S { currentRoom   :: SInt16
+           , itemLocations :: [SInt16]
+           } deriving (Show, Generic, Mergeable)
+
+tables :: Symbolic [(Int16, Int16)]
+tables = do
+    let theGame = Game
+            { gameDictSize = 1
+            , gameItems = [7]
+            , gameRooms = [[0],[2]]
+            }
+
+
+    let genWord = do
+            word <- freshVar_
+            constrain $ 0 .<= word .&& word .< literal (gameDictSize theGame)
+            return word
+        genCmd = do
+            verb <- genWord
+            noun <- genWord
+            return $ SBV.tuple (verb, noun)
+    query $ do
+            let s0 = initState theGame
+
+            let step cmd = do
+                    let (verb, noun) = SBV.untuple cmd
+                    runGame theGame $ stepPlayer (verb, noun)
+
+            cmd1 <- genCmd
+            push 1
+            (f1, s1) <- return $ runState (step cmd1) s0
+            constrain f1
+            _cs <- checkSat
+            pop 1
+
+            cmd2 <- genCmd
+            push 1
+            (f2, _s2) <- return $ runState (step cmd2) s1
+            constrain f2
+            _cs <- checkSat
+
+            mapM getValue [cmd1, cmd2]
+
+instance forall a. Mergeable a => Mergeable (Identity a) where
+    symbolicMerge force cond thn els = Identity $ symbolicMerge force cond (runIdentity thn) (runIdentity els)
+
+instance (Mergeable a, forall b. Mergeable b => Mergeable (m b)) => Mergeable (ReaderT r m a) where
+    symbolicMerge force cond thn els = ReaderT $ symbolicMerge force cond (runReaderT thn) (runReaderT els)
+
+instance (Mergeable s, Mergeable a, forall b. Mergeable b => Mergeable (m b)) => Mergeable (StateT s m a) where
+    symbolicMerge force cond thn els = StateT $ symbolicMerge force cond (runStateT thn) (runStateT els)
+
+data Game = Game { gameDictSize :: Int16
+                 , gameItems :: [Int16]
+                 , gameRooms :: [[Int16]]
+                 } deriving Show
+
+type SInput = (SInt16, SInt16)
+
+type Engine = ReaderT Game (State S)
+
+carried :: Int16
+carried = 255
+
+initState :: Game -> S
+initState _game = S { currentRoom = 0
+                    , itemLocations = [1]
+                    }
+
+runGame :: Game -> Engine a -> State S a
+runGame game act = runReaderT act game
+
+stepPlayer :: SInput -> Engine SBool
+stepPlayer (v, n) = do
+    perform (v, n)
+    finished
+
+finished :: Engine SBool
+finished = do
+    locs <- gets itemLocations
+    return $ map (.== 1) locs `pbExactly` 1
+
+perform :: SInput -> Engine ()
+perform (verb, noun) = goCase verb (return ())
+    [ (1, builtin_go)
+    , (10, builtin_get)
+    ]
+  where
+    builtin_go = sWhen (1 .<= noun .&& noun .<= 6) $ do
+        let dir = noun - 1
+        here <- gets currentRoom
+        exits <- asks $ (.!! here) . map (map literal) . gameRooms
+        let newRoom = select exits 0 dir
+        sUnless (newRoom .== 0) $ modify $ \s ->
+          s{ currentRoom = newRoom }
+
+    builtin_get = do
+        locs <- gets itemLocations
+        here <- gets currentRoom
+        items <- asks gameItems
+        let item = SBV.fromMaybe (-1) $ sFindIndex (\nm -> noun .== literal nm) items
+        sWhen (select locs (-1) item .== here) $ modify $ \s ->
+          s{ itemLocations = replaceAt item (literal carried) (itemLocations s) }
+
+(.!!) :: (Mergeable a) => [a] -> SInt16 -> a
+xs .!! i = case xs of
+    [] -> error "(.!) : empty array"
+    lst@(x:_) -> select lst x i
+
+replaceAt :: (Mergeable a) => SInt16 -> a -> [a] -> [a]
+replaceAt i x' = zipWith (\j x -> ite (i .== literal j) x' x) [0..]
+
+goCase :: (Mergeable a) => SInt16 -> a -> [(Int16, a)] -> a
+goCase x def = go
+  where
+    go [] = def
+    go ((k,v):kvs) = ite (x .== literal k) v (go kvs)
+
+sUnless :: (Monad m, Mergeable (m ())) => SBool -> m () -> m ()
+sUnless b = ite b (return ())
+
+sWhen :: (Monad m, Mergeable (m ())) => SBool -> m () -> m ()
+sWhen b act = ite b act (return ())
+
+sFindIndex :: (a -> SBool) -> [a] -> SBV.SMaybe Int16
+sFindIndex p = go 0
+  where
+    go _ [] = SBV.sNothing
+    go i (x:xs) = ite (p x) (SBV.sJust i) (go (i + 1) xs)
diff --git a/SBVTestSuite/TestSuite/Queries/Tuples.hs b/SBVTestSuite/TestSuite/Queries/Tuples.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Tuples.hs
@@ -0,0 +1,68 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TestSuite.Queries.Tuples
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Testing tuple queries
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Tuples (tests)  where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.Tuple hiding(fst)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QueryTuples"
+    [ goldenCapturedIO "query_Tuples1" $ testQuery queryTuples1
+    , goldenCapturedIO "query_Tuples2" $ testQuery queryTuples2
+    ]
+
+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")
+
+queryTuples1 :: Symbolic (Integer, Char)
+queryTuples1 = do
+  a <- sTuple @(Integer, Char) "a"
+
+  constrain $ a^._1 .== 1
+
+  query $ do
+    _ <- checkSat
+
+    av <- getValue a
+
+    if fst av == 1
+       then return av
+       else error $ "Didn't expect this: " ++ show av
+
+queryTuples2 :: Symbolic (Integer, (Char, ()))
+queryTuples2 = do
+  a <- sTuple @(Integer, (Char, ())) "a"
+
+  constrain $ a^._2^._1 .== literal 'c'
+
+  query $ do
+    _ <- checkSat
+
+    av@(_, (c, _)) <- getValue a
+
+    if c == 'c'
+       then return av
+       else error $ "Didn't expect this: " ++ show av
+
+{- HLint ignore module "Use ."        -}
+{- HLint ignore module "Redundant ^." -}
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,66 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.UISat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing UI function sat examples via queries
+-----------------------------------------------------------------------------
+{-# LANGUAGE OverloadedStrings #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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"
+                       DSat{} -> error "Failed! Expected Sat, got delta-satisfiable!"
+                       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,111 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.UISatEx
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing uninterpreted function extraction
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedLists     #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeAbstractions    #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+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
+    , goldenCapturedIO "query_uisatex3" testQuery3
+    ]
+
+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"
+                   registerFunction q6
+                   query $ do 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 :: ConstraintSet
+core = do x <- sInteger_
+          constrain $ q1 2    .== 12
+          constrain $ q1 3    .== 75
+          constrain $ q1 (-3) .== 9
+          constrain $ q1 x    .== x+1
+
+          registerFunction 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
+
+testQuery3 :: FilePath -> IO ()
+testQuery3 rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} t
+                   appendFile rf ("\n FINAL:\n" ++ show r ++ "\nDONE!\n")
+
+  where t = do constrain $ skolemize $ \(Forall @"x" x) (Exists @"y" y) -> y .== 3*(x::SInteger)
+               query $ do cs <- checkSat
+                          case cs of
+                            Sat -> do yv <- getFunction (uninterpret "y" :: SInteger -> SInteger)
+                                      case yv of
+                                        Left x -> pure x
+                                        _      -> error $ "Expected fundef, got: " ++ show yv
+                            _   -> error $ "Expected sat, got: " ++ show cs
+
+-- HLint complains about TypeApplications pragma, but if I remove it GHC complains
+-- I'm not sure who is right here; so ignore.
+{- HLint ignore module "Unused LANGUAGE pragma" -}
diff --git a/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
@@ -0,0 +1,43 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.Uninterpreted
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing uninterpreted value extraction
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeApplications    #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Queries.Uninterpreted where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+data L = A | B deriving Show
+mkSymbolic [''L]
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Queries.Uninterpreted"
+    [ goldenCapturedIO "qUninterp1" testQuery
+    ]
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} unint1
+                  appendFile rf ("\n FINAL:" ++ r ++ "\nDONE!\n")
+
+
+unint1 :: Symbolic String
+unint1 = do (x :: SBV L) <- free_
+
+            query $ do _ <- checkSat
+                       show <$> getValue x
diff --git a/SBVTestSuite/TestSuite/QuickCheck/QC.hs b/SBVTestSuite/TestSuite/QuickCheck/QC.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/QuickCheck/QC.hs
@@ -0,0 +1,59 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.QuickCheck.QC
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Quick-check based test suite for SBV
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE RankNTypes #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.QuickCheck.QC (tests) where
+
+import Utils.SBVTestFramework
+
+unaryArith :: String -> (forall a. Num a => a -> a) -> [TestTree]
+unaryArith nm op =  qc1 (nm ++ ".SWord8"  ) op (op :: SWord8   -> SWord8)
+                 ++ qc1 (nm ++ ".SWord16" ) op (op :: SWord16  -> SWord16)
+                 ++ qc1 (nm ++ ".SWord32" ) op (op :: SWord32  -> SWord32)
+                 ++ qc1 (nm ++ ".SWord64" ) op (op :: SWord64  -> SWord64)
+                 ++ qc1 (nm ++ ".SInt8"   ) op (op :: SInt8    -> SInt8)
+                 ++ qc1 (nm ++ ".SInt16"  ) op (op :: SInt16   -> SInt16)
+                 ++ qc1 (nm ++ ".SInt32"  ) op (op :: SInt32   -> SInt32)
+                 ++ qc1 (nm ++ ".SInt64"  ) op (op :: SInt64   -> SInt64)
+                 ++ qc1 (nm ++ ".SInteger") op (op :: SInteger -> SInteger)
+                 ++ qc1 (nm ++ ".SReal"   ) op (op :: SReal    -> SReal)
+                 ++ qc1 (nm ++ ".SFloat"  ) op (op :: SFloat   -> SFloat)
+                 ++ qc1 (nm ++ ".SDouble" ) op (op :: SDouble  -> SDouble)
+
+binaryArith :: String -> (forall a. Num a => a -> a -> a) -> [TestTree]
+binaryArith nm op = qc2 (nm ++ ".SWord8"  ) op (op :: SWord8   -> SWord8   -> SWord8)
+                 ++ qc2 (nm ++ ".SWord16" ) op (op :: SWord16  -> SWord16  -> SWord16)
+                 ++ qc2 (nm ++ ".SWord32" ) op (op :: SWord32  -> SWord32  -> SWord32)
+                 ++ qc2 (nm ++ ".SWord64" ) op (op :: SWord64  -> SWord64  -> SWord64)
+                 ++ qc2 (nm ++ ".SInt8"   ) op (op :: SInt8    -> SInt8    -> SInt8)
+                 ++ qc2 (nm ++ ".SInt16"  ) op (op :: SInt16   -> SInt16   -> SInt16)
+                 ++ qc2 (nm ++ ".SInt32"  ) op (op :: SInt32   -> SInt32   -> SInt32)
+                 ++ qc2 (nm ++ ".SInt64"  ) op (op :: SInt64   -> SInt64   -> SInt64)
+                 ++ qc2 (nm ++ ".SInteger") op (op :: SInteger -> SInteger -> SInteger)
+                 ++ qc2 (nm ++ ".SReal"   ) op (op :: SReal    -> SReal    -> SReal)
+                 ++ qc2 (nm ++ ".SFloat"  ) op (op :: SFloat   -> SFloat   -> SFloat)
+                 ++ qc2 (nm ++ ".SDouble" ) op (op :: SDouble  -> SDouble  -> SDouble)
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "QuickCheck.QC" [
+            testGroup "Arithmetic" [
+                 testGroup "Unary"  $    unaryArith "negate" negate
+                                      ++ unaryArith "abs"    abs
+                                      ++ unaryArith "signum" signum
+               , testGroup "Binary" $    binaryArith "+"     (+)
+                                      ++ binaryArith "-"     (-)
+                                      ++ binaryArith "*"     (*)
+               ]
+        ]
diff --git a/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs b/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs
@@ -0,0 +1,58 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Transformers.SymbolicEval
+-- Copyright : (c) Brian Schroeder
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Transformers.SymbolicEval
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Transformers.SymbolicEval(tests) where
+
+import Control.Monad.Except (ExceptT, runExceptT, throwError)
+import Data.Either          (isLeft)
+
+import Data.SBV.Trans         (runSMT, sat)
+import Data.SBV.Trans.Control (query)
+
+import Documentation.SBV.Examples.Transformers.SymbolicEval
+import Utils.SBVTestFramework                               hiding (runSMT, sat)
+
+isSat :: SatResult -> Bool
+isSat (SatResult Unsatisfiable{}) = False
+isSat (SatResult Satisfiable{})   = True
+isSat _                           = error "isSat: Unexpected result!"
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Transformers.SymbolicEval"
+    [ testCase "tse_alloc_success" $ assert $
+          (== Right True) . fmap isSat <$>
+            runExceptT (sat $ (.< 5) <$> runAlloc (alloc "x") :: ExceptT String IO SatResult)
+
+    , testCase "tse_alloc_failure" $ assert $
+          (== Left "tried to allocate unnamed value") <$>
+              runExceptT (runSMT (runAlloc (alloc "")))
+
+    , testCase "tse_query_success" $ assert $
+          (== Right (Just True)) . fmap unliteral <$>
+              runExceptT (runSMT (query (runQ (pure $ (5 :: SInt8) .< 6))))
+
+    , testCase "tse_query_failure" $ assert $
+          isLeft <$>
+              runExceptT (runSMT (query (runQ $ throwError "oops")))
+
+    , testCase "tse_combined_success" $ assert $
+          (== Right (Counterexample 0 9)) <$>
+              check (Program  $ Var "x" `Plus` Lit 1 `Plus` Var "y")
+                    (Property $ Var "result" `LessThan` Lit 10)
+
+    , testCase "tse_combined_failure" $ assert $
+          (== Left "unknown variable") <$>
+              check (Program  $ Var "notAValidVar")
+                    (Property $ Var "result" `LessThan` Lit 10)
+    ]
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs b/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs
@@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Uninterpreted.AUF
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for Documentation.SBV.Examples.Uninterpreted.AUF
+-----------------------------------------------------------------------------
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.AUF where
+
+import Documentation.SBV.Examples.Uninterpreted.AUF
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.AUF"
+    [ goldenVsStringShow "auf-1" $ runSAT      $ free "a" >>= \a -> free "x" >>= \x -> free "y" >>= \y -> pure (thm x y (a :: SArray Word32 Word32))
+    , testCase "tc_auf-0"        $ assertIsThm $ free "a" >>= \a -> free "x" >>= \x -> free "y" >>= \y -> pure (thm x y (a :: SArray Word32 Word32))
+    ]
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
@@ -0,0 +1,82 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Uninterpreted.Axioms
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for basic axioms and uninterpreted functions
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.Axioms(tests) where
+
+import Utils.SBVTestFramework
+
+import Data.SBV.Control
+
+data Bitstring
+data B
+data Thing
+
+mkSymbolic [''Bitstring]
+mkSymbolic [''B]
+mkSymbolic [''Thing]
+
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.Axioms"
+    [ goldenCapturedIO "unint-axioms"       $ \rf -> isTheoremWith z3{verbose=True, redirectVerbose=Just rf} p0 >>= \r -> appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+    , goldenCapturedIO "unint-axioms-empty" $ \rf -> isTheoremWith z3{verbose=True, redirectVerbose=Just rf} p1 >>= \r -> appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+    , goldenCapturedIO "unint-axioms-query" testQuery
+    ]
+
+a :: SBitstring -> SBool
+a = uninterpret "a"
+
+e :: SBitstring -> SBitstring -> SBitstring
+e = uninterpret "e"
+
+p0 :: Symbolic SBool
+p0 = do
+    constrain $ \(Forall p) (Forall k) -> a k .&& a p .=> a (e k p)
+    p <- free "p" :: Symbolic SBitstring
+    k <- free "k" :: Symbolic SBitstring
+    constrain $ a p
+    constrain $ a k
+    return $ a (e k p)
+
+thingCompare :: SThing -> SThing -> SBV Bool
+thingCompare = uninterpret "thingCompare"
+
+thingMerge :: SThing -> SThing -> SThing
+thingMerge = uninterpret "thingMerge"
+
+p1 :: Symbolic SBool
+p1 = do constrain $ \(Forall x) -> thingCompare x x
+        constrain $ \(Forall k1) (Forall k2) -> k1 ./= thingMerge k1 k2
+        registerFunction thingMerge
+        k1 <- free_
+        k2 <- free_
+        return $ k1 .== k2 .=> thingCompare k1 k2
+
+testQuery :: FilePath -> IO ()
+testQuery rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} t
+                  appendFile rf ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+ where t = do vp <- free "p"
+              vq <- free "q"
+              vr <- free "r"
+              query $ do let oR, aND :: SB  -> SB -> SB
+                             oR  = uninterpret "OR"
+                             aND = uninterpret "AND"
+                             nOT :: SB -> SB
+                             nOT = uninterpret "NOT"
+                         constrain  $ nOT (vp `oR` (vq `aND` vr)) ./= (nOT vp `aND` nOT vq) `oR` (nOT vp `aND` nOT vr)
+                         constrain $ \(Forall p) (Forall q) (Forall r) -> (p `oR` q) `aND` (p `oR` r) .== p `oR` (q `aND` r)
+                         constrain $ \(Forall p) (Forall q)            -> nOT (p `oR` q) .== nOT p `aND` nOT q
+                         constrain $ \(Forall p)                       -> nOT (nOT p) .== p
+                         checkSat
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/EUFLogic.hs b/SBVTestSuite/TestSuite/Uninterpreted/EUFLogic.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/EUFLogic.hs
@@ -0,0 +1,48 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.EUFLogic
+-- License   : BSD3
+-- Stability : experimental
+--
+-- Test suite for the EUFLogic example
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DataKinds #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.EUFLogic where
+
+import Documentation.SBV.Examples.Uninterpreted.EUFLogic
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.LargeArgs"
+    [ testCase "euflogic-1" $ assertIsSat (interpEUF fourteen)
+    , testCase "unint17arg" $ assertIsSat f17Args
+    ]
+
+fourteen :: EUFExpr Tp_Bool
+fourteen = applyOp (Op_BVEq knownBVWidth)
+                   (applyOp f14 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
+                   (applyOp (Op_Plus knownBVWidth) a b)
+  where
+    f14 :: Op '[Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8,
+                Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8, Tp_BV 8]
+           (Tp_BV 8)
+
+    f14 = mkUnintOp "f"
+    a, b :: EUFExpr (Tp_BV 8)
+    a = mkUnintExpr "a"
+    b = mkUnintExpr "b"
+
+f17Args :: SWord  1 -> SWord  2 -> SWord  3 -> SWord  4 -> SWord  5 -> SWord  6 -> SWord  7 -> SWord 8
+        -> SWord  9 -> SWord 10 -> SWord 11 -> SWord 12 -> SWord 13 -> SWord 14 -> SWord 15 -> SWord 16
+        -> SWord 17
+        -> SBool
+f17Args = uninterpret "f17Args"
+
+{- HLint ignore "Use camelCase" -}
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Function.hs b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
@@ -0,0 +1,171 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Uninterpreted.Function
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testsuite for Documentation.SBV.Examples.Uninterpreted.Function
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.Function(tests) where
+
+import Documentation.SBV.Examples.Uninterpreted.Function
+
+import Utils.SBVTestFramework
+
+data A1
+mkSymbolic [''A1]
+
+data A2
+mkSymbolic [''A2]
+
+data A3
+mkSymbolic [''A3]
+
+data A4
+mkSymbolic [''A4]
+
+data A5
+mkSymbolic [''A5]
+
+data A6
+mkSymbolic [''A6]
+
+data A7
+mkSymbolic [''A7]
+
+data A8
+mkSymbolic [''A8]
+
+data A9
+mkSymbolic [''A9]
+
+data A10
+mkSymbolic [''A10]
+
+data A11
+mkSymbolic [''A11]
+
+data A12
+mkSymbolic [''A12]
+
+
+f1 :: SA1 -> SBool
+f1 = uninterpret "f1"
+
+f2 :: SA1 -> SA2 -> SBool
+f2 = uninterpret "f2"
+
+f3 :: SA1 -> SA2 -> SA3 -> SBool
+f3 = uninterpret "f3"
+
+f4 :: SA1 -> SA2 -> SA3 -> SA4 -> SBool
+f4 = uninterpret "f4"
+
+f5 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SBool
+f5 = uninterpret "f5"
+
+f6 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SBool
+f6 = uninterpret "f6"
+
+f7 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SBool
+f7 = uninterpret "f7"
+
+f8 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SBool
+f8 = uninterpret "f8"
+
+f9 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SBool
+f9 = uninterpret "f9"
+
+f10 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SBool
+f10 = uninterpret "f10"
+
+f11 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SA11 -> SBool
+f11 = uninterpret "f11"
+
+f12 :: SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SA11 -> SA12 -> SBool
+f12 = uninterpret "f12"
+
+thm1 :: SA1 -> SA1 -> SBool
+thm1 x a1 =
+  x .== a1
+  .=> f1 x .== f1 a1
+
+thm2 :: SA1 -> SA1 -> SA2 -> SBool
+thm2 x a1 a2 =
+  x .== a1
+  .=> f2 x a2 .== f2 a1 a2
+
+thm3 :: SA1 -> SA1 -> SA2 -> SA3 -> SBool
+thm3 x a1 a2 a3 =
+  x .== a1
+  .=> f3 x a2 a3 .== f3 a1 a2 a3
+
+thm4 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SBool
+thm4 x a1 a2 a3 a4 =
+  x .== a1
+  .=> f4 x a2 a3 a4 .== f4 a1 a2 a3 a4
+
+thm5 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SBool
+thm5 x a1 a2 a3 a4 a5 =
+  x .== a1
+  .=> f5 x a2 a3 a4 a5 .== f5 a1 a2 a3 a4 a5
+
+thm6 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SBool
+thm6 x a1 a2 a3 a4 a5 a6 =
+  x .== a1
+  .=> f6 x a2 a3 a4 a5 a6 .== f6 a1 a2 a3 a4 a5 a6
+
+thm7 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SBool
+thm7 x a1 a2 a3 a4 a5 a6 a7 =
+  x .== a1
+  .=> f7 x a2 a3 a4 a5 a6 a7 .== f7 a1 a2 a3 a4 a5 a6 a7
+
+thm8 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SBool
+thm8 x a1 a2 a3 a4 a5 a6 a7 a8 =
+  x .== a1
+  .=> f8 x a2 a3 a4 a5 a6 a7 a8 .== f8 a1 a2 a3 a4 a5 a6 a7 a8
+
+thm9 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SBool
+thm9 x a1 a2 a3 a4 a5 a6 a7 a8 a9 =
+  x .== a1
+  .=> f9 x a2 a3 a4 a5 a6 a7 a8 a9 .== f9 a1 a2 a3 a4 a5 a6 a7 a8 a9
+
+thm10 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SBool
+thm10 x a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 =
+  x .== a1
+  .=> f10 x a2 a3 a4 a5 a6 a7 a8 a9 a10 .== f10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
+
+thm11 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SA11 -> SBool
+thm11 x a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 =
+  x .== a1
+  .=> f11 x a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 .== f11 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11
+
+thm12 :: SA1 -> SA1 -> SA2 -> SA3 -> SA4 -> SA5 -> SA6 -> SA7 -> SA8 -> SA9 -> SA10 -> SA11 -> SA12 -> SBool
+thm12 x a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 =
+  x .== a1
+  .=> f12 x a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 .== f12 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12
+
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.Function"
+  [ testCase "aufunc-0" (assertIsThm thmGood)
+  , testCase "aufunc-1" (assertIsThm thm1)
+  , testCase "aufunc-2" (assertIsThm thm2)
+  , testCase "aufunc-3" (assertIsThm thm3)
+  , testCase "aufunc-4" (assertIsThm thm4)
+  , testCase "aufunc-5" (assertIsThm thm5)
+  , testCase "aufunc-6" (assertIsThm thm6)
+  , testCase "aufunc-7" (assertIsThm thm7)
+  , testCase "aufunc-8" (assertIsThm thm8)
+  , testCase "aufunc-9" (assertIsThm thm9)
+  , testCase "aufunc-10" (assertIsThm thm10)
+  , testCase "aufunc-11" (assertIsThm thm11)
+  , testCase "aufunc-12" (assertIsThm thm12)
+  ]
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
@@ -0,0 +1,40 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Uninterpreted.Sort
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for uninterpreted sorts
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.Sort(tests) where
+
+import Utils.SBVTestFramework
+
+data L
+mkSymbolic [''L]
+
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.Sort"
+    [ goldenVsStringShow "unint-sort01" $ allSat p0
+    ]
+
+len :: SL -> SInteger
+len = uninterpret "len"
+
+p0 :: Symbolic SBool
+p0 = do
+    [l, l0, l1] <- symbolics ["l", "l0", "l1"]
+    constrain $ len l0 .== 0
+    constrain $ len l1 .== 1
+    x :: SInteger <- symbolic "x"
+    constrain $ x .== 0 .|| x.== 1
+    return $ l .== l0 .|| l .== l1
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
@@ -0,0 +1,76 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Uninterpreted.Uninterpreted
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE TemplateHaskell #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module TestSuite.Uninterpreted.Uninterpreted(tests) where
+
+import Utils.SBVTestFramework
+
+data Q
+mkSymbolic [''Q]
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Uninterpreted.Uninterpreted"
+    [ testCase         "uninterpreted-0"  $ assertIsThm   p0
+    , testCase         "uninterpreted-1"  $ assertIsThm   p1
+    , goldenCapturedIO "uninterpreted-1a" $ t p1_unc satWith
+    , testCase         "uninterpreted-2"  $ assertIsntThm p2
+    , goldenCapturedIO "uninterpreted-3"  $ t p3 satWith
+    , goldenCapturedIO "uninterpreted-3a" $ t p3 allSatWith
+    , goldenCapturedIO "uninterpreted-4"  $ t p4 satWith
+    , goldenCapturedIO "uninterpreted-4a" $ t p4 allSatWith
+    ]
+  where t tc chk goldFile = do r <- chk defaultSMTCfg{verbose = True, redirectVerbose = Just goldFile} tc
+                               appendFile goldFile ("\n FINAL:" ++ show r ++ "\nDONE!\n")
+
+f :: SInt8 -> SWord32
+f = uninterpret "f"
+
+g :: SInt8 -> SWord16 -> SWord32
+g = uninterpret "g"
+
+p0 :: SInt8 -> SInt8 -> SBool
+p0 x y   = x .== y .=> f x .== f y      -- OK
+
+p1 :: SInt8 -> SWord16 -> SWord16 -> SBool
+p1 x y z = y .== z .=> g x y .== g x z  -- OK
+
+p2 :: SInt8 -> SWord16 -> SWord16 -> SBool
+p2 x y z = y .== z .=> g x y .== f x    -- Not true
+
+-- | Uncurried version of 'g'
+g_unc :: (SInt8, SWord16) -> SWord32
+g_unc = uninterpret "g"
+
+-- | Same as 'p1' but using the uncurried version 'g_unc' of 'g'
+p1_unc :: SInt8 -> SWord16 -> SWord16 -> SBool
+p1_unc x y z = y .== z .=> g_unc (x, y) .== g_unc (x, z)  -- OK
+
+
+a, b :: SBool
+a = sym "p"
+b = sym "q"
+
+p3 :: SBool
+p3 = a .|| b
+
+c, d :: SQ
+c = sym "c"
+d = sym "d"
+
+p4 :: SBool
+p4 = c ./= d
+
+{- HLint ignore type g_unc "Use camelCase" -}
diff --git a/SBVTestSuite/Utils/SBVTestFramework.hs b/SBVTestSuite/Utils/SBVTestFramework.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/Utils/SBVTestFramework.hs
@@ -0,0 +1,342 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Utils.SBVTestFramework
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Various goodies for testing SBV
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies        #-}
+{-# LANGUAGE TypeOperators       #-}
+
+{-# OPTIONS_GHC -Wall -Werror #-}
+
+module Utils.SBVTestFramework (
+          showsAs
+        , runSAT, numberOfModels
+        , assert, assertIsThm, assertIsntThm, assertIsSat, assertIsntSat
+        , goldenString
+        , goldenVsStringShow
+        , goldenCapturedIO
+        , qc1, qc2
+        , shouldNotTypeCheck
+        , mkCompileTest
+        , mkCompileTestGlob
+        -- module exports to simplify life
+        , module Test.Tasty
+        , module Test.Tasty.HUnit
+        , module Data.SBV
+        ) where
+
+import qualified Control.Exception as C
+
+import Control.DeepSeq     (force, NFData)
+import Control.Exception   (evaluate, try, throwIO, TypeError(..))
+import Control.Monad.Trans (liftIO)
+
+import qualified Data.ByteString.Lazy.Char8 as LBC
+import System.Directory   (getCurrentDirectory, removeFile)
+
+import Test.Tasty            (testGroup, TestTree, TestName)
+import Test.Tasty.HUnit      ((@?), Assertion, testCase, AssertionPredicable, assertFailure)
+
+import Test.Tasty.Golden     (goldenVsString, goldenVsFileDiff, goldenVsStringDiff)
+
+import qualified Test.Tasty.QuickCheck   as QC
+import qualified Test.QuickCheck.Monadic as QC
+
+import Test.Tasty.Runners hiding (Result)
+
+import Data.SBV
+import Data.SBV.Control
+
+import System.FilePath      ((</>), (<.>), takeDirectory, takeBaseName)
+import System.FilePath.Glob (glob)
+
+import Data.List       (isInfixOf, isSuffixOf)
+
+import System.Exit
+import System.Process
+import System.IO hiding (stderr)
+
+import System.IO.Temp (withSystemTempDirectory)
+
+import Data.SBV.Internals (runSymbolic, Result, SBVRunMode(..), IStage(..), SBV(..), SVal(..), showModel, SMTModel(..), QueryContext(..), Outputtable)
+
+-- | Generic assertion. This is less safe than usual, but will do.
+assert :: AssertionPredicable t => t -> Assertion
+assert t = t @? "assertion-failure"
+
+-- | Checks that a particular result shows as @s@
+showsAs :: Show a => a -> String -> Assertion
+showsAs r s = assert $ show r == s
+
+goldFile :: FilePath -> FilePath
+goldFile nm = "SBVTestSuite" </> "GoldFiles" </> nm <.> "gold"
+
+goldenString :: TestName -> IO String -> TestTree
+goldenString n res = goldenVsString n (goldFile n) (fmap LBC.pack res)
+
+goldenVsStringShow :: Show a => TestName -> IO a -> TestTree
+goldenVsStringShow n res = goldenVsString n (goldFile n) (fmap (LBC.pack . show) res)
+
+goldenCapturedIO :: TestName -> (FilePath -> IO ()) -> TestTree
+goldenCapturedIO n res = goldenVsFileDiff n diff gf gfTmp (rm gfTmp >> res gfTmp)
+  where gf    = goldFile n
+        gfTmp = gf ++ "_temp"
+        rm f  = removeFile f `C.catch` (\(_ :: C.SomeException) -> return ())
+
+        diff ref new = ["diff", "-u", ref, new]
+
+-- | 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 :: Satisfiable a => a -> IO Int
+numberOfModels p = do AllSatResult { allSatMaxModelCountReached  = maxHit
+                                   , allSatSolverReturnedUnknown = unk
+                                   , allSatSolverReturnedDSat    = ds
+                                   , allSatResults               = rs
+                                   } <- allSat p
+                      let l = length rs
+                      case (unk, ds, 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 solver returned 'delta satisfiable'. 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
+
+-- | Symbolically run a SAT instance using the default config
+runSAT :: Outputtable a => Symbolic a -> IO Result
+runSAT cmp = snd <$> runSymbolic defaultSMTCfg (SMTMode QueryInternal ISetup True defaultSMTCfg) (cmp >>= output >> pure ())
+
+-- | Turn provable to an assertion, theorem case
+assertIsThm :: Provable a => a -> Assertion
+assertIsThm t = assert (isTheorem t)
+
+-- | Turn provable to a negative assertion, theorem case
+assertIsntThm :: Provable a => a -> Assertion
+assertIsntThm t = assert (fmap not (isTheorem t))
+
+-- | Turn provable to an assertion, satisfiability case
+assertIsSat :: Satisfiable a => a -> Assertion
+assertIsSat p = assert (isSatisfiable p)
+
+-- | Turn provable to a negative assertion, satisfiability case
+assertIsntSat :: Satisfiable a => a -> Assertion
+assertIsntSat p = assert (fmap not (isSatisfiable p))
+
+-- | Quick-check a unary function, creating one version for constant folding, and another for solver
+qc1 :: (Eq a, SymVal a, SymVal b, Show a, QC.Arbitrary a, Eq b) => String -> (a -> b) -> (SBV a -> SBV b) -> [TestTree]
+qc1 nm opC opS = [cf, sm]
+   where cf = QC.testProperty (nm ++ ".constantFold") $ \i ->
+                         case unliteral (opS (literal i)) of
+                             Just r -> opC i == r
+                             _      -> False
+
+         sm = QC.testProperty (nm ++ ".symbolic") $ QC.monadicIO $ do
+                        ((i, expected), result) <- QC.run $ runSMT $ do v   <- liftIO $ QC.generate QC.arbitrary
+                                                                        i   <- free_
+                                                                        res <- free_
+
+                                                                        constrain $ i   .== literal v
+                                                                        constrain $ res .== opS i
+
+                                                                        let pre = (v, opC v)
+
+                                                                        query $ do cs <- checkSat
+                                                                                   case cs of
+                                                                                     Unk    -> return (pre, Left "Unexpected: Solver responded Unknown!")
+                                                                                     Unsat  -> return (pre, Left "Unexpected: Solver responded Unsatisfiable!")
+                                                                                     DSat{} -> return (pre, Left "Unexpected: Solver responded Delta-satisfiable!")
+                                                                                     Sat    -> do r <- getValue res
+                                                                                                  return (pre, Right r)
+
+                        let getCV vnm (SBV (SVal _ (Left c))) = (vnm, c)
+                            getCV vnm (SBV (SVal k _       )) = error $ "qc2.getCV: Impossible happened, non-CV value while extracting: " ++ show (vnm, k)
+
+                            vals = [ getCV "i"        (literal i)
+                                   , getCV "Expected" (literal expected)
+                                   ]
+
+                            model = case result of
+                                      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)
+
+                        case result of
+                           Right a -> QC.assert $ expected == a
+                           _       -> QC.assert False
+
+
+-- | Quick-check a binary function, creating one version for constant folding, and another for solver
+qc2 :: (Eq a, Eq b, SymVal a, SymVal b, SymVal c, Show a, Show b, QC.Arbitrary a, QC.Arbitrary b, Eq c) => String -> (a -> b -> c) -> (SBV a -> SBV b -> SBV c) -> [TestTree]
+qc2 nm opC opS = [cf, sm]
+   where cf = QC.testProperty (nm ++ ".constantFold") $ \i j ->
+                         case unliteral (opS (literal i) (literal j)) of
+                             Just r -> opC i j == r
+                             _      -> False
+
+         sm = QC.testProperty (nm ++ ".symbolic") $ QC.monadicIO $ do
+                        ((i1, i2, expected), result) <- QC.run $ runSMT $ do v1  <- liftIO $ QC.generate QC.arbitrary
+                                                                             v2  <- liftIO $ QC.generate QC.arbitrary
+                                                                             i1  <- free_
+                                                                             i2  <- free_
+                                                                             res <- free_
+
+                                                                             constrain $ i1  .== literal v1
+                                                                             constrain $ i2  .== literal v2
+                                                                             constrain $ res .== i1 `opS` i2
+
+                                                                             let pre = (v1, v2, v1 `opC` v2)
+
+                                                                             query $ do cs <- checkSat
+                                                                                        case cs of
+                                                                                          Unk    -> return (pre, Left "Unexpected: Solver responded Unknown!")
+                                                                                          Unsat  -> return (pre, Left "Unexpected: Solver responded Unsatisfiable!")
+                                                                                          DSat{} -> return (pre, Left "Unexpected: Solver responded Delta-satisfiable!")
+                                                                                          Sat    -> do r <- getValue res
+                                                                                                       return (pre, Right r)
+
+                        let getCV vnm (SBV (SVal _ (Left c))) = (vnm, c)
+                            getCV vnm (SBV (SVal k _       )) = error $ "qc2.getCV: Impossible happened, non-CV value while extracting: " ++ show (vnm, k)
+
+                            vals = [ getCV "i1"       (literal i1)
+                                   , getCV "i2"       (literal i2)
+                                   , getCV "Expected" (literal expected)
+                                   ]
+
+                            model = case result of
+                                      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)
+
+                        case result of
+                           Right a -> QC.assert $ expected == a
+                           _       -> QC.assert False
+
+
+-- Adapted from https://github.com/CRogers/should-not-typecheck/blob/2929b8303634fcfe200e8e37b744171aed3a757b/src/Test/ShouldNotTypecheck.hs#L1
+shouldNotTypeCheck :: NFData a => (() ~ () => a) -> Assertion
+shouldNotTypeCheck a = do
+  result <- try (evaluate $ force a)
+  case result of
+    Right _ -> assertFailure "Expected to not compile but it did compile."
+
+    Left e@(TypeError msg)
+      | "(deferred type error)" `isSuffixOf` msg
+      -> case () of
+           () |     "No instance for" `isInfixOf` msg
+                 && "NFData"          `isInfixOf` msg
+              -> assertFailure $ "Make sure the expression has an NFData instance! Full error:\n" ++ msg
+              | True
+              -> pure ()
+      | True
+      -> throwIO e
+
+-- | Like readProcessWithExitCode, but in a given directory
+readProcessInDir :: FilePath -> String -> [String] -> String -> IO (ExitCode, String, String)
+readProcessInDir dir cmd args input = do
+    let cp = (proc cmd args)
+                { cwd     = Just dir
+                , std_in  = CreatePipe
+                , std_out = CreatePipe
+                , std_err = CreatePipe
+                }
+    withCreateProcess cp $ \mIn mOut mErr ph -> do
+        -- feed input if needed
+        case mIn of
+            Just hin -> hPutStr hin input >> hClose hin
+            Nothing  -> return ()
+
+        out <- case mOut of
+            Just hout -> do
+                s <- hGetContents hout
+                _ <- evaluate (length s)  -- force full read
+                return s
+            Nothing -> return ""
+
+        err <- case mErr of
+            Just herr -> do
+                s <- hGetContents herr
+                _ <- evaluate (length s)  -- force full read
+                return s
+            Nothing -> return ""
+
+        exitCode <- waitForProcess ph
+        return (exitCode, out, err)
+
+-- | Make a compilation test from all the files matching glob
+mkCompileTestGlob :: String -> IO [TestTree]
+mkCompileTestGlob g = do fs <- glob g
+                         pure $ map mkCompileTest fs
+
+-- | Make a compilation test
+mkCompileTest :: FilePath -> TestTree
+mkCompileTest file = goldenVsStringDiff nm diffCmd (testDir </> nm <.> "stderr") (compile (nm <.> "hs"))
+  where testDir = takeDirectory file
+        nm      = takeBaseName  file
+
+        diffCmd ref new = ["diff", "-u", ref, new]
+
+        packages = [ "QuickCheck"
+                   , "array"
+                   , "containers"
+                   , "deepseq"
+                   , "libBF"
+                   , "mtl"
+                   , "random"
+                   , "syb"
+                   , "template-haskell"
+                   , "text"
+                   , "time"
+                   , "transformers"
+                   , "uniplate"
+                   ]
+
+        args td  =  "-XHaskell2010 -fforce-recomp -tmpdir " ++ td ++ " -outputdir " ++ td
+                 ++ concat [" -package " ++ pkg | pkg <- packages]
+
+        compile path = withSystemTempDirectory "SBVTempDir" $ \tmpDir -> do
+           -- Use the inplace package DB from dist-newstyle so we pick up
+           -- the locally-built sbv (built by cabal test) without needing
+           -- a separate 'cabal install --lib' step.
+           projRoot <- getCurrentDirectory
+           let cabalFile = projRoot </> "sbv.cabal"
+           ver <- extractVersion <$> readFile cabalFile
+           sbvDBs <- glob (projRoot </> "dist-newstyle/build/*/ghc-*/sbv-" ++ ver ++ "/package.conf.inplace")
+           let pkgDbArgs = case sbvDBs of
+                             (db:_) -> ["-package-db", db]
+                             []     -> []
+           (exitCode, sOut, sErr) <- readProcessInDir testDir "ghc" (pkgDbArgs ++ words (args tmpDir) ++ [path]) ""
+           -- If the source uses -ddump-splices, include stdout (where GHC dumps splices)
+           -- Filter to only keep "Splicing expression" blocks, stripping temp paths and preamble
+           src <- readFile (testDir </> path)
+           let hasDump  = "-ddump-splices" `isInfixOf` src
+               splices  = unlines $ filter (not . skipLine) $ dropWhile (not . isSpliceLine) $ lines sOut
+               out      = if hasDump then splices ++ sErr else sErr
+           case exitCode of
+             ExitSuccess   -> return $ LBC.pack $ if hasDump && not (null splices)
+                                                   then splices
+                                                   else "There was no failure during compilation."
+             ExitFailure _ -> return $ LBC.pack out
+
+        isSpliceLine l = "Splicing expression" `isInfixOf` l
+        skipLine     l = "Loaded package environment" `isInfixOf` l
+                      || "Compiling" `isInfixOf` l
+
+        -- Extract the version string from sbv.cabal
+        extractVersion = go . lines
+          where go []     = error "mkCompileTest: Cannot find Version in sbv.cabal"
+                go (l:ls) = case words l of
+                              ["Version", ":", v] -> v
+                              _                   -> go ls
+
+{- HLint ignore module "Reduce duplication" -}
diff --git a/SBVUnitTest/Examples/Arrays/Memory.hs b/SBVUnitTest/Examples/Arrays/Memory.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Arrays/Memory.hs
+++ /dev/null
@@ -1,43 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Arrays.Memory
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Simple memory abstraction and properties
------------------------------------------------------------------------------
-
-module Examples.Arrays.Memory where
-
-import Data.SBV
-
-type Address = SWord32
-type Value   = SWord64
-type Memory  = SArray Word32 Word64
-
--- | read-after-write: If you write a value and read it back, you'll get it
-raw :: Address -> Value -> Memory -> SBool
-raw a v m = readArray (writeArray m a v) a .== v
-
--- | write-after-write: If you write to the same location twice, then the first one is ignored
-waw :: Address -> Value -> Value -> Memory -> SBool
-waw a v1 v2 m0 = m2 .== m3
-  where m1 = writeArray m0 a v1
-        m2 = writeArray m1 a v2
-        m3 = writeArray m0 a v2
-
--- | Two writes to different locations commute, i.e., can be done in any order
-wcommutesGood :: (Address, Value) -> (Address, Value) -> Memory -> SBool
-wcommutesGood (a, x) (b, y) m = a ./= b ==> wcommutesBad (a, x) (b, y) m
-
--- | Two writes do not commute if they can be done to the same location
-wcommutesBad :: (Address, Value) -> (Address, Value) -> Memory -> SBool
-wcommutesBad (a, x) (b, y) m = writeArray (writeArray m a x) b y .== writeArray (writeArray m b y) a x
-
-tests :: IO ()
-tests = do print =<< prove raw
-           print =<< prove waw
-           print =<< prove wcommutesBad
-           print =<< prove wcommutesGood
diff --git a/SBVUnitTest/Examples/Basics/BasicTests.hs b/SBVUnitTest/Examples/Basics/BasicTests.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Basics/BasicTests.hs
+++ /dev/null
@@ -1,51 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Basics.BasicTests
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Basic tests of the sbv library
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Examples.Basics.BasicTests where
-
-import Data.SBV
-import Data.SBV.Internals
-import SBVTest
-
-test0 :: (forall a. Num a => (a -> a -> a)) -> Word8
-test0 f = f (3 :: Word8) 2
-
-test1, test2, test3, test4, test5 :: (forall a. Num a => (a -> a -> a)) -> IO Result
-test1 f = runSAT $ do let x = literal (3 :: Word8)
-                          y = literal (2 :: Word8)
-                      output $ f x y
-test2 f = runSAT $ do let x = literal (3 :: Word8)
-                      y :: SWord8 <- forall "y"
-                      output $ f x y
-test3 f = runSAT $ do x :: SWord8 <- forall "x"
-                      y :: SWord8 <- forall "y"
-                      output $ f x y
-test4 f = runSAT $ do x :: SWord8 <- forall "x"
-                      output $ f x x
-test5 f = runSAT $ do x :: SWord8 <- forall "x"
-                      let r = f x x
-                      q :: SWord8 <- forall "q"
-                      _ <- output q
-                      output r
-
-f1, f2, f3, f4, f5 :: Num a => a -> a -> a
-f1 x y = (x+y)*(x-y)
-f2 x y = (x*x)-(y*y)
-f3 x y = (x+y)*(x+y)
-f4 x y = let z = x + y in z * z
-f5 x _ = x + 1
-
-{-# ANN f1 "NoHerbie" #-}
-{-# ANN f2 "NoHerbie" #-}
-{-# ANN f3 "NoHerbie" #-}
diff --git a/SBVUnitTest/Examples/Basics/Higher.hs b/SBVUnitTest/Examples/Basics/Higher.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Basics/Higher.hs
+++ /dev/null
@@ -1,49 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Basics.Higher
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Testing function equality
------------------------------------------------------------------------------
-
-module Examples.Basics.Higher where
-
-import Data.SBV
-
-type B = SWord8
-
-f11 :: B -> B
-f11 x = x
-
-f12 :: B -> (B, B)
-f12 x = (x, x)
-
-f21 :: (B, B) -> B
-f21 (x, y) = x + y
-
-f22 :: (B, B) -> (B, B)
-f22 (x, y) = (x, y)
-
-f31 :: B -> B -> B
-f31 x y = x + y
-
-f32 :: B -> B -> (B, B)
-f32 x y = (x, y)
-
-f33 :: B -> B -> B -> (B, B, B)
-f33 x y z = (x, y, z)
-
-
-t :: IO [ThmResult]
-t = sequence [
-       f11 === f11
-     , f12 === f12
-     , f21 === f21
-     , f22 === f22
-     , f31 === f31
-     , f32 === f32
-     , f33 === f33
-     ]
diff --git a/SBVUnitTest/Examples/Basics/Index.hs b/SBVUnitTest/Examples/Basics/Index.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Basics/Index.hs
+++ /dev/null
@@ -1,69 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Basics.Index
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Testing the select function
------------------------------------------------------------------------------
-
-module Examples.Basics.Index where
-
-import Data.SBV
-import SBVTest
-
--- prove that the "select" primitive is working correctly
-test1 :: Int -> IO Bool
-test1 n = isThm $ do
-            elts <- mkForallVars n
-            err  <- forall_
-            ind  <- forall_
-            ind2 <- forall_
-            let r1 = (select :: [SWord8] -> SWord8 -> SInt8 -> SWord8) elts err ind
-                r2 = (select :: [SWord8] -> SWord8 -> SWord8 -> SWord8) elts err ind2
-                r3 = slowSearch elts err ind
-                r4 = slowSearch elts err ind2
-            return $ r1 .== r3 &&& r2 .== r4
- where slowSearch elts err i = ite (i .< 0) err (go elts i)
-         where go []     _      = err
-               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
-
-test2 :: Int -> IO Bool
-test2 n = isThm $ do
-            elts1 <- mkForallVars n
-            elts2 <- mkForallVars n
-            let elts = zip elts1 elts2
-            err1  <- forall_
-            err2  <- forall_
-            let err = (err1, err2)
-            ind  <- forall_
-            ind2 <- forall_
-            let r1 = (select :: [(SWord8, SWord8)] -> (SWord8, SWord8) -> SInt8 -> (SWord8, SWord8)) elts err ind
-                r2 = (select :: [(SWord8, SWord8)] -> (SWord8, SWord8) -> SWord8 -> (SWord8, SWord8)) elts err ind2
-                r3 = slowSearch elts err ind
-                r4 = slowSearch elts err ind2
-            return $ r1 .== r3 &&& r2 .== r4
- where slowSearch elts err i = ite (i .< 0) err (go elts i)
-         where go []     _      = err
-               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
-
-test3 :: Int -> IO Bool
-test3 n = isThm $ do
-            eltsI <- mkForallVars n
-            let elts = map Left eltsI
-            errI  <- forall_
-            let err = Left errI
-            ind  <- forall_
-            let r1 = (select :: [Either SWord8 SWord8] -> Either SWord8 SWord8 -> SInt8 -> Either SWord8 SWord8) elts err ind
-                r2 = slowSearch elts err ind
-            return $ r1 .== r2
- where slowSearch elts err i = ite (i .< 0) err (go elts i)
-         where go []     _      = err
-               go (x:xs) curInd = ite (curInd .== 0) x (go xs (curInd - 1))
-
-tests :: IO ()
-tests = do mapM test1 [0..50] >>= print . and
-           mapM test2 [0..50] >>= print . and
-           mapM test3 [0..50] >>= print . and
diff --git a/SBVUnitTest/Examples/Basics/ProofTests.hs b/SBVUnitTest/Examples/Basics/ProofTests.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Basics/ProofTests.hs
+++ /dev/null
@@ -1,52 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Basics.ProofTests
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Basic proofs
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Examples.Basics.ProofTests where
-
-import Data.SBV
-
-f1, f2, f3, f4 :: Num a => a -> a -> a
-f1 x y = (x+y)*(x-y)
-f2 x y = (x*x)-(y*y)
-f3 x y = (x+y)*(x+y)
-f4 x y = x*x + 2*x*y + y*y
-
-f1eqf2 :: Predicate
-f1eqf2 = forAll_ $ \x y -> f1 x y .== f2 x (y :: SWord8)
-
-f1eqf3 :: Predicate
-f1eqf3 = forAll ["x", "y"] $ \x y -> f1 x y .== f3 x (y :: SWord8)
-
-f3eqf4 :: Predicate
-f3eqf4 = forAll_ $ \x y -> f3 x y .== f4 x (y :: SWord8)
-
-f1Single :: Predicate
-f1Single = forAll_ $ \x -> f1 x x .== (0 :: SWord16)
-
-queries :: IO ()
-queries = do print =<< prove f1eqf2   -- QED
-             print =<< prove f1eqf3   -- No
-             print =<< prove f3eqf4   -- QED
-             print =<< prove f1Single -- QED
-             print =<< sat (do x <- exists "x"
-                               y <- exists "y"
-                               return $ f1 x y .== f2 x (y :: SWord8))  -- yes, any output OK
-             print =<< sat (do x <- exists "x"
-                               y <- exists "y"
-                               return $ f1 x y .== f3 x (y:: SWord8))    -- yes, 0;0
-
-{-# ANN f1 "NoHerbie" #-}
-{-# ANN f2 "NoHerbie" #-}
-{-# ANN f3 "NoHerbie" #-}
-{-# ANN f4 "NoHerbie" #-}
diff --git a/SBVUnitTest/Examples/Basics/QRem.hs b/SBVUnitTest/Examples/Basics/QRem.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Basics/QRem.hs
+++ /dev/null
@@ -1,30 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Basics.QRem
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Testing the sQuotRem and sDivMod
------------------------------------------------------------------------------
-
-module Examples.Basics.QRem where
-
-import Data.SBV
-
--- check: if (a, b) = x `quotRem` y then x = y*a + b
--- same is also true for divMod
--- being careful about y = 0. When divisor is 0, then quotient is
--- defined to be 0 and the remainder is the numerator
-qrem :: (Num a, EqSymbolic a, SDivisible a) => a -> a -> SBool
-qrem x y = ite (y .== 0)
-               ((0, x) .== (q, r) &&& (0, x) .== (d, m))
-               (x .== y * q + r &&& x .== y * d + m)
-  where (q, r) = x `sQuotRem` y
-        (d, m) = x `sDivMod` y
-
-check :: IO ()
-check = do print =<< prove (qrem :: SWord8   -> SWord8   -> SBool)
-           print =<< prove (qrem :: SInt8    -> SInt8    -> SBool)
-           print =<< prove (qrem :: SInteger -> SInteger -> SBool)
diff --git a/SBVUnitTest/Examples/CRC/CCITT.hs b/SBVUnitTest/Examples/CRC/CCITT.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/CRC/CCITT.hs
+++ /dev/null
@@ -1,62 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.CRC.CCITT
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- CRC checks, hamming distance, etc.
------------------------------------------------------------------------------
-
-module Examples.CRC.CCITT where
-
-import Data.SBV
-
--- We don't have native support for 48 bits in Data.SBV
--- So, represent as 32 high-bits and 16 low
-type SWord48 = (SWord32, SWord16)
-
-extendData :: SWord48 -> SWord64
-extendData (h, l) = h # l # 0
-
-mkFrame :: SWord48 -> SWord64
-mkFrame msg@(h, l) = h # l # crc_48_16 msg
-
-crc_48_16 :: SWord48 -> SWord16
-crc_48_16 msg = res
-  where msg64, divisor :: SWord64
-        msg64   = extendData msg
-        divisor = polynomial [16, 12, 5, 0]
-        crc64 = pMod msg64 divisor
-        (_, res) = split (snd (split crc64))
-
-diffCount :: SWord64 -> SWord64 -> SWord8
-diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
-  where count []     = 0
-        count (b:bs) = let r = count bs in ite b r (1+r)
-
--- Claim: If there is an undetected corruption, it must be at least at 4 bits; i.e. HD is 4
-crcGood :: SWord48 -> SWord48 -> SBool
-crcGood sent received =
-     sent ./= received ==> diffCount frameSent frameReceived .> 3
-   where frameSent     = mkFrame sent
-         frameReceived = mkFrame received
-
--- How come we get way more than 168 (= 2*84) counter-examples for this? 
-hw4has84Inhabitants :: SWord48 -> SWord48 -> SBool
-hw4has84Inhabitants sent received = fourBitError
-   where frameSent     = mkFrame sent
-         frameReceived = mkFrame received
-         fourBitError  = diffCount frameSent frameReceived .== 4
-
-hw4 :: IO ()
-hw4 = do res <- allSat hw4has84Inhabitants
-         cnt <- displayModels disp res
-         putStrLn $ "Found: " ++ show cnt ++ " solution(s)."
-   where disp :: Int -> (Bool, (Word32, Word16, Word32, Word16)) -> IO ()
-         disp i (_, (sh, sl, rh, rl)) = do putStrLn $ "Solution #" ++ show i ++ ": "
-                                           putStrLn $ "  Sent    : " ++ binS (mkFrame (literal sh, literal sl))
-                                           putStrLn $ "  Received: " ++ binS (mkFrame (literal rh, literal rl))
-
-{-# ANN crc_48_16 ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/SBVUnitTest/Examples/CRC/CCITT_Unidir.hs b/SBVUnitTest/Examples/CRC/CCITT_Unidir.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/CRC/CCITT_Unidir.hs
+++ /dev/null
@@ -1,60 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.CRC.CCITT_Unidir
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Similar to CCITT. It shows that the CCITT is still HD 3
--- even if we consider only uni-directional errors
------------------------------------------------------------------------------
-
-module Examples.CRC.CCITT_Unidir where
-
-import Data.SBV
-
--- We don't have native support for 48 bits in Data.SBV
--- So, represent as 32 high-bits and 16 low
-type SWord48 = (SWord32, SWord16)
-
-extendData :: SWord48 -> SWord64
-extendData (h, l) = h # l # 0
-
-mkFrame :: SWord48 -> SWord64
-mkFrame msg@(h, l) = h # l # crc_48_16 msg
-
-crc_48_16 :: SWord48 -> SWord16
-crc_48_16 msg = res
-  where msg64, divisor :: SWord64
-        msg64   = extendData msg
-        divisor = polynomial [16, 12, 5, 0]
-        crc64 = pMod msg64 divisor
-        (_, res) = split (snd (split crc64))
-
-diffCount :: [SBool] -> [SBool] -> SWord8
-diffCount xs ys = count $ zipWith (.==) xs ys
-  where count []     = 0
-        count (b:bs) = let r = count bs in ite b r (1+r)
-
--- returns true if there's a 0->1 error (1->0 is ok)
-nonUnidir :: [SBool] -> [SBool] -> SBool
-nonUnidir []     _      = false
-nonUnidir _      []     = false
-nonUnidir (a:as) (b:bs) = (bnot a &&& b) ||| nonUnidir as bs
-
-crcUniGood :: SWord8 -> SWord48 -> SWord48 -> SBool
-crcUniGood hd sent received =
-     sent ./= received ==> nonUnidir frameSent frameReceived ||| diffCount frameSent frameReceived .> hd
-   where frameSent     = blastLE $ mkFrame sent
-         frameReceived = blastLE $ mkFrame received
-
--- Provable, i.e., HD is 3
-ccitHDis3 :: IO ()
-ccitHDis3 = print =<< prove (crcUniGood 3)
-
--- False; i.e., HD doesn't go to 4 just because we only look at uni-directional errors
-ccitHDis4 :: IO ()
-ccitHDis4 = print =<< prove (crcUniGood 4)
-
-{-# ANN crc_48_16 ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/SBVUnitTest/Examples/CRC/GenPoly.hs b/SBVUnitTest/Examples/CRC/GenPoly.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/CRC/GenPoly.hs
+++ /dev/null
@@ -1,75 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.CRC.GenPoly
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Finds good polynomials for CRC's
------------------------------------------------------------------------------
-
-module Examples.CRC.GenPoly where
-
-import Data.SBV
-
--- We don't have native support for 48 bits in Data.SBV
--- So, represent as 32 high-bits and 16 low
-type SWord48 = (SWord32, SWord16)
-
-extendData :: SWord48 -> SWord64
-extendData (h, l) = h # l # 0
-
-mkFrame :: SWord64 -> SWord48 -> SWord64
-mkFrame poly msg@(h, l) = h # l # crc_48_16 msg poly
-
-crc_48_16 :: SWord48 -> SWord64 -> SWord16
-crc_48_16 msg poly = res
-  where msg64 = extendData msg
-        crc64 = pMod msg64 poly
-        (_, res) = split (snd (split crc64))
-
-diffCount :: SWord64 -> SWord64 -> SWord8
-diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
-  where count []     = 0
-        count (b:bs) = let r = count bs in ite b r (1+r)
-
-crcGood :: SWord8 -> SWord16 -> SWord48 -> SWord48 -> SBool
-crcGood hd divisor sent received =
-     sent ./= received ==> diffCount frameSent frameReceived .> hd
-   where frameSent     = mkFrame poly sent
-         frameReceived = mkFrame poly received
-         poly          = mkPoly divisor
-
-mkPoly :: SWord16 -> SWord64
-mkPoly d = 0 # 1 # d
-
--- how long do we wait for each poly.. (seconds)
-waitFor :: Int
-waitFor = 15
-
-genPoly :: SWord8 -> IO ()
-genPoly hd = do putStrLn $ "*** Looking for polynomials with HD = " ++ show hd
-                (skipped, res) <- go 0 [] []
-                putStrLn $ "*** Good polynomials with HD = " ++ show hd
-                mapM_ (\(i, s) -> putStrLn (show i ++ ". " ++ showPoly (mkPoly s)))  (zip [(1::Integer)..] res)
-                putStrLn $ "*** Skipped the followings, proof exceeded timeout value of " ++ show waitFor
-                mapM_ (\(i, s) -> putStrLn (show i ++ ". " ++ showPoly (mkPoly s)))  (zip [(1::Integer)..] skipped)
-                putStrLn "*** Done."
-  where go :: SWord16 -> [SWord16] -> [SWord16] -> IO ([SWord16], [SWord16])
-        go poly skip acc
-         | poly == maxBound = return (skip, acc)
-         | True             = do putStr $ "Testing " ++ showPoly  (mkPoly poly) ++ "... "
-                                 thm <- isTheorem (Just waitFor) $ crcGood hd poly
-                                 case thm of
-                                   Nothing    -> do putStrLn "Timeout, skipping.."
-                                                    go (poly+1) (poly:skip) acc
-                                   Just True  -> do putStrLn "Good!"
-                                                    go (poly+1) skip (poly:acc)
-                                   Just False -> do putStrLn "Bad!"
-                                                    go (poly+1) skip acc
-
-findHD3Polynomials :: IO ()
-findHD3Polynomials = genPoly 3
-
-{-# ANN crc_48_16 ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/SBVUnitTest/Examples/CRC/Parity.hs b/SBVUnitTest/Examples/CRC/Parity.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/CRC/Parity.hs
+++ /dev/null
@@ -1,35 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.CRC.Parity
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Parity check as CRC's
------------------------------------------------------------------------------
-
-module Examples.CRC.Parity where
-
-import Data.SBV
-
-parity :: SWord64 -> SBool
-parity x = bnot (isOdd cnt)
-  where cnt :: SWord8
-        cnt = count (blastLE x)
-
-isOdd :: SWord8 -> SBool
-isOdd x = lsb x .== true
-
--- count the true bits
-count :: [SBool] -> SWord8
-count []     = 0
-count (x:xs) = let c' = count xs in ite x (1+c') c'
-
--- Example suggested by Lee Pike
--- If x and y differ in odd-number of bits, then their parities are flipped
-parityOK :: SWord64 -> SWord64 -> SBool
-parityOK x y = isOdd cnt ==> px .== bnot py
-  where cnt = count (zipWith (./=) (blastLE x) (blastLE y))
-        px  = parity x
-        py  = parity y
diff --git a/SBVUnitTest/Examples/CRC/USB5.hs b/SBVUnitTest/Examples/CRC/USB5.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/CRC/USB5.hs
+++ /dev/null
@@ -1,51 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.CRC.USB5
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- The USB5 CRC implementation
------------------------------------------------------------------------------
-
-module Examples.CRC.USB5 where
-
-import Data.SBV
-
-newtype SWord11 = S11 SWord16
-
-instance EqSymbolic SWord11 where
-  S11 w .== S11 w' = w .== w'
-
-mkSWord11 :: SWord16 -> SWord11
-mkSWord11 w = S11 (w .&. 0x07FF)
-
-extendData :: SWord11 -> SWord16
-extendData (S11 w) = w `shiftL` 5
-
-mkFrame :: SWord11 -> SWord16
-mkFrame w = extendData w .|. crc_11_16 w
-
--- crc returns 16 bits, but the first 11 are always 0
-crc_11_16 :: SWord11 -> SWord16
-crc_11_16 msg = crc16 .&. 0x1F -- just get the last 5 bits
-  where divisor :: SWord16
-        divisor = polynomial [5, 2, 0]
-        crc16 = pMod (extendData msg) divisor
-
-diffCount :: SWord16 -> SWord16 -> SWord8
-diffCount x y = count $ zipWith (.==) (blastLE x) (blastLE y)
-  where count []     = 0
-        count (b:bs) = let r = count bs in ite b r (1+r)
-
--- Claim: If there is an undetected corruption, it must be at least at 3 bits
-usbGood :: SWord16 -> SWord16 -> SBool
-usbGood sent16 received16 =
-    sent ./= received ==> diffCount frameSent frameReceived .>= 3
-   where sent     = mkSWord11 sent16
-         received = mkSWord11 received16
-         frameSent     = mkFrame sent
-         frameReceived = mkFrame received
-
-{-# ANN crc_11_16 ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/SBVUnitTest/Examples/Puzzles/PowerSet.hs b/SBVUnitTest/Examples/Puzzles/PowerSet.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Puzzles/PowerSet.hs
+++ /dev/null
@@ -1,34 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Puzzles.PowerSet
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Computes the powerset of a givenset
------------------------------------------------------------------------------
-
-module Examples.Puzzles.PowerSet where
-
-import Data.SBV
-
-genPowerSet :: [SBool] -> SBool
--- The following definition reveals an issue in Yices's model generation. The
--- seemingly vacuous test of checking true-or-false is necessary
--- so that Yices will return a satisfying assignment
--- otherwise, it just skips the "unused" inputs..
-genPowerSet = bAll isBool
-  where isBool x = x .== true ||| x .== false
-
-powerSet :: [Word8] -> IO ()
-powerSet xs = do putStrLn $ "Finding all subsets of " ++ show xs
-                 res <- allSat $ genPowerSet `fmap` mkExistVars n
-                 cnt <- displayModels disp res
-                 putStrLn $ "Found: " ++ show cnt ++ " subset(s)."
-     where n = length xs
-           disp i (_, ss)
-            | length ss /= n = error $ "Expected " ++ show n ++ " results; got: " ++ show (length ss)
-            | True           = putStrLn $ "Subset #" ++ show i ++ ": " ++ show (concat (zipWith pick ss xs))
-           pick True a  = [a]
-           pick False _ = []
diff --git a/SBVUnitTest/Examples/Puzzles/Temperature.hs b/SBVUnitTest/Examples/Puzzles/Temperature.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Puzzles/Temperature.hs
+++ /dev/null
@@ -1,39 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Puzzles.Temperature
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Puzzle:
---   What 2 digit fahrenheit/celcius values are reverses of each other?
---   Ignoring the fractions in the conversion
------------------------------------------------------------------------------
-
-module Examples.Puzzles.Temperature where
-
-import Data.SBV
-
-type Temp = SInteger
-
--- convert celcius to fahrenheit, rounding up/down properly
--- we have to be careful here to make sure rounding is done properly..
-d2f :: Temp -> Temp
-d2f d = 32 + ite (fr .>= 5) (1+fi) fi
-  where (fi, fr) = (18 * d) `sQuotRem` 10
-
--- puzzle: What 2 digit fahrenheit/celcius values are reverses of each other?
-revOf :: Temp -> SBool
-revOf c = swap (digits c) .== digits (d2f c)
-  where digits x = x `sQuotRem` 10
-        swap (a, b) = (b, a)
-
-puzzle :: IO ()
-puzzle = do res <- allSat $ revOf `fmap` exists_
-            cnt <- displayModels disp res
-            putStrLn $ "Found " ++ show cnt ++ " solutions."
-     where disp :: Int -> (Bool, Integer) -> IO ()
-           disp _ (_, x) = putStrLn $ " " ++ show x ++ "C --> " ++ show (round f :: Integer) ++ "F (exact value: " ++ show f ++ "F)"
-              where f :: Double
-                    f  = 32 + (9 * fromIntegral x) / 5
diff --git a/SBVUnitTest/Examples/Uninterpreted/Uninterpreted.hs b/SBVUnitTest/Examples/Uninterpreted/Uninterpreted.hs
deleted file mode 100644
--- a/SBVUnitTest/Examples/Uninterpreted/Uninterpreted.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.Uninterpreted.Uninterpreted
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Testing uninterpreted functions
------------------------------------------------------------------------------
-
-module Examples.Uninterpreted.Uninterpreted where
-
-import Data.SBV
-
-f :: SInt8 -> SWord32
-f = uninterpret "f"
-
-g :: SInt8 -> SWord16 -> SWord32
-g = uninterpret "g"
-
-p0 :: SInt8 -> SInt8 -> SBool
-p0 x y   = x .== y ==> f x .== f y      -- OK
-
-p1 :: SInt8 -> SWord16 -> SWord16 -> SBool
-p1 x y z = y .== z ==> g x y .== g x z  -- OK
-
-p2 :: SInt8 -> SWord16 -> SWord16 -> SBool
-p2 x y z = y .== z ==> g x y .== f x    -- Not true
diff --git a/SBVUnitTest/GoldFiles/U2Bridge.gold b/SBVUnitTest/GoldFiles/U2Bridge.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/U2Bridge.gold
+++ /dev/null
@@ -1,16 +0,0 @@
-Satisfiable. Model:
-  s0  = False :: Bool
-  s1  =  Edge :: U2Member
-  s2  =  Bono :: U2Member
-  s3  =  True :: Bool
-  s4  =  Edge :: U2Member
-  s5  =  Bono :: U2Member
-  s6  = False :: Bool
-  s7  = Larry :: U2Member
-  s8  =  Adam :: U2Member
-  s9  =  True :: Bool
-  s10 =  Bono :: U2Member
-  s11 =  Bono :: U2Member
-  s12 = False :: Bool
-  s13 =  Edge :: U2Member
-  s14 =  Bono :: U2Member
diff --git a/SBVUnitTest/GoldFiles/addSub.gold b/SBVUnitTest/GoldFiles/addSub.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/addSub.gold
+++ /dev/null
@@ -1,105 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for addSub. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: addSub_driver
-
-addSub.o: addSub.c addSub.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-addSub_driver.o: addSub_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-addSub_driver: addSub.o addSub_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f addSub_driver
-== END: "Makefile" ==================
-== BEGIN: "addSub.h" ================
-/* Header file for addSub. Automatically generated by SBV. Do not edit! */
-
-#ifndef __addSub__HEADER_INCLUDED__
-#define __addSub__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
-            SWord8 *dif);
-
-#endif /* __addSub__HEADER_INCLUDED__ */
-== END: "addSub.h" ==================
-== BEGIN: "addSub_driver.c" ================
-/* Example driver program for addSub. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "addSub.h"
-
-int main(void)
-{
-  SWord8 sum;
-  SWord8 dif;
-
-  addSub(76, 92, &sum, &dif);
-
-  printf("addSub(76, 92, &sum, &dif) ->\n");
-  printf("  sum = %"PRIu8"\n", sum);
-  printf("  dif = %"PRIu8"\n", dif);
-
-  return 0;
-}
-== END: "addSub_driver.c" ==================
-== BEGIN: "addSub.c" ================
-/* File: "addSub.c". Automatically generated by SBV. Do not edit! */
-
-#include "addSub.h"
-
-void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
-            SWord8 *dif)
-{
-  const SWord8 s0 = x;
-  const SWord8 s1 = y;
-  const SWord8 s2 = s0 + s1;
-  const SWord8 s3 = s0 - s1;
-
-  *sum = s2;
-  *dif = s3;
-}
-== END: "addSub.c" ==================
diff --git a/SBVUnitTest/GoldFiles/aes128Dec.gold b/SBVUnitTest/GoldFiles/aes128Dec.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/aes128Dec.gold
+++ /dev/null
@@ -1,2609 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for aes128Dec. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: aes128Dec_driver
-
-aes128Dec.o: aes128Dec.c aes128Dec.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128Dec_driver.o: aes128Dec_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128Dec_driver: aes128Dec.o aes128Dec_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f aes128Dec_driver
-== END: "Makefile" ==================
-== BEGIN: "aes128Dec.h" ================
-/* Header file for aes128Dec. Automatically generated by SBV. Do not edit! */
-
-#ifndef __aes128Dec__HEADER_INCLUDED__
-#define __aes128Dec__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-void aes128Dec(const SWord32 *pt, const SWord32 *key, SWord32 *ct);
-
-#endif /* __aes128Dec__HEADER_INCLUDED__ */
-== END: "aes128Dec.h" ==================
-== BEGIN: "aes128Dec_driver.c" ================
-/* Example driver program for aes128Dec. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "aes128Dec.h"
-
-int main(void)
-{
-  const SWord32 pt[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array pt:\n");
-  int pt_ctr;
-  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
-    printf("  pt[%d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
-
-  const SWord32 key[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array key:\n");
-  int key_ctr;
-  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
-    printf("  key[%d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
-
-  SWord32 ct[4];
-
-  aes128Dec(pt, key, ct);
-
-  printf("aes128Dec(pt, key, ct) ->\n");
-  int ct_ctr;
-  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
-    printf("  ct[%d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
-
-  return 0;
-}
-== END: "aes128Dec_driver.c" ==================
-== BEGIN: "aes128Dec.c" ================
-/* File: "aes128Dec.c". Automatically generated by SBV. Do not edit! */
-
-#include "aes128Dec.h"
-
-void aes128Dec(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
-{
-  const SWord32 s0 = pt[0];
-  const SWord32 s1 = pt[1];
-  const SWord32 s2 = pt[2];
-  const SWord32 s3 = pt[3];
-  const SWord32 s4 = key[0];
-  const SWord32 s5 = key[1];
-  const SWord32 s6 = key[2];
-  const SWord32 s7 = key[3];
-  static const SWord8 table0[] = {
-       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129,
-      243, 215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,
-       67,  68, 196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,
-       61, 238,  76, 149,  11,  66, 250, 195,  78,   8,  46, 161, 102,
-       40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 114,
-      248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101,
-      182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,
-       87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10,
-      247, 228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,
-       63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,  58, 145,
-       17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230,
-      115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,
-       28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 111,
-      183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
-      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
-       51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
-       96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147,
-      201, 156, 239, 160, 224,  59,  77, 174,  42, 245, 176, 200, 235,
-      187,  60, 131,  83, 153,  97,  23,  43,   4, 126, 186, 119, 214,
-       38, 225, 105,  20,  99,  85,  33,  12, 125
-  };
-  static const SWord32 table1[] = {
-      0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
-      0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
-      0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
-      0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
-      0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
-      0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
-      0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
-      0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
-      0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
-      0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
-      0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
-      0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
-      0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
-      0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
-      0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
-      0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
-      0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
-      0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
-      0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
-      0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
-      0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
-      0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
-      0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
-      0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
-      0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
-      0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
-      0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
-      0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
-      0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
-      0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
-      0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
-      0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
-      0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
-      0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
-      0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
-      0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
-      0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
-      0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
-      0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
-      0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
-      0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
-      0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
-      0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
-      0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
-      0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
-      0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
-      0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
-      0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
-      0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
-      0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
-      0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
-      0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
-      0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
-      0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
-      0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
-      0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
-      0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
-      0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
-      0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
-      0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
-      0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
-      0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
-      0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
-      0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL
-  };
-  static const SWord8 table2[] = {
-       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
-      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
-      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
-      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
-       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
-      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
-       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
-       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
-       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
-      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
-       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
-      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
-      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
-      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
-       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
-       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
-      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
-      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
-      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
-      104,  65, 153,  45,  15, 176,  84, 187,  22
-  };
-  static const SWord32 table3[] = {
-      0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
-      0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
-      0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
-      0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
-      0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
-      0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
-      0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
-      0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
-      0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
-      0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
-      0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
-      0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
-      0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
-      0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
-      0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
-      0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
-      0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
-      0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
-      0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
-      0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
-      0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
-      0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
-      0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
-      0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
-      0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
-      0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
-      0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
-      0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
-      0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
-      0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
-      0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
-      0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
-      0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
-      0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
-      0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
-      0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
-      0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
-      0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
-      0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
-      0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
-      0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
-      0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
-      0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
-      0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
-      0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
-      0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
-      0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
-      0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
-      0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
-      0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
-      0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
-      0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
-      0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
-      0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
-      0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
-      0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
-      0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
-      0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
-      0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
-      0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
-      0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
-      0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
-      0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
-      0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL
-  };
-  static const SWord32 table4[] = {
-      0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
-      0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
-      0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
-      0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
-      0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
-      0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
-      0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
-      0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
-      0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
-      0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
-      0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
-      0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
-      0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
-      0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
-      0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
-      0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
-      0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
-      0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
-      0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
-      0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
-      0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
-      0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
-      0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
-      0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
-      0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
-      0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
-      0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
-      0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
-      0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
-      0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
-      0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
-      0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
-      0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
-      0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
-      0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
-      0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
-      0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
-      0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
-      0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
-      0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
-      0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
-      0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
-      0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
-      0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
-      0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
-      0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
-      0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
-      0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
-      0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
-      0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
-      0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
-      0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
-      0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
-      0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
-      0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
-      0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
-      0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
-      0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
-      0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
-      0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
-      0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
-      0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
-      0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
-      0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL
-  };
-  static const SWord32 table5[] = {
-      0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
-      0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
-      0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
-      0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
-      0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
-      0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
-      0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
-      0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
-      0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
-      0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
-      0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
-      0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
-      0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
-      0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
-      0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
-      0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
-      0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
-      0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
-      0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
-      0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
-      0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
-      0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
-      0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
-      0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
-      0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
-      0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
-      0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
-      0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
-      0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
-      0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
-      0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
-      0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
-      0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
-      0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
-      0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
-      0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
-      0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
-      0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
-      0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
-      0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
-      0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
-      0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
-      0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
-      0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
-      0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
-      0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
-      0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
-      0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
-      0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
-      0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
-      0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
-      0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
-      0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
-      0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
-      0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
-      0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
-      0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
-      0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
-      0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
-      0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
-      0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
-      0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
-      0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
-      0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL
-  };
-  static const SWord8 table6[] = {
-        0,  14,  28,  18,  56,  54,  36,  42, 112, 126, 108,  98,  72,
-       70,  84,  90, 224, 238, 252, 242, 216, 214, 196, 202, 144, 158,
-      140, 130, 168, 166, 180, 186, 219, 213, 199, 201, 227, 237, 255,
-      241, 171, 165, 183, 185, 147, 157, 143, 129,  59,  53,  39,  41,
-        3,  13,  31,  17,  75,  69,  87,  89, 115, 125, 111,  97, 173,
-      163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235,
-      249, 247,  77,  67,  81,  95, 117, 123, 105, 103,  61,  51,  33,
-       47,   5,  11,  25,  23, 118, 120, 106, 100,  78,  64,  82,  92,
-        6,   8,  26,  20,  62,  48,  34,  44, 150, 152, 138, 132, 174,
-      160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204,  65,  79,
-       93,  83, 121, 119, 101, 107,  49,  63,  45,  35,   9,   7,  21,
-       27, 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205, 195,
-      233, 231, 245, 251, 154, 148, 134, 136, 162, 172, 190, 176, 234,
-      228, 246, 248, 210, 220, 206, 192, 122, 116, 102, 104,  66,  76,
-       94,  80,  10,   4,  22,  24,  50,  60,  46,  32, 236, 226, 240,
-      254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182,
-       12,   2,  16,  30,  52,  58,  40,  38, 124, 114,  96, 110,  68,
-       74,  88,  86,  55,  57,  43,  37,  15,   1,  19,  29,  71,  73,
-       91,  85, 127, 113,  99, 109, 215, 217, 203, 197, 239, 225, 243,
-      253, 167, 169, 187, 181, 159, 145, 131, 141
-  };
-  static const SWord8 table7[] = {
-        0,  11,  22,  29,  44,  39,  58,  49,  88,  83,  78,  69, 116,
-      127,  98, 105, 176, 187, 166, 173, 156, 151, 138, 129, 232, 227,
-      254, 245, 196, 207, 210, 217, 123, 112, 109, 102,  87,  92,  65,
-       74,  35,  40,  53,  62,  15,   4,  25,  18, 203, 192, 221, 214,
-      231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, 246,
-      253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137,
-      148, 159,  70,  77,  80,  91, 106,  97, 124, 119,  30,  21,   8,
-        3,  50,  57,  36,  47, 141, 134, 155, 144, 161, 170, 183, 188,
-      213, 222, 195, 200, 249, 242, 239, 228,  61,  54,  43,  32,  17,
-       26,   7,  12, 101, 110, 115, 120,  73,  66,  95,  84, 247, 252,
-      225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149,
-      158,  71,  76,  81,  90, 107,  96, 125, 118,  31,  20,   9,   2,
-       51,  56,  37,  46, 140, 135, 154, 145, 160, 171, 182, 189, 212,
-      223, 194, 201, 248, 243, 238, 229,  60,  55,  42,  33,  16,  27,
-        6,  13, 100, 111, 114, 121,  72,  67,  94,  85,   1,  10,  23,
-       28,  45,  38,  59,  48,  89,  82,  79,  68, 117, 126,  99, 104,
-      177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197,
-      206, 211, 216, 122, 113, 108, 103,  86,  93,  64,  75,  34,  41,
-       52,  63,  14,   5,  24,  19, 202, 193, 220, 215, 230, 237, 240,
-      251, 146, 153, 132, 143, 190, 181, 168, 163
-  };
-  static const SWord8 table8[] = {
-        0,  13,  26,  23,  52,  57,  46,  35, 104, 101, 114, 127,  92,
-       81,  70,  75, 208, 221, 202, 199, 228, 233, 254, 243, 184, 181,
-      162, 175, 140, 129, 150, 155, 187, 182, 161, 172, 143, 130, 149,
-      152, 211, 222, 201, 196, 231, 234, 253, 240, 107, 102, 113, 124,
-       95,  82,  69,  72,   3,  14,  25,  20,  55,  58,  45,  32, 109,
-       96, 119, 122,  89,  84,  67,  78,   5,   8,  31,  18,  49,  60,
-       43,  38, 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207,
-      194, 225, 236, 251, 246, 214, 219, 204, 193, 226, 239, 248, 245,
-      190, 179, 164, 169, 138, 135, 144, 157,   6,  11,  28,  17,  50,
-       63,  40,  37, 110,  99, 116, 121,  90,  87,  64,  77, 218, 215,
-      192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156,
-      145,  10,   7,  16,  29,  62,  51,  36,  41,  98, 111, 120, 117,
-       86,  91,  76,  65,  97, 108, 123, 118,  85,  88,  79,  66,   9,
-        4,  19,  30,  61,  48,  39,  42, 177, 188, 171, 166, 133, 136,
-      159, 146, 217, 212, 195, 206, 237, 224, 247, 250, 183, 186, 173,
-      160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252,
-      103, 106, 125, 112,  83,  94,  73,  68,  15,   2,  21,  24,  59,
-       54,  33,  44,  12,   1,  22,  27,  56,  53,  34,  47, 100, 105,
-      126, 115,  80,  93,  74,  71, 220, 209, 198, 203, 232, 229, 242,
-      255, 180, 185, 174, 163, 128, 141, 154, 151
-  };
-  static const SWord8 table9[] = {
-        0,   9,  18,  27,  36,  45,  54,  63,  72,  65,  90,  83, 108,
-      101, 126, 119, 144, 153, 130, 139, 180, 189, 166, 175, 216, 209,
-      202, 195, 252, 245, 238, 231,  59,  50,  41,  32,  31,  22,  13,
-        4, 115, 122,  97, 104,  87,  94,  69,  76, 171, 162, 185, 176,
-      143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, 118,
-      127, 100, 109,  82,  91,  64,  73,  62,  55,  44,  37,  26,  19,
-        8,   1, 230, 239, 244, 253, 194, 203, 208, 217, 174, 167, 188,
-      181, 138, 131, 152, 145,  77,  68,  95,  86, 105,  96, 123, 114,
-        5,  12,  23,  30,  33,  40,  51,  58, 221, 212, 207, 198, 249,
-      240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, 236, 229,
-      254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146,
-      155, 124, 117, 110, 103,  88,  81,  74,  67,  52,  61,  38,  47,
-       16,  25,   2,  11, 215, 222, 197, 204, 243, 250, 225, 232, 159,
-      150, 141, 132, 187, 178, 169, 160,  71,  78,  85,  92,  99, 106,
-      113, 120,  15,   6,  29,  20,  43,  34,  57,  48, 154, 147, 136,
-      129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237,
-       10,   3,  24,  17,  46,  39,  60,  53,  66,  75,  80,  89, 102,
-      111, 116, 125, 161, 168, 179, 186, 133, 140, 151, 158, 233, 224,
-      251, 242, 205, 196, 223, 214,  49,  56,  35,  42,  21,  28,   7,
-       14, 121, 112, 107,  98,  93,  84,  79,  70
-  };
-  const SWord32 s520 = (s7 << 8) | (s7 >> 24);
-  const SWord16 s521 = (SWord16) (s520 >> 16);
-  const SWord8  s522 = (SWord8) (s521 >> 8);
-  const SWord8  s523 = table2[s522];
-  const SWord8  s524 = 1 ^ s523;
-  const SWord8  s525 = (SWord8) s521;
-  const SWord8  s526 = table2[s525];
-  const SWord16 s527 = (((SWord16) s524) << 8) | ((SWord16) s526);
-  const SWord16 s528 = (SWord16) s520;
-  const SWord8  s529 = (SWord8) (s528 >> 8);
-  const SWord8  s530 = table2[s529];
-  const SWord8  s531 = (SWord8) s528;
-  const SWord8  s532 = table2[s531];
-  const SWord16 s533 = (((SWord16) s530) << 8) | ((SWord16) s532);
-  const SWord32 s534 = (((SWord32) s527) << 16) | ((SWord32) s533);
-  const SWord32 s535 = s4 ^ s534;
-  const SWord32 s536 = s5 ^ s535;
-  const SWord32 s537 = s6 ^ s536;
-  const SWord32 s538 = s7 ^ s537;
-  const SWord32 s539 = (s538 << 8) | (s538 >> 24);
-  const SWord16 s540 = (SWord16) (s539 >> 16);
-  const SWord8  s541 = (SWord8) (s540 >> 8);
-  const SWord8  s542 = table2[s541];
-  const SWord8  s543 = 2 ^ s542;
-  const SWord8  s544 = (SWord8) s540;
-  const SWord8  s545 = table2[s544];
-  const SWord16 s546 = (((SWord16) s543) << 8) | ((SWord16) s545);
-  const SWord16 s547 = (SWord16) s539;
-  const SWord8  s548 = (SWord8) (s547 >> 8);
-  const SWord8  s549 = table2[s548];
-  const SWord8  s550 = (SWord8) s547;
-  const SWord8  s551 = table2[s550];
-  const SWord16 s552 = (((SWord16) s549) << 8) | ((SWord16) s551);
-  const SWord32 s553 = (((SWord32) s546) << 16) | ((SWord32) s552);
-  const SWord32 s554 = s535 ^ s553;
-  const SWord32 s555 = s536 ^ s554;
-  const SWord32 s556 = s537 ^ s555;
-  const SWord32 s557 = s538 ^ s556;
-  const SWord32 s558 = (s557 << 8) | (s557 >> 24);
-  const SWord16 s559 = (SWord16) (s558 >> 16);
-  const SWord8  s560 = (SWord8) (s559 >> 8);
-  const SWord8  s561 = table2[s560];
-  const SWord8  s562 = 4 ^ s561;
-  const SWord8  s563 = (SWord8) s559;
-  const SWord8  s564 = table2[s563];
-  const SWord16 s565 = (((SWord16) s562) << 8) | ((SWord16) s564);
-  const SWord16 s566 = (SWord16) s558;
-  const SWord8  s567 = (SWord8) (s566 >> 8);
-  const SWord8  s568 = table2[s567];
-  const SWord8  s569 = (SWord8) s566;
-  const SWord8  s570 = table2[s569];
-  const SWord16 s571 = (((SWord16) s568) << 8) | ((SWord16) s570);
-  const SWord32 s572 = (((SWord32) s565) << 16) | ((SWord32) s571);
-  const SWord32 s573 = s554 ^ s572;
-  const SWord32 s574 = s555 ^ s573;
-  const SWord32 s575 = s556 ^ s574;
-  const SWord32 s576 = s557 ^ s575;
-  const SWord32 s577 = (s576 << 8) | (s576 >> 24);
-  const SWord16 s578 = (SWord16) (s577 >> 16);
-  const SWord8  s579 = (SWord8) (s578 >> 8);
-  const SWord8  s580 = table2[s579];
-  const SWord8  s581 = 8 ^ s580;
-  const SWord8  s582 = (SWord8) s578;
-  const SWord8  s583 = table2[s582];
-  const SWord16 s584 = (((SWord16) s581) << 8) | ((SWord16) s583);
-  const SWord16 s585 = (SWord16) s577;
-  const SWord8  s586 = (SWord8) (s585 >> 8);
-  const SWord8  s587 = table2[s586];
-  const SWord8  s588 = (SWord8) s585;
-  const SWord8  s589 = table2[s588];
-  const SWord16 s590 = (((SWord16) s587) << 8) | ((SWord16) s589);
-  const SWord32 s591 = (((SWord32) s584) << 16) | ((SWord32) s590);
-  const SWord32 s592 = s573 ^ s591;
-  const SWord32 s593 = s574 ^ s592;
-  const SWord32 s594 = s575 ^ s593;
-  const SWord32 s595 = s576 ^ s594;
-  const SWord32 s596 = (s595 << 8) | (s595 >> 24);
-  const SWord16 s597 = (SWord16) (s596 >> 16);
-  const SWord8  s598 = (SWord8) (s597 >> 8);
-  const SWord8  s599 = table2[s598];
-  const SWord8  s600 = 16 ^ s599;
-  const SWord8  s601 = (SWord8) s597;
-  const SWord8  s602 = table2[s601];
-  const SWord16 s603 = (((SWord16) s600) << 8) | ((SWord16) s602);
-  const SWord16 s604 = (SWord16) s596;
-  const SWord8  s605 = (SWord8) (s604 >> 8);
-  const SWord8  s606 = table2[s605];
-  const SWord8  s607 = (SWord8) s604;
-  const SWord8  s608 = table2[s607];
-  const SWord16 s609 = (((SWord16) s606) << 8) | ((SWord16) s608);
-  const SWord32 s610 = (((SWord32) s603) << 16) | ((SWord32) s609);
-  const SWord32 s611 = s592 ^ s610;
-  const SWord32 s612 = s593 ^ s611;
-  const SWord32 s613 = s594 ^ s612;
-  const SWord32 s614 = s595 ^ s613;
-  const SWord32 s615 = (s614 << 8) | (s614 >> 24);
-  const SWord16 s616 = (SWord16) (s615 >> 16);
-  const SWord8  s617 = (SWord8) (s616 >> 8);
-  const SWord8  s618 = table2[s617];
-  const SWord8  s619 = 32 ^ s618;
-  const SWord8  s620 = (SWord8) s616;
-  const SWord8  s621 = table2[s620];
-  const SWord16 s622 = (((SWord16) s619) << 8) | ((SWord16) s621);
-  const SWord16 s623 = (SWord16) s615;
-  const SWord8  s624 = (SWord8) (s623 >> 8);
-  const SWord8  s625 = table2[s624];
-  const SWord8  s626 = (SWord8) s623;
-  const SWord8  s627 = table2[s626];
-  const SWord16 s628 = (((SWord16) s625) << 8) | ((SWord16) s627);
-  const SWord32 s629 = (((SWord32) s622) << 16) | ((SWord32) s628);
-  const SWord32 s630 = s611 ^ s629;
-  const SWord32 s631 = s612 ^ s630;
-  const SWord32 s632 = s613 ^ s631;
-  const SWord32 s633 = s614 ^ s632;
-  const SWord32 s634 = (s633 << 8) | (s633 >> 24);
-  const SWord16 s635 = (SWord16) (s634 >> 16);
-  const SWord8  s636 = (SWord8) (s635 >> 8);
-  const SWord8  s637 = table2[s636];
-  const SWord8  s638 = 64 ^ s637;
-  const SWord8  s639 = (SWord8) s635;
-  const SWord8  s640 = table2[s639];
-  const SWord16 s641 = (((SWord16) s638) << 8) | ((SWord16) s640);
-  const SWord16 s642 = (SWord16) s634;
-  const SWord8  s643 = (SWord8) (s642 >> 8);
-  const SWord8  s644 = table2[s643];
-  const SWord8  s645 = (SWord8) s642;
-  const SWord8  s646 = table2[s645];
-  const SWord16 s647 = (((SWord16) s644) << 8) | ((SWord16) s646);
-  const SWord32 s648 = (((SWord32) s641) << 16) | ((SWord32) s647);
-  const SWord32 s649 = s630 ^ s648;
-  const SWord32 s650 = s631 ^ s649;
-  const SWord32 s651 = s632 ^ s650;
-  const SWord32 s652 = s633 ^ s651;
-  const SWord32 s653 = (s652 << 8) | (s652 >> 24);
-  const SWord16 s654 = (SWord16) (s653 >> 16);
-  const SWord8  s655 = (SWord8) (s654 >> 8);
-  const SWord8  s656 = table2[s655];
-  const SWord8  s657 = 128 ^ s656;
-  const SWord8  s658 = (SWord8) s654;
-  const SWord8  s659 = table2[s658];
-  const SWord16 s660 = (((SWord16) s657) << 8) | ((SWord16) s659);
-  const SWord16 s661 = (SWord16) s653;
-  const SWord8  s662 = (SWord8) (s661 >> 8);
-  const SWord8  s663 = table2[s662];
-  const SWord8  s664 = (SWord8) s661;
-  const SWord8  s665 = table2[s664];
-  const SWord16 s666 = (((SWord16) s663) << 8) | ((SWord16) s665);
-  const SWord32 s667 = (((SWord32) s660) << 16) | ((SWord32) s666);
-  const SWord32 s668 = s649 ^ s667;
-  const SWord32 s669 = s650 ^ s668;
-  const SWord32 s670 = s651 ^ s669;
-  const SWord32 s671 = s652 ^ s670;
-  const SWord32 s672 = (s671 << 8) | (s671 >> 24);
-  const SWord16 s673 = (SWord16) (s672 >> 16);
-  const SWord8  s674 = (SWord8) (s673 >> 8);
-  const SWord8  s675 = table2[s674];
-  const SWord8  s676 = 27 ^ s675;
-  const SWord8  s677 = (SWord8) s673;
-  const SWord8  s678 = table2[s677];
-  const SWord16 s679 = (((SWord16) s676) << 8) | ((SWord16) s678);
-  const SWord16 s680 = (SWord16) s672;
-  const SWord8  s681 = (SWord8) (s680 >> 8);
-  const SWord8  s682 = table2[s681];
-  const SWord8  s683 = (SWord8) s680;
-  const SWord8  s684 = table2[s683];
-  const SWord16 s685 = (((SWord16) s682) << 8) | ((SWord16) s684);
-  const SWord32 s686 = (((SWord32) s679) << 16) | ((SWord32) s685);
-  const SWord32 s687 = s668 ^ s686;
-  const SWord32 s688 = s669 ^ s687;
-  const SWord32 s689 = s670 ^ s688;
-  const SWord32 s690 = s671 ^ s689;
-  const SWord32 s691 = (s690 << 8) | (s690 >> 24);
-  const SWord16 s692 = (SWord16) (s691 >> 16);
-  const SWord8  s693 = (SWord8) (s692 >> 8);
-  const SWord8  s694 = table2[s693];
-  const SWord8  s695 = 54 ^ s694;
-  const SWord8  s696 = (SWord8) s692;
-  const SWord8  s697 = table2[s696];
-  const SWord16 s698 = (((SWord16) s695) << 8) | ((SWord16) s697);
-  const SWord16 s699 = (SWord16) s691;
-  const SWord8  s700 = (SWord8) (s699 >> 8);
-  const SWord8  s701 = table2[s700];
-  const SWord8  s702 = (SWord8) s699;
-  const SWord8  s703 = table2[s702];
-  const SWord16 s704 = (((SWord16) s701) << 8) | ((SWord16) s703);
-  const SWord32 s705 = (((SWord32) s698) << 16) | ((SWord32) s704);
-  const SWord32 s706 = s687 ^ s705;
-  const SWord32 s707 = s0 ^ s706;
-  const SWord16 s708 = (SWord16) (s707 >> 16);
-  const SWord8  s709 = (SWord8) (s708 >> 8);
-  const SWord32 s710 = table1[s709];
-  const SWord32 s966 = s688 ^ s706;
-  const SWord32 s967 = s689 ^ s966;
-  const SWord32 s968 = s690 ^ s967;
-  const SWord32 s969 = s3 ^ s968;
-  const SWord16 s970 = (SWord16) (s969 >> 16);
-  const SWord8  s971 = (SWord8) s970;
-  const SWord32 s972 = table3[s971];
-  const SWord32 s973 = s710 ^ s972;
-  const SWord32 s1229 = s2 ^ s967;
-  const SWord16 s1230 = (SWord16) s1229;
-  const SWord8  s1231 = (SWord8) (s1230 >> 8);
-  const SWord32 s1232 = table4[s1231];
-  const SWord32 s1233 = s973 ^ s1232;
-  const SWord32 s1489 = s1 ^ s966;
-  const SWord16 s1490 = (SWord16) s1489;
-  const SWord8  s1491 = (SWord8) s1490;
-  const SWord32 s1492 = table5[s1491];
-  const SWord32 s1493 = s1233 ^ s1492;
-  const SWord16 s1494 = (SWord16) (s687 >> 16);
-  const SWord8  s1495 = (SWord8) (s1494 >> 8);
-  const SWord8  s1496 = table6[s1495];
-  const SWord8  s1497 = (SWord8) s1494;
-  const SWord8  s1498 = table7[s1497];
-  const SWord16 s1499 = (SWord16) s687;
-  const SWord8  s1500 = (SWord8) (s1499 >> 8);
-  const SWord8  s1501 = table8[s1500];
-  const SWord8  s1502 = (SWord8) s1499;
-  const SWord8  s1503 = table9[s1502];
-  const SWord8  s1504 = s1501 ^ s1503;
-  const SWord8  s1505 = s1498 ^ s1504;
-  const SWord8  s1506 = s1496 ^ s1505;
-  const SWord8  s1507 = table9[s1495];
-  const SWord8  s1508 = table6[s1497];
-  const SWord8  s1509 = table7[s1500];
-  const SWord8  s1510 = table8[s1502];
-  const SWord8  s1511 = s1509 ^ s1510;
-  const SWord8  s1512 = s1508 ^ s1511;
-  const SWord8  s1513 = s1507 ^ s1512;
-  const SWord16 s1514 = (((SWord16) s1506) << 8) | ((SWord16) s1513);
-  const SWord8  s1515 = table8[s1495];
-  const SWord8  s1516 = table9[s1497];
-  const SWord8  s1517 = table6[s1500];
-  const SWord8  s1518 = table7[s1502];
-  const SWord8  s1519 = s1517 ^ s1518;
-  const SWord8  s1520 = s1516 ^ s1519;
-  const SWord8  s1521 = s1515 ^ s1520;
-  const SWord8  s1522 = table7[s1495];
-  const SWord8  s1523 = table8[s1497];
-  const SWord8  s1524 = table9[s1500];
-  const SWord8  s1525 = table6[s1502];
-  const SWord8  s1526 = s1524 ^ s1525;
-  const SWord8  s1527 = s1523 ^ s1526;
-  const SWord8  s1528 = s1522 ^ s1527;
-  const SWord16 s1529 = (((SWord16) s1521) << 8) | ((SWord16) s1528);
-  const SWord32 s1530 = (((SWord32) s1514) << 16) | ((SWord32) s1529);
-  const SWord32 s1531 = s1493 ^ s1530;
-  const SWord16 s1532 = (SWord16) (s1531 >> 16);
-  const SWord8  s1533 = (SWord8) (s1532 >> 8);
-  const SWord32 s1534 = table1[s1533];
-  const SWord8  s1535 = (SWord8) (s970 >> 8);
-  const SWord32 s1536 = table1[s1535];
-  const SWord16 s1537 = (SWord16) (s1229 >> 16);
-  const SWord8  s1538 = (SWord8) s1537;
-  const SWord32 s1539 = table3[s1538];
-  const SWord32 s1540 = s1536 ^ s1539;
-  const SWord8  s1541 = (SWord8) (s1490 >> 8);
-  const SWord32 s1542 = table4[s1541];
-  const SWord32 s1543 = s1540 ^ s1542;
-  const SWord16 s1544 = (SWord16) s707;
-  const SWord8  s1545 = (SWord8) s1544;
-  const SWord32 s1546 = table5[s1545];
-  const SWord32 s1547 = s1543 ^ s1546;
-  const SWord16 s1548 = (SWord16) (s690 >> 16);
-  const SWord8  s1549 = (SWord8) (s1548 >> 8);
-  const SWord8  s1550 = table6[s1549];
-  const SWord8  s1551 = (SWord8) s1548;
-  const SWord8  s1552 = table7[s1551];
-  const SWord16 s1553 = (SWord16) s690;
-  const SWord8  s1554 = (SWord8) (s1553 >> 8);
-  const SWord8  s1555 = table8[s1554];
-  const SWord8  s1556 = (SWord8) s1553;
-  const SWord8  s1557 = table9[s1556];
-  const SWord8  s1558 = s1555 ^ s1557;
-  const SWord8  s1559 = s1552 ^ s1558;
-  const SWord8  s1560 = s1550 ^ s1559;
-  const SWord8  s1561 = table9[s1549];
-  const SWord8  s1562 = table6[s1551];
-  const SWord8  s1563 = table7[s1554];
-  const SWord8  s1564 = table8[s1556];
-  const SWord8  s1565 = s1563 ^ s1564;
-  const SWord8  s1566 = s1562 ^ s1565;
-  const SWord8  s1567 = s1561 ^ s1566;
-  const SWord16 s1568 = (((SWord16) s1560) << 8) | ((SWord16) s1567);
-  const SWord8  s1569 = table8[s1549];
-  const SWord8  s1570 = table9[s1551];
-  const SWord8  s1571 = table6[s1554];
-  const SWord8  s1572 = table7[s1556];
-  const SWord8  s1573 = s1571 ^ s1572;
-  const SWord8  s1574 = s1570 ^ s1573;
-  const SWord8  s1575 = s1569 ^ s1574;
-  const SWord8  s1576 = table7[s1549];
-  const SWord8  s1577 = table8[s1551];
-  const SWord8  s1578 = table9[s1554];
-  const SWord8  s1579 = table6[s1556];
-  const SWord8  s1580 = s1578 ^ s1579;
-  const SWord8  s1581 = s1577 ^ s1580;
-  const SWord8  s1582 = s1576 ^ s1581;
-  const SWord16 s1583 = (((SWord16) s1575) << 8) | ((SWord16) s1582);
-  const SWord32 s1584 = (((SWord32) s1568) << 16) | ((SWord32) s1583);
-  const SWord32 s1585 = s1547 ^ s1584;
-  const SWord16 s1586 = (SWord16) (s1585 >> 16);
-  const SWord8  s1587 = (SWord8) s1586;
-  const SWord32 s1588 = table3[s1587];
-  const SWord32 s1589 = s1534 ^ s1588;
-  const SWord8  s1590 = (SWord8) (s1537 >> 8);
-  const SWord32 s1591 = table1[s1590];
-  const SWord16 s1592 = (SWord16) (s1489 >> 16);
-  const SWord8  s1593 = (SWord8) s1592;
-  const SWord32 s1594 = table3[s1593];
-  const SWord32 s1595 = s1591 ^ s1594;
-  const SWord8  s1596 = (SWord8) (s1544 >> 8);
-  const SWord32 s1597 = table4[s1596];
-  const SWord32 s1598 = s1595 ^ s1597;
-  const SWord16 s1599 = (SWord16) s969;
-  const SWord8  s1600 = (SWord8) s1599;
-  const SWord32 s1601 = table5[s1600];
-  const SWord32 s1602 = s1598 ^ s1601;
-  const SWord16 s1603 = (SWord16) (s689 >> 16);
-  const SWord8  s1604 = (SWord8) (s1603 >> 8);
-  const SWord8  s1605 = table6[s1604];
-  const SWord8  s1606 = (SWord8) s1603;
-  const SWord8  s1607 = table7[s1606];
-  const SWord16 s1608 = (SWord16) s689;
-  const SWord8  s1609 = (SWord8) (s1608 >> 8);
-  const SWord8  s1610 = table8[s1609];
-  const SWord8  s1611 = (SWord8) s1608;
-  const SWord8  s1612 = table9[s1611];
-  const SWord8  s1613 = s1610 ^ s1612;
-  const SWord8  s1614 = s1607 ^ s1613;
-  const SWord8  s1615 = s1605 ^ s1614;
-  const SWord8  s1616 = table9[s1604];
-  const SWord8  s1617 = table6[s1606];
-  const SWord8  s1618 = table7[s1609];
-  const SWord8  s1619 = table8[s1611];
-  const SWord8  s1620 = s1618 ^ s1619;
-  const SWord8  s1621 = s1617 ^ s1620;
-  const SWord8  s1622 = s1616 ^ s1621;
-  const SWord16 s1623 = (((SWord16) s1615) << 8) | ((SWord16) s1622);
-  const SWord8  s1624 = table8[s1604];
-  const SWord8  s1625 = table9[s1606];
-  const SWord8  s1626 = table6[s1609];
-  const SWord8  s1627 = table7[s1611];
-  const SWord8  s1628 = s1626 ^ s1627;
-  const SWord8  s1629 = s1625 ^ s1628;
-  const SWord8  s1630 = s1624 ^ s1629;
-  const SWord8  s1631 = table7[s1604];
-  const SWord8  s1632 = table8[s1606];
-  const SWord8  s1633 = table9[s1609];
-  const SWord8  s1634 = table6[s1611];
-  const SWord8  s1635 = s1633 ^ s1634;
-  const SWord8  s1636 = s1632 ^ s1635;
-  const SWord8  s1637 = s1631 ^ s1636;
-  const SWord16 s1638 = (((SWord16) s1630) << 8) | ((SWord16) s1637);
-  const SWord32 s1639 = (((SWord32) s1623) << 16) | ((SWord32) s1638);
-  const SWord32 s1640 = s1602 ^ s1639;
-  const SWord16 s1641 = (SWord16) s1640;
-  const SWord8  s1642 = (SWord8) (s1641 >> 8);
-  const SWord32 s1643 = table4[s1642];
-  const SWord32 s1644 = s1589 ^ s1643;
-  const SWord8  s1645 = (SWord8) (s1592 >> 8);
-  const SWord32 s1646 = table1[s1645];
-  const SWord8  s1647 = (SWord8) s708;
-  const SWord32 s1648 = table3[s1647];
-  const SWord32 s1649 = s1646 ^ s1648;
-  const SWord8  s1650 = (SWord8) (s1599 >> 8);
-  const SWord32 s1651 = table4[s1650];
-  const SWord32 s1652 = s1649 ^ s1651;
-  const SWord8  s1653 = (SWord8) s1230;
-  const SWord32 s1654 = table5[s1653];
-  const SWord32 s1655 = s1652 ^ s1654;
-  const SWord16 s1656 = (SWord16) (s688 >> 16);
-  const SWord8  s1657 = (SWord8) (s1656 >> 8);
-  const SWord8  s1658 = table6[s1657];
-  const SWord8  s1659 = (SWord8) s1656;
-  const SWord8  s1660 = table7[s1659];
-  const SWord16 s1661 = (SWord16) s688;
-  const SWord8  s1662 = (SWord8) (s1661 >> 8);
-  const SWord8  s1663 = table8[s1662];
-  const SWord8  s1664 = (SWord8) s1661;
-  const SWord8  s1665 = table9[s1664];
-  const SWord8  s1666 = s1663 ^ s1665;
-  const SWord8  s1667 = s1660 ^ s1666;
-  const SWord8  s1668 = s1658 ^ s1667;
-  const SWord8  s1669 = table9[s1657];
-  const SWord8  s1670 = table6[s1659];
-  const SWord8  s1671 = table7[s1662];
-  const SWord8  s1672 = table8[s1664];
-  const SWord8  s1673 = s1671 ^ s1672;
-  const SWord8  s1674 = s1670 ^ s1673;
-  const SWord8  s1675 = s1669 ^ s1674;
-  const SWord16 s1676 = (((SWord16) s1668) << 8) | ((SWord16) s1675);
-  const SWord8  s1677 = table8[s1657];
-  const SWord8  s1678 = table9[s1659];
-  const SWord8  s1679 = table6[s1662];
-  const SWord8  s1680 = table7[s1664];
-  const SWord8  s1681 = s1679 ^ s1680;
-  const SWord8  s1682 = s1678 ^ s1681;
-  const SWord8  s1683 = s1677 ^ s1682;
-  const SWord8  s1684 = table7[s1657];
-  const SWord8  s1685 = table8[s1659];
-  const SWord8  s1686 = table9[s1662];
-  const SWord8  s1687 = table6[s1664];
-  const SWord8  s1688 = s1686 ^ s1687;
-  const SWord8  s1689 = s1685 ^ s1688;
-  const SWord8  s1690 = s1684 ^ s1689;
-  const SWord16 s1691 = (((SWord16) s1683) << 8) | ((SWord16) s1690);
-  const SWord32 s1692 = (((SWord32) s1676) << 16) | ((SWord32) s1691);
-  const SWord32 s1693 = s1655 ^ s1692;
-  const SWord16 s1694 = (SWord16) s1693;
-  const SWord8  s1695 = (SWord8) s1694;
-  const SWord32 s1696 = table5[s1695];
-  const SWord32 s1697 = s1644 ^ s1696;
-  const SWord16 s1698 = (SWord16) (s668 >> 16);
-  const SWord8  s1699 = (SWord8) (s1698 >> 8);
-  const SWord8  s1700 = table6[s1699];
-  const SWord8  s1701 = (SWord8) s1698;
-  const SWord8  s1702 = table7[s1701];
-  const SWord16 s1703 = (SWord16) s668;
-  const SWord8  s1704 = (SWord8) (s1703 >> 8);
-  const SWord8  s1705 = table8[s1704];
-  const SWord8  s1706 = (SWord8) s1703;
-  const SWord8  s1707 = table9[s1706];
-  const SWord8  s1708 = s1705 ^ s1707;
-  const SWord8  s1709 = s1702 ^ s1708;
-  const SWord8  s1710 = s1700 ^ s1709;
-  const SWord8  s1711 = table9[s1699];
-  const SWord8  s1712 = table6[s1701];
-  const SWord8  s1713 = table7[s1704];
-  const SWord8  s1714 = table8[s1706];
-  const SWord8  s1715 = s1713 ^ s1714;
-  const SWord8  s1716 = s1712 ^ s1715;
-  const SWord8  s1717 = s1711 ^ s1716;
-  const SWord16 s1718 = (((SWord16) s1710) << 8) | ((SWord16) s1717);
-  const SWord8  s1719 = table8[s1699];
-  const SWord8  s1720 = table9[s1701];
-  const SWord8  s1721 = table6[s1704];
-  const SWord8  s1722 = table7[s1706];
-  const SWord8  s1723 = s1721 ^ s1722;
-  const SWord8  s1724 = s1720 ^ s1723;
-  const SWord8  s1725 = s1719 ^ s1724;
-  const SWord8  s1726 = table7[s1699];
-  const SWord8  s1727 = table8[s1701];
-  const SWord8  s1728 = table9[s1704];
-  const SWord8  s1729 = table6[s1706];
-  const SWord8  s1730 = s1728 ^ s1729;
-  const SWord8  s1731 = s1727 ^ s1730;
-  const SWord8  s1732 = s1726 ^ s1731;
-  const SWord16 s1733 = (((SWord16) s1725) << 8) | ((SWord16) s1732);
-  const SWord32 s1734 = (((SWord32) s1718) << 16) | ((SWord32) s1733);
-  const SWord32 s1735 = s1697 ^ s1734;
-  const SWord16 s1736 = (SWord16) (s1735 >> 16);
-  const SWord8  s1737 = (SWord8) (s1736 >> 8);
-  const SWord32 s1738 = table1[s1737];
-  const SWord8  s1739 = (SWord8) (s1586 >> 8);
-  const SWord32 s1740 = table1[s1739];
-  const SWord16 s1741 = (SWord16) (s1640 >> 16);
-  const SWord8  s1742 = (SWord8) s1741;
-  const SWord32 s1743 = table3[s1742];
-  const SWord32 s1744 = s1740 ^ s1743;
-  const SWord8  s1745 = (SWord8) (s1694 >> 8);
-  const SWord32 s1746 = table4[s1745];
-  const SWord32 s1747 = s1744 ^ s1746;
-  const SWord16 s1748 = (SWord16) s1531;
-  const SWord8  s1749 = (SWord8) s1748;
-  const SWord32 s1750 = table5[s1749];
-  const SWord32 s1751 = s1747 ^ s1750;
-  const SWord16 s1752 = (SWord16) (s671 >> 16);
-  const SWord8  s1753 = (SWord8) (s1752 >> 8);
-  const SWord8  s1754 = table6[s1753];
-  const SWord8  s1755 = (SWord8) s1752;
-  const SWord8  s1756 = table7[s1755];
-  const SWord16 s1757 = (SWord16) s671;
-  const SWord8  s1758 = (SWord8) (s1757 >> 8);
-  const SWord8  s1759 = table8[s1758];
-  const SWord8  s1760 = (SWord8) s1757;
-  const SWord8  s1761 = table9[s1760];
-  const SWord8  s1762 = s1759 ^ s1761;
-  const SWord8  s1763 = s1756 ^ s1762;
-  const SWord8  s1764 = s1754 ^ s1763;
-  const SWord8  s1765 = table9[s1753];
-  const SWord8  s1766 = table6[s1755];
-  const SWord8  s1767 = table7[s1758];
-  const SWord8  s1768 = table8[s1760];
-  const SWord8  s1769 = s1767 ^ s1768;
-  const SWord8  s1770 = s1766 ^ s1769;
-  const SWord8  s1771 = s1765 ^ s1770;
-  const SWord16 s1772 = (((SWord16) s1764) << 8) | ((SWord16) s1771);
-  const SWord8  s1773 = table8[s1753];
-  const SWord8  s1774 = table9[s1755];
-  const SWord8  s1775 = table6[s1758];
-  const SWord8  s1776 = table7[s1760];
-  const SWord8  s1777 = s1775 ^ s1776;
-  const SWord8  s1778 = s1774 ^ s1777;
-  const SWord8  s1779 = s1773 ^ s1778;
-  const SWord8  s1780 = table7[s1753];
-  const SWord8  s1781 = table8[s1755];
-  const SWord8  s1782 = table9[s1758];
-  const SWord8  s1783 = table6[s1760];
-  const SWord8  s1784 = s1782 ^ s1783;
-  const SWord8  s1785 = s1781 ^ s1784;
-  const SWord8  s1786 = s1780 ^ s1785;
-  const SWord16 s1787 = (((SWord16) s1779) << 8) | ((SWord16) s1786);
-  const SWord32 s1788 = (((SWord32) s1772) << 16) | ((SWord32) s1787);
-  const SWord32 s1789 = s1751 ^ s1788;
-  const SWord16 s1790 = (SWord16) (s1789 >> 16);
-  const SWord8  s1791 = (SWord8) s1790;
-  const SWord32 s1792 = table3[s1791];
-  const SWord32 s1793 = s1738 ^ s1792;
-  const SWord8  s1794 = (SWord8) (s1741 >> 8);
-  const SWord32 s1795 = table1[s1794];
-  const SWord16 s1796 = (SWord16) (s1693 >> 16);
-  const SWord8  s1797 = (SWord8) s1796;
-  const SWord32 s1798 = table3[s1797];
-  const SWord32 s1799 = s1795 ^ s1798;
-  const SWord8  s1800 = (SWord8) (s1748 >> 8);
-  const SWord32 s1801 = table4[s1800];
-  const SWord32 s1802 = s1799 ^ s1801;
-  const SWord16 s1803 = (SWord16) s1585;
-  const SWord8  s1804 = (SWord8) s1803;
-  const SWord32 s1805 = table5[s1804];
-  const SWord32 s1806 = s1802 ^ s1805;
-  const SWord16 s1807 = (SWord16) (s670 >> 16);
-  const SWord8  s1808 = (SWord8) (s1807 >> 8);
-  const SWord8  s1809 = table6[s1808];
-  const SWord8  s1810 = (SWord8) s1807;
-  const SWord8  s1811 = table7[s1810];
-  const SWord16 s1812 = (SWord16) s670;
-  const SWord8  s1813 = (SWord8) (s1812 >> 8);
-  const SWord8  s1814 = table8[s1813];
-  const SWord8  s1815 = (SWord8) s1812;
-  const SWord8  s1816 = table9[s1815];
-  const SWord8  s1817 = s1814 ^ s1816;
-  const SWord8  s1818 = s1811 ^ s1817;
-  const SWord8  s1819 = s1809 ^ s1818;
-  const SWord8  s1820 = table9[s1808];
-  const SWord8  s1821 = table6[s1810];
-  const SWord8  s1822 = table7[s1813];
-  const SWord8  s1823 = table8[s1815];
-  const SWord8  s1824 = s1822 ^ s1823;
-  const SWord8  s1825 = s1821 ^ s1824;
-  const SWord8  s1826 = s1820 ^ s1825;
-  const SWord16 s1827 = (((SWord16) s1819) << 8) | ((SWord16) s1826);
-  const SWord8  s1828 = table8[s1808];
-  const SWord8  s1829 = table9[s1810];
-  const SWord8  s1830 = table6[s1813];
-  const SWord8  s1831 = table7[s1815];
-  const SWord8  s1832 = s1830 ^ s1831;
-  const SWord8  s1833 = s1829 ^ s1832;
-  const SWord8  s1834 = s1828 ^ s1833;
-  const SWord8  s1835 = table7[s1808];
-  const SWord8  s1836 = table8[s1810];
-  const SWord8  s1837 = table9[s1813];
-  const SWord8  s1838 = table6[s1815];
-  const SWord8  s1839 = s1837 ^ s1838;
-  const SWord8  s1840 = s1836 ^ s1839;
-  const SWord8  s1841 = s1835 ^ s1840;
-  const SWord16 s1842 = (((SWord16) s1834) << 8) | ((SWord16) s1841);
-  const SWord32 s1843 = (((SWord32) s1827) << 16) | ((SWord32) s1842);
-  const SWord32 s1844 = s1806 ^ s1843;
-  const SWord16 s1845 = (SWord16) s1844;
-  const SWord8  s1846 = (SWord8) (s1845 >> 8);
-  const SWord32 s1847 = table4[s1846];
-  const SWord32 s1848 = s1793 ^ s1847;
-  const SWord8  s1849 = (SWord8) (s1796 >> 8);
-  const SWord32 s1850 = table1[s1849];
-  const SWord8  s1851 = (SWord8) s1532;
-  const SWord32 s1852 = table3[s1851];
-  const SWord32 s1853 = s1850 ^ s1852;
-  const SWord8  s1854 = (SWord8) (s1803 >> 8);
-  const SWord32 s1855 = table4[s1854];
-  const SWord32 s1856 = s1853 ^ s1855;
-  const SWord8  s1857 = (SWord8) s1641;
-  const SWord32 s1858 = table5[s1857];
-  const SWord32 s1859 = s1856 ^ s1858;
-  const SWord16 s1860 = (SWord16) (s669 >> 16);
-  const SWord8  s1861 = (SWord8) (s1860 >> 8);
-  const SWord8  s1862 = table6[s1861];
-  const SWord8  s1863 = (SWord8) s1860;
-  const SWord8  s1864 = table7[s1863];
-  const SWord16 s1865 = (SWord16) s669;
-  const SWord8  s1866 = (SWord8) (s1865 >> 8);
-  const SWord8  s1867 = table8[s1866];
-  const SWord8  s1868 = (SWord8) s1865;
-  const SWord8  s1869 = table9[s1868];
-  const SWord8  s1870 = s1867 ^ s1869;
-  const SWord8  s1871 = s1864 ^ s1870;
-  const SWord8  s1872 = s1862 ^ s1871;
-  const SWord8  s1873 = table9[s1861];
-  const SWord8  s1874 = table6[s1863];
-  const SWord8  s1875 = table7[s1866];
-  const SWord8  s1876 = table8[s1868];
-  const SWord8  s1877 = s1875 ^ s1876;
-  const SWord8  s1878 = s1874 ^ s1877;
-  const SWord8  s1879 = s1873 ^ s1878;
-  const SWord16 s1880 = (((SWord16) s1872) << 8) | ((SWord16) s1879);
-  const SWord8  s1881 = table8[s1861];
-  const SWord8  s1882 = table9[s1863];
-  const SWord8  s1883 = table6[s1866];
-  const SWord8  s1884 = table7[s1868];
-  const SWord8  s1885 = s1883 ^ s1884;
-  const SWord8  s1886 = s1882 ^ s1885;
-  const SWord8  s1887 = s1881 ^ s1886;
-  const SWord8  s1888 = table7[s1861];
-  const SWord8  s1889 = table8[s1863];
-  const SWord8  s1890 = table9[s1866];
-  const SWord8  s1891 = table6[s1868];
-  const SWord8  s1892 = s1890 ^ s1891;
-  const SWord8  s1893 = s1889 ^ s1892;
-  const SWord8  s1894 = s1888 ^ s1893;
-  const SWord16 s1895 = (((SWord16) s1887) << 8) | ((SWord16) s1894);
-  const SWord32 s1896 = (((SWord32) s1880) << 16) | ((SWord32) s1895);
-  const SWord32 s1897 = s1859 ^ s1896;
-  const SWord16 s1898 = (SWord16) s1897;
-  const SWord8  s1899 = (SWord8) s1898;
-  const SWord32 s1900 = table5[s1899];
-  const SWord32 s1901 = s1848 ^ s1900;
-  const SWord16 s1902 = (SWord16) (s649 >> 16);
-  const SWord8  s1903 = (SWord8) (s1902 >> 8);
-  const SWord8  s1904 = table6[s1903];
-  const SWord8  s1905 = (SWord8) s1902;
-  const SWord8  s1906 = table7[s1905];
-  const SWord16 s1907 = (SWord16) s649;
-  const SWord8  s1908 = (SWord8) (s1907 >> 8);
-  const SWord8  s1909 = table8[s1908];
-  const SWord8  s1910 = (SWord8) s1907;
-  const SWord8  s1911 = table9[s1910];
-  const SWord8  s1912 = s1909 ^ s1911;
-  const SWord8  s1913 = s1906 ^ s1912;
-  const SWord8  s1914 = s1904 ^ s1913;
-  const SWord8  s1915 = table9[s1903];
-  const SWord8  s1916 = table6[s1905];
-  const SWord8  s1917 = table7[s1908];
-  const SWord8  s1918 = table8[s1910];
-  const SWord8  s1919 = s1917 ^ s1918;
-  const SWord8  s1920 = s1916 ^ s1919;
-  const SWord8  s1921 = s1915 ^ s1920;
-  const SWord16 s1922 = (((SWord16) s1914) << 8) | ((SWord16) s1921);
-  const SWord8  s1923 = table8[s1903];
-  const SWord8  s1924 = table9[s1905];
-  const SWord8  s1925 = table6[s1908];
-  const SWord8  s1926 = table7[s1910];
-  const SWord8  s1927 = s1925 ^ s1926;
-  const SWord8  s1928 = s1924 ^ s1927;
-  const SWord8  s1929 = s1923 ^ s1928;
-  const SWord8  s1930 = table7[s1903];
-  const SWord8  s1931 = table8[s1905];
-  const SWord8  s1932 = table9[s1908];
-  const SWord8  s1933 = table6[s1910];
-  const SWord8  s1934 = s1932 ^ s1933;
-  const SWord8  s1935 = s1931 ^ s1934;
-  const SWord8  s1936 = s1930 ^ s1935;
-  const SWord16 s1937 = (((SWord16) s1929) << 8) | ((SWord16) s1936);
-  const SWord32 s1938 = (((SWord32) s1922) << 16) | ((SWord32) s1937);
-  const SWord32 s1939 = s1901 ^ s1938;
-  const SWord16 s1940 = (SWord16) (s1939 >> 16);
-  const SWord8  s1941 = (SWord8) (s1940 >> 8);
-  const SWord32 s1942 = table1[s1941];
-  const SWord8  s1943 = (SWord8) (s1790 >> 8);
-  const SWord32 s1944 = table1[s1943];
-  const SWord16 s1945 = (SWord16) (s1844 >> 16);
-  const SWord8  s1946 = (SWord8) s1945;
-  const SWord32 s1947 = table3[s1946];
-  const SWord32 s1948 = s1944 ^ s1947;
-  const SWord8  s1949 = (SWord8) (s1898 >> 8);
-  const SWord32 s1950 = table4[s1949];
-  const SWord32 s1951 = s1948 ^ s1950;
-  const SWord16 s1952 = (SWord16) s1735;
-  const SWord8  s1953 = (SWord8) s1952;
-  const SWord32 s1954 = table5[s1953];
-  const SWord32 s1955 = s1951 ^ s1954;
-  const SWord16 s1956 = (SWord16) (s652 >> 16);
-  const SWord8  s1957 = (SWord8) (s1956 >> 8);
-  const SWord8  s1958 = table6[s1957];
-  const SWord8  s1959 = (SWord8) s1956;
-  const SWord8  s1960 = table7[s1959];
-  const SWord16 s1961 = (SWord16) s652;
-  const SWord8  s1962 = (SWord8) (s1961 >> 8);
-  const SWord8  s1963 = table8[s1962];
-  const SWord8  s1964 = (SWord8) s1961;
-  const SWord8  s1965 = table9[s1964];
-  const SWord8  s1966 = s1963 ^ s1965;
-  const SWord8  s1967 = s1960 ^ s1966;
-  const SWord8  s1968 = s1958 ^ s1967;
-  const SWord8  s1969 = table9[s1957];
-  const SWord8  s1970 = table6[s1959];
-  const SWord8  s1971 = table7[s1962];
-  const SWord8  s1972 = table8[s1964];
-  const SWord8  s1973 = s1971 ^ s1972;
-  const SWord8  s1974 = s1970 ^ s1973;
-  const SWord8  s1975 = s1969 ^ s1974;
-  const SWord16 s1976 = (((SWord16) s1968) << 8) | ((SWord16) s1975);
-  const SWord8  s1977 = table8[s1957];
-  const SWord8  s1978 = table9[s1959];
-  const SWord8  s1979 = table6[s1962];
-  const SWord8  s1980 = table7[s1964];
-  const SWord8  s1981 = s1979 ^ s1980;
-  const SWord8  s1982 = s1978 ^ s1981;
-  const SWord8  s1983 = s1977 ^ s1982;
-  const SWord8  s1984 = table7[s1957];
-  const SWord8  s1985 = table8[s1959];
-  const SWord8  s1986 = table9[s1962];
-  const SWord8  s1987 = table6[s1964];
-  const SWord8  s1988 = s1986 ^ s1987;
-  const SWord8  s1989 = s1985 ^ s1988;
-  const SWord8  s1990 = s1984 ^ s1989;
-  const SWord16 s1991 = (((SWord16) s1983) << 8) | ((SWord16) s1990);
-  const SWord32 s1992 = (((SWord32) s1976) << 16) | ((SWord32) s1991);
-  const SWord32 s1993 = s1955 ^ s1992;
-  const SWord16 s1994 = (SWord16) (s1993 >> 16);
-  const SWord8  s1995 = (SWord8) s1994;
-  const SWord32 s1996 = table3[s1995];
-  const SWord32 s1997 = s1942 ^ s1996;
-  const SWord8  s1998 = (SWord8) (s1945 >> 8);
-  const SWord32 s1999 = table1[s1998];
-  const SWord16 s2000 = (SWord16) (s1897 >> 16);
-  const SWord8  s2001 = (SWord8) s2000;
-  const SWord32 s2002 = table3[s2001];
-  const SWord32 s2003 = s1999 ^ s2002;
-  const SWord8  s2004 = (SWord8) (s1952 >> 8);
-  const SWord32 s2005 = table4[s2004];
-  const SWord32 s2006 = s2003 ^ s2005;
-  const SWord16 s2007 = (SWord16) s1789;
-  const SWord8  s2008 = (SWord8) s2007;
-  const SWord32 s2009 = table5[s2008];
-  const SWord32 s2010 = s2006 ^ s2009;
-  const SWord16 s2011 = (SWord16) (s651 >> 16);
-  const SWord8  s2012 = (SWord8) (s2011 >> 8);
-  const SWord8  s2013 = table6[s2012];
-  const SWord8  s2014 = (SWord8) s2011;
-  const SWord8  s2015 = table7[s2014];
-  const SWord16 s2016 = (SWord16) s651;
-  const SWord8  s2017 = (SWord8) (s2016 >> 8);
-  const SWord8  s2018 = table8[s2017];
-  const SWord8  s2019 = (SWord8) s2016;
-  const SWord8  s2020 = table9[s2019];
-  const SWord8  s2021 = s2018 ^ s2020;
-  const SWord8  s2022 = s2015 ^ s2021;
-  const SWord8  s2023 = s2013 ^ s2022;
-  const SWord8  s2024 = table9[s2012];
-  const SWord8  s2025 = table6[s2014];
-  const SWord8  s2026 = table7[s2017];
-  const SWord8  s2027 = table8[s2019];
-  const SWord8  s2028 = s2026 ^ s2027;
-  const SWord8  s2029 = s2025 ^ s2028;
-  const SWord8  s2030 = s2024 ^ s2029;
-  const SWord16 s2031 = (((SWord16) s2023) << 8) | ((SWord16) s2030);
-  const SWord8  s2032 = table8[s2012];
-  const SWord8  s2033 = table9[s2014];
-  const SWord8  s2034 = table6[s2017];
-  const SWord8  s2035 = table7[s2019];
-  const SWord8  s2036 = s2034 ^ s2035;
-  const SWord8  s2037 = s2033 ^ s2036;
-  const SWord8  s2038 = s2032 ^ s2037;
-  const SWord8  s2039 = table7[s2012];
-  const SWord8  s2040 = table8[s2014];
-  const SWord8  s2041 = table9[s2017];
-  const SWord8  s2042 = table6[s2019];
-  const SWord8  s2043 = s2041 ^ s2042;
-  const SWord8  s2044 = s2040 ^ s2043;
-  const SWord8  s2045 = s2039 ^ s2044;
-  const SWord16 s2046 = (((SWord16) s2038) << 8) | ((SWord16) s2045);
-  const SWord32 s2047 = (((SWord32) s2031) << 16) | ((SWord32) s2046);
-  const SWord32 s2048 = s2010 ^ s2047;
-  const SWord16 s2049 = (SWord16) s2048;
-  const SWord8  s2050 = (SWord8) (s2049 >> 8);
-  const SWord32 s2051 = table4[s2050];
-  const SWord32 s2052 = s1997 ^ s2051;
-  const SWord8  s2053 = (SWord8) (s2000 >> 8);
-  const SWord32 s2054 = table1[s2053];
-  const SWord8  s2055 = (SWord8) s1736;
-  const SWord32 s2056 = table3[s2055];
-  const SWord32 s2057 = s2054 ^ s2056;
-  const SWord8  s2058 = (SWord8) (s2007 >> 8);
-  const SWord32 s2059 = table4[s2058];
-  const SWord32 s2060 = s2057 ^ s2059;
-  const SWord8  s2061 = (SWord8) s1845;
-  const SWord32 s2062 = table5[s2061];
-  const SWord32 s2063 = s2060 ^ s2062;
-  const SWord16 s2064 = (SWord16) (s650 >> 16);
-  const SWord8  s2065 = (SWord8) (s2064 >> 8);
-  const SWord8  s2066 = table6[s2065];
-  const SWord8  s2067 = (SWord8) s2064;
-  const SWord8  s2068 = table7[s2067];
-  const SWord16 s2069 = (SWord16) s650;
-  const SWord8  s2070 = (SWord8) (s2069 >> 8);
-  const SWord8  s2071 = table8[s2070];
-  const SWord8  s2072 = (SWord8) s2069;
-  const SWord8  s2073 = table9[s2072];
-  const SWord8  s2074 = s2071 ^ s2073;
-  const SWord8  s2075 = s2068 ^ s2074;
-  const SWord8  s2076 = s2066 ^ s2075;
-  const SWord8  s2077 = table9[s2065];
-  const SWord8  s2078 = table6[s2067];
-  const SWord8  s2079 = table7[s2070];
-  const SWord8  s2080 = table8[s2072];
-  const SWord8  s2081 = s2079 ^ s2080;
-  const SWord8  s2082 = s2078 ^ s2081;
-  const SWord8  s2083 = s2077 ^ s2082;
-  const SWord16 s2084 = (((SWord16) s2076) << 8) | ((SWord16) s2083);
-  const SWord8  s2085 = table8[s2065];
-  const SWord8  s2086 = table9[s2067];
-  const SWord8  s2087 = table6[s2070];
-  const SWord8  s2088 = table7[s2072];
-  const SWord8  s2089 = s2087 ^ s2088;
-  const SWord8  s2090 = s2086 ^ s2089;
-  const SWord8  s2091 = s2085 ^ s2090;
-  const SWord8  s2092 = table7[s2065];
-  const SWord8  s2093 = table8[s2067];
-  const SWord8  s2094 = table9[s2070];
-  const SWord8  s2095 = table6[s2072];
-  const SWord8  s2096 = s2094 ^ s2095;
-  const SWord8  s2097 = s2093 ^ s2096;
-  const SWord8  s2098 = s2092 ^ s2097;
-  const SWord16 s2099 = (((SWord16) s2091) << 8) | ((SWord16) s2098);
-  const SWord32 s2100 = (((SWord32) s2084) << 16) | ((SWord32) s2099);
-  const SWord32 s2101 = s2063 ^ s2100;
-  const SWord16 s2102 = (SWord16) s2101;
-  const SWord8  s2103 = (SWord8) s2102;
-  const SWord32 s2104 = table5[s2103];
-  const SWord32 s2105 = s2052 ^ s2104;
-  const SWord16 s2106 = (SWord16) (s630 >> 16);
-  const SWord8  s2107 = (SWord8) (s2106 >> 8);
-  const SWord8  s2108 = table6[s2107];
-  const SWord8  s2109 = (SWord8) s2106;
-  const SWord8  s2110 = table7[s2109];
-  const SWord16 s2111 = (SWord16) s630;
-  const SWord8  s2112 = (SWord8) (s2111 >> 8);
-  const SWord8  s2113 = table8[s2112];
-  const SWord8  s2114 = (SWord8) s2111;
-  const SWord8  s2115 = table9[s2114];
-  const SWord8  s2116 = s2113 ^ s2115;
-  const SWord8  s2117 = s2110 ^ s2116;
-  const SWord8  s2118 = s2108 ^ s2117;
-  const SWord8  s2119 = table9[s2107];
-  const SWord8  s2120 = table6[s2109];
-  const SWord8  s2121 = table7[s2112];
-  const SWord8  s2122 = table8[s2114];
-  const SWord8  s2123 = s2121 ^ s2122;
-  const SWord8  s2124 = s2120 ^ s2123;
-  const SWord8  s2125 = s2119 ^ s2124;
-  const SWord16 s2126 = (((SWord16) s2118) << 8) | ((SWord16) s2125);
-  const SWord8  s2127 = table8[s2107];
-  const SWord8  s2128 = table9[s2109];
-  const SWord8  s2129 = table6[s2112];
-  const SWord8  s2130 = table7[s2114];
-  const SWord8  s2131 = s2129 ^ s2130;
-  const SWord8  s2132 = s2128 ^ s2131;
-  const SWord8  s2133 = s2127 ^ s2132;
-  const SWord8  s2134 = table7[s2107];
-  const SWord8  s2135 = table8[s2109];
-  const SWord8  s2136 = table9[s2112];
-  const SWord8  s2137 = table6[s2114];
-  const SWord8  s2138 = s2136 ^ s2137;
-  const SWord8  s2139 = s2135 ^ s2138;
-  const SWord8  s2140 = s2134 ^ s2139;
-  const SWord16 s2141 = (((SWord16) s2133) << 8) | ((SWord16) s2140);
-  const SWord32 s2142 = (((SWord32) s2126) << 16) | ((SWord32) s2141);
-  const SWord32 s2143 = s2105 ^ s2142;
-  const SWord16 s2144 = (SWord16) (s2143 >> 16);
-  const SWord8  s2145 = (SWord8) (s2144 >> 8);
-  const SWord32 s2146 = table1[s2145];
-  const SWord8  s2147 = (SWord8) (s1994 >> 8);
-  const SWord32 s2148 = table1[s2147];
-  const SWord16 s2149 = (SWord16) (s2048 >> 16);
-  const SWord8  s2150 = (SWord8) s2149;
-  const SWord32 s2151 = table3[s2150];
-  const SWord32 s2152 = s2148 ^ s2151;
-  const SWord8  s2153 = (SWord8) (s2102 >> 8);
-  const SWord32 s2154 = table4[s2153];
-  const SWord32 s2155 = s2152 ^ s2154;
-  const SWord16 s2156 = (SWord16) s1939;
-  const SWord8  s2157 = (SWord8) s2156;
-  const SWord32 s2158 = table5[s2157];
-  const SWord32 s2159 = s2155 ^ s2158;
-  const SWord16 s2160 = (SWord16) (s633 >> 16);
-  const SWord8  s2161 = (SWord8) (s2160 >> 8);
-  const SWord8  s2162 = table6[s2161];
-  const SWord8  s2163 = (SWord8) s2160;
-  const SWord8  s2164 = table7[s2163];
-  const SWord16 s2165 = (SWord16) s633;
-  const SWord8  s2166 = (SWord8) (s2165 >> 8);
-  const SWord8  s2167 = table8[s2166];
-  const SWord8  s2168 = (SWord8) s2165;
-  const SWord8  s2169 = table9[s2168];
-  const SWord8  s2170 = s2167 ^ s2169;
-  const SWord8  s2171 = s2164 ^ s2170;
-  const SWord8  s2172 = s2162 ^ s2171;
-  const SWord8  s2173 = table9[s2161];
-  const SWord8  s2174 = table6[s2163];
-  const SWord8  s2175 = table7[s2166];
-  const SWord8  s2176 = table8[s2168];
-  const SWord8  s2177 = s2175 ^ s2176;
-  const SWord8  s2178 = s2174 ^ s2177;
-  const SWord8  s2179 = s2173 ^ s2178;
-  const SWord16 s2180 = (((SWord16) s2172) << 8) | ((SWord16) s2179);
-  const SWord8  s2181 = table8[s2161];
-  const SWord8  s2182 = table9[s2163];
-  const SWord8  s2183 = table6[s2166];
-  const SWord8  s2184 = table7[s2168];
-  const SWord8  s2185 = s2183 ^ s2184;
-  const SWord8  s2186 = s2182 ^ s2185;
-  const SWord8  s2187 = s2181 ^ s2186;
-  const SWord8  s2188 = table7[s2161];
-  const SWord8  s2189 = table8[s2163];
-  const SWord8  s2190 = table9[s2166];
-  const SWord8  s2191 = table6[s2168];
-  const SWord8  s2192 = s2190 ^ s2191;
-  const SWord8  s2193 = s2189 ^ s2192;
-  const SWord8  s2194 = s2188 ^ s2193;
-  const SWord16 s2195 = (((SWord16) s2187) << 8) | ((SWord16) s2194);
-  const SWord32 s2196 = (((SWord32) s2180) << 16) | ((SWord32) s2195);
-  const SWord32 s2197 = s2159 ^ s2196;
-  const SWord16 s2198 = (SWord16) (s2197 >> 16);
-  const SWord8  s2199 = (SWord8) s2198;
-  const SWord32 s2200 = table3[s2199];
-  const SWord32 s2201 = s2146 ^ s2200;
-  const SWord8  s2202 = (SWord8) (s2149 >> 8);
-  const SWord32 s2203 = table1[s2202];
-  const SWord16 s2204 = (SWord16) (s2101 >> 16);
-  const SWord8  s2205 = (SWord8) s2204;
-  const SWord32 s2206 = table3[s2205];
-  const SWord32 s2207 = s2203 ^ s2206;
-  const SWord8  s2208 = (SWord8) (s2156 >> 8);
-  const SWord32 s2209 = table4[s2208];
-  const SWord32 s2210 = s2207 ^ s2209;
-  const SWord16 s2211 = (SWord16) s1993;
-  const SWord8  s2212 = (SWord8) s2211;
-  const SWord32 s2213 = table5[s2212];
-  const SWord32 s2214 = s2210 ^ s2213;
-  const SWord16 s2215 = (SWord16) (s632 >> 16);
-  const SWord8  s2216 = (SWord8) (s2215 >> 8);
-  const SWord8  s2217 = table6[s2216];
-  const SWord8  s2218 = (SWord8) s2215;
-  const SWord8  s2219 = table7[s2218];
-  const SWord16 s2220 = (SWord16) s632;
-  const SWord8  s2221 = (SWord8) (s2220 >> 8);
-  const SWord8  s2222 = table8[s2221];
-  const SWord8  s2223 = (SWord8) s2220;
-  const SWord8  s2224 = table9[s2223];
-  const SWord8  s2225 = s2222 ^ s2224;
-  const SWord8  s2226 = s2219 ^ s2225;
-  const SWord8  s2227 = s2217 ^ s2226;
-  const SWord8  s2228 = table9[s2216];
-  const SWord8  s2229 = table6[s2218];
-  const SWord8  s2230 = table7[s2221];
-  const SWord8  s2231 = table8[s2223];
-  const SWord8  s2232 = s2230 ^ s2231;
-  const SWord8  s2233 = s2229 ^ s2232;
-  const SWord8  s2234 = s2228 ^ s2233;
-  const SWord16 s2235 = (((SWord16) s2227) << 8) | ((SWord16) s2234);
-  const SWord8  s2236 = table8[s2216];
-  const SWord8  s2237 = table9[s2218];
-  const SWord8  s2238 = table6[s2221];
-  const SWord8  s2239 = table7[s2223];
-  const SWord8  s2240 = s2238 ^ s2239;
-  const SWord8  s2241 = s2237 ^ s2240;
-  const SWord8  s2242 = s2236 ^ s2241;
-  const SWord8  s2243 = table7[s2216];
-  const SWord8  s2244 = table8[s2218];
-  const SWord8  s2245 = table9[s2221];
-  const SWord8  s2246 = table6[s2223];
-  const SWord8  s2247 = s2245 ^ s2246;
-  const SWord8  s2248 = s2244 ^ s2247;
-  const SWord8  s2249 = s2243 ^ s2248;
-  const SWord16 s2250 = (((SWord16) s2242) << 8) | ((SWord16) s2249);
-  const SWord32 s2251 = (((SWord32) s2235) << 16) | ((SWord32) s2250);
-  const SWord32 s2252 = s2214 ^ s2251;
-  const SWord16 s2253 = (SWord16) s2252;
-  const SWord8  s2254 = (SWord8) (s2253 >> 8);
-  const SWord32 s2255 = table4[s2254];
-  const SWord32 s2256 = s2201 ^ s2255;
-  const SWord8  s2257 = (SWord8) (s2204 >> 8);
-  const SWord32 s2258 = table1[s2257];
-  const SWord8  s2259 = (SWord8) s1940;
-  const SWord32 s2260 = table3[s2259];
-  const SWord32 s2261 = s2258 ^ s2260;
-  const SWord8  s2262 = (SWord8) (s2211 >> 8);
-  const SWord32 s2263 = table4[s2262];
-  const SWord32 s2264 = s2261 ^ s2263;
-  const SWord8  s2265 = (SWord8) s2049;
-  const SWord32 s2266 = table5[s2265];
-  const SWord32 s2267 = s2264 ^ s2266;
-  const SWord16 s2268 = (SWord16) (s631 >> 16);
-  const SWord8  s2269 = (SWord8) (s2268 >> 8);
-  const SWord8  s2270 = table6[s2269];
-  const SWord8  s2271 = (SWord8) s2268;
-  const SWord8  s2272 = table7[s2271];
-  const SWord16 s2273 = (SWord16) s631;
-  const SWord8  s2274 = (SWord8) (s2273 >> 8);
-  const SWord8  s2275 = table8[s2274];
-  const SWord8  s2276 = (SWord8) s2273;
-  const SWord8  s2277 = table9[s2276];
-  const SWord8  s2278 = s2275 ^ s2277;
-  const SWord8  s2279 = s2272 ^ s2278;
-  const SWord8  s2280 = s2270 ^ s2279;
-  const SWord8  s2281 = table9[s2269];
-  const SWord8  s2282 = table6[s2271];
-  const SWord8  s2283 = table7[s2274];
-  const SWord8  s2284 = table8[s2276];
-  const SWord8  s2285 = s2283 ^ s2284;
-  const SWord8  s2286 = s2282 ^ s2285;
-  const SWord8  s2287 = s2281 ^ s2286;
-  const SWord16 s2288 = (((SWord16) s2280) << 8) | ((SWord16) s2287);
-  const SWord8  s2289 = table8[s2269];
-  const SWord8  s2290 = table9[s2271];
-  const SWord8  s2291 = table6[s2274];
-  const SWord8  s2292 = table7[s2276];
-  const SWord8  s2293 = s2291 ^ s2292;
-  const SWord8  s2294 = s2290 ^ s2293;
-  const SWord8  s2295 = s2289 ^ s2294;
-  const SWord8  s2296 = table7[s2269];
-  const SWord8  s2297 = table8[s2271];
-  const SWord8  s2298 = table9[s2274];
-  const SWord8  s2299 = table6[s2276];
-  const SWord8  s2300 = s2298 ^ s2299;
-  const SWord8  s2301 = s2297 ^ s2300;
-  const SWord8  s2302 = s2296 ^ s2301;
-  const SWord16 s2303 = (((SWord16) s2295) << 8) | ((SWord16) s2302);
-  const SWord32 s2304 = (((SWord32) s2288) << 16) | ((SWord32) s2303);
-  const SWord32 s2305 = s2267 ^ s2304;
-  const SWord16 s2306 = (SWord16) s2305;
-  const SWord8  s2307 = (SWord8) s2306;
-  const SWord32 s2308 = table5[s2307];
-  const SWord32 s2309 = s2256 ^ s2308;
-  const SWord16 s2310 = (SWord16) (s611 >> 16);
-  const SWord8  s2311 = (SWord8) (s2310 >> 8);
-  const SWord8  s2312 = table6[s2311];
-  const SWord8  s2313 = (SWord8) s2310;
-  const SWord8  s2314 = table7[s2313];
-  const SWord16 s2315 = (SWord16) s611;
-  const SWord8  s2316 = (SWord8) (s2315 >> 8);
-  const SWord8  s2317 = table8[s2316];
-  const SWord8  s2318 = (SWord8) s2315;
-  const SWord8  s2319 = table9[s2318];
-  const SWord8  s2320 = s2317 ^ s2319;
-  const SWord8  s2321 = s2314 ^ s2320;
-  const SWord8  s2322 = s2312 ^ s2321;
-  const SWord8  s2323 = table9[s2311];
-  const SWord8  s2324 = table6[s2313];
-  const SWord8  s2325 = table7[s2316];
-  const SWord8  s2326 = table8[s2318];
-  const SWord8  s2327 = s2325 ^ s2326;
-  const SWord8  s2328 = s2324 ^ s2327;
-  const SWord8  s2329 = s2323 ^ s2328;
-  const SWord16 s2330 = (((SWord16) s2322) << 8) | ((SWord16) s2329);
-  const SWord8  s2331 = table8[s2311];
-  const SWord8  s2332 = table9[s2313];
-  const SWord8  s2333 = table6[s2316];
-  const SWord8  s2334 = table7[s2318];
-  const SWord8  s2335 = s2333 ^ s2334;
-  const SWord8  s2336 = s2332 ^ s2335;
-  const SWord8  s2337 = s2331 ^ s2336;
-  const SWord8  s2338 = table7[s2311];
-  const SWord8  s2339 = table8[s2313];
-  const SWord8  s2340 = table9[s2316];
-  const SWord8  s2341 = table6[s2318];
-  const SWord8  s2342 = s2340 ^ s2341;
-  const SWord8  s2343 = s2339 ^ s2342;
-  const SWord8  s2344 = s2338 ^ s2343;
-  const SWord16 s2345 = (((SWord16) s2337) << 8) | ((SWord16) s2344);
-  const SWord32 s2346 = (((SWord32) s2330) << 16) | ((SWord32) s2345);
-  const SWord32 s2347 = s2309 ^ s2346;
-  const SWord16 s2348 = (SWord16) (s2347 >> 16);
-  const SWord8  s2349 = (SWord8) (s2348 >> 8);
-  const SWord32 s2350 = table1[s2349];
-  const SWord8  s2351 = (SWord8) (s2198 >> 8);
-  const SWord32 s2352 = table1[s2351];
-  const SWord16 s2353 = (SWord16) (s2252 >> 16);
-  const SWord8  s2354 = (SWord8) s2353;
-  const SWord32 s2355 = table3[s2354];
-  const SWord32 s2356 = s2352 ^ s2355;
-  const SWord8  s2357 = (SWord8) (s2306 >> 8);
-  const SWord32 s2358 = table4[s2357];
-  const SWord32 s2359 = s2356 ^ s2358;
-  const SWord16 s2360 = (SWord16) s2143;
-  const SWord8  s2361 = (SWord8) s2360;
-  const SWord32 s2362 = table5[s2361];
-  const SWord32 s2363 = s2359 ^ s2362;
-  const SWord16 s2364 = (SWord16) (s614 >> 16);
-  const SWord8  s2365 = (SWord8) (s2364 >> 8);
-  const SWord8  s2366 = table6[s2365];
-  const SWord8  s2367 = (SWord8) s2364;
-  const SWord8  s2368 = table7[s2367];
-  const SWord16 s2369 = (SWord16) s614;
-  const SWord8  s2370 = (SWord8) (s2369 >> 8);
-  const SWord8  s2371 = table8[s2370];
-  const SWord8  s2372 = (SWord8) s2369;
-  const SWord8  s2373 = table9[s2372];
-  const SWord8  s2374 = s2371 ^ s2373;
-  const SWord8  s2375 = s2368 ^ s2374;
-  const SWord8  s2376 = s2366 ^ s2375;
-  const SWord8  s2377 = table9[s2365];
-  const SWord8  s2378 = table6[s2367];
-  const SWord8  s2379 = table7[s2370];
-  const SWord8  s2380 = table8[s2372];
-  const SWord8  s2381 = s2379 ^ s2380;
-  const SWord8  s2382 = s2378 ^ s2381;
-  const SWord8  s2383 = s2377 ^ s2382;
-  const SWord16 s2384 = (((SWord16) s2376) << 8) | ((SWord16) s2383);
-  const SWord8  s2385 = table8[s2365];
-  const SWord8  s2386 = table9[s2367];
-  const SWord8  s2387 = table6[s2370];
-  const SWord8  s2388 = table7[s2372];
-  const SWord8  s2389 = s2387 ^ s2388;
-  const SWord8  s2390 = s2386 ^ s2389;
-  const SWord8  s2391 = s2385 ^ s2390;
-  const SWord8  s2392 = table7[s2365];
-  const SWord8  s2393 = table8[s2367];
-  const SWord8  s2394 = table9[s2370];
-  const SWord8  s2395 = table6[s2372];
-  const SWord8  s2396 = s2394 ^ s2395;
-  const SWord8  s2397 = s2393 ^ s2396;
-  const SWord8  s2398 = s2392 ^ s2397;
-  const SWord16 s2399 = (((SWord16) s2391) << 8) | ((SWord16) s2398);
-  const SWord32 s2400 = (((SWord32) s2384) << 16) | ((SWord32) s2399);
-  const SWord32 s2401 = s2363 ^ s2400;
-  const SWord16 s2402 = (SWord16) (s2401 >> 16);
-  const SWord8  s2403 = (SWord8) s2402;
-  const SWord32 s2404 = table3[s2403];
-  const SWord32 s2405 = s2350 ^ s2404;
-  const SWord8  s2406 = (SWord8) (s2353 >> 8);
-  const SWord32 s2407 = table1[s2406];
-  const SWord16 s2408 = (SWord16) (s2305 >> 16);
-  const SWord8  s2409 = (SWord8) s2408;
-  const SWord32 s2410 = table3[s2409];
-  const SWord32 s2411 = s2407 ^ s2410;
-  const SWord8  s2412 = (SWord8) (s2360 >> 8);
-  const SWord32 s2413 = table4[s2412];
-  const SWord32 s2414 = s2411 ^ s2413;
-  const SWord16 s2415 = (SWord16) s2197;
-  const SWord8  s2416 = (SWord8) s2415;
-  const SWord32 s2417 = table5[s2416];
-  const SWord32 s2418 = s2414 ^ s2417;
-  const SWord16 s2419 = (SWord16) (s613 >> 16);
-  const SWord8  s2420 = (SWord8) (s2419 >> 8);
-  const SWord8  s2421 = table6[s2420];
-  const SWord8  s2422 = (SWord8) s2419;
-  const SWord8  s2423 = table7[s2422];
-  const SWord16 s2424 = (SWord16) s613;
-  const SWord8  s2425 = (SWord8) (s2424 >> 8);
-  const SWord8  s2426 = table8[s2425];
-  const SWord8  s2427 = (SWord8) s2424;
-  const SWord8  s2428 = table9[s2427];
-  const SWord8  s2429 = s2426 ^ s2428;
-  const SWord8  s2430 = s2423 ^ s2429;
-  const SWord8  s2431 = s2421 ^ s2430;
-  const SWord8  s2432 = table9[s2420];
-  const SWord8  s2433 = table6[s2422];
-  const SWord8  s2434 = table7[s2425];
-  const SWord8  s2435 = table8[s2427];
-  const SWord8  s2436 = s2434 ^ s2435;
-  const SWord8  s2437 = s2433 ^ s2436;
-  const SWord8  s2438 = s2432 ^ s2437;
-  const SWord16 s2439 = (((SWord16) s2431) << 8) | ((SWord16) s2438);
-  const SWord8  s2440 = table8[s2420];
-  const SWord8  s2441 = table9[s2422];
-  const SWord8  s2442 = table6[s2425];
-  const SWord8  s2443 = table7[s2427];
-  const SWord8  s2444 = s2442 ^ s2443;
-  const SWord8  s2445 = s2441 ^ s2444;
-  const SWord8  s2446 = s2440 ^ s2445;
-  const SWord8  s2447 = table7[s2420];
-  const SWord8  s2448 = table8[s2422];
-  const SWord8  s2449 = table9[s2425];
-  const SWord8  s2450 = table6[s2427];
-  const SWord8  s2451 = s2449 ^ s2450;
-  const SWord8  s2452 = s2448 ^ s2451;
-  const SWord8  s2453 = s2447 ^ s2452;
-  const SWord16 s2454 = (((SWord16) s2446) << 8) | ((SWord16) s2453);
-  const SWord32 s2455 = (((SWord32) s2439) << 16) | ((SWord32) s2454);
-  const SWord32 s2456 = s2418 ^ s2455;
-  const SWord16 s2457 = (SWord16) s2456;
-  const SWord8  s2458 = (SWord8) (s2457 >> 8);
-  const SWord32 s2459 = table4[s2458];
-  const SWord32 s2460 = s2405 ^ s2459;
-  const SWord8  s2461 = (SWord8) (s2408 >> 8);
-  const SWord32 s2462 = table1[s2461];
-  const SWord8  s2463 = (SWord8) s2144;
-  const SWord32 s2464 = table3[s2463];
-  const SWord32 s2465 = s2462 ^ s2464;
-  const SWord8  s2466 = (SWord8) (s2415 >> 8);
-  const SWord32 s2467 = table4[s2466];
-  const SWord32 s2468 = s2465 ^ s2467;
-  const SWord8  s2469 = (SWord8) s2253;
-  const SWord32 s2470 = table5[s2469];
-  const SWord32 s2471 = s2468 ^ s2470;
-  const SWord16 s2472 = (SWord16) (s612 >> 16);
-  const SWord8  s2473 = (SWord8) (s2472 >> 8);
-  const SWord8  s2474 = table6[s2473];
-  const SWord8  s2475 = (SWord8) s2472;
-  const SWord8  s2476 = table7[s2475];
-  const SWord16 s2477 = (SWord16) s612;
-  const SWord8  s2478 = (SWord8) (s2477 >> 8);
-  const SWord8  s2479 = table8[s2478];
-  const SWord8  s2480 = (SWord8) s2477;
-  const SWord8  s2481 = table9[s2480];
-  const SWord8  s2482 = s2479 ^ s2481;
-  const SWord8  s2483 = s2476 ^ s2482;
-  const SWord8  s2484 = s2474 ^ s2483;
-  const SWord8  s2485 = table9[s2473];
-  const SWord8  s2486 = table6[s2475];
-  const SWord8  s2487 = table7[s2478];
-  const SWord8  s2488 = table8[s2480];
-  const SWord8  s2489 = s2487 ^ s2488;
-  const SWord8  s2490 = s2486 ^ s2489;
-  const SWord8  s2491 = s2485 ^ s2490;
-  const SWord16 s2492 = (((SWord16) s2484) << 8) | ((SWord16) s2491);
-  const SWord8  s2493 = table8[s2473];
-  const SWord8  s2494 = table9[s2475];
-  const SWord8  s2495 = table6[s2478];
-  const SWord8  s2496 = table7[s2480];
-  const SWord8  s2497 = s2495 ^ s2496;
-  const SWord8  s2498 = s2494 ^ s2497;
-  const SWord8  s2499 = s2493 ^ s2498;
-  const SWord8  s2500 = table7[s2473];
-  const SWord8  s2501 = table8[s2475];
-  const SWord8  s2502 = table9[s2478];
-  const SWord8  s2503 = table6[s2480];
-  const SWord8  s2504 = s2502 ^ s2503;
-  const SWord8  s2505 = s2501 ^ s2504;
-  const SWord8  s2506 = s2500 ^ s2505;
-  const SWord16 s2507 = (((SWord16) s2499) << 8) | ((SWord16) s2506);
-  const SWord32 s2508 = (((SWord32) s2492) << 16) | ((SWord32) s2507);
-  const SWord32 s2509 = s2471 ^ s2508;
-  const SWord16 s2510 = (SWord16) s2509;
-  const SWord8  s2511 = (SWord8) s2510;
-  const SWord32 s2512 = table5[s2511];
-  const SWord32 s2513 = s2460 ^ s2512;
-  const SWord16 s2514 = (SWord16) (s592 >> 16);
-  const SWord8  s2515 = (SWord8) (s2514 >> 8);
-  const SWord8  s2516 = table6[s2515];
-  const SWord8  s2517 = (SWord8) s2514;
-  const SWord8  s2518 = table7[s2517];
-  const SWord16 s2519 = (SWord16) s592;
-  const SWord8  s2520 = (SWord8) (s2519 >> 8);
-  const SWord8  s2521 = table8[s2520];
-  const SWord8  s2522 = (SWord8) s2519;
-  const SWord8  s2523 = table9[s2522];
-  const SWord8  s2524 = s2521 ^ s2523;
-  const SWord8  s2525 = s2518 ^ s2524;
-  const SWord8  s2526 = s2516 ^ s2525;
-  const SWord8  s2527 = table9[s2515];
-  const SWord8  s2528 = table6[s2517];
-  const SWord8  s2529 = table7[s2520];
-  const SWord8  s2530 = table8[s2522];
-  const SWord8  s2531 = s2529 ^ s2530;
-  const SWord8  s2532 = s2528 ^ s2531;
-  const SWord8  s2533 = s2527 ^ s2532;
-  const SWord16 s2534 = (((SWord16) s2526) << 8) | ((SWord16) s2533);
-  const SWord8  s2535 = table8[s2515];
-  const SWord8  s2536 = table9[s2517];
-  const SWord8  s2537 = table6[s2520];
-  const SWord8  s2538 = table7[s2522];
-  const SWord8  s2539 = s2537 ^ s2538;
-  const SWord8  s2540 = s2536 ^ s2539;
-  const SWord8  s2541 = s2535 ^ s2540;
-  const SWord8  s2542 = table7[s2515];
-  const SWord8  s2543 = table8[s2517];
-  const SWord8  s2544 = table9[s2520];
-  const SWord8  s2545 = table6[s2522];
-  const SWord8  s2546 = s2544 ^ s2545;
-  const SWord8  s2547 = s2543 ^ s2546;
-  const SWord8  s2548 = s2542 ^ s2547;
-  const SWord16 s2549 = (((SWord16) s2541) << 8) | ((SWord16) s2548);
-  const SWord32 s2550 = (((SWord32) s2534) << 16) | ((SWord32) s2549);
-  const SWord32 s2551 = s2513 ^ s2550;
-  const SWord16 s2552 = (SWord16) (s2551 >> 16);
-  const SWord8  s2553 = (SWord8) (s2552 >> 8);
-  const SWord32 s2554 = table1[s2553];
-  const SWord8  s2555 = (SWord8) (s2402 >> 8);
-  const SWord32 s2556 = table1[s2555];
-  const SWord16 s2557 = (SWord16) (s2456 >> 16);
-  const SWord8  s2558 = (SWord8) s2557;
-  const SWord32 s2559 = table3[s2558];
-  const SWord32 s2560 = s2556 ^ s2559;
-  const SWord8  s2561 = (SWord8) (s2510 >> 8);
-  const SWord32 s2562 = table4[s2561];
-  const SWord32 s2563 = s2560 ^ s2562;
-  const SWord16 s2564 = (SWord16) s2347;
-  const SWord8  s2565 = (SWord8) s2564;
-  const SWord32 s2566 = table5[s2565];
-  const SWord32 s2567 = s2563 ^ s2566;
-  const SWord16 s2568 = (SWord16) (s595 >> 16);
-  const SWord8  s2569 = (SWord8) (s2568 >> 8);
-  const SWord8  s2570 = table6[s2569];
-  const SWord8  s2571 = (SWord8) s2568;
-  const SWord8  s2572 = table7[s2571];
-  const SWord16 s2573 = (SWord16) s595;
-  const SWord8  s2574 = (SWord8) (s2573 >> 8);
-  const SWord8  s2575 = table8[s2574];
-  const SWord8  s2576 = (SWord8) s2573;
-  const SWord8  s2577 = table9[s2576];
-  const SWord8  s2578 = s2575 ^ s2577;
-  const SWord8  s2579 = s2572 ^ s2578;
-  const SWord8  s2580 = s2570 ^ s2579;
-  const SWord8  s2581 = table9[s2569];
-  const SWord8  s2582 = table6[s2571];
-  const SWord8  s2583 = table7[s2574];
-  const SWord8  s2584 = table8[s2576];
-  const SWord8  s2585 = s2583 ^ s2584;
-  const SWord8  s2586 = s2582 ^ s2585;
-  const SWord8  s2587 = s2581 ^ s2586;
-  const SWord16 s2588 = (((SWord16) s2580) << 8) | ((SWord16) s2587);
-  const SWord8  s2589 = table8[s2569];
-  const SWord8  s2590 = table9[s2571];
-  const SWord8  s2591 = table6[s2574];
-  const SWord8  s2592 = table7[s2576];
-  const SWord8  s2593 = s2591 ^ s2592;
-  const SWord8  s2594 = s2590 ^ s2593;
-  const SWord8  s2595 = s2589 ^ s2594;
-  const SWord8  s2596 = table7[s2569];
-  const SWord8  s2597 = table8[s2571];
-  const SWord8  s2598 = table9[s2574];
-  const SWord8  s2599 = table6[s2576];
-  const SWord8  s2600 = s2598 ^ s2599;
-  const SWord8  s2601 = s2597 ^ s2600;
-  const SWord8  s2602 = s2596 ^ s2601;
-  const SWord16 s2603 = (((SWord16) s2595) << 8) | ((SWord16) s2602);
-  const SWord32 s2604 = (((SWord32) s2588) << 16) | ((SWord32) s2603);
-  const SWord32 s2605 = s2567 ^ s2604;
-  const SWord16 s2606 = (SWord16) (s2605 >> 16);
-  const SWord8  s2607 = (SWord8) s2606;
-  const SWord32 s2608 = table3[s2607];
-  const SWord32 s2609 = s2554 ^ s2608;
-  const SWord8  s2610 = (SWord8) (s2557 >> 8);
-  const SWord32 s2611 = table1[s2610];
-  const SWord16 s2612 = (SWord16) (s2509 >> 16);
-  const SWord8  s2613 = (SWord8) s2612;
-  const SWord32 s2614 = table3[s2613];
-  const SWord32 s2615 = s2611 ^ s2614;
-  const SWord8  s2616 = (SWord8) (s2564 >> 8);
-  const SWord32 s2617 = table4[s2616];
-  const SWord32 s2618 = s2615 ^ s2617;
-  const SWord16 s2619 = (SWord16) s2401;
-  const SWord8  s2620 = (SWord8) s2619;
-  const SWord32 s2621 = table5[s2620];
-  const SWord32 s2622 = s2618 ^ s2621;
-  const SWord16 s2623 = (SWord16) (s594 >> 16);
-  const SWord8  s2624 = (SWord8) (s2623 >> 8);
-  const SWord8  s2625 = table6[s2624];
-  const SWord8  s2626 = (SWord8) s2623;
-  const SWord8  s2627 = table7[s2626];
-  const SWord16 s2628 = (SWord16) s594;
-  const SWord8  s2629 = (SWord8) (s2628 >> 8);
-  const SWord8  s2630 = table8[s2629];
-  const SWord8  s2631 = (SWord8) s2628;
-  const SWord8  s2632 = table9[s2631];
-  const SWord8  s2633 = s2630 ^ s2632;
-  const SWord8  s2634 = s2627 ^ s2633;
-  const SWord8  s2635 = s2625 ^ s2634;
-  const SWord8  s2636 = table9[s2624];
-  const SWord8  s2637 = table6[s2626];
-  const SWord8  s2638 = table7[s2629];
-  const SWord8  s2639 = table8[s2631];
-  const SWord8  s2640 = s2638 ^ s2639;
-  const SWord8  s2641 = s2637 ^ s2640;
-  const SWord8  s2642 = s2636 ^ s2641;
-  const SWord16 s2643 = (((SWord16) s2635) << 8) | ((SWord16) s2642);
-  const SWord8  s2644 = table8[s2624];
-  const SWord8  s2645 = table9[s2626];
-  const SWord8  s2646 = table6[s2629];
-  const SWord8  s2647 = table7[s2631];
-  const SWord8  s2648 = s2646 ^ s2647;
-  const SWord8  s2649 = s2645 ^ s2648;
-  const SWord8  s2650 = s2644 ^ s2649;
-  const SWord8  s2651 = table7[s2624];
-  const SWord8  s2652 = table8[s2626];
-  const SWord8  s2653 = table9[s2629];
-  const SWord8  s2654 = table6[s2631];
-  const SWord8  s2655 = s2653 ^ s2654;
-  const SWord8  s2656 = s2652 ^ s2655;
-  const SWord8  s2657 = s2651 ^ s2656;
-  const SWord16 s2658 = (((SWord16) s2650) << 8) | ((SWord16) s2657);
-  const SWord32 s2659 = (((SWord32) s2643) << 16) | ((SWord32) s2658);
-  const SWord32 s2660 = s2622 ^ s2659;
-  const SWord16 s2661 = (SWord16) s2660;
-  const SWord8  s2662 = (SWord8) (s2661 >> 8);
-  const SWord32 s2663 = table4[s2662];
-  const SWord32 s2664 = s2609 ^ s2663;
-  const SWord8  s2665 = (SWord8) (s2612 >> 8);
-  const SWord32 s2666 = table1[s2665];
-  const SWord8  s2667 = (SWord8) s2348;
-  const SWord32 s2668 = table3[s2667];
-  const SWord32 s2669 = s2666 ^ s2668;
-  const SWord8  s2670 = (SWord8) (s2619 >> 8);
-  const SWord32 s2671 = table4[s2670];
-  const SWord32 s2672 = s2669 ^ s2671;
-  const SWord8  s2673 = (SWord8) s2457;
-  const SWord32 s2674 = table5[s2673];
-  const SWord32 s2675 = s2672 ^ s2674;
-  const SWord16 s2676 = (SWord16) (s593 >> 16);
-  const SWord8  s2677 = (SWord8) (s2676 >> 8);
-  const SWord8  s2678 = table6[s2677];
-  const SWord8  s2679 = (SWord8) s2676;
-  const SWord8  s2680 = table7[s2679];
-  const SWord16 s2681 = (SWord16) s593;
-  const SWord8  s2682 = (SWord8) (s2681 >> 8);
-  const SWord8  s2683 = table8[s2682];
-  const SWord8  s2684 = (SWord8) s2681;
-  const SWord8  s2685 = table9[s2684];
-  const SWord8  s2686 = s2683 ^ s2685;
-  const SWord8  s2687 = s2680 ^ s2686;
-  const SWord8  s2688 = s2678 ^ s2687;
-  const SWord8  s2689 = table9[s2677];
-  const SWord8  s2690 = table6[s2679];
-  const SWord8  s2691 = table7[s2682];
-  const SWord8  s2692 = table8[s2684];
-  const SWord8  s2693 = s2691 ^ s2692;
-  const SWord8  s2694 = s2690 ^ s2693;
-  const SWord8  s2695 = s2689 ^ s2694;
-  const SWord16 s2696 = (((SWord16) s2688) << 8) | ((SWord16) s2695);
-  const SWord8  s2697 = table8[s2677];
-  const SWord8  s2698 = table9[s2679];
-  const SWord8  s2699 = table6[s2682];
-  const SWord8  s2700 = table7[s2684];
-  const SWord8  s2701 = s2699 ^ s2700;
-  const SWord8  s2702 = s2698 ^ s2701;
-  const SWord8  s2703 = s2697 ^ s2702;
-  const SWord8  s2704 = table7[s2677];
-  const SWord8  s2705 = table8[s2679];
-  const SWord8  s2706 = table9[s2682];
-  const SWord8  s2707 = table6[s2684];
-  const SWord8  s2708 = s2706 ^ s2707;
-  const SWord8  s2709 = s2705 ^ s2708;
-  const SWord8  s2710 = s2704 ^ s2709;
-  const SWord16 s2711 = (((SWord16) s2703) << 8) | ((SWord16) s2710);
-  const SWord32 s2712 = (((SWord32) s2696) << 16) | ((SWord32) s2711);
-  const SWord32 s2713 = s2675 ^ s2712;
-  const SWord16 s2714 = (SWord16) s2713;
-  const SWord8  s2715 = (SWord8) s2714;
-  const SWord32 s2716 = table5[s2715];
-  const SWord32 s2717 = s2664 ^ s2716;
-  const SWord16 s2718 = (SWord16) (s573 >> 16);
-  const SWord8  s2719 = (SWord8) (s2718 >> 8);
-  const SWord8  s2720 = table6[s2719];
-  const SWord8  s2721 = (SWord8) s2718;
-  const SWord8  s2722 = table7[s2721];
-  const SWord16 s2723 = (SWord16) s573;
-  const SWord8  s2724 = (SWord8) (s2723 >> 8);
-  const SWord8  s2725 = table8[s2724];
-  const SWord8  s2726 = (SWord8) s2723;
-  const SWord8  s2727 = table9[s2726];
-  const SWord8  s2728 = s2725 ^ s2727;
-  const SWord8  s2729 = s2722 ^ s2728;
-  const SWord8  s2730 = s2720 ^ s2729;
-  const SWord8  s2731 = table9[s2719];
-  const SWord8  s2732 = table6[s2721];
-  const SWord8  s2733 = table7[s2724];
-  const SWord8  s2734 = table8[s2726];
-  const SWord8  s2735 = s2733 ^ s2734;
-  const SWord8  s2736 = s2732 ^ s2735;
-  const SWord8  s2737 = s2731 ^ s2736;
-  const SWord16 s2738 = (((SWord16) s2730) << 8) | ((SWord16) s2737);
-  const SWord8  s2739 = table8[s2719];
-  const SWord8  s2740 = table9[s2721];
-  const SWord8  s2741 = table6[s2724];
-  const SWord8  s2742 = table7[s2726];
-  const SWord8  s2743 = s2741 ^ s2742;
-  const SWord8  s2744 = s2740 ^ s2743;
-  const SWord8  s2745 = s2739 ^ s2744;
-  const SWord8  s2746 = table7[s2719];
-  const SWord8  s2747 = table8[s2721];
-  const SWord8  s2748 = table9[s2724];
-  const SWord8  s2749 = table6[s2726];
-  const SWord8  s2750 = s2748 ^ s2749;
-  const SWord8  s2751 = s2747 ^ s2750;
-  const SWord8  s2752 = s2746 ^ s2751;
-  const SWord16 s2753 = (((SWord16) s2745) << 8) | ((SWord16) s2752);
-  const SWord32 s2754 = (((SWord32) s2738) << 16) | ((SWord32) s2753);
-  const SWord32 s2755 = s2717 ^ s2754;
-  const SWord16 s2756 = (SWord16) (s2755 >> 16);
-  const SWord8  s2757 = (SWord8) (s2756 >> 8);
-  const SWord32 s2758 = table1[s2757];
-  const SWord8  s2759 = (SWord8) (s2606 >> 8);
-  const SWord32 s2760 = table1[s2759];
-  const SWord16 s2761 = (SWord16) (s2660 >> 16);
-  const SWord8  s2762 = (SWord8) s2761;
-  const SWord32 s2763 = table3[s2762];
-  const SWord32 s2764 = s2760 ^ s2763;
-  const SWord8  s2765 = (SWord8) (s2714 >> 8);
-  const SWord32 s2766 = table4[s2765];
-  const SWord32 s2767 = s2764 ^ s2766;
-  const SWord16 s2768 = (SWord16) s2551;
-  const SWord8  s2769 = (SWord8) s2768;
-  const SWord32 s2770 = table5[s2769];
-  const SWord32 s2771 = s2767 ^ s2770;
-  const SWord16 s2772 = (SWord16) (s576 >> 16);
-  const SWord8  s2773 = (SWord8) (s2772 >> 8);
-  const SWord8  s2774 = table6[s2773];
-  const SWord8  s2775 = (SWord8) s2772;
-  const SWord8  s2776 = table7[s2775];
-  const SWord16 s2777 = (SWord16) s576;
-  const SWord8  s2778 = (SWord8) (s2777 >> 8);
-  const SWord8  s2779 = table8[s2778];
-  const SWord8  s2780 = (SWord8) s2777;
-  const SWord8  s2781 = table9[s2780];
-  const SWord8  s2782 = s2779 ^ s2781;
-  const SWord8  s2783 = s2776 ^ s2782;
-  const SWord8  s2784 = s2774 ^ s2783;
-  const SWord8  s2785 = table9[s2773];
-  const SWord8  s2786 = table6[s2775];
-  const SWord8  s2787 = table7[s2778];
-  const SWord8  s2788 = table8[s2780];
-  const SWord8  s2789 = s2787 ^ s2788;
-  const SWord8  s2790 = s2786 ^ s2789;
-  const SWord8  s2791 = s2785 ^ s2790;
-  const SWord16 s2792 = (((SWord16) s2784) << 8) | ((SWord16) s2791);
-  const SWord8  s2793 = table8[s2773];
-  const SWord8  s2794 = table9[s2775];
-  const SWord8  s2795 = table6[s2778];
-  const SWord8  s2796 = table7[s2780];
-  const SWord8  s2797 = s2795 ^ s2796;
-  const SWord8  s2798 = s2794 ^ s2797;
-  const SWord8  s2799 = s2793 ^ s2798;
-  const SWord8  s2800 = table7[s2773];
-  const SWord8  s2801 = table8[s2775];
-  const SWord8  s2802 = table9[s2778];
-  const SWord8  s2803 = table6[s2780];
-  const SWord8  s2804 = s2802 ^ s2803;
-  const SWord8  s2805 = s2801 ^ s2804;
-  const SWord8  s2806 = s2800 ^ s2805;
-  const SWord16 s2807 = (((SWord16) s2799) << 8) | ((SWord16) s2806);
-  const SWord32 s2808 = (((SWord32) s2792) << 16) | ((SWord32) s2807);
-  const SWord32 s2809 = s2771 ^ s2808;
-  const SWord16 s2810 = (SWord16) (s2809 >> 16);
-  const SWord8  s2811 = (SWord8) s2810;
-  const SWord32 s2812 = table3[s2811];
-  const SWord32 s2813 = s2758 ^ s2812;
-  const SWord8  s2814 = (SWord8) (s2761 >> 8);
-  const SWord32 s2815 = table1[s2814];
-  const SWord16 s2816 = (SWord16) (s2713 >> 16);
-  const SWord8  s2817 = (SWord8) s2816;
-  const SWord32 s2818 = table3[s2817];
-  const SWord32 s2819 = s2815 ^ s2818;
-  const SWord8  s2820 = (SWord8) (s2768 >> 8);
-  const SWord32 s2821 = table4[s2820];
-  const SWord32 s2822 = s2819 ^ s2821;
-  const SWord16 s2823 = (SWord16) s2605;
-  const SWord8  s2824 = (SWord8) s2823;
-  const SWord32 s2825 = table5[s2824];
-  const SWord32 s2826 = s2822 ^ s2825;
-  const SWord16 s2827 = (SWord16) (s575 >> 16);
-  const SWord8  s2828 = (SWord8) (s2827 >> 8);
-  const SWord8  s2829 = table6[s2828];
-  const SWord8  s2830 = (SWord8) s2827;
-  const SWord8  s2831 = table7[s2830];
-  const SWord16 s2832 = (SWord16) s575;
-  const SWord8  s2833 = (SWord8) (s2832 >> 8);
-  const SWord8  s2834 = table8[s2833];
-  const SWord8  s2835 = (SWord8) s2832;
-  const SWord8  s2836 = table9[s2835];
-  const SWord8  s2837 = s2834 ^ s2836;
-  const SWord8  s2838 = s2831 ^ s2837;
-  const SWord8  s2839 = s2829 ^ s2838;
-  const SWord8  s2840 = table9[s2828];
-  const SWord8  s2841 = table6[s2830];
-  const SWord8  s2842 = table7[s2833];
-  const SWord8  s2843 = table8[s2835];
-  const SWord8  s2844 = s2842 ^ s2843;
-  const SWord8  s2845 = s2841 ^ s2844;
-  const SWord8  s2846 = s2840 ^ s2845;
-  const SWord16 s2847 = (((SWord16) s2839) << 8) | ((SWord16) s2846);
-  const SWord8  s2848 = table8[s2828];
-  const SWord8  s2849 = table9[s2830];
-  const SWord8  s2850 = table6[s2833];
-  const SWord8  s2851 = table7[s2835];
-  const SWord8  s2852 = s2850 ^ s2851;
-  const SWord8  s2853 = s2849 ^ s2852;
-  const SWord8  s2854 = s2848 ^ s2853;
-  const SWord8  s2855 = table7[s2828];
-  const SWord8  s2856 = table8[s2830];
-  const SWord8  s2857 = table9[s2833];
-  const SWord8  s2858 = table6[s2835];
-  const SWord8  s2859 = s2857 ^ s2858;
-  const SWord8  s2860 = s2856 ^ s2859;
-  const SWord8  s2861 = s2855 ^ s2860;
-  const SWord16 s2862 = (((SWord16) s2854) << 8) | ((SWord16) s2861);
-  const SWord32 s2863 = (((SWord32) s2847) << 16) | ((SWord32) s2862);
-  const SWord32 s2864 = s2826 ^ s2863;
-  const SWord16 s2865 = (SWord16) s2864;
-  const SWord8  s2866 = (SWord8) (s2865 >> 8);
-  const SWord32 s2867 = table4[s2866];
-  const SWord32 s2868 = s2813 ^ s2867;
-  const SWord8  s2869 = (SWord8) (s2816 >> 8);
-  const SWord32 s2870 = table1[s2869];
-  const SWord8  s2871 = (SWord8) s2552;
-  const SWord32 s2872 = table3[s2871];
-  const SWord32 s2873 = s2870 ^ s2872;
-  const SWord8  s2874 = (SWord8) (s2823 >> 8);
-  const SWord32 s2875 = table4[s2874];
-  const SWord32 s2876 = s2873 ^ s2875;
-  const SWord8  s2877 = (SWord8) s2661;
-  const SWord32 s2878 = table5[s2877];
-  const SWord32 s2879 = s2876 ^ s2878;
-  const SWord16 s2880 = (SWord16) (s574 >> 16);
-  const SWord8  s2881 = (SWord8) (s2880 >> 8);
-  const SWord8  s2882 = table6[s2881];
-  const SWord8  s2883 = (SWord8) s2880;
-  const SWord8  s2884 = table7[s2883];
-  const SWord16 s2885 = (SWord16) s574;
-  const SWord8  s2886 = (SWord8) (s2885 >> 8);
-  const SWord8  s2887 = table8[s2886];
-  const SWord8  s2888 = (SWord8) s2885;
-  const SWord8  s2889 = table9[s2888];
-  const SWord8  s2890 = s2887 ^ s2889;
-  const SWord8  s2891 = s2884 ^ s2890;
-  const SWord8  s2892 = s2882 ^ s2891;
-  const SWord8  s2893 = table9[s2881];
-  const SWord8  s2894 = table6[s2883];
-  const SWord8  s2895 = table7[s2886];
-  const SWord8  s2896 = table8[s2888];
-  const SWord8  s2897 = s2895 ^ s2896;
-  const SWord8  s2898 = s2894 ^ s2897;
-  const SWord8  s2899 = s2893 ^ s2898;
-  const SWord16 s2900 = (((SWord16) s2892) << 8) | ((SWord16) s2899);
-  const SWord8  s2901 = table8[s2881];
-  const SWord8  s2902 = table9[s2883];
-  const SWord8  s2903 = table6[s2886];
-  const SWord8  s2904 = table7[s2888];
-  const SWord8  s2905 = s2903 ^ s2904;
-  const SWord8  s2906 = s2902 ^ s2905;
-  const SWord8  s2907 = s2901 ^ s2906;
-  const SWord8  s2908 = table7[s2881];
-  const SWord8  s2909 = table8[s2883];
-  const SWord8  s2910 = table9[s2886];
-  const SWord8  s2911 = table6[s2888];
-  const SWord8  s2912 = s2910 ^ s2911;
-  const SWord8  s2913 = s2909 ^ s2912;
-  const SWord8  s2914 = s2908 ^ s2913;
-  const SWord16 s2915 = (((SWord16) s2907) << 8) | ((SWord16) s2914);
-  const SWord32 s2916 = (((SWord32) s2900) << 16) | ((SWord32) s2915);
-  const SWord32 s2917 = s2879 ^ s2916;
-  const SWord16 s2918 = (SWord16) s2917;
-  const SWord8  s2919 = (SWord8) s2918;
-  const SWord32 s2920 = table5[s2919];
-  const SWord32 s2921 = s2868 ^ s2920;
-  const SWord16 s2922 = (SWord16) (s554 >> 16);
-  const SWord8  s2923 = (SWord8) (s2922 >> 8);
-  const SWord8  s2924 = table6[s2923];
-  const SWord8  s2925 = (SWord8) s2922;
-  const SWord8  s2926 = table7[s2925];
-  const SWord16 s2927 = (SWord16) s554;
-  const SWord8  s2928 = (SWord8) (s2927 >> 8);
-  const SWord8  s2929 = table8[s2928];
-  const SWord8  s2930 = (SWord8) s2927;
-  const SWord8  s2931 = table9[s2930];
-  const SWord8  s2932 = s2929 ^ s2931;
-  const SWord8  s2933 = s2926 ^ s2932;
-  const SWord8  s2934 = s2924 ^ s2933;
-  const SWord8  s2935 = table9[s2923];
-  const SWord8  s2936 = table6[s2925];
-  const SWord8  s2937 = table7[s2928];
-  const SWord8  s2938 = table8[s2930];
-  const SWord8  s2939 = s2937 ^ s2938;
-  const SWord8  s2940 = s2936 ^ s2939;
-  const SWord8  s2941 = s2935 ^ s2940;
-  const SWord16 s2942 = (((SWord16) s2934) << 8) | ((SWord16) s2941);
-  const SWord8  s2943 = table8[s2923];
-  const SWord8  s2944 = table9[s2925];
-  const SWord8  s2945 = table6[s2928];
-  const SWord8  s2946 = table7[s2930];
-  const SWord8  s2947 = s2945 ^ s2946;
-  const SWord8  s2948 = s2944 ^ s2947;
-  const SWord8  s2949 = s2943 ^ s2948;
-  const SWord8  s2950 = table7[s2923];
-  const SWord8  s2951 = table8[s2925];
-  const SWord8  s2952 = table9[s2928];
-  const SWord8  s2953 = table6[s2930];
-  const SWord8  s2954 = s2952 ^ s2953;
-  const SWord8  s2955 = s2951 ^ s2954;
-  const SWord8  s2956 = s2950 ^ s2955;
-  const SWord16 s2957 = (((SWord16) s2949) << 8) | ((SWord16) s2956);
-  const SWord32 s2958 = (((SWord32) s2942) << 16) | ((SWord32) s2957);
-  const SWord32 s2959 = s2921 ^ s2958;
-  const SWord16 s2960 = (SWord16) (s2959 >> 16);
-  const SWord8  s2961 = (SWord8) (s2960 >> 8);
-  const SWord32 s2962 = table1[s2961];
-  const SWord8  s2963 = (SWord8) (s2810 >> 8);
-  const SWord32 s2964 = table1[s2963];
-  const SWord16 s2965 = (SWord16) (s2864 >> 16);
-  const SWord8  s2966 = (SWord8) s2965;
-  const SWord32 s2967 = table3[s2966];
-  const SWord32 s2968 = s2964 ^ s2967;
-  const SWord8  s2969 = (SWord8) (s2918 >> 8);
-  const SWord32 s2970 = table4[s2969];
-  const SWord32 s2971 = s2968 ^ s2970;
-  const SWord16 s2972 = (SWord16) s2755;
-  const SWord8  s2973 = (SWord8) s2972;
-  const SWord32 s2974 = table5[s2973];
-  const SWord32 s2975 = s2971 ^ s2974;
-  const SWord16 s2976 = (SWord16) (s557 >> 16);
-  const SWord8  s2977 = (SWord8) (s2976 >> 8);
-  const SWord8  s2978 = table6[s2977];
-  const SWord8  s2979 = (SWord8) s2976;
-  const SWord8  s2980 = table7[s2979];
-  const SWord16 s2981 = (SWord16) s557;
-  const SWord8  s2982 = (SWord8) (s2981 >> 8);
-  const SWord8  s2983 = table8[s2982];
-  const SWord8  s2984 = (SWord8) s2981;
-  const SWord8  s2985 = table9[s2984];
-  const SWord8  s2986 = s2983 ^ s2985;
-  const SWord8  s2987 = s2980 ^ s2986;
-  const SWord8  s2988 = s2978 ^ s2987;
-  const SWord8  s2989 = table9[s2977];
-  const SWord8  s2990 = table6[s2979];
-  const SWord8  s2991 = table7[s2982];
-  const SWord8  s2992 = table8[s2984];
-  const SWord8  s2993 = s2991 ^ s2992;
-  const SWord8  s2994 = s2990 ^ s2993;
-  const SWord8  s2995 = s2989 ^ s2994;
-  const SWord16 s2996 = (((SWord16) s2988) << 8) | ((SWord16) s2995);
-  const SWord8  s2997 = table8[s2977];
-  const SWord8  s2998 = table9[s2979];
-  const SWord8  s2999 = table6[s2982];
-  const SWord8  s3000 = table7[s2984];
-  const SWord8  s3001 = s2999 ^ s3000;
-  const SWord8  s3002 = s2998 ^ s3001;
-  const SWord8  s3003 = s2997 ^ s3002;
-  const SWord8  s3004 = table7[s2977];
-  const SWord8  s3005 = table8[s2979];
-  const SWord8  s3006 = table9[s2982];
-  const SWord8  s3007 = table6[s2984];
-  const SWord8  s3008 = s3006 ^ s3007;
-  const SWord8  s3009 = s3005 ^ s3008;
-  const SWord8  s3010 = s3004 ^ s3009;
-  const SWord16 s3011 = (((SWord16) s3003) << 8) | ((SWord16) s3010);
-  const SWord32 s3012 = (((SWord32) s2996) << 16) | ((SWord32) s3011);
-  const SWord32 s3013 = s2975 ^ s3012;
-  const SWord16 s3014 = (SWord16) (s3013 >> 16);
-  const SWord8  s3015 = (SWord8) s3014;
-  const SWord32 s3016 = table3[s3015];
-  const SWord32 s3017 = s2962 ^ s3016;
-  const SWord8  s3018 = (SWord8) (s2965 >> 8);
-  const SWord32 s3019 = table1[s3018];
-  const SWord16 s3020 = (SWord16) (s2917 >> 16);
-  const SWord8  s3021 = (SWord8) s3020;
-  const SWord32 s3022 = table3[s3021];
-  const SWord32 s3023 = s3019 ^ s3022;
-  const SWord8  s3024 = (SWord8) (s2972 >> 8);
-  const SWord32 s3025 = table4[s3024];
-  const SWord32 s3026 = s3023 ^ s3025;
-  const SWord16 s3027 = (SWord16) s2809;
-  const SWord8  s3028 = (SWord8) s3027;
-  const SWord32 s3029 = table5[s3028];
-  const SWord32 s3030 = s3026 ^ s3029;
-  const SWord16 s3031 = (SWord16) (s556 >> 16);
-  const SWord8  s3032 = (SWord8) (s3031 >> 8);
-  const SWord8  s3033 = table6[s3032];
-  const SWord8  s3034 = (SWord8) s3031;
-  const SWord8  s3035 = table7[s3034];
-  const SWord16 s3036 = (SWord16) s556;
-  const SWord8  s3037 = (SWord8) (s3036 >> 8);
-  const SWord8  s3038 = table8[s3037];
-  const SWord8  s3039 = (SWord8) s3036;
-  const SWord8  s3040 = table9[s3039];
-  const SWord8  s3041 = s3038 ^ s3040;
-  const SWord8  s3042 = s3035 ^ s3041;
-  const SWord8  s3043 = s3033 ^ s3042;
-  const SWord8  s3044 = table9[s3032];
-  const SWord8  s3045 = table6[s3034];
-  const SWord8  s3046 = table7[s3037];
-  const SWord8  s3047 = table8[s3039];
-  const SWord8  s3048 = s3046 ^ s3047;
-  const SWord8  s3049 = s3045 ^ s3048;
-  const SWord8  s3050 = s3044 ^ s3049;
-  const SWord16 s3051 = (((SWord16) s3043) << 8) | ((SWord16) s3050);
-  const SWord8  s3052 = table8[s3032];
-  const SWord8  s3053 = table9[s3034];
-  const SWord8  s3054 = table6[s3037];
-  const SWord8  s3055 = table7[s3039];
-  const SWord8  s3056 = s3054 ^ s3055;
-  const SWord8  s3057 = s3053 ^ s3056;
-  const SWord8  s3058 = s3052 ^ s3057;
-  const SWord8  s3059 = table7[s3032];
-  const SWord8  s3060 = table8[s3034];
-  const SWord8  s3061 = table9[s3037];
-  const SWord8  s3062 = table6[s3039];
-  const SWord8  s3063 = s3061 ^ s3062;
-  const SWord8  s3064 = s3060 ^ s3063;
-  const SWord8  s3065 = s3059 ^ s3064;
-  const SWord16 s3066 = (((SWord16) s3058) << 8) | ((SWord16) s3065);
-  const SWord32 s3067 = (((SWord32) s3051) << 16) | ((SWord32) s3066);
-  const SWord32 s3068 = s3030 ^ s3067;
-  const SWord16 s3069 = (SWord16) s3068;
-  const SWord8  s3070 = (SWord8) (s3069 >> 8);
-  const SWord32 s3071 = table4[s3070];
-  const SWord32 s3072 = s3017 ^ s3071;
-  const SWord8  s3073 = (SWord8) (s3020 >> 8);
-  const SWord32 s3074 = table1[s3073];
-  const SWord8  s3075 = (SWord8) s2756;
-  const SWord32 s3076 = table3[s3075];
-  const SWord32 s3077 = s3074 ^ s3076;
-  const SWord8  s3078 = (SWord8) (s3027 >> 8);
-  const SWord32 s3079 = table4[s3078];
-  const SWord32 s3080 = s3077 ^ s3079;
-  const SWord8  s3081 = (SWord8) s2865;
-  const SWord32 s3082 = table5[s3081];
-  const SWord32 s3083 = s3080 ^ s3082;
-  const SWord16 s3084 = (SWord16) (s555 >> 16);
-  const SWord8  s3085 = (SWord8) (s3084 >> 8);
-  const SWord8  s3086 = table6[s3085];
-  const SWord8  s3087 = (SWord8) s3084;
-  const SWord8  s3088 = table7[s3087];
-  const SWord16 s3089 = (SWord16) s555;
-  const SWord8  s3090 = (SWord8) (s3089 >> 8);
-  const SWord8  s3091 = table8[s3090];
-  const SWord8  s3092 = (SWord8) s3089;
-  const SWord8  s3093 = table9[s3092];
-  const SWord8  s3094 = s3091 ^ s3093;
-  const SWord8  s3095 = s3088 ^ s3094;
-  const SWord8  s3096 = s3086 ^ s3095;
-  const SWord8  s3097 = table9[s3085];
-  const SWord8  s3098 = table6[s3087];
-  const SWord8  s3099 = table7[s3090];
-  const SWord8  s3100 = table8[s3092];
-  const SWord8  s3101 = s3099 ^ s3100;
-  const SWord8  s3102 = s3098 ^ s3101;
-  const SWord8  s3103 = s3097 ^ s3102;
-  const SWord16 s3104 = (((SWord16) s3096) << 8) | ((SWord16) s3103);
-  const SWord8  s3105 = table8[s3085];
-  const SWord8  s3106 = table9[s3087];
-  const SWord8  s3107 = table6[s3090];
-  const SWord8  s3108 = table7[s3092];
-  const SWord8  s3109 = s3107 ^ s3108;
-  const SWord8  s3110 = s3106 ^ s3109;
-  const SWord8  s3111 = s3105 ^ s3110;
-  const SWord8  s3112 = table7[s3085];
-  const SWord8  s3113 = table8[s3087];
-  const SWord8  s3114 = table9[s3090];
-  const SWord8  s3115 = table6[s3092];
-  const SWord8  s3116 = s3114 ^ s3115;
-  const SWord8  s3117 = s3113 ^ s3116;
-  const SWord8  s3118 = s3112 ^ s3117;
-  const SWord16 s3119 = (((SWord16) s3111) << 8) | ((SWord16) s3118);
-  const SWord32 s3120 = (((SWord32) s3104) << 16) | ((SWord32) s3119);
-  const SWord32 s3121 = s3083 ^ s3120;
-  const SWord16 s3122 = (SWord16) s3121;
-  const SWord8  s3123 = (SWord8) s3122;
-  const SWord32 s3124 = table5[s3123];
-  const SWord32 s3125 = s3072 ^ s3124;
-  const SWord16 s3126 = (SWord16) (s535 >> 16);
-  const SWord8  s3127 = (SWord8) (s3126 >> 8);
-  const SWord8  s3128 = table6[s3127];
-  const SWord8  s3129 = (SWord8) s3126;
-  const SWord8  s3130 = table7[s3129];
-  const SWord16 s3131 = (SWord16) s535;
-  const SWord8  s3132 = (SWord8) (s3131 >> 8);
-  const SWord8  s3133 = table8[s3132];
-  const SWord8  s3134 = (SWord8) s3131;
-  const SWord8  s3135 = table9[s3134];
-  const SWord8  s3136 = s3133 ^ s3135;
-  const SWord8  s3137 = s3130 ^ s3136;
-  const SWord8  s3138 = s3128 ^ s3137;
-  const SWord8  s3139 = table9[s3127];
-  const SWord8  s3140 = table6[s3129];
-  const SWord8  s3141 = table7[s3132];
-  const SWord8  s3142 = table8[s3134];
-  const SWord8  s3143 = s3141 ^ s3142;
-  const SWord8  s3144 = s3140 ^ s3143;
-  const SWord8  s3145 = s3139 ^ s3144;
-  const SWord16 s3146 = (((SWord16) s3138) << 8) | ((SWord16) s3145);
-  const SWord8  s3147 = table8[s3127];
-  const SWord8  s3148 = table9[s3129];
-  const SWord8  s3149 = table6[s3132];
-  const SWord8  s3150 = table7[s3134];
-  const SWord8  s3151 = s3149 ^ s3150;
-  const SWord8  s3152 = s3148 ^ s3151;
-  const SWord8  s3153 = s3147 ^ s3152;
-  const SWord8  s3154 = table7[s3127];
-  const SWord8  s3155 = table8[s3129];
-  const SWord8  s3156 = table9[s3132];
-  const SWord8  s3157 = table6[s3134];
-  const SWord8  s3158 = s3156 ^ s3157;
-  const SWord8  s3159 = s3155 ^ s3158;
-  const SWord8  s3160 = s3154 ^ s3159;
-  const SWord16 s3161 = (((SWord16) s3153) << 8) | ((SWord16) s3160);
-  const SWord32 s3162 = (((SWord32) s3146) << 16) | ((SWord32) s3161);
-  const SWord32 s3163 = s3125 ^ s3162;
-  const SWord16 s3164 = (SWord16) (s3163 >> 16);
-  const SWord8  s3165 = (SWord8) (s3164 >> 8);
-  const SWord8  s3166 = table0[s3165];
-  const SWord8  s3167 = (SWord8) (s3014 >> 8);
-  const SWord32 s3168 = table1[s3167];
-  const SWord16 s3169 = (SWord16) (s3068 >> 16);
-  const SWord8  s3170 = (SWord8) s3169;
-  const SWord32 s3171 = table3[s3170];
-  const SWord32 s3172 = s3168 ^ s3171;
-  const SWord8  s3173 = (SWord8) (s3122 >> 8);
-  const SWord32 s3174 = table4[s3173];
-  const SWord32 s3175 = s3172 ^ s3174;
-  const SWord16 s3176 = (SWord16) s2959;
-  const SWord8  s3177 = (SWord8) s3176;
-  const SWord32 s3178 = table5[s3177];
-  const SWord32 s3179 = s3175 ^ s3178;
-  const SWord16 s3180 = (SWord16) (s538 >> 16);
-  const SWord8  s3181 = (SWord8) (s3180 >> 8);
-  const SWord8  s3182 = table6[s3181];
-  const SWord8  s3183 = (SWord8) s3180;
-  const SWord8  s3184 = table7[s3183];
-  const SWord16 s3185 = (SWord16) s538;
-  const SWord8  s3186 = (SWord8) (s3185 >> 8);
-  const SWord8  s3187 = table8[s3186];
-  const SWord8  s3188 = (SWord8) s3185;
-  const SWord8  s3189 = table9[s3188];
-  const SWord8  s3190 = s3187 ^ s3189;
-  const SWord8  s3191 = s3184 ^ s3190;
-  const SWord8  s3192 = s3182 ^ s3191;
-  const SWord8  s3193 = table9[s3181];
-  const SWord8  s3194 = table6[s3183];
-  const SWord8  s3195 = table7[s3186];
-  const SWord8  s3196 = table8[s3188];
-  const SWord8  s3197 = s3195 ^ s3196;
-  const SWord8  s3198 = s3194 ^ s3197;
-  const SWord8  s3199 = s3193 ^ s3198;
-  const SWord16 s3200 = (((SWord16) s3192) << 8) | ((SWord16) s3199);
-  const SWord8  s3201 = table8[s3181];
-  const SWord8  s3202 = table9[s3183];
-  const SWord8  s3203 = table6[s3186];
-  const SWord8  s3204 = table7[s3188];
-  const SWord8  s3205 = s3203 ^ s3204;
-  const SWord8  s3206 = s3202 ^ s3205;
-  const SWord8  s3207 = s3201 ^ s3206;
-  const SWord8  s3208 = table7[s3181];
-  const SWord8  s3209 = table8[s3183];
-  const SWord8  s3210 = table9[s3186];
-  const SWord8  s3211 = table6[s3188];
-  const SWord8  s3212 = s3210 ^ s3211;
-  const SWord8  s3213 = s3209 ^ s3212;
-  const SWord8  s3214 = s3208 ^ s3213;
-  const SWord16 s3215 = (((SWord16) s3207) << 8) | ((SWord16) s3214);
-  const SWord32 s3216 = (((SWord32) s3200) << 16) | ((SWord32) s3215);
-  const SWord32 s3217 = s3179 ^ s3216;
-  const SWord16 s3218 = (SWord16) (s3217 >> 16);
-  const SWord8  s3219 = (SWord8) s3218;
-  const SWord8  s3220 = table0[s3219];
-  const SWord16 s3221 = (((SWord16) s3166) << 8) | ((SWord16) s3220);
-  const SWord8  s3222 = (SWord8) (s3169 >> 8);
-  const SWord32 s3223 = table1[s3222];
-  const SWord16 s3224 = (SWord16) (s3121 >> 16);
-  const SWord8  s3225 = (SWord8) s3224;
-  const SWord32 s3226 = table3[s3225];
-  const SWord32 s3227 = s3223 ^ s3226;
-  const SWord8  s3228 = (SWord8) (s3176 >> 8);
-  const SWord32 s3229 = table4[s3228];
-  const SWord32 s3230 = s3227 ^ s3229;
-  const SWord16 s3231 = (SWord16) s3013;
-  const SWord8  s3232 = (SWord8) s3231;
-  const SWord32 s3233 = table5[s3232];
-  const SWord32 s3234 = s3230 ^ s3233;
-  const SWord16 s3235 = (SWord16) (s537 >> 16);
-  const SWord8  s3236 = (SWord8) (s3235 >> 8);
-  const SWord8  s3237 = table6[s3236];
-  const SWord8  s3238 = (SWord8) s3235;
-  const SWord8  s3239 = table7[s3238];
-  const SWord16 s3240 = (SWord16) s537;
-  const SWord8  s3241 = (SWord8) (s3240 >> 8);
-  const SWord8  s3242 = table8[s3241];
-  const SWord8  s3243 = (SWord8) s3240;
-  const SWord8  s3244 = table9[s3243];
-  const SWord8  s3245 = s3242 ^ s3244;
-  const SWord8  s3246 = s3239 ^ s3245;
-  const SWord8  s3247 = s3237 ^ s3246;
-  const SWord8  s3248 = table9[s3236];
-  const SWord8  s3249 = table6[s3238];
-  const SWord8  s3250 = table7[s3241];
-  const SWord8  s3251 = table8[s3243];
-  const SWord8  s3252 = s3250 ^ s3251;
-  const SWord8  s3253 = s3249 ^ s3252;
-  const SWord8  s3254 = s3248 ^ s3253;
-  const SWord16 s3255 = (((SWord16) s3247) << 8) | ((SWord16) s3254);
-  const SWord8  s3256 = table8[s3236];
-  const SWord8  s3257 = table9[s3238];
-  const SWord8  s3258 = table6[s3241];
-  const SWord8  s3259 = table7[s3243];
-  const SWord8  s3260 = s3258 ^ s3259;
-  const SWord8  s3261 = s3257 ^ s3260;
-  const SWord8  s3262 = s3256 ^ s3261;
-  const SWord8  s3263 = table7[s3236];
-  const SWord8  s3264 = table8[s3238];
-  const SWord8  s3265 = table9[s3241];
-  const SWord8  s3266 = table6[s3243];
-  const SWord8  s3267 = s3265 ^ s3266;
-  const SWord8  s3268 = s3264 ^ s3267;
-  const SWord8  s3269 = s3263 ^ s3268;
-  const SWord16 s3270 = (((SWord16) s3262) << 8) | ((SWord16) s3269);
-  const SWord32 s3271 = (((SWord32) s3255) << 16) | ((SWord32) s3270);
-  const SWord32 s3272 = s3234 ^ s3271;
-  const SWord16 s3273 = (SWord16) s3272;
-  const SWord8  s3274 = (SWord8) (s3273 >> 8);
-  const SWord8  s3275 = table0[s3274];
-  const SWord8  s3276 = (SWord8) (s3224 >> 8);
-  const SWord32 s3277 = table1[s3276];
-  const SWord8  s3278 = (SWord8) s2960;
-  const SWord32 s3279 = table3[s3278];
-  const SWord32 s3280 = s3277 ^ s3279;
-  const SWord8  s3281 = (SWord8) (s3231 >> 8);
-  const SWord32 s3282 = table4[s3281];
-  const SWord32 s3283 = s3280 ^ s3282;
-  const SWord8  s3284 = (SWord8) s3069;
-  const SWord32 s3285 = table5[s3284];
-  const SWord32 s3286 = s3283 ^ s3285;
-  const SWord16 s3287 = (SWord16) (s536 >> 16);
-  const SWord8  s3288 = (SWord8) (s3287 >> 8);
-  const SWord8  s3289 = table6[s3288];
-  const SWord8  s3290 = (SWord8) s3287;
-  const SWord8  s3291 = table7[s3290];
-  const SWord16 s3292 = (SWord16) s536;
-  const SWord8  s3293 = (SWord8) (s3292 >> 8);
-  const SWord8  s3294 = table8[s3293];
-  const SWord8  s3295 = (SWord8) s3292;
-  const SWord8  s3296 = table9[s3295];
-  const SWord8  s3297 = s3294 ^ s3296;
-  const SWord8  s3298 = s3291 ^ s3297;
-  const SWord8  s3299 = s3289 ^ s3298;
-  const SWord8  s3300 = table9[s3288];
-  const SWord8  s3301 = table6[s3290];
-  const SWord8  s3302 = table7[s3293];
-  const SWord8  s3303 = table8[s3295];
-  const SWord8  s3304 = s3302 ^ s3303;
-  const SWord8  s3305 = s3301 ^ s3304;
-  const SWord8  s3306 = s3300 ^ s3305;
-  const SWord16 s3307 = (((SWord16) s3299) << 8) | ((SWord16) s3306);
-  const SWord8  s3308 = table8[s3288];
-  const SWord8  s3309 = table9[s3290];
-  const SWord8  s3310 = table6[s3293];
-  const SWord8  s3311 = table7[s3295];
-  const SWord8  s3312 = s3310 ^ s3311;
-  const SWord8  s3313 = s3309 ^ s3312;
-  const SWord8  s3314 = s3308 ^ s3313;
-  const SWord8  s3315 = table7[s3288];
-  const SWord8  s3316 = table8[s3290];
-  const SWord8  s3317 = table9[s3293];
-  const SWord8  s3318 = table6[s3295];
-  const SWord8  s3319 = s3317 ^ s3318;
-  const SWord8  s3320 = s3316 ^ s3319;
-  const SWord8  s3321 = s3315 ^ s3320;
-  const SWord16 s3322 = (((SWord16) s3314) << 8) | ((SWord16) s3321);
-  const SWord32 s3323 = (((SWord32) s3307) << 16) | ((SWord32) s3322);
-  const SWord32 s3324 = s3286 ^ s3323;
-  const SWord16 s3325 = (SWord16) s3324;
-  const SWord8  s3326 = (SWord8) s3325;
-  const SWord8  s3327 = table0[s3326];
-  const SWord16 s3328 = (((SWord16) s3275) << 8) | ((SWord16) s3327);
-  const SWord32 s3329 = (((SWord32) s3221) << 16) | ((SWord32) s3328);
-  const SWord32 s3330 = s4 ^ s3329;
-  const SWord16 s3331 = (SWord16) (s3324 >> 16);
-  const SWord8  s3332 = (SWord8) (s3331 >> 8);
-  const SWord8  s3333 = table0[s3332];
-  const SWord8  s3334 = (SWord8) s3164;
-  const SWord8  s3335 = table0[s3334];
-  const SWord16 s3336 = (((SWord16) s3333) << 8) | ((SWord16) s3335);
-  const SWord16 s3337 = (SWord16) s3217;
-  const SWord8  s3338 = (SWord8) (s3337 >> 8);
-  const SWord8  s3339 = table0[s3338];
-  const SWord8  s3340 = (SWord8) s3273;
-  const SWord8  s3341 = table0[s3340];
-  const SWord16 s3342 = (((SWord16) s3339) << 8) | ((SWord16) s3341);
-  const SWord32 s3343 = (((SWord32) s3336) << 16) | ((SWord32) s3342);
-  const SWord32 s3344 = s5 ^ s3343;
-  const SWord16 s3345 = (SWord16) (s3272 >> 16);
-  const SWord8  s3346 = (SWord8) (s3345 >> 8);
-  const SWord8  s3347 = table0[s3346];
-  const SWord8  s3348 = (SWord8) s3331;
-  const SWord8  s3349 = table0[s3348];
-  const SWord16 s3350 = (((SWord16) s3347) << 8) | ((SWord16) s3349);
-  const SWord16 s3351 = (SWord16) s3163;
-  const SWord8  s3352 = (SWord8) (s3351 >> 8);
-  const SWord8  s3353 = table0[s3352];
-  const SWord8  s3354 = (SWord8) s3337;
-  const SWord8  s3355 = table0[s3354];
-  const SWord16 s3356 = (((SWord16) s3353) << 8) | ((SWord16) s3355);
-  const SWord32 s3357 = (((SWord32) s3350) << 16) | ((SWord32) s3356);
-  const SWord32 s3358 = s6 ^ s3357;
-  const SWord8  s3359 = (SWord8) (s3218 >> 8);
-  const SWord8  s3360 = table0[s3359];
-  const SWord8  s3361 = (SWord8) s3345;
-  const SWord8  s3362 = table0[s3361];
-  const SWord16 s3363 = (((SWord16) s3360) << 8) | ((SWord16) s3362);
-  const SWord8  s3364 = (SWord8) (s3325 >> 8);
-  const SWord8  s3365 = table0[s3364];
-  const SWord8  s3366 = (SWord8) s3351;
-  const SWord8  s3367 = table0[s3366];
-  const SWord16 s3368 = (((SWord16) s3365) << 8) | ((SWord16) s3367);
-  const SWord32 s3369 = (((SWord32) s3363) << 16) | ((SWord32) s3368);
-  const SWord32 s3370 = s7 ^ s3369;
-
-  ct[0] = s3330;
-  ct[1] = s3344;
-  ct[2] = s3358;
-  ct[3] = s3370;
-}
-== END: "aes128Dec.c" ==================
diff --git a/SBVUnitTest/GoldFiles/aes128Enc.gold b/SBVUnitTest/GoldFiles/aes128Enc.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/aes128Enc.gold
+++ /dev/null
@@ -1,1167 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for aes128Enc. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: aes128Enc_driver
-
-aes128Enc.o: aes128Enc.c aes128Enc.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128Enc_driver.o: aes128Enc_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128Enc_driver: aes128Enc.o aes128Enc_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f aes128Enc_driver
-== END: "Makefile" ==================
-== BEGIN: "aes128Enc.h" ================
-/* Header file for aes128Enc. Automatically generated by SBV. Do not edit! */
-
-#ifndef __aes128Enc__HEADER_INCLUDED__
-#define __aes128Enc__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-void aes128Enc(const SWord32 *pt, const SWord32 *key, SWord32 *ct);
-
-#endif /* __aes128Enc__HEADER_INCLUDED__ */
-== END: "aes128Enc.h" ==================
-== BEGIN: "aes128Enc_driver.c" ================
-/* Example driver program for aes128Enc. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "aes128Enc.h"
-
-int main(void)
-{
-  const SWord32 pt[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array pt:\n");
-  int pt_ctr;
-  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
-    printf("  pt[%d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
-
-  const SWord32 key[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array key:\n");
-  int key_ctr;
-  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
-    printf("  key[%d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
-
-  SWord32 ct[4];
-
-  aes128Enc(pt, key, ct);
-
-  printf("aes128Enc(pt, key, ct) ->\n");
-  int ct_ctr;
-  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
-    printf("  ct[%d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
-
-  return 0;
-}
-== END: "aes128Enc_driver.c" ==================
-== BEGIN: "aes128Enc.c" ================
-/* File: "aes128Enc.c". Automatically generated by SBV. Do not edit! */
-
-#include "aes128Enc.h"
-
-void aes128Enc(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
-{
-  const SWord32 s0 = pt[0];
-  const SWord32 s1 = pt[1];
-  const SWord32 s2 = pt[2];
-  const SWord32 s3 = pt[3];
-  const SWord32 s4 = key[0];
-  const SWord32 s5 = key[1];
-  const SWord32 s6 = key[2];
-  const SWord32 s7 = key[3];
-  static const SWord8 table0[] = {
-       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
-      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
-      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
-      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
-       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
-      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
-       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
-       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
-       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
-      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
-       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
-      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
-      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
-      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
-       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
-       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
-      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
-      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
-      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
-      104,  65, 153,  45,  15, 176,  84, 187,  22
-  };
-  static const SWord32 table1[] = {
-      0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
-      0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
-      0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
-      0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
-      0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
-      0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
-      0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
-      0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
-      0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
-      0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
-      0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
-      0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
-      0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
-      0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
-      0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
-      0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
-      0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
-      0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
-      0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
-      0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
-      0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
-      0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
-      0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
-      0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
-      0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
-      0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
-      0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
-      0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
-      0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
-      0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
-      0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
-      0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
-      0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
-      0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
-      0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
-      0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
-      0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
-      0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
-      0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
-      0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
-      0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
-      0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
-      0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
-      0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
-      0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
-      0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
-      0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
-      0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
-      0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
-      0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
-      0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
-      0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
-      0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
-      0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
-      0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
-      0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
-      0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
-      0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
-      0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
-      0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
-      0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
-      0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
-      0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
-      0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL
-  };
-  static const SWord32 table2[] = {
-      0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
-      0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
-      0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
-      0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
-      0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
-      0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
-      0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
-      0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
-      0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
-      0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
-      0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
-      0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
-      0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
-      0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
-      0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
-      0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
-      0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
-      0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
-      0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
-      0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
-      0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
-      0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
-      0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
-      0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
-      0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
-      0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
-      0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
-      0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
-      0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
-      0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
-      0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
-      0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
-      0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
-      0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
-      0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
-      0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
-      0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
-      0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
-      0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
-      0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
-      0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
-      0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
-      0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
-      0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
-      0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
-      0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
-      0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
-      0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
-      0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
-      0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
-      0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
-      0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
-      0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
-      0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
-      0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
-      0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
-      0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
-      0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
-      0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
-      0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
-      0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
-      0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
-      0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
-      0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL
-  };
-  static const SWord32 table3[] = {
-      0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
-      0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
-      0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
-      0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
-      0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
-      0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
-      0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
-      0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
-      0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
-      0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
-      0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
-      0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
-      0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
-      0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
-      0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
-      0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
-      0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
-      0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
-      0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
-      0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
-      0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
-      0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
-      0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
-      0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
-      0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
-      0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
-      0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
-      0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
-      0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
-      0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
-      0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
-      0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
-      0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
-      0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
-      0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
-      0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
-      0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
-      0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
-      0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
-      0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
-      0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
-      0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
-      0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
-      0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
-      0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
-      0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
-      0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
-      0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
-      0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
-      0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
-      0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
-      0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
-      0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
-      0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
-      0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
-      0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
-      0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
-      0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
-      0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
-      0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
-      0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
-      0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
-      0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
-      0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL
-  };
-  static const SWord32 table4[] = {
-      0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
-      0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
-      0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
-      0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
-      0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
-      0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
-      0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
-      0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
-      0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
-      0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
-      0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
-      0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
-      0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
-      0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
-      0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
-      0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
-      0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
-      0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
-      0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
-      0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
-      0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
-      0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
-      0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
-      0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
-      0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
-      0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
-      0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
-      0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
-      0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
-      0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
-      0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
-      0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
-      0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
-      0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
-      0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
-      0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
-      0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
-      0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
-      0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
-      0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
-      0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
-      0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
-      0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
-      0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
-      0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
-      0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
-      0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
-      0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
-      0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
-      0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
-      0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
-      0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
-      0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
-      0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
-      0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
-      0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
-      0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
-      0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
-      0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
-      0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
-      0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
-      0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
-      0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
-      0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL
-  };
-  const SWord32 s520 = s0 ^ s4;
-  const SWord16 s521 = (SWord16) (s520 >> 16);
-  const SWord8  s522 = (SWord8) (s521 >> 8);
-  const SWord32 s523 = table1[s522];
-  const SWord32 s779 = s1 ^ s5;
-  const SWord16 s780 = (SWord16) (s779 >> 16);
-  const SWord8  s781 = (SWord8) s780;
-  const SWord32 s782 = table2[s781];
-  const SWord32 s783 = s523 ^ s782;
-  const SWord32 s1039 = s2 ^ s6;
-  const SWord16 s1040 = (SWord16) s1039;
-  const SWord8  s1041 = (SWord8) (s1040 >> 8);
-  const SWord32 s1042 = table3[s1041];
-  const SWord32 s1043 = s783 ^ s1042;
-  const SWord32 s1299 = s3 ^ s7;
-  const SWord16 s1300 = (SWord16) s1299;
-  const SWord8  s1301 = (SWord8) s1300;
-  const SWord32 s1302 = table4[s1301];
-  const SWord32 s1303 = s1043 ^ s1302;
-  const SWord32 s1304 = (s7 << 8) | (s7 >> 24);
-  const SWord16 s1305 = (SWord16) (s1304 >> 16);
-  const SWord8  s1306 = (SWord8) (s1305 >> 8);
-  const SWord8  s1307 = table0[s1306];
-  const SWord8  s1308 = 1 ^ s1307;
-  const SWord8  s1309 = (SWord8) s1305;
-  const SWord8  s1310 = table0[s1309];
-  const SWord16 s1311 = (((SWord16) s1308) << 8) | ((SWord16) s1310);
-  const SWord16 s1312 = (SWord16) s1304;
-  const SWord8  s1313 = (SWord8) (s1312 >> 8);
-  const SWord8  s1314 = table0[s1313];
-  const SWord8  s1315 = (SWord8) s1312;
-  const SWord8  s1316 = table0[s1315];
-  const SWord16 s1317 = (((SWord16) s1314) << 8) | ((SWord16) s1316);
-  const SWord32 s1318 = (((SWord32) s1311) << 16) | ((SWord32) s1317);
-  const SWord32 s1319 = s4 ^ s1318;
-  const SWord32 s1320 = s1303 ^ s1319;
-  const SWord16 s1321 = (SWord16) (s1320 >> 16);
-  const SWord8  s1322 = (SWord8) (s1321 >> 8);
-  const SWord32 s1323 = table1[s1322];
-  const SWord8  s1324 = (SWord8) (s780 >> 8);
-  const SWord32 s1325 = table1[s1324];
-  const SWord16 s1326 = (SWord16) (s1039 >> 16);
-  const SWord8  s1327 = (SWord8) s1326;
-  const SWord32 s1328 = table2[s1327];
-  const SWord32 s1329 = s1325 ^ s1328;
-  const SWord8  s1330 = (SWord8) (s1300 >> 8);
-  const SWord32 s1331 = table3[s1330];
-  const SWord32 s1332 = s1329 ^ s1331;
-  const SWord16 s1333 = (SWord16) s520;
-  const SWord8  s1334 = (SWord8) s1333;
-  const SWord32 s1335 = table4[s1334];
-  const SWord32 s1336 = s1332 ^ s1335;
-  const SWord32 s1337 = s5 ^ s1319;
-  const SWord32 s1338 = s1336 ^ s1337;
-  const SWord16 s1339 = (SWord16) (s1338 >> 16);
-  const SWord8  s1340 = (SWord8) s1339;
-  const SWord32 s1341 = table2[s1340];
-  const SWord32 s1342 = s1323 ^ s1341;
-  const SWord8  s1343 = (SWord8) (s1326 >> 8);
-  const SWord32 s1344 = table1[s1343];
-  const SWord16 s1345 = (SWord16) (s1299 >> 16);
-  const SWord8  s1346 = (SWord8) s1345;
-  const SWord32 s1347 = table2[s1346];
-  const SWord32 s1348 = s1344 ^ s1347;
-  const SWord8  s1349 = (SWord8) (s1333 >> 8);
-  const SWord32 s1350 = table3[s1349];
-  const SWord32 s1351 = s1348 ^ s1350;
-  const SWord16 s1352 = (SWord16) s779;
-  const SWord8  s1353 = (SWord8) s1352;
-  const SWord32 s1354 = table4[s1353];
-  const SWord32 s1355 = s1351 ^ s1354;
-  const SWord32 s1356 = s6 ^ s1337;
-  const SWord32 s1357 = s1355 ^ s1356;
-  const SWord16 s1358 = (SWord16) s1357;
-  const SWord8  s1359 = (SWord8) (s1358 >> 8);
-  const SWord32 s1360 = table3[s1359];
-  const SWord32 s1361 = s1342 ^ s1360;
-  const SWord8  s1362 = (SWord8) (s1345 >> 8);
-  const SWord32 s1363 = table1[s1362];
-  const SWord8  s1364 = (SWord8) s521;
-  const SWord32 s1365 = table2[s1364];
-  const SWord32 s1366 = s1363 ^ s1365;
-  const SWord8  s1367 = (SWord8) (s1352 >> 8);
-  const SWord32 s1368 = table3[s1367];
-  const SWord32 s1369 = s1366 ^ s1368;
-  const SWord8  s1370 = (SWord8) s1040;
-  const SWord32 s1371 = table4[s1370];
-  const SWord32 s1372 = s1369 ^ s1371;
-  const SWord32 s1373 = s7 ^ s1356;
-  const SWord32 s1374 = s1372 ^ s1373;
-  const SWord16 s1375 = (SWord16) s1374;
-  const SWord8  s1376 = (SWord8) s1375;
-  const SWord32 s1377 = table4[s1376];
-  const SWord32 s1378 = s1361 ^ s1377;
-  const SWord32 s1379 = (s1373 << 8) | (s1373 >> 24);
-  const SWord16 s1380 = (SWord16) (s1379 >> 16);
-  const SWord8  s1381 = (SWord8) (s1380 >> 8);
-  const SWord8  s1382 = table0[s1381];
-  const SWord8  s1383 = 2 ^ s1382;
-  const SWord8  s1384 = (SWord8) s1380;
-  const SWord8  s1385 = table0[s1384];
-  const SWord16 s1386 = (((SWord16) s1383) << 8) | ((SWord16) s1385);
-  const SWord16 s1387 = (SWord16) s1379;
-  const SWord8  s1388 = (SWord8) (s1387 >> 8);
-  const SWord8  s1389 = table0[s1388];
-  const SWord8  s1390 = (SWord8) s1387;
-  const SWord8  s1391 = table0[s1390];
-  const SWord16 s1392 = (((SWord16) s1389) << 8) | ((SWord16) s1391);
-  const SWord32 s1393 = (((SWord32) s1386) << 16) | ((SWord32) s1392);
-  const SWord32 s1394 = s1319 ^ s1393;
-  const SWord32 s1395 = s1378 ^ s1394;
-  const SWord16 s1396 = (SWord16) (s1395 >> 16);
-  const SWord8  s1397 = (SWord8) (s1396 >> 8);
-  const SWord32 s1398 = table1[s1397];
-  const SWord8  s1399 = (SWord8) (s1339 >> 8);
-  const SWord32 s1400 = table1[s1399];
-  const SWord16 s1401 = (SWord16) (s1357 >> 16);
-  const SWord8  s1402 = (SWord8) s1401;
-  const SWord32 s1403 = table2[s1402];
-  const SWord32 s1404 = s1400 ^ s1403;
-  const SWord8  s1405 = (SWord8) (s1375 >> 8);
-  const SWord32 s1406 = table3[s1405];
-  const SWord32 s1407 = s1404 ^ s1406;
-  const SWord16 s1408 = (SWord16) s1320;
-  const SWord8  s1409 = (SWord8) s1408;
-  const SWord32 s1410 = table4[s1409];
-  const SWord32 s1411 = s1407 ^ s1410;
-  const SWord32 s1412 = s1337 ^ s1394;
-  const SWord32 s1413 = s1411 ^ s1412;
-  const SWord16 s1414 = (SWord16) (s1413 >> 16);
-  const SWord8  s1415 = (SWord8) s1414;
-  const SWord32 s1416 = table2[s1415];
-  const SWord32 s1417 = s1398 ^ s1416;
-  const SWord8  s1418 = (SWord8) (s1401 >> 8);
-  const SWord32 s1419 = table1[s1418];
-  const SWord16 s1420 = (SWord16) (s1374 >> 16);
-  const SWord8  s1421 = (SWord8) s1420;
-  const SWord32 s1422 = table2[s1421];
-  const SWord32 s1423 = s1419 ^ s1422;
-  const SWord8  s1424 = (SWord8) (s1408 >> 8);
-  const SWord32 s1425 = table3[s1424];
-  const SWord32 s1426 = s1423 ^ s1425;
-  const SWord16 s1427 = (SWord16) s1338;
-  const SWord8  s1428 = (SWord8) s1427;
-  const SWord32 s1429 = table4[s1428];
-  const SWord32 s1430 = s1426 ^ s1429;
-  const SWord32 s1431 = s1356 ^ s1412;
-  const SWord32 s1432 = s1430 ^ s1431;
-  const SWord16 s1433 = (SWord16) s1432;
-  const SWord8  s1434 = (SWord8) (s1433 >> 8);
-  const SWord32 s1435 = table3[s1434];
-  const SWord32 s1436 = s1417 ^ s1435;
-  const SWord8  s1437 = (SWord8) (s1420 >> 8);
-  const SWord32 s1438 = table1[s1437];
-  const SWord8  s1439 = (SWord8) s1321;
-  const SWord32 s1440 = table2[s1439];
-  const SWord32 s1441 = s1438 ^ s1440;
-  const SWord8  s1442 = (SWord8) (s1427 >> 8);
-  const SWord32 s1443 = table3[s1442];
-  const SWord32 s1444 = s1441 ^ s1443;
-  const SWord8  s1445 = (SWord8) s1358;
-  const SWord32 s1446 = table4[s1445];
-  const SWord32 s1447 = s1444 ^ s1446;
-  const SWord32 s1448 = s1373 ^ s1431;
-  const SWord32 s1449 = s1447 ^ s1448;
-  const SWord16 s1450 = (SWord16) s1449;
-  const SWord8  s1451 = (SWord8) s1450;
-  const SWord32 s1452 = table4[s1451];
-  const SWord32 s1453 = s1436 ^ s1452;
-  const SWord32 s1454 = (s1448 << 8) | (s1448 >> 24);
-  const SWord16 s1455 = (SWord16) (s1454 >> 16);
-  const SWord8  s1456 = (SWord8) (s1455 >> 8);
-  const SWord8  s1457 = table0[s1456];
-  const SWord8  s1458 = 4 ^ s1457;
-  const SWord8  s1459 = (SWord8) s1455;
-  const SWord8  s1460 = table0[s1459];
-  const SWord16 s1461 = (((SWord16) s1458) << 8) | ((SWord16) s1460);
-  const SWord16 s1462 = (SWord16) s1454;
-  const SWord8  s1463 = (SWord8) (s1462 >> 8);
-  const SWord8  s1464 = table0[s1463];
-  const SWord8  s1465 = (SWord8) s1462;
-  const SWord8  s1466 = table0[s1465];
-  const SWord16 s1467 = (((SWord16) s1464) << 8) | ((SWord16) s1466);
-  const SWord32 s1468 = (((SWord32) s1461) << 16) | ((SWord32) s1467);
-  const SWord32 s1469 = s1394 ^ s1468;
-  const SWord32 s1470 = s1453 ^ s1469;
-  const SWord16 s1471 = (SWord16) (s1470 >> 16);
-  const SWord8  s1472 = (SWord8) (s1471 >> 8);
-  const SWord32 s1473 = table1[s1472];
-  const SWord8  s1474 = (SWord8) (s1414 >> 8);
-  const SWord32 s1475 = table1[s1474];
-  const SWord16 s1476 = (SWord16) (s1432 >> 16);
-  const SWord8  s1477 = (SWord8) s1476;
-  const SWord32 s1478 = table2[s1477];
-  const SWord32 s1479 = s1475 ^ s1478;
-  const SWord8  s1480 = (SWord8) (s1450 >> 8);
-  const SWord32 s1481 = table3[s1480];
-  const SWord32 s1482 = s1479 ^ s1481;
-  const SWord16 s1483 = (SWord16) s1395;
-  const SWord8  s1484 = (SWord8) s1483;
-  const SWord32 s1485 = table4[s1484];
-  const SWord32 s1486 = s1482 ^ s1485;
-  const SWord32 s1487 = s1412 ^ s1469;
-  const SWord32 s1488 = s1486 ^ s1487;
-  const SWord16 s1489 = (SWord16) (s1488 >> 16);
-  const SWord8  s1490 = (SWord8) s1489;
-  const SWord32 s1491 = table2[s1490];
-  const SWord32 s1492 = s1473 ^ s1491;
-  const SWord8  s1493 = (SWord8) (s1476 >> 8);
-  const SWord32 s1494 = table1[s1493];
-  const SWord16 s1495 = (SWord16) (s1449 >> 16);
-  const SWord8  s1496 = (SWord8) s1495;
-  const SWord32 s1497 = table2[s1496];
-  const SWord32 s1498 = s1494 ^ s1497;
-  const SWord8  s1499 = (SWord8) (s1483 >> 8);
-  const SWord32 s1500 = table3[s1499];
-  const SWord32 s1501 = s1498 ^ s1500;
-  const SWord16 s1502 = (SWord16) s1413;
-  const SWord8  s1503 = (SWord8) s1502;
-  const SWord32 s1504 = table4[s1503];
-  const SWord32 s1505 = s1501 ^ s1504;
-  const SWord32 s1506 = s1431 ^ s1487;
-  const SWord32 s1507 = s1505 ^ s1506;
-  const SWord16 s1508 = (SWord16) s1507;
-  const SWord8  s1509 = (SWord8) (s1508 >> 8);
-  const SWord32 s1510 = table3[s1509];
-  const SWord32 s1511 = s1492 ^ s1510;
-  const SWord8  s1512 = (SWord8) (s1495 >> 8);
-  const SWord32 s1513 = table1[s1512];
-  const SWord8  s1514 = (SWord8) s1396;
-  const SWord32 s1515 = table2[s1514];
-  const SWord32 s1516 = s1513 ^ s1515;
-  const SWord8  s1517 = (SWord8) (s1502 >> 8);
-  const SWord32 s1518 = table3[s1517];
-  const SWord32 s1519 = s1516 ^ s1518;
-  const SWord8  s1520 = (SWord8) s1433;
-  const SWord32 s1521 = table4[s1520];
-  const SWord32 s1522 = s1519 ^ s1521;
-  const SWord32 s1523 = s1448 ^ s1506;
-  const SWord32 s1524 = s1522 ^ s1523;
-  const SWord16 s1525 = (SWord16) s1524;
-  const SWord8  s1526 = (SWord8) s1525;
-  const SWord32 s1527 = table4[s1526];
-  const SWord32 s1528 = s1511 ^ s1527;
-  const SWord32 s1529 = (s1523 << 8) | (s1523 >> 24);
-  const SWord16 s1530 = (SWord16) (s1529 >> 16);
-  const SWord8  s1531 = (SWord8) (s1530 >> 8);
-  const SWord8  s1532 = table0[s1531];
-  const SWord8  s1533 = 8 ^ s1532;
-  const SWord8  s1534 = (SWord8) s1530;
-  const SWord8  s1535 = table0[s1534];
-  const SWord16 s1536 = (((SWord16) s1533) << 8) | ((SWord16) s1535);
-  const SWord16 s1537 = (SWord16) s1529;
-  const SWord8  s1538 = (SWord8) (s1537 >> 8);
-  const SWord8  s1539 = table0[s1538];
-  const SWord8  s1540 = (SWord8) s1537;
-  const SWord8  s1541 = table0[s1540];
-  const SWord16 s1542 = (((SWord16) s1539) << 8) | ((SWord16) s1541);
-  const SWord32 s1543 = (((SWord32) s1536) << 16) | ((SWord32) s1542);
-  const SWord32 s1544 = s1469 ^ s1543;
-  const SWord32 s1545 = s1528 ^ s1544;
-  const SWord16 s1546 = (SWord16) (s1545 >> 16);
-  const SWord8  s1547 = (SWord8) (s1546 >> 8);
-  const SWord32 s1548 = table1[s1547];
-  const SWord8  s1549 = (SWord8) (s1489 >> 8);
-  const SWord32 s1550 = table1[s1549];
-  const SWord16 s1551 = (SWord16) (s1507 >> 16);
-  const SWord8  s1552 = (SWord8) s1551;
-  const SWord32 s1553 = table2[s1552];
-  const SWord32 s1554 = s1550 ^ s1553;
-  const SWord8  s1555 = (SWord8) (s1525 >> 8);
-  const SWord32 s1556 = table3[s1555];
-  const SWord32 s1557 = s1554 ^ s1556;
-  const SWord16 s1558 = (SWord16) s1470;
-  const SWord8  s1559 = (SWord8) s1558;
-  const SWord32 s1560 = table4[s1559];
-  const SWord32 s1561 = s1557 ^ s1560;
-  const SWord32 s1562 = s1487 ^ s1544;
-  const SWord32 s1563 = s1561 ^ s1562;
-  const SWord16 s1564 = (SWord16) (s1563 >> 16);
-  const SWord8  s1565 = (SWord8) s1564;
-  const SWord32 s1566 = table2[s1565];
-  const SWord32 s1567 = s1548 ^ s1566;
-  const SWord8  s1568 = (SWord8) (s1551 >> 8);
-  const SWord32 s1569 = table1[s1568];
-  const SWord16 s1570 = (SWord16) (s1524 >> 16);
-  const SWord8  s1571 = (SWord8) s1570;
-  const SWord32 s1572 = table2[s1571];
-  const SWord32 s1573 = s1569 ^ s1572;
-  const SWord8  s1574 = (SWord8) (s1558 >> 8);
-  const SWord32 s1575 = table3[s1574];
-  const SWord32 s1576 = s1573 ^ s1575;
-  const SWord16 s1577 = (SWord16) s1488;
-  const SWord8  s1578 = (SWord8) s1577;
-  const SWord32 s1579 = table4[s1578];
-  const SWord32 s1580 = s1576 ^ s1579;
-  const SWord32 s1581 = s1506 ^ s1562;
-  const SWord32 s1582 = s1580 ^ s1581;
-  const SWord16 s1583 = (SWord16) s1582;
-  const SWord8  s1584 = (SWord8) (s1583 >> 8);
-  const SWord32 s1585 = table3[s1584];
-  const SWord32 s1586 = s1567 ^ s1585;
-  const SWord8  s1587 = (SWord8) (s1570 >> 8);
-  const SWord32 s1588 = table1[s1587];
-  const SWord8  s1589 = (SWord8) s1471;
-  const SWord32 s1590 = table2[s1589];
-  const SWord32 s1591 = s1588 ^ s1590;
-  const SWord8  s1592 = (SWord8) (s1577 >> 8);
-  const SWord32 s1593 = table3[s1592];
-  const SWord32 s1594 = s1591 ^ s1593;
-  const SWord8  s1595 = (SWord8) s1508;
-  const SWord32 s1596 = table4[s1595];
-  const SWord32 s1597 = s1594 ^ s1596;
-  const SWord32 s1598 = s1523 ^ s1581;
-  const SWord32 s1599 = s1597 ^ s1598;
-  const SWord16 s1600 = (SWord16) s1599;
-  const SWord8  s1601 = (SWord8) s1600;
-  const SWord32 s1602 = table4[s1601];
-  const SWord32 s1603 = s1586 ^ s1602;
-  const SWord32 s1604 = (s1598 << 8) | (s1598 >> 24);
-  const SWord16 s1605 = (SWord16) (s1604 >> 16);
-  const SWord8  s1606 = (SWord8) (s1605 >> 8);
-  const SWord8  s1607 = table0[s1606];
-  const SWord8  s1608 = 16 ^ s1607;
-  const SWord8  s1609 = (SWord8) s1605;
-  const SWord8  s1610 = table0[s1609];
-  const SWord16 s1611 = (((SWord16) s1608) << 8) | ((SWord16) s1610);
-  const SWord16 s1612 = (SWord16) s1604;
-  const SWord8  s1613 = (SWord8) (s1612 >> 8);
-  const SWord8  s1614 = table0[s1613];
-  const SWord8  s1615 = (SWord8) s1612;
-  const SWord8  s1616 = table0[s1615];
-  const SWord16 s1617 = (((SWord16) s1614) << 8) | ((SWord16) s1616);
-  const SWord32 s1618 = (((SWord32) s1611) << 16) | ((SWord32) s1617);
-  const SWord32 s1619 = s1544 ^ s1618;
-  const SWord32 s1620 = s1603 ^ s1619;
-  const SWord16 s1621 = (SWord16) (s1620 >> 16);
-  const SWord8  s1622 = (SWord8) (s1621 >> 8);
-  const SWord32 s1623 = table1[s1622];
-  const SWord8  s1624 = (SWord8) (s1564 >> 8);
-  const SWord32 s1625 = table1[s1624];
-  const SWord16 s1626 = (SWord16) (s1582 >> 16);
-  const SWord8  s1627 = (SWord8) s1626;
-  const SWord32 s1628 = table2[s1627];
-  const SWord32 s1629 = s1625 ^ s1628;
-  const SWord8  s1630 = (SWord8) (s1600 >> 8);
-  const SWord32 s1631 = table3[s1630];
-  const SWord32 s1632 = s1629 ^ s1631;
-  const SWord16 s1633 = (SWord16) s1545;
-  const SWord8  s1634 = (SWord8) s1633;
-  const SWord32 s1635 = table4[s1634];
-  const SWord32 s1636 = s1632 ^ s1635;
-  const SWord32 s1637 = s1562 ^ s1619;
-  const SWord32 s1638 = s1636 ^ s1637;
-  const SWord16 s1639 = (SWord16) (s1638 >> 16);
-  const SWord8  s1640 = (SWord8) s1639;
-  const SWord32 s1641 = table2[s1640];
-  const SWord32 s1642 = s1623 ^ s1641;
-  const SWord8  s1643 = (SWord8) (s1626 >> 8);
-  const SWord32 s1644 = table1[s1643];
-  const SWord16 s1645 = (SWord16) (s1599 >> 16);
-  const SWord8  s1646 = (SWord8) s1645;
-  const SWord32 s1647 = table2[s1646];
-  const SWord32 s1648 = s1644 ^ s1647;
-  const SWord8  s1649 = (SWord8) (s1633 >> 8);
-  const SWord32 s1650 = table3[s1649];
-  const SWord32 s1651 = s1648 ^ s1650;
-  const SWord16 s1652 = (SWord16) s1563;
-  const SWord8  s1653 = (SWord8) s1652;
-  const SWord32 s1654 = table4[s1653];
-  const SWord32 s1655 = s1651 ^ s1654;
-  const SWord32 s1656 = s1581 ^ s1637;
-  const SWord32 s1657 = s1655 ^ s1656;
-  const SWord16 s1658 = (SWord16) s1657;
-  const SWord8  s1659 = (SWord8) (s1658 >> 8);
-  const SWord32 s1660 = table3[s1659];
-  const SWord32 s1661 = s1642 ^ s1660;
-  const SWord8  s1662 = (SWord8) (s1645 >> 8);
-  const SWord32 s1663 = table1[s1662];
-  const SWord8  s1664 = (SWord8) s1546;
-  const SWord32 s1665 = table2[s1664];
-  const SWord32 s1666 = s1663 ^ s1665;
-  const SWord8  s1667 = (SWord8) (s1652 >> 8);
-  const SWord32 s1668 = table3[s1667];
-  const SWord32 s1669 = s1666 ^ s1668;
-  const SWord8  s1670 = (SWord8) s1583;
-  const SWord32 s1671 = table4[s1670];
-  const SWord32 s1672 = s1669 ^ s1671;
-  const SWord32 s1673 = s1598 ^ s1656;
-  const SWord32 s1674 = s1672 ^ s1673;
-  const SWord16 s1675 = (SWord16) s1674;
-  const SWord8  s1676 = (SWord8) s1675;
-  const SWord32 s1677 = table4[s1676];
-  const SWord32 s1678 = s1661 ^ s1677;
-  const SWord32 s1679 = (s1673 << 8) | (s1673 >> 24);
-  const SWord16 s1680 = (SWord16) (s1679 >> 16);
-  const SWord8  s1681 = (SWord8) (s1680 >> 8);
-  const SWord8  s1682 = table0[s1681];
-  const SWord8  s1683 = 32 ^ s1682;
-  const SWord8  s1684 = (SWord8) s1680;
-  const SWord8  s1685 = table0[s1684];
-  const SWord16 s1686 = (((SWord16) s1683) << 8) | ((SWord16) s1685);
-  const SWord16 s1687 = (SWord16) s1679;
-  const SWord8  s1688 = (SWord8) (s1687 >> 8);
-  const SWord8  s1689 = table0[s1688];
-  const SWord8  s1690 = (SWord8) s1687;
-  const SWord8  s1691 = table0[s1690];
-  const SWord16 s1692 = (((SWord16) s1689) << 8) | ((SWord16) s1691);
-  const SWord32 s1693 = (((SWord32) s1686) << 16) | ((SWord32) s1692);
-  const SWord32 s1694 = s1619 ^ s1693;
-  const SWord32 s1695 = s1678 ^ s1694;
-  const SWord16 s1696 = (SWord16) (s1695 >> 16);
-  const SWord8  s1697 = (SWord8) (s1696 >> 8);
-  const SWord32 s1698 = table1[s1697];
-  const SWord8  s1699 = (SWord8) (s1639 >> 8);
-  const SWord32 s1700 = table1[s1699];
-  const SWord16 s1701 = (SWord16) (s1657 >> 16);
-  const SWord8  s1702 = (SWord8) s1701;
-  const SWord32 s1703 = table2[s1702];
-  const SWord32 s1704 = s1700 ^ s1703;
-  const SWord8  s1705 = (SWord8) (s1675 >> 8);
-  const SWord32 s1706 = table3[s1705];
-  const SWord32 s1707 = s1704 ^ s1706;
-  const SWord16 s1708 = (SWord16) s1620;
-  const SWord8  s1709 = (SWord8) s1708;
-  const SWord32 s1710 = table4[s1709];
-  const SWord32 s1711 = s1707 ^ s1710;
-  const SWord32 s1712 = s1637 ^ s1694;
-  const SWord32 s1713 = s1711 ^ s1712;
-  const SWord16 s1714 = (SWord16) (s1713 >> 16);
-  const SWord8  s1715 = (SWord8) s1714;
-  const SWord32 s1716 = table2[s1715];
-  const SWord32 s1717 = s1698 ^ s1716;
-  const SWord8  s1718 = (SWord8) (s1701 >> 8);
-  const SWord32 s1719 = table1[s1718];
-  const SWord16 s1720 = (SWord16) (s1674 >> 16);
-  const SWord8  s1721 = (SWord8) s1720;
-  const SWord32 s1722 = table2[s1721];
-  const SWord32 s1723 = s1719 ^ s1722;
-  const SWord8  s1724 = (SWord8) (s1708 >> 8);
-  const SWord32 s1725 = table3[s1724];
-  const SWord32 s1726 = s1723 ^ s1725;
-  const SWord16 s1727 = (SWord16) s1638;
-  const SWord8  s1728 = (SWord8) s1727;
-  const SWord32 s1729 = table4[s1728];
-  const SWord32 s1730 = s1726 ^ s1729;
-  const SWord32 s1731 = s1656 ^ s1712;
-  const SWord32 s1732 = s1730 ^ s1731;
-  const SWord16 s1733 = (SWord16) s1732;
-  const SWord8  s1734 = (SWord8) (s1733 >> 8);
-  const SWord32 s1735 = table3[s1734];
-  const SWord32 s1736 = s1717 ^ s1735;
-  const SWord8  s1737 = (SWord8) (s1720 >> 8);
-  const SWord32 s1738 = table1[s1737];
-  const SWord8  s1739 = (SWord8) s1621;
-  const SWord32 s1740 = table2[s1739];
-  const SWord32 s1741 = s1738 ^ s1740;
-  const SWord8  s1742 = (SWord8) (s1727 >> 8);
-  const SWord32 s1743 = table3[s1742];
-  const SWord32 s1744 = s1741 ^ s1743;
-  const SWord8  s1745 = (SWord8) s1658;
-  const SWord32 s1746 = table4[s1745];
-  const SWord32 s1747 = s1744 ^ s1746;
-  const SWord32 s1748 = s1673 ^ s1731;
-  const SWord32 s1749 = s1747 ^ s1748;
-  const SWord16 s1750 = (SWord16) s1749;
-  const SWord8  s1751 = (SWord8) s1750;
-  const SWord32 s1752 = table4[s1751];
-  const SWord32 s1753 = s1736 ^ s1752;
-  const SWord32 s1754 = (s1748 << 8) | (s1748 >> 24);
-  const SWord16 s1755 = (SWord16) (s1754 >> 16);
-  const SWord8  s1756 = (SWord8) (s1755 >> 8);
-  const SWord8  s1757 = table0[s1756];
-  const SWord8  s1758 = 64 ^ s1757;
-  const SWord8  s1759 = (SWord8) s1755;
-  const SWord8  s1760 = table0[s1759];
-  const SWord16 s1761 = (((SWord16) s1758) << 8) | ((SWord16) s1760);
-  const SWord16 s1762 = (SWord16) s1754;
-  const SWord8  s1763 = (SWord8) (s1762 >> 8);
-  const SWord8  s1764 = table0[s1763];
-  const SWord8  s1765 = (SWord8) s1762;
-  const SWord8  s1766 = table0[s1765];
-  const SWord16 s1767 = (((SWord16) s1764) << 8) | ((SWord16) s1766);
-  const SWord32 s1768 = (((SWord32) s1761) << 16) | ((SWord32) s1767);
-  const SWord32 s1769 = s1694 ^ s1768;
-  const SWord32 s1770 = s1753 ^ s1769;
-  const SWord16 s1771 = (SWord16) (s1770 >> 16);
-  const SWord8  s1772 = (SWord8) (s1771 >> 8);
-  const SWord32 s1773 = table1[s1772];
-  const SWord8  s1774 = (SWord8) (s1714 >> 8);
-  const SWord32 s1775 = table1[s1774];
-  const SWord16 s1776 = (SWord16) (s1732 >> 16);
-  const SWord8  s1777 = (SWord8) s1776;
-  const SWord32 s1778 = table2[s1777];
-  const SWord32 s1779 = s1775 ^ s1778;
-  const SWord8  s1780 = (SWord8) (s1750 >> 8);
-  const SWord32 s1781 = table3[s1780];
-  const SWord32 s1782 = s1779 ^ s1781;
-  const SWord16 s1783 = (SWord16) s1695;
-  const SWord8  s1784 = (SWord8) s1783;
-  const SWord32 s1785 = table4[s1784];
-  const SWord32 s1786 = s1782 ^ s1785;
-  const SWord32 s1787 = s1712 ^ s1769;
-  const SWord32 s1788 = s1786 ^ s1787;
-  const SWord16 s1789 = (SWord16) (s1788 >> 16);
-  const SWord8  s1790 = (SWord8) s1789;
-  const SWord32 s1791 = table2[s1790];
-  const SWord32 s1792 = s1773 ^ s1791;
-  const SWord8  s1793 = (SWord8) (s1776 >> 8);
-  const SWord32 s1794 = table1[s1793];
-  const SWord16 s1795 = (SWord16) (s1749 >> 16);
-  const SWord8  s1796 = (SWord8) s1795;
-  const SWord32 s1797 = table2[s1796];
-  const SWord32 s1798 = s1794 ^ s1797;
-  const SWord8  s1799 = (SWord8) (s1783 >> 8);
-  const SWord32 s1800 = table3[s1799];
-  const SWord32 s1801 = s1798 ^ s1800;
-  const SWord16 s1802 = (SWord16) s1713;
-  const SWord8  s1803 = (SWord8) s1802;
-  const SWord32 s1804 = table4[s1803];
-  const SWord32 s1805 = s1801 ^ s1804;
-  const SWord32 s1806 = s1731 ^ s1787;
-  const SWord32 s1807 = s1805 ^ s1806;
-  const SWord16 s1808 = (SWord16) s1807;
-  const SWord8  s1809 = (SWord8) (s1808 >> 8);
-  const SWord32 s1810 = table3[s1809];
-  const SWord32 s1811 = s1792 ^ s1810;
-  const SWord8  s1812 = (SWord8) (s1795 >> 8);
-  const SWord32 s1813 = table1[s1812];
-  const SWord8  s1814 = (SWord8) s1696;
-  const SWord32 s1815 = table2[s1814];
-  const SWord32 s1816 = s1813 ^ s1815;
-  const SWord8  s1817 = (SWord8) (s1802 >> 8);
-  const SWord32 s1818 = table3[s1817];
-  const SWord32 s1819 = s1816 ^ s1818;
-  const SWord8  s1820 = (SWord8) s1733;
-  const SWord32 s1821 = table4[s1820];
-  const SWord32 s1822 = s1819 ^ s1821;
-  const SWord32 s1823 = s1748 ^ s1806;
-  const SWord32 s1824 = s1822 ^ s1823;
-  const SWord16 s1825 = (SWord16) s1824;
-  const SWord8  s1826 = (SWord8) s1825;
-  const SWord32 s1827 = table4[s1826];
-  const SWord32 s1828 = s1811 ^ s1827;
-  const SWord32 s1829 = (s1823 << 8) | (s1823 >> 24);
-  const SWord16 s1830 = (SWord16) (s1829 >> 16);
-  const SWord8  s1831 = (SWord8) (s1830 >> 8);
-  const SWord8  s1832 = table0[s1831];
-  const SWord8  s1833 = 128 ^ s1832;
-  const SWord8  s1834 = (SWord8) s1830;
-  const SWord8  s1835 = table0[s1834];
-  const SWord16 s1836 = (((SWord16) s1833) << 8) | ((SWord16) s1835);
-  const SWord16 s1837 = (SWord16) s1829;
-  const SWord8  s1838 = (SWord8) (s1837 >> 8);
-  const SWord8  s1839 = table0[s1838];
-  const SWord8  s1840 = (SWord8) s1837;
-  const SWord8  s1841 = table0[s1840];
-  const SWord16 s1842 = (((SWord16) s1839) << 8) | ((SWord16) s1841);
-  const SWord32 s1843 = (((SWord32) s1836) << 16) | ((SWord32) s1842);
-  const SWord32 s1844 = s1769 ^ s1843;
-  const SWord32 s1845 = s1828 ^ s1844;
-  const SWord16 s1846 = (SWord16) (s1845 >> 16);
-  const SWord8  s1847 = (SWord8) (s1846 >> 8);
-  const SWord32 s1848 = table1[s1847];
-  const SWord8  s1849 = (SWord8) (s1789 >> 8);
-  const SWord32 s1850 = table1[s1849];
-  const SWord16 s1851 = (SWord16) (s1807 >> 16);
-  const SWord8  s1852 = (SWord8) s1851;
-  const SWord32 s1853 = table2[s1852];
-  const SWord32 s1854 = s1850 ^ s1853;
-  const SWord8  s1855 = (SWord8) (s1825 >> 8);
-  const SWord32 s1856 = table3[s1855];
-  const SWord32 s1857 = s1854 ^ s1856;
-  const SWord16 s1858 = (SWord16) s1770;
-  const SWord8  s1859 = (SWord8) s1858;
-  const SWord32 s1860 = table4[s1859];
-  const SWord32 s1861 = s1857 ^ s1860;
-  const SWord32 s1862 = s1787 ^ s1844;
-  const SWord32 s1863 = s1861 ^ s1862;
-  const SWord16 s1864 = (SWord16) (s1863 >> 16);
-  const SWord8  s1865 = (SWord8) s1864;
-  const SWord32 s1866 = table2[s1865];
-  const SWord32 s1867 = s1848 ^ s1866;
-  const SWord8  s1868 = (SWord8) (s1851 >> 8);
-  const SWord32 s1869 = table1[s1868];
-  const SWord16 s1870 = (SWord16) (s1824 >> 16);
-  const SWord8  s1871 = (SWord8) s1870;
-  const SWord32 s1872 = table2[s1871];
-  const SWord32 s1873 = s1869 ^ s1872;
-  const SWord8  s1874 = (SWord8) (s1858 >> 8);
-  const SWord32 s1875 = table3[s1874];
-  const SWord32 s1876 = s1873 ^ s1875;
-  const SWord16 s1877 = (SWord16) s1788;
-  const SWord8  s1878 = (SWord8) s1877;
-  const SWord32 s1879 = table4[s1878];
-  const SWord32 s1880 = s1876 ^ s1879;
-  const SWord32 s1881 = s1806 ^ s1862;
-  const SWord32 s1882 = s1880 ^ s1881;
-  const SWord16 s1883 = (SWord16) s1882;
-  const SWord8  s1884 = (SWord8) (s1883 >> 8);
-  const SWord32 s1885 = table3[s1884];
-  const SWord32 s1886 = s1867 ^ s1885;
-  const SWord8  s1887 = (SWord8) (s1870 >> 8);
-  const SWord32 s1888 = table1[s1887];
-  const SWord8  s1889 = (SWord8) s1771;
-  const SWord32 s1890 = table2[s1889];
-  const SWord32 s1891 = s1888 ^ s1890;
-  const SWord8  s1892 = (SWord8) (s1877 >> 8);
-  const SWord32 s1893 = table3[s1892];
-  const SWord32 s1894 = s1891 ^ s1893;
-  const SWord8  s1895 = (SWord8) s1808;
-  const SWord32 s1896 = table4[s1895];
-  const SWord32 s1897 = s1894 ^ s1896;
-  const SWord32 s1898 = s1823 ^ s1881;
-  const SWord32 s1899 = s1897 ^ s1898;
-  const SWord16 s1900 = (SWord16) s1899;
-  const SWord8  s1901 = (SWord8) s1900;
-  const SWord32 s1902 = table4[s1901];
-  const SWord32 s1903 = s1886 ^ s1902;
-  const SWord32 s1904 = (s1898 << 8) | (s1898 >> 24);
-  const SWord16 s1905 = (SWord16) (s1904 >> 16);
-  const SWord8  s1906 = (SWord8) (s1905 >> 8);
-  const SWord8  s1907 = table0[s1906];
-  const SWord8  s1908 = 27 ^ s1907;
-  const SWord8  s1909 = (SWord8) s1905;
-  const SWord8  s1910 = table0[s1909];
-  const SWord16 s1911 = (((SWord16) s1908) << 8) | ((SWord16) s1910);
-  const SWord16 s1912 = (SWord16) s1904;
-  const SWord8  s1913 = (SWord8) (s1912 >> 8);
-  const SWord8  s1914 = table0[s1913];
-  const SWord8  s1915 = (SWord8) s1912;
-  const SWord8  s1916 = table0[s1915];
-  const SWord16 s1917 = (((SWord16) s1914) << 8) | ((SWord16) s1916);
-  const SWord32 s1918 = (((SWord32) s1911) << 16) | ((SWord32) s1917);
-  const SWord32 s1919 = s1844 ^ s1918;
-  const SWord32 s1920 = s1903 ^ s1919;
-  const SWord16 s1921 = (SWord16) (s1920 >> 16);
-  const SWord8  s1922 = (SWord8) (s1921 >> 8);
-  const SWord8  s1923 = table0[s1922];
-  const SWord8  s1924 = (SWord8) (s1864 >> 8);
-  const SWord32 s1925 = table1[s1924];
-  const SWord16 s1926 = (SWord16) (s1882 >> 16);
-  const SWord8  s1927 = (SWord8) s1926;
-  const SWord32 s1928 = table2[s1927];
-  const SWord32 s1929 = s1925 ^ s1928;
-  const SWord8  s1930 = (SWord8) (s1900 >> 8);
-  const SWord32 s1931 = table3[s1930];
-  const SWord32 s1932 = s1929 ^ s1931;
-  const SWord16 s1933 = (SWord16) s1845;
-  const SWord8  s1934 = (SWord8) s1933;
-  const SWord32 s1935 = table4[s1934];
-  const SWord32 s1936 = s1932 ^ s1935;
-  const SWord32 s1937 = s1862 ^ s1919;
-  const SWord32 s1938 = s1936 ^ s1937;
-  const SWord16 s1939 = (SWord16) (s1938 >> 16);
-  const SWord8  s1940 = (SWord8) s1939;
-  const SWord8  s1941 = table0[s1940];
-  const SWord16 s1942 = (((SWord16) s1923) << 8) | ((SWord16) s1941);
-  const SWord8  s1943 = (SWord8) (s1926 >> 8);
-  const SWord32 s1944 = table1[s1943];
-  const SWord16 s1945 = (SWord16) (s1899 >> 16);
-  const SWord8  s1946 = (SWord8) s1945;
-  const SWord32 s1947 = table2[s1946];
-  const SWord32 s1948 = s1944 ^ s1947;
-  const SWord8  s1949 = (SWord8) (s1933 >> 8);
-  const SWord32 s1950 = table3[s1949];
-  const SWord32 s1951 = s1948 ^ s1950;
-  const SWord16 s1952 = (SWord16) s1863;
-  const SWord8  s1953 = (SWord8) s1952;
-  const SWord32 s1954 = table4[s1953];
-  const SWord32 s1955 = s1951 ^ s1954;
-  const SWord32 s1956 = s1881 ^ s1937;
-  const SWord32 s1957 = s1955 ^ s1956;
-  const SWord16 s1958 = (SWord16) s1957;
-  const SWord8  s1959 = (SWord8) (s1958 >> 8);
-  const SWord8  s1960 = table0[s1959];
-  const SWord8  s1961 = (SWord8) (s1945 >> 8);
-  const SWord32 s1962 = table1[s1961];
-  const SWord8  s1963 = (SWord8) s1846;
-  const SWord32 s1964 = table2[s1963];
-  const SWord32 s1965 = s1962 ^ s1964;
-  const SWord8  s1966 = (SWord8) (s1952 >> 8);
-  const SWord32 s1967 = table3[s1966];
-  const SWord32 s1968 = s1965 ^ s1967;
-  const SWord8  s1969 = (SWord8) s1883;
-  const SWord32 s1970 = table4[s1969];
-  const SWord32 s1971 = s1968 ^ s1970;
-  const SWord32 s1972 = s1898 ^ s1956;
-  const SWord32 s1973 = s1971 ^ s1972;
-  const SWord16 s1974 = (SWord16) s1973;
-  const SWord8  s1975 = (SWord8) s1974;
-  const SWord8  s1976 = table0[s1975];
-  const SWord16 s1977 = (((SWord16) s1960) << 8) | ((SWord16) s1976);
-  const SWord32 s1978 = (((SWord32) s1942) << 16) | ((SWord32) s1977);
-  const SWord32 s1979 = (s1972 << 8) | (s1972 >> 24);
-  const SWord16 s1980 = (SWord16) (s1979 >> 16);
-  const SWord8  s1981 = (SWord8) (s1980 >> 8);
-  const SWord8  s1982 = table0[s1981];
-  const SWord8  s1983 = 54 ^ s1982;
-  const SWord8  s1984 = (SWord8) s1980;
-  const SWord8  s1985 = table0[s1984];
-  const SWord16 s1986 = (((SWord16) s1983) << 8) | ((SWord16) s1985);
-  const SWord16 s1987 = (SWord16) s1979;
-  const SWord8  s1988 = (SWord8) (s1987 >> 8);
-  const SWord8  s1989 = table0[s1988];
-  const SWord8  s1990 = (SWord8) s1987;
-  const SWord8  s1991 = table0[s1990];
-  const SWord16 s1992 = (((SWord16) s1989) << 8) | ((SWord16) s1991);
-  const SWord32 s1993 = (((SWord32) s1986) << 16) | ((SWord32) s1992);
-  const SWord32 s1994 = s1919 ^ s1993;
-  const SWord32 s1995 = s1978 ^ s1994;
-  const SWord8  s1996 = (SWord8) (s1939 >> 8);
-  const SWord8  s1997 = table0[s1996];
-  const SWord16 s1998 = (SWord16) (s1957 >> 16);
-  const SWord8  s1999 = (SWord8) s1998;
-  const SWord8  s2000 = table0[s1999];
-  const SWord16 s2001 = (((SWord16) s1997) << 8) | ((SWord16) s2000);
-  const SWord8  s2002 = (SWord8) (s1974 >> 8);
-  const SWord8  s2003 = table0[s2002];
-  const SWord16 s2004 = (SWord16) s1920;
-  const SWord8  s2005 = (SWord8) s2004;
-  const SWord8  s2006 = table0[s2005];
-  const SWord16 s2007 = (((SWord16) s2003) << 8) | ((SWord16) s2006);
-  const SWord32 s2008 = (((SWord32) s2001) << 16) | ((SWord32) s2007);
-  const SWord32 s2009 = s1937 ^ s1994;
-  const SWord32 s2010 = s2008 ^ s2009;
-  const SWord8  s2011 = (SWord8) (s1998 >> 8);
-  const SWord8  s2012 = table0[s2011];
-  const SWord16 s2013 = (SWord16) (s1973 >> 16);
-  const SWord8  s2014 = (SWord8) s2013;
-  const SWord8  s2015 = table0[s2014];
-  const SWord16 s2016 = (((SWord16) s2012) << 8) | ((SWord16) s2015);
-  const SWord8  s2017 = (SWord8) (s2004 >> 8);
-  const SWord8  s2018 = table0[s2017];
-  const SWord16 s2019 = (SWord16) s1938;
-  const SWord8  s2020 = (SWord8) s2019;
-  const SWord8  s2021 = table0[s2020];
-  const SWord16 s2022 = (((SWord16) s2018) << 8) | ((SWord16) s2021);
-  const SWord32 s2023 = (((SWord32) s2016) << 16) | ((SWord32) s2022);
-  const SWord32 s2024 = s1956 ^ s2009;
-  const SWord32 s2025 = s2023 ^ s2024;
-  const SWord8  s2026 = (SWord8) (s2013 >> 8);
-  const SWord8  s2027 = table0[s2026];
-  const SWord8  s2028 = (SWord8) s1921;
-  const SWord8  s2029 = table0[s2028];
-  const SWord16 s2030 = (((SWord16) s2027) << 8) | ((SWord16) s2029);
-  const SWord8  s2031 = (SWord8) (s2019 >> 8);
-  const SWord8  s2032 = table0[s2031];
-  const SWord8  s2033 = (SWord8) s1958;
-  const SWord8  s2034 = table0[s2033];
-  const SWord16 s2035 = (((SWord16) s2032) << 8) | ((SWord16) s2034);
-  const SWord32 s2036 = (((SWord32) s2030) << 16) | ((SWord32) s2035);
-  const SWord32 s2037 = s1972 ^ s2024;
-  const SWord32 s2038 = s2036 ^ s2037;
-
-  ct[0] = s1995;
-  ct[1] = s2010;
-  ct[2] = s2025;
-  ct[3] = s2038;
-}
-== END: "aes128Enc.c" ==================
diff --git a/SBVUnitTest/GoldFiles/aes128Lib.gold b/SBVUnitTest/GoldFiles/aes128Lib.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/aes128Lib.gold
+++ /dev/null
@@ -1,3772 +0,0 @@
-== BEGIN: "aes128KeySchedule.c" ================
-/* File: "aes128KeySchedule.c". Automatically generated by SBV. Do not edit! */
-
-#include "aes128Lib.h"
-
-void aes128KeySchedule(const SWord32 *key, SWord32 *encKS,
-                       SWord32 *decKS)
-{
-  const SWord32 s0 = key[0];
-  const SWord32 s1 = key[1];
-  const SWord32 s2 = key[2];
-  const SWord32 s3 = key[3];
-  static const SWord8 table0[] = {
-       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
-      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
-      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
-      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
-       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
-      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
-       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
-       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
-       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
-      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
-       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
-      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
-      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
-      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
-       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
-       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
-      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
-      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
-      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
-      104,  65, 153,  45,  15, 176,  84, 187,  22
-  };
-  static const SWord8 table1[] = {
-        0,  14,  28,  18,  56,  54,  36,  42, 112, 126, 108,  98,  72,
-       70,  84,  90, 224, 238, 252, 242, 216, 214, 196, 202, 144, 158,
-      140, 130, 168, 166, 180, 186, 219, 213, 199, 201, 227, 237, 255,
-      241, 171, 165, 183, 185, 147, 157, 143, 129,  59,  53,  39,  41,
-        3,  13,  31,  17,  75,  69,  87,  89, 115, 125, 111,  97, 173,
-      163, 177, 191, 149, 155, 137, 135, 221, 211, 193, 207, 229, 235,
-      249, 247,  77,  67,  81,  95, 117, 123, 105, 103,  61,  51,  33,
-       47,   5,  11,  25,  23, 118, 120, 106, 100,  78,  64,  82,  92,
-        6,   8,  26,  20,  62,  48,  34,  44, 150, 152, 138, 132, 174,
-      160, 178, 188, 230, 232, 250, 244, 222, 208, 194, 204,  65,  79,
-       93,  83, 121, 119, 101, 107,  49,  63,  45,  35,   9,   7,  21,
-       27, 161, 175, 189, 179, 153, 151, 133, 139, 209, 223, 205, 195,
-      233, 231, 245, 251, 154, 148, 134, 136, 162, 172, 190, 176, 234,
-      228, 246, 248, 210, 220, 206, 192, 122, 116, 102, 104,  66,  76,
-       94,  80,  10,   4,  22,  24,  50,  60,  46,  32, 236, 226, 240,
-      254, 212, 218, 200, 198, 156, 146, 128, 142, 164, 170, 184, 182,
-       12,   2,  16,  30,  52,  58,  40,  38, 124, 114,  96, 110,  68,
-       74,  88,  86,  55,  57,  43,  37,  15,   1,  19,  29,  71,  73,
-       91,  85, 127, 113,  99, 109, 215, 217, 203, 197, 239, 225, 243,
-      253, 167, 169, 187, 181, 159, 145, 131, 141
-  };
-  static const SWord8 table2[] = {
-        0,  11,  22,  29,  44,  39,  58,  49,  88,  83,  78,  69, 116,
-      127,  98, 105, 176, 187, 166, 173, 156, 151, 138, 129, 232, 227,
-      254, 245, 196, 207, 210, 217, 123, 112, 109, 102,  87,  92,  65,
-       74,  35,  40,  53,  62,  15,   4,  25,  18, 203, 192, 221, 214,
-      231, 236, 241, 250, 147, 152, 133, 142, 191, 180, 169, 162, 246,
-      253, 224, 235, 218, 209, 204, 199, 174, 165, 184, 179, 130, 137,
-      148, 159,  70,  77,  80,  91, 106,  97, 124, 119,  30,  21,   8,
-        3,  50,  57,  36,  47, 141, 134, 155, 144, 161, 170, 183, 188,
-      213, 222, 195, 200, 249, 242, 239, 228,  61,  54,  43,  32,  17,
-       26,   7,  12, 101, 110, 115, 120,  73,  66,  95,  84, 247, 252,
-      225, 234, 219, 208, 205, 198, 175, 164, 185, 178, 131, 136, 149,
-      158,  71,  76,  81,  90, 107,  96, 125, 118,  31,  20,   9,   2,
-       51,  56,  37,  46, 140, 135, 154, 145, 160, 171, 182, 189, 212,
-      223, 194, 201, 248, 243, 238, 229,  60,  55,  42,  33,  16,  27,
-        6,  13, 100, 111, 114, 121,  72,  67,  94,  85,   1,  10,  23,
-       28,  45,  38,  59,  48,  89,  82,  79,  68, 117, 126,  99, 104,
-      177, 186, 167, 172, 157, 150, 139, 128, 233, 226, 255, 244, 197,
-      206, 211, 216, 122, 113, 108, 103,  86,  93,  64,  75,  34,  41,
-       52,  63,  14,   5,  24,  19, 202, 193, 220, 215, 230, 237, 240,
-      251, 146, 153, 132, 143, 190, 181, 168, 163
-  };
-  static const SWord8 table3[] = {
-        0,  13,  26,  23,  52,  57,  46,  35, 104, 101, 114, 127,  92,
-       81,  70,  75, 208, 221, 202, 199, 228, 233, 254, 243, 184, 181,
-      162, 175, 140, 129, 150, 155, 187, 182, 161, 172, 143, 130, 149,
-      152, 211, 222, 201, 196, 231, 234, 253, 240, 107, 102, 113, 124,
-       95,  82,  69,  72,   3,  14,  25,  20,  55,  58,  45,  32, 109,
-       96, 119, 122,  89,  84,  67,  78,   5,   8,  31,  18,  49,  60,
-       43,  38, 189, 176, 167, 170, 137, 132, 147, 158, 213, 216, 207,
-      194, 225, 236, 251, 246, 214, 219, 204, 193, 226, 239, 248, 245,
-      190, 179, 164, 169, 138, 135, 144, 157,   6,  11,  28,  17,  50,
-       63,  40,  37, 110,  99, 116, 121,  90,  87,  64,  77, 218, 215,
-      192, 205, 238, 227, 244, 249, 178, 191, 168, 165, 134, 139, 156,
-      145,  10,   7,  16,  29,  62,  51,  36,  41,  98, 111, 120, 117,
-       86,  91,  76,  65,  97, 108, 123, 118,  85,  88,  79,  66,   9,
-        4,  19,  30,  61,  48,  39,  42, 177, 188, 171, 166, 133, 136,
-      159, 146, 217, 212, 195, 206, 237, 224, 247, 250, 183, 186, 173,
-      160, 131, 142, 153, 148, 223, 210, 197, 200, 235, 230, 241, 252,
-      103, 106, 125, 112,  83,  94,  73,  68,  15,   2,  21,  24,  59,
-       54,  33,  44,  12,   1,  22,  27,  56,  53,  34,  47, 100, 105,
-      126, 115,  80,  93,  74,  71, 220, 209, 198, 203, 232, 229, 242,
-      255, 180, 185, 174, 163, 128, 141, 154, 151
-  };
-  static const SWord8 table4[] = {
-        0,   9,  18,  27,  36,  45,  54,  63,  72,  65,  90,  83, 108,
-      101, 126, 119, 144, 153, 130, 139, 180, 189, 166, 175, 216, 209,
-      202, 195, 252, 245, 238, 231,  59,  50,  41,  32,  31,  22,  13,
-        4, 115, 122,  97, 104,  87,  94,  69,  76, 171, 162, 185, 176,
-      143, 134, 157, 148, 227, 234, 241, 248, 199, 206, 213, 220, 118,
-      127, 100, 109,  82,  91,  64,  73,  62,  55,  44,  37,  26,  19,
-        8,   1, 230, 239, 244, 253, 194, 203, 208, 217, 174, 167, 188,
-      181, 138, 131, 152, 145,  77,  68,  95,  86, 105,  96, 123, 114,
-        5,  12,  23,  30,  33,  40,  51,  58, 221, 212, 207, 198, 249,
-      240, 235, 226, 149, 156, 135, 142, 177, 184, 163, 170, 236, 229,
-      254, 247, 200, 193, 218, 211, 164, 173, 182, 191, 128, 137, 146,
-      155, 124, 117, 110, 103,  88,  81,  74,  67,  52,  61,  38,  47,
-       16,  25,   2,  11, 215, 222, 197, 204, 243, 250, 225, 232, 159,
-      150, 141, 132, 187, 178, 169, 160,  71,  78,  85,  92,  99, 106,
-      113, 120,  15,   6,  29,  20,  43,  34,  57,  48, 154, 147, 136,
-      129, 190, 183, 172, 165, 210, 219, 192, 201, 246, 255, 228, 237,
-       10,   3,  24,  17,  46,  39,  60,  53,  66,  75,  80,  89, 102,
-      111, 116, 125, 161, 168, 179, 186, 133, 140, 151, 158, 233, 224,
-      251, 242, 205, 196, 223, 214,  49,  56,  35,  42,  21,  28,   7,
-       14, 121, 112, 107,  98,  93,  84,  79,  70
-  };
-  const SWord32 s260 = (s3 << 8) | (s3 >> 24);
-  const SWord16 s261 = (SWord16) (s260 >> 16);
-  const SWord8  s262 = (SWord8) (s261 >> 8);
-  const SWord8  s263 = table0[s262];
-  const SWord8  s264 = 1 ^ s263;
-  const SWord8  s265 = (SWord8) s261;
-  const SWord8  s266 = table0[s265];
-  const SWord16 s267 = (((SWord16) s264) << 8) | ((SWord16) s266);
-  const SWord16 s268 = (SWord16) s260;
-  const SWord8  s269 = (SWord8) (s268 >> 8);
-  const SWord8  s270 = table0[s269];
-  const SWord8  s271 = (SWord8) s268;
-  const SWord8  s272 = table0[s271];
-  const SWord16 s273 = (((SWord16) s270) << 8) | ((SWord16) s272);
-  const SWord32 s274 = (((SWord32) s267) << 16) | ((SWord32) s273);
-  const SWord32 s275 = s0 ^ s274;
-  const SWord32 s276 = s1 ^ s275;
-  const SWord32 s277 = s2 ^ s276;
-  const SWord32 s278 = s3 ^ s277;
-  const SWord32 s279 = (s278 << 8) | (s278 >> 24);
-  const SWord16 s280 = (SWord16) (s279 >> 16);
-  const SWord8  s281 = (SWord8) (s280 >> 8);
-  const SWord8  s282 = table0[s281];
-  const SWord8  s283 = 2 ^ s282;
-  const SWord8  s284 = (SWord8) s280;
-  const SWord8  s285 = table0[s284];
-  const SWord16 s286 = (((SWord16) s283) << 8) | ((SWord16) s285);
-  const SWord16 s287 = (SWord16) s279;
-  const SWord8  s288 = (SWord8) (s287 >> 8);
-  const SWord8  s289 = table0[s288];
-  const SWord8  s290 = (SWord8) s287;
-  const SWord8  s291 = table0[s290];
-  const SWord16 s292 = (((SWord16) s289) << 8) | ((SWord16) s291);
-  const SWord32 s293 = (((SWord32) s286) << 16) | ((SWord32) s292);
-  const SWord32 s294 = s275 ^ s293;
-  const SWord32 s295 = s276 ^ s294;
-  const SWord32 s296 = s277 ^ s295;
-  const SWord32 s297 = s278 ^ s296;
-  const SWord32 s298 = (s297 << 8) | (s297 >> 24);
-  const SWord16 s299 = (SWord16) (s298 >> 16);
-  const SWord8  s300 = (SWord8) (s299 >> 8);
-  const SWord8  s301 = table0[s300];
-  const SWord8  s302 = 4 ^ s301;
-  const SWord8  s303 = (SWord8) s299;
-  const SWord8  s304 = table0[s303];
-  const SWord16 s305 = (((SWord16) s302) << 8) | ((SWord16) s304);
-  const SWord16 s306 = (SWord16) s298;
-  const SWord8  s307 = (SWord8) (s306 >> 8);
-  const SWord8  s308 = table0[s307];
-  const SWord8  s309 = (SWord8) s306;
-  const SWord8  s310 = table0[s309];
-  const SWord16 s311 = (((SWord16) s308) << 8) | ((SWord16) s310);
-  const SWord32 s312 = (((SWord32) s305) << 16) | ((SWord32) s311);
-  const SWord32 s313 = s294 ^ s312;
-  const SWord32 s314 = s295 ^ s313;
-  const SWord32 s315 = s296 ^ s314;
-  const SWord32 s316 = s297 ^ s315;
-  const SWord32 s317 = (s316 << 8) | (s316 >> 24);
-  const SWord16 s318 = (SWord16) (s317 >> 16);
-  const SWord8  s319 = (SWord8) (s318 >> 8);
-  const SWord8  s320 = table0[s319];
-  const SWord8  s321 = 8 ^ s320;
-  const SWord8  s322 = (SWord8) s318;
-  const SWord8  s323 = table0[s322];
-  const SWord16 s324 = (((SWord16) s321) << 8) | ((SWord16) s323);
-  const SWord16 s325 = (SWord16) s317;
-  const SWord8  s326 = (SWord8) (s325 >> 8);
-  const SWord8  s327 = table0[s326];
-  const SWord8  s328 = (SWord8) s325;
-  const SWord8  s329 = table0[s328];
-  const SWord16 s330 = (((SWord16) s327) << 8) | ((SWord16) s329);
-  const SWord32 s331 = (((SWord32) s324) << 16) | ((SWord32) s330);
-  const SWord32 s332 = s313 ^ s331;
-  const SWord32 s333 = s314 ^ s332;
-  const SWord32 s334 = s315 ^ s333;
-  const SWord32 s335 = s316 ^ s334;
-  const SWord32 s336 = (s335 << 8) | (s335 >> 24);
-  const SWord16 s337 = (SWord16) (s336 >> 16);
-  const SWord8  s338 = (SWord8) (s337 >> 8);
-  const SWord8  s339 = table0[s338];
-  const SWord8  s340 = 16 ^ s339;
-  const SWord8  s341 = (SWord8) s337;
-  const SWord8  s342 = table0[s341];
-  const SWord16 s343 = (((SWord16) s340) << 8) | ((SWord16) s342);
-  const SWord16 s344 = (SWord16) s336;
-  const SWord8  s345 = (SWord8) (s344 >> 8);
-  const SWord8  s346 = table0[s345];
-  const SWord8  s347 = (SWord8) s344;
-  const SWord8  s348 = table0[s347];
-  const SWord16 s349 = (((SWord16) s346) << 8) | ((SWord16) s348);
-  const SWord32 s350 = (((SWord32) s343) << 16) | ((SWord32) s349);
-  const SWord32 s351 = s332 ^ s350;
-  const SWord32 s352 = s333 ^ s351;
-  const SWord32 s353 = s334 ^ s352;
-  const SWord32 s354 = s335 ^ s353;
-  const SWord32 s355 = (s354 << 8) | (s354 >> 24);
-  const SWord16 s356 = (SWord16) (s355 >> 16);
-  const SWord8  s357 = (SWord8) (s356 >> 8);
-  const SWord8  s358 = table0[s357];
-  const SWord8  s359 = 32 ^ s358;
-  const SWord8  s360 = (SWord8) s356;
-  const SWord8  s361 = table0[s360];
-  const SWord16 s362 = (((SWord16) s359) << 8) | ((SWord16) s361);
-  const SWord16 s363 = (SWord16) s355;
-  const SWord8  s364 = (SWord8) (s363 >> 8);
-  const SWord8  s365 = table0[s364];
-  const SWord8  s366 = (SWord8) s363;
-  const SWord8  s367 = table0[s366];
-  const SWord16 s368 = (((SWord16) s365) << 8) | ((SWord16) s367);
-  const SWord32 s369 = (((SWord32) s362) << 16) | ((SWord32) s368);
-  const SWord32 s370 = s351 ^ s369;
-  const SWord32 s371 = s352 ^ s370;
-  const SWord32 s372 = s353 ^ s371;
-  const SWord32 s373 = s354 ^ s372;
-  const SWord32 s374 = (s373 << 8) | (s373 >> 24);
-  const SWord16 s375 = (SWord16) (s374 >> 16);
-  const SWord8  s376 = (SWord8) (s375 >> 8);
-  const SWord8  s377 = table0[s376];
-  const SWord8  s378 = 64 ^ s377;
-  const SWord8  s379 = (SWord8) s375;
-  const SWord8  s380 = table0[s379];
-  const SWord16 s381 = (((SWord16) s378) << 8) | ((SWord16) s380);
-  const SWord16 s382 = (SWord16) s374;
-  const SWord8  s383 = (SWord8) (s382 >> 8);
-  const SWord8  s384 = table0[s383];
-  const SWord8  s385 = (SWord8) s382;
-  const SWord8  s386 = table0[s385];
-  const SWord16 s387 = (((SWord16) s384) << 8) | ((SWord16) s386);
-  const SWord32 s388 = (((SWord32) s381) << 16) | ((SWord32) s387);
-  const SWord32 s389 = s370 ^ s388;
-  const SWord32 s390 = s371 ^ s389;
-  const SWord32 s391 = s372 ^ s390;
-  const SWord32 s392 = s373 ^ s391;
-  const SWord32 s393 = (s392 << 8) | (s392 >> 24);
-  const SWord16 s394 = (SWord16) (s393 >> 16);
-  const SWord8  s395 = (SWord8) (s394 >> 8);
-  const SWord8  s396 = table0[s395];
-  const SWord8  s397 = 128 ^ s396;
-  const SWord8  s398 = (SWord8) s394;
-  const SWord8  s399 = table0[s398];
-  const SWord16 s400 = (((SWord16) s397) << 8) | ((SWord16) s399);
-  const SWord16 s401 = (SWord16) s393;
-  const SWord8  s402 = (SWord8) (s401 >> 8);
-  const SWord8  s403 = table0[s402];
-  const SWord8  s404 = (SWord8) s401;
-  const SWord8  s405 = table0[s404];
-  const SWord16 s406 = (((SWord16) s403) << 8) | ((SWord16) s405);
-  const SWord32 s407 = (((SWord32) s400) << 16) | ((SWord32) s406);
-  const SWord32 s408 = s389 ^ s407;
-  const SWord32 s409 = s390 ^ s408;
-  const SWord32 s410 = s391 ^ s409;
-  const SWord32 s411 = s392 ^ s410;
-  const SWord32 s412 = (s411 << 8) | (s411 >> 24);
-  const SWord16 s413 = (SWord16) (s412 >> 16);
-  const SWord8  s414 = (SWord8) (s413 >> 8);
-  const SWord8  s415 = table0[s414];
-  const SWord8  s416 = 27 ^ s415;
-  const SWord8  s417 = (SWord8) s413;
-  const SWord8  s418 = table0[s417];
-  const SWord16 s419 = (((SWord16) s416) << 8) | ((SWord16) s418);
-  const SWord16 s420 = (SWord16) s412;
-  const SWord8  s421 = (SWord8) (s420 >> 8);
-  const SWord8  s422 = table0[s421];
-  const SWord8  s423 = (SWord8) s420;
-  const SWord8  s424 = table0[s423];
-  const SWord16 s425 = (((SWord16) s422) << 8) | ((SWord16) s424);
-  const SWord32 s426 = (((SWord32) s419) << 16) | ((SWord32) s425);
-  const SWord32 s427 = s408 ^ s426;
-  const SWord32 s428 = s409 ^ s427;
-  const SWord32 s429 = s410 ^ s428;
-  const SWord32 s430 = s411 ^ s429;
-  const SWord32 s431 = (s430 << 8) | (s430 >> 24);
-  const SWord16 s432 = (SWord16) (s431 >> 16);
-  const SWord8  s433 = (SWord8) (s432 >> 8);
-  const SWord8  s434 = table0[s433];
-  const SWord8  s435 = 54 ^ s434;
-  const SWord8  s436 = (SWord8) s432;
-  const SWord8  s437 = table0[s436];
-  const SWord16 s438 = (((SWord16) s435) << 8) | ((SWord16) s437);
-  const SWord16 s439 = (SWord16) s431;
-  const SWord8  s440 = (SWord8) (s439 >> 8);
-  const SWord8  s441 = table0[s440];
-  const SWord8  s442 = (SWord8) s439;
-  const SWord8  s443 = table0[s442];
-  const SWord16 s444 = (((SWord16) s441) << 8) | ((SWord16) s443);
-  const SWord32 s445 = (((SWord32) s438) << 16) | ((SWord32) s444);
-  const SWord32 s446 = s427 ^ s445;
-  const SWord32 s447 = s428 ^ s446;
-  const SWord32 s448 = s429 ^ s447;
-  const SWord32 s449 = s430 ^ s448;
-  const SWord16 s450 = (SWord16) (s427 >> 16);
-  const SWord8  s451 = (SWord8) (s450 >> 8);
-  const SWord8  s452 = table1[s451];
-  const SWord8  s453 = (SWord8) s450;
-  const SWord8  s454 = table2[s453];
-  const SWord16 s455 = (SWord16) s427;
-  const SWord8  s456 = (SWord8) (s455 >> 8);
-  const SWord8  s457 = table3[s456];
-  const SWord8  s458 = (SWord8) s455;
-  const SWord8  s459 = table4[s458];
-  const SWord8  s460 = s457 ^ s459;
-  const SWord8  s461 = s454 ^ s460;
-  const SWord8  s462 = s452 ^ s461;
-  const SWord8  s463 = table4[s451];
-  const SWord8  s464 = table1[s453];
-  const SWord8  s465 = table2[s456];
-  const SWord8  s466 = table3[s458];
-  const SWord8  s467 = s465 ^ s466;
-  const SWord8  s468 = s464 ^ s467;
-  const SWord8  s469 = s463 ^ s468;
-  const SWord16 s470 = (((SWord16) s462) << 8) | ((SWord16) s469);
-  const SWord8  s471 = table3[s451];
-  const SWord8  s472 = table4[s453];
-  const SWord8  s473 = table1[s456];
-  const SWord8  s474 = table2[s458];
-  const SWord8  s475 = s473 ^ s474;
-  const SWord8  s476 = s472 ^ s475;
-  const SWord8  s477 = s471 ^ s476;
-  const SWord8  s478 = table2[s451];
-  const SWord8  s479 = table3[s453];
-  const SWord8  s480 = table4[s456];
-  const SWord8  s481 = table1[s458];
-  const SWord8  s482 = s480 ^ s481;
-  const SWord8  s483 = s479 ^ s482;
-  const SWord8  s484 = s478 ^ s483;
-  const SWord16 s485 = (((SWord16) s477) << 8) | ((SWord16) s484);
-  const SWord32 s486 = (((SWord32) s470) << 16) | ((SWord32) s485);
-  const SWord16 s487 = (SWord16) (s428 >> 16);
-  const SWord8  s488 = (SWord8) (s487 >> 8);
-  const SWord8  s489 = table1[s488];
-  const SWord8  s490 = (SWord8) s487;
-  const SWord8  s491 = table2[s490];
-  const SWord16 s492 = (SWord16) s428;
-  const SWord8  s493 = (SWord8) (s492 >> 8);
-  const SWord8  s494 = table3[s493];
-  const SWord8  s495 = (SWord8) s492;
-  const SWord8  s496 = table4[s495];
-  const SWord8  s497 = s494 ^ s496;
-  const SWord8  s498 = s491 ^ s497;
-  const SWord8  s499 = s489 ^ s498;
-  const SWord8  s500 = table4[s488];
-  const SWord8  s501 = table1[s490];
-  const SWord8  s502 = table2[s493];
-  const SWord8  s503 = table3[s495];
-  const SWord8  s504 = s502 ^ s503;
-  const SWord8  s505 = s501 ^ s504;
-  const SWord8  s506 = s500 ^ s505;
-  const SWord16 s507 = (((SWord16) s499) << 8) | ((SWord16) s506);
-  const SWord8  s508 = table3[s488];
-  const SWord8  s509 = table4[s490];
-  const SWord8  s510 = table1[s493];
-  const SWord8  s511 = table2[s495];
-  const SWord8  s512 = s510 ^ s511;
-  const SWord8  s513 = s509 ^ s512;
-  const SWord8  s514 = s508 ^ s513;
-  const SWord8  s515 = table2[s488];
-  const SWord8  s516 = table3[s490];
-  const SWord8  s517 = table4[s493];
-  const SWord8  s518 = table1[s495];
-  const SWord8  s519 = s517 ^ s518;
-  const SWord8  s520 = s516 ^ s519;
-  const SWord8  s521 = s515 ^ s520;
-  const SWord16 s522 = (((SWord16) s514) << 8) | ((SWord16) s521);
-  const SWord32 s523 = (((SWord32) s507) << 16) | ((SWord32) s522);
-  const SWord16 s524 = (SWord16) (s429 >> 16);
-  const SWord8  s525 = (SWord8) (s524 >> 8);
-  const SWord8  s526 = table1[s525];
-  const SWord8  s527 = (SWord8) s524;
-  const SWord8  s528 = table2[s527];
-  const SWord16 s529 = (SWord16) s429;
-  const SWord8  s530 = (SWord8) (s529 >> 8);
-  const SWord8  s531 = table3[s530];
-  const SWord8  s532 = (SWord8) s529;
-  const SWord8  s533 = table4[s532];
-  const SWord8  s534 = s531 ^ s533;
-  const SWord8  s535 = s528 ^ s534;
-  const SWord8  s536 = s526 ^ s535;
-  const SWord8  s537 = table4[s525];
-  const SWord8  s538 = table1[s527];
-  const SWord8  s539 = table2[s530];
-  const SWord8  s540 = table3[s532];
-  const SWord8  s541 = s539 ^ s540;
-  const SWord8  s542 = s538 ^ s541;
-  const SWord8  s543 = s537 ^ s542;
-  const SWord16 s544 = (((SWord16) s536) << 8) | ((SWord16) s543);
-  const SWord8  s545 = table3[s525];
-  const SWord8  s546 = table4[s527];
-  const SWord8  s547 = table1[s530];
-  const SWord8  s548 = table2[s532];
-  const SWord8  s549 = s547 ^ s548;
-  const SWord8  s550 = s546 ^ s549;
-  const SWord8  s551 = s545 ^ s550;
-  const SWord8  s552 = table2[s525];
-  const SWord8  s553 = table3[s527];
-  const SWord8  s554 = table4[s530];
-  const SWord8  s555 = table1[s532];
-  const SWord8  s556 = s554 ^ s555;
-  const SWord8  s557 = s553 ^ s556;
-  const SWord8  s558 = s552 ^ s557;
-  const SWord16 s559 = (((SWord16) s551) << 8) | ((SWord16) s558);
-  const SWord32 s560 = (((SWord32) s544) << 16) | ((SWord32) s559);
-  const SWord16 s561 = (SWord16) (s430 >> 16);
-  const SWord8  s562 = (SWord8) (s561 >> 8);
-  const SWord8  s563 = table1[s562];
-  const SWord8  s564 = (SWord8) s561;
-  const SWord8  s565 = table2[s564];
-  const SWord16 s566 = (SWord16) s430;
-  const SWord8  s567 = (SWord8) (s566 >> 8);
-  const SWord8  s568 = table3[s567];
-  const SWord8  s569 = (SWord8) s566;
-  const SWord8  s570 = table4[s569];
-  const SWord8  s571 = s568 ^ s570;
-  const SWord8  s572 = s565 ^ s571;
-  const SWord8  s573 = s563 ^ s572;
-  const SWord8  s574 = table4[s562];
-  const SWord8  s575 = table1[s564];
-  const SWord8  s576 = table2[s567];
-  const SWord8  s577 = table3[s569];
-  const SWord8  s578 = s576 ^ s577;
-  const SWord8  s579 = s575 ^ s578;
-  const SWord8  s580 = s574 ^ s579;
-  const SWord16 s581 = (((SWord16) s573) << 8) | ((SWord16) s580);
-  const SWord8  s582 = table3[s562];
-  const SWord8  s583 = table4[s564];
-  const SWord8  s584 = table1[s567];
-  const SWord8  s585 = table2[s569];
-  const SWord8  s586 = s584 ^ s585;
-  const SWord8  s587 = s583 ^ s586;
-  const SWord8  s588 = s582 ^ s587;
-  const SWord8  s589 = table2[s562];
-  const SWord8  s590 = table3[s564];
-  const SWord8  s591 = table4[s567];
-  const SWord8  s592 = table1[s569];
-  const SWord8  s593 = s591 ^ s592;
-  const SWord8  s594 = s590 ^ s593;
-  const SWord8  s595 = s589 ^ s594;
-  const SWord16 s596 = (((SWord16) s588) << 8) | ((SWord16) s595);
-  const SWord32 s597 = (((SWord32) s581) << 16) | ((SWord32) s596);
-  const SWord16 s598 = (SWord16) (s408 >> 16);
-  const SWord8  s599 = (SWord8) (s598 >> 8);
-  const SWord8  s600 = table1[s599];
-  const SWord8  s601 = (SWord8) s598;
-  const SWord8  s602 = table2[s601];
-  const SWord16 s603 = (SWord16) s408;
-  const SWord8  s604 = (SWord8) (s603 >> 8);
-  const SWord8  s605 = table3[s604];
-  const SWord8  s606 = (SWord8) s603;
-  const SWord8  s607 = table4[s606];
-  const SWord8  s608 = s605 ^ s607;
-  const SWord8  s609 = s602 ^ s608;
-  const SWord8  s610 = s600 ^ s609;
-  const SWord8  s611 = table4[s599];
-  const SWord8  s612 = table1[s601];
-  const SWord8  s613 = table2[s604];
-  const SWord8  s614 = table3[s606];
-  const SWord8  s615 = s613 ^ s614;
-  const SWord8  s616 = s612 ^ s615;
-  const SWord8  s617 = s611 ^ s616;
-  const SWord16 s618 = (((SWord16) s610) << 8) | ((SWord16) s617);
-  const SWord8  s619 = table3[s599];
-  const SWord8  s620 = table4[s601];
-  const SWord8  s621 = table1[s604];
-  const SWord8  s622 = table2[s606];
-  const SWord8  s623 = s621 ^ s622;
-  const SWord8  s624 = s620 ^ s623;
-  const SWord8  s625 = s619 ^ s624;
-  const SWord8  s626 = table2[s599];
-  const SWord8  s627 = table3[s601];
-  const SWord8  s628 = table4[s604];
-  const SWord8  s629 = table1[s606];
-  const SWord8  s630 = s628 ^ s629;
-  const SWord8  s631 = s627 ^ s630;
-  const SWord8  s632 = s626 ^ s631;
-  const SWord16 s633 = (((SWord16) s625) << 8) | ((SWord16) s632);
-  const SWord32 s634 = (((SWord32) s618) << 16) | ((SWord32) s633);
-  const SWord16 s635 = (SWord16) (s409 >> 16);
-  const SWord8  s636 = (SWord8) (s635 >> 8);
-  const SWord8  s637 = table1[s636];
-  const SWord8  s638 = (SWord8) s635;
-  const SWord8  s639 = table2[s638];
-  const SWord16 s640 = (SWord16) s409;
-  const SWord8  s641 = (SWord8) (s640 >> 8);
-  const SWord8  s642 = table3[s641];
-  const SWord8  s643 = (SWord8) s640;
-  const SWord8  s644 = table4[s643];
-  const SWord8  s645 = s642 ^ s644;
-  const SWord8  s646 = s639 ^ s645;
-  const SWord8  s647 = s637 ^ s646;
-  const SWord8  s648 = table4[s636];
-  const SWord8  s649 = table1[s638];
-  const SWord8  s650 = table2[s641];
-  const SWord8  s651 = table3[s643];
-  const SWord8  s652 = s650 ^ s651;
-  const SWord8  s653 = s649 ^ s652;
-  const SWord8  s654 = s648 ^ s653;
-  const SWord16 s655 = (((SWord16) s647) << 8) | ((SWord16) s654);
-  const SWord8  s656 = table3[s636];
-  const SWord8  s657 = table4[s638];
-  const SWord8  s658 = table1[s641];
-  const SWord8  s659 = table2[s643];
-  const SWord8  s660 = s658 ^ s659;
-  const SWord8  s661 = s657 ^ s660;
-  const SWord8  s662 = s656 ^ s661;
-  const SWord8  s663 = table2[s636];
-  const SWord8  s664 = table3[s638];
-  const SWord8  s665 = table4[s641];
-  const SWord8  s666 = table1[s643];
-  const SWord8  s667 = s665 ^ s666;
-  const SWord8  s668 = s664 ^ s667;
-  const SWord8  s669 = s663 ^ s668;
-  const SWord16 s670 = (((SWord16) s662) << 8) | ((SWord16) s669);
-  const SWord32 s671 = (((SWord32) s655) << 16) | ((SWord32) s670);
-  const SWord16 s672 = (SWord16) (s410 >> 16);
-  const SWord8  s673 = (SWord8) (s672 >> 8);
-  const SWord8  s674 = table1[s673];
-  const SWord8  s675 = (SWord8) s672;
-  const SWord8  s676 = table2[s675];
-  const SWord16 s677 = (SWord16) s410;
-  const SWord8  s678 = (SWord8) (s677 >> 8);
-  const SWord8  s679 = table3[s678];
-  const SWord8  s680 = (SWord8) s677;
-  const SWord8  s681 = table4[s680];
-  const SWord8  s682 = s679 ^ s681;
-  const SWord8  s683 = s676 ^ s682;
-  const SWord8  s684 = s674 ^ s683;
-  const SWord8  s685 = table4[s673];
-  const SWord8  s686 = table1[s675];
-  const SWord8  s687 = table2[s678];
-  const SWord8  s688 = table3[s680];
-  const SWord8  s689 = s687 ^ s688;
-  const SWord8  s690 = s686 ^ s689;
-  const SWord8  s691 = s685 ^ s690;
-  const SWord16 s692 = (((SWord16) s684) << 8) | ((SWord16) s691);
-  const SWord8  s693 = table3[s673];
-  const SWord8  s694 = table4[s675];
-  const SWord8  s695 = table1[s678];
-  const SWord8  s696 = table2[s680];
-  const SWord8  s697 = s695 ^ s696;
-  const SWord8  s698 = s694 ^ s697;
-  const SWord8  s699 = s693 ^ s698;
-  const SWord8  s700 = table2[s673];
-  const SWord8  s701 = table3[s675];
-  const SWord8  s702 = table4[s678];
-  const SWord8  s703 = table1[s680];
-  const SWord8  s704 = s702 ^ s703;
-  const SWord8  s705 = s701 ^ s704;
-  const SWord8  s706 = s700 ^ s705;
-  const SWord16 s707 = (((SWord16) s699) << 8) | ((SWord16) s706);
-  const SWord32 s708 = (((SWord32) s692) << 16) | ((SWord32) s707);
-  const SWord16 s709 = (SWord16) (s411 >> 16);
-  const SWord8  s710 = (SWord8) (s709 >> 8);
-  const SWord8  s711 = table1[s710];
-  const SWord8  s712 = (SWord8) s709;
-  const SWord8  s713 = table2[s712];
-  const SWord16 s714 = (SWord16) s411;
-  const SWord8  s715 = (SWord8) (s714 >> 8);
-  const SWord8  s716 = table3[s715];
-  const SWord8  s717 = (SWord8) s714;
-  const SWord8  s718 = table4[s717];
-  const SWord8  s719 = s716 ^ s718;
-  const SWord8  s720 = s713 ^ s719;
-  const SWord8  s721 = s711 ^ s720;
-  const SWord8  s722 = table4[s710];
-  const SWord8  s723 = table1[s712];
-  const SWord8  s724 = table2[s715];
-  const SWord8  s725 = table3[s717];
-  const SWord8  s726 = s724 ^ s725;
-  const SWord8  s727 = s723 ^ s726;
-  const SWord8  s728 = s722 ^ s727;
-  const SWord16 s729 = (((SWord16) s721) << 8) | ((SWord16) s728);
-  const SWord8  s730 = table3[s710];
-  const SWord8  s731 = table4[s712];
-  const SWord8  s732 = table1[s715];
-  const SWord8  s733 = table2[s717];
-  const SWord8  s734 = s732 ^ s733;
-  const SWord8  s735 = s731 ^ s734;
-  const SWord8  s736 = s730 ^ s735;
-  const SWord8  s737 = table2[s710];
-  const SWord8  s738 = table3[s712];
-  const SWord8  s739 = table4[s715];
-  const SWord8  s740 = table1[s717];
-  const SWord8  s741 = s739 ^ s740;
-  const SWord8  s742 = s738 ^ s741;
-  const SWord8  s743 = s737 ^ s742;
-  const SWord16 s744 = (((SWord16) s736) << 8) | ((SWord16) s743);
-  const SWord32 s745 = (((SWord32) s729) << 16) | ((SWord32) s744);
-  const SWord16 s746 = (SWord16) (s389 >> 16);
-  const SWord8  s747 = (SWord8) (s746 >> 8);
-  const SWord8  s748 = table1[s747];
-  const SWord8  s749 = (SWord8) s746;
-  const SWord8  s750 = table2[s749];
-  const SWord16 s751 = (SWord16) s389;
-  const SWord8  s752 = (SWord8) (s751 >> 8);
-  const SWord8  s753 = table3[s752];
-  const SWord8  s754 = (SWord8) s751;
-  const SWord8  s755 = table4[s754];
-  const SWord8  s756 = s753 ^ s755;
-  const SWord8  s757 = s750 ^ s756;
-  const SWord8  s758 = s748 ^ s757;
-  const SWord8  s759 = table4[s747];
-  const SWord8  s760 = table1[s749];
-  const SWord8  s761 = table2[s752];
-  const SWord8  s762 = table3[s754];
-  const SWord8  s763 = s761 ^ s762;
-  const SWord8  s764 = s760 ^ s763;
-  const SWord8  s765 = s759 ^ s764;
-  const SWord16 s766 = (((SWord16) s758) << 8) | ((SWord16) s765);
-  const SWord8  s767 = table3[s747];
-  const SWord8  s768 = table4[s749];
-  const SWord8  s769 = table1[s752];
-  const SWord8  s770 = table2[s754];
-  const SWord8  s771 = s769 ^ s770;
-  const SWord8  s772 = s768 ^ s771;
-  const SWord8  s773 = s767 ^ s772;
-  const SWord8  s774 = table2[s747];
-  const SWord8  s775 = table3[s749];
-  const SWord8  s776 = table4[s752];
-  const SWord8  s777 = table1[s754];
-  const SWord8  s778 = s776 ^ s777;
-  const SWord8  s779 = s775 ^ s778;
-  const SWord8  s780 = s774 ^ s779;
-  const SWord16 s781 = (((SWord16) s773) << 8) | ((SWord16) s780);
-  const SWord32 s782 = (((SWord32) s766) << 16) | ((SWord32) s781);
-  const SWord16 s783 = (SWord16) (s390 >> 16);
-  const SWord8  s784 = (SWord8) (s783 >> 8);
-  const SWord8  s785 = table1[s784];
-  const SWord8  s786 = (SWord8) s783;
-  const SWord8  s787 = table2[s786];
-  const SWord16 s788 = (SWord16) s390;
-  const SWord8  s789 = (SWord8) (s788 >> 8);
-  const SWord8  s790 = table3[s789];
-  const SWord8  s791 = (SWord8) s788;
-  const SWord8  s792 = table4[s791];
-  const SWord8  s793 = s790 ^ s792;
-  const SWord8  s794 = s787 ^ s793;
-  const SWord8  s795 = s785 ^ s794;
-  const SWord8  s796 = table4[s784];
-  const SWord8  s797 = table1[s786];
-  const SWord8  s798 = table2[s789];
-  const SWord8  s799 = table3[s791];
-  const SWord8  s800 = s798 ^ s799;
-  const SWord8  s801 = s797 ^ s800;
-  const SWord8  s802 = s796 ^ s801;
-  const SWord16 s803 = (((SWord16) s795) << 8) | ((SWord16) s802);
-  const SWord8  s804 = table3[s784];
-  const SWord8  s805 = table4[s786];
-  const SWord8  s806 = table1[s789];
-  const SWord8  s807 = table2[s791];
-  const SWord8  s808 = s806 ^ s807;
-  const SWord8  s809 = s805 ^ s808;
-  const SWord8  s810 = s804 ^ s809;
-  const SWord8  s811 = table2[s784];
-  const SWord8  s812 = table3[s786];
-  const SWord8  s813 = table4[s789];
-  const SWord8  s814 = table1[s791];
-  const SWord8  s815 = s813 ^ s814;
-  const SWord8  s816 = s812 ^ s815;
-  const SWord8  s817 = s811 ^ s816;
-  const SWord16 s818 = (((SWord16) s810) << 8) | ((SWord16) s817);
-  const SWord32 s819 = (((SWord32) s803) << 16) | ((SWord32) s818);
-  const SWord16 s820 = (SWord16) (s391 >> 16);
-  const SWord8  s821 = (SWord8) (s820 >> 8);
-  const SWord8  s822 = table1[s821];
-  const SWord8  s823 = (SWord8) s820;
-  const SWord8  s824 = table2[s823];
-  const SWord16 s825 = (SWord16) s391;
-  const SWord8  s826 = (SWord8) (s825 >> 8);
-  const SWord8  s827 = table3[s826];
-  const SWord8  s828 = (SWord8) s825;
-  const SWord8  s829 = table4[s828];
-  const SWord8  s830 = s827 ^ s829;
-  const SWord8  s831 = s824 ^ s830;
-  const SWord8  s832 = s822 ^ s831;
-  const SWord8  s833 = table4[s821];
-  const SWord8  s834 = table1[s823];
-  const SWord8  s835 = table2[s826];
-  const SWord8  s836 = table3[s828];
-  const SWord8  s837 = s835 ^ s836;
-  const SWord8  s838 = s834 ^ s837;
-  const SWord8  s839 = s833 ^ s838;
-  const SWord16 s840 = (((SWord16) s832) << 8) | ((SWord16) s839);
-  const SWord8  s841 = table3[s821];
-  const SWord8  s842 = table4[s823];
-  const SWord8  s843 = table1[s826];
-  const SWord8  s844 = table2[s828];
-  const SWord8  s845 = s843 ^ s844;
-  const SWord8  s846 = s842 ^ s845;
-  const SWord8  s847 = s841 ^ s846;
-  const SWord8  s848 = table2[s821];
-  const SWord8  s849 = table3[s823];
-  const SWord8  s850 = table4[s826];
-  const SWord8  s851 = table1[s828];
-  const SWord8  s852 = s850 ^ s851;
-  const SWord8  s853 = s849 ^ s852;
-  const SWord8  s854 = s848 ^ s853;
-  const SWord16 s855 = (((SWord16) s847) << 8) | ((SWord16) s854);
-  const SWord32 s856 = (((SWord32) s840) << 16) | ((SWord32) s855);
-  const SWord16 s857 = (SWord16) (s392 >> 16);
-  const SWord8  s858 = (SWord8) (s857 >> 8);
-  const SWord8  s859 = table1[s858];
-  const SWord8  s860 = (SWord8) s857;
-  const SWord8  s861 = table2[s860];
-  const SWord16 s862 = (SWord16) s392;
-  const SWord8  s863 = (SWord8) (s862 >> 8);
-  const SWord8  s864 = table3[s863];
-  const SWord8  s865 = (SWord8) s862;
-  const SWord8  s866 = table4[s865];
-  const SWord8  s867 = s864 ^ s866;
-  const SWord8  s868 = s861 ^ s867;
-  const SWord8  s869 = s859 ^ s868;
-  const SWord8  s870 = table4[s858];
-  const SWord8  s871 = table1[s860];
-  const SWord8  s872 = table2[s863];
-  const SWord8  s873 = table3[s865];
-  const SWord8  s874 = s872 ^ s873;
-  const SWord8  s875 = s871 ^ s874;
-  const SWord8  s876 = s870 ^ s875;
-  const SWord16 s877 = (((SWord16) s869) << 8) | ((SWord16) s876);
-  const SWord8  s878 = table3[s858];
-  const SWord8  s879 = table4[s860];
-  const SWord8  s880 = table1[s863];
-  const SWord8  s881 = table2[s865];
-  const SWord8  s882 = s880 ^ s881;
-  const SWord8  s883 = s879 ^ s882;
-  const SWord8  s884 = s878 ^ s883;
-  const SWord8  s885 = table2[s858];
-  const SWord8  s886 = table3[s860];
-  const SWord8  s887 = table4[s863];
-  const SWord8  s888 = table1[s865];
-  const SWord8  s889 = s887 ^ s888;
-  const SWord8  s890 = s886 ^ s889;
-  const SWord8  s891 = s885 ^ s890;
-  const SWord16 s892 = (((SWord16) s884) << 8) | ((SWord16) s891);
-  const SWord32 s893 = (((SWord32) s877) << 16) | ((SWord32) s892);
-  const SWord16 s894 = (SWord16) (s370 >> 16);
-  const SWord8  s895 = (SWord8) (s894 >> 8);
-  const SWord8  s896 = table1[s895];
-  const SWord8  s897 = (SWord8) s894;
-  const SWord8  s898 = table2[s897];
-  const SWord16 s899 = (SWord16) s370;
-  const SWord8  s900 = (SWord8) (s899 >> 8);
-  const SWord8  s901 = table3[s900];
-  const SWord8  s902 = (SWord8) s899;
-  const SWord8  s903 = table4[s902];
-  const SWord8  s904 = s901 ^ s903;
-  const SWord8  s905 = s898 ^ s904;
-  const SWord8  s906 = s896 ^ s905;
-  const SWord8  s907 = table4[s895];
-  const SWord8  s908 = table1[s897];
-  const SWord8  s909 = table2[s900];
-  const SWord8  s910 = table3[s902];
-  const SWord8  s911 = s909 ^ s910;
-  const SWord8  s912 = s908 ^ s911;
-  const SWord8  s913 = s907 ^ s912;
-  const SWord16 s914 = (((SWord16) s906) << 8) | ((SWord16) s913);
-  const SWord8  s915 = table3[s895];
-  const SWord8  s916 = table4[s897];
-  const SWord8  s917 = table1[s900];
-  const SWord8  s918 = table2[s902];
-  const SWord8  s919 = s917 ^ s918;
-  const SWord8  s920 = s916 ^ s919;
-  const SWord8  s921 = s915 ^ s920;
-  const SWord8  s922 = table2[s895];
-  const SWord8  s923 = table3[s897];
-  const SWord8  s924 = table4[s900];
-  const SWord8  s925 = table1[s902];
-  const SWord8  s926 = s924 ^ s925;
-  const SWord8  s927 = s923 ^ s926;
-  const SWord8  s928 = s922 ^ s927;
-  const SWord16 s929 = (((SWord16) s921) << 8) | ((SWord16) s928);
-  const SWord32 s930 = (((SWord32) s914) << 16) | ((SWord32) s929);
-  const SWord16 s931 = (SWord16) (s371 >> 16);
-  const SWord8  s932 = (SWord8) (s931 >> 8);
-  const SWord8  s933 = table1[s932];
-  const SWord8  s934 = (SWord8) s931;
-  const SWord8  s935 = table2[s934];
-  const SWord16 s936 = (SWord16) s371;
-  const SWord8  s937 = (SWord8) (s936 >> 8);
-  const SWord8  s938 = table3[s937];
-  const SWord8  s939 = (SWord8) s936;
-  const SWord8  s940 = table4[s939];
-  const SWord8  s941 = s938 ^ s940;
-  const SWord8  s942 = s935 ^ s941;
-  const SWord8  s943 = s933 ^ s942;
-  const SWord8  s944 = table4[s932];
-  const SWord8  s945 = table1[s934];
-  const SWord8  s946 = table2[s937];
-  const SWord8  s947 = table3[s939];
-  const SWord8  s948 = s946 ^ s947;
-  const SWord8  s949 = s945 ^ s948;
-  const SWord8  s950 = s944 ^ s949;
-  const SWord16 s951 = (((SWord16) s943) << 8) | ((SWord16) s950);
-  const SWord8  s952 = table3[s932];
-  const SWord8  s953 = table4[s934];
-  const SWord8  s954 = table1[s937];
-  const SWord8  s955 = table2[s939];
-  const SWord8  s956 = s954 ^ s955;
-  const SWord8  s957 = s953 ^ s956;
-  const SWord8  s958 = s952 ^ s957;
-  const SWord8  s959 = table2[s932];
-  const SWord8  s960 = table3[s934];
-  const SWord8  s961 = table4[s937];
-  const SWord8  s962 = table1[s939];
-  const SWord8  s963 = s961 ^ s962;
-  const SWord8  s964 = s960 ^ s963;
-  const SWord8  s965 = s959 ^ s964;
-  const SWord16 s966 = (((SWord16) s958) << 8) | ((SWord16) s965);
-  const SWord32 s967 = (((SWord32) s951) << 16) | ((SWord32) s966);
-  const SWord16 s968 = (SWord16) (s372 >> 16);
-  const SWord8  s969 = (SWord8) (s968 >> 8);
-  const SWord8  s970 = table1[s969];
-  const SWord8  s971 = (SWord8) s968;
-  const SWord8  s972 = table2[s971];
-  const SWord16 s973 = (SWord16) s372;
-  const SWord8  s974 = (SWord8) (s973 >> 8);
-  const SWord8  s975 = table3[s974];
-  const SWord8  s976 = (SWord8) s973;
-  const SWord8  s977 = table4[s976];
-  const SWord8  s978 = s975 ^ s977;
-  const SWord8  s979 = s972 ^ s978;
-  const SWord8  s980 = s970 ^ s979;
-  const SWord8  s981 = table4[s969];
-  const SWord8  s982 = table1[s971];
-  const SWord8  s983 = table2[s974];
-  const SWord8  s984 = table3[s976];
-  const SWord8  s985 = s983 ^ s984;
-  const SWord8  s986 = s982 ^ s985;
-  const SWord8  s987 = s981 ^ s986;
-  const SWord16 s988 = (((SWord16) s980) << 8) | ((SWord16) s987);
-  const SWord8  s989 = table3[s969];
-  const SWord8  s990 = table4[s971];
-  const SWord8  s991 = table1[s974];
-  const SWord8  s992 = table2[s976];
-  const SWord8  s993 = s991 ^ s992;
-  const SWord8  s994 = s990 ^ s993;
-  const SWord8  s995 = s989 ^ s994;
-  const SWord8  s996 = table2[s969];
-  const SWord8  s997 = table3[s971];
-  const SWord8  s998 = table4[s974];
-  const SWord8  s999 = table1[s976];
-  const SWord8  s1000 = s998 ^ s999;
-  const SWord8  s1001 = s997 ^ s1000;
-  const SWord8  s1002 = s996 ^ s1001;
-  const SWord16 s1003 = (((SWord16) s995) << 8) | ((SWord16) s1002);
-  const SWord32 s1004 = (((SWord32) s988) << 16) | ((SWord32) s1003);
-  const SWord16 s1005 = (SWord16) (s373 >> 16);
-  const SWord8  s1006 = (SWord8) (s1005 >> 8);
-  const SWord8  s1007 = table1[s1006];
-  const SWord8  s1008 = (SWord8) s1005;
-  const SWord8  s1009 = table2[s1008];
-  const SWord16 s1010 = (SWord16) s373;
-  const SWord8  s1011 = (SWord8) (s1010 >> 8);
-  const SWord8  s1012 = table3[s1011];
-  const SWord8  s1013 = (SWord8) s1010;
-  const SWord8  s1014 = table4[s1013];
-  const SWord8  s1015 = s1012 ^ s1014;
-  const SWord8  s1016 = s1009 ^ s1015;
-  const SWord8  s1017 = s1007 ^ s1016;
-  const SWord8  s1018 = table4[s1006];
-  const SWord8  s1019 = table1[s1008];
-  const SWord8  s1020 = table2[s1011];
-  const SWord8  s1021 = table3[s1013];
-  const SWord8  s1022 = s1020 ^ s1021;
-  const SWord8  s1023 = s1019 ^ s1022;
-  const SWord8  s1024 = s1018 ^ s1023;
-  const SWord16 s1025 = (((SWord16) s1017) << 8) | ((SWord16) s1024);
-  const SWord8  s1026 = table3[s1006];
-  const SWord8  s1027 = table4[s1008];
-  const SWord8  s1028 = table1[s1011];
-  const SWord8  s1029 = table2[s1013];
-  const SWord8  s1030 = s1028 ^ s1029;
-  const SWord8  s1031 = s1027 ^ s1030;
-  const SWord8  s1032 = s1026 ^ s1031;
-  const SWord8  s1033 = table2[s1006];
-  const SWord8  s1034 = table3[s1008];
-  const SWord8  s1035 = table4[s1011];
-  const SWord8  s1036 = table1[s1013];
-  const SWord8  s1037 = s1035 ^ s1036;
-  const SWord8  s1038 = s1034 ^ s1037;
-  const SWord8  s1039 = s1033 ^ s1038;
-  const SWord16 s1040 = (((SWord16) s1032) << 8) | ((SWord16) s1039);
-  const SWord32 s1041 = (((SWord32) s1025) << 16) | ((SWord32) s1040);
-  const SWord16 s1042 = (SWord16) (s351 >> 16);
-  const SWord8  s1043 = (SWord8) (s1042 >> 8);
-  const SWord8  s1044 = table1[s1043];
-  const SWord8  s1045 = (SWord8) s1042;
-  const SWord8  s1046 = table2[s1045];
-  const SWord16 s1047 = (SWord16) s351;
-  const SWord8  s1048 = (SWord8) (s1047 >> 8);
-  const SWord8  s1049 = table3[s1048];
-  const SWord8  s1050 = (SWord8) s1047;
-  const SWord8  s1051 = table4[s1050];
-  const SWord8  s1052 = s1049 ^ s1051;
-  const SWord8  s1053 = s1046 ^ s1052;
-  const SWord8  s1054 = s1044 ^ s1053;
-  const SWord8  s1055 = table4[s1043];
-  const SWord8  s1056 = table1[s1045];
-  const SWord8  s1057 = table2[s1048];
-  const SWord8  s1058 = table3[s1050];
-  const SWord8  s1059 = s1057 ^ s1058;
-  const SWord8  s1060 = s1056 ^ s1059;
-  const SWord8  s1061 = s1055 ^ s1060;
-  const SWord16 s1062 = (((SWord16) s1054) << 8) | ((SWord16) s1061);
-  const SWord8  s1063 = table3[s1043];
-  const SWord8  s1064 = table4[s1045];
-  const SWord8  s1065 = table1[s1048];
-  const SWord8  s1066 = table2[s1050];
-  const SWord8  s1067 = s1065 ^ s1066;
-  const SWord8  s1068 = s1064 ^ s1067;
-  const SWord8  s1069 = s1063 ^ s1068;
-  const SWord8  s1070 = table2[s1043];
-  const SWord8  s1071 = table3[s1045];
-  const SWord8  s1072 = table4[s1048];
-  const SWord8  s1073 = table1[s1050];
-  const SWord8  s1074 = s1072 ^ s1073;
-  const SWord8  s1075 = s1071 ^ s1074;
-  const SWord8  s1076 = s1070 ^ s1075;
-  const SWord16 s1077 = (((SWord16) s1069) << 8) | ((SWord16) s1076);
-  const SWord32 s1078 = (((SWord32) s1062) << 16) | ((SWord32) s1077);
-  const SWord16 s1079 = (SWord16) (s352 >> 16);
-  const SWord8  s1080 = (SWord8) (s1079 >> 8);
-  const SWord8  s1081 = table1[s1080];
-  const SWord8  s1082 = (SWord8) s1079;
-  const SWord8  s1083 = table2[s1082];
-  const SWord16 s1084 = (SWord16) s352;
-  const SWord8  s1085 = (SWord8) (s1084 >> 8);
-  const SWord8  s1086 = table3[s1085];
-  const SWord8  s1087 = (SWord8) s1084;
-  const SWord8  s1088 = table4[s1087];
-  const SWord8  s1089 = s1086 ^ s1088;
-  const SWord8  s1090 = s1083 ^ s1089;
-  const SWord8  s1091 = s1081 ^ s1090;
-  const SWord8  s1092 = table4[s1080];
-  const SWord8  s1093 = table1[s1082];
-  const SWord8  s1094 = table2[s1085];
-  const SWord8  s1095 = table3[s1087];
-  const SWord8  s1096 = s1094 ^ s1095;
-  const SWord8  s1097 = s1093 ^ s1096;
-  const SWord8  s1098 = s1092 ^ s1097;
-  const SWord16 s1099 = (((SWord16) s1091) << 8) | ((SWord16) s1098);
-  const SWord8  s1100 = table3[s1080];
-  const SWord8  s1101 = table4[s1082];
-  const SWord8  s1102 = table1[s1085];
-  const SWord8  s1103 = table2[s1087];
-  const SWord8  s1104 = s1102 ^ s1103;
-  const SWord8  s1105 = s1101 ^ s1104;
-  const SWord8  s1106 = s1100 ^ s1105;
-  const SWord8  s1107 = table2[s1080];
-  const SWord8  s1108 = table3[s1082];
-  const SWord8  s1109 = table4[s1085];
-  const SWord8  s1110 = table1[s1087];
-  const SWord8  s1111 = s1109 ^ s1110;
-  const SWord8  s1112 = s1108 ^ s1111;
-  const SWord8  s1113 = s1107 ^ s1112;
-  const SWord16 s1114 = (((SWord16) s1106) << 8) | ((SWord16) s1113);
-  const SWord32 s1115 = (((SWord32) s1099) << 16) | ((SWord32) s1114);
-  const SWord16 s1116 = (SWord16) (s353 >> 16);
-  const SWord8  s1117 = (SWord8) (s1116 >> 8);
-  const SWord8  s1118 = table1[s1117];
-  const SWord8  s1119 = (SWord8) s1116;
-  const SWord8  s1120 = table2[s1119];
-  const SWord16 s1121 = (SWord16) s353;
-  const SWord8  s1122 = (SWord8) (s1121 >> 8);
-  const SWord8  s1123 = table3[s1122];
-  const SWord8  s1124 = (SWord8) s1121;
-  const SWord8  s1125 = table4[s1124];
-  const SWord8  s1126 = s1123 ^ s1125;
-  const SWord8  s1127 = s1120 ^ s1126;
-  const SWord8  s1128 = s1118 ^ s1127;
-  const SWord8  s1129 = table4[s1117];
-  const SWord8  s1130 = table1[s1119];
-  const SWord8  s1131 = table2[s1122];
-  const SWord8  s1132 = table3[s1124];
-  const SWord8  s1133 = s1131 ^ s1132;
-  const SWord8  s1134 = s1130 ^ s1133;
-  const SWord8  s1135 = s1129 ^ s1134;
-  const SWord16 s1136 = (((SWord16) s1128) << 8) | ((SWord16) s1135);
-  const SWord8  s1137 = table3[s1117];
-  const SWord8  s1138 = table4[s1119];
-  const SWord8  s1139 = table1[s1122];
-  const SWord8  s1140 = table2[s1124];
-  const SWord8  s1141 = s1139 ^ s1140;
-  const SWord8  s1142 = s1138 ^ s1141;
-  const SWord8  s1143 = s1137 ^ s1142;
-  const SWord8  s1144 = table2[s1117];
-  const SWord8  s1145 = table3[s1119];
-  const SWord8  s1146 = table4[s1122];
-  const SWord8  s1147 = table1[s1124];
-  const SWord8  s1148 = s1146 ^ s1147;
-  const SWord8  s1149 = s1145 ^ s1148;
-  const SWord8  s1150 = s1144 ^ s1149;
-  const SWord16 s1151 = (((SWord16) s1143) << 8) | ((SWord16) s1150);
-  const SWord32 s1152 = (((SWord32) s1136) << 16) | ((SWord32) s1151);
-  const SWord16 s1153 = (SWord16) (s354 >> 16);
-  const SWord8  s1154 = (SWord8) (s1153 >> 8);
-  const SWord8  s1155 = table1[s1154];
-  const SWord8  s1156 = (SWord8) s1153;
-  const SWord8  s1157 = table2[s1156];
-  const SWord16 s1158 = (SWord16) s354;
-  const SWord8  s1159 = (SWord8) (s1158 >> 8);
-  const SWord8  s1160 = table3[s1159];
-  const SWord8  s1161 = (SWord8) s1158;
-  const SWord8  s1162 = table4[s1161];
-  const SWord8  s1163 = s1160 ^ s1162;
-  const SWord8  s1164 = s1157 ^ s1163;
-  const SWord8  s1165 = s1155 ^ s1164;
-  const SWord8  s1166 = table4[s1154];
-  const SWord8  s1167 = table1[s1156];
-  const SWord8  s1168 = table2[s1159];
-  const SWord8  s1169 = table3[s1161];
-  const SWord8  s1170 = s1168 ^ s1169;
-  const SWord8  s1171 = s1167 ^ s1170;
-  const SWord8  s1172 = s1166 ^ s1171;
-  const SWord16 s1173 = (((SWord16) s1165) << 8) | ((SWord16) s1172);
-  const SWord8  s1174 = table3[s1154];
-  const SWord8  s1175 = table4[s1156];
-  const SWord8  s1176 = table1[s1159];
-  const SWord8  s1177 = table2[s1161];
-  const SWord8  s1178 = s1176 ^ s1177;
-  const SWord8  s1179 = s1175 ^ s1178;
-  const SWord8  s1180 = s1174 ^ s1179;
-  const SWord8  s1181 = table2[s1154];
-  const SWord8  s1182 = table3[s1156];
-  const SWord8  s1183 = table4[s1159];
-  const SWord8  s1184 = table1[s1161];
-  const SWord8  s1185 = s1183 ^ s1184;
-  const SWord8  s1186 = s1182 ^ s1185;
-  const SWord8  s1187 = s1181 ^ s1186;
-  const SWord16 s1188 = (((SWord16) s1180) << 8) | ((SWord16) s1187);
-  const SWord32 s1189 = (((SWord32) s1173) << 16) | ((SWord32) s1188);
-  const SWord16 s1190 = (SWord16) (s332 >> 16);
-  const SWord8  s1191 = (SWord8) (s1190 >> 8);
-  const SWord8  s1192 = table1[s1191];
-  const SWord8  s1193 = (SWord8) s1190;
-  const SWord8  s1194 = table2[s1193];
-  const SWord16 s1195 = (SWord16) s332;
-  const SWord8  s1196 = (SWord8) (s1195 >> 8);
-  const SWord8  s1197 = table3[s1196];
-  const SWord8  s1198 = (SWord8) s1195;
-  const SWord8  s1199 = table4[s1198];
-  const SWord8  s1200 = s1197 ^ s1199;
-  const SWord8  s1201 = s1194 ^ s1200;
-  const SWord8  s1202 = s1192 ^ s1201;
-  const SWord8  s1203 = table4[s1191];
-  const SWord8  s1204 = table1[s1193];
-  const SWord8  s1205 = table2[s1196];
-  const SWord8  s1206 = table3[s1198];
-  const SWord8  s1207 = s1205 ^ s1206;
-  const SWord8  s1208 = s1204 ^ s1207;
-  const SWord8  s1209 = s1203 ^ s1208;
-  const SWord16 s1210 = (((SWord16) s1202) << 8) | ((SWord16) s1209);
-  const SWord8  s1211 = table3[s1191];
-  const SWord8  s1212 = table4[s1193];
-  const SWord8  s1213 = table1[s1196];
-  const SWord8  s1214 = table2[s1198];
-  const SWord8  s1215 = s1213 ^ s1214;
-  const SWord8  s1216 = s1212 ^ s1215;
-  const SWord8  s1217 = s1211 ^ s1216;
-  const SWord8  s1218 = table2[s1191];
-  const SWord8  s1219 = table3[s1193];
-  const SWord8  s1220 = table4[s1196];
-  const SWord8  s1221 = table1[s1198];
-  const SWord8  s1222 = s1220 ^ s1221;
-  const SWord8  s1223 = s1219 ^ s1222;
-  const SWord8  s1224 = s1218 ^ s1223;
-  const SWord16 s1225 = (((SWord16) s1217) << 8) | ((SWord16) s1224);
-  const SWord32 s1226 = (((SWord32) s1210) << 16) | ((SWord32) s1225);
-  const SWord16 s1227 = (SWord16) (s333 >> 16);
-  const SWord8  s1228 = (SWord8) (s1227 >> 8);
-  const SWord8  s1229 = table1[s1228];
-  const SWord8  s1230 = (SWord8) s1227;
-  const SWord8  s1231 = table2[s1230];
-  const SWord16 s1232 = (SWord16) s333;
-  const SWord8  s1233 = (SWord8) (s1232 >> 8);
-  const SWord8  s1234 = table3[s1233];
-  const SWord8  s1235 = (SWord8) s1232;
-  const SWord8  s1236 = table4[s1235];
-  const SWord8  s1237 = s1234 ^ s1236;
-  const SWord8  s1238 = s1231 ^ s1237;
-  const SWord8  s1239 = s1229 ^ s1238;
-  const SWord8  s1240 = table4[s1228];
-  const SWord8  s1241 = table1[s1230];
-  const SWord8  s1242 = table2[s1233];
-  const SWord8  s1243 = table3[s1235];
-  const SWord8  s1244 = s1242 ^ s1243;
-  const SWord8  s1245 = s1241 ^ s1244;
-  const SWord8  s1246 = s1240 ^ s1245;
-  const SWord16 s1247 = (((SWord16) s1239) << 8) | ((SWord16) s1246);
-  const SWord8  s1248 = table3[s1228];
-  const SWord8  s1249 = table4[s1230];
-  const SWord8  s1250 = table1[s1233];
-  const SWord8  s1251 = table2[s1235];
-  const SWord8  s1252 = s1250 ^ s1251;
-  const SWord8  s1253 = s1249 ^ s1252;
-  const SWord8  s1254 = s1248 ^ s1253;
-  const SWord8  s1255 = table2[s1228];
-  const SWord8  s1256 = table3[s1230];
-  const SWord8  s1257 = table4[s1233];
-  const SWord8  s1258 = table1[s1235];
-  const SWord8  s1259 = s1257 ^ s1258;
-  const SWord8  s1260 = s1256 ^ s1259;
-  const SWord8  s1261 = s1255 ^ s1260;
-  const SWord16 s1262 = (((SWord16) s1254) << 8) | ((SWord16) s1261);
-  const SWord32 s1263 = (((SWord32) s1247) << 16) | ((SWord32) s1262);
-  const SWord16 s1264 = (SWord16) (s334 >> 16);
-  const SWord8  s1265 = (SWord8) (s1264 >> 8);
-  const SWord8  s1266 = table1[s1265];
-  const SWord8  s1267 = (SWord8) s1264;
-  const SWord8  s1268 = table2[s1267];
-  const SWord16 s1269 = (SWord16) s334;
-  const SWord8  s1270 = (SWord8) (s1269 >> 8);
-  const SWord8  s1271 = table3[s1270];
-  const SWord8  s1272 = (SWord8) s1269;
-  const SWord8  s1273 = table4[s1272];
-  const SWord8  s1274 = s1271 ^ s1273;
-  const SWord8  s1275 = s1268 ^ s1274;
-  const SWord8  s1276 = s1266 ^ s1275;
-  const SWord8  s1277 = table4[s1265];
-  const SWord8  s1278 = table1[s1267];
-  const SWord8  s1279 = table2[s1270];
-  const SWord8  s1280 = table3[s1272];
-  const SWord8  s1281 = s1279 ^ s1280;
-  const SWord8  s1282 = s1278 ^ s1281;
-  const SWord8  s1283 = s1277 ^ s1282;
-  const SWord16 s1284 = (((SWord16) s1276) << 8) | ((SWord16) s1283);
-  const SWord8  s1285 = table3[s1265];
-  const SWord8  s1286 = table4[s1267];
-  const SWord8  s1287 = table1[s1270];
-  const SWord8  s1288 = table2[s1272];
-  const SWord8  s1289 = s1287 ^ s1288;
-  const SWord8  s1290 = s1286 ^ s1289;
-  const SWord8  s1291 = s1285 ^ s1290;
-  const SWord8  s1292 = table2[s1265];
-  const SWord8  s1293 = table3[s1267];
-  const SWord8  s1294 = table4[s1270];
-  const SWord8  s1295 = table1[s1272];
-  const SWord8  s1296 = s1294 ^ s1295;
-  const SWord8  s1297 = s1293 ^ s1296;
-  const SWord8  s1298 = s1292 ^ s1297;
-  const SWord16 s1299 = (((SWord16) s1291) << 8) | ((SWord16) s1298);
-  const SWord32 s1300 = (((SWord32) s1284) << 16) | ((SWord32) s1299);
-  const SWord16 s1301 = (SWord16) (s335 >> 16);
-  const SWord8  s1302 = (SWord8) (s1301 >> 8);
-  const SWord8  s1303 = table1[s1302];
-  const SWord8  s1304 = (SWord8) s1301;
-  const SWord8  s1305 = table2[s1304];
-  const SWord16 s1306 = (SWord16) s335;
-  const SWord8  s1307 = (SWord8) (s1306 >> 8);
-  const SWord8  s1308 = table3[s1307];
-  const SWord8  s1309 = (SWord8) s1306;
-  const SWord8  s1310 = table4[s1309];
-  const SWord8  s1311 = s1308 ^ s1310;
-  const SWord8  s1312 = s1305 ^ s1311;
-  const SWord8  s1313 = s1303 ^ s1312;
-  const SWord8  s1314 = table4[s1302];
-  const SWord8  s1315 = table1[s1304];
-  const SWord8  s1316 = table2[s1307];
-  const SWord8  s1317 = table3[s1309];
-  const SWord8  s1318 = s1316 ^ s1317;
-  const SWord8  s1319 = s1315 ^ s1318;
-  const SWord8  s1320 = s1314 ^ s1319;
-  const SWord16 s1321 = (((SWord16) s1313) << 8) | ((SWord16) s1320);
-  const SWord8  s1322 = table3[s1302];
-  const SWord8  s1323 = table4[s1304];
-  const SWord8  s1324 = table1[s1307];
-  const SWord8  s1325 = table2[s1309];
-  const SWord8  s1326 = s1324 ^ s1325;
-  const SWord8  s1327 = s1323 ^ s1326;
-  const SWord8  s1328 = s1322 ^ s1327;
-  const SWord8  s1329 = table2[s1302];
-  const SWord8  s1330 = table3[s1304];
-  const SWord8  s1331 = table4[s1307];
-  const SWord8  s1332 = table1[s1309];
-  const SWord8  s1333 = s1331 ^ s1332;
-  const SWord8  s1334 = s1330 ^ s1333;
-  const SWord8  s1335 = s1329 ^ s1334;
-  const SWord16 s1336 = (((SWord16) s1328) << 8) | ((SWord16) s1335);
-  const SWord32 s1337 = (((SWord32) s1321) << 16) | ((SWord32) s1336);
-  const SWord16 s1338 = (SWord16) (s313 >> 16);
-  const SWord8  s1339 = (SWord8) (s1338 >> 8);
-  const SWord8  s1340 = table1[s1339];
-  const SWord8  s1341 = (SWord8) s1338;
-  const SWord8  s1342 = table2[s1341];
-  const SWord16 s1343 = (SWord16) s313;
-  const SWord8  s1344 = (SWord8) (s1343 >> 8);
-  const SWord8  s1345 = table3[s1344];
-  const SWord8  s1346 = (SWord8) s1343;
-  const SWord8  s1347 = table4[s1346];
-  const SWord8  s1348 = s1345 ^ s1347;
-  const SWord8  s1349 = s1342 ^ s1348;
-  const SWord8  s1350 = s1340 ^ s1349;
-  const SWord8  s1351 = table4[s1339];
-  const SWord8  s1352 = table1[s1341];
-  const SWord8  s1353 = table2[s1344];
-  const SWord8  s1354 = table3[s1346];
-  const SWord8  s1355 = s1353 ^ s1354;
-  const SWord8  s1356 = s1352 ^ s1355;
-  const SWord8  s1357 = s1351 ^ s1356;
-  const SWord16 s1358 = (((SWord16) s1350) << 8) | ((SWord16) s1357);
-  const SWord8  s1359 = table3[s1339];
-  const SWord8  s1360 = table4[s1341];
-  const SWord8  s1361 = table1[s1344];
-  const SWord8  s1362 = table2[s1346];
-  const SWord8  s1363 = s1361 ^ s1362;
-  const SWord8  s1364 = s1360 ^ s1363;
-  const SWord8  s1365 = s1359 ^ s1364;
-  const SWord8  s1366 = table2[s1339];
-  const SWord8  s1367 = table3[s1341];
-  const SWord8  s1368 = table4[s1344];
-  const SWord8  s1369 = table1[s1346];
-  const SWord8  s1370 = s1368 ^ s1369;
-  const SWord8  s1371 = s1367 ^ s1370;
-  const SWord8  s1372 = s1366 ^ s1371;
-  const SWord16 s1373 = (((SWord16) s1365) << 8) | ((SWord16) s1372);
-  const SWord32 s1374 = (((SWord32) s1358) << 16) | ((SWord32) s1373);
-  const SWord16 s1375 = (SWord16) (s314 >> 16);
-  const SWord8  s1376 = (SWord8) (s1375 >> 8);
-  const SWord8  s1377 = table1[s1376];
-  const SWord8  s1378 = (SWord8) s1375;
-  const SWord8  s1379 = table2[s1378];
-  const SWord16 s1380 = (SWord16) s314;
-  const SWord8  s1381 = (SWord8) (s1380 >> 8);
-  const SWord8  s1382 = table3[s1381];
-  const SWord8  s1383 = (SWord8) s1380;
-  const SWord8  s1384 = table4[s1383];
-  const SWord8  s1385 = s1382 ^ s1384;
-  const SWord8  s1386 = s1379 ^ s1385;
-  const SWord8  s1387 = s1377 ^ s1386;
-  const SWord8  s1388 = table4[s1376];
-  const SWord8  s1389 = table1[s1378];
-  const SWord8  s1390 = table2[s1381];
-  const SWord8  s1391 = table3[s1383];
-  const SWord8  s1392 = s1390 ^ s1391;
-  const SWord8  s1393 = s1389 ^ s1392;
-  const SWord8  s1394 = s1388 ^ s1393;
-  const SWord16 s1395 = (((SWord16) s1387) << 8) | ((SWord16) s1394);
-  const SWord8  s1396 = table3[s1376];
-  const SWord8  s1397 = table4[s1378];
-  const SWord8  s1398 = table1[s1381];
-  const SWord8  s1399 = table2[s1383];
-  const SWord8  s1400 = s1398 ^ s1399;
-  const SWord8  s1401 = s1397 ^ s1400;
-  const SWord8  s1402 = s1396 ^ s1401;
-  const SWord8  s1403 = table2[s1376];
-  const SWord8  s1404 = table3[s1378];
-  const SWord8  s1405 = table4[s1381];
-  const SWord8  s1406 = table1[s1383];
-  const SWord8  s1407 = s1405 ^ s1406;
-  const SWord8  s1408 = s1404 ^ s1407;
-  const SWord8  s1409 = s1403 ^ s1408;
-  const SWord16 s1410 = (((SWord16) s1402) << 8) | ((SWord16) s1409);
-  const SWord32 s1411 = (((SWord32) s1395) << 16) | ((SWord32) s1410);
-  const SWord16 s1412 = (SWord16) (s315 >> 16);
-  const SWord8  s1413 = (SWord8) (s1412 >> 8);
-  const SWord8  s1414 = table1[s1413];
-  const SWord8  s1415 = (SWord8) s1412;
-  const SWord8  s1416 = table2[s1415];
-  const SWord16 s1417 = (SWord16) s315;
-  const SWord8  s1418 = (SWord8) (s1417 >> 8);
-  const SWord8  s1419 = table3[s1418];
-  const SWord8  s1420 = (SWord8) s1417;
-  const SWord8  s1421 = table4[s1420];
-  const SWord8  s1422 = s1419 ^ s1421;
-  const SWord8  s1423 = s1416 ^ s1422;
-  const SWord8  s1424 = s1414 ^ s1423;
-  const SWord8  s1425 = table4[s1413];
-  const SWord8  s1426 = table1[s1415];
-  const SWord8  s1427 = table2[s1418];
-  const SWord8  s1428 = table3[s1420];
-  const SWord8  s1429 = s1427 ^ s1428;
-  const SWord8  s1430 = s1426 ^ s1429;
-  const SWord8  s1431 = s1425 ^ s1430;
-  const SWord16 s1432 = (((SWord16) s1424) << 8) | ((SWord16) s1431);
-  const SWord8  s1433 = table3[s1413];
-  const SWord8  s1434 = table4[s1415];
-  const SWord8  s1435 = table1[s1418];
-  const SWord8  s1436 = table2[s1420];
-  const SWord8  s1437 = s1435 ^ s1436;
-  const SWord8  s1438 = s1434 ^ s1437;
-  const SWord8  s1439 = s1433 ^ s1438;
-  const SWord8  s1440 = table2[s1413];
-  const SWord8  s1441 = table3[s1415];
-  const SWord8  s1442 = table4[s1418];
-  const SWord8  s1443 = table1[s1420];
-  const SWord8  s1444 = s1442 ^ s1443;
-  const SWord8  s1445 = s1441 ^ s1444;
-  const SWord8  s1446 = s1440 ^ s1445;
-  const SWord16 s1447 = (((SWord16) s1439) << 8) | ((SWord16) s1446);
-  const SWord32 s1448 = (((SWord32) s1432) << 16) | ((SWord32) s1447);
-  const SWord16 s1449 = (SWord16) (s316 >> 16);
-  const SWord8  s1450 = (SWord8) (s1449 >> 8);
-  const SWord8  s1451 = table1[s1450];
-  const SWord8  s1452 = (SWord8) s1449;
-  const SWord8  s1453 = table2[s1452];
-  const SWord16 s1454 = (SWord16) s316;
-  const SWord8  s1455 = (SWord8) (s1454 >> 8);
-  const SWord8  s1456 = table3[s1455];
-  const SWord8  s1457 = (SWord8) s1454;
-  const SWord8  s1458 = table4[s1457];
-  const SWord8  s1459 = s1456 ^ s1458;
-  const SWord8  s1460 = s1453 ^ s1459;
-  const SWord8  s1461 = s1451 ^ s1460;
-  const SWord8  s1462 = table4[s1450];
-  const SWord8  s1463 = table1[s1452];
-  const SWord8  s1464 = table2[s1455];
-  const SWord8  s1465 = table3[s1457];
-  const SWord8  s1466 = s1464 ^ s1465;
-  const SWord8  s1467 = s1463 ^ s1466;
-  const SWord8  s1468 = s1462 ^ s1467;
-  const SWord16 s1469 = (((SWord16) s1461) << 8) | ((SWord16) s1468);
-  const SWord8  s1470 = table3[s1450];
-  const SWord8  s1471 = table4[s1452];
-  const SWord8  s1472 = table1[s1455];
-  const SWord8  s1473 = table2[s1457];
-  const SWord8  s1474 = s1472 ^ s1473;
-  const SWord8  s1475 = s1471 ^ s1474;
-  const SWord8  s1476 = s1470 ^ s1475;
-  const SWord8  s1477 = table2[s1450];
-  const SWord8  s1478 = table3[s1452];
-  const SWord8  s1479 = table4[s1455];
-  const SWord8  s1480 = table1[s1457];
-  const SWord8  s1481 = s1479 ^ s1480;
-  const SWord8  s1482 = s1478 ^ s1481;
-  const SWord8  s1483 = s1477 ^ s1482;
-  const SWord16 s1484 = (((SWord16) s1476) << 8) | ((SWord16) s1483);
-  const SWord32 s1485 = (((SWord32) s1469) << 16) | ((SWord32) s1484);
-  const SWord16 s1486 = (SWord16) (s294 >> 16);
-  const SWord8  s1487 = (SWord8) (s1486 >> 8);
-  const SWord8  s1488 = table1[s1487];
-  const SWord8  s1489 = (SWord8) s1486;
-  const SWord8  s1490 = table2[s1489];
-  const SWord16 s1491 = (SWord16) s294;
-  const SWord8  s1492 = (SWord8) (s1491 >> 8);
-  const SWord8  s1493 = table3[s1492];
-  const SWord8  s1494 = (SWord8) s1491;
-  const SWord8  s1495 = table4[s1494];
-  const SWord8  s1496 = s1493 ^ s1495;
-  const SWord8  s1497 = s1490 ^ s1496;
-  const SWord8  s1498 = s1488 ^ s1497;
-  const SWord8  s1499 = table4[s1487];
-  const SWord8  s1500 = table1[s1489];
-  const SWord8  s1501 = table2[s1492];
-  const SWord8  s1502 = table3[s1494];
-  const SWord8  s1503 = s1501 ^ s1502;
-  const SWord8  s1504 = s1500 ^ s1503;
-  const SWord8  s1505 = s1499 ^ s1504;
-  const SWord16 s1506 = (((SWord16) s1498) << 8) | ((SWord16) s1505);
-  const SWord8  s1507 = table3[s1487];
-  const SWord8  s1508 = table4[s1489];
-  const SWord8  s1509 = table1[s1492];
-  const SWord8  s1510 = table2[s1494];
-  const SWord8  s1511 = s1509 ^ s1510;
-  const SWord8  s1512 = s1508 ^ s1511;
-  const SWord8  s1513 = s1507 ^ s1512;
-  const SWord8  s1514 = table2[s1487];
-  const SWord8  s1515 = table3[s1489];
-  const SWord8  s1516 = table4[s1492];
-  const SWord8  s1517 = table1[s1494];
-  const SWord8  s1518 = s1516 ^ s1517;
-  const SWord8  s1519 = s1515 ^ s1518;
-  const SWord8  s1520 = s1514 ^ s1519;
-  const SWord16 s1521 = (((SWord16) s1513) << 8) | ((SWord16) s1520);
-  const SWord32 s1522 = (((SWord32) s1506) << 16) | ((SWord32) s1521);
-  const SWord16 s1523 = (SWord16) (s295 >> 16);
-  const SWord8  s1524 = (SWord8) (s1523 >> 8);
-  const SWord8  s1525 = table1[s1524];
-  const SWord8  s1526 = (SWord8) s1523;
-  const SWord8  s1527 = table2[s1526];
-  const SWord16 s1528 = (SWord16) s295;
-  const SWord8  s1529 = (SWord8) (s1528 >> 8);
-  const SWord8  s1530 = table3[s1529];
-  const SWord8  s1531 = (SWord8) s1528;
-  const SWord8  s1532 = table4[s1531];
-  const SWord8  s1533 = s1530 ^ s1532;
-  const SWord8  s1534 = s1527 ^ s1533;
-  const SWord8  s1535 = s1525 ^ s1534;
-  const SWord8  s1536 = table4[s1524];
-  const SWord8  s1537 = table1[s1526];
-  const SWord8  s1538 = table2[s1529];
-  const SWord8  s1539 = table3[s1531];
-  const SWord8  s1540 = s1538 ^ s1539;
-  const SWord8  s1541 = s1537 ^ s1540;
-  const SWord8  s1542 = s1536 ^ s1541;
-  const SWord16 s1543 = (((SWord16) s1535) << 8) | ((SWord16) s1542);
-  const SWord8  s1544 = table3[s1524];
-  const SWord8  s1545 = table4[s1526];
-  const SWord8  s1546 = table1[s1529];
-  const SWord8  s1547 = table2[s1531];
-  const SWord8  s1548 = s1546 ^ s1547;
-  const SWord8  s1549 = s1545 ^ s1548;
-  const SWord8  s1550 = s1544 ^ s1549;
-  const SWord8  s1551 = table2[s1524];
-  const SWord8  s1552 = table3[s1526];
-  const SWord8  s1553 = table4[s1529];
-  const SWord8  s1554 = table1[s1531];
-  const SWord8  s1555 = s1553 ^ s1554;
-  const SWord8  s1556 = s1552 ^ s1555;
-  const SWord8  s1557 = s1551 ^ s1556;
-  const SWord16 s1558 = (((SWord16) s1550) << 8) | ((SWord16) s1557);
-  const SWord32 s1559 = (((SWord32) s1543) << 16) | ((SWord32) s1558);
-  const SWord16 s1560 = (SWord16) (s296 >> 16);
-  const SWord8  s1561 = (SWord8) (s1560 >> 8);
-  const SWord8  s1562 = table1[s1561];
-  const SWord8  s1563 = (SWord8) s1560;
-  const SWord8  s1564 = table2[s1563];
-  const SWord16 s1565 = (SWord16) s296;
-  const SWord8  s1566 = (SWord8) (s1565 >> 8);
-  const SWord8  s1567 = table3[s1566];
-  const SWord8  s1568 = (SWord8) s1565;
-  const SWord8  s1569 = table4[s1568];
-  const SWord8  s1570 = s1567 ^ s1569;
-  const SWord8  s1571 = s1564 ^ s1570;
-  const SWord8  s1572 = s1562 ^ s1571;
-  const SWord8  s1573 = table4[s1561];
-  const SWord8  s1574 = table1[s1563];
-  const SWord8  s1575 = table2[s1566];
-  const SWord8  s1576 = table3[s1568];
-  const SWord8  s1577 = s1575 ^ s1576;
-  const SWord8  s1578 = s1574 ^ s1577;
-  const SWord8  s1579 = s1573 ^ s1578;
-  const SWord16 s1580 = (((SWord16) s1572) << 8) | ((SWord16) s1579);
-  const SWord8  s1581 = table3[s1561];
-  const SWord8  s1582 = table4[s1563];
-  const SWord8  s1583 = table1[s1566];
-  const SWord8  s1584 = table2[s1568];
-  const SWord8  s1585 = s1583 ^ s1584;
-  const SWord8  s1586 = s1582 ^ s1585;
-  const SWord8  s1587 = s1581 ^ s1586;
-  const SWord8  s1588 = table2[s1561];
-  const SWord8  s1589 = table3[s1563];
-  const SWord8  s1590 = table4[s1566];
-  const SWord8  s1591 = table1[s1568];
-  const SWord8  s1592 = s1590 ^ s1591;
-  const SWord8  s1593 = s1589 ^ s1592;
-  const SWord8  s1594 = s1588 ^ s1593;
-  const SWord16 s1595 = (((SWord16) s1587) << 8) | ((SWord16) s1594);
-  const SWord32 s1596 = (((SWord32) s1580) << 16) | ((SWord32) s1595);
-  const SWord16 s1597 = (SWord16) (s297 >> 16);
-  const SWord8  s1598 = (SWord8) (s1597 >> 8);
-  const SWord8  s1599 = table1[s1598];
-  const SWord8  s1600 = (SWord8) s1597;
-  const SWord8  s1601 = table2[s1600];
-  const SWord16 s1602 = (SWord16) s297;
-  const SWord8  s1603 = (SWord8) (s1602 >> 8);
-  const SWord8  s1604 = table3[s1603];
-  const SWord8  s1605 = (SWord8) s1602;
-  const SWord8  s1606 = table4[s1605];
-  const SWord8  s1607 = s1604 ^ s1606;
-  const SWord8  s1608 = s1601 ^ s1607;
-  const SWord8  s1609 = s1599 ^ s1608;
-  const SWord8  s1610 = table4[s1598];
-  const SWord8  s1611 = table1[s1600];
-  const SWord8  s1612 = table2[s1603];
-  const SWord8  s1613 = table3[s1605];
-  const SWord8  s1614 = s1612 ^ s1613;
-  const SWord8  s1615 = s1611 ^ s1614;
-  const SWord8  s1616 = s1610 ^ s1615;
-  const SWord16 s1617 = (((SWord16) s1609) << 8) | ((SWord16) s1616);
-  const SWord8  s1618 = table3[s1598];
-  const SWord8  s1619 = table4[s1600];
-  const SWord8  s1620 = table1[s1603];
-  const SWord8  s1621 = table2[s1605];
-  const SWord8  s1622 = s1620 ^ s1621;
-  const SWord8  s1623 = s1619 ^ s1622;
-  const SWord8  s1624 = s1618 ^ s1623;
-  const SWord8  s1625 = table2[s1598];
-  const SWord8  s1626 = table3[s1600];
-  const SWord8  s1627 = table4[s1603];
-  const SWord8  s1628 = table1[s1605];
-  const SWord8  s1629 = s1627 ^ s1628;
-  const SWord8  s1630 = s1626 ^ s1629;
-  const SWord8  s1631 = s1625 ^ s1630;
-  const SWord16 s1632 = (((SWord16) s1624) << 8) | ((SWord16) s1631);
-  const SWord32 s1633 = (((SWord32) s1617) << 16) | ((SWord32) s1632);
-  const SWord16 s1634 = (SWord16) (s275 >> 16);
-  const SWord8  s1635 = (SWord8) (s1634 >> 8);
-  const SWord8  s1636 = table1[s1635];
-  const SWord8  s1637 = (SWord8) s1634;
-  const SWord8  s1638 = table2[s1637];
-  const SWord16 s1639 = (SWord16) s275;
-  const SWord8  s1640 = (SWord8) (s1639 >> 8);
-  const SWord8  s1641 = table3[s1640];
-  const SWord8  s1642 = (SWord8) s1639;
-  const SWord8  s1643 = table4[s1642];
-  const SWord8  s1644 = s1641 ^ s1643;
-  const SWord8  s1645 = s1638 ^ s1644;
-  const SWord8  s1646 = s1636 ^ s1645;
-  const SWord8  s1647 = table4[s1635];
-  const SWord8  s1648 = table1[s1637];
-  const SWord8  s1649 = table2[s1640];
-  const SWord8  s1650 = table3[s1642];
-  const SWord8  s1651 = s1649 ^ s1650;
-  const SWord8  s1652 = s1648 ^ s1651;
-  const SWord8  s1653 = s1647 ^ s1652;
-  const SWord16 s1654 = (((SWord16) s1646) << 8) | ((SWord16) s1653);
-  const SWord8  s1655 = table3[s1635];
-  const SWord8  s1656 = table4[s1637];
-  const SWord8  s1657 = table1[s1640];
-  const SWord8  s1658 = table2[s1642];
-  const SWord8  s1659 = s1657 ^ s1658;
-  const SWord8  s1660 = s1656 ^ s1659;
-  const SWord8  s1661 = s1655 ^ s1660;
-  const SWord8  s1662 = table2[s1635];
-  const SWord8  s1663 = table3[s1637];
-  const SWord8  s1664 = table4[s1640];
-  const SWord8  s1665 = table1[s1642];
-  const SWord8  s1666 = s1664 ^ s1665;
-  const SWord8  s1667 = s1663 ^ s1666;
-  const SWord8  s1668 = s1662 ^ s1667;
-  const SWord16 s1669 = (((SWord16) s1661) << 8) | ((SWord16) s1668);
-  const SWord32 s1670 = (((SWord32) s1654) << 16) | ((SWord32) s1669);
-  const SWord16 s1671 = (SWord16) (s276 >> 16);
-  const SWord8  s1672 = (SWord8) (s1671 >> 8);
-  const SWord8  s1673 = table1[s1672];
-  const SWord8  s1674 = (SWord8) s1671;
-  const SWord8  s1675 = table2[s1674];
-  const SWord16 s1676 = (SWord16) s276;
-  const SWord8  s1677 = (SWord8) (s1676 >> 8);
-  const SWord8  s1678 = table3[s1677];
-  const SWord8  s1679 = (SWord8) s1676;
-  const SWord8  s1680 = table4[s1679];
-  const SWord8  s1681 = s1678 ^ s1680;
-  const SWord8  s1682 = s1675 ^ s1681;
-  const SWord8  s1683 = s1673 ^ s1682;
-  const SWord8  s1684 = table4[s1672];
-  const SWord8  s1685 = table1[s1674];
-  const SWord8  s1686 = table2[s1677];
-  const SWord8  s1687 = table3[s1679];
-  const SWord8  s1688 = s1686 ^ s1687;
-  const SWord8  s1689 = s1685 ^ s1688;
-  const SWord8  s1690 = s1684 ^ s1689;
-  const SWord16 s1691 = (((SWord16) s1683) << 8) | ((SWord16) s1690);
-  const SWord8  s1692 = table3[s1672];
-  const SWord8  s1693 = table4[s1674];
-  const SWord8  s1694 = table1[s1677];
-  const SWord8  s1695 = table2[s1679];
-  const SWord8  s1696 = s1694 ^ s1695;
-  const SWord8  s1697 = s1693 ^ s1696;
-  const SWord8  s1698 = s1692 ^ s1697;
-  const SWord8  s1699 = table2[s1672];
-  const SWord8  s1700 = table3[s1674];
-  const SWord8  s1701 = table4[s1677];
-  const SWord8  s1702 = table1[s1679];
-  const SWord8  s1703 = s1701 ^ s1702;
-  const SWord8  s1704 = s1700 ^ s1703;
-  const SWord8  s1705 = s1699 ^ s1704;
-  const SWord16 s1706 = (((SWord16) s1698) << 8) | ((SWord16) s1705);
-  const SWord32 s1707 = (((SWord32) s1691) << 16) | ((SWord32) s1706);
-  const SWord16 s1708 = (SWord16) (s277 >> 16);
-  const SWord8  s1709 = (SWord8) (s1708 >> 8);
-  const SWord8  s1710 = table1[s1709];
-  const SWord8  s1711 = (SWord8) s1708;
-  const SWord8  s1712 = table2[s1711];
-  const SWord16 s1713 = (SWord16) s277;
-  const SWord8  s1714 = (SWord8) (s1713 >> 8);
-  const SWord8  s1715 = table3[s1714];
-  const SWord8  s1716 = (SWord8) s1713;
-  const SWord8  s1717 = table4[s1716];
-  const SWord8  s1718 = s1715 ^ s1717;
-  const SWord8  s1719 = s1712 ^ s1718;
-  const SWord8  s1720 = s1710 ^ s1719;
-  const SWord8  s1721 = table4[s1709];
-  const SWord8  s1722 = table1[s1711];
-  const SWord8  s1723 = table2[s1714];
-  const SWord8  s1724 = table3[s1716];
-  const SWord8  s1725 = s1723 ^ s1724;
-  const SWord8  s1726 = s1722 ^ s1725;
-  const SWord8  s1727 = s1721 ^ s1726;
-  const SWord16 s1728 = (((SWord16) s1720) << 8) | ((SWord16) s1727);
-  const SWord8  s1729 = table3[s1709];
-  const SWord8  s1730 = table4[s1711];
-  const SWord8  s1731 = table1[s1714];
-  const SWord8  s1732 = table2[s1716];
-  const SWord8  s1733 = s1731 ^ s1732;
-  const SWord8  s1734 = s1730 ^ s1733;
-  const SWord8  s1735 = s1729 ^ s1734;
-  const SWord8  s1736 = table2[s1709];
-  const SWord8  s1737 = table3[s1711];
-  const SWord8  s1738 = table4[s1714];
-  const SWord8  s1739 = table1[s1716];
-  const SWord8  s1740 = s1738 ^ s1739;
-  const SWord8  s1741 = s1737 ^ s1740;
-  const SWord8  s1742 = s1736 ^ s1741;
-  const SWord16 s1743 = (((SWord16) s1735) << 8) | ((SWord16) s1742);
-  const SWord32 s1744 = (((SWord32) s1728) << 16) | ((SWord32) s1743);
-  const SWord16 s1745 = (SWord16) (s278 >> 16);
-  const SWord8  s1746 = (SWord8) (s1745 >> 8);
-  const SWord8  s1747 = table1[s1746];
-  const SWord8  s1748 = (SWord8) s1745;
-  const SWord8  s1749 = table2[s1748];
-  const SWord16 s1750 = (SWord16) s278;
-  const SWord8  s1751 = (SWord8) (s1750 >> 8);
-  const SWord8  s1752 = table3[s1751];
-  const SWord8  s1753 = (SWord8) s1750;
-  const SWord8  s1754 = table4[s1753];
-  const SWord8  s1755 = s1752 ^ s1754;
-  const SWord8  s1756 = s1749 ^ s1755;
-  const SWord8  s1757 = s1747 ^ s1756;
-  const SWord8  s1758 = table4[s1746];
-  const SWord8  s1759 = table1[s1748];
-  const SWord8  s1760 = table2[s1751];
-  const SWord8  s1761 = table3[s1753];
-  const SWord8  s1762 = s1760 ^ s1761;
-  const SWord8  s1763 = s1759 ^ s1762;
-  const SWord8  s1764 = s1758 ^ s1763;
-  const SWord16 s1765 = (((SWord16) s1757) << 8) | ((SWord16) s1764);
-  const SWord8  s1766 = table3[s1746];
-  const SWord8  s1767 = table4[s1748];
-  const SWord8  s1768 = table1[s1751];
-  const SWord8  s1769 = table2[s1753];
-  const SWord8  s1770 = s1768 ^ s1769;
-  const SWord8  s1771 = s1767 ^ s1770;
-  const SWord8  s1772 = s1766 ^ s1771;
-  const SWord8  s1773 = table2[s1746];
-  const SWord8  s1774 = table3[s1748];
-  const SWord8  s1775 = table4[s1751];
-  const SWord8  s1776 = table1[s1753];
-  const SWord8  s1777 = s1775 ^ s1776;
-  const SWord8  s1778 = s1774 ^ s1777;
-  const SWord8  s1779 = s1773 ^ s1778;
-  const SWord16 s1780 = (((SWord16) s1772) << 8) | ((SWord16) s1779);
-  const SWord32 s1781 = (((SWord32) s1765) << 16) | ((SWord32) s1780);
-
-  encKS[0] = s0;
-  encKS[1] = s1;
-  encKS[2] = s2;
-  encKS[3] = s3;
-  encKS[4] = s275;
-  encKS[5] = s276;
-  encKS[6] = s277;
-  encKS[7] = s278;
-  encKS[8] = s294;
-  encKS[9] = s295;
-  encKS[10] = s296;
-  encKS[11] = s297;
-  encKS[12] = s313;
-  encKS[13] = s314;
-  encKS[14] = s315;
-  encKS[15] = s316;
-  encKS[16] = s332;
-  encKS[17] = s333;
-  encKS[18] = s334;
-  encKS[19] = s335;
-  encKS[20] = s351;
-  encKS[21] = s352;
-  encKS[22] = s353;
-  encKS[23] = s354;
-  encKS[24] = s370;
-  encKS[25] = s371;
-  encKS[26] = s372;
-  encKS[27] = s373;
-  encKS[28] = s389;
-  encKS[29] = s390;
-  encKS[30] = s391;
-  encKS[31] = s392;
-  encKS[32] = s408;
-  encKS[33] = s409;
-  encKS[34] = s410;
-  encKS[35] = s411;
-  encKS[36] = s427;
-  encKS[37] = s428;
-  encKS[38] = s429;
-  encKS[39] = s430;
-  encKS[40] = s446;
-  encKS[41] = s447;
-  encKS[42] = s448;
-  encKS[43] = s449;
-  decKS[0] = s446;
-  decKS[1] = s447;
-  decKS[2] = s448;
-  decKS[3] = s449;
-  decKS[4] = s486;
-  decKS[5] = s523;
-  decKS[6] = s560;
-  decKS[7] = s597;
-  decKS[8] = s634;
-  decKS[9] = s671;
-  decKS[10] = s708;
-  decKS[11] = s745;
-  decKS[12] = s782;
-  decKS[13] = s819;
-  decKS[14] = s856;
-  decKS[15] = s893;
-  decKS[16] = s930;
-  decKS[17] = s967;
-  decKS[18] = s1004;
-  decKS[19] = s1041;
-  decKS[20] = s1078;
-  decKS[21] = s1115;
-  decKS[22] = s1152;
-  decKS[23] = s1189;
-  decKS[24] = s1226;
-  decKS[25] = s1263;
-  decKS[26] = s1300;
-  decKS[27] = s1337;
-  decKS[28] = s1374;
-  decKS[29] = s1411;
-  decKS[30] = s1448;
-  decKS[31] = s1485;
-  decKS[32] = s1522;
-  decKS[33] = s1559;
-  decKS[34] = s1596;
-  decKS[35] = s1633;
-  decKS[36] = s1670;
-  decKS[37] = s1707;
-  decKS[38] = s1744;
-  decKS[39] = s1781;
-  decKS[40] = s0;
-  decKS[41] = s1;
-  decKS[42] = s2;
-  decKS[43] = s3;
-}
-== END: "aes128KeySchedule.c" ==================
-== BEGIN: "aes128BlockEncrypt.c" ================
-/* File: "aes128BlockEncrypt.c". Automatically generated by SBV. Do not edit! */
-
-#include "aes128Lib.h"
-
-void aes128BlockEncrypt(const SWord32 *pt, const SWord32 *xkey,
-                        SWord32 *ct)
-{
-  const SWord32 s0 = pt[0];
-  const SWord32 s1 = pt[1];
-  const SWord32 s2 = pt[2];
-  const SWord32 s3 = pt[3];
-  const SWord32 s4 = xkey[0];
-  const SWord32 s5 = xkey[1];
-  const SWord32 s6 = xkey[2];
-  const SWord32 s7 = xkey[3];
-  const SWord32 s8 = xkey[4];
-  const SWord32 s9 = xkey[5];
-  const SWord32 s10 = xkey[6];
-  const SWord32 s11 = xkey[7];
-  const SWord32 s12 = xkey[8];
-  const SWord32 s13 = xkey[9];
-  const SWord32 s14 = xkey[10];
-  const SWord32 s15 = xkey[11];
-  const SWord32 s16 = xkey[12];
-  const SWord32 s17 = xkey[13];
-  const SWord32 s18 = xkey[14];
-  const SWord32 s19 = xkey[15];
-  const SWord32 s20 = xkey[16];
-  const SWord32 s21 = xkey[17];
-  const SWord32 s22 = xkey[18];
-  const SWord32 s23 = xkey[19];
-  const SWord32 s24 = xkey[20];
-  const SWord32 s25 = xkey[21];
-  const SWord32 s26 = xkey[22];
-  const SWord32 s27 = xkey[23];
-  const SWord32 s28 = xkey[24];
-  const SWord32 s29 = xkey[25];
-  const SWord32 s30 = xkey[26];
-  const SWord32 s31 = xkey[27];
-  const SWord32 s32 = xkey[28];
-  const SWord32 s33 = xkey[29];
-  const SWord32 s34 = xkey[30];
-  const SWord32 s35 = xkey[31];
-  const SWord32 s36 = xkey[32];
-  const SWord32 s37 = xkey[33];
-  const SWord32 s38 = xkey[34];
-  const SWord32 s39 = xkey[35];
-  const SWord32 s40 = xkey[36];
-  const SWord32 s41 = xkey[37];
-  const SWord32 s42 = xkey[38];
-  const SWord32 s43 = xkey[39];
-  const SWord32 s44 = xkey[40];
-  const SWord32 s45 = xkey[41];
-  const SWord32 s46 = xkey[42];
-  const SWord32 s47 = xkey[43];
-  static const SWord8 table0[] = {
-       99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254,
-      215, 171, 118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212,
-      162, 175, 156, 164, 114, 192, 183, 253, 147,  38,  54,  63, 247,
-      204,  52, 165, 229, 241, 113, 216,  49,  21,   4, 199,  35, 195,
-       24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,   9,
-      131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,
-       47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,
-       57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,
-       69, 249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146,
-      157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210, 205,  12,
-       19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25,
-      115,  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20,
-      222,  94,  11, 219, 224,  50,  58,  10,  73,   6,  36,  92, 194,
-      211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 141, 213,
-       78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,
-       46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
-      112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134,
-      193,  29, 158, 225, 248, 152,  17, 105, 217, 142, 148, 155,  30,
-      135, 233, 206,  85,  40, 223, 140, 161, 137,  13, 191, 230,  66,
-      104,  65, 153,  45,  15, 176,  84, 187,  22
-  };
-  static const SWord32 table1[] = {
-      0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
-      0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
-      0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
-      0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
-      0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
-      0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
-      0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
-      0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
-      0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
-      0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
-      0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
-      0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
-      0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
-      0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
-      0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
-      0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
-      0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
-      0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
-      0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
-      0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
-      0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
-      0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
-      0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
-      0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
-      0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
-      0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
-      0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
-      0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
-      0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
-      0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
-      0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
-      0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
-      0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
-      0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
-      0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
-      0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
-      0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
-      0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
-      0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
-      0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
-      0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
-      0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
-      0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
-      0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
-      0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
-      0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
-      0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
-      0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
-      0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
-      0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
-      0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
-      0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
-      0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
-      0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
-      0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
-      0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
-      0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
-      0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
-      0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
-      0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
-      0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
-      0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
-      0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
-      0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL
-  };
-  static const SWord32 table2[] = {
-      0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
-      0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
-      0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
-      0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
-      0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
-      0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
-      0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
-      0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
-      0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
-      0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
-      0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
-      0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
-      0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
-      0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
-      0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
-      0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
-      0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
-      0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
-      0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
-      0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
-      0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
-      0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
-      0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
-      0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
-      0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
-      0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
-      0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
-      0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
-      0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
-      0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
-      0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
-      0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
-      0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
-      0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
-      0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
-      0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
-      0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
-      0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
-      0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
-      0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
-      0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
-      0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
-      0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
-      0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
-      0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
-      0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
-      0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
-      0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
-      0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
-      0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
-      0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
-      0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
-      0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
-      0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
-      0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
-      0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
-      0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
-      0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
-      0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
-      0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
-      0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
-      0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
-      0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
-      0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL
-  };
-  static const SWord32 table3[] = {
-      0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
-      0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
-      0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
-      0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
-      0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
-      0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
-      0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
-      0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
-      0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
-      0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
-      0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
-      0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
-      0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
-      0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
-      0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
-      0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
-      0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
-      0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
-      0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
-      0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
-      0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
-      0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
-      0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
-      0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
-      0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
-      0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
-      0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
-      0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
-      0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
-      0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
-      0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
-      0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
-      0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
-      0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
-      0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
-      0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
-      0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
-      0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
-      0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
-      0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
-      0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
-      0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
-      0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
-      0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
-      0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
-      0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
-      0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
-      0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
-      0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
-      0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
-      0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
-      0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
-      0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
-      0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
-      0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
-      0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
-      0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
-      0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
-      0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
-      0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
-      0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
-      0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
-      0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
-      0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL
-  };
-  static const SWord32 table4[] = {
-      0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
-      0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
-      0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
-      0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
-      0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
-      0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
-      0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
-      0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
-      0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
-      0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
-      0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
-      0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
-      0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
-      0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
-      0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
-      0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
-      0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
-      0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
-      0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
-      0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
-      0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
-      0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
-      0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
-      0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
-      0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
-      0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
-      0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
-      0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
-      0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
-      0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
-      0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
-      0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
-      0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
-      0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
-      0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
-      0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
-      0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
-      0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
-      0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
-      0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
-      0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
-      0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
-      0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
-      0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
-      0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
-      0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
-      0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
-      0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
-      0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
-      0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
-      0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
-      0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
-      0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
-      0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
-      0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
-      0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
-      0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
-      0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
-      0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
-      0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
-      0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
-      0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
-      0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
-      0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL
-  };
-  const SWord32 s560 = s0 ^ s4;
-  const SWord16 s561 = (SWord16) (s560 >> 16);
-  const SWord8  s562 = (SWord8) (s561 >> 8);
-  const SWord32 s563 = table1[s562];
-  const SWord32 s819 = s1 ^ s5;
-  const SWord16 s820 = (SWord16) (s819 >> 16);
-  const SWord8  s821 = (SWord8) s820;
-  const SWord32 s822 = table2[s821];
-  const SWord32 s823 = s563 ^ s822;
-  const SWord32 s1079 = s2 ^ s6;
-  const SWord16 s1080 = (SWord16) s1079;
-  const SWord8  s1081 = (SWord8) (s1080 >> 8);
-  const SWord32 s1082 = table3[s1081];
-  const SWord32 s1083 = s823 ^ s1082;
-  const SWord32 s1339 = s3 ^ s7;
-  const SWord16 s1340 = (SWord16) s1339;
-  const SWord8  s1341 = (SWord8) s1340;
-  const SWord32 s1342 = table4[s1341];
-  const SWord32 s1343 = s1083 ^ s1342;
-  const SWord32 s1344 = s8 ^ s1343;
-  const SWord16 s1345 = (SWord16) (s1344 >> 16);
-  const SWord8  s1346 = (SWord8) (s1345 >> 8);
-  const SWord32 s1347 = table1[s1346];
-  const SWord8  s1348 = (SWord8) (s820 >> 8);
-  const SWord32 s1349 = table1[s1348];
-  const SWord16 s1350 = (SWord16) (s1079 >> 16);
-  const SWord8  s1351 = (SWord8) s1350;
-  const SWord32 s1352 = table2[s1351];
-  const SWord32 s1353 = s1349 ^ s1352;
-  const SWord8  s1354 = (SWord8) (s1340 >> 8);
-  const SWord32 s1355 = table3[s1354];
-  const SWord32 s1356 = s1353 ^ s1355;
-  const SWord16 s1357 = (SWord16) s560;
-  const SWord8  s1358 = (SWord8) s1357;
-  const SWord32 s1359 = table4[s1358];
-  const SWord32 s1360 = s1356 ^ s1359;
-  const SWord32 s1361 = s9 ^ s1360;
-  const SWord16 s1362 = (SWord16) (s1361 >> 16);
-  const SWord8  s1363 = (SWord8) s1362;
-  const SWord32 s1364 = table2[s1363];
-  const SWord32 s1365 = s1347 ^ s1364;
-  const SWord8  s1366 = (SWord8) (s1350 >> 8);
-  const SWord32 s1367 = table1[s1366];
-  const SWord16 s1368 = (SWord16) (s1339 >> 16);
-  const SWord8  s1369 = (SWord8) s1368;
-  const SWord32 s1370 = table2[s1369];
-  const SWord32 s1371 = s1367 ^ s1370;
-  const SWord8  s1372 = (SWord8) (s1357 >> 8);
-  const SWord32 s1373 = table3[s1372];
-  const SWord32 s1374 = s1371 ^ s1373;
-  const SWord16 s1375 = (SWord16) s819;
-  const SWord8  s1376 = (SWord8) s1375;
-  const SWord32 s1377 = table4[s1376];
-  const SWord32 s1378 = s1374 ^ s1377;
-  const SWord32 s1379 = s10 ^ s1378;
-  const SWord16 s1380 = (SWord16) s1379;
-  const SWord8  s1381 = (SWord8) (s1380 >> 8);
-  const SWord32 s1382 = table3[s1381];
-  const SWord32 s1383 = s1365 ^ s1382;
-  const SWord8  s1384 = (SWord8) (s1368 >> 8);
-  const SWord32 s1385 = table1[s1384];
-  const SWord8  s1386 = (SWord8) s561;
-  const SWord32 s1387 = table2[s1386];
-  const SWord32 s1388 = s1385 ^ s1387;
-  const SWord8  s1389 = (SWord8) (s1375 >> 8);
-  const SWord32 s1390 = table3[s1389];
-  const SWord32 s1391 = s1388 ^ s1390;
-  const SWord8  s1392 = (SWord8) s1080;
-  const SWord32 s1393 = table4[s1392];
-  const SWord32 s1394 = s1391 ^ s1393;
-  const SWord32 s1395 = s11 ^ s1394;
-  const SWord16 s1396 = (SWord16) s1395;
-  const SWord8  s1397 = (SWord8) s1396;
-  const SWord32 s1398 = table4[s1397];
-  const SWord32 s1399 = s1383 ^ s1398;
-  const SWord32 s1400 = s12 ^ s1399;
-  const SWord16 s1401 = (SWord16) (s1400 >> 16);
-  const SWord8  s1402 = (SWord8) (s1401 >> 8);
-  const SWord32 s1403 = table1[s1402];
-  const SWord8  s1404 = (SWord8) (s1362 >> 8);
-  const SWord32 s1405 = table1[s1404];
-  const SWord16 s1406 = (SWord16) (s1379 >> 16);
-  const SWord8  s1407 = (SWord8) s1406;
-  const SWord32 s1408 = table2[s1407];
-  const SWord32 s1409 = s1405 ^ s1408;
-  const SWord8  s1410 = (SWord8) (s1396 >> 8);
-  const SWord32 s1411 = table3[s1410];
-  const SWord32 s1412 = s1409 ^ s1411;
-  const SWord16 s1413 = (SWord16) s1344;
-  const SWord8  s1414 = (SWord8) s1413;
-  const SWord32 s1415 = table4[s1414];
-  const SWord32 s1416 = s1412 ^ s1415;
-  const SWord32 s1417 = s13 ^ s1416;
-  const SWord16 s1418 = (SWord16) (s1417 >> 16);
-  const SWord8  s1419 = (SWord8) s1418;
-  const SWord32 s1420 = table2[s1419];
-  const SWord32 s1421 = s1403 ^ s1420;
-  const SWord8  s1422 = (SWord8) (s1406 >> 8);
-  const SWord32 s1423 = table1[s1422];
-  const SWord16 s1424 = (SWord16) (s1395 >> 16);
-  const SWord8  s1425 = (SWord8) s1424;
-  const SWord32 s1426 = table2[s1425];
-  const SWord32 s1427 = s1423 ^ s1426;
-  const SWord8  s1428 = (SWord8) (s1413 >> 8);
-  const SWord32 s1429 = table3[s1428];
-  const SWord32 s1430 = s1427 ^ s1429;
-  const SWord16 s1431 = (SWord16) s1361;
-  const SWord8  s1432 = (SWord8) s1431;
-  const SWord32 s1433 = table4[s1432];
-  const SWord32 s1434 = s1430 ^ s1433;
-  const SWord32 s1435 = s14 ^ s1434;
-  const SWord16 s1436 = (SWord16) s1435;
-  const SWord8  s1437 = (SWord8) (s1436 >> 8);
-  const SWord32 s1438 = table3[s1437];
-  const SWord32 s1439 = s1421 ^ s1438;
-  const SWord8  s1440 = (SWord8) (s1424 >> 8);
-  const SWord32 s1441 = table1[s1440];
-  const SWord8  s1442 = (SWord8) s1345;
-  const SWord32 s1443 = table2[s1442];
-  const SWord32 s1444 = s1441 ^ s1443;
-  const SWord8  s1445 = (SWord8) (s1431 >> 8);
-  const SWord32 s1446 = table3[s1445];
-  const SWord32 s1447 = s1444 ^ s1446;
-  const SWord8  s1448 = (SWord8) s1380;
-  const SWord32 s1449 = table4[s1448];
-  const SWord32 s1450 = s1447 ^ s1449;
-  const SWord32 s1451 = s15 ^ s1450;
-  const SWord16 s1452 = (SWord16) s1451;
-  const SWord8  s1453 = (SWord8) s1452;
-  const SWord32 s1454 = table4[s1453];
-  const SWord32 s1455 = s1439 ^ s1454;
-  const SWord32 s1456 = s16 ^ s1455;
-  const SWord16 s1457 = (SWord16) (s1456 >> 16);
-  const SWord8  s1458 = (SWord8) (s1457 >> 8);
-  const SWord32 s1459 = table1[s1458];
-  const SWord8  s1460 = (SWord8) (s1418 >> 8);
-  const SWord32 s1461 = table1[s1460];
-  const SWord16 s1462 = (SWord16) (s1435 >> 16);
-  const SWord8  s1463 = (SWord8) s1462;
-  const SWord32 s1464 = table2[s1463];
-  const SWord32 s1465 = s1461 ^ s1464;
-  const SWord8  s1466 = (SWord8) (s1452 >> 8);
-  const SWord32 s1467 = table3[s1466];
-  const SWord32 s1468 = s1465 ^ s1467;
-  const SWord16 s1469 = (SWord16) s1400;
-  const SWord8  s1470 = (SWord8) s1469;
-  const SWord32 s1471 = table4[s1470];
-  const SWord32 s1472 = s1468 ^ s1471;
-  const SWord32 s1473 = s17 ^ s1472;
-  const SWord16 s1474 = (SWord16) (s1473 >> 16);
-  const SWord8  s1475 = (SWord8) s1474;
-  const SWord32 s1476 = table2[s1475];
-  const SWord32 s1477 = s1459 ^ s1476;
-  const SWord8  s1478 = (SWord8) (s1462 >> 8);
-  const SWord32 s1479 = table1[s1478];
-  const SWord16 s1480 = (SWord16) (s1451 >> 16);
-  const SWord8  s1481 = (SWord8) s1480;
-  const SWord32 s1482 = table2[s1481];
-  const SWord32 s1483 = s1479 ^ s1482;
-  const SWord8  s1484 = (SWord8) (s1469 >> 8);
-  const SWord32 s1485 = table3[s1484];
-  const SWord32 s1486 = s1483 ^ s1485;
-  const SWord16 s1487 = (SWord16) s1417;
-  const SWord8  s1488 = (SWord8) s1487;
-  const SWord32 s1489 = table4[s1488];
-  const SWord32 s1490 = s1486 ^ s1489;
-  const SWord32 s1491 = s18 ^ s1490;
-  const SWord16 s1492 = (SWord16) s1491;
-  const SWord8  s1493 = (SWord8) (s1492 >> 8);
-  const SWord32 s1494 = table3[s1493];
-  const SWord32 s1495 = s1477 ^ s1494;
-  const SWord8  s1496 = (SWord8) (s1480 >> 8);
-  const SWord32 s1497 = table1[s1496];
-  const SWord8  s1498 = (SWord8) s1401;
-  const SWord32 s1499 = table2[s1498];
-  const SWord32 s1500 = s1497 ^ s1499;
-  const SWord8  s1501 = (SWord8) (s1487 >> 8);
-  const SWord32 s1502 = table3[s1501];
-  const SWord32 s1503 = s1500 ^ s1502;
-  const SWord8  s1504 = (SWord8) s1436;
-  const SWord32 s1505 = table4[s1504];
-  const SWord32 s1506 = s1503 ^ s1505;
-  const SWord32 s1507 = s19 ^ s1506;
-  const SWord16 s1508 = (SWord16) s1507;
-  const SWord8  s1509 = (SWord8) s1508;
-  const SWord32 s1510 = table4[s1509];
-  const SWord32 s1511 = s1495 ^ s1510;
-  const SWord32 s1512 = s20 ^ s1511;
-  const SWord16 s1513 = (SWord16) (s1512 >> 16);
-  const SWord8  s1514 = (SWord8) (s1513 >> 8);
-  const SWord32 s1515 = table1[s1514];
-  const SWord8  s1516 = (SWord8) (s1474 >> 8);
-  const SWord32 s1517 = table1[s1516];
-  const SWord16 s1518 = (SWord16) (s1491 >> 16);
-  const SWord8  s1519 = (SWord8) s1518;
-  const SWord32 s1520 = table2[s1519];
-  const SWord32 s1521 = s1517 ^ s1520;
-  const SWord8  s1522 = (SWord8) (s1508 >> 8);
-  const SWord32 s1523 = table3[s1522];
-  const SWord32 s1524 = s1521 ^ s1523;
-  const SWord16 s1525 = (SWord16) s1456;
-  const SWord8  s1526 = (SWord8) s1525;
-  const SWord32 s1527 = table4[s1526];
-  const SWord32 s1528 = s1524 ^ s1527;
-  const SWord32 s1529 = s21 ^ s1528;
-  const SWord16 s1530 = (SWord16) (s1529 >> 16);
-  const SWord8  s1531 = (SWord8) s1530;
-  const SWord32 s1532 = table2[s1531];
-  const SWord32 s1533 = s1515 ^ s1532;
-  const SWord8  s1534 = (SWord8) (s1518 >> 8);
-  const SWord32 s1535 = table1[s1534];
-  const SWord16 s1536 = (SWord16) (s1507 >> 16);
-  const SWord8  s1537 = (SWord8) s1536;
-  const SWord32 s1538 = table2[s1537];
-  const SWord32 s1539 = s1535 ^ s1538;
-  const SWord8  s1540 = (SWord8) (s1525 >> 8);
-  const SWord32 s1541 = table3[s1540];
-  const SWord32 s1542 = s1539 ^ s1541;
-  const SWord16 s1543 = (SWord16) s1473;
-  const SWord8  s1544 = (SWord8) s1543;
-  const SWord32 s1545 = table4[s1544];
-  const SWord32 s1546 = s1542 ^ s1545;
-  const SWord32 s1547 = s22 ^ s1546;
-  const SWord16 s1548 = (SWord16) s1547;
-  const SWord8  s1549 = (SWord8) (s1548 >> 8);
-  const SWord32 s1550 = table3[s1549];
-  const SWord32 s1551 = s1533 ^ s1550;
-  const SWord8  s1552 = (SWord8) (s1536 >> 8);
-  const SWord32 s1553 = table1[s1552];
-  const SWord8  s1554 = (SWord8) s1457;
-  const SWord32 s1555 = table2[s1554];
-  const SWord32 s1556 = s1553 ^ s1555;
-  const SWord8  s1557 = (SWord8) (s1543 >> 8);
-  const SWord32 s1558 = table3[s1557];
-  const SWord32 s1559 = s1556 ^ s1558;
-  const SWord8  s1560 = (SWord8) s1492;
-  const SWord32 s1561 = table4[s1560];
-  const SWord32 s1562 = s1559 ^ s1561;
-  const SWord32 s1563 = s23 ^ s1562;
-  const SWord16 s1564 = (SWord16) s1563;
-  const SWord8  s1565 = (SWord8) s1564;
-  const SWord32 s1566 = table4[s1565];
-  const SWord32 s1567 = s1551 ^ s1566;
-  const SWord32 s1568 = s24 ^ s1567;
-  const SWord16 s1569 = (SWord16) (s1568 >> 16);
-  const SWord8  s1570 = (SWord8) (s1569 >> 8);
-  const SWord32 s1571 = table1[s1570];
-  const SWord8  s1572 = (SWord8) (s1530 >> 8);
-  const SWord32 s1573 = table1[s1572];
-  const SWord16 s1574 = (SWord16) (s1547 >> 16);
-  const SWord8  s1575 = (SWord8) s1574;
-  const SWord32 s1576 = table2[s1575];
-  const SWord32 s1577 = s1573 ^ s1576;
-  const SWord8  s1578 = (SWord8) (s1564 >> 8);
-  const SWord32 s1579 = table3[s1578];
-  const SWord32 s1580 = s1577 ^ s1579;
-  const SWord16 s1581 = (SWord16) s1512;
-  const SWord8  s1582 = (SWord8) s1581;
-  const SWord32 s1583 = table4[s1582];
-  const SWord32 s1584 = s1580 ^ s1583;
-  const SWord32 s1585 = s25 ^ s1584;
-  const SWord16 s1586 = (SWord16) (s1585 >> 16);
-  const SWord8  s1587 = (SWord8) s1586;
-  const SWord32 s1588 = table2[s1587];
-  const SWord32 s1589 = s1571 ^ s1588;
-  const SWord8  s1590 = (SWord8) (s1574 >> 8);
-  const SWord32 s1591 = table1[s1590];
-  const SWord16 s1592 = (SWord16) (s1563 >> 16);
-  const SWord8  s1593 = (SWord8) s1592;
-  const SWord32 s1594 = table2[s1593];
-  const SWord32 s1595 = s1591 ^ s1594;
-  const SWord8  s1596 = (SWord8) (s1581 >> 8);
-  const SWord32 s1597 = table3[s1596];
-  const SWord32 s1598 = s1595 ^ s1597;
-  const SWord16 s1599 = (SWord16) s1529;
-  const SWord8  s1600 = (SWord8) s1599;
-  const SWord32 s1601 = table4[s1600];
-  const SWord32 s1602 = s1598 ^ s1601;
-  const SWord32 s1603 = s26 ^ s1602;
-  const SWord16 s1604 = (SWord16) s1603;
-  const SWord8  s1605 = (SWord8) (s1604 >> 8);
-  const SWord32 s1606 = table3[s1605];
-  const SWord32 s1607 = s1589 ^ s1606;
-  const SWord8  s1608 = (SWord8) (s1592 >> 8);
-  const SWord32 s1609 = table1[s1608];
-  const SWord8  s1610 = (SWord8) s1513;
-  const SWord32 s1611 = table2[s1610];
-  const SWord32 s1612 = s1609 ^ s1611;
-  const SWord8  s1613 = (SWord8) (s1599 >> 8);
-  const SWord32 s1614 = table3[s1613];
-  const SWord32 s1615 = s1612 ^ s1614;
-  const SWord8  s1616 = (SWord8) s1548;
-  const SWord32 s1617 = table4[s1616];
-  const SWord32 s1618 = s1615 ^ s1617;
-  const SWord32 s1619 = s27 ^ s1618;
-  const SWord16 s1620 = (SWord16) s1619;
-  const SWord8  s1621 = (SWord8) s1620;
-  const SWord32 s1622 = table4[s1621];
-  const SWord32 s1623 = s1607 ^ s1622;
-  const SWord32 s1624 = s28 ^ s1623;
-  const SWord16 s1625 = (SWord16) (s1624 >> 16);
-  const SWord8  s1626 = (SWord8) (s1625 >> 8);
-  const SWord32 s1627 = table1[s1626];
-  const SWord8  s1628 = (SWord8) (s1586 >> 8);
-  const SWord32 s1629 = table1[s1628];
-  const SWord16 s1630 = (SWord16) (s1603 >> 16);
-  const SWord8  s1631 = (SWord8) s1630;
-  const SWord32 s1632 = table2[s1631];
-  const SWord32 s1633 = s1629 ^ s1632;
-  const SWord8  s1634 = (SWord8) (s1620 >> 8);
-  const SWord32 s1635 = table3[s1634];
-  const SWord32 s1636 = s1633 ^ s1635;
-  const SWord16 s1637 = (SWord16) s1568;
-  const SWord8  s1638 = (SWord8) s1637;
-  const SWord32 s1639 = table4[s1638];
-  const SWord32 s1640 = s1636 ^ s1639;
-  const SWord32 s1641 = s29 ^ s1640;
-  const SWord16 s1642 = (SWord16) (s1641 >> 16);
-  const SWord8  s1643 = (SWord8) s1642;
-  const SWord32 s1644 = table2[s1643];
-  const SWord32 s1645 = s1627 ^ s1644;
-  const SWord8  s1646 = (SWord8) (s1630 >> 8);
-  const SWord32 s1647 = table1[s1646];
-  const SWord16 s1648 = (SWord16) (s1619 >> 16);
-  const SWord8  s1649 = (SWord8) s1648;
-  const SWord32 s1650 = table2[s1649];
-  const SWord32 s1651 = s1647 ^ s1650;
-  const SWord8  s1652 = (SWord8) (s1637 >> 8);
-  const SWord32 s1653 = table3[s1652];
-  const SWord32 s1654 = s1651 ^ s1653;
-  const SWord16 s1655 = (SWord16) s1585;
-  const SWord8  s1656 = (SWord8) s1655;
-  const SWord32 s1657 = table4[s1656];
-  const SWord32 s1658 = s1654 ^ s1657;
-  const SWord32 s1659 = s30 ^ s1658;
-  const SWord16 s1660 = (SWord16) s1659;
-  const SWord8  s1661 = (SWord8) (s1660 >> 8);
-  const SWord32 s1662 = table3[s1661];
-  const SWord32 s1663 = s1645 ^ s1662;
-  const SWord8  s1664 = (SWord8) (s1648 >> 8);
-  const SWord32 s1665 = table1[s1664];
-  const SWord8  s1666 = (SWord8) s1569;
-  const SWord32 s1667 = table2[s1666];
-  const SWord32 s1668 = s1665 ^ s1667;
-  const SWord8  s1669 = (SWord8) (s1655 >> 8);
-  const SWord32 s1670 = table3[s1669];
-  const SWord32 s1671 = s1668 ^ s1670;
-  const SWord8  s1672 = (SWord8) s1604;
-  const SWord32 s1673 = table4[s1672];
-  const SWord32 s1674 = s1671 ^ s1673;
-  const SWord32 s1675 = s31 ^ s1674;
-  const SWord16 s1676 = (SWord16) s1675;
-  const SWord8  s1677 = (SWord8) s1676;
-  const SWord32 s1678 = table4[s1677];
-  const SWord32 s1679 = s1663 ^ s1678;
-  const SWord32 s1680 = s32 ^ s1679;
-  const SWord16 s1681 = (SWord16) (s1680 >> 16);
-  const SWord8  s1682 = (SWord8) (s1681 >> 8);
-  const SWord32 s1683 = table1[s1682];
-  const SWord8  s1684 = (SWord8) (s1642 >> 8);
-  const SWord32 s1685 = table1[s1684];
-  const SWord16 s1686 = (SWord16) (s1659 >> 16);
-  const SWord8  s1687 = (SWord8) s1686;
-  const SWord32 s1688 = table2[s1687];
-  const SWord32 s1689 = s1685 ^ s1688;
-  const SWord8  s1690 = (SWord8) (s1676 >> 8);
-  const SWord32 s1691 = table3[s1690];
-  const SWord32 s1692 = s1689 ^ s1691;
-  const SWord16 s1693 = (SWord16) s1624;
-  const SWord8  s1694 = (SWord8) s1693;
-  const SWord32 s1695 = table4[s1694];
-  const SWord32 s1696 = s1692 ^ s1695;
-  const SWord32 s1697 = s33 ^ s1696;
-  const SWord16 s1698 = (SWord16) (s1697 >> 16);
-  const SWord8  s1699 = (SWord8) s1698;
-  const SWord32 s1700 = table2[s1699];
-  const SWord32 s1701 = s1683 ^ s1700;
-  const SWord8  s1702 = (SWord8) (s1686 >> 8);
-  const SWord32 s1703 = table1[s1702];
-  const SWord16 s1704 = (SWord16) (s1675 >> 16);
-  const SWord8  s1705 = (SWord8) s1704;
-  const SWord32 s1706 = table2[s1705];
-  const SWord32 s1707 = s1703 ^ s1706;
-  const SWord8  s1708 = (SWord8) (s1693 >> 8);
-  const SWord32 s1709 = table3[s1708];
-  const SWord32 s1710 = s1707 ^ s1709;
-  const SWord16 s1711 = (SWord16) s1641;
-  const SWord8  s1712 = (SWord8) s1711;
-  const SWord32 s1713 = table4[s1712];
-  const SWord32 s1714 = s1710 ^ s1713;
-  const SWord32 s1715 = s34 ^ s1714;
-  const SWord16 s1716 = (SWord16) s1715;
-  const SWord8  s1717 = (SWord8) (s1716 >> 8);
-  const SWord32 s1718 = table3[s1717];
-  const SWord32 s1719 = s1701 ^ s1718;
-  const SWord8  s1720 = (SWord8) (s1704 >> 8);
-  const SWord32 s1721 = table1[s1720];
-  const SWord8  s1722 = (SWord8) s1625;
-  const SWord32 s1723 = table2[s1722];
-  const SWord32 s1724 = s1721 ^ s1723;
-  const SWord8  s1725 = (SWord8) (s1711 >> 8);
-  const SWord32 s1726 = table3[s1725];
-  const SWord32 s1727 = s1724 ^ s1726;
-  const SWord8  s1728 = (SWord8) s1660;
-  const SWord32 s1729 = table4[s1728];
-  const SWord32 s1730 = s1727 ^ s1729;
-  const SWord32 s1731 = s35 ^ s1730;
-  const SWord16 s1732 = (SWord16) s1731;
-  const SWord8  s1733 = (SWord8) s1732;
-  const SWord32 s1734 = table4[s1733];
-  const SWord32 s1735 = s1719 ^ s1734;
-  const SWord32 s1736 = s36 ^ s1735;
-  const SWord16 s1737 = (SWord16) (s1736 >> 16);
-  const SWord8  s1738 = (SWord8) (s1737 >> 8);
-  const SWord32 s1739 = table1[s1738];
-  const SWord8  s1740 = (SWord8) (s1698 >> 8);
-  const SWord32 s1741 = table1[s1740];
-  const SWord16 s1742 = (SWord16) (s1715 >> 16);
-  const SWord8  s1743 = (SWord8) s1742;
-  const SWord32 s1744 = table2[s1743];
-  const SWord32 s1745 = s1741 ^ s1744;
-  const SWord8  s1746 = (SWord8) (s1732 >> 8);
-  const SWord32 s1747 = table3[s1746];
-  const SWord32 s1748 = s1745 ^ s1747;
-  const SWord16 s1749 = (SWord16) s1680;
-  const SWord8  s1750 = (SWord8) s1749;
-  const SWord32 s1751 = table4[s1750];
-  const SWord32 s1752 = s1748 ^ s1751;
-  const SWord32 s1753 = s37 ^ s1752;
-  const SWord16 s1754 = (SWord16) (s1753 >> 16);
-  const SWord8  s1755 = (SWord8) s1754;
-  const SWord32 s1756 = table2[s1755];
-  const SWord32 s1757 = s1739 ^ s1756;
-  const SWord8  s1758 = (SWord8) (s1742 >> 8);
-  const SWord32 s1759 = table1[s1758];
-  const SWord16 s1760 = (SWord16) (s1731 >> 16);
-  const SWord8  s1761 = (SWord8) s1760;
-  const SWord32 s1762 = table2[s1761];
-  const SWord32 s1763 = s1759 ^ s1762;
-  const SWord8  s1764 = (SWord8) (s1749 >> 8);
-  const SWord32 s1765 = table3[s1764];
-  const SWord32 s1766 = s1763 ^ s1765;
-  const SWord16 s1767 = (SWord16) s1697;
-  const SWord8  s1768 = (SWord8) s1767;
-  const SWord32 s1769 = table4[s1768];
-  const SWord32 s1770 = s1766 ^ s1769;
-  const SWord32 s1771 = s38 ^ s1770;
-  const SWord16 s1772 = (SWord16) s1771;
-  const SWord8  s1773 = (SWord8) (s1772 >> 8);
-  const SWord32 s1774 = table3[s1773];
-  const SWord32 s1775 = s1757 ^ s1774;
-  const SWord8  s1776 = (SWord8) (s1760 >> 8);
-  const SWord32 s1777 = table1[s1776];
-  const SWord8  s1778 = (SWord8) s1681;
-  const SWord32 s1779 = table2[s1778];
-  const SWord32 s1780 = s1777 ^ s1779;
-  const SWord8  s1781 = (SWord8) (s1767 >> 8);
-  const SWord32 s1782 = table3[s1781];
-  const SWord32 s1783 = s1780 ^ s1782;
-  const SWord8  s1784 = (SWord8) s1716;
-  const SWord32 s1785 = table4[s1784];
-  const SWord32 s1786 = s1783 ^ s1785;
-  const SWord32 s1787 = s39 ^ s1786;
-  const SWord16 s1788 = (SWord16) s1787;
-  const SWord8  s1789 = (SWord8) s1788;
-  const SWord32 s1790 = table4[s1789];
-  const SWord32 s1791 = s1775 ^ s1790;
-  const SWord32 s1792 = s40 ^ s1791;
-  const SWord16 s1793 = (SWord16) (s1792 >> 16);
-  const SWord8  s1794 = (SWord8) (s1793 >> 8);
-  const SWord8  s1795 = table0[s1794];
-  const SWord8  s1796 = (SWord8) (s1754 >> 8);
-  const SWord32 s1797 = table1[s1796];
-  const SWord16 s1798 = (SWord16) (s1771 >> 16);
-  const SWord8  s1799 = (SWord8) s1798;
-  const SWord32 s1800 = table2[s1799];
-  const SWord32 s1801 = s1797 ^ s1800;
-  const SWord8  s1802 = (SWord8) (s1788 >> 8);
-  const SWord32 s1803 = table3[s1802];
-  const SWord32 s1804 = s1801 ^ s1803;
-  const SWord16 s1805 = (SWord16) s1736;
-  const SWord8  s1806 = (SWord8) s1805;
-  const SWord32 s1807 = table4[s1806];
-  const SWord32 s1808 = s1804 ^ s1807;
-  const SWord32 s1809 = s41 ^ s1808;
-  const SWord16 s1810 = (SWord16) (s1809 >> 16);
-  const SWord8  s1811 = (SWord8) s1810;
-  const SWord8  s1812 = table0[s1811];
-  const SWord16 s1813 = (((SWord16) s1795) << 8) | ((SWord16) s1812);
-  const SWord8  s1814 = (SWord8) (s1798 >> 8);
-  const SWord32 s1815 = table1[s1814];
-  const SWord16 s1816 = (SWord16) (s1787 >> 16);
-  const SWord8  s1817 = (SWord8) s1816;
-  const SWord32 s1818 = table2[s1817];
-  const SWord32 s1819 = s1815 ^ s1818;
-  const SWord8  s1820 = (SWord8) (s1805 >> 8);
-  const SWord32 s1821 = table3[s1820];
-  const SWord32 s1822 = s1819 ^ s1821;
-  const SWord16 s1823 = (SWord16) s1753;
-  const SWord8  s1824 = (SWord8) s1823;
-  const SWord32 s1825 = table4[s1824];
-  const SWord32 s1826 = s1822 ^ s1825;
-  const SWord32 s1827 = s42 ^ s1826;
-  const SWord16 s1828 = (SWord16) s1827;
-  const SWord8  s1829 = (SWord8) (s1828 >> 8);
-  const SWord8  s1830 = table0[s1829];
-  const SWord8  s1831 = (SWord8) (s1816 >> 8);
-  const SWord32 s1832 = table1[s1831];
-  const SWord8  s1833 = (SWord8) s1737;
-  const SWord32 s1834 = table2[s1833];
-  const SWord32 s1835 = s1832 ^ s1834;
-  const SWord8  s1836 = (SWord8) (s1823 >> 8);
-  const SWord32 s1837 = table3[s1836];
-  const SWord32 s1838 = s1835 ^ s1837;
-  const SWord8  s1839 = (SWord8) s1772;
-  const SWord32 s1840 = table4[s1839];
-  const SWord32 s1841 = s1838 ^ s1840;
-  const SWord32 s1842 = s43 ^ s1841;
-  const SWord16 s1843 = (SWord16) s1842;
-  const SWord8  s1844 = (SWord8) s1843;
-  const SWord8  s1845 = table0[s1844];
-  const SWord16 s1846 = (((SWord16) s1830) << 8) | ((SWord16) s1845);
-  const SWord32 s1847 = (((SWord32) s1813) << 16) | ((SWord32) s1846);
-  const SWord32 s1848 = s44 ^ s1847;
-  const SWord8  s1849 = (SWord8) (s1810 >> 8);
-  const SWord8  s1850 = table0[s1849];
-  const SWord16 s1851 = (SWord16) (s1827 >> 16);
-  const SWord8  s1852 = (SWord8) s1851;
-  const SWord8  s1853 = table0[s1852];
-  const SWord16 s1854 = (((SWord16) s1850) << 8) | ((SWord16) s1853);
-  const SWord8  s1855 = (SWord8) (s1843 >> 8);
-  const SWord8  s1856 = table0[s1855];
-  const SWord16 s1857 = (SWord16) s1792;
-  const SWord8  s1858 = (SWord8) s1857;
-  const SWord8  s1859 = table0[s1858];
-  const SWord16 s1860 = (((SWord16) s1856) << 8) | ((SWord16) s1859);
-  const SWord32 s1861 = (((SWord32) s1854) << 16) | ((SWord32) s1860);
-  const SWord32 s1862 = s45 ^ s1861;
-  const SWord8  s1863 = (SWord8) (s1851 >> 8);
-  const SWord8  s1864 = table0[s1863];
-  const SWord16 s1865 = (SWord16) (s1842 >> 16);
-  const SWord8  s1866 = (SWord8) s1865;
-  const SWord8  s1867 = table0[s1866];
-  const SWord16 s1868 = (((SWord16) s1864) << 8) | ((SWord16) s1867);
-  const SWord8  s1869 = (SWord8) (s1857 >> 8);
-  const SWord8  s1870 = table0[s1869];
-  const SWord16 s1871 = (SWord16) s1809;
-  const SWord8  s1872 = (SWord8) s1871;
-  const SWord8  s1873 = table0[s1872];
-  const SWord16 s1874 = (((SWord16) s1870) << 8) | ((SWord16) s1873);
-  const SWord32 s1875 = (((SWord32) s1868) << 16) | ((SWord32) s1874);
-  const SWord32 s1876 = s46 ^ s1875;
-  const SWord8  s1877 = (SWord8) (s1865 >> 8);
-  const SWord8  s1878 = table0[s1877];
-  const SWord8  s1879 = (SWord8) s1793;
-  const SWord8  s1880 = table0[s1879];
-  const SWord16 s1881 = (((SWord16) s1878) << 8) | ((SWord16) s1880);
-  const SWord8  s1882 = (SWord8) (s1871 >> 8);
-  const SWord8  s1883 = table0[s1882];
-  const SWord8  s1884 = (SWord8) s1828;
-  const SWord8  s1885 = table0[s1884];
-  const SWord16 s1886 = (((SWord16) s1883) << 8) | ((SWord16) s1885);
-  const SWord32 s1887 = (((SWord32) s1881) << 16) | ((SWord32) s1886);
-  const SWord32 s1888 = s47 ^ s1887;
-
-  ct[0] = s1848;
-  ct[1] = s1862;
-  ct[2] = s1876;
-  ct[3] = s1888;
-}
-== END: "aes128BlockEncrypt.c" ==================
-== BEGIN: "aes128BlockDecrypt.c" ================
-/* File: "aes128BlockDecrypt.c". Automatically generated by SBV. Do not edit! */
-
-#include "aes128Lib.h"
-
-void aes128BlockDecrypt(const SWord32 *ct, const SWord32 *xkey,
-                        SWord32 *pt)
-{
-  const SWord32 s0 = ct[0];
-  const SWord32 s1 = ct[1];
-  const SWord32 s2 = ct[2];
-  const SWord32 s3 = ct[3];
-  const SWord32 s4 = xkey[0];
-  const SWord32 s5 = xkey[1];
-  const SWord32 s6 = xkey[2];
-  const SWord32 s7 = xkey[3];
-  const SWord32 s8 = xkey[4];
-  const SWord32 s9 = xkey[5];
-  const SWord32 s10 = xkey[6];
-  const SWord32 s11 = xkey[7];
-  const SWord32 s12 = xkey[8];
-  const SWord32 s13 = xkey[9];
-  const SWord32 s14 = xkey[10];
-  const SWord32 s15 = xkey[11];
-  const SWord32 s16 = xkey[12];
-  const SWord32 s17 = xkey[13];
-  const SWord32 s18 = xkey[14];
-  const SWord32 s19 = xkey[15];
-  const SWord32 s20 = xkey[16];
-  const SWord32 s21 = xkey[17];
-  const SWord32 s22 = xkey[18];
-  const SWord32 s23 = xkey[19];
-  const SWord32 s24 = xkey[20];
-  const SWord32 s25 = xkey[21];
-  const SWord32 s26 = xkey[22];
-  const SWord32 s27 = xkey[23];
-  const SWord32 s28 = xkey[24];
-  const SWord32 s29 = xkey[25];
-  const SWord32 s30 = xkey[26];
-  const SWord32 s31 = xkey[27];
-  const SWord32 s32 = xkey[28];
-  const SWord32 s33 = xkey[29];
-  const SWord32 s34 = xkey[30];
-  const SWord32 s35 = xkey[31];
-  const SWord32 s36 = xkey[32];
-  const SWord32 s37 = xkey[33];
-  const SWord32 s38 = xkey[34];
-  const SWord32 s39 = xkey[35];
-  const SWord32 s40 = xkey[36];
-  const SWord32 s41 = xkey[37];
-  const SWord32 s42 = xkey[38];
-  const SWord32 s43 = xkey[39];
-  const SWord32 s44 = xkey[40];
-  const SWord32 s45 = xkey[41];
-  const SWord32 s46 = xkey[42];
-  const SWord32 s47 = xkey[43];
-  static const SWord8 table0[] = {
-       82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129,
-      243, 215, 251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,
-       67,  68, 196, 222, 233, 203,  84, 123, 148,  50, 166, 194,  35,
-       61, 238,  76, 149,  11,  66, 250, 195,  78,   8,  46, 161, 102,
-       40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37, 114,
-      248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101,
-      182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,
-       87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10,
-      247, 228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,
-       63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,  58, 145,
-       17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230,
-      115, 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,
-       28, 117, 223, 110,  71, 241,  26, 113,  29,  41, 197, 137, 111,
-      183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 198, 210,
-      121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
-       51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
-       96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147,
-      201, 156, 239, 160, 224,  59,  77, 174,  42, 245, 176, 200, 235,
-      187,  60, 131,  83, 153,  97,  23,  43,   4, 126, 186, 119, 214,
-       38, 225, 105,  20,  99,  85,  33,  12, 125
-  };
-  static const SWord32 table1[] = {
-      0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
-      0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
-      0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
-      0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
-      0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
-      0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
-      0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
-      0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
-      0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
-      0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
-      0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
-      0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
-      0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
-      0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
-      0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
-      0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
-      0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
-      0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
-      0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
-      0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
-      0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
-      0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
-      0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
-      0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
-      0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
-      0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
-      0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
-      0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
-      0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
-      0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
-      0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
-      0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
-      0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
-      0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
-      0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
-      0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
-      0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
-      0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
-      0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
-      0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
-      0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
-      0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
-      0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
-      0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
-      0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
-      0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
-      0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
-      0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
-      0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
-      0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
-      0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
-      0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
-      0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
-      0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
-      0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
-      0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
-      0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
-      0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
-      0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
-      0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
-      0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
-      0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
-      0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
-      0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL
-  };
-  static const SWord32 table2[] = {
-      0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
-      0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
-      0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
-      0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
-      0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
-      0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
-      0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
-      0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
-      0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
-      0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
-      0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
-      0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
-      0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
-      0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
-      0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
-      0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
-      0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
-      0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
-      0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
-      0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
-      0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
-      0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
-      0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
-      0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
-      0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
-      0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
-      0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
-      0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
-      0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
-      0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
-      0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
-      0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
-      0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
-      0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
-      0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
-      0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
-      0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
-      0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
-      0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
-      0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
-      0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
-      0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
-      0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
-      0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
-      0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
-      0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
-      0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
-      0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
-      0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
-      0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
-      0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
-      0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
-      0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
-      0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
-      0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
-      0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
-      0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
-      0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
-      0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
-      0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
-      0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
-      0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
-      0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
-      0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL
-  };
-  static const SWord32 table3[] = {
-      0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
-      0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
-      0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
-      0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
-      0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
-      0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
-      0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
-      0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
-      0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
-      0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
-      0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
-      0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
-      0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
-      0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
-      0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
-      0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
-      0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
-      0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
-      0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
-      0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
-      0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
-      0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
-      0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
-      0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
-      0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
-      0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
-      0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
-      0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
-      0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
-      0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
-      0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
-      0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
-      0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
-      0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
-      0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
-      0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
-      0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
-      0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
-      0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
-      0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
-      0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
-      0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
-      0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
-      0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
-      0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
-      0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
-      0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
-      0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
-      0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
-      0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
-      0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
-      0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
-      0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
-      0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
-      0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
-      0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
-      0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
-      0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
-      0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
-      0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
-      0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
-      0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
-      0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
-      0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL
-  };
-  static const SWord32 table4[] = {
-      0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
-      0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
-      0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
-      0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
-      0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
-      0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
-      0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
-      0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
-      0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
-      0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
-      0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
-      0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
-      0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
-      0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
-      0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
-      0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
-      0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
-      0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
-      0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
-      0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
-      0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
-      0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
-      0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
-      0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
-      0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
-      0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
-      0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
-      0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
-      0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
-      0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
-      0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
-      0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
-      0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
-      0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
-      0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
-      0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
-      0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
-      0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
-      0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
-      0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
-      0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
-      0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
-      0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
-      0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
-      0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
-      0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
-      0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
-      0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
-      0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
-      0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
-      0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
-      0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
-      0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
-      0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
-      0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
-      0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
-      0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
-      0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
-      0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
-      0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
-      0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
-      0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
-      0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
-      0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL
-  };
-  const SWord32 s560 = s0 ^ s4;
-  const SWord16 s561 = (SWord16) (s560 >> 16);
-  const SWord8  s562 = (SWord8) (s561 >> 8);
-  const SWord32 s563 = table1[s562];
-  const SWord32 s819 = s3 ^ s7;
-  const SWord16 s820 = (SWord16) (s819 >> 16);
-  const SWord8  s821 = (SWord8) s820;
-  const SWord32 s822 = table2[s821];
-  const SWord32 s823 = s563 ^ s822;
-  const SWord32 s1079 = s2 ^ s6;
-  const SWord16 s1080 = (SWord16) s1079;
-  const SWord8  s1081 = (SWord8) (s1080 >> 8);
-  const SWord32 s1082 = table3[s1081];
-  const SWord32 s1083 = s823 ^ s1082;
-  const SWord32 s1339 = s1 ^ s5;
-  const SWord16 s1340 = (SWord16) s1339;
-  const SWord8  s1341 = (SWord8) s1340;
-  const SWord32 s1342 = table4[s1341];
-  const SWord32 s1343 = s1083 ^ s1342;
-  const SWord32 s1344 = s8 ^ s1343;
-  const SWord16 s1345 = (SWord16) (s1344 >> 16);
-  const SWord8  s1346 = (SWord8) (s1345 >> 8);
-  const SWord32 s1347 = table1[s1346];
-  const SWord8  s1348 = (SWord8) (s820 >> 8);
-  const SWord32 s1349 = table1[s1348];
-  const SWord16 s1350 = (SWord16) (s1079 >> 16);
-  const SWord8  s1351 = (SWord8) s1350;
-  const SWord32 s1352 = table2[s1351];
-  const SWord32 s1353 = s1349 ^ s1352;
-  const SWord8  s1354 = (SWord8) (s1340 >> 8);
-  const SWord32 s1355 = table3[s1354];
-  const SWord32 s1356 = s1353 ^ s1355;
-  const SWord16 s1357 = (SWord16) s560;
-  const SWord8  s1358 = (SWord8) s1357;
-  const SWord32 s1359 = table4[s1358];
-  const SWord32 s1360 = s1356 ^ s1359;
-  const SWord32 s1361 = s11 ^ s1360;
-  const SWord16 s1362 = (SWord16) (s1361 >> 16);
-  const SWord8  s1363 = (SWord8) s1362;
-  const SWord32 s1364 = table2[s1363];
-  const SWord32 s1365 = s1347 ^ s1364;
-  const SWord8  s1366 = (SWord8) (s1350 >> 8);
-  const SWord32 s1367 = table1[s1366];
-  const SWord16 s1368 = (SWord16) (s1339 >> 16);
-  const SWord8  s1369 = (SWord8) s1368;
-  const SWord32 s1370 = table2[s1369];
-  const SWord32 s1371 = s1367 ^ s1370;
-  const SWord8  s1372 = (SWord8) (s1357 >> 8);
-  const SWord32 s1373 = table3[s1372];
-  const SWord32 s1374 = s1371 ^ s1373;
-  const SWord16 s1375 = (SWord16) s819;
-  const SWord8  s1376 = (SWord8) s1375;
-  const SWord32 s1377 = table4[s1376];
-  const SWord32 s1378 = s1374 ^ s1377;
-  const SWord32 s1379 = s10 ^ s1378;
-  const SWord16 s1380 = (SWord16) s1379;
-  const SWord8  s1381 = (SWord8) (s1380 >> 8);
-  const SWord32 s1382 = table3[s1381];
-  const SWord32 s1383 = s1365 ^ s1382;
-  const SWord8  s1384 = (SWord8) (s1368 >> 8);
-  const SWord32 s1385 = table1[s1384];
-  const SWord8  s1386 = (SWord8) s561;
-  const SWord32 s1387 = table2[s1386];
-  const SWord32 s1388 = s1385 ^ s1387;
-  const SWord8  s1389 = (SWord8) (s1375 >> 8);
-  const SWord32 s1390 = table3[s1389];
-  const SWord32 s1391 = s1388 ^ s1390;
-  const SWord8  s1392 = (SWord8) s1080;
-  const SWord32 s1393 = table4[s1392];
-  const SWord32 s1394 = s1391 ^ s1393;
-  const SWord32 s1395 = s9 ^ s1394;
-  const SWord16 s1396 = (SWord16) s1395;
-  const SWord8  s1397 = (SWord8) s1396;
-  const SWord32 s1398 = table4[s1397];
-  const SWord32 s1399 = s1383 ^ s1398;
-  const SWord32 s1400 = s12 ^ s1399;
-  const SWord16 s1401 = (SWord16) (s1400 >> 16);
-  const SWord8  s1402 = (SWord8) (s1401 >> 8);
-  const SWord32 s1403 = table1[s1402];
-  const SWord8  s1404 = (SWord8) (s1362 >> 8);
-  const SWord32 s1405 = table1[s1404];
-  const SWord16 s1406 = (SWord16) (s1379 >> 16);
-  const SWord8  s1407 = (SWord8) s1406;
-  const SWord32 s1408 = table2[s1407];
-  const SWord32 s1409 = s1405 ^ s1408;
-  const SWord8  s1410 = (SWord8) (s1396 >> 8);
-  const SWord32 s1411 = table3[s1410];
-  const SWord32 s1412 = s1409 ^ s1411;
-  const SWord16 s1413 = (SWord16) s1344;
-  const SWord8  s1414 = (SWord8) s1413;
-  const SWord32 s1415 = table4[s1414];
-  const SWord32 s1416 = s1412 ^ s1415;
-  const SWord32 s1417 = s15 ^ s1416;
-  const SWord16 s1418 = (SWord16) (s1417 >> 16);
-  const SWord8  s1419 = (SWord8) s1418;
-  const SWord32 s1420 = table2[s1419];
-  const SWord32 s1421 = s1403 ^ s1420;
-  const SWord8  s1422 = (SWord8) (s1406 >> 8);
-  const SWord32 s1423 = table1[s1422];
-  const SWord16 s1424 = (SWord16) (s1395 >> 16);
-  const SWord8  s1425 = (SWord8) s1424;
-  const SWord32 s1426 = table2[s1425];
-  const SWord32 s1427 = s1423 ^ s1426;
-  const SWord8  s1428 = (SWord8) (s1413 >> 8);
-  const SWord32 s1429 = table3[s1428];
-  const SWord32 s1430 = s1427 ^ s1429;
-  const SWord16 s1431 = (SWord16) s1361;
-  const SWord8  s1432 = (SWord8) s1431;
-  const SWord32 s1433 = table4[s1432];
-  const SWord32 s1434 = s1430 ^ s1433;
-  const SWord32 s1435 = s14 ^ s1434;
-  const SWord16 s1436 = (SWord16) s1435;
-  const SWord8  s1437 = (SWord8) (s1436 >> 8);
-  const SWord32 s1438 = table3[s1437];
-  const SWord32 s1439 = s1421 ^ s1438;
-  const SWord8  s1440 = (SWord8) (s1424 >> 8);
-  const SWord32 s1441 = table1[s1440];
-  const SWord8  s1442 = (SWord8) s1345;
-  const SWord32 s1443 = table2[s1442];
-  const SWord32 s1444 = s1441 ^ s1443;
-  const SWord8  s1445 = (SWord8) (s1431 >> 8);
-  const SWord32 s1446 = table3[s1445];
-  const SWord32 s1447 = s1444 ^ s1446;
-  const SWord8  s1448 = (SWord8) s1380;
-  const SWord32 s1449 = table4[s1448];
-  const SWord32 s1450 = s1447 ^ s1449;
-  const SWord32 s1451 = s13 ^ s1450;
-  const SWord16 s1452 = (SWord16) s1451;
-  const SWord8  s1453 = (SWord8) s1452;
-  const SWord32 s1454 = table4[s1453];
-  const SWord32 s1455 = s1439 ^ s1454;
-  const SWord32 s1456 = s16 ^ s1455;
-  const SWord16 s1457 = (SWord16) (s1456 >> 16);
-  const SWord8  s1458 = (SWord8) (s1457 >> 8);
-  const SWord32 s1459 = table1[s1458];
-  const SWord8  s1460 = (SWord8) (s1418 >> 8);
-  const SWord32 s1461 = table1[s1460];
-  const SWord16 s1462 = (SWord16) (s1435 >> 16);
-  const SWord8  s1463 = (SWord8) s1462;
-  const SWord32 s1464 = table2[s1463];
-  const SWord32 s1465 = s1461 ^ s1464;
-  const SWord8  s1466 = (SWord8) (s1452 >> 8);
-  const SWord32 s1467 = table3[s1466];
-  const SWord32 s1468 = s1465 ^ s1467;
-  const SWord16 s1469 = (SWord16) s1400;
-  const SWord8  s1470 = (SWord8) s1469;
-  const SWord32 s1471 = table4[s1470];
-  const SWord32 s1472 = s1468 ^ s1471;
-  const SWord32 s1473 = s19 ^ s1472;
-  const SWord16 s1474 = (SWord16) (s1473 >> 16);
-  const SWord8  s1475 = (SWord8) s1474;
-  const SWord32 s1476 = table2[s1475];
-  const SWord32 s1477 = s1459 ^ s1476;
-  const SWord8  s1478 = (SWord8) (s1462 >> 8);
-  const SWord32 s1479 = table1[s1478];
-  const SWord16 s1480 = (SWord16) (s1451 >> 16);
-  const SWord8  s1481 = (SWord8) s1480;
-  const SWord32 s1482 = table2[s1481];
-  const SWord32 s1483 = s1479 ^ s1482;
-  const SWord8  s1484 = (SWord8) (s1469 >> 8);
-  const SWord32 s1485 = table3[s1484];
-  const SWord32 s1486 = s1483 ^ s1485;
-  const SWord16 s1487 = (SWord16) s1417;
-  const SWord8  s1488 = (SWord8) s1487;
-  const SWord32 s1489 = table4[s1488];
-  const SWord32 s1490 = s1486 ^ s1489;
-  const SWord32 s1491 = s18 ^ s1490;
-  const SWord16 s1492 = (SWord16) s1491;
-  const SWord8  s1493 = (SWord8) (s1492 >> 8);
-  const SWord32 s1494 = table3[s1493];
-  const SWord32 s1495 = s1477 ^ s1494;
-  const SWord8  s1496 = (SWord8) (s1480 >> 8);
-  const SWord32 s1497 = table1[s1496];
-  const SWord8  s1498 = (SWord8) s1401;
-  const SWord32 s1499 = table2[s1498];
-  const SWord32 s1500 = s1497 ^ s1499;
-  const SWord8  s1501 = (SWord8) (s1487 >> 8);
-  const SWord32 s1502 = table3[s1501];
-  const SWord32 s1503 = s1500 ^ s1502;
-  const SWord8  s1504 = (SWord8) s1436;
-  const SWord32 s1505 = table4[s1504];
-  const SWord32 s1506 = s1503 ^ s1505;
-  const SWord32 s1507 = s17 ^ s1506;
-  const SWord16 s1508 = (SWord16) s1507;
-  const SWord8  s1509 = (SWord8) s1508;
-  const SWord32 s1510 = table4[s1509];
-  const SWord32 s1511 = s1495 ^ s1510;
-  const SWord32 s1512 = s20 ^ s1511;
-  const SWord16 s1513 = (SWord16) (s1512 >> 16);
-  const SWord8  s1514 = (SWord8) (s1513 >> 8);
-  const SWord32 s1515 = table1[s1514];
-  const SWord8  s1516 = (SWord8) (s1474 >> 8);
-  const SWord32 s1517 = table1[s1516];
-  const SWord16 s1518 = (SWord16) (s1491 >> 16);
-  const SWord8  s1519 = (SWord8) s1518;
-  const SWord32 s1520 = table2[s1519];
-  const SWord32 s1521 = s1517 ^ s1520;
-  const SWord8  s1522 = (SWord8) (s1508 >> 8);
-  const SWord32 s1523 = table3[s1522];
-  const SWord32 s1524 = s1521 ^ s1523;
-  const SWord16 s1525 = (SWord16) s1456;
-  const SWord8  s1526 = (SWord8) s1525;
-  const SWord32 s1527 = table4[s1526];
-  const SWord32 s1528 = s1524 ^ s1527;
-  const SWord32 s1529 = s23 ^ s1528;
-  const SWord16 s1530 = (SWord16) (s1529 >> 16);
-  const SWord8  s1531 = (SWord8) s1530;
-  const SWord32 s1532 = table2[s1531];
-  const SWord32 s1533 = s1515 ^ s1532;
-  const SWord8  s1534 = (SWord8) (s1518 >> 8);
-  const SWord32 s1535 = table1[s1534];
-  const SWord16 s1536 = (SWord16) (s1507 >> 16);
-  const SWord8  s1537 = (SWord8) s1536;
-  const SWord32 s1538 = table2[s1537];
-  const SWord32 s1539 = s1535 ^ s1538;
-  const SWord8  s1540 = (SWord8) (s1525 >> 8);
-  const SWord32 s1541 = table3[s1540];
-  const SWord32 s1542 = s1539 ^ s1541;
-  const SWord16 s1543 = (SWord16) s1473;
-  const SWord8  s1544 = (SWord8) s1543;
-  const SWord32 s1545 = table4[s1544];
-  const SWord32 s1546 = s1542 ^ s1545;
-  const SWord32 s1547 = s22 ^ s1546;
-  const SWord16 s1548 = (SWord16) s1547;
-  const SWord8  s1549 = (SWord8) (s1548 >> 8);
-  const SWord32 s1550 = table3[s1549];
-  const SWord32 s1551 = s1533 ^ s1550;
-  const SWord8  s1552 = (SWord8) (s1536 >> 8);
-  const SWord32 s1553 = table1[s1552];
-  const SWord8  s1554 = (SWord8) s1457;
-  const SWord32 s1555 = table2[s1554];
-  const SWord32 s1556 = s1553 ^ s1555;
-  const SWord8  s1557 = (SWord8) (s1543 >> 8);
-  const SWord32 s1558 = table3[s1557];
-  const SWord32 s1559 = s1556 ^ s1558;
-  const SWord8  s1560 = (SWord8) s1492;
-  const SWord32 s1561 = table4[s1560];
-  const SWord32 s1562 = s1559 ^ s1561;
-  const SWord32 s1563 = s21 ^ s1562;
-  const SWord16 s1564 = (SWord16) s1563;
-  const SWord8  s1565 = (SWord8) s1564;
-  const SWord32 s1566 = table4[s1565];
-  const SWord32 s1567 = s1551 ^ s1566;
-  const SWord32 s1568 = s24 ^ s1567;
-  const SWord16 s1569 = (SWord16) (s1568 >> 16);
-  const SWord8  s1570 = (SWord8) (s1569 >> 8);
-  const SWord32 s1571 = table1[s1570];
-  const SWord8  s1572 = (SWord8) (s1530 >> 8);
-  const SWord32 s1573 = table1[s1572];
-  const SWord16 s1574 = (SWord16) (s1547 >> 16);
-  const SWord8  s1575 = (SWord8) s1574;
-  const SWord32 s1576 = table2[s1575];
-  const SWord32 s1577 = s1573 ^ s1576;
-  const SWord8  s1578 = (SWord8) (s1564 >> 8);
-  const SWord32 s1579 = table3[s1578];
-  const SWord32 s1580 = s1577 ^ s1579;
-  const SWord16 s1581 = (SWord16) s1512;
-  const SWord8  s1582 = (SWord8) s1581;
-  const SWord32 s1583 = table4[s1582];
-  const SWord32 s1584 = s1580 ^ s1583;
-  const SWord32 s1585 = s27 ^ s1584;
-  const SWord16 s1586 = (SWord16) (s1585 >> 16);
-  const SWord8  s1587 = (SWord8) s1586;
-  const SWord32 s1588 = table2[s1587];
-  const SWord32 s1589 = s1571 ^ s1588;
-  const SWord8  s1590 = (SWord8) (s1574 >> 8);
-  const SWord32 s1591 = table1[s1590];
-  const SWord16 s1592 = (SWord16) (s1563 >> 16);
-  const SWord8  s1593 = (SWord8) s1592;
-  const SWord32 s1594 = table2[s1593];
-  const SWord32 s1595 = s1591 ^ s1594;
-  const SWord8  s1596 = (SWord8) (s1581 >> 8);
-  const SWord32 s1597 = table3[s1596];
-  const SWord32 s1598 = s1595 ^ s1597;
-  const SWord16 s1599 = (SWord16) s1529;
-  const SWord8  s1600 = (SWord8) s1599;
-  const SWord32 s1601 = table4[s1600];
-  const SWord32 s1602 = s1598 ^ s1601;
-  const SWord32 s1603 = s26 ^ s1602;
-  const SWord16 s1604 = (SWord16) s1603;
-  const SWord8  s1605 = (SWord8) (s1604 >> 8);
-  const SWord32 s1606 = table3[s1605];
-  const SWord32 s1607 = s1589 ^ s1606;
-  const SWord8  s1608 = (SWord8) (s1592 >> 8);
-  const SWord32 s1609 = table1[s1608];
-  const SWord8  s1610 = (SWord8) s1513;
-  const SWord32 s1611 = table2[s1610];
-  const SWord32 s1612 = s1609 ^ s1611;
-  const SWord8  s1613 = (SWord8) (s1599 >> 8);
-  const SWord32 s1614 = table3[s1613];
-  const SWord32 s1615 = s1612 ^ s1614;
-  const SWord8  s1616 = (SWord8) s1548;
-  const SWord32 s1617 = table4[s1616];
-  const SWord32 s1618 = s1615 ^ s1617;
-  const SWord32 s1619 = s25 ^ s1618;
-  const SWord16 s1620 = (SWord16) s1619;
-  const SWord8  s1621 = (SWord8) s1620;
-  const SWord32 s1622 = table4[s1621];
-  const SWord32 s1623 = s1607 ^ s1622;
-  const SWord32 s1624 = s28 ^ s1623;
-  const SWord16 s1625 = (SWord16) (s1624 >> 16);
-  const SWord8  s1626 = (SWord8) (s1625 >> 8);
-  const SWord32 s1627 = table1[s1626];
-  const SWord8  s1628 = (SWord8) (s1586 >> 8);
-  const SWord32 s1629 = table1[s1628];
-  const SWord16 s1630 = (SWord16) (s1603 >> 16);
-  const SWord8  s1631 = (SWord8) s1630;
-  const SWord32 s1632 = table2[s1631];
-  const SWord32 s1633 = s1629 ^ s1632;
-  const SWord8  s1634 = (SWord8) (s1620 >> 8);
-  const SWord32 s1635 = table3[s1634];
-  const SWord32 s1636 = s1633 ^ s1635;
-  const SWord16 s1637 = (SWord16) s1568;
-  const SWord8  s1638 = (SWord8) s1637;
-  const SWord32 s1639 = table4[s1638];
-  const SWord32 s1640 = s1636 ^ s1639;
-  const SWord32 s1641 = s31 ^ s1640;
-  const SWord16 s1642 = (SWord16) (s1641 >> 16);
-  const SWord8  s1643 = (SWord8) s1642;
-  const SWord32 s1644 = table2[s1643];
-  const SWord32 s1645 = s1627 ^ s1644;
-  const SWord8  s1646 = (SWord8) (s1630 >> 8);
-  const SWord32 s1647 = table1[s1646];
-  const SWord16 s1648 = (SWord16) (s1619 >> 16);
-  const SWord8  s1649 = (SWord8) s1648;
-  const SWord32 s1650 = table2[s1649];
-  const SWord32 s1651 = s1647 ^ s1650;
-  const SWord8  s1652 = (SWord8) (s1637 >> 8);
-  const SWord32 s1653 = table3[s1652];
-  const SWord32 s1654 = s1651 ^ s1653;
-  const SWord16 s1655 = (SWord16) s1585;
-  const SWord8  s1656 = (SWord8) s1655;
-  const SWord32 s1657 = table4[s1656];
-  const SWord32 s1658 = s1654 ^ s1657;
-  const SWord32 s1659 = s30 ^ s1658;
-  const SWord16 s1660 = (SWord16) s1659;
-  const SWord8  s1661 = (SWord8) (s1660 >> 8);
-  const SWord32 s1662 = table3[s1661];
-  const SWord32 s1663 = s1645 ^ s1662;
-  const SWord8  s1664 = (SWord8) (s1648 >> 8);
-  const SWord32 s1665 = table1[s1664];
-  const SWord8  s1666 = (SWord8) s1569;
-  const SWord32 s1667 = table2[s1666];
-  const SWord32 s1668 = s1665 ^ s1667;
-  const SWord8  s1669 = (SWord8) (s1655 >> 8);
-  const SWord32 s1670 = table3[s1669];
-  const SWord32 s1671 = s1668 ^ s1670;
-  const SWord8  s1672 = (SWord8) s1604;
-  const SWord32 s1673 = table4[s1672];
-  const SWord32 s1674 = s1671 ^ s1673;
-  const SWord32 s1675 = s29 ^ s1674;
-  const SWord16 s1676 = (SWord16) s1675;
-  const SWord8  s1677 = (SWord8) s1676;
-  const SWord32 s1678 = table4[s1677];
-  const SWord32 s1679 = s1663 ^ s1678;
-  const SWord32 s1680 = s32 ^ s1679;
-  const SWord16 s1681 = (SWord16) (s1680 >> 16);
-  const SWord8  s1682 = (SWord8) (s1681 >> 8);
-  const SWord32 s1683 = table1[s1682];
-  const SWord8  s1684 = (SWord8) (s1642 >> 8);
-  const SWord32 s1685 = table1[s1684];
-  const SWord16 s1686 = (SWord16) (s1659 >> 16);
-  const SWord8  s1687 = (SWord8) s1686;
-  const SWord32 s1688 = table2[s1687];
-  const SWord32 s1689 = s1685 ^ s1688;
-  const SWord8  s1690 = (SWord8) (s1676 >> 8);
-  const SWord32 s1691 = table3[s1690];
-  const SWord32 s1692 = s1689 ^ s1691;
-  const SWord16 s1693 = (SWord16) s1624;
-  const SWord8  s1694 = (SWord8) s1693;
-  const SWord32 s1695 = table4[s1694];
-  const SWord32 s1696 = s1692 ^ s1695;
-  const SWord32 s1697 = s35 ^ s1696;
-  const SWord16 s1698 = (SWord16) (s1697 >> 16);
-  const SWord8  s1699 = (SWord8) s1698;
-  const SWord32 s1700 = table2[s1699];
-  const SWord32 s1701 = s1683 ^ s1700;
-  const SWord8  s1702 = (SWord8) (s1686 >> 8);
-  const SWord32 s1703 = table1[s1702];
-  const SWord16 s1704 = (SWord16) (s1675 >> 16);
-  const SWord8  s1705 = (SWord8) s1704;
-  const SWord32 s1706 = table2[s1705];
-  const SWord32 s1707 = s1703 ^ s1706;
-  const SWord8  s1708 = (SWord8) (s1693 >> 8);
-  const SWord32 s1709 = table3[s1708];
-  const SWord32 s1710 = s1707 ^ s1709;
-  const SWord16 s1711 = (SWord16) s1641;
-  const SWord8  s1712 = (SWord8) s1711;
-  const SWord32 s1713 = table4[s1712];
-  const SWord32 s1714 = s1710 ^ s1713;
-  const SWord32 s1715 = s34 ^ s1714;
-  const SWord16 s1716 = (SWord16) s1715;
-  const SWord8  s1717 = (SWord8) (s1716 >> 8);
-  const SWord32 s1718 = table3[s1717];
-  const SWord32 s1719 = s1701 ^ s1718;
-  const SWord8  s1720 = (SWord8) (s1704 >> 8);
-  const SWord32 s1721 = table1[s1720];
-  const SWord8  s1722 = (SWord8) s1625;
-  const SWord32 s1723 = table2[s1722];
-  const SWord32 s1724 = s1721 ^ s1723;
-  const SWord8  s1725 = (SWord8) (s1711 >> 8);
-  const SWord32 s1726 = table3[s1725];
-  const SWord32 s1727 = s1724 ^ s1726;
-  const SWord8  s1728 = (SWord8) s1660;
-  const SWord32 s1729 = table4[s1728];
-  const SWord32 s1730 = s1727 ^ s1729;
-  const SWord32 s1731 = s33 ^ s1730;
-  const SWord16 s1732 = (SWord16) s1731;
-  const SWord8  s1733 = (SWord8) s1732;
-  const SWord32 s1734 = table4[s1733];
-  const SWord32 s1735 = s1719 ^ s1734;
-  const SWord32 s1736 = s36 ^ s1735;
-  const SWord16 s1737 = (SWord16) (s1736 >> 16);
-  const SWord8  s1738 = (SWord8) (s1737 >> 8);
-  const SWord32 s1739 = table1[s1738];
-  const SWord8  s1740 = (SWord8) (s1698 >> 8);
-  const SWord32 s1741 = table1[s1740];
-  const SWord16 s1742 = (SWord16) (s1715 >> 16);
-  const SWord8  s1743 = (SWord8) s1742;
-  const SWord32 s1744 = table2[s1743];
-  const SWord32 s1745 = s1741 ^ s1744;
-  const SWord8  s1746 = (SWord8) (s1732 >> 8);
-  const SWord32 s1747 = table3[s1746];
-  const SWord32 s1748 = s1745 ^ s1747;
-  const SWord16 s1749 = (SWord16) s1680;
-  const SWord8  s1750 = (SWord8) s1749;
-  const SWord32 s1751 = table4[s1750];
-  const SWord32 s1752 = s1748 ^ s1751;
-  const SWord32 s1753 = s39 ^ s1752;
-  const SWord16 s1754 = (SWord16) (s1753 >> 16);
-  const SWord8  s1755 = (SWord8) s1754;
-  const SWord32 s1756 = table2[s1755];
-  const SWord32 s1757 = s1739 ^ s1756;
-  const SWord8  s1758 = (SWord8) (s1742 >> 8);
-  const SWord32 s1759 = table1[s1758];
-  const SWord16 s1760 = (SWord16) (s1731 >> 16);
-  const SWord8  s1761 = (SWord8) s1760;
-  const SWord32 s1762 = table2[s1761];
-  const SWord32 s1763 = s1759 ^ s1762;
-  const SWord8  s1764 = (SWord8) (s1749 >> 8);
-  const SWord32 s1765 = table3[s1764];
-  const SWord32 s1766 = s1763 ^ s1765;
-  const SWord16 s1767 = (SWord16) s1697;
-  const SWord8  s1768 = (SWord8) s1767;
-  const SWord32 s1769 = table4[s1768];
-  const SWord32 s1770 = s1766 ^ s1769;
-  const SWord32 s1771 = s38 ^ s1770;
-  const SWord16 s1772 = (SWord16) s1771;
-  const SWord8  s1773 = (SWord8) (s1772 >> 8);
-  const SWord32 s1774 = table3[s1773];
-  const SWord32 s1775 = s1757 ^ s1774;
-  const SWord8  s1776 = (SWord8) (s1760 >> 8);
-  const SWord32 s1777 = table1[s1776];
-  const SWord8  s1778 = (SWord8) s1681;
-  const SWord32 s1779 = table2[s1778];
-  const SWord32 s1780 = s1777 ^ s1779;
-  const SWord8  s1781 = (SWord8) (s1767 >> 8);
-  const SWord32 s1782 = table3[s1781];
-  const SWord32 s1783 = s1780 ^ s1782;
-  const SWord8  s1784 = (SWord8) s1716;
-  const SWord32 s1785 = table4[s1784];
-  const SWord32 s1786 = s1783 ^ s1785;
-  const SWord32 s1787 = s37 ^ s1786;
-  const SWord16 s1788 = (SWord16) s1787;
-  const SWord8  s1789 = (SWord8) s1788;
-  const SWord32 s1790 = table4[s1789];
-  const SWord32 s1791 = s1775 ^ s1790;
-  const SWord32 s1792 = s40 ^ s1791;
-  const SWord16 s1793 = (SWord16) (s1792 >> 16);
-  const SWord8  s1794 = (SWord8) (s1793 >> 8);
-  const SWord8  s1795 = table0[s1794];
-  const SWord8  s1796 = (SWord8) (s1754 >> 8);
-  const SWord32 s1797 = table1[s1796];
-  const SWord16 s1798 = (SWord16) (s1771 >> 16);
-  const SWord8  s1799 = (SWord8) s1798;
-  const SWord32 s1800 = table2[s1799];
-  const SWord32 s1801 = s1797 ^ s1800;
-  const SWord8  s1802 = (SWord8) (s1788 >> 8);
-  const SWord32 s1803 = table3[s1802];
-  const SWord32 s1804 = s1801 ^ s1803;
-  const SWord16 s1805 = (SWord16) s1736;
-  const SWord8  s1806 = (SWord8) s1805;
-  const SWord32 s1807 = table4[s1806];
-  const SWord32 s1808 = s1804 ^ s1807;
-  const SWord32 s1809 = s43 ^ s1808;
-  const SWord16 s1810 = (SWord16) (s1809 >> 16);
-  const SWord8  s1811 = (SWord8) s1810;
-  const SWord8  s1812 = table0[s1811];
-  const SWord16 s1813 = (((SWord16) s1795) << 8) | ((SWord16) s1812);
-  const SWord8  s1814 = (SWord8) (s1798 >> 8);
-  const SWord32 s1815 = table1[s1814];
-  const SWord16 s1816 = (SWord16) (s1787 >> 16);
-  const SWord8  s1817 = (SWord8) s1816;
-  const SWord32 s1818 = table2[s1817];
-  const SWord32 s1819 = s1815 ^ s1818;
-  const SWord8  s1820 = (SWord8) (s1805 >> 8);
-  const SWord32 s1821 = table3[s1820];
-  const SWord32 s1822 = s1819 ^ s1821;
-  const SWord16 s1823 = (SWord16) s1753;
-  const SWord8  s1824 = (SWord8) s1823;
-  const SWord32 s1825 = table4[s1824];
-  const SWord32 s1826 = s1822 ^ s1825;
-  const SWord32 s1827 = s42 ^ s1826;
-  const SWord16 s1828 = (SWord16) s1827;
-  const SWord8  s1829 = (SWord8) (s1828 >> 8);
-  const SWord8  s1830 = table0[s1829];
-  const SWord8  s1831 = (SWord8) (s1816 >> 8);
-  const SWord32 s1832 = table1[s1831];
-  const SWord8  s1833 = (SWord8) s1737;
-  const SWord32 s1834 = table2[s1833];
-  const SWord32 s1835 = s1832 ^ s1834;
-  const SWord8  s1836 = (SWord8) (s1823 >> 8);
-  const SWord32 s1837 = table3[s1836];
-  const SWord32 s1838 = s1835 ^ s1837;
-  const SWord8  s1839 = (SWord8) s1772;
-  const SWord32 s1840 = table4[s1839];
-  const SWord32 s1841 = s1838 ^ s1840;
-  const SWord32 s1842 = s41 ^ s1841;
-  const SWord16 s1843 = (SWord16) s1842;
-  const SWord8  s1844 = (SWord8) s1843;
-  const SWord8  s1845 = table0[s1844];
-  const SWord16 s1846 = (((SWord16) s1830) << 8) | ((SWord16) s1845);
-  const SWord32 s1847 = (((SWord32) s1813) << 16) | ((SWord32) s1846);
-  const SWord32 s1848 = s44 ^ s1847;
-  const SWord16 s1849 = (SWord16) (s1842 >> 16);
-  const SWord8  s1850 = (SWord8) (s1849 >> 8);
-  const SWord8  s1851 = table0[s1850];
-  const SWord8  s1852 = (SWord8) s1793;
-  const SWord8  s1853 = table0[s1852];
-  const SWord16 s1854 = (((SWord16) s1851) << 8) | ((SWord16) s1853);
-  const SWord16 s1855 = (SWord16) s1809;
-  const SWord8  s1856 = (SWord8) (s1855 >> 8);
-  const SWord8  s1857 = table0[s1856];
-  const SWord8  s1858 = (SWord8) s1828;
-  const SWord8  s1859 = table0[s1858];
-  const SWord16 s1860 = (((SWord16) s1857) << 8) | ((SWord16) s1859);
-  const SWord32 s1861 = (((SWord32) s1854) << 16) | ((SWord32) s1860);
-  const SWord32 s1862 = s45 ^ s1861;
-  const SWord16 s1863 = (SWord16) (s1827 >> 16);
-  const SWord8  s1864 = (SWord8) (s1863 >> 8);
-  const SWord8  s1865 = table0[s1864];
-  const SWord8  s1866 = (SWord8) s1849;
-  const SWord8  s1867 = table0[s1866];
-  const SWord16 s1868 = (((SWord16) s1865) << 8) | ((SWord16) s1867);
-  const SWord16 s1869 = (SWord16) s1792;
-  const SWord8  s1870 = (SWord8) (s1869 >> 8);
-  const SWord8  s1871 = table0[s1870];
-  const SWord8  s1872 = (SWord8) s1855;
-  const SWord8  s1873 = table0[s1872];
-  const SWord16 s1874 = (((SWord16) s1871) << 8) | ((SWord16) s1873);
-  const SWord32 s1875 = (((SWord32) s1868) << 16) | ((SWord32) s1874);
-  const SWord32 s1876 = s46 ^ s1875;
-  const SWord8  s1877 = (SWord8) (s1810 >> 8);
-  const SWord8  s1878 = table0[s1877];
-  const SWord8  s1879 = (SWord8) s1863;
-  const SWord8  s1880 = table0[s1879];
-  const SWord16 s1881 = (((SWord16) s1878) << 8) | ((SWord16) s1880);
-  const SWord8  s1882 = (SWord8) (s1843 >> 8);
-  const SWord8  s1883 = table0[s1882];
-  const SWord8  s1884 = (SWord8) s1869;
-  const SWord8  s1885 = table0[s1884];
-  const SWord16 s1886 = (((SWord16) s1883) << 8) | ((SWord16) s1885);
-  const SWord32 s1887 = (((SWord32) s1881) << 16) | ((SWord32) s1886);
-  const SWord32 s1888 = s47 ^ s1887;
-
-  pt[0] = s1848;
-  pt[1] = s1862;
-  pt[2] = s1876;
-  pt[3] = s1888;
-}
-== END: "aes128BlockDecrypt.c" ==================
-== BEGIN: "aes128Lib.h" ================
-/* Header file for aes128Lib. Automatically generated by SBV. Do not edit! */
-
-#ifndef __aes128Lib__HEADER_INCLUDED__
-#define __aes128Lib__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototypes: */
-void aes128KeySchedule(const SWord32 *key, SWord32 *encKS,
-                       SWord32 *decKS);
-void aes128BlockEncrypt(const SWord32 *pt, const SWord32 *xkey,
-                        SWord32 *ct);
-void aes128BlockDecrypt(const SWord32 *ct, const SWord32 *xkey,
-                        SWord32 *pt);
-
-#endif /* __aes128Lib__HEADER_INCLUDED__ */
-== END: "aes128Lib.h" ==================
-== BEGIN: "aes128Lib_driver.c" ================
-/* Example driver program for aes128Lib. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "aes128Lib.h"
-
-void aes128KeySchedule_driver(void)
-{
-  const SWord32 key[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array key:\n");
-  int key_ctr;
-  for(key_ctr = 0; key_ctr < 4 ; ++key_ctr)
-    printf("  key[%d] = 0x%08"PRIx32"UL\n", key_ctr ,key[key_ctr]);
-
-  SWord32 encKS[44];
-  SWord32 decKS[44];
-
-  aes128KeySchedule(key, encKS, decKS);
-
-  printf("aes128KeySchedule(key, encKS, decKS) ->\n");
-  int encKS_ctr;
-  for(encKS_ctr = 0; encKS_ctr < 44 ; ++encKS_ctr)
-    printf("  encKS[%d] = 0x%08"PRIx32"UL\n", encKS_ctr ,encKS[encKS_ctr]);
-  int decKS_ctr;
-  for(decKS_ctr = 0; decKS_ctr < 44 ; ++decKS_ctr)
-    printf("  decKS[%d] = 0x%08"PRIx32"UL\n", decKS_ctr ,decKS[decKS_ctr]);
-}
-
-void aes128BlockEncrypt_driver(void)
-{
-  const SWord32 pt[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array pt:\n");
-  int pt_ctr;
-  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
-    printf("  pt[%d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
-
-  const SWord32 xkey[44] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array xkey:\n");
-  int xkey_ctr;
-  for(xkey_ctr = 0; xkey_ctr < 44 ; ++xkey_ctr)
-    printf("  xkey[%d] = 0x%08"PRIx32"UL\n", xkey_ctr ,xkey[xkey_ctr]);
-
-  SWord32 ct[4];
-
-  aes128BlockEncrypt(pt, xkey, ct);
-
-  printf("aes128BlockEncrypt(pt, xkey, ct) ->\n");
-  int ct_ctr;
-  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
-    printf("  ct[%d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
-}
-
-void aes128BlockDecrypt_driver(void)
-{
-  const SWord32 ct[4] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array ct:\n");
-  int ct_ctr;
-  for(ct_ctr = 0; ct_ctr < 4 ; ++ct_ctr)
-    printf("  ct[%d] = 0x%08"PRIx32"UL\n", ct_ctr ,ct[ct_ctr]);
-
-  const SWord32 xkey[44] = {
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
-      0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL
-  };
-
-  printf("Contents of input array xkey:\n");
-  int xkey_ctr;
-  for(xkey_ctr = 0; xkey_ctr < 44 ; ++xkey_ctr)
-    printf("  xkey[%d] = 0x%08"PRIx32"UL\n", xkey_ctr ,xkey[xkey_ctr]);
-
-  SWord32 pt[4];
-
-  aes128BlockDecrypt(ct, xkey, pt);
-
-  printf("aes128BlockDecrypt(ct, xkey, pt) ->\n");
-  int pt_ctr;
-  for(pt_ctr = 0; pt_ctr < 4 ; ++pt_ctr)
-    printf("  pt[%d] = 0x%08"PRIx32"UL\n", pt_ctr ,pt[pt_ctr]);
-}
-
-int main(void)
-{
-  printf("====================================\n");
-  printf("** Driver run for aes128KeySchedule:\n");
-  printf("====================================\n");
-  aes128KeySchedule_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for aes128BlockEncrypt:\n");
-  printf("=====================================\n");
-  aes128BlockEncrypt_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for aes128BlockDecrypt:\n");
-  printf("=====================================\n");
-  aes128BlockDecrypt_driver();
-
-  return 0;
-}
-== END: "aes128Lib_driver.c" ==================
-== BEGIN: "Makefile" ================
-# Makefile for aes128Lib. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-AR?=ar
-ARFLAGS?=cr
-
-all: aes128Lib.a aes128Lib_driver
-
-aes128Lib.a: aes128KeySchedule.o aes128BlockEncrypt.o aes128BlockDecrypt.o
-	${AR} ${ARFLAGS} $@ $^
-
-aes128Lib_driver: aes128Lib_driver.c aes128Lib.h
-	${CC} ${CCFLAGS} $< -o $@ aes128Lib.a
-
-aes128KeySchedule.o: aes128KeySchedule.c aes128Lib.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128BlockEncrypt.o: aes128BlockEncrypt.c aes128Lib.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-aes128BlockDecrypt.o: aes128BlockDecrypt.c aes128Lib.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f aes128Lib.a aes128Lib_driver
-== END: "Makefile" ==================
diff --git a/SBVUnitTest/GoldFiles/auf-1.gold b/SBVUnitTest/GoldFiles/auf-1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/auf-1.gold
+++ /dev/null
@@ -1,33 +0,0 @@
-INPUTS
-  s0 :: SWord32, existential, aliasing "x"
-  s1 :: SWord32, existential, aliasing "y"
-  s2 :: SWord32, existential, aliasing "initVal"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s3 = 2 :: Word32
-  s9 = 3 :: Word32
-  s13 = 1 :: Word32
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-  [uninterpreted] f :: SWord32 -> SWord64
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s4 :: SWord32 = s0 + s3
-  s5 :: SBool = s1 == s4
-  s6 :: SBool = ~ s5
-  s7 :: SWord32 = s1 - s3
-  s8 :: SBool = s0 == s7
-  s10 :: SWord32 = if s8 then s9 else s2
-  s11 :: SWord64 = [uninterpreted] f s10
-  s12 :: SWord32 = s1 - s0
-  s14 :: SWord32 = s12 + s13
-  s15 :: SWord64 = [uninterpreted] f s14
-  s16 :: SBool = s11 == s15
-  s17 :: SBool = s6 | s16
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s17
diff --git a/SBVUnitTest/GoldFiles/basic-1_1.gold b/SBVUnitTest/GoldFiles/basic-1_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-1_1.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-5 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-1_2.gold b/SBVUnitTest/GoldFiles/basic-1_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-1_2.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-5 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-1_3.gold b/SBVUnitTest/GoldFiles/basic-1_3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-1_3.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-25 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-1_4.gold b/SBVUnitTest/GoldFiles/basic-1_4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-1_4.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-25 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-1_5.gold b/SBVUnitTest/GoldFiles/basic-1_5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-1_5.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-4 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-2_1.gold b/SBVUnitTest/GoldFiles/basic-2_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-2_1.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 3 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s1 - s0
-  s4 :: SWord8 = s2 * s3
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s4
diff --git a/SBVUnitTest/GoldFiles/basic-2_2.gold b/SBVUnitTest/GoldFiles/basic-2_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-2_2.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 9 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 * s0
-  s3 :: SWord8 = s1 - s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-2_3.gold b/SBVUnitTest/GoldFiles/basic-2_3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-2_3.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 3 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-2_4.gold b/SBVUnitTest/GoldFiles/basic-2_4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-2_4.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 3 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-2_5.gold b/SBVUnitTest/GoldFiles/basic-2_5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-2_5.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-4 :: Word8
diff --git a/SBVUnitTest/GoldFiles/basic-3_1.gold b/SBVUnitTest/GoldFiles/basic-3_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-3_1.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s0 - s1
-  s4 :: SWord8 = s2 * s3
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s4
diff --git a/SBVUnitTest/GoldFiles/basic-3_2.gold b/SBVUnitTest/GoldFiles/basic-3_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-3_2.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 * s0
-  s3 :: SWord8 = s1 * s1
-  s4 :: SWord8 = s2 - s3
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s4
diff --git a/SBVUnitTest/GoldFiles/basic-3_3.gold b/SBVUnitTest/GoldFiles/basic-3_3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-3_3.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-3_4.gold b/SBVUnitTest/GoldFiles/basic-3_4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-3_4.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-3_5.gold b/SBVUnitTest/GoldFiles/basic-3_5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-3_5.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "y"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s2 = 1 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s3 :: SWord8 = s0 + s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-4_1.gold b/SBVUnitTest/GoldFiles/basic-4_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-4_1.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s1 :: SWord8 = s0 + s0
-  s2 :: SWord8 = s0 - s0
-  s3 :: SWord8 = s1 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-4_2.gold b/SBVUnitTest/GoldFiles/basic-4_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-4_2.gold
+++ /dev/null
@@ -1,17 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s1 :: SWord8 = s0 * s0
-  s2 :: SWord8 = s1 - s1
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s2
diff --git a/SBVUnitTest/GoldFiles/basic-4_3.gold b/SBVUnitTest/GoldFiles/basic-4_3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-4_3.gold
+++ /dev/null
@@ -1,17 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s1 :: SWord8 = s0 + s0
-  s2 :: SWord8 = s1 * s1
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s2
diff --git a/SBVUnitTest/GoldFiles/basic-4_4.gold b/SBVUnitTest/GoldFiles/basic-4_4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-4_4.gold
+++ /dev/null
@@ -1,17 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s1 :: SWord8 = s0 + s0
-  s2 :: SWord8 = s1 * s1
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s2
diff --git a/SBVUnitTest/GoldFiles/basic-4_5.gold b/SBVUnitTest/GoldFiles/basic-4_5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-4_5.gold
+++ /dev/null
@@ -1,17 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 1 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s1
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s2
diff --git a/SBVUnitTest/GoldFiles/basic-5_1.gold b/SBVUnitTest/GoldFiles/basic-5_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-5_1.gold
+++ /dev/null
@@ -1,20 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "q"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s0
-  s3 :: SWord8 = s0 - s0
-  s4 :: SWord8 = s2 * s3
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1
-  s4
diff --git a/SBVUnitTest/GoldFiles/basic-5_2.gold b/SBVUnitTest/GoldFiles/basic-5_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-5_2.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "q"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 * s0
-  s3 :: SWord8 = s2 - s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-5_3.gold b/SBVUnitTest/GoldFiles/basic-5_3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-5_3.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "q"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s0
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-5_4.gold b/SBVUnitTest/GoldFiles/basic-5_4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-5_4.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "q"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SWord8 = s0 + s0
-  s3 :: SWord8 = s2 * s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1
-  s3
diff --git a/SBVUnitTest/GoldFiles/basic-5_5.gold b/SBVUnitTest/GoldFiles/basic-5_5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/basic-5_5.gold
+++ /dev/null
@@ -1,19 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-  s1 :: SWord8, aliasing "q"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s2 = 1 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s3 :: SWord8 = s0 + s2
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1
-  s3
diff --git a/SBVUnitTest/GoldFiles/ccitt.gold b/SBVUnitTest/GoldFiles/ccitt.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/ccitt.gold
+++ /dev/null
@@ -1,1832 +0,0 @@
-INPUTS
-  s0 :: SWord32
-  s1 :: SWord16
-  s2 :: SWord32
-  s3 :: SWord16
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s13 = 0 :: Word1
-  s1686 = 0 :: Word8
-  s1687 = 1 :: Word8
-  s1815 = 3 :: Word8
-  s9 = 0 :: Word16
-  s525 = 1 :: Word64
-  s526 = 0 :: Word64
-  s528 = 2 :: Word64
-  s531 = 4 :: Word64
-  s534 = 8 :: Word64
-  s537 = 16 :: Word64
-  s540 = 32 :: Word64
-  s543 = 64 :: Word64
-  s546 = 128 :: Word64
-  s549 = 256 :: Word64
-  s552 = 512 :: Word64
-  s555 = 1024 :: Word64
-  s558 = 2048 :: Word64
-  s561 = 4096 :: Word64
-  s564 = 8192 :: Word64
-  s567 = 16384 :: Word64
-  s570 = 32768 :: Word64
-  s573 = 65536 :: Word64
-  s576 = 131072 :: Word64
-  s579 = 262144 :: Word64
-  s582 = 524288 :: Word64
-  s585 = 1048576 :: Word64
-  s588 = 2097152 :: Word64
-  s591 = 4194304 :: Word64
-  s594 = 8388608 :: Word64
-  s597 = 16777216 :: Word64
-  s600 = 33554432 :: Word64
-  s603 = 67108864 :: Word64
-  s606 = 134217728 :: Word64
-  s609 = 268435456 :: Word64
-  s612 = 536870912 :: Word64
-  s615 = 1073741824 :: Word64
-  s618 = 2147483648 :: Word64
-  s621 = 4294967296 :: Word64
-  s624 = 8589934592 :: Word64
-  s627 = 17179869184 :: Word64
-  s630 = 34359738368 :: Word64
-  s633 = 68719476736 :: Word64
-  s636 = 137438953472 :: Word64
-  s639 = 274877906944 :: Word64
-  s642 = 549755813888 :: Word64
-  s645 = 1099511627776 :: Word64
-  s648 = 2199023255552 :: Word64
-  s651 = 4398046511104 :: Word64
-  s654 = 8796093022208 :: Word64
-  s657 = 17592186044416 :: Word64
-  s660 = 35184372088832 :: Word64
-  s663 = 70368744177664 :: Word64
-  s666 = 140737488355328 :: Word64
-  s669 = 281474976710656 :: Word64
-  s672 = 562949953421312 :: Word64
-  s675 = 1125899906842624 :: Word64
-  s678 = 2251799813685248 :: Word64
-  s681 = 4503599627370496 :: Word64
-  s684 = 9007199254740992 :: Word64
-  s687 = 18014398509481984 :: Word64
-  s690 = 36028797018963968 :: Word64
-  s693 = 72057594037927936 :: Word64
-  s696 = 144115188075855872 :: Word64
-  s699 = 288230376151711744 :: Word64
-  s702 = 576460752303423488 :: Word64
-  s705 = 1152921504606846976 :: Word64
-  s708 = 2305843009213693952 :: Word64
-  s711 = 4611686018427387904 :: Word64
-  s714 = 9223372036854775808 :: Word64
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s4 :: SBool = s0 == s2
-  s5 :: SBool = s1 == s3
-  s6 :: SBool = s4 & s5
-  s7 :: SBool = ~ s6
-  s8 :: SBool = ~ s7
-  s10 :: SWord32 = s1 # s9
-  s11 :: SWord64 = s0 # s10
-  s12 :: SWord1 = choose [63:63] s11
-  s14 :: SBool = s12 /= s13
-  s15 :: SWord1 = choose [62:62] s11
-  s16 :: SBool = s13 /= s15
-  s17 :: SWord1 = choose [61:61] s11
-  s18 :: SBool = s13 /= s17
-  s19 :: SWord1 = choose [60:60] s11
-  s20 :: SBool = s13 /= s19
-  s21 :: SWord1 = choose [59:59] s11
-  s22 :: SBool = s13 /= s21
-  s23 :: SBool = ~ s22
-  s24 :: SBool = if s14 then s23 else s22
-  s25 :: SWord1 = choose [58:58] s11
-  s26 :: SBool = s13 /= s25
-  s27 :: SBool = ~ s26
-  s28 :: SBool = if s16 then s27 else s26
-  s29 :: SWord1 = choose [57:57] s11
-  s30 :: SBool = s13 /= s29
-  s31 :: SBool = ~ s30
-  s32 :: SBool = if s18 then s31 else s30
-  s33 :: SWord1 = choose [56:56] s11
-  s34 :: SBool = s13 /= s33
-  s35 :: SBool = ~ s34
-  s36 :: SBool = if s20 then s35 else s34
-  s37 :: SWord1 = choose [55:55] s11
-  s38 :: SBool = s13 /= s37
-  s39 :: SBool = ~ s38
-  s40 :: SBool = if s24 then s39 else s38
-  s41 :: SWord1 = choose [54:54] s11
-  s42 :: SBool = s13 /= s41
-  s43 :: SBool = ~ s42
-  s44 :: SBool = if s28 then s43 else s42
-  s45 :: SWord1 = choose [53:53] s11
-  s46 :: SBool = s13 /= s45
-  s47 :: SBool = ~ s46
-  s48 :: SBool = if s32 then s47 else s46
-  s49 :: SWord1 = choose [52:52] s11
-  s50 :: SBool = s13 /= s49
-  s51 :: SBool = ~ s50
-  s52 :: SBool = if s14 then s51 else s50
-  s53 :: SBool = ~ s52
-  s54 :: SBool = if s36 then s53 else s52
-  s55 :: SWord1 = choose [51:51] s11
-  s56 :: SBool = s13 /= s55
-  s57 :: SBool = ~ s56
-  s58 :: SBool = if s16 then s57 else s56
-  s59 :: SBool = ~ s58
-  s60 :: SBool = if s40 then s59 else s58
-  s61 :: SWord1 = choose [50:50] s11
-  s62 :: SBool = s13 /= s61
-  s63 :: SBool = ~ s62
-  s64 :: SBool = if s18 then s63 else s62
-  s65 :: SBool = ~ s64
-  s66 :: SBool = if s44 then s65 else s64
-  s67 :: SWord1 = choose [49:49] s11
-  s68 :: SBool = s13 /= s67
-  s69 :: SBool = ~ s68
-  s70 :: SBool = if s20 then s69 else s68
-  s71 :: SBool = ~ s70
-  s72 :: SBool = if s48 then s71 else s70
-  s73 :: SWord1 = choose [48:48] s11
-  s74 :: SBool = s13 /= s73
-  s75 :: SBool = ~ s74
-  s76 :: SBool = if s24 then s75 else s74
-  s77 :: SBool = ~ s76
-  s78 :: SBool = if s54 then s77 else s76
-  s79 :: SWord1 = choose [47:47] s11
-  s80 :: SBool = s13 /= s79
-  s81 :: SBool = ~ s80
-  s82 :: SBool = if s14 then s81 else s80
-  s83 :: SBool = ~ s82
-  s84 :: SBool = if s28 then s83 else s82
-  s85 :: SBool = ~ s84
-  s86 :: SBool = if s60 then s85 else s84
-  s87 :: SWord1 = choose [46:46] s11
-  s88 :: SBool = s13 /= s87
-  s89 :: SBool = ~ s88
-  s90 :: SBool = if s16 then s89 else s88
-  s91 :: SBool = ~ s90
-  s92 :: SBool = if s32 then s91 else s90
-  s93 :: SBool = ~ s92
-  s94 :: SBool = if s66 then s93 else s92
-  s95 :: SWord1 = choose [45:45] s11
-  s96 :: SBool = s13 /= s95
-  s97 :: SBool = ~ s96
-  s98 :: SBool = if s18 then s97 else s96
-  s99 :: SBool = ~ s98
-  s100 :: SBool = if s36 then s99 else s98
-  s101 :: SBool = ~ s100
-  s102 :: SBool = if s72 then s101 else s100
-  s103 :: SWord1 = choose [44:44] s11
-  s104 :: SBool = s13 /= s103
-  s105 :: SBool = ~ s104
-  s106 :: SBool = if s20 then s105 else s104
-  s107 :: SBool = ~ s106
-  s108 :: SBool = if s40 then s107 else s106
-  s109 :: SBool = ~ s108
-  s110 :: SBool = if s78 then s109 else s108
-  s111 :: SWord1 = choose [43:43] s11
-  s112 :: SBool = s13 /= s111
-  s113 :: SBool = ~ s112
-  s114 :: SBool = if s24 then s113 else s112
-  s115 :: SBool = ~ s114
-  s116 :: SBool = if s44 then s115 else s114
-  s117 :: SBool = ~ s116
-  s118 :: SBool = if s86 then s117 else s116
-  s119 :: SWord1 = choose [42:42] s11
-  s120 :: SBool = s13 /= s119
-  s121 :: SBool = ~ s120
-  s122 :: SBool = if s28 then s121 else s120
-  s123 :: SBool = ~ s122
-  s124 :: SBool = if s48 then s123 else s122
-  s125 :: SBool = ~ s124
-  s126 :: SBool = if s94 then s125 else s124
-  s127 :: SWord1 = choose [41:41] s11
-  s128 :: SBool = s13 /= s127
-  s129 :: SBool = ~ s128
-  s130 :: SBool = if s32 then s129 else s128
-  s131 :: SBool = ~ s130
-  s132 :: SBool = if s54 then s131 else s130
-  s133 :: SBool = ~ s132
-  s134 :: SBool = if s102 then s133 else s132
-  s135 :: SWord1 = choose [40:40] s11
-  s136 :: SBool = s13 /= s135
-  s137 :: SBool = ~ s136
-  s138 :: SBool = if s36 then s137 else s136
-  s139 :: SBool = ~ s138
-  s140 :: SBool = if s60 then s139 else s138
-  s141 :: SBool = ~ s140
-  s142 :: SBool = if s110 then s141 else s140
-  s143 :: SWord1 = choose [39:39] s11
-  s144 :: SBool = s13 /= s143
-  s145 :: SBool = ~ s144
-  s146 :: SBool = if s40 then s145 else s144
-  s147 :: SBool = ~ s146
-  s148 :: SBool = if s66 then s147 else s146
-  s149 :: SBool = ~ s148
-  s150 :: SBool = if s118 then s149 else s148
-  s151 :: SWord1 = choose [38:38] s11
-  s152 :: SBool = s13 /= s151
-  s153 :: SBool = ~ s152
-  s154 :: SBool = if s44 then s153 else s152
-  s155 :: SBool = ~ s154
-  s156 :: SBool = if s72 then s155 else s154
-  s157 :: SBool = ~ s156
-  s158 :: SBool = if s126 then s157 else s156
-  s159 :: SWord1 = choose [37:37] s11
-  s160 :: SBool = s13 /= s159
-  s161 :: SBool = ~ s160
-  s162 :: SBool = if s48 then s161 else s160
-  s163 :: SBool = ~ s162
-  s164 :: SBool = if s78 then s163 else s162
-  s165 :: SBool = ~ s164
-  s166 :: SBool = if s134 then s165 else s164
-  s167 :: SWord1 = choose [36:36] s11
-  s168 :: SBool = s13 /= s167
-  s169 :: SBool = ~ s168
-  s170 :: SBool = if s54 then s169 else s168
-  s171 :: SBool = ~ s170
-  s172 :: SBool = if s86 then s171 else s170
-  s173 :: SBool = ~ s172
-  s174 :: SBool = if s142 then s173 else s172
-  s175 :: SWord1 = choose [35:35] s11
-  s176 :: SBool = s13 /= s175
-  s177 :: SBool = ~ s176
-  s178 :: SBool = if s60 then s177 else s176
-  s179 :: SBool = ~ s178
-  s180 :: SBool = if s94 then s179 else s178
-  s181 :: SBool = ~ s180
-  s182 :: SBool = if s150 then s181 else s180
-  s183 :: SWord1 = choose [34:34] s11
-  s184 :: SBool = s13 /= s183
-  s185 :: SBool = ~ s184
-  s186 :: SBool = if s66 then s185 else s184
-  s187 :: SBool = ~ s186
-  s188 :: SBool = if s102 then s187 else s186
-  s189 :: SBool = ~ s188
-  s190 :: SBool = if s158 then s189 else s188
-  s191 :: SWord1 = choose [33:33] s11
-  s192 :: SBool = s13 /= s191
-  s193 :: SBool = ~ s192
-  s194 :: SBool = if s72 then s193 else s192
-  s195 :: SBool = ~ s194
-  s196 :: SBool = if s110 then s195 else s194
-  s197 :: SBool = ~ s196
-  s198 :: SBool = if s166 then s197 else s196
-  s199 :: SWord1 = choose [32:32] s11
-  s200 :: SBool = s13 /= s199
-  s201 :: SBool = ~ s200
-  s202 :: SBool = if s78 then s201 else s200
-  s203 :: SBool = ~ s202
-  s204 :: SBool = if s118 then s203 else s202
-  s205 :: SBool = ~ s204
-  s206 :: SBool = if s174 then s205 else s204
-  s207 :: SWord1 = choose [31:31] s11
-  s208 :: SBool = s13 /= s207
-  s209 :: SBool = ~ s208
-  s210 :: SBool = if s86 then s209 else s208
-  s211 :: SBool = ~ s210
-  s212 :: SBool = if s126 then s211 else s210
-  s213 :: SBool = ~ s212
-  s214 :: SBool = if s182 then s213 else s212
-  s215 :: SWord1 = choose [30:30] s11
-  s216 :: SBool = s13 /= s215
-  s217 :: SBool = ~ s216
-  s218 :: SBool = if s94 then s217 else s216
-  s219 :: SBool = ~ s218
-  s220 :: SBool = if s134 then s219 else s218
-  s221 :: SBool = ~ s220
-  s222 :: SBool = if s190 then s221 else s220
-  s223 :: SWord1 = choose [29:29] s11
-  s224 :: SBool = s13 /= s223
-  s225 :: SBool = ~ s224
-  s226 :: SBool = if s102 then s225 else s224
-  s227 :: SBool = ~ s226
-  s228 :: SBool = if s142 then s227 else s226
-  s229 :: SBool = ~ s228
-  s230 :: SBool = if s198 then s229 else s228
-  s231 :: SWord1 = choose [28:28] s11
-  s232 :: SBool = s13 /= s231
-  s233 :: SBool = ~ s232
-  s234 :: SBool = if s110 then s233 else s232
-  s235 :: SBool = ~ s234
-  s236 :: SBool = if s150 then s235 else s234
-  s237 :: SBool = ~ s236
-  s238 :: SBool = if s206 then s237 else s236
-  s239 :: SWord1 = choose [27:27] s11
-  s240 :: SBool = s13 /= s239
-  s241 :: SBool = ~ s240
-  s242 :: SBool = if s118 then s241 else s240
-  s243 :: SBool = ~ s242
-  s244 :: SBool = if s158 then s243 else s242
-  s245 :: SBool = ~ s244
-  s246 :: SBool = if s214 then s245 else s244
-  s247 :: SWord1 = choose [26:26] s11
-  s248 :: SBool = s13 /= s247
-  s249 :: SBool = ~ s248
-  s250 :: SBool = if s126 then s249 else s248
-  s251 :: SBool = ~ s250
-  s252 :: SBool = if s166 then s251 else s250
-  s253 :: SBool = ~ s252
-  s254 :: SBool = if s222 then s253 else s252
-  s255 :: SWord1 = choose [25:25] s11
-  s256 :: SBool = s13 /= s255
-  s257 :: SBool = ~ s256
-  s258 :: SBool = if s134 then s257 else s256
-  s259 :: SBool = ~ s258
-  s260 :: SBool = if s174 then s259 else s258
-  s261 :: SBool = ~ s260
-  s262 :: SBool = if s230 then s261 else s260
-  s263 :: SWord1 = choose [24:24] s11
-  s264 :: SBool = s13 /= s263
-  s265 :: SBool = ~ s264
-  s266 :: SBool = if s142 then s265 else s264
-  s267 :: SBool = ~ s266
-  s268 :: SBool = if s182 then s267 else s266
-  s269 :: SBool = ~ s268
-  s270 :: SBool = if s238 then s269 else s268
-  s271 :: SWord1 = choose [23:23] s11
-  s272 :: SBool = s13 /= s271
-  s273 :: SBool = ~ s272
-  s274 :: SBool = if s150 then s273 else s272
-  s275 :: SBool = ~ s274
-  s276 :: SBool = if s190 then s275 else s274
-  s277 :: SBool = ~ s276
-  s278 :: SBool = if s246 then s277 else s276
-  s279 :: SWord1 = choose [22:22] s11
-  s280 :: SBool = s13 /= s279
-  s281 :: SBool = ~ s280
-  s282 :: SBool = if s158 then s281 else s280
-  s283 :: SBool = ~ s282
-  s284 :: SBool = if s198 then s283 else s282
-  s285 :: SBool = ~ s284
-  s286 :: SBool = if s254 then s285 else s284
-  s287 :: SWord1 = choose [21:21] s11
-  s288 :: SBool = s13 /= s287
-  s289 :: SBool = ~ s288
-  s290 :: SBool = if s166 then s289 else s288
-  s291 :: SBool = ~ s290
-  s292 :: SBool = if s206 then s291 else s290
-  s293 :: SBool = ~ s292
-  s294 :: SBool = if s262 then s293 else s292
-  s295 :: SWord1 = choose [20:20] s11
-  s296 :: SBool = s13 /= s295
-  s297 :: SBool = ~ s296
-  s298 :: SBool = if s174 then s297 else s296
-  s299 :: SBool = ~ s298
-  s300 :: SBool = if s214 then s299 else s298
-  s301 :: SBool = ~ s300
-  s302 :: SBool = if s270 then s301 else s300
-  s303 :: SWord1 = choose [19:19] s11
-  s304 :: SBool = s13 /= s303
-  s305 :: SBool = ~ s304
-  s306 :: SBool = if s182 then s305 else s304
-  s307 :: SBool = ~ s306
-  s308 :: SBool = if s222 then s307 else s306
-  s309 :: SBool = ~ s308
-  s310 :: SBool = if s278 then s309 else s308
-  s311 :: SWord1 = choose [18:18] s11
-  s312 :: SBool = s13 /= s311
-  s313 :: SBool = ~ s312
-  s314 :: SBool = if s190 then s313 else s312
-  s315 :: SBool = ~ s314
-  s316 :: SBool = if s230 then s315 else s314
-  s317 :: SBool = ~ s316
-  s318 :: SBool = if s286 then s317 else s316
-  s319 :: SWord1 = choose [17:17] s11
-  s320 :: SBool = s13 /= s319
-  s321 :: SBool = ~ s320
-  s322 :: SBool = if s198 then s321 else s320
-  s323 :: SBool = ~ s322
-  s324 :: SBool = if s238 then s323 else s322
-  s325 :: SBool = ~ s324
-  s326 :: SBool = if s294 then s325 else s324
-  s327 :: SWord1 = choose [16:16] s11
-  s328 :: SBool = s13 /= s327
-  s329 :: SBool = ~ s328
-  s330 :: SBool = if s206 then s329 else s328
-  s331 :: SBool = ~ s330
-  s332 :: SBool = if s246 then s331 else s330
-  s333 :: SBool = ~ s332
-  s334 :: SBool = if s302 then s333 else s332
-  s335 :: SBool = ~ s14
-  s336 :: SBool = if s14 then s335 else s14
-  s337 :: SBool = ~ s16
-  s338 :: SBool = if s16 then s337 else s16
-  s339 :: SBool = ~ s18
-  s340 :: SBool = if s18 then s339 else s18
-  s341 :: SBool = ~ s20
-  s342 :: SBool = if s20 then s341 else s20
-  s343 :: SBool = ~ s24
-  s344 :: SBool = if s24 then s343 else s24
-  s345 :: SBool = ~ s28
-  s346 :: SBool = if s28 then s345 else s28
-  s347 :: SBool = ~ s32
-  s348 :: SBool = if s32 then s347 else s32
-  s349 :: SBool = ~ s36
-  s350 :: SBool = if s36 then s349 else s36
-  s351 :: SBool = ~ s40
-  s352 :: SBool = if s40 then s351 else s40
-  s353 :: SBool = ~ s44
-  s354 :: SBool = if s44 then s353 else s44
-  s355 :: SBool = ~ s48
-  s356 :: SBool = if s48 then s355 else s48
-  s357 :: SBool = ~ s54
-  s358 :: SBool = if s54 then s357 else s54
-  s359 :: SBool = ~ s60
-  s360 :: SBool = if s60 then s359 else s60
-  s361 :: SBool = ~ s66
-  s362 :: SBool = if s66 then s361 else s66
-  s363 :: SBool = ~ s72
-  s364 :: SBool = if s72 then s363 else s72
-  s365 :: SBool = ~ s78
-  s366 :: SBool = if s78 then s365 else s78
-  s367 :: SBool = ~ s86
-  s368 :: SBool = if s86 then s367 else s86
-  s369 :: SBool = ~ s94
-  s370 :: SBool = if s94 then s369 else s94
-  s371 :: SBool = ~ s102
-  s372 :: SBool = if s102 then s371 else s102
-  s373 :: SBool = ~ s110
-  s374 :: SBool = if s110 then s373 else s110
-  s375 :: SBool = ~ s118
-  s376 :: SBool = if s118 then s375 else s118
-  s377 :: SBool = ~ s126
-  s378 :: SBool = if s126 then s377 else s126
-  s379 :: SBool = ~ s134
-  s380 :: SBool = if s134 then s379 else s134
-  s381 :: SBool = ~ s142
-  s382 :: SBool = if s142 then s381 else s142
-  s383 :: SBool = ~ s150
-  s384 :: SBool = if s150 then s383 else s150
-  s385 :: SBool = ~ s158
-  s386 :: SBool = if s158 then s385 else s158
-  s387 :: SBool = ~ s166
-  s388 :: SBool = if s166 then s387 else s166
-  s389 :: SBool = ~ s174
-  s390 :: SBool = if s174 then s389 else s174
-  s391 :: SBool = ~ s182
-  s392 :: SBool = if s182 then s391 else s182
-  s393 :: SBool = ~ s190
-  s394 :: SBool = if s190 then s393 else s190
-  s395 :: SBool = ~ s198
-  s396 :: SBool = if s198 then s395 else s198
-  s397 :: SBool = ~ s206
-  s398 :: SBool = if s206 then s397 else s206
-  s399 :: SBool = ~ s214
-  s400 :: SBool = if s214 then s399 else s214
-  s401 :: SBool = ~ s222
-  s402 :: SBool = if s222 then s401 else s222
-  s403 :: SBool = ~ s230
-  s404 :: SBool = if s230 then s403 else s230
-  s405 :: SBool = ~ s238
-  s406 :: SBool = if s238 then s405 else s238
-  s407 :: SBool = ~ s246
-  s408 :: SBool = if s246 then s407 else s246
-  s409 :: SBool = ~ s254
-  s410 :: SBool = if s254 then s409 else s254
-  s411 :: SBool = ~ s262
-  s412 :: SBool = if s262 then s411 else s262
-  s413 :: SBool = ~ s270
-  s414 :: SBool = if s270 then s413 else s270
-  s415 :: SBool = ~ s278
-  s416 :: SBool = if s278 then s415 else s278
-  s417 :: SBool = ~ s286
-  s418 :: SBool = if s286 then s417 else s286
-  s419 :: SBool = ~ s294
-  s420 :: SBool = if s294 then s419 else s294
-  s421 :: SBool = ~ s302
-  s422 :: SBool = if s302 then s421 else s302
-  s423 :: SBool = ~ s310
-  s424 :: SBool = if s310 then s423 else s310
-  s425 :: SBool = ~ s318
-  s426 :: SBool = if s318 then s425 else s318
-  s427 :: SBool = ~ s326
-  s428 :: SBool = if s326 then s427 else s326
-  s429 :: SBool = ~ s334
-  s430 :: SBool = if s334 then s429 else s334
-  s431 :: SWord1 = choose [15:15] s11
-  s432 :: SBool = s13 /= s431
-  s433 :: SBool = ~ s432
-  s434 :: SBool = if s214 then s433 else s432
-  s435 :: SBool = ~ s434
-  s436 :: SBool = if s254 then s435 else s434
-  s437 :: SBool = ~ s436
-  s438 :: SBool = if s310 then s437 else s436
-  s439 :: SWord1 = choose [14:14] s11
-  s440 :: SBool = s13 /= s439
-  s441 :: SBool = ~ s440
-  s442 :: SBool = if s222 then s441 else s440
-  s443 :: SBool = ~ s442
-  s444 :: SBool = if s262 then s443 else s442
-  s445 :: SBool = ~ s444
-  s446 :: SBool = if s318 then s445 else s444
-  s447 :: SWord1 = choose [13:13] s11
-  s448 :: SBool = s13 /= s447
-  s449 :: SBool = ~ s448
-  s450 :: SBool = if s230 then s449 else s448
-  s451 :: SBool = ~ s450
-  s452 :: SBool = if s270 then s451 else s450
-  s453 :: SBool = ~ s452
-  s454 :: SBool = if s326 then s453 else s452
-  s455 :: SWord1 = choose [12:12] s11
-  s456 :: SBool = s13 /= s455
-  s457 :: SBool = ~ s456
-  s458 :: SBool = if s238 then s457 else s456
-  s459 :: SBool = ~ s458
-  s460 :: SBool = if s278 then s459 else s458
-  s461 :: SBool = ~ s460
-  s462 :: SBool = if s334 then s461 else s460
-  s463 :: SWord1 = choose [11:11] s11
-  s464 :: SBool = s13 /= s463
-  s465 :: SBool = ~ s464
-  s466 :: SBool = if s246 then s465 else s464
-  s467 :: SBool = ~ s466
-  s468 :: SBool = if s286 then s467 else s466
-  s469 :: SWord1 = choose [10:10] s11
-  s470 :: SBool = s13 /= s469
-  s471 :: SBool = ~ s470
-  s472 :: SBool = if s254 then s471 else s470
-  s473 :: SBool = ~ s472
-  s474 :: SBool = if s294 then s473 else s472
-  s475 :: SWord1 = choose [9:9] s11
-  s476 :: SBool = s13 /= s475
-  s477 :: SBool = ~ s476
-  s478 :: SBool = if s262 then s477 else s476
-  s479 :: SBool = ~ s478
-  s480 :: SBool = if s302 then s479 else s478
-  s481 :: SWord1 = choose [8:8] s11
-  s482 :: SBool = s13 /= s481
-  s483 :: SBool = ~ s482
-  s484 :: SBool = if s270 then s483 else s482
-  s485 :: SBool = ~ s484
-  s486 :: SBool = if s310 then s485 else s484
-  s487 :: SWord1 = choose [7:7] s11
-  s488 :: SBool = s13 /= s487
-  s489 :: SBool = ~ s488
-  s490 :: SBool = if s278 then s489 else s488
-  s491 :: SBool = ~ s490
-  s492 :: SBool = if s318 then s491 else s490
-  s493 :: SWord1 = choose [6:6] s11
-  s494 :: SBool = s13 /= s493
-  s495 :: SBool = ~ s494
-  s496 :: SBool = if s286 then s495 else s494
-  s497 :: SBool = ~ s496
-  s498 :: SBool = if s326 then s497 else s496
-  s499 :: SWord1 = choose [5:5] s11
-  s500 :: SBool = s13 /= s499
-  s501 :: SBool = ~ s500
-  s502 :: SBool = if s294 then s501 else s500
-  s503 :: SBool = ~ s502
-  s504 :: SBool = if s334 then s503 else s502
-  s505 :: SWord1 = choose [4:4] s11
-  s506 :: SBool = s13 /= s505
-  s507 :: SBool = ~ s506
-  s508 :: SBool = if s302 then s507 else s506
-  s509 :: SWord1 = choose [3:3] s11
-  s510 :: SBool = s13 /= s509
-  s511 :: SBool = ~ s510
-  s512 :: SBool = if s310 then s511 else s510
-  s513 :: SWord1 = choose [2:2] s11
-  s514 :: SBool = s13 /= s513
-  s515 :: SBool = ~ s514
-  s516 :: SBool = if s318 then s515 else s514
-  s517 :: SWord1 = choose [1:1] s11
-  s518 :: SBool = s13 /= s517
-  s519 :: SBool = ~ s518
-  s520 :: SBool = if s326 then s519 else s518
-  s521 :: SWord1 = choose [0:0] s11
-  s522 :: SBool = s13 /= s521
-  s523 :: SBool = ~ s522
-  s524 :: SBool = if s334 then s523 else s522
-  s527 :: SWord64 = if s524 then s525 else s526
-  s529 :: SWord64 = s527 | s528
-  s530 :: SWord64 = if s520 then s529 else s527
-  s532 :: SWord64 = s530 | s531
-  s533 :: SWord64 = if s516 then s532 else s530
-  s535 :: SWord64 = s533 | s534
-  s536 :: SWord64 = if s512 then s535 else s533
-  s538 :: SWord64 = s536 | s537
-  s539 :: SWord64 = if s508 then s538 else s536
-  s541 :: SWord64 = s539 | s540
-  s542 :: SWord64 = if s504 then s541 else s539
-  s544 :: SWord64 = s542 | s543
-  s545 :: SWord64 = if s498 then s544 else s542
-  s547 :: SWord64 = s545 | s546
-  s548 :: SWord64 = if s492 then s547 else s545
-  s550 :: SWord64 = s548 | s549
-  s551 :: SWord64 = if s486 then s550 else s548
-  s553 :: SWord64 = s551 | s552
-  s554 :: SWord64 = if s480 then s553 else s551
-  s556 :: SWord64 = s554 | s555
-  s557 :: SWord64 = if s474 then s556 else s554
-  s559 :: SWord64 = s557 | s558
-  s560 :: SWord64 = if s468 then s559 else s557
-  s562 :: SWord64 = s560 | s561
-  s563 :: SWord64 = if s462 then s562 else s560
-  s565 :: SWord64 = s563 | s564
-  s566 :: SWord64 = if s454 then s565 else s563
-  s568 :: SWord64 = s566 | s567
-  s569 :: SWord64 = if s446 then s568 else s566
-  s571 :: SWord64 = s569 | s570
-  s572 :: SWord64 = if s438 then s571 else s569
-  s574 :: SWord64 = s572 | s573
-  s575 :: SWord64 = if s430 then s574 else s572
-  s577 :: SWord64 = s575 | s576
-  s578 :: SWord64 = if s428 then s577 else s575
-  s580 :: SWord64 = s578 | s579
-  s581 :: SWord64 = if s426 then s580 else s578
-  s583 :: SWord64 = s581 | s582
-  s584 :: SWord64 = if s424 then s583 else s581
-  s586 :: SWord64 = s584 | s585
-  s587 :: SWord64 = if s422 then s586 else s584
-  s589 :: SWord64 = s587 | s588
-  s590 :: SWord64 = if s420 then s589 else s587
-  s592 :: SWord64 = s590 | s591
-  s593 :: SWord64 = if s418 then s592 else s590
-  s595 :: SWord64 = s593 | s594
-  s596 :: SWord64 = if s416 then s595 else s593
-  s598 :: SWord64 = s596 | s597
-  s599 :: SWord64 = if s414 then s598 else s596
-  s601 :: SWord64 = s599 | s600
-  s602 :: SWord64 = if s412 then s601 else s599
-  s604 :: SWord64 = s602 | s603
-  s605 :: SWord64 = if s410 then s604 else s602
-  s607 :: SWord64 = s605 | s606
-  s608 :: SWord64 = if s408 then s607 else s605
-  s610 :: SWord64 = s608 | s609
-  s611 :: SWord64 = if s406 then s610 else s608
-  s613 :: SWord64 = s611 | s612
-  s614 :: SWord64 = if s404 then s613 else s611
-  s616 :: SWord64 = s614 | s615
-  s617 :: SWord64 = if s402 then s616 else s614
-  s619 :: SWord64 = s617 | s618
-  s620 :: SWord64 = if s400 then s619 else s617
-  s622 :: SWord64 = s620 | s621
-  s623 :: SWord64 = if s398 then s622 else s620
-  s625 :: SWord64 = s623 | s624
-  s626 :: SWord64 = if s396 then s625 else s623
-  s628 :: SWord64 = s626 | s627
-  s629 :: SWord64 = if s394 then s628 else s626
-  s631 :: SWord64 = s629 | s630
-  s632 :: SWord64 = if s392 then s631 else s629
-  s634 :: SWord64 = s632 | s633
-  s635 :: SWord64 = if s390 then s634 else s632
-  s637 :: SWord64 = s635 | s636
-  s638 :: SWord64 = if s388 then s637 else s635
-  s640 :: SWord64 = s638 | s639
-  s641 :: SWord64 = if s386 then s640 else s638
-  s643 :: SWord64 = s641 | s642
-  s644 :: SWord64 = if s384 then s643 else s641
-  s646 :: SWord64 = s644 | s645
-  s647 :: SWord64 = if s382 then s646 else s644
-  s649 :: SWord64 = s647 | s648
-  s650 :: SWord64 = if s380 then s649 else s647
-  s652 :: SWord64 = s650 | s651
-  s653 :: SWord64 = if s378 then s652 else s650
-  s655 :: SWord64 = s653 | s654
-  s656 :: SWord64 = if s376 then s655 else s653
-  s658 :: SWord64 = s656 | s657
-  s659 :: SWord64 = if s374 then s658 else s656
-  s661 :: SWord64 = s659 | s660
-  s662 :: SWord64 = if s372 then s661 else s659
-  s664 :: SWord64 = s662 | s663
-  s665 :: SWord64 = if s370 then s664 else s662
-  s667 :: SWord64 = s665 | s666
-  s668 :: SWord64 = if s368 then s667 else s665
-  s670 :: SWord64 = s668 | s669
-  s671 :: SWord64 = if s366 then s670 else s668
-  s673 :: SWord64 = s671 | s672
-  s674 :: SWord64 = if s364 then s673 else s671
-  s676 :: SWord64 = s674 | s675
-  s677 :: SWord64 = if s362 then s676 else s674
-  s679 :: SWord64 = s677 | s678
-  s680 :: SWord64 = if s360 then s679 else s677
-  s682 :: SWord64 = s680 | s681
-  s683 :: SWord64 = if s358 then s682 else s680
-  s685 :: SWord64 = s683 | s684
-  s686 :: SWord64 = if s356 then s685 else s683
-  s688 :: SWord64 = s686 | s687
-  s689 :: SWord64 = if s354 then s688 else s686
-  s691 :: SWord64 = s689 | s690
-  s692 :: SWord64 = if s352 then s691 else s689
-  s694 :: SWord64 = s692 | s693
-  s695 :: SWord64 = if s350 then s694 else s692
-  s697 :: SWord64 = s695 | s696
-  s698 :: SWord64 = if s348 then s697 else s695
-  s700 :: SWord64 = s698 | s699
-  s701 :: SWord64 = if s346 then s700 else s698
-  s703 :: SWord64 = s701 | s702
-  s704 :: SWord64 = if s344 then s703 else s701
-  s706 :: SWord64 = s704 | s705
-  s707 :: SWord64 = if s342 then s706 else s704
-  s709 :: SWord64 = s707 | s708
-  s710 :: SWord64 = if s340 then s709 else s707
-  s712 :: SWord64 = s710 | s711
-  s713 :: SWord64 = if s338 then s712 else s710
-  s715 :: SWord64 = s713 | s714
-  s716 :: SWord64 = if s336 then s715 else s713
-  s717 :: SWord32 = choose [31:0] s716
-  s718 :: SWord16 = choose [15:0] s717
-  s719 :: SWord32 = s1 # s718
-  s720 :: SWord64 = s0 # s719
-  s721 :: SWord1 = choose [0:0] s720
-  s722 :: SBool = s13 /= s721
-  s723 :: SWord32 = s3 # s9
-  s724 :: SWord64 = s2 # s723
-  s725 :: SWord1 = choose [63:63] s724
-  s726 :: SBool = s13 /= s725
-  s727 :: SWord1 = choose [62:62] s724
-  s728 :: SBool = s13 /= s727
-  s729 :: SWord1 = choose [61:61] s724
-  s730 :: SBool = s13 /= s729
-  s731 :: SWord1 = choose [60:60] s724
-  s732 :: SBool = s13 /= s731
-  s733 :: SWord1 = choose [59:59] s724
-  s734 :: SBool = s13 /= s733
-  s735 :: SBool = ~ s734
-  s736 :: SBool = if s726 then s735 else s734
-  s737 :: SWord1 = choose [58:58] s724
-  s738 :: SBool = s13 /= s737
-  s739 :: SBool = ~ s738
-  s740 :: SBool = if s728 then s739 else s738
-  s741 :: SWord1 = choose [57:57] s724
-  s742 :: SBool = s13 /= s741
-  s743 :: SBool = ~ s742
-  s744 :: SBool = if s730 then s743 else s742
-  s745 :: SWord1 = choose [56:56] s724
-  s746 :: SBool = s13 /= s745
-  s747 :: SBool = ~ s746
-  s748 :: SBool = if s732 then s747 else s746
-  s749 :: SWord1 = choose [55:55] s724
-  s750 :: SBool = s13 /= s749
-  s751 :: SBool = ~ s750
-  s752 :: SBool = if s736 then s751 else s750
-  s753 :: SWord1 = choose [54:54] s724
-  s754 :: SBool = s13 /= s753
-  s755 :: SBool = ~ s754
-  s756 :: SBool = if s740 then s755 else s754
-  s757 :: SWord1 = choose [53:53] s724
-  s758 :: SBool = s13 /= s757
-  s759 :: SBool = ~ s758
-  s760 :: SBool = if s744 then s759 else s758
-  s761 :: SWord1 = choose [52:52] s724
-  s762 :: SBool = s13 /= s761
-  s763 :: SBool = ~ s762
-  s764 :: SBool = if s726 then s763 else s762
-  s765 :: SBool = ~ s764
-  s766 :: SBool = if s748 then s765 else s764
-  s767 :: SWord1 = choose [51:51] s724
-  s768 :: SBool = s13 /= s767
-  s769 :: SBool = ~ s768
-  s770 :: SBool = if s728 then s769 else s768
-  s771 :: SBool = ~ s770
-  s772 :: SBool = if s752 then s771 else s770
-  s773 :: SWord1 = choose [50:50] s724
-  s774 :: SBool = s13 /= s773
-  s775 :: SBool = ~ s774
-  s776 :: SBool = if s730 then s775 else s774
-  s777 :: SBool = ~ s776
-  s778 :: SBool = if s756 then s777 else s776
-  s779 :: SWord1 = choose [49:49] s724
-  s780 :: SBool = s13 /= s779
-  s781 :: SBool = ~ s780
-  s782 :: SBool = if s732 then s781 else s780
-  s783 :: SBool = ~ s782
-  s784 :: SBool = if s760 then s783 else s782
-  s785 :: SWord1 = choose [48:48] s724
-  s786 :: SBool = s13 /= s785
-  s787 :: SBool = ~ s786
-  s788 :: SBool = if s736 then s787 else s786
-  s789 :: SBool = ~ s788
-  s790 :: SBool = if s766 then s789 else s788
-  s791 :: SWord1 = choose [47:47] s724
-  s792 :: SBool = s13 /= s791
-  s793 :: SBool = ~ s792
-  s794 :: SBool = if s726 then s793 else s792
-  s795 :: SBool = ~ s794
-  s796 :: SBool = if s740 then s795 else s794
-  s797 :: SBool = ~ s796
-  s798 :: SBool = if s772 then s797 else s796
-  s799 :: SWord1 = choose [46:46] s724
-  s800 :: SBool = s13 /= s799
-  s801 :: SBool = ~ s800
-  s802 :: SBool = if s728 then s801 else s800
-  s803 :: SBool = ~ s802
-  s804 :: SBool = if s744 then s803 else s802
-  s805 :: SBool = ~ s804
-  s806 :: SBool = if s778 then s805 else s804
-  s807 :: SWord1 = choose [45:45] s724
-  s808 :: SBool = s13 /= s807
-  s809 :: SBool = ~ s808
-  s810 :: SBool = if s730 then s809 else s808
-  s811 :: SBool = ~ s810
-  s812 :: SBool = if s748 then s811 else s810
-  s813 :: SBool = ~ s812
-  s814 :: SBool = if s784 then s813 else s812
-  s815 :: SWord1 = choose [44:44] s724
-  s816 :: SBool = s13 /= s815
-  s817 :: SBool = ~ s816
-  s818 :: SBool = if s732 then s817 else s816
-  s819 :: SBool = ~ s818
-  s820 :: SBool = if s752 then s819 else s818
-  s821 :: SBool = ~ s820
-  s822 :: SBool = if s790 then s821 else s820
-  s823 :: SWord1 = choose [43:43] s724
-  s824 :: SBool = s13 /= s823
-  s825 :: SBool = ~ s824
-  s826 :: SBool = if s736 then s825 else s824
-  s827 :: SBool = ~ s826
-  s828 :: SBool = if s756 then s827 else s826
-  s829 :: SBool = ~ s828
-  s830 :: SBool = if s798 then s829 else s828
-  s831 :: SWord1 = choose [42:42] s724
-  s832 :: SBool = s13 /= s831
-  s833 :: SBool = ~ s832
-  s834 :: SBool = if s740 then s833 else s832
-  s835 :: SBool = ~ s834
-  s836 :: SBool = if s760 then s835 else s834
-  s837 :: SBool = ~ s836
-  s838 :: SBool = if s806 then s837 else s836
-  s839 :: SWord1 = choose [41:41] s724
-  s840 :: SBool = s13 /= s839
-  s841 :: SBool = ~ s840
-  s842 :: SBool = if s744 then s841 else s840
-  s843 :: SBool = ~ s842
-  s844 :: SBool = if s766 then s843 else s842
-  s845 :: SBool = ~ s844
-  s846 :: SBool = if s814 then s845 else s844
-  s847 :: SWord1 = choose [40:40] s724
-  s848 :: SBool = s13 /= s847
-  s849 :: SBool = ~ s848
-  s850 :: SBool = if s748 then s849 else s848
-  s851 :: SBool = ~ s850
-  s852 :: SBool = if s772 then s851 else s850
-  s853 :: SBool = ~ s852
-  s854 :: SBool = if s822 then s853 else s852
-  s855 :: SWord1 = choose [39:39] s724
-  s856 :: SBool = s13 /= s855
-  s857 :: SBool = ~ s856
-  s858 :: SBool = if s752 then s857 else s856
-  s859 :: SBool = ~ s858
-  s860 :: SBool = if s778 then s859 else s858
-  s861 :: SBool = ~ s860
-  s862 :: SBool = if s830 then s861 else s860
-  s863 :: SWord1 = choose [38:38] s724
-  s864 :: SBool = s13 /= s863
-  s865 :: SBool = ~ s864
-  s866 :: SBool = if s756 then s865 else s864
-  s867 :: SBool = ~ s866
-  s868 :: SBool = if s784 then s867 else s866
-  s869 :: SBool = ~ s868
-  s870 :: SBool = if s838 then s869 else s868
-  s871 :: SWord1 = choose [37:37] s724
-  s872 :: SBool = s13 /= s871
-  s873 :: SBool = ~ s872
-  s874 :: SBool = if s760 then s873 else s872
-  s875 :: SBool = ~ s874
-  s876 :: SBool = if s790 then s875 else s874
-  s877 :: SBool = ~ s876
-  s878 :: SBool = if s846 then s877 else s876
-  s879 :: SWord1 = choose [36:36] s724
-  s880 :: SBool = s13 /= s879
-  s881 :: SBool = ~ s880
-  s882 :: SBool = if s766 then s881 else s880
-  s883 :: SBool = ~ s882
-  s884 :: SBool = if s798 then s883 else s882
-  s885 :: SBool = ~ s884
-  s886 :: SBool = if s854 then s885 else s884
-  s887 :: SWord1 = choose [35:35] s724
-  s888 :: SBool = s13 /= s887
-  s889 :: SBool = ~ s888
-  s890 :: SBool = if s772 then s889 else s888
-  s891 :: SBool = ~ s890
-  s892 :: SBool = if s806 then s891 else s890
-  s893 :: SBool = ~ s892
-  s894 :: SBool = if s862 then s893 else s892
-  s895 :: SWord1 = choose [34:34] s724
-  s896 :: SBool = s13 /= s895
-  s897 :: SBool = ~ s896
-  s898 :: SBool = if s778 then s897 else s896
-  s899 :: SBool = ~ s898
-  s900 :: SBool = if s814 then s899 else s898
-  s901 :: SBool = ~ s900
-  s902 :: SBool = if s870 then s901 else s900
-  s903 :: SWord1 = choose [33:33] s724
-  s904 :: SBool = s13 /= s903
-  s905 :: SBool = ~ s904
-  s906 :: SBool = if s784 then s905 else s904
-  s907 :: SBool = ~ s906
-  s908 :: SBool = if s822 then s907 else s906
-  s909 :: SBool = ~ s908
-  s910 :: SBool = if s878 then s909 else s908
-  s911 :: SWord1 = choose [32:32] s724
-  s912 :: SBool = s13 /= s911
-  s913 :: SBool = ~ s912
-  s914 :: SBool = if s790 then s913 else s912
-  s915 :: SBool = ~ s914
-  s916 :: SBool = if s830 then s915 else s914
-  s917 :: SBool = ~ s916
-  s918 :: SBool = if s886 then s917 else s916
-  s919 :: SWord1 = choose [31:31] s724
-  s920 :: SBool = s13 /= s919
-  s921 :: SBool = ~ s920
-  s922 :: SBool = if s798 then s921 else s920
-  s923 :: SBool = ~ s922
-  s924 :: SBool = if s838 then s923 else s922
-  s925 :: SBool = ~ s924
-  s926 :: SBool = if s894 then s925 else s924
-  s927 :: SWord1 = choose [30:30] s724
-  s928 :: SBool = s13 /= s927
-  s929 :: SBool = ~ s928
-  s930 :: SBool = if s806 then s929 else s928
-  s931 :: SBool = ~ s930
-  s932 :: SBool = if s846 then s931 else s930
-  s933 :: SBool = ~ s932
-  s934 :: SBool = if s902 then s933 else s932
-  s935 :: SWord1 = choose [29:29] s724
-  s936 :: SBool = s13 /= s935
-  s937 :: SBool = ~ s936
-  s938 :: SBool = if s814 then s937 else s936
-  s939 :: SBool = ~ s938
-  s940 :: SBool = if s854 then s939 else s938
-  s941 :: SBool = ~ s940
-  s942 :: SBool = if s910 then s941 else s940
-  s943 :: SWord1 = choose [28:28] s724
-  s944 :: SBool = s13 /= s943
-  s945 :: SBool = ~ s944
-  s946 :: SBool = if s822 then s945 else s944
-  s947 :: SBool = ~ s946
-  s948 :: SBool = if s862 then s947 else s946
-  s949 :: SBool = ~ s948
-  s950 :: SBool = if s918 then s949 else s948
-  s951 :: SWord1 = choose [27:27] s724
-  s952 :: SBool = s13 /= s951
-  s953 :: SBool = ~ s952
-  s954 :: SBool = if s830 then s953 else s952
-  s955 :: SBool = ~ s954
-  s956 :: SBool = if s870 then s955 else s954
-  s957 :: SBool = ~ s956
-  s958 :: SBool = if s926 then s957 else s956
-  s959 :: SWord1 = choose [26:26] s724
-  s960 :: SBool = s13 /= s959
-  s961 :: SBool = ~ s960
-  s962 :: SBool = if s838 then s961 else s960
-  s963 :: SBool = ~ s962
-  s964 :: SBool = if s878 then s963 else s962
-  s965 :: SBool = ~ s964
-  s966 :: SBool = if s934 then s965 else s964
-  s967 :: SWord1 = choose [25:25] s724
-  s968 :: SBool = s13 /= s967
-  s969 :: SBool = ~ s968
-  s970 :: SBool = if s846 then s969 else s968
-  s971 :: SBool = ~ s970
-  s972 :: SBool = if s886 then s971 else s970
-  s973 :: SBool = ~ s972
-  s974 :: SBool = if s942 then s973 else s972
-  s975 :: SWord1 = choose [24:24] s724
-  s976 :: SBool = s13 /= s975
-  s977 :: SBool = ~ s976
-  s978 :: SBool = if s854 then s977 else s976
-  s979 :: SBool = ~ s978
-  s980 :: SBool = if s894 then s979 else s978
-  s981 :: SBool = ~ s980
-  s982 :: SBool = if s950 then s981 else s980
-  s983 :: SWord1 = choose [23:23] s724
-  s984 :: SBool = s13 /= s983
-  s985 :: SBool = ~ s984
-  s986 :: SBool = if s862 then s985 else s984
-  s987 :: SBool = ~ s986
-  s988 :: SBool = if s902 then s987 else s986
-  s989 :: SBool = ~ s988
-  s990 :: SBool = if s958 then s989 else s988
-  s991 :: SWord1 = choose [22:22] s724
-  s992 :: SBool = s13 /= s991
-  s993 :: SBool = ~ s992
-  s994 :: SBool = if s870 then s993 else s992
-  s995 :: SBool = ~ s994
-  s996 :: SBool = if s910 then s995 else s994
-  s997 :: SBool = ~ s996
-  s998 :: SBool = if s966 then s997 else s996
-  s999 :: SWord1 = choose [21:21] s724
-  s1000 :: SBool = s13 /= s999
-  s1001 :: SBool = ~ s1000
-  s1002 :: SBool = if s878 then s1001 else s1000
-  s1003 :: SBool = ~ s1002
-  s1004 :: SBool = if s918 then s1003 else s1002
-  s1005 :: SBool = ~ s1004
-  s1006 :: SBool = if s974 then s1005 else s1004
-  s1007 :: SWord1 = choose [20:20] s724
-  s1008 :: SBool = s13 /= s1007
-  s1009 :: SBool = ~ s1008
-  s1010 :: SBool = if s886 then s1009 else s1008
-  s1011 :: SBool = ~ s1010
-  s1012 :: SBool = if s926 then s1011 else s1010
-  s1013 :: SBool = ~ s1012
-  s1014 :: SBool = if s982 then s1013 else s1012
-  s1015 :: SWord1 = choose [19:19] s724
-  s1016 :: SBool = s13 /= s1015
-  s1017 :: SBool = ~ s1016
-  s1018 :: SBool = if s894 then s1017 else s1016
-  s1019 :: SBool = ~ s1018
-  s1020 :: SBool = if s934 then s1019 else s1018
-  s1021 :: SBool = ~ s1020
-  s1022 :: SBool = if s990 then s1021 else s1020
-  s1023 :: SWord1 = choose [18:18] s724
-  s1024 :: SBool = s13 /= s1023
-  s1025 :: SBool = ~ s1024
-  s1026 :: SBool = if s902 then s1025 else s1024
-  s1027 :: SBool = ~ s1026
-  s1028 :: SBool = if s942 then s1027 else s1026
-  s1029 :: SBool = ~ s1028
-  s1030 :: SBool = if s998 then s1029 else s1028
-  s1031 :: SWord1 = choose [17:17] s724
-  s1032 :: SBool = s13 /= s1031
-  s1033 :: SBool = ~ s1032
-  s1034 :: SBool = if s910 then s1033 else s1032
-  s1035 :: SBool = ~ s1034
-  s1036 :: SBool = if s950 then s1035 else s1034
-  s1037 :: SBool = ~ s1036
-  s1038 :: SBool = if s1006 then s1037 else s1036
-  s1039 :: SWord1 = choose [16:16] s724
-  s1040 :: SBool = s13 /= s1039
-  s1041 :: SBool = ~ s1040
-  s1042 :: SBool = if s918 then s1041 else s1040
-  s1043 :: SBool = ~ s1042
-  s1044 :: SBool = if s958 then s1043 else s1042
-  s1045 :: SBool = ~ s1044
-  s1046 :: SBool = if s1014 then s1045 else s1044
-  s1047 :: SBool = ~ s726
-  s1048 :: SBool = if s726 then s1047 else s726
-  s1049 :: SBool = ~ s728
-  s1050 :: SBool = if s728 then s1049 else s728
-  s1051 :: SBool = ~ s730
-  s1052 :: SBool = if s730 then s1051 else s730
-  s1053 :: SBool = ~ s732
-  s1054 :: SBool = if s732 then s1053 else s732
-  s1055 :: SBool = ~ s736
-  s1056 :: SBool = if s736 then s1055 else s736
-  s1057 :: SBool = ~ s740
-  s1058 :: SBool = if s740 then s1057 else s740
-  s1059 :: SBool = ~ s744
-  s1060 :: SBool = if s744 then s1059 else s744
-  s1061 :: SBool = ~ s748
-  s1062 :: SBool = if s748 then s1061 else s748
-  s1063 :: SBool = ~ s752
-  s1064 :: SBool = if s752 then s1063 else s752
-  s1065 :: SBool = ~ s756
-  s1066 :: SBool = if s756 then s1065 else s756
-  s1067 :: SBool = ~ s760
-  s1068 :: SBool = if s760 then s1067 else s760
-  s1069 :: SBool = ~ s766
-  s1070 :: SBool = if s766 then s1069 else s766
-  s1071 :: SBool = ~ s772
-  s1072 :: SBool = if s772 then s1071 else s772
-  s1073 :: SBool = ~ s778
-  s1074 :: SBool = if s778 then s1073 else s778
-  s1075 :: SBool = ~ s784
-  s1076 :: SBool = if s784 then s1075 else s784
-  s1077 :: SBool = ~ s790
-  s1078 :: SBool = if s790 then s1077 else s790
-  s1079 :: SBool = ~ s798
-  s1080 :: SBool = if s798 then s1079 else s798
-  s1081 :: SBool = ~ s806
-  s1082 :: SBool = if s806 then s1081 else s806
-  s1083 :: SBool = ~ s814
-  s1084 :: SBool = if s814 then s1083 else s814
-  s1085 :: SBool = ~ s822
-  s1086 :: SBool = if s822 then s1085 else s822
-  s1087 :: SBool = ~ s830
-  s1088 :: SBool = if s830 then s1087 else s830
-  s1089 :: SBool = ~ s838
-  s1090 :: SBool = if s838 then s1089 else s838
-  s1091 :: SBool = ~ s846
-  s1092 :: SBool = if s846 then s1091 else s846
-  s1093 :: SBool = ~ s854
-  s1094 :: SBool = if s854 then s1093 else s854
-  s1095 :: SBool = ~ s862
-  s1096 :: SBool = if s862 then s1095 else s862
-  s1097 :: SBool = ~ s870
-  s1098 :: SBool = if s870 then s1097 else s870
-  s1099 :: SBool = ~ s878
-  s1100 :: SBool = if s878 then s1099 else s878
-  s1101 :: SBool = ~ s886
-  s1102 :: SBool = if s886 then s1101 else s886
-  s1103 :: SBool = ~ s894
-  s1104 :: SBool = if s894 then s1103 else s894
-  s1105 :: SBool = ~ s902
-  s1106 :: SBool = if s902 then s1105 else s902
-  s1107 :: SBool = ~ s910
-  s1108 :: SBool = if s910 then s1107 else s910
-  s1109 :: SBool = ~ s918
-  s1110 :: SBool = if s918 then s1109 else s918
-  s1111 :: SBool = ~ s926
-  s1112 :: SBool = if s926 then s1111 else s926
-  s1113 :: SBool = ~ s934
-  s1114 :: SBool = if s934 then s1113 else s934
-  s1115 :: SBool = ~ s942
-  s1116 :: SBool = if s942 then s1115 else s942
-  s1117 :: SBool = ~ s950
-  s1118 :: SBool = if s950 then s1117 else s950
-  s1119 :: SBool = ~ s958
-  s1120 :: SBool = if s958 then s1119 else s958
-  s1121 :: SBool = ~ s966
-  s1122 :: SBool = if s966 then s1121 else s966
-  s1123 :: SBool = ~ s974
-  s1124 :: SBool = if s974 then s1123 else s974
-  s1125 :: SBool = ~ s982
-  s1126 :: SBool = if s982 then s1125 else s982
-  s1127 :: SBool = ~ s990
-  s1128 :: SBool = if s990 then s1127 else s990
-  s1129 :: SBool = ~ s998
-  s1130 :: SBool = if s998 then s1129 else s998
-  s1131 :: SBool = ~ s1006
-  s1132 :: SBool = if s1006 then s1131 else s1006
-  s1133 :: SBool = ~ s1014
-  s1134 :: SBool = if s1014 then s1133 else s1014
-  s1135 :: SBool = ~ s1022
-  s1136 :: SBool = if s1022 then s1135 else s1022
-  s1137 :: SBool = ~ s1030
-  s1138 :: SBool = if s1030 then s1137 else s1030
-  s1139 :: SBool = ~ s1038
-  s1140 :: SBool = if s1038 then s1139 else s1038
-  s1141 :: SBool = ~ s1046
-  s1142 :: SBool = if s1046 then s1141 else s1046
-  s1143 :: SWord1 = choose [15:15] s724
-  s1144 :: SBool = s13 /= s1143
-  s1145 :: SBool = ~ s1144
-  s1146 :: SBool = if s926 then s1145 else s1144
-  s1147 :: SBool = ~ s1146
-  s1148 :: SBool = if s966 then s1147 else s1146
-  s1149 :: SBool = ~ s1148
-  s1150 :: SBool = if s1022 then s1149 else s1148
-  s1151 :: SWord1 = choose [14:14] s724
-  s1152 :: SBool = s13 /= s1151
-  s1153 :: SBool = ~ s1152
-  s1154 :: SBool = if s934 then s1153 else s1152
-  s1155 :: SBool = ~ s1154
-  s1156 :: SBool = if s974 then s1155 else s1154
-  s1157 :: SBool = ~ s1156
-  s1158 :: SBool = if s1030 then s1157 else s1156
-  s1159 :: SWord1 = choose [13:13] s724
-  s1160 :: SBool = s13 /= s1159
-  s1161 :: SBool = ~ s1160
-  s1162 :: SBool = if s942 then s1161 else s1160
-  s1163 :: SBool = ~ s1162
-  s1164 :: SBool = if s982 then s1163 else s1162
-  s1165 :: SBool = ~ s1164
-  s1166 :: SBool = if s1038 then s1165 else s1164
-  s1167 :: SWord1 = choose [12:12] s724
-  s1168 :: SBool = s13 /= s1167
-  s1169 :: SBool = ~ s1168
-  s1170 :: SBool = if s950 then s1169 else s1168
-  s1171 :: SBool = ~ s1170
-  s1172 :: SBool = if s990 then s1171 else s1170
-  s1173 :: SBool = ~ s1172
-  s1174 :: SBool = if s1046 then s1173 else s1172
-  s1175 :: SWord1 = choose [11:11] s724
-  s1176 :: SBool = s13 /= s1175
-  s1177 :: SBool = ~ s1176
-  s1178 :: SBool = if s958 then s1177 else s1176
-  s1179 :: SBool = ~ s1178
-  s1180 :: SBool = if s998 then s1179 else s1178
-  s1181 :: SWord1 = choose [10:10] s724
-  s1182 :: SBool = s13 /= s1181
-  s1183 :: SBool = ~ s1182
-  s1184 :: SBool = if s966 then s1183 else s1182
-  s1185 :: SBool = ~ s1184
-  s1186 :: SBool = if s1006 then s1185 else s1184
-  s1187 :: SWord1 = choose [9:9] s724
-  s1188 :: SBool = s13 /= s1187
-  s1189 :: SBool = ~ s1188
-  s1190 :: SBool = if s974 then s1189 else s1188
-  s1191 :: SBool = ~ s1190
-  s1192 :: SBool = if s1014 then s1191 else s1190
-  s1193 :: SWord1 = choose [8:8] s724
-  s1194 :: SBool = s13 /= s1193
-  s1195 :: SBool = ~ s1194
-  s1196 :: SBool = if s982 then s1195 else s1194
-  s1197 :: SBool = ~ s1196
-  s1198 :: SBool = if s1022 then s1197 else s1196
-  s1199 :: SWord1 = choose [7:7] s724
-  s1200 :: SBool = s13 /= s1199
-  s1201 :: SBool = ~ s1200
-  s1202 :: SBool = if s990 then s1201 else s1200
-  s1203 :: SBool = ~ s1202
-  s1204 :: SBool = if s1030 then s1203 else s1202
-  s1205 :: SWord1 = choose [6:6] s724
-  s1206 :: SBool = s13 /= s1205
-  s1207 :: SBool = ~ s1206
-  s1208 :: SBool = if s998 then s1207 else s1206
-  s1209 :: SBool = ~ s1208
-  s1210 :: SBool = if s1038 then s1209 else s1208
-  s1211 :: SWord1 = choose [5:5] s724
-  s1212 :: SBool = s13 /= s1211
-  s1213 :: SBool = ~ s1212
-  s1214 :: SBool = if s1006 then s1213 else s1212
-  s1215 :: SBool = ~ s1214
-  s1216 :: SBool = if s1046 then s1215 else s1214
-  s1217 :: SWord1 = choose [4:4] s724
-  s1218 :: SBool = s13 /= s1217
-  s1219 :: SBool = ~ s1218
-  s1220 :: SBool = if s1014 then s1219 else s1218
-  s1221 :: SWord1 = choose [3:3] s724
-  s1222 :: SBool = s13 /= s1221
-  s1223 :: SBool = ~ s1222
-  s1224 :: SBool = if s1022 then s1223 else s1222
-  s1225 :: SWord1 = choose [2:2] s724
-  s1226 :: SBool = s13 /= s1225
-  s1227 :: SBool = ~ s1226
-  s1228 :: SBool = if s1030 then s1227 else s1226
-  s1229 :: SWord1 = choose [1:1] s724
-  s1230 :: SBool = s13 /= s1229
-  s1231 :: SBool = ~ s1230
-  s1232 :: SBool = if s1038 then s1231 else s1230
-  s1233 :: SWord1 = choose [0:0] s724
-  s1234 :: SBool = s13 /= s1233
-  s1235 :: SBool = ~ s1234
-  s1236 :: SBool = if s1046 then s1235 else s1234
-  s1237 :: SWord64 = if s1236 then s525 else s526
-  s1238 :: SWord64 = s528 | s1237
-  s1239 :: SWord64 = if s1232 then s1238 else s1237
-  s1240 :: SWord64 = s531 | s1239
-  s1241 :: SWord64 = if s1228 then s1240 else s1239
-  s1242 :: SWord64 = s534 | s1241
-  s1243 :: SWord64 = if s1224 then s1242 else s1241
-  s1244 :: SWord64 = s537 | s1243
-  s1245 :: SWord64 = if s1220 then s1244 else s1243
-  s1246 :: SWord64 = s540 | s1245
-  s1247 :: SWord64 = if s1216 then s1246 else s1245
-  s1248 :: SWord64 = s543 | s1247
-  s1249 :: SWord64 = if s1210 then s1248 else s1247
-  s1250 :: SWord64 = s546 | s1249
-  s1251 :: SWord64 = if s1204 then s1250 else s1249
-  s1252 :: SWord64 = s549 | s1251
-  s1253 :: SWord64 = if s1198 then s1252 else s1251
-  s1254 :: SWord64 = s552 | s1253
-  s1255 :: SWord64 = if s1192 then s1254 else s1253
-  s1256 :: SWord64 = s555 | s1255
-  s1257 :: SWord64 = if s1186 then s1256 else s1255
-  s1258 :: SWord64 = s558 | s1257
-  s1259 :: SWord64 = if s1180 then s1258 else s1257
-  s1260 :: SWord64 = s561 | s1259
-  s1261 :: SWord64 = if s1174 then s1260 else s1259
-  s1262 :: SWord64 = s564 | s1261
-  s1263 :: SWord64 = if s1166 then s1262 else s1261
-  s1264 :: SWord64 = s567 | s1263
-  s1265 :: SWord64 = if s1158 then s1264 else s1263
-  s1266 :: SWord64 = s570 | s1265
-  s1267 :: SWord64 = if s1150 then s1266 else s1265
-  s1268 :: SWord64 = s573 | s1267
-  s1269 :: SWord64 = if s1142 then s1268 else s1267
-  s1270 :: SWord64 = s576 | s1269
-  s1271 :: SWord64 = if s1140 then s1270 else s1269
-  s1272 :: SWord64 = s579 | s1271
-  s1273 :: SWord64 = if s1138 then s1272 else s1271
-  s1274 :: SWord64 = s582 | s1273
-  s1275 :: SWord64 = if s1136 then s1274 else s1273
-  s1276 :: SWord64 = s585 | s1275
-  s1277 :: SWord64 = if s1134 then s1276 else s1275
-  s1278 :: SWord64 = s588 | s1277
-  s1279 :: SWord64 = if s1132 then s1278 else s1277
-  s1280 :: SWord64 = s591 | s1279
-  s1281 :: SWord64 = if s1130 then s1280 else s1279
-  s1282 :: SWord64 = s594 | s1281
-  s1283 :: SWord64 = if s1128 then s1282 else s1281
-  s1284 :: SWord64 = s597 | s1283
-  s1285 :: SWord64 = if s1126 then s1284 else s1283
-  s1286 :: SWord64 = s600 | s1285
-  s1287 :: SWord64 = if s1124 then s1286 else s1285
-  s1288 :: SWord64 = s603 | s1287
-  s1289 :: SWord64 = if s1122 then s1288 else s1287
-  s1290 :: SWord64 = s606 | s1289
-  s1291 :: SWord64 = if s1120 then s1290 else s1289
-  s1292 :: SWord64 = s609 | s1291
-  s1293 :: SWord64 = if s1118 then s1292 else s1291
-  s1294 :: SWord64 = s612 | s1293
-  s1295 :: SWord64 = if s1116 then s1294 else s1293
-  s1296 :: SWord64 = s615 | s1295
-  s1297 :: SWord64 = if s1114 then s1296 else s1295
-  s1298 :: SWord64 = s618 | s1297
-  s1299 :: SWord64 = if s1112 then s1298 else s1297
-  s1300 :: SWord64 = s621 | s1299
-  s1301 :: SWord64 = if s1110 then s1300 else s1299
-  s1302 :: SWord64 = s624 | s1301
-  s1303 :: SWord64 = if s1108 then s1302 else s1301
-  s1304 :: SWord64 = s627 | s1303
-  s1305 :: SWord64 = if s1106 then s1304 else s1303
-  s1306 :: SWord64 = s630 | s1305
-  s1307 :: SWord64 = if s1104 then s1306 else s1305
-  s1308 :: SWord64 = s633 | s1307
-  s1309 :: SWord64 = if s1102 then s1308 else s1307
-  s1310 :: SWord64 = s636 | s1309
-  s1311 :: SWord64 = if s1100 then s1310 else s1309
-  s1312 :: SWord64 = s639 | s1311
-  s1313 :: SWord64 = if s1098 then s1312 else s1311
-  s1314 :: SWord64 = s642 | s1313
-  s1315 :: SWord64 = if s1096 then s1314 else s1313
-  s1316 :: SWord64 = s645 | s1315
-  s1317 :: SWord64 = if s1094 then s1316 else s1315
-  s1318 :: SWord64 = s648 | s1317
-  s1319 :: SWord64 = if s1092 then s1318 else s1317
-  s1320 :: SWord64 = s651 | s1319
-  s1321 :: SWord64 = if s1090 then s1320 else s1319
-  s1322 :: SWord64 = s654 | s1321
-  s1323 :: SWord64 = if s1088 then s1322 else s1321
-  s1324 :: SWord64 = s657 | s1323
-  s1325 :: SWord64 = if s1086 then s1324 else s1323
-  s1326 :: SWord64 = s660 | s1325
-  s1327 :: SWord64 = if s1084 then s1326 else s1325
-  s1328 :: SWord64 = s663 | s1327
-  s1329 :: SWord64 = if s1082 then s1328 else s1327
-  s1330 :: SWord64 = s666 | s1329
-  s1331 :: SWord64 = if s1080 then s1330 else s1329
-  s1332 :: SWord64 = s669 | s1331
-  s1333 :: SWord64 = if s1078 then s1332 else s1331
-  s1334 :: SWord64 = s672 | s1333
-  s1335 :: SWord64 = if s1076 then s1334 else s1333
-  s1336 :: SWord64 = s675 | s1335
-  s1337 :: SWord64 = if s1074 then s1336 else s1335
-  s1338 :: SWord64 = s678 | s1337
-  s1339 :: SWord64 = if s1072 then s1338 else s1337
-  s1340 :: SWord64 = s681 | s1339
-  s1341 :: SWord64 = if s1070 then s1340 else s1339
-  s1342 :: SWord64 = s684 | s1341
-  s1343 :: SWord64 = if s1068 then s1342 else s1341
-  s1344 :: SWord64 = s687 | s1343
-  s1345 :: SWord64 = if s1066 then s1344 else s1343
-  s1346 :: SWord64 = s690 | s1345
-  s1347 :: SWord64 = if s1064 then s1346 else s1345
-  s1348 :: SWord64 = s693 | s1347
-  s1349 :: SWord64 = if s1062 then s1348 else s1347
-  s1350 :: SWord64 = s696 | s1349
-  s1351 :: SWord64 = if s1060 then s1350 else s1349
-  s1352 :: SWord64 = s699 | s1351
-  s1353 :: SWord64 = if s1058 then s1352 else s1351
-  s1354 :: SWord64 = s702 | s1353
-  s1355 :: SWord64 = if s1056 then s1354 else s1353
-  s1356 :: SWord64 = s705 | s1355
-  s1357 :: SWord64 = if s1054 then s1356 else s1355
-  s1358 :: SWord64 = s708 | s1357
-  s1359 :: SWord64 = if s1052 then s1358 else s1357
-  s1360 :: SWord64 = s711 | s1359
-  s1361 :: SWord64 = if s1050 then s1360 else s1359
-  s1362 :: SWord64 = s714 | s1361
-  s1363 :: SWord64 = if s1048 then s1362 else s1361
-  s1364 :: SWord32 = choose [31:0] s1363
-  s1365 :: SWord16 = choose [15:0] s1364
-  s1366 :: SWord32 = s3 # s1365
-  s1367 :: SWord64 = s2 # s1366
-  s1368 :: SWord1 = choose [0:0] s1367
-  s1369 :: SBool = s13 /= s1368
-  s1370 :: SBool = s722 == s1369
-  s1371 :: SWord1 = choose [1:1] s720
-  s1372 :: SBool = s13 /= s1371
-  s1373 :: SWord1 = choose [1:1] s1367
-  s1374 :: SBool = s13 /= s1373
-  s1375 :: SBool = s1372 == s1374
-  s1376 :: SWord1 = choose [2:2] s720
-  s1377 :: SBool = s13 /= s1376
-  s1378 :: SWord1 = choose [2:2] s1367
-  s1379 :: SBool = s13 /= s1378
-  s1380 :: SBool = s1377 == s1379
-  s1381 :: SWord1 = choose [3:3] s720
-  s1382 :: SBool = s13 /= s1381
-  s1383 :: SWord1 = choose [3:3] s1367
-  s1384 :: SBool = s13 /= s1383
-  s1385 :: SBool = s1382 == s1384
-  s1386 :: SWord1 = choose [4:4] s720
-  s1387 :: SBool = s13 /= s1386
-  s1388 :: SWord1 = choose [4:4] s1367
-  s1389 :: SBool = s13 /= s1388
-  s1390 :: SBool = s1387 == s1389
-  s1391 :: SWord1 = choose [5:5] s720
-  s1392 :: SBool = s13 /= s1391
-  s1393 :: SWord1 = choose [5:5] s1367
-  s1394 :: SBool = s13 /= s1393
-  s1395 :: SBool = s1392 == s1394
-  s1396 :: SWord1 = choose [6:6] s720
-  s1397 :: SBool = s13 /= s1396
-  s1398 :: SWord1 = choose [6:6] s1367
-  s1399 :: SBool = s13 /= s1398
-  s1400 :: SBool = s1397 == s1399
-  s1401 :: SWord1 = choose [7:7] s720
-  s1402 :: SBool = s13 /= s1401
-  s1403 :: SWord1 = choose [7:7] s1367
-  s1404 :: SBool = s13 /= s1403
-  s1405 :: SBool = s1402 == s1404
-  s1406 :: SWord1 = choose [8:8] s720
-  s1407 :: SBool = s13 /= s1406
-  s1408 :: SWord1 = choose [8:8] s1367
-  s1409 :: SBool = s13 /= s1408
-  s1410 :: SBool = s1407 == s1409
-  s1411 :: SWord1 = choose [9:9] s720
-  s1412 :: SBool = s13 /= s1411
-  s1413 :: SWord1 = choose [9:9] s1367
-  s1414 :: SBool = s13 /= s1413
-  s1415 :: SBool = s1412 == s1414
-  s1416 :: SWord1 = choose [10:10] s720
-  s1417 :: SBool = s13 /= s1416
-  s1418 :: SWord1 = choose [10:10] s1367
-  s1419 :: SBool = s13 /= s1418
-  s1420 :: SBool = s1417 == s1419
-  s1421 :: SWord1 = choose [11:11] s720
-  s1422 :: SBool = s13 /= s1421
-  s1423 :: SWord1 = choose [11:11] s1367
-  s1424 :: SBool = s13 /= s1423
-  s1425 :: SBool = s1422 == s1424
-  s1426 :: SWord1 = choose [12:12] s720
-  s1427 :: SBool = s13 /= s1426
-  s1428 :: SWord1 = choose [12:12] s1367
-  s1429 :: SBool = s13 /= s1428
-  s1430 :: SBool = s1427 == s1429
-  s1431 :: SWord1 = choose [13:13] s720
-  s1432 :: SBool = s13 /= s1431
-  s1433 :: SWord1 = choose [13:13] s1367
-  s1434 :: SBool = s13 /= s1433
-  s1435 :: SBool = s1432 == s1434
-  s1436 :: SWord1 = choose [14:14] s720
-  s1437 :: SBool = s13 /= s1436
-  s1438 :: SWord1 = choose [14:14] s1367
-  s1439 :: SBool = s13 /= s1438
-  s1440 :: SBool = s1437 == s1439
-  s1441 :: SWord1 = choose [15:15] s720
-  s1442 :: SBool = s13 /= s1441
-  s1443 :: SWord1 = choose [15:15] s1367
-  s1444 :: SBool = s13 /= s1443
-  s1445 :: SBool = s1442 == s1444
-  s1446 :: SWord1 = choose [16:16] s720
-  s1447 :: SBool = s13 /= s1446
-  s1448 :: SWord1 = choose [16:16] s1367
-  s1449 :: SBool = s13 /= s1448
-  s1450 :: SBool = s1447 == s1449
-  s1451 :: SWord1 = choose [17:17] s720
-  s1452 :: SBool = s13 /= s1451
-  s1453 :: SWord1 = choose [17:17] s1367
-  s1454 :: SBool = s13 /= s1453
-  s1455 :: SBool = s1452 == s1454
-  s1456 :: SWord1 = choose [18:18] s720
-  s1457 :: SBool = s13 /= s1456
-  s1458 :: SWord1 = choose [18:18] s1367
-  s1459 :: SBool = s13 /= s1458
-  s1460 :: SBool = s1457 == s1459
-  s1461 :: SWord1 = choose [19:19] s720
-  s1462 :: SBool = s13 /= s1461
-  s1463 :: SWord1 = choose [19:19] s1367
-  s1464 :: SBool = s13 /= s1463
-  s1465 :: SBool = s1462 == s1464
-  s1466 :: SWord1 = choose [20:20] s720
-  s1467 :: SBool = s13 /= s1466
-  s1468 :: SWord1 = choose [20:20] s1367
-  s1469 :: SBool = s13 /= s1468
-  s1470 :: SBool = s1467 == s1469
-  s1471 :: SWord1 = choose [21:21] s720
-  s1472 :: SBool = s13 /= s1471
-  s1473 :: SWord1 = choose [21:21] s1367
-  s1474 :: SBool = s13 /= s1473
-  s1475 :: SBool = s1472 == s1474
-  s1476 :: SWord1 = choose [22:22] s720
-  s1477 :: SBool = s13 /= s1476
-  s1478 :: SWord1 = choose [22:22] s1367
-  s1479 :: SBool = s13 /= s1478
-  s1480 :: SBool = s1477 == s1479
-  s1481 :: SWord1 = choose [23:23] s720
-  s1482 :: SBool = s13 /= s1481
-  s1483 :: SWord1 = choose [23:23] s1367
-  s1484 :: SBool = s13 /= s1483
-  s1485 :: SBool = s1482 == s1484
-  s1486 :: SWord1 = choose [24:24] s720
-  s1487 :: SBool = s13 /= s1486
-  s1488 :: SWord1 = choose [24:24] s1367
-  s1489 :: SBool = s13 /= s1488
-  s1490 :: SBool = s1487 == s1489
-  s1491 :: SWord1 = choose [25:25] s720
-  s1492 :: SBool = s13 /= s1491
-  s1493 :: SWord1 = choose [25:25] s1367
-  s1494 :: SBool = s13 /= s1493
-  s1495 :: SBool = s1492 == s1494
-  s1496 :: SWord1 = choose [26:26] s720
-  s1497 :: SBool = s13 /= s1496
-  s1498 :: SWord1 = choose [26:26] s1367
-  s1499 :: SBool = s13 /= s1498
-  s1500 :: SBool = s1497 == s1499
-  s1501 :: SWord1 = choose [27:27] s720
-  s1502 :: SBool = s13 /= s1501
-  s1503 :: SWord1 = choose [27:27] s1367
-  s1504 :: SBool = s13 /= s1503
-  s1505 :: SBool = s1502 == s1504
-  s1506 :: SWord1 = choose [28:28] s720
-  s1507 :: SBool = s13 /= s1506
-  s1508 :: SWord1 = choose [28:28] s1367
-  s1509 :: SBool = s13 /= s1508
-  s1510 :: SBool = s1507 == s1509
-  s1511 :: SWord1 = choose [29:29] s720
-  s1512 :: SBool = s13 /= s1511
-  s1513 :: SWord1 = choose [29:29] s1367
-  s1514 :: SBool = s13 /= s1513
-  s1515 :: SBool = s1512 == s1514
-  s1516 :: SWord1 = choose [30:30] s720
-  s1517 :: SBool = s13 /= s1516
-  s1518 :: SWord1 = choose [30:30] s1367
-  s1519 :: SBool = s13 /= s1518
-  s1520 :: SBool = s1517 == s1519
-  s1521 :: SWord1 = choose [31:31] s720
-  s1522 :: SBool = s13 /= s1521
-  s1523 :: SWord1 = choose [31:31] s1367
-  s1524 :: SBool = s13 /= s1523
-  s1525 :: SBool = s1522 == s1524
-  s1526 :: SWord1 = choose [32:32] s720
-  s1527 :: SBool = s13 /= s1526
-  s1528 :: SWord1 = choose [32:32] s1367
-  s1529 :: SBool = s13 /= s1528
-  s1530 :: SBool = s1527 == s1529
-  s1531 :: SWord1 = choose [33:33] s720
-  s1532 :: SBool = s13 /= s1531
-  s1533 :: SWord1 = choose [33:33] s1367
-  s1534 :: SBool = s13 /= s1533
-  s1535 :: SBool = s1532 == s1534
-  s1536 :: SWord1 = choose [34:34] s720
-  s1537 :: SBool = s13 /= s1536
-  s1538 :: SWord1 = choose [34:34] s1367
-  s1539 :: SBool = s13 /= s1538
-  s1540 :: SBool = s1537 == s1539
-  s1541 :: SWord1 = choose [35:35] s720
-  s1542 :: SBool = s13 /= s1541
-  s1543 :: SWord1 = choose [35:35] s1367
-  s1544 :: SBool = s13 /= s1543
-  s1545 :: SBool = s1542 == s1544
-  s1546 :: SWord1 = choose [36:36] s720
-  s1547 :: SBool = s13 /= s1546
-  s1548 :: SWord1 = choose [36:36] s1367
-  s1549 :: SBool = s13 /= s1548
-  s1550 :: SBool = s1547 == s1549
-  s1551 :: SWord1 = choose [37:37] s720
-  s1552 :: SBool = s13 /= s1551
-  s1553 :: SWord1 = choose [37:37] s1367
-  s1554 :: SBool = s13 /= s1553
-  s1555 :: SBool = s1552 == s1554
-  s1556 :: SWord1 = choose [38:38] s720
-  s1557 :: SBool = s13 /= s1556
-  s1558 :: SWord1 = choose [38:38] s1367
-  s1559 :: SBool = s13 /= s1558
-  s1560 :: SBool = s1557 == s1559
-  s1561 :: SWord1 = choose [39:39] s720
-  s1562 :: SBool = s13 /= s1561
-  s1563 :: SWord1 = choose [39:39] s1367
-  s1564 :: SBool = s13 /= s1563
-  s1565 :: SBool = s1562 == s1564
-  s1566 :: SWord1 = choose [40:40] s720
-  s1567 :: SBool = s13 /= s1566
-  s1568 :: SWord1 = choose [40:40] s1367
-  s1569 :: SBool = s13 /= s1568
-  s1570 :: SBool = s1567 == s1569
-  s1571 :: SWord1 = choose [41:41] s720
-  s1572 :: SBool = s13 /= s1571
-  s1573 :: SWord1 = choose [41:41] s1367
-  s1574 :: SBool = s13 /= s1573
-  s1575 :: SBool = s1572 == s1574
-  s1576 :: SWord1 = choose [42:42] s720
-  s1577 :: SBool = s13 /= s1576
-  s1578 :: SWord1 = choose [42:42] s1367
-  s1579 :: SBool = s13 /= s1578
-  s1580 :: SBool = s1577 == s1579
-  s1581 :: SWord1 = choose [43:43] s720
-  s1582 :: SBool = s13 /= s1581
-  s1583 :: SWord1 = choose [43:43] s1367
-  s1584 :: SBool = s13 /= s1583
-  s1585 :: SBool = s1582 == s1584
-  s1586 :: SWord1 = choose [44:44] s720
-  s1587 :: SBool = s13 /= s1586
-  s1588 :: SWord1 = choose [44:44] s1367
-  s1589 :: SBool = s13 /= s1588
-  s1590 :: SBool = s1587 == s1589
-  s1591 :: SWord1 = choose [45:45] s720
-  s1592 :: SBool = s13 /= s1591
-  s1593 :: SWord1 = choose [45:45] s1367
-  s1594 :: SBool = s13 /= s1593
-  s1595 :: SBool = s1592 == s1594
-  s1596 :: SWord1 = choose [46:46] s720
-  s1597 :: SBool = s13 /= s1596
-  s1598 :: SWord1 = choose [46:46] s1367
-  s1599 :: SBool = s13 /= s1598
-  s1600 :: SBool = s1597 == s1599
-  s1601 :: SWord1 = choose [47:47] s720
-  s1602 :: SBool = s13 /= s1601
-  s1603 :: SWord1 = choose [47:47] s1367
-  s1604 :: SBool = s13 /= s1603
-  s1605 :: SBool = s1602 == s1604
-  s1606 :: SWord1 = choose [48:48] s720
-  s1607 :: SBool = s13 /= s1606
-  s1608 :: SWord1 = choose [48:48] s1367
-  s1609 :: SBool = s13 /= s1608
-  s1610 :: SBool = s1607 == s1609
-  s1611 :: SWord1 = choose [49:49] s720
-  s1612 :: SBool = s13 /= s1611
-  s1613 :: SWord1 = choose [49:49] s1367
-  s1614 :: SBool = s13 /= s1613
-  s1615 :: SBool = s1612 == s1614
-  s1616 :: SWord1 = choose [50:50] s720
-  s1617 :: SBool = s13 /= s1616
-  s1618 :: SWord1 = choose [50:50] s1367
-  s1619 :: SBool = s13 /= s1618
-  s1620 :: SBool = s1617 == s1619
-  s1621 :: SWord1 = choose [51:51] s720
-  s1622 :: SBool = s13 /= s1621
-  s1623 :: SWord1 = choose [51:51] s1367
-  s1624 :: SBool = s13 /= s1623
-  s1625 :: SBool = s1622 == s1624
-  s1626 :: SWord1 = choose [52:52] s720
-  s1627 :: SBool = s13 /= s1626
-  s1628 :: SWord1 = choose [52:52] s1367
-  s1629 :: SBool = s13 /= s1628
-  s1630 :: SBool = s1627 == s1629
-  s1631 :: SWord1 = choose [53:53] s720
-  s1632 :: SBool = s13 /= s1631
-  s1633 :: SWord1 = choose [53:53] s1367
-  s1634 :: SBool = s13 /= s1633
-  s1635 :: SBool = s1632 == s1634
-  s1636 :: SWord1 = choose [54:54] s720
-  s1637 :: SBool = s13 /= s1636
-  s1638 :: SWord1 = choose [54:54] s1367
-  s1639 :: SBool = s13 /= s1638
-  s1640 :: SBool = s1637 == s1639
-  s1641 :: SWord1 = choose [55:55] s720
-  s1642 :: SBool = s13 /= s1641
-  s1643 :: SWord1 = choose [55:55] s1367
-  s1644 :: SBool = s13 /= s1643
-  s1645 :: SBool = s1642 == s1644
-  s1646 :: SWord1 = choose [56:56] s720
-  s1647 :: SBool = s13 /= s1646
-  s1648 :: SWord1 = choose [56:56] s1367
-  s1649 :: SBool = s13 /= s1648
-  s1650 :: SBool = s1647 == s1649
-  s1651 :: SWord1 = choose [57:57] s720
-  s1652 :: SBool = s13 /= s1651
-  s1653 :: SWord1 = choose [57:57] s1367
-  s1654 :: SBool = s13 /= s1653
-  s1655 :: SBool = s1652 == s1654
-  s1656 :: SWord1 = choose [58:58] s720
-  s1657 :: SBool = s13 /= s1656
-  s1658 :: SWord1 = choose [58:58] s1367
-  s1659 :: SBool = s13 /= s1658
-  s1660 :: SBool = s1657 == s1659
-  s1661 :: SWord1 = choose [59:59] s720
-  s1662 :: SBool = s13 /= s1661
-  s1663 :: SWord1 = choose [59:59] s1367
-  s1664 :: SBool = s13 /= s1663
-  s1665 :: SBool = s1662 == s1664
-  s1666 :: SWord1 = choose [60:60] s720
-  s1667 :: SBool = s13 /= s1666
-  s1668 :: SWord1 = choose [60:60] s1367
-  s1669 :: SBool = s13 /= s1668
-  s1670 :: SBool = s1667 == s1669
-  s1671 :: SWord1 = choose [61:61] s720
-  s1672 :: SBool = s13 /= s1671
-  s1673 :: SWord1 = choose [61:61] s1367
-  s1674 :: SBool = s13 /= s1673
-  s1675 :: SBool = s1672 == s1674
-  s1676 :: SWord1 = choose [62:62] s720
-  s1677 :: SBool = s13 /= s1676
-  s1678 :: SWord1 = choose [62:62] s1367
-  s1679 :: SBool = s13 /= s1678
-  s1680 :: SBool = s1677 == s1679
-  s1681 :: SWord1 = choose [63:63] s720
-  s1682 :: SBool = s13 /= s1681
-  s1683 :: SWord1 = choose [63:63] s1367
-  s1684 :: SBool = s13 /= s1683
-  s1685 :: SBool = s1682 == s1684
-  s1688 :: SWord8 = if s1685 then s1686 else s1687
-  s1689 :: SWord8 = s1687 + s1688
-  s1690 :: SWord8 = if s1680 then s1688 else s1689
-  s1691 :: SWord8 = s1687 + s1690
-  s1692 :: SWord8 = if s1675 then s1690 else s1691
-  s1693 :: SWord8 = s1687 + s1692
-  s1694 :: SWord8 = if s1670 then s1692 else s1693
-  s1695 :: SWord8 = s1687 + s1694
-  s1696 :: SWord8 = if s1665 then s1694 else s1695
-  s1697 :: SWord8 = s1687 + s1696
-  s1698 :: SWord8 = if s1660 then s1696 else s1697
-  s1699 :: SWord8 = s1687 + s1698
-  s1700 :: SWord8 = if s1655 then s1698 else s1699
-  s1701 :: SWord8 = s1687 + s1700
-  s1702 :: SWord8 = if s1650 then s1700 else s1701
-  s1703 :: SWord8 = s1687 + s1702
-  s1704 :: SWord8 = if s1645 then s1702 else s1703
-  s1705 :: SWord8 = s1687 + s1704
-  s1706 :: SWord8 = if s1640 then s1704 else s1705
-  s1707 :: SWord8 = s1687 + s1706
-  s1708 :: SWord8 = if s1635 then s1706 else s1707
-  s1709 :: SWord8 = s1687 + s1708
-  s1710 :: SWord8 = if s1630 then s1708 else s1709
-  s1711 :: SWord8 = s1687 + s1710
-  s1712 :: SWord8 = if s1625 then s1710 else s1711
-  s1713 :: SWord8 = s1687 + s1712
-  s1714 :: SWord8 = if s1620 then s1712 else s1713
-  s1715 :: SWord8 = s1687 + s1714
-  s1716 :: SWord8 = if s1615 then s1714 else s1715
-  s1717 :: SWord8 = s1687 + s1716
-  s1718 :: SWord8 = if s1610 then s1716 else s1717
-  s1719 :: SWord8 = s1687 + s1718
-  s1720 :: SWord8 = if s1605 then s1718 else s1719
-  s1721 :: SWord8 = s1687 + s1720
-  s1722 :: SWord8 = if s1600 then s1720 else s1721
-  s1723 :: SWord8 = s1687 + s1722
-  s1724 :: SWord8 = if s1595 then s1722 else s1723
-  s1725 :: SWord8 = s1687 + s1724
-  s1726 :: SWord8 = if s1590 then s1724 else s1725
-  s1727 :: SWord8 = s1687 + s1726
-  s1728 :: SWord8 = if s1585 then s1726 else s1727
-  s1729 :: SWord8 = s1687 + s1728
-  s1730 :: SWord8 = if s1580 then s1728 else s1729
-  s1731 :: SWord8 = s1687 + s1730
-  s1732 :: SWord8 = if s1575 then s1730 else s1731
-  s1733 :: SWord8 = s1687 + s1732
-  s1734 :: SWord8 = if s1570 then s1732 else s1733
-  s1735 :: SWord8 = s1687 + s1734
-  s1736 :: SWord8 = if s1565 then s1734 else s1735
-  s1737 :: SWord8 = s1687 + s1736
-  s1738 :: SWord8 = if s1560 then s1736 else s1737
-  s1739 :: SWord8 = s1687 + s1738
-  s1740 :: SWord8 = if s1555 then s1738 else s1739
-  s1741 :: SWord8 = s1687 + s1740
-  s1742 :: SWord8 = if s1550 then s1740 else s1741
-  s1743 :: SWord8 = s1687 + s1742
-  s1744 :: SWord8 = if s1545 then s1742 else s1743
-  s1745 :: SWord8 = s1687 + s1744
-  s1746 :: SWord8 = if s1540 then s1744 else s1745
-  s1747 :: SWord8 = s1687 + s1746
-  s1748 :: SWord8 = if s1535 then s1746 else s1747
-  s1749 :: SWord8 = s1687 + s1748
-  s1750 :: SWord8 = if s1530 then s1748 else s1749
-  s1751 :: SWord8 = s1687 + s1750
-  s1752 :: SWord8 = if s1525 then s1750 else s1751
-  s1753 :: SWord8 = s1687 + s1752
-  s1754 :: SWord8 = if s1520 then s1752 else s1753
-  s1755 :: SWord8 = s1687 + s1754
-  s1756 :: SWord8 = if s1515 then s1754 else s1755
-  s1757 :: SWord8 = s1687 + s1756
-  s1758 :: SWord8 = if s1510 then s1756 else s1757
-  s1759 :: SWord8 = s1687 + s1758
-  s1760 :: SWord8 = if s1505 then s1758 else s1759
-  s1761 :: SWord8 = s1687 + s1760
-  s1762 :: SWord8 = if s1500 then s1760 else s1761
-  s1763 :: SWord8 = s1687 + s1762
-  s1764 :: SWord8 = if s1495 then s1762 else s1763
-  s1765 :: SWord8 = s1687 + s1764
-  s1766 :: SWord8 = if s1490 then s1764 else s1765
-  s1767 :: SWord8 = s1687 + s1766
-  s1768 :: SWord8 = if s1485 then s1766 else s1767
-  s1769 :: SWord8 = s1687 + s1768
-  s1770 :: SWord8 = if s1480 then s1768 else s1769
-  s1771 :: SWord8 = s1687 + s1770
-  s1772 :: SWord8 = if s1475 then s1770 else s1771
-  s1773 :: SWord8 = s1687 + s1772
-  s1774 :: SWord8 = if s1470 then s1772 else s1773
-  s1775 :: SWord8 = s1687 + s1774
-  s1776 :: SWord8 = if s1465 then s1774 else s1775
-  s1777 :: SWord8 = s1687 + s1776
-  s1778 :: SWord8 = if s1460 then s1776 else s1777
-  s1779 :: SWord8 = s1687 + s1778
-  s1780 :: SWord8 = if s1455 then s1778 else s1779
-  s1781 :: SWord8 = s1687 + s1780
-  s1782 :: SWord8 = if s1450 then s1780 else s1781
-  s1783 :: SWord8 = s1687 + s1782
-  s1784 :: SWord8 = if s1445 then s1782 else s1783
-  s1785 :: SWord8 = s1687 + s1784
-  s1786 :: SWord8 = if s1440 then s1784 else s1785
-  s1787 :: SWord8 = s1687 + s1786
-  s1788 :: SWord8 = if s1435 then s1786 else s1787
-  s1789 :: SWord8 = s1687 + s1788
-  s1790 :: SWord8 = if s1430 then s1788 else s1789
-  s1791 :: SWord8 = s1687 + s1790
-  s1792 :: SWord8 = if s1425 then s1790 else s1791
-  s1793 :: SWord8 = s1687 + s1792
-  s1794 :: SWord8 = if s1420 then s1792 else s1793
-  s1795 :: SWord8 = s1687 + s1794
-  s1796 :: SWord8 = if s1415 then s1794 else s1795
-  s1797 :: SWord8 = s1687 + s1796
-  s1798 :: SWord8 = if s1410 then s1796 else s1797
-  s1799 :: SWord8 = s1687 + s1798
-  s1800 :: SWord8 = if s1405 then s1798 else s1799
-  s1801 :: SWord8 = s1687 + s1800
-  s1802 :: SWord8 = if s1400 then s1800 else s1801
-  s1803 :: SWord8 = s1687 + s1802
-  s1804 :: SWord8 = if s1395 then s1802 else s1803
-  s1805 :: SWord8 = s1687 + s1804
-  s1806 :: SWord8 = if s1390 then s1804 else s1805
-  s1807 :: SWord8 = s1687 + s1806
-  s1808 :: SWord8 = if s1385 then s1806 else s1807
-  s1809 :: SWord8 = s1687 + s1808
-  s1810 :: SWord8 = if s1380 then s1808 else s1809
-  s1811 :: SWord8 = s1687 + s1810
-  s1812 :: SWord8 = if s1375 then s1810 else s1811
-  s1813 :: SWord8 = s1687 + s1812
-  s1814 :: SWord8 = if s1370 then s1812 else s1813
-  s1816 :: SBool = s1814 > s1815
-  s1817 :: SBool = s8 | s1816
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1817
diff --git a/SBVUnitTest/GoldFiles/cgUninterpret.gold b/SBVUnitTest/GoldFiles/cgUninterpret.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/cgUninterpret.gold
+++ /dev/null
@@ -1,114 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for tstShiftLeft. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: tstShiftLeft_driver
-
-tstShiftLeft.o: tstShiftLeft.c tstShiftLeft.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-tstShiftLeft_driver.o: tstShiftLeft_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-tstShiftLeft_driver: tstShiftLeft.o tstShiftLeft_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f tstShiftLeft_driver
-== END: "Makefile" ==================
-== BEGIN: "tstShiftLeft.h" ================
-/* Header file for tstShiftLeft. Automatically generated by SBV. Do not edit! */
-
-#ifndef __tstShiftLeft__HEADER_INCLUDED__
-#define __tstShiftLeft__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord32 tstShiftLeft(const SWord32 *vs);
-
-#endif /* __tstShiftLeft__HEADER_INCLUDED__ */
-== END: "tstShiftLeft.h" ==================
-== BEGIN: "tstShiftLeft_driver.c" ================
-/* Example driver program for tstShiftLeft. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "tstShiftLeft.h"
-
-int main(void)
-{
-  const SWord32 vs[3] = {
-      0x00000001UL, 0x00000002UL, 0x00000003UL
-  };
-
-  printf("Contents of input array vs:\n");
-  int vs_ctr;
-  for(vs_ctr = 0; vs_ctr < 3 ; ++vs_ctr)
-    printf("  vs[%d] = 0x%08"PRIx32"UL\n", vs_ctr ,vs[vs_ctr]);
-
-
-  const SWord32 __result = tstShiftLeft(vs);
-
-  printf("tstShiftLeft(vs) = 0x%08"PRIx32"UL\n", __result);
-
-  return 0;
-}
-== END: "tstShiftLeft_driver.c" ==================
-== BEGIN: "tstShiftLeft.c" ================
-/* File: "tstShiftLeft.c". Automatically generated by SBV. Do not edit! */
-
-#include "tstShiftLeft.h"
-
-/* User specified custom code for "SBV_SHIFTLEFT" */
-#define SBV_SHIFTLEFT(x, y) ((x) << (y))
-
-SWord32 tstShiftLeft(const SWord32 *vs)
-{
-  const SWord32 s0 = vs[0];
-  const SWord32 s1 = vs[1];
-  const SWord32 s2 = vs[2];
-  const SWord32 s3 = /* Uninterpreted function */ SBV_SHIFTLEFT(s0,
-                                                                s2);
-  const SWord32 s4 = /* Uninterpreted function */ SBV_SHIFTLEFT(s1,
-                                                                s2);
-  const SWord32 s5 = s3 + s4;
-
-  return s5;
-}
-== END: "tstShiftLeft.c" ==================
diff --git a/SBVUnitTest/GoldFiles/codeGen1.gold b/SBVUnitTest/GoldFiles/codeGen1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/codeGen1.gold
+++ /dev/null
@@ -1,230 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for foo. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: foo_driver
-
-foo.o: foo.c foo.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-foo_driver.o: foo_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-foo_driver: foo.o foo_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f foo_driver
-== END: "Makefile" ==================
-== BEGIN: "foo.h" ================
-/* Header file for foo. Automatically generated by SBV. Do not edit! */
-
-#ifndef __foo__HEADER_INCLUDED__
-#define __foo__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SInt16 foo(const SInt16 x, const SInt64 *xArr, SWord16 *z,
-           SInt16 *zArr, SInt64 *yArr);
-
-#endif /* __foo__HEADER_INCLUDED__ */
-== END: "foo.h" ==================
-== BEGIN: "foo_driver.c" ================
-/* Example driver program for foo. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "foo.h"
-
-int main(void)
-{
-  const SInt64 xArr[45] = {
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL,
-      0x0000000000000000LL, 0x0000000000000000LL, 0x0000000000000000LL
-  };
-
-  printf("Contents of input array xArr:\n");
-  int xArr_ctr;
-  for(xArr_ctr = 0; xArr_ctr < 45 ; ++xArr_ctr)
-    printf("  xArr[%d] = %"PRId64"LL\n", xArr_ctr ,xArr[xArr_ctr]);
-
-  SWord16 z;
-  SInt16 zArr[7];
-  SInt64 yArr[45];
-
-  const SInt16 __result = foo(0x0000, xArr, &z, zArr, yArr);
-
-  printf("foo(0x0000, xArr, &z, zArr, yArr) = %"PRId16"\n", __result);
-  printf("  z = 0x%04"PRIx16"U\n", z);
-  int zArr_ctr;
-  for(zArr_ctr = 0; zArr_ctr < 7 ; ++zArr_ctr)
-    printf("  zArr[%d] = %"PRId16"\n", zArr_ctr ,zArr[zArr_ctr]);
-  int yArr_ctr;
-  for(yArr_ctr = 0; yArr_ctr < 45 ; ++yArr_ctr)
-    printf("  yArr[%d] = %"PRId64"LL\n", yArr_ctr ,yArr[yArr_ctr]);
-
-  return 0;
-}
-== END: "foo_driver.c" ==================
-== BEGIN: "foo.c" ================
-/* File: "foo.c". Automatically generated by SBV. Do not edit! */
-
-#include "foo.h"
-
-SInt16 foo(const SInt16 x, const SInt64 *xArr, SWord16 *z,
-           SInt16 *zArr, SInt64 *yArr)
-{
-  const SInt16 s0 = x;
-  const SInt64 s1 = xArr[0];
-  const SInt64 s2 = xArr[1];
-  const SInt64 s3 = xArr[2];
-  const SInt64 s4 = xArr[3];
-  const SInt64 s5 = xArr[4];
-  const SInt64 s6 = xArr[5];
-  const SInt64 s7 = xArr[6];
-  const SInt64 s8 = xArr[7];
-  const SInt64 s9 = xArr[8];
-  const SInt64 s10 = xArr[9];
-  const SInt64 s11 = xArr[10];
-  const SInt64 s12 = xArr[11];
-  const SInt64 s13 = xArr[12];
-  const SInt64 s14 = xArr[13];
-  const SInt64 s15 = xArr[14];
-  const SInt64 s16 = xArr[15];
-  const SInt64 s17 = xArr[16];
-  const SInt64 s18 = xArr[17];
-  const SInt64 s19 = xArr[18];
-  const SInt64 s20 = xArr[19];
-  const SInt64 s21 = xArr[20];
-  const SInt64 s22 = xArr[21];
-  const SInt64 s23 = xArr[22];
-  const SInt64 s24 = xArr[23];
-  const SInt64 s25 = xArr[24];
-  const SInt64 s26 = xArr[25];
-  const SInt64 s27 = xArr[26];
-  const SInt64 s28 = xArr[27];
-  const SInt64 s29 = xArr[28];
-  const SInt64 s30 = xArr[29];
-  const SInt64 s31 = xArr[30];
-  const SInt64 s32 = xArr[31];
-  const SInt64 s33 = xArr[32];
-  const SInt64 s34 = xArr[33];
-  const SInt64 s35 = xArr[34];
-  const SInt64 s36 = xArr[35];
-  const SInt64 s37 = xArr[36];
-  const SInt64 s38 = xArr[37];
-  const SInt64 s39 = xArr[38];
-  const SInt64 s40 = xArr[39];
-  const SInt64 s41 = xArr[40];
-  const SInt64 s42 = xArr[41];
-  const SInt64 s43 = xArr[42];
-  const SInt64 s44 = xArr[43];
-  const SInt64 s45 = xArr[44];
-  const SInt16 s48 = s0 + 0x0001;
-  const SInt16 s50 = s0 * 0x0002;
-
-  *z = 0x0005U;
-  zArr[0] = s48;
-  zArr[1] = s48;
-  zArr[2] = s48;
-  zArr[3] = s48;
-  zArr[4] = s48;
-  zArr[5] = s48;
-  zArr[6] = s48;
-  yArr[0] = s1;
-  yArr[1] = s2;
-  yArr[2] = s3;
-  yArr[3] = s4;
-  yArr[4] = s5;
-  yArr[5] = s6;
-  yArr[6] = s7;
-  yArr[7] = s8;
-  yArr[8] = s9;
-  yArr[9] = s10;
-  yArr[10] = s11;
-  yArr[11] = s12;
-  yArr[12] = s13;
-  yArr[13] = s14;
-  yArr[14] = s15;
-  yArr[15] = s16;
-  yArr[16] = s17;
-  yArr[17] = s18;
-  yArr[18] = s19;
-  yArr[19] = s20;
-  yArr[20] = s21;
-  yArr[21] = s22;
-  yArr[22] = s23;
-  yArr[23] = s24;
-  yArr[24] = s25;
-  yArr[25] = s26;
-  yArr[26] = s27;
-  yArr[27] = s28;
-  yArr[28] = s29;
-  yArr[29] = s30;
-  yArr[30] = s31;
-  yArr[31] = s32;
-  yArr[32] = s33;
-  yArr[33] = s34;
-  yArr[34] = s35;
-  yArr[35] = s36;
-  yArr[36] = s37;
-  yArr[37] = s38;
-  yArr[38] = s39;
-  yArr[39] = s40;
-  yArr[40] = s41;
-  yArr[41] = s42;
-  yArr[42] = s43;
-  yArr[43] = s44;
-  yArr[44] = s45;
-  return s50;
-}
-== END: "foo.c" ==================
diff --git a/SBVUnitTest/GoldFiles/coins.gold b/SBVUnitTest/GoldFiles/coins.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/coins.gold
+++ /dev/null
@@ -1,916 +0,0 @@
-INPUTS
-  s0 :: SWord16, existential, aliasing "c1"
-  s18 :: SWord16, existential, aliasing "c2"
-  s30 :: SWord16, existential, aliasing "c3"
-  s42 :: SWord16, existential, aliasing "c4"
-  s54 :: SWord16, existential, aliasing "c5"
-  s66 :: SWord16, existential, aliasing "c6"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s1 = 1 :: Word16
-  s3 = 5 :: Word16
-  s5 = 10 :: Word16
-  s7 = 25 :: Word16
-  s9 = 50 :: Word16
-  s11 = 100 :: Word16
-  s84 = 0 :: Word16
-  s88 = 95 :: Word16
-  s551 = 115 :: Word16
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s2 :: SBool = s0 == s1
-  s4 :: SBool = s0 == s3
-  s6 :: SBool = s0 == s5
-  s8 :: SBool = s0 == s7
-  s10 :: SBool = s0 == s9
-  s12 :: SBool = s0 == s11
-  s13 :: SBool = s10 | s12
-  s14 :: SBool = s8 | s13
-  s15 :: SBool = s6 | s14
-  s16 :: SBool = s4 | s15
-  s17 :: SBool = s2 | s16
-  s19 :: SBool = s1 == s18
-  s20 :: SBool = s3 == s18
-  s21 :: SBool = s5 == s18
-  s22 :: SBool = s7 == s18
-  s23 :: SBool = s9 == s18
-  s24 :: SBool = s11 == s18
-  s25 :: SBool = s23 | s24
-  s26 :: SBool = s22 | s25
-  s27 :: SBool = s21 | s26
-  s28 :: SBool = s20 | s27
-  s29 :: SBool = s19 | s28
-  s31 :: SBool = s1 == s30
-  s32 :: SBool = s3 == s30
-  s33 :: SBool = s5 == s30
-  s34 :: SBool = s7 == s30
-  s35 :: SBool = s9 == s30
-  s36 :: SBool = s11 == s30
-  s37 :: SBool = s35 | s36
-  s38 :: SBool = s34 | s37
-  s39 :: SBool = s33 | s38
-  s40 :: SBool = s32 | s39
-  s41 :: SBool = s31 | s40
-  s43 :: SBool = s1 == s42
-  s44 :: SBool = s3 == s42
-  s45 :: SBool = s5 == s42
-  s46 :: SBool = s7 == s42
-  s47 :: SBool = s9 == s42
-  s48 :: SBool = s11 == s42
-  s49 :: SBool = s47 | s48
-  s50 :: SBool = s46 | s49
-  s51 :: SBool = s45 | s50
-  s52 :: SBool = s44 | s51
-  s53 :: SBool = s43 | s52
-  s55 :: SBool = s1 == s54
-  s56 :: SBool = s3 == s54
-  s57 :: SBool = s5 == s54
-  s58 :: SBool = s7 == s54
-  s59 :: SBool = s9 == s54
-  s60 :: SBool = s11 == s54
-  s61 :: SBool = s59 | s60
-  s62 :: SBool = s58 | s61
-  s63 :: SBool = s57 | s62
-  s64 :: SBool = s56 | s63
-  s65 :: SBool = s55 | s64
-  s67 :: SBool = s1 == s66
-  s68 :: SBool = s3 == s66
-  s69 :: SBool = s5 == s66
-  s70 :: SBool = s7 == s66
-  s71 :: SBool = s9 == s66
-  s72 :: SBool = s11 == s66
-  s73 :: SBool = s71 | s72
-  s74 :: SBool = s70 | s73
-  s75 :: SBool = s69 | s74
-  s76 :: SBool = s68 | s75
-  s77 :: SBool = s67 | s76
-  s78 :: SWord16 = s0 + s18
-  s79 :: SBool = s11 /= s78
-  s80 :: SBool = s9 /= s78
-  s81 :: SBool = s7 /= s78
-  s82 :: SBool = s5 /= s78
-  s83 :: SBool = s3 /= s78
-  s85 :: SWord16 = if s10 then s84 else s0
-  s86 :: SWord16 = if s23 then s84 else s18
-  s87 :: SWord16 = s85 + s86
-  s89 :: SBool = s87 /= s88
-  s90 :: SWord16 = s0 + s30
-  s91 :: SBool = s11 /= s90
-  s92 :: SBool = s9 /= s90
-  s93 :: SBool = s7 /= s90
-  s94 :: SBool = s5 /= s90
-  s95 :: SBool = s3 /= s90
-  s96 :: SWord16 = if s35 then s84 else s30
-  s97 :: SWord16 = s85 + s96
-  s98 :: SBool = s88 /= s97
-  s99 :: SWord16 = s0 + s42
-  s100 :: SBool = s11 /= s99
-  s101 :: SBool = s9 /= s99
-  s102 :: SBool = s7 /= s99
-  s103 :: SBool = s5 /= s99
-  s104 :: SBool = s3 /= s99
-  s105 :: SWord16 = if s47 then s84 else s42
-  s106 :: SWord16 = s85 + s105
-  s107 :: SBool = s88 /= s106
-  s108 :: SWord16 = s0 + s54
-  s109 :: SBool = s11 /= s108
-  s110 :: SBool = s9 /= s108
-  s111 :: SBool = s7 /= s108
-  s112 :: SBool = s5 /= s108
-  s113 :: SBool = s3 /= s108
-  s114 :: SWord16 = if s59 then s84 else s54
-  s115 :: SWord16 = s85 + s114
-  s116 :: SBool = s88 /= s115
-  s117 :: SWord16 = s0 + s66
-  s118 :: SBool = s11 /= s117
-  s119 :: SBool = s9 /= s117
-  s120 :: SBool = s7 /= s117
-  s121 :: SBool = s5 /= s117
-  s122 :: SBool = s3 /= s117
-  s123 :: SWord16 = if s71 then s84 else s66
-  s124 :: SWord16 = s85 + s123
-  s125 :: SBool = s88 /= s124
-  s126 :: SWord16 = s18 + s30
-  s127 :: SBool = s11 /= s126
-  s128 :: SBool = s9 /= s126
-  s129 :: SBool = s7 /= s126
-  s130 :: SBool = s5 /= s126
-  s131 :: SBool = s3 /= s126
-  s132 :: SWord16 = s86 + s96
-  s133 :: SBool = s88 /= s132
-  s134 :: SWord16 = s18 + s42
-  s135 :: SBool = s11 /= s134
-  s136 :: SBool = s9 /= s134
-  s137 :: SBool = s7 /= s134
-  s138 :: SBool = s5 /= s134
-  s139 :: SBool = s3 /= s134
-  s140 :: SWord16 = s86 + s105
-  s141 :: SBool = s88 /= s140
-  s142 :: SWord16 = s18 + s54
-  s143 :: SBool = s11 /= s142
-  s144 :: SBool = s9 /= s142
-  s145 :: SBool = s7 /= s142
-  s146 :: SBool = s5 /= s142
-  s147 :: SBool = s3 /= s142
-  s148 :: SWord16 = s86 + s114
-  s149 :: SBool = s88 /= s148
-  s150 :: SWord16 = s18 + s66
-  s151 :: SBool = s11 /= s150
-  s152 :: SBool = s9 /= s150
-  s153 :: SBool = s7 /= s150
-  s154 :: SBool = s5 /= s150
-  s155 :: SBool = s3 /= s150
-  s156 :: SWord16 = s86 + s123
-  s157 :: SBool = s88 /= s156
-  s158 :: SWord16 = s30 + s42
-  s159 :: SBool = s11 /= s158
-  s160 :: SBool = s9 /= s158
-  s161 :: SBool = s7 /= s158
-  s162 :: SBool = s5 /= s158
-  s163 :: SBool = s3 /= s158
-  s164 :: SWord16 = s96 + s105
-  s165 :: SBool = s88 /= s164
-  s166 :: SWord16 = s30 + s54
-  s167 :: SBool = s11 /= s166
-  s168 :: SBool = s9 /= s166
-  s169 :: SBool = s7 /= s166
-  s170 :: SBool = s5 /= s166
-  s171 :: SBool = s3 /= s166
-  s172 :: SWord16 = s96 + s114
-  s173 :: SBool = s88 /= s172
-  s174 :: SWord16 = s30 + s66
-  s175 :: SBool = s11 /= s174
-  s176 :: SBool = s9 /= s174
-  s177 :: SBool = s7 /= s174
-  s178 :: SBool = s5 /= s174
-  s179 :: SBool = s3 /= s174
-  s180 :: SWord16 = s96 + s123
-  s181 :: SBool = s88 /= s180
-  s182 :: SWord16 = s42 + s54
-  s183 :: SBool = s11 /= s182
-  s184 :: SBool = s9 /= s182
-  s185 :: SBool = s7 /= s182
-  s186 :: SBool = s5 /= s182
-  s187 :: SBool = s3 /= s182
-  s188 :: SWord16 = s105 + s114
-  s189 :: SBool = s88 /= s188
-  s190 :: SWord16 = s42 + s66
-  s191 :: SBool = s11 /= s190
-  s192 :: SBool = s9 /= s190
-  s193 :: SBool = s7 /= s190
-  s194 :: SBool = s5 /= s190
-  s195 :: SBool = s3 /= s190
-  s196 :: SWord16 = s105 + s123
-  s197 :: SBool = s88 /= s196
-  s198 :: SWord16 = s54 + s66
-  s199 :: SBool = s11 /= s198
-  s200 :: SBool = s9 /= s198
-  s201 :: SBool = s7 /= s198
-  s202 :: SBool = s5 /= s198
-  s203 :: SBool = s3 /= s198
-  s204 :: SWord16 = s114 + s123
-  s205 :: SBool = s88 /= s204
-  s206 :: SWord16 = s30 + s78
-  s207 :: SBool = s11 /= s206
-  s208 :: SBool = s9 /= s206
-  s209 :: SBool = s7 /= s206
-  s210 :: SBool = s5 /= s206
-  s211 :: SBool = s3 /= s206
-  s212 :: SWord16 = s87 + s96
-  s213 :: SBool = s88 /= s212
-  s214 :: SWord16 = s42 + s78
-  s215 :: SBool = s11 /= s214
-  s216 :: SBool = s9 /= s214
-  s217 :: SBool = s7 /= s214
-  s218 :: SBool = s5 /= s214
-  s219 :: SBool = s3 /= s214
-  s220 :: SWord16 = s87 + s105
-  s221 :: SBool = s88 /= s220
-  s222 :: SWord16 = s54 + s78
-  s223 :: SBool = s11 /= s222
-  s224 :: SBool = s9 /= s222
-  s225 :: SBool = s7 /= s222
-  s226 :: SBool = s5 /= s222
-  s227 :: SBool = s3 /= s222
-  s228 :: SWord16 = s87 + s114
-  s229 :: SBool = s88 /= s228
-  s230 :: SWord16 = s66 + s78
-  s231 :: SBool = s11 /= s230
-  s232 :: SBool = s9 /= s230
-  s233 :: SBool = s7 /= s230
-  s234 :: SBool = s5 /= s230
-  s235 :: SBool = s3 /= s230
-  s236 :: SWord16 = s87 + s123
-  s237 :: SBool = s88 /= s236
-  s238 :: SWord16 = s42 + s90
-  s239 :: SBool = s11 /= s238
-  s240 :: SBool = s9 /= s238
-  s241 :: SBool = s7 /= s238
-  s242 :: SBool = s5 /= s238
-  s243 :: SBool = s3 /= s238
-  s244 :: SWord16 = s97 + s105
-  s245 :: SBool = s88 /= s244
-  s246 :: SWord16 = s54 + s90
-  s247 :: SBool = s11 /= s246
-  s248 :: SBool = s9 /= s246
-  s249 :: SBool = s7 /= s246
-  s250 :: SBool = s5 /= s246
-  s251 :: SBool = s3 /= s246
-  s252 :: SWord16 = s97 + s114
-  s253 :: SBool = s88 /= s252
-  s254 :: SWord16 = s66 + s90
-  s255 :: SBool = s11 /= s254
-  s256 :: SBool = s9 /= s254
-  s257 :: SBool = s7 /= s254
-  s258 :: SBool = s5 /= s254
-  s259 :: SBool = s3 /= s254
-  s260 :: SWord16 = s97 + s123
-  s261 :: SBool = s88 /= s260
-  s262 :: SWord16 = s54 + s99
-  s263 :: SBool = s11 /= s262
-  s264 :: SBool = s9 /= s262
-  s265 :: SBool = s7 /= s262
-  s266 :: SBool = s5 /= s262
-  s267 :: SBool = s3 /= s262
-  s268 :: SWord16 = s106 + s114
-  s269 :: SBool = s88 /= s268
-  s270 :: SWord16 = s66 + s99
-  s271 :: SBool = s11 /= s270
-  s272 :: SBool = s9 /= s270
-  s273 :: SBool = s7 /= s270
-  s274 :: SBool = s5 /= s270
-  s275 :: SBool = s3 /= s270
-  s276 :: SWord16 = s106 + s123
-  s277 :: SBool = s88 /= s276
-  s278 :: SWord16 = s66 + s108
-  s279 :: SBool = s11 /= s278
-  s280 :: SBool = s9 /= s278
-  s281 :: SBool = s7 /= s278
-  s282 :: SBool = s5 /= s278
-  s283 :: SBool = s3 /= s278
-  s284 :: SWord16 = s115 + s123
-  s285 :: SBool = s88 /= s284
-  s286 :: SWord16 = s42 + s126
-  s287 :: SBool = s11 /= s286
-  s288 :: SBool = s9 /= s286
-  s289 :: SBool = s7 /= s286
-  s290 :: SBool = s5 /= s286
-  s291 :: SBool = s3 /= s286
-  s292 :: SWord16 = s105 + s132
-  s293 :: SBool = s88 /= s292
-  s294 :: SWord16 = s54 + s126
-  s295 :: SBool = s11 /= s294
-  s296 :: SBool = s9 /= s294
-  s297 :: SBool = s7 /= s294
-  s298 :: SBool = s5 /= s294
-  s299 :: SBool = s3 /= s294
-  s300 :: SWord16 = s114 + s132
-  s301 :: SBool = s88 /= s300
-  s302 :: SWord16 = s66 + s126
-  s303 :: SBool = s11 /= s302
-  s304 :: SBool = s9 /= s302
-  s305 :: SBool = s7 /= s302
-  s306 :: SBool = s5 /= s302
-  s307 :: SBool = s3 /= s302
-  s308 :: SWord16 = s123 + s132
-  s309 :: SBool = s88 /= s308
-  s310 :: SWord16 = s54 + s134
-  s311 :: SBool = s11 /= s310
-  s312 :: SBool = s9 /= s310
-  s313 :: SBool = s7 /= s310
-  s314 :: SBool = s5 /= s310
-  s315 :: SBool = s3 /= s310
-  s316 :: SWord16 = s114 + s140
-  s317 :: SBool = s88 /= s316
-  s318 :: SWord16 = s66 + s134
-  s319 :: SBool = s11 /= s318
-  s320 :: SBool = s9 /= s318
-  s321 :: SBool = s7 /= s318
-  s322 :: SBool = s5 /= s318
-  s323 :: SBool = s3 /= s318
-  s324 :: SWord16 = s123 + s140
-  s325 :: SBool = s88 /= s324
-  s326 :: SWord16 = s66 + s142
-  s327 :: SBool = s11 /= s326
-  s328 :: SBool = s9 /= s326
-  s329 :: SBool = s7 /= s326
-  s330 :: SBool = s5 /= s326
-  s331 :: SBool = s3 /= s326
-  s332 :: SWord16 = s123 + s148
-  s333 :: SBool = s88 /= s332
-  s334 :: SWord16 = s54 + s158
-  s335 :: SBool = s11 /= s334
-  s336 :: SBool = s9 /= s334
-  s337 :: SBool = s7 /= s334
-  s338 :: SBool = s5 /= s334
-  s339 :: SBool = s3 /= s334
-  s340 :: SWord16 = s114 + s164
-  s341 :: SBool = s88 /= s340
-  s342 :: SWord16 = s66 + s158
-  s343 :: SBool = s11 /= s342
-  s344 :: SBool = s9 /= s342
-  s345 :: SBool = s7 /= s342
-  s346 :: SBool = s5 /= s342
-  s347 :: SBool = s3 /= s342
-  s348 :: SWord16 = s123 + s164
-  s349 :: SBool = s88 /= s348
-  s350 :: SWord16 = s66 + s166
-  s351 :: SBool = s11 /= s350
-  s352 :: SBool = s9 /= s350
-  s353 :: SBool = s7 /= s350
-  s354 :: SBool = s5 /= s350
-  s355 :: SBool = s3 /= s350
-  s356 :: SWord16 = s123 + s172
-  s357 :: SBool = s88 /= s356
-  s358 :: SWord16 = s66 + s182
-  s359 :: SBool = s11 /= s358
-  s360 :: SBool = s9 /= s358
-  s361 :: SBool = s7 /= s358
-  s362 :: SBool = s5 /= s358
-  s363 :: SBool = s3 /= s358
-  s364 :: SWord16 = s123 + s188
-  s365 :: SBool = s88 /= s364
-  s366 :: SWord16 = s42 + s206
-  s367 :: SBool = s11 /= s366
-  s368 :: SBool = s9 /= s366
-  s369 :: SBool = s7 /= s366
-  s370 :: SBool = s5 /= s366
-  s371 :: SBool = s3 /= s366
-  s372 :: SWord16 = s105 + s212
-  s373 :: SBool = s88 /= s372
-  s374 :: SWord16 = s54 + s206
-  s375 :: SBool = s11 /= s374
-  s376 :: SBool = s9 /= s374
-  s377 :: SBool = s7 /= s374
-  s378 :: SBool = s5 /= s374
-  s379 :: SBool = s3 /= s374
-  s380 :: SWord16 = s114 + s212
-  s381 :: SBool = s88 /= s380
-  s382 :: SWord16 = s66 + s206
-  s383 :: SBool = s11 /= s382
-  s384 :: SBool = s9 /= s382
-  s385 :: SBool = s7 /= s382
-  s386 :: SBool = s5 /= s382
-  s387 :: SBool = s3 /= s382
-  s388 :: SWord16 = s123 + s212
-  s389 :: SBool = s88 /= s388
-  s390 :: SWord16 = s54 + s214
-  s391 :: SBool = s11 /= s390
-  s392 :: SBool = s9 /= s390
-  s393 :: SBool = s7 /= s390
-  s394 :: SBool = s5 /= s390
-  s395 :: SBool = s3 /= s390
-  s396 :: SWord16 = s114 + s220
-  s397 :: SBool = s88 /= s396
-  s398 :: SWord16 = s66 + s214
-  s399 :: SBool = s11 /= s398
-  s400 :: SBool = s9 /= s398
-  s401 :: SBool = s7 /= s398
-  s402 :: SBool = s5 /= s398
-  s403 :: SBool = s3 /= s398
-  s404 :: SWord16 = s123 + s220
-  s405 :: SBool = s88 /= s404
-  s406 :: SWord16 = s66 + s222
-  s407 :: SBool = s11 /= s406
-  s408 :: SBool = s9 /= s406
-  s409 :: SBool = s7 /= s406
-  s410 :: SBool = s5 /= s406
-  s411 :: SBool = s3 /= s406
-  s412 :: SWord16 = s123 + s228
-  s413 :: SBool = s88 /= s412
-  s414 :: SWord16 = s54 + s238
-  s415 :: SBool = s11 /= s414
-  s416 :: SBool = s9 /= s414
-  s417 :: SBool = s7 /= s414
-  s418 :: SBool = s5 /= s414
-  s419 :: SBool = s3 /= s414
-  s420 :: SWord16 = s114 + s244
-  s421 :: SBool = s88 /= s420
-  s422 :: SWord16 = s66 + s238
-  s423 :: SBool = s11 /= s422
-  s424 :: SBool = s9 /= s422
-  s425 :: SBool = s7 /= s422
-  s426 :: SBool = s5 /= s422
-  s427 :: SBool = s3 /= s422
-  s428 :: SWord16 = s123 + s244
-  s429 :: SBool = s88 /= s428
-  s430 :: SWord16 = s66 + s246
-  s431 :: SBool = s11 /= s430
-  s432 :: SBool = s9 /= s430
-  s433 :: SBool = s7 /= s430
-  s434 :: SBool = s5 /= s430
-  s435 :: SBool = s3 /= s430
-  s436 :: SWord16 = s123 + s252
-  s437 :: SBool = s88 /= s436
-  s438 :: SWord16 = s66 + s262
-  s439 :: SBool = s11 /= s438
-  s440 :: SBool = s9 /= s438
-  s441 :: SBool = s7 /= s438
-  s442 :: SBool = s5 /= s438
-  s443 :: SBool = s3 /= s438
-  s444 :: SWord16 = s123 + s268
-  s445 :: SBool = s88 /= s444
-  s446 :: SWord16 = s54 + s286
-  s447 :: SBool = s11 /= s446
-  s448 :: SBool = s9 /= s446
-  s449 :: SBool = s7 /= s446
-  s450 :: SBool = s5 /= s446
-  s451 :: SBool = s3 /= s446
-  s452 :: SWord16 = s114 + s292
-  s453 :: SBool = s88 /= s452
-  s454 :: SWord16 = s66 + s286
-  s455 :: SBool = s11 /= s454
-  s456 :: SBool = s9 /= s454
-  s457 :: SBool = s7 /= s454
-  s458 :: SBool = s5 /= s454
-  s459 :: SBool = s3 /= s454
-  s460 :: SWord16 = s123 + s292
-  s461 :: SBool = s88 /= s460
-  s462 :: SWord16 = s66 + s294
-  s463 :: SBool = s11 /= s462
-  s464 :: SBool = s9 /= s462
-  s465 :: SBool = s7 /= s462
-  s466 :: SBool = s5 /= s462
-  s467 :: SBool = s3 /= s462
-  s468 :: SWord16 = s123 + s300
-  s469 :: SBool = s88 /= s468
-  s470 :: SWord16 = s66 + s310
-  s471 :: SBool = s11 /= s470
-  s472 :: SBool = s9 /= s470
-  s473 :: SBool = s7 /= s470
-  s474 :: SBool = s5 /= s470
-  s475 :: SBool = s3 /= s470
-  s476 :: SWord16 = s123 + s316
-  s477 :: SBool = s88 /= s476
-  s478 :: SWord16 = s66 + s334
-  s479 :: SBool = s11 /= s478
-  s480 :: SBool = s9 /= s478
-  s481 :: SBool = s7 /= s478
-  s482 :: SBool = s5 /= s478
-  s483 :: SBool = s3 /= s478
-  s484 :: SWord16 = s123 + s340
-  s485 :: SBool = s88 /= s484
-  s486 :: SWord16 = s54 + s366
-  s487 :: SBool = s11 /= s486
-  s488 :: SBool = s9 /= s486
-  s489 :: SBool = s7 /= s486
-  s490 :: SBool = s5 /= s486
-  s491 :: SBool = s3 /= s486
-  s492 :: SWord16 = s114 + s372
-  s493 :: SBool = s88 /= s492
-  s494 :: SWord16 = s66 + s366
-  s495 :: SBool = s11 /= s494
-  s496 :: SBool = s9 /= s494
-  s497 :: SBool = s7 /= s494
-  s498 :: SBool = s5 /= s494
-  s499 :: SBool = s3 /= s494
-  s500 :: SWord16 = s123 + s372
-  s501 :: SBool = s88 /= s500
-  s502 :: SWord16 = s66 + s374
-  s503 :: SBool = s11 /= s502
-  s504 :: SBool = s9 /= s502
-  s505 :: SBool = s7 /= s502
-  s506 :: SBool = s5 /= s502
-  s507 :: SBool = s3 /= s502
-  s508 :: SWord16 = s123 + s380
-  s509 :: SBool = s88 /= s508
-  s510 :: SWord16 = s66 + s390
-  s511 :: SBool = s11 /= s510
-  s512 :: SBool = s9 /= s510
-  s513 :: SBool = s7 /= s510
-  s514 :: SBool = s5 /= s510
-  s515 :: SBool = s3 /= s510
-  s516 :: SWord16 = s123 + s396
-  s517 :: SBool = s88 /= s516
-  s518 :: SWord16 = s66 + s414
-  s519 :: SBool = s11 /= s518
-  s520 :: SBool = s9 /= s518
-  s521 :: SBool = s7 /= s518
-  s522 :: SBool = s5 /= s518
-  s523 :: SBool = s3 /= s518
-  s524 :: SWord16 = s123 + s420
-  s525 :: SBool = s88 /= s524
-  s526 :: SWord16 = s66 + s446
-  s527 :: SBool = s11 /= s526
-  s528 :: SBool = s9 /= s526
-  s529 :: SBool = s7 /= s526
-  s530 :: SBool = s5 /= s526
-  s531 :: SBool = s3 /= s526
-  s532 :: SWord16 = s123 + s452
-  s533 :: SBool = s88 /= s532
-  s534 :: SWord16 = s66 + s486
-  s535 :: SBool = s11 /= s534
-  s536 :: SBool = s9 /= s534
-  s537 :: SBool = s7 /= s534
-  s538 :: SBool = s5 /= s534
-  s539 :: SBool = s3 /= s534
-  s540 :: SWord16 = s123 + s492
-  s541 :: SBool = s88 /= s540
-  s542 :: SBool = s0 >= s18
-  s543 :: SBool = s18 >= s30
-  s544 :: SBool = s30 >= s42
-  s545 :: SBool = s42 >= s54
-  s546 :: SBool = s54 >= s66
-  s547 :: SBool = s545 & s546
-  s548 :: SBool = s544 & s547
-  s549 :: SBool = s543 & s548
-  s550 :: SBool = s542 & s549
-  s552 :: SBool = s534 == s551
-CONSTRAINTS
-  s17
-  s29
-  s41
-  s53
-  s65
-  s77
-  s79
-  s80
-  s81
-  s82
-  s83
-  s89
-  s91
-  s92
-  s93
-  s94
-  s95
-  s98
-  s100
-  s101
-  s102
-  s103
-  s104
-  s107
-  s109
-  s110
-  s111
-  s112
-  s113
-  s116
-  s118
-  s119
-  s120
-  s121
-  s122
-  s125
-  s127
-  s128
-  s129
-  s130
-  s131
-  s133
-  s135
-  s136
-  s137
-  s138
-  s139
-  s141
-  s143
-  s144
-  s145
-  s146
-  s147
-  s149
-  s151
-  s152
-  s153
-  s154
-  s155
-  s157
-  s159
-  s160
-  s161
-  s162
-  s163
-  s165
-  s167
-  s168
-  s169
-  s170
-  s171
-  s173
-  s175
-  s176
-  s177
-  s178
-  s179
-  s181
-  s183
-  s184
-  s185
-  s186
-  s187
-  s189
-  s191
-  s192
-  s193
-  s194
-  s195
-  s197
-  s199
-  s200
-  s201
-  s202
-  s203
-  s205
-  s207
-  s208
-  s209
-  s210
-  s211
-  s213
-  s215
-  s216
-  s217
-  s218
-  s219
-  s221
-  s223
-  s224
-  s225
-  s226
-  s227
-  s229
-  s231
-  s232
-  s233
-  s234
-  s235
-  s237
-  s239
-  s240
-  s241
-  s242
-  s243
-  s245
-  s247
-  s248
-  s249
-  s250
-  s251
-  s253
-  s255
-  s256
-  s257
-  s258
-  s259
-  s261
-  s263
-  s264
-  s265
-  s266
-  s267
-  s269
-  s271
-  s272
-  s273
-  s274
-  s275
-  s277
-  s279
-  s280
-  s281
-  s282
-  s283
-  s285
-  s287
-  s288
-  s289
-  s290
-  s291
-  s293
-  s295
-  s296
-  s297
-  s298
-  s299
-  s301
-  s303
-  s304
-  s305
-  s306
-  s307
-  s309
-  s311
-  s312
-  s313
-  s314
-  s315
-  s317
-  s319
-  s320
-  s321
-  s322
-  s323
-  s325
-  s327
-  s328
-  s329
-  s330
-  s331
-  s333
-  s335
-  s336
-  s337
-  s338
-  s339
-  s341
-  s343
-  s344
-  s345
-  s346
-  s347
-  s349
-  s351
-  s352
-  s353
-  s354
-  s355
-  s357
-  s359
-  s360
-  s361
-  s362
-  s363
-  s365
-  s367
-  s368
-  s369
-  s370
-  s371
-  s373
-  s375
-  s376
-  s377
-  s378
-  s379
-  s381
-  s383
-  s384
-  s385
-  s386
-  s387
-  s389
-  s391
-  s392
-  s393
-  s394
-  s395
-  s397
-  s399
-  s400
-  s401
-  s402
-  s403
-  s405
-  s407
-  s408
-  s409
-  s410
-  s411
-  s413
-  s415
-  s416
-  s417
-  s418
-  s419
-  s421
-  s423
-  s424
-  s425
-  s426
-  s427
-  s429
-  s431
-  s432
-  s433
-  s434
-  s435
-  s437
-  s439
-  s440
-  s441
-  s442
-  s443
-  s445
-  s447
-  s448
-  s449
-  s450
-  s451
-  s453
-  s455
-  s456
-  s457
-  s458
-  s459
-  s461
-  s463
-  s464
-  s465
-  s466
-  s467
-  s469
-  s471
-  s472
-  s473
-  s474
-  s475
-  s477
-  s479
-  s480
-  s481
-  s482
-  s483
-  s485
-  s487
-  s488
-  s489
-  s490
-  s491
-  s493
-  s495
-  s496
-  s497
-  s498
-  s499
-  s501
-  s503
-  s504
-  s505
-  s506
-  s507
-  s509
-  s511
-  s512
-  s513
-  s514
-  s515
-  s517
-  s519
-  s520
-  s521
-  s522
-  s523
-  s525
-  s527
-  s528
-  s529
-  s530
-  s531
-  s533
-  s535
-  s536
-  s537
-  s538
-  s539
-  s541
-  s550
-ASSERTIONS
-OUTPUTS
-  s552
diff --git a/SBVUnitTest/GoldFiles/counts.gold b/SBVUnitTest/GoldFiles/counts.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/counts.gold
+++ /dev/null
@@ -1,1705 +0,0 @@
-INPUTS
-  s0 :: SWord8
-  s1 :: SWord8
-  s2 :: SWord8
-  s3 :: SWord8
-  s4 :: SWord8
-  s5 :: SWord8
-  s6 :: SWord8
-  s7 :: SWord8
-  s8 :: SWord8
-  s9 :: SWord8
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s10 = 10 :: Word8
-  s12 = 0 :: Word8
-  s32 = 2 :: Word8
-  s33 = 1 :: Word8
-  s35 = 100 :: Word8
-  s555 = 3 :: Word8
-  s716 = 4 :: Word8
-  s877 = 5 :: Word8
-  s1038 = 6 :: Word8
-  s1199 = 7 :: Word8
-  s1360 = 8 :: Word8
-  s1521 = 9 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s11 :: SBool = s9 < s10
-  s13 :: SBool = s9 == s12
-  s14 :: SBool = s8 < s10
-  s15 :: SBool = s8 == s12
-  s16 :: SBool = s7 < s10
-  s17 :: SBool = s7 == s12
-  s18 :: SBool = s6 < s10
-  s19 :: SBool = s6 == s12
-  s20 :: SBool = s5 < s10
-  s21 :: SBool = s5 == s12
-  s22 :: SBool = s4 < s10
-  s23 :: SBool = s4 == s12
-  s24 :: SBool = s3 < s10
-  s25 :: SBool = s3 == s12
-  s26 :: SBool = s2 < s10
-  s27 :: SBool = s2 == s12
-  s28 :: SBool = s1 < s10
-  s29 :: SBool = s1 == s12
-  s30 :: SBool = s0 < s10
-  s31 :: SBool = s0 == s12
-  s34 :: SWord8 = if s31 then s32 else s33
-  s36 :: SBool = s0 < s35
-  s37 :: SWord8 = s0 rem s10
-  s38 :: SBool = s12 == s37
-  s39 :: SWord8 = s0 quot s10
-  s40 :: SWord8 = s39 rem s10
-  s41 :: SBool = s12 == s40
-  s42 :: SWord8 = if s41 then s32 else s33
-  s43 :: SWord8 = s33 + s42
-  s44 :: SWord8 = if s38 then s43 else s42
-  s45 :: SWord8 = s39 quot s10
-  s46 :: SBool = s12 == s45
-  s47 :: SWord8 = if s46 then s32 else s33
-  s48 :: SWord8 = s33 + s47
-  s49 :: SWord8 = if s41 then s48 else s47
-  s50 :: SWord8 = s33 + s49
-  s51 :: SWord8 = if s38 then s50 else s49
-  s52 :: SWord8 = if s36 then s44 else s51
-  s53 :: SWord8 = if s30 then s34 else s52
-  s54 :: SWord8 = s33 + s53
-  s55 :: SWord8 = if s29 then s54 else s53
-  s56 :: SBool = s1 < s35
-  s57 :: SWord8 = s1 rem s10
-  s58 :: SBool = s12 == s57
-  s59 :: SWord8 = s1 quot s10
-  s60 :: SWord8 = s59 rem s10
-  s61 :: SBool = s12 == s60
-  s62 :: SWord8 = if s61 then s54 else s53
-  s63 :: SWord8 = s33 + s62
-  s64 :: SWord8 = if s58 then s63 else s62
-  s65 :: SWord8 = s59 quot s10
-  s66 :: SBool = s12 == s65
-  s67 :: SWord8 = if s66 then s54 else s53
-  s68 :: SWord8 = s33 + s67
-  s69 :: SWord8 = if s61 then s68 else s67
-  s70 :: SWord8 = s33 + s69
-  s71 :: SWord8 = if s58 then s70 else s69
-  s72 :: SWord8 = if s56 then s64 else s71
-  s73 :: SWord8 = if s28 then s55 else s72
-  s74 :: SWord8 = s33 + s73
-  s75 :: SWord8 = if s27 then s74 else s73
-  s76 :: SBool = s2 < s35
-  s77 :: SWord8 = s2 rem s10
-  s78 :: SBool = s12 == s77
-  s79 :: SWord8 = s2 quot s10
-  s80 :: SWord8 = s79 rem s10
-  s81 :: SBool = s12 == s80
-  s82 :: SWord8 = if s81 then s74 else s73
-  s83 :: SWord8 = s33 + s82
-  s84 :: SWord8 = if s78 then s83 else s82
-  s85 :: SWord8 = s79 quot s10
-  s86 :: SBool = s12 == s85
-  s87 :: SWord8 = if s86 then s74 else s73
-  s88 :: SWord8 = s33 + s87
-  s89 :: SWord8 = if s81 then s88 else s87
-  s90 :: SWord8 = s33 + s89
-  s91 :: SWord8 = if s78 then s90 else s89
-  s92 :: SWord8 = if s76 then s84 else s91
-  s93 :: SWord8 = if s26 then s75 else s92
-  s94 :: SWord8 = s33 + s93
-  s95 :: SWord8 = if s25 then s94 else s93
-  s96 :: SBool = s3 < s35
-  s97 :: SWord8 = s3 rem s10
-  s98 :: SBool = s12 == s97
-  s99 :: SWord8 = s3 quot s10
-  s100 :: SWord8 = s99 rem s10
-  s101 :: SBool = s12 == s100
-  s102 :: SWord8 = if s101 then s94 else s93
-  s103 :: SWord8 = s33 + s102
-  s104 :: SWord8 = if s98 then s103 else s102
-  s105 :: SWord8 = s99 quot s10
-  s106 :: SBool = s12 == s105
-  s107 :: SWord8 = if s106 then s94 else s93
-  s108 :: SWord8 = s33 + s107
-  s109 :: SWord8 = if s101 then s108 else s107
-  s110 :: SWord8 = s33 + s109
-  s111 :: SWord8 = if s98 then s110 else s109
-  s112 :: SWord8 = if s96 then s104 else s111
-  s113 :: SWord8 = if s24 then s95 else s112
-  s114 :: SWord8 = s33 + s113
-  s115 :: SWord8 = if s23 then s114 else s113
-  s116 :: SBool = s4 < s35
-  s117 :: SWord8 = s4 rem s10
-  s118 :: SBool = s12 == s117
-  s119 :: SWord8 = s4 quot s10
-  s120 :: SWord8 = s119 rem s10
-  s121 :: SBool = s12 == s120
-  s122 :: SWord8 = if s121 then s114 else s113
-  s123 :: SWord8 = s33 + s122
-  s124 :: SWord8 = if s118 then s123 else s122
-  s125 :: SWord8 = s119 quot s10
-  s126 :: SBool = s12 == s125
-  s127 :: SWord8 = if s126 then s114 else s113
-  s128 :: SWord8 = s33 + s127
-  s129 :: SWord8 = if s121 then s128 else s127
-  s130 :: SWord8 = s33 + s129
-  s131 :: SWord8 = if s118 then s130 else s129
-  s132 :: SWord8 = if s116 then s124 else s131
-  s133 :: SWord8 = if s22 then s115 else s132
-  s134 :: SWord8 = s33 + s133
-  s135 :: SWord8 = if s21 then s134 else s133
-  s136 :: SBool = s5 < s35
-  s137 :: SWord8 = s5 rem s10
-  s138 :: SBool = s12 == s137
-  s139 :: SWord8 = s5 quot s10
-  s140 :: SWord8 = s139 rem s10
-  s141 :: SBool = s12 == s140
-  s142 :: SWord8 = if s141 then s134 else s133
-  s143 :: SWord8 = s33 + s142
-  s144 :: SWord8 = if s138 then s143 else s142
-  s145 :: SWord8 = s139 quot s10
-  s146 :: SBool = s12 == s145
-  s147 :: SWord8 = if s146 then s134 else s133
-  s148 :: SWord8 = s33 + s147
-  s149 :: SWord8 = if s141 then s148 else s147
-  s150 :: SWord8 = s33 + s149
-  s151 :: SWord8 = if s138 then s150 else s149
-  s152 :: SWord8 = if s136 then s144 else s151
-  s153 :: SWord8 = if s20 then s135 else s152
-  s154 :: SWord8 = s33 + s153
-  s155 :: SWord8 = if s19 then s154 else s153
-  s156 :: SBool = s6 < s35
-  s157 :: SWord8 = s6 rem s10
-  s158 :: SBool = s12 == s157
-  s159 :: SWord8 = s6 quot s10
-  s160 :: SWord8 = s159 rem s10
-  s161 :: SBool = s12 == s160
-  s162 :: SWord8 = if s161 then s154 else s153
-  s163 :: SWord8 = s33 + s162
-  s164 :: SWord8 = if s158 then s163 else s162
-  s165 :: SWord8 = s159 quot s10
-  s166 :: SBool = s12 == s165
-  s167 :: SWord8 = if s166 then s154 else s153
-  s168 :: SWord8 = s33 + s167
-  s169 :: SWord8 = if s161 then s168 else s167
-  s170 :: SWord8 = s33 + s169
-  s171 :: SWord8 = if s158 then s170 else s169
-  s172 :: SWord8 = if s156 then s164 else s171
-  s173 :: SWord8 = if s18 then s155 else s172
-  s174 :: SWord8 = s33 + s173
-  s175 :: SWord8 = if s17 then s174 else s173
-  s176 :: SBool = s7 < s35
-  s177 :: SWord8 = s7 rem s10
-  s178 :: SBool = s12 == s177
-  s179 :: SWord8 = s7 quot s10
-  s180 :: SWord8 = s179 rem s10
-  s181 :: SBool = s12 == s180
-  s182 :: SWord8 = if s181 then s174 else s173
-  s183 :: SWord8 = s33 + s182
-  s184 :: SWord8 = if s178 then s183 else s182
-  s185 :: SWord8 = s179 quot s10
-  s186 :: SBool = s12 == s185
-  s187 :: SWord8 = if s186 then s174 else s173
-  s188 :: SWord8 = s33 + s187
-  s189 :: SWord8 = if s181 then s188 else s187
-  s190 :: SWord8 = s33 + s189
-  s191 :: SWord8 = if s178 then s190 else s189
-  s192 :: SWord8 = if s176 then s184 else s191
-  s193 :: SWord8 = if s16 then s175 else s192
-  s194 :: SWord8 = s33 + s193
-  s195 :: SWord8 = if s15 then s194 else s193
-  s196 :: SBool = s8 < s35
-  s197 :: SWord8 = s8 rem s10
-  s198 :: SBool = s12 == s197
-  s199 :: SWord8 = s8 quot s10
-  s200 :: SWord8 = s199 rem s10
-  s201 :: SBool = s12 == s200
-  s202 :: SWord8 = if s201 then s194 else s193
-  s203 :: SWord8 = s33 + s202
-  s204 :: SWord8 = if s198 then s203 else s202
-  s205 :: SWord8 = s199 quot s10
-  s206 :: SBool = s12 == s205
-  s207 :: SWord8 = if s206 then s194 else s193
-  s208 :: SWord8 = s33 + s207
-  s209 :: SWord8 = if s201 then s208 else s207
-  s210 :: SWord8 = s33 + s209
-  s211 :: SWord8 = if s198 then s210 else s209
-  s212 :: SWord8 = if s196 then s204 else s211
-  s213 :: SWord8 = if s14 then s195 else s212
-  s214 :: SWord8 = s33 + s213
-  s215 :: SWord8 = if s13 then s214 else s213
-  s216 :: SBool = s9 < s35
-  s217 :: SWord8 = s9 rem s10
-  s218 :: SBool = s12 == s217
-  s219 :: SWord8 = s9 quot s10
-  s220 :: SWord8 = s219 rem s10
-  s221 :: SBool = s12 == s220
-  s222 :: SWord8 = if s221 then s214 else s213
-  s223 :: SWord8 = s33 + s222
-  s224 :: SWord8 = if s218 then s223 else s222
-  s225 :: SWord8 = s219 quot s10
-  s226 :: SBool = s12 == s225
-  s227 :: SWord8 = if s226 then s214 else s213
-  s228 :: SWord8 = s33 + s227
-  s229 :: SWord8 = if s221 then s228 else s227
-  s230 :: SWord8 = s33 + s229
-  s231 :: SWord8 = if s218 then s230 else s229
-  s232 :: SWord8 = if s216 then s224 else s231
-  s233 :: SWord8 = if s11 then s215 else s232
-  s234 :: SBool = s0 == s233
-  s235 :: SBool = s9 == s33
-  s236 :: SBool = s8 == s33
-  s237 :: SBool = s7 == s33
-  s238 :: SBool = s6 == s33
-  s239 :: SBool = s5 == s33
-  s240 :: SBool = s4 == s33
-  s241 :: SBool = s3 == s33
-  s242 :: SBool = s2 == s33
-  s243 :: SBool = s1 == s33
-  s244 :: SBool = s0 == s33
-  s245 :: SWord8 = if s244 then s32 else s33
-  s246 :: SBool = s33 == s37
-  s247 :: SBool = s33 == s40
-  s248 :: SWord8 = if s247 then s32 else s33
-  s249 :: SWord8 = s33 + s248
-  s250 :: SWord8 = if s246 then s249 else s248
-  s251 :: SBool = s33 == s45
-  s252 :: SWord8 = if s251 then s32 else s33
-  s253 :: SWord8 = s33 + s252
-  s254 :: SWord8 = if s247 then s253 else s252
-  s255 :: SWord8 = s33 + s254
-  s256 :: SWord8 = if s246 then s255 else s254
-  s257 :: SWord8 = if s36 then s250 else s256
-  s258 :: SWord8 = if s30 then s245 else s257
-  s259 :: SWord8 = s33 + s258
-  s260 :: SWord8 = if s243 then s259 else s258
-  s261 :: SBool = s33 == s57
-  s262 :: SBool = s33 == s60
-  s263 :: SWord8 = if s262 then s259 else s258
-  s264 :: SWord8 = s33 + s263
-  s265 :: SWord8 = if s261 then s264 else s263
-  s266 :: SBool = s33 == s65
-  s267 :: SWord8 = if s266 then s259 else s258
-  s268 :: SWord8 = s33 + s267
-  s269 :: SWord8 = if s262 then s268 else s267
-  s270 :: SWord8 = s33 + s269
-  s271 :: SWord8 = if s261 then s270 else s269
-  s272 :: SWord8 = if s56 then s265 else s271
-  s273 :: SWord8 = if s28 then s260 else s272
-  s274 :: SWord8 = s33 + s273
-  s275 :: SWord8 = if s242 then s274 else s273
-  s276 :: SBool = s33 == s77
-  s277 :: SBool = s33 == s80
-  s278 :: SWord8 = if s277 then s274 else s273
-  s279 :: SWord8 = s33 + s278
-  s280 :: SWord8 = if s276 then s279 else s278
-  s281 :: SBool = s33 == s85
-  s282 :: SWord8 = if s281 then s274 else s273
-  s283 :: SWord8 = s33 + s282
-  s284 :: SWord8 = if s277 then s283 else s282
-  s285 :: SWord8 = s33 + s284
-  s286 :: SWord8 = if s276 then s285 else s284
-  s287 :: SWord8 = if s76 then s280 else s286
-  s288 :: SWord8 = if s26 then s275 else s287
-  s289 :: SWord8 = s33 + s288
-  s290 :: SWord8 = if s241 then s289 else s288
-  s291 :: SBool = s33 == s97
-  s292 :: SBool = s33 == s100
-  s293 :: SWord8 = if s292 then s289 else s288
-  s294 :: SWord8 = s33 + s293
-  s295 :: SWord8 = if s291 then s294 else s293
-  s296 :: SBool = s33 == s105
-  s297 :: SWord8 = if s296 then s289 else s288
-  s298 :: SWord8 = s33 + s297
-  s299 :: SWord8 = if s292 then s298 else s297
-  s300 :: SWord8 = s33 + s299
-  s301 :: SWord8 = if s291 then s300 else s299
-  s302 :: SWord8 = if s96 then s295 else s301
-  s303 :: SWord8 = if s24 then s290 else s302
-  s304 :: SWord8 = s33 + s303
-  s305 :: SWord8 = if s240 then s304 else s303
-  s306 :: SBool = s33 == s117
-  s307 :: SBool = s33 == s120
-  s308 :: SWord8 = if s307 then s304 else s303
-  s309 :: SWord8 = s33 + s308
-  s310 :: SWord8 = if s306 then s309 else s308
-  s311 :: SBool = s33 == s125
-  s312 :: SWord8 = if s311 then s304 else s303
-  s313 :: SWord8 = s33 + s312
-  s314 :: SWord8 = if s307 then s313 else s312
-  s315 :: SWord8 = s33 + s314
-  s316 :: SWord8 = if s306 then s315 else s314
-  s317 :: SWord8 = if s116 then s310 else s316
-  s318 :: SWord8 = if s22 then s305 else s317
-  s319 :: SWord8 = s33 + s318
-  s320 :: SWord8 = if s239 then s319 else s318
-  s321 :: SBool = s33 == s137
-  s322 :: SBool = s33 == s140
-  s323 :: SWord8 = if s322 then s319 else s318
-  s324 :: SWord8 = s33 + s323
-  s325 :: SWord8 = if s321 then s324 else s323
-  s326 :: SBool = s33 == s145
-  s327 :: SWord8 = if s326 then s319 else s318
-  s328 :: SWord8 = s33 + s327
-  s329 :: SWord8 = if s322 then s328 else s327
-  s330 :: SWord8 = s33 + s329
-  s331 :: SWord8 = if s321 then s330 else s329
-  s332 :: SWord8 = if s136 then s325 else s331
-  s333 :: SWord8 = if s20 then s320 else s332
-  s334 :: SWord8 = s33 + s333
-  s335 :: SWord8 = if s238 then s334 else s333
-  s336 :: SBool = s33 == s157
-  s337 :: SBool = s33 == s160
-  s338 :: SWord8 = if s337 then s334 else s333
-  s339 :: SWord8 = s33 + s338
-  s340 :: SWord8 = if s336 then s339 else s338
-  s341 :: SBool = s33 == s165
-  s342 :: SWord8 = if s341 then s334 else s333
-  s343 :: SWord8 = s33 + s342
-  s344 :: SWord8 = if s337 then s343 else s342
-  s345 :: SWord8 = s33 + s344
-  s346 :: SWord8 = if s336 then s345 else s344
-  s347 :: SWord8 = if s156 then s340 else s346
-  s348 :: SWord8 = if s18 then s335 else s347
-  s349 :: SWord8 = s33 + s348
-  s350 :: SWord8 = if s237 then s349 else s348
-  s351 :: SBool = s33 == s177
-  s352 :: SBool = s33 == s180
-  s353 :: SWord8 = if s352 then s349 else s348
-  s354 :: SWord8 = s33 + s353
-  s355 :: SWord8 = if s351 then s354 else s353
-  s356 :: SBool = s33 == s185
-  s357 :: SWord8 = if s356 then s349 else s348
-  s358 :: SWord8 = s33 + s357
-  s359 :: SWord8 = if s352 then s358 else s357
-  s360 :: SWord8 = s33 + s359
-  s361 :: SWord8 = if s351 then s360 else s359
-  s362 :: SWord8 = if s176 then s355 else s361
-  s363 :: SWord8 = if s16 then s350 else s362
-  s364 :: SWord8 = s33 + s363
-  s365 :: SWord8 = if s236 then s364 else s363
-  s366 :: SBool = s33 == s197
-  s367 :: SBool = s33 == s200
-  s368 :: SWord8 = if s367 then s364 else s363
-  s369 :: SWord8 = s33 + s368
-  s370 :: SWord8 = if s366 then s369 else s368
-  s371 :: SBool = s33 == s205
-  s372 :: SWord8 = if s371 then s364 else s363
-  s373 :: SWord8 = s33 + s372
-  s374 :: SWord8 = if s367 then s373 else s372
-  s375 :: SWord8 = s33 + s374
-  s376 :: SWord8 = if s366 then s375 else s374
-  s377 :: SWord8 = if s196 then s370 else s376
-  s378 :: SWord8 = if s14 then s365 else s377
-  s379 :: SWord8 = s33 + s378
-  s380 :: SWord8 = if s235 then s379 else s378
-  s381 :: SBool = s33 == s217
-  s382 :: SBool = s33 == s220
-  s383 :: SWord8 = if s382 then s379 else s378
-  s384 :: SWord8 = s33 + s383
-  s385 :: SWord8 = if s381 then s384 else s383
-  s386 :: SBool = s33 == s225
-  s387 :: SWord8 = if s386 then s379 else s378
-  s388 :: SWord8 = s33 + s387
-  s389 :: SWord8 = if s382 then s388 else s387
-  s390 :: SWord8 = s33 + s389
-  s391 :: SWord8 = if s381 then s390 else s389
-  s392 :: SWord8 = if s216 then s385 else s391
-  s393 :: SWord8 = if s11 then s380 else s392
-  s394 :: SBool = s1 == s393
-  s395 :: SBool = s9 == s32
-  s396 :: SBool = s8 == s32
-  s397 :: SBool = s7 == s32
-  s398 :: SBool = s6 == s32
-  s399 :: SBool = s5 == s32
-  s400 :: SBool = s4 == s32
-  s401 :: SBool = s3 == s32
-  s402 :: SBool = s2 == s32
-  s403 :: SBool = s1 == s32
-  s404 :: SBool = s0 == s32
-  s405 :: SWord8 = if s404 then s32 else s33
-  s406 :: SBool = s32 == s37
-  s407 :: SBool = s32 == s40
-  s408 :: SWord8 = if s407 then s32 else s33
-  s409 :: SWord8 = s33 + s408
-  s410 :: SWord8 = if s406 then s409 else s408
-  s411 :: SBool = s32 == s45
-  s412 :: SWord8 = if s411 then s32 else s33
-  s413 :: SWord8 = s33 + s412
-  s414 :: SWord8 = if s407 then s413 else s412
-  s415 :: SWord8 = s33 + s414
-  s416 :: SWord8 = if s406 then s415 else s414
-  s417 :: SWord8 = if s36 then s410 else s416
-  s418 :: SWord8 = if s30 then s405 else s417
-  s419 :: SWord8 = s33 + s418
-  s420 :: SWord8 = if s403 then s419 else s418
-  s421 :: SBool = s32 == s57
-  s422 :: SBool = s32 == s60
-  s423 :: SWord8 = if s422 then s419 else s418
-  s424 :: SWord8 = s33 + s423
-  s425 :: SWord8 = if s421 then s424 else s423
-  s426 :: SBool = s32 == s65
-  s427 :: SWord8 = if s426 then s419 else s418
-  s428 :: SWord8 = s33 + s427
-  s429 :: SWord8 = if s422 then s428 else s427
-  s430 :: SWord8 = s33 + s429
-  s431 :: SWord8 = if s421 then s430 else s429
-  s432 :: SWord8 = if s56 then s425 else s431
-  s433 :: SWord8 = if s28 then s420 else s432
-  s434 :: SWord8 = s33 + s433
-  s435 :: SWord8 = if s402 then s434 else s433
-  s436 :: SBool = s32 == s77
-  s437 :: SBool = s32 == s80
-  s438 :: SWord8 = if s437 then s434 else s433
-  s439 :: SWord8 = s33 + s438
-  s440 :: SWord8 = if s436 then s439 else s438
-  s441 :: SBool = s32 == s85
-  s442 :: SWord8 = if s441 then s434 else s433
-  s443 :: SWord8 = s33 + s442
-  s444 :: SWord8 = if s437 then s443 else s442
-  s445 :: SWord8 = s33 + s444
-  s446 :: SWord8 = if s436 then s445 else s444
-  s447 :: SWord8 = if s76 then s440 else s446
-  s448 :: SWord8 = if s26 then s435 else s447
-  s449 :: SWord8 = s33 + s448
-  s450 :: SWord8 = if s401 then s449 else s448
-  s451 :: SBool = s32 == s97
-  s452 :: SBool = s32 == s100
-  s453 :: SWord8 = if s452 then s449 else s448
-  s454 :: SWord8 = s33 + s453
-  s455 :: SWord8 = if s451 then s454 else s453
-  s456 :: SBool = s32 == s105
-  s457 :: SWord8 = if s456 then s449 else s448
-  s458 :: SWord8 = s33 + s457
-  s459 :: SWord8 = if s452 then s458 else s457
-  s460 :: SWord8 = s33 + s459
-  s461 :: SWord8 = if s451 then s460 else s459
-  s462 :: SWord8 = if s96 then s455 else s461
-  s463 :: SWord8 = if s24 then s450 else s462
-  s464 :: SWord8 = s33 + s463
-  s465 :: SWord8 = if s400 then s464 else s463
-  s466 :: SBool = s32 == s117
-  s467 :: SBool = s32 == s120
-  s468 :: SWord8 = if s467 then s464 else s463
-  s469 :: SWord8 = s33 + s468
-  s470 :: SWord8 = if s466 then s469 else s468
-  s471 :: SBool = s32 == s125
-  s472 :: SWord8 = if s471 then s464 else s463
-  s473 :: SWord8 = s33 + s472
-  s474 :: SWord8 = if s467 then s473 else s472
-  s475 :: SWord8 = s33 + s474
-  s476 :: SWord8 = if s466 then s475 else s474
-  s477 :: SWord8 = if s116 then s470 else s476
-  s478 :: SWord8 = if s22 then s465 else s477
-  s479 :: SWord8 = s33 + s478
-  s480 :: SWord8 = if s399 then s479 else s478
-  s481 :: SBool = s32 == s137
-  s482 :: SBool = s32 == s140
-  s483 :: SWord8 = if s482 then s479 else s478
-  s484 :: SWord8 = s33 + s483
-  s485 :: SWord8 = if s481 then s484 else s483
-  s486 :: SBool = s32 == s145
-  s487 :: SWord8 = if s486 then s479 else s478
-  s488 :: SWord8 = s33 + s487
-  s489 :: SWord8 = if s482 then s488 else s487
-  s490 :: SWord8 = s33 + s489
-  s491 :: SWord8 = if s481 then s490 else s489
-  s492 :: SWord8 = if s136 then s485 else s491
-  s493 :: SWord8 = if s20 then s480 else s492
-  s494 :: SWord8 = s33 + s493
-  s495 :: SWord8 = if s398 then s494 else s493
-  s496 :: SBool = s32 == s157
-  s497 :: SBool = s32 == s160
-  s498 :: SWord8 = if s497 then s494 else s493
-  s499 :: SWord8 = s33 + s498
-  s500 :: SWord8 = if s496 then s499 else s498
-  s501 :: SBool = s32 == s165
-  s502 :: SWord8 = if s501 then s494 else s493
-  s503 :: SWord8 = s33 + s502
-  s504 :: SWord8 = if s497 then s503 else s502
-  s505 :: SWord8 = s33 + s504
-  s506 :: SWord8 = if s496 then s505 else s504
-  s507 :: SWord8 = if s156 then s500 else s506
-  s508 :: SWord8 = if s18 then s495 else s507
-  s509 :: SWord8 = s33 + s508
-  s510 :: SWord8 = if s397 then s509 else s508
-  s511 :: SBool = s32 == s177
-  s512 :: SBool = s32 == s180
-  s513 :: SWord8 = if s512 then s509 else s508
-  s514 :: SWord8 = s33 + s513
-  s515 :: SWord8 = if s511 then s514 else s513
-  s516 :: SBool = s32 == s185
-  s517 :: SWord8 = if s516 then s509 else s508
-  s518 :: SWord8 = s33 + s517
-  s519 :: SWord8 = if s512 then s518 else s517
-  s520 :: SWord8 = s33 + s519
-  s521 :: SWord8 = if s511 then s520 else s519
-  s522 :: SWord8 = if s176 then s515 else s521
-  s523 :: SWord8 = if s16 then s510 else s522
-  s524 :: SWord8 = s33 + s523
-  s525 :: SWord8 = if s396 then s524 else s523
-  s526 :: SBool = s32 == s197
-  s527 :: SBool = s32 == s200
-  s528 :: SWord8 = if s527 then s524 else s523
-  s529 :: SWord8 = s33 + s528
-  s530 :: SWord8 = if s526 then s529 else s528
-  s531 :: SBool = s32 == s205
-  s532 :: SWord8 = if s531 then s524 else s523
-  s533 :: SWord8 = s33 + s532
-  s534 :: SWord8 = if s527 then s533 else s532
-  s535 :: SWord8 = s33 + s534
-  s536 :: SWord8 = if s526 then s535 else s534
-  s537 :: SWord8 = if s196 then s530 else s536
-  s538 :: SWord8 = if s14 then s525 else s537
-  s539 :: SWord8 = s33 + s538
-  s540 :: SWord8 = if s395 then s539 else s538
-  s541 :: SBool = s32 == s217
-  s542 :: SBool = s32 == s220
-  s543 :: SWord8 = if s542 then s539 else s538
-  s544 :: SWord8 = s33 + s543
-  s545 :: SWord8 = if s541 then s544 else s543
-  s546 :: SBool = s32 == s225
-  s547 :: SWord8 = if s546 then s539 else s538
-  s548 :: SWord8 = s33 + s547
-  s549 :: SWord8 = if s542 then s548 else s547
-  s550 :: SWord8 = s33 + s549
-  s551 :: SWord8 = if s541 then s550 else s549
-  s552 :: SWord8 = if s216 then s545 else s551
-  s553 :: SWord8 = if s11 then s540 else s552
-  s554 :: SBool = s2 == s553
-  s556 :: SBool = s9 == s555
-  s557 :: SBool = s8 == s555
-  s558 :: SBool = s7 == s555
-  s559 :: SBool = s6 == s555
-  s560 :: SBool = s5 == s555
-  s561 :: SBool = s4 == s555
-  s562 :: SBool = s3 == s555
-  s563 :: SBool = s2 == s555
-  s564 :: SBool = s1 == s555
-  s565 :: SBool = s0 == s555
-  s566 :: SWord8 = if s565 then s32 else s33
-  s567 :: SBool = s37 == s555
-  s568 :: SBool = s40 == s555
-  s569 :: SWord8 = if s568 then s32 else s33
-  s570 :: SWord8 = s33 + s569
-  s571 :: SWord8 = if s567 then s570 else s569
-  s572 :: SBool = s45 == s555
-  s573 :: SWord8 = if s572 then s32 else s33
-  s574 :: SWord8 = s33 + s573
-  s575 :: SWord8 = if s568 then s574 else s573
-  s576 :: SWord8 = s33 + s575
-  s577 :: SWord8 = if s567 then s576 else s575
-  s578 :: SWord8 = if s36 then s571 else s577
-  s579 :: SWord8 = if s30 then s566 else s578
-  s580 :: SWord8 = s33 + s579
-  s581 :: SWord8 = if s564 then s580 else s579
-  s582 :: SBool = s57 == s555
-  s583 :: SBool = s60 == s555
-  s584 :: SWord8 = if s583 then s580 else s579
-  s585 :: SWord8 = s33 + s584
-  s586 :: SWord8 = if s582 then s585 else s584
-  s587 :: SBool = s65 == s555
-  s588 :: SWord8 = if s587 then s580 else s579
-  s589 :: SWord8 = s33 + s588
-  s590 :: SWord8 = if s583 then s589 else s588
-  s591 :: SWord8 = s33 + s590
-  s592 :: SWord8 = if s582 then s591 else s590
-  s593 :: SWord8 = if s56 then s586 else s592
-  s594 :: SWord8 = if s28 then s581 else s593
-  s595 :: SWord8 = s33 + s594
-  s596 :: SWord8 = if s563 then s595 else s594
-  s597 :: SBool = s77 == s555
-  s598 :: SBool = s80 == s555
-  s599 :: SWord8 = if s598 then s595 else s594
-  s600 :: SWord8 = s33 + s599
-  s601 :: SWord8 = if s597 then s600 else s599
-  s602 :: SBool = s85 == s555
-  s603 :: SWord8 = if s602 then s595 else s594
-  s604 :: SWord8 = s33 + s603
-  s605 :: SWord8 = if s598 then s604 else s603
-  s606 :: SWord8 = s33 + s605
-  s607 :: SWord8 = if s597 then s606 else s605
-  s608 :: SWord8 = if s76 then s601 else s607
-  s609 :: SWord8 = if s26 then s596 else s608
-  s610 :: SWord8 = s33 + s609
-  s611 :: SWord8 = if s562 then s610 else s609
-  s612 :: SBool = s97 == s555
-  s613 :: SBool = s100 == s555
-  s614 :: SWord8 = if s613 then s610 else s609
-  s615 :: SWord8 = s33 + s614
-  s616 :: SWord8 = if s612 then s615 else s614
-  s617 :: SBool = s105 == s555
-  s618 :: SWord8 = if s617 then s610 else s609
-  s619 :: SWord8 = s33 + s618
-  s620 :: SWord8 = if s613 then s619 else s618
-  s621 :: SWord8 = s33 + s620
-  s622 :: SWord8 = if s612 then s621 else s620
-  s623 :: SWord8 = if s96 then s616 else s622
-  s624 :: SWord8 = if s24 then s611 else s623
-  s625 :: SWord8 = s33 + s624
-  s626 :: SWord8 = if s561 then s625 else s624
-  s627 :: SBool = s117 == s555
-  s628 :: SBool = s120 == s555
-  s629 :: SWord8 = if s628 then s625 else s624
-  s630 :: SWord8 = s33 + s629
-  s631 :: SWord8 = if s627 then s630 else s629
-  s632 :: SBool = s125 == s555
-  s633 :: SWord8 = if s632 then s625 else s624
-  s634 :: SWord8 = s33 + s633
-  s635 :: SWord8 = if s628 then s634 else s633
-  s636 :: SWord8 = s33 + s635
-  s637 :: SWord8 = if s627 then s636 else s635
-  s638 :: SWord8 = if s116 then s631 else s637
-  s639 :: SWord8 = if s22 then s626 else s638
-  s640 :: SWord8 = s33 + s639
-  s641 :: SWord8 = if s560 then s640 else s639
-  s642 :: SBool = s137 == s555
-  s643 :: SBool = s140 == s555
-  s644 :: SWord8 = if s643 then s640 else s639
-  s645 :: SWord8 = s33 + s644
-  s646 :: SWord8 = if s642 then s645 else s644
-  s647 :: SBool = s145 == s555
-  s648 :: SWord8 = if s647 then s640 else s639
-  s649 :: SWord8 = s33 + s648
-  s650 :: SWord8 = if s643 then s649 else s648
-  s651 :: SWord8 = s33 + s650
-  s652 :: SWord8 = if s642 then s651 else s650
-  s653 :: SWord8 = if s136 then s646 else s652
-  s654 :: SWord8 = if s20 then s641 else s653
-  s655 :: SWord8 = s33 + s654
-  s656 :: SWord8 = if s559 then s655 else s654
-  s657 :: SBool = s157 == s555
-  s658 :: SBool = s160 == s555
-  s659 :: SWord8 = if s658 then s655 else s654
-  s660 :: SWord8 = s33 + s659
-  s661 :: SWord8 = if s657 then s660 else s659
-  s662 :: SBool = s165 == s555
-  s663 :: SWord8 = if s662 then s655 else s654
-  s664 :: SWord8 = s33 + s663
-  s665 :: SWord8 = if s658 then s664 else s663
-  s666 :: SWord8 = s33 + s665
-  s667 :: SWord8 = if s657 then s666 else s665
-  s668 :: SWord8 = if s156 then s661 else s667
-  s669 :: SWord8 = if s18 then s656 else s668
-  s670 :: SWord8 = s33 + s669
-  s671 :: SWord8 = if s558 then s670 else s669
-  s672 :: SBool = s177 == s555
-  s673 :: SBool = s180 == s555
-  s674 :: SWord8 = if s673 then s670 else s669
-  s675 :: SWord8 = s33 + s674
-  s676 :: SWord8 = if s672 then s675 else s674
-  s677 :: SBool = s185 == s555
-  s678 :: SWord8 = if s677 then s670 else s669
-  s679 :: SWord8 = s33 + s678
-  s680 :: SWord8 = if s673 then s679 else s678
-  s681 :: SWord8 = s33 + s680
-  s682 :: SWord8 = if s672 then s681 else s680
-  s683 :: SWord8 = if s176 then s676 else s682
-  s684 :: SWord8 = if s16 then s671 else s683
-  s685 :: SWord8 = s33 + s684
-  s686 :: SWord8 = if s557 then s685 else s684
-  s687 :: SBool = s197 == s555
-  s688 :: SBool = s200 == s555
-  s689 :: SWord8 = if s688 then s685 else s684
-  s690 :: SWord8 = s33 + s689
-  s691 :: SWord8 = if s687 then s690 else s689
-  s692 :: SBool = s205 == s555
-  s693 :: SWord8 = if s692 then s685 else s684
-  s694 :: SWord8 = s33 + s693
-  s695 :: SWord8 = if s688 then s694 else s693
-  s696 :: SWord8 = s33 + s695
-  s697 :: SWord8 = if s687 then s696 else s695
-  s698 :: SWord8 = if s196 then s691 else s697
-  s699 :: SWord8 = if s14 then s686 else s698
-  s700 :: SWord8 = s33 + s699
-  s701 :: SWord8 = if s556 then s700 else s699
-  s702 :: SBool = s217 == s555
-  s703 :: SBool = s220 == s555
-  s704 :: SWord8 = if s703 then s700 else s699
-  s705 :: SWord8 = s33 + s704
-  s706 :: SWord8 = if s702 then s705 else s704
-  s707 :: SBool = s225 == s555
-  s708 :: SWord8 = if s707 then s700 else s699
-  s709 :: SWord8 = s33 + s708
-  s710 :: SWord8 = if s703 then s709 else s708
-  s711 :: SWord8 = s33 + s710
-  s712 :: SWord8 = if s702 then s711 else s710
-  s713 :: SWord8 = if s216 then s706 else s712
-  s714 :: SWord8 = if s11 then s701 else s713
-  s715 :: SBool = s3 == s714
-  s717 :: SBool = s9 == s716
-  s718 :: SBool = s8 == s716
-  s719 :: SBool = s7 == s716
-  s720 :: SBool = s6 == s716
-  s721 :: SBool = s5 == s716
-  s722 :: SBool = s4 == s716
-  s723 :: SBool = s3 == s716
-  s724 :: SBool = s2 == s716
-  s725 :: SBool = s1 == s716
-  s726 :: SBool = s0 == s716
-  s727 :: SWord8 = if s726 then s32 else s33
-  s728 :: SBool = s37 == s716
-  s729 :: SBool = s40 == s716
-  s730 :: SWord8 = if s729 then s32 else s33
-  s731 :: SWord8 = s33 + s730
-  s732 :: SWord8 = if s728 then s731 else s730
-  s733 :: SBool = s45 == s716
-  s734 :: SWord8 = if s733 then s32 else s33
-  s735 :: SWord8 = s33 + s734
-  s736 :: SWord8 = if s729 then s735 else s734
-  s737 :: SWord8 = s33 + s736
-  s738 :: SWord8 = if s728 then s737 else s736
-  s739 :: SWord8 = if s36 then s732 else s738
-  s740 :: SWord8 = if s30 then s727 else s739
-  s741 :: SWord8 = s33 + s740
-  s742 :: SWord8 = if s725 then s741 else s740
-  s743 :: SBool = s57 == s716
-  s744 :: SBool = s60 == s716
-  s745 :: SWord8 = if s744 then s741 else s740
-  s746 :: SWord8 = s33 + s745
-  s747 :: SWord8 = if s743 then s746 else s745
-  s748 :: SBool = s65 == s716
-  s749 :: SWord8 = if s748 then s741 else s740
-  s750 :: SWord8 = s33 + s749
-  s751 :: SWord8 = if s744 then s750 else s749
-  s752 :: SWord8 = s33 + s751
-  s753 :: SWord8 = if s743 then s752 else s751
-  s754 :: SWord8 = if s56 then s747 else s753
-  s755 :: SWord8 = if s28 then s742 else s754
-  s756 :: SWord8 = s33 + s755
-  s757 :: SWord8 = if s724 then s756 else s755
-  s758 :: SBool = s77 == s716
-  s759 :: SBool = s80 == s716
-  s760 :: SWord8 = if s759 then s756 else s755
-  s761 :: SWord8 = s33 + s760
-  s762 :: SWord8 = if s758 then s761 else s760
-  s763 :: SBool = s85 == s716
-  s764 :: SWord8 = if s763 then s756 else s755
-  s765 :: SWord8 = s33 + s764
-  s766 :: SWord8 = if s759 then s765 else s764
-  s767 :: SWord8 = s33 + s766
-  s768 :: SWord8 = if s758 then s767 else s766
-  s769 :: SWord8 = if s76 then s762 else s768
-  s770 :: SWord8 = if s26 then s757 else s769
-  s771 :: SWord8 = s33 + s770
-  s772 :: SWord8 = if s723 then s771 else s770
-  s773 :: SBool = s97 == s716
-  s774 :: SBool = s100 == s716
-  s775 :: SWord8 = if s774 then s771 else s770
-  s776 :: SWord8 = s33 + s775
-  s777 :: SWord8 = if s773 then s776 else s775
-  s778 :: SBool = s105 == s716
-  s779 :: SWord8 = if s778 then s771 else s770
-  s780 :: SWord8 = s33 + s779
-  s781 :: SWord8 = if s774 then s780 else s779
-  s782 :: SWord8 = s33 + s781
-  s783 :: SWord8 = if s773 then s782 else s781
-  s784 :: SWord8 = if s96 then s777 else s783
-  s785 :: SWord8 = if s24 then s772 else s784
-  s786 :: SWord8 = s33 + s785
-  s787 :: SWord8 = if s722 then s786 else s785
-  s788 :: SBool = s117 == s716
-  s789 :: SBool = s120 == s716
-  s790 :: SWord8 = if s789 then s786 else s785
-  s791 :: SWord8 = s33 + s790
-  s792 :: SWord8 = if s788 then s791 else s790
-  s793 :: SBool = s125 == s716
-  s794 :: SWord8 = if s793 then s786 else s785
-  s795 :: SWord8 = s33 + s794
-  s796 :: SWord8 = if s789 then s795 else s794
-  s797 :: SWord8 = s33 + s796
-  s798 :: SWord8 = if s788 then s797 else s796
-  s799 :: SWord8 = if s116 then s792 else s798
-  s800 :: SWord8 = if s22 then s787 else s799
-  s801 :: SWord8 = s33 + s800
-  s802 :: SWord8 = if s721 then s801 else s800
-  s803 :: SBool = s137 == s716
-  s804 :: SBool = s140 == s716
-  s805 :: SWord8 = if s804 then s801 else s800
-  s806 :: SWord8 = s33 + s805
-  s807 :: SWord8 = if s803 then s806 else s805
-  s808 :: SBool = s145 == s716
-  s809 :: SWord8 = if s808 then s801 else s800
-  s810 :: SWord8 = s33 + s809
-  s811 :: SWord8 = if s804 then s810 else s809
-  s812 :: SWord8 = s33 + s811
-  s813 :: SWord8 = if s803 then s812 else s811
-  s814 :: SWord8 = if s136 then s807 else s813
-  s815 :: SWord8 = if s20 then s802 else s814
-  s816 :: SWord8 = s33 + s815
-  s817 :: SWord8 = if s720 then s816 else s815
-  s818 :: SBool = s157 == s716
-  s819 :: SBool = s160 == s716
-  s820 :: SWord8 = if s819 then s816 else s815
-  s821 :: SWord8 = s33 + s820
-  s822 :: SWord8 = if s818 then s821 else s820
-  s823 :: SBool = s165 == s716
-  s824 :: SWord8 = if s823 then s816 else s815
-  s825 :: SWord8 = s33 + s824
-  s826 :: SWord8 = if s819 then s825 else s824
-  s827 :: SWord8 = s33 + s826
-  s828 :: SWord8 = if s818 then s827 else s826
-  s829 :: SWord8 = if s156 then s822 else s828
-  s830 :: SWord8 = if s18 then s817 else s829
-  s831 :: SWord8 = s33 + s830
-  s832 :: SWord8 = if s719 then s831 else s830
-  s833 :: SBool = s177 == s716
-  s834 :: SBool = s180 == s716
-  s835 :: SWord8 = if s834 then s831 else s830
-  s836 :: SWord8 = s33 + s835
-  s837 :: SWord8 = if s833 then s836 else s835
-  s838 :: SBool = s185 == s716
-  s839 :: SWord8 = if s838 then s831 else s830
-  s840 :: SWord8 = s33 + s839
-  s841 :: SWord8 = if s834 then s840 else s839
-  s842 :: SWord8 = s33 + s841
-  s843 :: SWord8 = if s833 then s842 else s841
-  s844 :: SWord8 = if s176 then s837 else s843
-  s845 :: SWord8 = if s16 then s832 else s844
-  s846 :: SWord8 = s33 + s845
-  s847 :: SWord8 = if s718 then s846 else s845
-  s848 :: SBool = s197 == s716
-  s849 :: SBool = s200 == s716
-  s850 :: SWord8 = if s849 then s846 else s845
-  s851 :: SWord8 = s33 + s850
-  s852 :: SWord8 = if s848 then s851 else s850
-  s853 :: SBool = s205 == s716
-  s854 :: SWord8 = if s853 then s846 else s845
-  s855 :: SWord8 = s33 + s854
-  s856 :: SWord8 = if s849 then s855 else s854
-  s857 :: SWord8 = s33 + s856
-  s858 :: SWord8 = if s848 then s857 else s856
-  s859 :: SWord8 = if s196 then s852 else s858
-  s860 :: SWord8 = if s14 then s847 else s859
-  s861 :: SWord8 = s33 + s860
-  s862 :: SWord8 = if s717 then s861 else s860
-  s863 :: SBool = s217 == s716
-  s864 :: SBool = s220 == s716
-  s865 :: SWord8 = if s864 then s861 else s860
-  s866 :: SWord8 = s33 + s865
-  s867 :: SWord8 = if s863 then s866 else s865
-  s868 :: SBool = s225 == s716
-  s869 :: SWord8 = if s868 then s861 else s860
-  s870 :: SWord8 = s33 + s869
-  s871 :: SWord8 = if s864 then s870 else s869
-  s872 :: SWord8 = s33 + s871
-  s873 :: SWord8 = if s863 then s872 else s871
-  s874 :: SWord8 = if s216 then s867 else s873
-  s875 :: SWord8 = if s11 then s862 else s874
-  s876 :: SBool = s4 == s875
-  s878 :: SBool = s9 == s877
-  s879 :: SBool = s8 == s877
-  s880 :: SBool = s7 == s877
-  s881 :: SBool = s6 == s877
-  s882 :: SBool = s5 == s877
-  s883 :: SBool = s4 == s877
-  s884 :: SBool = s3 == s877
-  s885 :: SBool = s2 == s877
-  s886 :: SBool = s1 == s877
-  s887 :: SBool = s0 == s877
-  s888 :: SWord8 = if s887 then s32 else s33
-  s889 :: SBool = s37 == s877
-  s890 :: SBool = s40 == s877
-  s891 :: SWord8 = if s890 then s32 else s33
-  s892 :: SWord8 = s33 + s891
-  s893 :: SWord8 = if s889 then s892 else s891
-  s894 :: SBool = s45 == s877
-  s895 :: SWord8 = if s894 then s32 else s33
-  s896 :: SWord8 = s33 + s895
-  s897 :: SWord8 = if s890 then s896 else s895
-  s898 :: SWord8 = s33 + s897
-  s899 :: SWord8 = if s889 then s898 else s897
-  s900 :: SWord8 = if s36 then s893 else s899
-  s901 :: SWord8 = if s30 then s888 else s900
-  s902 :: SWord8 = s33 + s901
-  s903 :: SWord8 = if s886 then s902 else s901
-  s904 :: SBool = s57 == s877
-  s905 :: SBool = s60 == s877
-  s906 :: SWord8 = if s905 then s902 else s901
-  s907 :: SWord8 = s33 + s906
-  s908 :: SWord8 = if s904 then s907 else s906
-  s909 :: SBool = s65 == s877
-  s910 :: SWord8 = if s909 then s902 else s901
-  s911 :: SWord8 = s33 + s910
-  s912 :: SWord8 = if s905 then s911 else s910
-  s913 :: SWord8 = s33 + s912
-  s914 :: SWord8 = if s904 then s913 else s912
-  s915 :: SWord8 = if s56 then s908 else s914
-  s916 :: SWord8 = if s28 then s903 else s915
-  s917 :: SWord8 = s33 + s916
-  s918 :: SWord8 = if s885 then s917 else s916
-  s919 :: SBool = s77 == s877
-  s920 :: SBool = s80 == s877
-  s921 :: SWord8 = if s920 then s917 else s916
-  s922 :: SWord8 = s33 + s921
-  s923 :: SWord8 = if s919 then s922 else s921
-  s924 :: SBool = s85 == s877
-  s925 :: SWord8 = if s924 then s917 else s916
-  s926 :: SWord8 = s33 + s925
-  s927 :: SWord8 = if s920 then s926 else s925
-  s928 :: SWord8 = s33 + s927
-  s929 :: SWord8 = if s919 then s928 else s927
-  s930 :: SWord8 = if s76 then s923 else s929
-  s931 :: SWord8 = if s26 then s918 else s930
-  s932 :: SWord8 = s33 + s931
-  s933 :: SWord8 = if s884 then s932 else s931
-  s934 :: SBool = s97 == s877
-  s935 :: SBool = s100 == s877
-  s936 :: SWord8 = if s935 then s932 else s931
-  s937 :: SWord8 = s33 + s936
-  s938 :: SWord8 = if s934 then s937 else s936
-  s939 :: SBool = s105 == s877
-  s940 :: SWord8 = if s939 then s932 else s931
-  s941 :: SWord8 = s33 + s940
-  s942 :: SWord8 = if s935 then s941 else s940
-  s943 :: SWord8 = s33 + s942
-  s944 :: SWord8 = if s934 then s943 else s942
-  s945 :: SWord8 = if s96 then s938 else s944
-  s946 :: SWord8 = if s24 then s933 else s945
-  s947 :: SWord8 = s33 + s946
-  s948 :: SWord8 = if s883 then s947 else s946
-  s949 :: SBool = s117 == s877
-  s950 :: SBool = s120 == s877
-  s951 :: SWord8 = if s950 then s947 else s946
-  s952 :: SWord8 = s33 + s951
-  s953 :: SWord8 = if s949 then s952 else s951
-  s954 :: SBool = s125 == s877
-  s955 :: SWord8 = if s954 then s947 else s946
-  s956 :: SWord8 = s33 + s955
-  s957 :: SWord8 = if s950 then s956 else s955
-  s958 :: SWord8 = s33 + s957
-  s959 :: SWord8 = if s949 then s958 else s957
-  s960 :: SWord8 = if s116 then s953 else s959
-  s961 :: SWord8 = if s22 then s948 else s960
-  s962 :: SWord8 = s33 + s961
-  s963 :: SWord8 = if s882 then s962 else s961
-  s964 :: SBool = s137 == s877
-  s965 :: SBool = s140 == s877
-  s966 :: SWord8 = if s965 then s962 else s961
-  s967 :: SWord8 = s33 + s966
-  s968 :: SWord8 = if s964 then s967 else s966
-  s969 :: SBool = s145 == s877
-  s970 :: SWord8 = if s969 then s962 else s961
-  s971 :: SWord8 = s33 + s970
-  s972 :: SWord8 = if s965 then s971 else s970
-  s973 :: SWord8 = s33 + s972
-  s974 :: SWord8 = if s964 then s973 else s972
-  s975 :: SWord8 = if s136 then s968 else s974
-  s976 :: SWord8 = if s20 then s963 else s975
-  s977 :: SWord8 = s33 + s976
-  s978 :: SWord8 = if s881 then s977 else s976
-  s979 :: SBool = s157 == s877
-  s980 :: SBool = s160 == s877
-  s981 :: SWord8 = if s980 then s977 else s976
-  s982 :: SWord8 = s33 + s981
-  s983 :: SWord8 = if s979 then s982 else s981
-  s984 :: SBool = s165 == s877
-  s985 :: SWord8 = if s984 then s977 else s976
-  s986 :: SWord8 = s33 + s985
-  s987 :: SWord8 = if s980 then s986 else s985
-  s988 :: SWord8 = s33 + s987
-  s989 :: SWord8 = if s979 then s988 else s987
-  s990 :: SWord8 = if s156 then s983 else s989
-  s991 :: SWord8 = if s18 then s978 else s990
-  s992 :: SWord8 = s33 + s991
-  s993 :: SWord8 = if s880 then s992 else s991
-  s994 :: SBool = s177 == s877
-  s995 :: SBool = s180 == s877
-  s996 :: SWord8 = if s995 then s992 else s991
-  s997 :: SWord8 = s33 + s996
-  s998 :: SWord8 = if s994 then s997 else s996
-  s999 :: SBool = s185 == s877
-  s1000 :: SWord8 = if s999 then s992 else s991
-  s1001 :: SWord8 = s33 + s1000
-  s1002 :: SWord8 = if s995 then s1001 else s1000
-  s1003 :: SWord8 = s33 + s1002
-  s1004 :: SWord8 = if s994 then s1003 else s1002
-  s1005 :: SWord8 = if s176 then s998 else s1004
-  s1006 :: SWord8 = if s16 then s993 else s1005
-  s1007 :: SWord8 = s33 + s1006
-  s1008 :: SWord8 = if s879 then s1007 else s1006
-  s1009 :: SBool = s197 == s877
-  s1010 :: SBool = s200 == s877
-  s1011 :: SWord8 = if s1010 then s1007 else s1006
-  s1012 :: SWord8 = s33 + s1011
-  s1013 :: SWord8 = if s1009 then s1012 else s1011
-  s1014 :: SBool = s205 == s877
-  s1015 :: SWord8 = if s1014 then s1007 else s1006
-  s1016 :: SWord8 = s33 + s1015
-  s1017 :: SWord8 = if s1010 then s1016 else s1015
-  s1018 :: SWord8 = s33 + s1017
-  s1019 :: SWord8 = if s1009 then s1018 else s1017
-  s1020 :: SWord8 = if s196 then s1013 else s1019
-  s1021 :: SWord8 = if s14 then s1008 else s1020
-  s1022 :: SWord8 = s33 + s1021
-  s1023 :: SWord8 = if s878 then s1022 else s1021
-  s1024 :: SBool = s217 == s877
-  s1025 :: SBool = s220 == s877
-  s1026 :: SWord8 = if s1025 then s1022 else s1021
-  s1027 :: SWord8 = s33 + s1026
-  s1028 :: SWord8 = if s1024 then s1027 else s1026
-  s1029 :: SBool = s225 == s877
-  s1030 :: SWord8 = if s1029 then s1022 else s1021
-  s1031 :: SWord8 = s33 + s1030
-  s1032 :: SWord8 = if s1025 then s1031 else s1030
-  s1033 :: SWord8 = s33 + s1032
-  s1034 :: SWord8 = if s1024 then s1033 else s1032
-  s1035 :: SWord8 = if s216 then s1028 else s1034
-  s1036 :: SWord8 = if s11 then s1023 else s1035
-  s1037 :: SBool = s5 == s1036
-  s1039 :: SBool = s9 == s1038
-  s1040 :: SBool = s8 == s1038
-  s1041 :: SBool = s7 == s1038
-  s1042 :: SBool = s6 == s1038
-  s1043 :: SBool = s5 == s1038
-  s1044 :: SBool = s4 == s1038
-  s1045 :: SBool = s3 == s1038
-  s1046 :: SBool = s2 == s1038
-  s1047 :: SBool = s1 == s1038
-  s1048 :: SBool = s0 == s1038
-  s1049 :: SWord8 = if s1048 then s32 else s33
-  s1050 :: SBool = s37 == s1038
-  s1051 :: SBool = s40 == s1038
-  s1052 :: SWord8 = if s1051 then s32 else s33
-  s1053 :: SWord8 = s33 + s1052
-  s1054 :: SWord8 = if s1050 then s1053 else s1052
-  s1055 :: SBool = s45 == s1038
-  s1056 :: SWord8 = if s1055 then s32 else s33
-  s1057 :: SWord8 = s33 + s1056
-  s1058 :: SWord8 = if s1051 then s1057 else s1056
-  s1059 :: SWord8 = s33 + s1058
-  s1060 :: SWord8 = if s1050 then s1059 else s1058
-  s1061 :: SWord8 = if s36 then s1054 else s1060
-  s1062 :: SWord8 = if s30 then s1049 else s1061
-  s1063 :: SWord8 = s33 + s1062
-  s1064 :: SWord8 = if s1047 then s1063 else s1062
-  s1065 :: SBool = s57 == s1038
-  s1066 :: SBool = s60 == s1038
-  s1067 :: SWord8 = if s1066 then s1063 else s1062
-  s1068 :: SWord8 = s33 + s1067
-  s1069 :: SWord8 = if s1065 then s1068 else s1067
-  s1070 :: SBool = s65 == s1038
-  s1071 :: SWord8 = if s1070 then s1063 else s1062
-  s1072 :: SWord8 = s33 + s1071
-  s1073 :: SWord8 = if s1066 then s1072 else s1071
-  s1074 :: SWord8 = s33 + s1073
-  s1075 :: SWord8 = if s1065 then s1074 else s1073
-  s1076 :: SWord8 = if s56 then s1069 else s1075
-  s1077 :: SWord8 = if s28 then s1064 else s1076
-  s1078 :: SWord8 = s33 + s1077
-  s1079 :: SWord8 = if s1046 then s1078 else s1077
-  s1080 :: SBool = s77 == s1038
-  s1081 :: SBool = s80 == s1038
-  s1082 :: SWord8 = if s1081 then s1078 else s1077
-  s1083 :: SWord8 = s33 + s1082
-  s1084 :: SWord8 = if s1080 then s1083 else s1082
-  s1085 :: SBool = s85 == s1038
-  s1086 :: SWord8 = if s1085 then s1078 else s1077
-  s1087 :: SWord8 = s33 + s1086
-  s1088 :: SWord8 = if s1081 then s1087 else s1086
-  s1089 :: SWord8 = s33 + s1088
-  s1090 :: SWord8 = if s1080 then s1089 else s1088
-  s1091 :: SWord8 = if s76 then s1084 else s1090
-  s1092 :: SWord8 = if s26 then s1079 else s1091
-  s1093 :: SWord8 = s33 + s1092
-  s1094 :: SWord8 = if s1045 then s1093 else s1092
-  s1095 :: SBool = s97 == s1038
-  s1096 :: SBool = s100 == s1038
-  s1097 :: SWord8 = if s1096 then s1093 else s1092
-  s1098 :: SWord8 = s33 + s1097
-  s1099 :: SWord8 = if s1095 then s1098 else s1097
-  s1100 :: SBool = s105 == s1038
-  s1101 :: SWord8 = if s1100 then s1093 else s1092
-  s1102 :: SWord8 = s33 + s1101
-  s1103 :: SWord8 = if s1096 then s1102 else s1101
-  s1104 :: SWord8 = s33 + s1103
-  s1105 :: SWord8 = if s1095 then s1104 else s1103
-  s1106 :: SWord8 = if s96 then s1099 else s1105
-  s1107 :: SWord8 = if s24 then s1094 else s1106
-  s1108 :: SWord8 = s33 + s1107
-  s1109 :: SWord8 = if s1044 then s1108 else s1107
-  s1110 :: SBool = s117 == s1038
-  s1111 :: SBool = s120 == s1038
-  s1112 :: SWord8 = if s1111 then s1108 else s1107
-  s1113 :: SWord8 = s33 + s1112
-  s1114 :: SWord8 = if s1110 then s1113 else s1112
-  s1115 :: SBool = s125 == s1038
-  s1116 :: SWord8 = if s1115 then s1108 else s1107
-  s1117 :: SWord8 = s33 + s1116
-  s1118 :: SWord8 = if s1111 then s1117 else s1116
-  s1119 :: SWord8 = s33 + s1118
-  s1120 :: SWord8 = if s1110 then s1119 else s1118
-  s1121 :: SWord8 = if s116 then s1114 else s1120
-  s1122 :: SWord8 = if s22 then s1109 else s1121
-  s1123 :: SWord8 = s33 + s1122
-  s1124 :: SWord8 = if s1043 then s1123 else s1122
-  s1125 :: SBool = s137 == s1038
-  s1126 :: SBool = s140 == s1038
-  s1127 :: SWord8 = if s1126 then s1123 else s1122
-  s1128 :: SWord8 = s33 + s1127
-  s1129 :: SWord8 = if s1125 then s1128 else s1127
-  s1130 :: SBool = s145 == s1038
-  s1131 :: SWord8 = if s1130 then s1123 else s1122
-  s1132 :: SWord8 = s33 + s1131
-  s1133 :: SWord8 = if s1126 then s1132 else s1131
-  s1134 :: SWord8 = s33 + s1133
-  s1135 :: SWord8 = if s1125 then s1134 else s1133
-  s1136 :: SWord8 = if s136 then s1129 else s1135
-  s1137 :: SWord8 = if s20 then s1124 else s1136
-  s1138 :: SWord8 = s33 + s1137
-  s1139 :: SWord8 = if s1042 then s1138 else s1137
-  s1140 :: SBool = s157 == s1038
-  s1141 :: SBool = s160 == s1038
-  s1142 :: SWord8 = if s1141 then s1138 else s1137
-  s1143 :: SWord8 = s33 + s1142
-  s1144 :: SWord8 = if s1140 then s1143 else s1142
-  s1145 :: SBool = s165 == s1038
-  s1146 :: SWord8 = if s1145 then s1138 else s1137
-  s1147 :: SWord8 = s33 + s1146
-  s1148 :: SWord8 = if s1141 then s1147 else s1146
-  s1149 :: SWord8 = s33 + s1148
-  s1150 :: SWord8 = if s1140 then s1149 else s1148
-  s1151 :: SWord8 = if s156 then s1144 else s1150
-  s1152 :: SWord8 = if s18 then s1139 else s1151
-  s1153 :: SWord8 = s33 + s1152
-  s1154 :: SWord8 = if s1041 then s1153 else s1152
-  s1155 :: SBool = s177 == s1038
-  s1156 :: SBool = s180 == s1038
-  s1157 :: SWord8 = if s1156 then s1153 else s1152
-  s1158 :: SWord8 = s33 + s1157
-  s1159 :: SWord8 = if s1155 then s1158 else s1157
-  s1160 :: SBool = s185 == s1038
-  s1161 :: SWord8 = if s1160 then s1153 else s1152
-  s1162 :: SWord8 = s33 + s1161
-  s1163 :: SWord8 = if s1156 then s1162 else s1161
-  s1164 :: SWord8 = s33 + s1163
-  s1165 :: SWord8 = if s1155 then s1164 else s1163
-  s1166 :: SWord8 = if s176 then s1159 else s1165
-  s1167 :: SWord8 = if s16 then s1154 else s1166
-  s1168 :: SWord8 = s33 + s1167
-  s1169 :: SWord8 = if s1040 then s1168 else s1167
-  s1170 :: SBool = s197 == s1038
-  s1171 :: SBool = s200 == s1038
-  s1172 :: SWord8 = if s1171 then s1168 else s1167
-  s1173 :: SWord8 = s33 + s1172
-  s1174 :: SWord8 = if s1170 then s1173 else s1172
-  s1175 :: SBool = s205 == s1038
-  s1176 :: SWord8 = if s1175 then s1168 else s1167
-  s1177 :: SWord8 = s33 + s1176
-  s1178 :: SWord8 = if s1171 then s1177 else s1176
-  s1179 :: SWord8 = s33 + s1178
-  s1180 :: SWord8 = if s1170 then s1179 else s1178
-  s1181 :: SWord8 = if s196 then s1174 else s1180
-  s1182 :: SWord8 = if s14 then s1169 else s1181
-  s1183 :: SWord8 = s33 + s1182
-  s1184 :: SWord8 = if s1039 then s1183 else s1182
-  s1185 :: SBool = s217 == s1038
-  s1186 :: SBool = s220 == s1038
-  s1187 :: SWord8 = if s1186 then s1183 else s1182
-  s1188 :: SWord8 = s33 + s1187
-  s1189 :: SWord8 = if s1185 then s1188 else s1187
-  s1190 :: SBool = s225 == s1038
-  s1191 :: SWord8 = if s1190 then s1183 else s1182
-  s1192 :: SWord8 = s33 + s1191
-  s1193 :: SWord8 = if s1186 then s1192 else s1191
-  s1194 :: SWord8 = s33 + s1193
-  s1195 :: SWord8 = if s1185 then s1194 else s1193
-  s1196 :: SWord8 = if s216 then s1189 else s1195
-  s1197 :: SWord8 = if s11 then s1184 else s1196
-  s1198 :: SBool = s6 == s1197
-  s1200 :: SBool = s9 == s1199
-  s1201 :: SBool = s8 == s1199
-  s1202 :: SBool = s7 == s1199
-  s1203 :: SBool = s6 == s1199
-  s1204 :: SBool = s5 == s1199
-  s1205 :: SBool = s4 == s1199
-  s1206 :: SBool = s3 == s1199
-  s1207 :: SBool = s2 == s1199
-  s1208 :: SBool = s1 == s1199
-  s1209 :: SBool = s0 == s1199
-  s1210 :: SWord8 = if s1209 then s32 else s33
-  s1211 :: SBool = s37 == s1199
-  s1212 :: SBool = s40 == s1199
-  s1213 :: SWord8 = if s1212 then s32 else s33
-  s1214 :: SWord8 = s33 + s1213
-  s1215 :: SWord8 = if s1211 then s1214 else s1213
-  s1216 :: SBool = s45 == s1199
-  s1217 :: SWord8 = if s1216 then s32 else s33
-  s1218 :: SWord8 = s33 + s1217
-  s1219 :: SWord8 = if s1212 then s1218 else s1217
-  s1220 :: SWord8 = s33 + s1219
-  s1221 :: SWord8 = if s1211 then s1220 else s1219
-  s1222 :: SWord8 = if s36 then s1215 else s1221
-  s1223 :: SWord8 = if s30 then s1210 else s1222
-  s1224 :: SWord8 = s33 + s1223
-  s1225 :: SWord8 = if s1208 then s1224 else s1223
-  s1226 :: SBool = s57 == s1199
-  s1227 :: SBool = s60 == s1199
-  s1228 :: SWord8 = if s1227 then s1224 else s1223
-  s1229 :: SWord8 = s33 + s1228
-  s1230 :: SWord8 = if s1226 then s1229 else s1228
-  s1231 :: SBool = s65 == s1199
-  s1232 :: SWord8 = if s1231 then s1224 else s1223
-  s1233 :: SWord8 = s33 + s1232
-  s1234 :: SWord8 = if s1227 then s1233 else s1232
-  s1235 :: SWord8 = s33 + s1234
-  s1236 :: SWord8 = if s1226 then s1235 else s1234
-  s1237 :: SWord8 = if s56 then s1230 else s1236
-  s1238 :: SWord8 = if s28 then s1225 else s1237
-  s1239 :: SWord8 = s33 + s1238
-  s1240 :: SWord8 = if s1207 then s1239 else s1238
-  s1241 :: SBool = s77 == s1199
-  s1242 :: SBool = s80 == s1199
-  s1243 :: SWord8 = if s1242 then s1239 else s1238
-  s1244 :: SWord8 = s33 + s1243
-  s1245 :: SWord8 = if s1241 then s1244 else s1243
-  s1246 :: SBool = s85 == s1199
-  s1247 :: SWord8 = if s1246 then s1239 else s1238
-  s1248 :: SWord8 = s33 + s1247
-  s1249 :: SWord8 = if s1242 then s1248 else s1247
-  s1250 :: SWord8 = s33 + s1249
-  s1251 :: SWord8 = if s1241 then s1250 else s1249
-  s1252 :: SWord8 = if s76 then s1245 else s1251
-  s1253 :: SWord8 = if s26 then s1240 else s1252
-  s1254 :: SWord8 = s33 + s1253
-  s1255 :: SWord8 = if s1206 then s1254 else s1253
-  s1256 :: SBool = s97 == s1199
-  s1257 :: SBool = s100 == s1199
-  s1258 :: SWord8 = if s1257 then s1254 else s1253
-  s1259 :: SWord8 = s33 + s1258
-  s1260 :: SWord8 = if s1256 then s1259 else s1258
-  s1261 :: SBool = s105 == s1199
-  s1262 :: SWord8 = if s1261 then s1254 else s1253
-  s1263 :: SWord8 = s33 + s1262
-  s1264 :: SWord8 = if s1257 then s1263 else s1262
-  s1265 :: SWord8 = s33 + s1264
-  s1266 :: SWord8 = if s1256 then s1265 else s1264
-  s1267 :: SWord8 = if s96 then s1260 else s1266
-  s1268 :: SWord8 = if s24 then s1255 else s1267
-  s1269 :: SWord8 = s33 + s1268
-  s1270 :: SWord8 = if s1205 then s1269 else s1268
-  s1271 :: SBool = s117 == s1199
-  s1272 :: SBool = s120 == s1199
-  s1273 :: SWord8 = if s1272 then s1269 else s1268
-  s1274 :: SWord8 = s33 + s1273
-  s1275 :: SWord8 = if s1271 then s1274 else s1273
-  s1276 :: SBool = s125 == s1199
-  s1277 :: SWord8 = if s1276 then s1269 else s1268
-  s1278 :: SWord8 = s33 + s1277
-  s1279 :: SWord8 = if s1272 then s1278 else s1277
-  s1280 :: SWord8 = s33 + s1279
-  s1281 :: SWord8 = if s1271 then s1280 else s1279
-  s1282 :: SWord8 = if s116 then s1275 else s1281
-  s1283 :: SWord8 = if s22 then s1270 else s1282
-  s1284 :: SWord8 = s33 + s1283
-  s1285 :: SWord8 = if s1204 then s1284 else s1283
-  s1286 :: SBool = s137 == s1199
-  s1287 :: SBool = s140 == s1199
-  s1288 :: SWord8 = if s1287 then s1284 else s1283
-  s1289 :: SWord8 = s33 + s1288
-  s1290 :: SWord8 = if s1286 then s1289 else s1288
-  s1291 :: SBool = s145 == s1199
-  s1292 :: SWord8 = if s1291 then s1284 else s1283
-  s1293 :: SWord8 = s33 + s1292
-  s1294 :: SWord8 = if s1287 then s1293 else s1292
-  s1295 :: SWord8 = s33 + s1294
-  s1296 :: SWord8 = if s1286 then s1295 else s1294
-  s1297 :: SWord8 = if s136 then s1290 else s1296
-  s1298 :: SWord8 = if s20 then s1285 else s1297
-  s1299 :: SWord8 = s33 + s1298
-  s1300 :: SWord8 = if s1203 then s1299 else s1298
-  s1301 :: SBool = s157 == s1199
-  s1302 :: SBool = s160 == s1199
-  s1303 :: SWord8 = if s1302 then s1299 else s1298
-  s1304 :: SWord8 = s33 + s1303
-  s1305 :: SWord8 = if s1301 then s1304 else s1303
-  s1306 :: SBool = s165 == s1199
-  s1307 :: SWord8 = if s1306 then s1299 else s1298
-  s1308 :: SWord8 = s33 + s1307
-  s1309 :: SWord8 = if s1302 then s1308 else s1307
-  s1310 :: SWord8 = s33 + s1309
-  s1311 :: SWord8 = if s1301 then s1310 else s1309
-  s1312 :: SWord8 = if s156 then s1305 else s1311
-  s1313 :: SWord8 = if s18 then s1300 else s1312
-  s1314 :: SWord8 = s33 + s1313
-  s1315 :: SWord8 = if s1202 then s1314 else s1313
-  s1316 :: SBool = s177 == s1199
-  s1317 :: SBool = s180 == s1199
-  s1318 :: SWord8 = if s1317 then s1314 else s1313
-  s1319 :: SWord8 = s33 + s1318
-  s1320 :: SWord8 = if s1316 then s1319 else s1318
-  s1321 :: SBool = s185 == s1199
-  s1322 :: SWord8 = if s1321 then s1314 else s1313
-  s1323 :: SWord8 = s33 + s1322
-  s1324 :: SWord8 = if s1317 then s1323 else s1322
-  s1325 :: SWord8 = s33 + s1324
-  s1326 :: SWord8 = if s1316 then s1325 else s1324
-  s1327 :: SWord8 = if s176 then s1320 else s1326
-  s1328 :: SWord8 = if s16 then s1315 else s1327
-  s1329 :: SWord8 = s33 + s1328
-  s1330 :: SWord8 = if s1201 then s1329 else s1328
-  s1331 :: SBool = s197 == s1199
-  s1332 :: SBool = s200 == s1199
-  s1333 :: SWord8 = if s1332 then s1329 else s1328
-  s1334 :: SWord8 = s33 + s1333
-  s1335 :: SWord8 = if s1331 then s1334 else s1333
-  s1336 :: SBool = s205 == s1199
-  s1337 :: SWord8 = if s1336 then s1329 else s1328
-  s1338 :: SWord8 = s33 + s1337
-  s1339 :: SWord8 = if s1332 then s1338 else s1337
-  s1340 :: SWord8 = s33 + s1339
-  s1341 :: SWord8 = if s1331 then s1340 else s1339
-  s1342 :: SWord8 = if s196 then s1335 else s1341
-  s1343 :: SWord8 = if s14 then s1330 else s1342
-  s1344 :: SWord8 = s33 + s1343
-  s1345 :: SWord8 = if s1200 then s1344 else s1343
-  s1346 :: SBool = s217 == s1199
-  s1347 :: SBool = s220 == s1199
-  s1348 :: SWord8 = if s1347 then s1344 else s1343
-  s1349 :: SWord8 = s33 + s1348
-  s1350 :: SWord8 = if s1346 then s1349 else s1348
-  s1351 :: SBool = s225 == s1199
-  s1352 :: SWord8 = if s1351 then s1344 else s1343
-  s1353 :: SWord8 = s33 + s1352
-  s1354 :: SWord8 = if s1347 then s1353 else s1352
-  s1355 :: SWord8 = s33 + s1354
-  s1356 :: SWord8 = if s1346 then s1355 else s1354
-  s1357 :: SWord8 = if s216 then s1350 else s1356
-  s1358 :: SWord8 = if s11 then s1345 else s1357
-  s1359 :: SBool = s7 == s1358
-  s1361 :: SBool = s9 == s1360
-  s1362 :: SBool = s8 == s1360
-  s1363 :: SBool = s7 == s1360
-  s1364 :: SBool = s6 == s1360
-  s1365 :: SBool = s5 == s1360
-  s1366 :: SBool = s4 == s1360
-  s1367 :: SBool = s3 == s1360
-  s1368 :: SBool = s2 == s1360
-  s1369 :: SBool = s1 == s1360
-  s1370 :: SBool = s0 == s1360
-  s1371 :: SWord8 = if s1370 then s32 else s33
-  s1372 :: SBool = s37 == s1360
-  s1373 :: SBool = s40 == s1360
-  s1374 :: SWord8 = if s1373 then s32 else s33
-  s1375 :: SWord8 = s33 + s1374
-  s1376 :: SWord8 = if s1372 then s1375 else s1374
-  s1377 :: SBool = s45 == s1360
-  s1378 :: SWord8 = if s1377 then s32 else s33
-  s1379 :: SWord8 = s33 + s1378
-  s1380 :: SWord8 = if s1373 then s1379 else s1378
-  s1381 :: SWord8 = s33 + s1380
-  s1382 :: SWord8 = if s1372 then s1381 else s1380
-  s1383 :: SWord8 = if s36 then s1376 else s1382
-  s1384 :: SWord8 = if s30 then s1371 else s1383
-  s1385 :: SWord8 = s33 + s1384
-  s1386 :: SWord8 = if s1369 then s1385 else s1384
-  s1387 :: SBool = s57 == s1360
-  s1388 :: SBool = s60 == s1360
-  s1389 :: SWord8 = if s1388 then s1385 else s1384
-  s1390 :: SWord8 = s33 + s1389
-  s1391 :: SWord8 = if s1387 then s1390 else s1389
-  s1392 :: SBool = s65 == s1360
-  s1393 :: SWord8 = if s1392 then s1385 else s1384
-  s1394 :: SWord8 = s33 + s1393
-  s1395 :: SWord8 = if s1388 then s1394 else s1393
-  s1396 :: SWord8 = s33 + s1395
-  s1397 :: SWord8 = if s1387 then s1396 else s1395
-  s1398 :: SWord8 = if s56 then s1391 else s1397
-  s1399 :: SWord8 = if s28 then s1386 else s1398
-  s1400 :: SWord8 = s33 + s1399
-  s1401 :: SWord8 = if s1368 then s1400 else s1399
-  s1402 :: SBool = s77 == s1360
-  s1403 :: SBool = s80 == s1360
-  s1404 :: SWord8 = if s1403 then s1400 else s1399
-  s1405 :: SWord8 = s33 + s1404
-  s1406 :: SWord8 = if s1402 then s1405 else s1404
-  s1407 :: SBool = s85 == s1360
-  s1408 :: SWord8 = if s1407 then s1400 else s1399
-  s1409 :: SWord8 = s33 + s1408
-  s1410 :: SWord8 = if s1403 then s1409 else s1408
-  s1411 :: SWord8 = s33 + s1410
-  s1412 :: SWord8 = if s1402 then s1411 else s1410
-  s1413 :: SWord8 = if s76 then s1406 else s1412
-  s1414 :: SWord8 = if s26 then s1401 else s1413
-  s1415 :: SWord8 = s33 + s1414
-  s1416 :: SWord8 = if s1367 then s1415 else s1414
-  s1417 :: SBool = s97 == s1360
-  s1418 :: SBool = s100 == s1360
-  s1419 :: SWord8 = if s1418 then s1415 else s1414
-  s1420 :: SWord8 = s33 + s1419
-  s1421 :: SWord8 = if s1417 then s1420 else s1419
-  s1422 :: SBool = s105 == s1360
-  s1423 :: SWord8 = if s1422 then s1415 else s1414
-  s1424 :: SWord8 = s33 + s1423
-  s1425 :: SWord8 = if s1418 then s1424 else s1423
-  s1426 :: SWord8 = s33 + s1425
-  s1427 :: SWord8 = if s1417 then s1426 else s1425
-  s1428 :: SWord8 = if s96 then s1421 else s1427
-  s1429 :: SWord8 = if s24 then s1416 else s1428
-  s1430 :: SWord8 = s33 + s1429
-  s1431 :: SWord8 = if s1366 then s1430 else s1429
-  s1432 :: SBool = s117 == s1360
-  s1433 :: SBool = s120 == s1360
-  s1434 :: SWord8 = if s1433 then s1430 else s1429
-  s1435 :: SWord8 = s33 + s1434
-  s1436 :: SWord8 = if s1432 then s1435 else s1434
-  s1437 :: SBool = s125 == s1360
-  s1438 :: SWord8 = if s1437 then s1430 else s1429
-  s1439 :: SWord8 = s33 + s1438
-  s1440 :: SWord8 = if s1433 then s1439 else s1438
-  s1441 :: SWord8 = s33 + s1440
-  s1442 :: SWord8 = if s1432 then s1441 else s1440
-  s1443 :: SWord8 = if s116 then s1436 else s1442
-  s1444 :: SWord8 = if s22 then s1431 else s1443
-  s1445 :: SWord8 = s33 + s1444
-  s1446 :: SWord8 = if s1365 then s1445 else s1444
-  s1447 :: SBool = s137 == s1360
-  s1448 :: SBool = s140 == s1360
-  s1449 :: SWord8 = if s1448 then s1445 else s1444
-  s1450 :: SWord8 = s33 + s1449
-  s1451 :: SWord8 = if s1447 then s1450 else s1449
-  s1452 :: SBool = s145 == s1360
-  s1453 :: SWord8 = if s1452 then s1445 else s1444
-  s1454 :: SWord8 = s33 + s1453
-  s1455 :: SWord8 = if s1448 then s1454 else s1453
-  s1456 :: SWord8 = s33 + s1455
-  s1457 :: SWord8 = if s1447 then s1456 else s1455
-  s1458 :: SWord8 = if s136 then s1451 else s1457
-  s1459 :: SWord8 = if s20 then s1446 else s1458
-  s1460 :: SWord8 = s33 + s1459
-  s1461 :: SWord8 = if s1364 then s1460 else s1459
-  s1462 :: SBool = s157 == s1360
-  s1463 :: SBool = s160 == s1360
-  s1464 :: SWord8 = if s1463 then s1460 else s1459
-  s1465 :: SWord8 = s33 + s1464
-  s1466 :: SWord8 = if s1462 then s1465 else s1464
-  s1467 :: SBool = s165 == s1360
-  s1468 :: SWord8 = if s1467 then s1460 else s1459
-  s1469 :: SWord8 = s33 + s1468
-  s1470 :: SWord8 = if s1463 then s1469 else s1468
-  s1471 :: SWord8 = s33 + s1470
-  s1472 :: SWord8 = if s1462 then s1471 else s1470
-  s1473 :: SWord8 = if s156 then s1466 else s1472
-  s1474 :: SWord8 = if s18 then s1461 else s1473
-  s1475 :: SWord8 = s33 + s1474
-  s1476 :: SWord8 = if s1363 then s1475 else s1474
-  s1477 :: SBool = s177 == s1360
-  s1478 :: SBool = s180 == s1360
-  s1479 :: SWord8 = if s1478 then s1475 else s1474
-  s1480 :: SWord8 = s33 + s1479
-  s1481 :: SWord8 = if s1477 then s1480 else s1479
-  s1482 :: SBool = s185 == s1360
-  s1483 :: SWord8 = if s1482 then s1475 else s1474
-  s1484 :: SWord8 = s33 + s1483
-  s1485 :: SWord8 = if s1478 then s1484 else s1483
-  s1486 :: SWord8 = s33 + s1485
-  s1487 :: SWord8 = if s1477 then s1486 else s1485
-  s1488 :: SWord8 = if s176 then s1481 else s1487
-  s1489 :: SWord8 = if s16 then s1476 else s1488
-  s1490 :: SWord8 = s33 + s1489
-  s1491 :: SWord8 = if s1362 then s1490 else s1489
-  s1492 :: SBool = s197 == s1360
-  s1493 :: SBool = s200 == s1360
-  s1494 :: SWord8 = if s1493 then s1490 else s1489
-  s1495 :: SWord8 = s33 + s1494
-  s1496 :: SWord8 = if s1492 then s1495 else s1494
-  s1497 :: SBool = s205 == s1360
-  s1498 :: SWord8 = if s1497 then s1490 else s1489
-  s1499 :: SWord8 = s33 + s1498
-  s1500 :: SWord8 = if s1493 then s1499 else s1498
-  s1501 :: SWord8 = s33 + s1500
-  s1502 :: SWord8 = if s1492 then s1501 else s1500
-  s1503 :: SWord8 = if s196 then s1496 else s1502
-  s1504 :: SWord8 = if s14 then s1491 else s1503
-  s1505 :: SWord8 = s33 + s1504
-  s1506 :: SWord8 = if s1361 then s1505 else s1504
-  s1507 :: SBool = s217 == s1360
-  s1508 :: SBool = s220 == s1360
-  s1509 :: SWord8 = if s1508 then s1505 else s1504
-  s1510 :: SWord8 = s33 + s1509
-  s1511 :: SWord8 = if s1507 then s1510 else s1509
-  s1512 :: SBool = s225 == s1360
-  s1513 :: SWord8 = if s1512 then s1505 else s1504
-  s1514 :: SWord8 = s33 + s1513
-  s1515 :: SWord8 = if s1508 then s1514 else s1513
-  s1516 :: SWord8 = s33 + s1515
-  s1517 :: SWord8 = if s1507 then s1516 else s1515
-  s1518 :: SWord8 = if s216 then s1511 else s1517
-  s1519 :: SWord8 = if s11 then s1506 else s1518
-  s1520 :: SBool = s8 == s1519
-  s1522 :: SBool = s9 == s1521
-  s1523 :: SBool = s8 == s1521
-  s1524 :: SBool = s7 == s1521
-  s1525 :: SBool = s6 == s1521
-  s1526 :: SBool = s5 == s1521
-  s1527 :: SBool = s4 == s1521
-  s1528 :: SBool = s3 == s1521
-  s1529 :: SBool = s2 == s1521
-  s1530 :: SBool = s1 == s1521
-  s1531 :: SBool = s0 == s1521
-  s1532 :: SWord8 = if s1531 then s32 else s33
-  s1533 :: SBool = s37 == s1521
-  s1534 :: SBool = s40 == s1521
-  s1535 :: SWord8 = if s1534 then s32 else s33
-  s1536 :: SWord8 = s33 + s1535
-  s1537 :: SWord8 = if s1533 then s1536 else s1535
-  s1538 :: SBool = s45 == s1521
-  s1539 :: SWord8 = if s1538 then s32 else s33
-  s1540 :: SWord8 = s33 + s1539
-  s1541 :: SWord8 = if s1534 then s1540 else s1539
-  s1542 :: SWord8 = s33 + s1541
-  s1543 :: SWord8 = if s1533 then s1542 else s1541
-  s1544 :: SWord8 = if s36 then s1537 else s1543
-  s1545 :: SWord8 = if s30 then s1532 else s1544
-  s1546 :: SWord8 = s33 + s1545
-  s1547 :: SWord8 = if s1530 then s1546 else s1545
-  s1548 :: SBool = s57 == s1521
-  s1549 :: SBool = s60 == s1521
-  s1550 :: SWord8 = if s1549 then s1546 else s1545
-  s1551 :: SWord8 = s33 + s1550
-  s1552 :: SWord8 = if s1548 then s1551 else s1550
-  s1553 :: SBool = s65 == s1521
-  s1554 :: SWord8 = if s1553 then s1546 else s1545
-  s1555 :: SWord8 = s33 + s1554
-  s1556 :: SWord8 = if s1549 then s1555 else s1554
-  s1557 :: SWord8 = s33 + s1556
-  s1558 :: SWord8 = if s1548 then s1557 else s1556
-  s1559 :: SWord8 = if s56 then s1552 else s1558
-  s1560 :: SWord8 = if s28 then s1547 else s1559
-  s1561 :: SWord8 = s33 + s1560
-  s1562 :: SWord8 = if s1529 then s1561 else s1560
-  s1563 :: SBool = s77 == s1521
-  s1564 :: SBool = s80 == s1521
-  s1565 :: SWord8 = if s1564 then s1561 else s1560
-  s1566 :: SWord8 = s33 + s1565
-  s1567 :: SWord8 = if s1563 then s1566 else s1565
-  s1568 :: SBool = s85 == s1521
-  s1569 :: SWord8 = if s1568 then s1561 else s1560
-  s1570 :: SWord8 = s33 + s1569
-  s1571 :: SWord8 = if s1564 then s1570 else s1569
-  s1572 :: SWord8 = s33 + s1571
-  s1573 :: SWord8 = if s1563 then s1572 else s1571
-  s1574 :: SWord8 = if s76 then s1567 else s1573
-  s1575 :: SWord8 = if s26 then s1562 else s1574
-  s1576 :: SWord8 = s33 + s1575
-  s1577 :: SWord8 = if s1528 then s1576 else s1575
-  s1578 :: SBool = s97 == s1521
-  s1579 :: SBool = s100 == s1521
-  s1580 :: SWord8 = if s1579 then s1576 else s1575
-  s1581 :: SWord8 = s33 + s1580
-  s1582 :: SWord8 = if s1578 then s1581 else s1580
-  s1583 :: SBool = s105 == s1521
-  s1584 :: SWord8 = if s1583 then s1576 else s1575
-  s1585 :: SWord8 = s33 + s1584
-  s1586 :: SWord8 = if s1579 then s1585 else s1584
-  s1587 :: SWord8 = s33 + s1586
-  s1588 :: SWord8 = if s1578 then s1587 else s1586
-  s1589 :: SWord8 = if s96 then s1582 else s1588
-  s1590 :: SWord8 = if s24 then s1577 else s1589
-  s1591 :: SWord8 = s33 + s1590
-  s1592 :: SWord8 = if s1527 then s1591 else s1590
-  s1593 :: SBool = s117 == s1521
-  s1594 :: SBool = s120 == s1521
-  s1595 :: SWord8 = if s1594 then s1591 else s1590
-  s1596 :: SWord8 = s33 + s1595
-  s1597 :: SWord8 = if s1593 then s1596 else s1595
-  s1598 :: SBool = s125 == s1521
-  s1599 :: SWord8 = if s1598 then s1591 else s1590
-  s1600 :: SWord8 = s33 + s1599
-  s1601 :: SWord8 = if s1594 then s1600 else s1599
-  s1602 :: SWord8 = s33 + s1601
-  s1603 :: SWord8 = if s1593 then s1602 else s1601
-  s1604 :: SWord8 = if s116 then s1597 else s1603
-  s1605 :: SWord8 = if s22 then s1592 else s1604
-  s1606 :: SWord8 = s33 + s1605
-  s1607 :: SWord8 = if s1526 then s1606 else s1605
-  s1608 :: SBool = s137 == s1521
-  s1609 :: SBool = s140 == s1521
-  s1610 :: SWord8 = if s1609 then s1606 else s1605
-  s1611 :: SWord8 = s33 + s1610
-  s1612 :: SWord8 = if s1608 then s1611 else s1610
-  s1613 :: SBool = s145 == s1521
-  s1614 :: SWord8 = if s1613 then s1606 else s1605
-  s1615 :: SWord8 = s33 + s1614
-  s1616 :: SWord8 = if s1609 then s1615 else s1614
-  s1617 :: SWord8 = s33 + s1616
-  s1618 :: SWord8 = if s1608 then s1617 else s1616
-  s1619 :: SWord8 = if s136 then s1612 else s1618
-  s1620 :: SWord8 = if s20 then s1607 else s1619
-  s1621 :: SWord8 = s33 + s1620
-  s1622 :: SWord8 = if s1525 then s1621 else s1620
-  s1623 :: SBool = s157 == s1521
-  s1624 :: SBool = s160 == s1521
-  s1625 :: SWord8 = if s1624 then s1621 else s1620
-  s1626 :: SWord8 = s33 + s1625
-  s1627 :: SWord8 = if s1623 then s1626 else s1625
-  s1628 :: SBool = s165 == s1521
-  s1629 :: SWord8 = if s1628 then s1621 else s1620
-  s1630 :: SWord8 = s33 + s1629
-  s1631 :: SWord8 = if s1624 then s1630 else s1629
-  s1632 :: SWord8 = s33 + s1631
-  s1633 :: SWord8 = if s1623 then s1632 else s1631
-  s1634 :: SWord8 = if s156 then s1627 else s1633
-  s1635 :: SWord8 = if s18 then s1622 else s1634
-  s1636 :: SWord8 = s33 + s1635
-  s1637 :: SWord8 = if s1524 then s1636 else s1635
-  s1638 :: SBool = s177 == s1521
-  s1639 :: SBool = s180 == s1521
-  s1640 :: SWord8 = if s1639 then s1636 else s1635
-  s1641 :: SWord8 = s33 + s1640
-  s1642 :: SWord8 = if s1638 then s1641 else s1640
-  s1643 :: SBool = s185 == s1521
-  s1644 :: SWord8 = if s1643 then s1636 else s1635
-  s1645 :: SWord8 = s33 + s1644
-  s1646 :: SWord8 = if s1639 then s1645 else s1644
-  s1647 :: SWord8 = s33 + s1646
-  s1648 :: SWord8 = if s1638 then s1647 else s1646
-  s1649 :: SWord8 = if s176 then s1642 else s1648
-  s1650 :: SWord8 = if s16 then s1637 else s1649
-  s1651 :: SWord8 = s33 + s1650
-  s1652 :: SWord8 = if s1523 then s1651 else s1650
-  s1653 :: SBool = s197 == s1521
-  s1654 :: SBool = s200 == s1521
-  s1655 :: SWord8 = if s1654 then s1651 else s1650
-  s1656 :: SWord8 = s33 + s1655
-  s1657 :: SWord8 = if s1653 then s1656 else s1655
-  s1658 :: SBool = s205 == s1521
-  s1659 :: SWord8 = if s1658 then s1651 else s1650
-  s1660 :: SWord8 = s33 + s1659
-  s1661 :: SWord8 = if s1654 then s1660 else s1659
-  s1662 :: SWord8 = s33 + s1661
-  s1663 :: SWord8 = if s1653 then s1662 else s1661
-  s1664 :: SWord8 = if s196 then s1657 else s1663
-  s1665 :: SWord8 = if s14 then s1652 else s1664
-  s1666 :: SWord8 = s33 + s1665
-  s1667 :: SWord8 = if s1522 then s1666 else s1665
-  s1668 :: SBool = s217 == s1521
-  s1669 :: SBool = s220 == s1521
-  s1670 :: SWord8 = if s1669 then s1666 else s1665
-  s1671 :: SWord8 = s33 + s1670
-  s1672 :: SWord8 = if s1668 then s1671 else s1670
-  s1673 :: SBool = s225 == s1521
-  s1674 :: SWord8 = if s1673 then s1666 else s1665
-  s1675 :: SWord8 = s33 + s1674
-  s1676 :: SWord8 = if s1669 then s1675 else s1674
-  s1677 :: SWord8 = s33 + s1676
-  s1678 :: SWord8 = if s1668 then s1677 else s1676
-  s1679 :: SWord8 = if s216 then s1672 else s1678
-  s1680 :: SWord8 = if s11 then s1667 else s1679
-  s1681 :: SBool = s9 == s1680
-  s1682 :: SBool = s1520 & s1681
-  s1683 :: SBool = s1359 & s1682
-  s1684 :: SBool = s1198 & s1683
-  s1685 :: SBool = s1037 & s1684
-  s1686 :: SBool = s876 & s1685
-  s1687 :: SBool = s715 & s1686
-  s1688 :: SBool = s554 & s1687
-  s1689 :: SBool = s394 & s1688
-  s1690 :: SBool = s234 & s1689
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s1690
diff --git a/SBVUnitTest/GoldFiles/crcPolyExist.gold b/SBVUnitTest/GoldFiles/crcPolyExist.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/crcPolyExist.gold
+++ /dev/null
@@ -1,3486 +0,0 @@
-INPUTS
-  s0 :: SWord16, existential, aliasing "poly"
-  s1 :: SWord32, aliasing "sh"
-  s2 :: SWord16, aliasing "sl"
-  s3 :: SWord32, aliasing "rh"
-  s4 :: SWord16, aliasing "rl"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s6 = 0 :: Word1
-  s18 = 1 :: Word8
-  s3340 = 0 :: Word8
-  s3468 = 4 :: Word8
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s5 :: SWord1 = choose [0:0] s0
-  s7 :: SBool = s5 /= s6
-  s8 :: SBool = s1 == s3
-  s9 :: SBool = s2 == s4
-  s10 :: SBool = s8 & s9
-  s11 :: SBool = ~ s10
-  s12 :: SBool = ~ s11
-  s13 :: SWord1 = choose [31:31] s1
-  s14 :: SBool = s6 /= s13
-  s15 :: SWord1 = choose [31:31] s3
-  s16 :: SBool = s6 /= s15
-  s17 :: SBool = s14 ^ s16
-  s19 :: SWord1 = choose [30:30] s1
-  s20 :: SBool = s6 /= s19
-  s21 :: SWord1 = choose [30:30] s3
-  s22 :: SBool = s6 /= s21
-  s23 :: SBool = s20 ^ s22
-  s24 :: SWord1 = choose [29:29] s1
-  s25 :: SBool = s6 /= s24
-  s26 :: SWord1 = choose [29:29] s3
-  s27 :: SBool = s6 /= s26
-  s28 :: SBool = s25 ^ s27
-  s29 :: SWord1 = choose [28:28] s1
-  s30 :: SBool = s6 /= s29
-  s31 :: SWord1 = choose [28:28] s3
-  s32 :: SBool = s6 /= s31
-  s33 :: SBool = s30 ^ s32
-  s34 :: SWord1 = choose [27:27] s1
-  s35 :: SBool = s6 /= s34
-  s36 :: SWord1 = choose [27:27] s3
-  s37 :: SBool = s6 /= s36
-  s38 :: SBool = s35 ^ s37
-  s39 :: SWord1 = choose [26:26] s1
-  s40 :: SBool = s6 /= s39
-  s41 :: SWord1 = choose [26:26] s3
-  s42 :: SBool = s6 /= s41
-  s43 :: SBool = s40 ^ s42
-  s44 :: SWord1 = choose [25:25] s1
-  s45 :: SBool = s6 /= s44
-  s46 :: SWord1 = choose [25:25] s3
-  s47 :: SBool = s6 /= s46
-  s48 :: SBool = s45 ^ s47
-  s49 :: SWord1 = choose [24:24] s1
-  s50 :: SBool = s6 /= s49
-  s51 :: SWord1 = choose [24:24] s3
-  s52 :: SBool = s6 /= s51
-  s53 :: SBool = s50 ^ s52
-  s54 :: SWord1 = choose [23:23] s1
-  s55 :: SBool = s6 /= s54
-  s56 :: SWord1 = choose [23:23] s3
-  s57 :: SBool = s6 /= s56
-  s58 :: SBool = s55 ^ s57
-  s59 :: SWord1 = choose [22:22] s1
-  s60 :: SBool = s6 /= s59
-  s61 :: SWord1 = choose [22:22] s3
-  s62 :: SBool = s6 /= s61
-  s63 :: SBool = s60 ^ s62
-  s64 :: SWord1 = choose [21:21] s1
-  s65 :: SBool = s6 /= s64
-  s66 :: SWord1 = choose [21:21] s3
-  s67 :: SBool = s6 /= s66
-  s68 :: SBool = s65 ^ s67
-  s69 :: SWord1 = choose [20:20] s1
-  s70 :: SBool = s6 /= s69
-  s71 :: SWord1 = choose [20:20] s3
-  s72 :: SBool = s6 /= s71
-  s73 :: SBool = s70 ^ s72
-  s74 :: SWord1 = choose [19:19] s1
-  s75 :: SBool = s6 /= s74
-  s76 :: SWord1 = choose [19:19] s3
-  s77 :: SBool = s6 /= s76
-  s78 :: SBool = s75 ^ s77
-  s79 :: SWord1 = choose [18:18] s1
-  s80 :: SBool = s6 /= s79
-  s81 :: SWord1 = choose [18:18] s3
-  s82 :: SBool = s6 /= s81
-  s83 :: SBool = s80 ^ s82
-  s84 :: SWord1 = choose [17:17] s1
-  s85 :: SBool = s6 /= s84
-  s86 :: SWord1 = choose [17:17] s3
-  s87 :: SBool = s6 /= s86
-  s88 :: SBool = s85 ^ s87
-  s89 :: SWord1 = choose [16:16] s1
-  s90 :: SBool = s6 /= s89
-  s91 :: SWord1 = choose [16:16] s3
-  s92 :: SBool = s6 /= s91
-  s93 :: SBool = s90 ^ s92
-  s94 :: SWord1 = choose [15:15] s1
-  s95 :: SBool = s6 /= s94
-  s96 :: SWord1 = choose [15:15] s3
-  s97 :: SBool = s6 /= s96
-  s98 :: SBool = s95 ^ s97
-  s99 :: SWord1 = choose [14:14] s1
-  s100 :: SBool = s6 /= s99
-  s101 :: SWord1 = choose [14:14] s3
-  s102 :: SBool = s6 /= s101
-  s103 :: SBool = s100 ^ s102
-  s104 :: SWord1 = choose [13:13] s1
-  s105 :: SBool = s6 /= s104
-  s106 :: SWord1 = choose [13:13] s3
-  s107 :: SBool = s6 /= s106
-  s108 :: SBool = s105 ^ s107
-  s109 :: SWord1 = choose [12:12] s1
-  s110 :: SBool = s6 /= s109
-  s111 :: SWord1 = choose [12:12] s3
-  s112 :: SBool = s6 /= s111
-  s113 :: SBool = s110 ^ s112
-  s114 :: SWord1 = choose [11:11] s1
-  s115 :: SBool = s6 /= s114
-  s116 :: SWord1 = choose [11:11] s3
-  s117 :: SBool = s6 /= s116
-  s118 :: SBool = s115 ^ s117
-  s119 :: SWord1 = choose [10:10] s1
-  s120 :: SBool = s6 /= s119
-  s121 :: SWord1 = choose [10:10] s3
-  s122 :: SBool = s6 /= s121
-  s123 :: SBool = s120 ^ s122
-  s124 :: SWord1 = choose [9:9] s1
-  s125 :: SBool = s6 /= s124
-  s126 :: SWord1 = choose [9:9] s3
-  s127 :: SBool = s6 /= s126
-  s128 :: SBool = s125 ^ s127
-  s129 :: SWord1 = choose [8:8] s1
-  s130 :: SBool = s6 /= s129
-  s131 :: SWord1 = choose [8:8] s3
-  s132 :: SBool = s6 /= s131
-  s133 :: SBool = s130 ^ s132
-  s134 :: SWord1 = choose [7:7] s1
-  s135 :: SBool = s6 /= s134
-  s136 :: SWord1 = choose [7:7] s3
-  s137 :: SBool = s6 /= s136
-  s138 :: SBool = s135 ^ s137
-  s139 :: SWord1 = choose [6:6] s1
-  s140 :: SBool = s6 /= s139
-  s141 :: SWord1 = choose [6:6] s3
-  s142 :: SBool = s6 /= s141
-  s143 :: SBool = s140 ^ s142
-  s144 :: SWord1 = choose [5:5] s1
-  s145 :: SBool = s6 /= s144
-  s146 :: SWord1 = choose [5:5] s3
-  s147 :: SBool = s6 /= s146
-  s148 :: SBool = s145 ^ s147
-  s149 :: SWord1 = choose [4:4] s1
-  s150 :: SBool = s6 /= s149
-  s151 :: SWord1 = choose [4:4] s3
-  s152 :: SBool = s6 /= s151
-  s153 :: SBool = s150 ^ s152
-  s154 :: SWord1 = choose [3:3] s1
-  s155 :: SBool = s6 /= s154
-  s156 :: SWord1 = choose [3:3] s3
-  s157 :: SBool = s6 /= s156
-  s158 :: SBool = s155 ^ s157
-  s159 :: SWord1 = choose [2:2] s1
-  s160 :: SBool = s6 /= s159
-  s161 :: SWord1 = choose [2:2] s3
-  s162 :: SBool = s6 /= s161
-  s163 :: SBool = s160 ^ s162
-  s164 :: SWord1 = choose [1:1] s1
-  s165 :: SBool = s6 /= s164
-  s166 :: SWord1 = choose [1:1] s3
-  s167 :: SBool = s6 /= s166
-  s168 :: SBool = s165 ^ s167
-  s169 :: SWord1 = choose [0:0] s1
-  s170 :: SBool = s6 /= s169
-  s171 :: SWord1 = choose [0:0] s3
-  s172 :: SBool = s6 /= s171
-  s173 :: SBool = s170 ^ s172
-  s174 :: SWord1 = choose [15:15] s2
-  s175 :: SBool = s6 /= s174
-  s176 :: SWord1 = choose [15:15] s4
-  s177 :: SBool = s6 /= s176
-  s178 :: SBool = s175 ^ s177
-  s179 :: SWord1 = choose [14:14] s2
-  s180 :: SBool = s6 /= s179
-  s181 :: SWord1 = choose [14:14] s4
-  s182 :: SBool = s6 /= s181
-  s183 :: SBool = s180 ^ s182
-  s184 :: SWord1 = choose [13:13] s2
-  s185 :: SBool = s6 /= s184
-  s186 :: SWord1 = choose [13:13] s4
-  s187 :: SBool = s6 /= s186
-  s188 :: SBool = s185 ^ s187
-  s189 :: SWord1 = choose [12:12] s2
-  s190 :: SBool = s6 /= s189
-  s191 :: SWord1 = choose [12:12] s4
-  s192 :: SBool = s6 /= s191
-  s193 :: SBool = s190 ^ s192
-  s194 :: SWord1 = choose [11:11] s2
-  s195 :: SBool = s6 /= s194
-  s196 :: SWord1 = choose [11:11] s4
-  s197 :: SBool = s6 /= s196
-  s198 :: SBool = s195 ^ s197
-  s199 :: SWord1 = choose [10:10] s2
-  s200 :: SBool = s6 /= s199
-  s201 :: SWord1 = choose [10:10] s4
-  s202 :: SBool = s6 /= s201
-  s203 :: SBool = s200 ^ s202
-  s204 :: SWord1 = choose [9:9] s2
-  s205 :: SBool = s6 /= s204
-  s206 :: SWord1 = choose [9:9] s4
-  s207 :: SBool = s6 /= s206
-  s208 :: SBool = s205 ^ s207
-  s209 :: SWord1 = choose [8:8] s2
-  s210 :: SBool = s6 /= s209
-  s211 :: SWord1 = choose [8:8] s4
-  s212 :: SBool = s6 /= s211
-  s213 :: SBool = s210 ^ s212
-  s214 :: SWord1 = choose [7:7] s2
-  s215 :: SBool = s6 /= s214
-  s216 :: SWord1 = choose [7:7] s4
-  s217 :: SBool = s6 /= s216
-  s218 :: SBool = s215 ^ s217
-  s219 :: SWord1 = choose [6:6] s2
-  s220 :: SBool = s6 /= s219
-  s221 :: SWord1 = choose [6:6] s4
-  s222 :: SBool = s6 /= s221
-  s223 :: SBool = s220 ^ s222
-  s224 :: SWord1 = choose [5:5] s2
-  s225 :: SBool = s6 /= s224
-  s226 :: SWord1 = choose [5:5] s4
-  s227 :: SBool = s6 /= s226
-  s228 :: SBool = s225 ^ s227
-  s229 :: SWord1 = choose [4:4] s2
-  s230 :: SBool = s6 /= s229
-  s231 :: SWord1 = choose [4:4] s4
-  s232 :: SBool = s6 /= s231
-  s233 :: SBool = s230 ^ s232
-  s234 :: SWord1 = choose [3:3] s2
-  s235 :: SBool = s6 /= s234
-  s236 :: SWord1 = choose [3:3] s4
-  s237 :: SBool = s6 /= s236
-  s238 :: SBool = s235 ^ s237
-  s239 :: SWord1 = choose [2:2] s2
-  s240 :: SBool = s6 /= s239
-  s241 :: SWord1 = choose [2:2] s4
-  s242 :: SBool = s6 /= s241
-  s243 :: SBool = s240 ^ s242
-  s244 :: SWord1 = choose [1:1] s2
-  s245 :: SBool = s6 /= s244
-  s246 :: SWord1 = choose [1:1] s4
-  s247 :: SBool = s6 /= s246
-  s248 :: SBool = s245 ^ s247
-  s249 :: SWord1 = choose [0:0] s2
-  s250 :: SBool = s6 /= s249
-  s251 :: SWord1 = choose [0:0] s4
-  s252 :: SBool = s6 /= s251
-  s253 :: SBool = s250 ^ s252
-  s254 :: SWord1 = choose [15:15] s0
-  s255 :: SBool = s6 /= s254
-  s256 :: SBool = s20 ^ s255
-  s257 :: SBool = if s14 then s256 else s20
-  s258 :: SWord1 = choose [14:14] s0
-  s259 :: SBool = s6 /= s258
-  s260 :: SBool = s25 ^ s259
-  s261 :: SBool = if s14 then s260 else s25
-  s262 :: SBool = s255 ^ s261
-  s263 :: SBool = if s257 then s262 else s261
-  s264 :: SWord1 = choose [13:13] s0
-  s265 :: SBool = s6 /= s264
-  s266 :: SBool = s30 ^ s265
-  s267 :: SBool = if s14 then s266 else s30
-  s268 :: SBool = s259 ^ s267
-  s269 :: SBool = if s257 then s268 else s267
-  s270 :: SBool = s255 ^ s269
-  s271 :: SBool = if s263 then s270 else s269
-  s272 :: SWord1 = choose [12:12] s0
-  s273 :: SBool = s6 /= s272
-  s274 :: SBool = s35 ^ s273
-  s275 :: SBool = if s14 then s274 else s35
-  s276 :: SBool = s265 ^ s275
-  s277 :: SBool = if s257 then s276 else s275
-  s278 :: SBool = s259 ^ s277
-  s279 :: SBool = if s263 then s278 else s277
-  s280 :: SBool = s255 ^ s279
-  s281 :: SBool = if s271 then s280 else s279
-  s282 :: SWord1 = choose [11:11] s0
-  s283 :: SBool = s6 /= s282
-  s284 :: SBool = s40 ^ s283
-  s285 :: SBool = if s14 then s284 else s40
-  s286 :: SBool = s273 ^ s285
-  s287 :: SBool = if s257 then s286 else s285
-  s288 :: SBool = s265 ^ s287
-  s289 :: SBool = if s263 then s288 else s287
-  s290 :: SBool = s259 ^ s289
-  s291 :: SBool = if s271 then s290 else s289
-  s292 :: SBool = s255 ^ s291
-  s293 :: SBool = if s281 then s292 else s291
-  s294 :: SWord1 = choose [10:10] s0
-  s295 :: SBool = s6 /= s294
-  s296 :: SBool = s45 ^ s295
-  s297 :: SBool = if s14 then s296 else s45
-  s298 :: SBool = s283 ^ s297
-  s299 :: SBool = if s257 then s298 else s297
-  s300 :: SBool = s273 ^ s299
-  s301 :: SBool = if s263 then s300 else s299
-  s302 :: SBool = s265 ^ s301
-  s303 :: SBool = if s271 then s302 else s301
-  s304 :: SBool = s259 ^ s303
-  s305 :: SBool = if s281 then s304 else s303
-  s306 :: SBool = s255 ^ s305
-  s307 :: SBool = if s293 then s306 else s305
-  s308 :: SWord1 = choose [9:9] s0
-  s309 :: SBool = s6 /= s308
-  s310 :: SBool = s50 ^ s309
-  s311 :: SBool = if s14 then s310 else s50
-  s312 :: SBool = s295 ^ s311
-  s313 :: SBool = if s257 then s312 else s311
-  s314 :: SBool = s283 ^ s313
-  s315 :: SBool = if s263 then s314 else s313
-  s316 :: SBool = s273 ^ s315
-  s317 :: SBool = if s271 then s316 else s315
-  s318 :: SBool = s265 ^ s317
-  s319 :: SBool = if s281 then s318 else s317
-  s320 :: SBool = s259 ^ s319
-  s321 :: SBool = if s293 then s320 else s319
-  s322 :: SBool = s255 ^ s321
-  s323 :: SBool = if s307 then s322 else s321
-  s324 :: SWord1 = choose [8:8] s0
-  s325 :: SBool = s6 /= s324
-  s326 :: SBool = s55 ^ s325
-  s327 :: SBool = if s14 then s326 else s55
-  s328 :: SBool = s309 ^ s327
-  s329 :: SBool = if s257 then s328 else s327
-  s330 :: SBool = s295 ^ s329
-  s331 :: SBool = if s263 then s330 else s329
-  s332 :: SBool = s283 ^ s331
-  s333 :: SBool = if s271 then s332 else s331
-  s334 :: SBool = s273 ^ s333
-  s335 :: SBool = if s281 then s334 else s333
-  s336 :: SBool = s265 ^ s335
-  s337 :: SBool = if s293 then s336 else s335
-  s338 :: SBool = s259 ^ s337
-  s339 :: SBool = if s307 then s338 else s337
-  s340 :: SBool = s255 ^ s339
-  s341 :: SBool = if s323 then s340 else s339
-  s342 :: SWord1 = choose [7:7] s0
-  s343 :: SBool = s6 /= s342
-  s344 :: SBool = s60 ^ s343
-  s345 :: SBool = if s14 then s344 else s60
-  s346 :: SBool = s325 ^ s345
-  s347 :: SBool = if s257 then s346 else s345
-  s348 :: SBool = s309 ^ s347
-  s349 :: SBool = if s263 then s348 else s347
-  s350 :: SBool = s295 ^ s349
-  s351 :: SBool = if s271 then s350 else s349
-  s352 :: SBool = s283 ^ s351
-  s353 :: SBool = if s281 then s352 else s351
-  s354 :: SBool = s273 ^ s353
-  s355 :: SBool = if s293 then s354 else s353
-  s356 :: SBool = s265 ^ s355
-  s357 :: SBool = if s307 then s356 else s355
-  s358 :: SBool = s259 ^ s357
-  s359 :: SBool = if s323 then s358 else s357
-  s360 :: SBool = s255 ^ s359
-  s361 :: SBool = if s341 then s360 else s359
-  s362 :: SWord1 = choose [6:6] s0
-  s363 :: SBool = s6 /= s362
-  s364 :: SBool = s65 ^ s363
-  s365 :: SBool = if s14 then s364 else s65
-  s366 :: SBool = s343 ^ s365
-  s367 :: SBool = if s257 then s366 else s365
-  s368 :: SBool = s325 ^ s367
-  s369 :: SBool = if s263 then s368 else s367
-  s370 :: SBool = s309 ^ s369
-  s371 :: SBool = if s271 then s370 else s369
-  s372 :: SBool = s295 ^ s371
-  s373 :: SBool = if s281 then s372 else s371
-  s374 :: SBool = s283 ^ s373
-  s375 :: SBool = if s293 then s374 else s373
-  s376 :: SBool = s273 ^ s375
-  s377 :: SBool = if s307 then s376 else s375
-  s378 :: SBool = s265 ^ s377
-  s379 :: SBool = if s323 then s378 else s377
-  s380 :: SBool = s259 ^ s379
-  s381 :: SBool = if s341 then s380 else s379
-  s382 :: SBool = s255 ^ s381
-  s383 :: SBool = if s361 then s382 else s381
-  s384 :: SWord1 = choose [5:5] s0
-  s385 :: SBool = s6 /= s384
-  s386 :: SBool = s70 ^ s385
-  s387 :: SBool = if s14 then s386 else s70
-  s388 :: SBool = s363 ^ s387
-  s389 :: SBool = if s257 then s388 else s387
-  s390 :: SBool = s343 ^ s389
-  s391 :: SBool = if s263 then s390 else s389
-  s392 :: SBool = s325 ^ s391
-  s393 :: SBool = if s271 then s392 else s391
-  s394 :: SBool = s309 ^ s393
-  s395 :: SBool = if s281 then s394 else s393
-  s396 :: SBool = s295 ^ s395
-  s397 :: SBool = if s293 then s396 else s395
-  s398 :: SBool = s283 ^ s397
-  s399 :: SBool = if s307 then s398 else s397
-  s400 :: SBool = s273 ^ s399
-  s401 :: SBool = if s323 then s400 else s399
-  s402 :: SBool = s265 ^ s401
-  s403 :: SBool = if s341 then s402 else s401
-  s404 :: SBool = s259 ^ s403
-  s405 :: SBool = if s361 then s404 else s403
-  s406 :: SBool = s255 ^ s405
-  s407 :: SBool = if s383 then s406 else s405
-  s408 :: SWord1 = choose [4:4] s0
-  s409 :: SBool = s6 /= s408
-  s410 :: SBool = s75 ^ s409
-  s411 :: SBool = if s14 then s410 else s75
-  s412 :: SBool = s385 ^ s411
-  s413 :: SBool = if s257 then s412 else s411
-  s414 :: SBool = s363 ^ s413
-  s415 :: SBool = if s263 then s414 else s413
-  s416 :: SBool = s343 ^ s415
-  s417 :: SBool = if s271 then s416 else s415
-  s418 :: SBool = s325 ^ s417
-  s419 :: SBool = if s281 then s418 else s417
-  s420 :: SBool = s309 ^ s419
-  s421 :: SBool = if s293 then s420 else s419
-  s422 :: SBool = s295 ^ s421
-  s423 :: SBool = if s307 then s422 else s421
-  s424 :: SBool = s283 ^ s423
-  s425 :: SBool = if s323 then s424 else s423
-  s426 :: SBool = s273 ^ s425
-  s427 :: SBool = if s341 then s426 else s425
-  s428 :: SBool = s265 ^ s427
-  s429 :: SBool = if s361 then s428 else s427
-  s430 :: SBool = s259 ^ s429
-  s431 :: SBool = if s383 then s430 else s429
-  s432 :: SBool = s255 ^ s431
-  s433 :: SBool = if s407 then s432 else s431
-  s434 :: SWord1 = choose [3:3] s0
-  s435 :: SBool = s6 /= s434
-  s436 :: SBool = s80 ^ s435
-  s437 :: SBool = if s14 then s436 else s80
-  s438 :: SBool = s409 ^ s437
-  s439 :: SBool = if s257 then s438 else s437
-  s440 :: SBool = s385 ^ s439
-  s441 :: SBool = if s263 then s440 else s439
-  s442 :: SBool = s363 ^ s441
-  s443 :: SBool = if s271 then s442 else s441
-  s444 :: SBool = s343 ^ s443
-  s445 :: SBool = if s281 then s444 else s443
-  s446 :: SBool = s325 ^ s445
-  s447 :: SBool = if s293 then s446 else s445
-  s448 :: SBool = s309 ^ s447
-  s449 :: SBool = if s307 then s448 else s447
-  s450 :: SBool = s295 ^ s449
-  s451 :: SBool = if s323 then s450 else s449
-  s452 :: SBool = s283 ^ s451
-  s453 :: SBool = if s341 then s452 else s451
-  s454 :: SBool = s273 ^ s453
-  s455 :: SBool = if s361 then s454 else s453
-  s456 :: SBool = s265 ^ s455
-  s457 :: SBool = if s383 then s456 else s455
-  s458 :: SBool = s259 ^ s457
-  s459 :: SBool = if s407 then s458 else s457
-  s460 :: SBool = s255 ^ s459
-  s461 :: SBool = if s433 then s460 else s459
-  s462 :: SWord1 = choose [2:2] s0
-  s463 :: SBool = s6 /= s462
-  s464 :: SBool = s85 ^ s463
-  s465 :: SBool = if s14 then s464 else s85
-  s466 :: SBool = s435 ^ s465
-  s467 :: SBool = if s257 then s466 else s465
-  s468 :: SBool = s409 ^ s467
-  s469 :: SBool = if s263 then s468 else s467
-  s470 :: SBool = s385 ^ s469
-  s471 :: SBool = if s271 then s470 else s469
-  s472 :: SBool = s363 ^ s471
-  s473 :: SBool = if s281 then s472 else s471
-  s474 :: SBool = s343 ^ s473
-  s475 :: SBool = if s293 then s474 else s473
-  s476 :: SBool = s325 ^ s475
-  s477 :: SBool = if s307 then s476 else s475
-  s478 :: SBool = s309 ^ s477
-  s479 :: SBool = if s323 then s478 else s477
-  s480 :: SBool = s295 ^ s479
-  s481 :: SBool = if s341 then s480 else s479
-  s482 :: SBool = s283 ^ s481
-  s483 :: SBool = if s361 then s482 else s481
-  s484 :: SBool = s273 ^ s483
-  s485 :: SBool = if s383 then s484 else s483
-  s486 :: SBool = s265 ^ s485
-  s487 :: SBool = if s407 then s486 else s485
-  s488 :: SBool = s259 ^ s487
-  s489 :: SBool = if s433 then s488 else s487
-  s490 :: SBool = s255 ^ s489
-  s491 :: SBool = if s461 then s490 else s489
-  s492 :: SWord1 = choose [1:1] s0
-  s493 :: SBool = s6 /= s492
-  s494 :: SBool = s90 ^ s493
-  s495 :: SBool = if s14 then s494 else s90
-  s496 :: SBool = s463 ^ s495
-  s497 :: SBool = if s257 then s496 else s495
-  s498 :: SBool = s435 ^ s497
-  s499 :: SBool = if s263 then s498 else s497
-  s500 :: SBool = s409 ^ s499
-  s501 :: SBool = if s271 then s500 else s499
-  s502 :: SBool = s385 ^ s501
-  s503 :: SBool = if s281 then s502 else s501
-  s504 :: SBool = s363 ^ s503
-  s505 :: SBool = if s293 then s504 else s503
-  s506 :: SBool = s343 ^ s505
-  s507 :: SBool = if s307 then s506 else s505
-  s508 :: SBool = s325 ^ s507
-  s509 :: SBool = if s323 then s508 else s507
-  s510 :: SBool = s309 ^ s509
-  s511 :: SBool = if s341 then s510 else s509
-  s512 :: SBool = s295 ^ s511
-  s513 :: SBool = if s361 then s512 else s511
-  s514 :: SBool = s283 ^ s513
-  s515 :: SBool = if s383 then s514 else s513
-  s516 :: SBool = s273 ^ s515
-  s517 :: SBool = if s407 then s516 else s515
-  s518 :: SBool = s265 ^ s517
-  s519 :: SBool = if s433 then s518 else s517
-  s520 :: SBool = s259 ^ s519
-  s521 :: SBool = if s461 then s520 else s519
-  s522 :: SBool = s255 ^ s521
-  s523 :: SBool = if s491 then s522 else s521
-  s524 :: SBool = s7 ^ s95
-  s525 :: SBool = if s14 then s524 else s95
-  s526 :: SBool = s493 ^ s525
-  s527 :: SBool = if s257 then s526 else s525
-  s528 :: SBool = s463 ^ s527
-  s529 :: SBool = if s263 then s528 else s527
-  s530 :: SBool = s435 ^ s529
-  s531 :: SBool = if s271 then s530 else s529
-  s532 :: SBool = s409 ^ s531
-  s533 :: SBool = if s281 then s532 else s531
-  s534 :: SBool = s385 ^ s533
-  s535 :: SBool = if s293 then s534 else s533
-  s536 :: SBool = s363 ^ s535
-  s537 :: SBool = if s307 then s536 else s535
-  s538 :: SBool = s343 ^ s537
-  s539 :: SBool = if s323 then s538 else s537
-  s540 :: SBool = s325 ^ s539
-  s541 :: SBool = if s341 then s540 else s539
-  s542 :: SBool = s309 ^ s541
-  s543 :: SBool = if s361 then s542 else s541
-  s544 :: SBool = s295 ^ s543
-  s545 :: SBool = if s383 then s544 else s543
-  s546 :: SBool = s283 ^ s545
-  s547 :: SBool = if s407 then s546 else s545
-  s548 :: SBool = s273 ^ s547
-  s549 :: SBool = if s433 then s548 else s547
-  s550 :: SBool = s265 ^ s549
-  s551 :: SBool = if s461 then s550 else s549
-  s552 :: SBool = s259 ^ s551
-  s553 :: SBool = if s491 then s552 else s551
-  s554 :: SBool = s255 ^ s553
-  s555 :: SBool = if s523 then s554 else s553
-  s556 :: SBool = s7 ^ s100
-  s557 :: SBool = if s257 then s556 else s100
-  s558 :: SBool = s493 ^ s557
-  s559 :: SBool = if s263 then s558 else s557
-  s560 :: SBool = s463 ^ s559
-  s561 :: SBool = if s271 then s560 else s559
-  s562 :: SBool = s435 ^ s561
-  s563 :: SBool = if s281 then s562 else s561
-  s564 :: SBool = s409 ^ s563
-  s565 :: SBool = if s293 then s564 else s563
-  s566 :: SBool = s385 ^ s565
-  s567 :: SBool = if s307 then s566 else s565
-  s568 :: SBool = s363 ^ s567
-  s569 :: SBool = if s323 then s568 else s567
-  s570 :: SBool = s343 ^ s569
-  s571 :: SBool = if s341 then s570 else s569
-  s572 :: SBool = s325 ^ s571
-  s573 :: SBool = if s361 then s572 else s571
-  s574 :: SBool = s309 ^ s573
-  s575 :: SBool = if s383 then s574 else s573
-  s576 :: SBool = s295 ^ s575
-  s577 :: SBool = if s407 then s576 else s575
-  s578 :: SBool = s283 ^ s577
-  s579 :: SBool = if s433 then s578 else s577
-  s580 :: SBool = s273 ^ s579
-  s581 :: SBool = if s461 then s580 else s579
-  s582 :: SBool = s265 ^ s581
-  s583 :: SBool = if s491 then s582 else s581
-  s584 :: SBool = s259 ^ s583
-  s585 :: SBool = if s523 then s584 else s583
-  s586 :: SBool = s255 ^ s585
-  s587 :: SBool = if s555 then s586 else s585
-  s588 :: SBool = s7 ^ s105
-  s589 :: SBool = if s263 then s588 else s105
-  s590 :: SBool = s493 ^ s589
-  s591 :: SBool = if s271 then s590 else s589
-  s592 :: SBool = s463 ^ s591
-  s593 :: SBool = if s281 then s592 else s591
-  s594 :: SBool = s435 ^ s593
-  s595 :: SBool = if s293 then s594 else s593
-  s596 :: SBool = s409 ^ s595
-  s597 :: SBool = if s307 then s596 else s595
-  s598 :: SBool = s385 ^ s597
-  s599 :: SBool = if s323 then s598 else s597
-  s600 :: SBool = s363 ^ s599
-  s601 :: SBool = if s341 then s600 else s599
-  s602 :: SBool = s343 ^ s601
-  s603 :: SBool = if s361 then s602 else s601
-  s604 :: SBool = s325 ^ s603
-  s605 :: SBool = if s383 then s604 else s603
-  s606 :: SBool = s309 ^ s605
-  s607 :: SBool = if s407 then s606 else s605
-  s608 :: SBool = s295 ^ s607
-  s609 :: SBool = if s433 then s608 else s607
-  s610 :: SBool = s283 ^ s609
-  s611 :: SBool = if s461 then s610 else s609
-  s612 :: SBool = s273 ^ s611
-  s613 :: SBool = if s491 then s612 else s611
-  s614 :: SBool = s265 ^ s613
-  s615 :: SBool = if s523 then s614 else s613
-  s616 :: SBool = s259 ^ s615
-  s617 :: SBool = if s555 then s616 else s615
-  s618 :: SBool = s255 ^ s617
-  s619 :: SBool = if s587 then s618 else s617
-  s620 :: SBool = s7 ^ s110
-  s621 :: SBool = if s271 then s620 else s110
-  s622 :: SBool = s493 ^ s621
-  s623 :: SBool = if s281 then s622 else s621
-  s624 :: SBool = s463 ^ s623
-  s625 :: SBool = if s293 then s624 else s623
-  s626 :: SBool = s435 ^ s625
-  s627 :: SBool = if s307 then s626 else s625
-  s628 :: SBool = s409 ^ s627
-  s629 :: SBool = if s323 then s628 else s627
-  s630 :: SBool = s385 ^ s629
-  s631 :: SBool = if s341 then s630 else s629
-  s632 :: SBool = s363 ^ s631
-  s633 :: SBool = if s361 then s632 else s631
-  s634 :: SBool = s343 ^ s633
-  s635 :: SBool = if s383 then s634 else s633
-  s636 :: SBool = s325 ^ s635
-  s637 :: SBool = if s407 then s636 else s635
-  s638 :: SBool = s309 ^ s637
-  s639 :: SBool = if s433 then s638 else s637
-  s640 :: SBool = s295 ^ s639
-  s641 :: SBool = if s461 then s640 else s639
-  s642 :: SBool = s283 ^ s641
-  s643 :: SBool = if s491 then s642 else s641
-  s644 :: SBool = s273 ^ s643
-  s645 :: SBool = if s523 then s644 else s643
-  s646 :: SBool = s265 ^ s645
-  s647 :: SBool = if s555 then s646 else s645
-  s648 :: SBool = s259 ^ s647
-  s649 :: SBool = if s587 then s648 else s647
-  s650 :: SBool = s255 ^ s649
-  s651 :: SBool = if s619 then s650 else s649
-  s652 :: SBool = s7 ^ s115
-  s653 :: SBool = if s281 then s652 else s115
-  s654 :: SBool = s493 ^ s653
-  s655 :: SBool = if s293 then s654 else s653
-  s656 :: SBool = s463 ^ s655
-  s657 :: SBool = if s307 then s656 else s655
-  s658 :: SBool = s435 ^ s657
-  s659 :: SBool = if s323 then s658 else s657
-  s660 :: SBool = s409 ^ s659
-  s661 :: SBool = if s341 then s660 else s659
-  s662 :: SBool = s385 ^ s661
-  s663 :: SBool = if s361 then s662 else s661
-  s664 :: SBool = s363 ^ s663
-  s665 :: SBool = if s383 then s664 else s663
-  s666 :: SBool = s343 ^ s665
-  s667 :: SBool = if s407 then s666 else s665
-  s668 :: SBool = s325 ^ s667
-  s669 :: SBool = if s433 then s668 else s667
-  s670 :: SBool = s309 ^ s669
-  s671 :: SBool = if s461 then s670 else s669
-  s672 :: SBool = s295 ^ s671
-  s673 :: SBool = if s491 then s672 else s671
-  s674 :: SBool = s283 ^ s673
-  s675 :: SBool = if s523 then s674 else s673
-  s676 :: SBool = s273 ^ s675
-  s677 :: SBool = if s555 then s676 else s675
-  s678 :: SBool = s265 ^ s677
-  s679 :: SBool = if s587 then s678 else s677
-  s680 :: SBool = s259 ^ s679
-  s681 :: SBool = if s619 then s680 else s679
-  s682 :: SBool = s255 ^ s681
-  s683 :: SBool = if s651 then s682 else s681
-  s684 :: SBool = s7 ^ s120
-  s685 :: SBool = if s293 then s684 else s120
-  s686 :: SBool = s493 ^ s685
-  s687 :: SBool = if s307 then s686 else s685
-  s688 :: SBool = s463 ^ s687
-  s689 :: SBool = if s323 then s688 else s687
-  s690 :: SBool = s435 ^ s689
-  s691 :: SBool = if s341 then s690 else s689
-  s692 :: SBool = s409 ^ s691
-  s693 :: SBool = if s361 then s692 else s691
-  s694 :: SBool = s385 ^ s693
-  s695 :: SBool = if s383 then s694 else s693
-  s696 :: SBool = s363 ^ s695
-  s697 :: SBool = if s407 then s696 else s695
-  s698 :: SBool = s343 ^ s697
-  s699 :: SBool = if s433 then s698 else s697
-  s700 :: SBool = s325 ^ s699
-  s701 :: SBool = if s461 then s700 else s699
-  s702 :: SBool = s309 ^ s701
-  s703 :: SBool = if s491 then s702 else s701
-  s704 :: SBool = s295 ^ s703
-  s705 :: SBool = if s523 then s704 else s703
-  s706 :: SBool = s283 ^ s705
-  s707 :: SBool = if s555 then s706 else s705
-  s708 :: SBool = s273 ^ s707
-  s709 :: SBool = if s587 then s708 else s707
-  s710 :: SBool = s265 ^ s709
-  s711 :: SBool = if s619 then s710 else s709
-  s712 :: SBool = s259 ^ s711
-  s713 :: SBool = if s651 then s712 else s711
-  s714 :: SBool = s255 ^ s713
-  s715 :: SBool = if s683 then s714 else s713
-  s716 :: SBool = s7 ^ s125
-  s717 :: SBool = if s307 then s716 else s125
-  s718 :: SBool = s493 ^ s717
-  s719 :: SBool = if s323 then s718 else s717
-  s720 :: SBool = s463 ^ s719
-  s721 :: SBool = if s341 then s720 else s719
-  s722 :: SBool = s435 ^ s721
-  s723 :: SBool = if s361 then s722 else s721
-  s724 :: SBool = s409 ^ s723
-  s725 :: SBool = if s383 then s724 else s723
-  s726 :: SBool = s385 ^ s725
-  s727 :: SBool = if s407 then s726 else s725
-  s728 :: SBool = s363 ^ s727
-  s729 :: SBool = if s433 then s728 else s727
-  s730 :: SBool = s343 ^ s729
-  s731 :: SBool = if s461 then s730 else s729
-  s732 :: SBool = s325 ^ s731
-  s733 :: SBool = if s491 then s732 else s731
-  s734 :: SBool = s309 ^ s733
-  s735 :: SBool = if s523 then s734 else s733
-  s736 :: SBool = s295 ^ s735
-  s737 :: SBool = if s555 then s736 else s735
-  s738 :: SBool = s283 ^ s737
-  s739 :: SBool = if s587 then s738 else s737
-  s740 :: SBool = s273 ^ s739
-  s741 :: SBool = if s619 then s740 else s739
-  s742 :: SBool = s265 ^ s741
-  s743 :: SBool = if s651 then s742 else s741
-  s744 :: SBool = s259 ^ s743
-  s745 :: SBool = if s683 then s744 else s743
-  s746 :: SBool = s255 ^ s745
-  s747 :: SBool = if s715 then s746 else s745
-  s748 :: SBool = s7 ^ s130
-  s749 :: SBool = if s323 then s748 else s130
-  s750 :: SBool = s493 ^ s749
-  s751 :: SBool = if s341 then s750 else s749
-  s752 :: SBool = s463 ^ s751
-  s753 :: SBool = if s361 then s752 else s751
-  s754 :: SBool = s435 ^ s753
-  s755 :: SBool = if s383 then s754 else s753
-  s756 :: SBool = s409 ^ s755
-  s757 :: SBool = if s407 then s756 else s755
-  s758 :: SBool = s385 ^ s757
-  s759 :: SBool = if s433 then s758 else s757
-  s760 :: SBool = s363 ^ s759
-  s761 :: SBool = if s461 then s760 else s759
-  s762 :: SBool = s343 ^ s761
-  s763 :: SBool = if s491 then s762 else s761
-  s764 :: SBool = s325 ^ s763
-  s765 :: SBool = if s523 then s764 else s763
-  s766 :: SBool = s309 ^ s765
-  s767 :: SBool = if s555 then s766 else s765
-  s768 :: SBool = s295 ^ s767
-  s769 :: SBool = if s587 then s768 else s767
-  s770 :: SBool = s283 ^ s769
-  s771 :: SBool = if s619 then s770 else s769
-  s772 :: SBool = s273 ^ s771
-  s773 :: SBool = if s651 then s772 else s771
-  s774 :: SBool = s265 ^ s773
-  s775 :: SBool = if s683 then s774 else s773
-  s776 :: SBool = s259 ^ s775
-  s777 :: SBool = if s715 then s776 else s775
-  s778 :: SBool = s255 ^ s777
-  s779 :: SBool = if s747 then s778 else s777
-  s780 :: SBool = s7 ^ s135
-  s781 :: SBool = if s341 then s780 else s135
-  s782 :: SBool = s493 ^ s781
-  s783 :: SBool = if s361 then s782 else s781
-  s784 :: SBool = s463 ^ s783
-  s785 :: SBool = if s383 then s784 else s783
-  s786 :: SBool = s435 ^ s785
-  s787 :: SBool = if s407 then s786 else s785
-  s788 :: SBool = s409 ^ s787
-  s789 :: SBool = if s433 then s788 else s787
-  s790 :: SBool = s385 ^ s789
-  s791 :: SBool = if s461 then s790 else s789
-  s792 :: SBool = s363 ^ s791
-  s793 :: SBool = if s491 then s792 else s791
-  s794 :: SBool = s343 ^ s793
-  s795 :: SBool = if s523 then s794 else s793
-  s796 :: SBool = s325 ^ s795
-  s797 :: SBool = if s555 then s796 else s795
-  s798 :: SBool = s309 ^ s797
-  s799 :: SBool = if s587 then s798 else s797
-  s800 :: SBool = s295 ^ s799
-  s801 :: SBool = if s619 then s800 else s799
-  s802 :: SBool = s283 ^ s801
-  s803 :: SBool = if s651 then s802 else s801
-  s804 :: SBool = s273 ^ s803
-  s805 :: SBool = if s683 then s804 else s803
-  s806 :: SBool = s265 ^ s805
-  s807 :: SBool = if s715 then s806 else s805
-  s808 :: SBool = s259 ^ s807
-  s809 :: SBool = if s747 then s808 else s807
-  s810 :: SBool = s255 ^ s809
-  s811 :: SBool = if s779 then s810 else s809
-  s812 :: SBool = s7 ^ s140
-  s813 :: SBool = if s361 then s812 else s140
-  s814 :: SBool = s493 ^ s813
-  s815 :: SBool = if s383 then s814 else s813
-  s816 :: SBool = s463 ^ s815
-  s817 :: SBool = if s407 then s816 else s815
-  s818 :: SBool = s435 ^ s817
-  s819 :: SBool = if s433 then s818 else s817
-  s820 :: SBool = s409 ^ s819
-  s821 :: SBool = if s461 then s820 else s819
-  s822 :: SBool = s385 ^ s821
-  s823 :: SBool = if s491 then s822 else s821
-  s824 :: SBool = s363 ^ s823
-  s825 :: SBool = if s523 then s824 else s823
-  s826 :: SBool = s343 ^ s825
-  s827 :: SBool = if s555 then s826 else s825
-  s828 :: SBool = s325 ^ s827
-  s829 :: SBool = if s587 then s828 else s827
-  s830 :: SBool = s309 ^ s829
-  s831 :: SBool = if s619 then s830 else s829
-  s832 :: SBool = s295 ^ s831
-  s833 :: SBool = if s651 then s832 else s831
-  s834 :: SBool = s283 ^ s833
-  s835 :: SBool = if s683 then s834 else s833
-  s836 :: SBool = s273 ^ s835
-  s837 :: SBool = if s715 then s836 else s835
-  s838 :: SBool = s265 ^ s837
-  s839 :: SBool = if s747 then s838 else s837
-  s840 :: SBool = s259 ^ s839
-  s841 :: SBool = if s779 then s840 else s839
-  s842 :: SBool = s255 ^ s841
-  s843 :: SBool = if s811 then s842 else s841
-  s844 :: SBool = s7 ^ s145
-  s845 :: SBool = if s383 then s844 else s145
-  s846 :: SBool = s493 ^ s845
-  s847 :: SBool = if s407 then s846 else s845
-  s848 :: SBool = s463 ^ s847
-  s849 :: SBool = if s433 then s848 else s847
-  s850 :: SBool = s435 ^ s849
-  s851 :: SBool = if s461 then s850 else s849
-  s852 :: SBool = s409 ^ s851
-  s853 :: SBool = if s491 then s852 else s851
-  s854 :: SBool = s385 ^ s853
-  s855 :: SBool = if s523 then s854 else s853
-  s856 :: SBool = s363 ^ s855
-  s857 :: SBool = if s555 then s856 else s855
-  s858 :: SBool = s343 ^ s857
-  s859 :: SBool = if s587 then s858 else s857
-  s860 :: SBool = s325 ^ s859
-  s861 :: SBool = if s619 then s860 else s859
-  s862 :: SBool = s309 ^ s861
-  s863 :: SBool = if s651 then s862 else s861
-  s864 :: SBool = s295 ^ s863
-  s865 :: SBool = if s683 then s864 else s863
-  s866 :: SBool = s283 ^ s865
-  s867 :: SBool = if s715 then s866 else s865
-  s868 :: SBool = s273 ^ s867
-  s869 :: SBool = if s747 then s868 else s867
-  s870 :: SBool = s265 ^ s869
-  s871 :: SBool = if s779 then s870 else s869
-  s872 :: SBool = s259 ^ s871
-  s873 :: SBool = if s811 then s872 else s871
-  s874 :: SBool = s255 ^ s873
-  s875 :: SBool = if s843 then s874 else s873
-  s876 :: SBool = s7 ^ s150
-  s877 :: SBool = if s407 then s876 else s150
-  s878 :: SBool = s493 ^ s877
-  s879 :: SBool = if s433 then s878 else s877
-  s880 :: SBool = s463 ^ s879
-  s881 :: SBool = if s461 then s880 else s879
-  s882 :: SBool = s435 ^ s881
-  s883 :: SBool = if s491 then s882 else s881
-  s884 :: SBool = s409 ^ s883
-  s885 :: SBool = if s523 then s884 else s883
-  s886 :: SBool = s385 ^ s885
-  s887 :: SBool = if s555 then s886 else s885
-  s888 :: SBool = s363 ^ s887
-  s889 :: SBool = if s587 then s888 else s887
-  s890 :: SBool = s343 ^ s889
-  s891 :: SBool = if s619 then s890 else s889
-  s892 :: SBool = s325 ^ s891
-  s893 :: SBool = if s651 then s892 else s891
-  s894 :: SBool = s309 ^ s893
-  s895 :: SBool = if s683 then s894 else s893
-  s896 :: SBool = s295 ^ s895
-  s897 :: SBool = if s715 then s896 else s895
-  s898 :: SBool = s283 ^ s897
-  s899 :: SBool = if s747 then s898 else s897
-  s900 :: SBool = s273 ^ s899
-  s901 :: SBool = if s779 then s900 else s899
-  s902 :: SBool = s265 ^ s901
-  s903 :: SBool = if s811 then s902 else s901
-  s904 :: SBool = s259 ^ s903
-  s905 :: SBool = if s843 then s904 else s903
-  s906 :: SBool = s255 ^ s905
-  s907 :: SBool = if s875 then s906 else s905
-  s908 :: SBool = s7 ^ s155
-  s909 :: SBool = if s433 then s908 else s155
-  s910 :: SBool = s493 ^ s909
-  s911 :: SBool = if s461 then s910 else s909
-  s912 :: SBool = s463 ^ s911
-  s913 :: SBool = if s491 then s912 else s911
-  s914 :: SBool = s435 ^ s913
-  s915 :: SBool = if s523 then s914 else s913
-  s916 :: SBool = s409 ^ s915
-  s917 :: SBool = if s555 then s916 else s915
-  s918 :: SBool = s385 ^ s917
-  s919 :: SBool = if s587 then s918 else s917
-  s920 :: SBool = s363 ^ s919
-  s921 :: SBool = if s619 then s920 else s919
-  s922 :: SBool = s343 ^ s921
-  s923 :: SBool = if s651 then s922 else s921
-  s924 :: SBool = s325 ^ s923
-  s925 :: SBool = if s683 then s924 else s923
-  s926 :: SBool = s309 ^ s925
-  s927 :: SBool = if s715 then s926 else s925
-  s928 :: SBool = s295 ^ s927
-  s929 :: SBool = if s747 then s928 else s927
-  s930 :: SBool = s283 ^ s929
-  s931 :: SBool = if s779 then s930 else s929
-  s932 :: SBool = s273 ^ s931
-  s933 :: SBool = if s811 then s932 else s931
-  s934 :: SBool = s265 ^ s933
-  s935 :: SBool = if s843 then s934 else s933
-  s936 :: SBool = s259 ^ s935
-  s937 :: SBool = if s875 then s936 else s935
-  s938 :: SBool = s255 ^ s937
-  s939 :: SBool = if s907 then s938 else s937
-  s940 :: SBool = s7 ^ s160
-  s941 :: SBool = if s461 then s940 else s160
-  s942 :: SBool = s493 ^ s941
-  s943 :: SBool = if s491 then s942 else s941
-  s944 :: SBool = s463 ^ s943
-  s945 :: SBool = if s523 then s944 else s943
-  s946 :: SBool = s435 ^ s945
-  s947 :: SBool = if s555 then s946 else s945
-  s948 :: SBool = s409 ^ s947
-  s949 :: SBool = if s587 then s948 else s947
-  s950 :: SBool = s385 ^ s949
-  s951 :: SBool = if s619 then s950 else s949
-  s952 :: SBool = s363 ^ s951
-  s953 :: SBool = if s651 then s952 else s951
-  s954 :: SBool = s343 ^ s953
-  s955 :: SBool = if s683 then s954 else s953
-  s956 :: SBool = s325 ^ s955
-  s957 :: SBool = if s715 then s956 else s955
-  s958 :: SBool = s309 ^ s957
-  s959 :: SBool = if s747 then s958 else s957
-  s960 :: SBool = s295 ^ s959
-  s961 :: SBool = if s779 then s960 else s959
-  s962 :: SBool = s283 ^ s961
-  s963 :: SBool = if s811 then s962 else s961
-  s964 :: SBool = s273 ^ s963
-  s965 :: SBool = if s843 then s964 else s963
-  s966 :: SBool = s265 ^ s965
-  s967 :: SBool = if s875 then s966 else s965
-  s968 :: SBool = s259 ^ s967
-  s969 :: SBool = if s907 then s968 else s967
-  s970 :: SBool = s255 ^ s969
-  s971 :: SBool = if s939 then s970 else s969
-  s972 :: SBool = s7 ^ s165
-  s973 :: SBool = if s491 then s972 else s165
-  s974 :: SBool = s493 ^ s973
-  s975 :: SBool = if s523 then s974 else s973
-  s976 :: SBool = s463 ^ s975
-  s977 :: SBool = if s555 then s976 else s975
-  s978 :: SBool = s435 ^ s977
-  s979 :: SBool = if s587 then s978 else s977
-  s980 :: SBool = s409 ^ s979
-  s981 :: SBool = if s619 then s980 else s979
-  s982 :: SBool = s385 ^ s981
-  s983 :: SBool = if s651 then s982 else s981
-  s984 :: SBool = s363 ^ s983
-  s985 :: SBool = if s683 then s984 else s983
-  s986 :: SBool = s343 ^ s985
-  s987 :: SBool = if s715 then s986 else s985
-  s988 :: SBool = s325 ^ s987
-  s989 :: SBool = if s747 then s988 else s987
-  s990 :: SBool = s309 ^ s989
-  s991 :: SBool = if s779 then s990 else s989
-  s992 :: SBool = s295 ^ s991
-  s993 :: SBool = if s811 then s992 else s991
-  s994 :: SBool = s283 ^ s993
-  s995 :: SBool = if s843 then s994 else s993
-  s996 :: SBool = s273 ^ s995
-  s997 :: SBool = if s875 then s996 else s995
-  s998 :: SBool = s265 ^ s997
-  s999 :: SBool = if s907 then s998 else s997
-  s1000 :: SBool = s259 ^ s999
-  s1001 :: SBool = if s939 then s1000 else s999
-  s1002 :: SBool = s255 ^ s1001
-  s1003 :: SBool = if s971 then s1002 else s1001
-  s1004 :: SBool = s7 ^ s170
-  s1005 :: SBool = if s523 then s1004 else s170
-  s1006 :: SBool = s493 ^ s1005
-  s1007 :: SBool = if s555 then s1006 else s1005
-  s1008 :: SBool = s463 ^ s1007
-  s1009 :: SBool = if s587 then s1008 else s1007
-  s1010 :: SBool = s435 ^ s1009
-  s1011 :: SBool = if s619 then s1010 else s1009
-  s1012 :: SBool = s409 ^ s1011
-  s1013 :: SBool = if s651 then s1012 else s1011
-  s1014 :: SBool = s385 ^ s1013
-  s1015 :: SBool = if s683 then s1014 else s1013
-  s1016 :: SBool = s363 ^ s1015
-  s1017 :: SBool = if s715 then s1016 else s1015
-  s1018 :: SBool = s343 ^ s1017
-  s1019 :: SBool = if s747 then s1018 else s1017
-  s1020 :: SBool = s325 ^ s1019
-  s1021 :: SBool = if s779 then s1020 else s1019
-  s1022 :: SBool = s309 ^ s1021
-  s1023 :: SBool = if s811 then s1022 else s1021
-  s1024 :: SBool = s295 ^ s1023
-  s1025 :: SBool = if s843 then s1024 else s1023
-  s1026 :: SBool = s283 ^ s1025
-  s1027 :: SBool = if s875 then s1026 else s1025
-  s1028 :: SBool = s273 ^ s1027
-  s1029 :: SBool = if s907 then s1028 else s1027
-  s1030 :: SBool = s265 ^ s1029
-  s1031 :: SBool = if s939 then s1030 else s1029
-  s1032 :: SBool = s259 ^ s1031
-  s1033 :: SBool = if s971 then s1032 else s1031
-  s1034 :: SBool = s255 ^ s1033
-  s1035 :: SBool = if s1003 then s1034 else s1033
-  s1036 :: SBool = s7 ^ s175
-  s1037 :: SBool = if s555 then s1036 else s175
-  s1038 :: SBool = s493 ^ s1037
-  s1039 :: SBool = if s587 then s1038 else s1037
-  s1040 :: SBool = s463 ^ s1039
-  s1041 :: SBool = if s619 then s1040 else s1039
-  s1042 :: SBool = s435 ^ s1041
-  s1043 :: SBool = if s651 then s1042 else s1041
-  s1044 :: SBool = s409 ^ s1043
-  s1045 :: SBool = if s683 then s1044 else s1043
-  s1046 :: SBool = s385 ^ s1045
-  s1047 :: SBool = if s715 then s1046 else s1045
-  s1048 :: SBool = s363 ^ s1047
-  s1049 :: SBool = if s747 then s1048 else s1047
-  s1050 :: SBool = s343 ^ s1049
-  s1051 :: SBool = if s779 then s1050 else s1049
-  s1052 :: SBool = s325 ^ s1051
-  s1053 :: SBool = if s811 then s1052 else s1051
-  s1054 :: SBool = s309 ^ s1053
-  s1055 :: SBool = if s843 then s1054 else s1053
-  s1056 :: SBool = s295 ^ s1055
-  s1057 :: SBool = if s875 then s1056 else s1055
-  s1058 :: SBool = s283 ^ s1057
-  s1059 :: SBool = if s907 then s1058 else s1057
-  s1060 :: SBool = s273 ^ s1059
-  s1061 :: SBool = if s939 then s1060 else s1059
-  s1062 :: SBool = s265 ^ s1061
-  s1063 :: SBool = if s971 then s1062 else s1061
-  s1064 :: SBool = s259 ^ s1063
-  s1065 :: SBool = if s1003 then s1064 else s1063
-  s1066 :: SBool = s255 ^ s1065
-  s1067 :: SBool = if s1035 then s1066 else s1065
-  s1068 :: SBool = s7 ^ s180
-  s1069 :: SBool = if s587 then s1068 else s180
-  s1070 :: SBool = s493 ^ s1069
-  s1071 :: SBool = if s619 then s1070 else s1069
-  s1072 :: SBool = s463 ^ s1071
-  s1073 :: SBool = if s651 then s1072 else s1071
-  s1074 :: SBool = s435 ^ s1073
-  s1075 :: SBool = if s683 then s1074 else s1073
-  s1076 :: SBool = s409 ^ s1075
-  s1077 :: SBool = if s715 then s1076 else s1075
-  s1078 :: SBool = s385 ^ s1077
-  s1079 :: SBool = if s747 then s1078 else s1077
-  s1080 :: SBool = s363 ^ s1079
-  s1081 :: SBool = if s779 then s1080 else s1079
-  s1082 :: SBool = s343 ^ s1081
-  s1083 :: SBool = if s811 then s1082 else s1081
-  s1084 :: SBool = s325 ^ s1083
-  s1085 :: SBool = if s843 then s1084 else s1083
-  s1086 :: SBool = s309 ^ s1085
-  s1087 :: SBool = if s875 then s1086 else s1085
-  s1088 :: SBool = s295 ^ s1087
-  s1089 :: SBool = if s907 then s1088 else s1087
-  s1090 :: SBool = s283 ^ s1089
-  s1091 :: SBool = if s939 then s1090 else s1089
-  s1092 :: SBool = s273 ^ s1091
-  s1093 :: SBool = if s971 then s1092 else s1091
-  s1094 :: SBool = s265 ^ s1093
-  s1095 :: SBool = if s1003 then s1094 else s1093
-  s1096 :: SBool = s259 ^ s1095
-  s1097 :: SBool = if s1035 then s1096 else s1095
-  s1098 :: SBool = s255 ^ s1097
-  s1099 :: SBool = if s1067 then s1098 else s1097
-  s1100 :: SBool = s7 ^ s185
-  s1101 :: SBool = if s619 then s1100 else s185
-  s1102 :: SBool = s493 ^ s1101
-  s1103 :: SBool = if s651 then s1102 else s1101
-  s1104 :: SBool = s463 ^ s1103
-  s1105 :: SBool = if s683 then s1104 else s1103
-  s1106 :: SBool = s435 ^ s1105
-  s1107 :: SBool = if s715 then s1106 else s1105
-  s1108 :: SBool = s409 ^ s1107
-  s1109 :: SBool = if s747 then s1108 else s1107
-  s1110 :: SBool = s385 ^ s1109
-  s1111 :: SBool = if s779 then s1110 else s1109
-  s1112 :: SBool = s363 ^ s1111
-  s1113 :: SBool = if s811 then s1112 else s1111
-  s1114 :: SBool = s343 ^ s1113
-  s1115 :: SBool = if s843 then s1114 else s1113
-  s1116 :: SBool = s325 ^ s1115
-  s1117 :: SBool = if s875 then s1116 else s1115
-  s1118 :: SBool = s309 ^ s1117
-  s1119 :: SBool = if s907 then s1118 else s1117
-  s1120 :: SBool = s295 ^ s1119
-  s1121 :: SBool = if s939 then s1120 else s1119
-  s1122 :: SBool = s283 ^ s1121
-  s1123 :: SBool = if s971 then s1122 else s1121
-  s1124 :: SBool = s273 ^ s1123
-  s1125 :: SBool = if s1003 then s1124 else s1123
-  s1126 :: SBool = s265 ^ s1125
-  s1127 :: SBool = if s1035 then s1126 else s1125
-  s1128 :: SBool = s259 ^ s1127
-  s1129 :: SBool = if s1067 then s1128 else s1127
-  s1130 :: SBool = s255 ^ s1129
-  s1131 :: SBool = if s1099 then s1130 else s1129
-  s1132 :: SBool = s7 ^ s190
-  s1133 :: SBool = if s651 then s1132 else s190
-  s1134 :: SBool = s493 ^ s1133
-  s1135 :: SBool = if s683 then s1134 else s1133
-  s1136 :: SBool = s463 ^ s1135
-  s1137 :: SBool = if s715 then s1136 else s1135
-  s1138 :: SBool = s435 ^ s1137
-  s1139 :: SBool = if s747 then s1138 else s1137
-  s1140 :: SBool = s409 ^ s1139
-  s1141 :: SBool = if s779 then s1140 else s1139
-  s1142 :: SBool = s385 ^ s1141
-  s1143 :: SBool = if s811 then s1142 else s1141
-  s1144 :: SBool = s363 ^ s1143
-  s1145 :: SBool = if s843 then s1144 else s1143
-  s1146 :: SBool = s343 ^ s1145
-  s1147 :: SBool = if s875 then s1146 else s1145
-  s1148 :: SBool = s325 ^ s1147
-  s1149 :: SBool = if s907 then s1148 else s1147
-  s1150 :: SBool = s309 ^ s1149
-  s1151 :: SBool = if s939 then s1150 else s1149
-  s1152 :: SBool = s295 ^ s1151
-  s1153 :: SBool = if s971 then s1152 else s1151
-  s1154 :: SBool = s283 ^ s1153
-  s1155 :: SBool = if s1003 then s1154 else s1153
-  s1156 :: SBool = s273 ^ s1155
-  s1157 :: SBool = if s1035 then s1156 else s1155
-  s1158 :: SBool = s265 ^ s1157
-  s1159 :: SBool = if s1067 then s1158 else s1157
-  s1160 :: SBool = s259 ^ s1159
-  s1161 :: SBool = if s1099 then s1160 else s1159
-  s1162 :: SBool = s255 ^ s1161
-  s1163 :: SBool = if s1131 then s1162 else s1161
-  s1164 :: SBool = s7 ^ s195
-  s1165 :: SBool = if s683 then s1164 else s195
-  s1166 :: SBool = s493 ^ s1165
-  s1167 :: SBool = if s715 then s1166 else s1165
-  s1168 :: SBool = s463 ^ s1167
-  s1169 :: SBool = if s747 then s1168 else s1167
-  s1170 :: SBool = s435 ^ s1169
-  s1171 :: SBool = if s779 then s1170 else s1169
-  s1172 :: SBool = s409 ^ s1171
-  s1173 :: SBool = if s811 then s1172 else s1171
-  s1174 :: SBool = s385 ^ s1173
-  s1175 :: SBool = if s843 then s1174 else s1173
-  s1176 :: SBool = s363 ^ s1175
-  s1177 :: SBool = if s875 then s1176 else s1175
-  s1178 :: SBool = s343 ^ s1177
-  s1179 :: SBool = if s907 then s1178 else s1177
-  s1180 :: SBool = s325 ^ s1179
-  s1181 :: SBool = if s939 then s1180 else s1179
-  s1182 :: SBool = s309 ^ s1181
-  s1183 :: SBool = if s971 then s1182 else s1181
-  s1184 :: SBool = s295 ^ s1183
-  s1185 :: SBool = if s1003 then s1184 else s1183
-  s1186 :: SBool = s283 ^ s1185
-  s1187 :: SBool = if s1035 then s1186 else s1185
-  s1188 :: SBool = s273 ^ s1187
-  s1189 :: SBool = if s1067 then s1188 else s1187
-  s1190 :: SBool = s265 ^ s1189
-  s1191 :: SBool = if s1099 then s1190 else s1189
-  s1192 :: SBool = s259 ^ s1191
-  s1193 :: SBool = if s1131 then s1192 else s1191
-  s1194 :: SBool = s255 ^ s1193
-  s1195 :: SBool = if s1163 then s1194 else s1193
-  s1196 :: SBool = s7 ^ s200
-  s1197 :: SBool = if s715 then s1196 else s200
-  s1198 :: SBool = s493 ^ s1197
-  s1199 :: SBool = if s747 then s1198 else s1197
-  s1200 :: SBool = s463 ^ s1199
-  s1201 :: SBool = if s779 then s1200 else s1199
-  s1202 :: SBool = s435 ^ s1201
-  s1203 :: SBool = if s811 then s1202 else s1201
-  s1204 :: SBool = s409 ^ s1203
-  s1205 :: SBool = if s843 then s1204 else s1203
-  s1206 :: SBool = s385 ^ s1205
-  s1207 :: SBool = if s875 then s1206 else s1205
-  s1208 :: SBool = s363 ^ s1207
-  s1209 :: SBool = if s907 then s1208 else s1207
-  s1210 :: SBool = s343 ^ s1209
-  s1211 :: SBool = if s939 then s1210 else s1209
-  s1212 :: SBool = s325 ^ s1211
-  s1213 :: SBool = if s971 then s1212 else s1211
-  s1214 :: SBool = s309 ^ s1213
-  s1215 :: SBool = if s1003 then s1214 else s1213
-  s1216 :: SBool = s295 ^ s1215
-  s1217 :: SBool = if s1035 then s1216 else s1215
-  s1218 :: SBool = s283 ^ s1217
-  s1219 :: SBool = if s1067 then s1218 else s1217
-  s1220 :: SBool = s273 ^ s1219
-  s1221 :: SBool = if s1099 then s1220 else s1219
-  s1222 :: SBool = s265 ^ s1221
-  s1223 :: SBool = if s1131 then s1222 else s1221
-  s1224 :: SBool = s259 ^ s1223
-  s1225 :: SBool = if s1163 then s1224 else s1223
-  s1226 :: SBool = s255 ^ s1225
-  s1227 :: SBool = if s1195 then s1226 else s1225
-  s1228 :: SBool = s7 ^ s205
-  s1229 :: SBool = if s747 then s1228 else s205
-  s1230 :: SBool = s493 ^ s1229
-  s1231 :: SBool = if s779 then s1230 else s1229
-  s1232 :: SBool = s463 ^ s1231
-  s1233 :: SBool = if s811 then s1232 else s1231
-  s1234 :: SBool = s435 ^ s1233
-  s1235 :: SBool = if s843 then s1234 else s1233
-  s1236 :: SBool = s409 ^ s1235
-  s1237 :: SBool = if s875 then s1236 else s1235
-  s1238 :: SBool = s385 ^ s1237
-  s1239 :: SBool = if s907 then s1238 else s1237
-  s1240 :: SBool = s363 ^ s1239
-  s1241 :: SBool = if s939 then s1240 else s1239
-  s1242 :: SBool = s343 ^ s1241
-  s1243 :: SBool = if s971 then s1242 else s1241
-  s1244 :: SBool = s325 ^ s1243
-  s1245 :: SBool = if s1003 then s1244 else s1243
-  s1246 :: SBool = s309 ^ s1245
-  s1247 :: SBool = if s1035 then s1246 else s1245
-  s1248 :: SBool = s295 ^ s1247
-  s1249 :: SBool = if s1067 then s1248 else s1247
-  s1250 :: SBool = s283 ^ s1249
-  s1251 :: SBool = if s1099 then s1250 else s1249
-  s1252 :: SBool = s273 ^ s1251
-  s1253 :: SBool = if s1131 then s1252 else s1251
-  s1254 :: SBool = s265 ^ s1253
-  s1255 :: SBool = if s1163 then s1254 else s1253
-  s1256 :: SBool = s259 ^ s1255
-  s1257 :: SBool = if s1195 then s1256 else s1255
-  s1258 :: SBool = s255 ^ s1257
-  s1259 :: SBool = if s1227 then s1258 else s1257
-  s1260 :: SBool = s7 ^ s210
-  s1261 :: SBool = if s779 then s1260 else s210
-  s1262 :: SBool = s493 ^ s1261
-  s1263 :: SBool = if s811 then s1262 else s1261
-  s1264 :: SBool = s463 ^ s1263
-  s1265 :: SBool = if s843 then s1264 else s1263
-  s1266 :: SBool = s435 ^ s1265
-  s1267 :: SBool = if s875 then s1266 else s1265
-  s1268 :: SBool = s409 ^ s1267
-  s1269 :: SBool = if s907 then s1268 else s1267
-  s1270 :: SBool = s385 ^ s1269
-  s1271 :: SBool = if s939 then s1270 else s1269
-  s1272 :: SBool = s363 ^ s1271
-  s1273 :: SBool = if s971 then s1272 else s1271
-  s1274 :: SBool = s343 ^ s1273
-  s1275 :: SBool = if s1003 then s1274 else s1273
-  s1276 :: SBool = s325 ^ s1275
-  s1277 :: SBool = if s1035 then s1276 else s1275
-  s1278 :: SBool = s309 ^ s1277
-  s1279 :: SBool = if s1067 then s1278 else s1277
-  s1280 :: SBool = s295 ^ s1279
-  s1281 :: SBool = if s1099 then s1280 else s1279
-  s1282 :: SBool = s283 ^ s1281
-  s1283 :: SBool = if s1131 then s1282 else s1281
-  s1284 :: SBool = s273 ^ s1283
-  s1285 :: SBool = if s1163 then s1284 else s1283
-  s1286 :: SBool = s265 ^ s1285
-  s1287 :: SBool = if s1195 then s1286 else s1285
-  s1288 :: SBool = s259 ^ s1287
-  s1289 :: SBool = if s1227 then s1288 else s1287
-  s1290 :: SBool = s255 ^ s1289
-  s1291 :: SBool = if s1259 then s1290 else s1289
-  s1292 :: SBool = s7 ^ s215
-  s1293 :: SBool = if s811 then s1292 else s215
-  s1294 :: SBool = s493 ^ s1293
-  s1295 :: SBool = if s843 then s1294 else s1293
-  s1296 :: SBool = s463 ^ s1295
-  s1297 :: SBool = if s875 then s1296 else s1295
-  s1298 :: SBool = s435 ^ s1297
-  s1299 :: SBool = if s907 then s1298 else s1297
-  s1300 :: SBool = s409 ^ s1299
-  s1301 :: SBool = if s939 then s1300 else s1299
-  s1302 :: SBool = s385 ^ s1301
-  s1303 :: SBool = if s971 then s1302 else s1301
-  s1304 :: SBool = s363 ^ s1303
-  s1305 :: SBool = if s1003 then s1304 else s1303
-  s1306 :: SBool = s343 ^ s1305
-  s1307 :: SBool = if s1035 then s1306 else s1305
-  s1308 :: SBool = s325 ^ s1307
-  s1309 :: SBool = if s1067 then s1308 else s1307
-  s1310 :: SBool = s309 ^ s1309
-  s1311 :: SBool = if s1099 then s1310 else s1309
-  s1312 :: SBool = s295 ^ s1311
-  s1313 :: SBool = if s1131 then s1312 else s1311
-  s1314 :: SBool = s283 ^ s1313
-  s1315 :: SBool = if s1163 then s1314 else s1313
-  s1316 :: SBool = s273 ^ s1315
-  s1317 :: SBool = if s1195 then s1316 else s1315
-  s1318 :: SBool = s265 ^ s1317
-  s1319 :: SBool = if s1227 then s1318 else s1317
-  s1320 :: SBool = s259 ^ s1319
-  s1321 :: SBool = if s1259 then s1320 else s1319
-  s1322 :: SBool = s255 ^ s1321
-  s1323 :: SBool = if s1291 then s1322 else s1321
-  s1324 :: SBool = s7 ^ s220
-  s1325 :: SBool = if s843 then s1324 else s220
-  s1326 :: SBool = s493 ^ s1325
-  s1327 :: SBool = if s875 then s1326 else s1325
-  s1328 :: SBool = s463 ^ s1327
-  s1329 :: SBool = if s907 then s1328 else s1327
-  s1330 :: SBool = s435 ^ s1329
-  s1331 :: SBool = if s939 then s1330 else s1329
-  s1332 :: SBool = s409 ^ s1331
-  s1333 :: SBool = if s971 then s1332 else s1331
-  s1334 :: SBool = s385 ^ s1333
-  s1335 :: SBool = if s1003 then s1334 else s1333
-  s1336 :: SBool = s363 ^ s1335
-  s1337 :: SBool = if s1035 then s1336 else s1335
-  s1338 :: SBool = s343 ^ s1337
-  s1339 :: SBool = if s1067 then s1338 else s1337
-  s1340 :: SBool = s325 ^ s1339
-  s1341 :: SBool = if s1099 then s1340 else s1339
-  s1342 :: SBool = s309 ^ s1341
-  s1343 :: SBool = if s1131 then s1342 else s1341
-  s1344 :: SBool = s295 ^ s1343
-  s1345 :: SBool = if s1163 then s1344 else s1343
-  s1346 :: SBool = s283 ^ s1345
-  s1347 :: SBool = if s1195 then s1346 else s1345
-  s1348 :: SBool = s273 ^ s1347
-  s1349 :: SBool = if s1227 then s1348 else s1347
-  s1350 :: SBool = s265 ^ s1349
-  s1351 :: SBool = if s1259 then s1350 else s1349
-  s1352 :: SBool = s259 ^ s1351
-  s1353 :: SBool = if s1291 then s1352 else s1351
-  s1354 :: SBool = s255 ^ s1353
-  s1355 :: SBool = if s1323 then s1354 else s1353
-  s1356 :: SBool = s7 ^ s225
-  s1357 :: SBool = if s875 then s1356 else s225
-  s1358 :: SBool = s493 ^ s1357
-  s1359 :: SBool = if s907 then s1358 else s1357
-  s1360 :: SBool = s463 ^ s1359
-  s1361 :: SBool = if s939 then s1360 else s1359
-  s1362 :: SBool = s435 ^ s1361
-  s1363 :: SBool = if s971 then s1362 else s1361
-  s1364 :: SBool = s409 ^ s1363
-  s1365 :: SBool = if s1003 then s1364 else s1363
-  s1366 :: SBool = s385 ^ s1365
-  s1367 :: SBool = if s1035 then s1366 else s1365
-  s1368 :: SBool = s363 ^ s1367
-  s1369 :: SBool = if s1067 then s1368 else s1367
-  s1370 :: SBool = s343 ^ s1369
-  s1371 :: SBool = if s1099 then s1370 else s1369
-  s1372 :: SBool = s325 ^ s1371
-  s1373 :: SBool = if s1131 then s1372 else s1371
-  s1374 :: SBool = s309 ^ s1373
-  s1375 :: SBool = if s1163 then s1374 else s1373
-  s1376 :: SBool = s295 ^ s1375
-  s1377 :: SBool = if s1195 then s1376 else s1375
-  s1378 :: SBool = s283 ^ s1377
-  s1379 :: SBool = if s1227 then s1378 else s1377
-  s1380 :: SBool = s273 ^ s1379
-  s1381 :: SBool = if s1259 then s1380 else s1379
-  s1382 :: SBool = s265 ^ s1381
-  s1383 :: SBool = if s1291 then s1382 else s1381
-  s1384 :: SBool = s259 ^ s1383
-  s1385 :: SBool = if s1323 then s1384 else s1383
-  s1386 :: SBool = s255 ^ s1385
-  s1387 :: SBool = if s1355 then s1386 else s1385
-  s1388 :: SBool = s7 ^ s230
-  s1389 :: SBool = if s907 then s1388 else s230
-  s1390 :: SBool = s493 ^ s1389
-  s1391 :: SBool = if s939 then s1390 else s1389
-  s1392 :: SBool = s463 ^ s1391
-  s1393 :: SBool = if s971 then s1392 else s1391
-  s1394 :: SBool = s435 ^ s1393
-  s1395 :: SBool = if s1003 then s1394 else s1393
-  s1396 :: SBool = s409 ^ s1395
-  s1397 :: SBool = if s1035 then s1396 else s1395
-  s1398 :: SBool = s385 ^ s1397
-  s1399 :: SBool = if s1067 then s1398 else s1397
-  s1400 :: SBool = s363 ^ s1399
-  s1401 :: SBool = if s1099 then s1400 else s1399
-  s1402 :: SBool = s343 ^ s1401
-  s1403 :: SBool = if s1131 then s1402 else s1401
-  s1404 :: SBool = s325 ^ s1403
-  s1405 :: SBool = if s1163 then s1404 else s1403
-  s1406 :: SBool = s309 ^ s1405
-  s1407 :: SBool = if s1195 then s1406 else s1405
-  s1408 :: SBool = s295 ^ s1407
-  s1409 :: SBool = if s1227 then s1408 else s1407
-  s1410 :: SBool = s283 ^ s1409
-  s1411 :: SBool = if s1259 then s1410 else s1409
-  s1412 :: SBool = s273 ^ s1411
-  s1413 :: SBool = if s1291 then s1412 else s1411
-  s1414 :: SBool = s265 ^ s1413
-  s1415 :: SBool = if s1323 then s1414 else s1413
-  s1416 :: SBool = s259 ^ s1415
-  s1417 :: SBool = if s1355 then s1416 else s1415
-  s1418 :: SBool = s255 ^ s1417
-  s1419 :: SBool = if s1387 then s1418 else s1417
-  s1420 :: SBool = s7 ^ s235
-  s1421 :: SBool = if s939 then s1420 else s235
-  s1422 :: SBool = s493 ^ s1421
-  s1423 :: SBool = if s971 then s1422 else s1421
-  s1424 :: SBool = s463 ^ s1423
-  s1425 :: SBool = if s1003 then s1424 else s1423
-  s1426 :: SBool = s435 ^ s1425
-  s1427 :: SBool = if s1035 then s1426 else s1425
-  s1428 :: SBool = s409 ^ s1427
-  s1429 :: SBool = if s1067 then s1428 else s1427
-  s1430 :: SBool = s385 ^ s1429
-  s1431 :: SBool = if s1099 then s1430 else s1429
-  s1432 :: SBool = s363 ^ s1431
-  s1433 :: SBool = if s1131 then s1432 else s1431
-  s1434 :: SBool = s343 ^ s1433
-  s1435 :: SBool = if s1163 then s1434 else s1433
-  s1436 :: SBool = s325 ^ s1435
-  s1437 :: SBool = if s1195 then s1436 else s1435
-  s1438 :: SBool = s309 ^ s1437
-  s1439 :: SBool = if s1227 then s1438 else s1437
-  s1440 :: SBool = s295 ^ s1439
-  s1441 :: SBool = if s1259 then s1440 else s1439
-  s1442 :: SBool = s283 ^ s1441
-  s1443 :: SBool = if s1291 then s1442 else s1441
-  s1444 :: SBool = s273 ^ s1443
-  s1445 :: SBool = if s1323 then s1444 else s1443
-  s1446 :: SBool = s265 ^ s1445
-  s1447 :: SBool = if s1355 then s1446 else s1445
-  s1448 :: SBool = s259 ^ s1447
-  s1449 :: SBool = if s1387 then s1448 else s1447
-  s1450 :: SBool = s255 ^ s1449
-  s1451 :: SBool = if s1419 then s1450 else s1449
-  s1452 :: SBool = s7 ^ s240
-  s1453 :: SBool = if s971 then s1452 else s240
-  s1454 :: SBool = s493 ^ s1453
-  s1455 :: SBool = if s1003 then s1454 else s1453
-  s1456 :: SBool = s463 ^ s1455
-  s1457 :: SBool = if s1035 then s1456 else s1455
-  s1458 :: SBool = s435 ^ s1457
-  s1459 :: SBool = if s1067 then s1458 else s1457
-  s1460 :: SBool = s409 ^ s1459
-  s1461 :: SBool = if s1099 then s1460 else s1459
-  s1462 :: SBool = s385 ^ s1461
-  s1463 :: SBool = if s1131 then s1462 else s1461
-  s1464 :: SBool = s363 ^ s1463
-  s1465 :: SBool = if s1163 then s1464 else s1463
-  s1466 :: SBool = s343 ^ s1465
-  s1467 :: SBool = if s1195 then s1466 else s1465
-  s1468 :: SBool = s325 ^ s1467
-  s1469 :: SBool = if s1227 then s1468 else s1467
-  s1470 :: SBool = s309 ^ s1469
-  s1471 :: SBool = if s1259 then s1470 else s1469
-  s1472 :: SBool = s295 ^ s1471
-  s1473 :: SBool = if s1291 then s1472 else s1471
-  s1474 :: SBool = s283 ^ s1473
-  s1475 :: SBool = if s1323 then s1474 else s1473
-  s1476 :: SBool = s273 ^ s1475
-  s1477 :: SBool = if s1355 then s1476 else s1475
-  s1478 :: SBool = s265 ^ s1477
-  s1479 :: SBool = if s1387 then s1478 else s1477
-  s1480 :: SBool = s259 ^ s1479
-  s1481 :: SBool = if s1419 then s1480 else s1479
-  s1482 :: SBool = s255 ^ s1481
-  s1483 :: SBool = if s1451 then s1482 else s1481
-  s1484 :: SBool = s7 ^ s245
-  s1485 :: SBool = if s1003 then s1484 else s245
-  s1486 :: SBool = s493 ^ s1485
-  s1487 :: SBool = if s1035 then s1486 else s1485
-  s1488 :: SBool = s463 ^ s1487
-  s1489 :: SBool = if s1067 then s1488 else s1487
-  s1490 :: SBool = s435 ^ s1489
-  s1491 :: SBool = if s1099 then s1490 else s1489
-  s1492 :: SBool = s409 ^ s1491
-  s1493 :: SBool = if s1131 then s1492 else s1491
-  s1494 :: SBool = s385 ^ s1493
-  s1495 :: SBool = if s1163 then s1494 else s1493
-  s1496 :: SBool = s363 ^ s1495
-  s1497 :: SBool = if s1195 then s1496 else s1495
-  s1498 :: SBool = s343 ^ s1497
-  s1499 :: SBool = if s1227 then s1498 else s1497
-  s1500 :: SBool = s325 ^ s1499
-  s1501 :: SBool = if s1259 then s1500 else s1499
-  s1502 :: SBool = s309 ^ s1501
-  s1503 :: SBool = if s1291 then s1502 else s1501
-  s1504 :: SBool = s295 ^ s1503
-  s1505 :: SBool = if s1323 then s1504 else s1503
-  s1506 :: SBool = s283 ^ s1505
-  s1507 :: SBool = if s1355 then s1506 else s1505
-  s1508 :: SBool = s273 ^ s1507
-  s1509 :: SBool = if s1387 then s1508 else s1507
-  s1510 :: SBool = s265 ^ s1509
-  s1511 :: SBool = if s1419 then s1510 else s1509
-  s1512 :: SBool = s259 ^ s1511
-  s1513 :: SBool = if s1451 then s1512 else s1511
-  s1514 :: SBool = s255 ^ s1513
-  s1515 :: SBool = if s1483 then s1514 else s1513
-  s1516 :: SBool = s7 ^ s250
-  s1517 :: SBool = if s1035 then s1516 else s250
-  s1518 :: SBool = s493 ^ s1517
-  s1519 :: SBool = if s1067 then s1518 else s1517
-  s1520 :: SBool = s463 ^ s1519
-  s1521 :: SBool = if s1099 then s1520 else s1519
-  s1522 :: SBool = s435 ^ s1521
-  s1523 :: SBool = if s1131 then s1522 else s1521
-  s1524 :: SBool = s409 ^ s1523
-  s1525 :: SBool = if s1163 then s1524 else s1523
-  s1526 :: SBool = s385 ^ s1525
-  s1527 :: SBool = if s1195 then s1526 else s1525
-  s1528 :: SBool = s363 ^ s1527
-  s1529 :: SBool = if s1227 then s1528 else s1527
-  s1530 :: SBool = s343 ^ s1529
-  s1531 :: SBool = if s1259 then s1530 else s1529
-  s1532 :: SBool = s325 ^ s1531
-  s1533 :: SBool = if s1291 then s1532 else s1531
-  s1534 :: SBool = s309 ^ s1533
-  s1535 :: SBool = if s1323 then s1534 else s1533
-  s1536 :: SBool = s295 ^ s1535
-  s1537 :: SBool = if s1355 then s1536 else s1535
-  s1538 :: SBool = s283 ^ s1537
-  s1539 :: SBool = if s1387 then s1538 else s1537
-  s1540 :: SBool = s273 ^ s1539
-  s1541 :: SBool = if s1419 then s1540 else s1539
-  s1542 :: SBool = s265 ^ s1541
-  s1543 :: SBool = if s1451 then s1542 else s1541
-  s1544 :: SBool = s259 ^ s1543
-  s1545 :: SBool = if s1483 then s1544 else s1543
-  s1546 :: SBool = s255 ^ s1545
-  s1547 :: SBool = if s1515 then s1546 else s1545
-  s1548 :: SBool = if s1067 then s7 else s_2
-  s1549 :: SBool = s493 ^ s1548
-  s1550 :: SBool = if s1099 then s1549 else s1548
-  s1551 :: SBool = s463 ^ s1550
-  s1552 :: SBool = if s1131 then s1551 else s1550
-  s1553 :: SBool = s435 ^ s1552
-  s1554 :: SBool = if s1163 then s1553 else s1552
-  s1555 :: SBool = s409 ^ s1554
-  s1556 :: SBool = if s1195 then s1555 else s1554
-  s1557 :: SBool = s385 ^ s1556
-  s1558 :: SBool = if s1227 then s1557 else s1556
-  s1559 :: SBool = s363 ^ s1558
-  s1560 :: SBool = if s1259 then s1559 else s1558
-  s1561 :: SBool = s343 ^ s1560
-  s1562 :: SBool = if s1291 then s1561 else s1560
-  s1563 :: SBool = s325 ^ s1562
-  s1564 :: SBool = if s1323 then s1563 else s1562
-  s1565 :: SBool = s309 ^ s1564
-  s1566 :: SBool = if s1355 then s1565 else s1564
-  s1567 :: SBool = s295 ^ s1566
-  s1568 :: SBool = if s1387 then s1567 else s1566
-  s1569 :: SBool = s283 ^ s1568
-  s1570 :: SBool = if s1419 then s1569 else s1568
-  s1571 :: SBool = s273 ^ s1570
-  s1572 :: SBool = if s1451 then s1571 else s1570
-  s1573 :: SBool = s265 ^ s1572
-  s1574 :: SBool = if s1483 then s1573 else s1572
-  s1575 :: SBool = s259 ^ s1574
-  s1576 :: SBool = if s1515 then s1575 else s1574
-  s1577 :: SBool = s255 ^ s1576
-  s1578 :: SBool = if s1547 then s1577 else s1576
-  s1579 :: SBool = s22 ^ s255
-  s1580 :: SBool = if s16 then s1579 else s22
-  s1581 :: SBool = s27 ^ s259
-  s1582 :: SBool = if s16 then s1581 else s27
-  s1583 :: SBool = s255 ^ s1582
-  s1584 :: SBool = if s1580 then s1583 else s1582
-  s1585 :: SBool = s32 ^ s265
-  s1586 :: SBool = if s16 then s1585 else s32
-  s1587 :: SBool = s259 ^ s1586
-  s1588 :: SBool = if s1580 then s1587 else s1586
-  s1589 :: SBool = s255 ^ s1588
-  s1590 :: SBool = if s1584 then s1589 else s1588
-  s1591 :: SBool = s37 ^ s273
-  s1592 :: SBool = if s16 then s1591 else s37
-  s1593 :: SBool = s265 ^ s1592
-  s1594 :: SBool = if s1580 then s1593 else s1592
-  s1595 :: SBool = s259 ^ s1594
-  s1596 :: SBool = if s1584 then s1595 else s1594
-  s1597 :: SBool = s255 ^ s1596
-  s1598 :: SBool = if s1590 then s1597 else s1596
-  s1599 :: SBool = s42 ^ s283
-  s1600 :: SBool = if s16 then s1599 else s42
-  s1601 :: SBool = s273 ^ s1600
-  s1602 :: SBool = if s1580 then s1601 else s1600
-  s1603 :: SBool = s265 ^ s1602
-  s1604 :: SBool = if s1584 then s1603 else s1602
-  s1605 :: SBool = s259 ^ s1604
-  s1606 :: SBool = if s1590 then s1605 else s1604
-  s1607 :: SBool = s255 ^ s1606
-  s1608 :: SBool = if s1598 then s1607 else s1606
-  s1609 :: SBool = s47 ^ s295
-  s1610 :: SBool = if s16 then s1609 else s47
-  s1611 :: SBool = s283 ^ s1610
-  s1612 :: SBool = if s1580 then s1611 else s1610
-  s1613 :: SBool = s273 ^ s1612
-  s1614 :: SBool = if s1584 then s1613 else s1612
-  s1615 :: SBool = s265 ^ s1614
-  s1616 :: SBool = if s1590 then s1615 else s1614
-  s1617 :: SBool = s259 ^ s1616
-  s1618 :: SBool = if s1598 then s1617 else s1616
-  s1619 :: SBool = s255 ^ s1618
-  s1620 :: SBool = if s1608 then s1619 else s1618
-  s1621 :: SBool = s52 ^ s309
-  s1622 :: SBool = if s16 then s1621 else s52
-  s1623 :: SBool = s295 ^ s1622
-  s1624 :: SBool = if s1580 then s1623 else s1622
-  s1625 :: SBool = s283 ^ s1624
-  s1626 :: SBool = if s1584 then s1625 else s1624
-  s1627 :: SBool = s273 ^ s1626
-  s1628 :: SBool = if s1590 then s1627 else s1626
-  s1629 :: SBool = s265 ^ s1628
-  s1630 :: SBool = if s1598 then s1629 else s1628
-  s1631 :: SBool = s259 ^ s1630
-  s1632 :: SBool = if s1608 then s1631 else s1630
-  s1633 :: SBool = s255 ^ s1632
-  s1634 :: SBool = if s1620 then s1633 else s1632
-  s1635 :: SBool = s57 ^ s325
-  s1636 :: SBool = if s16 then s1635 else s57
-  s1637 :: SBool = s309 ^ s1636
-  s1638 :: SBool = if s1580 then s1637 else s1636
-  s1639 :: SBool = s295 ^ s1638
-  s1640 :: SBool = if s1584 then s1639 else s1638
-  s1641 :: SBool = s283 ^ s1640
-  s1642 :: SBool = if s1590 then s1641 else s1640
-  s1643 :: SBool = s273 ^ s1642
-  s1644 :: SBool = if s1598 then s1643 else s1642
-  s1645 :: SBool = s265 ^ s1644
-  s1646 :: SBool = if s1608 then s1645 else s1644
-  s1647 :: SBool = s259 ^ s1646
-  s1648 :: SBool = if s1620 then s1647 else s1646
-  s1649 :: SBool = s255 ^ s1648
-  s1650 :: SBool = if s1634 then s1649 else s1648
-  s1651 :: SBool = s62 ^ s343
-  s1652 :: SBool = if s16 then s1651 else s62
-  s1653 :: SBool = s325 ^ s1652
-  s1654 :: SBool = if s1580 then s1653 else s1652
-  s1655 :: SBool = s309 ^ s1654
-  s1656 :: SBool = if s1584 then s1655 else s1654
-  s1657 :: SBool = s295 ^ s1656
-  s1658 :: SBool = if s1590 then s1657 else s1656
-  s1659 :: SBool = s283 ^ s1658
-  s1660 :: SBool = if s1598 then s1659 else s1658
-  s1661 :: SBool = s273 ^ s1660
-  s1662 :: SBool = if s1608 then s1661 else s1660
-  s1663 :: SBool = s265 ^ s1662
-  s1664 :: SBool = if s1620 then s1663 else s1662
-  s1665 :: SBool = s259 ^ s1664
-  s1666 :: SBool = if s1634 then s1665 else s1664
-  s1667 :: SBool = s255 ^ s1666
-  s1668 :: SBool = if s1650 then s1667 else s1666
-  s1669 :: SBool = s67 ^ s363
-  s1670 :: SBool = if s16 then s1669 else s67
-  s1671 :: SBool = s343 ^ s1670
-  s1672 :: SBool = if s1580 then s1671 else s1670
-  s1673 :: SBool = s325 ^ s1672
-  s1674 :: SBool = if s1584 then s1673 else s1672
-  s1675 :: SBool = s309 ^ s1674
-  s1676 :: SBool = if s1590 then s1675 else s1674
-  s1677 :: SBool = s295 ^ s1676
-  s1678 :: SBool = if s1598 then s1677 else s1676
-  s1679 :: SBool = s283 ^ s1678
-  s1680 :: SBool = if s1608 then s1679 else s1678
-  s1681 :: SBool = s273 ^ s1680
-  s1682 :: SBool = if s1620 then s1681 else s1680
-  s1683 :: SBool = s265 ^ s1682
-  s1684 :: SBool = if s1634 then s1683 else s1682
-  s1685 :: SBool = s259 ^ s1684
-  s1686 :: SBool = if s1650 then s1685 else s1684
-  s1687 :: SBool = s255 ^ s1686
-  s1688 :: SBool = if s1668 then s1687 else s1686
-  s1689 :: SBool = s72 ^ s385
-  s1690 :: SBool = if s16 then s1689 else s72
-  s1691 :: SBool = s363 ^ s1690
-  s1692 :: SBool = if s1580 then s1691 else s1690
-  s1693 :: SBool = s343 ^ s1692
-  s1694 :: SBool = if s1584 then s1693 else s1692
-  s1695 :: SBool = s325 ^ s1694
-  s1696 :: SBool = if s1590 then s1695 else s1694
-  s1697 :: SBool = s309 ^ s1696
-  s1698 :: SBool = if s1598 then s1697 else s1696
-  s1699 :: SBool = s295 ^ s1698
-  s1700 :: SBool = if s1608 then s1699 else s1698
-  s1701 :: SBool = s283 ^ s1700
-  s1702 :: SBool = if s1620 then s1701 else s1700
-  s1703 :: SBool = s273 ^ s1702
-  s1704 :: SBool = if s1634 then s1703 else s1702
-  s1705 :: SBool = s265 ^ s1704
-  s1706 :: SBool = if s1650 then s1705 else s1704
-  s1707 :: SBool = s259 ^ s1706
-  s1708 :: SBool = if s1668 then s1707 else s1706
-  s1709 :: SBool = s255 ^ s1708
-  s1710 :: SBool = if s1688 then s1709 else s1708
-  s1711 :: SBool = s77 ^ s409
-  s1712 :: SBool = if s16 then s1711 else s77
-  s1713 :: SBool = s385 ^ s1712
-  s1714 :: SBool = if s1580 then s1713 else s1712
-  s1715 :: SBool = s363 ^ s1714
-  s1716 :: SBool = if s1584 then s1715 else s1714
-  s1717 :: SBool = s343 ^ s1716
-  s1718 :: SBool = if s1590 then s1717 else s1716
-  s1719 :: SBool = s325 ^ s1718
-  s1720 :: SBool = if s1598 then s1719 else s1718
-  s1721 :: SBool = s309 ^ s1720
-  s1722 :: SBool = if s1608 then s1721 else s1720
-  s1723 :: SBool = s295 ^ s1722
-  s1724 :: SBool = if s1620 then s1723 else s1722
-  s1725 :: SBool = s283 ^ s1724
-  s1726 :: SBool = if s1634 then s1725 else s1724
-  s1727 :: SBool = s273 ^ s1726
-  s1728 :: SBool = if s1650 then s1727 else s1726
-  s1729 :: SBool = s265 ^ s1728
-  s1730 :: SBool = if s1668 then s1729 else s1728
-  s1731 :: SBool = s259 ^ s1730
-  s1732 :: SBool = if s1688 then s1731 else s1730
-  s1733 :: SBool = s255 ^ s1732
-  s1734 :: SBool = if s1710 then s1733 else s1732
-  s1735 :: SBool = s82 ^ s435
-  s1736 :: SBool = if s16 then s1735 else s82
-  s1737 :: SBool = s409 ^ s1736
-  s1738 :: SBool = if s1580 then s1737 else s1736
-  s1739 :: SBool = s385 ^ s1738
-  s1740 :: SBool = if s1584 then s1739 else s1738
-  s1741 :: SBool = s363 ^ s1740
-  s1742 :: SBool = if s1590 then s1741 else s1740
-  s1743 :: SBool = s343 ^ s1742
-  s1744 :: SBool = if s1598 then s1743 else s1742
-  s1745 :: SBool = s325 ^ s1744
-  s1746 :: SBool = if s1608 then s1745 else s1744
-  s1747 :: SBool = s309 ^ s1746
-  s1748 :: SBool = if s1620 then s1747 else s1746
-  s1749 :: SBool = s295 ^ s1748
-  s1750 :: SBool = if s1634 then s1749 else s1748
-  s1751 :: SBool = s283 ^ s1750
-  s1752 :: SBool = if s1650 then s1751 else s1750
-  s1753 :: SBool = s273 ^ s1752
-  s1754 :: SBool = if s1668 then s1753 else s1752
-  s1755 :: SBool = s265 ^ s1754
-  s1756 :: SBool = if s1688 then s1755 else s1754
-  s1757 :: SBool = s259 ^ s1756
-  s1758 :: SBool = if s1710 then s1757 else s1756
-  s1759 :: SBool = s255 ^ s1758
-  s1760 :: SBool = if s1734 then s1759 else s1758
-  s1761 :: SBool = s87 ^ s463
-  s1762 :: SBool = if s16 then s1761 else s87
-  s1763 :: SBool = s435 ^ s1762
-  s1764 :: SBool = if s1580 then s1763 else s1762
-  s1765 :: SBool = s409 ^ s1764
-  s1766 :: SBool = if s1584 then s1765 else s1764
-  s1767 :: SBool = s385 ^ s1766
-  s1768 :: SBool = if s1590 then s1767 else s1766
-  s1769 :: SBool = s363 ^ s1768
-  s1770 :: SBool = if s1598 then s1769 else s1768
-  s1771 :: SBool = s343 ^ s1770
-  s1772 :: SBool = if s1608 then s1771 else s1770
-  s1773 :: SBool = s325 ^ s1772
-  s1774 :: SBool = if s1620 then s1773 else s1772
-  s1775 :: SBool = s309 ^ s1774
-  s1776 :: SBool = if s1634 then s1775 else s1774
-  s1777 :: SBool = s295 ^ s1776
-  s1778 :: SBool = if s1650 then s1777 else s1776
-  s1779 :: SBool = s283 ^ s1778
-  s1780 :: SBool = if s1668 then s1779 else s1778
-  s1781 :: SBool = s273 ^ s1780
-  s1782 :: SBool = if s1688 then s1781 else s1780
-  s1783 :: SBool = s265 ^ s1782
-  s1784 :: SBool = if s1710 then s1783 else s1782
-  s1785 :: SBool = s259 ^ s1784
-  s1786 :: SBool = if s1734 then s1785 else s1784
-  s1787 :: SBool = s255 ^ s1786
-  s1788 :: SBool = if s1760 then s1787 else s1786
-  s1789 :: SBool = s92 ^ s493
-  s1790 :: SBool = if s16 then s1789 else s92
-  s1791 :: SBool = s463 ^ s1790
-  s1792 :: SBool = if s1580 then s1791 else s1790
-  s1793 :: SBool = s435 ^ s1792
-  s1794 :: SBool = if s1584 then s1793 else s1792
-  s1795 :: SBool = s409 ^ s1794
-  s1796 :: SBool = if s1590 then s1795 else s1794
-  s1797 :: SBool = s385 ^ s1796
-  s1798 :: SBool = if s1598 then s1797 else s1796
-  s1799 :: SBool = s363 ^ s1798
-  s1800 :: SBool = if s1608 then s1799 else s1798
-  s1801 :: SBool = s343 ^ s1800
-  s1802 :: SBool = if s1620 then s1801 else s1800
-  s1803 :: SBool = s325 ^ s1802
-  s1804 :: SBool = if s1634 then s1803 else s1802
-  s1805 :: SBool = s309 ^ s1804
-  s1806 :: SBool = if s1650 then s1805 else s1804
-  s1807 :: SBool = s295 ^ s1806
-  s1808 :: SBool = if s1668 then s1807 else s1806
-  s1809 :: SBool = s283 ^ s1808
-  s1810 :: SBool = if s1688 then s1809 else s1808
-  s1811 :: SBool = s273 ^ s1810
-  s1812 :: SBool = if s1710 then s1811 else s1810
-  s1813 :: SBool = s265 ^ s1812
-  s1814 :: SBool = if s1734 then s1813 else s1812
-  s1815 :: SBool = s259 ^ s1814
-  s1816 :: SBool = if s1760 then s1815 else s1814
-  s1817 :: SBool = s255 ^ s1816
-  s1818 :: SBool = if s1788 then s1817 else s1816
-  s1819 :: SBool = s7 ^ s97
-  s1820 :: SBool = if s16 then s1819 else s97
-  s1821 :: SBool = s493 ^ s1820
-  s1822 :: SBool = if s1580 then s1821 else s1820
-  s1823 :: SBool = s463 ^ s1822
-  s1824 :: SBool = if s1584 then s1823 else s1822
-  s1825 :: SBool = s435 ^ s1824
-  s1826 :: SBool = if s1590 then s1825 else s1824
-  s1827 :: SBool = s409 ^ s1826
-  s1828 :: SBool = if s1598 then s1827 else s1826
-  s1829 :: SBool = s385 ^ s1828
-  s1830 :: SBool = if s1608 then s1829 else s1828
-  s1831 :: SBool = s363 ^ s1830
-  s1832 :: SBool = if s1620 then s1831 else s1830
-  s1833 :: SBool = s343 ^ s1832
-  s1834 :: SBool = if s1634 then s1833 else s1832
-  s1835 :: SBool = s325 ^ s1834
-  s1836 :: SBool = if s1650 then s1835 else s1834
-  s1837 :: SBool = s309 ^ s1836
-  s1838 :: SBool = if s1668 then s1837 else s1836
-  s1839 :: SBool = s295 ^ s1838
-  s1840 :: SBool = if s1688 then s1839 else s1838
-  s1841 :: SBool = s283 ^ s1840
-  s1842 :: SBool = if s1710 then s1841 else s1840
-  s1843 :: SBool = s273 ^ s1842
-  s1844 :: SBool = if s1734 then s1843 else s1842
-  s1845 :: SBool = s265 ^ s1844
-  s1846 :: SBool = if s1760 then s1845 else s1844
-  s1847 :: SBool = s259 ^ s1846
-  s1848 :: SBool = if s1788 then s1847 else s1846
-  s1849 :: SBool = s255 ^ s1848
-  s1850 :: SBool = if s1818 then s1849 else s1848
-  s1851 :: SBool = s7 ^ s102
-  s1852 :: SBool = if s1580 then s1851 else s102
-  s1853 :: SBool = s493 ^ s1852
-  s1854 :: SBool = if s1584 then s1853 else s1852
-  s1855 :: SBool = s463 ^ s1854
-  s1856 :: SBool = if s1590 then s1855 else s1854
-  s1857 :: SBool = s435 ^ s1856
-  s1858 :: SBool = if s1598 then s1857 else s1856
-  s1859 :: SBool = s409 ^ s1858
-  s1860 :: SBool = if s1608 then s1859 else s1858
-  s1861 :: SBool = s385 ^ s1860
-  s1862 :: SBool = if s1620 then s1861 else s1860
-  s1863 :: SBool = s363 ^ s1862
-  s1864 :: SBool = if s1634 then s1863 else s1862
-  s1865 :: SBool = s343 ^ s1864
-  s1866 :: SBool = if s1650 then s1865 else s1864
-  s1867 :: SBool = s325 ^ s1866
-  s1868 :: SBool = if s1668 then s1867 else s1866
-  s1869 :: SBool = s309 ^ s1868
-  s1870 :: SBool = if s1688 then s1869 else s1868
-  s1871 :: SBool = s295 ^ s1870
-  s1872 :: SBool = if s1710 then s1871 else s1870
-  s1873 :: SBool = s283 ^ s1872
-  s1874 :: SBool = if s1734 then s1873 else s1872
-  s1875 :: SBool = s273 ^ s1874
-  s1876 :: SBool = if s1760 then s1875 else s1874
-  s1877 :: SBool = s265 ^ s1876
-  s1878 :: SBool = if s1788 then s1877 else s1876
-  s1879 :: SBool = s259 ^ s1878
-  s1880 :: SBool = if s1818 then s1879 else s1878
-  s1881 :: SBool = s255 ^ s1880
-  s1882 :: SBool = if s1850 then s1881 else s1880
-  s1883 :: SBool = s7 ^ s107
-  s1884 :: SBool = if s1584 then s1883 else s107
-  s1885 :: SBool = s493 ^ s1884
-  s1886 :: SBool = if s1590 then s1885 else s1884
-  s1887 :: SBool = s463 ^ s1886
-  s1888 :: SBool = if s1598 then s1887 else s1886
-  s1889 :: SBool = s435 ^ s1888
-  s1890 :: SBool = if s1608 then s1889 else s1888
-  s1891 :: SBool = s409 ^ s1890
-  s1892 :: SBool = if s1620 then s1891 else s1890
-  s1893 :: SBool = s385 ^ s1892
-  s1894 :: SBool = if s1634 then s1893 else s1892
-  s1895 :: SBool = s363 ^ s1894
-  s1896 :: SBool = if s1650 then s1895 else s1894
-  s1897 :: SBool = s343 ^ s1896
-  s1898 :: SBool = if s1668 then s1897 else s1896
-  s1899 :: SBool = s325 ^ s1898
-  s1900 :: SBool = if s1688 then s1899 else s1898
-  s1901 :: SBool = s309 ^ s1900
-  s1902 :: SBool = if s1710 then s1901 else s1900
-  s1903 :: SBool = s295 ^ s1902
-  s1904 :: SBool = if s1734 then s1903 else s1902
-  s1905 :: SBool = s283 ^ s1904
-  s1906 :: SBool = if s1760 then s1905 else s1904
-  s1907 :: SBool = s273 ^ s1906
-  s1908 :: SBool = if s1788 then s1907 else s1906
-  s1909 :: SBool = s265 ^ s1908
-  s1910 :: SBool = if s1818 then s1909 else s1908
-  s1911 :: SBool = s259 ^ s1910
-  s1912 :: SBool = if s1850 then s1911 else s1910
-  s1913 :: SBool = s255 ^ s1912
-  s1914 :: SBool = if s1882 then s1913 else s1912
-  s1915 :: SBool = s7 ^ s112
-  s1916 :: SBool = if s1590 then s1915 else s112
-  s1917 :: SBool = s493 ^ s1916
-  s1918 :: SBool = if s1598 then s1917 else s1916
-  s1919 :: SBool = s463 ^ s1918
-  s1920 :: SBool = if s1608 then s1919 else s1918
-  s1921 :: SBool = s435 ^ s1920
-  s1922 :: SBool = if s1620 then s1921 else s1920
-  s1923 :: SBool = s409 ^ s1922
-  s1924 :: SBool = if s1634 then s1923 else s1922
-  s1925 :: SBool = s385 ^ s1924
-  s1926 :: SBool = if s1650 then s1925 else s1924
-  s1927 :: SBool = s363 ^ s1926
-  s1928 :: SBool = if s1668 then s1927 else s1926
-  s1929 :: SBool = s343 ^ s1928
-  s1930 :: SBool = if s1688 then s1929 else s1928
-  s1931 :: SBool = s325 ^ s1930
-  s1932 :: SBool = if s1710 then s1931 else s1930
-  s1933 :: SBool = s309 ^ s1932
-  s1934 :: SBool = if s1734 then s1933 else s1932
-  s1935 :: SBool = s295 ^ s1934
-  s1936 :: SBool = if s1760 then s1935 else s1934
-  s1937 :: SBool = s283 ^ s1936
-  s1938 :: SBool = if s1788 then s1937 else s1936
-  s1939 :: SBool = s273 ^ s1938
-  s1940 :: SBool = if s1818 then s1939 else s1938
-  s1941 :: SBool = s265 ^ s1940
-  s1942 :: SBool = if s1850 then s1941 else s1940
-  s1943 :: SBool = s259 ^ s1942
-  s1944 :: SBool = if s1882 then s1943 else s1942
-  s1945 :: SBool = s255 ^ s1944
-  s1946 :: SBool = if s1914 then s1945 else s1944
-  s1947 :: SBool = s7 ^ s117
-  s1948 :: SBool = if s1598 then s1947 else s117
-  s1949 :: SBool = s493 ^ s1948
-  s1950 :: SBool = if s1608 then s1949 else s1948
-  s1951 :: SBool = s463 ^ s1950
-  s1952 :: SBool = if s1620 then s1951 else s1950
-  s1953 :: SBool = s435 ^ s1952
-  s1954 :: SBool = if s1634 then s1953 else s1952
-  s1955 :: SBool = s409 ^ s1954
-  s1956 :: SBool = if s1650 then s1955 else s1954
-  s1957 :: SBool = s385 ^ s1956
-  s1958 :: SBool = if s1668 then s1957 else s1956
-  s1959 :: SBool = s363 ^ s1958
-  s1960 :: SBool = if s1688 then s1959 else s1958
-  s1961 :: SBool = s343 ^ s1960
-  s1962 :: SBool = if s1710 then s1961 else s1960
-  s1963 :: SBool = s325 ^ s1962
-  s1964 :: SBool = if s1734 then s1963 else s1962
-  s1965 :: SBool = s309 ^ s1964
-  s1966 :: SBool = if s1760 then s1965 else s1964
-  s1967 :: SBool = s295 ^ s1966
-  s1968 :: SBool = if s1788 then s1967 else s1966
-  s1969 :: SBool = s283 ^ s1968
-  s1970 :: SBool = if s1818 then s1969 else s1968
-  s1971 :: SBool = s273 ^ s1970
-  s1972 :: SBool = if s1850 then s1971 else s1970
-  s1973 :: SBool = s265 ^ s1972
-  s1974 :: SBool = if s1882 then s1973 else s1972
-  s1975 :: SBool = s259 ^ s1974
-  s1976 :: SBool = if s1914 then s1975 else s1974
-  s1977 :: SBool = s255 ^ s1976
-  s1978 :: SBool = if s1946 then s1977 else s1976
-  s1979 :: SBool = s7 ^ s122
-  s1980 :: SBool = if s1608 then s1979 else s122
-  s1981 :: SBool = s493 ^ s1980
-  s1982 :: SBool = if s1620 then s1981 else s1980
-  s1983 :: SBool = s463 ^ s1982
-  s1984 :: SBool = if s1634 then s1983 else s1982
-  s1985 :: SBool = s435 ^ s1984
-  s1986 :: SBool = if s1650 then s1985 else s1984
-  s1987 :: SBool = s409 ^ s1986
-  s1988 :: SBool = if s1668 then s1987 else s1986
-  s1989 :: SBool = s385 ^ s1988
-  s1990 :: SBool = if s1688 then s1989 else s1988
-  s1991 :: SBool = s363 ^ s1990
-  s1992 :: SBool = if s1710 then s1991 else s1990
-  s1993 :: SBool = s343 ^ s1992
-  s1994 :: SBool = if s1734 then s1993 else s1992
-  s1995 :: SBool = s325 ^ s1994
-  s1996 :: SBool = if s1760 then s1995 else s1994
-  s1997 :: SBool = s309 ^ s1996
-  s1998 :: SBool = if s1788 then s1997 else s1996
-  s1999 :: SBool = s295 ^ s1998
-  s2000 :: SBool = if s1818 then s1999 else s1998
-  s2001 :: SBool = s283 ^ s2000
-  s2002 :: SBool = if s1850 then s2001 else s2000
-  s2003 :: SBool = s273 ^ s2002
-  s2004 :: SBool = if s1882 then s2003 else s2002
-  s2005 :: SBool = s265 ^ s2004
-  s2006 :: SBool = if s1914 then s2005 else s2004
-  s2007 :: SBool = s259 ^ s2006
-  s2008 :: SBool = if s1946 then s2007 else s2006
-  s2009 :: SBool = s255 ^ s2008
-  s2010 :: SBool = if s1978 then s2009 else s2008
-  s2011 :: SBool = s7 ^ s127
-  s2012 :: SBool = if s1620 then s2011 else s127
-  s2013 :: SBool = s493 ^ s2012
-  s2014 :: SBool = if s1634 then s2013 else s2012
-  s2015 :: SBool = s463 ^ s2014
-  s2016 :: SBool = if s1650 then s2015 else s2014
-  s2017 :: SBool = s435 ^ s2016
-  s2018 :: SBool = if s1668 then s2017 else s2016
-  s2019 :: SBool = s409 ^ s2018
-  s2020 :: SBool = if s1688 then s2019 else s2018
-  s2021 :: SBool = s385 ^ s2020
-  s2022 :: SBool = if s1710 then s2021 else s2020
-  s2023 :: SBool = s363 ^ s2022
-  s2024 :: SBool = if s1734 then s2023 else s2022
-  s2025 :: SBool = s343 ^ s2024
-  s2026 :: SBool = if s1760 then s2025 else s2024
-  s2027 :: SBool = s325 ^ s2026
-  s2028 :: SBool = if s1788 then s2027 else s2026
-  s2029 :: SBool = s309 ^ s2028
-  s2030 :: SBool = if s1818 then s2029 else s2028
-  s2031 :: SBool = s295 ^ s2030
-  s2032 :: SBool = if s1850 then s2031 else s2030
-  s2033 :: SBool = s283 ^ s2032
-  s2034 :: SBool = if s1882 then s2033 else s2032
-  s2035 :: SBool = s273 ^ s2034
-  s2036 :: SBool = if s1914 then s2035 else s2034
-  s2037 :: SBool = s265 ^ s2036
-  s2038 :: SBool = if s1946 then s2037 else s2036
-  s2039 :: SBool = s259 ^ s2038
-  s2040 :: SBool = if s1978 then s2039 else s2038
-  s2041 :: SBool = s255 ^ s2040
-  s2042 :: SBool = if s2010 then s2041 else s2040
-  s2043 :: SBool = s7 ^ s132
-  s2044 :: SBool = if s1634 then s2043 else s132
-  s2045 :: SBool = s493 ^ s2044
-  s2046 :: SBool = if s1650 then s2045 else s2044
-  s2047 :: SBool = s463 ^ s2046
-  s2048 :: SBool = if s1668 then s2047 else s2046
-  s2049 :: SBool = s435 ^ s2048
-  s2050 :: SBool = if s1688 then s2049 else s2048
-  s2051 :: SBool = s409 ^ s2050
-  s2052 :: SBool = if s1710 then s2051 else s2050
-  s2053 :: SBool = s385 ^ s2052
-  s2054 :: SBool = if s1734 then s2053 else s2052
-  s2055 :: SBool = s363 ^ s2054
-  s2056 :: SBool = if s1760 then s2055 else s2054
-  s2057 :: SBool = s343 ^ s2056
-  s2058 :: SBool = if s1788 then s2057 else s2056
-  s2059 :: SBool = s325 ^ s2058
-  s2060 :: SBool = if s1818 then s2059 else s2058
-  s2061 :: SBool = s309 ^ s2060
-  s2062 :: SBool = if s1850 then s2061 else s2060
-  s2063 :: SBool = s295 ^ s2062
-  s2064 :: SBool = if s1882 then s2063 else s2062
-  s2065 :: SBool = s283 ^ s2064
-  s2066 :: SBool = if s1914 then s2065 else s2064
-  s2067 :: SBool = s273 ^ s2066
-  s2068 :: SBool = if s1946 then s2067 else s2066
-  s2069 :: SBool = s265 ^ s2068
-  s2070 :: SBool = if s1978 then s2069 else s2068
-  s2071 :: SBool = s259 ^ s2070
-  s2072 :: SBool = if s2010 then s2071 else s2070
-  s2073 :: SBool = s255 ^ s2072
-  s2074 :: SBool = if s2042 then s2073 else s2072
-  s2075 :: SBool = s7 ^ s137
-  s2076 :: SBool = if s1650 then s2075 else s137
-  s2077 :: SBool = s493 ^ s2076
-  s2078 :: SBool = if s1668 then s2077 else s2076
-  s2079 :: SBool = s463 ^ s2078
-  s2080 :: SBool = if s1688 then s2079 else s2078
-  s2081 :: SBool = s435 ^ s2080
-  s2082 :: SBool = if s1710 then s2081 else s2080
-  s2083 :: SBool = s409 ^ s2082
-  s2084 :: SBool = if s1734 then s2083 else s2082
-  s2085 :: SBool = s385 ^ s2084
-  s2086 :: SBool = if s1760 then s2085 else s2084
-  s2087 :: SBool = s363 ^ s2086
-  s2088 :: SBool = if s1788 then s2087 else s2086
-  s2089 :: SBool = s343 ^ s2088
-  s2090 :: SBool = if s1818 then s2089 else s2088
-  s2091 :: SBool = s325 ^ s2090
-  s2092 :: SBool = if s1850 then s2091 else s2090
-  s2093 :: SBool = s309 ^ s2092
-  s2094 :: SBool = if s1882 then s2093 else s2092
-  s2095 :: SBool = s295 ^ s2094
-  s2096 :: SBool = if s1914 then s2095 else s2094
-  s2097 :: SBool = s283 ^ s2096
-  s2098 :: SBool = if s1946 then s2097 else s2096
-  s2099 :: SBool = s273 ^ s2098
-  s2100 :: SBool = if s1978 then s2099 else s2098
-  s2101 :: SBool = s265 ^ s2100
-  s2102 :: SBool = if s2010 then s2101 else s2100
-  s2103 :: SBool = s259 ^ s2102
-  s2104 :: SBool = if s2042 then s2103 else s2102
-  s2105 :: SBool = s255 ^ s2104
-  s2106 :: SBool = if s2074 then s2105 else s2104
-  s2107 :: SBool = s7 ^ s142
-  s2108 :: SBool = if s1668 then s2107 else s142
-  s2109 :: SBool = s493 ^ s2108
-  s2110 :: SBool = if s1688 then s2109 else s2108
-  s2111 :: SBool = s463 ^ s2110
-  s2112 :: SBool = if s1710 then s2111 else s2110
-  s2113 :: SBool = s435 ^ s2112
-  s2114 :: SBool = if s1734 then s2113 else s2112
-  s2115 :: SBool = s409 ^ s2114
-  s2116 :: SBool = if s1760 then s2115 else s2114
-  s2117 :: SBool = s385 ^ s2116
-  s2118 :: SBool = if s1788 then s2117 else s2116
-  s2119 :: SBool = s363 ^ s2118
-  s2120 :: SBool = if s1818 then s2119 else s2118
-  s2121 :: SBool = s343 ^ s2120
-  s2122 :: SBool = if s1850 then s2121 else s2120
-  s2123 :: SBool = s325 ^ s2122
-  s2124 :: SBool = if s1882 then s2123 else s2122
-  s2125 :: SBool = s309 ^ s2124
-  s2126 :: SBool = if s1914 then s2125 else s2124
-  s2127 :: SBool = s295 ^ s2126
-  s2128 :: SBool = if s1946 then s2127 else s2126
-  s2129 :: SBool = s283 ^ s2128
-  s2130 :: SBool = if s1978 then s2129 else s2128
-  s2131 :: SBool = s273 ^ s2130
-  s2132 :: SBool = if s2010 then s2131 else s2130
-  s2133 :: SBool = s265 ^ s2132
-  s2134 :: SBool = if s2042 then s2133 else s2132
-  s2135 :: SBool = s259 ^ s2134
-  s2136 :: SBool = if s2074 then s2135 else s2134
-  s2137 :: SBool = s255 ^ s2136
-  s2138 :: SBool = if s2106 then s2137 else s2136
-  s2139 :: SBool = s7 ^ s147
-  s2140 :: SBool = if s1688 then s2139 else s147
-  s2141 :: SBool = s493 ^ s2140
-  s2142 :: SBool = if s1710 then s2141 else s2140
-  s2143 :: SBool = s463 ^ s2142
-  s2144 :: SBool = if s1734 then s2143 else s2142
-  s2145 :: SBool = s435 ^ s2144
-  s2146 :: SBool = if s1760 then s2145 else s2144
-  s2147 :: SBool = s409 ^ s2146
-  s2148 :: SBool = if s1788 then s2147 else s2146
-  s2149 :: SBool = s385 ^ s2148
-  s2150 :: SBool = if s1818 then s2149 else s2148
-  s2151 :: SBool = s363 ^ s2150
-  s2152 :: SBool = if s1850 then s2151 else s2150
-  s2153 :: SBool = s343 ^ s2152
-  s2154 :: SBool = if s1882 then s2153 else s2152
-  s2155 :: SBool = s325 ^ s2154
-  s2156 :: SBool = if s1914 then s2155 else s2154
-  s2157 :: SBool = s309 ^ s2156
-  s2158 :: SBool = if s1946 then s2157 else s2156
-  s2159 :: SBool = s295 ^ s2158
-  s2160 :: SBool = if s1978 then s2159 else s2158
-  s2161 :: SBool = s283 ^ s2160
-  s2162 :: SBool = if s2010 then s2161 else s2160
-  s2163 :: SBool = s273 ^ s2162
-  s2164 :: SBool = if s2042 then s2163 else s2162
-  s2165 :: SBool = s265 ^ s2164
-  s2166 :: SBool = if s2074 then s2165 else s2164
-  s2167 :: SBool = s259 ^ s2166
-  s2168 :: SBool = if s2106 then s2167 else s2166
-  s2169 :: SBool = s255 ^ s2168
-  s2170 :: SBool = if s2138 then s2169 else s2168
-  s2171 :: SBool = s7 ^ s152
-  s2172 :: SBool = if s1710 then s2171 else s152
-  s2173 :: SBool = s493 ^ s2172
-  s2174 :: SBool = if s1734 then s2173 else s2172
-  s2175 :: SBool = s463 ^ s2174
-  s2176 :: SBool = if s1760 then s2175 else s2174
-  s2177 :: SBool = s435 ^ s2176
-  s2178 :: SBool = if s1788 then s2177 else s2176
-  s2179 :: SBool = s409 ^ s2178
-  s2180 :: SBool = if s1818 then s2179 else s2178
-  s2181 :: SBool = s385 ^ s2180
-  s2182 :: SBool = if s1850 then s2181 else s2180
-  s2183 :: SBool = s363 ^ s2182
-  s2184 :: SBool = if s1882 then s2183 else s2182
-  s2185 :: SBool = s343 ^ s2184
-  s2186 :: SBool = if s1914 then s2185 else s2184
-  s2187 :: SBool = s325 ^ s2186
-  s2188 :: SBool = if s1946 then s2187 else s2186
-  s2189 :: SBool = s309 ^ s2188
-  s2190 :: SBool = if s1978 then s2189 else s2188
-  s2191 :: SBool = s295 ^ s2190
-  s2192 :: SBool = if s2010 then s2191 else s2190
-  s2193 :: SBool = s283 ^ s2192
-  s2194 :: SBool = if s2042 then s2193 else s2192
-  s2195 :: SBool = s273 ^ s2194
-  s2196 :: SBool = if s2074 then s2195 else s2194
-  s2197 :: SBool = s265 ^ s2196
-  s2198 :: SBool = if s2106 then s2197 else s2196
-  s2199 :: SBool = s259 ^ s2198
-  s2200 :: SBool = if s2138 then s2199 else s2198
-  s2201 :: SBool = s255 ^ s2200
-  s2202 :: SBool = if s2170 then s2201 else s2200
-  s2203 :: SBool = s7 ^ s157
-  s2204 :: SBool = if s1734 then s2203 else s157
-  s2205 :: SBool = s493 ^ s2204
-  s2206 :: SBool = if s1760 then s2205 else s2204
-  s2207 :: SBool = s463 ^ s2206
-  s2208 :: SBool = if s1788 then s2207 else s2206
-  s2209 :: SBool = s435 ^ s2208
-  s2210 :: SBool = if s1818 then s2209 else s2208
-  s2211 :: SBool = s409 ^ s2210
-  s2212 :: SBool = if s1850 then s2211 else s2210
-  s2213 :: SBool = s385 ^ s2212
-  s2214 :: SBool = if s1882 then s2213 else s2212
-  s2215 :: SBool = s363 ^ s2214
-  s2216 :: SBool = if s1914 then s2215 else s2214
-  s2217 :: SBool = s343 ^ s2216
-  s2218 :: SBool = if s1946 then s2217 else s2216
-  s2219 :: SBool = s325 ^ s2218
-  s2220 :: SBool = if s1978 then s2219 else s2218
-  s2221 :: SBool = s309 ^ s2220
-  s2222 :: SBool = if s2010 then s2221 else s2220
-  s2223 :: SBool = s295 ^ s2222
-  s2224 :: SBool = if s2042 then s2223 else s2222
-  s2225 :: SBool = s283 ^ s2224
-  s2226 :: SBool = if s2074 then s2225 else s2224
-  s2227 :: SBool = s273 ^ s2226
-  s2228 :: SBool = if s2106 then s2227 else s2226
-  s2229 :: SBool = s265 ^ s2228
-  s2230 :: SBool = if s2138 then s2229 else s2228
-  s2231 :: SBool = s259 ^ s2230
-  s2232 :: SBool = if s2170 then s2231 else s2230
-  s2233 :: SBool = s255 ^ s2232
-  s2234 :: SBool = if s2202 then s2233 else s2232
-  s2235 :: SBool = s7 ^ s162
-  s2236 :: SBool = if s1760 then s2235 else s162
-  s2237 :: SBool = s493 ^ s2236
-  s2238 :: SBool = if s1788 then s2237 else s2236
-  s2239 :: SBool = s463 ^ s2238
-  s2240 :: SBool = if s1818 then s2239 else s2238
-  s2241 :: SBool = s435 ^ s2240
-  s2242 :: SBool = if s1850 then s2241 else s2240
-  s2243 :: SBool = s409 ^ s2242
-  s2244 :: SBool = if s1882 then s2243 else s2242
-  s2245 :: SBool = s385 ^ s2244
-  s2246 :: SBool = if s1914 then s2245 else s2244
-  s2247 :: SBool = s363 ^ s2246
-  s2248 :: SBool = if s1946 then s2247 else s2246
-  s2249 :: SBool = s343 ^ s2248
-  s2250 :: SBool = if s1978 then s2249 else s2248
-  s2251 :: SBool = s325 ^ s2250
-  s2252 :: SBool = if s2010 then s2251 else s2250
-  s2253 :: SBool = s309 ^ s2252
-  s2254 :: SBool = if s2042 then s2253 else s2252
-  s2255 :: SBool = s295 ^ s2254
-  s2256 :: SBool = if s2074 then s2255 else s2254
-  s2257 :: SBool = s283 ^ s2256
-  s2258 :: SBool = if s2106 then s2257 else s2256
-  s2259 :: SBool = s273 ^ s2258
-  s2260 :: SBool = if s2138 then s2259 else s2258
-  s2261 :: SBool = s265 ^ s2260
-  s2262 :: SBool = if s2170 then s2261 else s2260
-  s2263 :: SBool = s259 ^ s2262
-  s2264 :: SBool = if s2202 then s2263 else s2262
-  s2265 :: SBool = s255 ^ s2264
-  s2266 :: SBool = if s2234 then s2265 else s2264
-  s2267 :: SBool = s7 ^ s167
-  s2268 :: SBool = if s1788 then s2267 else s167
-  s2269 :: SBool = s493 ^ s2268
-  s2270 :: SBool = if s1818 then s2269 else s2268
-  s2271 :: SBool = s463 ^ s2270
-  s2272 :: SBool = if s1850 then s2271 else s2270
-  s2273 :: SBool = s435 ^ s2272
-  s2274 :: SBool = if s1882 then s2273 else s2272
-  s2275 :: SBool = s409 ^ s2274
-  s2276 :: SBool = if s1914 then s2275 else s2274
-  s2277 :: SBool = s385 ^ s2276
-  s2278 :: SBool = if s1946 then s2277 else s2276
-  s2279 :: SBool = s363 ^ s2278
-  s2280 :: SBool = if s1978 then s2279 else s2278
-  s2281 :: SBool = s343 ^ s2280
-  s2282 :: SBool = if s2010 then s2281 else s2280
-  s2283 :: SBool = s325 ^ s2282
-  s2284 :: SBool = if s2042 then s2283 else s2282
-  s2285 :: SBool = s309 ^ s2284
-  s2286 :: SBool = if s2074 then s2285 else s2284
-  s2287 :: SBool = s295 ^ s2286
-  s2288 :: SBool = if s2106 then s2287 else s2286
-  s2289 :: SBool = s283 ^ s2288
-  s2290 :: SBool = if s2138 then s2289 else s2288
-  s2291 :: SBool = s273 ^ s2290
-  s2292 :: SBool = if s2170 then s2291 else s2290
-  s2293 :: SBool = s265 ^ s2292
-  s2294 :: SBool = if s2202 then s2293 else s2292
-  s2295 :: SBool = s259 ^ s2294
-  s2296 :: SBool = if s2234 then s2295 else s2294
-  s2297 :: SBool = s255 ^ s2296
-  s2298 :: SBool = if s2266 then s2297 else s2296
-  s2299 :: SBool = s7 ^ s172
-  s2300 :: SBool = if s1818 then s2299 else s172
-  s2301 :: SBool = s493 ^ s2300
-  s2302 :: SBool = if s1850 then s2301 else s2300
-  s2303 :: SBool = s463 ^ s2302
-  s2304 :: SBool = if s1882 then s2303 else s2302
-  s2305 :: SBool = s435 ^ s2304
-  s2306 :: SBool = if s1914 then s2305 else s2304
-  s2307 :: SBool = s409 ^ s2306
-  s2308 :: SBool = if s1946 then s2307 else s2306
-  s2309 :: SBool = s385 ^ s2308
-  s2310 :: SBool = if s1978 then s2309 else s2308
-  s2311 :: SBool = s363 ^ s2310
-  s2312 :: SBool = if s2010 then s2311 else s2310
-  s2313 :: SBool = s343 ^ s2312
-  s2314 :: SBool = if s2042 then s2313 else s2312
-  s2315 :: SBool = s325 ^ s2314
-  s2316 :: SBool = if s2074 then s2315 else s2314
-  s2317 :: SBool = s309 ^ s2316
-  s2318 :: SBool = if s2106 then s2317 else s2316
-  s2319 :: SBool = s295 ^ s2318
-  s2320 :: SBool = if s2138 then s2319 else s2318
-  s2321 :: SBool = s283 ^ s2320
-  s2322 :: SBool = if s2170 then s2321 else s2320
-  s2323 :: SBool = s273 ^ s2322
-  s2324 :: SBool = if s2202 then s2323 else s2322
-  s2325 :: SBool = s265 ^ s2324
-  s2326 :: SBool = if s2234 then s2325 else s2324
-  s2327 :: SBool = s259 ^ s2326
-  s2328 :: SBool = if s2266 then s2327 else s2326
-  s2329 :: SBool = s255 ^ s2328
-  s2330 :: SBool = if s2298 then s2329 else s2328
-  s2331 :: SBool = s7 ^ s177
-  s2332 :: SBool = if s1850 then s2331 else s177
-  s2333 :: SBool = s493 ^ s2332
-  s2334 :: SBool = if s1882 then s2333 else s2332
-  s2335 :: SBool = s463 ^ s2334
-  s2336 :: SBool = if s1914 then s2335 else s2334
-  s2337 :: SBool = s435 ^ s2336
-  s2338 :: SBool = if s1946 then s2337 else s2336
-  s2339 :: SBool = s409 ^ s2338
-  s2340 :: SBool = if s1978 then s2339 else s2338
-  s2341 :: SBool = s385 ^ s2340
-  s2342 :: SBool = if s2010 then s2341 else s2340
-  s2343 :: SBool = s363 ^ s2342
-  s2344 :: SBool = if s2042 then s2343 else s2342
-  s2345 :: SBool = s343 ^ s2344
-  s2346 :: SBool = if s2074 then s2345 else s2344
-  s2347 :: SBool = s325 ^ s2346
-  s2348 :: SBool = if s2106 then s2347 else s2346
-  s2349 :: SBool = s309 ^ s2348
-  s2350 :: SBool = if s2138 then s2349 else s2348
-  s2351 :: SBool = s295 ^ s2350
-  s2352 :: SBool = if s2170 then s2351 else s2350
-  s2353 :: SBool = s283 ^ s2352
-  s2354 :: SBool = if s2202 then s2353 else s2352
-  s2355 :: SBool = s273 ^ s2354
-  s2356 :: SBool = if s2234 then s2355 else s2354
-  s2357 :: SBool = s265 ^ s2356
-  s2358 :: SBool = if s2266 then s2357 else s2356
-  s2359 :: SBool = s259 ^ s2358
-  s2360 :: SBool = if s2298 then s2359 else s2358
-  s2361 :: SBool = s255 ^ s2360
-  s2362 :: SBool = if s2330 then s2361 else s2360
-  s2363 :: SBool = s7 ^ s182
-  s2364 :: SBool = if s1882 then s2363 else s182
-  s2365 :: SBool = s493 ^ s2364
-  s2366 :: SBool = if s1914 then s2365 else s2364
-  s2367 :: SBool = s463 ^ s2366
-  s2368 :: SBool = if s1946 then s2367 else s2366
-  s2369 :: SBool = s435 ^ s2368
-  s2370 :: SBool = if s1978 then s2369 else s2368
-  s2371 :: SBool = s409 ^ s2370
-  s2372 :: SBool = if s2010 then s2371 else s2370
-  s2373 :: SBool = s385 ^ s2372
-  s2374 :: SBool = if s2042 then s2373 else s2372
-  s2375 :: SBool = s363 ^ s2374
-  s2376 :: SBool = if s2074 then s2375 else s2374
-  s2377 :: SBool = s343 ^ s2376
-  s2378 :: SBool = if s2106 then s2377 else s2376
-  s2379 :: SBool = s325 ^ s2378
-  s2380 :: SBool = if s2138 then s2379 else s2378
-  s2381 :: SBool = s309 ^ s2380
-  s2382 :: SBool = if s2170 then s2381 else s2380
-  s2383 :: SBool = s295 ^ s2382
-  s2384 :: SBool = if s2202 then s2383 else s2382
-  s2385 :: SBool = s283 ^ s2384
-  s2386 :: SBool = if s2234 then s2385 else s2384
-  s2387 :: SBool = s273 ^ s2386
-  s2388 :: SBool = if s2266 then s2387 else s2386
-  s2389 :: SBool = s265 ^ s2388
-  s2390 :: SBool = if s2298 then s2389 else s2388
-  s2391 :: SBool = s259 ^ s2390
-  s2392 :: SBool = if s2330 then s2391 else s2390
-  s2393 :: SBool = s255 ^ s2392
-  s2394 :: SBool = if s2362 then s2393 else s2392
-  s2395 :: SBool = s7 ^ s187
-  s2396 :: SBool = if s1914 then s2395 else s187
-  s2397 :: SBool = s493 ^ s2396
-  s2398 :: SBool = if s1946 then s2397 else s2396
-  s2399 :: SBool = s463 ^ s2398
-  s2400 :: SBool = if s1978 then s2399 else s2398
-  s2401 :: SBool = s435 ^ s2400
-  s2402 :: SBool = if s2010 then s2401 else s2400
-  s2403 :: SBool = s409 ^ s2402
-  s2404 :: SBool = if s2042 then s2403 else s2402
-  s2405 :: SBool = s385 ^ s2404
-  s2406 :: SBool = if s2074 then s2405 else s2404
-  s2407 :: SBool = s363 ^ s2406
-  s2408 :: SBool = if s2106 then s2407 else s2406
-  s2409 :: SBool = s343 ^ s2408
-  s2410 :: SBool = if s2138 then s2409 else s2408
-  s2411 :: SBool = s325 ^ s2410
-  s2412 :: SBool = if s2170 then s2411 else s2410
-  s2413 :: SBool = s309 ^ s2412
-  s2414 :: SBool = if s2202 then s2413 else s2412
-  s2415 :: SBool = s295 ^ s2414
-  s2416 :: SBool = if s2234 then s2415 else s2414
-  s2417 :: SBool = s283 ^ s2416
-  s2418 :: SBool = if s2266 then s2417 else s2416
-  s2419 :: SBool = s273 ^ s2418
-  s2420 :: SBool = if s2298 then s2419 else s2418
-  s2421 :: SBool = s265 ^ s2420
-  s2422 :: SBool = if s2330 then s2421 else s2420
-  s2423 :: SBool = s259 ^ s2422
-  s2424 :: SBool = if s2362 then s2423 else s2422
-  s2425 :: SBool = s255 ^ s2424
-  s2426 :: SBool = if s2394 then s2425 else s2424
-  s2427 :: SBool = s7 ^ s192
-  s2428 :: SBool = if s1946 then s2427 else s192
-  s2429 :: SBool = s493 ^ s2428
-  s2430 :: SBool = if s1978 then s2429 else s2428
-  s2431 :: SBool = s463 ^ s2430
-  s2432 :: SBool = if s2010 then s2431 else s2430
-  s2433 :: SBool = s435 ^ s2432
-  s2434 :: SBool = if s2042 then s2433 else s2432
-  s2435 :: SBool = s409 ^ s2434
-  s2436 :: SBool = if s2074 then s2435 else s2434
-  s2437 :: SBool = s385 ^ s2436
-  s2438 :: SBool = if s2106 then s2437 else s2436
-  s2439 :: SBool = s363 ^ s2438
-  s2440 :: SBool = if s2138 then s2439 else s2438
-  s2441 :: SBool = s343 ^ s2440
-  s2442 :: SBool = if s2170 then s2441 else s2440
-  s2443 :: SBool = s325 ^ s2442
-  s2444 :: SBool = if s2202 then s2443 else s2442
-  s2445 :: SBool = s309 ^ s2444
-  s2446 :: SBool = if s2234 then s2445 else s2444
-  s2447 :: SBool = s295 ^ s2446
-  s2448 :: SBool = if s2266 then s2447 else s2446
-  s2449 :: SBool = s283 ^ s2448
-  s2450 :: SBool = if s2298 then s2449 else s2448
-  s2451 :: SBool = s273 ^ s2450
-  s2452 :: SBool = if s2330 then s2451 else s2450
-  s2453 :: SBool = s265 ^ s2452
-  s2454 :: SBool = if s2362 then s2453 else s2452
-  s2455 :: SBool = s259 ^ s2454
-  s2456 :: SBool = if s2394 then s2455 else s2454
-  s2457 :: SBool = s255 ^ s2456
-  s2458 :: SBool = if s2426 then s2457 else s2456
-  s2459 :: SBool = s7 ^ s197
-  s2460 :: SBool = if s1978 then s2459 else s197
-  s2461 :: SBool = s493 ^ s2460
-  s2462 :: SBool = if s2010 then s2461 else s2460
-  s2463 :: SBool = s463 ^ s2462
-  s2464 :: SBool = if s2042 then s2463 else s2462
-  s2465 :: SBool = s435 ^ s2464
-  s2466 :: SBool = if s2074 then s2465 else s2464
-  s2467 :: SBool = s409 ^ s2466
-  s2468 :: SBool = if s2106 then s2467 else s2466
-  s2469 :: SBool = s385 ^ s2468
-  s2470 :: SBool = if s2138 then s2469 else s2468
-  s2471 :: SBool = s363 ^ s2470
-  s2472 :: SBool = if s2170 then s2471 else s2470
-  s2473 :: SBool = s343 ^ s2472
-  s2474 :: SBool = if s2202 then s2473 else s2472
-  s2475 :: SBool = s325 ^ s2474
-  s2476 :: SBool = if s2234 then s2475 else s2474
-  s2477 :: SBool = s309 ^ s2476
-  s2478 :: SBool = if s2266 then s2477 else s2476
-  s2479 :: SBool = s295 ^ s2478
-  s2480 :: SBool = if s2298 then s2479 else s2478
-  s2481 :: SBool = s283 ^ s2480
-  s2482 :: SBool = if s2330 then s2481 else s2480
-  s2483 :: SBool = s273 ^ s2482
-  s2484 :: SBool = if s2362 then s2483 else s2482
-  s2485 :: SBool = s265 ^ s2484
-  s2486 :: SBool = if s2394 then s2485 else s2484
-  s2487 :: SBool = s259 ^ s2486
-  s2488 :: SBool = if s2426 then s2487 else s2486
-  s2489 :: SBool = s255 ^ s2488
-  s2490 :: SBool = if s2458 then s2489 else s2488
-  s2491 :: SBool = s7 ^ s202
-  s2492 :: SBool = if s2010 then s2491 else s202
-  s2493 :: SBool = s493 ^ s2492
-  s2494 :: SBool = if s2042 then s2493 else s2492
-  s2495 :: SBool = s463 ^ s2494
-  s2496 :: SBool = if s2074 then s2495 else s2494
-  s2497 :: SBool = s435 ^ s2496
-  s2498 :: SBool = if s2106 then s2497 else s2496
-  s2499 :: SBool = s409 ^ s2498
-  s2500 :: SBool = if s2138 then s2499 else s2498
-  s2501 :: SBool = s385 ^ s2500
-  s2502 :: SBool = if s2170 then s2501 else s2500
-  s2503 :: SBool = s363 ^ s2502
-  s2504 :: SBool = if s2202 then s2503 else s2502
-  s2505 :: SBool = s343 ^ s2504
-  s2506 :: SBool = if s2234 then s2505 else s2504
-  s2507 :: SBool = s325 ^ s2506
-  s2508 :: SBool = if s2266 then s2507 else s2506
-  s2509 :: SBool = s309 ^ s2508
-  s2510 :: SBool = if s2298 then s2509 else s2508
-  s2511 :: SBool = s295 ^ s2510
-  s2512 :: SBool = if s2330 then s2511 else s2510
-  s2513 :: SBool = s283 ^ s2512
-  s2514 :: SBool = if s2362 then s2513 else s2512
-  s2515 :: SBool = s273 ^ s2514
-  s2516 :: SBool = if s2394 then s2515 else s2514
-  s2517 :: SBool = s265 ^ s2516
-  s2518 :: SBool = if s2426 then s2517 else s2516
-  s2519 :: SBool = s259 ^ s2518
-  s2520 :: SBool = if s2458 then s2519 else s2518
-  s2521 :: SBool = s255 ^ s2520
-  s2522 :: SBool = if s2490 then s2521 else s2520
-  s2523 :: SBool = s7 ^ s207
-  s2524 :: SBool = if s2042 then s2523 else s207
-  s2525 :: SBool = s493 ^ s2524
-  s2526 :: SBool = if s2074 then s2525 else s2524
-  s2527 :: SBool = s463 ^ s2526
-  s2528 :: SBool = if s2106 then s2527 else s2526
-  s2529 :: SBool = s435 ^ s2528
-  s2530 :: SBool = if s2138 then s2529 else s2528
-  s2531 :: SBool = s409 ^ s2530
-  s2532 :: SBool = if s2170 then s2531 else s2530
-  s2533 :: SBool = s385 ^ s2532
-  s2534 :: SBool = if s2202 then s2533 else s2532
-  s2535 :: SBool = s363 ^ s2534
-  s2536 :: SBool = if s2234 then s2535 else s2534
-  s2537 :: SBool = s343 ^ s2536
-  s2538 :: SBool = if s2266 then s2537 else s2536
-  s2539 :: SBool = s325 ^ s2538
-  s2540 :: SBool = if s2298 then s2539 else s2538
-  s2541 :: SBool = s309 ^ s2540
-  s2542 :: SBool = if s2330 then s2541 else s2540
-  s2543 :: SBool = s295 ^ s2542
-  s2544 :: SBool = if s2362 then s2543 else s2542
-  s2545 :: SBool = s283 ^ s2544
-  s2546 :: SBool = if s2394 then s2545 else s2544
-  s2547 :: SBool = s273 ^ s2546
-  s2548 :: SBool = if s2426 then s2547 else s2546
-  s2549 :: SBool = s265 ^ s2548
-  s2550 :: SBool = if s2458 then s2549 else s2548
-  s2551 :: SBool = s259 ^ s2550
-  s2552 :: SBool = if s2490 then s2551 else s2550
-  s2553 :: SBool = s255 ^ s2552
-  s2554 :: SBool = if s2522 then s2553 else s2552
-  s2555 :: SBool = s7 ^ s212
-  s2556 :: SBool = if s2074 then s2555 else s212
-  s2557 :: SBool = s493 ^ s2556
-  s2558 :: SBool = if s2106 then s2557 else s2556
-  s2559 :: SBool = s463 ^ s2558
-  s2560 :: SBool = if s2138 then s2559 else s2558
-  s2561 :: SBool = s435 ^ s2560
-  s2562 :: SBool = if s2170 then s2561 else s2560
-  s2563 :: SBool = s409 ^ s2562
-  s2564 :: SBool = if s2202 then s2563 else s2562
-  s2565 :: SBool = s385 ^ s2564
-  s2566 :: SBool = if s2234 then s2565 else s2564
-  s2567 :: SBool = s363 ^ s2566
-  s2568 :: SBool = if s2266 then s2567 else s2566
-  s2569 :: SBool = s343 ^ s2568
-  s2570 :: SBool = if s2298 then s2569 else s2568
-  s2571 :: SBool = s325 ^ s2570
-  s2572 :: SBool = if s2330 then s2571 else s2570
-  s2573 :: SBool = s309 ^ s2572
-  s2574 :: SBool = if s2362 then s2573 else s2572
-  s2575 :: SBool = s295 ^ s2574
-  s2576 :: SBool = if s2394 then s2575 else s2574
-  s2577 :: SBool = s283 ^ s2576
-  s2578 :: SBool = if s2426 then s2577 else s2576
-  s2579 :: SBool = s273 ^ s2578
-  s2580 :: SBool = if s2458 then s2579 else s2578
-  s2581 :: SBool = s265 ^ s2580
-  s2582 :: SBool = if s2490 then s2581 else s2580
-  s2583 :: SBool = s259 ^ s2582
-  s2584 :: SBool = if s2522 then s2583 else s2582
-  s2585 :: SBool = s255 ^ s2584
-  s2586 :: SBool = if s2554 then s2585 else s2584
-  s2587 :: SBool = s7 ^ s217
-  s2588 :: SBool = if s2106 then s2587 else s217
-  s2589 :: SBool = s493 ^ s2588
-  s2590 :: SBool = if s2138 then s2589 else s2588
-  s2591 :: SBool = s463 ^ s2590
-  s2592 :: SBool = if s2170 then s2591 else s2590
-  s2593 :: SBool = s435 ^ s2592
-  s2594 :: SBool = if s2202 then s2593 else s2592
-  s2595 :: SBool = s409 ^ s2594
-  s2596 :: SBool = if s2234 then s2595 else s2594
-  s2597 :: SBool = s385 ^ s2596
-  s2598 :: SBool = if s2266 then s2597 else s2596
-  s2599 :: SBool = s363 ^ s2598
-  s2600 :: SBool = if s2298 then s2599 else s2598
-  s2601 :: SBool = s343 ^ s2600
-  s2602 :: SBool = if s2330 then s2601 else s2600
-  s2603 :: SBool = s325 ^ s2602
-  s2604 :: SBool = if s2362 then s2603 else s2602
-  s2605 :: SBool = s309 ^ s2604
-  s2606 :: SBool = if s2394 then s2605 else s2604
-  s2607 :: SBool = s295 ^ s2606
-  s2608 :: SBool = if s2426 then s2607 else s2606
-  s2609 :: SBool = s283 ^ s2608
-  s2610 :: SBool = if s2458 then s2609 else s2608
-  s2611 :: SBool = s273 ^ s2610
-  s2612 :: SBool = if s2490 then s2611 else s2610
-  s2613 :: SBool = s265 ^ s2612
-  s2614 :: SBool = if s2522 then s2613 else s2612
-  s2615 :: SBool = s259 ^ s2614
-  s2616 :: SBool = if s2554 then s2615 else s2614
-  s2617 :: SBool = s255 ^ s2616
-  s2618 :: SBool = if s2586 then s2617 else s2616
-  s2619 :: SBool = s7 ^ s222
-  s2620 :: SBool = if s2138 then s2619 else s222
-  s2621 :: SBool = s493 ^ s2620
-  s2622 :: SBool = if s2170 then s2621 else s2620
-  s2623 :: SBool = s463 ^ s2622
-  s2624 :: SBool = if s2202 then s2623 else s2622
-  s2625 :: SBool = s435 ^ s2624
-  s2626 :: SBool = if s2234 then s2625 else s2624
-  s2627 :: SBool = s409 ^ s2626
-  s2628 :: SBool = if s2266 then s2627 else s2626
-  s2629 :: SBool = s385 ^ s2628
-  s2630 :: SBool = if s2298 then s2629 else s2628
-  s2631 :: SBool = s363 ^ s2630
-  s2632 :: SBool = if s2330 then s2631 else s2630
-  s2633 :: SBool = s343 ^ s2632
-  s2634 :: SBool = if s2362 then s2633 else s2632
-  s2635 :: SBool = s325 ^ s2634
-  s2636 :: SBool = if s2394 then s2635 else s2634
-  s2637 :: SBool = s309 ^ s2636
-  s2638 :: SBool = if s2426 then s2637 else s2636
-  s2639 :: SBool = s295 ^ s2638
-  s2640 :: SBool = if s2458 then s2639 else s2638
-  s2641 :: SBool = s283 ^ s2640
-  s2642 :: SBool = if s2490 then s2641 else s2640
-  s2643 :: SBool = s273 ^ s2642
-  s2644 :: SBool = if s2522 then s2643 else s2642
-  s2645 :: SBool = s265 ^ s2644
-  s2646 :: SBool = if s2554 then s2645 else s2644
-  s2647 :: SBool = s259 ^ s2646
-  s2648 :: SBool = if s2586 then s2647 else s2646
-  s2649 :: SBool = s255 ^ s2648
-  s2650 :: SBool = if s2618 then s2649 else s2648
-  s2651 :: SBool = s7 ^ s227
-  s2652 :: SBool = if s2170 then s2651 else s227
-  s2653 :: SBool = s493 ^ s2652
-  s2654 :: SBool = if s2202 then s2653 else s2652
-  s2655 :: SBool = s463 ^ s2654
-  s2656 :: SBool = if s2234 then s2655 else s2654
-  s2657 :: SBool = s435 ^ s2656
-  s2658 :: SBool = if s2266 then s2657 else s2656
-  s2659 :: SBool = s409 ^ s2658
-  s2660 :: SBool = if s2298 then s2659 else s2658
-  s2661 :: SBool = s385 ^ s2660
-  s2662 :: SBool = if s2330 then s2661 else s2660
-  s2663 :: SBool = s363 ^ s2662
-  s2664 :: SBool = if s2362 then s2663 else s2662
-  s2665 :: SBool = s343 ^ s2664
-  s2666 :: SBool = if s2394 then s2665 else s2664
-  s2667 :: SBool = s325 ^ s2666
-  s2668 :: SBool = if s2426 then s2667 else s2666
-  s2669 :: SBool = s309 ^ s2668
-  s2670 :: SBool = if s2458 then s2669 else s2668
-  s2671 :: SBool = s295 ^ s2670
-  s2672 :: SBool = if s2490 then s2671 else s2670
-  s2673 :: SBool = s283 ^ s2672
-  s2674 :: SBool = if s2522 then s2673 else s2672
-  s2675 :: SBool = s273 ^ s2674
-  s2676 :: SBool = if s2554 then s2675 else s2674
-  s2677 :: SBool = s265 ^ s2676
-  s2678 :: SBool = if s2586 then s2677 else s2676
-  s2679 :: SBool = s259 ^ s2678
-  s2680 :: SBool = if s2618 then s2679 else s2678
-  s2681 :: SBool = s255 ^ s2680
-  s2682 :: SBool = if s2650 then s2681 else s2680
-  s2683 :: SBool = s7 ^ s232
-  s2684 :: SBool = if s2202 then s2683 else s232
-  s2685 :: SBool = s493 ^ s2684
-  s2686 :: SBool = if s2234 then s2685 else s2684
-  s2687 :: SBool = s463 ^ s2686
-  s2688 :: SBool = if s2266 then s2687 else s2686
-  s2689 :: SBool = s435 ^ s2688
-  s2690 :: SBool = if s2298 then s2689 else s2688
-  s2691 :: SBool = s409 ^ s2690
-  s2692 :: SBool = if s2330 then s2691 else s2690
-  s2693 :: SBool = s385 ^ s2692
-  s2694 :: SBool = if s2362 then s2693 else s2692
-  s2695 :: SBool = s363 ^ s2694
-  s2696 :: SBool = if s2394 then s2695 else s2694
-  s2697 :: SBool = s343 ^ s2696
-  s2698 :: SBool = if s2426 then s2697 else s2696
-  s2699 :: SBool = s325 ^ s2698
-  s2700 :: SBool = if s2458 then s2699 else s2698
-  s2701 :: SBool = s309 ^ s2700
-  s2702 :: SBool = if s2490 then s2701 else s2700
-  s2703 :: SBool = s295 ^ s2702
-  s2704 :: SBool = if s2522 then s2703 else s2702
-  s2705 :: SBool = s283 ^ s2704
-  s2706 :: SBool = if s2554 then s2705 else s2704
-  s2707 :: SBool = s273 ^ s2706
-  s2708 :: SBool = if s2586 then s2707 else s2706
-  s2709 :: SBool = s265 ^ s2708
-  s2710 :: SBool = if s2618 then s2709 else s2708
-  s2711 :: SBool = s259 ^ s2710
-  s2712 :: SBool = if s2650 then s2711 else s2710
-  s2713 :: SBool = s255 ^ s2712
-  s2714 :: SBool = if s2682 then s2713 else s2712
-  s2715 :: SBool = s7 ^ s237
-  s2716 :: SBool = if s2234 then s2715 else s237
-  s2717 :: SBool = s493 ^ s2716
-  s2718 :: SBool = if s2266 then s2717 else s2716
-  s2719 :: SBool = s463 ^ s2718
-  s2720 :: SBool = if s2298 then s2719 else s2718
-  s2721 :: SBool = s435 ^ s2720
-  s2722 :: SBool = if s2330 then s2721 else s2720
-  s2723 :: SBool = s409 ^ s2722
-  s2724 :: SBool = if s2362 then s2723 else s2722
-  s2725 :: SBool = s385 ^ s2724
-  s2726 :: SBool = if s2394 then s2725 else s2724
-  s2727 :: SBool = s363 ^ s2726
-  s2728 :: SBool = if s2426 then s2727 else s2726
-  s2729 :: SBool = s343 ^ s2728
-  s2730 :: SBool = if s2458 then s2729 else s2728
-  s2731 :: SBool = s325 ^ s2730
-  s2732 :: SBool = if s2490 then s2731 else s2730
-  s2733 :: SBool = s309 ^ s2732
-  s2734 :: SBool = if s2522 then s2733 else s2732
-  s2735 :: SBool = s295 ^ s2734
-  s2736 :: SBool = if s2554 then s2735 else s2734
-  s2737 :: SBool = s283 ^ s2736
-  s2738 :: SBool = if s2586 then s2737 else s2736
-  s2739 :: SBool = s273 ^ s2738
-  s2740 :: SBool = if s2618 then s2739 else s2738
-  s2741 :: SBool = s265 ^ s2740
-  s2742 :: SBool = if s2650 then s2741 else s2740
-  s2743 :: SBool = s259 ^ s2742
-  s2744 :: SBool = if s2682 then s2743 else s2742
-  s2745 :: SBool = s255 ^ s2744
-  s2746 :: SBool = if s2714 then s2745 else s2744
-  s2747 :: SBool = s7 ^ s242
-  s2748 :: SBool = if s2266 then s2747 else s242
-  s2749 :: SBool = s493 ^ s2748
-  s2750 :: SBool = if s2298 then s2749 else s2748
-  s2751 :: SBool = s463 ^ s2750
-  s2752 :: SBool = if s2330 then s2751 else s2750
-  s2753 :: SBool = s435 ^ s2752
-  s2754 :: SBool = if s2362 then s2753 else s2752
-  s2755 :: SBool = s409 ^ s2754
-  s2756 :: SBool = if s2394 then s2755 else s2754
-  s2757 :: SBool = s385 ^ s2756
-  s2758 :: SBool = if s2426 then s2757 else s2756
-  s2759 :: SBool = s363 ^ s2758
-  s2760 :: SBool = if s2458 then s2759 else s2758
-  s2761 :: SBool = s343 ^ s2760
-  s2762 :: SBool = if s2490 then s2761 else s2760
-  s2763 :: SBool = s325 ^ s2762
-  s2764 :: SBool = if s2522 then s2763 else s2762
-  s2765 :: SBool = s309 ^ s2764
-  s2766 :: SBool = if s2554 then s2765 else s2764
-  s2767 :: SBool = s295 ^ s2766
-  s2768 :: SBool = if s2586 then s2767 else s2766
-  s2769 :: SBool = s283 ^ s2768
-  s2770 :: SBool = if s2618 then s2769 else s2768
-  s2771 :: SBool = s273 ^ s2770
-  s2772 :: SBool = if s2650 then s2771 else s2770
-  s2773 :: SBool = s265 ^ s2772
-  s2774 :: SBool = if s2682 then s2773 else s2772
-  s2775 :: SBool = s259 ^ s2774
-  s2776 :: SBool = if s2714 then s2775 else s2774
-  s2777 :: SBool = s255 ^ s2776
-  s2778 :: SBool = if s2746 then s2777 else s2776
-  s2779 :: SBool = s7 ^ s247
-  s2780 :: SBool = if s2298 then s2779 else s247
-  s2781 :: SBool = s493 ^ s2780
-  s2782 :: SBool = if s2330 then s2781 else s2780
-  s2783 :: SBool = s463 ^ s2782
-  s2784 :: SBool = if s2362 then s2783 else s2782
-  s2785 :: SBool = s435 ^ s2784
-  s2786 :: SBool = if s2394 then s2785 else s2784
-  s2787 :: SBool = s409 ^ s2786
-  s2788 :: SBool = if s2426 then s2787 else s2786
-  s2789 :: SBool = s385 ^ s2788
-  s2790 :: SBool = if s2458 then s2789 else s2788
-  s2791 :: SBool = s363 ^ s2790
-  s2792 :: SBool = if s2490 then s2791 else s2790
-  s2793 :: SBool = s343 ^ s2792
-  s2794 :: SBool = if s2522 then s2793 else s2792
-  s2795 :: SBool = s325 ^ s2794
-  s2796 :: SBool = if s2554 then s2795 else s2794
-  s2797 :: SBool = s309 ^ s2796
-  s2798 :: SBool = if s2586 then s2797 else s2796
-  s2799 :: SBool = s295 ^ s2798
-  s2800 :: SBool = if s2618 then s2799 else s2798
-  s2801 :: SBool = s283 ^ s2800
-  s2802 :: SBool = if s2650 then s2801 else s2800
-  s2803 :: SBool = s273 ^ s2802
-  s2804 :: SBool = if s2682 then s2803 else s2802
-  s2805 :: SBool = s265 ^ s2804
-  s2806 :: SBool = if s2714 then s2805 else s2804
-  s2807 :: SBool = s259 ^ s2806
-  s2808 :: SBool = if s2746 then s2807 else s2806
-  s2809 :: SBool = s255 ^ s2808
-  s2810 :: SBool = if s2778 then s2809 else s2808
-  s2811 :: SBool = s7 ^ s252
-  s2812 :: SBool = if s2330 then s2811 else s252
-  s2813 :: SBool = s493 ^ s2812
-  s2814 :: SBool = if s2362 then s2813 else s2812
-  s2815 :: SBool = s463 ^ s2814
-  s2816 :: SBool = if s2394 then s2815 else s2814
-  s2817 :: SBool = s435 ^ s2816
-  s2818 :: SBool = if s2426 then s2817 else s2816
-  s2819 :: SBool = s409 ^ s2818
-  s2820 :: SBool = if s2458 then s2819 else s2818
-  s2821 :: SBool = s385 ^ s2820
-  s2822 :: SBool = if s2490 then s2821 else s2820
-  s2823 :: SBool = s363 ^ s2822
-  s2824 :: SBool = if s2522 then s2823 else s2822
-  s2825 :: SBool = s343 ^ s2824
-  s2826 :: SBool = if s2554 then s2825 else s2824
-  s2827 :: SBool = s325 ^ s2826
-  s2828 :: SBool = if s2586 then s2827 else s2826
-  s2829 :: SBool = s309 ^ s2828
-  s2830 :: SBool = if s2618 then s2829 else s2828
-  s2831 :: SBool = s295 ^ s2830
-  s2832 :: SBool = if s2650 then s2831 else s2830
-  s2833 :: SBool = s283 ^ s2832
-  s2834 :: SBool = if s2682 then s2833 else s2832
-  s2835 :: SBool = s273 ^ s2834
-  s2836 :: SBool = if s2714 then s2835 else s2834
-  s2837 :: SBool = s265 ^ s2836
-  s2838 :: SBool = if s2746 then s2837 else s2836
-  s2839 :: SBool = s259 ^ s2838
-  s2840 :: SBool = if s2778 then s2839 else s2838
-  s2841 :: SBool = s255 ^ s2840
-  s2842 :: SBool = if s2810 then s2841 else s2840
-  s2843 :: SBool = if s2362 then s7 else s_2
-  s2844 :: SBool = s493 ^ s2843
-  s2845 :: SBool = if s2394 then s2844 else s2843
-  s2846 :: SBool = s463 ^ s2845
-  s2847 :: SBool = if s2426 then s2846 else s2845
-  s2848 :: SBool = s435 ^ s2847
-  s2849 :: SBool = if s2458 then s2848 else s2847
-  s2850 :: SBool = s409 ^ s2849
-  s2851 :: SBool = if s2490 then s2850 else s2849
-  s2852 :: SBool = s385 ^ s2851
-  s2853 :: SBool = if s2522 then s2852 else s2851
-  s2854 :: SBool = s363 ^ s2853
-  s2855 :: SBool = if s2554 then s2854 else s2853
-  s2856 :: SBool = s343 ^ s2855
-  s2857 :: SBool = if s2586 then s2856 else s2855
-  s2858 :: SBool = s325 ^ s2857
-  s2859 :: SBool = if s2618 then s2858 else s2857
-  s2860 :: SBool = s309 ^ s2859
-  s2861 :: SBool = if s2650 then s2860 else s2859
-  s2862 :: SBool = s295 ^ s2861
-  s2863 :: SBool = if s2682 then s2862 else s2861
-  s2864 :: SBool = s283 ^ s2863
-  s2865 :: SBool = if s2714 then s2864 else s2863
-  s2866 :: SBool = s273 ^ s2865
-  s2867 :: SBool = if s2746 then s2866 else s2865
-  s2868 :: SBool = s265 ^ s2867
-  s2869 :: SBool = if s2778 then s2868 else s2867
-  s2870 :: SBool = s259 ^ s2869
-  s2871 :: SBool = if s2810 then s2870 else s2869
-  s2872 :: SBool = s255 ^ s2871
-  s2873 :: SBool = if s2842 then s2872 else s2871
-  s2874 :: SBool = s1578 ^ s2873
-  s2875 :: SBool = if s1099 then s7 else s_2
-  s2876 :: SBool = s493 ^ s2875
-  s2877 :: SBool = if s1131 then s2876 else s2875
-  s2878 :: SBool = s463 ^ s2877
-  s2879 :: SBool = if s1163 then s2878 else s2877
-  s2880 :: SBool = s435 ^ s2879
-  s2881 :: SBool = if s1195 then s2880 else s2879
-  s2882 :: SBool = s409 ^ s2881
-  s2883 :: SBool = if s1227 then s2882 else s2881
-  s2884 :: SBool = s385 ^ s2883
-  s2885 :: SBool = if s1259 then s2884 else s2883
-  s2886 :: SBool = s363 ^ s2885
-  s2887 :: SBool = if s1291 then s2886 else s2885
-  s2888 :: SBool = s343 ^ s2887
-  s2889 :: SBool = if s1323 then s2888 else s2887
-  s2890 :: SBool = s325 ^ s2889
-  s2891 :: SBool = if s1355 then s2890 else s2889
-  s2892 :: SBool = s309 ^ s2891
-  s2893 :: SBool = if s1387 then s2892 else s2891
-  s2894 :: SBool = s295 ^ s2893
-  s2895 :: SBool = if s1419 then s2894 else s2893
-  s2896 :: SBool = s283 ^ s2895
-  s2897 :: SBool = if s1451 then s2896 else s2895
-  s2898 :: SBool = s273 ^ s2897
-  s2899 :: SBool = if s1483 then s2898 else s2897
-  s2900 :: SBool = s265 ^ s2899
-  s2901 :: SBool = if s1515 then s2900 else s2899
-  s2902 :: SBool = s259 ^ s2901
-  s2903 :: SBool = if s1547 then s2902 else s2901
-  s2904 :: SBool = if s2394 then s7 else s_2
-  s2905 :: SBool = s493 ^ s2904
-  s2906 :: SBool = if s2426 then s2905 else s2904
-  s2907 :: SBool = s463 ^ s2906
-  s2908 :: SBool = if s2458 then s2907 else s2906
-  s2909 :: SBool = s435 ^ s2908
-  s2910 :: SBool = if s2490 then s2909 else s2908
-  s2911 :: SBool = s409 ^ s2910
-  s2912 :: SBool = if s2522 then s2911 else s2910
-  s2913 :: SBool = s385 ^ s2912
-  s2914 :: SBool = if s2554 then s2913 else s2912
-  s2915 :: SBool = s363 ^ s2914
-  s2916 :: SBool = if s2586 then s2915 else s2914
-  s2917 :: SBool = s343 ^ s2916
-  s2918 :: SBool = if s2618 then s2917 else s2916
-  s2919 :: SBool = s325 ^ s2918
-  s2920 :: SBool = if s2650 then s2919 else s2918
-  s2921 :: SBool = s309 ^ s2920
-  s2922 :: SBool = if s2682 then s2921 else s2920
-  s2923 :: SBool = s295 ^ s2922
-  s2924 :: SBool = if s2714 then s2923 else s2922
-  s2925 :: SBool = s283 ^ s2924
-  s2926 :: SBool = if s2746 then s2925 else s2924
-  s2927 :: SBool = s273 ^ s2926
-  s2928 :: SBool = if s2778 then s2927 else s2926
-  s2929 :: SBool = s265 ^ s2928
-  s2930 :: SBool = if s2810 then s2929 else s2928
-  s2931 :: SBool = s259 ^ s2930
-  s2932 :: SBool = if s2842 then s2931 else s2930
-  s2933 :: SBool = s2903 ^ s2932
-  s2934 :: SBool = if s1131 then s7 else s_2
-  s2935 :: SBool = s493 ^ s2934
-  s2936 :: SBool = if s1163 then s2935 else s2934
-  s2937 :: SBool = s463 ^ s2936
-  s2938 :: SBool = if s1195 then s2937 else s2936
-  s2939 :: SBool = s435 ^ s2938
-  s2940 :: SBool = if s1227 then s2939 else s2938
-  s2941 :: SBool = s409 ^ s2940
-  s2942 :: SBool = if s1259 then s2941 else s2940
-  s2943 :: SBool = s385 ^ s2942
-  s2944 :: SBool = if s1291 then s2943 else s2942
-  s2945 :: SBool = s363 ^ s2944
-  s2946 :: SBool = if s1323 then s2945 else s2944
-  s2947 :: SBool = s343 ^ s2946
-  s2948 :: SBool = if s1355 then s2947 else s2946
-  s2949 :: SBool = s325 ^ s2948
-  s2950 :: SBool = if s1387 then s2949 else s2948
-  s2951 :: SBool = s309 ^ s2950
-  s2952 :: SBool = if s1419 then s2951 else s2950
-  s2953 :: SBool = s295 ^ s2952
-  s2954 :: SBool = if s1451 then s2953 else s2952
-  s2955 :: SBool = s283 ^ s2954
-  s2956 :: SBool = if s1483 then s2955 else s2954
-  s2957 :: SBool = s273 ^ s2956
-  s2958 :: SBool = if s1515 then s2957 else s2956
-  s2959 :: SBool = s265 ^ s2958
-  s2960 :: SBool = if s1547 then s2959 else s2958
-  s2961 :: SBool = if s2426 then s7 else s_2
-  s2962 :: SBool = s493 ^ s2961
-  s2963 :: SBool = if s2458 then s2962 else s2961
-  s2964 :: SBool = s463 ^ s2963
-  s2965 :: SBool = if s2490 then s2964 else s2963
-  s2966 :: SBool = s435 ^ s2965
-  s2967 :: SBool = if s2522 then s2966 else s2965
-  s2968 :: SBool = s409 ^ s2967
-  s2969 :: SBool = if s2554 then s2968 else s2967
-  s2970 :: SBool = s385 ^ s2969
-  s2971 :: SBool = if s2586 then s2970 else s2969
-  s2972 :: SBool = s363 ^ s2971
-  s2973 :: SBool = if s2618 then s2972 else s2971
-  s2974 :: SBool = s343 ^ s2973
-  s2975 :: SBool = if s2650 then s2974 else s2973
-  s2976 :: SBool = s325 ^ s2975
-  s2977 :: SBool = if s2682 then s2976 else s2975
-  s2978 :: SBool = s309 ^ s2977
-  s2979 :: SBool = if s2714 then s2978 else s2977
-  s2980 :: SBool = s295 ^ s2979
-  s2981 :: SBool = if s2746 then s2980 else s2979
-  s2982 :: SBool = s283 ^ s2981
-  s2983 :: SBool = if s2778 then s2982 else s2981
-  s2984 :: SBool = s273 ^ s2983
-  s2985 :: SBool = if s2810 then s2984 else s2983
-  s2986 :: SBool = s265 ^ s2985
-  s2987 :: SBool = if s2842 then s2986 else s2985
-  s2988 :: SBool = s2960 ^ s2987
-  s2989 :: SBool = if s1163 then s7 else s_2
-  s2990 :: SBool = s493 ^ s2989
-  s2991 :: SBool = if s1195 then s2990 else s2989
-  s2992 :: SBool = s463 ^ s2991
-  s2993 :: SBool = if s1227 then s2992 else s2991
-  s2994 :: SBool = s435 ^ s2993
-  s2995 :: SBool = if s1259 then s2994 else s2993
-  s2996 :: SBool = s409 ^ s2995
-  s2997 :: SBool = if s1291 then s2996 else s2995
-  s2998 :: SBool = s385 ^ s2997
-  s2999 :: SBool = if s1323 then s2998 else s2997
-  s3000 :: SBool = s363 ^ s2999
-  s3001 :: SBool = if s1355 then s3000 else s2999
-  s3002 :: SBool = s343 ^ s3001
-  s3003 :: SBool = if s1387 then s3002 else s3001
-  s3004 :: SBool = s325 ^ s3003
-  s3005 :: SBool = if s1419 then s3004 else s3003
-  s3006 :: SBool = s309 ^ s3005
-  s3007 :: SBool = if s1451 then s3006 else s3005
-  s3008 :: SBool = s295 ^ s3007
-  s3009 :: SBool = if s1483 then s3008 else s3007
-  s3010 :: SBool = s283 ^ s3009
-  s3011 :: SBool = if s1515 then s3010 else s3009
-  s3012 :: SBool = s273 ^ s3011
-  s3013 :: SBool = if s1547 then s3012 else s3011
-  s3014 :: SBool = if s2458 then s7 else s_2
-  s3015 :: SBool = s493 ^ s3014
-  s3016 :: SBool = if s2490 then s3015 else s3014
-  s3017 :: SBool = s463 ^ s3016
-  s3018 :: SBool = if s2522 then s3017 else s3016
-  s3019 :: SBool = s435 ^ s3018
-  s3020 :: SBool = if s2554 then s3019 else s3018
-  s3021 :: SBool = s409 ^ s3020
-  s3022 :: SBool = if s2586 then s3021 else s3020
-  s3023 :: SBool = s385 ^ s3022
-  s3024 :: SBool = if s2618 then s3023 else s3022
-  s3025 :: SBool = s363 ^ s3024
-  s3026 :: SBool = if s2650 then s3025 else s3024
-  s3027 :: SBool = s343 ^ s3026
-  s3028 :: SBool = if s2682 then s3027 else s3026
-  s3029 :: SBool = s325 ^ s3028
-  s3030 :: SBool = if s2714 then s3029 else s3028
-  s3031 :: SBool = s309 ^ s3030
-  s3032 :: SBool = if s2746 then s3031 else s3030
-  s3033 :: SBool = s295 ^ s3032
-  s3034 :: SBool = if s2778 then s3033 else s3032
-  s3035 :: SBool = s283 ^ s3034
-  s3036 :: SBool = if s2810 then s3035 else s3034
-  s3037 :: SBool = s273 ^ s3036
-  s3038 :: SBool = if s2842 then s3037 else s3036
-  s3039 :: SBool = s3013 ^ s3038
-  s3040 :: SBool = if s1195 then s7 else s_2
-  s3041 :: SBool = s493 ^ s3040
-  s3042 :: SBool = if s1227 then s3041 else s3040
-  s3043 :: SBool = s463 ^ s3042
-  s3044 :: SBool = if s1259 then s3043 else s3042
-  s3045 :: SBool = s435 ^ s3044
-  s3046 :: SBool = if s1291 then s3045 else s3044
-  s3047 :: SBool = s409 ^ s3046
-  s3048 :: SBool = if s1323 then s3047 else s3046
-  s3049 :: SBool = s385 ^ s3048
-  s3050 :: SBool = if s1355 then s3049 else s3048
-  s3051 :: SBool = s363 ^ s3050
-  s3052 :: SBool = if s1387 then s3051 else s3050
-  s3053 :: SBool = s343 ^ s3052
-  s3054 :: SBool = if s1419 then s3053 else s3052
-  s3055 :: SBool = s325 ^ s3054
-  s3056 :: SBool = if s1451 then s3055 else s3054
-  s3057 :: SBool = s309 ^ s3056
-  s3058 :: SBool = if s1483 then s3057 else s3056
-  s3059 :: SBool = s295 ^ s3058
-  s3060 :: SBool = if s1515 then s3059 else s3058
-  s3061 :: SBool = s283 ^ s3060
-  s3062 :: SBool = if s1547 then s3061 else s3060
-  s3063 :: SBool = if s2490 then s7 else s_2
-  s3064 :: SBool = s493 ^ s3063
-  s3065 :: SBool = if s2522 then s3064 else s3063
-  s3066 :: SBool = s463 ^ s3065
-  s3067 :: SBool = if s2554 then s3066 else s3065
-  s3068 :: SBool = s435 ^ s3067
-  s3069 :: SBool = if s2586 then s3068 else s3067
-  s3070 :: SBool = s409 ^ s3069
-  s3071 :: SBool = if s2618 then s3070 else s3069
-  s3072 :: SBool = s385 ^ s3071
-  s3073 :: SBool = if s2650 then s3072 else s3071
-  s3074 :: SBool = s363 ^ s3073
-  s3075 :: SBool = if s2682 then s3074 else s3073
-  s3076 :: SBool = s343 ^ s3075
-  s3077 :: SBool = if s2714 then s3076 else s3075
-  s3078 :: SBool = s325 ^ s3077
-  s3079 :: SBool = if s2746 then s3078 else s3077
-  s3080 :: SBool = s309 ^ s3079
-  s3081 :: SBool = if s2778 then s3080 else s3079
-  s3082 :: SBool = s295 ^ s3081
-  s3083 :: SBool = if s2810 then s3082 else s3081
-  s3084 :: SBool = s283 ^ s3083
-  s3085 :: SBool = if s2842 then s3084 else s3083
-  s3086 :: SBool = s3062 ^ s3085
-  s3087 :: SBool = if s1227 then s7 else s_2
-  s3088 :: SBool = s493 ^ s3087
-  s3089 :: SBool = if s1259 then s3088 else s3087
-  s3090 :: SBool = s463 ^ s3089
-  s3091 :: SBool = if s1291 then s3090 else s3089
-  s3092 :: SBool = s435 ^ s3091
-  s3093 :: SBool = if s1323 then s3092 else s3091
-  s3094 :: SBool = s409 ^ s3093
-  s3095 :: SBool = if s1355 then s3094 else s3093
-  s3096 :: SBool = s385 ^ s3095
-  s3097 :: SBool = if s1387 then s3096 else s3095
-  s3098 :: SBool = s363 ^ s3097
-  s3099 :: SBool = if s1419 then s3098 else s3097
-  s3100 :: SBool = s343 ^ s3099
-  s3101 :: SBool = if s1451 then s3100 else s3099
-  s3102 :: SBool = s325 ^ s3101
-  s3103 :: SBool = if s1483 then s3102 else s3101
-  s3104 :: SBool = s309 ^ s3103
-  s3105 :: SBool = if s1515 then s3104 else s3103
-  s3106 :: SBool = s295 ^ s3105
-  s3107 :: SBool = if s1547 then s3106 else s3105
-  s3108 :: SBool = if s2522 then s7 else s_2
-  s3109 :: SBool = s493 ^ s3108
-  s3110 :: SBool = if s2554 then s3109 else s3108
-  s3111 :: SBool = s463 ^ s3110
-  s3112 :: SBool = if s2586 then s3111 else s3110
-  s3113 :: SBool = s435 ^ s3112
-  s3114 :: SBool = if s2618 then s3113 else s3112
-  s3115 :: SBool = s409 ^ s3114
-  s3116 :: SBool = if s2650 then s3115 else s3114
-  s3117 :: SBool = s385 ^ s3116
-  s3118 :: SBool = if s2682 then s3117 else s3116
-  s3119 :: SBool = s363 ^ s3118
-  s3120 :: SBool = if s2714 then s3119 else s3118
-  s3121 :: SBool = s343 ^ s3120
-  s3122 :: SBool = if s2746 then s3121 else s3120
-  s3123 :: SBool = s325 ^ s3122
-  s3124 :: SBool = if s2778 then s3123 else s3122
-  s3125 :: SBool = s309 ^ s3124
-  s3126 :: SBool = if s2810 then s3125 else s3124
-  s3127 :: SBool = s295 ^ s3126
-  s3128 :: SBool = if s2842 then s3127 else s3126
-  s3129 :: SBool = s3107 ^ s3128
-  s3130 :: SBool = if s1259 then s7 else s_2
-  s3131 :: SBool = s493 ^ s3130
-  s3132 :: SBool = if s1291 then s3131 else s3130
-  s3133 :: SBool = s463 ^ s3132
-  s3134 :: SBool = if s1323 then s3133 else s3132
-  s3135 :: SBool = s435 ^ s3134
-  s3136 :: SBool = if s1355 then s3135 else s3134
-  s3137 :: SBool = s409 ^ s3136
-  s3138 :: SBool = if s1387 then s3137 else s3136
-  s3139 :: SBool = s385 ^ s3138
-  s3140 :: SBool = if s1419 then s3139 else s3138
-  s3141 :: SBool = s363 ^ s3140
-  s3142 :: SBool = if s1451 then s3141 else s3140
-  s3143 :: SBool = s343 ^ s3142
-  s3144 :: SBool = if s1483 then s3143 else s3142
-  s3145 :: SBool = s325 ^ s3144
-  s3146 :: SBool = if s1515 then s3145 else s3144
-  s3147 :: SBool = s309 ^ s3146
-  s3148 :: SBool = if s1547 then s3147 else s3146
-  s3149 :: SBool = if s2554 then s7 else s_2
-  s3150 :: SBool = s493 ^ s3149
-  s3151 :: SBool = if s2586 then s3150 else s3149
-  s3152 :: SBool = s463 ^ s3151
-  s3153 :: SBool = if s2618 then s3152 else s3151
-  s3154 :: SBool = s435 ^ s3153
-  s3155 :: SBool = if s2650 then s3154 else s3153
-  s3156 :: SBool = s409 ^ s3155
-  s3157 :: SBool = if s2682 then s3156 else s3155
-  s3158 :: SBool = s385 ^ s3157
-  s3159 :: SBool = if s2714 then s3158 else s3157
-  s3160 :: SBool = s363 ^ s3159
-  s3161 :: SBool = if s2746 then s3160 else s3159
-  s3162 :: SBool = s343 ^ s3161
-  s3163 :: SBool = if s2778 then s3162 else s3161
-  s3164 :: SBool = s325 ^ s3163
-  s3165 :: SBool = if s2810 then s3164 else s3163
-  s3166 :: SBool = s309 ^ s3165
-  s3167 :: SBool = if s2842 then s3166 else s3165
-  s3168 :: SBool = s3148 ^ s3167
-  s3169 :: SBool = if s1291 then s7 else s_2
-  s3170 :: SBool = s493 ^ s3169
-  s3171 :: SBool = if s1323 then s3170 else s3169
-  s3172 :: SBool = s463 ^ s3171
-  s3173 :: SBool = if s1355 then s3172 else s3171
-  s3174 :: SBool = s435 ^ s3173
-  s3175 :: SBool = if s1387 then s3174 else s3173
-  s3176 :: SBool = s409 ^ s3175
-  s3177 :: SBool = if s1419 then s3176 else s3175
-  s3178 :: SBool = s385 ^ s3177
-  s3179 :: SBool = if s1451 then s3178 else s3177
-  s3180 :: SBool = s363 ^ s3179
-  s3181 :: SBool = if s1483 then s3180 else s3179
-  s3182 :: SBool = s343 ^ s3181
-  s3183 :: SBool = if s1515 then s3182 else s3181
-  s3184 :: SBool = s325 ^ s3183
-  s3185 :: SBool = if s1547 then s3184 else s3183
-  s3186 :: SBool = if s2586 then s7 else s_2
-  s3187 :: SBool = s493 ^ s3186
-  s3188 :: SBool = if s2618 then s3187 else s3186
-  s3189 :: SBool = s463 ^ s3188
-  s3190 :: SBool = if s2650 then s3189 else s3188
-  s3191 :: SBool = s435 ^ s3190
-  s3192 :: SBool = if s2682 then s3191 else s3190
-  s3193 :: SBool = s409 ^ s3192
-  s3194 :: SBool = if s2714 then s3193 else s3192
-  s3195 :: SBool = s385 ^ s3194
-  s3196 :: SBool = if s2746 then s3195 else s3194
-  s3197 :: SBool = s363 ^ s3196
-  s3198 :: SBool = if s2778 then s3197 else s3196
-  s3199 :: SBool = s343 ^ s3198
-  s3200 :: SBool = if s2810 then s3199 else s3198
-  s3201 :: SBool = s325 ^ s3200
-  s3202 :: SBool = if s2842 then s3201 else s3200
-  s3203 :: SBool = s3185 ^ s3202
-  s3204 :: SBool = if s1323 then s7 else s_2
-  s3205 :: SBool = s493 ^ s3204
-  s3206 :: SBool = if s1355 then s3205 else s3204
-  s3207 :: SBool = s463 ^ s3206
-  s3208 :: SBool = if s1387 then s3207 else s3206
-  s3209 :: SBool = s435 ^ s3208
-  s3210 :: SBool = if s1419 then s3209 else s3208
-  s3211 :: SBool = s409 ^ s3210
-  s3212 :: SBool = if s1451 then s3211 else s3210
-  s3213 :: SBool = s385 ^ s3212
-  s3214 :: SBool = if s1483 then s3213 else s3212
-  s3215 :: SBool = s363 ^ s3214
-  s3216 :: SBool = if s1515 then s3215 else s3214
-  s3217 :: SBool = s343 ^ s3216
-  s3218 :: SBool = if s1547 then s3217 else s3216
-  s3219 :: SBool = if s2618 then s7 else s_2
-  s3220 :: SBool = s493 ^ s3219
-  s3221 :: SBool = if s2650 then s3220 else s3219
-  s3222 :: SBool = s463 ^ s3221
-  s3223 :: SBool = if s2682 then s3222 else s3221
-  s3224 :: SBool = s435 ^ s3223
-  s3225 :: SBool = if s2714 then s3224 else s3223
-  s3226 :: SBool = s409 ^ s3225
-  s3227 :: SBool = if s2746 then s3226 else s3225
-  s3228 :: SBool = s385 ^ s3227
-  s3229 :: SBool = if s2778 then s3228 else s3227
-  s3230 :: SBool = s363 ^ s3229
-  s3231 :: SBool = if s2810 then s3230 else s3229
-  s3232 :: SBool = s343 ^ s3231
-  s3233 :: SBool = if s2842 then s3232 else s3231
-  s3234 :: SBool = s3218 ^ s3233
-  s3235 :: SBool = if s1355 then s7 else s_2
-  s3236 :: SBool = s493 ^ s3235
-  s3237 :: SBool = if s1387 then s3236 else s3235
-  s3238 :: SBool = s463 ^ s3237
-  s3239 :: SBool = if s1419 then s3238 else s3237
-  s3240 :: SBool = s435 ^ s3239
-  s3241 :: SBool = if s1451 then s3240 else s3239
-  s3242 :: SBool = s409 ^ s3241
-  s3243 :: SBool = if s1483 then s3242 else s3241
-  s3244 :: SBool = s385 ^ s3243
-  s3245 :: SBool = if s1515 then s3244 else s3243
-  s3246 :: SBool = s363 ^ s3245
-  s3247 :: SBool = if s1547 then s3246 else s3245
-  s3248 :: SBool = if s2650 then s7 else s_2
-  s3249 :: SBool = s493 ^ s3248
-  s3250 :: SBool = if s2682 then s3249 else s3248
-  s3251 :: SBool = s463 ^ s3250
-  s3252 :: SBool = if s2714 then s3251 else s3250
-  s3253 :: SBool = s435 ^ s3252
-  s3254 :: SBool = if s2746 then s3253 else s3252
-  s3255 :: SBool = s409 ^ s3254
-  s3256 :: SBool = if s2778 then s3255 else s3254
-  s3257 :: SBool = s385 ^ s3256
-  s3258 :: SBool = if s2810 then s3257 else s3256
-  s3259 :: SBool = s363 ^ s3258
-  s3260 :: SBool = if s2842 then s3259 else s3258
-  s3261 :: SBool = s3247 ^ s3260
-  s3262 :: SBool = if s1387 then s7 else s_2
-  s3263 :: SBool = s493 ^ s3262
-  s3264 :: SBool = if s1419 then s3263 else s3262
-  s3265 :: SBool = s463 ^ s3264
-  s3266 :: SBool = if s1451 then s3265 else s3264
-  s3267 :: SBool = s435 ^ s3266
-  s3268 :: SBool = if s1483 then s3267 else s3266
-  s3269 :: SBool = s409 ^ s3268
-  s3270 :: SBool = if s1515 then s3269 else s3268
-  s3271 :: SBool = s385 ^ s3270
-  s3272 :: SBool = if s1547 then s3271 else s3270
-  s3273 :: SBool = if s2682 then s7 else s_2
-  s3274 :: SBool = s493 ^ s3273
-  s3275 :: SBool = if s2714 then s3274 else s3273
-  s3276 :: SBool = s463 ^ s3275
-  s3277 :: SBool = if s2746 then s3276 else s3275
-  s3278 :: SBool = s435 ^ s3277
-  s3279 :: SBool = if s2778 then s3278 else s3277
-  s3280 :: SBool = s409 ^ s3279
-  s3281 :: SBool = if s2810 then s3280 else s3279
-  s3282 :: SBool = s385 ^ s3281
-  s3283 :: SBool = if s2842 then s3282 else s3281
-  s3284 :: SBool = s3272 ^ s3283
-  s3285 :: SBool = if s1419 then s7 else s_2
-  s3286 :: SBool = s493 ^ s3285
-  s3287 :: SBool = if s1451 then s3286 else s3285
-  s3288 :: SBool = s463 ^ s3287
-  s3289 :: SBool = if s1483 then s3288 else s3287
-  s3290 :: SBool = s435 ^ s3289
-  s3291 :: SBool = if s1515 then s3290 else s3289
-  s3292 :: SBool = s409 ^ s3291
-  s3293 :: SBool = if s1547 then s3292 else s3291
-  s3294 :: SBool = if s2714 then s7 else s_2
-  s3295 :: SBool = s493 ^ s3294
-  s3296 :: SBool = if s2746 then s3295 else s3294
-  s3297 :: SBool = s463 ^ s3296
-  s3298 :: SBool = if s2778 then s3297 else s3296
-  s3299 :: SBool = s435 ^ s3298
-  s3300 :: SBool = if s2810 then s3299 else s3298
-  s3301 :: SBool = s409 ^ s3300
-  s3302 :: SBool = if s2842 then s3301 else s3300
-  s3303 :: SBool = s3293 ^ s3302
-  s3304 :: SBool = if s1451 then s7 else s_2
-  s3305 :: SBool = s493 ^ s3304
-  s3306 :: SBool = if s1483 then s3305 else s3304
-  s3307 :: SBool = s463 ^ s3306
-  s3308 :: SBool = if s1515 then s3307 else s3306
-  s3309 :: SBool = s435 ^ s3308
-  s3310 :: SBool = if s1547 then s3309 else s3308
-  s3311 :: SBool = if s2746 then s7 else s_2
-  s3312 :: SBool = s493 ^ s3311
-  s3313 :: SBool = if s2778 then s3312 else s3311
-  s3314 :: SBool = s463 ^ s3313
-  s3315 :: SBool = if s2810 then s3314 else s3313
-  s3316 :: SBool = s435 ^ s3315
-  s3317 :: SBool = if s2842 then s3316 else s3315
-  s3318 :: SBool = s3310 ^ s3317
-  s3319 :: SBool = if s1483 then s7 else s_2
-  s3320 :: SBool = s493 ^ s3319
-  s3321 :: SBool = if s1515 then s3320 else s3319
-  s3322 :: SBool = s463 ^ s3321
-  s3323 :: SBool = if s1547 then s3322 else s3321
-  s3324 :: SBool = if s2778 then s7 else s_2
-  s3325 :: SBool = s493 ^ s3324
-  s3326 :: SBool = if s2810 then s3325 else s3324
-  s3327 :: SBool = s463 ^ s3326
-  s3328 :: SBool = if s2842 then s3327 else s3326
-  s3329 :: SBool = s3323 ^ s3328
-  s3330 :: SBool = if s1515 then s7 else s_2
-  s3331 :: SBool = s493 ^ s3330
-  s3332 :: SBool = if s1547 then s3331 else s3330
-  s3333 :: SBool = if s2810 then s7 else s_2
-  s3334 :: SBool = s493 ^ s3333
-  s3335 :: SBool = if s2842 then s3334 else s3333
-  s3336 :: SBool = s3332 ^ s3335
-  s3337 :: SBool = if s1547 then s7 else s_2
-  s3338 :: SBool = if s2842 then s7 else s_2
-  s3339 :: SBool = s3337 ^ s3338
-  s3341 :: SWord8 = if s3339 then s18 else s3340
-  s3342 :: SWord8 = s18 + s3341
-  s3343 :: SWord8 = if s3336 then s3342 else s3341
-  s3344 :: SWord8 = s18 + s3343
-  s3345 :: SWord8 = if s3329 then s3344 else s3343
-  s3346 :: SWord8 = s18 + s3345
-  s3347 :: SWord8 = if s3318 then s3346 else s3345
-  s3348 :: SWord8 = s18 + s3347
-  s3349 :: SWord8 = if s3303 then s3348 else s3347
-  s3350 :: SWord8 = s18 + s3349
-  s3351 :: SWord8 = if s3284 then s3350 else s3349
-  s3352 :: SWord8 = s18 + s3351
-  s3353 :: SWord8 = if s3261 then s3352 else s3351
-  s3354 :: SWord8 = s18 + s3353
-  s3355 :: SWord8 = if s3234 then s3354 else s3353
-  s3356 :: SWord8 = s18 + s3355
-  s3357 :: SWord8 = if s3203 then s3356 else s3355
-  s3358 :: SWord8 = s18 + s3357
-  s3359 :: SWord8 = if s3168 then s3358 else s3357
-  s3360 :: SWord8 = s18 + s3359
-  s3361 :: SWord8 = if s3129 then s3360 else s3359
-  s3362 :: SWord8 = s18 + s3361
-  s3363 :: SWord8 = if s3086 then s3362 else s3361
-  s3364 :: SWord8 = s18 + s3363
-  s3365 :: SWord8 = if s3039 then s3364 else s3363
-  s3366 :: SWord8 = s18 + s3365
-  s3367 :: SWord8 = if s2988 then s3366 else s3365
-  s3368 :: SWord8 = s18 + s3367
-  s3369 :: SWord8 = if s2933 then s3368 else s3367
-  s3370 :: SWord8 = s18 + s3369
-  s3371 :: SWord8 = if s2874 then s3370 else s3369
-  s3372 :: SWord8 = s18 + s3371
-  s3373 :: SWord8 = if s253 then s3372 else s3371
-  s3374 :: SWord8 = s18 + s3373
-  s3375 :: SWord8 = if s248 then s3374 else s3373
-  s3376 :: SWord8 = s18 + s3375
-  s3377 :: SWord8 = if s243 then s3376 else s3375
-  s3378 :: SWord8 = s18 + s3377
-  s3379 :: SWord8 = if s238 then s3378 else s3377
-  s3380 :: SWord8 = s18 + s3379
-  s3381 :: SWord8 = if s233 then s3380 else s3379
-  s3382 :: SWord8 = s18 + s3381
-  s3383 :: SWord8 = if s228 then s3382 else s3381
-  s3384 :: SWord8 = s18 + s3383
-  s3385 :: SWord8 = if s223 then s3384 else s3383
-  s3386 :: SWord8 = s18 + s3385
-  s3387 :: SWord8 = if s218 then s3386 else s3385
-  s3388 :: SWord8 = s18 + s3387
-  s3389 :: SWord8 = if s213 then s3388 else s3387
-  s3390 :: SWord8 = s18 + s3389
-  s3391 :: SWord8 = if s208 then s3390 else s3389
-  s3392 :: SWord8 = s18 + s3391
-  s3393 :: SWord8 = if s203 then s3392 else s3391
-  s3394 :: SWord8 = s18 + s3393
-  s3395 :: SWord8 = if s198 then s3394 else s3393
-  s3396 :: SWord8 = s18 + s3395
-  s3397 :: SWord8 = if s193 then s3396 else s3395
-  s3398 :: SWord8 = s18 + s3397
-  s3399 :: SWord8 = if s188 then s3398 else s3397
-  s3400 :: SWord8 = s18 + s3399
-  s3401 :: SWord8 = if s183 then s3400 else s3399
-  s3402 :: SWord8 = s18 + s3401
-  s3403 :: SWord8 = if s178 then s3402 else s3401
-  s3404 :: SWord8 = s18 + s3403
-  s3405 :: SWord8 = if s173 then s3404 else s3403
-  s3406 :: SWord8 = s18 + s3405
-  s3407 :: SWord8 = if s168 then s3406 else s3405
-  s3408 :: SWord8 = s18 + s3407
-  s3409 :: SWord8 = if s163 then s3408 else s3407
-  s3410 :: SWord8 = s18 + s3409
-  s3411 :: SWord8 = if s158 then s3410 else s3409
-  s3412 :: SWord8 = s18 + s3411
-  s3413 :: SWord8 = if s153 then s3412 else s3411
-  s3414 :: SWord8 = s18 + s3413
-  s3415 :: SWord8 = if s148 then s3414 else s3413
-  s3416 :: SWord8 = s18 + s3415
-  s3417 :: SWord8 = if s143 then s3416 else s3415
-  s3418 :: SWord8 = s18 + s3417
-  s3419 :: SWord8 = if s138 then s3418 else s3417
-  s3420 :: SWord8 = s18 + s3419
-  s3421 :: SWord8 = if s133 then s3420 else s3419
-  s3422 :: SWord8 = s18 + s3421
-  s3423 :: SWord8 = if s128 then s3422 else s3421
-  s3424 :: SWord8 = s18 + s3423
-  s3425 :: SWord8 = if s123 then s3424 else s3423
-  s3426 :: SWord8 = s18 + s3425
-  s3427 :: SWord8 = if s118 then s3426 else s3425
-  s3428 :: SWord8 = s18 + s3427
-  s3429 :: SWord8 = if s113 then s3428 else s3427
-  s3430 :: SWord8 = s18 + s3429
-  s3431 :: SWord8 = if s108 then s3430 else s3429
-  s3432 :: SWord8 = s18 + s3431
-  s3433 :: SWord8 = if s103 then s3432 else s3431
-  s3434 :: SWord8 = s18 + s3433
-  s3435 :: SWord8 = if s98 then s3434 else s3433
-  s3436 :: SWord8 = s18 + s3435
-  s3437 :: SWord8 = if s93 then s3436 else s3435
-  s3438 :: SWord8 = s18 + s3437
-  s3439 :: SWord8 = if s88 then s3438 else s3437
-  s3440 :: SWord8 = s18 + s3439
-  s3441 :: SWord8 = if s83 then s3440 else s3439
-  s3442 :: SWord8 = s18 + s3441
-  s3443 :: SWord8 = if s78 then s3442 else s3441
-  s3444 :: SWord8 = s18 + s3443
-  s3445 :: SWord8 = if s73 then s3444 else s3443
-  s3446 :: SWord8 = s18 + s3445
-  s3447 :: SWord8 = if s68 then s3446 else s3445
-  s3448 :: SWord8 = s18 + s3447
-  s3449 :: SWord8 = if s63 then s3448 else s3447
-  s3450 :: SWord8 = s18 + s3449
-  s3451 :: SWord8 = if s58 then s3450 else s3449
-  s3452 :: SWord8 = s18 + s3451
-  s3453 :: SWord8 = if s53 then s3452 else s3451
-  s3454 :: SWord8 = s18 + s3453
-  s3455 :: SWord8 = if s48 then s3454 else s3453
-  s3456 :: SWord8 = s18 + s3455
-  s3457 :: SWord8 = if s43 then s3456 else s3455
-  s3458 :: SWord8 = s18 + s3457
-  s3459 :: SWord8 = if s38 then s3458 else s3457
-  s3460 :: SWord8 = s18 + s3459
-  s3461 :: SWord8 = if s33 then s3460 else s3459
-  s3462 :: SWord8 = s18 + s3461
-  s3463 :: SWord8 = if s28 then s3462 else s3461
-  s3464 :: SWord8 = s18 + s3463
-  s3465 :: SWord8 = if s23 then s3464 else s3463
-  s3466 :: SWord8 = s18 + s3465
-  s3467 :: SWord8 = if s17 then s3466 else s3465
-  s3469 :: SBool = s3467 >= s3468
-  s3470 :: SBool = s12 | s3469
-  s3471 :: SBool = s7 & s3470
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s3471
diff --git a/SBVUnitTest/GoldFiles/crcUSB5_1.gold b/SBVUnitTest/GoldFiles/crcUSB5_1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/crcUSB5_1.gold
+++ /dev/null
@@ -1,181 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for crcUSB5. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: crcUSB5_driver
-
-crcUSB5.o: crcUSB5.c crcUSB5.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-crcUSB5_driver.o: crcUSB5_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-crcUSB5_driver: crcUSB5.o crcUSB5_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f crcUSB5_driver
-== END: "Makefile" ==================
-== BEGIN: "crcUSB5.h" ================
-/* Header file for crcUSB5. Automatically generated by SBV. Do not edit! */
-
-#ifndef __crcUSB5__HEADER_INCLUDED__
-#define __crcUSB5__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord16 crcUSB5(const SWord16 msg);
-
-#endif /* __crcUSB5__HEADER_INCLUDED__ */
-== END: "crcUSB5.h" ==================
-== BEGIN: "crcUSB5_driver.c" ================
-/* Example driver program for crcUSB5. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "crcUSB5.h"
-
-int main(void)
-{
-  const SWord16 __result = crcUSB5(0xfedcU);
-
-  printf("crcUSB5(0xfedcU) = 0x%04"PRIx16"U\n", __result);
-
-  return 0;
-}
-== END: "crcUSB5_driver.c" ==================
-== BEGIN: "crcUSB5.c" ================
-/* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
-
-#include "crcUSB5.h"
-
-SWord16 crcUSB5(const SWord16 msg)
-{
-  const SWord16 s0 = msg;
-  const SBool   s1 = (SBool) ((s0 >> 10) & 1);
-  const SBool   s3 = s1 != false;
-  const SBool   s4 = (SBool) ((s0 >> 9) & 1);
-  const SBool   s5 = false != s4;
-  const SBool   s6 = (SBool) ((s0 >> 8) & 1);
-  const SBool   s7 = false != s6;
-  const SBool   s8 = (SBool) ((s0 >> 7) & 1);
-  const SBool   s9 = false != s8;
-  const SBool   s10 = (SBool) ((s0 >> 6) & 1);
-  const SBool   s11 = false != s10;
-  const SBool   s12 = (SBool) ((s0 >> 5) & 1);
-  const SBool   s13 = false != s12;
-  const SBool   s14 = (SBool) ((s0 >> 4) & 1);
-  const SBool   s15 = false != s14;
-  const SBool   s16 = (SBool) ((s0 >> 3) & 1);
-  const SBool   s17 = false != s16;
-  const SBool   s18 = (SBool) ((s0 >> 2) & 1);
-  const SBool   s19 = false != s18;
-  const SBool   s20 = (SBool) ((s0 >> 1) & 1);
-  const SBool   s21 = false != s20;
-  const SBool   s22 = (SBool) ((s0 >> 0) & 1);
-  const SBool   s23 = false != s22;
-  const SBool   s24 = !s9;
-  const SBool   s25 = s3 ? s24 : s9;
-  const SBool   s26 = !s11;
-  const SBool   s27 = s5 ? s26 : s11;
-  const SBool   s28 = !s13;
-  const SBool   s29 = s3 ? s28 : s13;
-  const SBool   s30 = !s29;
-  const SBool   s31 = s7 ? s30 : s29;
-  const SBool   s32 = !s15;
-  const SBool   s33 = s5 ? s32 : s15;
-  const SBool   s34 = !s33;
-  const SBool   s35 = s25 ? s34 : s33;
-  const SBool   s36 = !s17;
-  const SBool   s37 = s7 ? s36 : s17;
-  const SBool   s38 = !s37;
-  const SBool   s39 = s27 ? s38 : s37;
-  const SBool   s40 = !s19;
-  const SBool   s41 = s25 ? s40 : s19;
-  const SBool   s42 = !s41;
-  const SBool   s43 = s31 ? s42 : s41;
-  const SBool   s44 = !s21;
-  const SBool   s45 = s27 ? s44 : s21;
-  const SBool   s46 = !s45;
-  const SBool   s47 = s35 ? s46 : s45;
-  const SBool   s48 = !s23;
-  const SBool   s49 = s31 ? s48 : s23;
-  const SBool   s50 = !s49;
-  const SBool   s51 = s39 ? s50 : s49;
-  const SBool   s52 = !s35;
-  const SBool   s53 = s43 ? s52 : s35;
-  const SBool   s54 = !s39;
-  const SBool   s55 = s47 ? s54 : s39;
-  const SBool   s56 = !s43;
-  const SBool   s57 = s51 ? s56 : s43;
-  const SWord16 s60 = s51 ? 0x0001U : 0x0000U;
-  const SWord16 s62 = s60 | 0x0002U;
-  const SWord16 s63 = s47 ? s62 : s60;
-  const SWord16 s65 = s63 | 0x0004U;
-  const SWord16 s66 = s57 ? s65 : s63;
-  const SWord16 s68 = s66 | 0x0008U;
-  const SWord16 s69 = s55 ? s68 : s66;
-  const SWord16 s71 = s69 | 0x0010U;
-  const SWord16 s72 = s53 ? s71 : s69;
-  const SWord16 s74 = s72 | 0x0020U;
-  const SWord16 s75 = s23 ? s74 : s72;
-  const SWord16 s77 = s75 | 0x0040U;
-  const SWord16 s78 = s21 ? s77 : s75;
-  const SWord16 s80 = s78 | 0x0080U;
-  const SWord16 s81 = s19 ? s80 : s78;
-  const SWord16 s83 = s81 | 0x0100U;
-  const SWord16 s84 = s17 ? s83 : s81;
-  const SWord16 s86 = s84 | 0x0200U;
-  const SWord16 s87 = s15 ? s86 : s84;
-  const SWord16 s89 = s87 | 0x0400U;
-  const SWord16 s90 = s13 ? s89 : s87;
-  const SWord16 s92 = s90 | 0x0800U;
-  const SWord16 s93 = s11 ? s92 : s90;
-  const SWord16 s95 = s93 | 0x1000U;
-  const SWord16 s96 = s9 ? s95 : s93;
-  const SWord16 s98 = s96 | 0x2000U;
-  const SWord16 s99 = s7 ? s98 : s96;
-  const SWord16 s101 = s99 | 0x4000U;
-  const SWord16 s102 = s5 ? s101 : s99;
-  const SWord16 s104 = s102 | 0x8000U;
-  const SWord16 s105 = s3 ? s104 : s102;
-
-  return s105;
-}
-== END: "crcUSB5.c" ==================
diff --git a/SBVUnitTest/GoldFiles/crcUSB5_2.gold b/SBVUnitTest/GoldFiles/crcUSB5_2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/crcUSB5_2.gold
+++ /dev/null
@@ -1,225 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for crcUSB5. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: crcUSB5_driver
-
-crcUSB5.o: crcUSB5.c crcUSB5.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-crcUSB5_driver.o: crcUSB5_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-crcUSB5_driver: crcUSB5.o crcUSB5_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f crcUSB5_driver
-== END: "Makefile" ==================
-== BEGIN: "crcUSB5.h" ================
-/* Header file for crcUSB5. Automatically generated by SBV. Do not edit! */
-
-#ifndef __crcUSB5__HEADER_INCLUDED__
-#define __crcUSB5__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord16 crcUSB5(const SWord16 msg);
-
-#endif /* __crcUSB5__HEADER_INCLUDED__ */
-== END: "crcUSB5.h" ==================
-== BEGIN: "crcUSB5_driver.c" ================
-/* Example driver program for crcUSB5. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "crcUSB5.h"
-
-int main(void)
-{
-  const SWord16 __result = crcUSB5(0xfedcU);
-
-  printf("crcUSB5(0xfedcU) = 0x%04"PRIx16"U\n", __result);
-
-  return 0;
-}
-== END: "crcUSB5_driver.c" ==================
-== BEGIN: "crcUSB5.c" ================
-/* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
-
-#include "crcUSB5.h"
-
-SWord16 crcUSB5(const SWord16 msg)
-{
-  const SWord16 s0 = msg;
-  const SWord16 s1 = s0 << 5;
-  const SBool   s2 = (SBool) ((s1 >> 15) & 1);
-  const SBool   s4 = s2 != false;
-  const SBool   s5 = (SBool) ((s1 >> 14) & 1);
-  const SBool   s6 = false != s5;
-  const SBool   s7 = (SBool) ((s1 >> 13) & 1);
-  const SBool   s8 = false != s7;
-  const SBool   s9 = (SBool) ((s1 >> 12) & 1);
-  const SBool   s10 = false != s9;
-  const SBool   s11 = !s10;
-  const SBool   s12 = s4 ? s11 : s10;
-  const SBool   s13 = (SBool) ((s1 >> 11) & 1);
-  const SBool   s14 = false != s13;
-  const SBool   s15 = !s14;
-  const SBool   s16 = s6 ? s15 : s14;
-  const SBool   s17 = (SBool) ((s1 >> 10) & 1);
-  const SBool   s18 = false != s17;
-  const SBool   s19 = !s18;
-  const SBool   s20 = s4 ? s19 : s18;
-  const SBool   s21 = !s20;
-  const SBool   s22 = s8 ? s21 : s20;
-  const SBool   s23 = (SBool) ((s1 >> 9) & 1);
-  const SBool   s24 = false != s23;
-  const SBool   s25 = !s24;
-  const SBool   s26 = s6 ? s25 : s24;
-  const SBool   s27 = !s26;
-  const SBool   s28 = s12 ? s27 : s26;
-  const SBool   s29 = (SBool) ((s1 >> 8) & 1);
-  const SBool   s30 = false != s29;
-  const SBool   s31 = !s30;
-  const SBool   s32 = s8 ? s31 : s30;
-  const SBool   s33 = !s32;
-  const SBool   s34 = s16 ? s33 : s32;
-  const SBool   s35 = (SBool) ((s1 >> 7) & 1);
-  const SBool   s36 = false != s35;
-  const SBool   s37 = !s36;
-  const SBool   s38 = s12 ? s37 : s36;
-  const SBool   s39 = !s38;
-  const SBool   s40 = s22 ? s39 : s38;
-  const SBool   s41 = (SBool) ((s1 >> 6) & 1);
-  const SBool   s42 = false != s41;
-  const SBool   s43 = !s42;
-  const SBool   s44 = s16 ? s43 : s42;
-  const SBool   s45 = !s44;
-  const SBool   s46 = s28 ? s45 : s44;
-  const SBool   s47 = (SBool) ((s1 >> 5) & 1);
-  const SBool   s48 = false != s47;
-  const SBool   s49 = !s48;
-  const SBool   s50 = s22 ? s49 : s48;
-  const SBool   s51 = !s50;
-  const SBool   s52 = s34 ? s51 : s50;
-  const SBool   s53 = !s4;
-  const SBool   s54 = s4 ? s53 : s4;
-  const SBool   s55 = !s6;
-  const SBool   s56 = s6 ? s55 : s6;
-  const SBool   s57 = !s8;
-  const SBool   s58 = s8 ? s57 : s8;
-  const SBool   s59 = !s12;
-  const SBool   s60 = s12 ? s59 : s12;
-  const SBool   s61 = !s16;
-  const SBool   s62 = s16 ? s61 : s16;
-  const SBool   s63 = !s22;
-  const SBool   s64 = s22 ? s63 : s22;
-  const SBool   s65 = !s28;
-  const SBool   s66 = s28 ? s65 : s28;
-  const SBool   s67 = !s34;
-  const SBool   s68 = s34 ? s67 : s34;
-  const SBool   s69 = !s40;
-  const SBool   s70 = s40 ? s69 : s40;
-  const SBool   s71 = !s46;
-  const SBool   s72 = s46 ? s71 : s46;
-  const SBool   s73 = !s52;
-  const SBool   s74 = s52 ? s73 : s52;
-  const SBool   s75 = (SBool) ((s1 >> 4) & 1);
-  const SBool   s76 = false != s75;
-  const SBool   s77 = !s76;
-  const SBool   s78 = s28 ? s77 : s76;
-  const SBool   s79 = !s78;
-  const SBool   s80 = s40 ? s79 : s78;
-  const SBool   s81 = (SBool) ((s1 >> 3) & 1);
-  const SBool   s82 = false != s81;
-  const SBool   s83 = !s82;
-  const SBool   s84 = s34 ? s83 : s82;
-  const SBool   s85 = !s84;
-  const SBool   s86 = s46 ? s85 : s84;
-  const SBool   s87 = (SBool) ((s1 >> 2) & 1);
-  const SBool   s88 = false != s87;
-  const SBool   s89 = !s88;
-  const SBool   s90 = s40 ? s89 : s88;
-  const SBool   s91 = !s90;
-  const SBool   s92 = s52 ? s91 : s90;
-  const SBool   s93 = (SBool) ((s1 >> 1) & 1);
-  const SBool   s94 = false != s93;
-  const SBool   s95 = !s94;
-  const SBool   s96 = s46 ? s95 : s94;
-  const SBool   s97 = (SBool) ((s1 >> 0) & 1);
-  const SBool   s98 = false != s97;
-  const SBool   s99 = !s98;
-  const SBool   s100 = s52 ? s99 : s98;
-  const SWord16 s103 = s100 ? 0x0001U : 0x0000U;
-  const SWord16 s105 = s103 | 0x0002U;
-  const SWord16 s106 = s96 ? s105 : s103;
-  const SWord16 s108 = s106 | 0x0004U;
-  const SWord16 s109 = s92 ? s108 : s106;
-  const SWord16 s111 = s109 | 0x0008U;
-  const SWord16 s112 = s86 ? s111 : s109;
-  const SWord16 s114 = s112 | 0x0010U;
-  const SWord16 s115 = s80 ? s114 : s112;
-  const SWord16 s117 = s115 | 0x0020U;
-  const SWord16 s118 = s74 ? s117 : s115;
-  const SWord16 s120 = s118 | 0x0040U;
-  const SWord16 s121 = s72 ? s120 : s118;
-  const SWord16 s123 = s121 | 0x0080U;
-  const SWord16 s124 = s70 ? s123 : s121;
-  const SWord16 s126 = s124 | 0x0100U;
-  const SWord16 s127 = s68 ? s126 : s124;
-  const SWord16 s129 = s127 | 0x0200U;
-  const SWord16 s130 = s66 ? s129 : s127;
-  const SWord16 s132 = s130 | 0x0400U;
-  const SWord16 s133 = s64 ? s132 : s130;
-  const SWord16 s135 = s133 | 0x0800U;
-  const SWord16 s136 = s62 ? s135 : s133;
-  const SWord16 s138 = s136 | 0x1000U;
-  const SWord16 s139 = s60 ? s138 : s136;
-  const SWord16 s141 = s139 | 0x2000U;
-  const SWord16 s142 = s58 ? s141 : s139;
-  const SWord16 s144 = s142 | 0x4000U;
-  const SWord16 s145 = s56 ? s144 : s142;
-  const SWord16 s147 = s145 | 0x8000U;
-  const SWord16 s148 = s54 ? s147 : s145;
-  const SWord16 s149 = s1 | s148;
-
-  return s149;
-}
-== END: "crcUSB5.c" ==================
diff --git a/SBVUnitTest/GoldFiles/dogCatMouse.gold b/SBVUnitTest/GoldFiles/dogCatMouse.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/dogCatMouse.gold
+++ /dev/null
@@ -1,5 +0,0 @@
-Solution #1:
-  dog   =  3 :: Integer
-  cat   = 41 :: Integer
-  mouse = 56 :: Integer
-This is the only solution.
diff --git a/SBVUnitTest/GoldFiles/euler185.gold b/SBVUnitTest/GoldFiles/euler185.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/euler185.gold
+++ /dev/null
@@ -1,18 +0,0 @@
-Solution #1:
-  s0  = 4 :: Word8
-  s1  = 6 :: Word8
-  s2  = 4 :: Word8
-  s3  = 0 :: Word8
-  s4  = 2 :: Word8
-  s5  = 6 :: Word8
-  s6  = 1 :: Word8
-  s7  = 5 :: Word8
-  s8  = 7 :: Word8
-  s9  = 1 :: Word8
-  s10 = 8 :: Word8
-  s11 = 4 :: Word8
-  s12 = 9 :: Word8
-  s13 = 5 :: Word8
-  s14 = 3 :: Word8
-  s15 = 3 :: Word8
-This is the only solution.
diff --git a/SBVUnitTest/GoldFiles/fib1.gold b/SBVUnitTest/GoldFiles/fib1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/fib1.gold
+++ /dev/null
@@ -1,222 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for fib1. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: fib1_driver
-
-fib1.o: fib1.c fib1.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fib1_driver.o: fib1_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fib1_driver: fib1.o fib1_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f fib1_driver
-== END: "Makefile" ==================
-== BEGIN: "fib1.h" ================
-/* Header file for fib1. Automatically generated by SBV. Do not edit! */
-
-#ifndef __fib1__HEADER_INCLUDED__
-#define __fib1__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord64 fib1(const SWord64 n);
-
-#endif /* __fib1__HEADER_INCLUDED__ */
-== END: "fib1.h" ==================
-== BEGIN: "fib1_driver.c" ================
-/* Example driver program for fib1. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "fib1.h"
-
-int main(void)
-{
-  const SWord64 __result = fib1(0x000000000000000cULL);
-
-  printf("fib1(0x000000000000000cULL) = 0x%016"PRIx64"ULL\n", __result);
-
-  return 0;
-}
-== END: "fib1_driver.c" ==================
-== BEGIN: "fib1.c" ================
-/* File: "fib1.c". Automatically generated by SBV. Do not edit! */
-
-#include "fib1.h"
-
-SWord64 fib1(const SWord64 n)
-{
-  const SWord64 s0 = n;
-  const SBool   s2 = s0 == 0x0000000000000000ULL;
-  const SBool   s4 = s0 == 0x0000000000000001ULL;
-  const SBool   s6 = s0 == 0x0000000000000002ULL;
-  const SBool   s8 = s0 == 0x0000000000000003ULL;
-  const SBool   s10 = s0 == 0x0000000000000004ULL;
-  const SBool   s12 = s0 == 0x0000000000000005ULL;
-  const SBool   s14 = s0 == 0x0000000000000006ULL;
-  const SBool   s17 = s0 == 0x0000000000000007ULL;
-  const SBool   s19 = s0 == 0x0000000000000008ULL;
-  const SBool   s22 = s0 == 0x0000000000000009ULL;
-  const SBool   s25 = s0 == 0x000000000000000aULL;
-  const SBool   s28 = s0 == 0x000000000000000bULL;
-  const SBool   s31 = s0 == 0x000000000000000cULL;
-  const SBool   s33 = s0 == 0x000000000000000dULL;
-  const SBool   s36 = s0 == 0x000000000000000eULL;
-  const SBool   s39 = s0 == 0x000000000000000fULL;
-  const SBool   s42 = s0 == 0x0000000000000010ULL;
-  const SBool   s45 = s0 == 0x0000000000000011ULL;
-  const SBool   s48 = s0 == 0x0000000000000012ULL;
-  const SBool   s51 = s0 == 0x0000000000000013ULL;
-  const SBool   s54 = s0 == 0x0000000000000014ULL;
-  const SBool   s56 = s0 == 0x0000000000000015ULL;
-  const SBool   s59 = s0 == 0x0000000000000016ULL;
-  const SBool   s62 = s0 == 0x0000000000000017ULL;
-  const SBool   s65 = s0 == 0x0000000000000018ULL;
-  const SBool   s68 = s0 == 0x0000000000000019ULL;
-  const SBool   s71 = s0 == 0x000000000000001aULL;
-  const SBool   s74 = s0 == 0x000000000000001bULL;
-  const SBool   s77 = s0 == 0x000000000000001cULL;
-  const SBool   s80 = s0 == 0x000000000000001dULL;
-  const SBool   s83 = s0 == 0x000000000000001eULL;
-  const SBool   s86 = s0 == 0x000000000000001fULL;
-  const SBool   s89 = s0 == 0x0000000000000020ULL;
-  const SBool   s92 = s0 == 0x0000000000000021ULL;
-  const SBool   s94 = s0 == 0x0000000000000022ULL;
-  const SBool   s97 = s0 == 0x0000000000000023ULL;
-  const SBool   s100 = s0 == 0x0000000000000024ULL;
-  const SBool   s103 = s0 == 0x0000000000000025ULL;
-  const SBool   s106 = s0 == 0x0000000000000026ULL;
-  const SBool   s109 = s0 == 0x0000000000000027ULL;
-  const SBool   s112 = s0 == 0x0000000000000028ULL;
-  const SBool   s115 = s0 == 0x0000000000000029ULL;
-  const SBool   s118 = s0 == 0x000000000000002aULL;
-  const SBool   s121 = s0 == 0x000000000000002bULL;
-  const SBool   s124 = s0 == 0x000000000000002cULL;
-  const SBool   s127 = s0 == 0x000000000000002dULL;
-  const SBool   s130 = s0 == 0x000000000000002eULL;
-  const SBool   s133 = s0 == 0x000000000000002fULL;
-  const SBool   s136 = s0 == 0x0000000000000030ULL;
-  const SBool   s139 = s0 == 0x0000000000000031ULL;
-  const SBool   s142 = s0 == 0x0000000000000032ULL;
-  const SBool   s145 = s0 == 0x0000000000000033ULL;
-  const SBool   s148 = s0 == 0x0000000000000034ULL;
-  const SBool   s151 = s0 == 0x0000000000000035ULL;
-  const SBool   s154 = s0 == 0x0000000000000036ULL;
-  const SBool   s156 = s0 == 0x0000000000000037ULL;
-  const SBool   s159 = s0 == 0x0000000000000038ULL;
-  const SBool   s162 = s0 == 0x0000000000000039ULL;
-  const SBool   s165 = s0 == 0x000000000000003aULL;
-  const SBool   s168 = s0 == 0x000000000000003bULL;
-  const SBool   s171 = s0 == 0x000000000000003cULL;
-  const SBool   s174 = s0 == 0x000000000000003dULL;
-  const SBool   s177 = s0 == 0x000000000000003eULL;
-  const SBool   s180 = s0 == 0x000000000000003fULL;
-  const SWord64 s183 = s180 ? 0x000005f6c7b064e2ULL : 0x000009a661ca20bbULL;
-  const SWord64 s184 = s177 ? 0x000003af9a19bbd9ULL : s183;
-  const SWord64 s185 = s174 ? 0x000002472d96a909ULL : s184;
-  const SWord64 s186 = s171 ? 0x000001686c8312d0ULL : s185;
-  const SWord64 s187 = s168 ? 0x000000dec1139639ULL : s186;
-  const SWord64 s188 = s165 ? 0x00000089ab6f7c97ULL : s187;
-  const SWord64 s189 = s162 ? 0x0000005515a419a2ULL : s188;
-  const SWord64 s190 = s159 ? 0x0000003495cb62f5ULL : s189;
-  const SWord64 s191 = s156 ? 0x000000207fd8b6adULL : s190;
-  const SWord64 s192 = s154 ? 0x0000001415f2ac48ULL : s191;
-  const SWord64 s193 = s151 ? 0x0000000c69e60a65ULL : s192;
-  const SWord64 s194 = s148 ? 0x00000007ac0ca1e3ULL : s193;
-  const SWord64 s195 = s145 ? 0x00000004bdd96882ULL : s194;
-  const SWord64 s196 = s142 ? 0x00000002ee333961ULL : s195;
-  const SWord64 s197 = s139 ? 0x00000001cfa62f21ULL : s196;
-  const SWord64 s198 = s136 ? 0x000000011e8d0a40ULL : s197;
-  const SWord64 s199 = s133 ? 0x00000000b11924e1ULL : s198;
-  const SWord64 s200 = s130 ? 0x000000006d73e55fULL : s199;
-  const SWord64 s201 = s127 ? 0x0000000043a53f82ULL : s200;
-  const SWord64 s202 = s124 ? 0x0000000029cea5ddULL : s201;
-  const SWord64 s203 = s121 ? 0x0000000019d699a5ULL : s202;
-  const SWord64 s204 = s118 ? 0x000000000ff80c38ULL : s203;
-  const SWord64 s205 = s115 ? 0x0000000009de8d6dULL : s204;
-  const SWord64 s206 = s112 ? 0x0000000006197ecbULL : s205;
-  const SWord64 s207 = s109 ? 0x0000000003c50ea2ULL : s206;
-  const SWord64 s208 = s106 ? 0x0000000002547029ULL : s207;
-  const SWord64 s209 = s103 ? 0x0000000001709e79ULL : s208;
-  const SWord64 s210 = s100 ? 0x0000000000e3d1b0ULL : s209;
-  const SWord64 s211 = s97 ? 0x00000000008cccc9ULL : s210;
-  const SWord64 s212 = s94 ? 0x00000000005704e7ULL : s211;
-  const SWord64 s213 = s92 ? 0x000000000035c7e2ULL : s212;
-  const SWord64 s214 = s89 ? 0x0000000000213d05ULL : s213;
-  const SWord64 s215 = s86 ? 0x0000000000148addULL : s214;
-  const SWord64 s216 = s83 ? 0x00000000000cb228ULL : s215;
-  const SWord64 s217 = s80 ? 0x000000000007d8b5ULL : s216;
-  const SWord64 s218 = s77 ? 0x000000000004d973ULL : s217;
-  const SWord64 s219 = s74 ? 0x000000000002ff42ULL : s218;
-  const SWord64 s220 = s71 ? 0x000000000001da31ULL : s219;
-  const SWord64 s221 = s68 ? 0x0000000000012511ULL : s220;
-  const SWord64 s222 = s65 ? 0x000000000000b520ULL : s221;
-  const SWord64 s223 = s62 ? 0x0000000000006ff1ULL : s222;
-  const SWord64 s224 = s59 ? 0x000000000000452fULL : s223;
-  const SWord64 s225 = s56 ? 0x0000000000002ac2ULL : s224;
-  const SWord64 s226 = s54 ? 0x0000000000001a6dULL : s225;
-  const SWord64 s227 = s51 ? 0x0000000000001055ULL : s226;
-  const SWord64 s228 = s48 ? 0x0000000000000a18ULL : s227;
-  const SWord64 s229 = s45 ? 0x000000000000063dULL : s228;
-  const SWord64 s230 = s42 ? 0x00000000000003dbULL : s229;
-  const SWord64 s231 = s39 ? 0x0000000000000262ULL : s230;
-  const SWord64 s232 = s36 ? 0x0000000000000179ULL : s231;
-  const SWord64 s233 = s33 ? 0x00000000000000e9ULL : s232;
-  const SWord64 s234 = s31 ? 0x0000000000000090ULL : s233;
-  const SWord64 s235 = s28 ? 0x0000000000000059ULL : s234;
-  const SWord64 s236 = s25 ? 0x0000000000000037ULL : s235;
-  const SWord64 s237 = s22 ? 0x0000000000000022ULL : s236;
-  const SWord64 s238 = s19 ? 0x0000000000000015ULL : s237;
-  const SWord64 s239 = s17 ? 0x000000000000000dULL : s238;
-  const SWord64 s240 = s14 ? 0x0000000000000008ULL : s239;
-  const SWord64 s241 = s12 ? 0x0000000000000005ULL : s240;
-  const SWord64 s242 = s10 ? 0x0000000000000003ULL : s241;
-  const SWord64 s243 = s8 ? 0x0000000000000002ULL : s242;
-  const SWord64 s244 = s6 ? 0x0000000000000001ULL : s243;
-  const SWord64 s245 = s4 ? 0x0000000000000001ULL : s244;
-  const SWord64 s246 = s2 ? 0x0000000000000000ULL : s245;
-
-  return s246;
-}
-== END: "fib1.c" ==================
diff --git a/SBVUnitTest/GoldFiles/fib2.gold b/SBVUnitTest/GoldFiles/fib2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/fib2.gold
+++ /dev/null
@@ -1,129 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for fib2. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: fib2_driver
-
-fib2.o: fib2.c fib2.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fib2_driver.o: fib2_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fib2_driver: fib2.o fib2_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f fib2_driver
-== END: "Makefile" ==================
-== BEGIN: "fib2.h" ================
-/* Header file for fib2. Automatically generated by SBV. Do not edit! */
-
-#ifndef __fib2__HEADER_INCLUDED__
-#define __fib2__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord64 fib2(const SWord64 n);
-
-#endif /* __fib2__HEADER_INCLUDED__ */
-== END: "fib2.h" ==================
-== BEGIN: "fib2_driver.c" ================
-/* Example driver program for fib2. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "fib2.h"
-
-int main(void)
-{
-  const SWord64 __result = fib2(0x0000000000000014ULL);
-
-  printf("fib2(0x0000000000000014ULL) = 0x%016"PRIx64"ULL\n", __result);
-
-  return 0;
-}
-== END: "fib2_driver.c" ==================
-== BEGIN: "fib2.c" ================
-/* File: "fib2.c". Automatically generated by SBV. Do not edit! */
-
-#include "fib2.h"
-
-SWord64 fib2(const SWord64 n)
-{
-  const SWord64 s0 = n;
-  static const SWord64 table0[] = {
-      0x0000000000000000ULL, 0x0000000000000001ULL,
-      0x0000000000000001ULL, 0x0000000000000002ULL,
-      0x0000000000000003ULL, 0x0000000000000005ULL,
-      0x0000000000000008ULL, 0x000000000000000dULL,
-      0x0000000000000015ULL, 0x0000000000000022ULL,
-      0x0000000000000037ULL, 0x0000000000000059ULL,
-      0x0000000000000090ULL, 0x00000000000000e9ULL,
-      0x0000000000000179ULL, 0x0000000000000262ULL,
-      0x00000000000003dbULL, 0x000000000000063dULL,
-      0x0000000000000a18ULL, 0x0000000000001055ULL,
-      0x0000000000001a6dULL, 0x0000000000002ac2ULL,
-      0x000000000000452fULL, 0x0000000000006ff1ULL,
-      0x000000000000b520ULL, 0x0000000000012511ULL,
-      0x000000000001da31ULL, 0x000000000002ff42ULL,
-      0x000000000004d973ULL, 0x000000000007d8b5ULL,
-      0x00000000000cb228ULL, 0x0000000000148addULL,
-      0x0000000000213d05ULL, 0x000000000035c7e2ULL,
-      0x00000000005704e7ULL, 0x00000000008cccc9ULL,
-      0x0000000000e3d1b0ULL, 0x0000000001709e79ULL,
-      0x0000000002547029ULL, 0x0000000003c50ea2ULL,
-      0x0000000006197ecbULL, 0x0000000009de8d6dULL,
-      0x000000000ff80c38ULL, 0x0000000019d699a5ULL,
-      0x0000000029cea5ddULL, 0x0000000043a53f82ULL,
-      0x000000006d73e55fULL, 0x00000000b11924e1ULL,
-      0x000000011e8d0a40ULL, 0x00000001cfa62f21ULL,
-      0x00000002ee333961ULL, 0x00000004bdd96882ULL,
-      0x00000007ac0ca1e3ULL, 0x0000000c69e60a65ULL,
-      0x0000001415f2ac48ULL, 0x000000207fd8b6adULL,
-      0x0000003495cb62f5ULL, 0x0000005515a419a2ULL,
-      0x00000089ab6f7c97ULL, 0x000000dec1139639ULL,
-      0x000001686c8312d0ULL, 0x000002472d96a909ULL,
-      0x000003af9a19bbd9ULL, 0x000005f6c7b064e2ULL, 0x000009a661ca20bbULL
-  };
-  const SWord64 s65 = s0 >= 65 ? 0x0000000000000000ULL : table0[s0];
-
-  return s65;
-}
-== END: "fib2.c" ==================
diff --git a/SBVUnitTest/GoldFiles/floats_cgen.gold b/SBVUnitTest/GoldFiles/floats_cgen.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/floats_cgen.gold
+++ /dev/null
@@ -1,2869 +0,0 @@
-== BEGIN: "toFP_Int8_ToFloat.c" ================
-/* File: "toFP_Int8_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Int8_ToFloat(const SInt8 a)
-{
-  const SInt8  s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Int8_ToFloat.c" ==================
-== BEGIN: "toFP_Int16_ToFloat.c" ================
-/* File: "toFP_Int16_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Int16_ToFloat(const SInt16 a)
-{
-  const SInt16 s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Int16_ToFloat.c" ==================
-== BEGIN: "toFP_Int32_ToFloat.c" ================
-/* File: "toFP_Int32_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Int32_ToFloat(const SInt32 a)
-{
-  const SInt32 s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Int32_ToFloat.c" ==================
-== BEGIN: "toFP_Int64_ToFloat.c" ================
-/* File: "toFP_Int64_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Int64_ToFloat(const SInt64 a)
-{
-  const SInt64 s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Int64_ToFloat.c" ==================
-== BEGIN: "toFP_Word8_ToFloat.c" ================
-/* File: "toFP_Word8_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Word8_ToFloat(const SWord8 a)
-{
-  const SWord8 s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Word8_ToFloat.c" ==================
-== BEGIN: "toFP_Word16_ToFloat.c" ================
-/* File: "toFP_Word16_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Word16_ToFloat(const SWord16 a)
-{
-  const SWord16 s0 = a;
-  const SFloat  s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Word16_ToFloat.c" ==================
-== BEGIN: "toFP_Word32_ToFloat.c" ================
-/* File: "toFP_Word32_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Word32_ToFloat(const SWord32 a)
-{
-  const SWord32 s0 = a;
-  const SFloat  s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Word32_ToFloat.c" ==================
-== BEGIN: "toFP_Word64_ToFloat.c" ================
-/* File: "toFP_Word64_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Word64_ToFloat(const SWord64 a)
-{
-  const SWord64 s0 = a;
-  const SFloat  s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Word64_ToFloat.c" ==================
-== BEGIN: "toFP_Float_ToFloat.c" ================
-/* File: "toFP_Float_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Float_ToFloat(const SFloat a)
-{
-  const SFloat s0 = a;
-  return s0;
-}
-== END: "toFP_Float_ToFloat.c" ==================
-== BEGIN: "toFP_Double_ToFloat.c" ================
-/* File: "toFP_Double_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Double_ToFloat(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SFloat  s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Double_ToFloat.c" ==================
-== BEGIN: "toFP_Integer_ToFloat.c" ================
-/* File: "toFP_Integer_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Integer_ToFloat(const SInteger a)
-{
-  const SInteger s0 = a;
-  const SFloat   s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Integer_ToFloat.c" ==================
-== BEGIN: "toFP_Real_ToFloat.c" ================
-/* File: "toFP_Real_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat toFP_Real_ToFloat(const SReal a)
-{
-  const SReal  s0 = a;
-  const SFloat s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "toFP_Real_ToFloat.c" ==================
-== BEGIN: "toFP_Int8_ToDouble.c" ================
-/* File: "toFP_Int8_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Int8_ToDouble(const SInt8 a)
-{
-  const SInt8   s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Int8_ToDouble.c" ==================
-== BEGIN: "toFP_Int16_ToDouble.c" ================
-/* File: "toFP_Int16_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Int16_ToDouble(const SInt16 a)
-{
-  const SInt16  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Int16_ToDouble.c" ==================
-== BEGIN: "toFP_Int32_ToDouble.c" ================
-/* File: "toFP_Int32_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Int32_ToDouble(const SInt32 a)
-{
-  const SInt32  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Int32_ToDouble.c" ==================
-== BEGIN: "toFP_Int64_ToDouble.c" ================
-/* File: "toFP_Int64_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Int64_ToDouble(const SInt64 a)
-{
-  const SInt64  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Int64_ToDouble.c" ==================
-== BEGIN: "toFP_Word8_ToDouble.c" ================
-/* File: "toFP_Word8_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Word8_ToDouble(const SWord8 a)
-{
-  const SWord8  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Word8_ToDouble.c" ==================
-== BEGIN: "toFP_Word16_ToDouble.c" ================
-/* File: "toFP_Word16_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Word16_ToDouble(const SWord16 a)
-{
-  const SWord16 s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Word16_ToDouble.c" ==================
-== BEGIN: "toFP_Word32_ToDouble.c" ================
-/* File: "toFP_Word32_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Word32_ToDouble(const SWord32 a)
-{
-  const SWord32 s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Word32_ToDouble.c" ==================
-== BEGIN: "toFP_Word64_ToDouble.c" ================
-/* File: "toFP_Word64_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Word64_ToDouble(const SWord64 a)
-{
-  const SWord64 s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Word64_ToDouble.c" ==================
-== BEGIN: "toFP_Float_ToDouble.c" ================
-/* File: "toFP_Float_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Float_ToDouble(const SFloat a)
-{
-  const SFloat  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Float_ToDouble.c" ==================
-== BEGIN: "toFP_Double_ToDouble.c" ================
-/* File: "toFP_Double_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Double_ToDouble(const SDouble a)
-{
-  const SDouble s0 = a;
-  return s0;
-}
-== END: "toFP_Double_ToDouble.c" ==================
-== BEGIN: "toFP_Integer_ToDouble.c" ================
-/* File: "toFP_Integer_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Integer_ToDouble(const SInteger a)
-{
-  const SInteger s0 = a;
-  const SDouble  s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Integer_ToDouble.c" ==================
-== BEGIN: "toFP_Real_ToDouble.c" ================
-/* File: "toFP_Real_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble toFP_Real_ToDouble(const SReal a)
-{
-  const SReal   s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "toFP_Real_ToDouble.c" ==================
-== BEGIN: "fromFP_Float_ToInt8.c" ================
-/* File: "fromFP_Float_ToInt8.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToInt8.c" ==================
-== BEGIN: "fromFP_Float_ToInt16.c" ================
-/* File: "fromFP_Float_ToInt16.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToInt16.c" ==================
-== BEGIN: "fromFP_Float_ToInt32.c" ================
-/* File: "fromFP_Float_ToInt32.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToInt32.c" ==================
-== BEGIN: "fromFP_Float_ToInt64.c" ================
-/* File: "fromFP_Float_ToInt64.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToInt64.c" ==================
-== BEGIN: "fromFP_Float_ToWord8.c" ================
-/* File: "fromFP_Float_ToWord8.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToWord8.c" ==================
-== BEGIN: "fromFP_Float_ToWord16.c" ================
-/* File: "fromFP_Float_ToWord16.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToWord16.c" ==================
-== BEGIN: "fromFP_Float_ToWord32.c" ================
-/* File: "fromFP_Float_ToWord32.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToWord32.c" ==================
-== BEGIN: "fromFP_Float_ToWord64.c" ================
-/* File: "fromFP_Float_ToWord64.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToWord64.c" ==================
-== BEGIN: "fromFP_Float_ToFloat.c" ================
-/* File: "fromFP_Float_ToFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat fromFP_Float_ToFloat(const SFloat a)
-{
-  const SFloat s0 = a;
-  return s0;
-}
-== END: "fromFP_Float_ToFloat.c" ==================
-== BEGIN: "fromFP_Float_ToDouble.c" ================
-/* File: "fromFP_Float_ToDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble fromFP_Float_ToDouble(const SFloat a)
-{
-  const SFloat  s0 = a;
-  const SDouble s2 = (SDouble) s0;
-
-  return s2;
-}
-== END: "fromFP_Float_ToDouble.c" ==================
-== BEGIN: "fromFP_Float_ToInteger.c" ================
-/* File: "fromFP_Float_ToInteger.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToInteger.c" ==================
-== BEGIN: "fromFP_Float_ToReal.c" ================
-/* File: "fromFP_Float_ToReal.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_Float_ToReal.c" ==================
-== BEGIN: "fromFP_DoubleTo_Int8.c" ================
-/* File: "fromFP_DoubleTo_Int8.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Int8.c" ==================
-== BEGIN: "fromFP_DoubleTo_Int16.c" ================
-/* File: "fromFP_DoubleTo_Int16.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Int16.c" ==================
-== BEGIN: "fromFP_DoubleTo_Int32.c" ================
-/* File: "fromFP_DoubleTo_Int32.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Int32.c" ==================
-== BEGIN: "fromFP_DoubleTo_Int64.c" ================
-/* File: "fromFP_DoubleTo_Int64.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Int64.c" ==================
-== BEGIN: "fromFP_DoubleTo_Word8.c" ================
-/* File: "fromFP_DoubleTo_Word8.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Word8.c" ==================
-== BEGIN: "fromFP_DoubleTo_Word16.c" ================
-/* File: "fromFP_DoubleTo_Word16.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Word16.c" ==================
-== BEGIN: "fromFP_DoubleTo_Word32.c" ================
-/* File: "fromFP_DoubleTo_Word32.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Word32.c" ==================
-== BEGIN: "fromFP_DoubleTo_Word64.c" ================
-/* File: "fromFP_DoubleTo_Word64.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Word64.c" ==================
-== BEGIN: "fromFP_DoubleTo_Float.c" ================
-/* File: "fromFP_DoubleTo_Float.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat fromFP_DoubleTo_Float(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SFloat  s2 = (SFloat) s0;
-
-  return s2;
-}
-== END: "fromFP_DoubleTo_Float.c" ==================
-== BEGIN: "fromFP_DoubleTo_Double.c" ================
-/* File: "fromFP_DoubleTo_Double.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble fromFP_DoubleTo_Double(const SDouble a)
-{
-  const SDouble s0 = a;
-  return s0;
-}
-== END: "fromFP_DoubleTo_Double.c" ==================
-== BEGIN: "fromFP_DoubleTo_Integer.c" ================
-/* File: "fromFP_DoubleTo_Integer.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Integer.c" ==================
-== BEGIN: "fromFP_DoubleTo_Real.c" ================
-/* File: "fromFP_DoubleTo_Real.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-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;
-
-  return s8;
-}
-== END: "fromFP_DoubleTo_Real.c" ==================
-== BEGIN: "fromFP_SWord32_SFloat.c" ================
-/* File: "fromFP_SWord32_SFloat.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat fromFP_SWord32_SFloat(const SWord32 a)
-{
-  const SWord32 s0 = a;
-        SFloat  s1; memcpy(&s1, &s0, sizeof(SFloat));
-
-  return s1;
-}
-== END: "fromFP_SWord32_SFloat.c" ==================
-== BEGIN: "fromFP_SWord64_SDouble.c" ================
-/* File: "fromFP_SWord64_SDouble.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble fromFP_SWord64_SDouble(const SWord64 a)
-{
-  const SWord64 s0 = a;
-        SDouble s1; memcpy(&s1, &s0, sizeof(SDouble));
-
-  return s1;
-}
-== END: "fromFP_SWord64_SDouble.c" ==================
-== BEGIN: "fromFP_SFloat_SWord32.c" ================
-/* File: "fromFP_SFloat_SWord32.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SWord32 fromFP_SFloat_SWord32(const SFloat a)
-{
-  const SFloat  s0 = a;
-        SWord32 s1; memcpy(&s1, &s0, sizeof(SWord32));
-
-  return s1;
-}
-== END: "fromFP_SFloat_SWord32.c" ==================
-== BEGIN: "fromFP_SDouble_SWord64.c" ================
-/* File: "fromFP_SDouble_SWord64.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SWord64 fromFP_SDouble_SWord64(const SDouble a)
-{
-  const SDouble s0 = a;
-        SWord64 s1; memcpy(&s1, &s0, sizeof(SWord64));
-
-  return s1;
-}
-== END: "fromFP_SDouble_SWord64.c" ==================
-== BEGIN: "f_FP_Abs.c" ================
-/* File: "f_FP_Abs.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Abs(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = fabsf(s0);
-
-  return s1;
-}
-== END: "f_FP_Abs.c" ==================
-== BEGIN: "d_FP_Abs.c" ================
-/* File: "d_FP_Abs.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Abs(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = fabs(s0);
-
-  return s1;
-}
-== END: "d_FP_Abs.c" ==================
-== BEGIN: "f_FP_Neg.c" ================
-/* File: "f_FP_Neg.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Neg(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = (- s0);
-
-  return s1;
-}
-== END: "f_FP_Neg.c" ==================
-== BEGIN: "d_FP_Neg.c" ================
-/* File: "d_FP_Neg.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Neg(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = (- s0);
-
-  return s1;
-}
-== END: "d_FP_Neg.c" ==================
-== BEGIN: "f_FP_Add.c" ================
-/* File: "f_FP_Add.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Add(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s3 = s0 + s1;
-
-  return s3;
-}
-== END: "f_FP_Add.c" ==================
-== BEGIN: "d_FP_Add.c" ================
-/* File: "d_FP_Add.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Add(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s3 = s0 + s1;
-
-  return s3;
-}
-== END: "d_FP_Add.c" ==================
-== BEGIN: "f_FP_Sub.c" ================
-/* File: "f_FP_Sub.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Sub(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s3 = s0 - s1;
-
-  return s3;
-}
-== END: "f_FP_Sub.c" ==================
-== BEGIN: "d_FP_Sub.c" ================
-/* File: "d_FP_Sub.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Sub(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s3 = s0 - s1;
-
-  return s3;
-}
-== END: "d_FP_Sub.c" ==================
-== BEGIN: "f_FP_Mul.c" ================
-/* File: "f_FP_Mul.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Mul(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s3 = s0 * s1;
-
-  return s3;
-}
-== END: "f_FP_Mul.c" ==================
-== BEGIN: "d_FP_Mul.c" ================
-/* File: "d_FP_Mul.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Mul(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s3 = s0 * s1;
-
-  return s3;
-}
-== END: "d_FP_Mul.c" ==================
-== BEGIN: "f_FP_Div.c" ================
-/* File: "f_FP_Div.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Div(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s3 = s0 / s1;
-
-  return s3;
-}
-== END: "f_FP_Div.c" ==================
-== BEGIN: "d_FP_Div.c" ================
-/* File: "d_FP_Div.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Div(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s3 = s0 / s1;
-
-  return s3;
-}
-== END: "d_FP_Div.c" ==================
-== BEGIN: "f_FP_FMA.c" ================
-/* File: "f_FP_FMA.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_FMA(const SFloat a, const SFloat b, const SFloat c)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s2 = c;
-  const SFloat s4 = fmaf(s0, s1, s2);
-
-  return s4;
-}
-== END: "f_FP_FMA.c" ==================
-== BEGIN: "d_FP_FMA.c" ================
-/* File: "d_FP_FMA.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_FMA(const SDouble a, const SDouble b, const SDouble c)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s2 = c;
-  const SDouble s4 = fma(s0, s1, s2);
-
-  return s4;
-}
-== END: "d_FP_FMA.c" ==================
-== BEGIN: "f_FP_Sqrt.c" ================
-/* File: "f_FP_Sqrt.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Sqrt(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SFloat s2 = sqrtf(s0);
-
-  return s2;
-}
-== END: "f_FP_Sqrt.c" ==================
-== BEGIN: "d_FP_Sqrt.c" ================
-/* File: "d_FP_Sqrt.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Sqrt(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SDouble s2 = sqrt(s0);
-
-  return s2;
-}
-== END: "d_FP_Sqrt.c" ==================
-== BEGIN: "f_FP_Rem.c" ================
-/* File: "f_FP_Rem.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Rem(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SFloat s2 = fmodf(s0, s1);
-
-  return s2;
-}
-== END: "f_FP_Rem.c" ==================
-== BEGIN: "d_FP_Rem.c" ================
-/* File: "d_FP_Rem.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Rem(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SDouble s2 = fmod(s0, s1);
-
-  return s2;
-}
-== END: "d_FP_Rem.c" ==================
-== BEGIN: "f_FP_RoundToIntegral.c" ================
-/* File: "f_FP_RoundToIntegral.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_RoundToIntegral(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SFloat s2 = rintf(s0);
-
-  return s2;
-}
-== END: "f_FP_RoundToIntegral.c" ==================
-== BEGIN: "d_FP_RoundToIntegral.c" ================
-/* File: "d_FP_RoundToIntegral.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_RoundToIntegral(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SDouble s2 = rint(s0);
-
-  return s2;
-}
-== END: "d_FP_RoundToIntegral.c" ==================
-== BEGIN: "f_FP_Min.c" ================
-/* File: "f_FP_Min.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Min(const SFloat a, const SFloat b)
-{
-  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);
-
-  return s2;
-}
-== END: "f_FP_Min.c" ==================
-== BEGIN: "d_FP_Min.c" ================
-/* File: "d_FP_Min.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Min(const SDouble a, const SDouble b)
-{
-  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);
-
-  return s2;
-}
-== END: "d_FP_Min.c" ==================
-== BEGIN: "f_FP_Max.c" ================
-/* File: "f_FP_Max.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SFloat f_FP_Max(const SFloat a, const SFloat b)
-{
-  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);
-
-  return s2;
-}
-== END: "f_FP_Max.c" ==================
-== BEGIN: "d_FP_Max.c" ================
-/* File: "d_FP_Max.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SDouble d_FP_Max(const SDouble a, const SDouble b)
-{
-  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);
-
-  return s2;
-}
-== END: "d_FP_Max.c" ==================
-== BEGIN: "f_FP_IsEqualObject.c" ================
-/* File: "f_FP_IsEqualObject.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsEqualObject(const SFloat a, const SFloat b)
-{
-  const SFloat s0 = a;
-  const SFloat s1 = b;
-  const SBool  s2 = isnan(s0) ? isnan(s1) : (signbit(s0) && (s0 == 0)) ? (signbit(s1) && (s1 == 0)) : (signbit(s1) && (s1 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s1);
-
-  return s2;
-}
-== END: "f_FP_IsEqualObject.c" ==================
-== BEGIN: "d_FP_IsEqualObject.c" ================
-/* File: "d_FP_IsEqualObject.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsEqualObject(const SDouble a, const SDouble b)
-{
-  const SDouble s0 = a;
-  const SDouble s1 = b;
-  const SBool   s2 = isnan(s0) ? isnan(s1) : (signbit(s0) && (s0 == 0)) ? (signbit(s1) && (s1 == 0)) : (signbit(s1) && (s1 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s1);
-
-  return s2;
-}
-== END: "d_FP_IsEqualObject.c" ==================
-== BEGIN: "f_FP_IsNormal.c" ================
-/* File: "f_FP_IsNormal.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsNormal(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = isnormal(s0);
-
-  return s1;
-}
-== END: "f_FP_IsNormal.c" ==================
-== BEGIN: "d_FP_IsNormal.c" ================
-/* File: "d_FP_IsNormal.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsNormal(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = isnormal(s0);
-
-  return s1;
-}
-== END: "d_FP_IsNormal.c" ==================
-== BEGIN: "f_FP_IsZero.c" ================
-/* File: "f_FP_IsZero.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsZero(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = FP_ZERO == fpclassify(s0);
-
-  return s1;
-}
-== END: "f_FP_IsZero.c" ==================
-== BEGIN: "d_FP_IsZero.c" ================
-/* File: "d_FP_IsZero.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsZero(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = FP_ZERO == fpclassify(s0);
-
-  return s1;
-}
-== END: "d_FP_IsZero.c" ==================
-== BEGIN: "f_FP_IsSubnormal.c" ================
-/* File: "f_FP_IsSubnormal.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsSubnormal(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = FP_SUBNORMAL == fpclassify(s0);
-
-  return s1;
-}
-== END: "f_FP_IsSubnormal.c" ==================
-== BEGIN: "d_FP_IsSubnormal.c" ================
-/* File: "d_FP_IsSubnormal.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsSubnormal(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = FP_SUBNORMAL == fpclassify(s0);
-
-  return s1;
-}
-== END: "d_FP_IsSubnormal.c" ==================
-== BEGIN: "f_FP_IsInfinite.c" ================
-/* File: "f_FP_IsInfinite.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsInfinite(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = isinf(s0);
-
-  return s1;
-}
-== END: "f_FP_IsInfinite.c" ==================
-== BEGIN: "d_FP_IsInfinite.c" ================
-/* File: "d_FP_IsInfinite.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsInfinite(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = isinf(s0);
-
-  return s1;
-}
-== END: "d_FP_IsInfinite.c" ==================
-== BEGIN: "f_FP_IsNaN.c" ================
-/* File: "f_FP_IsNaN.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsNaN(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-
-  return s1;
-}
-== END: "f_FP_IsNaN.c" ==================
-== BEGIN: "d_FP_IsNaN.c" ================
-/* File: "d_FP_IsNaN.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsNaN(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-
-  return s1;
-}
-== END: "d_FP_IsNaN.c" ==================
-== BEGIN: "f_FP_IsNegative.c" ================
-/* File: "f_FP_IsNegative.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsNegative(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = !isnan(s0) && signbit(s0);
-
-  return s1;
-}
-== END: "f_FP_IsNegative.c" ==================
-== BEGIN: "d_FP_IsNegative.c" ================
-/* File: "d_FP_IsNegative.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsNegative(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = !isnan(s0) && signbit(s0);
-
-  return s1;
-}
-== END: "d_FP_IsNegative.c" ==================
-== BEGIN: "f_FP_IsPositive.c" ================
-/* File: "f_FP_IsPositive.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool f_FP_IsPositive(const SFloat a)
-{
-  const SFloat s0 = a;
-  const SBool  s1 = !isnan(s0) && !signbit(s0);
-
-  return s1;
-}
-== END: "f_FP_IsPositive.c" ==================
-== BEGIN: "d_FP_IsPositive.c" ================
-/* File: "d_FP_IsPositive.c". Automatically generated by SBV. Do not edit! */
-
-#include "floatCodeGen.h"
-
-SBool d_FP_IsPositive(const SDouble a)
-{
-  const SDouble s0 = a;
-  const SBool   s1 = !isnan(s0) && !signbit(s0);
-
-  return s1;
-}
-== END: "d_FP_IsPositive.c" ==================
-== BEGIN: "floatCodeGen.h" ================
-/* Header file for floatCodeGen. Automatically generated by SBV. Do not edit! */
-
-#ifndef __floatCodeGen__HEADER_INCLUDED__
-#define __floatCodeGen__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* User requested mapping for SInteger.                                 */
-/* NB. Loss of precision: Target type is subject to modular arithmetic. */
-typedef SInt64 SInteger;
-
-/* User requested mapping for SReal.                          */
-/* NB. Loss of precision: Target type is subject to rounding. */
-typedef long double SReal;
-
-/* Entry point prototypes: */
-SFloat toFP_Int8_ToFloat(const SInt8 a);
-SFloat toFP_Int16_ToFloat(const SInt16 a);
-SFloat toFP_Int32_ToFloat(const SInt32 a);
-SFloat toFP_Int64_ToFloat(const SInt64 a);
-SFloat toFP_Word8_ToFloat(const SWord8 a);
-SFloat toFP_Word16_ToFloat(const SWord16 a);
-SFloat toFP_Word32_ToFloat(const SWord32 a);
-SFloat toFP_Word64_ToFloat(const SWord64 a);
-SFloat toFP_Float_ToFloat(const SFloat a);
-SFloat toFP_Double_ToFloat(const SDouble a);
-SFloat toFP_Integer_ToFloat(const SInteger a);
-SFloat toFP_Real_ToFloat(const SReal a);
-SDouble toFP_Int8_ToDouble(const SInt8 a);
-SDouble toFP_Int16_ToDouble(const SInt16 a);
-SDouble toFP_Int32_ToDouble(const SInt32 a);
-SDouble toFP_Int64_ToDouble(const SInt64 a);
-SDouble toFP_Word8_ToDouble(const SWord8 a);
-SDouble toFP_Word16_ToDouble(const SWord16 a);
-SDouble toFP_Word32_ToDouble(const SWord32 a);
-SDouble toFP_Word64_ToDouble(const SWord64 a);
-SDouble toFP_Float_ToDouble(const SFloat a);
-SDouble toFP_Double_ToDouble(const SDouble a);
-SDouble toFP_Integer_ToDouble(const SInteger a);
-SDouble toFP_Real_ToDouble(const SReal a);
-SInt8 fromFP_Float_ToInt8(const SFloat a);
-SInt16 fromFP_Float_ToInt16(const SFloat a);
-SInt32 fromFP_Float_ToInt32(const SFloat a);
-SInt64 fromFP_Float_ToInt64(const SFloat a);
-SWord8 fromFP_Float_ToWord8(const SFloat a);
-SWord16 fromFP_Float_ToWord16(const SFloat a);
-SWord32 fromFP_Float_ToWord32(const SFloat a);
-SWord64 fromFP_Float_ToWord64(const SFloat a);
-SFloat fromFP_Float_ToFloat(const SFloat a);
-SDouble fromFP_Float_ToDouble(const SFloat a);
-SInteger fromFP_Float_ToInteger(const SFloat a);
-SReal fromFP_Float_ToReal(const SFloat a);
-SInt8 fromFP_DoubleTo_Int8(const SDouble a);
-SInt16 fromFP_DoubleTo_Int16(const SDouble a);
-SInt32 fromFP_DoubleTo_Int32(const SDouble a);
-SInt64 fromFP_DoubleTo_Int64(const SDouble a);
-SWord8 fromFP_DoubleTo_Word8(const SDouble a);
-SWord16 fromFP_DoubleTo_Word16(const SDouble a);
-SWord32 fromFP_DoubleTo_Word32(const SDouble a);
-SWord64 fromFP_DoubleTo_Word64(const SDouble a);
-SFloat fromFP_DoubleTo_Float(const SDouble a);
-SDouble fromFP_DoubleTo_Double(const SDouble a);
-SInteger fromFP_DoubleTo_Integer(const SDouble a);
-SReal fromFP_DoubleTo_Real(const SDouble a);
-SFloat fromFP_SWord32_SFloat(const SWord32 a);
-SDouble fromFP_SWord64_SDouble(const SWord64 a);
-SWord32 fromFP_SFloat_SWord32(const SFloat a);
-SWord64 fromFP_SDouble_SWord64(const SDouble a);
-SFloat f_FP_Abs(const SFloat a);
-SDouble d_FP_Abs(const SDouble a);
-SFloat f_FP_Neg(const SFloat a);
-SDouble d_FP_Neg(const SDouble a);
-SFloat f_FP_Add(const SFloat a, const SFloat b);
-SDouble d_FP_Add(const SDouble a, const SDouble b);
-SFloat f_FP_Sub(const SFloat a, const SFloat b);
-SDouble d_FP_Sub(const SDouble a, const SDouble b);
-SFloat f_FP_Mul(const SFloat a, const SFloat b);
-SDouble d_FP_Mul(const SDouble a, const SDouble b);
-SFloat f_FP_Div(const SFloat a, const SFloat b);
-SDouble d_FP_Div(const SDouble a, const SDouble b);
-SFloat f_FP_FMA(const SFloat a, const SFloat b, const SFloat c);
-SDouble d_FP_FMA(const SDouble a, const SDouble b,
-                 const SDouble c);
-SFloat f_FP_Sqrt(const SFloat a);
-SDouble d_FP_Sqrt(const SDouble a);
-SFloat f_FP_Rem(const SFloat a, const SFloat b);
-SDouble d_FP_Rem(const SDouble a, const SDouble b);
-SFloat f_FP_RoundToIntegral(const SFloat a);
-SDouble d_FP_RoundToIntegral(const SDouble a);
-SFloat f_FP_Min(const SFloat a, const SFloat b);
-SDouble d_FP_Min(const SDouble a, const SDouble b);
-SFloat f_FP_Max(const SFloat a, const SFloat b);
-SDouble d_FP_Max(const SDouble a, const SDouble b);
-SBool f_FP_IsEqualObject(const SFloat a, const SFloat b);
-SBool d_FP_IsEqualObject(const SDouble a, const SDouble b);
-SBool f_FP_IsNormal(const SFloat a);
-SBool d_FP_IsNormal(const SDouble a);
-SBool f_FP_IsZero(const SFloat a);
-SBool d_FP_IsZero(const SDouble a);
-SBool f_FP_IsSubnormal(const SFloat a);
-SBool d_FP_IsSubnormal(const SDouble a);
-SBool f_FP_IsInfinite(const SFloat a);
-SBool d_FP_IsInfinite(const SDouble a);
-SBool f_FP_IsNaN(const SFloat a);
-SBool d_FP_IsNaN(const SDouble a);
-SBool f_FP_IsNegative(const SFloat a);
-SBool d_FP_IsNegative(const SDouble a);
-SBool f_FP_IsPositive(const SFloat a);
-SBool d_FP_IsPositive(const SDouble a);
-
-#endif /* __floatCodeGen__HEADER_INCLUDED__ */
-== END: "floatCodeGen.h" ==================
-== BEGIN: "floatCodeGen_driver.c" ================
-/* Example driver program for floatCodeGen. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "floatCodeGen.h"
-
-void toFP_Int8_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Int8_ToFloat(42);
-
-  printf("toFP_Int8_ToFloat(42) = %.6g\n", __result);
-}
-
-void toFP_Int16_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Int16_ToFloat(0x002a);
-
-  printf("toFP_Int16_ToFloat(0x002a) = %.6g\n", __result);
-}
-
-void toFP_Int32_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Int32_ToFloat(0x0000002aL);
-
-  printf("toFP_Int32_ToFloat(0x0000002aL) = %.6g\n", __result);
-}
-
-void toFP_Int64_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Int64_ToFloat(0x000000000000002aLL);
-
-  printf("toFP_Int64_ToFloat(0x000000000000002aLL) = %.6g\n", __result);
-}
-
-void toFP_Word8_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Word8_ToFloat(42);
-
-  printf("toFP_Word8_ToFloat(42) = %.6g\n", __result);
-}
-
-void toFP_Word16_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Word16_ToFloat(0x002aU);
-
-  printf("toFP_Word16_ToFloat(0x002aU) = %.6g\n", __result);
-}
-
-void toFP_Word32_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Word32_ToFloat(0x0000002aUL);
-
-  printf("toFP_Word32_ToFloat(0x0000002aUL) = %.6g\n", __result);
-}
-
-void toFP_Word64_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Word64_ToFloat(0x000000000000002aULL);
-
-  printf("toFP_Word64_ToFloat(0x000000000000002aULL) = %.6g\n", __result);
-}
-
-void toFP_Float_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Float_ToFloat(42.0F);
-
-  printf("toFP_Float_ToFloat(42.0F) = %.6g\n", __result);
-}
-
-void toFP_Double_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Double_ToFloat(42.0);
-
-  printf("toFP_Double_ToFloat(42.0) = %.6g\n", __result);
-}
-
-void toFP_Integer_ToFloat_driver(void)
-{
-  const SFloat __result = toFP_Integer_ToFloat(0x000000000000002aLL);
-
-  printf("toFP_Integer_ToFloat(0x000000000000002aLL) = %.6g\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);
-}
-
-void toFP_Int8_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Int8_ToDouble(42);
-
-  printf("toFP_Int8_ToDouble(42) = %.15g\n", __result);
-}
-
-void toFP_Int16_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Int16_ToDouble(0x002a);
-
-  printf("toFP_Int16_ToDouble(0x002a) = %.15g\n", __result);
-}
-
-void toFP_Int32_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Int32_ToDouble(0x0000002aL);
-
-  printf("toFP_Int32_ToDouble(0x0000002aL) = %.15g\n", __result);
-}
-
-void toFP_Int64_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Int64_ToDouble(0x000000000000002aLL);
-
-  printf("toFP_Int64_ToDouble(0x000000000000002aLL) = %.15g\n", __result);
-}
-
-void toFP_Word8_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Word8_ToDouble(42);
-
-  printf("toFP_Word8_ToDouble(42) = %.15g\n", __result);
-}
-
-void toFP_Word16_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Word16_ToDouble(0x002aU);
-
-  printf("toFP_Word16_ToDouble(0x002aU) = %.15g\n", __result);
-}
-
-void toFP_Word32_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Word32_ToDouble(0x0000002aUL);
-
-  printf("toFP_Word32_ToDouble(0x0000002aUL) = %.15g\n", __result);
-}
-
-void toFP_Word64_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Word64_ToDouble(0x000000000000002aULL);
-
-  printf("toFP_Word64_ToDouble(0x000000000000002aULL) = %.15g\n", __result);
-}
-
-void toFP_Float_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Float_ToDouble(42.0F);
-
-  printf("toFP_Float_ToDouble(42.0F) = %.15g\n", __result);
-}
-
-void toFP_Double_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Double_ToDouble(42.0);
-
-  printf("toFP_Double_ToDouble(42.0) = %.15g\n", __result);
-}
-
-void toFP_Integer_ToDouble_driver(void)
-{
-  const SDouble __result = toFP_Integer_ToDouble(0x000000000000002aLL);
-
-  printf("toFP_Integer_ToDouble(0x000000000000002aLL) = %.15g\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);
-}
-
-void fromFP_Float_ToInt8_driver(void)
-{
-  const SInt8 __result = fromFP_Float_ToInt8(42.0F);
-
-  printf("fromFP_Float_ToInt8(42.0F) = %"PRId8"\n", __result);
-}
-
-void fromFP_Float_ToInt16_driver(void)
-{
-  const SInt16 __result = fromFP_Float_ToInt16(42.0F);
-
-  printf("fromFP_Float_ToInt16(42.0F) = %"PRId16"\n", __result);
-}
-
-void fromFP_Float_ToInt32_driver(void)
-{
-  const SInt32 __result = fromFP_Float_ToInt32(42.0F);
-
-  printf("fromFP_Float_ToInt32(42.0F) = %"PRId32"L\n", __result);
-}
-
-void fromFP_Float_ToInt64_driver(void)
-{
-  const SInt64 __result = fromFP_Float_ToInt64(42.0F);
-
-  printf("fromFP_Float_ToInt64(42.0F) = %"PRId64"LL\n", __result);
-}
-
-void fromFP_Float_ToWord8_driver(void)
-{
-  const SWord8 __result = fromFP_Float_ToWord8(42.0F);
-
-  printf("fromFP_Float_ToWord8(42.0F) = %"PRIu8"\n", __result);
-}
-
-void fromFP_Float_ToWord16_driver(void)
-{
-  const SWord16 __result = fromFP_Float_ToWord16(42.0F);
-
-  printf("fromFP_Float_ToWord16(42.0F) = 0x%04"PRIx16"U\n", __result);
-}
-
-void fromFP_Float_ToWord32_driver(void)
-{
-  const SWord32 __result = fromFP_Float_ToWord32(42.0F);
-
-  printf("fromFP_Float_ToWord32(42.0F) = 0x%08"PRIx32"UL\n", __result);
-}
-
-void fromFP_Float_ToWord64_driver(void)
-{
-  const SWord64 __result = fromFP_Float_ToWord64(42.0F);
-
-  printf("fromFP_Float_ToWord64(42.0F) = 0x%016"PRIx64"ULL\n", __result);
-}
-
-void fromFP_Float_ToFloat_driver(void)
-{
-  const SFloat __result = fromFP_Float_ToFloat(42.0F);
-
-  printf("fromFP_Float_ToFloat(42.0F) = %.6g\n", __result);
-}
-
-void fromFP_Float_ToDouble_driver(void)
-{
-  const SDouble __result = fromFP_Float_ToDouble(42.0F);
-
-  printf("fromFP_Float_ToDouble(42.0F) = %.15g\n", __result);
-}
-
-void fromFP_Float_ToInteger_driver(void)
-{
-  const SInteger __result = fromFP_Float_ToInteger(42.0F);
-
-  printf("fromFP_Float_ToInteger(42.0F) = %"PRId64"LL\n", __result);
-}
-
-void fromFP_Float_ToReal_driver(void)
-{
-  const SReal __result = fromFP_Float_ToReal(42.0F);
-
-  printf("fromFP_Float_ToReal(42.0F) = %Lf\n", __result);
-}
-
-void fromFP_DoubleTo_Int8_driver(void)
-{
-  const SInt8 __result = fromFP_DoubleTo_Int8(42.0);
-
-  printf("fromFP_DoubleTo_Int8(42.0) = %"PRId8"\n", __result);
-}
-
-void fromFP_DoubleTo_Int16_driver(void)
-{
-  const SInt16 __result = fromFP_DoubleTo_Int16(42.0);
-
-  printf("fromFP_DoubleTo_Int16(42.0) = %"PRId16"\n", __result);
-}
-
-void fromFP_DoubleTo_Int32_driver(void)
-{
-  const SInt32 __result = fromFP_DoubleTo_Int32(42.0);
-
-  printf("fromFP_DoubleTo_Int32(42.0) = %"PRId32"L\n", __result);
-}
-
-void fromFP_DoubleTo_Int64_driver(void)
-{
-  const SInt64 __result = fromFP_DoubleTo_Int64(42.0);
-
-  printf("fromFP_DoubleTo_Int64(42.0) = %"PRId64"LL\n", __result);
-}
-
-void fromFP_DoubleTo_Word8_driver(void)
-{
-  const SWord8 __result = fromFP_DoubleTo_Word8(42.0);
-
-  printf("fromFP_DoubleTo_Word8(42.0) = %"PRIu8"\n", __result);
-}
-
-void fromFP_DoubleTo_Word16_driver(void)
-{
-  const SWord16 __result = fromFP_DoubleTo_Word16(42.0);
-
-  printf("fromFP_DoubleTo_Word16(42.0) = 0x%04"PRIx16"U\n", __result);
-}
-
-void fromFP_DoubleTo_Word32_driver(void)
-{
-  const SWord32 __result = fromFP_DoubleTo_Word32(42.0);
-
-  printf("fromFP_DoubleTo_Word32(42.0) = 0x%08"PRIx32"UL\n", __result);
-}
-
-void fromFP_DoubleTo_Word64_driver(void)
-{
-  const SWord64 __result = fromFP_DoubleTo_Word64(42.0);
-
-  printf("fromFP_DoubleTo_Word64(42.0) = 0x%016"PRIx64"ULL\n", __result);
-}
-
-void fromFP_DoubleTo_Float_driver(void)
-{
-  const SFloat __result = fromFP_DoubleTo_Float(42.0);
-
-  printf("fromFP_DoubleTo_Float(42.0) = %.6g\n", __result);
-}
-
-void fromFP_DoubleTo_Double_driver(void)
-{
-  const SDouble __result = fromFP_DoubleTo_Double(42.0);
-
-  printf("fromFP_DoubleTo_Double(42.0) = %.15g\n", __result);
-}
-
-void fromFP_DoubleTo_Integer_driver(void)
-{
-  const SInteger __result = fromFP_DoubleTo_Integer(42.0);
-
-  printf("fromFP_DoubleTo_Integer(42.0) = %"PRId64"LL\n", __result);
-}
-
-void fromFP_DoubleTo_Real_driver(void)
-{
-  const SReal __result = fromFP_DoubleTo_Real(42.0);
-
-  printf("fromFP_DoubleTo_Real(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);
-}
-
-void fromFP_SWord64_SDouble_driver(void)
-{
-  const SDouble __result = fromFP_SWord64_SDouble(0x000000000000002aULL);
-
-  printf("fromFP_SWord64_SDouble(0x000000000000002aULL) = %.15g\n", __result);
-}
-
-void fromFP_SFloat_SWord32_driver(void)
-{
-  const SWord32 __result = fromFP_SFloat_SWord32(42.0F);
-
-  printf("fromFP_SFloat_SWord32(42.0F) = 0x%08"PRIx32"UL\n", __result);
-}
-
-void fromFP_SDouble_SWord64_driver(void)
-{
-  const SWord64 __result = fromFP_SDouble_SWord64(42.0);
-
-  printf("fromFP_SDouble_SWord64(42.0) = 0x%016"PRIx64"ULL\n", __result);
-}
-
-void f_FP_Abs_driver(void)
-{
-  const SFloat __result = f_FP_Abs(42.0F);
-
-  printf("f_FP_Abs(42.0F) = %.6g\n", __result);
-}
-
-void d_FP_Abs_driver(void)
-{
-  const SDouble __result = d_FP_Abs(42.0);
-
-  printf("d_FP_Abs(42.0) = %.15g\n", __result);
-}
-
-void f_FP_Neg_driver(void)
-{
-  const SFloat __result = f_FP_Neg(42.0F);
-
-  printf("f_FP_Neg(42.0F) = %.6g\n", __result);
-}
-
-void d_FP_Neg_driver(void)
-{
-  const SDouble __result = d_FP_Neg(42.0);
-
-  printf("d_FP_Neg(42.0) = %.15g\n", __result);
-}
-
-void f_FP_Add_driver(void)
-{
-  const SFloat __result = f_FP_Add(42.0F, 43.0F);
-
-  printf("f_FP_Add(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Add_driver(void)
-{
-  const SDouble __result = d_FP_Add(42.0, 43.0);
-
-  printf("d_FP_Add(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_Sub_driver(void)
-{
-  const SFloat __result = f_FP_Sub(42.0F, 43.0F);
-
-  printf("f_FP_Sub(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Sub_driver(void)
-{
-  const SDouble __result = d_FP_Sub(42.0, 43.0);
-
-  printf("d_FP_Sub(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_Mul_driver(void)
-{
-  const SFloat __result = f_FP_Mul(42.0F, 43.0F);
-
-  printf("f_FP_Mul(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Mul_driver(void)
-{
-  const SDouble __result = d_FP_Mul(42.0, 43.0);
-
-  printf("d_FP_Mul(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_Div_driver(void)
-{
-  const SFloat __result = f_FP_Div(42.0F, 43.0F);
-
-  printf("f_FP_Div(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Div_driver(void)
-{
-  const SDouble __result = d_FP_Div(42.0, 43.0);
-
-  printf("d_FP_Div(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_FMA_driver(void)
-{
-  const SFloat __result = f_FP_FMA(42.0F, 43.0F, 44.0F);
-
-  printf("f_FP_FMA(42.0F, 43.0F, 44.0F) = %.6g\n", __result);
-}
-
-void d_FP_FMA_driver(void)
-{
-  const SDouble __result = d_FP_FMA(42.0, 43.0, 44.0);
-
-  printf("d_FP_FMA(42.0, 43.0, 44.0) = %.15g\n", __result);
-}
-
-void f_FP_Sqrt_driver(void)
-{
-  const SFloat __result = f_FP_Sqrt(42.0F);
-
-  printf("f_FP_Sqrt(42.0F) = %.6g\n", __result);
-}
-
-void d_FP_Sqrt_driver(void)
-{
-  const SDouble __result = d_FP_Sqrt(42.0);
-
-  printf("d_FP_Sqrt(42.0) = %.15g\n", __result);
-}
-
-void f_FP_Rem_driver(void)
-{
-  const SFloat __result = f_FP_Rem(42.0F, 43.0F);
-
-  printf("f_FP_Rem(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Rem_driver(void)
-{
-  const SDouble __result = d_FP_Rem(42.0, 43.0);
-
-  printf("d_FP_Rem(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_RoundToIntegral_driver(void)
-{
-  const SFloat __result = f_FP_RoundToIntegral(42.0F);
-
-  printf("f_FP_RoundToIntegral(42.0F) = %.6g\n", __result);
-}
-
-void d_FP_RoundToIntegral_driver(void)
-{
-  const SDouble __result = d_FP_RoundToIntegral(42.0);
-
-  printf("d_FP_RoundToIntegral(42.0) = %.15g\n", __result);
-}
-
-void f_FP_Min_driver(void)
-{
-  const SFloat __result = f_FP_Min(42.0F, 43.0F);
-
-  printf("f_FP_Min(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Min_driver(void)
-{
-  const SDouble __result = d_FP_Min(42.0, 43.0);
-
-  printf("d_FP_Min(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_Max_driver(void)
-{
-  const SFloat __result = f_FP_Max(42.0F, 43.0F);
-
-  printf("f_FP_Max(42.0F, 43.0F) = %.6g\n", __result);
-}
-
-void d_FP_Max_driver(void)
-{
-  const SDouble __result = d_FP_Max(42.0, 43.0);
-
-  printf("d_FP_Max(42.0, 43.0) = %.15g\n", __result);
-}
-
-void f_FP_IsEqualObject_driver(void)
-{
-  const SBool __result = f_FP_IsEqualObject(42.0F, 43.0F);
-
-  printf("f_FP_IsEqualObject(42.0F, 43.0F) = %d\n", __result);
-}
-
-void d_FP_IsEqualObject_driver(void)
-{
-  const SBool __result = d_FP_IsEqualObject(42.0, 43.0);
-
-  printf("d_FP_IsEqualObject(42.0, 43.0) = %d\n", __result);
-}
-
-void f_FP_IsNormal_driver(void)
-{
-  const SBool __result = f_FP_IsNormal(42.0F);
-
-  printf("f_FP_IsNormal(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsNormal_driver(void)
-{
-  const SBool __result = d_FP_IsNormal(42.0);
-
-  printf("d_FP_IsNormal(42.0) = %d\n", __result);
-}
-
-void f_FP_IsZero_driver(void)
-{
-  const SBool __result = f_FP_IsZero(42.0F);
-
-  printf("f_FP_IsZero(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsZero_driver(void)
-{
-  const SBool __result = d_FP_IsZero(42.0);
-
-  printf("d_FP_IsZero(42.0) = %d\n", __result);
-}
-
-void f_FP_IsSubnormal_driver(void)
-{
-  const SBool __result = f_FP_IsSubnormal(42.0F);
-
-  printf("f_FP_IsSubnormal(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsSubnormal_driver(void)
-{
-  const SBool __result = d_FP_IsSubnormal(42.0);
-
-  printf("d_FP_IsSubnormal(42.0) = %d\n", __result);
-}
-
-void f_FP_IsInfinite_driver(void)
-{
-  const SBool __result = f_FP_IsInfinite(42.0F);
-
-  printf("f_FP_IsInfinite(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsInfinite_driver(void)
-{
-  const SBool __result = d_FP_IsInfinite(42.0);
-
-  printf("d_FP_IsInfinite(42.0) = %d\n", __result);
-}
-
-void f_FP_IsNaN_driver(void)
-{
-  const SBool __result = f_FP_IsNaN(42.0F);
-
-  printf("f_FP_IsNaN(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsNaN_driver(void)
-{
-  const SBool __result = d_FP_IsNaN(42.0);
-
-  printf("d_FP_IsNaN(42.0) = %d\n", __result);
-}
-
-void f_FP_IsNegative_driver(void)
-{
-  const SBool __result = f_FP_IsNegative(42.0F);
-
-  printf("f_FP_IsNegative(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsNegative_driver(void)
-{
-  const SBool __result = d_FP_IsNegative(42.0);
-
-  printf("d_FP_IsNegative(42.0) = %d\n", __result);
-}
-
-void f_FP_IsPositive_driver(void)
-{
-  const SBool __result = f_FP_IsPositive(42.0F);
-
-  printf("f_FP_IsPositive(42.0F) = %d\n", __result);
-}
-
-void d_FP_IsPositive_driver(void)
-{
-  const SBool __result = d_FP_IsPositive(42.0);
-
-  printf("d_FP_IsPositive(42.0) = %d\n", __result);
-}
-
-int main(void)
-{
-  printf("====================================\n");
-  printf("** Driver run for toFP_Int8_ToFloat:\n");
-  printf("====================================\n");
-  toFP_Int8_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Int16_ToFloat:\n");
-  printf("=====================================\n");
-  toFP_Int16_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Int32_ToFloat:\n");
-  printf("=====================================\n");
-  toFP_Int32_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Int64_ToFloat:\n");
-  printf("=====================================\n");
-  toFP_Int64_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Word8_ToFloat:\n");
-  printf("=====================================\n");
-  toFP_Word8_ToFloat_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Word16_ToFloat:\n");
-  printf("======================================\n");
-  toFP_Word16_ToFloat_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Word32_ToFloat:\n");
-  printf("======================================\n");
-  toFP_Word32_ToFloat_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Word64_ToFloat:\n");
-  printf("======================================\n");
-  toFP_Word64_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Float_ToFloat:\n");
-  printf("=====================================\n");
-  toFP_Float_ToFloat_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Double_ToFloat:\n");
-  printf("======================================\n");
-  toFP_Double_ToFloat_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for toFP_Integer_ToFloat:\n");
-  printf("=======================================\n");
-  toFP_Integer_ToFloat_driver();
-
-  printf("====================================\n");
-  printf("** Driver run for toFP_Real_ToFloat:\n");
-  printf("====================================\n");
-  toFP_Real_ToFloat_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Int8_ToDouble:\n");
-  printf("=====================================\n");
-  toFP_Int8_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Int16_ToDouble:\n");
-  printf("======================================\n");
-  toFP_Int16_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Int32_ToDouble:\n");
-  printf("======================================\n");
-  toFP_Int32_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Int64_ToDouble:\n");
-  printf("======================================\n");
-  toFP_Int64_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Word8_ToDouble:\n");
-  printf("======================================\n");
-  toFP_Word8_ToDouble_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for toFP_Word16_ToDouble:\n");
-  printf("=======================================\n");
-  toFP_Word16_ToDouble_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for toFP_Word32_ToDouble:\n");
-  printf("=======================================\n");
-  toFP_Word32_ToDouble_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for toFP_Word64_ToDouble:\n");
-  printf("=======================================\n");
-  toFP_Word64_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for toFP_Float_ToDouble:\n");
-  printf("======================================\n");
-  toFP_Float_ToDouble_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for toFP_Double_ToDouble:\n");
-  printf("=======================================\n");
-  toFP_Double_ToDouble_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for toFP_Integer_ToDouble:\n");
-  printf("========================================\n");
-  toFP_Integer_ToDouble_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for toFP_Real_ToDouble:\n");
-  printf("=====================================\n");
-  toFP_Real_ToDouble_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for fromFP_Float_ToInt8:\n");
-  printf("======================================\n");
-  fromFP_Float_ToInt8_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_Float_ToInt16:\n");
-  printf("=======================================\n");
-  fromFP_Float_ToInt16_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_Float_ToInt32:\n");
-  printf("=======================================\n");
-  fromFP_Float_ToInt32_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_Float_ToInt64:\n");
-  printf("=======================================\n");
-  fromFP_Float_ToInt64_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_Float_ToWord8:\n");
-  printf("=======================================\n");
-  fromFP_Float_ToWord8_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_Float_ToWord16:\n");
-  printf("========================================\n");
-  fromFP_Float_ToWord16_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_Float_ToWord32:\n");
-  printf("========================================\n");
-  fromFP_Float_ToWord32_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_Float_ToWord64:\n");
-  printf("========================================\n");
-  fromFP_Float_ToWord64_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_Float_ToFloat:\n");
-  printf("=======================================\n");
-  fromFP_Float_ToFloat_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_Float_ToDouble:\n");
-  printf("========================================\n");
-  fromFP_Float_ToDouble_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_Float_ToInteger:\n");
-  printf("=========================================\n");
-  fromFP_Float_ToInteger_driver();
-
-  printf("======================================\n");
-  printf("** Driver run for fromFP_Float_ToReal:\n");
-  printf("======================================\n");
-  fromFP_Float_ToReal_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Int8:\n");
-  printf("=======================================\n");
-  fromFP_DoubleTo_Int8_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Int16:\n");
-  printf("========================================\n");
-  fromFP_DoubleTo_Int16_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Int32:\n");
-  printf("========================================\n");
-  fromFP_DoubleTo_Int32_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Int64:\n");
-  printf("========================================\n");
-  fromFP_DoubleTo_Int64_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Word8:\n");
-  printf("========================================\n");
-  fromFP_DoubleTo_Word8_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Word16:\n");
-  printf("=========================================\n");
-  fromFP_DoubleTo_Word16_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Word32:\n");
-  printf("=========================================\n");
-  fromFP_DoubleTo_Word32_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Word64:\n");
-  printf("=========================================\n");
-  fromFP_DoubleTo_Word64_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Float:\n");
-  printf("========================================\n");
-  fromFP_DoubleTo_Float_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Double:\n");
-  printf("=========================================\n");
-  fromFP_DoubleTo_Double_driver();
-
-  printf("==========================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Integer:\n");
-  printf("==========================================\n");
-  fromFP_DoubleTo_Integer_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for fromFP_DoubleTo_Real:\n");
-  printf("=======================================\n");
-  fromFP_DoubleTo_Real_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_SWord32_SFloat:\n");
-  printf("========================================\n");
-  fromFP_SWord32_SFloat_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_SWord64_SDouble:\n");
-  printf("=========================================\n");
-  fromFP_SWord64_SDouble_driver();
-
-  printf("========================================\n");
-  printf("** Driver run for fromFP_SFloat_SWord32:\n");
-  printf("========================================\n");
-  fromFP_SFloat_SWord32_driver();
-
-  printf("=========================================\n");
-  printf("** Driver run for fromFP_SDouble_SWord64:\n");
-  printf("=========================================\n");
-  fromFP_SDouble_SWord64_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Abs:\n");
-  printf("===========================\n");
-  f_FP_Abs_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Abs:\n");
-  printf("===========================\n");
-  d_FP_Abs_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Neg:\n");
-  printf("===========================\n");
-  f_FP_Neg_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Neg:\n");
-  printf("===========================\n");
-  d_FP_Neg_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Add:\n");
-  printf("===========================\n");
-  f_FP_Add_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Add:\n");
-  printf("===========================\n");
-  d_FP_Add_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Sub:\n");
-  printf("===========================\n");
-  f_FP_Sub_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Sub:\n");
-  printf("===========================\n");
-  d_FP_Sub_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Mul:\n");
-  printf("===========================\n");
-  f_FP_Mul_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Mul:\n");
-  printf("===========================\n");
-  d_FP_Mul_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Div:\n");
-  printf("===========================\n");
-  f_FP_Div_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Div:\n");
-  printf("===========================\n");
-  d_FP_Div_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_FMA:\n");
-  printf("===========================\n");
-  f_FP_FMA_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_FMA:\n");
-  printf("===========================\n");
-  d_FP_FMA_driver();
-
-  printf("============================\n");
-  printf("** Driver run for f_FP_Sqrt:\n");
-  printf("============================\n");
-  f_FP_Sqrt_driver();
-
-  printf("============================\n");
-  printf("** Driver run for d_FP_Sqrt:\n");
-  printf("============================\n");
-  d_FP_Sqrt_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Rem:\n");
-  printf("===========================\n");
-  f_FP_Rem_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Rem:\n");
-  printf("===========================\n");
-  d_FP_Rem_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for f_FP_RoundToIntegral:\n");
-  printf("=======================================\n");
-  f_FP_RoundToIntegral_driver();
-
-  printf("=======================================\n");
-  printf("** Driver run for d_FP_RoundToIntegral:\n");
-  printf("=======================================\n");
-  d_FP_RoundToIntegral_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Min:\n");
-  printf("===========================\n");
-  f_FP_Min_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Min:\n");
-  printf("===========================\n");
-  d_FP_Min_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for f_FP_Max:\n");
-  printf("===========================\n");
-  f_FP_Max_driver();
-
-  printf("===========================\n");
-  printf("** Driver run for d_FP_Max:\n");
-  printf("===========================\n");
-  d_FP_Max_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for f_FP_IsEqualObject:\n");
-  printf("=====================================\n");
-  f_FP_IsEqualObject_driver();
-
-  printf("=====================================\n");
-  printf("** Driver run for d_FP_IsEqualObject:\n");
-  printf("=====================================\n");
-  d_FP_IsEqualObject_driver();
-
-  printf("================================\n");
-  printf("** Driver run for f_FP_IsNormal:\n");
-  printf("================================\n");
-  f_FP_IsNormal_driver();
-
-  printf("================================\n");
-  printf("** Driver run for d_FP_IsNormal:\n");
-  printf("================================\n");
-  d_FP_IsNormal_driver();
-
-  printf("==============================\n");
-  printf("** Driver run for f_FP_IsZero:\n");
-  printf("==============================\n");
-  f_FP_IsZero_driver();
-
-  printf("==============================\n");
-  printf("** Driver run for d_FP_IsZero:\n");
-  printf("==============================\n");
-  d_FP_IsZero_driver();
-
-  printf("===================================\n");
-  printf("** Driver run for f_FP_IsSubnormal:\n");
-  printf("===================================\n");
-  f_FP_IsSubnormal_driver();
-
-  printf("===================================\n");
-  printf("** Driver run for d_FP_IsSubnormal:\n");
-  printf("===================================\n");
-  d_FP_IsSubnormal_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for f_FP_IsInfinite:\n");
-  printf("==================================\n");
-  f_FP_IsInfinite_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for d_FP_IsInfinite:\n");
-  printf("==================================\n");
-  d_FP_IsInfinite_driver();
-
-  printf("=============================\n");
-  printf("** Driver run for f_FP_IsNaN:\n");
-  printf("=============================\n");
-  f_FP_IsNaN_driver();
-
-  printf("=============================\n");
-  printf("** Driver run for d_FP_IsNaN:\n");
-  printf("=============================\n");
-  d_FP_IsNaN_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for f_FP_IsNegative:\n");
-  printf("==================================\n");
-  f_FP_IsNegative_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for d_FP_IsNegative:\n");
-  printf("==================================\n");
-  d_FP_IsNegative_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for f_FP_IsPositive:\n");
-  printf("==================================\n");
-  f_FP_IsPositive_driver();
-
-  printf("==================================\n");
-  printf("** Driver run for d_FP_IsPositive:\n");
-  printf("==================================\n");
-  d_FP_IsPositive_driver();
-
-  return 0;
-}
-== END: "floatCodeGen_driver.c" ==================
-== BEGIN: "Makefile" ================
-# Makefile for floatCodeGen. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-AR?=ar
-ARFLAGS?=cr
-
-all: floatCodeGen.a floatCodeGen_driver
-
-floatCodeGen.a: toFP_Int8_ToFloat.o toFP_Int16_ToFloat.o toFP_Int32_ToFloat.o toFP_Int64_ToFloat.o toFP_Word8_ToFloat.o toFP_Word16_ToFloat.o toFP_Word32_ToFloat.o toFP_Word64_ToFloat.o toFP_Float_ToFloat.o toFP_Double_ToFloat.o toFP_Integer_ToFloat.o toFP_Real_ToFloat.o toFP_Int8_ToDouble.o toFP_Int16_ToDouble.o toFP_Int32_ToDouble.o toFP_Int64_ToDouble.o toFP_Word8_ToDouble.o toFP_Word16_ToDouble.o toFP_Word32_ToDouble.o toFP_Word64_ToDouble.o toFP_Float_ToDouble.o toFP_Double_ToDouble.o toFP_Integer_ToDouble.o toFP_Real_ToDouble.o fromFP_Float_ToInt8.o fromFP_Float_ToInt16.o fromFP_Float_ToInt32.o fromFP_Float_ToInt64.o fromFP_Float_ToWord8.o fromFP_Float_ToWord16.o fromFP_Float_ToWord32.o fromFP_Float_ToWord64.o fromFP_Float_ToFloat.o fromFP_Float_ToDouble.o fromFP_Float_ToInteger.o fromFP_Float_ToReal.o fromFP_DoubleTo_Int8.o fromFP_DoubleTo_Int16.o fromFP_DoubleTo_Int32.o fromFP_DoubleTo_Int64.o fromFP_DoubleTo_Word8.o fromFP_DoubleTo_Word16.o fromFP_DoubleTo_Word32.o fromFP_DoubleTo_Word64.o fromFP_DoubleTo_Float.o fromFP_DoubleTo_Double.o fromFP_DoubleTo_Integer.o fromFP_DoubleTo_Real.o fromFP_SWord32_SFloat.o fromFP_SWord64_SDouble.o fromFP_SFloat_SWord32.o fromFP_SDouble_SWord64.o f_FP_Abs.o d_FP_Abs.o f_FP_Neg.o d_FP_Neg.o f_FP_Add.o d_FP_Add.o f_FP_Sub.o d_FP_Sub.o f_FP_Mul.o d_FP_Mul.o f_FP_Div.o d_FP_Div.o f_FP_FMA.o d_FP_FMA.o f_FP_Sqrt.o d_FP_Sqrt.o f_FP_Rem.o d_FP_Rem.o f_FP_RoundToIntegral.o d_FP_RoundToIntegral.o f_FP_Min.o d_FP_Min.o f_FP_Max.o d_FP_Max.o f_FP_IsEqualObject.o d_FP_IsEqualObject.o f_FP_IsNormal.o d_FP_IsNormal.o f_FP_IsZero.o d_FP_IsZero.o f_FP_IsSubnormal.o d_FP_IsSubnormal.o f_FP_IsInfinite.o d_FP_IsInfinite.o f_FP_IsNaN.o d_FP_IsNaN.o f_FP_IsNegative.o d_FP_IsNegative.o f_FP_IsPositive.o d_FP_IsPositive.o
-	${AR} ${ARFLAGS} $@ $^
-
-floatCodeGen_driver: floatCodeGen_driver.c floatCodeGen.h
-	${CC} ${CCFLAGS} $< -o $@ floatCodeGen.a
-
-toFP_Int8_ToFloat.o: toFP_Int8_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int16_ToFloat.o: toFP_Int16_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int32_ToFloat.o: toFP_Int32_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int64_ToFloat.o: toFP_Int64_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word8_ToFloat.o: toFP_Word8_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word16_ToFloat.o: toFP_Word16_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word32_ToFloat.o: toFP_Word32_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word64_ToFloat.o: toFP_Word64_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Float_ToFloat.o: toFP_Float_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Double_ToFloat.o: toFP_Double_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Integer_ToFloat.o: toFP_Integer_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Real_ToFloat.o: toFP_Real_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int8_ToDouble.o: toFP_Int8_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int16_ToDouble.o: toFP_Int16_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int32_ToDouble.o: toFP_Int32_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Int64_ToDouble.o: toFP_Int64_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word8_ToDouble.o: toFP_Word8_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word16_ToDouble.o: toFP_Word16_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word32_ToDouble.o: toFP_Word32_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Word64_ToDouble.o: toFP_Word64_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Float_ToDouble.o: toFP_Float_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Double_ToDouble.o: toFP_Double_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Integer_ToDouble.o: toFP_Integer_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-toFP_Real_ToDouble.o: toFP_Real_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToInt8.o: fromFP_Float_ToInt8.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToInt16.o: fromFP_Float_ToInt16.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToInt32.o: fromFP_Float_ToInt32.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToInt64.o: fromFP_Float_ToInt64.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToWord8.o: fromFP_Float_ToWord8.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToWord16.o: fromFP_Float_ToWord16.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToWord32.o: fromFP_Float_ToWord32.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToWord64.o: fromFP_Float_ToWord64.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToFloat.o: fromFP_Float_ToFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToDouble.o: fromFP_Float_ToDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToInteger.o: fromFP_Float_ToInteger.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_Float_ToReal.o: fromFP_Float_ToReal.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Int8.o: fromFP_DoubleTo_Int8.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Int16.o: fromFP_DoubleTo_Int16.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Int32.o: fromFP_DoubleTo_Int32.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Int64.o: fromFP_DoubleTo_Int64.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Word8.o: fromFP_DoubleTo_Word8.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Word16.o: fromFP_DoubleTo_Word16.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Word32.o: fromFP_DoubleTo_Word32.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Word64.o: fromFP_DoubleTo_Word64.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Float.o: fromFP_DoubleTo_Float.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Double.o: fromFP_DoubleTo_Double.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Integer.o: fromFP_DoubleTo_Integer.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_DoubleTo_Real.o: fromFP_DoubleTo_Real.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_SWord32_SFloat.o: fromFP_SWord32_SFloat.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_SWord64_SDouble.o: fromFP_SWord64_SDouble.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_SFloat_SWord32.o: fromFP_SFloat_SWord32.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-fromFP_SDouble_SWord64.o: fromFP_SDouble_SWord64.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Abs.o: f_FP_Abs.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Abs.o: d_FP_Abs.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Neg.o: f_FP_Neg.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Neg.o: d_FP_Neg.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Add.o: f_FP_Add.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Add.o: d_FP_Add.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Sub.o: f_FP_Sub.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Sub.o: d_FP_Sub.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Mul.o: f_FP_Mul.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Mul.o: d_FP_Mul.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Div.o: f_FP_Div.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Div.o: d_FP_Div.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_FMA.o: f_FP_FMA.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_FMA.o: d_FP_FMA.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Sqrt.o: f_FP_Sqrt.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Sqrt.o: d_FP_Sqrt.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Rem.o: f_FP_Rem.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Rem.o: d_FP_Rem.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_RoundToIntegral.o: f_FP_RoundToIntegral.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_RoundToIntegral.o: d_FP_RoundToIntegral.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Min.o: f_FP_Min.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Min.o: d_FP_Min.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_Max.o: f_FP_Max.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_Max.o: d_FP_Max.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsEqualObject.o: f_FP_IsEqualObject.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsEqualObject.o: d_FP_IsEqualObject.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsNormal.o: f_FP_IsNormal.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsNormal.o: d_FP_IsNormal.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsZero.o: f_FP_IsZero.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsZero.o: d_FP_IsZero.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsSubnormal.o: f_FP_IsSubnormal.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsSubnormal.o: d_FP_IsSubnormal.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsInfinite.o: f_FP_IsInfinite.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsInfinite.o: d_FP_IsInfinite.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsNaN.o: f_FP_IsNaN.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsNaN.o: d_FP_IsNaN.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsNegative.o: f_FP_IsNegative.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsNegative.o: d_FP_IsNegative.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-f_FP_IsPositive.o: f_FP_IsPositive.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-d_FP_IsPositive.o: d_FP_IsPositive.c floatCodeGen.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f floatCodeGen.a floatCodeGen_driver
-== END: "Makefile" ==================
diff --git a/SBVUnitTest/GoldFiles/gcd.gold b/SBVUnitTest/GoldFiles/gcd.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/gcd.gold
+++ /dev/null
@@ -1,141 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for sgcd. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: sgcd_driver
-
-sgcd.o: sgcd.c sgcd.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-sgcd_driver.o: sgcd_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-sgcd_driver: sgcd.o sgcd_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f sgcd_driver
-== END: "Makefile" ==================
-== BEGIN: "sgcd.h" ================
-/* Header file for sgcd. Automatically generated by SBV. Do not edit! */
-
-#ifndef __sgcd__HEADER_INCLUDED__
-#define __sgcd__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord8 sgcd(const SWord8 x, const SWord8 y);
-
-#endif /* __sgcd__HEADER_INCLUDED__ */
-== END: "sgcd.h" ==================
-== BEGIN: "sgcd_driver.c" ================
-/* Example driver program for sgcd. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "sgcd.h"
-
-int main(void)
-{
-  const SWord8 __result = sgcd(55, 154);
-
-  printf("sgcd(55, 154) = %"PRIu8"\n", __result);
-
-  return 0;
-}
-== END: "sgcd_driver.c" ==================
-== BEGIN: "sgcd.c" ================
-/* File: "sgcd.c". Automatically generated by SBV. Do not edit! */
-
-#include "sgcd.h"
-
-SWord8 sgcd(const SWord8 x, const SWord8 y)
-{
-  const SWord8 s0 = x;
-  const SWord8 s1 = y;
-  const SBool  s3 = s1 == 0;
-  const SWord8 s4 = (s1 == 0) ? s0 : (s0 % s1);
-  const SWord8 s5 = s3 ? s0 : s4;
-  const SBool  s6 = 0 == s5;
-  const SWord8 s7 = (s5 == 0) ? s1 : (s1 % s5);
-  const SWord8 s8 = s6 ? s1 : s7;
-  const SBool  s9 = 0 == s8;
-  const SWord8 s10 = (s8 == 0) ? s5 : (s5 % s8);
-  const SWord8 s11 = s9 ? s5 : s10;
-  const SBool  s12 = 0 == s11;
-  const SWord8 s13 = (s11 == 0) ? s8 : (s8 % s11);
-  const SWord8 s14 = s12 ? s8 : s13;
-  const SBool  s15 = 0 == s14;
-  const SWord8 s16 = (s14 == 0) ? s11 : (s11 % s14);
-  const SWord8 s17 = s15 ? s11 : s16;
-  const SBool  s18 = 0 == s17;
-  const SWord8 s19 = (s17 == 0) ? s14 : (s14 % s17);
-  const SWord8 s20 = s18 ? s14 : s19;
-  const SBool  s21 = 0 == s20;
-  const SWord8 s22 = (s20 == 0) ? s17 : (s17 % s20);
-  const SWord8 s23 = s21 ? s17 : s22;
-  const SBool  s24 = 0 == s23;
-  const SWord8 s25 = (s23 == 0) ? s20 : (s20 % s23);
-  const SWord8 s26 = s24 ? s20 : s25;
-  const SBool  s27 = 0 == s26;
-  const SWord8 s28 = (s26 == 0) ? s23 : (s23 % s26);
-  const SWord8 s29 = s27 ? s23 : s28;
-  const SBool  s30 = 0 == s29;
-  const SWord8 s31 = (s29 == 0) ? s26 : (s26 % s29);
-  const SWord8 s32 = s30 ? s26 : s31;
-  const SBool  s33 = 0 == s32;
-  const SWord8 s34 = (s32 == 0) ? s29 : (s29 % s32);
-  const SWord8 s35 = s33 ? s29 : s34;
-  const SBool  s36 = 0 == s35;
-  const SWord8 s37 = s36 ? s32 : s35;
-  const SWord8 s38 = s33 ? s29 : s37;
-  const SWord8 s39 = s30 ? s26 : s38;
-  const SWord8 s40 = s27 ? s23 : s39;
-  const SWord8 s41 = s24 ? s20 : s40;
-  const SWord8 s42 = s21 ? s17 : s41;
-  const SWord8 s43 = s18 ? s14 : s42;
-  const SWord8 s44 = s15 ? s11 : s43;
-  const SWord8 s45 = s12 ? s8 : s44;
-  const SWord8 s46 = s9 ? s5 : s45;
-  const SWord8 s47 = s6 ? s1 : s46;
-  const SWord8 s48 = s3 ? s0 : s47;
-
-  return s48;
-}
-== END: "sgcd.c" ==================
diff --git a/SBVUnitTest/GoldFiles/higher-1.gold b/SBVUnitTest/GoldFiles/higher-1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-1.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-2.gold b/SBVUnitTest/GoldFiles/higher-2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-2.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-3.gold b/SBVUnitTest/GoldFiles/higher-3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-3.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-4.gold b/SBVUnitTest/GoldFiles/higher-4.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-4.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-5.gold b/SBVUnitTest/GoldFiles/higher-5.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-5.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-6.gold b/SBVUnitTest/GoldFiles/higher-6.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-6.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-7.gold b/SBVUnitTest/GoldFiles/higher-7.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-7.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-8.gold b/SBVUnitTest/GoldFiles/higher-8.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-8.gold
+++ /dev/null
@@ -1,1 +0,0 @@
-Q.E.D.
diff --git a/SBVUnitTest/GoldFiles/higher-9.gold b/SBVUnitTest/GoldFiles/higher-9.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/higher-9.gold
+++ /dev/null
@@ -1,2 +0,0 @@
-Falsifiable. Counter-example:
-  s0 = 128 :: Word8
diff --git a/SBVUnitTest/GoldFiles/iteTest1.gold b/SBVUnitTest/GoldFiles/iteTest1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/iteTest1.gold
+++ /dev/null
@@ -1,14 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
diff --git a/SBVUnitTest/GoldFiles/iteTest2.gold b/SBVUnitTest/GoldFiles/iteTest2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/iteTest2.gold
+++ /dev/null
@@ -1,14 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
diff --git a/SBVUnitTest/GoldFiles/iteTest3.gold b/SBVUnitTest/GoldFiles/iteTest3.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/iteTest3.gold
+++ /dev/null
@@ -1,14 +0,0 @@
-INPUTS
-  s0 :: SWord8, aliasing "x"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
diff --git a/SBVUnitTest/GoldFiles/legato.gold b/SBVUnitTest/GoldFiles/legato.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/legato.gold
+++ /dev/null
@@ -1,8960 +0,0 @@
-INPUTS
-  s0 :: SWord32, existential, aliasing "addrX"
-  s1 :: SWord8, existential, aliasing "x"
-  s2 :: SWord32, existential, aliasing "addrY"
-  s3 :: SWord8, existential, aliasing "y"
-  s4 :: SWord32, existential, aliasing "addrLow"
-  s5 :: SWord8, existential, aliasing "regX"
-  s6 :: SWord8, existential, aliasing "regA"
-  s7 :: SWord8, existential, aliasing "memVals"
-  s8 :: SBool, existential, aliasing "flagC"
-  s9 :: SBool, existential, aliasing "flagZ"
-CONSTANTS
-  s_2 = False :: Bool
-  s_1 = True :: Bool
-  s19 = 0 :: Word1
-  s17 = 0 :: Word8
-  s24 = 128 :: Word8
-  s26 = 127 :: Word8
-  s16 = 256 :: Word16
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-USER GIVEN CODE SEGMENTS
-AXIOMS
-DEFINE
-  s10 :: SBool = s0 /= s2
-  s11 :: SBool = s0 /= s4
-  s12 :: SBool = s10 & s11
-  s13 :: SBool = s2 /= s4
-  s14 :: SBool = s12 & s13
-  s15 :: SBool = ~ s14
-  s18 :: SWord1 = choose [0:0] s1
-  s20 :: SBool = s18 /= s19
-  s21 :: SBool = s_2 == s20
-  s22 :: SBool = s0 == s4
-  s23 :: SWord8 = s1 >>> 1
-  s25 :: SWord8 = s23 | s24
-  s27 :: SWord8 = s23 & s26
-  s28 :: SWord8 = if s8 then s25 else s27
-  s29 :: SBool = s2 == s4
-  s30 :: SWord8 = if s29 then s3 else s7
-  s31 :: SWord8 = if s22 then s1 else s30
-  s32 :: SWord8 = if s22 then s28 else s31
-  s33 :: SWord8 = s32 >>> 1
-  s34 :: SWord8 = s26 & s33
-  s35 :: SWord8 = if s22 then s34 else s28
-  s36 :: SWord1 = choose [0:0] s35
-  s37 :: SBool = s19 /= s36
-  s38 :: SBool = s_2 == s37
-  s39 :: SWord8 = if s20 then s24 else s17
-  s40 :: SWord1 = choose [0:0] s39
-  s41 :: SBool = s19 /= s40
-  s42 :: SWord1 = choose [0:0] s32
-  s43 :: SBool = s19 /= s42
-  s44 :: SWord8 = s35 >>> 1
-  s45 :: SWord8 = s24 | s44
-  s46 :: SWord8 = s26 & s44
-  s47 :: SWord8 = if s43 then s45 else s46
-  s48 :: SWord8 = if s22 then s47 else s34
-  s49 :: SWord8 = s48 >>> 1
-  s50 :: SWord8 = s24 | s49
-  s51 :: SWord8 = s26 & s49
-  s52 :: SWord8 = if s41 then s50 else s51
-  s53 :: SWord8 = if s22 then s52 else s47
-  s54 :: SWord1 = choose [0:0] s53
-  s55 :: SBool = s19 /= s54
-  s56 :: SBool = s_2 == s55
-  s57 :: SWord8 = s39 >>> 1
-  s58 :: SWord8 = s24 | s57
-  s59 :: SWord8 = s26 & s57
-  s60 :: SWord8 = if s37 then s58 else s59
-  s61 :: SWord1 = choose [0:0] s60
-  s62 :: SBool = s19 /= s61
-  s63 :: SWord1 = choose [0:0] s48
-  s64 :: SBool = s19 /= s63
-  s65 :: SWord8 = s53 >>> 1
-  s66 :: SWord8 = s24 | s65
-  s67 :: SWord8 = s26 & s65
-  s68 :: SWord8 = if s64 then s66 else s67
-  s69 :: SWord8 = if s22 then s68 else s52
-  s70 :: SWord8 = s69 >>> 1
-  s71 :: SWord8 = s24 | s70
-  s72 :: SWord8 = s26 & s70
-  s73 :: SWord8 = if s62 then s71 else s72
-  s74 :: SWord8 = if s22 then s73 else s68
-  s75 :: SWord1 = choose [0:0] s74
-  s76 :: SBool = s19 /= s75
-  s77 :: SBool = s_2 == s76
-  s78 :: SWord8 = s60 >>> 1
-  s79 :: SWord8 = s24 | s78
-  s80 :: SWord8 = s26 & s78
-  s81 :: SWord8 = if s55 then s79 else s80
-  s82 :: SWord1 = choose [0:0] s81
-  s83 :: SBool = s19 /= s82
-  s84 :: SWord1 = choose [0:0] s69
-  s85 :: SBool = s19 /= s84
-  s86 :: SWord8 = s74 >>> 1
-  s87 :: SWord8 = s24 | s86
-  s88 :: SWord8 = s26 & s86
-  s89 :: SWord8 = if s85 then s87 else s88
-  s90 :: SWord8 = if s22 then s89 else s73
-  s91 :: SWord8 = s90 >>> 1
-  s92 :: SWord8 = s24 | s91
-  s93 :: SWord8 = s26 & s91
-  s94 :: SWord8 = if s83 then s92 else s93
-  s95 :: SWord8 = if s22 then s94 else s89
-  s96 :: SWord1 = choose [0:0] s95
-  s97 :: SBool = s19 /= s96
-  s98 :: SBool = s_2 == s97
-  s99 :: SWord8 = s81 >>> 1
-  s100 :: SWord8 = s24 | s99
-  s101 :: SWord8 = s26 & s99
-  s102 :: SWord8 = if s76 then s100 else s101
-  s103 :: SWord1 = choose [0:0] s102
-  s104 :: SBool = s19 /= s103
-  s105 :: SWord1 = choose [0:0] s90
-  s106 :: SBool = s19 /= s105
-  s107 :: SWord8 = s95 >>> 1
-  s108 :: SWord8 = s24 | s107
-  s109 :: SWord8 = s26 & s107
-  s110 :: SWord8 = if s106 then s108 else s109
-  s111 :: SWord8 = if s22 then s110 else s94
-  s112 :: SWord8 = s111 >>> 1
-  s113 :: SWord8 = s24 | s112
-  s114 :: SWord8 = s26 & s112
-  s115 :: SWord8 = if s104 then s113 else s114
-  s116 :: SWord8 = if s22 then s115 else s110
-  s117 :: SWord1 = choose [0:0] s116
-  s118 :: SBool = s19 /= s117
-  s119 :: SBool = s_2 == s118
-  s120 :: SWord8 = s102 >>> 1
-  s121 :: SWord8 = s24 | s120
-  s122 :: SWord8 = s26 & s120
-  s123 :: SWord8 = if s97 then s121 else s122
-  s124 :: SWord1 = choose [0:0] s123
-  s125 :: SBool = s19 /= s124
-  s126 :: SWord1 = choose [0:0] s111
-  s127 :: SBool = s19 /= s126
-  s128 :: SWord8 = s116 >>> 1
-  s129 :: SWord8 = s24 | s128
-  s130 :: SWord8 = s26 & s128
-  s131 :: SWord8 = if s127 then s129 else s130
-  s132 :: SWord8 = if s22 then s131 else s115
-  s133 :: SWord8 = s132 >>> 1
-  s134 :: SWord8 = s24 | s133
-  s135 :: SWord8 = s26 & s133
-  s136 :: SWord8 = if s125 then s134 else s135
-  s137 :: SWord8 = if s22 then s136 else s131
-  s138 :: SWord1 = choose [0:0] s137
-  s139 :: SBool = s19 /= s138
-  s140 :: SBool = s_2 == s139
-  s141 :: SWord8 = s123 >>> 1
-  s142 :: SWord8 = s24 | s141
-  s143 :: SWord8 = s26 & s141
-  s144 :: SWord8 = if s118 then s142 else s143
-  s145 :: SWord1 = choose [0:0] s144
-  s146 :: SBool = s19 /= s145
-  s147 :: SWord1 = choose [0:0] s132
-  s148 :: SBool = s19 /= s147
-  s149 :: SWord8 = s137 >>> 1
-  s150 :: SWord8 = s24 | s149
-  s151 :: SWord8 = s26 & s149
-  s152 :: SWord8 = if s148 then s150 else s151
-  s153 :: SWord8 = if s22 then s152 else s136
-  s154 :: SWord8 = s153 >>> 1
-  s155 :: SWord8 = s24 | s154
-  s156 :: SWord8 = s26 & s154
-  s157 :: SWord8 = if s146 then s155 else s156
-  s158 :: SWord8 = if s22 then s157 else s152
-  s159 :: SWord1 = choose [0:0] s158
-  s160 :: SBool = s19 /= s159
-  s161 :: SBool = s_2 == s160
-  s162 :: SWord8 = s144 >>> 1
-  s163 :: SWord8 = s24 | s162
-  s164 :: SWord8 = s26 & s162
-  s165 :: SWord8 = if s139 then s163 else s164
-  s166 :: SWord8 = s165 >>> 1
-  s167 :: SWord8 = s24 | s166
-  s168 :: SWord8 = s26 & s166
-  s169 :: SWord8 = if s160 then s167 else s168
-  s170 :: SBool = s0 == s2
-  s171 :: SWord1 = choose [0:0] s153
-  s172 :: SBool = s19 /= s171
-  s173 :: SWord8 = s158 >>> 1
-  s174 :: SWord8 = s24 | s173
-  s175 :: SWord8 = s26 & s173
-  s176 :: SWord8 = if s172 then s174 else s175
-  s177 :: SWord8 = if s170 then s1 else s3
-  s178 :: SWord8 = if s170 then s28 else s177
-  s179 :: SWord8 = if s29 then s34 else s178
-  s180 :: SWord8 = if s170 then s47 else s179
-  s181 :: SWord8 = if s29 then s52 else s180
-  s182 :: SWord8 = if s170 then s68 else s181
-  s183 :: SWord8 = if s29 then s73 else s182
-  s184 :: SWord8 = if s170 then s89 else s183
-  s185 :: SWord8 = if s29 then s94 else s184
-  s186 :: SWord8 = if s170 then s110 else s185
-  s187 :: SWord8 = if s29 then s115 else s186
-  s188 :: SWord8 = if s170 then s131 else s187
-  s189 :: SWord8 = if s29 then s136 else s188
-  s190 :: SWord8 = if s170 then s152 else s189
-  s191 :: SWord8 = if s29 then s157 else s190
-  s192 :: SWord8 = if s170 then s176 else s191
-  s193 :: SWord8 = s165 + s192
-  s194 :: SBool = s193 < s192
-  s195 :: SBool = s193 < s165
-  s196 :: SBool = s194 | s195
-  s197 :: SWord8 = s193 >>> 1
-  s198 :: SWord8 = s24 | s197
-  s199 :: SWord8 = s26 & s197
-  s200 :: SWord8 = if s196 then s198 else s199
-  s201 :: SWord8 = if s161 then s169 else s200
-  s202 :: SWord8 = s144 + s190
-  s203 :: SWord1 = choose [0:0] s202
-  s204 :: SBool = s19 /= s203
-  s205 :: SWord8 = if s204 then s155 else s156
-  s206 :: SWord8 = if s22 then s205 else s152
-  s207 :: SWord1 = choose [0:0] s206
-  s208 :: SBool = s19 /= s207
-  s209 :: SBool = s_2 == s208
-  s210 :: SBool = s202 < s190
-  s211 :: SBool = s202 < s144
-  s212 :: SBool = s210 | s211
-  s213 :: SWord8 = s202 >>> 1
-  s214 :: SWord8 = s24 | s213
-  s215 :: SWord8 = s26 & s213
-  s216 :: SWord8 = if s212 then s214 else s215
-  s217 :: SWord8 = s216 >>> 1
-  s218 :: SWord8 = s24 | s217
-  s219 :: SWord8 = s26 & s217
-  s220 :: SWord8 = if s208 then s218 else s219
-  s221 :: SWord8 = s206 >>> 1
-  s222 :: SWord8 = s24 | s221
-  s223 :: SWord8 = s26 & s221
-  s224 :: SWord8 = if s172 then s222 else s223
-  s225 :: SWord8 = if s29 then s205 else s190
-  s226 :: SWord8 = if s170 then s224 else s225
-  s227 :: SWord8 = s216 + s226
-  s228 :: SBool = s227 < s226
-  s229 :: SBool = s227 < s216
-  s230 :: SBool = s228 | s229
-  s231 :: SWord8 = s227 >>> 1
-  s232 :: SWord8 = s24 | s231
-  s233 :: SWord8 = s26 & s231
-  s234 :: SWord8 = if s230 then s232 else s233
-  s235 :: SWord8 = if s209 then s220 else s234
-  s236 :: SWord8 = if s140 then s201 else s235
-  s237 :: SWord8 = s123 + s188
-  s238 :: SWord1 = choose [0:0] s237
-  s239 :: SBool = s19 /= s238
-  s240 :: SWord8 = if s239 then s134 else s135
-  s241 :: SWord8 = if s22 then s240 else s131
-  s242 :: SWord1 = choose [0:0] s241
-  s243 :: SBool = s19 /= s242
-  s244 :: SBool = s_2 == s243
-  s245 :: SBool = s237 < s188
-  s246 :: SBool = s237 < s123
-  s247 :: SBool = s245 | s246
-  s248 :: SWord8 = s237 >>> 1
-  s249 :: SWord8 = s24 | s248
-  s250 :: SWord8 = s26 & s248
-  s251 :: SWord8 = if s247 then s249 else s250
-  s252 :: SWord1 = choose [0:0] s251
-  s253 :: SBool = s19 /= s252
-  s254 :: SWord8 = s241 >>> 1
-  s255 :: SWord8 = s24 | s254
-  s256 :: SWord8 = s26 & s254
-  s257 :: SWord8 = if s148 then s255 else s256
-  s258 :: SWord8 = if s22 then s257 else s240
-  s259 :: SWord8 = s258 >>> 1
-  s260 :: SWord8 = s24 | s259
-  s261 :: SWord8 = s26 & s259
-  s262 :: SWord8 = if s253 then s260 else s261
-  s263 :: SWord8 = if s22 then s262 else s257
-  s264 :: SWord1 = choose [0:0] s263
-  s265 :: SBool = s19 /= s264
-  s266 :: SBool = s_2 == s265
-  s267 :: SWord8 = s251 >>> 1
-  s268 :: SWord8 = s24 | s267
-  s269 :: SWord8 = s26 & s267
-  s270 :: SWord8 = if s243 then s268 else s269
-  s271 :: SWord8 = s270 >>> 1
-  s272 :: SWord8 = s24 | s271
-  s273 :: SWord8 = s26 & s271
-  s274 :: SWord8 = if s265 then s272 else s273
-  s275 :: SWord1 = choose [0:0] s258
-  s276 :: SBool = s19 /= s275
-  s277 :: SWord8 = s263 >>> 1
-  s278 :: SWord8 = s24 | s277
-  s279 :: SWord8 = s26 & s277
-  s280 :: SWord8 = if s276 then s278 else s279
-  s281 :: SWord8 = if s29 then s240 else s188
-  s282 :: SWord8 = if s170 then s257 else s281
-  s283 :: SWord8 = if s29 then s262 else s282
-  s284 :: SWord8 = if s170 then s280 else s283
-  s285 :: SWord8 = s270 + s284
-  s286 :: SBool = s285 < s284
-  s287 :: SBool = s285 < s270
-  s288 :: SBool = s286 | s287
-  s289 :: SWord8 = s285 >>> 1
-  s290 :: SWord8 = s24 | s289
-  s291 :: SWord8 = s26 & s289
-  s292 :: SWord8 = if s288 then s290 else s291
-  s293 :: SWord8 = if s266 then s274 else s292
-  s294 :: SWord8 = s251 + s282
-  s295 :: SWord1 = choose [0:0] s294
-  s296 :: SBool = s19 /= s295
-  s297 :: SWord8 = if s296 then s260 else s261
-  s298 :: SWord8 = if s22 then s297 else s257
-  s299 :: SWord1 = choose [0:0] s298
-  s300 :: SBool = s19 /= s299
-  s301 :: SBool = s_2 == s300
-  s302 :: SBool = s294 < s282
-  s303 :: SBool = s294 < s251
-  s304 :: SBool = s302 | s303
-  s305 :: SWord8 = s294 >>> 1
-  s306 :: SWord8 = s24 | s305
-  s307 :: SWord8 = s26 & s305
-  s308 :: SWord8 = if s304 then s306 else s307
-  s309 :: SWord8 = s308 >>> 1
-  s310 :: SWord8 = s24 | s309
-  s311 :: SWord8 = s26 & s309
-  s312 :: SWord8 = if s300 then s310 else s311
-  s313 :: SWord8 = s298 >>> 1
-  s314 :: SWord8 = s24 | s313
-  s315 :: SWord8 = s26 & s313
-  s316 :: SWord8 = if s276 then s314 else s315
-  s317 :: SWord8 = if s29 then s297 else s282
-  s318 :: SWord8 = if s170 then s316 else s317
-  s319 :: SWord8 = s308 + s318
-  s320 :: SBool = s319 < s318
-  s321 :: SBool = s319 < s308
-  s322 :: SBool = s320 | s321
-  s323 :: SWord8 = s319 >>> 1
-  s324 :: SWord8 = s24 | s323
-  s325 :: SWord8 = s26 & s323
-  s326 :: SWord8 = if s322 then s324 else s325
-  s327 :: SWord8 = if s301 then s312 else s326
-  s328 :: SWord8 = if s244 then s293 else s327
-  s329 :: SWord8 = if s119 then s236 else s328
-  s330 :: SWord8 = s102 + s186
-  s331 :: SWord1 = choose [0:0] s330
-  s332 :: SBool = s19 /= s331
-  s333 :: SWord8 = if s332 then s113 else s114
-  s334 :: SWord8 = if s22 then s333 else s110
-  s335 :: SWord1 = choose [0:0] s334
-  s336 :: SBool = s19 /= s335
-  s337 :: SBool = s_2 == s336
-  s338 :: SBool = s330 < s186
-  s339 :: SBool = s330 < s102
-  s340 :: SBool = s338 | s339
-  s341 :: SWord8 = s330 >>> 1
-  s342 :: SWord8 = s24 | s341
-  s343 :: SWord8 = s26 & s341
-  s344 :: SWord8 = if s340 then s342 else s343
-  s345 :: SWord1 = choose [0:0] s344
-  s346 :: SBool = s19 /= s345
-  s347 :: SWord8 = s334 >>> 1
-  s348 :: SWord8 = s24 | s347
-  s349 :: SWord8 = s26 & s347
-  s350 :: SWord8 = if s127 then s348 else s349
-  s351 :: SWord8 = if s22 then s350 else s333
-  s352 :: SWord8 = s351 >>> 1
-  s353 :: SWord8 = s24 | s352
-  s354 :: SWord8 = s26 & s352
-  s355 :: SWord8 = if s346 then s353 else s354
-  s356 :: SWord8 = if s22 then s355 else s350
-  s357 :: SWord1 = choose [0:0] s356
-  s358 :: SBool = s19 /= s357
-  s359 :: SBool = s_2 == s358
-  s360 :: SWord8 = s344 >>> 1
-  s361 :: SWord8 = s24 | s360
-  s362 :: SWord8 = s26 & s360
-  s363 :: SWord8 = if s336 then s361 else s362
-  s364 :: SWord1 = choose [0:0] s363
-  s365 :: SBool = s19 /= s364
-  s366 :: SWord1 = choose [0:0] s351
-  s367 :: SBool = s19 /= s366
-  s368 :: SWord8 = s356 >>> 1
-  s369 :: SWord8 = s24 | s368
-  s370 :: SWord8 = s26 & s368
-  s371 :: SWord8 = if s367 then s369 else s370
-  s372 :: SWord8 = if s22 then s371 else s355
-  s373 :: SWord8 = s372 >>> 1
-  s374 :: SWord8 = s24 | s373
-  s375 :: SWord8 = s26 & s373
-  s376 :: SWord8 = if s365 then s374 else s375
-  s377 :: SWord8 = if s22 then s376 else s371
-  s378 :: SWord1 = choose [0:0] s377
-  s379 :: SBool = s19 /= s378
-  s380 :: SBool = s_2 == s379
-  s381 :: SWord8 = s363 >>> 1
-  s382 :: SWord8 = s24 | s381
-  s383 :: SWord8 = s26 & s381
-  s384 :: SWord8 = if s358 then s382 else s383
-  s385 :: SWord8 = s384 >>> 1
-  s386 :: SWord8 = s24 | s385
-  s387 :: SWord8 = s26 & s385
-  s388 :: SWord8 = if s379 then s386 else s387
-  s389 :: SWord1 = choose [0:0] s372
-  s390 :: SBool = s19 /= s389
-  s391 :: SWord8 = s377 >>> 1
-  s392 :: SWord8 = s24 | s391
-  s393 :: SWord8 = s26 & s391
-  s394 :: SWord8 = if s390 then s392 else s393
-  s395 :: SWord8 = if s29 then s333 else s186
-  s396 :: SWord8 = if s170 then s350 else s395
-  s397 :: SWord8 = if s29 then s355 else s396
-  s398 :: SWord8 = if s170 then s371 else s397
-  s399 :: SWord8 = if s29 then s376 else s398
-  s400 :: SWord8 = if s170 then s394 else s399
-  s401 :: SWord8 = s384 + s400
-  s402 :: SBool = s401 < s400
-  s403 :: SBool = s401 < s384
-  s404 :: SBool = s402 | s403
-  s405 :: SWord8 = s401 >>> 1
-  s406 :: SWord8 = s24 | s405
-  s407 :: SWord8 = s26 & s405
-  s408 :: SWord8 = if s404 then s406 else s407
-  s409 :: SWord8 = if s380 then s388 else s408
-  s410 :: SWord8 = s363 + s398
-  s411 :: SWord1 = choose [0:0] s410
-  s412 :: SBool = s19 /= s411
-  s413 :: SWord8 = if s412 then s374 else s375
-  s414 :: SWord8 = if s22 then s413 else s371
-  s415 :: SWord1 = choose [0:0] s414
-  s416 :: SBool = s19 /= s415
-  s417 :: SBool = s_2 == s416
-  s418 :: SBool = s410 < s398
-  s419 :: SBool = s410 < s363
-  s420 :: SBool = s418 | s419
-  s421 :: SWord8 = s410 >>> 1
-  s422 :: SWord8 = s24 | s421
-  s423 :: SWord8 = s26 & s421
-  s424 :: SWord8 = if s420 then s422 else s423
-  s425 :: SWord8 = s424 >>> 1
-  s426 :: SWord8 = s24 | s425
-  s427 :: SWord8 = s26 & s425
-  s428 :: SWord8 = if s416 then s426 else s427
-  s429 :: SWord8 = s414 >>> 1
-  s430 :: SWord8 = s24 | s429
-  s431 :: SWord8 = s26 & s429
-  s432 :: SWord8 = if s390 then s430 else s431
-  s433 :: SWord8 = if s29 then s413 else s398
-  s434 :: SWord8 = if s170 then s432 else s433
-  s435 :: SWord8 = s424 + s434
-  s436 :: SBool = s435 < s434
-  s437 :: SBool = s435 < s424
-  s438 :: SBool = s436 | s437
-  s439 :: SWord8 = s435 >>> 1
-  s440 :: SWord8 = s24 | s439
-  s441 :: SWord8 = s26 & s439
-  s442 :: SWord8 = if s438 then s440 else s441
-  s443 :: SWord8 = if s417 then s428 else s442
-  s444 :: SWord8 = if s359 then s409 else s443
-  s445 :: SWord8 = s344 + s396
-  s446 :: SWord1 = choose [0:0] s445
-  s447 :: SBool = s19 /= s446
-  s448 :: SWord8 = if s447 then s353 else s354
-  s449 :: SWord8 = if s22 then s448 else s350
-  s450 :: SWord1 = choose [0:0] s449
-  s451 :: SBool = s19 /= s450
-  s452 :: SBool = s_2 == s451
-  s453 :: SBool = s445 < s396
-  s454 :: SBool = s445 < s344
-  s455 :: SBool = s453 | s454
-  s456 :: SWord8 = s445 >>> 1
-  s457 :: SWord8 = s24 | s456
-  s458 :: SWord8 = s26 & s456
-  s459 :: SWord8 = if s455 then s457 else s458
-  s460 :: SWord1 = choose [0:0] s459
-  s461 :: SBool = s19 /= s460
-  s462 :: SWord8 = s449 >>> 1
-  s463 :: SWord8 = s24 | s462
-  s464 :: SWord8 = s26 & s462
-  s465 :: SWord8 = if s367 then s463 else s464
-  s466 :: SWord8 = if s22 then s465 else s448
-  s467 :: SWord8 = s466 >>> 1
-  s468 :: SWord8 = s24 | s467
-  s469 :: SWord8 = s26 & s467
-  s470 :: SWord8 = if s461 then s468 else s469
-  s471 :: SWord8 = if s22 then s470 else s465
-  s472 :: SWord1 = choose [0:0] s471
-  s473 :: SBool = s19 /= s472
-  s474 :: SBool = s_2 == s473
-  s475 :: SWord8 = s459 >>> 1
-  s476 :: SWord8 = s24 | s475
-  s477 :: SWord8 = s26 & s475
-  s478 :: SWord8 = if s451 then s476 else s477
-  s479 :: SWord8 = s478 >>> 1
-  s480 :: SWord8 = s24 | s479
-  s481 :: SWord8 = s26 & s479
-  s482 :: SWord8 = if s473 then s480 else s481
-  s483 :: SWord1 = choose [0:0] s466
-  s484 :: SBool = s19 /= s483
-  s485 :: SWord8 = s471 >>> 1
-  s486 :: SWord8 = s24 | s485
-  s487 :: SWord8 = s26 & s485
-  s488 :: SWord8 = if s484 then s486 else s487
-  s489 :: SWord8 = if s29 then s448 else s396
-  s490 :: SWord8 = if s170 then s465 else s489
-  s491 :: SWord8 = if s29 then s470 else s490
-  s492 :: SWord8 = if s170 then s488 else s491
-  s493 :: SWord8 = s478 + s492
-  s494 :: SBool = s493 < s492
-  s495 :: SBool = s493 < s478
-  s496 :: SBool = s494 | s495
-  s497 :: SWord8 = s493 >>> 1
-  s498 :: SWord8 = s24 | s497
-  s499 :: SWord8 = s26 & s497
-  s500 :: SWord8 = if s496 then s498 else s499
-  s501 :: SWord8 = if s474 then s482 else s500
-  s502 :: SWord8 = s459 + s490
-  s503 :: SWord1 = choose [0:0] s502
-  s504 :: SBool = s19 /= s503
-  s505 :: SWord8 = if s504 then s468 else s469
-  s506 :: SWord8 = if s22 then s505 else s465
-  s507 :: SWord1 = choose [0:0] s506
-  s508 :: SBool = s19 /= s507
-  s509 :: SBool = s_2 == s508
-  s510 :: SBool = s502 < s490
-  s511 :: SBool = s502 < s459
-  s512 :: SBool = s510 | s511
-  s513 :: SWord8 = s502 >>> 1
-  s514 :: SWord8 = s24 | s513
-  s515 :: SWord8 = s26 & s513
-  s516 :: SWord8 = if s512 then s514 else s515
-  s517 :: SWord8 = s516 >>> 1
-  s518 :: SWord8 = s24 | s517
-  s519 :: SWord8 = s26 & s517
-  s520 :: SWord8 = if s508 then s518 else s519
-  s521 :: SWord8 = s506 >>> 1
-  s522 :: SWord8 = s24 | s521
-  s523 :: SWord8 = s26 & s521
-  s524 :: SWord8 = if s484 then s522 else s523
-  s525 :: SWord8 = if s29 then s505 else s490
-  s526 :: SWord8 = if s170 then s524 else s525
-  s527 :: SWord8 = s516 + s526
-  s528 :: SBool = s527 < s526
-  s529 :: SBool = s527 < s516
-  s530 :: SBool = s528 | s529
-  s531 :: SWord8 = s527 >>> 1
-  s532 :: SWord8 = s24 | s531
-  s533 :: SWord8 = s26 & s531
-  s534 :: SWord8 = if s530 then s532 else s533
-  s535 :: SWord8 = if s509 then s520 else s534
-  s536 :: SWord8 = if s452 then s501 else s535
-  s537 :: SWord8 = if s337 then s444 else s536
-  s538 :: SWord8 = if s98 then s329 else s537
-  s539 :: SWord8 = s81 + s184
-  s540 :: SWord1 = choose [0:0] s539
-  s541 :: SBool = s19 /= s540
-  s542 :: SWord8 = if s541 then s92 else s93
-  s543 :: SWord8 = if s22 then s542 else s89
-  s544 :: SWord1 = choose [0:0] s543
-  s545 :: SBool = s19 /= s544
-  s546 :: SBool = s_2 == s545
-  s547 :: SBool = s539 < s184
-  s548 :: SBool = s539 < s81
-  s549 :: SBool = s547 | s548
-  s550 :: SWord8 = s539 >>> 1
-  s551 :: SWord8 = s24 | s550
-  s552 :: SWord8 = s26 & s550
-  s553 :: SWord8 = if s549 then s551 else s552
-  s554 :: SWord1 = choose [0:0] s553
-  s555 :: SBool = s19 /= s554
-  s556 :: SWord8 = s543 >>> 1
-  s557 :: SWord8 = s24 | s556
-  s558 :: SWord8 = s26 & s556
-  s559 :: SWord8 = if s106 then s557 else s558
-  s560 :: SWord8 = if s22 then s559 else s542
-  s561 :: SWord8 = s560 >>> 1
-  s562 :: SWord8 = s24 | s561
-  s563 :: SWord8 = s26 & s561
-  s564 :: SWord8 = if s555 then s562 else s563
-  s565 :: SWord8 = if s22 then s564 else s559
-  s566 :: SWord1 = choose [0:0] s565
-  s567 :: SBool = s19 /= s566
-  s568 :: SBool = s_2 == s567
-  s569 :: SWord8 = s553 >>> 1
-  s570 :: SWord8 = s24 | s569
-  s571 :: SWord8 = s26 & s569
-  s572 :: SWord8 = if s545 then s570 else s571
-  s573 :: SWord1 = choose [0:0] s572
-  s574 :: SBool = s19 /= s573
-  s575 :: SWord1 = choose [0:0] s560
-  s576 :: SBool = s19 /= s575
-  s577 :: SWord8 = s565 >>> 1
-  s578 :: SWord8 = s24 | s577
-  s579 :: SWord8 = s26 & s577
-  s580 :: SWord8 = if s576 then s578 else s579
-  s581 :: SWord8 = if s22 then s580 else s564
-  s582 :: SWord8 = s581 >>> 1
-  s583 :: SWord8 = s24 | s582
-  s584 :: SWord8 = s26 & s582
-  s585 :: SWord8 = if s574 then s583 else s584
-  s586 :: SWord8 = if s22 then s585 else s580
-  s587 :: SWord1 = choose [0:0] s586
-  s588 :: SBool = s19 /= s587
-  s589 :: SBool = s_2 == s588
-  s590 :: SWord8 = s572 >>> 1
-  s591 :: SWord8 = s24 | s590
-  s592 :: SWord8 = s26 & s590
-  s593 :: SWord8 = if s567 then s591 else s592
-  s594 :: SWord1 = choose [0:0] s593
-  s595 :: SBool = s19 /= s594
-  s596 :: SWord1 = choose [0:0] s581
-  s597 :: SBool = s19 /= s596
-  s598 :: SWord8 = s586 >>> 1
-  s599 :: SWord8 = s24 | s598
-  s600 :: SWord8 = s26 & s598
-  s601 :: SWord8 = if s597 then s599 else s600
-  s602 :: SWord8 = if s22 then s601 else s585
-  s603 :: SWord8 = s602 >>> 1
-  s604 :: SWord8 = s24 | s603
-  s605 :: SWord8 = s26 & s603
-  s606 :: SWord8 = if s595 then s604 else s605
-  s607 :: SWord8 = if s22 then s606 else s601
-  s608 :: SWord1 = choose [0:0] s607
-  s609 :: SBool = s19 /= s608
-  s610 :: SBool = s_2 == s609
-  s611 :: SWord8 = s593 >>> 1
-  s612 :: SWord8 = s24 | s611
-  s613 :: SWord8 = s26 & s611
-  s614 :: SWord8 = if s588 then s612 else s613
-  s615 :: SWord8 = s614 >>> 1
-  s616 :: SWord8 = s24 | s615
-  s617 :: SWord8 = s26 & s615
-  s618 :: SWord8 = if s609 then s616 else s617
-  s619 :: SWord1 = choose [0:0] s602
-  s620 :: SBool = s19 /= s619
-  s621 :: SWord8 = s607 >>> 1
-  s622 :: SWord8 = s24 | s621
-  s623 :: SWord8 = s26 & s621
-  s624 :: SWord8 = if s620 then s622 else s623
-  s625 :: SWord8 = if s29 then s542 else s184
-  s626 :: SWord8 = if s170 then s559 else s625
-  s627 :: SWord8 = if s29 then s564 else s626
-  s628 :: SWord8 = if s170 then s580 else s627
-  s629 :: SWord8 = if s29 then s585 else s628
-  s630 :: SWord8 = if s170 then s601 else s629
-  s631 :: SWord8 = if s29 then s606 else s630
-  s632 :: SWord8 = if s170 then s624 else s631
-  s633 :: SWord8 = s614 + s632
-  s634 :: SBool = s633 < s632
-  s635 :: SBool = s633 < s614
-  s636 :: SBool = s634 | s635
-  s637 :: SWord8 = s633 >>> 1
-  s638 :: SWord8 = s24 | s637
-  s639 :: SWord8 = s26 & s637
-  s640 :: SWord8 = if s636 then s638 else s639
-  s641 :: SWord8 = if s610 then s618 else s640
-  s642 :: SWord8 = s593 + s630
-  s643 :: SWord1 = choose [0:0] s642
-  s644 :: SBool = s19 /= s643
-  s645 :: SWord8 = if s644 then s604 else s605
-  s646 :: SWord8 = if s22 then s645 else s601
-  s647 :: SWord1 = choose [0:0] s646
-  s648 :: SBool = s19 /= s647
-  s649 :: SBool = s_2 == s648
-  s650 :: SBool = s642 < s630
-  s651 :: SBool = s642 < s593
-  s652 :: SBool = s650 | s651
-  s653 :: SWord8 = s642 >>> 1
-  s654 :: SWord8 = s24 | s653
-  s655 :: SWord8 = s26 & s653
-  s656 :: SWord8 = if s652 then s654 else s655
-  s657 :: SWord8 = s656 >>> 1
-  s658 :: SWord8 = s24 | s657
-  s659 :: SWord8 = s26 & s657
-  s660 :: SWord8 = if s648 then s658 else s659
-  s661 :: SWord8 = s646 >>> 1
-  s662 :: SWord8 = s24 | s661
-  s663 :: SWord8 = s26 & s661
-  s664 :: SWord8 = if s620 then s662 else s663
-  s665 :: SWord8 = if s29 then s645 else s630
-  s666 :: SWord8 = if s170 then s664 else s665
-  s667 :: SWord8 = s656 + s666
-  s668 :: SBool = s667 < s666
-  s669 :: SBool = s667 < s656
-  s670 :: SBool = s668 | s669
-  s671 :: SWord8 = s667 >>> 1
-  s672 :: SWord8 = s24 | s671
-  s673 :: SWord8 = s26 & s671
-  s674 :: SWord8 = if s670 then s672 else s673
-  s675 :: SWord8 = if s649 then s660 else s674
-  s676 :: SWord8 = if s589 then s641 else s675
-  s677 :: SWord8 = s572 + s628
-  s678 :: SWord1 = choose [0:0] s677
-  s679 :: SBool = s19 /= s678
-  s680 :: SWord8 = if s679 then s583 else s584
-  s681 :: SWord8 = if s22 then s680 else s580
-  s682 :: SWord1 = choose [0:0] s681
-  s683 :: SBool = s19 /= s682
-  s684 :: SBool = s_2 == s683
-  s685 :: SBool = s677 < s628
-  s686 :: SBool = s677 < s572
-  s687 :: SBool = s685 | s686
-  s688 :: SWord8 = s677 >>> 1
-  s689 :: SWord8 = s24 | s688
-  s690 :: SWord8 = s26 & s688
-  s691 :: SWord8 = if s687 then s689 else s690
-  s692 :: SWord1 = choose [0:0] s691
-  s693 :: SBool = s19 /= s692
-  s694 :: SWord8 = s681 >>> 1
-  s695 :: SWord8 = s24 | s694
-  s696 :: SWord8 = s26 & s694
-  s697 :: SWord8 = if s597 then s695 else s696
-  s698 :: SWord8 = if s22 then s697 else s680
-  s699 :: SWord8 = s698 >>> 1
-  s700 :: SWord8 = s24 | s699
-  s701 :: SWord8 = s26 & s699
-  s702 :: SWord8 = if s693 then s700 else s701
-  s703 :: SWord8 = if s22 then s702 else s697
-  s704 :: SWord1 = choose [0:0] s703
-  s705 :: SBool = s19 /= s704
-  s706 :: SBool = s_2 == s705
-  s707 :: SWord8 = s691 >>> 1
-  s708 :: SWord8 = s24 | s707
-  s709 :: SWord8 = s26 & s707
-  s710 :: SWord8 = if s683 then s708 else s709
-  s711 :: SWord8 = s710 >>> 1
-  s712 :: SWord8 = s24 | s711
-  s713 :: SWord8 = s26 & s711
-  s714 :: SWord8 = if s705 then s712 else s713
-  s715 :: SWord1 = choose [0:0] s698
-  s716 :: SBool = s19 /= s715
-  s717 :: SWord8 = s703 >>> 1
-  s718 :: SWord8 = s24 | s717
-  s719 :: SWord8 = s26 & s717
-  s720 :: SWord8 = if s716 then s718 else s719
-  s721 :: SWord8 = if s29 then s680 else s628
-  s722 :: SWord8 = if s170 then s697 else s721
-  s723 :: SWord8 = if s29 then s702 else s722
-  s724 :: SWord8 = if s170 then s720 else s723
-  s725 :: SWord8 = s710 + s724
-  s726 :: SBool = s725 < s724
-  s727 :: SBool = s725 < s710
-  s728 :: SBool = s726 | s727
-  s729 :: SWord8 = s725 >>> 1
-  s730 :: SWord8 = s24 | s729
-  s731 :: SWord8 = s26 & s729
-  s732 :: SWord8 = if s728 then s730 else s731
-  s733 :: SWord8 = if s706 then s714 else s732
-  s734 :: SWord8 = s691 + s722
-  s735 :: SWord1 = choose [0:0] s734
-  s736 :: SBool = s19 /= s735
-  s737 :: SWord8 = if s736 then s700 else s701
-  s738 :: SWord8 = if s22 then s737 else s697
-  s739 :: SWord1 = choose [0:0] s738
-  s740 :: SBool = s19 /= s739
-  s741 :: SBool = s_2 == s740
-  s742 :: SBool = s734 < s722
-  s743 :: SBool = s734 < s691
-  s744 :: SBool = s742 | s743
-  s745 :: SWord8 = s734 >>> 1
-  s746 :: SWord8 = s24 | s745
-  s747 :: SWord8 = s26 & s745
-  s748 :: SWord8 = if s744 then s746 else s747
-  s749 :: SWord8 = s748 >>> 1
-  s750 :: SWord8 = s24 | s749
-  s751 :: SWord8 = s26 & s749
-  s752 :: SWord8 = if s740 then s750 else s751
-  s753 :: SWord8 = s738 >>> 1
-  s754 :: SWord8 = s24 | s753
-  s755 :: SWord8 = s26 & s753
-  s756 :: SWord8 = if s716 then s754 else s755
-  s757 :: SWord8 = if s29 then s737 else s722
-  s758 :: SWord8 = if s170 then s756 else s757
-  s759 :: SWord8 = s748 + s758
-  s760 :: SBool = s759 < s758
-  s761 :: SBool = s759 < s748
-  s762 :: SBool = s760 | s761
-  s763 :: SWord8 = s759 >>> 1
-  s764 :: SWord8 = s24 | s763
-  s765 :: SWord8 = s26 & s763
-  s766 :: SWord8 = if s762 then s764 else s765
-  s767 :: SWord8 = if s741 then s752 else s766
-  s768 :: SWord8 = if s684 then s733 else s767
-  s769 :: SWord8 = if s568 then s676 else s768
-  s770 :: SWord8 = s553 + s626
-  s771 :: SWord1 = choose [0:0] s770
-  s772 :: SBool = s19 /= s771
-  s773 :: SWord8 = if s772 then s562 else s563
-  s774 :: SWord8 = if s22 then s773 else s559
-  s775 :: SWord1 = choose [0:0] s774
-  s776 :: SBool = s19 /= s775
-  s777 :: SBool = s_2 == s776
-  s778 :: SBool = s770 < s626
-  s779 :: SBool = s770 < s553
-  s780 :: SBool = s778 | s779
-  s781 :: SWord8 = s770 >>> 1
-  s782 :: SWord8 = s24 | s781
-  s783 :: SWord8 = s26 & s781
-  s784 :: SWord8 = if s780 then s782 else s783
-  s785 :: SWord1 = choose [0:0] s784
-  s786 :: SBool = s19 /= s785
-  s787 :: SWord8 = s774 >>> 1
-  s788 :: SWord8 = s24 | s787
-  s789 :: SWord8 = s26 & s787
-  s790 :: SWord8 = if s576 then s788 else s789
-  s791 :: SWord8 = if s22 then s790 else s773
-  s792 :: SWord8 = s791 >>> 1
-  s793 :: SWord8 = s24 | s792
-  s794 :: SWord8 = s26 & s792
-  s795 :: SWord8 = if s786 then s793 else s794
-  s796 :: SWord8 = if s22 then s795 else s790
-  s797 :: SWord1 = choose [0:0] s796
-  s798 :: SBool = s19 /= s797
-  s799 :: SBool = s_2 == s798
-  s800 :: SWord8 = s784 >>> 1
-  s801 :: SWord8 = s24 | s800
-  s802 :: SWord8 = s26 & s800
-  s803 :: SWord8 = if s776 then s801 else s802
-  s804 :: SWord1 = choose [0:0] s803
-  s805 :: SBool = s19 /= s804
-  s806 :: SWord1 = choose [0:0] s791
-  s807 :: SBool = s19 /= s806
-  s808 :: SWord8 = s796 >>> 1
-  s809 :: SWord8 = s24 | s808
-  s810 :: SWord8 = s26 & s808
-  s811 :: SWord8 = if s807 then s809 else s810
-  s812 :: SWord8 = if s22 then s811 else s795
-  s813 :: SWord8 = s812 >>> 1
-  s814 :: SWord8 = s24 | s813
-  s815 :: SWord8 = s26 & s813
-  s816 :: SWord8 = if s805 then s814 else s815
-  s817 :: SWord8 = if s22 then s816 else s811
-  s818 :: SWord1 = choose [0:0] s817
-  s819 :: SBool = s19 /= s818
-  s820 :: SBool = s_2 == s819
-  s821 :: SWord8 = s803 >>> 1
-  s822 :: SWord8 = s24 | s821
-  s823 :: SWord8 = s26 & s821
-  s824 :: SWord8 = if s798 then s822 else s823
-  s825 :: SWord8 = s824 >>> 1
-  s826 :: SWord8 = s24 | s825
-  s827 :: SWord8 = s26 & s825
-  s828 :: SWord8 = if s819 then s826 else s827
-  s829 :: SWord1 = choose [0:0] s812
-  s830 :: SBool = s19 /= s829
-  s831 :: SWord8 = s817 >>> 1
-  s832 :: SWord8 = s24 | s831
-  s833 :: SWord8 = s26 & s831
-  s834 :: SWord8 = if s830 then s832 else s833
-  s835 :: SWord8 = if s29 then s773 else s626
-  s836 :: SWord8 = if s170 then s790 else s835
-  s837 :: SWord8 = if s29 then s795 else s836
-  s838 :: SWord8 = if s170 then s811 else s837
-  s839 :: SWord8 = if s29 then s816 else s838
-  s840 :: SWord8 = if s170 then s834 else s839
-  s841 :: SWord8 = s824 + s840
-  s842 :: SBool = s841 < s840
-  s843 :: SBool = s841 < s824
-  s844 :: SBool = s842 | s843
-  s845 :: SWord8 = s841 >>> 1
-  s846 :: SWord8 = s24 | s845
-  s847 :: SWord8 = s26 & s845
-  s848 :: SWord8 = if s844 then s846 else s847
-  s849 :: SWord8 = if s820 then s828 else s848
-  s850 :: SWord8 = s803 + s838
-  s851 :: SWord1 = choose [0:0] s850
-  s852 :: SBool = s19 /= s851
-  s853 :: SWord8 = if s852 then s814 else s815
-  s854 :: SWord8 = if s22 then s853 else s811
-  s855 :: SWord1 = choose [0:0] s854
-  s856 :: SBool = s19 /= s855
-  s857 :: SBool = s_2 == s856
-  s858 :: SBool = s850 < s838
-  s859 :: SBool = s850 < s803
-  s860 :: SBool = s858 | s859
-  s861 :: SWord8 = s850 >>> 1
-  s862 :: SWord8 = s24 | s861
-  s863 :: SWord8 = s26 & s861
-  s864 :: SWord8 = if s860 then s862 else s863
-  s865 :: SWord8 = s864 >>> 1
-  s866 :: SWord8 = s24 | s865
-  s867 :: SWord8 = s26 & s865
-  s868 :: SWord8 = if s856 then s866 else s867
-  s869 :: SWord8 = s854 >>> 1
-  s870 :: SWord8 = s24 | s869
-  s871 :: SWord8 = s26 & s869
-  s872 :: SWord8 = if s830 then s870 else s871
-  s873 :: SWord8 = if s29 then s853 else s838
-  s874 :: SWord8 = if s170 then s872 else s873
-  s875 :: SWord8 = s864 + s874
-  s876 :: SBool = s875 < s874
-  s877 :: SBool = s875 < s864
-  s878 :: SBool = s876 | s877
-  s879 :: SWord8 = s875 >>> 1
-  s880 :: SWord8 = s24 | s879
-  s881 :: SWord8 = s26 & s879
-  s882 :: SWord8 = if s878 then s880 else s881
-  s883 :: SWord8 = if s857 then s868 else s882
-  s884 :: SWord8 = if s799 then s849 else s883
-  s885 :: SWord8 = s784 + s836
-  s886 :: SWord1 = choose [0:0] s885
-  s887 :: SBool = s19 /= s886
-  s888 :: SWord8 = if s887 then s793 else s794
-  s889 :: SWord8 = if s22 then s888 else s790
-  s890 :: SWord1 = choose [0:0] s889
-  s891 :: SBool = s19 /= s890
-  s892 :: SBool = s_2 == s891
-  s893 :: SBool = s885 < s836
-  s894 :: SBool = s885 < s784
-  s895 :: SBool = s893 | s894
-  s896 :: SWord8 = s885 >>> 1
-  s897 :: SWord8 = s24 | s896
-  s898 :: SWord8 = s26 & s896
-  s899 :: SWord8 = if s895 then s897 else s898
-  s900 :: SWord1 = choose [0:0] s899
-  s901 :: SBool = s19 /= s900
-  s902 :: SWord8 = s889 >>> 1
-  s903 :: SWord8 = s24 | s902
-  s904 :: SWord8 = s26 & s902
-  s905 :: SWord8 = if s807 then s903 else s904
-  s906 :: SWord8 = if s22 then s905 else s888
-  s907 :: SWord8 = s906 >>> 1
-  s908 :: SWord8 = s24 | s907
-  s909 :: SWord8 = s26 & s907
-  s910 :: SWord8 = if s901 then s908 else s909
-  s911 :: SWord8 = if s22 then s910 else s905
-  s912 :: SWord1 = choose [0:0] s911
-  s913 :: SBool = s19 /= s912
-  s914 :: SBool = s_2 == s913
-  s915 :: SWord8 = s899 >>> 1
-  s916 :: SWord8 = s24 | s915
-  s917 :: SWord8 = s26 & s915
-  s918 :: SWord8 = if s891 then s916 else s917
-  s919 :: SWord8 = s918 >>> 1
-  s920 :: SWord8 = s24 | s919
-  s921 :: SWord8 = s26 & s919
-  s922 :: SWord8 = if s913 then s920 else s921
-  s923 :: SWord1 = choose [0:0] s906
-  s924 :: SBool = s19 /= s923
-  s925 :: SWord8 = s911 >>> 1
-  s926 :: SWord8 = s24 | s925
-  s927 :: SWord8 = s26 & s925
-  s928 :: SWord8 = if s924 then s926 else s927
-  s929 :: SWord8 = if s29 then s888 else s836
-  s930 :: SWord8 = if s170 then s905 else s929
-  s931 :: SWord8 = if s29 then s910 else s930
-  s932 :: SWord8 = if s170 then s928 else s931
-  s933 :: SWord8 = s918 + s932
-  s934 :: SBool = s933 < s932
-  s935 :: SBool = s933 < s918
-  s936 :: SBool = s934 | s935
-  s937 :: SWord8 = s933 >>> 1
-  s938 :: SWord8 = s24 | s937
-  s939 :: SWord8 = s26 & s937
-  s940 :: SWord8 = if s936 then s938 else s939
-  s941 :: SWord8 = if s914 then s922 else s940
-  s942 :: SWord8 = s899 + s930
-  s943 :: SWord1 = choose [0:0] s942
-  s944 :: SBool = s19 /= s943
-  s945 :: SWord8 = if s944 then s908 else s909
-  s946 :: SWord8 = if s22 then s945 else s905
-  s947 :: SWord1 = choose [0:0] s946
-  s948 :: SBool = s19 /= s947
-  s949 :: SBool = s_2 == s948
-  s950 :: SBool = s942 < s930
-  s951 :: SBool = s942 < s899
-  s952 :: SBool = s950 | s951
-  s953 :: SWord8 = s942 >>> 1
-  s954 :: SWord8 = s24 | s953
-  s955 :: SWord8 = s26 & s953
-  s956 :: SWord8 = if s952 then s954 else s955
-  s957 :: SWord8 = s956 >>> 1
-  s958 :: SWord8 = s24 | s957
-  s959 :: SWord8 = s26 & s957
-  s960 :: SWord8 = if s948 then s958 else s959
-  s961 :: SWord8 = s946 >>> 1
-  s962 :: SWord8 = s24 | s961
-  s963 :: SWord8 = s26 & s961
-  s964 :: SWord8 = if s924 then s962 else s963
-  s965 :: SWord8 = if s29 then s945 else s930
-  s966 :: SWord8 = if s170 then s964 else s965
-  s967 :: SWord8 = s956 + s966
-  s968 :: SBool = s967 < s966
-  s969 :: SBool = s967 < s956
-  s970 :: SBool = s968 | s969
-  s971 :: SWord8 = s967 >>> 1
-  s972 :: SWord8 = s24 | s971
-  s973 :: SWord8 = s26 & s971
-  s974 :: SWord8 = if s970 then s972 else s973
-  s975 :: SWord8 = if s949 then s960 else s974
-  s976 :: SWord8 = if s892 then s941 else s975
-  s977 :: SWord8 = if s777 then s884 else s976
-  s978 :: SWord8 = if s546 then s769 else s977
-  s979 :: SWord8 = if s77 then s538 else s978
-  s980 :: SWord8 = s60 + s182
-  s981 :: SWord1 = choose [0:0] s980
-  s982 :: SBool = s19 /= s981
-  s983 :: SWord8 = if s982 then s71 else s72
-  s984 :: SWord8 = if s22 then s983 else s68
-  s985 :: SWord1 = choose [0:0] s984
-  s986 :: SBool = s19 /= s985
-  s987 :: SBool = s_2 == s986
-  s988 :: SBool = s980 < s182
-  s989 :: SBool = s980 < s60
-  s990 :: SBool = s988 | s989
-  s991 :: SWord8 = s980 >>> 1
-  s992 :: SWord8 = s24 | s991
-  s993 :: SWord8 = s26 & s991
-  s994 :: SWord8 = if s990 then s992 else s993
-  s995 :: SWord1 = choose [0:0] s994
-  s996 :: SBool = s19 /= s995
-  s997 :: SWord8 = s984 >>> 1
-  s998 :: SWord8 = s24 | s997
-  s999 :: SWord8 = s26 & s997
-  s1000 :: SWord8 = if s85 then s998 else s999
-  s1001 :: SWord8 = if s22 then s1000 else s983
-  s1002 :: SWord8 = s1001 >>> 1
-  s1003 :: SWord8 = s24 | s1002
-  s1004 :: SWord8 = s26 & s1002
-  s1005 :: SWord8 = if s996 then s1003 else s1004
-  s1006 :: SWord8 = if s22 then s1005 else s1000
-  s1007 :: SWord1 = choose [0:0] s1006
-  s1008 :: SBool = s19 /= s1007
-  s1009 :: SBool = s_2 == s1008
-  s1010 :: SWord8 = s994 >>> 1
-  s1011 :: SWord8 = s24 | s1010
-  s1012 :: SWord8 = s26 & s1010
-  s1013 :: SWord8 = if s986 then s1011 else s1012
-  s1014 :: SWord1 = choose [0:0] s1013
-  s1015 :: SBool = s19 /= s1014
-  s1016 :: SWord1 = choose [0:0] s1001
-  s1017 :: SBool = s19 /= s1016
-  s1018 :: SWord8 = s1006 >>> 1
-  s1019 :: SWord8 = s24 | s1018
-  s1020 :: SWord8 = s26 & s1018
-  s1021 :: SWord8 = if s1017 then s1019 else s1020
-  s1022 :: SWord8 = if s22 then s1021 else s1005
-  s1023 :: SWord8 = s1022 >>> 1
-  s1024 :: SWord8 = s24 | s1023
-  s1025 :: SWord8 = s26 & s1023
-  s1026 :: SWord8 = if s1015 then s1024 else s1025
-  s1027 :: SWord8 = if s22 then s1026 else s1021
-  s1028 :: SWord1 = choose [0:0] s1027
-  s1029 :: SBool = s19 /= s1028
-  s1030 :: SBool = s_2 == s1029
-  s1031 :: SWord8 = s1013 >>> 1
-  s1032 :: SWord8 = s24 | s1031
-  s1033 :: SWord8 = s26 & s1031
-  s1034 :: SWord8 = if s1008 then s1032 else s1033
-  s1035 :: SWord1 = choose [0:0] s1034
-  s1036 :: SBool = s19 /= s1035
-  s1037 :: SWord1 = choose [0:0] s1022
-  s1038 :: SBool = s19 /= s1037
-  s1039 :: SWord8 = s1027 >>> 1
-  s1040 :: SWord8 = s24 | s1039
-  s1041 :: SWord8 = s26 & s1039
-  s1042 :: SWord8 = if s1038 then s1040 else s1041
-  s1043 :: SWord8 = if s22 then s1042 else s1026
-  s1044 :: SWord8 = s1043 >>> 1
-  s1045 :: SWord8 = s24 | s1044
-  s1046 :: SWord8 = s26 & s1044
-  s1047 :: SWord8 = if s1036 then s1045 else s1046
-  s1048 :: SWord8 = if s22 then s1047 else s1042
-  s1049 :: SWord1 = choose [0:0] s1048
-  s1050 :: SBool = s19 /= s1049
-  s1051 :: SBool = s_2 == s1050
-  s1052 :: SWord8 = s1034 >>> 1
-  s1053 :: SWord8 = s24 | s1052
-  s1054 :: SWord8 = s26 & s1052
-  s1055 :: SWord8 = if s1029 then s1053 else s1054
-  s1056 :: SWord1 = choose [0:0] s1055
-  s1057 :: SBool = s19 /= s1056
-  s1058 :: SWord1 = choose [0:0] s1043
-  s1059 :: SBool = s19 /= s1058
-  s1060 :: SWord8 = s1048 >>> 1
-  s1061 :: SWord8 = s24 | s1060
-  s1062 :: SWord8 = s26 & s1060
-  s1063 :: SWord8 = if s1059 then s1061 else s1062
-  s1064 :: SWord8 = if s22 then s1063 else s1047
-  s1065 :: SWord8 = s1064 >>> 1
-  s1066 :: SWord8 = s24 | s1065
-  s1067 :: SWord8 = s26 & s1065
-  s1068 :: SWord8 = if s1057 then s1066 else s1067
-  s1069 :: SWord8 = if s22 then s1068 else s1063
-  s1070 :: SWord1 = choose [0:0] s1069
-  s1071 :: SBool = s19 /= s1070
-  s1072 :: SBool = s_2 == s1071
-  s1073 :: SWord8 = s1055 >>> 1
-  s1074 :: SWord8 = s24 | s1073
-  s1075 :: SWord8 = s26 & s1073
-  s1076 :: SWord8 = if s1050 then s1074 else s1075
-  s1077 :: SWord8 = s1076 >>> 1
-  s1078 :: SWord8 = s24 | s1077
-  s1079 :: SWord8 = s26 & s1077
-  s1080 :: SWord8 = if s1071 then s1078 else s1079
-  s1081 :: SWord1 = choose [0:0] s1064
-  s1082 :: SBool = s19 /= s1081
-  s1083 :: SWord8 = s1069 >>> 1
-  s1084 :: SWord8 = s24 | s1083
-  s1085 :: SWord8 = s26 & s1083
-  s1086 :: SWord8 = if s1082 then s1084 else s1085
-  s1087 :: SWord8 = if s29 then s983 else s182
-  s1088 :: SWord8 = if s170 then s1000 else s1087
-  s1089 :: SWord8 = if s29 then s1005 else s1088
-  s1090 :: SWord8 = if s170 then s1021 else s1089
-  s1091 :: SWord8 = if s29 then s1026 else s1090
-  s1092 :: SWord8 = if s170 then s1042 else s1091
-  s1093 :: SWord8 = if s29 then s1047 else s1092
-  s1094 :: SWord8 = if s170 then s1063 else s1093
-  s1095 :: SWord8 = if s29 then s1068 else s1094
-  s1096 :: SWord8 = if s170 then s1086 else s1095
-  s1097 :: SWord8 = s1076 + s1096
-  s1098 :: SBool = s1097 < s1096
-  s1099 :: SBool = s1097 < s1076
-  s1100 :: SBool = s1098 | s1099
-  s1101 :: SWord8 = s1097 >>> 1
-  s1102 :: SWord8 = s24 | s1101
-  s1103 :: SWord8 = s26 & s1101
-  s1104 :: SWord8 = if s1100 then s1102 else s1103
-  s1105 :: SWord8 = if s1072 then s1080 else s1104
-  s1106 :: SWord8 = s1055 + s1094
-  s1107 :: SWord1 = choose [0:0] s1106
-  s1108 :: SBool = s19 /= s1107
-  s1109 :: SWord8 = if s1108 then s1066 else s1067
-  s1110 :: SWord8 = if s22 then s1109 else s1063
-  s1111 :: SWord1 = choose [0:0] s1110
-  s1112 :: SBool = s19 /= s1111
-  s1113 :: SBool = s_2 == s1112
-  s1114 :: SBool = s1106 < s1094
-  s1115 :: SBool = s1106 < s1055
-  s1116 :: SBool = s1114 | s1115
-  s1117 :: SWord8 = s1106 >>> 1
-  s1118 :: SWord8 = s24 | s1117
-  s1119 :: SWord8 = s26 & s1117
-  s1120 :: SWord8 = if s1116 then s1118 else s1119
-  s1121 :: SWord8 = s1120 >>> 1
-  s1122 :: SWord8 = s24 | s1121
-  s1123 :: SWord8 = s26 & s1121
-  s1124 :: SWord8 = if s1112 then s1122 else s1123
-  s1125 :: SWord8 = s1110 >>> 1
-  s1126 :: SWord8 = s24 | s1125
-  s1127 :: SWord8 = s26 & s1125
-  s1128 :: SWord8 = if s1082 then s1126 else s1127
-  s1129 :: SWord8 = if s29 then s1109 else s1094
-  s1130 :: SWord8 = if s170 then s1128 else s1129
-  s1131 :: SWord8 = s1120 + s1130
-  s1132 :: SBool = s1131 < s1130
-  s1133 :: SBool = s1131 < s1120
-  s1134 :: SBool = s1132 | s1133
-  s1135 :: SWord8 = s1131 >>> 1
-  s1136 :: SWord8 = s24 | s1135
-  s1137 :: SWord8 = s26 & s1135
-  s1138 :: SWord8 = if s1134 then s1136 else s1137
-  s1139 :: SWord8 = if s1113 then s1124 else s1138
-  s1140 :: SWord8 = if s1051 then s1105 else s1139
-  s1141 :: SWord8 = s1034 + s1092
-  s1142 :: SWord1 = choose [0:0] s1141
-  s1143 :: SBool = s19 /= s1142
-  s1144 :: SWord8 = if s1143 then s1045 else s1046
-  s1145 :: SWord8 = if s22 then s1144 else s1042
-  s1146 :: SWord1 = choose [0:0] s1145
-  s1147 :: SBool = s19 /= s1146
-  s1148 :: SBool = s_2 == s1147
-  s1149 :: SBool = s1141 < s1092
-  s1150 :: SBool = s1141 < s1034
-  s1151 :: SBool = s1149 | s1150
-  s1152 :: SWord8 = s1141 >>> 1
-  s1153 :: SWord8 = s24 | s1152
-  s1154 :: SWord8 = s26 & s1152
-  s1155 :: SWord8 = if s1151 then s1153 else s1154
-  s1156 :: SWord1 = choose [0:0] s1155
-  s1157 :: SBool = s19 /= s1156
-  s1158 :: SWord8 = s1145 >>> 1
-  s1159 :: SWord8 = s24 | s1158
-  s1160 :: SWord8 = s26 & s1158
-  s1161 :: SWord8 = if s1059 then s1159 else s1160
-  s1162 :: SWord8 = if s22 then s1161 else s1144
-  s1163 :: SWord8 = s1162 >>> 1
-  s1164 :: SWord8 = s24 | s1163
-  s1165 :: SWord8 = s26 & s1163
-  s1166 :: SWord8 = if s1157 then s1164 else s1165
-  s1167 :: SWord8 = if s22 then s1166 else s1161
-  s1168 :: SWord1 = choose [0:0] s1167
-  s1169 :: SBool = s19 /= s1168
-  s1170 :: SBool = s_2 == s1169
-  s1171 :: SWord8 = s1155 >>> 1
-  s1172 :: SWord8 = s24 | s1171
-  s1173 :: SWord8 = s26 & s1171
-  s1174 :: SWord8 = if s1147 then s1172 else s1173
-  s1175 :: SWord8 = s1174 >>> 1
-  s1176 :: SWord8 = s24 | s1175
-  s1177 :: SWord8 = s26 & s1175
-  s1178 :: SWord8 = if s1169 then s1176 else s1177
-  s1179 :: SWord1 = choose [0:0] s1162
-  s1180 :: SBool = s19 /= s1179
-  s1181 :: SWord8 = s1167 >>> 1
-  s1182 :: SWord8 = s24 | s1181
-  s1183 :: SWord8 = s26 & s1181
-  s1184 :: SWord8 = if s1180 then s1182 else s1183
-  s1185 :: SWord8 = if s29 then s1144 else s1092
-  s1186 :: SWord8 = if s170 then s1161 else s1185
-  s1187 :: SWord8 = if s29 then s1166 else s1186
-  s1188 :: SWord8 = if s170 then s1184 else s1187
-  s1189 :: SWord8 = s1174 + s1188
-  s1190 :: SBool = s1189 < s1188
-  s1191 :: SBool = s1189 < s1174
-  s1192 :: SBool = s1190 | s1191
-  s1193 :: SWord8 = s1189 >>> 1
-  s1194 :: SWord8 = s24 | s1193
-  s1195 :: SWord8 = s26 & s1193
-  s1196 :: SWord8 = if s1192 then s1194 else s1195
-  s1197 :: SWord8 = if s1170 then s1178 else s1196
-  s1198 :: SWord8 = s1155 + s1186
-  s1199 :: SWord1 = choose [0:0] s1198
-  s1200 :: SBool = s19 /= s1199
-  s1201 :: SWord8 = if s1200 then s1164 else s1165
-  s1202 :: SWord8 = if s22 then s1201 else s1161
-  s1203 :: SWord1 = choose [0:0] s1202
-  s1204 :: SBool = s19 /= s1203
-  s1205 :: SBool = s_2 == s1204
-  s1206 :: SBool = s1198 < s1186
-  s1207 :: SBool = s1198 < s1155
-  s1208 :: SBool = s1206 | s1207
-  s1209 :: SWord8 = s1198 >>> 1
-  s1210 :: SWord8 = s24 | s1209
-  s1211 :: SWord8 = s26 & s1209
-  s1212 :: SWord8 = if s1208 then s1210 else s1211
-  s1213 :: SWord8 = s1212 >>> 1
-  s1214 :: SWord8 = s24 | s1213
-  s1215 :: SWord8 = s26 & s1213
-  s1216 :: SWord8 = if s1204 then s1214 else s1215
-  s1217 :: SWord8 = s1202 >>> 1
-  s1218 :: SWord8 = s24 | s1217
-  s1219 :: SWord8 = s26 & s1217
-  s1220 :: SWord8 = if s1180 then s1218 else s1219
-  s1221 :: SWord8 = if s29 then s1201 else s1186
-  s1222 :: SWord8 = if s170 then s1220 else s1221
-  s1223 :: SWord8 = s1212 + s1222
-  s1224 :: SBool = s1223 < s1222
-  s1225 :: SBool = s1223 < s1212
-  s1226 :: SBool = s1224 | s1225
-  s1227 :: SWord8 = s1223 >>> 1
-  s1228 :: SWord8 = s24 | s1227
-  s1229 :: SWord8 = s26 & s1227
-  s1230 :: SWord8 = if s1226 then s1228 else s1229
-  s1231 :: SWord8 = if s1205 then s1216 else s1230
-  s1232 :: SWord8 = if s1148 then s1197 else s1231
-  s1233 :: SWord8 = if s1030 then s1140 else s1232
-  s1234 :: SWord8 = s1013 + s1090
-  s1235 :: SWord1 = choose [0:0] s1234
-  s1236 :: SBool = s19 /= s1235
-  s1237 :: SWord8 = if s1236 then s1024 else s1025
-  s1238 :: SWord8 = if s22 then s1237 else s1021
-  s1239 :: SWord1 = choose [0:0] s1238
-  s1240 :: SBool = s19 /= s1239
-  s1241 :: SBool = s_2 == s1240
-  s1242 :: SBool = s1234 < s1090
-  s1243 :: SBool = s1234 < s1013
-  s1244 :: SBool = s1242 | s1243
-  s1245 :: SWord8 = s1234 >>> 1
-  s1246 :: SWord8 = s24 | s1245
-  s1247 :: SWord8 = s26 & s1245
-  s1248 :: SWord8 = if s1244 then s1246 else s1247
-  s1249 :: SWord1 = choose [0:0] s1248
-  s1250 :: SBool = s19 /= s1249
-  s1251 :: SWord8 = s1238 >>> 1
-  s1252 :: SWord8 = s24 | s1251
-  s1253 :: SWord8 = s26 & s1251
-  s1254 :: SWord8 = if s1038 then s1252 else s1253
-  s1255 :: SWord8 = if s22 then s1254 else s1237
-  s1256 :: SWord8 = s1255 >>> 1
-  s1257 :: SWord8 = s24 | s1256
-  s1258 :: SWord8 = s26 & s1256
-  s1259 :: SWord8 = if s1250 then s1257 else s1258
-  s1260 :: SWord8 = if s22 then s1259 else s1254
-  s1261 :: SWord1 = choose [0:0] s1260
-  s1262 :: SBool = s19 /= s1261
-  s1263 :: SBool = s_2 == s1262
-  s1264 :: SWord8 = s1248 >>> 1
-  s1265 :: SWord8 = s24 | s1264
-  s1266 :: SWord8 = s26 & s1264
-  s1267 :: SWord8 = if s1240 then s1265 else s1266
-  s1268 :: SWord1 = choose [0:0] s1267
-  s1269 :: SBool = s19 /= s1268
-  s1270 :: SWord1 = choose [0:0] s1255
-  s1271 :: SBool = s19 /= s1270
-  s1272 :: SWord8 = s1260 >>> 1
-  s1273 :: SWord8 = s24 | s1272
-  s1274 :: SWord8 = s26 & s1272
-  s1275 :: SWord8 = if s1271 then s1273 else s1274
-  s1276 :: SWord8 = if s22 then s1275 else s1259
-  s1277 :: SWord8 = s1276 >>> 1
-  s1278 :: SWord8 = s24 | s1277
-  s1279 :: SWord8 = s26 & s1277
-  s1280 :: SWord8 = if s1269 then s1278 else s1279
-  s1281 :: SWord8 = if s22 then s1280 else s1275
-  s1282 :: SWord1 = choose [0:0] s1281
-  s1283 :: SBool = s19 /= s1282
-  s1284 :: SBool = s_2 == s1283
-  s1285 :: SWord8 = s1267 >>> 1
-  s1286 :: SWord8 = s24 | s1285
-  s1287 :: SWord8 = s26 & s1285
-  s1288 :: SWord8 = if s1262 then s1286 else s1287
-  s1289 :: SWord8 = s1288 >>> 1
-  s1290 :: SWord8 = s24 | s1289
-  s1291 :: SWord8 = s26 & s1289
-  s1292 :: SWord8 = if s1283 then s1290 else s1291
-  s1293 :: SWord1 = choose [0:0] s1276
-  s1294 :: SBool = s19 /= s1293
-  s1295 :: SWord8 = s1281 >>> 1
-  s1296 :: SWord8 = s24 | s1295
-  s1297 :: SWord8 = s26 & s1295
-  s1298 :: SWord8 = if s1294 then s1296 else s1297
-  s1299 :: SWord8 = if s29 then s1237 else s1090
-  s1300 :: SWord8 = if s170 then s1254 else s1299
-  s1301 :: SWord8 = if s29 then s1259 else s1300
-  s1302 :: SWord8 = if s170 then s1275 else s1301
-  s1303 :: SWord8 = if s29 then s1280 else s1302
-  s1304 :: SWord8 = if s170 then s1298 else s1303
-  s1305 :: SWord8 = s1288 + s1304
-  s1306 :: SBool = s1305 < s1304
-  s1307 :: SBool = s1305 < s1288
-  s1308 :: SBool = s1306 | s1307
-  s1309 :: SWord8 = s1305 >>> 1
-  s1310 :: SWord8 = s24 | s1309
-  s1311 :: SWord8 = s26 & s1309
-  s1312 :: SWord8 = if s1308 then s1310 else s1311
-  s1313 :: SWord8 = if s1284 then s1292 else s1312
-  s1314 :: SWord8 = s1267 + s1302
-  s1315 :: SWord1 = choose [0:0] s1314
-  s1316 :: SBool = s19 /= s1315
-  s1317 :: SWord8 = if s1316 then s1278 else s1279
-  s1318 :: SWord8 = if s22 then s1317 else s1275
-  s1319 :: SWord1 = choose [0:0] s1318
-  s1320 :: SBool = s19 /= s1319
-  s1321 :: SBool = s_2 == s1320
-  s1322 :: SBool = s1314 < s1302
-  s1323 :: SBool = s1314 < s1267
-  s1324 :: SBool = s1322 | s1323
-  s1325 :: SWord8 = s1314 >>> 1
-  s1326 :: SWord8 = s24 | s1325
-  s1327 :: SWord8 = s26 & s1325
-  s1328 :: SWord8 = if s1324 then s1326 else s1327
-  s1329 :: SWord8 = s1328 >>> 1
-  s1330 :: SWord8 = s24 | s1329
-  s1331 :: SWord8 = s26 & s1329
-  s1332 :: SWord8 = if s1320 then s1330 else s1331
-  s1333 :: SWord8 = s1318 >>> 1
-  s1334 :: SWord8 = s24 | s1333
-  s1335 :: SWord8 = s26 & s1333
-  s1336 :: SWord8 = if s1294 then s1334 else s1335
-  s1337 :: SWord8 = if s29 then s1317 else s1302
-  s1338 :: SWord8 = if s170 then s1336 else s1337
-  s1339 :: SWord8 = s1328 + s1338
-  s1340 :: SBool = s1339 < s1338
-  s1341 :: SBool = s1339 < s1328
-  s1342 :: SBool = s1340 | s1341
-  s1343 :: SWord8 = s1339 >>> 1
-  s1344 :: SWord8 = s24 | s1343
-  s1345 :: SWord8 = s26 & s1343
-  s1346 :: SWord8 = if s1342 then s1344 else s1345
-  s1347 :: SWord8 = if s1321 then s1332 else s1346
-  s1348 :: SWord8 = if s1263 then s1313 else s1347
-  s1349 :: SWord8 = s1248 + s1300
-  s1350 :: SWord1 = choose [0:0] s1349
-  s1351 :: SBool = s19 /= s1350
-  s1352 :: SWord8 = if s1351 then s1257 else s1258
-  s1353 :: SWord8 = if s22 then s1352 else s1254
-  s1354 :: SWord1 = choose [0:0] s1353
-  s1355 :: SBool = s19 /= s1354
-  s1356 :: SBool = s_2 == s1355
-  s1357 :: SBool = s1349 < s1300
-  s1358 :: SBool = s1349 < s1248
-  s1359 :: SBool = s1357 | s1358
-  s1360 :: SWord8 = s1349 >>> 1
-  s1361 :: SWord8 = s24 | s1360
-  s1362 :: SWord8 = s26 & s1360
-  s1363 :: SWord8 = if s1359 then s1361 else s1362
-  s1364 :: SWord1 = choose [0:0] s1363
-  s1365 :: SBool = s19 /= s1364
-  s1366 :: SWord8 = s1353 >>> 1
-  s1367 :: SWord8 = s24 | s1366
-  s1368 :: SWord8 = s26 & s1366
-  s1369 :: SWord8 = if s1271 then s1367 else s1368
-  s1370 :: SWord8 = if s22 then s1369 else s1352
-  s1371 :: SWord8 = s1370 >>> 1
-  s1372 :: SWord8 = s24 | s1371
-  s1373 :: SWord8 = s26 & s1371
-  s1374 :: SWord8 = if s1365 then s1372 else s1373
-  s1375 :: SWord8 = if s22 then s1374 else s1369
-  s1376 :: SWord1 = choose [0:0] s1375
-  s1377 :: SBool = s19 /= s1376
-  s1378 :: SBool = s_2 == s1377
-  s1379 :: SWord8 = s1363 >>> 1
-  s1380 :: SWord8 = s24 | s1379
-  s1381 :: SWord8 = s26 & s1379
-  s1382 :: SWord8 = if s1355 then s1380 else s1381
-  s1383 :: SWord8 = s1382 >>> 1
-  s1384 :: SWord8 = s24 | s1383
-  s1385 :: SWord8 = s26 & s1383
-  s1386 :: SWord8 = if s1377 then s1384 else s1385
-  s1387 :: SWord1 = choose [0:0] s1370
-  s1388 :: SBool = s19 /= s1387
-  s1389 :: SWord8 = s1375 >>> 1
-  s1390 :: SWord8 = s24 | s1389
-  s1391 :: SWord8 = s26 & s1389
-  s1392 :: SWord8 = if s1388 then s1390 else s1391
-  s1393 :: SWord8 = if s29 then s1352 else s1300
-  s1394 :: SWord8 = if s170 then s1369 else s1393
-  s1395 :: SWord8 = if s29 then s1374 else s1394
-  s1396 :: SWord8 = if s170 then s1392 else s1395
-  s1397 :: SWord8 = s1382 + s1396
-  s1398 :: SBool = s1397 < s1396
-  s1399 :: SBool = s1397 < s1382
-  s1400 :: SBool = s1398 | s1399
-  s1401 :: SWord8 = s1397 >>> 1
-  s1402 :: SWord8 = s24 | s1401
-  s1403 :: SWord8 = s26 & s1401
-  s1404 :: SWord8 = if s1400 then s1402 else s1403
-  s1405 :: SWord8 = if s1378 then s1386 else s1404
-  s1406 :: SWord8 = s1363 + s1394
-  s1407 :: SWord1 = choose [0:0] s1406
-  s1408 :: SBool = s19 /= s1407
-  s1409 :: SWord8 = if s1408 then s1372 else s1373
-  s1410 :: SWord8 = if s22 then s1409 else s1369
-  s1411 :: SWord1 = choose [0:0] s1410
-  s1412 :: SBool = s19 /= s1411
-  s1413 :: SBool = s_2 == s1412
-  s1414 :: SBool = s1406 < s1394
-  s1415 :: SBool = s1406 < s1363
-  s1416 :: SBool = s1414 | s1415
-  s1417 :: SWord8 = s1406 >>> 1
-  s1418 :: SWord8 = s24 | s1417
-  s1419 :: SWord8 = s26 & s1417
-  s1420 :: SWord8 = if s1416 then s1418 else s1419
-  s1421 :: SWord8 = s1420 >>> 1
-  s1422 :: SWord8 = s24 | s1421
-  s1423 :: SWord8 = s26 & s1421
-  s1424 :: SWord8 = if s1412 then s1422 else s1423
-  s1425 :: SWord8 = s1410 >>> 1
-  s1426 :: SWord8 = s24 | s1425
-  s1427 :: SWord8 = s26 & s1425
-  s1428 :: SWord8 = if s1388 then s1426 else s1427
-  s1429 :: SWord8 = if s29 then s1409 else s1394
-  s1430 :: SWord8 = if s170 then s1428 else s1429
-  s1431 :: SWord8 = s1420 + s1430
-  s1432 :: SBool = s1431 < s1430
-  s1433 :: SBool = s1431 < s1420
-  s1434 :: SBool = s1432 | s1433
-  s1435 :: SWord8 = s1431 >>> 1
-  s1436 :: SWord8 = s24 | s1435
-  s1437 :: SWord8 = s26 & s1435
-  s1438 :: SWord8 = if s1434 then s1436 else s1437
-  s1439 :: SWord8 = if s1413 then s1424 else s1438
-  s1440 :: SWord8 = if s1356 then s1405 else s1439
-  s1441 :: SWord8 = if s1241 then s1348 else s1440
-  s1442 :: SWord8 = if s1009 then s1233 else s1441
-  s1443 :: SWord8 = s994 + s1088
-  s1444 :: SWord1 = choose [0:0] s1443
-  s1445 :: SBool = s19 /= s1444
-  s1446 :: SWord8 = if s1445 then s1003 else s1004
-  s1447 :: SWord8 = if s22 then s1446 else s1000
-  s1448 :: SWord1 = choose [0:0] s1447
-  s1449 :: SBool = s19 /= s1448
-  s1450 :: SBool = s_2 == s1449
-  s1451 :: SBool = s1443 < s1088
-  s1452 :: SBool = s1443 < s994
-  s1453 :: SBool = s1451 | s1452
-  s1454 :: SWord8 = s1443 >>> 1
-  s1455 :: SWord8 = s24 | s1454
-  s1456 :: SWord8 = s26 & s1454
-  s1457 :: SWord8 = if s1453 then s1455 else s1456
-  s1458 :: SWord1 = choose [0:0] s1457
-  s1459 :: SBool = s19 /= s1458
-  s1460 :: SWord8 = s1447 >>> 1
-  s1461 :: SWord8 = s24 | s1460
-  s1462 :: SWord8 = s26 & s1460
-  s1463 :: SWord8 = if s1017 then s1461 else s1462
-  s1464 :: SWord8 = if s22 then s1463 else s1446
-  s1465 :: SWord8 = s1464 >>> 1
-  s1466 :: SWord8 = s24 | s1465
-  s1467 :: SWord8 = s26 & s1465
-  s1468 :: SWord8 = if s1459 then s1466 else s1467
-  s1469 :: SWord8 = if s22 then s1468 else s1463
-  s1470 :: SWord1 = choose [0:0] s1469
-  s1471 :: SBool = s19 /= s1470
-  s1472 :: SBool = s_2 == s1471
-  s1473 :: SWord8 = s1457 >>> 1
-  s1474 :: SWord8 = s24 | s1473
-  s1475 :: SWord8 = s26 & s1473
-  s1476 :: SWord8 = if s1449 then s1474 else s1475
-  s1477 :: SWord1 = choose [0:0] s1476
-  s1478 :: SBool = s19 /= s1477
-  s1479 :: SWord1 = choose [0:0] s1464
-  s1480 :: SBool = s19 /= s1479
-  s1481 :: SWord8 = s1469 >>> 1
-  s1482 :: SWord8 = s24 | s1481
-  s1483 :: SWord8 = s26 & s1481
-  s1484 :: SWord8 = if s1480 then s1482 else s1483
-  s1485 :: SWord8 = if s22 then s1484 else s1468
-  s1486 :: SWord8 = s1485 >>> 1
-  s1487 :: SWord8 = s24 | s1486
-  s1488 :: SWord8 = s26 & s1486
-  s1489 :: SWord8 = if s1478 then s1487 else s1488
-  s1490 :: SWord8 = if s22 then s1489 else s1484
-  s1491 :: SWord1 = choose [0:0] s1490
-  s1492 :: SBool = s19 /= s1491
-  s1493 :: SBool = s_2 == s1492
-  s1494 :: SWord8 = s1476 >>> 1
-  s1495 :: SWord8 = s24 | s1494
-  s1496 :: SWord8 = s26 & s1494
-  s1497 :: SWord8 = if s1471 then s1495 else s1496
-  s1498 :: SWord1 = choose [0:0] s1497
-  s1499 :: SBool = s19 /= s1498
-  s1500 :: SWord1 = choose [0:0] s1485
-  s1501 :: SBool = s19 /= s1500
-  s1502 :: SWord8 = s1490 >>> 1
-  s1503 :: SWord8 = s24 | s1502
-  s1504 :: SWord8 = s26 & s1502
-  s1505 :: SWord8 = if s1501 then s1503 else s1504
-  s1506 :: SWord8 = if s22 then s1505 else s1489
-  s1507 :: SWord8 = s1506 >>> 1
-  s1508 :: SWord8 = s24 | s1507
-  s1509 :: SWord8 = s26 & s1507
-  s1510 :: SWord8 = if s1499 then s1508 else s1509
-  s1511 :: SWord8 = if s22 then s1510 else s1505
-  s1512 :: SWord1 = choose [0:0] s1511
-  s1513 :: SBool = s19 /= s1512
-  s1514 :: SBool = s_2 == s1513
-  s1515 :: SWord8 = s1497 >>> 1
-  s1516 :: SWord8 = s24 | s1515
-  s1517 :: SWord8 = s26 & s1515
-  s1518 :: SWord8 = if s1492 then s1516 else s1517
-  s1519 :: SWord8 = s1518 >>> 1
-  s1520 :: SWord8 = s24 | s1519
-  s1521 :: SWord8 = s26 & s1519
-  s1522 :: SWord8 = if s1513 then s1520 else s1521
-  s1523 :: SWord1 = choose [0:0] s1506
-  s1524 :: SBool = s19 /= s1523
-  s1525 :: SWord8 = s1511 >>> 1
-  s1526 :: SWord8 = s24 | s1525
-  s1527 :: SWord8 = s26 & s1525
-  s1528 :: SWord8 = if s1524 then s1526 else s1527
-  s1529 :: SWord8 = if s29 then s1446 else s1088
-  s1530 :: SWord8 = if s170 then s1463 else s1529
-  s1531 :: SWord8 = if s29 then s1468 else s1530
-  s1532 :: SWord8 = if s170 then s1484 else s1531
-  s1533 :: SWord8 = if s29 then s1489 else s1532
-  s1534 :: SWord8 = if s170 then s1505 else s1533
-  s1535 :: SWord8 = if s29 then s1510 else s1534
-  s1536 :: SWord8 = if s170 then s1528 else s1535
-  s1537 :: SWord8 = s1518 + s1536
-  s1538 :: SBool = s1537 < s1536
-  s1539 :: SBool = s1537 < s1518
-  s1540 :: SBool = s1538 | s1539
-  s1541 :: SWord8 = s1537 >>> 1
-  s1542 :: SWord8 = s24 | s1541
-  s1543 :: SWord8 = s26 & s1541
-  s1544 :: SWord8 = if s1540 then s1542 else s1543
-  s1545 :: SWord8 = if s1514 then s1522 else s1544
-  s1546 :: SWord8 = s1497 + s1534
-  s1547 :: SWord1 = choose [0:0] s1546
-  s1548 :: SBool = s19 /= s1547
-  s1549 :: SWord8 = if s1548 then s1508 else s1509
-  s1550 :: SWord8 = if s22 then s1549 else s1505
-  s1551 :: SWord1 = choose [0:0] s1550
-  s1552 :: SBool = s19 /= s1551
-  s1553 :: SBool = s_2 == s1552
-  s1554 :: SBool = s1546 < s1534
-  s1555 :: SBool = s1546 < s1497
-  s1556 :: SBool = s1554 | s1555
-  s1557 :: SWord8 = s1546 >>> 1
-  s1558 :: SWord8 = s24 | s1557
-  s1559 :: SWord8 = s26 & s1557
-  s1560 :: SWord8 = if s1556 then s1558 else s1559
-  s1561 :: SWord8 = s1560 >>> 1
-  s1562 :: SWord8 = s24 | s1561
-  s1563 :: SWord8 = s26 & s1561
-  s1564 :: SWord8 = if s1552 then s1562 else s1563
-  s1565 :: SWord8 = s1550 >>> 1
-  s1566 :: SWord8 = s24 | s1565
-  s1567 :: SWord8 = s26 & s1565
-  s1568 :: SWord8 = if s1524 then s1566 else s1567
-  s1569 :: SWord8 = if s29 then s1549 else s1534
-  s1570 :: SWord8 = if s170 then s1568 else s1569
-  s1571 :: SWord8 = s1560 + s1570
-  s1572 :: SBool = s1571 < s1570
-  s1573 :: SBool = s1571 < s1560
-  s1574 :: SBool = s1572 | s1573
-  s1575 :: SWord8 = s1571 >>> 1
-  s1576 :: SWord8 = s24 | s1575
-  s1577 :: SWord8 = s26 & s1575
-  s1578 :: SWord8 = if s1574 then s1576 else s1577
-  s1579 :: SWord8 = if s1553 then s1564 else s1578
-  s1580 :: SWord8 = if s1493 then s1545 else s1579
-  s1581 :: SWord8 = s1476 + s1532
-  s1582 :: SWord1 = choose [0:0] s1581
-  s1583 :: SBool = s19 /= s1582
-  s1584 :: SWord8 = if s1583 then s1487 else s1488
-  s1585 :: SWord8 = if s22 then s1584 else s1484
-  s1586 :: SWord1 = choose [0:0] s1585
-  s1587 :: SBool = s19 /= s1586
-  s1588 :: SBool = s_2 == s1587
-  s1589 :: SBool = s1581 < s1532
-  s1590 :: SBool = s1581 < s1476
-  s1591 :: SBool = s1589 | s1590
-  s1592 :: SWord8 = s1581 >>> 1
-  s1593 :: SWord8 = s24 | s1592
-  s1594 :: SWord8 = s26 & s1592
-  s1595 :: SWord8 = if s1591 then s1593 else s1594
-  s1596 :: SWord1 = choose [0:0] s1595
-  s1597 :: SBool = s19 /= s1596
-  s1598 :: SWord8 = s1585 >>> 1
-  s1599 :: SWord8 = s24 | s1598
-  s1600 :: SWord8 = s26 & s1598
-  s1601 :: SWord8 = if s1501 then s1599 else s1600
-  s1602 :: SWord8 = if s22 then s1601 else s1584
-  s1603 :: SWord8 = s1602 >>> 1
-  s1604 :: SWord8 = s24 | s1603
-  s1605 :: SWord8 = s26 & s1603
-  s1606 :: SWord8 = if s1597 then s1604 else s1605
-  s1607 :: SWord8 = if s22 then s1606 else s1601
-  s1608 :: SWord1 = choose [0:0] s1607
-  s1609 :: SBool = s19 /= s1608
-  s1610 :: SBool = s_2 == s1609
-  s1611 :: SWord8 = s1595 >>> 1
-  s1612 :: SWord8 = s24 | s1611
-  s1613 :: SWord8 = s26 & s1611
-  s1614 :: SWord8 = if s1587 then s1612 else s1613
-  s1615 :: SWord8 = s1614 >>> 1
-  s1616 :: SWord8 = s24 | s1615
-  s1617 :: SWord8 = s26 & s1615
-  s1618 :: SWord8 = if s1609 then s1616 else s1617
-  s1619 :: SWord1 = choose [0:0] s1602
-  s1620 :: SBool = s19 /= s1619
-  s1621 :: SWord8 = s1607 >>> 1
-  s1622 :: SWord8 = s24 | s1621
-  s1623 :: SWord8 = s26 & s1621
-  s1624 :: SWord8 = if s1620 then s1622 else s1623
-  s1625 :: SWord8 = if s29 then s1584 else s1532
-  s1626 :: SWord8 = if s170 then s1601 else s1625
-  s1627 :: SWord8 = if s29 then s1606 else s1626
-  s1628 :: SWord8 = if s170 then s1624 else s1627
-  s1629 :: SWord8 = s1614 + s1628
-  s1630 :: SBool = s1629 < s1628
-  s1631 :: SBool = s1629 < s1614
-  s1632 :: SBool = s1630 | s1631
-  s1633 :: SWord8 = s1629 >>> 1
-  s1634 :: SWord8 = s24 | s1633
-  s1635 :: SWord8 = s26 & s1633
-  s1636 :: SWord8 = if s1632 then s1634 else s1635
-  s1637 :: SWord8 = if s1610 then s1618 else s1636
-  s1638 :: SWord8 = s1595 + s1626
-  s1639 :: SWord1 = choose [0:0] s1638
-  s1640 :: SBool = s19 /= s1639
-  s1641 :: SWord8 = if s1640 then s1604 else s1605
-  s1642 :: SWord8 = if s22 then s1641 else s1601
-  s1643 :: SWord1 = choose [0:0] s1642
-  s1644 :: SBool = s19 /= s1643
-  s1645 :: SBool = s_2 == s1644
-  s1646 :: SBool = s1638 < s1626
-  s1647 :: SBool = s1638 < s1595
-  s1648 :: SBool = s1646 | s1647
-  s1649 :: SWord8 = s1638 >>> 1
-  s1650 :: SWord8 = s24 | s1649
-  s1651 :: SWord8 = s26 & s1649
-  s1652 :: SWord8 = if s1648 then s1650 else s1651
-  s1653 :: SWord8 = s1652 >>> 1
-  s1654 :: SWord8 = s24 | s1653
-  s1655 :: SWord8 = s26 & s1653
-  s1656 :: SWord8 = if s1644 then s1654 else s1655
-  s1657 :: SWord8 = s1642 >>> 1
-  s1658 :: SWord8 = s24 | s1657
-  s1659 :: SWord8 = s26 & s1657
-  s1660 :: SWord8 = if s1620 then s1658 else s1659
-  s1661 :: SWord8 = if s29 then s1641 else s1626
-  s1662 :: SWord8 = if s170 then s1660 else s1661
-  s1663 :: SWord8 = s1652 + s1662
-  s1664 :: SBool = s1663 < s1662
-  s1665 :: SBool = s1663 < s1652
-  s1666 :: SBool = s1664 | s1665
-  s1667 :: SWord8 = s1663 >>> 1
-  s1668 :: SWord8 = s24 | s1667
-  s1669 :: SWord8 = s26 & s1667
-  s1670 :: SWord8 = if s1666 then s1668 else s1669
-  s1671 :: SWord8 = if s1645 then s1656 else s1670
-  s1672 :: SWord8 = if s1588 then s1637 else s1671
-  s1673 :: SWord8 = if s1472 then s1580 else s1672
-  s1674 :: SWord8 = s1457 + s1530
-  s1675 :: SWord1 = choose [0:0] s1674
-  s1676 :: SBool = s19 /= s1675
-  s1677 :: SWord8 = if s1676 then s1466 else s1467
-  s1678 :: SWord8 = if s22 then s1677 else s1463
-  s1679 :: SWord1 = choose [0:0] s1678
-  s1680 :: SBool = s19 /= s1679
-  s1681 :: SBool = s_2 == s1680
-  s1682 :: SBool = s1674 < s1530
-  s1683 :: SBool = s1674 < s1457
-  s1684 :: SBool = s1682 | s1683
-  s1685 :: SWord8 = s1674 >>> 1
-  s1686 :: SWord8 = s24 | s1685
-  s1687 :: SWord8 = s26 & s1685
-  s1688 :: SWord8 = if s1684 then s1686 else s1687
-  s1689 :: SWord1 = choose [0:0] s1688
-  s1690 :: SBool = s19 /= s1689
-  s1691 :: SWord8 = s1678 >>> 1
-  s1692 :: SWord8 = s24 | s1691
-  s1693 :: SWord8 = s26 & s1691
-  s1694 :: SWord8 = if s1480 then s1692 else s1693
-  s1695 :: SWord8 = if s22 then s1694 else s1677
-  s1696 :: SWord8 = s1695 >>> 1
-  s1697 :: SWord8 = s24 | s1696
-  s1698 :: SWord8 = s26 & s1696
-  s1699 :: SWord8 = if s1690 then s1697 else s1698
-  s1700 :: SWord8 = if s22 then s1699 else s1694
-  s1701 :: SWord1 = choose [0:0] s1700
-  s1702 :: SBool = s19 /= s1701
-  s1703 :: SBool = s_2 == s1702
-  s1704 :: SWord8 = s1688 >>> 1
-  s1705 :: SWord8 = s24 | s1704
-  s1706 :: SWord8 = s26 & s1704
-  s1707 :: SWord8 = if s1680 then s1705 else s1706
-  s1708 :: SWord1 = choose [0:0] s1707
-  s1709 :: SBool = s19 /= s1708
-  s1710 :: SWord1 = choose [0:0] s1695
-  s1711 :: SBool = s19 /= s1710
-  s1712 :: SWord8 = s1700 >>> 1
-  s1713 :: SWord8 = s24 | s1712
-  s1714 :: SWord8 = s26 & s1712
-  s1715 :: SWord8 = if s1711 then s1713 else s1714
-  s1716 :: SWord8 = if s22 then s1715 else s1699
-  s1717 :: SWord8 = s1716 >>> 1
-  s1718 :: SWord8 = s24 | s1717
-  s1719 :: SWord8 = s26 & s1717
-  s1720 :: SWord8 = if s1709 then s1718 else s1719
-  s1721 :: SWord8 = if s22 then s1720 else s1715
-  s1722 :: SWord1 = choose [0:0] s1721
-  s1723 :: SBool = s19 /= s1722
-  s1724 :: SBool = s_2 == s1723
-  s1725 :: SWord8 = s1707 >>> 1
-  s1726 :: SWord8 = s24 | s1725
-  s1727 :: SWord8 = s26 & s1725
-  s1728 :: SWord8 = if s1702 then s1726 else s1727
-  s1729 :: SWord8 = s1728 >>> 1
-  s1730 :: SWord8 = s24 | s1729
-  s1731 :: SWord8 = s26 & s1729
-  s1732 :: SWord8 = if s1723 then s1730 else s1731
-  s1733 :: SWord1 = choose [0:0] s1716
-  s1734 :: SBool = s19 /= s1733
-  s1735 :: SWord8 = s1721 >>> 1
-  s1736 :: SWord8 = s24 | s1735
-  s1737 :: SWord8 = s26 & s1735
-  s1738 :: SWord8 = if s1734 then s1736 else s1737
-  s1739 :: SWord8 = if s29 then s1677 else s1530
-  s1740 :: SWord8 = if s170 then s1694 else s1739
-  s1741 :: SWord8 = if s29 then s1699 else s1740
-  s1742 :: SWord8 = if s170 then s1715 else s1741
-  s1743 :: SWord8 = if s29 then s1720 else s1742
-  s1744 :: SWord8 = if s170 then s1738 else s1743
-  s1745 :: SWord8 = s1728 + s1744
-  s1746 :: SBool = s1745 < s1744
-  s1747 :: SBool = s1745 < s1728
-  s1748 :: SBool = s1746 | s1747
-  s1749 :: SWord8 = s1745 >>> 1
-  s1750 :: SWord8 = s24 | s1749
-  s1751 :: SWord8 = s26 & s1749
-  s1752 :: SWord8 = if s1748 then s1750 else s1751
-  s1753 :: SWord8 = if s1724 then s1732 else s1752
-  s1754 :: SWord8 = s1707 + s1742
-  s1755 :: SWord1 = choose [0:0] s1754
-  s1756 :: SBool = s19 /= s1755
-  s1757 :: SWord8 = if s1756 then s1718 else s1719
-  s1758 :: SWord8 = if s22 then s1757 else s1715
-  s1759 :: SWord1 = choose [0:0] s1758
-  s1760 :: SBool = s19 /= s1759
-  s1761 :: SBool = s_2 == s1760
-  s1762 :: SBool = s1754 < s1742
-  s1763 :: SBool = s1754 < s1707
-  s1764 :: SBool = s1762 | s1763
-  s1765 :: SWord8 = s1754 >>> 1
-  s1766 :: SWord8 = s24 | s1765
-  s1767 :: SWord8 = s26 & s1765
-  s1768 :: SWord8 = if s1764 then s1766 else s1767
-  s1769 :: SWord8 = s1768 >>> 1
-  s1770 :: SWord8 = s24 | s1769
-  s1771 :: SWord8 = s26 & s1769
-  s1772 :: SWord8 = if s1760 then s1770 else s1771
-  s1773 :: SWord8 = s1758 >>> 1
-  s1774 :: SWord8 = s24 | s1773
-  s1775 :: SWord8 = s26 & s1773
-  s1776 :: SWord8 = if s1734 then s1774 else s1775
-  s1777 :: SWord8 = if s29 then s1757 else s1742
-  s1778 :: SWord8 = if s170 then s1776 else s1777
-  s1779 :: SWord8 = s1768 + s1778
-  s1780 :: SBool = s1779 < s1778
-  s1781 :: SBool = s1779 < s1768
-  s1782 :: SBool = s1780 | s1781
-  s1783 :: SWord8 = s1779 >>> 1
-  s1784 :: SWord8 = s24 | s1783
-  s1785 :: SWord8 = s26 & s1783
-  s1786 :: SWord8 = if s1782 then s1784 else s1785
-  s1787 :: SWord8 = if s1761 then s1772 else s1786
-  s1788 :: SWord8 = if s1703 then s1753 else s1787
-  s1789 :: SWord8 = s1688 + s1740
-  s1790 :: SWord1 = choose [0:0] s1789
-  s1791 :: SBool = s19 /= s1790
-  s1792 :: SWord8 = if s1791 then s1697 else s1698
-  s1793 :: SWord8 = if s22 then s1792 else s1694
-  s1794 :: SWord1 = choose [0:0] s1793
-  s1795 :: SBool = s19 /= s1794
-  s1796 :: SBool = s_2 == s1795
-  s1797 :: SBool = s1789 < s1740
-  s1798 :: SBool = s1789 < s1688
-  s1799 :: SBool = s1797 | s1798
-  s1800 :: SWord8 = s1789 >>> 1
-  s1801 :: SWord8 = s24 | s1800
-  s1802 :: SWord8 = s26 & s1800
-  s1803 :: SWord8 = if s1799 then s1801 else s1802
-  s1804 :: SWord1 = choose [0:0] s1803
-  s1805 :: SBool = s19 /= s1804
-  s1806 :: SWord8 = s1793 >>> 1
-  s1807 :: SWord8 = s24 | s1806
-  s1808 :: SWord8 = s26 & s1806
-  s1809 :: SWord8 = if s1711 then s1807 else s1808
-  s1810 :: SWord8 = if s22 then s1809 else s1792
-  s1811 :: SWord8 = s1810 >>> 1
-  s1812 :: SWord8 = s24 | s1811
-  s1813 :: SWord8 = s26 & s1811
-  s1814 :: SWord8 = if s1805 then s1812 else s1813
-  s1815 :: SWord8 = if s22 then s1814 else s1809
-  s1816 :: SWord1 = choose [0:0] s1815
-  s1817 :: SBool = s19 /= s1816
-  s1818 :: SBool = s_2 == s1817
-  s1819 :: SWord8 = s1803 >>> 1
-  s1820 :: SWord8 = s24 | s1819
-  s1821 :: SWord8 = s26 & s1819
-  s1822 :: SWord8 = if s1795 then s1820 else s1821
-  s1823 :: SWord8 = s1822 >>> 1
-  s1824 :: SWord8 = s24 | s1823
-  s1825 :: SWord8 = s26 & s1823
-  s1826 :: SWord8 = if s1817 then s1824 else s1825
-  s1827 :: SWord1 = choose [0:0] s1810
-  s1828 :: SBool = s19 /= s1827
-  s1829 :: SWord8 = s1815 >>> 1
-  s1830 :: SWord8 = s24 | s1829
-  s1831 :: SWord8 = s26 & s1829
-  s1832 :: SWord8 = if s1828 then s1830 else s1831
-  s1833 :: SWord8 = if s29 then s1792 else s1740
-  s1834 :: SWord8 = if s170 then s1809 else s1833
-  s1835 :: SWord8 = if s29 then s1814 else s1834
-  s1836 :: SWord8 = if s170 then s1832 else s1835
-  s1837 :: SWord8 = s1822 + s1836
-  s1838 :: SBool = s1837 < s1836
-  s1839 :: SBool = s1837 < s1822
-  s1840 :: SBool = s1838 | s1839
-  s1841 :: SWord8 = s1837 >>> 1
-  s1842 :: SWord8 = s24 | s1841
-  s1843 :: SWord8 = s26 & s1841
-  s1844 :: SWord8 = if s1840 then s1842 else s1843
-  s1845 :: SWord8 = if s1818 then s1826 else s1844
-  s1846 :: SWord8 = s1803 + s1834
-  s1847 :: SWord1 = choose [0:0] s1846
-  s1848 :: SBool = s19 /= s1847
-  s1849 :: SWord8 = if s1848 then s1812 else s1813
-  s1850 :: SWord8 = if s22 then s1849 else s1809
-  s1851 :: SWord1 = choose [0:0] s1850
-  s1852 :: SBool = s19 /= s1851
-  s1853 :: SBool = s_2 == s1852
-  s1854 :: SBool = s1846 < s1834
-  s1855 :: SBool = s1846 < s1803
-  s1856 :: SBool = s1854 | s1855
-  s1857 :: SWord8 = s1846 >>> 1
-  s1858 :: SWord8 = s24 | s1857
-  s1859 :: SWord8 = s26 & s1857
-  s1860 :: SWord8 = if s1856 then s1858 else s1859
-  s1861 :: SWord8 = s1860 >>> 1
-  s1862 :: SWord8 = s24 | s1861
-  s1863 :: SWord8 = s26 & s1861
-  s1864 :: SWord8 = if s1852 then s1862 else s1863
-  s1865 :: SWord8 = s1850 >>> 1
-  s1866 :: SWord8 = s24 | s1865
-  s1867 :: SWord8 = s26 & s1865
-  s1868 :: SWord8 = if s1828 then s1866 else s1867
-  s1869 :: SWord8 = if s29 then s1849 else s1834
-  s1870 :: SWord8 = if s170 then s1868 else s1869
-  s1871 :: SWord8 = s1860 + s1870
-  s1872 :: SBool = s1871 < s1870
-  s1873 :: SBool = s1871 < s1860
-  s1874 :: SBool = s1872 | s1873
-  s1875 :: SWord8 = s1871 >>> 1
-  s1876 :: SWord8 = s24 | s1875
-  s1877 :: SWord8 = s26 & s1875
-  s1878 :: SWord8 = if s1874 then s1876 else s1877
-  s1879 :: SWord8 = if s1853 then s1864 else s1878
-  s1880 :: SWord8 = if s1796 then s1845 else s1879
-  s1881 :: SWord8 = if s1681 then s1788 else s1880
-  s1882 :: SWord8 = if s1450 then s1673 else s1881
-  s1883 :: SWord8 = if s987 then s1442 else s1882
-  s1884 :: SWord8 = if s56 then s979 else s1883
-  s1885 :: SWord8 = s39 + s180
-  s1886 :: SWord1 = choose [0:0] s1885
-  s1887 :: SBool = s19 /= s1886
-  s1888 :: SWord8 = if s1887 then s50 else s51
-  s1889 :: SWord8 = if s22 then s1888 else s47
-  s1890 :: SWord1 = choose [0:0] s1889
-  s1891 :: SBool = s19 /= s1890
-  s1892 :: SBool = s_2 == s1891
-  s1893 :: SBool = s1885 < s180
-  s1894 :: SBool = s1885 < s39
-  s1895 :: SBool = s1893 | s1894
-  s1896 :: SWord8 = s1885 >>> 1
-  s1897 :: SWord8 = s24 | s1896
-  s1898 :: SWord8 = s26 & s1896
-  s1899 :: SWord8 = if s1895 then s1897 else s1898
-  s1900 :: SWord1 = choose [0:0] s1899
-  s1901 :: SBool = s19 /= s1900
-  s1902 :: SWord8 = s1889 >>> 1
-  s1903 :: SWord8 = s24 | s1902
-  s1904 :: SWord8 = s26 & s1902
-  s1905 :: SWord8 = if s64 then s1903 else s1904
-  s1906 :: SWord8 = if s22 then s1905 else s1888
-  s1907 :: SWord8 = s1906 >>> 1
-  s1908 :: SWord8 = s24 | s1907
-  s1909 :: SWord8 = s26 & s1907
-  s1910 :: SWord8 = if s1901 then s1908 else s1909
-  s1911 :: SWord8 = if s22 then s1910 else s1905
-  s1912 :: SWord1 = choose [0:0] s1911
-  s1913 :: SBool = s19 /= s1912
-  s1914 :: SBool = s_2 == s1913
-  s1915 :: SWord8 = s1899 >>> 1
-  s1916 :: SWord8 = s24 | s1915
-  s1917 :: SWord8 = s26 & s1915
-  s1918 :: SWord8 = if s1891 then s1916 else s1917
-  s1919 :: SWord1 = choose [0:0] s1918
-  s1920 :: SBool = s19 /= s1919
-  s1921 :: SWord1 = choose [0:0] s1906
-  s1922 :: SBool = s19 /= s1921
-  s1923 :: SWord8 = s1911 >>> 1
-  s1924 :: SWord8 = s24 | s1923
-  s1925 :: SWord8 = s26 & s1923
-  s1926 :: SWord8 = if s1922 then s1924 else s1925
-  s1927 :: SWord8 = if s22 then s1926 else s1910
-  s1928 :: SWord8 = s1927 >>> 1
-  s1929 :: SWord8 = s24 | s1928
-  s1930 :: SWord8 = s26 & s1928
-  s1931 :: SWord8 = if s1920 then s1929 else s1930
-  s1932 :: SWord8 = if s22 then s1931 else s1926
-  s1933 :: SWord1 = choose [0:0] s1932
-  s1934 :: SBool = s19 /= s1933
-  s1935 :: SBool = s_2 == s1934
-  s1936 :: SWord8 = s1918 >>> 1
-  s1937 :: SWord8 = s24 | s1936
-  s1938 :: SWord8 = s26 & s1936
-  s1939 :: SWord8 = if s1913 then s1937 else s1938
-  s1940 :: SWord1 = choose [0:0] s1939
-  s1941 :: SBool = s19 /= s1940
-  s1942 :: SWord1 = choose [0:0] s1927
-  s1943 :: SBool = s19 /= s1942
-  s1944 :: SWord8 = s1932 >>> 1
-  s1945 :: SWord8 = s24 | s1944
-  s1946 :: SWord8 = s26 & s1944
-  s1947 :: SWord8 = if s1943 then s1945 else s1946
-  s1948 :: SWord8 = if s22 then s1947 else s1931
-  s1949 :: SWord8 = s1948 >>> 1
-  s1950 :: SWord8 = s24 | s1949
-  s1951 :: SWord8 = s26 & s1949
-  s1952 :: SWord8 = if s1941 then s1950 else s1951
-  s1953 :: SWord8 = if s22 then s1952 else s1947
-  s1954 :: SWord1 = choose [0:0] s1953
-  s1955 :: SBool = s19 /= s1954
-  s1956 :: SBool = s_2 == s1955
-  s1957 :: SWord8 = s1939 >>> 1
-  s1958 :: SWord8 = s24 | s1957
-  s1959 :: SWord8 = s26 & s1957
-  s1960 :: SWord8 = if s1934 then s1958 else s1959
-  s1961 :: SWord1 = choose [0:0] s1960
-  s1962 :: SBool = s19 /= s1961
-  s1963 :: SWord1 = choose [0:0] s1948
-  s1964 :: SBool = s19 /= s1963
-  s1965 :: SWord8 = s1953 >>> 1
-  s1966 :: SWord8 = s24 | s1965
-  s1967 :: SWord8 = s26 & s1965
-  s1968 :: SWord8 = if s1964 then s1966 else s1967
-  s1969 :: SWord8 = if s22 then s1968 else s1952
-  s1970 :: SWord8 = s1969 >>> 1
-  s1971 :: SWord8 = s24 | s1970
-  s1972 :: SWord8 = s26 & s1970
-  s1973 :: SWord8 = if s1962 then s1971 else s1972
-  s1974 :: SWord8 = if s22 then s1973 else s1968
-  s1975 :: SWord1 = choose [0:0] s1974
-  s1976 :: SBool = s19 /= s1975
-  s1977 :: SBool = s_2 == s1976
-  s1978 :: SWord8 = s1960 >>> 1
-  s1979 :: SWord8 = s24 | s1978
-  s1980 :: SWord8 = s26 & s1978
-  s1981 :: SWord8 = if s1955 then s1979 else s1980
-  s1982 :: SWord1 = choose [0:0] s1981
-  s1983 :: SBool = s19 /= s1982
-  s1984 :: SWord1 = choose [0:0] s1969
-  s1985 :: SBool = s19 /= s1984
-  s1986 :: SWord8 = s1974 >>> 1
-  s1987 :: SWord8 = s24 | s1986
-  s1988 :: SWord8 = s26 & s1986
-  s1989 :: SWord8 = if s1985 then s1987 else s1988
-  s1990 :: SWord8 = if s22 then s1989 else s1973
-  s1991 :: SWord8 = s1990 >>> 1
-  s1992 :: SWord8 = s24 | s1991
-  s1993 :: SWord8 = s26 & s1991
-  s1994 :: SWord8 = if s1983 then s1992 else s1993
-  s1995 :: SWord8 = if s22 then s1994 else s1989
-  s1996 :: SWord1 = choose [0:0] s1995
-  s1997 :: SBool = s19 /= s1996
-  s1998 :: SBool = s_2 == s1997
-  s1999 :: SWord8 = s1981 >>> 1
-  s2000 :: SWord8 = s24 | s1999
-  s2001 :: SWord8 = s26 & s1999
-  s2002 :: SWord8 = if s1976 then s2000 else s2001
-  s2003 :: SWord8 = s2002 >>> 1
-  s2004 :: SWord8 = s24 | s2003
-  s2005 :: SWord8 = s26 & s2003
-  s2006 :: SWord8 = if s1997 then s2004 else s2005
-  s2007 :: SWord1 = choose [0:0] s1990
-  s2008 :: SBool = s19 /= s2007
-  s2009 :: SWord8 = s1995 >>> 1
-  s2010 :: SWord8 = s24 | s2009
-  s2011 :: SWord8 = s26 & s2009
-  s2012 :: SWord8 = if s2008 then s2010 else s2011
-  s2013 :: SWord8 = if s29 then s1888 else s180
-  s2014 :: SWord8 = if s170 then s1905 else s2013
-  s2015 :: SWord8 = if s29 then s1910 else s2014
-  s2016 :: SWord8 = if s170 then s1926 else s2015
-  s2017 :: SWord8 = if s29 then s1931 else s2016
-  s2018 :: SWord8 = if s170 then s1947 else s2017
-  s2019 :: SWord8 = if s29 then s1952 else s2018
-  s2020 :: SWord8 = if s170 then s1968 else s2019
-  s2021 :: SWord8 = if s29 then s1973 else s2020
-  s2022 :: SWord8 = if s170 then s1989 else s2021
-  s2023 :: SWord8 = if s29 then s1994 else s2022
-  s2024 :: SWord8 = if s170 then s2012 else s2023
-  s2025 :: SWord8 = s2002 + s2024
-  s2026 :: SBool = s2025 < s2024
-  s2027 :: SBool = s2025 < s2002
-  s2028 :: SBool = s2026 | s2027
-  s2029 :: SWord8 = s2025 >>> 1
-  s2030 :: SWord8 = s24 | s2029
-  s2031 :: SWord8 = s26 & s2029
-  s2032 :: SWord8 = if s2028 then s2030 else s2031
-  s2033 :: SWord8 = if s1998 then s2006 else s2032
-  s2034 :: SWord8 = s1981 + s2022
-  s2035 :: SWord1 = choose [0:0] s2034
-  s2036 :: SBool = s19 /= s2035
-  s2037 :: SWord8 = if s2036 then s1992 else s1993
-  s2038 :: SWord8 = if s22 then s2037 else s1989
-  s2039 :: SWord1 = choose [0:0] s2038
-  s2040 :: SBool = s19 /= s2039
-  s2041 :: SBool = s_2 == s2040
-  s2042 :: SBool = s2034 < s2022
-  s2043 :: SBool = s2034 < s1981
-  s2044 :: SBool = s2042 | s2043
-  s2045 :: SWord8 = s2034 >>> 1
-  s2046 :: SWord8 = s24 | s2045
-  s2047 :: SWord8 = s26 & s2045
-  s2048 :: SWord8 = if s2044 then s2046 else s2047
-  s2049 :: SWord8 = s2048 >>> 1
-  s2050 :: SWord8 = s24 | s2049
-  s2051 :: SWord8 = s26 & s2049
-  s2052 :: SWord8 = if s2040 then s2050 else s2051
-  s2053 :: SWord8 = s2038 >>> 1
-  s2054 :: SWord8 = s24 | s2053
-  s2055 :: SWord8 = s26 & s2053
-  s2056 :: SWord8 = if s2008 then s2054 else s2055
-  s2057 :: SWord8 = if s29 then s2037 else s2022
-  s2058 :: SWord8 = if s170 then s2056 else s2057
-  s2059 :: SWord8 = s2048 + s2058
-  s2060 :: SBool = s2059 < s2058
-  s2061 :: SBool = s2059 < s2048
-  s2062 :: SBool = s2060 | s2061
-  s2063 :: SWord8 = s2059 >>> 1
-  s2064 :: SWord8 = s24 | s2063
-  s2065 :: SWord8 = s26 & s2063
-  s2066 :: SWord8 = if s2062 then s2064 else s2065
-  s2067 :: SWord8 = if s2041 then s2052 else s2066
-  s2068 :: SWord8 = if s1977 then s2033 else s2067
-  s2069 :: SWord8 = s1960 + s2020
-  s2070 :: SWord1 = choose [0:0] s2069
-  s2071 :: SBool = s19 /= s2070
-  s2072 :: SWord8 = if s2071 then s1971 else s1972
-  s2073 :: SWord8 = if s22 then s2072 else s1968
-  s2074 :: SWord1 = choose [0:0] s2073
-  s2075 :: SBool = s19 /= s2074
-  s2076 :: SBool = s_2 == s2075
-  s2077 :: SBool = s2069 < s2020
-  s2078 :: SBool = s2069 < s1960
-  s2079 :: SBool = s2077 | s2078
-  s2080 :: SWord8 = s2069 >>> 1
-  s2081 :: SWord8 = s24 | s2080
-  s2082 :: SWord8 = s26 & s2080
-  s2083 :: SWord8 = if s2079 then s2081 else s2082
-  s2084 :: SWord1 = choose [0:0] s2083
-  s2085 :: SBool = s19 /= s2084
-  s2086 :: SWord8 = s2073 >>> 1
-  s2087 :: SWord8 = s24 | s2086
-  s2088 :: SWord8 = s26 & s2086
-  s2089 :: SWord8 = if s1985 then s2087 else s2088
-  s2090 :: SWord8 = if s22 then s2089 else s2072
-  s2091 :: SWord8 = s2090 >>> 1
-  s2092 :: SWord8 = s24 | s2091
-  s2093 :: SWord8 = s26 & s2091
-  s2094 :: SWord8 = if s2085 then s2092 else s2093
-  s2095 :: SWord8 = if s22 then s2094 else s2089
-  s2096 :: SWord1 = choose [0:0] s2095
-  s2097 :: SBool = s19 /= s2096
-  s2098 :: SBool = s_2 == s2097
-  s2099 :: SWord8 = s2083 >>> 1
-  s2100 :: SWord8 = s24 | s2099
-  s2101 :: SWord8 = s26 & s2099
-  s2102 :: SWord8 = if s2075 then s2100 else s2101
-  s2103 :: SWord8 = s2102 >>> 1
-  s2104 :: SWord8 = s24 | s2103
-  s2105 :: SWord8 = s26 & s2103
-  s2106 :: SWord8 = if s2097 then s2104 else s2105
-  s2107 :: SWord1 = choose [0:0] s2090
-  s2108 :: SBool = s19 /= s2107
-  s2109 :: SWord8 = s2095 >>> 1
-  s2110 :: SWord8 = s24 | s2109
-  s2111 :: SWord8 = s26 & s2109
-  s2112 :: SWord8 = if s2108 then s2110 else s2111
-  s2113 :: SWord8 = if s29 then s2072 else s2020
-  s2114 :: SWord8 = if s170 then s2089 else s2113
-  s2115 :: SWord8 = if s29 then s2094 else s2114
-  s2116 :: SWord8 = if s170 then s2112 else s2115
-  s2117 :: SWord8 = s2102 + s2116
-  s2118 :: SBool = s2117 < s2116
-  s2119 :: SBool = s2117 < s2102
-  s2120 :: SBool = s2118 | s2119
-  s2121 :: SWord8 = s2117 >>> 1
-  s2122 :: SWord8 = s24 | s2121
-  s2123 :: SWord8 = s26 & s2121
-  s2124 :: SWord8 = if s2120 then s2122 else s2123
-  s2125 :: SWord8 = if s2098 then s2106 else s2124
-  s2126 :: SWord8 = s2083 + s2114
-  s2127 :: SWord1 = choose [0:0] s2126
-  s2128 :: SBool = s19 /= s2127
-  s2129 :: SWord8 = if s2128 then s2092 else s2093
-  s2130 :: SWord8 = if s22 then s2129 else s2089
-  s2131 :: SWord1 = choose [0:0] s2130
-  s2132 :: SBool = s19 /= s2131
-  s2133 :: SBool = s_2 == s2132
-  s2134 :: SBool = s2126 < s2114
-  s2135 :: SBool = s2126 < s2083
-  s2136 :: SBool = s2134 | s2135
-  s2137 :: SWord8 = s2126 >>> 1
-  s2138 :: SWord8 = s24 | s2137
-  s2139 :: SWord8 = s26 & s2137
-  s2140 :: SWord8 = if s2136 then s2138 else s2139
-  s2141 :: SWord8 = s2140 >>> 1
-  s2142 :: SWord8 = s24 | s2141
-  s2143 :: SWord8 = s26 & s2141
-  s2144 :: SWord8 = if s2132 then s2142 else s2143
-  s2145 :: SWord8 = s2130 >>> 1
-  s2146 :: SWord8 = s24 | s2145
-  s2147 :: SWord8 = s26 & s2145
-  s2148 :: SWord8 = if s2108 then s2146 else s2147
-  s2149 :: SWord8 = if s29 then s2129 else s2114
-  s2150 :: SWord8 = if s170 then s2148 else s2149
-  s2151 :: SWord8 = s2140 + s2150
-  s2152 :: SBool = s2151 < s2150
-  s2153 :: SBool = s2151 < s2140
-  s2154 :: SBool = s2152 | s2153
-  s2155 :: SWord8 = s2151 >>> 1
-  s2156 :: SWord8 = s24 | s2155
-  s2157 :: SWord8 = s26 & s2155
-  s2158 :: SWord8 = if s2154 then s2156 else s2157
-  s2159 :: SWord8 = if s2133 then s2144 else s2158
-  s2160 :: SWord8 = if s2076 then s2125 else s2159
-  s2161 :: SWord8 = if s1956 then s2068 else s2160
-  s2162 :: SWord8 = s1939 + s2018
-  s2163 :: SWord1 = choose [0:0] s2162
-  s2164 :: SBool = s19 /= s2163
-  s2165 :: SWord8 = if s2164 then s1950 else s1951
-  s2166 :: SWord8 = if s22 then s2165 else s1947
-  s2167 :: SWord1 = choose [0:0] s2166
-  s2168 :: SBool = s19 /= s2167
-  s2169 :: SBool = s_2 == s2168
-  s2170 :: SBool = s2162 < s2018
-  s2171 :: SBool = s2162 < s1939
-  s2172 :: SBool = s2170 | s2171
-  s2173 :: SWord8 = s2162 >>> 1
-  s2174 :: SWord8 = s24 | s2173
-  s2175 :: SWord8 = s26 & s2173
-  s2176 :: SWord8 = if s2172 then s2174 else s2175
-  s2177 :: SWord1 = choose [0:0] s2176
-  s2178 :: SBool = s19 /= s2177
-  s2179 :: SWord8 = s2166 >>> 1
-  s2180 :: SWord8 = s24 | s2179
-  s2181 :: SWord8 = s26 & s2179
-  s2182 :: SWord8 = if s1964 then s2180 else s2181
-  s2183 :: SWord8 = if s22 then s2182 else s2165
-  s2184 :: SWord8 = s2183 >>> 1
-  s2185 :: SWord8 = s24 | s2184
-  s2186 :: SWord8 = s26 & s2184
-  s2187 :: SWord8 = if s2178 then s2185 else s2186
-  s2188 :: SWord8 = if s22 then s2187 else s2182
-  s2189 :: SWord1 = choose [0:0] s2188
-  s2190 :: SBool = s19 /= s2189
-  s2191 :: SBool = s_2 == s2190
-  s2192 :: SWord8 = s2176 >>> 1
-  s2193 :: SWord8 = s24 | s2192
-  s2194 :: SWord8 = s26 & s2192
-  s2195 :: SWord8 = if s2168 then s2193 else s2194
-  s2196 :: SWord1 = choose [0:0] s2195
-  s2197 :: SBool = s19 /= s2196
-  s2198 :: SWord1 = choose [0:0] s2183
-  s2199 :: SBool = s19 /= s2198
-  s2200 :: SWord8 = s2188 >>> 1
-  s2201 :: SWord8 = s24 | s2200
-  s2202 :: SWord8 = s26 & s2200
-  s2203 :: SWord8 = if s2199 then s2201 else s2202
-  s2204 :: SWord8 = if s22 then s2203 else s2187
-  s2205 :: SWord8 = s2204 >>> 1
-  s2206 :: SWord8 = s24 | s2205
-  s2207 :: SWord8 = s26 & s2205
-  s2208 :: SWord8 = if s2197 then s2206 else s2207
-  s2209 :: SWord8 = if s22 then s2208 else s2203
-  s2210 :: SWord1 = choose [0:0] s2209
-  s2211 :: SBool = s19 /= s2210
-  s2212 :: SBool = s_2 == s2211
-  s2213 :: SWord8 = s2195 >>> 1
-  s2214 :: SWord8 = s24 | s2213
-  s2215 :: SWord8 = s26 & s2213
-  s2216 :: SWord8 = if s2190 then s2214 else s2215
-  s2217 :: SWord8 = s2216 >>> 1
-  s2218 :: SWord8 = s24 | s2217
-  s2219 :: SWord8 = s26 & s2217
-  s2220 :: SWord8 = if s2211 then s2218 else s2219
-  s2221 :: SWord1 = choose [0:0] s2204
-  s2222 :: SBool = s19 /= s2221
-  s2223 :: SWord8 = s2209 >>> 1
-  s2224 :: SWord8 = s24 | s2223
-  s2225 :: SWord8 = s26 & s2223
-  s2226 :: SWord8 = if s2222 then s2224 else s2225
-  s2227 :: SWord8 = if s29 then s2165 else s2018
-  s2228 :: SWord8 = if s170 then s2182 else s2227
-  s2229 :: SWord8 = if s29 then s2187 else s2228
-  s2230 :: SWord8 = if s170 then s2203 else s2229
-  s2231 :: SWord8 = if s29 then s2208 else s2230
-  s2232 :: SWord8 = if s170 then s2226 else s2231
-  s2233 :: SWord8 = s2216 + s2232
-  s2234 :: SBool = s2233 < s2232
-  s2235 :: SBool = s2233 < s2216
-  s2236 :: SBool = s2234 | s2235
-  s2237 :: SWord8 = s2233 >>> 1
-  s2238 :: SWord8 = s24 | s2237
-  s2239 :: SWord8 = s26 & s2237
-  s2240 :: SWord8 = if s2236 then s2238 else s2239
-  s2241 :: SWord8 = if s2212 then s2220 else s2240
-  s2242 :: SWord8 = s2195 + s2230
-  s2243 :: SWord1 = choose [0:0] s2242
-  s2244 :: SBool = s19 /= s2243
-  s2245 :: SWord8 = if s2244 then s2206 else s2207
-  s2246 :: SWord8 = if s22 then s2245 else s2203
-  s2247 :: SWord1 = choose [0:0] s2246
-  s2248 :: SBool = s19 /= s2247
-  s2249 :: SBool = s_2 == s2248
-  s2250 :: SBool = s2242 < s2230
-  s2251 :: SBool = s2242 < s2195
-  s2252 :: SBool = s2250 | s2251
-  s2253 :: SWord8 = s2242 >>> 1
-  s2254 :: SWord8 = s24 | s2253
-  s2255 :: SWord8 = s26 & s2253
-  s2256 :: SWord8 = if s2252 then s2254 else s2255
-  s2257 :: SWord8 = s2256 >>> 1
-  s2258 :: SWord8 = s24 | s2257
-  s2259 :: SWord8 = s26 & s2257
-  s2260 :: SWord8 = if s2248 then s2258 else s2259
-  s2261 :: SWord8 = s2246 >>> 1
-  s2262 :: SWord8 = s24 | s2261
-  s2263 :: SWord8 = s26 & s2261
-  s2264 :: SWord8 = if s2222 then s2262 else s2263
-  s2265 :: SWord8 = if s29 then s2245 else s2230
-  s2266 :: SWord8 = if s170 then s2264 else s2265
-  s2267 :: SWord8 = s2256 + s2266
-  s2268 :: SBool = s2267 < s2266
-  s2269 :: SBool = s2267 < s2256
-  s2270 :: SBool = s2268 | s2269
-  s2271 :: SWord8 = s2267 >>> 1
-  s2272 :: SWord8 = s24 | s2271
-  s2273 :: SWord8 = s26 & s2271
-  s2274 :: SWord8 = if s2270 then s2272 else s2273
-  s2275 :: SWord8 = if s2249 then s2260 else s2274
-  s2276 :: SWord8 = if s2191 then s2241 else s2275
-  s2277 :: SWord8 = s2176 + s2228
-  s2278 :: SWord1 = choose [0:0] s2277
-  s2279 :: SBool = s19 /= s2278
-  s2280 :: SWord8 = if s2279 then s2185 else s2186
-  s2281 :: SWord8 = if s22 then s2280 else s2182
-  s2282 :: SWord1 = choose [0:0] s2281
-  s2283 :: SBool = s19 /= s2282
-  s2284 :: SBool = s_2 == s2283
-  s2285 :: SBool = s2277 < s2228
-  s2286 :: SBool = s2277 < s2176
-  s2287 :: SBool = s2285 | s2286
-  s2288 :: SWord8 = s2277 >>> 1
-  s2289 :: SWord8 = s24 | s2288
-  s2290 :: SWord8 = s26 & s2288
-  s2291 :: SWord8 = if s2287 then s2289 else s2290
-  s2292 :: SWord1 = choose [0:0] s2291
-  s2293 :: SBool = s19 /= s2292
-  s2294 :: SWord8 = s2281 >>> 1
-  s2295 :: SWord8 = s24 | s2294
-  s2296 :: SWord8 = s26 & s2294
-  s2297 :: SWord8 = if s2199 then s2295 else s2296
-  s2298 :: SWord8 = if s22 then s2297 else s2280
-  s2299 :: SWord8 = s2298 >>> 1
-  s2300 :: SWord8 = s24 | s2299
-  s2301 :: SWord8 = s26 & s2299
-  s2302 :: SWord8 = if s2293 then s2300 else s2301
-  s2303 :: SWord8 = if s22 then s2302 else s2297
-  s2304 :: SWord1 = choose [0:0] s2303
-  s2305 :: SBool = s19 /= s2304
-  s2306 :: SBool = s_2 == s2305
-  s2307 :: SWord8 = s2291 >>> 1
-  s2308 :: SWord8 = s24 | s2307
-  s2309 :: SWord8 = s26 & s2307
-  s2310 :: SWord8 = if s2283 then s2308 else s2309
-  s2311 :: SWord8 = s2310 >>> 1
-  s2312 :: SWord8 = s24 | s2311
-  s2313 :: SWord8 = s26 & s2311
-  s2314 :: SWord8 = if s2305 then s2312 else s2313
-  s2315 :: SWord1 = choose [0:0] s2298
-  s2316 :: SBool = s19 /= s2315
-  s2317 :: SWord8 = s2303 >>> 1
-  s2318 :: SWord8 = s24 | s2317
-  s2319 :: SWord8 = s26 & s2317
-  s2320 :: SWord8 = if s2316 then s2318 else s2319
-  s2321 :: SWord8 = if s29 then s2280 else s2228
-  s2322 :: SWord8 = if s170 then s2297 else s2321
-  s2323 :: SWord8 = if s29 then s2302 else s2322
-  s2324 :: SWord8 = if s170 then s2320 else s2323
-  s2325 :: SWord8 = s2310 + s2324
-  s2326 :: SBool = s2325 < s2324
-  s2327 :: SBool = s2325 < s2310
-  s2328 :: SBool = s2326 | s2327
-  s2329 :: SWord8 = s2325 >>> 1
-  s2330 :: SWord8 = s24 | s2329
-  s2331 :: SWord8 = s26 & s2329
-  s2332 :: SWord8 = if s2328 then s2330 else s2331
-  s2333 :: SWord8 = if s2306 then s2314 else s2332
-  s2334 :: SWord8 = s2291 + s2322
-  s2335 :: SWord1 = choose [0:0] s2334
-  s2336 :: SBool = s19 /= s2335
-  s2337 :: SWord8 = if s2336 then s2300 else s2301
-  s2338 :: SWord8 = if s22 then s2337 else s2297
-  s2339 :: SWord1 = choose [0:0] s2338
-  s2340 :: SBool = s19 /= s2339
-  s2341 :: SBool = s_2 == s2340
-  s2342 :: SBool = s2334 < s2322
-  s2343 :: SBool = s2334 < s2291
-  s2344 :: SBool = s2342 | s2343
-  s2345 :: SWord8 = s2334 >>> 1
-  s2346 :: SWord8 = s24 | s2345
-  s2347 :: SWord8 = s26 & s2345
-  s2348 :: SWord8 = if s2344 then s2346 else s2347
-  s2349 :: SWord8 = s2348 >>> 1
-  s2350 :: SWord8 = s24 | s2349
-  s2351 :: SWord8 = s26 & s2349
-  s2352 :: SWord8 = if s2340 then s2350 else s2351
-  s2353 :: SWord8 = s2338 >>> 1
-  s2354 :: SWord8 = s24 | s2353
-  s2355 :: SWord8 = s26 & s2353
-  s2356 :: SWord8 = if s2316 then s2354 else s2355
-  s2357 :: SWord8 = if s29 then s2337 else s2322
-  s2358 :: SWord8 = if s170 then s2356 else s2357
-  s2359 :: SWord8 = s2348 + s2358
-  s2360 :: SBool = s2359 < s2358
-  s2361 :: SBool = s2359 < s2348
-  s2362 :: SBool = s2360 | s2361
-  s2363 :: SWord8 = s2359 >>> 1
-  s2364 :: SWord8 = s24 | s2363
-  s2365 :: SWord8 = s26 & s2363
-  s2366 :: SWord8 = if s2362 then s2364 else s2365
-  s2367 :: SWord8 = if s2341 then s2352 else s2366
-  s2368 :: SWord8 = if s2284 then s2333 else s2367
-  s2369 :: SWord8 = if s2169 then s2276 else s2368
-  s2370 :: SWord8 = if s1935 then s2161 else s2369
-  s2371 :: SWord8 = s1918 + s2016
-  s2372 :: SWord1 = choose [0:0] s2371
-  s2373 :: SBool = s19 /= s2372
-  s2374 :: SWord8 = if s2373 then s1929 else s1930
-  s2375 :: SWord8 = if s22 then s2374 else s1926
-  s2376 :: SWord1 = choose [0:0] s2375
-  s2377 :: SBool = s19 /= s2376
-  s2378 :: SBool = s_2 == s2377
-  s2379 :: SBool = s2371 < s2016
-  s2380 :: SBool = s2371 < s1918
-  s2381 :: SBool = s2379 | s2380
-  s2382 :: SWord8 = s2371 >>> 1
-  s2383 :: SWord8 = s24 | s2382
-  s2384 :: SWord8 = s26 & s2382
-  s2385 :: SWord8 = if s2381 then s2383 else s2384
-  s2386 :: SWord1 = choose [0:0] s2385
-  s2387 :: SBool = s19 /= s2386
-  s2388 :: SWord8 = s2375 >>> 1
-  s2389 :: SWord8 = s24 | s2388
-  s2390 :: SWord8 = s26 & s2388
-  s2391 :: SWord8 = if s1943 then s2389 else s2390
-  s2392 :: SWord8 = if s22 then s2391 else s2374
-  s2393 :: SWord8 = s2392 >>> 1
-  s2394 :: SWord8 = s24 | s2393
-  s2395 :: SWord8 = s26 & s2393
-  s2396 :: SWord8 = if s2387 then s2394 else s2395
-  s2397 :: SWord8 = if s22 then s2396 else s2391
-  s2398 :: SWord1 = choose [0:0] s2397
-  s2399 :: SBool = s19 /= s2398
-  s2400 :: SBool = s_2 == s2399
-  s2401 :: SWord8 = s2385 >>> 1
-  s2402 :: SWord8 = s24 | s2401
-  s2403 :: SWord8 = s26 & s2401
-  s2404 :: SWord8 = if s2377 then s2402 else s2403
-  s2405 :: SWord1 = choose [0:0] s2404
-  s2406 :: SBool = s19 /= s2405
-  s2407 :: SWord1 = choose [0:0] s2392
-  s2408 :: SBool = s19 /= s2407
-  s2409 :: SWord8 = s2397 >>> 1
-  s2410 :: SWord8 = s24 | s2409
-  s2411 :: SWord8 = s26 & s2409
-  s2412 :: SWord8 = if s2408 then s2410 else s2411
-  s2413 :: SWord8 = if s22 then s2412 else s2396
-  s2414 :: SWord8 = s2413 >>> 1
-  s2415 :: SWord8 = s24 | s2414
-  s2416 :: SWord8 = s26 & s2414
-  s2417 :: SWord8 = if s2406 then s2415 else s2416
-  s2418 :: SWord8 = if s22 then s2417 else s2412
-  s2419 :: SWord1 = choose [0:0] s2418
-  s2420 :: SBool = s19 /= s2419
-  s2421 :: SBool = s_2 == s2420
-  s2422 :: SWord8 = s2404 >>> 1
-  s2423 :: SWord8 = s24 | s2422
-  s2424 :: SWord8 = s26 & s2422
-  s2425 :: SWord8 = if s2399 then s2423 else s2424
-  s2426 :: SWord1 = choose [0:0] s2425
-  s2427 :: SBool = s19 /= s2426
-  s2428 :: SWord1 = choose [0:0] s2413
-  s2429 :: SBool = s19 /= s2428
-  s2430 :: SWord8 = s2418 >>> 1
-  s2431 :: SWord8 = s24 | s2430
-  s2432 :: SWord8 = s26 & s2430
-  s2433 :: SWord8 = if s2429 then s2431 else s2432
-  s2434 :: SWord8 = if s22 then s2433 else s2417
-  s2435 :: SWord8 = s2434 >>> 1
-  s2436 :: SWord8 = s24 | s2435
-  s2437 :: SWord8 = s26 & s2435
-  s2438 :: SWord8 = if s2427 then s2436 else s2437
-  s2439 :: SWord8 = if s22 then s2438 else s2433
-  s2440 :: SWord1 = choose [0:0] s2439
-  s2441 :: SBool = s19 /= s2440
-  s2442 :: SBool = s_2 == s2441
-  s2443 :: SWord8 = s2425 >>> 1
-  s2444 :: SWord8 = s24 | s2443
-  s2445 :: SWord8 = s26 & s2443
-  s2446 :: SWord8 = if s2420 then s2444 else s2445
-  s2447 :: SWord8 = s2446 >>> 1
-  s2448 :: SWord8 = s24 | s2447
-  s2449 :: SWord8 = s26 & s2447
-  s2450 :: SWord8 = if s2441 then s2448 else s2449
-  s2451 :: SWord1 = choose [0:0] s2434
-  s2452 :: SBool = s19 /= s2451
-  s2453 :: SWord8 = s2439 >>> 1
-  s2454 :: SWord8 = s24 | s2453
-  s2455 :: SWord8 = s26 & s2453
-  s2456 :: SWord8 = if s2452 then s2454 else s2455
-  s2457 :: SWord8 = if s29 then s2374 else s2016
-  s2458 :: SWord8 = if s170 then s2391 else s2457
-  s2459 :: SWord8 = if s29 then s2396 else s2458
-  s2460 :: SWord8 = if s170 then s2412 else s2459
-  s2461 :: SWord8 = if s29 then s2417 else s2460
-  s2462 :: SWord8 = if s170 then s2433 else s2461
-  s2463 :: SWord8 = if s29 then s2438 else s2462
-  s2464 :: SWord8 = if s170 then s2456 else s2463
-  s2465 :: SWord8 = s2446 + s2464
-  s2466 :: SBool = s2465 < s2464
-  s2467 :: SBool = s2465 < s2446
-  s2468 :: SBool = s2466 | s2467
-  s2469 :: SWord8 = s2465 >>> 1
-  s2470 :: SWord8 = s24 | s2469
-  s2471 :: SWord8 = s26 & s2469
-  s2472 :: SWord8 = if s2468 then s2470 else s2471
-  s2473 :: SWord8 = if s2442 then s2450 else s2472
-  s2474 :: SWord8 = s2425 + s2462
-  s2475 :: SWord1 = choose [0:0] s2474
-  s2476 :: SBool = s19 /= s2475
-  s2477 :: SWord8 = if s2476 then s2436 else s2437
-  s2478 :: SWord8 = if s22 then s2477 else s2433
-  s2479 :: SWord1 = choose [0:0] s2478
-  s2480 :: SBool = s19 /= s2479
-  s2481 :: SBool = s_2 == s2480
-  s2482 :: SBool = s2474 < s2462
-  s2483 :: SBool = s2474 < s2425
-  s2484 :: SBool = s2482 | s2483
-  s2485 :: SWord8 = s2474 >>> 1
-  s2486 :: SWord8 = s24 | s2485
-  s2487 :: SWord8 = s26 & s2485
-  s2488 :: SWord8 = if s2484 then s2486 else s2487
-  s2489 :: SWord8 = s2488 >>> 1
-  s2490 :: SWord8 = s24 | s2489
-  s2491 :: SWord8 = s26 & s2489
-  s2492 :: SWord8 = if s2480 then s2490 else s2491
-  s2493 :: SWord8 = s2478 >>> 1
-  s2494 :: SWord8 = s24 | s2493
-  s2495 :: SWord8 = s26 & s2493
-  s2496 :: SWord8 = if s2452 then s2494 else s2495
-  s2497 :: SWord8 = if s29 then s2477 else s2462
-  s2498 :: SWord8 = if s170 then s2496 else s2497
-  s2499 :: SWord8 = s2488 + s2498
-  s2500 :: SBool = s2499 < s2498
-  s2501 :: SBool = s2499 < s2488
-  s2502 :: SBool = s2500 | s2501
-  s2503 :: SWord8 = s2499 >>> 1
-  s2504 :: SWord8 = s24 | s2503
-  s2505 :: SWord8 = s26 & s2503
-  s2506 :: SWord8 = if s2502 then s2504 else s2505
-  s2507 :: SWord8 = if s2481 then s2492 else s2506
-  s2508 :: SWord8 = if s2421 then s2473 else s2507
-  s2509 :: SWord8 = s2404 + s2460
-  s2510 :: SWord1 = choose [0:0] s2509
-  s2511 :: SBool = s19 /= s2510
-  s2512 :: SWord8 = if s2511 then s2415 else s2416
-  s2513 :: SWord8 = if s22 then s2512 else s2412
-  s2514 :: SWord1 = choose [0:0] s2513
-  s2515 :: SBool = s19 /= s2514
-  s2516 :: SBool = s_2 == s2515
-  s2517 :: SBool = s2509 < s2460
-  s2518 :: SBool = s2509 < s2404
-  s2519 :: SBool = s2517 | s2518
-  s2520 :: SWord8 = s2509 >>> 1
-  s2521 :: SWord8 = s24 | s2520
-  s2522 :: SWord8 = s26 & s2520
-  s2523 :: SWord8 = if s2519 then s2521 else s2522
-  s2524 :: SWord1 = choose [0:0] s2523
-  s2525 :: SBool = s19 /= s2524
-  s2526 :: SWord8 = s2513 >>> 1
-  s2527 :: SWord8 = s24 | s2526
-  s2528 :: SWord8 = s26 & s2526
-  s2529 :: SWord8 = if s2429 then s2527 else s2528
-  s2530 :: SWord8 = if s22 then s2529 else s2512
-  s2531 :: SWord8 = s2530 >>> 1
-  s2532 :: SWord8 = s24 | s2531
-  s2533 :: SWord8 = s26 & s2531
-  s2534 :: SWord8 = if s2525 then s2532 else s2533
-  s2535 :: SWord8 = if s22 then s2534 else s2529
-  s2536 :: SWord1 = choose [0:0] s2535
-  s2537 :: SBool = s19 /= s2536
-  s2538 :: SBool = s_2 == s2537
-  s2539 :: SWord8 = s2523 >>> 1
-  s2540 :: SWord8 = s24 | s2539
-  s2541 :: SWord8 = s26 & s2539
-  s2542 :: SWord8 = if s2515 then s2540 else s2541
-  s2543 :: SWord8 = s2542 >>> 1
-  s2544 :: SWord8 = s24 | s2543
-  s2545 :: SWord8 = s26 & s2543
-  s2546 :: SWord8 = if s2537 then s2544 else s2545
-  s2547 :: SWord1 = choose [0:0] s2530
-  s2548 :: SBool = s19 /= s2547
-  s2549 :: SWord8 = s2535 >>> 1
-  s2550 :: SWord8 = s24 | s2549
-  s2551 :: SWord8 = s26 & s2549
-  s2552 :: SWord8 = if s2548 then s2550 else s2551
-  s2553 :: SWord8 = if s29 then s2512 else s2460
-  s2554 :: SWord8 = if s170 then s2529 else s2553
-  s2555 :: SWord8 = if s29 then s2534 else s2554
-  s2556 :: SWord8 = if s170 then s2552 else s2555
-  s2557 :: SWord8 = s2542 + s2556
-  s2558 :: SBool = s2557 < s2556
-  s2559 :: SBool = s2557 < s2542
-  s2560 :: SBool = s2558 | s2559
-  s2561 :: SWord8 = s2557 >>> 1
-  s2562 :: SWord8 = s24 | s2561
-  s2563 :: SWord8 = s26 & s2561
-  s2564 :: SWord8 = if s2560 then s2562 else s2563
-  s2565 :: SWord8 = if s2538 then s2546 else s2564
-  s2566 :: SWord8 = s2523 + s2554
-  s2567 :: SWord1 = choose [0:0] s2566
-  s2568 :: SBool = s19 /= s2567
-  s2569 :: SWord8 = if s2568 then s2532 else s2533
-  s2570 :: SWord8 = if s22 then s2569 else s2529
-  s2571 :: SWord1 = choose [0:0] s2570
-  s2572 :: SBool = s19 /= s2571
-  s2573 :: SBool = s_2 == s2572
-  s2574 :: SBool = s2566 < s2554
-  s2575 :: SBool = s2566 < s2523
-  s2576 :: SBool = s2574 | s2575
-  s2577 :: SWord8 = s2566 >>> 1
-  s2578 :: SWord8 = s24 | s2577
-  s2579 :: SWord8 = s26 & s2577
-  s2580 :: SWord8 = if s2576 then s2578 else s2579
-  s2581 :: SWord8 = s2580 >>> 1
-  s2582 :: SWord8 = s24 | s2581
-  s2583 :: SWord8 = s26 & s2581
-  s2584 :: SWord8 = if s2572 then s2582 else s2583
-  s2585 :: SWord8 = s2570 >>> 1
-  s2586 :: SWord8 = s24 | s2585
-  s2587 :: SWord8 = s26 & s2585
-  s2588 :: SWord8 = if s2548 then s2586 else s2587
-  s2589 :: SWord8 = if s29 then s2569 else s2554
-  s2590 :: SWord8 = if s170 then s2588 else s2589
-  s2591 :: SWord8 = s2580 + s2590
-  s2592 :: SBool = s2591 < s2590
-  s2593 :: SBool = s2591 < s2580
-  s2594 :: SBool = s2592 | s2593
-  s2595 :: SWord8 = s2591 >>> 1
-  s2596 :: SWord8 = s24 | s2595
-  s2597 :: SWord8 = s26 & s2595
-  s2598 :: SWord8 = if s2594 then s2596 else s2597
-  s2599 :: SWord8 = if s2573 then s2584 else s2598
-  s2600 :: SWord8 = if s2516 then s2565 else s2599
-  s2601 :: SWord8 = if s2400 then s2508 else s2600
-  s2602 :: SWord8 = s2385 + s2458
-  s2603 :: SWord1 = choose [0:0] s2602
-  s2604 :: SBool = s19 /= s2603
-  s2605 :: SWord8 = if s2604 then s2394 else s2395
-  s2606 :: SWord8 = if s22 then s2605 else s2391
-  s2607 :: SWord1 = choose [0:0] s2606
-  s2608 :: SBool = s19 /= s2607
-  s2609 :: SBool = s_2 == s2608
-  s2610 :: SBool = s2602 < s2458
-  s2611 :: SBool = s2602 < s2385
-  s2612 :: SBool = s2610 | s2611
-  s2613 :: SWord8 = s2602 >>> 1
-  s2614 :: SWord8 = s24 | s2613
-  s2615 :: SWord8 = s26 & s2613
-  s2616 :: SWord8 = if s2612 then s2614 else s2615
-  s2617 :: SWord1 = choose [0:0] s2616
-  s2618 :: SBool = s19 /= s2617
-  s2619 :: SWord8 = s2606 >>> 1
-  s2620 :: SWord8 = s24 | s2619
-  s2621 :: SWord8 = s26 & s2619
-  s2622 :: SWord8 = if s2408 then s2620 else s2621
-  s2623 :: SWord8 = if s22 then s2622 else s2605
-  s2624 :: SWord8 = s2623 >>> 1
-  s2625 :: SWord8 = s24 | s2624
-  s2626 :: SWord8 = s26 & s2624
-  s2627 :: SWord8 = if s2618 then s2625 else s2626
-  s2628 :: SWord8 = if s22 then s2627 else s2622
-  s2629 :: SWord1 = choose [0:0] s2628
-  s2630 :: SBool = s19 /= s2629
-  s2631 :: SBool = s_2 == s2630
-  s2632 :: SWord8 = s2616 >>> 1
-  s2633 :: SWord8 = s24 | s2632
-  s2634 :: SWord8 = s26 & s2632
-  s2635 :: SWord8 = if s2608 then s2633 else s2634
-  s2636 :: SWord1 = choose [0:0] s2635
-  s2637 :: SBool = s19 /= s2636
-  s2638 :: SWord1 = choose [0:0] s2623
-  s2639 :: SBool = s19 /= s2638
-  s2640 :: SWord8 = s2628 >>> 1
-  s2641 :: SWord8 = s24 | s2640
-  s2642 :: SWord8 = s26 & s2640
-  s2643 :: SWord8 = if s2639 then s2641 else s2642
-  s2644 :: SWord8 = if s22 then s2643 else s2627
-  s2645 :: SWord8 = s2644 >>> 1
-  s2646 :: SWord8 = s24 | s2645
-  s2647 :: SWord8 = s26 & s2645
-  s2648 :: SWord8 = if s2637 then s2646 else s2647
-  s2649 :: SWord8 = if s22 then s2648 else s2643
-  s2650 :: SWord1 = choose [0:0] s2649
-  s2651 :: SBool = s19 /= s2650
-  s2652 :: SBool = s_2 == s2651
-  s2653 :: SWord8 = s2635 >>> 1
-  s2654 :: SWord8 = s24 | s2653
-  s2655 :: SWord8 = s26 & s2653
-  s2656 :: SWord8 = if s2630 then s2654 else s2655
-  s2657 :: SWord8 = s2656 >>> 1
-  s2658 :: SWord8 = s24 | s2657
-  s2659 :: SWord8 = s26 & s2657
-  s2660 :: SWord8 = if s2651 then s2658 else s2659
-  s2661 :: SWord1 = choose [0:0] s2644
-  s2662 :: SBool = s19 /= s2661
-  s2663 :: SWord8 = s2649 >>> 1
-  s2664 :: SWord8 = s24 | s2663
-  s2665 :: SWord8 = s26 & s2663
-  s2666 :: SWord8 = if s2662 then s2664 else s2665
-  s2667 :: SWord8 = if s29 then s2605 else s2458
-  s2668 :: SWord8 = if s170 then s2622 else s2667
-  s2669 :: SWord8 = if s29 then s2627 else s2668
-  s2670 :: SWord8 = if s170 then s2643 else s2669
-  s2671 :: SWord8 = if s29 then s2648 else s2670
-  s2672 :: SWord8 = if s170 then s2666 else s2671
-  s2673 :: SWord8 = s2656 + s2672
-  s2674 :: SBool = s2673 < s2672
-  s2675 :: SBool = s2673 < s2656
-  s2676 :: SBool = s2674 | s2675
-  s2677 :: SWord8 = s2673 >>> 1
-  s2678 :: SWord8 = s24 | s2677
-  s2679 :: SWord8 = s26 & s2677
-  s2680 :: SWord8 = if s2676 then s2678 else s2679
-  s2681 :: SWord8 = if s2652 then s2660 else s2680
-  s2682 :: SWord8 = s2635 + s2670
-  s2683 :: SWord1 = choose [0:0] s2682
-  s2684 :: SBool = s19 /= s2683
-  s2685 :: SWord8 = if s2684 then s2646 else s2647
-  s2686 :: SWord8 = if s22 then s2685 else s2643
-  s2687 :: SWord1 = choose [0:0] s2686
-  s2688 :: SBool = s19 /= s2687
-  s2689 :: SBool = s_2 == s2688
-  s2690 :: SBool = s2682 < s2670
-  s2691 :: SBool = s2682 < s2635
-  s2692 :: SBool = s2690 | s2691
-  s2693 :: SWord8 = s2682 >>> 1
-  s2694 :: SWord8 = s24 | s2693
-  s2695 :: SWord8 = s26 & s2693
-  s2696 :: SWord8 = if s2692 then s2694 else s2695
-  s2697 :: SWord8 = s2696 >>> 1
-  s2698 :: SWord8 = s24 | s2697
-  s2699 :: SWord8 = s26 & s2697
-  s2700 :: SWord8 = if s2688 then s2698 else s2699
-  s2701 :: SWord8 = s2686 >>> 1
-  s2702 :: SWord8 = s24 | s2701
-  s2703 :: SWord8 = s26 & s2701
-  s2704 :: SWord8 = if s2662 then s2702 else s2703
-  s2705 :: SWord8 = if s29 then s2685 else s2670
-  s2706 :: SWord8 = if s170 then s2704 else s2705
-  s2707 :: SWord8 = s2696 + s2706
-  s2708 :: SBool = s2707 < s2706
-  s2709 :: SBool = s2707 < s2696
-  s2710 :: SBool = s2708 | s2709
-  s2711 :: SWord8 = s2707 >>> 1
-  s2712 :: SWord8 = s24 | s2711
-  s2713 :: SWord8 = s26 & s2711
-  s2714 :: SWord8 = if s2710 then s2712 else s2713
-  s2715 :: SWord8 = if s2689 then s2700 else s2714
-  s2716 :: SWord8 = if s2631 then s2681 else s2715
-  s2717 :: SWord8 = s2616 + s2668
-  s2718 :: SWord1 = choose [0:0] s2717
-  s2719 :: SBool = s19 /= s2718
-  s2720 :: SWord8 = if s2719 then s2625 else s2626
-  s2721 :: SWord8 = if s22 then s2720 else s2622
-  s2722 :: SWord1 = choose [0:0] s2721
-  s2723 :: SBool = s19 /= s2722
-  s2724 :: SBool = s_2 == s2723
-  s2725 :: SBool = s2717 < s2668
-  s2726 :: SBool = s2717 < s2616
-  s2727 :: SBool = s2725 | s2726
-  s2728 :: SWord8 = s2717 >>> 1
-  s2729 :: SWord8 = s24 | s2728
-  s2730 :: SWord8 = s26 & s2728
-  s2731 :: SWord8 = if s2727 then s2729 else s2730
-  s2732 :: SWord1 = choose [0:0] s2731
-  s2733 :: SBool = s19 /= s2732
-  s2734 :: SWord8 = s2721 >>> 1
-  s2735 :: SWord8 = s24 | s2734
-  s2736 :: SWord8 = s26 & s2734
-  s2737 :: SWord8 = if s2639 then s2735 else s2736
-  s2738 :: SWord8 = if s22 then s2737 else s2720
-  s2739 :: SWord8 = s2738 >>> 1
-  s2740 :: SWord8 = s24 | s2739
-  s2741 :: SWord8 = s26 & s2739
-  s2742 :: SWord8 = if s2733 then s2740 else s2741
-  s2743 :: SWord8 = if s22 then s2742 else s2737
-  s2744 :: SWord1 = choose [0:0] s2743
-  s2745 :: SBool = s19 /= s2744
-  s2746 :: SBool = s_2 == s2745
-  s2747 :: SWord8 = s2731 >>> 1
-  s2748 :: SWord8 = s24 | s2747
-  s2749 :: SWord8 = s26 & s2747
-  s2750 :: SWord8 = if s2723 then s2748 else s2749
-  s2751 :: SWord8 = s2750 >>> 1
-  s2752 :: SWord8 = s24 | s2751
-  s2753 :: SWord8 = s26 & s2751
-  s2754 :: SWord8 = if s2745 then s2752 else s2753
-  s2755 :: SWord1 = choose [0:0] s2738
-  s2756 :: SBool = s19 /= s2755
-  s2757 :: SWord8 = s2743 >>> 1
-  s2758 :: SWord8 = s24 | s2757
-  s2759 :: SWord8 = s26 & s2757
-  s2760 :: SWord8 = if s2756 then s2758 else s2759
-  s2761 :: SWord8 = if s29 then s2720 else s2668
-  s2762 :: SWord8 = if s170 then s2737 else s2761
-  s2763 :: SWord8 = if s29 then s2742 else s2762
-  s2764 :: SWord8 = if s170 then s2760 else s2763
-  s2765 :: SWord8 = s2750 + s2764
-  s2766 :: SBool = s2765 < s2764
-  s2767 :: SBool = s2765 < s2750
-  s2768 :: SBool = s2766 | s2767
-  s2769 :: SWord8 = s2765 >>> 1
-  s2770 :: SWord8 = s24 | s2769
-  s2771 :: SWord8 = s26 & s2769
-  s2772 :: SWord8 = if s2768 then s2770 else s2771
-  s2773 :: SWord8 = if s2746 then s2754 else s2772
-  s2774 :: SWord8 = s2731 + s2762
-  s2775 :: SWord1 = choose [0:0] s2774
-  s2776 :: SBool = s19 /= s2775
-  s2777 :: SWord8 = if s2776 then s2740 else s2741
-  s2778 :: SWord8 = if s22 then s2777 else s2737
-  s2779 :: SWord1 = choose [0:0] s2778
-  s2780 :: SBool = s19 /= s2779
-  s2781 :: SBool = s_2 == s2780
-  s2782 :: SBool = s2774 < s2762
-  s2783 :: SBool = s2774 < s2731
-  s2784 :: SBool = s2782 | s2783
-  s2785 :: SWord8 = s2774 >>> 1
-  s2786 :: SWord8 = s24 | s2785
-  s2787 :: SWord8 = s26 & s2785
-  s2788 :: SWord8 = if s2784 then s2786 else s2787
-  s2789 :: SWord8 = s2788 >>> 1
-  s2790 :: SWord8 = s24 | s2789
-  s2791 :: SWord8 = s26 & s2789
-  s2792 :: SWord8 = if s2780 then s2790 else s2791
-  s2793 :: SWord8 = s2778 >>> 1
-  s2794 :: SWord8 = s24 | s2793
-  s2795 :: SWord8 = s26 & s2793
-  s2796 :: SWord8 = if s2756 then s2794 else s2795
-  s2797 :: SWord8 = if s29 then s2777 else s2762
-  s2798 :: SWord8 = if s170 then s2796 else s2797
-  s2799 :: SWord8 = s2788 + s2798
-  s2800 :: SBool = s2799 < s2798
-  s2801 :: SBool = s2799 < s2788
-  s2802 :: SBool = s2800 | s2801
-  s2803 :: SWord8 = s2799 >>> 1
-  s2804 :: SWord8 = s24 | s2803
-  s2805 :: SWord8 = s26 & s2803
-  s2806 :: SWord8 = if s2802 then s2804 else s2805
-  s2807 :: SWord8 = if s2781 then s2792 else s2806
-  s2808 :: SWord8 = if s2724 then s2773 else s2807
-  s2809 :: SWord8 = if s2609 then s2716 else s2808
-  s2810 :: SWord8 = if s2378 then s2601 else s2809
-  s2811 :: SWord8 = if s1914 then s2370 else s2810
-  s2812 :: SWord8 = s1899 + s2014
-  s2813 :: SWord1 = choose [0:0] s2812
-  s2814 :: SBool = s19 /= s2813
-  s2815 :: SWord8 = if s2814 then s1908 else s1909
-  s2816 :: SWord8 = if s22 then s2815 else s1905
-  s2817 :: SWord1 = choose [0:0] s2816
-  s2818 :: SBool = s19 /= s2817
-  s2819 :: SBool = s_2 == s2818
-  s2820 :: SBool = s2812 < s2014
-  s2821 :: SBool = s2812 < s1899
-  s2822 :: SBool = s2820 | s2821
-  s2823 :: SWord8 = s2812 >>> 1
-  s2824 :: SWord8 = s24 | s2823
-  s2825 :: SWord8 = s26 & s2823
-  s2826 :: SWord8 = if s2822 then s2824 else s2825
-  s2827 :: SWord1 = choose [0:0] s2826
-  s2828 :: SBool = s19 /= s2827
-  s2829 :: SWord8 = s2816 >>> 1
-  s2830 :: SWord8 = s24 | s2829
-  s2831 :: SWord8 = s26 & s2829
-  s2832 :: SWord8 = if s1922 then s2830 else s2831
-  s2833 :: SWord8 = if s22 then s2832 else s2815
-  s2834 :: SWord8 = s2833 >>> 1
-  s2835 :: SWord8 = s24 | s2834
-  s2836 :: SWord8 = s26 & s2834
-  s2837 :: SWord8 = if s2828 then s2835 else s2836
-  s2838 :: SWord8 = if s22 then s2837 else s2832
-  s2839 :: SWord1 = choose [0:0] s2838
-  s2840 :: SBool = s19 /= s2839
-  s2841 :: SBool = s_2 == s2840
-  s2842 :: SWord8 = s2826 >>> 1
-  s2843 :: SWord8 = s24 | s2842
-  s2844 :: SWord8 = s26 & s2842
-  s2845 :: SWord8 = if s2818 then s2843 else s2844
-  s2846 :: SWord1 = choose [0:0] s2845
-  s2847 :: SBool = s19 /= s2846
-  s2848 :: SWord1 = choose [0:0] s2833
-  s2849 :: SBool = s19 /= s2848
-  s2850 :: SWord8 = s2838 >>> 1
-  s2851 :: SWord8 = s24 | s2850
-  s2852 :: SWord8 = s26 & s2850
-  s2853 :: SWord8 = if s2849 then s2851 else s2852
-  s2854 :: SWord8 = if s22 then s2853 else s2837
-  s2855 :: SWord8 = s2854 >>> 1
-  s2856 :: SWord8 = s24 | s2855
-  s2857 :: SWord8 = s26 & s2855
-  s2858 :: SWord8 = if s2847 then s2856 else s2857
-  s2859 :: SWord8 = if s22 then s2858 else s2853
-  s2860 :: SWord1 = choose [0:0] s2859
-  s2861 :: SBool = s19 /= s2860
-  s2862 :: SBool = s_2 == s2861
-  s2863 :: SWord8 = s2845 >>> 1
-  s2864 :: SWord8 = s24 | s2863
-  s2865 :: SWord8 = s26 & s2863
-  s2866 :: SWord8 = if s2840 then s2864 else s2865
-  s2867 :: SWord1 = choose [0:0] s2866
-  s2868 :: SBool = s19 /= s2867
-  s2869 :: SWord1 = choose [0:0] s2854
-  s2870 :: SBool = s19 /= s2869
-  s2871 :: SWord8 = s2859 >>> 1
-  s2872 :: SWord8 = s24 | s2871
-  s2873 :: SWord8 = s26 & s2871
-  s2874 :: SWord8 = if s2870 then s2872 else s2873
-  s2875 :: SWord8 = if s22 then s2874 else s2858
-  s2876 :: SWord8 = s2875 >>> 1
-  s2877 :: SWord8 = s24 | s2876
-  s2878 :: SWord8 = s26 & s2876
-  s2879 :: SWord8 = if s2868 then s2877 else s2878
-  s2880 :: SWord8 = if s22 then s2879 else s2874
-  s2881 :: SWord1 = choose [0:0] s2880
-  s2882 :: SBool = s19 /= s2881
-  s2883 :: SBool = s_2 == s2882
-  s2884 :: SWord8 = s2866 >>> 1
-  s2885 :: SWord8 = s24 | s2884
-  s2886 :: SWord8 = s26 & s2884
-  s2887 :: SWord8 = if s2861 then s2885 else s2886
-  s2888 :: SWord1 = choose [0:0] s2887
-  s2889 :: SBool = s19 /= s2888
-  s2890 :: SWord1 = choose [0:0] s2875
-  s2891 :: SBool = s19 /= s2890
-  s2892 :: SWord8 = s2880 >>> 1
-  s2893 :: SWord8 = s24 | s2892
-  s2894 :: SWord8 = s26 & s2892
-  s2895 :: SWord8 = if s2891 then s2893 else s2894
-  s2896 :: SWord8 = if s22 then s2895 else s2879
-  s2897 :: SWord8 = s2896 >>> 1
-  s2898 :: SWord8 = s24 | s2897
-  s2899 :: SWord8 = s26 & s2897
-  s2900 :: SWord8 = if s2889 then s2898 else s2899
-  s2901 :: SWord8 = if s22 then s2900 else s2895
-  s2902 :: SWord1 = choose [0:0] s2901
-  s2903 :: SBool = s19 /= s2902
-  s2904 :: SBool = s_2 == s2903
-  s2905 :: SWord8 = s2887 >>> 1
-  s2906 :: SWord8 = s24 | s2905
-  s2907 :: SWord8 = s26 & s2905
-  s2908 :: SWord8 = if s2882 then s2906 else s2907
-  s2909 :: SWord8 = s2908 >>> 1
-  s2910 :: SWord8 = s24 | s2909
-  s2911 :: SWord8 = s26 & s2909
-  s2912 :: SWord8 = if s2903 then s2910 else s2911
-  s2913 :: SWord1 = choose [0:0] s2896
-  s2914 :: SBool = s19 /= s2913
-  s2915 :: SWord8 = s2901 >>> 1
-  s2916 :: SWord8 = s24 | s2915
-  s2917 :: SWord8 = s26 & s2915
-  s2918 :: SWord8 = if s2914 then s2916 else s2917
-  s2919 :: SWord8 = if s29 then s2815 else s2014
-  s2920 :: SWord8 = if s170 then s2832 else s2919
-  s2921 :: SWord8 = if s29 then s2837 else s2920
-  s2922 :: SWord8 = if s170 then s2853 else s2921
-  s2923 :: SWord8 = if s29 then s2858 else s2922
-  s2924 :: SWord8 = if s170 then s2874 else s2923
-  s2925 :: SWord8 = if s29 then s2879 else s2924
-  s2926 :: SWord8 = if s170 then s2895 else s2925
-  s2927 :: SWord8 = if s29 then s2900 else s2926
-  s2928 :: SWord8 = if s170 then s2918 else s2927
-  s2929 :: SWord8 = s2908 + s2928
-  s2930 :: SBool = s2929 < s2928
-  s2931 :: SBool = s2929 < s2908
-  s2932 :: SBool = s2930 | s2931
-  s2933 :: SWord8 = s2929 >>> 1
-  s2934 :: SWord8 = s24 | s2933
-  s2935 :: SWord8 = s26 & s2933
-  s2936 :: SWord8 = if s2932 then s2934 else s2935
-  s2937 :: SWord8 = if s2904 then s2912 else s2936
-  s2938 :: SWord8 = s2887 + s2926
-  s2939 :: SWord1 = choose [0:0] s2938
-  s2940 :: SBool = s19 /= s2939
-  s2941 :: SWord8 = if s2940 then s2898 else s2899
-  s2942 :: SWord8 = if s22 then s2941 else s2895
-  s2943 :: SWord1 = choose [0:0] s2942
-  s2944 :: SBool = s19 /= s2943
-  s2945 :: SBool = s_2 == s2944
-  s2946 :: SBool = s2938 < s2926
-  s2947 :: SBool = s2938 < s2887
-  s2948 :: SBool = s2946 | s2947
-  s2949 :: SWord8 = s2938 >>> 1
-  s2950 :: SWord8 = s24 | s2949
-  s2951 :: SWord8 = s26 & s2949
-  s2952 :: SWord8 = if s2948 then s2950 else s2951
-  s2953 :: SWord8 = s2952 >>> 1
-  s2954 :: SWord8 = s24 | s2953
-  s2955 :: SWord8 = s26 & s2953
-  s2956 :: SWord8 = if s2944 then s2954 else s2955
-  s2957 :: SWord8 = s2942 >>> 1
-  s2958 :: SWord8 = s24 | s2957
-  s2959 :: SWord8 = s26 & s2957
-  s2960 :: SWord8 = if s2914 then s2958 else s2959
-  s2961 :: SWord8 = if s29 then s2941 else s2926
-  s2962 :: SWord8 = if s170 then s2960 else s2961
-  s2963 :: SWord8 = s2952 + s2962
-  s2964 :: SBool = s2963 < s2962
-  s2965 :: SBool = s2963 < s2952
-  s2966 :: SBool = s2964 | s2965
-  s2967 :: SWord8 = s2963 >>> 1
-  s2968 :: SWord8 = s24 | s2967
-  s2969 :: SWord8 = s26 & s2967
-  s2970 :: SWord8 = if s2966 then s2968 else s2969
-  s2971 :: SWord8 = if s2945 then s2956 else s2970
-  s2972 :: SWord8 = if s2883 then s2937 else s2971
-  s2973 :: SWord8 = s2866 + s2924
-  s2974 :: SWord1 = choose [0:0] s2973
-  s2975 :: SBool = s19 /= s2974
-  s2976 :: SWord8 = if s2975 then s2877 else s2878
-  s2977 :: SWord8 = if s22 then s2976 else s2874
-  s2978 :: SWord1 = choose [0:0] s2977
-  s2979 :: SBool = s19 /= s2978
-  s2980 :: SBool = s_2 == s2979
-  s2981 :: SBool = s2973 < s2924
-  s2982 :: SBool = s2973 < s2866
-  s2983 :: SBool = s2981 | s2982
-  s2984 :: SWord8 = s2973 >>> 1
-  s2985 :: SWord8 = s24 | s2984
-  s2986 :: SWord8 = s26 & s2984
-  s2987 :: SWord8 = if s2983 then s2985 else s2986
-  s2988 :: SWord1 = choose [0:0] s2987
-  s2989 :: SBool = s19 /= s2988
-  s2990 :: SWord8 = s2977 >>> 1
-  s2991 :: SWord8 = s24 | s2990
-  s2992 :: SWord8 = s26 & s2990
-  s2993 :: SWord8 = if s2891 then s2991 else s2992
-  s2994 :: SWord8 = if s22 then s2993 else s2976
-  s2995 :: SWord8 = s2994 >>> 1
-  s2996 :: SWord8 = s24 | s2995
-  s2997 :: SWord8 = s26 & s2995
-  s2998 :: SWord8 = if s2989 then s2996 else s2997
-  s2999 :: SWord8 = if s22 then s2998 else s2993
-  s3000 :: SWord1 = choose [0:0] s2999
-  s3001 :: SBool = s19 /= s3000
-  s3002 :: SBool = s_2 == s3001
-  s3003 :: SWord8 = s2987 >>> 1
-  s3004 :: SWord8 = s24 | s3003
-  s3005 :: SWord8 = s26 & s3003
-  s3006 :: SWord8 = if s2979 then s3004 else s3005
-  s3007 :: SWord8 = s3006 >>> 1
-  s3008 :: SWord8 = s24 | s3007
-  s3009 :: SWord8 = s26 & s3007
-  s3010 :: SWord8 = if s3001 then s3008 else s3009
-  s3011 :: SWord1 = choose [0:0] s2994
-  s3012 :: SBool = s19 /= s3011
-  s3013 :: SWord8 = s2999 >>> 1
-  s3014 :: SWord8 = s24 | s3013
-  s3015 :: SWord8 = s26 & s3013
-  s3016 :: SWord8 = if s3012 then s3014 else s3015
-  s3017 :: SWord8 = if s29 then s2976 else s2924
-  s3018 :: SWord8 = if s170 then s2993 else s3017
-  s3019 :: SWord8 = if s29 then s2998 else s3018
-  s3020 :: SWord8 = if s170 then s3016 else s3019
-  s3021 :: SWord8 = s3006 + s3020
-  s3022 :: SBool = s3021 < s3020
-  s3023 :: SBool = s3021 < s3006
-  s3024 :: SBool = s3022 | s3023
-  s3025 :: SWord8 = s3021 >>> 1
-  s3026 :: SWord8 = s24 | s3025
-  s3027 :: SWord8 = s26 & s3025
-  s3028 :: SWord8 = if s3024 then s3026 else s3027
-  s3029 :: SWord8 = if s3002 then s3010 else s3028
-  s3030 :: SWord8 = s2987 + s3018
-  s3031 :: SWord1 = choose [0:0] s3030
-  s3032 :: SBool = s19 /= s3031
-  s3033 :: SWord8 = if s3032 then s2996 else s2997
-  s3034 :: SWord8 = if s22 then s3033 else s2993
-  s3035 :: SWord1 = choose [0:0] s3034
-  s3036 :: SBool = s19 /= s3035
-  s3037 :: SBool = s_2 == s3036
-  s3038 :: SBool = s3030 < s3018
-  s3039 :: SBool = s3030 < s2987
-  s3040 :: SBool = s3038 | s3039
-  s3041 :: SWord8 = s3030 >>> 1
-  s3042 :: SWord8 = s24 | s3041
-  s3043 :: SWord8 = s26 & s3041
-  s3044 :: SWord8 = if s3040 then s3042 else s3043
-  s3045 :: SWord8 = s3044 >>> 1
-  s3046 :: SWord8 = s24 | s3045
-  s3047 :: SWord8 = s26 & s3045
-  s3048 :: SWord8 = if s3036 then s3046 else s3047
-  s3049 :: SWord8 = s3034 >>> 1
-  s3050 :: SWord8 = s24 | s3049
-  s3051 :: SWord8 = s26 & s3049
-  s3052 :: SWord8 = if s3012 then s3050 else s3051
-  s3053 :: SWord8 = if s29 then s3033 else s3018
-  s3054 :: SWord8 = if s170 then s3052 else s3053
-  s3055 :: SWord8 = s3044 + s3054
-  s3056 :: SBool = s3055 < s3054
-  s3057 :: SBool = s3055 < s3044
-  s3058 :: SBool = s3056 | s3057
-  s3059 :: SWord8 = s3055 >>> 1
-  s3060 :: SWord8 = s24 | s3059
-  s3061 :: SWord8 = s26 & s3059
-  s3062 :: SWord8 = if s3058 then s3060 else s3061
-  s3063 :: SWord8 = if s3037 then s3048 else s3062
-  s3064 :: SWord8 = if s2980 then s3029 else s3063
-  s3065 :: SWord8 = if s2862 then s2972 else s3064
-  s3066 :: SWord8 = s2845 + s2922
-  s3067 :: SWord1 = choose [0:0] s3066
-  s3068 :: SBool = s19 /= s3067
-  s3069 :: SWord8 = if s3068 then s2856 else s2857
-  s3070 :: SWord8 = if s22 then s3069 else s2853
-  s3071 :: SWord1 = choose [0:0] s3070
-  s3072 :: SBool = s19 /= s3071
-  s3073 :: SBool = s_2 == s3072
-  s3074 :: SBool = s3066 < s2922
-  s3075 :: SBool = s3066 < s2845
-  s3076 :: SBool = s3074 | s3075
-  s3077 :: SWord8 = s3066 >>> 1
-  s3078 :: SWord8 = s24 | s3077
-  s3079 :: SWord8 = s26 & s3077
-  s3080 :: SWord8 = if s3076 then s3078 else s3079
-  s3081 :: SWord1 = choose [0:0] s3080
-  s3082 :: SBool = s19 /= s3081
-  s3083 :: SWord8 = s3070 >>> 1
-  s3084 :: SWord8 = s24 | s3083
-  s3085 :: SWord8 = s26 & s3083
-  s3086 :: SWord8 = if s2870 then s3084 else s3085
-  s3087 :: SWord8 = if s22 then s3086 else s3069
-  s3088 :: SWord8 = s3087 >>> 1
-  s3089 :: SWord8 = s24 | s3088
-  s3090 :: SWord8 = s26 & s3088
-  s3091 :: SWord8 = if s3082 then s3089 else s3090
-  s3092 :: SWord8 = if s22 then s3091 else s3086
-  s3093 :: SWord1 = choose [0:0] s3092
-  s3094 :: SBool = s19 /= s3093
-  s3095 :: SBool = s_2 == s3094
-  s3096 :: SWord8 = s3080 >>> 1
-  s3097 :: SWord8 = s24 | s3096
-  s3098 :: SWord8 = s26 & s3096
-  s3099 :: SWord8 = if s3072 then s3097 else s3098
-  s3100 :: SWord1 = choose [0:0] s3099
-  s3101 :: SBool = s19 /= s3100
-  s3102 :: SWord1 = choose [0:0] s3087
-  s3103 :: SBool = s19 /= s3102
-  s3104 :: SWord8 = s3092 >>> 1
-  s3105 :: SWord8 = s24 | s3104
-  s3106 :: SWord8 = s26 & s3104
-  s3107 :: SWord8 = if s3103 then s3105 else s3106
-  s3108 :: SWord8 = if s22 then s3107 else s3091
-  s3109 :: SWord8 = s3108 >>> 1
-  s3110 :: SWord8 = s24 | s3109
-  s3111 :: SWord8 = s26 & s3109
-  s3112 :: SWord8 = if s3101 then s3110 else s3111
-  s3113 :: SWord8 = if s22 then s3112 else s3107
-  s3114 :: SWord1 = choose [0:0] s3113
-  s3115 :: SBool = s19 /= s3114
-  s3116 :: SBool = s_2 == s3115
-  s3117 :: SWord8 = s3099 >>> 1
-  s3118 :: SWord8 = s24 | s3117
-  s3119 :: SWord8 = s26 & s3117
-  s3120 :: SWord8 = if s3094 then s3118 else s3119
-  s3121 :: SWord8 = s3120 >>> 1
-  s3122 :: SWord8 = s24 | s3121
-  s3123 :: SWord8 = s26 & s3121
-  s3124 :: SWord8 = if s3115 then s3122 else s3123
-  s3125 :: SWord1 = choose [0:0] s3108
-  s3126 :: SBool = s19 /= s3125
-  s3127 :: SWord8 = s3113 >>> 1
-  s3128 :: SWord8 = s24 | s3127
-  s3129 :: SWord8 = s26 & s3127
-  s3130 :: SWord8 = if s3126 then s3128 else s3129
-  s3131 :: SWord8 = if s29 then s3069 else s2922
-  s3132 :: SWord8 = if s170 then s3086 else s3131
-  s3133 :: SWord8 = if s29 then s3091 else s3132
-  s3134 :: SWord8 = if s170 then s3107 else s3133
-  s3135 :: SWord8 = if s29 then s3112 else s3134
-  s3136 :: SWord8 = if s170 then s3130 else s3135
-  s3137 :: SWord8 = s3120 + s3136
-  s3138 :: SBool = s3137 < s3136
-  s3139 :: SBool = s3137 < s3120
-  s3140 :: SBool = s3138 | s3139
-  s3141 :: SWord8 = s3137 >>> 1
-  s3142 :: SWord8 = s24 | s3141
-  s3143 :: SWord8 = s26 & s3141
-  s3144 :: SWord8 = if s3140 then s3142 else s3143
-  s3145 :: SWord8 = if s3116 then s3124 else s3144
-  s3146 :: SWord8 = s3099 + s3134
-  s3147 :: SWord1 = choose [0:0] s3146
-  s3148 :: SBool = s19 /= s3147
-  s3149 :: SWord8 = if s3148 then s3110 else s3111
-  s3150 :: SWord8 = if s22 then s3149 else s3107
-  s3151 :: SWord1 = choose [0:0] s3150
-  s3152 :: SBool = s19 /= s3151
-  s3153 :: SBool = s_2 == s3152
-  s3154 :: SBool = s3146 < s3134
-  s3155 :: SBool = s3146 < s3099
-  s3156 :: SBool = s3154 | s3155
-  s3157 :: SWord8 = s3146 >>> 1
-  s3158 :: SWord8 = s24 | s3157
-  s3159 :: SWord8 = s26 & s3157
-  s3160 :: SWord8 = if s3156 then s3158 else s3159
-  s3161 :: SWord8 = s3160 >>> 1
-  s3162 :: SWord8 = s24 | s3161
-  s3163 :: SWord8 = s26 & s3161
-  s3164 :: SWord8 = if s3152 then s3162 else s3163
-  s3165 :: SWord8 = s3150 >>> 1
-  s3166 :: SWord8 = s24 | s3165
-  s3167 :: SWord8 = s26 & s3165
-  s3168 :: SWord8 = if s3126 then s3166 else s3167
-  s3169 :: SWord8 = if s29 then s3149 else s3134
-  s3170 :: SWord8 = if s170 then s3168 else s3169
-  s3171 :: SWord8 = s3160 + s3170
-  s3172 :: SBool = s3171 < s3170
-  s3173 :: SBool = s3171 < s3160
-  s3174 :: SBool = s3172 | s3173
-  s3175 :: SWord8 = s3171 >>> 1
-  s3176 :: SWord8 = s24 | s3175
-  s3177 :: SWord8 = s26 & s3175
-  s3178 :: SWord8 = if s3174 then s3176 else s3177
-  s3179 :: SWord8 = if s3153 then s3164 else s3178
-  s3180 :: SWord8 = if s3095 then s3145 else s3179
-  s3181 :: SWord8 = s3080 + s3132
-  s3182 :: SWord1 = choose [0:0] s3181
-  s3183 :: SBool = s19 /= s3182
-  s3184 :: SWord8 = if s3183 then s3089 else s3090
-  s3185 :: SWord8 = if s22 then s3184 else s3086
-  s3186 :: SWord1 = choose [0:0] s3185
-  s3187 :: SBool = s19 /= s3186
-  s3188 :: SBool = s_2 == s3187
-  s3189 :: SBool = s3181 < s3132
-  s3190 :: SBool = s3181 < s3080
-  s3191 :: SBool = s3189 | s3190
-  s3192 :: SWord8 = s3181 >>> 1
-  s3193 :: SWord8 = s24 | s3192
-  s3194 :: SWord8 = s26 & s3192
-  s3195 :: SWord8 = if s3191 then s3193 else s3194
-  s3196 :: SWord1 = choose [0:0] s3195
-  s3197 :: SBool = s19 /= s3196
-  s3198 :: SWord8 = s3185 >>> 1
-  s3199 :: SWord8 = s24 | s3198
-  s3200 :: SWord8 = s26 & s3198
-  s3201 :: SWord8 = if s3103 then s3199 else s3200
-  s3202 :: SWord8 = if s22 then s3201 else s3184
-  s3203 :: SWord8 = s3202 >>> 1
-  s3204 :: SWord8 = s24 | s3203
-  s3205 :: SWord8 = s26 & s3203
-  s3206 :: SWord8 = if s3197 then s3204 else s3205
-  s3207 :: SWord8 = if s22 then s3206 else s3201
-  s3208 :: SWord1 = choose [0:0] s3207
-  s3209 :: SBool = s19 /= s3208
-  s3210 :: SBool = s_2 == s3209
-  s3211 :: SWord8 = s3195 >>> 1
-  s3212 :: SWord8 = s24 | s3211
-  s3213 :: SWord8 = s26 & s3211
-  s3214 :: SWord8 = if s3187 then s3212 else s3213
-  s3215 :: SWord8 = s3214 >>> 1
-  s3216 :: SWord8 = s24 | s3215
-  s3217 :: SWord8 = s26 & s3215
-  s3218 :: SWord8 = if s3209 then s3216 else s3217
-  s3219 :: SWord1 = choose [0:0] s3202
-  s3220 :: SBool = s19 /= s3219
-  s3221 :: SWord8 = s3207 >>> 1
-  s3222 :: SWord8 = s24 | s3221
-  s3223 :: SWord8 = s26 & s3221
-  s3224 :: SWord8 = if s3220 then s3222 else s3223
-  s3225 :: SWord8 = if s29 then s3184 else s3132
-  s3226 :: SWord8 = if s170 then s3201 else s3225
-  s3227 :: SWord8 = if s29 then s3206 else s3226
-  s3228 :: SWord8 = if s170 then s3224 else s3227
-  s3229 :: SWord8 = s3214 + s3228
-  s3230 :: SBool = s3229 < s3228
-  s3231 :: SBool = s3229 < s3214
-  s3232 :: SBool = s3230 | s3231
-  s3233 :: SWord8 = s3229 >>> 1
-  s3234 :: SWord8 = s24 | s3233
-  s3235 :: SWord8 = s26 & s3233
-  s3236 :: SWord8 = if s3232 then s3234 else s3235
-  s3237 :: SWord8 = if s3210 then s3218 else s3236
-  s3238 :: SWord8 = s3195 + s3226
-  s3239 :: SWord1 = choose [0:0] s3238
-  s3240 :: SBool = s19 /= s3239
-  s3241 :: SWord8 = if s3240 then s3204 else s3205
-  s3242 :: SWord8 = if s22 then s3241 else s3201
-  s3243 :: SWord1 = choose [0:0] s3242
-  s3244 :: SBool = s19 /= s3243
-  s3245 :: SBool = s_2 == s3244
-  s3246 :: SBool = s3238 < s3226
-  s3247 :: SBool = s3238 < s3195
-  s3248 :: SBool = s3246 | s3247
-  s3249 :: SWord8 = s3238 >>> 1
-  s3250 :: SWord8 = s24 | s3249
-  s3251 :: SWord8 = s26 & s3249
-  s3252 :: SWord8 = if s3248 then s3250 else s3251
-  s3253 :: SWord8 = s3252 >>> 1
-  s3254 :: SWord8 = s24 | s3253
-  s3255 :: SWord8 = s26 & s3253
-  s3256 :: SWord8 = if s3244 then s3254 else s3255
-  s3257 :: SWord8 = s3242 >>> 1
-  s3258 :: SWord8 = s24 | s3257
-  s3259 :: SWord8 = s26 & s3257
-  s3260 :: SWord8 = if s3220 then s3258 else s3259
-  s3261 :: SWord8 = if s29 then s3241 else s3226
-  s3262 :: SWord8 = if s170 then s3260 else s3261
-  s3263 :: SWord8 = s3252 + s3262
-  s3264 :: SBool = s3263 < s3262
-  s3265 :: SBool = s3263 < s3252
-  s3266 :: SBool = s3264 | s3265
-  s3267 :: SWord8 = s3263 >>> 1
-  s3268 :: SWord8 = s24 | s3267
-  s3269 :: SWord8 = s26 & s3267
-  s3270 :: SWord8 = if s3266 then s3268 else s3269
-  s3271 :: SWord8 = if s3245 then s3256 else s3270
-  s3272 :: SWord8 = if s3188 then s3237 else s3271
-  s3273 :: SWord8 = if s3073 then s3180 else s3272
-  s3274 :: SWord8 = if s2841 then s3065 else s3273
-  s3275 :: SWord8 = s2826 + s2920
-  s3276 :: SWord1 = choose [0:0] s3275
-  s3277 :: SBool = s19 /= s3276
-  s3278 :: SWord8 = if s3277 then s2835 else s2836
-  s3279 :: SWord8 = if s22 then s3278 else s2832
-  s3280 :: SWord1 = choose [0:0] s3279
-  s3281 :: SBool = s19 /= s3280
-  s3282 :: SBool = s_2 == s3281
-  s3283 :: SBool = s3275 < s2920
-  s3284 :: SBool = s3275 < s2826
-  s3285 :: SBool = s3283 | s3284
-  s3286 :: SWord8 = s3275 >>> 1
-  s3287 :: SWord8 = s24 | s3286
-  s3288 :: SWord8 = s26 & s3286
-  s3289 :: SWord8 = if s3285 then s3287 else s3288
-  s3290 :: SWord1 = choose [0:0] s3289
-  s3291 :: SBool = s19 /= s3290
-  s3292 :: SWord8 = s3279 >>> 1
-  s3293 :: SWord8 = s24 | s3292
-  s3294 :: SWord8 = s26 & s3292
-  s3295 :: SWord8 = if s2849 then s3293 else s3294
-  s3296 :: SWord8 = if s22 then s3295 else s3278
-  s3297 :: SWord8 = s3296 >>> 1
-  s3298 :: SWord8 = s24 | s3297
-  s3299 :: SWord8 = s26 & s3297
-  s3300 :: SWord8 = if s3291 then s3298 else s3299
-  s3301 :: SWord8 = if s22 then s3300 else s3295
-  s3302 :: SWord1 = choose [0:0] s3301
-  s3303 :: SBool = s19 /= s3302
-  s3304 :: SBool = s_2 == s3303
-  s3305 :: SWord8 = s3289 >>> 1
-  s3306 :: SWord8 = s24 | s3305
-  s3307 :: SWord8 = s26 & s3305
-  s3308 :: SWord8 = if s3281 then s3306 else s3307
-  s3309 :: SWord1 = choose [0:0] s3308
-  s3310 :: SBool = s19 /= s3309
-  s3311 :: SWord1 = choose [0:0] s3296
-  s3312 :: SBool = s19 /= s3311
-  s3313 :: SWord8 = s3301 >>> 1
-  s3314 :: SWord8 = s24 | s3313
-  s3315 :: SWord8 = s26 & s3313
-  s3316 :: SWord8 = if s3312 then s3314 else s3315
-  s3317 :: SWord8 = if s22 then s3316 else s3300
-  s3318 :: SWord8 = s3317 >>> 1
-  s3319 :: SWord8 = s24 | s3318
-  s3320 :: SWord8 = s26 & s3318
-  s3321 :: SWord8 = if s3310 then s3319 else s3320
-  s3322 :: SWord8 = if s22 then s3321 else s3316
-  s3323 :: SWord1 = choose [0:0] s3322
-  s3324 :: SBool = s19 /= s3323
-  s3325 :: SBool = s_2 == s3324
-  s3326 :: SWord8 = s3308 >>> 1
-  s3327 :: SWord8 = s24 | s3326
-  s3328 :: SWord8 = s26 & s3326
-  s3329 :: SWord8 = if s3303 then s3327 else s3328
-  s3330 :: SWord1 = choose [0:0] s3329
-  s3331 :: SBool = s19 /= s3330
-  s3332 :: SWord1 = choose [0:0] s3317
-  s3333 :: SBool = s19 /= s3332
-  s3334 :: SWord8 = s3322 >>> 1
-  s3335 :: SWord8 = s24 | s3334
-  s3336 :: SWord8 = s26 & s3334
-  s3337 :: SWord8 = if s3333 then s3335 else s3336
-  s3338 :: SWord8 = if s22 then s3337 else s3321
-  s3339 :: SWord8 = s3338 >>> 1
-  s3340 :: SWord8 = s24 | s3339
-  s3341 :: SWord8 = s26 & s3339
-  s3342 :: SWord8 = if s3331 then s3340 else s3341
-  s3343 :: SWord8 = if s22 then s3342 else s3337
-  s3344 :: SWord1 = choose [0:0] s3343
-  s3345 :: SBool = s19 /= s3344
-  s3346 :: SBool = s_2 == s3345
-  s3347 :: SWord8 = s3329 >>> 1
-  s3348 :: SWord8 = s24 | s3347
-  s3349 :: SWord8 = s26 & s3347
-  s3350 :: SWord8 = if s3324 then s3348 else s3349
-  s3351 :: SWord8 = s3350 >>> 1
-  s3352 :: SWord8 = s24 | s3351
-  s3353 :: SWord8 = s26 & s3351
-  s3354 :: SWord8 = if s3345 then s3352 else s3353
-  s3355 :: SWord1 = choose [0:0] s3338
-  s3356 :: SBool = s19 /= s3355
-  s3357 :: SWord8 = s3343 >>> 1
-  s3358 :: SWord8 = s24 | s3357
-  s3359 :: SWord8 = s26 & s3357
-  s3360 :: SWord8 = if s3356 then s3358 else s3359
-  s3361 :: SWord8 = if s29 then s3278 else s2920
-  s3362 :: SWord8 = if s170 then s3295 else s3361
-  s3363 :: SWord8 = if s29 then s3300 else s3362
-  s3364 :: SWord8 = if s170 then s3316 else s3363
-  s3365 :: SWord8 = if s29 then s3321 else s3364
-  s3366 :: SWord8 = if s170 then s3337 else s3365
-  s3367 :: SWord8 = if s29 then s3342 else s3366
-  s3368 :: SWord8 = if s170 then s3360 else s3367
-  s3369 :: SWord8 = s3350 + s3368
-  s3370 :: SBool = s3369 < s3368
-  s3371 :: SBool = s3369 < s3350
-  s3372 :: SBool = s3370 | s3371
-  s3373 :: SWord8 = s3369 >>> 1
-  s3374 :: SWord8 = s24 | s3373
-  s3375 :: SWord8 = s26 & s3373
-  s3376 :: SWord8 = if s3372 then s3374 else s3375
-  s3377 :: SWord8 = if s3346 then s3354 else s3376
-  s3378 :: SWord8 = s3329 + s3366
-  s3379 :: SWord1 = choose [0:0] s3378
-  s3380 :: SBool = s19 /= s3379
-  s3381 :: SWord8 = if s3380 then s3340 else s3341
-  s3382 :: SWord8 = if s22 then s3381 else s3337
-  s3383 :: SWord1 = choose [0:0] s3382
-  s3384 :: SBool = s19 /= s3383
-  s3385 :: SBool = s_2 == s3384
-  s3386 :: SBool = s3378 < s3366
-  s3387 :: SBool = s3378 < s3329
-  s3388 :: SBool = s3386 | s3387
-  s3389 :: SWord8 = s3378 >>> 1
-  s3390 :: SWord8 = s24 | s3389
-  s3391 :: SWord8 = s26 & s3389
-  s3392 :: SWord8 = if s3388 then s3390 else s3391
-  s3393 :: SWord8 = s3392 >>> 1
-  s3394 :: SWord8 = s24 | s3393
-  s3395 :: SWord8 = s26 & s3393
-  s3396 :: SWord8 = if s3384 then s3394 else s3395
-  s3397 :: SWord8 = s3382 >>> 1
-  s3398 :: SWord8 = s24 | s3397
-  s3399 :: SWord8 = s26 & s3397
-  s3400 :: SWord8 = if s3356 then s3398 else s3399
-  s3401 :: SWord8 = if s29 then s3381 else s3366
-  s3402 :: SWord8 = if s170 then s3400 else s3401
-  s3403 :: SWord8 = s3392 + s3402
-  s3404 :: SBool = s3403 < s3402
-  s3405 :: SBool = s3403 < s3392
-  s3406 :: SBool = s3404 | s3405
-  s3407 :: SWord8 = s3403 >>> 1
-  s3408 :: SWord8 = s24 | s3407
-  s3409 :: SWord8 = s26 & s3407
-  s3410 :: SWord8 = if s3406 then s3408 else s3409
-  s3411 :: SWord8 = if s3385 then s3396 else s3410
-  s3412 :: SWord8 = if s3325 then s3377 else s3411
-  s3413 :: SWord8 = s3308 + s3364
-  s3414 :: SWord1 = choose [0:0] s3413
-  s3415 :: SBool = s19 /= s3414
-  s3416 :: SWord8 = if s3415 then s3319 else s3320
-  s3417 :: SWord8 = if s22 then s3416 else s3316
-  s3418 :: SWord1 = choose [0:0] s3417
-  s3419 :: SBool = s19 /= s3418
-  s3420 :: SBool = s_2 == s3419
-  s3421 :: SBool = s3413 < s3364
-  s3422 :: SBool = s3413 < s3308
-  s3423 :: SBool = s3421 | s3422
-  s3424 :: SWord8 = s3413 >>> 1
-  s3425 :: SWord8 = s24 | s3424
-  s3426 :: SWord8 = s26 & s3424
-  s3427 :: SWord8 = if s3423 then s3425 else s3426
-  s3428 :: SWord1 = choose [0:0] s3427
-  s3429 :: SBool = s19 /= s3428
-  s3430 :: SWord8 = s3417 >>> 1
-  s3431 :: SWord8 = s24 | s3430
-  s3432 :: SWord8 = s26 & s3430
-  s3433 :: SWord8 = if s3333 then s3431 else s3432
-  s3434 :: SWord8 = if s22 then s3433 else s3416
-  s3435 :: SWord8 = s3434 >>> 1
-  s3436 :: SWord8 = s24 | s3435
-  s3437 :: SWord8 = s26 & s3435
-  s3438 :: SWord8 = if s3429 then s3436 else s3437
-  s3439 :: SWord8 = if s22 then s3438 else s3433
-  s3440 :: SWord1 = choose [0:0] s3439
-  s3441 :: SBool = s19 /= s3440
-  s3442 :: SBool = s_2 == s3441
-  s3443 :: SWord8 = s3427 >>> 1
-  s3444 :: SWord8 = s24 | s3443
-  s3445 :: SWord8 = s26 & s3443
-  s3446 :: SWord8 = if s3419 then s3444 else s3445
-  s3447 :: SWord8 = s3446 >>> 1
-  s3448 :: SWord8 = s24 | s3447
-  s3449 :: SWord8 = s26 & s3447
-  s3450 :: SWord8 = if s3441 then s3448 else s3449
-  s3451 :: SWord1 = choose [0:0] s3434
-  s3452 :: SBool = s19 /= s3451
-  s3453 :: SWord8 = s3439 >>> 1
-  s3454 :: SWord8 = s24 | s3453
-  s3455 :: SWord8 = s26 & s3453
-  s3456 :: SWord8 = if s3452 then s3454 else s3455
-  s3457 :: SWord8 = if s29 then s3416 else s3364
-  s3458 :: SWord8 = if s170 then s3433 else s3457
-  s3459 :: SWord8 = if s29 then s3438 else s3458
-  s3460 :: SWord8 = if s170 then s3456 else s3459
-  s3461 :: SWord8 = s3446 + s3460
-  s3462 :: SBool = s3461 < s3460
-  s3463 :: SBool = s3461 < s3446
-  s3464 :: SBool = s3462 | s3463
-  s3465 :: SWord8 = s3461 >>> 1
-  s3466 :: SWord8 = s24 | s3465
-  s3467 :: SWord8 = s26 & s3465
-  s3468 :: SWord8 = if s3464 then s3466 else s3467
-  s3469 :: SWord8 = if s3442 then s3450 else s3468
-  s3470 :: SWord8 = s3427 + s3458
-  s3471 :: SWord1 = choose [0:0] s3470
-  s3472 :: SBool = s19 /= s3471
-  s3473 :: SWord8 = if s3472 then s3436 else s3437
-  s3474 :: SWord8 = if s22 then s3473 else s3433
-  s3475 :: SWord1 = choose [0:0] s3474
-  s3476 :: SBool = s19 /= s3475
-  s3477 :: SBool = s_2 == s3476
-  s3478 :: SBool = s3470 < s3458
-  s3479 :: SBool = s3470 < s3427
-  s3480 :: SBool = s3478 | s3479
-  s3481 :: SWord8 = s3470 >>> 1
-  s3482 :: SWord8 = s24 | s3481
-  s3483 :: SWord8 = s26 & s3481
-  s3484 :: SWord8 = if s3480 then s3482 else s3483
-  s3485 :: SWord8 = s3484 >>> 1
-  s3486 :: SWord8 = s24 | s3485
-  s3487 :: SWord8 = s26 & s3485
-  s3488 :: SWord8 = if s3476 then s3486 else s3487
-  s3489 :: SWord8 = s3474 >>> 1
-  s3490 :: SWord8 = s24 | s3489
-  s3491 :: SWord8 = s26 & s3489
-  s3492 :: SWord8 = if s3452 then s3490 else s3491
-  s3493 :: SWord8 = if s29 then s3473 else s3458
-  s3494 :: SWord8 = if s170 then s3492 else s3493
-  s3495 :: SWord8 = s3484 + s3494
-  s3496 :: SBool = s3495 < s3494
-  s3497 :: SBool = s3495 < s3484
-  s3498 :: SBool = s3496 | s3497
-  s3499 :: SWord8 = s3495 >>> 1
-  s3500 :: SWord8 = s24 | s3499
-  s3501 :: SWord8 = s26 & s3499
-  s3502 :: SWord8 = if s3498 then s3500 else s3501
-  s3503 :: SWord8 = if s3477 then s3488 else s3502
-  s3504 :: SWord8 = if s3420 then s3469 else s3503
-  s3505 :: SWord8 = if s3304 then s3412 else s3504
-  s3506 :: SWord8 = s3289 + s3362
-  s3507 :: SWord1 = choose [0:0] s3506
-  s3508 :: SBool = s19 /= s3507
-  s3509 :: SWord8 = if s3508 then s3298 else s3299
-  s3510 :: SWord8 = if s22 then s3509 else s3295
-  s3511 :: SWord1 = choose [0:0] s3510
-  s3512 :: SBool = s19 /= s3511
-  s3513 :: SBool = s_2 == s3512
-  s3514 :: SBool = s3506 < s3362
-  s3515 :: SBool = s3506 < s3289
-  s3516 :: SBool = s3514 | s3515
-  s3517 :: SWord8 = s3506 >>> 1
-  s3518 :: SWord8 = s24 | s3517
-  s3519 :: SWord8 = s26 & s3517
-  s3520 :: SWord8 = if s3516 then s3518 else s3519
-  s3521 :: SWord1 = choose [0:0] s3520
-  s3522 :: SBool = s19 /= s3521
-  s3523 :: SWord8 = s3510 >>> 1
-  s3524 :: SWord8 = s24 | s3523
-  s3525 :: SWord8 = s26 & s3523
-  s3526 :: SWord8 = if s3312 then s3524 else s3525
-  s3527 :: SWord8 = if s22 then s3526 else s3509
-  s3528 :: SWord8 = s3527 >>> 1
-  s3529 :: SWord8 = s24 | s3528
-  s3530 :: SWord8 = s26 & s3528
-  s3531 :: SWord8 = if s3522 then s3529 else s3530
-  s3532 :: SWord8 = if s22 then s3531 else s3526
-  s3533 :: SWord1 = choose [0:0] s3532
-  s3534 :: SBool = s19 /= s3533
-  s3535 :: SBool = s_2 == s3534
-  s3536 :: SWord8 = s3520 >>> 1
-  s3537 :: SWord8 = s24 | s3536
-  s3538 :: SWord8 = s26 & s3536
-  s3539 :: SWord8 = if s3512 then s3537 else s3538
-  s3540 :: SWord1 = choose [0:0] s3539
-  s3541 :: SBool = s19 /= s3540
-  s3542 :: SWord1 = choose [0:0] s3527
-  s3543 :: SBool = s19 /= s3542
-  s3544 :: SWord8 = s3532 >>> 1
-  s3545 :: SWord8 = s24 | s3544
-  s3546 :: SWord8 = s26 & s3544
-  s3547 :: SWord8 = if s3543 then s3545 else s3546
-  s3548 :: SWord8 = if s22 then s3547 else s3531
-  s3549 :: SWord8 = s3548 >>> 1
-  s3550 :: SWord8 = s24 | s3549
-  s3551 :: SWord8 = s26 & s3549
-  s3552 :: SWord8 = if s3541 then s3550 else s3551
-  s3553 :: SWord8 = if s22 then s3552 else s3547
-  s3554 :: SWord1 = choose [0:0] s3553
-  s3555 :: SBool = s19 /= s3554
-  s3556 :: SBool = s_2 == s3555
-  s3557 :: SWord8 = s3539 >>> 1
-  s3558 :: SWord8 = s24 | s3557
-  s3559 :: SWord8 = s26 & s3557
-  s3560 :: SWord8 = if s3534 then s3558 else s3559
-  s3561 :: SWord8 = s3560 >>> 1
-  s3562 :: SWord8 = s24 | s3561
-  s3563 :: SWord8 = s26 & s3561
-  s3564 :: SWord8 = if s3555 then s3562 else s3563
-  s3565 :: SWord1 = choose [0:0] s3548
-  s3566 :: SBool = s19 /= s3565
-  s3567 :: SWord8 = s3553 >>> 1
-  s3568 :: SWord8 = s24 | s3567
-  s3569 :: SWord8 = s26 & s3567
-  s3570 :: SWord8 = if s3566 then s3568 else s3569
-  s3571 :: SWord8 = if s29 then s3509 else s3362
-  s3572 :: SWord8 = if s170 then s3526 else s3571
-  s3573 :: SWord8 = if s29 then s3531 else s3572
-  s3574 :: SWord8 = if s170 then s3547 else s3573
-  s3575 :: SWord8 = if s29 then s3552 else s3574
-  s3576 :: SWord8 = if s170 then s3570 else s3575
-  s3577 :: SWord8 = s3560 + s3576
-  s3578 :: SBool = s3577 < s3576
-  s3579 :: SBool = s3577 < s3560
-  s3580 :: SBool = s3578 | s3579
-  s3581 :: SWord8 = s3577 >>> 1
-  s3582 :: SWord8 = s24 | s3581
-  s3583 :: SWord8 = s26 & s3581
-  s3584 :: SWord8 = if s3580 then s3582 else s3583
-  s3585 :: SWord8 = if s3556 then s3564 else s3584
-  s3586 :: SWord8 = s3539 + s3574
-  s3587 :: SWord1 = choose [0:0] s3586
-  s3588 :: SBool = s19 /= s3587
-  s3589 :: SWord8 = if s3588 then s3550 else s3551
-  s3590 :: SWord8 = if s22 then s3589 else s3547
-  s3591 :: SWord1 = choose [0:0] s3590
-  s3592 :: SBool = s19 /= s3591
-  s3593 :: SBool = s_2 == s3592
-  s3594 :: SBool = s3586 < s3574
-  s3595 :: SBool = s3586 < s3539
-  s3596 :: SBool = s3594 | s3595
-  s3597 :: SWord8 = s3586 >>> 1
-  s3598 :: SWord8 = s24 | s3597
-  s3599 :: SWord8 = s26 & s3597
-  s3600 :: SWord8 = if s3596 then s3598 else s3599
-  s3601 :: SWord8 = s3600 >>> 1
-  s3602 :: SWord8 = s24 | s3601
-  s3603 :: SWord8 = s26 & s3601
-  s3604 :: SWord8 = if s3592 then s3602 else s3603
-  s3605 :: SWord8 = s3590 >>> 1
-  s3606 :: SWord8 = s24 | s3605
-  s3607 :: SWord8 = s26 & s3605
-  s3608 :: SWord8 = if s3566 then s3606 else s3607
-  s3609 :: SWord8 = if s29 then s3589 else s3574
-  s3610 :: SWord8 = if s170 then s3608 else s3609
-  s3611 :: SWord8 = s3600 + s3610
-  s3612 :: SBool = s3611 < s3610
-  s3613 :: SBool = s3611 < s3600
-  s3614 :: SBool = s3612 | s3613
-  s3615 :: SWord8 = s3611 >>> 1
-  s3616 :: SWord8 = s24 | s3615
-  s3617 :: SWord8 = s26 & s3615
-  s3618 :: SWord8 = if s3614 then s3616 else s3617
-  s3619 :: SWord8 = if s3593 then s3604 else s3618
-  s3620 :: SWord8 = if s3535 then s3585 else s3619
-  s3621 :: SWord8 = s3520 + s3572
-  s3622 :: SWord1 = choose [0:0] s3621
-  s3623 :: SBool = s19 /= s3622
-  s3624 :: SWord8 = if s3623 then s3529 else s3530
-  s3625 :: SWord8 = if s22 then s3624 else s3526
-  s3626 :: SWord1 = choose [0:0] s3625
-  s3627 :: SBool = s19 /= s3626
-  s3628 :: SBool = s_2 == s3627
-  s3629 :: SBool = s3621 < s3572
-  s3630 :: SBool = s3621 < s3520
-  s3631 :: SBool = s3629 | s3630
-  s3632 :: SWord8 = s3621 >>> 1
-  s3633 :: SWord8 = s24 | s3632
-  s3634 :: SWord8 = s26 & s3632
-  s3635 :: SWord8 = if s3631 then s3633 else s3634
-  s3636 :: SWord1 = choose [0:0] s3635
-  s3637 :: SBool = s19 /= s3636
-  s3638 :: SWord8 = s3625 >>> 1
-  s3639 :: SWord8 = s24 | s3638
-  s3640 :: SWord8 = s26 & s3638
-  s3641 :: SWord8 = if s3543 then s3639 else s3640
-  s3642 :: SWord8 = if s22 then s3641 else s3624
-  s3643 :: SWord8 = s3642 >>> 1
-  s3644 :: SWord8 = s24 | s3643
-  s3645 :: SWord8 = s26 & s3643
-  s3646 :: SWord8 = if s3637 then s3644 else s3645
-  s3647 :: SWord8 = if s22 then s3646 else s3641
-  s3648 :: SWord1 = choose [0:0] s3647
-  s3649 :: SBool = s19 /= s3648
-  s3650 :: SBool = s_2 == s3649
-  s3651 :: SWord8 = s3635 >>> 1
-  s3652 :: SWord8 = s24 | s3651
-  s3653 :: SWord8 = s26 & s3651
-  s3654 :: SWord8 = if s3627 then s3652 else s3653
-  s3655 :: SWord8 = s3654 >>> 1
-  s3656 :: SWord8 = s24 | s3655
-  s3657 :: SWord8 = s26 & s3655
-  s3658 :: SWord8 = if s3649 then s3656 else s3657
-  s3659 :: SWord1 = choose [0:0] s3642
-  s3660 :: SBool = s19 /= s3659
-  s3661 :: SWord8 = s3647 >>> 1
-  s3662 :: SWord8 = s24 | s3661
-  s3663 :: SWord8 = s26 & s3661
-  s3664 :: SWord8 = if s3660 then s3662 else s3663
-  s3665 :: SWord8 = if s29 then s3624 else s3572
-  s3666 :: SWord8 = if s170 then s3641 else s3665
-  s3667 :: SWord8 = if s29 then s3646 else s3666
-  s3668 :: SWord8 = if s170 then s3664 else s3667
-  s3669 :: SWord8 = s3654 + s3668
-  s3670 :: SBool = s3669 < s3668
-  s3671 :: SBool = s3669 < s3654
-  s3672 :: SBool = s3670 | s3671
-  s3673 :: SWord8 = s3669 >>> 1
-  s3674 :: SWord8 = s24 | s3673
-  s3675 :: SWord8 = s26 & s3673
-  s3676 :: SWord8 = if s3672 then s3674 else s3675
-  s3677 :: SWord8 = if s3650 then s3658 else s3676
-  s3678 :: SWord8 = s3635 + s3666
-  s3679 :: SWord1 = choose [0:0] s3678
-  s3680 :: SBool = s19 /= s3679
-  s3681 :: SWord8 = if s3680 then s3644 else s3645
-  s3682 :: SWord8 = if s22 then s3681 else s3641
-  s3683 :: SWord1 = choose [0:0] s3682
-  s3684 :: SBool = s19 /= s3683
-  s3685 :: SBool = s_2 == s3684
-  s3686 :: SBool = s3678 < s3666
-  s3687 :: SBool = s3678 < s3635
-  s3688 :: SBool = s3686 | s3687
-  s3689 :: SWord8 = s3678 >>> 1
-  s3690 :: SWord8 = s24 | s3689
-  s3691 :: SWord8 = s26 & s3689
-  s3692 :: SWord8 = if s3688 then s3690 else s3691
-  s3693 :: SWord8 = s3692 >>> 1
-  s3694 :: SWord8 = s24 | s3693
-  s3695 :: SWord8 = s26 & s3693
-  s3696 :: SWord8 = if s3684 then s3694 else s3695
-  s3697 :: SWord8 = s3682 >>> 1
-  s3698 :: SWord8 = s24 | s3697
-  s3699 :: SWord8 = s26 & s3697
-  s3700 :: SWord8 = if s3660 then s3698 else s3699
-  s3701 :: SWord8 = if s29 then s3681 else s3666
-  s3702 :: SWord8 = if s170 then s3700 else s3701
-  s3703 :: SWord8 = s3692 + s3702
-  s3704 :: SBool = s3703 < s3702
-  s3705 :: SBool = s3703 < s3692
-  s3706 :: SBool = s3704 | s3705
-  s3707 :: SWord8 = s3703 >>> 1
-  s3708 :: SWord8 = s24 | s3707
-  s3709 :: SWord8 = s26 & s3707
-  s3710 :: SWord8 = if s3706 then s3708 else s3709
-  s3711 :: SWord8 = if s3685 then s3696 else s3710
-  s3712 :: SWord8 = if s3628 then s3677 else s3711
-  s3713 :: SWord8 = if s3513 then s3620 else s3712
-  s3714 :: SWord8 = if s3282 then s3505 else s3713
-  s3715 :: SWord8 = if s2819 then s3274 else s3714
-  s3716 :: SWord8 = if s1892 then s2811 else s3715
-  s3717 :: SWord8 = if s38 then s1884 else s3716
-  s3718 :: SWord1 = choose [0:0] s178
-  s3719 :: SBool = s19 /= s3718
-  s3720 :: SWord8 = s24 | s33
-  s3721 :: SWord8 = if s3719 then s3720 else s34
-  s3722 :: SWord8 = if s22 then s3721 else s28
-  s3723 :: SWord1 = choose [0:0] s3722
-  s3724 :: SBool = s19 /= s3723
-  s3725 :: SBool = s_2 == s3724
-  s3726 :: SWord8 = s178 >>> 1
-  s3727 :: SWord8 = s26 & s3726
-  s3728 :: SWord1 = choose [0:0] s3727
-  s3729 :: SBool = s19 /= s3728
-  s3730 :: SWord8 = s3722 >>> 1
-  s3731 :: SWord8 = s24 | s3730
-  s3732 :: SWord8 = s26 & s3730
-  s3733 :: SWord8 = if s43 then s3731 else s3732
-  s3734 :: SWord8 = if s22 then s3733 else s3721
-  s3735 :: SWord8 = s3734 >>> 1
-  s3736 :: SWord8 = s24 | s3735
-  s3737 :: SWord8 = s26 & s3735
-  s3738 :: SWord8 = if s3729 then s3736 else s3737
-  s3739 :: SWord8 = if s22 then s3738 else s3733
-  s3740 :: SWord1 = choose [0:0] s3739
-  s3741 :: SBool = s19 /= s3740
-  s3742 :: SBool = s_2 == s3741
-  s3743 :: SWord8 = s3727 >>> 1
-  s3744 :: SWord8 = s24 | s3743
-  s3745 :: SWord8 = s26 & s3743
-  s3746 :: SWord8 = if s3724 then s3744 else s3745
-  s3747 :: SWord1 = choose [0:0] s3746
-  s3748 :: SBool = s19 /= s3747
-  s3749 :: SWord1 = choose [0:0] s3734
-  s3750 :: SBool = s19 /= s3749
-  s3751 :: SWord8 = s3739 >>> 1
-  s3752 :: SWord8 = s24 | s3751
-  s3753 :: SWord8 = s26 & s3751
-  s3754 :: SWord8 = if s3750 then s3752 else s3753
-  s3755 :: SWord8 = if s22 then s3754 else s3738
-  s3756 :: SWord8 = s3755 >>> 1
-  s3757 :: SWord8 = s24 | s3756
-  s3758 :: SWord8 = s26 & s3756
-  s3759 :: SWord8 = if s3748 then s3757 else s3758
-  s3760 :: SWord8 = if s22 then s3759 else s3754
-  s3761 :: SWord1 = choose [0:0] s3760
-  s3762 :: SBool = s19 /= s3761
-  s3763 :: SBool = s_2 == s3762
-  s3764 :: SWord8 = s3746 >>> 1
-  s3765 :: SWord8 = s24 | s3764
-  s3766 :: SWord8 = s26 & s3764
-  s3767 :: SWord8 = if s3741 then s3765 else s3766
-  s3768 :: SWord1 = choose [0:0] s3767
-  s3769 :: SBool = s19 /= s3768
-  s3770 :: SWord1 = choose [0:0] s3755
-  s3771 :: SBool = s19 /= s3770
-  s3772 :: SWord8 = s3760 >>> 1
-  s3773 :: SWord8 = s24 | s3772
-  s3774 :: SWord8 = s26 & s3772
-  s3775 :: SWord8 = if s3771 then s3773 else s3774
-  s3776 :: SWord8 = if s22 then s3775 else s3759
-  s3777 :: SWord8 = s3776 >>> 1
-  s3778 :: SWord8 = s24 | s3777
-  s3779 :: SWord8 = s26 & s3777
-  s3780 :: SWord8 = if s3769 then s3778 else s3779
-  s3781 :: SWord8 = if s22 then s3780 else s3775
-  s3782 :: SWord1 = choose [0:0] s3781
-  s3783 :: SBool = s19 /= s3782
-  s3784 :: SBool = s_2 == s3783
-  s3785 :: SWord8 = s3767 >>> 1
-  s3786 :: SWord8 = s24 | s3785
-  s3787 :: SWord8 = s26 & s3785
-  s3788 :: SWord8 = if s3762 then s3786 else s3787
-  s3789 :: SWord1 = choose [0:0] s3788
-  s3790 :: SBool = s19 /= s3789
-  s3791 :: SWord1 = choose [0:0] s3776
-  s3792 :: SBool = s19 /= s3791
-  s3793 :: SWord8 = s3781 >>> 1
-  s3794 :: SWord8 = s24 | s3793
-  s3795 :: SWord8 = s26 & s3793
-  s3796 :: SWord8 = if s3792 then s3794 else s3795
-  s3797 :: SWord8 = if s22 then s3796 else s3780
-  s3798 :: SWord8 = s3797 >>> 1
-  s3799 :: SWord8 = s24 | s3798
-  s3800 :: SWord8 = s26 & s3798
-  s3801 :: SWord8 = if s3790 then s3799 else s3800
-  s3802 :: SWord8 = if s22 then s3801 else s3796
-  s3803 :: SWord1 = choose [0:0] s3802
-  s3804 :: SBool = s19 /= s3803
-  s3805 :: SBool = s_2 == s3804
-  s3806 :: SWord8 = s3788 >>> 1
-  s3807 :: SWord8 = s24 | s3806
-  s3808 :: SWord8 = s26 & s3806
-  s3809 :: SWord8 = if s3783 then s3807 else s3808
-  s3810 :: SWord1 = choose [0:0] s3809
-  s3811 :: SBool = s19 /= s3810
-  s3812 :: SWord1 = choose [0:0] s3797
-  s3813 :: SBool = s19 /= s3812
-  s3814 :: SWord8 = s3802 >>> 1
-  s3815 :: SWord8 = s24 | s3814
-  s3816 :: SWord8 = s26 & s3814
-  s3817 :: SWord8 = if s3813 then s3815 else s3816
-  s3818 :: SWord8 = if s22 then s3817 else s3801
-  s3819 :: SWord8 = s3818 >>> 1
-  s3820 :: SWord8 = s24 | s3819
-  s3821 :: SWord8 = s26 & s3819
-  s3822 :: SWord8 = if s3811 then s3820 else s3821
-  s3823 :: SWord8 = if s22 then s3822 else s3817
-  s3824 :: SWord1 = choose [0:0] s3823
-  s3825 :: SBool = s19 /= s3824
-  s3826 :: SBool = s_2 == s3825
-  s3827 :: SWord8 = s3809 >>> 1
-  s3828 :: SWord8 = s24 | s3827
-  s3829 :: SWord8 = s26 & s3827
-  s3830 :: SWord8 = if s3804 then s3828 else s3829
-  s3831 :: SWord1 = choose [0:0] s3830
-  s3832 :: SBool = s19 /= s3831
-  s3833 :: SWord1 = choose [0:0] s3818
-  s3834 :: SBool = s19 /= s3833
-  s3835 :: SWord8 = s3823 >>> 1
-  s3836 :: SWord8 = s24 | s3835
-  s3837 :: SWord8 = s26 & s3835
-  s3838 :: SWord8 = if s3834 then s3836 else s3837
-  s3839 :: SWord8 = if s22 then s3838 else s3822
-  s3840 :: SWord8 = s3839 >>> 1
-  s3841 :: SWord8 = s24 | s3840
-  s3842 :: SWord8 = s26 & s3840
-  s3843 :: SWord8 = if s3832 then s3841 else s3842
-  s3844 :: SWord8 = if s22 then s3843 else s3838
-  s3845 :: SWord1 = choose [0:0] s3844
-  s3846 :: SBool = s19 /= s3845
-  s3847 :: SBool = s_2 == s3846
-  s3848 :: SWord8 = s3830 >>> 1
-  s3849 :: SWord8 = s24 | s3848
-  s3850 :: SWord8 = s26 & s3848
-  s3851 :: SWord8 = if s3825 then s3849 else s3850
-  s3852 :: SWord8 = s3851 >>> 1
-  s3853 :: SWord8 = s24 | s3852
-  s3854 :: SWord8 = s26 & s3852
-  s3855 :: SWord8 = if s3846 then s3853 else s3854
-  s3856 :: SWord1 = choose [0:0] s3839
-  s3857 :: SBool = s19 /= s3856
-  s3858 :: SWord8 = s3844 >>> 1
-  s3859 :: SWord8 = s24 | s3858
-  s3860 :: SWord8 = s26 & s3858
-  s3861 :: SWord8 = if s3857 then s3859 else s3860
-  s3862 :: SWord8 = if s29 then s3721 else s178
-  s3863 :: SWord8 = if s170 then s3733 else s3862
-  s3864 :: SWord8 = if s29 then s3738 else s3863
-  s3865 :: SWord8 = if s170 then s3754 else s3864
-  s3866 :: SWord8 = if s29 then s3759 else s3865
-  s3867 :: SWord8 = if s170 then s3775 else s3866
-  s3868 :: SWord8 = if s29 then s3780 else s3867
-  s3869 :: SWord8 = if s170 then s3796 else s3868
-  s3870 :: SWord8 = if s29 then s3801 else s3869
-  s3871 :: SWord8 = if s170 then s3817 else s3870
-  s3872 :: SWord8 = if s29 then s3822 else s3871
-  s3873 :: SWord8 = if s170 then s3838 else s3872
-  s3874 :: SWord8 = if s29 then s3843 else s3873
-  s3875 :: SWord8 = if s170 then s3861 else s3874
-  s3876 :: SWord8 = s3851 + s3875
-  s3877 :: SBool = s3876 < s3875
-  s3878 :: SBool = s3876 < s3851
-  s3879 :: SBool = s3877 | s3878
-  s3880 :: SWord8 = s3876 >>> 1
-  s3881 :: SWord8 = s24 | s3880
-  s3882 :: SWord8 = s26 & s3880
-  s3883 :: SWord8 = if s3879 then s3881 else s3882
-  s3884 :: SWord8 = if s3847 then s3855 else s3883
-  s3885 :: SWord8 = s3830 + s3873
-  s3886 :: SWord1 = choose [0:0] s3885
-  s3887 :: SBool = s19 /= s3886
-  s3888 :: SWord8 = if s3887 then s3841 else s3842
-  s3889 :: SWord8 = if s22 then s3888 else s3838
-  s3890 :: SWord1 = choose [0:0] s3889
-  s3891 :: SBool = s19 /= s3890
-  s3892 :: SBool = s_2 == s3891
-  s3893 :: SBool = s3885 < s3873
-  s3894 :: SBool = s3885 < s3830
-  s3895 :: SBool = s3893 | s3894
-  s3896 :: SWord8 = s3885 >>> 1
-  s3897 :: SWord8 = s24 | s3896
-  s3898 :: SWord8 = s26 & s3896
-  s3899 :: SWord8 = if s3895 then s3897 else s3898
-  s3900 :: SWord8 = s3899 >>> 1
-  s3901 :: SWord8 = s24 | s3900
-  s3902 :: SWord8 = s26 & s3900
-  s3903 :: SWord8 = if s3891 then s3901 else s3902
-  s3904 :: SWord8 = s3889 >>> 1
-  s3905 :: SWord8 = s24 | s3904
-  s3906 :: SWord8 = s26 & s3904
-  s3907 :: SWord8 = if s3857 then s3905 else s3906
-  s3908 :: SWord8 = if s29 then s3888 else s3873
-  s3909 :: SWord8 = if s170 then s3907 else s3908
-  s3910 :: SWord8 = s3899 + s3909
-  s3911 :: SBool = s3910 < s3909
-  s3912 :: SBool = s3910 < s3899
-  s3913 :: SBool = s3911 | s3912
-  s3914 :: SWord8 = s3910 >>> 1
-  s3915 :: SWord8 = s24 | s3914
-  s3916 :: SWord8 = s26 & s3914
-  s3917 :: SWord8 = if s3913 then s3915 else s3916
-  s3918 :: SWord8 = if s3892 then s3903 else s3917
-  s3919 :: SWord8 = if s3826 then s3884 else s3918
-  s3920 :: SWord8 = s3809 + s3871
-  s3921 :: SWord1 = choose [0:0] s3920
-  s3922 :: SBool = s19 /= s3921
-  s3923 :: SWord8 = if s3922 then s3820 else s3821
-  s3924 :: SWord8 = if s22 then s3923 else s3817
-  s3925 :: SWord1 = choose [0:0] s3924
-  s3926 :: SBool = s19 /= s3925
-  s3927 :: SBool = s_2 == s3926
-  s3928 :: SBool = s3920 < s3871
-  s3929 :: SBool = s3920 < s3809
-  s3930 :: SBool = s3928 | s3929
-  s3931 :: SWord8 = s3920 >>> 1
-  s3932 :: SWord8 = s24 | s3931
-  s3933 :: SWord8 = s26 & s3931
-  s3934 :: SWord8 = if s3930 then s3932 else s3933
-  s3935 :: SWord1 = choose [0:0] s3934
-  s3936 :: SBool = s19 /= s3935
-  s3937 :: SWord8 = s3924 >>> 1
-  s3938 :: SWord8 = s24 | s3937
-  s3939 :: SWord8 = s26 & s3937
-  s3940 :: SWord8 = if s3834 then s3938 else s3939
-  s3941 :: SWord8 = if s22 then s3940 else s3923
-  s3942 :: SWord8 = s3941 >>> 1
-  s3943 :: SWord8 = s24 | s3942
-  s3944 :: SWord8 = s26 & s3942
-  s3945 :: SWord8 = if s3936 then s3943 else s3944
-  s3946 :: SWord8 = if s22 then s3945 else s3940
-  s3947 :: SWord1 = choose [0:0] s3946
-  s3948 :: SBool = s19 /= s3947
-  s3949 :: SBool = s_2 == s3948
-  s3950 :: SWord8 = s3934 >>> 1
-  s3951 :: SWord8 = s24 | s3950
-  s3952 :: SWord8 = s26 & s3950
-  s3953 :: SWord8 = if s3926 then s3951 else s3952
-  s3954 :: SWord8 = s3953 >>> 1
-  s3955 :: SWord8 = s24 | s3954
-  s3956 :: SWord8 = s26 & s3954
-  s3957 :: SWord8 = if s3948 then s3955 else s3956
-  s3958 :: SWord1 = choose [0:0] s3941
-  s3959 :: SBool = s19 /= s3958
-  s3960 :: SWord8 = s3946 >>> 1
-  s3961 :: SWord8 = s24 | s3960
-  s3962 :: SWord8 = s26 & s3960
-  s3963 :: SWord8 = if s3959 then s3961 else s3962
-  s3964 :: SWord8 = if s29 then s3923 else s3871
-  s3965 :: SWord8 = if s170 then s3940 else s3964
-  s3966 :: SWord8 = if s29 then s3945 else s3965
-  s3967 :: SWord8 = if s170 then s3963 else s3966
-  s3968 :: SWord8 = s3953 + s3967
-  s3969 :: SBool = s3968 < s3967
-  s3970 :: SBool = s3968 < s3953
-  s3971 :: SBool = s3969 | s3970
-  s3972 :: SWord8 = s3968 >>> 1
-  s3973 :: SWord8 = s24 | s3972
-  s3974 :: SWord8 = s26 & s3972
-  s3975 :: SWord8 = if s3971 then s3973 else s3974
-  s3976 :: SWord8 = if s3949 then s3957 else s3975
-  s3977 :: SWord8 = s3934 + s3965
-  s3978 :: SWord1 = choose [0:0] s3977
-  s3979 :: SBool = s19 /= s3978
-  s3980 :: SWord8 = if s3979 then s3943 else s3944
-  s3981 :: SWord8 = if s22 then s3980 else s3940
-  s3982 :: SWord1 = choose [0:0] s3981
-  s3983 :: SBool = s19 /= s3982
-  s3984 :: SBool = s_2 == s3983
-  s3985 :: SBool = s3977 < s3965
-  s3986 :: SBool = s3977 < s3934
-  s3987 :: SBool = s3985 | s3986
-  s3988 :: SWord8 = s3977 >>> 1
-  s3989 :: SWord8 = s24 | s3988
-  s3990 :: SWord8 = s26 & s3988
-  s3991 :: SWord8 = if s3987 then s3989 else s3990
-  s3992 :: SWord8 = s3991 >>> 1
-  s3993 :: SWord8 = s24 | s3992
-  s3994 :: SWord8 = s26 & s3992
-  s3995 :: SWord8 = if s3983 then s3993 else s3994
-  s3996 :: SWord8 = s3981 >>> 1
-  s3997 :: SWord8 = s24 | s3996
-  s3998 :: SWord8 = s26 & s3996
-  s3999 :: SWord8 = if s3959 then s3997 else s3998
-  s4000 :: SWord8 = if s29 then s3980 else s3965
-  s4001 :: SWord8 = if s170 then s3999 else s4000
-  s4002 :: SWord8 = s3991 + s4001
-  s4003 :: SBool = s4002 < s4001
-  s4004 :: SBool = s4002 < s3991
-  s4005 :: SBool = s4003 | s4004
-  s4006 :: SWord8 = s4002 >>> 1
-  s4007 :: SWord8 = s24 | s4006
-  s4008 :: SWord8 = s26 & s4006
-  s4009 :: SWord8 = if s4005 then s4007 else s4008
-  s4010 :: SWord8 = if s3984 then s3995 else s4009
-  s4011 :: SWord8 = if s3927 then s3976 else s4010
-  s4012 :: SWord8 = if s3805 then s3919 else s4011
-  s4013 :: SWord8 = s3788 + s3869
-  s4014 :: SWord1 = choose [0:0] s4013
-  s4015 :: SBool = s19 /= s4014
-  s4016 :: SWord8 = if s4015 then s3799 else s3800
-  s4017 :: SWord8 = if s22 then s4016 else s3796
-  s4018 :: SWord1 = choose [0:0] s4017
-  s4019 :: SBool = s19 /= s4018
-  s4020 :: SBool = s_2 == s4019
-  s4021 :: SBool = s4013 < s3869
-  s4022 :: SBool = s4013 < s3788
-  s4023 :: SBool = s4021 | s4022
-  s4024 :: SWord8 = s4013 >>> 1
-  s4025 :: SWord8 = s24 | s4024
-  s4026 :: SWord8 = s26 & s4024
-  s4027 :: SWord8 = if s4023 then s4025 else s4026
-  s4028 :: SWord1 = choose [0:0] s4027
-  s4029 :: SBool = s19 /= s4028
-  s4030 :: SWord8 = s4017 >>> 1
-  s4031 :: SWord8 = s24 | s4030
-  s4032 :: SWord8 = s26 & s4030
-  s4033 :: SWord8 = if s3813 then s4031 else s4032
-  s4034 :: SWord8 = if s22 then s4033 else s4016
-  s4035 :: SWord8 = s4034 >>> 1
-  s4036 :: SWord8 = s24 | s4035
-  s4037 :: SWord8 = s26 & s4035
-  s4038 :: SWord8 = if s4029 then s4036 else s4037
-  s4039 :: SWord8 = if s22 then s4038 else s4033
-  s4040 :: SWord1 = choose [0:0] s4039
-  s4041 :: SBool = s19 /= s4040
-  s4042 :: SBool = s_2 == s4041
-  s4043 :: SWord8 = s4027 >>> 1
-  s4044 :: SWord8 = s24 | s4043
-  s4045 :: SWord8 = s26 & s4043
-  s4046 :: SWord8 = if s4019 then s4044 else s4045
-  s4047 :: SWord1 = choose [0:0] s4046
-  s4048 :: SBool = s19 /= s4047
-  s4049 :: SWord1 = choose [0:0] s4034
-  s4050 :: SBool = s19 /= s4049
-  s4051 :: SWord8 = s4039 >>> 1
-  s4052 :: SWord8 = s24 | s4051
-  s4053 :: SWord8 = s26 & s4051
-  s4054 :: SWord8 = if s4050 then s4052 else s4053
-  s4055 :: SWord8 = if s22 then s4054 else s4038
-  s4056 :: SWord8 = s4055 >>> 1
-  s4057 :: SWord8 = s24 | s4056
-  s4058 :: SWord8 = s26 & s4056
-  s4059 :: SWord8 = if s4048 then s4057 else s4058
-  s4060 :: SWord8 = if s22 then s4059 else s4054
-  s4061 :: SWord1 = choose [0:0] s4060
-  s4062 :: SBool = s19 /= s4061
-  s4063 :: SBool = s_2 == s4062
-  s4064 :: SWord8 = s4046 >>> 1
-  s4065 :: SWord8 = s24 | s4064
-  s4066 :: SWord8 = s26 & s4064
-  s4067 :: SWord8 = if s4041 then s4065 else s4066
-  s4068 :: SWord8 = s4067 >>> 1
-  s4069 :: SWord8 = s24 | s4068
-  s4070 :: SWord8 = s26 & s4068
-  s4071 :: SWord8 = if s4062 then s4069 else s4070
-  s4072 :: SWord1 = choose [0:0] s4055
-  s4073 :: SBool = s19 /= s4072
-  s4074 :: SWord8 = s4060 >>> 1
-  s4075 :: SWord8 = s24 | s4074
-  s4076 :: SWord8 = s26 & s4074
-  s4077 :: SWord8 = if s4073 then s4075 else s4076
-  s4078 :: SWord8 = if s29 then s4016 else s3869
-  s4079 :: SWord8 = if s170 then s4033 else s4078
-  s4080 :: SWord8 = if s29 then s4038 else s4079
-  s4081 :: SWord8 = if s170 then s4054 else s4080
-  s4082 :: SWord8 = if s29 then s4059 else s4081
-  s4083 :: SWord8 = if s170 then s4077 else s4082
-  s4084 :: SWord8 = s4067 + s4083
-  s4085 :: SBool = s4084 < s4083
-  s4086 :: SBool = s4084 < s4067
-  s4087 :: SBool = s4085 | s4086
-  s4088 :: SWord8 = s4084 >>> 1
-  s4089 :: SWord8 = s24 | s4088
-  s4090 :: SWord8 = s26 & s4088
-  s4091 :: SWord8 = if s4087 then s4089 else s4090
-  s4092 :: SWord8 = if s4063 then s4071 else s4091
-  s4093 :: SWord8 = s4046 + s4081
-  s4094 :: SWord1 = choose [0:0] s4093
-  s4095 :: SBool = s19 /= s4094
-  s4096 :: SWord8 = if s4095 then s4057 else s4058
-  s4097 :: SWord8 = if s22 then s4096 else s4054
-  s4098 :: SWord1 = choose [0:0] s4097
-  s4099 :: SBool = s19 /= s4098
-  s4100 :: SBool = s_2 == s4099
-  s4101 :: SBool = s4093 < s4081
-  s4102 :: SBool = s4093 < s4046
-  s4103 :: SBool = s4101 | s4102
-  s4104 :: SWord8 = s4093 >>> 1
-  s4105 :: SWord8 = s24 | s4104
-  s4106 :: SWord8 = s26 & s4104
-  s4107 :: SWord8 = if s4103 then s4105 else s4106
-  s4108 :: SWord8 = s4107 >>> 1
-  s4109 :: SWord8 = s24 | s4108
-  s4110 :: SWord8 = s26 & s4108
-  s4111 :: SWord8 = if s4099 then s4109 else s4110
-  s4112 :: SWord8 = s4097 >>> 1
-  s4113 :: SWord8 = s24 | s4112
-  s4114 :: SWord8 = s26 & s4112
-  s4115 :: SWord8 = if s4073 then s4113 else s4114
-  s4116 :: SWord8 = if s29 then s4096 else s4081
-  s4117 :: SWord8 = if s170 then s4115 else s4116
-  s4118 :: SWord8 = s4107 + s4117
-  s4119 :: SBool = s4118 < s4117
-  s4120 :: SBool = s4118 < s4107
-  s4121 :: SBool = s4119 | s4120
-  s4122 :: SWord8 = s4118 >>> 1
-  s4123 :: SWord8 = s24 | s4122
-  s4124 :: SWord8 = s26 & s4122
-  s4125 :: SWord8 = if s4121 then s4123 else s4124
-  s4126 :: SWord8 = if s4100 then s4111 else s4125
-  s4127 :: SWord8 = if s4042 then s4092 else s4126
-  s4128 :: SWord8 = s4027 + s4079
-  s4129 :: SWord1 = choose [0:0] s4128
-  s4130 :: SBool = s19 /= s4129
-  s4131 :: SWord8 = if s4130 then s4036 else s4037
-  s4132 :: SWord8 = if s22 then s4131 else s4033
-  s4133 :: SWord1 = choose [0:0] s4132
-  s4134 :: SBool = s19 /= s4133
-  s4135 :: SBool = s_2 == s4134
-  s4136 :: SBool = s4128 < s4079
-  s4137 :: SBool = s4128 < s4027
-  s4138 :: SBool = s4136 | s4137
-  s4139 :: SWord8 = s4128 >>> 1
-  s4140 :: SWord8 = s24 | s4139
-  s4141 :: SWord8 = s26 & s4139
-  s4142 :: SWord8 = if s4138 then s4140 else s4141
-  s4143 :: SWord1 = choose [0:0] s4142
-  s4144 :: SBool = s19 /= s4143
-  s4145 :: SWord8 = s4132 >>> 1
-  s4146 :: SWord8 = s24 | s4145
-  s4147 :: SWord8 = s26 & s4145
-  s4148 :: SWord8 = if s4050 then s4146 else s4147
-  s4149 :: SWord8 = if s22 then s4148 else s4131
-  s4150 :: SWord8 = s4149 >>> 1
-  s4151 :: SWord8 = s24 | s4150
-  s4152 :: SWord8 = s26 & s4150
-  s4153 :: SWord8 = if s4144 then s4151 else s4152
-  s4154 :: SWord8 = if s22 then s4153 else s4148
-  s4155 :: SWord1 = choose [0:0] s4154
-  s4156 :: SBool = s19 /= s4155
-  s4157 :: SBool = s_2 == s4156
-  s4158 :: SWord8 = s4142 >>> 1
-  s4159 :: SWord8 = s24 | s4158
-  s4160 :: SWord8 = s26 & s4158
-  s4161 :: SWord8 = if s4134 then s4159 else s4160
-  s4162 :: SWord8 = s4161 >>> 1
-  s4163 :: SWord8 = s24 | s4162
-  s4164 :: SWord8 = s26 & s4162
-  s4165 :: SWord8 = if s4156 then s4163 else s4164
-  s4166 :: SWord1 = choose [0:0] s4149
-  s4167 :: SBool = s19 /= s4166
-  s4168 :: SWord8 = s4154 >>> 1
-  s4169 :: SWord8 = s24 | s4168
-  s4170 :: SWord8 = s26 & s4168
-  s4171 :: SWord8 = if s4167 then s4169 else s4170
-  s4172 :: SWord8 = if s29 then s4131 else s4079
-  s4173 :: SWord8 = if s170 then s4148 else s4172
-  s4174 :: SWord8 = if s29 then s4153 else s4173
-  s4175 :: SWord8 = if s170 then s4171 else s4174
-  s4176 :: SWord8 = s4161 + s4175
-  s4177 :: SBool = s4176 < s4175
-  s4178 :: SBool = s4176 < s4161
-  s4179 :: SBool = s4177 | s4178
-  s4180 :: SWord8 = s4176 >>> 1
-  s4181 :: SWord8 = s24 | s4180
-  s4182 :: SWord8 = s26 & s4180
-  s4183 :: SWord8 = if s4179 then s4181 else s4182
-  s4184 :: SWord8 = if s4157 then s4165 else s4183
-  s4185 :: SWord8 = s4142 + s4173
-  s4186 :: SWord1 = choose [0:0] s4185
-  s4187 :: SBool = s19 /= s4186
-  s4188 :: SWord8 = if s4187 then s4151 else s4152
-  s4189 :: SWord8 = if s22 then s4188 else s4148
-  s4190 :: SWord1 = choose [0:0] s4189
-  s4191 :: SBool = s19 /= s4190
-  s4192 :: SBool = s_2 == s4191
-  s4193 :: SBool = s4185 < s4173
-  s4194 :: SBool = s4185 < s4142
-  s4195 :: SBool = s4193 | s4194
-  s4196 :: SWord8 = s4185 >>> 1
-  s4197 :: SWord8 = s24 | s4196
-  s4198 :: SWord8 = s26 & s4196
-  s4199 :: SWord8 = if s4195 then s4197 else s4198
-  s4200 :: SWord8 = s4199 >>> 1
-  s4201 :: SWord8 = s24 | s4200
-  s4202 :: SWord8 = s26 & s4200
-  s4203 :: SWord8 = if s4191 then s4201 else s4202
-  s4204 :: SWord8 = s4189 >>> 1
-  s4205 :: SWord8 = s24 | s4204
-  s4206 :: SWord8 = s26 & s4204
-  s4207 :: SWord8 = if s4167 then s4205 else s4206
-  s4208 :: SWord8 = if s29 then s4188 else s4173
-  s4209 :: SWord8 = if s170 then s4207 else s4208
-  s4210 :: SWord8 = s4199 + s4209
-  s4211 :: SBool = s4210 < s4209
-  s4212 :: SBool = s4210 < s4199
-  s4213 :: SBool = s4211 | s4212
-  s4214 :: SWord8 = s4210 >>> 1
-  s4215 :: SWord8 = s24 | s4214
-  s4216 :: SWord8 = s26 & s4214
-  s4217 :: SWord8 = if s4213 then s4215 else s4216
-  s4218 :: SWord8 = if s4192 then s4203 else s4217
-  s4219 :: SWord8 = if s4135 then s4184 else s4218
-  s4220 :: SWord8 = if s4020 then s4127 else s4219
-  s4221 :: SWord8 = if s3784 then s4012 else s4220
-  s4222 :: SWord8 = s3767 + s3867
-  s4223 :: SWord1 = choose [0:0] s4222
-  s4224 :: SBool = s19 /= s4223
-  s4225 :: SWord8 = if s4224 then s3778 else s3779
-  s4226 :: SWord8 = if s22 then s4225 else s3775
-  s4227 :: SWord1 = choose [0:0] s4226
-  s4228 :: SBool = s19 /= s4227
-  s4229 :: SBool = s_2 == s4228
-  s4230 :: SBool = s4222 < s3867
-  s4231 :: SBool = s4222 < s3767
-  s4232 :: SBool = s4230 | s4231
-  s4233 :: SWord8 = s4222 >>> 1
-  s4234 :: SWord8 = s24 | s4233
-  s4235 :: SWord8 = s26 & s4233
-  s4236 :: SWord8 = if s4232 then s4234 else s4235
-  s4237 :: SWord1 = choose [0:0] s4236
-  s4238 :: SBool = s19 /= s4237
-  s4239 :: SWord8 = s4226 >>> 1
-  s4240 :: SWord8 = s24 | s4239
-  s4241 :: SWord8 = s26 & s4239
-  s4242 :: SWord8 = if s3792 then s4240 else s4241
-  s4243 :: SWord8 = if s22 then s4242 else s4225
-  s4244 :: SWord8 = s4243 >>> 1
-  s4245 :: SWord8 = s24 | s4244
-  s4246 :: SWord8 = s26 & s4244
-  s4247 :: SWord8 = if s4238 then s4245 else s4246
-  s4248 :: SWord8 = if s22 then s4247 else s4242
-  s4249 :: SWord1 = choose [0:0] s4248
-  s4250 :: SBool = s19 /= s4249
-  s4251 :: SBool = s_2 == s4250
-  s4252 :: SWord8 = s4236 >>> 1
-  s4253 :: SWord8 = s24 | s4252
-  s4254 :: SWord8 = s26 & s4252
-  s4255 :: SWord8 = if s4228 then s4253 else s4254
-  s4256 :: SWord1 = choose [0:0] s4255
-  s4257 :: SBool = s19 /= s4256
-  s4258 :: SWord1 = choose [0:0] s4243
-  s4259 :: SBool = s19 /= s4258
-  s4260 :: SWord8 = s4248 >>> 1
-  s4261 :: SWord8 = s24 | s4260
-  s4262 :: SWord8 = s26 & s4260
-  s4263 :: SWord8 = if s4259 then s4261 else s4262
-  s4264 :: SWord8 = if s22 then s4263 else s4247
-  s4265 :: SWord8 = s4264 >>> 1
-  s4266 :: SWord8 = s24 | s4265
-  s4267 :: SWord8 = s26 & s4265
-  s4268 :: SWord8 = if s4257 then s4266 else s4267
-  s4269 :: SWord8 = if s22 then s4268 else s4263
-  s4270 :: SWord1 = choose [0:0] s4269
-  s4271 :: SBool = s19 /= s4270
-  s4272 :: SBool = s_2 == s4271
-  s4273 :: SWord8 = s4255 >>> 1
-  s4274 :: SWord8 = s24 | s4273
-  s4275 :: SWord8 = s26 & s4273
-  s4276 :: SWord8 = if s4250 then s4274 else s4275
-  s4277 :: SWord1 = choose [0:0] s4276
-  s4278 :: SBool = s19 /= s4277
-  s4279 :: SWord1 = choose [0:0] s4264
-  s4280 :: SBool = s19 /= s4279
-  s4281 :: SWord8 = s4269 >>> 1
-  s4282 :: SWord8 = s24 | s4281
-  s4283 :: SWord8 = s26 & s4281
-  s4284 :: SWord8 = if s4280 then s4282 else s4283
-  s4285 :: SWord8 = if s22 then s4284 else s4268
-  s4286 :: SWord8 = s4285 >>> 1
-  s4287 :: SWord8 = s24 | s4286
-  s4288 :: SWord8 = s26 & s4286
-  s4289 :: SWord8 = if s4278 then s4287 else s4288
-  s4290 :: SWord8 = if s22 then s4289 else s4284
-  s4291 :: SWord1 = choose [0:0] s4290
-  s4292 :: SBool = s19 /= s4291
-  s4293 :: SBool = s_2 == s4292
-  s4294 :: SWord8 = s4276 >>> 1
-  s4295 :: SWord8 = s24 | s4294
-  s4296 :: SWord8 = s26 & s4294
-  s4297 :: SWord8 = if s4271 then s4295 else s4296
-  s4298 :: SWord8 = s4297 >>> 1
-  s4299 :: SWord8 = s24 | s4298
-  s4300 :: SWord8 = s26 & s4298
-  s4301 :: SWord8 = if s4292 then s4299 else s4300
-  s4302 :: SWord1 = choose [0:0] s4285
-  s4303 :: SBool = s19 /= s4302
-  s4304 :: SWord8 = s4290 >>> 1
-  s4305 :: SWord8 = s24 | s4304
-  s4306 :: SWord8 = s26 & s4304
-  s4307 :: SWord8 = if s4303 then s4305 else s4306
-  s4308 :: SWord8 = if s29 then s4225 else s3867
-  s4309 :: SWord8 = if s170 then s4242 else s4308
-  s4310 :: SWord8 = if s29 then s4247 else s4309
-  s4311 :: SWord8 = if s170 then s4263 else s4310
-  s4312 :: SWord8 = if s29 then s4268 else s4311
-  s4313 :: SWord8 = if s170 then s4284 else s4312
-  s4314 :: SWord8 = if s29 then s4289 else s4313
-  s4315 :: SWord8 = if s170 then s4307 else s4314
-  s4316 :: SWord8 = s4297 + s4315
-  s4317 :: SBool = s4316 < s4315
-  s4318 :: SBool = s4316 < s4297
-  s4319 :: SBool = s4317 | s4318
-  s4320 :: SWord8 = s4316 >>> 1
-  s4321 :: SWord8 = s24 | s4320
-  s4322 :: SWord8 = s26 & s4320
-  s4323 :: SWord8 = if s4319 then s4321 else s4322
-  s4324 :: SWord8 = if s4293 then s4301 else s4323
-  s4325 :: SWord8 = s4276 + s4313
-  s4326 :: SWord1 = choose [0:0] s4325
-  s4327 :: SBool = s19 /= s4326
-  s4328 :: SWord8 = if s4327 then s4287 else s4288
-  s4329 :: SWord8 = if s22 then s4328 else s4284
-  s4330 :: SWord1 = choose [0:0] s4329
-  s4331 :: SBool = s19 /= s4330
-  s4332 :: SBool = s_2 == s4331
-  s4333 :: SBool = s4325 < s4313
-  s4334 :: SBool = s4325 < s4276
-  s4335 :: SBool = s4333 | s4334
-  s4336 :: SWord8 = s4325 >>> 1
-  s4337 :: SWord8 = s24 | s4336
-  s4338 :: SWord8 = s26 & s4336
-  s4339 :: SWord8 = if s4335 then s4337 else s4338
-  s4340 :: SWord8 = s4339 >>> 1
-  s4341 :: SWord8 = s24 | s4340
-  s4342 :: SWord8 = s26 & s4340
-  s4343 :: SWord8 = if s4331 then s4341 else s4342
-  s4344 :: SWord8 = s4329 >>> 1
-  s4345 :: SWord8 = s24 | s4344
-  s4346 :: SWord8 = s26 & s4344
-  s4347 :: SWord8 = if s4303 then s4345 else s4346
-  s4348 :: SWord8 = if s29 then s4328 else s4313
-  s4349 :: SWord8 = if s170 then s4347 else s4348
-  s4350 :: SWord8 = s4339 + s4349
-  s4351 :: SBool = s4350 < s4349
-  s4352 :: SBool = s4350 < s4339
-  s4353 :: SBool = s4351 | s4352
-  s4354 :: SWord8 = s4350 >>> 1
-  s4355 :: SWord8 = s24 | s4354
-  s4356 :: SWord8 = s26 & s4354
-  s4357 :: SWord8 = if s4353 then s4355 else s4356
-  s4358 :: SWord8 = if s4332 then s4343 else s4357
-  s4359 :: SWord8 = if s4272 then s4324 else s4358
-  s4360 :: SWord8 = s4255 + s4311
-  s4361 :: SWord1 = choose [0:0] s4360
-  s4362 :: SBool = s19 /= s4361
-  s4363 :: SWord8 = if s4362 then s4266 else s4267
-  s4364 :: SWord8 = if s22 then s4363 else s4263
-  s4365 :: SWord1 = choose [0:0] s4364
-  s4366 :: SBool = s19 /= s4365
-  s4367 :: SBool = s_2 == s4366
-  s4368 :: SBool = s4360 < s4311
-  s4369 :: SBool = s4360 < s4255
-  s4370 :: SBool = s4368 | s4369
-  s4371 :: SWord8 = s4360 >>> 1
-  s4372 :: SWord8 = s24 | s4371
-  s4373 :: SWord8 = s26 & s4371
-  s4374 :: SWord8 = if s4370 then s4372 else s4373
-  s4375 :: SWord1 = choose [0:0] s4374
-  s4376 :: SBool = s19 /= s4375
-  s4377 :: SWord8 = s4364 >>> 1
-  s4378 :: SWord8 = s24 | s4377
-  s4379 :: SWord8 = s26 & s4377
-  s4380 :: SWord8 = if s4280 then s4378 else s4379
-  s4381 :: SWord8 = if s22 then s4380 else s4363
-  s4382 :: SWord8 = s4381 >>> 1
-  s4383 :: SWord8 = s24 | s4382
-  s4384 :: SWord8 = s26 & s4382
-  s4385 :: SWord8 = if s4376 then s4383 else s4384
-  s4386 :: SWord8 = if s22 then s4385 else s4380
-  s4387 :: SWord1 = choose [0:0] s4386
-  s4388 :: SBool = s19 /= s4387
-  s4389 :: SBool = s_2 == s4388
-  s4390 :: SWord8 = s4374 >>> 1
-  s4391 :: SWord8 = s24 | s4390
-  s4392 :: SWord8 = s26 & s4390
-  s4393 :: SWord8 = if s4366 then s4391 else s4392
-  s4394 :: SWord8 = s4393 >>> 1
-  s4395 :: SWord8 = s24 | s4394
-  s4396 :: SWord8 = s26 & s4394
-  s4397 :: SWord8 = if s4388 then s4395 else s4396
-  s4398 :: SWord1 = choose [0:0] s4381
-  s4399 :: SBool = s19 /= s4398
-  s4400 :: SWord8 = s4386 >>> 1
-  s4401 :: SWord8 = s24 | s4400
-  s4402 :: SWord8 = s26 & s4400
-  s4403 :: SWord8 = if s4399 then s4401 else s4402
-  s4404 :: SWord8 = if s29 then s4363 else s4311
-  s4405 :: SWord8 = if s170 then s4380 else s4404
-  s4406 :: SWord8 = if s29 then s4385 else s4405
-  s4407 :: SWord8 = if s170 then s4403 else s4406
-  s4408 :: SWord8 = s4393 + s4407
-  s4409 :: SBool = s4408 < s4407
-  s4410 :: SBool = s4408 < s4393
-  s4411 :: SBool = s4409 | s4410
-  s4412 :: SWord8 = s4408 >>> 1
-  s4413 :: SWord8 = s24 | s4412
-  s4414 :: SWord8 = s26 & s4412
-  s4415 :: SWord8 = if s4411 then s4413 else s4414
-  s4416 :: SWord8 = if s4389 then s4397 else s4415
-  s4417 :: SWord8 = s4374 + s4405
-  s4418 :: SWord1 = choose [0:0] s4417
-  s4419 :: SBool = s19 /= s4418
-  s4420 :: SWord8 = if s4419 then s4383 else s4384
-  s4421 :: SWord8 = if s22 then s4420 else s4380
-  s4422 :: SWord1 = choose [0:0] s4421
-  s4423 :: SBool = s19 /= s4422
-  s4424 :: SBool = s_2 == s4423
-  s4425 :: SBool = s4417 < s4405
-  s4426 :: SBool = s4417 < s4374
-  s4427 :: SBool = s4425 | s4426
-  s4428 :: SWord8 = s4417 >>> 1
-  s4429 :: SWord8 = s24 | s4428
-  s4430 :: SWord8 = s26 & s4428
-  s4431 :: SWord8 = if s4427 then s4429 else s4430
-  s4432 :: SWord8 = s4431 >>> 1
-  s4433 :: SWord8 = s24 | s4432
-  s4434 :: SWord8 = s26 & s4432
-  s4435 :: SWord8 = if s4423 then s4433 else s4434
-  s4436 :: SWord8 = s4421 >>> 1
-  s4437 :: SWord8 = s24 | s4436
-  s4438 :: SWord8 = s26 & s4436
-  s4439 :: SWord8 = if s4399 then s4437 else s4438
-  s4440 :: SWord8 = if s29 then s4420 else s4405
-  s4441 :: SWord8 = if s170 then s4439 else s4440
-  s4442 :: SWord8 = s4431 + s4441
-  s4443 :: SBool = s4442 < s4441
-  s4444 :: SBool = s4442 < s4431
-  s4445 :: SBool = s4443 | s4444
-  s4446 :: SWord8 = s4442 >>> 1
-  s4447 :: SWord8 = s24 | s4446
-  s4448 :: SWord8 = s26 & s4446
-  s4449 :: SWord8 = if s4445 then s4447 else s4448
-  s4450 :: SWord8 = if s4424 then s4435 else s4449
-  s4451 :: SWord8 = if s4367 then s4416 else s4450
-  s4452 :: SWord8 = if s4251 then s4359 else s4451
-  s4453 :: SWord8 = s4236 + s4309
-  s4454 :: SWord1 = choose [0:0] s4453
-  s4455 :: SBool = s19 /= s4454
-  s4456 :: SWord8 = if s4455 then s4245 else s4246
-  s4457 :: SWord8 = if s22 then s4456 else s4242
-  s4458 :: SWord1 = choose [0:0] s4457
-  s4459 :: SBool = s19 /= s4458
-  s4460 :: SBool = s_2 == s4459
-  s4461 :: SBool = s4453 < s4309
-  s4462 :: SBool = s4453 < s4236
-  s4463 :: SBool = s4461 | s4462
-  s4464 :: SWord8 = s4453 >>> 1
-  s4465 :: SWord8 = s24 | s4464
-  s4466 :: SWord8 = s26 & s4464
-  s4467 :: SWord8 = if s4463 then s4465 else s4466
-  s4468 :: SWord1 = choose [0:0] s4467
-  s4469 :: SBool = s19 /= s4468
-  s4470 :: SWord8 = s4457 >>> 1
-  s4471 :: SWord8 = s24 | s4470
-  s4472 :: SWord8 = s26 & s4470
-  s4473 :: SWord8 = if s4259 then s4471 else s4472
-  s4474 :: SWord8 = if s22 then s4473 else s4456
-  s4475 :: SWord8 = s4474 >>> 1
-  s4476 :: SWord8 = s24 | s4475
-  s4477 :: SWord8 = s26 & s4475
-  s4478 :: SWord8 = if s4469 then s4476 else s4477
-  s4479 :: SWord8 = if s22 then s4478 else s4473
-  s4480 :: SWord1 = choose [0:0] s4479
-  s4481 :: SBool = s19 /= s4480
-  s4482 :: SBool = s_2 == s4481
-  s4483 :: SWord8 = s4467 >>> 1
-  s4484 :: SWord8 = s24 | s4483
-  s4485 :: SWord8 = s26 & s4483
-  s4486 :: SWord8 = if s4459 then s4484 else s4485
-  s4487 :: SWord1 = choose [0:0] s4486
-  s4488 :: SBool = s19 /= s4487
-  s4489 :: SWord1 = choose [0:0] s4474
-  s4490 :: SBool = s19 /= s4489
-  s4491 :: SWord8 = s4479 >>> 1
-  s4492 :: SWord8 = s24 | s4491
-  s4493 :: SWord8 = s26 & s4491
-  s4494 :: SWord8 = if s4490 then s4492 else s4493
-  s4495 :: SWord8 = if s22 then s4494 else s4478
-  s4496 :: SWord8 = s4495 >>> 1
-  s4497 :: SWord8 = s24 | s4496
-  s4498 :: SWord8 = s26 & s4496
-  s4499 :: SWord8 = if s4488 then s4497 else s4498
-  s4500 :: SWord8 = if s22 then s4499 else s4494
-  s4501 :: SWord1 = choose [0:0] s4500
-  s4502 :: SBool = s19 /= s4501
-  s4503 :: SBool = s_2 == s4502
-  s4504 :: SWord8 = s4486 >>> 1
-  s4505 :: SWord8 = s24 | s4504
-  s4506 :: SWord8 = s26 & s4504
-  s4507 :: SWord8 = if s4481 then s4505 else s4506
-  s4508 :: SWord8 = s4507 >>> 1
-  s4509 :: SWord8 = s24 | s4508
-  s4510 :: SWord8 = s26 & s4508
-  s4511 :: SWord8 = if s4502 then s4509 else s4510
-  s4512 :: SWord1 = choose [0:0] s4495
-  s4513 :: SBool = s19 /= s4512
-  s4514 :: SWord8 = s4500 >>> 1
-  s4515 :: SWord8 = s24 | s4514
-  s4516 :: SWord8 = s26 & s4514
-  s4517 :: SWord8 = if s4513 then s4515 else s4516
-  s4518 :: SWord8 = if s29 then s4456 else s4309
-  s4519 :: SWord8 = if s170 then s4473 else s4518
-  s4520 :: SWord8 = if s29 then s4478 else s4519
-  s4521 :: SWord8 = if s170 then s4494 else s4520
-  s4522 :: SWord8 = if s29 then s4499 else s4521
-  s4523 :: SWord8 = if s170 then s4517 else s4522
-  s4524 :: SWord8 = s4507 + s4523
-  s4525 :: SBool = s4524 < s4523
-  s4526 :: SBool = s4524 < s4507
-  s4527 :: SBool = s4525 | s4526
-  s4528 :: SWord8 = s4524 >>> 1
-  s4529 :: SWord8 = s24 | s4528
-  s4530 :: SWord8 = s26 & s4528
-  s4531 :: SWord8 = if s4527 then s4529 else s4530
-  s4532 :: SWord8 = if s4503 then s4511 else s4531
-  s4533 :: SWord8 = s4486 + s4521
-  s4534 :: SWord1 = choose [0:0] s4533
-  s4535 :: SBool = s19 /= s4534
-  s4536 :: SWord8 = if s4535 then s4497 else s4498
-  s4537 :: SWord8 = if s22 then s4536 else s4494
-  s4538 :: SWord1 = choose [0:0] s4537
-  s4539 :: SBool = s19 /= s4538
-  s4540 :: SBool = s_2 == s4539
-  s4541 :: SBool = s4533 < s4521
-  s4542 :: SBool = s4533 < s4486
-  s4543 :: SBool = s4541 | s4542
-  s4544 :: SWord8 = s4533 >>> 1
-  s4545 :: SWord8 = s24 | s4544
-  s4546 :: SWord8 = s26 & s4544
-  s4547 :: SWord8 = if s4543 then s4545 else s4546
-  s4548 :: SWord8 = s4547 >>> 1
-  s4549 :: SWord8 = s24 | s4548
-  s4550 :: SWord8 = s26 & s4548
-  s4551 :: SWord8 = if s4539 then s4549 else s4550
-  s4552 :: SWord8 = s4537 >>> 1
-  s4553 :: SWord8 = s24 | s4552
-  s4554 :: SWord8 = s26 & s4552
-  s4555 :: SWord8 = if s4513 then s4553 else s4554
-  s4556 :: SWord8 = if s29 then s4536 else s4521
-  s4557 :: SWord8 = if s170 then s4555 else s4556
-  s4558 :: SWord8 = s4547 + s4557
-  s4559 :: SBool = s4558 < s4557
-  s4560 :: SBool = s4558 < s4547
-  s4561 :: SBool = s4559 | s4560
-  s4562 :: SWord8 = s4558 >>> 1
-  s4563 :: SWord8 = s24 | s4562
-  s4564 :: SWord8 = s26 & s4562
-  s4565 :: SWord8 = if s4561 then s4563 else s4564
-  s4566 :: SWord8 = if s4540 then s4551 else s4565
-  s4567 :: SWord8 = if s4482 then s4532 else s4566
-  s4568 :: SWord8 = s4467 + s4519
-  s4569 :: SWord1 = choose [0:0] s4568
-  s4570 :: SBool = s19 /= s4569
-  s4571 :: SWord8 = if s4570 then s4476 else s4477
-  s4572 :: SWord8 = if s22 then s4571 else s4473
-  s4573 :: SWord1 = choose [0:0] s4572
-  s4574 :: SBool = s19 /= s4573
-  s4575 :: SBool = s_2 == s4574
-  s4576 :: SBool = s4568 < s4519
-  s4577 :: SBool = s4568 < s4467
-  s4578 :: SBool = s4576 | s4577
-  s4579 :: SWord8 = s4568 >>> 1
-  s4580 :: SWord8 = s24 | s4579
-  s4581 :: SWord8 = s26 & s4579
-  s4582 :: SWord8 = if s4578 then s4580 else s4581
-  s4583 :: SWord1 = choose [0:0] s4582
-  s4584 :: SBool = s19 /= s4583
-  s4585 :: SWord8 = s4572 >>> 1
-  s4586 :: SWord8 = s24 | s4585
-  s4587 :: SWord8 = s26 & s4585
-  s4588 :: SWord8 = if s4490 then s4586 else s4587
-  s4589 :: SWord8 = if s22 then s4588 else s4571
-  s4590 :: SWord8 = s4589 >>> 1
-  s4591 :: SWord8 = s24 | s4590
-  s4592 :: SWord8 = s26 & s4590
-  s4593 :: SWord8 = if s4584 then s4591 else s4592
-  s4594 :: SWord8 = if s22 then s4593 else s4588
-  s4595 :: SWord1 = choose [0:0] s4594
-  s4596 :: SBool = s19 /= s4595
-  s4597 :: SBool = s_2 == s4596
-  s4598 :: SWord8 = s4582 >>> 1
-  s4599 :: SWord8 = s24 | s4598
-  s4600 :: SWord8 = s26 & s4598
-  s4601 :: SWord8 = if s4574 then s4599 else s4600
-  s4602 :: SWord8 = s4601 >>> 1
-  s4603 :: SWord8 = s24 | s4602
-  s4604 :: SWord8 = s26 & s4602
-  s4605 :: SWord8 = if s4596 then s4603 else s4604
-  s4606 :: SWord1 = choose [0:0] s4589
-  s4607 :: SBool = s19 /= s4606
-  s4608 :: SWord8 = s4594 >>> 1
-  s4609 :: SWord8 = s24 | s4608
-  s4610 :: SWord8 = s26 & s4608
-  s4611 :: SWord8 = if s4607 then s4609 else s4610
-  s4612 :: SWord8 = if s29 then s4571 else s4519
-  s4613 :: SWord8 = if s170 then s4588 else s4612
-  s4614 :: SWord8 = if s29 then s4593 else s4613
-  s4615 :: SWord8 = if s170 then s4611 else s4614
-  s4616 :: SWord8 = s4601 + s4615
-  s4617 :: SBool = s4616 < s4615
-  s4618 :: SBool = s4616 < s4601
-  s4619 :: SBool = s4617 | s4618
-  s4620 :: SWord8 = s4616 >>> 1
-  s4621 :: SWord8 = s24 | s4620
-  s4622 :: SWord8 = s26 & s4620
-  s4623 :: SWord8 = if s4619 then s4621 else s4622
-  s4624 :: SWord8 = if s4597 then s4605 else s4623
-  s4625 :: SWord8 = s4582 + s4613
-  s4626 :: SWord1 = choose [0:0] s4625
-  s4627 :: SBool = s19 /= s4626
-  s4628 :: SWord8 = if s4627 then s4591 else s4592
-  s4629 :: SWord8 = if s22 then s4628 else s4588
-  s4630 :: SWord1 = choose [0:0] s4629
-  s4631 :: SBool = s19 /= s4630
-  s4632 :: SBool = s_2 == s4631
-  s4633 :: SBool = s4625 < s4613
-  s4634 :: SBool = s4625 < s4582
-  s4635 :: SBool = s4633 | s4634
-  s4636 :: SWord8 = s4625 >>> 1
-  s4637 :: SWord8 = s24 | s4636
-  s4638 :: SWord8 = s26 & s4636
-  s4639 :: SWord8 = if s4635 then s4637 else s4638
-  s4640 :: SWord8 = s4639 >>> 1
-  s4641 :: SWord8 = s24 | s4640
-  s4642 :: SWord8 = s26 & s4640
-  s4643 :: SWord8 = if s4631 then s4641 else s4642
-  s4644 :: SWord8 = s4629 >>> 1
-  s4645 :: SWord8 = s24 | s4644
-  s4646 :: SWord8 = s26 & s4644
-  s4647 :: SWord8 = if s4607 then s4645 else s4646
-  s4648 :: SWord8 = if s29 then s4628 else s4613
-  s4649 :: SWord8 = if s170 then s4647 else s4648
-  s4650 :: SWord8 = s4639 + s4649
-  s4651 :: SBool = s4650 < s4649
-  s4652 :: SBool = s4650 < s4639
-  s4653 :: SBool = s4651 | s4652
-  s4654 :: SWord8 = s4650 >>> 1
-  s4655 :: SWord8 = s24 | s4654
-  s4656 :: SWord8 = s26 & s4654
-  s4657 :: SWord8 = if s4653 then s4655 else s4656
-  s4658 :: SWord8 = if s4632 then s4643 else s4657
-  s4659 :: SWord8 = if s4575 then s4624 else s4658
-  s4660 :: SWord8 = if s4460 then s4567 else s4659
-  s4661 :: SWord8 = if s4229 then s4452 else s4660
-  s4662 :: SWord8 = if s3763 then s4221 else s4661
-  s4663 :: SWord8 = s3746 + s3865
-  s4664 :: SWord1 = choose [0:0] s4663
-  s4665 :: SBool = s19 /= s4664
-  s4666 :: SWord8 = if s4665 then s3757 else s3758
-  s4667 :: SWord8 = if s22 then s4666 else s3754
-  s4668 :: SWord1 = choose [0:0] s4667
-  s4669 :: SBool = s19 /= s4668
-  s4670 :: SBool = s_2 == s4669
-  s4671 :: SBool = s4663 < s3865
-  s4672 :: SBool = s4663 < s3746
-  s4673 :: SBool = s4671 | s4672
-  s4674 :: SWord8 = s4663 >>> 1
-  s4675 :: SWord8 = s24 | s4674
-  s4676 :: SWord8 = s26 & s4674
-  s4677 :: SWord8 = if s4673 then s4675 else s4676
-  s4678 :: SWord1 = choose [0:0] s4677
-  s4679 :: SBool = s19 /= s4678
-  s4680 :: SWord8 = s4667 >>> 1
-  s4681 :: SWord8 = s24 | s4680
-  s4682 :: SWord8 = s26 & s4680
-  s4683 :: SWord8 = if s3771 then s4681 else s4682
-  s4684 :: SWord8 = if s22 then s4683 else s4666
-  s4685 :: SWord8 = s4684 >>> 1
-  s4686 :: SWord8 = s24 | s4685
-  s4687 :: SWord8 = s26 & s4685
-  s4688 :: SWord8 = if s4679 then s4686 else s4687
-  s4689 :: SWord8 = if s22 then s4688 else s4683
-  s4690 :: SWord1 = choose [0:0] s4689
-  s4691 :: SBool = s19 /= s4690
-  s4692 :: SBool = s_2 == s4691
-  s4693 :: SWord8 = s4677 >>> 1
-  s4694 :: SWord8 = s24 | s4693
-  s4695 :: SWord8 = s26 & s4693
-  s4696 :: SWord8 = if s4669 then s4694 else s4695
-  s4697 :: SWord1 = choose [0:0] s4696
-  s4698 :: SBool = s19 /= s4697
-  s4699 :: SWord1 = choose [0:0] s4684
-  s4700 :: SBool = s19 /= s4699
-  s4701 :: SWord8 = s4689 >>> 1
-  s4702 :: SWord8 = s24 | s4701
-  s4703 :: SWord8 = s26 & s4701
-  s4704 :: SWord8 = if s4700 then s4702 else s4703
-  s4705 :: SWord8 = if s22 then s4704 else s4688
-  s4706 :: SWord8 = s4705 >>> 1
-  s4707 :: SWord8 = s24 | s4706
-  s4708 :: SWord8 = s26 & s4706
-  s4709 :: SWord8 = if s4698 then s4707 else s4708
-  s4710 :: SWord8 = if s22 then s4709 else s4704
-  s4711 :: SWord1 = choose [0:0] s4710
-  s4712 :: SBool = s19 /= s4711
-  s4713 :: SBool = s_2 == s4712
-  s4714 :: SWord8 = s4696 >>> 1
-  s4715 :: SWord8 = s24 | s4714
-  s4716 :: SWord8 = s26 & s4714
-  s4717 :: SWord8 = if s4691 then s4715 else s4716
-  s4718 :: SWord1 = choose [0:0] s4717
-  s4719 :: SBool = s19 /= s4718
-  s4720 :: SWord1 = choose [0:0] s4705
-  s4721 :: SBool = s19 /= s4720
-  s4722 :: SWord8 = s4710 >>> 1
-  s4723 :: SWord8 = s24 | s4722
-  s4724 :: SWord8 = s26 & s4722
-  s4725 :: SWord8 = if s4721 then s4723 else s4724
-  s4726 :: SWord8 = if s22 then s4725 else s4709
-  s4727 :: SWord8 = s4726 >>> 1
-  s4728 :: SWord8 = s24 | s4727
-  s4729 :: SWord8 = s26 & s4727
-  s4730 :: SWord8 = if s4719 then s4728 else s4729
-  s4731 :: SWord8 = if s22 then s4730 else s4725
-  s4732 :: SWord1 = choose [0:0] s4731
-  s4733 :: SBool = s19 /= s4732
-  s4734 :: SBool = s_2 == s4733
-  s4735 :: SWord8 = s4717 >>> 1
-  s4736 :: SWord8 = s24 | s4735
-  s4737 :: SWord8 = s26 & s4735
-  s4738 :: SWord8 = if s4712 then s4736 else s4737
-  s4739 :: SWord1 = choose [0:0] s4738
-  s4740 :: SBool = s19 /= s4739
-  s4741 :: SWord1 = choose [0:0] s4726
-  s4742 :: SBool = s19 /= s4741
-  s4743 :: SWord8 = s4731 >>> 1
-  s4744 :: SWord8 = s24 | s4743
-  s4745 :: SWord8 = s26 & s4743
-  s4746 :: SWord8 = if s4742 then s4744 else s4745
-  s4747 :: SWord8 = if s22 then s4746 else s4730
-  s4748 :: SWord8 = s4747 >>> 1
-  s4749 :: SWord8 = s24 | s4748
-  s4750 :: SWord8 = s26 & s4748
-  s4751 :: SWord8 = if s4740 then s4749 else s4750
-  s4752 :: SWord8 = if s22 then s4751 else s4746
-  s4753 :: SWord1 = choose [0:0] s4752
-  s4754 :: SBool = s19 /= s4753
-  s4755 :: SBool = s_2 == s4754
-  s4756 :: SWord8 = s4738 >>> 1
-  s4757 :: SWord8 = s24 | s4756
-  s4758 :: SWord8 = s26 & s4756
-  s4759 :: SWord8 = if s4733 then s4757 else s4758
-  s4760 :: SWord8 = s4759 >>> 1
-  s4761 :: SWord8 = s24 | s4760
-  s4762 :: SWord8 = s26 & s4760
-  s4763 :: SWord8 = if s4754 then s4761 else s4762
-  s4764 :: SWord1 = choose [0:0] s4747
-  s4765 :: SBool = s19 /= s4764
-  s4766 :: SWord8 = s4752 >>> 1
-  s4767 :: SWord8 = s24 | s4766
-  s4768 :: SWord8 = s26 & s4766
-  s4769 :: SWord8 = if s4765 then s4767 else s4768
-  s4770 :: SWord8 = if s29 then s4666 else s3865
-  s4771 :: SWord8 = if s170 then s4683 else s4770
-  s4772 :: SWord8 = if s29 then s4688 else s4771
-  s4773 :: SWord8 = if s170 then s4704 else s4772
-  s4774 :: SWord8 = if s29 then s4709 else s4773
-  s4775 :: SWord8 = if s170 then s4725 else s4774
-  s4776 :: SWord8 = if s29 then s4730 else s4775
-  s4777 :: SWord8 = if s170 then s4746 else s4776
-  s4778 :: SWord8 = if s29 then s4751 else s4777
-  s4779 :: SWord8 = if s170 then s4769 else s4778
-  s4780 :: SWord8 = s4759 + s4779
-  s4781 :: SBool = s4780 < s4779
-  s4782 :: SBool = s4780 < s4759
-  s4783 :: SBool = s4781 | s4782
-  s4784 :: SWord8 = s4780 >>> 1
-  s4785 :: SWord8 = s24 | s4784
-  s4786 :: SWord8 = s26 & s4784
-  s4787 :: SWord8 = if s4783 then s4785 else s4786
-  s4788 :: SWord8 = if s4755 then s4763 else s4787
-  s4789 :: SWord8 = s4738 + s4777
-  s4790 :: SWord1 = choose [0:0] s4789
-  s4791 :: SBool = s19 /= s4790
-  s4792 :: SWord8 = if s4791 then s4749 else s4750
-  s4793 :: SWord8 = if s22 then s4792 else s4746
-  s4794 :: SWord1 = choose [0:0] s4793
-  s4795 :: SBool = s19 /= s4794
-  s4796 :: SBool = s_2 == s4795
-  s4797 :: SBool = s4789 < s4777
-  s4798 :: SBool = s4789 < s4738
-  s4799 :: SBool = s4797 | s4798
-  s4800 :: SWord8 = s4789 >>> 1
-  s4801 :: SWord8 = s24 | s4800
-  s4802 :: SWord8 = s26 & s4800
-  s4803 :: SWord8 = if s4799 then s4801 else s4802
-  s4804 :: SWord8 = s4803 >>> 1
-  s4805 :: SWord8 = s24 | s4804
-  s4806 :: SWord8 = s26 & s4804
-  s4807 :: SWord8 = if s4795 then s4805 else s4806
-  s4808 :: SWord8 = s4793 >>> 1
-  s4809 :: SWord8 = s24 | s4808
-  s4810 :: SWord8 = s26 & s4808
-  s4811 :: SWord8 = if s4765 then s4809 else s4810
-  s4812 :: SWord8 = if s29 then s4792 else s4777
-  s4813 :: SWord8 = if s170 then s4811 else s4812
-  s4814 :: SWord8 = s4803 + s4813
-  s4815 :: SBool = s4814 < s4813
-  s4816 :: SBool = s4814 < s4803
-  s4817 :: SBool = s4815 | s4816
-  s4818 :: SWord8 = s4814 >>> 1
-  s4819 :: SWord8 = s24 | s4818
-  s4820 :: SWord8 = s26 & s4818
-  s4821 :: SWord8 = if s4817 then s4819 else s4820
-  s4822 :: SWord8 = if s4796 then s4807 else s4821
-  s4823 :: SWord8 = if s4734 then s4788 else s4822
-  s4824 :: SWord8 = s4717 + s4775
-  s4825 :: SWord1 = choose [0:0] s4824
-  s4826 :: SBool = s19 /= s4825
-  s4827 :: SWord8 = if s4826 then s4728 else s4729
-  s4828 :: SWord8 = if s22 then s4827 else s4725
-  s4829 :: SWord1 = choose [0:0] s4828
-  s4830 :: SBool = s19 /= s4829
-  s4831 :: SBool = s_2 == s4830
-  s4832 :: SBool = s4824 < s4775
-  s4833 :: SBool = s4824 < s4717
-  s4834 :: SBool = s4832 | s4833
-  s4835 :: SWord8 = s4824 >>> 1
-  s4836 :: SWord8 = s24 | s4835
-  s4837 :: SWord8 = s26 & s4835
-  s4838 :: SWord8 = if s4834 then s4836 else s4837
-  s4839 :: SWord1 = choose [0:0] s4838
-  s4840 :: SBool = s19 /= s4839
-  s4841 :: SWord8 = s4828 >>> 1
-  s4842 :: SWord8 = s24 | s4841
-  s4843 :: SWord8 = s26 & s4841
-  s4844 :: SWord8 = if s4742 then s4842 else s4843
-  s4845 :: SWord8 = if s22 then s4844 else s4827
-  s4846 :: SWord8 = s4845 >>> 1
-  s4847 :: SWord8 = s24 | s4846
-  s4848 :: SWord8 = s26 & s4846
-  s4849 :: SWord8 = if s4840 then s4847 else s4848
-  s4850 :: SWord8 = if s22 then s4849 else s4844
-  s4851 :: SWord1 = choose [0:0] s4850
-  s4852 :: SBool = s19 /= s4851
-  s4853 :: SBool = s_2 == s4852
-  s4854 :: SWord8 = s4838 >>> 1
-  s4855 :: SWord8 = s24 | s4854
-  s4856 :: SWord8 = s26 & s4854
-  s4857 :: SWord8 = if s4830 then s4855 else s4856
-  s4858 :: SWord8 = s4857 >>> 1
-  s4859 :: SWord8 = s24 | s4858
-  s4860 :: SWord8 = s26 & s4858
-  s4861 :: SWord8 = if s4852 then s4859 else s4860
-  s4862 :: SWord1 = choose [0:0] s4845
-  s4863 :: SBool = s19 /= s4862
-  s4864 :: SWord8 = s4850 >>> 1
-  s4865 :: SWord8 = s24 | s4864
-  s4866 :: SWord8 = s26 & s4864
-  s4867 :: SWord8 = if s4863 then s4865 else s4866
-  s4868 :: SWord8 = if s29 then s4827 else s4775
-  s4869 :: SWord8 = if s170 then s4844 else s4868
-  s4870 :: SWord8 = if s29 then s4849 else s4869
-  s4871 :: SWord8 = if s170 then s4867 else s4870
-  s4872 :: SWord8 = s4857 + s4871
-  s4873 :: SBool = s4872 < s4871
-  s4874 :: SBool = s4872 < s4857
-  s4875 :: SBool = s4873 | s4874
-  s4876 :: SWord8 = s4872 >>> 1
-  s4877 :: SWord8 = s24 | s4876
-  s4878 :: SWord8 = s26 & s4876
-  s4879 :: SWord8 = if s4875 then s4877 else s4878
-  s4880 :: SWord8 = if s4853 then s4861 else s4879
-  s4881 :: SWord8 = s4838 + s4869
-  s4882 :: SWord1 = choose [0:0] s4881
-  s4883 :: SBool = s19 /= s4882
-  s4884 :: SWord8 = if s4883 then s4847 else s4848
-  s4885 :: SWord8 = if s22 then s4884 else s4844
-  s4886 :: SWord1 = choose [0:0] s4885
-  s4887 :: SBool = s19 /= s4886
-  s4888 :: SBool = s_2 == s4887
-  s4889 :: SBool = s4881 < s4869
-  s4890 :: SBool = s4881 < s4838
-  s4891 :: SBool = s4889 | s4890
-  s4892 :: SWord8 = s4881 >>> 1
-  s4893 :: SWord8 = s24 | s4892
-  s4894 :: SWord8 = s26 & s4892
-  s4895 :: SWord8 = if s4891 then s4893 else s4894
-  s4896 :: SWord8 = s4895 >>> 1
-  s4897 :: SWord8 = s24 | s4896
-  s4898 :: SWord8 = s26 & s4896
-  s4899 :: SWord8 = if s4887 then s4897 else s4898
-  s4900 :: SWord8 = s4885 >>> 1
-  s4901 :: SWord8 = s24 | s4900
-  s4902 :: SWord8 = s26 & s4900
-  s4903 :: SWord8 = if s4863 then s4901 else s4902
-  s4904 :: SWord8 = if s29 then s4884 else s4869
-  s4905 :: SWord8 = if s170 then s4903 else s4904
-  s4906 :: SWord8 = s4895 + s4905
-  s4907 :: SBool = s4906 < s4905
-  s4908 :: SBool = s4906 < s4895
-  s4909 :: SBool = s4907 | s4908
-  s4910 :: SWord8 = s4906 >>> 1
-  s4911 :: SWord8 = s24 | s4910
-  s4912 :: SWord8 = s26 & s4910
-  s4913 :: SWord8 = if s4909 then s4911 else s4912
-  s4914 :: SWord8 = if s4888 then s4899 else s4913
-  s4915 :: SWord8 = if s4831 then s4880 else s4914
-  s4916 :: SWord8 = if s4713 then s4823 else s4915
-  s4917 :: SWord8 = s4696 + s4773
-  s4918 :: SWord1 = choose [0:0] s4917
-  s4919 :: SBool = s19 /= s4918
-  s4920 :: SWord8 = if s4919 then s4707 else s4708
-  s4921 :: SWord8 = if s22 then s4920 else s4704
-  s4922 :: SWord1 = choose [0:0] s4921
-  s4923 :: SBool = s19 /= s4922
-  s4924 :: SBool = s_2 == s4923
-  s4925 :: SBool = s4917 < s4773
-  s4926 :: SBool = s4917 < s4696
-  s4927 :: SBool = s4925 | s4926
-  s4928 :: SWord8 = s4917 >>> 1
-  s4929 :: SWord8 = s24 | s4928
-  s4930 :: SWord8 = s26 & s4928
-  s4931 :: SWord8 = if s4927 then s4929 else s4930
-  s4932 :: SWord1 = choose [0:0] s4931
-  s4933 :: SBool = s19 /= s4932
-  s4934 :: SWord8 = s4921 >>> 1
-  s4935 :: SWord8 = s24 | s4934
-  s4936 :: SWord8 = s26 & s4934
-  s4937 :: SWord8 = if s4721 then s4935 else s4936
-  s4938 :: SWord8 = if s22 then s4937 else s4920
-  s4939 :: SWord8 = s4938 >>> 1
-  s4940 :: SWord8 = s24 | s4939
-  s4941 :: SWord8 = s26 & s4939
-  s4942 :: SWord8 = if s4933 then s4940 else s4941
-  s4943 :: SWord8 = if s22 then s4942 else s4937
-  s4944 :: SWord1 = choose [0:0] s4943
-  s4945 :: SBool = s19 /= s4944
-  s4946 :: SBool = s_2 == s4945
-  s4947 :: SWord8 = s4931 >>> 1
-  s4948 :: SWord8 = s24 | s4947
-  s4949 :: SWord8 = s26 & s4947
-  s4950 :: SWord8 = if s4923 then s4948 else s4949
-  s4951 :: SWord1 = choose [0:0] s4950
-  s4952 :: SBool = s19 /= s4951
-  s4953 :: SWord1 = choose [0:0] s4938
-  s4954 :: SBool = s19 /= s4953
-  s4955 :: SWord8 = s4943 >>> 1
-  s4956 :: SWord8 = s24 | s4955
-  s4957 :: SWord8 = s26 & s4955
-  s4958 :: SWord8 = if s4954 then s4956 else s4957
-  s4959 :: SWord8 = if s22 then s4958 else s4942
-  s4960 :: SWord8 = s4959 >>> 1
-  s4961 :: SWord8 = s24 | s4960
-  s4962 :: SWord8 = s26 & s4960
-  s4963 :: SWord8 = if s4952 then s4961 else s4962
-  s4964 :: SWord8 = if s22 then s4963 else s4958
-  s4965 :: SWord1 = choose [0:0] s4964
-  s4966 :: SBool = s19 /= s4965
-  s4967 :: SBool = s_2 == s4966
-  s4968 :: SWord8 = s4950 >>> 1
-  s4969 :: SWord8 = s24 | s4968
-  s4970 :: SWord8 = s26 & s4968
-  s4971 :: SWord8 = if s4945 then s4969 else s4970
-  s4972 :: SWord8 = s4971 >>> 1
-  s4973 :: SWord8 = s24 | s4972
-  s4974 :: SWord8 = s26 & s4972
-  s4975 :: SWord8 = if s4966 then s4973 else s4974
-  s4976 :: SWord1 = choose [0:0] s4959
-  s4977 :: SBool = s19 /= s4976
-  s4978 :: SWord8 = s4964 >>> 1
-  s4979 :: SWord8 = s24 | s4978
-  s4980 :: SWord8 = s26 & s4978
-  s4981 :: SWord8 = if s4977 then s4979 else s4980
-  s4982 :: SWord8 = if s29 then s4920 else s4773
-  s4983 :: SWord8 = if s170 then s4937 else s4982
-  s4984 :: SWord8 = if s29 then s4942 else s4983
-  s4985 :: SWord8 = if s170 then s4958 else s4984
-  s4986 :: SWord8 = if s29 then s4963 else s4985
-  s4987 :: SWord8 = if s170 then s4981 else s4986
-  s4988 :: SWord8 = s4971 + s4987
-  s4989 :: SBool = s4988 < s4987
-  s4990 :: SBool = s4988 < s4971
-  s4991 :: SBool = s4989 | s4990
-  s4992 :: SWord8 = s4988 >>> 1
-  s4993 :: SWord8 = s24 | s4992
-  s4994 :: SWord8 = s26 & s4992
-  s4995 :: SWord8 = if s4991 then s4993 else s4994
-  s4996 :: SWord8 = if s4967 then s4975 else s4995
-  s4997 :: SWord8 = s4950 + s4985
-  s4998 :: SWord1 = choose [0:0] s4997
-  s4999 :: SBool = s19 /= s4998
-  s5000 :: SWord8 = if s4999 then s4961 else s4962
-  s5001 :: SWord8 = if s22 then s5000 else s4958
-  s5002 :: SWord1 = choose [0:0] s5001
-  s5003 :: SBool = s19 /= s5002
-  s5004 :: SBool = s_2 == s5003
-  s5005 :: SBool = s4997 < s4985
-  s5006 :: SBool = s4997 < s4950
-  s5007 :: SBool = s5005 | s5006
-  s5008 :: SWord8 = s4997 >>> 1
-  s5009 :: SWord8 = s24 | s5008
-  s5010 :: SWord8 = s26 & s5008
-  s5011 :: SWord8 = if s5007 then s5009 else s5010
-  s5012 :: SWord8 = s5011 >>> 1
-  s5013 :: SWord8 = s24 | s5012
-  s5014 :: SWord8 = s26 & s5012
-  s5015 :: SWord8 = if s5003 then s5013 else s5014
-  s5016 :: SWord8 = s5001 >>> 1
-  s5017 :: SWord8 = s24 | s5016
-  s5018 :: SWord8 = s26 & s5016
-  s5019 :: SWord8 = if s4977 then s5017 else s5018
-  s5020 :: SWord8 = if s29 then s5000 else s4985
-  s5021 :: SWord8 = if s170 then s5019 else s5020
-  s5022 :: SWord8 = s5011 + s5021
-  s5023 :: SBool = s5022 < s5021
-  s5024 :: SBool = s5022 < s5011
-  s5025 :: SBool = s5023 | s5024
-  s5026 :: SWord8 = s5022 >>> 1
-  s5027 :: SWord8 = s24 | s5026
-  s5028 :: SWord8 = s26 & s5026
-  s5029 :: SWord8 = if s5025 then s5027 else s5028
-  s5030 :: SWord8 = if s5004 then s5015 else s5029
-  s5031 :: SWord8 = if s4946 then s4996 else s5030
-  s5032 :: SWord8 = s4931 + s4983
-  s5033 :: SWord1 = choose [0:0] s5032
-  s5034 :: SBool = s19 /= s5033
-  s5035 :: SWord8 = if s5034 then s4940 else s4941
-  s5036 :: SWord8 = if s22 then s5035 else s4937
-  s5037 :: SWord1 = choose [0:0] s5036
-  s5038 :: SBool = s19 /= s5037
-  s5039 :: SBool = s_2 == s5038
-  s5040 :: SBool = s5032 < s4983
-  s5041 :: SBool = s5032 < s4931
-  s5042 :: SBool = s5040 | s5041
-  s5043 :: SWord8 = s5032 >>> 1
-  s5044 :: SWord8 = s24 | s5043
-  s5045 :: SWord8 = s26 & s5043
-  s5046 :: SWord8 = if s5042 then s5044 else s5045
-  s5047 :: SWord1 = choose [0:0] s5046
-  s5048 :: SBool = s19 /= s5047
-  s5049 :: SWord8 = s5036 >>> 1
-  s5050 :: SWord8 = s24 | s5049
-  s5051 :: SWord8 = s26 & s5049
-  s5052 :: SWord8 = if s4954 then s5050 else s5051
-  s5053 :: SWord8 = if s22 then s5052 else s5035
-  s5054 :: SWord8 = s5053 >>> 1
-  s5055 :: SWord8 = s24 | s5054
-  s5056 :: SWord8 = s26 & s5054
-  s5057 :: SWord8 = if s5048 then s5055 else s5056
-  s5058 :: SWord8 = if s22 then s5057 else s5052
-  s5059 :: SWord1 = choose [0:0] s5058
-  s5060 :: SBool = s19 /= s5059
-  s5061 :: SBool = s_2 == s5060
-  s5062 :: SWord8 = s5046 >>> 1
-  s5063 :: SWord8 = s24 | s5062
-  s5064 :: SWord8 = s26 & s5062
-  s5065 :: SWord8 = if s5038 then s5063 else s5064
-  s5066 :: SWord8 = s5065 >>> 1
-  s5067 :: SWord8 = s24 | s5066
-  s5068 :: SWord8 = s26 & s5066
-  s5069 :: SWord8 = if s5060 then s5067 else s5068
-  s5070 :: SWord1 = choose [0:0] s5053
-  s5071 :: SBool = s19 /= s5070
-  s5072 :: SWord8 = s5058 >>> 1
-  s5073 :: SWord8 = s24 | s5072
-  s5074 :: SWord8 = s26 & s5072
-  s5075 :: SWord8 = if s5071 then s5073 else s5074
-  s5076 :: SWord8 = if s29 then s5035 else s4983
-  s5077 :: SWord8 = if s170 then s5052 else s5076
-  s5078 :: SWord8 = if s29 then s5057 else s5077
-  s5079 :: SWord8 = if s170 then s5075 else s5078
-  s5080 :: SWord8 = s5065 + s5079
-  s5081 :: SBool = s5080 < s5079
-  s5082 :: SBool = s5080 < s5065
-  s5083 :: SBool = s5081 | s5082
-  s5084 :: SWord8 = s5080 >>> 1
-  s5085 :: SWord8 = s24 | s5084
-  s5086 :: SWord8 = s26 & s5084
-  s5087 :: SWord8 = if s5083 then s5085 else s5086
-  s5088 :: SWord8 = if s5061 then s5069 else s5087
-  s5089 :: SWord8 = s5046 + s5077
-  s5090 :: SWord1 = choose [0:0] s5089
-  s5091 :: SBool = s19 /= s5090
-  s5092 :: SWord8 = if s5091 then s5055 else s5056
-  s5093 :: SWord8 = if s22 then s5092 else s5052
-  s5094 :: SWord1 = choose [0:0] s5093
-  s5095 :: SBool = s19 /= s5094
-  s5096 :: SBool = s_2 == s5095
-  s5097 :: SBool = s5089 < s5077
-  s5098 :: SBool = s5089 < s5046
-  s5099 :: SBool = s5097 | s5098
-  s5100 :: SWord8 = s5089 >>> 1
-  s5101 :: SWord8 = s24 | s5100
-  s5102 :: SWord8 = s26 & s5100
-  s5103 :: SWord8 = if s5099 then s5101 else s5102
-  s5104 :: SWord8 = s5103 >>> 1
-  s5105 :: SWord8 = s24 | s5104
-  s5106 :: SWord8 = s26 & s5104
-  s5107 :: SWord8 = if s5095 then s5105 else s5106
-  s5108 :: SWord8 = s5093 >>> 1
-  s5109 :: SWord8 = s24 | s5108
-  s5110 :: SWord8 = s26 & s5108
-  s5111 :: SWord8 = if s5071 then s5109 else s5110
-  s5112 :: SWord8 = if s29 then s5092 else s5077
-  s5113 :: SWord8 = if s170 then s5111 else s5112
-  s5114 :: SWord8 = s5103 + s5113
-  s5115 :: SBool = s5114 < s5113
-  s5116 :: SBool = s5114 < s5103
-  s5117 :: SBool = s5115 | s5116
-  s5118 :: SWord8 = s5114 >>> 1
-  s5119 :: SWord8 = s24 | s5118
-  s5120 :: SWord8 = s26 & s5118
-  s5121 :: SWord8 = if s5117 then s5119 else s5120
-  s5122 :: SWord8 = if s5096 then s5107 else s5121
-  s5123 :: SWord8 = if s5039 then s5088 else s5122
-  s5124 :: SWord8 = if s4924 then s5031 else s5123
-  s5125 :: SWord8 = if s4692 then s4916 else s5124
-  s5126 :: SWord8 = s4677 + s4771
-  s5127 :: SWord1 = choose [0:0] s5126
-  s5128 :: SBool = s19 /= s5127
-  s5129 :: SWord8 = if s5128 then s4686 else s4687
-  s5130 :: SWord8 = if s22 then s5129 else s4683
-  s5131 :: SWord1 = choose [0:0] s5130
-  s5132 :: SBool = s19 /= s5131
-  s5133 :: SBool = s_2 == s5132
-  s5134 :: SBool = s5126 < s4771
-  s5135 :: SBool = s5126 < s4677
-  s5136 :: SBool = s5134 | s5135
-  s5137 :: SWord8 = s5126 >>> 1
-  s5138 :: SWord8 = s24 | s5137
-  s5139 :: SWord8 = s26 & s5137
-  s5140 :: SWord8 = if s5136 then s5138 else s5139
-  s5141 :: SWord1 = choose [0:0] s5140
-  s5142 :: SBool = s19 /= s5141
-  s5143 :: SWord8 = s5130 >>> 1
-  s5144 :: SWord8 = s24 | s5143
-  s5145 :: SWord8 = s26 & s5143
-  s5146 :: SWord8 = if s4700 then s5144 else s5145
-  s5147 :: SWord8 = if s22 then s5146 else s5129
-  s5148 :: SWord8 = s5147 >>> 1
-  s5149 :: SWord8 = s24 | s5148
-  s5150 :: SWord8 = s26 & s5148
-  s5151 :: SWord8 = if s5142 then s5149 else s5150
-  s5152 :: SWord8 = if s22 then s5151 else s5146
-  s5153 :: SWord1 = choose [0:0] s5152
-  s5154 :: SBool = s19 /= s5153
-  s5155 :: SBool = s_2 == s5154
-  s5156 :: SWord8 = s5140 >>> 1
-  s5157 :: SWord8 = s24 | s5156
-  s5158 :: SWord8 = s26 & s5156
-  s5159 :: SWord8 = if s5132 then s5157 else s5158
-  s5160 :: SWord1 = choose [0:0] s5159
-  s5161 :: SBool = s19 /= s5160
-  s5162 :: SWord1 = choose [0:0] s5147
-  s5163 :: SBool = s19 /= s5162
-  s5164 :: SWord8 = s5152 >>> 1
-  s5165 :: SWord8 = s24 | s5164
-  s5166 :: SWord8 = s26 & s5164
-  s5167 :: SWord8 = if s5163 then s5165 else s5166
-  s5168 :: SWord8 = if s22 then s5167 else s5151
-  s5169 :: SWord8 = s5168 >>> 1
-  s5170 :: SWord8 = s24 | s5169
-  s5171 :: SWord8 = s26 & s5169
-  s5172 :: SWord8 = if s5161 then s5170 else s5171
-  s5173 :: SWord8 = if s22 then s5172 else s5167
-  s5174 :: SWord1 = choose [0:0] s5173
-  s5175 :: SBool = s19 /= s5174
-  s5176 :: SBool = s_2 == s5175
-  s5177 :: SWord8 = s5159 >>> 1
-  s5178 :: SWord8 = s24 | s5177
-  s5179 :: SWord8 = s26 & s5177
-  s5180 :: SWord8 = if s5154 then s5178 else s5179
-  s5181 :: SWord1 = choose [0:0] s5180
-  s5182 :: SBool = s19 /= s5181
-  s5183 :: SWord1 = choose [0:0] s5168
-  s5184 :: SBool = s19 /= s5183
-  s5185 :: SWord8 = s5173 >>> 1
-  s5186 :: SWord8 = s24 | s5185
-  s5187 :: SWord8 = s26 & s5185
-  s5188 :: SWord8 = if s5184 then s5186 else s5187
-  s5189 :: SWord8 = if s22 then s5188 else s5172
-  s5190 :: SWord8 = s5189 >>> 1
-  s5191 :: SWord8 = s24 | s5190
-  s5192 :: SWord8 = s26 & s5190
-  s5193 :: SWord8 = if s5182 then s5191 else s5192
-  s5194 :: SWord8 = if s22 then s5193 else s5188
-  s5195 :: SWord1 = choose [0:0] s5194
-  s5196 :: SBool = s19 /= s5195
-  s5197 :: SBool = s_2 == s5196
-  s5198 :: SWord8 = s5180 >>> 1
-  s5199 :: SWord8 = s24 | s5198
-  s5200 :: SWord8 = s26 & s5198
-  s5201 :: SWord8 = if s5175 then s5199 else s5200
-  s5202 :: SWord8 = s5201 >>> 1
-  s5203 :: SWord8 = s24 | s5202
-  s5204 :: SWord8 = s26 & s5202
-  s5205 :: SWord8 = if s5196 then s5203 else s5204
-  s5206 :: SWord1 = choose [0:0] s5189
-  s5207 :: SBool = s19 /= s5206
-  s5208 :: SWord8 = s5194 >>> 1
-  s5209 :: SWord8 = s24 | s5208
-  s5210 :: SWord8 = s26 & s5208
-  s5211 :: SWord8 = if s5207 then s5209 else s5210
-  s5212 :: SWord8 = if s29 then s5129 else s4771
-  s5213 :: SWord8 = if s170 then s5146 else s5212
-  s5214 :: SWord8 = if s29 then s5151 else s5213
-  s5215 :: SWord8 = if s170 then s5167 else s5214
-  s5216 :: SWord8 = if s29 then s5172 else s5215
-  s5217 :: SWord8 = if s170 then s5188 else s5216
-  s5218 :: SWord8 = if s29 then s5193 else s5217
-  s5219 :: SWord8 = if s170 then s5211 else s5218
-  s5220 :: SWord8 = s5201 + s5219
-  s5221 :: SBool = s5220 < s5219
-  s5222 :: SBool = s5220 < s5201
-  s5223 :: SBool = s5221 | s5222
-  s5224 :: SWord8 = s5220 >>> 1
-  s5225 :: SWord8 = s24 | s5224
-  s5226 :: SWord8 = s26 & s5224
-  s5227 :: SWord8 = if s5223 then s5225 else s5226
-  s5228 :: SWord8 = if s5197 then s5205 else s5227
-  s5229 :: SWord8 = s5180 + s5217
-  s5230 :: SWord1 = choose [0:0] s5229
-  s5231 :: SBool = s19 /= s5230
-  s5232 :: SWord8 = if s5231 then s5191 else s5192
-  s5233 :: SWord8 = if s22 then s5232 else s5188
-  s5234 :: SWord1 = choose [0:0] s5233
-  s5235 :: SBool = s19 /= s5234
-  s5236 :: SBool = s_2 == s5235
-  s5237 :: SBool = s5229 < s5217
-  s5238 :: SBool = s5229 < s5180
-  s5239 :: SBool = s5237 | s5238
-  s5240 :: SWord8 = s5229 >>> 1
-  s5241 :: SWord8 = s24 | s5240
-  s5242 :: SWord8 = s26 & s5240
-  s5243 :: SWord8 = if s5239 then s5241 else s5242
-  s5244 :: SWord8 = s5243 >>> 1
-  s5245 :: SWord8 = s24 | s5244
-  s5246 :: SWord8 = s26 & s5244
-  s5247 :: SWord8 = if s5235 then s5245 else s5246
-  s5248 :: SWord8 = s5233 >>> 1
-  s5249 :: SWord8 = s24 | s5248
-  s5250 :: SWord8 = s26 & s5248
-  s5251 :: SWord8 = if s5207 then s5249 else s5250
-  s5252 :: SWord8 = if s29 then s5232 else s5217
-  s5253 :: SWord8 = if s170 then s5251 else s5252
-  s5254 :: SWord8 = s5243 + s5253
-  s5255 :: SBool = s5254 < s5253
-  s5256 :: SBool = s5254 < s5243
-  s5257 :: SBool = s5255 | s5256
-  s5258 :: SWord8 = s5254 >>> 1
-  s5259 :: SWord8 = s24 | s5258
-  s5260 :: SWord8 = s26 & s5258
-  s5261 :: SWord8 = if s5257 then s5259 else s5260
-  s5262 :: SWord8 = if s5236 then s5247 else s5261
-  s5263 :: SWord8 = if s5176 then s5228 else s5262
-  s5264 :: SWord8 = s5159 + s5215
-  s5265 :: SWord1 = choose [0:0] s5264
-  s5266 :: SBool = s19 /= s5265
-  s5267 :: SWord8 = if s5266 then s5170 else s5171
-  s5268 :: SWord8 = if s22 then s5267 else s5167
-  s5269 :: SWord1 = choose [0:0] s5268
-  s5270 :: SBool = s19 /= s5269
-  s5271 :: SBool = s_2 == s5270
-  s5272 :: SBool = s5264 < s5215
-  s5273 :: SBool = s5264 < s5159
-  s5274 :: SBool = s5272 | s5273
-  s5275 :: SWord8 = s5264 >>> 1
-  s5276 :: SWord8 = s24 | s5275
-  s5277 :: SWord8 = s26 & s5275
-  s5278 :: SWord8 = if s5274 then s5276 else s5277
-  s5279 :: SWord1 = choose [0:0] s5278
-  s5280 :: SBool = s19 /= s5279
-  s5281 :: SWord8 = s5268 >>> 1
-  s5282 :: SWord8 = s24 | s5281
-  s5283 :: SWord8 = s26 & s5281
-  s5284 :: SWord8 = if s5184 then s5282 else s5283
-  s5285 :: SWord8 = if s22 then s5284 else s5267
-  s5286 :: SWord8 = s5285 >>> 1
-  s5287 :: SWord8 = s24 | s5286
-  s5288 :: SWord8 = s26 & s5286
-  s5289 :: SWord8 = if s5280 then s5287 else s5288
-  s5290 :: SWord8 = if s22 then s5289 else s5284
-  s5291 :: SWord1 = choose [0:0] s5290
-  s5292 :: SBool = s19 /= s5291
-  s5293 :: SBool = s_2 == s5292
-  s5294 :: SWord8 = s5278 >>> 1
-  s5295 :: SWord8 = s24 | s5294
-  s5296 :: SWord8 = s26 & s5294
-  s5297 :: SWord8 = if s5270 then s5295 else s5296
-  s5298 :: SWord8 = s5297 >>> 1
-  s5299 :: SWord8 = s24 | s5298
-  s5300 :: SWord8 = s26 & s5298
-  s5301 :: SWord8 = if s5292 then s5299 else s5300
-  s5302 :: SWord1 = choose [0:0] s5285
-  s5303 :: SBool = s19 /= s5302
-  s5304 :: SWord8 = s5290 >>> 1
-  s5305 :: SWord8 = s24 | s5304
-  s5306 :: SWord8 = s26 & s5304
-  s5307 :: SWord8 = if s5303 then s5305 else s5306
-  s5308 :: SWord8 = if s29 then s5267 else s5215
-  s5309 :: SWord8 = if s170 then s5284 else s5308
-  s5310 :: SWord8 = if s29 then s5289 else s5309
-  s5311 :: SWord8 = if s170 then s5307 else s5310
-  s5312 :: SWord8 = s5297 + s5311
-  s5313 :: SBool = s5312 < s5311
-  s5314 :: SBool = s5312 < s5297
-  s5315 :: SBool = s5313 | s5314
-  s5316 :: SWord8 = s5312 >>> 1
-  s5317 :: SWord8 = s24 | s5316
-  s5318 :: SWord8 = s26 & s5316
-  s5319 :: SWord8 = if s5315 then s5317 else s5318
-  s5320 :: SWord8 = if s5293 then s5301 else s5319
-  s5321 :: SWord8 = s5278 + s5309
-  s5322 :: SWord1 = choose [0:0] s5321
-  s5323 :: SBool = s19 /= s5322
-  s5324 :: SWord8 = if s5323 then s5287 else s5288
-  s5325 :: SWord8 = if s22 then s5324 else s5284
-  s5326 :: SWord1 = choose [0:0] s5325
-  s5327 :: SBool = s19 /= s5326
-  s5328 :: SBool = s_2 == s5327
-  s5329 :: SBool = s5321 < s5309
-  s5330 :: SBool = s5321 < s5278
-  s5331 :: SBool = s5329 | s5330
-  s5332 :: SWord8 = s5321 >>> 1
-  s5333 :: SWord8 = s24 | s5332
-  s5334 :: SWord8 = s26 & s5332
-  s5335 :: SWord8 = if s5331 then s5333 else s5334
-  s5336 :: SWord8 = s5335 >>> 1
-  s5337 :: SWord8 = s24 | s5336
-  s5338 :: SWord8 = s26 & s5336
-  s5339 :: SWord8 = if s5327 then s5337 else s5338
-  s5340 :: SWord8 = s5325 >>> 1
-  s5341 :: SWord8 = s24 | s5340
-  s5342 :: SWord8 = s26 & s5340
-  s5343 :: SWord8 = if s5303 then s5341 else s5342
-  s5344 :: SWord8 = if s29 then s5324 else s5309
-  s5345 :: SWord8 = if s170 then s5343 else s5344
-  s5346 :: SWord8 = s5335 + s5345
-  s5347 :: SBool = s5346 < s5345
-  s5348 :: SBool = s5346 < s5335
-  s5349 :: SBool = s5347 | s5348
-  s5350 :: SWord8 = s5346 >>> 1
-  s5351 :: SWord8 = s24 | s5350
-  s5352 :: SWord8 = s26 & s5350
-  s5353 :: SWord8 = if s5349 then s5351 else s5352
-  s5354 :: SWord8 = if s5328 then s5339 else s5353
-  s5355 :: SWord8 = if s5271 then s5320 else s5354
-  s5356 :: SWord8 = if s5155 then s5263 else s5355
-  s5357 :: SWord8 = s5140 + s5213
-  s5358 :: SWord1 = choose [0:0] s5357
-  s5359 :: SBool = s19 /= s5358
-  s5360 :: SWord8 = if s5359 then s5149 else s5150
-  s5361 :: SWord8 = if s22 then s5360 else s5146
-  s5362 :: SWord1 = choose [0:0] s5361
-  s5363 :: SBool = s19 /= s5362
-  s5364 :: SBool = s_2 == s5363
-  s5365 :: SBool = s5357 < s5213
-  s5366 :: SBool = s5357 < s5140
-  s5367 :: SBool = s5365 | s5366
-  s5368 :: SWord8 = s5357 >>> 1
-  s5369 :: SWord8 = s24 | s5368
-  s5370 :: SWord8 = s26 & s5368
-  s5371 :: SWord8 = if s5367 then s5369 else s5370
-  s5372 :: SWord1 = choose [0:0] s5371
-  s5373 :: SBool = s19 /= s5372
-  s5374 :: SWord8 = s5361 >>> 1
-  s5375 :: SWord8 = s24 | s5374
-  s5376 :: SWord8 = s26 & s5374
-  s5377 :: SWord8 = if s5163 then s5375 else s5376
-  s5378 :: SWord8 = if s22 then s5377 else s5360
-  s5379 :: SWord8 = s5378 >>> 1
-  s5380 :: SWord8 = s24 | s5379
-  s5381 :: SWord8 = s26 & s5379
-  s5382 :: SWord8 = if s5373 then s5380 else s5381
-  s5383 :: SWord8 = if s22 then s5382 else s5377
-  s5384 :: SWord1 = choose [0:0] s5383
-  s5385 :: SBool = s19 /= s5384
-  s5386 :: SBool = s_2 == s5385
-  s5387 :: SWord8 = s5371 >>> 1
-  s5388 :: SWord8 = s24 | s5387
-  s5389 :: SWord8 = s26 & s5387
-  s5390 :: SWord8 = if s5363 then s5388 else s5389
-  s5391 :: SWord1 = choose [0:0] s5390
-  s5392 :: SBool = s19 /= s5391
-  s5393 :: SWord1 = choose [0:0] s5378
-  s5394 :: SBool = s19 /= s5393
-  s5395 :: SWord8 = s5383 >>> 1
-  s5396 :: SWord8 = s24 | s5395
-  s5397 :: SWord8 = s26 & s5395
-  s5398 :: SWord8 = if s5394 then s5396 else s5397
-  s5399 :: SWord8 = if s22 then s5398 else s5382
-  s5400 :: SWord8 = s5399 >>> 1
-  s5401 :: SWord8 = s24 | s5400
-  s5402 :: SWord8 = s26 & s5400
-  s5403 :: SWord8 = if s5392 then s5401 else s5402
-  s5404 :: SWord8 = if s22 then s5403 else s5398
-  s5405 :: SWord1 = choose [0:0] s5404
-  s5406 :: SBool = s19 /= s5405
-  s5407 :: SBool = s_2 == s5406
-  s5408 :: SWord8 = s5390 >>> 1
-  s5409 :: SWord8 = s24 | s5408
-  s5410 :: SWord8 = s26 & s5408
-  s5411 :: SWord8 = if s5385 then s5409 else s5410
-  s5412 :: SWord8 = s5411 >>> 1
-  s5413 :: SWord8 = s24 | s5412
-  s5414 :: SWord8 = s26 & s5412
-  s5415 :: SWord8 = if s5406 then s5413 else s5414
-  s5416 :: SWord1 = choose [0:0] s5399
-  s5417 :: SBool = s19 /= s5416
-  s5418 :: SWord8 = s5404 >>> 1
-  s5419 :: SWord8 = s24 | s5418
-  s5420 :: SWord8 = s26 & s5418
-  s5421 :: SWord8 = if s5417 then s5419 else s5420
-  s5422 :: SWord8 = if s29 then s5360 else s5213
-  s5423 :: SWord8 = if s170 then s5377 else s5422
-  s5424 :: SWord8 = if s29 then s5382 else s5423
-  s5425 :: SWord8 = if s170 then s5398 else s5424
-  s5426 :: SWord8 = if s29 then s5403 else s5425
-  s5427 :: SWord8 = if s170 then s5421 else s5426
-  s5428 :: SWord8 = s5411 + s5427
-  s5429 :: SBool = s5428 < s5427
-  s5430 :: SBool = s5428 < s5411
-  s5431 :: SBool = s5429 | s5430
-  s5432 :: SWord8 = s5428 >>> 1
-  s5433 :: SWord8 = s24 | s5432
-  s5434 :: SWord8 = s26 & s5432
-  s5435 :: SWord8 = if s5431 then s5433 else s5434
-  s5436 :: SWord8 = if s5407 then s5415 else s5435
-  s5437 :: SWord8 = s5390 + s5425
-  s5438 :: SWord1 = choose [0:0] s5437
-  s5439 :: SBool = s19 /= s5438
-  s5440 :: SWord8 = if s5439 then s5401 else s5402
-  s5441 :: SWord8 = if s22 then s5440 else s5398
-  s5442 :: SWord1 = choose [0:0] s5441
-  s5443 :: SBool = s19 /= s5442
-  s5444 :: SBool = s_2 == s5443
-  s5445 :: SBool = s5437 < s5425
-  s5446 :: SBool = s5437 < s5390
-  s5447 :: SBool = s5445 | s5446
-  s5448 :: SWord8 = s5437 >>> 1
-  s5449 :: SWord8 = s24 | s5448
-  s5450 :: SWord8 = s26 & s5448
-  s5451 :: SWord8 = if s5447 then s5449 else s5450
-  s5452 :: SWord8 = s5451 >>> 1
-  s5453 :: SWord8 = s24 | s5452
-  s5454 :: SWord8 = s26 & s5452
-  s5455 :: SWord8 = if s5443 then s5453 else s5454
-  s5456 :: SWord8 = s5441 >>> 1
-  s5457 :: SWord8 = s24 | s5456
-  s5458 :: SWord8 = s26 & s5456
-  s5459 :: SWord8 = if s5417 then s5457 else s5458
-  s5460 :: SWord8 = if s29 then s5440 else s5425
-  s5461 :: SWord8 = if s170 then s5459 else s5460
-  s5462 :: SWord8 = s5451 + s5461
-  s5463 :: SBool = s5462 < s5461
-  s5464 :: SBool = s5462 < s5451
-  s5465 :: SBool = s5463 | s5464
-  s5466 :: SWord8 = s5462 >>> 1
-  s5467 :: SWord8 = s24 | s5466
-  s5468 :: SWord8 = s26 & s5466
-  s5469 :: SWord8 = if s5465 then s5467 else s5468
-  s5470 :: SWord8 = if s5444 then s5455 else s5469
-  s5471 :: SWord8 = if s5386 then s5436 else s5470
-  s5472 :: SWord8 = s5371 + s5423
-  s5473 :: SWord1 = choose [0:0] s5472
-  s5474 :: SBool = s19 /= s5473
-  s5475 :: SWord8 = if s5474 then s5380 else s5381
-  s5476 :: SWord8 = if s22 then s5475 else s5377
-  s5477 :: SWord1 = choose [0:0] s5476
-  s5478 :: SBool = s19 /= s5477
-  s5479 :: SBool = s_2 == s5478
-  s5480 :: SBool = s5472 < s5423
-  s5481 :: SBool = s5472 < s5371
-  s5482 :: SBool = s5480 | s5481
-  s5483 :: SWord8 = s5472 >>> 1
-  s5484 :: SWord8 = s24 | s5483
-  s5485 :: SWord8 = s26 & s5483
-  s5486 :: SWord8 = if s5482 then s5484 else s5485
-  s5487 :: SWord1 = choose [0:0] s5486
-  s5488 :: SBool = s19 /= s5487
-  s5489 :: SWord8 = s5476 >>> 1
-  s5490 :: SWord8 = s24 | s5489
-  s5491 :: SWord8 = s26 & s5489
-  s5492 :: SWord8 = if s5394 then s5490 else s5491
-  s5493 :: SWord8 = if s22 then s5492 else s5475
-  s5494 :: SWord8 = s5493 >>> 1
-  s5495 :: SWord8 = s24 | s5494
-  s5496 :: SWord8 = s26 & s5494
-  s5497 :: SWord8 = if s5488 then s5495 else s5496
-  s5498 :: SWord8 = if s22 then s5497 else s5492
-  s5499 :: SWord1 = choose [0:0] s5498
-  s5500 :: SBool = s19 /= s5499
-  s5501 :: SBool = s_2 == s5500
-  s5502 :: SWord8 = s5486 >>> 1
-  s5503 :: SWord8 = s24 | s5502
-  s5504 :: SWord8 = s26 & s5502
-  s5505 :: SWord8 = if s5478 then s5503 else s5504
-  s5506 :: SWord8 = s5505 >>> 1
-  s5507 :: SWord8 = s24 | s5506
-  s5508 :: SWord8 = s26 & s5506
-  s5509 :: SWord8 = if s5500 then s5507 else s5508
-  s5510 :: SWord1 = choose [0:0] s5493
-  s5511 :: SBool = s19 /= s5510
-  s5512 :: SWord8 = s5498 >>> 1
-  s5513 :: SWord8 = s24 | s5512
-  s5514 :: SWord8 = s26 & s5512
-  s5515 :: SWord8 = if s5511 then s5513 else s5514
-  s5516 :: SWord8 = if s29 then s5475 else s5423
-  s5517 :: SWord8 = if s170 then s5492 else s5516
-  s5518 :: SWord8 = if s29 then s5497 else s5517
-  s5519 :: SWord8 = if s170 then s5515 else s5518
-  s5520 :: SWord8 = s5505 + s5519
-  s5521 :: SBool = s5520 < s5519
-  s5522 :: SBool = s5520 < s5505
-  s5523 :: SBool = s5521 | s5522
-  s5524 :: SWord8 = s5520 >>> 1
-  s5525 :: SWord8 = s24 | s5524
-  s5526 :: SWord8 = s26 & s5524
-  s5527 :: SWord8 = if s5523 then s5525 else s5526
-  s5528 :: SWord8 = if s5501 then s5509 else s5527
-  s5529 :: SWord8 = s5486 + s5517
-  s5530 :: SWord1 = choose [0:0] s5529
-  s5531 :: SBool = s19 /= s5530
-  s5532 :: SWord8 = if s5531 then s5495 else s5496
-  s5533 :: SWord8 = if s22 then s5532 else s5492
-  s5534 :: SWord1 = choose [0:0] s5533
-  s5535 :: SBool = s19 /= s5534
-  s5536 :: SBool = s_2 == s5535
-  s5537 :: SBool = s5529 < s5517
-  s5538 :: SBool = s5529 < s5486
-  s5539 :: SBool = s5537 | s5538
-  s5540 :: SWord8 = s5529 >>> 1
-  s5541 :: SWord8 = s24 | s5540
-  s5542 :: SWord8 = s26 & s5540
-  s5543 :: SWord8 = if s5539 then s5541 else s5542
-  s5544 :: SWord8 = s5543 >>> 1
-  s5545 :: SWord8 = s24 | s5544
-  s5546 :: SWord8 = s26 & s5544
-  s5547 :: SWord8 = if s5535 then s5545 else s5546
-  s5548 :: SWord8 = s5533 >>> 1
-  s5549 :: SWord8 = s24 | s5548
-  s5550 :: SWord8 = s26 & s5548
-  s5551 :: SWord8 = if s5511 then s5549 else s5550
-  s5552 :: SWord8 = if s29 then s5532 else s5517
-  s5553 :: SWord8 = if s170 then s5551 else s5552
-  s5554 :: SWord8 = s5543 + s5553
-  s5555 :: SBool = s5554 < s5553
-  s5556 :: SBool = s5554 < s5543
-  s5557 :: SBool = s5555 | s5556
-  s5558 :: SWord8 = s5554 >>> 1
-  s5559 :: SWord8 = s24 | s5558
-  s5560 :: SWord8 = s26 & s5558
-  s5561 :: SWord8 = if s5557 then s5559 else s5560
-  s5562 :: SWord8 = if s5536 then s5547 else s5561
-  s5563 :: SWord8 = if s5479 then s5528 else s5562
-  s5564 :: SWord8 = if s5364 then s5471 else s5563
-  s5565 :: SWord8 = if s5133 then s5356 else s5564
-  s5566 :: SWord8 = if s4670 then s5125 else s5565
-  s5567 :: SWord8 = if s3742 then s4662 else s5566
-  s5568 :: SWord8 = s3727 + s3863
-  s5569 :: SWord1 = choose [0:0] s5568
-  s5570 :: SBool = s19 /= s5569
-  s5571 :: SWord8 = if s5570 then s3736 else s3737
-  s5572 :: SWord8 = if s22 then s5571 else s3733
-  s5573 :: SWord1 = choose [0:0] s5572
-  s5574 :: SBool = s19 /= s5573
-  s5575 :: SBool = s_2 == s5574
-  s5576 :: SBool = s5568 < s3863
-  s5577 :: SBool = s5568 < s3727
-  s5578 :: SBool = s5576 | s5577
-  s5579 :: SWord8 = s5568 >>> 1
-  s5580 :: SWord8 = s24 | s5579
-  s5581 :: SWord8 = s26 & s5579
-  s5582 :: SWord8 = if s5578 then s5580 else s5581
-  s5583 :: SWord1 = choose [0:0] s5582
-  s5584 :: SBool = s19 /= s5583
-  s5585 :: SWord8 = s5572 >>> 1
-  s5586 :: SWord8 = s24 | s5585
-  s5587 :: SWord8 = s26 & s5585
-  s5588 :: SWord8 = if s3750 then s5586 else s5587
-  s5589 :: SWord8 = if s22 then s5588 else s5571
-  s5590 :: SWord8 = s5589 >>> 1
-  s5591 :: SWord8 = s24 | s5590
-  s5592 :: SWord8 = s26 & s5590
-  s5593 :: SWord8 = if s5584 then s5591 else s5592
-  s5594 :: SWord8 = if s22 then s5593 else s5588
-  s5595 :: SWord1 = choose [0:0] s5594
-  s5596 :: SBool = s19 /= s5595
-  s5597 :: SBool = s_2 == s5596
-  s5598 :: SWord8 = s5582 >>> 1
-  s5599 :: SWord8 = s24 | s5598
-  s5600 :: SWord8 = s26 & s5598
-  s5601 :: SWord8 = if s5574 then s5599 else s5600
-  s5602 :: SWord1 = choose [0:0] s5601
-  s5603 :: SBool = s19 /= s5602
-  s5604 :: SWord1 = choose [0:0] s5589
-  s5605 :: SBool = s19 /= s5604
-  s5606 :: SWord8 = s5594 >>> 1
-  s5607 :: SWord8 = s24 | s5606
-  s5608 :: SWord8 = s26 & s5606
-  s5609 :: SWord8 = if s5605 then s5607 else s5608
-  s5610 :: SWord8 = if s22 then s5609 else s5593
-  s5611 :: SWord8 = s5610 >>> 1
-  s5612 :: SWord8 = s24 | s5611
-  s5613 :: SWord8 = s26 & s5611
-  s5614 :: SWord8 = if s5603 then s5612 else s5613
-  s5615 :: SWord8 = if s22 then s5614 else s5609
-  s5616 :: SWord1 = choose [0:0] s5615
-  s5617 :: SBool = s19 /= s5616
-  s5618 :: SBool = s_2 == s5617
-  s5619 :: SWord8 = s5601 >>> 1
-  s5620 :: SWord8 = s24 | s5619
-  s5621 :: SWord8 = s26 & s5619
-  s5622 :: SWord8 = if s5596 then s5620 else s5621
-  s5623 :: SWord1 = choose [0:0] s5622
-  s5624 :: SBool = s19 /= s5623
-  s5625 :: SWord1 = choose [0:0] s5610
-  s5626 :: SBool = s19 /= s5625
-  s5627 :: SWord8 = s5615 >>> 1
-  s5628 :: SWord8 = s24 | s5627
-  s5629 :: SWord8 = s26 & s5627
-  s5630 :: SWord8 = if s5626 then s5628 else s5629
-  s5631 :: SWord8 = if s22 then s5630 else s5614
-  s5632 :: SWord8 = s5631 >>> 1
-  s5633 :: SWord8 = s24 | s5632
-  s5634 :: SWord8 = s26 & s5632
-  s5635 :: SWord8 = if s5624 then s5633 else s5634
-  s5636 :: SWord8 = if s22 then s5635 else s5630
-  s5637 :: SWord1 = choose [0:0] s5636
-  s5638 :: SBool = s19 /= s5637
-  s5639 :: SBool = s_2 == s5638
-  s5640 :: SWord8 = s5622 >>> 1
-  s5641 :: SWord8 = s24 | s5640
-  s5642 :: SWord8 = s26 & s5640
-  s5643 :: SWord8 = if s5617 then s5641 else s5642
-  s5644 :: SWord1 = choose [0:0] s5643
-  s5645 :: SBool = s19 /= s5644
-  s5646 :: SWord1 = choose [0:0] s5631
-  s5647 :: SBool = s19 /= s5646
-  s5648 :: SWord8 = s5636 >>> 1
-  s5649 :: SWord8 = s24 | s5648
-  s5650 :: SWord8 = s26 & s5648
-  s5651 :: SWord8 = if s5647 then s5649 else s5650
-  s5652 :: SWord8 = if s22 then s5651 else s5635
-  s5653 :: SWord8 = s5652 >>> 1
-  s5654 :: SWord8 = s24 | s5653
-  s5655 :: SWord8 = s26 & s5653
-  s5656 :: SWord8 = if s5645 then s5654 else s5655
-  s5657 :: SWord8 = if s22 then s5656 else s5651
-  s5658 :: SWord1 = choose [0:0] s5657
-  s5659 :: SBool = s19 /= s5658
-  s5660 :: SBool = s_2 == s5659
-  s5661 :: SWord8 = s5643 >>> 1
-  s5662 :: SWord8 = s24 | s5661
-  s5663 :: SWord8 = s26 & s5661
-  s5664 :: SWord8 = if s5638 then s5662 else s5663
-  s5665 :: SWord1 = choose [0:0] s5664
-  s5666 :: SBool = s19 /= s5665
-  s5667 :: SWord1 = choose [0:0] s5652
-  s5668 :: SBool = s19 /= s5667
-  s5669 :: SWord8 = s5657 >>> 1
-  s5670 :: SWord8 = s24 | s5669
-  s5671 :: SWord8 = s26 & s5669
-  s5672 :: SWord8 = if s5668 then s5670 else s5671
-  s5673 :: SWord8 = if s22 then s5672 else s5656
-  s5674 :: SWord8 = s5673 >>> 1
-  s5675 :: SWord8 = s24 | s5674
-  s5676 :: SWord8 = s26 & s5674
-  s5677 :: SWord8 = if s5666 then s5675 else s5676
-  s5678 :: SWord8 = if s22 then s5677 else s5672
-  s5679 :: SWord1 = choose [0:0] s5678
-  s5680 :: SBool = s19 /= s5679
-  s5681 :: SBool = s_2 == s5680
-  s5682 :: SWord8 = s5664 >>> 1
-  s5683 :: SWord8 = s24 | s5682
-  s5684 :: SWord8 = s26 & s5682
-  s5685 :: SWord8 = if s5659 then s5683 else s5684
-  s5686 :: SWord8 = s5685 >>> 1
-  s5687 :: SWord8 = s24 | s5686
-  s5688 :: SWord8 = s26 & s5686
-  s5689 :: SWord8 = if s5680 then s5687 else s5688
-  s5690 :: SWord1 = choose [0:0] s5673
-  s5691 :: SBool = s19 /= s5690
-  s5692 :: SWord8 = s5678 >>> 1
-  s5693 :: SWord8 = s24 | s5692
-  s5694 :: SWord8 = s26 & s5692
-  s5695 :: SWord8 = if s5691 then s5693 else s5694
-  s5696 :: SWord8 = if s29 then s5571 else s3863
-  s5697 :: SWord8 = if s170 then s5588 else s5696
-  s5698 :: SWord8 = if s29 then s5593 else s5697
-  s5699 :: SWord8 = if s170 then s5609 else s5698
-  s5700 :: SWord8 = if s29 then s5614 else s5699
-  s5701 :: SWord8 = if s170 then s5630 else s5700
-  s5702 :: SWord8 = if s29 then s5635 else s5701
-  s5703 :: SWord8 = if s170 then s5651 else s5702
-  s5704 :: SWord8 = if s29 then s5656 else s5703
-  s5705 :: SWord8 = if s170 then s5672 else s5704
-  s5706 :: SWord8 = if s29 then s5677 else s5705
-  s5707 :: SWord8 = if s170 then s5695 else s5706
-  s5708 :: SWord8 = s5685 + s5707
-  s5709 :: SBool = s5708 < s5707
-  s5710 :: SBool = s5708 < s5685
-  s5711 :: SBool = s5709 | s5710
-  s5712 :: SWord8 = s5708 >>> 1
-  s5713 :: SWord8 = s24 | s5712
-  s5714 :: SWord8 = s26 & s5712
-  s5715 :: SWord8 = if s5711 then s5713 else s5714
-  s5716 :: SWord8 = if s5681 then s5689 else s5715
-  s5717 :: SWord8 = s5664 + s5705
-  s5718 :: SWord1 = choose [0:0] s5717
-  s5719 :: SBool = s19 /= s5718
-  s5720 :: SWord8 = if s5719 then s5675 else s5676
-  s5721 :: SWord8 = if s22 then s5720 else s5672
-  s5722 :: SWord1 = choose [0:0] s5721
-  s5723 :: SBool = s19 /= s5722
-  s5724 :: SBool = s_2 == s5723
-  s5725 :: SBool = s5717 < s5705
-  s5726 :: SBool = s5717 < s5664
-  s5727 :: SBool = s5725 | s5726
-  s5728 :: SWord8 = s5717 >>> 1
-  s5729 :: SWord8 = s24 | s5728
-  s5730 :: SWord8 = s26 & s5728
-  s5731 :: SWord8 = if s5727 then s5729 else s5730
-  s5732 :: SWord8 = s5731 >>> 1
-  s5733 :: SWord8 = s24 | s5732
-  s5734 :: SWord8 = s26 & s5732
-  s5735 :: SWord8 = if s5723 then s5733 else s5734
-  s5736 :: SWord8 = s5721 >>> 1
-  s5737 :: SWord8 = s24 | s5736
-  s5738 :: SWord8 = s26 & s5736
-  s5739 :: SWord8 = if s5691 then s5737 else s5738
-  s5740 :: SWord8 = if s29 then s5720 else s5705
-  s5741 :: SWord8 = if s170 then s5739 else s5740
-  s5742 :: SWord8 = s5731 + s5741
-  s5743 :: SBool = s5742 < s5741
-  s5744 :: SBool = s5742 < s5731
-  s5745 :: SBool = s5743 | s5744
-  s5746 :: SWord8 = s5742 >>> 1
-  s5747 :: SWord8 = s24 | s5746
-  s5748 :: SWord8 = s26 & s5746
-  s5749 :: SWord8 = if s5745 then s5747 else s5748
-  s5750 :: SWord8 = if s5724 then s5735 else s5749
-  s5751 :: SWord8 = if s5660 then s5716 else s5750
-  s5752 :: SWord8 = s5643 + s5703
-  s5753 :: SWord1 = choose [0:0] s5752
-  s5754 :: SBool = s19 /= s5753
-  s5755 :: SWord8 = if s5754 then s5654 else s5655
-  s5756 :: SWord8 = if s22 then s5755 else s5651
-  s5757 :: SWord1 = choose [0:0] s5756
-  s5758 :: SBool = s19 /= s5757
-  s5759 :: SBool = s_2 == s5758
-  s5760 :: SBool = s5752 < s5703
-  s5761 :: SBool = s5752 < s5643
-  s5762 :: SBool = s5760 | s5761
-  s5763 :: SWord8 = s5752 >>> 1
-  s5764 :: SWord8 = s24 | s5763
-  s5765 :: SWord8 = s26 & s5763
-  s5766 :: SWord8 = if s5762 then s5764 else s5765
-  s5767 :: SWord1 = choose [0:0] s5766
-  s5768 :: SBool = s19 /= s5767
-  s5769 :: SWord8 = s5756 >>> 1
-  s5770 :: SWord8 = s24 | s5769
-  s5771 :: SWord8 = s26 & s5769
-  s5772 :: SWord8 = if s5668 then s5770 else s5771
-  s5773 :: SWord8 = if s22 then s5772 else s5755
-  s5774 :: SWord8 = s5773 >>> 1
-  s5775 :: SWord8 = s24 | s5774
-  s5776 :: SWord8 = s26 & s5774
-  s5777 :: SWord8 = if s5768 then s5775 else s5776
-  s5778 :: SWord8 = if s22 then s5777 else s5772
-  s5779 :: SWord1 = choose [0:0] s5778
-  s5780 :: SBool = s19 /= s5779
-  s5781 :: SBool = s_2 == s5780
-  s5782 :: SWord8 = s5766 >>> 1
-  s5783 :: SWord8 = s24 | s5782
-  s5784 :: SWord8 = s26 & s5782
-  s5785 :: SWord8 = if s5758 then s5783 else s5784
-  s5786 :: SWord8 = s5785 >>> 1
-  s5787 :: SWord8 = s24 | s5786
-  s5788 :: SWord8 = s26 & s5786
-  s5789 :: SWord8 = if s5780 then s5787 else s5788
-  s5790 :: SWord1 = choose [0:0] s5773
-  s5791 :: SBool = s19 /= s5790
-  s5792 :: SWord8 = s5778 >>> 1
-  s5793 :: SWord8 = s24 | s5792
-  s5794 :: SWord8 = s26 & s5792
-  s5795 :: SWord8 = if s5791 then s5793 else s5794
-  s5796 :: SWord8 = if s29 then s5755 else s5703
-  s5797 :: SWord8 = if s170 then s5772 else s5796
-  s5798 :: SWord8 = if s29 then s5777 else s5797
-  s5799 :: SWord8 = if s170 then s5795 else s5798
-  s5800 :: SWord8 = s5785 + s5799
-  s5801 :: SBool = s5800 < s5799
-  s5802 :: SBool = s5800 < s5785
-  s5803 :: SBool = s5801 | s5802
-  s5804 :: SWord8 = s5800 >>> 1
-  s5805 :: SWord8 = s24 | s5804
-  s5806 :: SWord8 = s26 & s5804
-  s5807 :: SWord8 = if s5803 then s5805 else s5806
-  s5808 :: SWord8 = if s5781 then s5789 else s5807
-  s5809 :: SWord8 = s5766 + s5797
-  s5810 :: SWord1 = choose [0:0] s5809
-  s5811 :: SBool = s19 /= s5810
-  s5812 :: SWord8 = if s5811 then s5775 else s5776
-  s5813 :: SWord8 = if s22 then s5812 else s5772
-  s5814 :: SWord1 = choose [0:0] s5813
-  s5815 :: SBool = s19 /= s5814
-  s5816 :: SBool = s_2 == s5815
-  s5817 :: SBool = s5809 < s5797
-  s5818 :: SBool = s5809 < s5766
-  s5819 :: SBool = s5817 | s5818
-  s5820 :: SWord8 = s5809 >>> 1
-  s5821 :: SWord8 = s24 | s5820
-  s5822 :: SWord8 = s26 & s5820
-  s5823 :: SWord8 = if s5819 then s5821 else s5822
-  s5824 :: SWord8 = s5823 >>> 1
-  s5825 :: SWord8 = s24 | s5824
-  s5826 :: SWord8 = s26 & s5824
-  s5827 :: SWord8 = if s5815 then s5825 else s5826
-  s5828 :: SWord8 = s5813 >>> 1
-  s5829 :: SWord8 = s24 | s5828
-  s5830 :: SWord8 = s26 & s5828
-  s5831 :: SWord8 = if s5791 then s5829 else s5830
-  s5832 :: SWord8 = if s29 then s5812 else s5797
-  s5833 :: SWord8 = if s170 then s5831 else s5832
-  s5834 :: SWord8 = s5823 + s5833
-  s5835 :: SBool = s5834 < s5833
-  s5836 :: SBool = s5834 < s5823
-  s5837 :: SBool = s5835 | s5836
-  s5838 :: SWord8 = s5834 >>> 1
-  s5839 :: SWord8 = s24 | s5838
-  s5840 :: SWord8 = s26 & s5838
-  s5841 :: SWord8 = if s5837 then s5839 else s5840
-  s5842 :: SWord8 = if s5816 then s5827 else s5841
-  s5843 :: SWord8 = if s5759 then s5808 else s5842
-  s5844 :: SWord8 = if s5639 then s5751 else s5843
-  s5845 :: SWord8 = s5622 + s5701
-  s5846 :: SWord1 = choose [0:0] s5845
-  s5847 :: SBool = s19 /= s5846
-  s5848 :: SWord8 = if s5847 then s5633 else s5634
-  s5849 :: SWord8 = if s22 then s5848 else s5630
-  s5850 :: SWord1 = choose [0:0] s5849
-  s5851 :: SBool = s19 /= s5850
-  s5852 :: SBool = s_2 == s5851
-  s5853 :: SBool = s5845 < s5701
-  s5854 :: SBool = s5845 < s5622
-  s5855 :: SBool = s5853 | s5854
-  s5856 :: SWord8 = s5845 >>> 1
-  s5857 :: SWord8 = s24 | s5856
-  s5858 :: SWord8 = s26 & s5856
-  s5859 :: SWord8 = if s5855 then s5857 else s5858
-  s5860 :: SWord1 = choose [0:0] s5859
-  s5861 :: SBool = s19 /= s5860
-  s5862 :: SWord8 = s5849 >>> 1
-  s5863 :: SWord8 = s24 | s5862
-  s5864 :: SWord8 = s26 & s5862
-  s5865 :: SWord8 = if s5647 then s5863 else s5864
-  s5866 :: SWord8 = if s22 then s5865 else s5848
-  s5867 :: SWord8 = s5866 >>> 1
-  s5868 :: SWord8 = s24 | s5867
-  s5869 :: SWord8 = s26 & s5867
-  s5870 :: SWord8 = if s5861 then s5868 else s5869
-  s5871 :: SWord8 = if s22 then s5870 else s5865
-  s5872 :: SWord1 = choose [0:0] s5871
-  s5873 :: SBool = s19 /= s5872
-  s5874 :: SBool = s_2 == s5873
-  s5875 :: SWord8 = s5859 >>> 1
-  s5876 :: SWord8 = s24 | s5875
-  s5877 :: SWord8 = s26 & s5875
-  s5878 :: SWord8 = if s5851 then s5876 else s5877
-  s5879 :: SWord1 = choose [0:0] s5878
-  s5880 :: SBool = s19 /= s5879
-  s5881 :: SWord1 = choose [0:0] s5866
-  s5882 :: SBool = s19 /= s5881
-  s5883 :: SWord8 = s5871 >>> 1
-  s5884 :: SWord8 = s24 | s5883
-  s5885 :: SWord8 = s26 & s5883
-  s5886 :: SWord8 = if s5882 then s5884 else s5885
-  s5887 :: SWord8 = if s22 then s5886 else s5870
-  s5888 :: SWord8 = s5887 >>> 1
-  s5889 :: SWord8 = s24 | s5888
-  s5890 :: SWord8 = s26 & s5888
-  s5891 :: SWord8 = if s5880 then s5889 else s5890
-  s5892 :: SWord8 = if s22 then s5891 else s5886
-  s5893 :: SWord1 = choose [0:0] s5892
-  s5894 :: SBool = s19 /= s5893
-  s5895 :: SBool = s_2 == s5894
-  s5896 :: SWord8 = s5878 >>> 1
-  s5897 :: SWord8 = s24 | s5896
-  s5898 :: SWord8 = s26 & s5896
-  s5899 :: SWord8 = if s5873 then s5897 else s5898
-  s5900 :: SWord8 = s5899 >>> 1
-  s5901 :: SWord8 = s24 | s5900
-  s5902 :: SWord8 = s26 & s5900
-  s5903 :: SWord8 = if s5894 then s5901 else s5902
-  s5904 :: SWord1 = choose [0:0] s5887
-  s5905 :: SBool = s19 /= s5904
-  s5906 :: SWord8 = s5892 >>> 1
-  s5907 :: SWord8 = s24 | s5906
-  s5908 :: SWord8 = s26 & s5906
-  s5909 :: SWord8 = if s5905 then s5907 else s5908
-  s5910 :: SWord8 = if s29 then s5848 else s5701
-  s5911 :: SWord8 = if s170 then s5865 else s5910
-  s5912 :: SWord8 = if s29 then s5870 else s5911
-  s5913 :: SWord8 = if s170 then s5886 else s5912
-  s5914 :: SWord8 = if s29 then s5891 else s5913
-  s5915 :: SWord8 = if s170 then s5909 else s5914
-  s5916 :: SWord8 = s5899 + s5915
-  s5917 :: SBool = s5916 < s5915
-  s5918 :: SBool = s5916 < s5899
-  s5919 :: SBool = s5917 | s5918
-  s5920 :: SWord8 = s5916 >>> 1
-  s5921 :: SWord8 = s24 | s5920
-  s5922 :: SWord8 = s26 & s5920
-  s5923 :: SWord8 = if s5919 then s5921 else s5922
-  s5924 :: SWord8 = if s5895 then s5903 else s5923
-  s5925 :: SWord8 = s5878 + s5913
-  s5926 :: SWord1 = choose [0:0] s5925
-  s5927 :: SBool = s19 /= s5926
-  s5928 :: SWord8 = if s5927 then s5889 else s5890
-  s5929 :: SWord8 = if s22 then s5928 else s5886
-  s5930 :: SWord1 = choose [0:0] s5929
-  s5931 :: SBool = s19 /= s5930
-  s5932 :: SBool = s_2 == s5931
-  s5933 :: SBool = s5925 < s5913
-  s5934 :: SBool = s5925 < s5878
-  s5935 :: SBool = s5933 | s5934
-  s5936 :: SWord8 = s5925 >>> 1
-  s5937 :: SWord8 = s24 | s5936
-  s5938 :: SWord8 = s26 & s5936
-  s5939 :: SWord8 = if s5935 then s5937 else s5938
-  s5940 :: SWord8 = s5939 >>> 1
-  s5941 :: SWord8 = s24 | s5940
-  s5942 :: SWord8 = s26 & s5940
-  s5943 :: SWord8 = if s5931 then s5941 else s5942
-  s5944 :: SWord8 = s5929 >>> 1
-  s5945 :: SWord8 = s24 | s5944
-  s5946 :: SWord8 = s26 & s5944
-  s5947 :: SWord8 = if s5905 then s5945 else s5946
-  s5948 :: SWord8 = if s29 then s5928 else s5913
-  s5949 :: SWord8 = if s170 then s5947 else s5948
-  s5950 :: SWord8 = s5939 + s5949
-  s5951 :: SBool = s5950 < s5949
-  s5952 :: SBool = s5950 < s5939
-  s5953 :: SBool = s5951 | s5952
-  s5954 :: SWord8 = s5950 >>> 1
-  s5955 :: SWord8 = s24 | s5954
-  s5956 :: SWord8 = s26 & s5954
-  s5957 :: SWord8 = if s5953 then s5955 else s5956
-  s5958 :: SWord8 = if s5932 then s5943 else s5957
-  s5959 :: SWord8 = if s5874 then s5924 else s5958
-  s5960 :: SWord8 = s5859 + s5911
-  s5961 :: SWord1 = choose [0:0] s5960
-  s5962 :: SBool = s19 /= s5961
-  s5963 :: SWord8 = if s5962 then s5868 else s5869
-  s5964 :: SWord8 = if s22 then s5963 else s5865
-  s5965 :: SWord1 = choose [0:0] s5964
-  s5966 :: SBool = s19 /= s5965
-  s5967 :: SBool = s_2 == s5966
-  s5968 :: SBool = s5960 < s5911
-  s5969 :: SBool = s5960 < s5859
-  s5970 :: SBool = s5968 | s5969
-  s5971 :: SWord8 = s5960 >>> 1
-  s5972 :: SWord8 = s24 | s5971
-  s5973 :: SWord8 = s26 & s5971
-  s5974 :: SWord8 = if s5970 then s5972 else s5973
-  s5975 :: SWord1 = choose [0:0] s5974
-  s5976 :: SBool = s19 /= s5975
-  s5977 :: SWord8 = s5964 >>> 1
-  s5978 :: SWord8 = s24 | s5977
-  s5979 :: SWord8 = s26 & s5977
-  s5980 :: SWord8 = if s5882 then s5978 else s5979
-  s5981 :: SWord8 = if s22 then s5980 else s5963
-  s5982 :: SWord8 = s5981 >>> 1
-  s5983 :: SWord8 = s24 | s5982
-  s5984 :: SWord8 = s26 & s5982
-  s5985 :: SWord8 = if s5976 then s5983 else s5984
-  s5986 :: SWord8 = if s22 then s5985 else s5980
-  s5987 :: SWord1 = choose [0:0] s5986
-  s5988 :: SBool = s19 /= s5987
-  s5989 :: SBool = s_2 == s5988
-  s5990 :: SWord8 = s5974 >>> 1
-  s5991 :: SWord8 = s24 | s5990
-  s5992 :: SWord8 = s26 & s5990
-  s5993 :: SWord8 = if s5966 then s5991 else s5992
-  s5994 :: SWord8 = s5993 >>> 1
-  s5995 :: SWord8 = s24 | s5994
-  s5996 :: SWord8 = s26 & s5994
-  s5997 :: SWord8 = if s5988 then s5995 else s5996
-  s5998 :: SWord1 = choose [0:0] s5981
-  s5999 :: SBool = s19 /= s5998
-  s6000 :: SWord8 = s5986 >>> 1
-  s6001 :: SWord8 = s24 | s6000
-  s6002 :: SWord8 = s26 & s6000
-  s6003 :: SWord8 = if s5999 then s6001 else s6002
-  s6004 :: SWord8 = if s29 then s5963 else s5911
-  s6005 :: SWord8 = if s170 then s5980 else s6004
-  s6006 :: SWord8 = if s29 then s5985 else s6005
-  s6007 :: SWord8 = if s170 then s6003 else s6006
-  s6008 :: SWord8 = s5993 + s6007
-  s6009 :: SBool = s6008 < s6007
-  s6010 :: SBool = s6008 < s5993
-  s6011 :: SBool = s6009 | s6010
-  s6012 :: SWord8 = s6008 >>> 1
-  s6013 :: SWord8 = s24 | s6012
-  s6014 :: SWord8 = s26 & s6012
-  s6015 :: SWord8 = if s6011 then s6013 else s6014
-  s6016 :: SWord8 = if s5989 then s5997 else s6015
-  s6017 :: SWord8 = s5974 + s6005
-  s6018 :: SWord1 = choose [0:0] s6017
-  s6019 :: SBool = s19 /= s6018
-  s6020 :: SWord8 = if s6019 then s5983 else s5984
-  s6021 :: SWord8 = if s22 then s6020 else s5980
-  s6022 :: SWord1 = choose [0:0] s6021
-  s6023 :: SBool = s19 /= s6022
-  s6024 :: SBool = s_2 == s6023
-  s6025 :: SBool = s6017 < s6005
-  s6026 :: SBool = s6017 < s5974
-  s6027 :: SBool = s6025 | s6026
-  s6028 :: SWord8 = s6017 >>> 1
-  s6029 :: SWord8 = s24 | s6028
-  s6030 :: SWord8 = s26 & s6028
-  s6031 :: SWord8 = if s6027 then s6029 else s6030
-  s6032 :: SWord8 = s6031 >>> 1
-  s6033 :: SWord8 = s24 | s6032
-  s6034 :: SWord8 = s26 & s6032
-  s6035 :: SWord8 = if s6023 then s6033 else s6034
-  s6036 :: SWord8 = s6021 >>> 1
-  s6037 :: SWord8 = s24 | s6036
-  s6038 :: SWord8 = s26 & s6036
-  s6039 :: SWord8 = if s5999 then s6037 else s6038
-  s6040 :: SWord8 = if s29 then s6020 else s6005
-  s6041 :: SWord8 = if s170 then s6039 else s6040
-  s6042 :: SWord8 = s6031 + s6041
-  s6043 :: SBool = s6042 < s6041
-  s6044 :: SBool = s6042 < s6031
-  s6045 :: SBool = s6043 | s6044
-  s6046 :: SWord8 = s6042 >>> 1
-  s6047 :: SWord8 = s24 | s6046
-  s6048 :: SWord8 = s26 & s6046
-  s6049 :: SWord8 = if s6045 then s6047 else s6048
-  s6050 :: SWord8 = if s6024 then s6035 else s6049
-  s6051 :: SWord8 = if s5967 then s6016 else s6050
-  s6052 :: SWord8 = if s5852 then s5959 else s6051
-  s6053 :: SWord8 = if s5618 then s5844 else s6052
-  s6054 :: SWord8 = s5601 + s5699
-  s6055 :: SWord1 = choose [0:0] s6054
-  s6056 :: SBool = s19 /= s6055
-  s6057 :: SWord8 = if s6056 then s5612 else s5613
-  s6058 :: SWord8 = if s22 then s6057 else s5609
-  s6059 :: SWord1 = choose [0:0] s6058
-  s6060 :: SBool = s19 /= s6059
-  s6061 :: SBool = s_2 == s6060
-  s6062 :: SBool = s6054 < s5699
-  s6063 :: SBool = s6054 < s5601
-  s6064 :: SBool = s6062 | s6063
-  s6065 :: SWord8 = s6054 >>> 1
-  s6066 :: SWord8 = s24 | s6065
-  s6067 :: SWord8 = s26 & s6065
-  s6068 :: SWord8 = if s6064 then s6066 else s6067
-  s6069 :: SWord1 = choose [0:0] s6068
-  s6070 :: SBool = s19 /= s6069
-  s6071 :: SWord8 = s6058 >>> 1
-  s6072 :: SWord8 = s24 | s6071
-  s6073 :: SWord8 = s26 & s6071
-  s6074 :: SWord8 = if s5626 then s6072 else s6073
-  s6075 :: SWord8 = if s22 then s6074 else s6057
-  s6076 :: SWord8 = s6075 >>> 1
-  s6077 :: SWord8 = s24 | s6076
-  s6078 :: SWord8 = s26 & s6076
-  s6079 :: SWord8 = if s6070 then s6077 else s6078
-  s6080 :: SWord8 = if s22 then s6079 else s6074
-  s6081 :: SWord1 = choose [0:0] s6080
-  s6082 :: SBool = s19 /= s6081
-  s6083 :: SBool = s_2 == s6082
-  s6084 :: SWord8 = s6068 >>> 1
-  s6085 :: SWord8 = s24 | s6084
-  s6086 :: SWord8 = s26 & s6084
-  s6087 :: SWord8 = if s6060 then s6085 else s6086
-  s6088 :: SWord1 = choose [0:0] s6087
-  s6089 :: SBool = s19 /= s6088
-  s6090 :: SWord1 = choose [0:0] s6075
-  s6091 :: SBool = s19 /= s6090
-  s6092 :: SWord8 = s6080 >>> 1
-  s6093 :: SWord8 = s24 | s6092
-  s6094 :: SWord8 = s26 & s6092
-  s6095 :: SWord8 = if s6091 then s6093 else s6094
-  s6096 :: SWord8 = if s22 then s6095 else s6079
-  s6097 :: SWord8 = s6096 >>> 1
-  s6098 :: SWord8 = s24 | s6097
-  s6099 :: SWord8 = s26 & s6097
-  s6100 :: SWord8 = if s6089 then s6098 else s6099
-  s6101 :: SWord8 = if s22 then s6100 else s6095
-  s6102 :: SWord1 = choose [0:0] s6101
-  s6103 :: SBool = s19 /= s6102
-  s6104 :: SBool = s_2 == s6103
-  s6105 :: SWord8 = s6087 >>> 1
-  s6106 :: SWord8 = s24 | s6105
-  s6107 :: SWord8 = s26 & s6105
-  s6108 :: SWord8 = if s6082 then s6106 else s6107
-  s6109 :: SWord1 = choose [0:0] s6108
-  s6110 :: SBool = s19 /= s6109
-  s6111 :: SWord1 = choose [0:0] s6096
-  s6112 :: SBool = s19 /= s6111
-  s6113 :: SWord8 = s6101 >>> 1
-  s6114 :: SWord8 = s24 | s6113
-  s6115 :: SWord8 = s26 & s6113
-  s6116 :: SWord8 = if s6112 then s6114 else s6115
-  s6117 :: SWord8 = if s22 then s6116 else s6100
-  s6118 :: SWord8 = s6117 >>> 1
-  s6119 :: SWord8 = s24 | s6118
-  s6120 :: SWord8 = s26 & s6118
-  s6121 :: SWord8 = if s6110 then s6119 else s6120
-  s6122 :: SWord8 = if s22 then s6121 else s6116
-  s6123 :: SWord1 = choose [0:0] s6122
-  s6124 :: SBool = s19 /= s6123
-  s6125 :: SBool = s_2 == s6124
-  s6126 :: SWord8 = s6108 >>> 1
-  s6127 :: SWord8 = s24 | s6126
-  s6128 :: SWord8 = s26 & s6126
-  s6129 :: SWord8 = if s6103 then s6127 else s6128
-  s6130 :: SWord8 = s6129 >>> 1
-  s6131 :: SWord8 = s24 | s6130
-  s6132 :: SWord8 = s26 & s6130
-  s6133 :: SWord8 = if s6124 then s6131 else s6132
-  s6134 :: SWord1 = choose [0:0] s6117
-  s6135 :: SBool = s19 /= s6134
-  s6136 :: SWord8 = s6122 >>> 1
-  s6137 :: SWord8 = s24 | s6136
-  s6138 :: SWord8 = s26 & s6136
-  s6139 :: SWord8 = if s6135 then s6137 else s6138
-  s6140 :: SWord8 = if s29 then s6057 else s5699
-  s6141 :: SWord8 = if s170 then s6074 else s6140
-  s6142 :: SWord8 = if s29 then s6079 else s6141
-  s6143 :: SWord8 = if s170 then s6095 else s6142
-  s6144 :: SWord8 = if s29 then s6100 else s6143
-  s6145 :: SWord8 = if s170 then s6116 else s6144
-  s6146 :: SWord8 = if s29 then s6121 else s6145
-  s6147 :: SWord8 = if s170 then s6139 else s6146
-  s6148 :: SWord8 = s6129 + s6147
-  s6149 :: SBool = s6148 < s6147
-  s6150 :: SBool = s6148 < s6129
-  s6151 :: SBool = s6149 | s6150
-  s6152 :: SWord8 = s6148 >>> 1
-  s6153 :: SWord8 = s24 | s6152
-  s6154 :: SWord8 = s26 & s6152
-  s6155 :: SWord8 = if s6151 then s6153 else s6154
-  s6156 :: SWord8 = if s6125 then s6133 else s6155
-  s6157 :: SWord8 = s6108 + s6145
-  s6158 :: SWord1 = choose [0:0] s6157
-  s6159 :: SBool = s19 /= s6158
-  s6160 :: SWord8 = if s6159 then s6119 else s6120
-  s6161 :: SWord8 = if s22 then s6160 else s6116
-  s6162 :: SWord1 = choose [0:0] s6161
-  s6163 :: SBool = s19 /= s6162
-  s6164 :: SBool = s_2 == s6163
-  s6165 :: SBool = s6157 < s6145
-  s6166 :: SBool = s6157 < s6108
-  s6167 :: SBool = s6165 | s6166
-  s6168 :: SWord8 = s6157 >>> 1
-  s6169 :: SWord8 = s24 | s6168
-  s6170 :: SWord8 = s26 & s6168
-  s6171 :: SWord8 = if s6167 then s6169 else s6170
-  s6172 :: SWord8 = s6171 >>> 1
-  s6173 :: SWord8 = s24 | s6172
-  s6174 :: SWord8 = s26 & s6172
-  s6175 :: SWord8 = if s6163 then s6173 else s6174
-  s6176 :: SWord8 = s6161 >>> 1
-  s6177 :: SWord8 = s24 | s6176
-  s6178 :: SWord8 = s26 & s6176
-  s6179 :: SWord8 = if s6135 then s6177 else s6178
-  s6180 :: SWord8 = if s29 then s6160 else s6145
-  s6181 :: SWord8 = if s170 then s6179 else s6180
-  s6182 :: SWord8 = s6171 + s6181
-  s6183 :: SBool = s6182 < s6181
-  s6184 :: SBool = s6182 < s6171
-  s6185 :: SBool = s6183 | s6184
-  s6186 :: SWord8 = s6182 >>> 1
-  s6187 :: SWord8 = s24 | s6186
-  s6188 :: SWord8 = s26 & s6186
-  s6189 :: SWord8 = if s6185 then s6187 else s6188
-  s6190 :: SWord8 = if s6164 then s6175 else s6189
-  s6191 :: SWord8 = if s6104 then s6156 else s6190
-  s6192 :: SWord8 = s6087 + s6143
-  s6193 :: SWord1 = choose [0:0] s6192
-  s6194 :: SBool = s19 /= s6193
-  s6195 :: SWord8 = if s6194 then s6098 else s6099
-  s6196 :: SWord8 = if s22 then s6195 else s6095
-  s6197 :: SWord1 = choose [0:0] s6196
-  s6198 :: SBool = s19 /= s6197
-  s6199 :: SBool = s_2 == s6198
-  s6200 :: SBool = s6192 < s6143
-  s6201 :: SBool = s6192 < s6087
-  s6202 :: SBool = s6200 | s6201
-  s6203 :: SWord8 = s6192 >>> 1
-  s6204 :: SWord8 = s24 | s6203
-  s6205 :: SWord8 = s26 & s6203
-  s6206 :: SWord8 = if s6202 then s6204 else s6205
-  s6207 :: SWord1 = choose [0:0] s6206
-  s6208 :: SBool = s19 /= s6207
-  s6209 :: SWord8 = s6196 >>> 1
-  s6210 :: SWord8 = s24 | s6209
-  s6211 :: SWord8 = s26 & s6209
-  s6212 :: SWord8 = if s6112 then s6210 else s6211
-  s6213 :: SWord8 = if s22 then s6212 else s6195
-  s6214 :: SWord8 = s6213 >>> 1
-  s6215 :: SWord8 = s24 | s6214
-  s6216 :: SWord8 = s26 & s6214
-  s6217 :: SWord8 = if s6208 then s6215 else s6216
-  s6218 :: SWord8 = if s22 then s6217 else s6212
-  s6219 :: SWord1 = choose [0:0] s6218
-  s6220 :: SBool = s19 /= s6219
-  s6221 :: SBool = s_2 == s6220
-  s6222 :: SWord8 = s6206 >>> 1
-  s6223 :: SWord8 = s24 | s6222
-  s6224 :: SWord8 = s26 & s6222
-  s6225 :: SWord8 = if s6198 then s6223 else s6224
-  s6226 :: SWord8 = s6225 >>> 1
-  s6227 :: SWord8 = s24 | s6226
-  s6228 :: SWord8 = s26 & s6226
-  s6229 :: SWord8 = if s6220 then s6227 else s6228
-  s6230 :: SWord1 = choose [0:0] s6213
-  s6231 :: SBool = s19 /= s6230
-  s6232 :: SWord8 = s6218 >>> 1
-  s6233 :: SWord8 = s24 | s6232
-  s6234 :: SWord8 = s26 & s6232
-  s6235 :: SWord8 = if s6231 then s6233 else s6234
-  s6236 :: SWord8 = if s29 then s6195 else s6143
-  s6237 :: SWord8 = if s170 then s6212 else s6236
-  s6238 :: SWord8 = if s29 then s6217 else s6237
-  s6239 :: SWord8 = if s170 then s6235 else s6238
-  s6240 :: SWord8 = s6225 + s6239
-  s6241 :: SBool = s6240 < s6239
-  s6242 :: SBool = s6240 < s6225
-  s6243 :: SBool = s6241 | s6242
-  s6244 :: SWord8 = s6240 >>> 1
-  s6245 :: SWord8 = s24 | s6244
-  s6246 :: SWord8 = s26 & s6244
-  s6247 :: SWord8 = if s6243 then s6245 else s6246
-  s6248 :: SWord8 = if s6221 then s6229 else s6247
-  s6249 :: SWord8 = s6206 + s6237
-  s6250 :: SWord1 = choose [0:0] s6249
-  s6251 :: SBool = s19 /= s6250
-  s6252 :: SWord8 = if s6251 then s6215 else s6216
-  s6253 :: SWord8 = if s22 then s6252 else s6212
-  s6254 :: SWord1 = choose [0:0] s6253
-  s6255 :: SBool = s19 /= s6254
-  s6256 :: SBool = s_2 == s6255
-  s6257 :: SBool = s6249 < s6237
-  s6258 :: SBool = s6249 < s6206
-  s6259 :: SBool = s6257 | s6258
-  s6260 :: SWord8 = s6249 >>> 1
-  s6261 :: SWord8 = s24 | s6260
-  s6262 :: SWord8 = s26 & s6260
-  s6263 :: SWord8 = if s6259 then s6261 else s6262
-  s6264 :: SWord8 = s6263 >>> 1
-  s6265 :: SWord8 = s24 | s6264
-  s6266 :: SWord8 = s26 & s6264
-  s6267 :: SWord8 = if s6255 then s6265 else s6266
-  s6268 :: SWord8 = s6253 >>> 1
-  s6269 :: SWord8 = s24 | s6268
-  s6270 :: SWord8 = s26 & s6268
-  s6271 :: SWord8 = if s6231 then s6269 else s6270
-  s6272 :: SWord8 = if s29 then s6252 else s6237
-  s6273 :: SWord8 = if s170 then s6271 else s6272
-  s6274 :: SWord8 = s6263 + s6273
-  s6275 :: SBool = s6274 < s6273
-  s6276 :: SBool = s6274 < s6263
-  s6277 :: SBool = s6275 | s6276
-  s6278 :: SWord8 = s6274 >>> 1
-  s6279 :: SWord8 = s24 | s6278
-  s6280 :: SWord8 = s26 & s6278
-  s6281 :: SWord8 = if s6277 then s6279 else s6280
-  s6282 :: SWord8 = if s6256 then s6267 else s6281
-  s6283 :: SWord8 = if s6199 then s6248 else s6282
-  s6284 :: SWord8 = if s6083 then s6191 else s6283
-  s6285 :: SWord8 = s6068 + s6141
-  s6286 :: SWord1 = choose [0:0] s6285
-  s6287 :: SBool = s19 /= s6286
-  s6288 :: SWord8 = if s6287 then s6077 else s6078
-  s6289 :: SWord8 = if s22 then s6288 else s6074
-  s6290 :: SWord1 = choose [0:0] s6289
-  s6291 :: SBool = s19 /= s6290
-  s6292 :: SBool = s_2 == s6291
-  s6293 :: SBool = s6285 < s6141
-  s6294 :: SBool = s6285 < s6068
-  s6295 :: SBool = s6293 | s6294
-  s6296 :: SWord8 = s6285 >>> 1
-  s6297 :: SWord8 = s24 | s6296
-  s6298 :: SWord8 = s26 & s6296
-  s6299 :: SWord8 = if s6295 then s6297 else s6298
-  s6300 :: SWord1 = choose [0:0] s6299
-  s6301 :: SBool = s19 /= s6300
-  s6302 :: SWord8 = s6289 >>> 1
-  s6303 :: SWord8 = s24 | s6302
-  s6304 :: SWord8 = s26 & s6302
-  s6305 :: SWord8 = if s6091 then s6303 else s6304
-  s6306 :: SWord8 = if s22 then s6305 else s6288
-  s6307 :: SWord8 = s6306 >>> 1
-  s6308 :: SWord8 = s24 | s6307
-  s6309 :: SWord8 = s26 & s6307
-  s6310 :: SWord8 = if s6301 then s6308 else s6309
-  s6311 :: SWord8 = if s22 then s6310 else s6305
-  s6312 :: SWord1 = choose [0:0] s6311
-  s6313 :: SBool = s19 /= s6312
-  s6314 :: SBool = s_2 == s6313
-  s6315 :: SWord8 = s6299 >>> 1
-  s6316 :: SWord8 = s24 | s6315
-  s6317 :: SWord8 = s26 & s6315
-  s6318 :: SWord8 = if s6291 then s6316 else s6317
-  s6319 :: SWord1 = choose [0:0] s6318
-  s6320 :: SBool = s19 /= s6319
-  s6321 :: SWord1 = choose [0:0] s6306
-  s6322 :: SBool = s19 /= s6321
-  s6323 :: SWord8 = s6311 >>> 1
-  s6324 :: SWord8 = s24 | s6323
-  s6325 :: SWord8 = s26 & s6323
-  s6326 :: SWord8 = if s6322 then s6324 else s6325
-  s6327 :: SWord8 = if s22 then s6326 else s6310
-  s6328 :: SWord8 = s6327 >>> 1
-  s6329 :: SWord8 = s24 | s6328
-  s6330 :: SWord8 = s26 & s6328
-  s6331 :: SWord8 = if s6320 then s6329 else s6330
-  s6332 :: SWord8 = if s22 then s6331 else s6326
-  s6333 :: SWord1 = choose [0:0] s6332
-  s6334 :: SBool = s19 /= s6333
-  s6335 :: SBool = s_2 == s6334
-  s6336 :: SWord8 = s6318 >>> 1
-  s6337 :: SWord8 = s24 | s6336
-  s6338 :: SWord8 = s26 & s6336
-  s6339 :: SWord8 = if s6313 then s6337 else s6338
-  s6340 :: SWord8 = s6339 >>> 1
-  s6341 :: SWord8 = s24 | s6340
-  s6342 :: SWord8 = s26 & s6340
-  s6343 :: SWord8 = if s6334 then s6341 else s6342
-  s6344 :: SWord1 = choose [0:0] s6327
-  s6345 :: SBool = s19 /= s6344
-  s6346 :: SWord8 = s6332 >>> 1
-  s6347 :: SWord8 = s24 | s6346
-  s6348 :: SWord8 = s26 & s6346
-  s6349 :: SWord8 = if s6345 then s6347 else s6348
-  s6350 :: SWord8 = if s29 then s6288 else s6141
-  s6351 :: SWord8 = if s170 then s6305 else s6350
-  s6352 :: SWord8 = if s29 then s6310 else s6351
-  s6353 :: SWord8 = if s170 then s6326 else s6352
-  s6354 :: SWord8 = if s29 then s6331 else s6353
-  s6355 :: SWord8 = if s170 then s6349 else s6354
-  s6356 :: SWord8 = s6339 + s6355
-  s6357 :: SBool = s6356 < s6355
-  s6358 :: SBool = s6356 < s6339
-  s6359 :: SBool = s6357 | s6358
-  s6360 :: SWord8 = s6356 >>> 1
-  s6361 :: SWord8 = s24 | s6360
-  s6362 :: SWord8 = s26 & s6360
-  s6363 :: SWord8 = if s6359 then s6361 else s6362
-  s6364 :: SWord8 = if s6335 then s6343 else s6363
-  s6365 :: SWord8 = s6318 + s6353
-  s6366 :: SWord1 = choose [0:0] s6365
-  s6367 :: SBool = s19 /= s6366
-  s6368 :: SWord8 = if s6367 then s6329 else s6330
-  s6369 :: SWord8 = if s22 then s6368 else s6326
-  s6370 :: SWord1 = choose [0:0] s6369
-  s6371 :: SBool = s19 /= s6370
-  s6372 :: SBool = s_2 == s6371
-  s6373 :: SBool = s6365 < s6353
-  s6374 :: SBool = s6365 < s6318
-  s6375 :: SBool = s6373 | s6374
-  s6376 :: SWord8 = s6365 >>> 1
-  s6377 :: SWord8 = s24 | s6376
-  s6378 :: SWord8 = s26 & s6376
-  s6379 :: SWord8 = if s6375 then s6377 else s6378
-  s6380 :: SWord8 = s6379 >>> 1
-  s6381 :: SWord8 = s24 | s6380
-  s6382 :: SWord8 = s26 & s6380
-  s6383 :: SWord8 = if s6371 then s6381 else s6382
-  s6384 :: SWord8 = s6369 >>> 1
-  s6385 :: SWord8 = s24 | s6384
-  s6386 :: SWord8 = s26 & s6384
-  s6387 :: SWord8 = if s6345 then s6385 else s6386
-  s6388 :: SWord8 = if s29 then s6368 else s6353
-  s6389 :: SWord8 = if s170 then s6387 else s6388
-  s6390 :: SWord8 = s6379 + s6389
-  s6391 :: SBool = s6390 < s6389
-  s6392 :: SBool = s6390 < s6379
-  s6393 :: SBool = s6391 | s6392
-  s6394 :: SWord8 = s6390 >>> 1
-  s6395 :: SWord8 = s24 | s6394
-  s6396 :: SWord8 = s26 & s6394
-  s6397 :: SWord8 = if s6393 then s6395 else s6396
-  s6398 :: SWord8 = if s6372 then s6383 else s6397
-  s6399 :: SWord8 = if s6314 then s6364 else s6398
-  s6400 :: SWord8 = s6299 + s6351
-  s6401 :: SWord1 = choose [0:0] s6400
-  s6402 :: SBool = s19 /= s6401
-  s6403 :: SWord8 = if s6402 then s6308 else s6309
-  s6404 :: SWord8 = if s22 then s6403 else s6305
-  s6405 :: SWord1 = choose [0:0] s6404
-  s6406 :: SBool = s19 /= s6405
-  s6407 :: SBool = s_2 == s6406
-  s6408 :: SBool = s6400 < s6351
-  s6409 :: SBool = s6400 < s6299
-  s6410 :: SBool = s6408 | s6409
-  s6411 :: SWord8 = s6400 >>> 1
-  s6412 :: SWord8 = s24 | s6411
-  s6413 :: SWord8 = s26 & s6411
-  s6414 :: SWord8 = if s6410 then s6412 else s6413
-  s6415 :: SWord1 = choose [0:0] s6414
-  s6416 :: SBool = s19 /= s6415
-  s6417 :: SWord8 = s6404 >>> 1
-  s6418 :: SWord8 = s24 | s6417
-  s6419 :: SWord8 = s26 & s6417
-  s6420 :: SWord8 = if s6322 then s6418 else s6419
-  s6421 :: SWord8 = if s22 then s6420 else s6403
-  s6422 :: SWord8 = s6421 >>> 1
-  s6423 :: SWord8 = s24 | s6422
-  s6424 :: SWord8 = s26 & s6422
-  s6425 :: SWord8 = if s6416 then s6423 else s6424
-  s6426 :: SWord8 = if s22 then s6425 else s6420
-  s6427 :: SWord1 = choose [0:0] s6426
-  s6428 :: SBool = s19 /= s6427
-  s6429 :: SBool = s_2 == s6428
-  s6430 :: SWord8 = s6414 >>> 1
-  s6431 :: SWord8 = s24 | s6430
-  s6432 :: SWord8 = s26 & s6430
-  s6433 :: SWord8 = if s6406 then s6431 else s6432
-  s6434 :: SWord8 = s6433 >>> 1
-  s6435 :: SWord8 = s24 | s6434
-  s6436 :: SWord8 = s26 & s6434
-  s6437 :: SWord8 = if s6428 then s6435 else s6436
-  s6438 :: SWord1 = choose [0:0] s6421
-  s6439 :: SBool = s19 /= s6438
-  s6440 :: SWord8 = s6426 >>> 1
-  s6441 :: SWord8 = s24 | s6440
-  s6442 :: SWord8 = s26 & s6440
-  s6443 :: SWord8 = if s6439 then s6441 else s6442
-  s6444 :: SWord8 = if s29 then s6403 else s6351
-  s6445 :: SWord8 = if s170 then s6420 else s6444
-  s6446 :: SWord8 = if s29 then s6425 else s6445
-  s6447 :: SWord8 = if s170 then s6443 else s6446
-  s6448 :: SWord8 = s6433 + s6447
-  s6449 :: SBool = s6448 < s6447
-  s6450 :: SBool = s6448 < s6433
-  s6451 :: SBool = s6449 | s6450
-  s6452 :: SWord8 = s6448 >>> 1
-  s6453 :: SWord8 = s24 | s6452
-  s6454 :: SWord8 = s26 & s6452
-  s6455 :: SWord8 = if s6451 then s6453 else s6454
-  s6456 :: SWord8 = if s6429 then s6437 else s6455
-  s6457 :: SWord8 = s6414 + s6445
-  s6458 :: SWord1 = choose [0:0] s6457
-  s6459 :: SBool = s19 /= s6458
-  s6460 :: SWord8 = if s6459 then s6423 else s6424
-  s6461 :: SWord8 = if s22 then s6460 else s6420
-  s6462 :: SWord1 = choose [0:0] s6461
-  s6463 :: SBool = s19 /= s6462
-  s6464 :: SBool = s_2 == s6463
-  s6465 :: SBool = s6457 < s6445
-  s6466 :: SBool = s6457 < s6414
-  s6467 :: SBool = s6465 | s6466
-  s6468 :: SWord8 = s6457 >>> 1
-  s6469 :: SWord8 = s24 | s6468
-  s6470 :: SWord8 = s26 & s6468
-  s6471 :: SWord8 = if s6467 then s6469 else s6470
-  s6472 :: SWord8 = s6471 >>> 1
-  s6473 :: SWord8 = s24 | s6472
-  s6474 :: SWord8 = s26 & s6472
-  s6475 :: SWord8 = if s6463 then s6473 else s6474
-  s6476 :: SWord8 = s6461 >>> 1
-  s6477 :: SWord8 = s24 | s6476
-  s6478 :: SWord8 = s26 & s6476
-  s6479 :: SWord8 = if s6439 then s6477 else s6478
-  s6480 :: SWord8 = if s29 then s6460 else s6445
-  s6481 :: SWord8 = if s170 then s6479 else s6480
-  s6482 :: SWord8 = s6471 + s6481
-  s6483 :: SBool = s6482 < s6481
-  s6484 :: SBool = s6482 < s6471
-  s6485 :: SBool = s6483 | s6484
-  s6486 :: SWord8 = s6482 >>> 1
-  s6487 :: SWord8 = s24 | s6486
-  s6488 :: SWord8 = s26 & s6486
-  s6489 :: SWord8 = if s6485 then s6487 else s6488
-  s6490 :: SWord8 = if s6464 then s6475 else s6489
-  s6491 :: SWord8 = if s6407 then s6456 else s6490
-  s6492 :: SWord8 = if s6292 then s6399 else s6491
-  s6493 :: SWord8 = if s6061 then s6284 else s6492
-  s6494 :: SWord8 = if s5597 then s6053 else s6493
-  s6495 :: SWord8 = s5582 + s5697
-  s6496 :: SWord1 = choose [0:0] s6495
-  s6497 :: SBool = s19 /= s6496
-  s6498 :: SWord8 = if s6497 then s5591 else s5592
-  s6499 :: SWord8 = if s22 then s6498 else s5588
-  s6500 :: SWord1 = choose [0:0] s6499
-  s6501 :: SBool = s19 /= s6500
-  s6502 :: SBool = s_2 == s6501
-  s6503 :: SBool = s6495 < s5697
-  s6504 :: SBool = s6495 < s5582
-  s6505 :: SBool = s6503 | s6504
-  s6506 :: SWord8 = s6495 >>> 1
-  s6507 :: SWord8 = s24 | s6506
-  s6508 :: SWord8 = s26 & s6506
-  s6509 :: SWord8 = if s6505 then s6507 else s6508
-  s6510 :: SWord1 = choose [0:0] s6509
-  s6511 :: SBool = s19 /= s6510
-  s6512 :: SWord8 = s6499 >>> 1
-  s6513 :: SWord8 = s24 | s6512
-  s6514 :: SWord8 = s26 & s6512
-  s6515 :: SWord8 = if s5605 then s6513 else s6514
-  s6516 :: SWord8 = if s22 then s6515 else s6498
-  s6517 :: SWord8 = s6516 >>> 1
-  s6518 :: SWord8 = s24 | s6517
-  s6519 :: SWord8 = s26 & s6517
-  s6520 :: SWord8 = if s6511 then s6518 else s6519
-  s6521 :: SWord8 = if s22 then s6520 else s6515
-  s6522 :: SWord1 = choose [0:0] s6521
-  s6523 :: SBool = s19 /= s6522
-  s6524 :: SBool = s_2 == s6523
-  s6525 :: SWord8 = s6509 >>> 1
-  s6526 :: SWord8 = s24 | s6525
-  s6527 :: SWord8 = s26 & s6525
-  s6528 :: SWord8 = if s6501 then s6526 else s6527
-  s6529 :: SWord1 = choose [0:0] s6528
-  s6530 :: SBool = s19 /= s6529
-  s6531 :: SWord1 = choose [0:0] s6516
-  s6532 :: SBool = s19 /= s6531
-  s6533 :: SWord8 = s6521 >>> 1
-  s6534 :: SWord8 = s24 | s6533
-  s6535 :: SWord8 = s26 & s6533
-  s6536 :: SWord8 = if s6532 then s6534 else s6535
-  s6537 :: SWord8 = if s22 then s6536 else s6520
-  s6538 :: SWord8 = s6537 >>> 1
-  s6539 :: SWord8 = s24 | s6538
-  s6540 :: SWord8 = s26 & s6538
-  s6541 :: SWord8 = if s6530 then s6539 else s6540
-  s6542 :: SWord8 = if s22 then s6541 else s6536
-  s6543 :: SWord1 = choose [0:0] s6542
-  s6544 :: SBool = s19 /= s6543
-  s6545 :: SBool = s_2 == s6544
-  s6546 :: SWord8 = s6528 >>> 1
-  s6547 :: SWord8 = s24 | s6546
-  s6548 :: SWord8 = s26 & s6546
-  s6549 :: SWord8 = if s6523 then s6547 else s6548
-  s6550 :: SWord1 = choose [0:0] s6549
-  s6551 :: SBool = s19 /= s6550
-  s6552 :: SWord1 = choose [0:0] s6537
-  s6553 :: SBool = s19 /= s6552
-  s6554 :: SWord8 = s6542 >>> 1
-  s6555 :: SWord8 = s24 | s6554
-  s6556 :: SWord8 = s26 & s6554
-  s6557 :: SWord8 = if s6553 then s6555 else s6556
-  s6558 :: SWord8 = if s22 then s6557 else s6541
-  s6559 :: SWord8 = s6558 >>> 1
-  s6560 :: SWord8 = s24 | s6559
-  s6561 :: SWord8 = s26 & s6559
-  s6562 :: SWord8 = if s6551 then s6560 else s6561
-  s6563 :: SWord8 = if s22 then s6562 else s6557
-  s6564 :: SWord1 = choose [0:0] s6563
-  s6565 :: SBool = s19 /= s6564
-  s6566 :: SBool = s_2 == s6565
-  s6567 :: SWord8 = s6549 >>> 1
-  s6568 :: SWord8 = s24 | s6567
-  s6569 :: SWord8 = s26 & s6567
-  s6570 :: SWord8 = if s6544 then s6568 else s6569
-  s6571 :: SWord1 = choose [0:0] s6570
-  s6572 :: SBool = s19 /= s6571
-  s6573 :: SWord1 = choose [0:0] s6558
-  s6574 :: SBool = s19 /= s6573
-  s6575 :: SWord8 = s6563 >>> 1
-  s6576 :: SWord8 = s24 | s6575
-  s6577 :: SWord8 = s26 & s6575
-  s6578 :: SWord8 = if s6574 then s6576 else s6577
-  s6579 :: SWord8 = if s22 then s6578 else s6562
-  s6580 :: SWord8 = s6579 >>> 1
-  s6581 :: SWord8 = s24 | s6580
-  s6582 :: SWord8 = s26 & s6580
-  s6583 :: SWord8 = if s6572 then s6581 else s6582
-  s6584 :: SWord8 = if s22 then s6583 else s6578
-  s6585 :: SWord1 = choose [0:0] s6584
-  s6586 :: SBool = s19 /= s6585
-  s6587 :: SBool = s_2 == s6586
-  s6588 :: SWord8 = s6570 >>> 1
-  s6589 :: SWord8 = s24 | s6588
-  s6590 :: SWord8 = s26 & s6588
-  s6591 :: SWord8 = if s6565 then s6589 else s6590
-  s6592 :: SWord8 = s6591 >>> 1
-  s6593 :: SWord8 = s24 | s6592
-  s6594 :: SWord8 = s26 & s6592
-  s6595 :: SWord8 = if s6586 then s6593 else s6594
-  s6596 :: SWord1 = choose [0:0] s6579
-  s6597 :: SBool = s19 /= s6596
-  s6598 :: SWord8 = s6584 >>> 1
-  s6599 :: SWord8 = s24 | s6598
-  s6600 :: SWord8 = s26 & s6598
-  s6601 :: SWord8 = if s6597 then s6599 else s6600
-  s6602 :: SWord8 = if s29 then s6498 else s5697
-  s6603 :: SWord8 = if s170 then s6515 else s6602
-  s6604 :: SWord8 = if s29 then s6520 else s6603
-  s6605 :: SWord8 = if s170 then s6536 else s6604
-  s6606 :: SWord8 = if s29 then s6541 else s6605
-  s6607 :: SWord8 = if s170 then s6557 else s6606
-  s6608 :: SWord8 = if s29 then s6562 else s6607
-  s6609 :: SWord8 = if s170 then s6578 else s6608
-  s6610 :: SWord8 = if s29 then s6583 else s6609
-  s6611 :: SWord8 = if s170 then s6601 else s6610
-  s6612 :: SWord8 = s6591 + s6611
-  s6613 :: SBool = s6612 < s6611
-  s6614 :: SBool = s6612 < s6591
-  s6615 :: SBool = s6613 | s6614
-  s6616 :: SWord8 = s6612 >>> 1
-  s6617 :: SWord8 = s24 | s6616
-  s6618 :: SWord8 = s26 & s6616
-  s6619 :: SWord8 = if s6615 then s6617 else s6618
-  s6620 :: SWord8 = if s6587 then s6595 else s6619
-  s6621 :: SWord8 = s6570 + s6609
-  s6622 :: SWord1 = choose [0:0] s6621
-  s6623 :: SBool = s19 /= s6622
-  s6624 :: SWord8 = if s6623 then s6581 else s6582
-  s6625 :: SWord8 = if s22 then s6624 else s6578
-  s6626 :: SWord1 = choose [0:0] s6625
-  s6627 :: SBool = s19 /= s6626
-  s6628 :: SBool = s_2 == s6627
-  s6629 :: SBool = s6621 < s6609
-  s6630 :: SBool = s6621 < s6570
-  s6631 :: SBool = s6629 | s6630
-  s6632 :: SWord8 = s6621 >>> 1
-  s6633 :: SWord8 = s24 | s6632
-  s6634 :: SWord8 = s26 & s6632
-  s6635 :: SWord8 = if s6631 then s6633 else s6634
-  s6636 :: SWord8 = s6635 >>> 1
-  s6637 :: SWord8 = s24 | s6636
-  s6638 :: SWord8 = s26 & s6636
-  s6639 :: SWord8 = if s6627 then s6637 else s6638
-  s6640 :: SWord8 = s6625 >>> 1
-  s6641 :: SWord8 = s24 | s6640
-  s6642 :: SWord8 = s26 & s6640
-  s6643 :: SWord8 = if s6597 then s6641 else s6642
-  s6644 :: SWord8 = if s29 then s6624 else s6609
-  s6645 :: SWord8 = if s170 then s6643 else s6644
-  s6646 :: SWord8 = s6635 + s6645
-  s6647 :: SBool = s6646 < s6645
-  s6648 :: SBool = s6646 < s6635
-  s6649 :: SBool = s6647 | s6648
-  s6650 :: SWord8 = s6646 >>> 1
-  s6651 :: SWord8 = s24 | s6650
-  s6652 :: SWord8 = s26 & s6650
-  s6653 :: SWord8 = if s6649 then s6651 else s6652
-  s6654 :: SWord8 = if s6628 then s6639 else s6653
-  s6655 :: SWord8 = if s6566 then s6620 else s6654
-  s6656 :: SWord8 = s6549 + s6607
-  s6657 :: SWord1 = choose [0:0] s6656
-  s6658 :: SBool = s19 /= s6657
-  s6659 :: SWord8 = if s6658 then s6560 else s6561
-  s6660 :: SWord8 = if s22 then s6659 else s6557
-  s6661 :: SWord1 = choose [0:0] s6660
-  s6662 :: SBool = s19 /= s6661
-  s6663 :: SBool = s_2 == s6662
-  s6664 :: SBool = s6656 < s6607
-  s6665 :: SBool = s6656 < s6549
-  s6666 :: SBool = s6664 | s6665
-  s6667 :: SWord8 = s6656 >>> 1
-  s6668 :: SWord8 = s24 | s6667
-  s6669 :: SWord8 = s26 & s6667
-  s6670 :: SWord8 = if s6666 then s6668 else s6669
-  s6671 :: SWord1 = choose [0:0] s6670
-  s6672 :: SBool = s19 /= s6671
-  s6673 :: SWord8 = s6660 >>> 1
-  s6674 :: SWord8 = s24 | s6673
-  s6675 :: SWord8 = s26 & s6673
-  s6676 :: SWord8 = if s6574 then s6674 else s6675
-  s6677 :: SWord8 = if s22 then s6676 else s6659
-  s6678 :: SWord8 = s6677 >>> 1
-  s6679 :: SWord8 = s24 | s6678
-  s6680 :: SWord8 = s26 & s6678
-  s6681 :: SWord8 = if s6672 then s6679 else s6680
-  s6682 :: SWord8 = if s22 then s6681 else s6676
-  s6683 :: SWord1 = choose [0:0] s6682
-  s6684 :: SBool = s19 /= s6683
-  s6685 :: SBool = s_2 == s6684
-  s6686 :: SWord8 = s6670 >>> 1
-  s6687 :: SWord8 = s24 | s6686
-  s6688 :: SWord8 = s26 & s6686
-  s6689 :: SWord8 = if s6662 then s6687 else s6688
-  s6690 :: SWord8 = s6689 >>> 1
-  s6691 :: SWord8 = s24 | s6690
-  s6692 :: SWord8 = s26 & s6690
-  s6693 :: SWord8 = if s6684 then s6691 else s6692
-  s6694 :: SWord1 = choose [0:0] s6677
-  s6695 :: SBool = s19 /= s6694
-  s6696 :: SWord8 = s6682 >>> 1
-  s6697 :: SWord8 = s24 | s6696
-  s6698 :: SWord8 = s26 & s6696
-  s6699 :: SWord8 = if s6695 then s6697 else s6698
-  s6700 :: SWord8 = if s29 then s6659 else s6607
-  s6701 :: SWord8 = if s170 then s6676 else s6700
-  s6702 :: SWord8 = if s29 then s6681 else s6701
-  s6703 :: SWord8 = if s170 then s6699 else s6702
-  s6704 :: SWord8 = s6689 + s6703
-  s6705 :: SBool = s6704 < s6703
-  s6706 :: SBool = s6704 < s6689
-  s6707 :: SBool = s6705 | s6706
-  s6708 :: SWord8 = s6704 >>> 1
-  s6709 :: SWord8 = s24 | s6708
-  s6710 :: SWord8 = s26 & s6708
-  s6711 :: SWord8 = if s6707 then s6709 else s6710
-  s6712 :: SWord8 = if s6685 then s6693 else s6711
-  s6713 :: SWord8 = s6670 + s6701
-  s6714 :: SWord1 = choose [0:0] s6713
-  s6715 :: SBool = s19 /= s6714
-  s6716 :: SWord8 = if s6715 then s6679 else s6680
-  s6717 :: SWord8 = if s22 then s6716 else s6676
-  s6718 :: SWord1 = choose [0:0] s6717
-  s6719 :: SBool = s19 /= s6718
-  s6720 :: SBool = s_2 == s6719
-  s6721 :: SBool = s6713 < s6701
-  s6722 :: SBool = s6713 < s6670
-  s6723 :: SBool = s6721 | s6722
-  s6724 :: SWord8 = s6713 >>> 1
-  s6725 :: SWord8 = s24 | s6724
-  s6726 :: SWord8 = s26 & s6724
-  s6727 :: SWord8 = if s6723 then s6725 else s6726
-  s6728 :: SWord8 = s6727 >>> 1
-  s6729 :: SWord8 = s24 | s6728
-  s6730 :: SWord8 = s26 & s6728
-  s6731 :: SWord8 = if s6719 then s6729 else s6730
-  s6732 :: SWord8 = s6717 >>> 1
-  s6733 :: SWord8 = s24 | s6732
-  s6734 :: SWord8 = s26 & s6732
-  s6735 :: SWord8 = if s6695 then s6733 else s6734
-  s6736 :: SWord8 = if s29 then s6716 else s6701
-  s6737 :: SWord8 = if s170 then s6735 else s6736
-  s6738 :: SWord8 = s6727 + s6737
-  s6739 :: SBool = s6738 < s6737
-  s6740 :: SBool = s6738 < s6727
-  s6741 :: SBool = s6739 | s6740
-  s6742 :: SWord8 = s6738 >>> 1
-  s6743 :: SWord8 = s24 | s6742
-  s6744 :: SWord8 = s26 & s6742
-  s6745 :: SWord8 = if s6741 then s6743 else s6744
-  s6746 :: SWord8 = if s6720 then s6731 else s6745
-  s6747 :: SWord8 = if s6663 then s6712 else s6746
-  s6748 :: SWord8 = if s6545 then s6655 else s6747
-  s6749 :: SWord8 = s6528 + s6605
-  s6750 :: SWord1 = choose [0:0] s6749
-  s6751 :: SBool = s19 /= s6750
-  s6752 :: SWord8 = if s6751 then s6539 else s6540
-  s6753 :: SWord8 = if s22 then s6752 else s6536
-  s6754 :: SWord1 = choose [0:0] s6753
-  s6755 :: SBool = s19 /= s6754
-  s6756 :: SBool = s_2 == s6755
-  s6757 :: SBool = s6749 < s6605
-  s6758 :: SBool = s6749 < s6528
-  s6759 :: SBool = s6757 | s6758
-  s6760 :: SWord8 = s6749 >>> 1
-  s6761 :: SWord8 = s24 | s6760
-  s6762 :: SWord8 = s26 & s6760
-  s6763 :: SWord8 = if s6759 then s6761 else s6762
-  s6764 :: SWord1 = choose [0:0] s6763
-  s6765 :: SBool = s19 /= s6764
-  s6766 :: SWord8 = s6753 >>> 1
-  s6767 :: SWord8 = s24 | s6766
-  s6768 :: SWord8 = s26 & s6766
-  s6769 :: SWord8 = if s6553 then s6767 else s6768
-  s6770 :: SWord8 = if s22 then s6769 else s6752
-  s6771 :: SWord8 = s6770 >>> 1
-  s6772 :: SWord8 = s24 | s6771
-  s6773 :: SWord8 = s26 & s6771
-  s6774 :: SWord8 = if s6765 then s6772 else s6773
-  s6775 :: SWord8 = if s22 then s6774 else s6769
-  s6776 :: SWord1 = choose [0:0] s6775
-  s6777 :: SBool = s19 /= s6776
-  s6778 :: SBool = s_2 == s6777
-  s6779 :: SWord8 = s6763 >>> 1
-  s6780 :: SWord8 = s24 | s6779
-  s6781 :: SWord8 = s26 & s6779
-  s6782 :: SWord8 = if s6755 then s6780 else s6781
-  s6783 :: SWord1 = choose [0:0] s6782
-  s6784 :: SBool = s19 /= s6783
-  s6785 :: SWord1 = choose [0:0] s6770
-  s6786 :: SBool = s19 /= s6785
-  s6787 :: SWord8 = s6775 >>> 1
-  s6788 :: SWord8 = s24 | s6787
-  s6789 :: SWord8 = s26 & s6787
-  s6790 :: SWord8 = if s6786 then s6788 else s6789
-  s6791 :: SWord8 = if s22 then s6790 else s6774
-  s6792 :: SWord8 = s6791 >>> 1
-  s6793 :: SWord8 = s24 | s6792
-  s6794 :: SWord8 = s26 & s6792
-  s6795 :: SWord8 = if s6784 then s6793 else s6794
-  s6796 :: SWord8 = if s22 then s6795 else s6790
-  s6797 :: SWord1 = choose [0:0] s6796
-  s6798 :: SBool = s19 /= s6797
-  s6799 :: SBool = s_2 == s6798
-  s6800 :: SWord8 = s6782 >>> 1
-  s6801 :: SWord8 = s24 | s6800
-  s6802 :: SWord8 = s26 & s6800
-  s6803 :: SWord8 = if s6777 then s6801 else s6802
-  s6804 :: SWord8 = s6803 >>> 1
-  s6805 :: SWord8 = s24 | s6804
-  s6806 :: SWord8 = s26 & s6804
-  s6807 :: SWord8 = if s6798 then s6805 else s6806
-  s6808 :: SWord1 = choose [0:0] s6791
-  s6809 :: SBool = s19 /= s6808
-  s6810 :: SWord8 = s6796 >>> 1
-  s6811 :: SWord8 = s24 | s6810
-  s6812 :: SWord8 = s26 & s6810
-  s6813 :: SWord8 = if s6809 then s6811 else s6812
-  s6814 :: SWord8 = if s29 then s6752 else s6605
-  s6815 :: SWord8 = if s170 then s6769 else s6814
-  s6816 :: SWord8 = if s29 then s6774 else s6815
-  s6817 :: SWord8 = if s170 then s6790 else s6816
-  s6818 :: SWord8 = if s29 then s6795 else s6817
-  s6819 :: SWord8 = if s170 then s6813 else s6818
-  s6820 :: SWord8 = s6803 + s6819
-  s6821 :: SBool = s6820 < s6819
-  s6822 :: SBool = s6820 < s6803
-  s6823 :: SBool = s6821 | s6822
-  s6824 :: SWord8 = s6820 >>> 1
-  s6825 :: SWord8 = s24 | s6824
-  s6826 :: SWord8 = s26 & s6824
-  s6827 :: SWord8 = if s6823 then s6825 else s6826
-  s6828 :: SWord8 = if s6799 then s6807 else s6827
-  s6829 :: SWord8 = s6782 + s6817
-  s6830 :: SWord1 = choose [0:0] s6829
-  s6831 :: SBool = s19 /= s6830
-  s6832 :: SWord8 = if s6831 then s6793 else s6794
-  s6833 :: SWord8 = if s22 then s6832 else s6790
-  s6834 :: SWord1 = choose [0:0] s6833
-  s6835 :: SBool = s19 /= s6834
-  s6836 :: SBool = s_2 == s6835
-  s6837 :: SBool = s6829 < s6817
-  s6838 :: SBool = s6829 < s6782
-  s6839 :: SBool = s6837 | s6838
-  s6840 :: SWord8 = s6829 >>> 1
-  s6841 :: SWord8 = s24 | s6840
-  s6842 :: SWord8 = s26 & s6840
-  s6843 :: SWord8 = if s6839 then s6841 else s6842
-  s6844 :: SWord8 = s6843 >>> 1
-  s6845 :: SWord8 = s24 | s6844
-  s6846 :: SWord8 = s26 & s6844
-  s6847 :: SWord8 = if s6835 then s6845 else s6846
-  s6848 :: SWord8 = s6833 >>> 1
-  s6849 :: SWord8 = s24 | s6848
-  s6850 :: SWord8 = s26 & s6848
-  s6851 :: SWord8 = if s6809 then s6849 else s6850
-  s6852 :: SWord8 = if s29 then s6832 else s6817
-  s6853 :: SWord8 = if s170 then s6851 else s6852
-  s6854 :: SWord8 = s6843 + s6853
-  s6855 :: SBool = s6854 < s6853
-  s6856 :: SBool = s6854 < s6843
-  s6857 :: SBool = s6855 | s6856
-  s6858 :: SWord8 = s6854 >>> 1
-  s6859 :: SWord8 = s24 | s6858
-  s6860 :: SWord8 = s26 & s6858
-  s6861 :: SWord8 = if s6857 then s6859 else s6860
-  s6862 :: SWord8 = if s6836 then s6847 else s6861
-  s6863 :: SWord8 = if s6778 then s6828 else s6862
-  s6864 :: SWord8 = s6763 + s6815
-  s6865 :: SWord1 = choose [0:0] s6864
-  s6866 :: SBool = s19 /= s6865
-  s6867 :: SWord8 = if s6866 then s6772 else s6773
-  s6868 :: SWord8 = if s22 then s6867 else s6769
-  s6869 :: SWord1 = choose [0:0] s6868
-  s6870 :: SBool = s19 /= s6869
-  s6871 :: SBool = s_2 == s6870
-  s6872 :: SBool = s6864 < s6815
-  s6873 :: SBool = s6864 < s6763
-  s6874 :: SBool = s6872 | s6873
-  s6875 :: SWord8 = s6864 >>> 1
-  s6876 :: SWord8 = s24 | s6875
-  s6877 :: SWord8 = s26 & s6875
-  s6878 :: SWord8 = if s6874 then s6876 else s6877
-  s6879 :: SWord1 = choose [0:0] s6878
-  s6880 :: SBool = s19 /= s6879
-  s6881 :: SWord8 = s6868 >>> 1
-  s6882 :: SWord8 = s24 | s6881
-  s6883 :: SWord8 = s26 & s6881
-  s6884 :: SWord8 = if s6786 then s6882 else s6883
-  s6885 :: SWord8 = if s22 then s6884 else s6867
-  s6886 :: SWord8 = s6885 >>> 1
-  s6887 :: SWord8 = s24 | s6886
-  s6888 :: SWord8 = s26 & s6886
-  s6889 :: SWord8 = if s6880 then s6887 else s6888
-  s6890 :: SWord8 = if s22 then s6889 else s6884
-  s6891 :: SWord1 = choose [0:0] s6890
-  s6892 :: SBool = s19 /= s6891
-  s6893 :: SBool = s_2 == s6892
-  s6894 :: SWord8 = s6878 >>> 1
-  s6895 :: SWord8 = s24 | s6894
-  s6896 :: SWord8 = s26 & s6894
-  s6897 :: SWord8 = if s6870 then s6895 else s6896
-  s6898 :: SWord8 = s6897 >>> 1
-  s6899 :: SWord8 = s24 | s6898
-  s6900 :: SWord8 = s26 & s6898
-  s6901 :: SWord8 = if s6892 then s6899 else s6900
-  s6902 :: SWord1 = choose [0:0] s6885
-  s6903 :: SBool = s19 /= s6902
-  s6904 :: SWord8 = s6890 >>> 1
-  s6905 :: SWord8 = s24 | s6904
-  s6906 :: SWord8 = s26 & s6904
-  s6907 :: SWord8 = if s6903 then s6905 else s6906
-  s6908 :: SWord8 = if s29 then s6867 else s6815
-  s6909 :: SWord8 = if s170 then s6884 else s6908
-  s6910 :: SWord8 = if s29 then s6889 else s6909
-  s6911 :: SWord8 = if s170 then s6907 else s6910
-  s6912 :: SWord8 = s6897 + s6911
-  s6913 :: SBool = s6912 < s6911
-  s6914 :: SBool = s6912 < s6897
-  s6915 :: SBool = s6913 | s6914
-  s6916 :: SWord8 = s6912 >>> 1
-  s6917 :: SWord8 = s24 | s6916
-  s6918 :: SWord8 = s26 & s6916
-  s6919 :: SWord8 = if s6915 then s6917 else s6918
-  s6920 :: SWord8 = if s6893 then s6901 else s6919
-  s6921 :: SWord8 = s6878 + s6909
-  s6922 :: SWord1 = choose [0:0] s6921
-  s6923 :: SBool = s19 /= s6922
-  s6924 :: SWord8 = if s6923 then s6887 else s6888
-  s6925 :: SWord8 = if s22 then s6924 else s6884
-  s6926 :: SWord1 = choose [0:0] s6925
-  s6927 :: SBool = s19 /= s6926
-  s6928 :: SBool = s_2 == s6927
-  s6929 :: SBool = s6921 < s6909
-  s6930 :: SBool = s6921 < s6878
-  s6931 :: SBool = s6929 | s6930
-  s6932 :: SWord8 = s6921 >>> 1
-  s6933 :: SWord8 = s24 | s6932
-  s6934 :: SWord8 = s26 & s6932
-  s6935 :: SWord8 = if s6931 then s6933 else s6934
-  s6936 :: SWord8 = s6935 >>> 1
-  s6937 :: SWord8 = s24 | s6936
-  s6938 :: SWord8 = s26 & s6936
-  s6939 :: SWord8 = if s6927 then s6937 else s6938
-  s6940 :: SWord8 = s6925 >>> 1
-  s6941 :: SWord8 = s24 | s6940
-  s6942 :: SWord8 = s26 & s6940
-  s6943 :: SWord8 = if s6903 then s6941 else s6942
-  s6944 :: SWord8 = if s29 then s6924 else s6909
-  s6945 :: SWord8 = if s170 then s6943 else s6944
-  s6946 :: SWord8 = s6935 + s6945
-  s6947 :: SBool = s6946 < s6945
-  s6948 :: SBool = s6946 < s6935
-  s6949 :: SBool = s6947 | s6948
-  s6950 :: SWord8 = s6946 >>> 1
-  s6951 :: SWord8 = s24 | s6950
-  s6952 :: SWord8 = s26 & s6950
-  s6953 :: SWord8 = if s6949 then s6951 else s6952
-  s6954 :: SWord8 = if s6928 then s6939 else s6953
-  s6955 :: SWord8 = if s6871 then s6920 else s6954
-  s6956 :: SWord8 = if s6756 then s6863 else s6955
-  s6957 :: SWord8 = if s6524 then s6748 else s6956
-  s6958 :: SWord8 = s6509 + s6603
-  s6959 :: SWord1 = choose [0:0] s6958
-  s6960 :: SBool = s19 /= s6959
-  s6961 :: SWord8 = if s6960 then s6518 else s6519
-  s6962 :: SWord8 = if s22 then s6961 else s6515
-  s6963 :: SWord1 = choose [0:0] s6962
-  s6964 :: SBool = s19 /= s6963
-  s6965 :: SBool = s_2 == s6964
-  s6966 :: SBool = s6958 < s6603
-  s6967 :: SBool = s6958 < s6509
-  s6968 :: SBool = s6966 | s6967
-  s6969 :: SWord8 = s6958 >>> 1
-  s6970 :: SWord8 = s24 | s6969
-  s6971 :: SWord8 = s26 & s6969
-  s6972 :: SWord8 = if s6968 then s6970 else s6971
-  s6973 :: SWord1 = choose [0:0] s6972
-  s6974 :: SBool = s19 /= s6973
-  s6975 :: SWord8 = s6962 >>> 1
-  s6976 :: SWord8 = s24 | s6975
-  s6977 :: SWord8 = s26 & s6975
-  s6978 :: SWord8 = if s6532 then s6976 else s6977
-  s6979 :: SWord8 = if s22 then s6978 else s6961
-  s6980 :: SWord8 = s6979 >>> 1
-  s6981 :: SWord8 = s24 | s6980
-  s6982 :: SWord8 = s26 & s6980
-  s6983 :: SWord8 = if s6974 then s6981 else s6982
-  s6984 :: SWord8 = if s22 then s6983 else s6978
-  s6985 :: SWord1 = choose [0:0] s6984
-  s6986 :: SBool = s19 /= s6985
-  s6987 :: SBool = s_2 == s6986
-  s6988 :: SWord8 = s6972 >>> 1
-  s6989 :: SWord8 = s24 | s6988
-  s6990 :: SWord8 = s26 & s6988
-  s6991 :: SWord8 = if s6964 then s6989 else s6990
-  s6992 :: SWord1 = choose [0:0] s6991
-  s6993 :: SBool = s19 /= s6992
-  s6994 :: SWord1 = choose [0:0] s6979
-  s6995 :: SBool = s19 /= s6994
-  s6996 :: SWord8 = s6984 >>> 1
-  s6997 :: SWord8 = s24 | s6996
-  s6998 :: SWord8 = s26 & s6996
-  s6999 :: SWord8 = if s6995 then s6997 else s6998
-  s7000 :: SWord8 = if s22 then s6999 else s6983
-  s7001 :: SWord8 = s7000 >>> 1
-  s7002 :: SWord8 = s24 | s7001
-  s7003 :: SWord8 = s26 & s7001
-  s7004 :: SWord8 = if s6993 then s7002 else s7003
-  s7005 :: SWord8 = if s22 then s7004 else s6999
-  s7006 :: SWord1 = choose [0:0] s7005
-  s7007 :: SBool = s19 /= s7006
-  s7008 :: SBool = s_2 == s7007
-  s7009 :: SWord8 = s6991 >>> 1
-  s7010 :: SWord8 = s24 | s7009
-  s7011 :: SWord8 = s26 & s7009
-  s7012 :: SWord8 = if s6986 then s7010 else s7011
-  s7013 :: SWord1 = choose [0:0] s7012
-  s7014 :: SBool = s19 /= s7013
-  s7015 :: SWord1 = choose [0:0] s7000
-  s7016 :: SBool = s19 /= s7015
-  s7017 :: SWord8 = s7005 >>> 1
-  s7018 :: SWord8 = s24 | s7017
-  s7019 :: SWord8 = s26 & s7017
-  s7020 :: SWord8 = if s7016 then s7018 else s7019
-  s7021 :: SWord8 = if s22 then s7020 else s7004
-  s7022 :: SWord8 = s7021 >>> 1
-  s7023 :: SWord8 = s24 | s7022
-  s7024 :: SWord8 = s26 & s7022
-  s7025 :: SWord8 = if s7014 then s7023 else s7024
-  s7026 :: SWord8 = if s22 then s7025 else s7020
-  s7027 :: SWord1 = choose [0:0] s7026
-  s7028 :: SBool = s19 /= s7027
-  s7029 :: SBool = s_2 == s7028
-  s7030 :: SWord8 = s7012 >>> 1
-  s7031 :: SWord8 = s24 | s7030
-  s7032 :: SWord8 = s26 & s7030
-  s7033 :: SWord8 = if s7007 then s7031 else s7032
-  s7034 :: SWord8 = s7033 >>> 1
-  s7035 :: SWord8 = s24 | s7034
-  s7036 :: SWord8 = s26 & s7034
-  s7037 :: SWord8 = if s7028 then s7035 else s7036
-  s7038 :: SWord1 = choose [0:0] s7021
-  s7039 :: SBool = s19 /= s7038
-  s7040 :: SWord8 = s7026 >>> 1
-  s7041 :: SWord8 = s24 | s7040
-  s7042 :: SWord8 = s26 & s7040
-  s7043 :: SWord8 = if s7039 then s7041 else s7042
-  s7044 :: SWord8 = if s29 then s6961 else s6603
-  s7045 :: SWord8 = if s170 then s6978 else s7044
-  s7046 :: SWord8 = if s29 then s6983 else s7045
-  s7047 :: SWord8 = if s170 then s6999 else s7046
-  s7048 :: SWord8 = if s29 then s7004 else s7047
-  s7049 :: SWord8 = if s170 then s7020 else s7048
-  s7050 :: SWord8 = if s29 then s7025 else s7049
-  s7051 :: SWord8 = if s170 then s7043 else s7050
-  s7052 :: SWord8 = s7033 + s7051
-  s7053 :: SBool = s7052 < s7051
-  s7054 :: SBool = s7052 < s7033
-  s7055 :: SBool = s7053 | s7054
-  s7056 :: SWord8 = s7052 >>> 1
-  s7057 :: SWord8 = s24 | s7056
-  s7058 :: SWord8 = s26 & s7056
-  s7059 :: SWord8 = if s7055 then s7057 else s7058
-  s7060 :: SWord8 = if s7029 then s7037 else s7059
-  s7061 :: SWord8 = s7012 + s7049
-  s7062 :: SWord1 = choose [0:0] s7061
-  s7063 :: SBool = s19 /= s7062
-  s7064 :: SWord8 = if s7063 then s7023 else s7024
-  s7065 :: SWord8 = if s22 then s7064 else s7020
-  s7066 :: SWord1 = choose [0:0] s7065
-  s7067 :: SBool = s19 /= s7066
-  s7068 :: SBool = s_2 == s7067
-  s7069 :: SBool = s7061 < s7049
-  s7070 :: SBool = s7061 < s7012
-  s7071 :: SBool = s7069 | s7070
-  s7072 :: SWord8 = s7061 >>> 1
-  s7073 :: SWord8 = s24 | s7072
-  s7074 :: SWord8 = s26 & s7072
-  s7075 :: SWord8 = if s7071 then s7073 else s7074
-  s7076 :: SWord8 = s7075 >>> 1
-  s7077 :: SWord8 = s24 | s7076
-  s7078 :: SWord8 = s26 & s7076
-  s7079 :: SWord8 = if s7067 then s7077 else s7078
-  s7080 :: SWord8 = s7065 >>> 1
-  s7081 :: SWord8 = s24 | s7080
-  s7082 :: SWord8 = s26 & s7080
-  s7083 :: SWord8 = if s7039 then s7081 else s7082
-  s7084 :: SWord8 = if s29 then s7064 else s7049
-  s7085 :: SWord8 = if s170 then s7083 else s7084
-  s7086 :: SWord8 = s7075 + s7085
-  s7087 :: SBool = s7086 < s7085
-  s7088 :: SBool = s7086 < s7075
-  s7089 :: SBool = s7087 | s7088
-  s7090 :: SWord8 = s7086 >>> 1
-  s7091 :: SWord8 = s24 | s7090
-  s7092 :: SWord8 = s26 & s7090
-  s7093 :: SWord8 = if s7089 then s7091 else s7092
-  s7094 :: SWord8 = if s7068 then s7079 else s7093
-  s7095 :: SWord8 = if s7008 then s7060 else s7094
-  s7096 :: SWord8 = s6991 + s7047
-  s7097 :: SWord1 = choose [0:0] s7096
-  s7098 :: SBool = s19 /= s7097
-  s7099 :: SWord8 = if s7098 then s7002 else s7003
-  s7100 :: SWord8 = if s22 then s7099 else s6999
-  s7101 :: SWord1 = choose [0:0] s7100
-  s7102 :: SBool = s19 /= s7101
-  s7103 :: SBool = s_2 == s7102
-  s7104 :: SBool = s7096 < s7047
-  s7105 :: SBool = s7096 < s6991
-  s7106 :: SBool = s7104 | s7105
-  s7107 :: SWord8 = s7096 >>> 1
-  s7108 :: SWord8 = s24 | s7107
-  s7109 :: SWord8 = s26 & s7107
-  s7110 :: SWord8 = if s7106 then s7108 else s7109
-  s7111 :: SWord1 = choose [0:0] s7110
-  s7112 :: SBool = s19 /= s7111
-  s7113 :: SWord8 = s7100 >>> 1
-  s7114 :: SWord8 = s24 | s7113
-  s7115 :: SWord8 = s26 & s7113
-  s7116 :: SWord8 = if s7016 then s7114 else s7115
-  s7117 :: SWord8 = if s22 then s7116 else s7099
-  s7118 :: SWord8 = s7117 >>> 1
-  s7119 :: SWord8 = s24 | s7118
-  s7120 :: SWord8 = s26 & s7118
-  s7121 :: SWord8 = if s7112 then s7119 else s7120
-  s7122 :: SWord8 = if s22 then s7121 else s7116
-  s7123 :: SWord1 = choose [0:0] s7122
-  s7124 :: SBool = s19 /= s7123
-  s7125 :: SBool = s_2 == s7124
-  s7126 :: SWord8 = s7110 >>> 1
-  s7127 :: SWord8 = s24 | s7126
-  s7128 :: SWord8 = s26 & s7126
-  s7129 :: SWord8 = if s7102 then s7127 else s7128
-  s7130 :: SWord8 = s7129 >>> 1
-  s7131 :: SWord8 = s24 | s7130
-  s7132 :: SWord8 = s26 & s7130
-  s7133 :: SWord8 = if s7124 then s7131 else s7132
-  s7134 :: SWord1 = choose [0:0] s7117
-  s7135 :: SBool = s19 /= s7134
-  s7136 :: SWord8 = s7122 >>> 1
-  s7137 :: SWord8 = s24 | s7136
-  s7138 :: SWord8 = s26 & s7136
-  s7139 :: SWord8 = if s7135 then s7137 else s7138
-  s7140 :: SWord8 = if s29 then s7099 else s7047
-  s7141 :: SWord8 = if s170 then s7116 else s7140
-  s7142 :: SWord8 = if s29 then s7121 else s7141
-  s7143 :: SWord8 = if s170 then s7139 else s7142
-  s7144 :: SWord8 = s7129 + s7143
-  s7145 :: SBool = s7144 < s7143
-  s7146 :: SBool = s7144 < s7129
-  s7147 :: SBool = s7145 | s7146
-  s7148 :: SWord8 = s7144 >>> 1
-  s7149 :: SWord8 = s24 | s7148
-  s7150 :: SWord8 = s26 & s7148
-  s7151 :: SWord8 = if s7147 then s7149 else s7150
-  s7152 :: SWord8 = if s7125 then s7133 else s7151
-  s7153 :: SWord8 = s7110 + s7141
-  s7154 :: SWord1 = choose [0:0] s7153
-  s7155 :: SBool = s19 /= s7154
-  s7156 :: SWord8 = if s7155 then s7119 else s7120
-  s7157 :: SWord8 = if s22 then s7156 else s7116
-  s7158 :: SWord1 = choose [0:0] s7157
-  s7159 :: SBool = s19 /= s7158
-  s7160 :: SBool = s_2 == s7159
-  s7161 :: SBool = s7153 < s7141
-  s7162 :: SBool = s7153 < s7110
-  s7163 :: SBool = s7161 | s7162
-  s7164 :: SWord8 = s7153 >>> 1
-  s7165 :: SWord8 = s24 | s7164
-  s7166 :: SWord8 = s26 & s7164
-  s7167 :: SWord8 = if s7163 then s7165 else s7166
-  s7168 :: SWord8 = s7167 >>> 1
-  s7169 :: SWord8 = s24 | s7168
-  s7170 :: SWord8 = s26 & s7168
-  s7171 :: SWord8 = if s7159 then s7169 else s7170
-  s7172 :: SWord8 = s7157 >>> 1
-  s7173 :: SWord8 = s24 | s7172
-  s7174 :: SWord8 = s26 & s7172
-  s7175 :: SWord8 = if s7135 then s7173 else s7174
-  s7176 :: SWord8 = if s29 then s7156 else s7141
-  s7177 :: SWord8 = if s170 then s7175 else s7176
-  s7178 :: SWord8 = s7167 + s7177
-  s7179 :: SBool = s7178 < s7177
-  s7180 :: SBool = s7178 < s7167
-  s7181 :: SBool = s7179 | s7180
-  s7182 :: SWord8 = s7178 >>> 1
-  s7183 :: SWord8 = s24 | s7182
-  s7184 :: SWord8 = s26 & s7182
-  s7185 :: SWord8 = if s7181 then s7183 else s7184
-  s7186 :: SWord8 = if s7160 then s7171 else s7185
-  s7187 :: SWord8 = if s7103 then s7152 else s7186
-  s7188 :: SWord8 = if s6987 then s7095 else s7187
-  s7189 :: SWord8 = s6972 + s7045
-  s7190 :: SWord1 = choose [0:0] s7189
-  s7191 :: SBool = s19 /= s7190
-  s7192 :: SWord8 = if s7191 then s6981 else s6982
-  s7193 :: SWord8 = if s22 then s7192 else s6978
-  s7194 :: SWord1 = choose [0:0] s7193
-  s7195 :: SBool = s19 /= s7194
-  s7196 :: SBool = s_2 == s7195
-  s7197 :: SBool = s7189 < s7045
-  s7198 :: SBool = s7189 < s6972
-  s7199 :: SBool = s7197 | s7198
-  s7200 :: SWord8 = s7189 >>> 1
-  s7201 :: SWord8 = s24 | s7200
-  s7202 :: SWord8 = s26 & s7200
-  s7203 :: SWord8 = if s7199 then s7201 else s7202
-  s7204 :: SWord1 = choose [0:0] s7203
-  s7205 :: SBool = s19 /= s7204
-  s7206 :: SWord8 = s7193 >>> 1
-  s7207 :: SWord8 = s24 | s7206
-  s7208 :: SWord8 = s26 & s7206
-  s7209 :: SWord8 = if s6995 then s7207 else s7208
-  s7210 :: SWord8 = if s22 then s7209 else s7192
-  s7211 :: SWord8 = s7210 >>> 1
-  s7212 :: SWord8 = s24 | s7211
-  s7213 :: SWord8 = s26 & s7211
-  s7214 :: SWord8 = if s7205 then s7212 else s7213
-  s7215 :: SWord8 = if s22 then s7214 else s7209
-  s7216 :: SWord1 = choose [0:0] s7215
-  s7217 :: SBool = s19 /= s7216
-  s7218 :: SBool = s_2 == s7217
-  s7219 :: SWord8 = s7203 >>> 1
-  s7220 :: SWord8 = s24 | s7219
-  s7221 :: SWord8 = s26 & s7219
-  s7222 :: SWord8 = if s7195 then s7220 else s7221
-  s7223 :: SWord1 = choose [0:0] s7222
-  s7224 :: SBool = s19 /= s7223
-  s7225 :: SWord1 = choose [0:0] s7210
-  s7226 :: SBool = s19 /= s7225
-  s7227 :: SWord8 = s7215 >>> 1
-  s7228 :: SWord8 = s24 | s7227
-  s7229 :: SWord8 = s26 & s7227
-  s7230 :: SWord8 = if s7226 then s7228 else s7229
-  s7231 :: SWord8 = if s22 then s7230 else s7214
-  s7232 :: SWord8 = s7231 >>> 1
-  s7233 :: SWord8 = s24 | s7232
-  s7234 :: SWord8 = s26 & s7232
-  s7235 :: SWord8 = if s7224 then s7233 else s7234
-  s7236 :: SWord8 = if s22 then s7235 else s7230
-  s7237 :: SWord1 = choose [0:0] s7236
-  s7238 :: SBool = s19 /= s7237
-  s7239 :: SBool = s_2 == s7238
-  s7240 :: SWord8 = s7222 >>> 1
-  s7241 :: SWord8 = s24 | s7240
-  s7242 :: SWord8 = s26 & s7240
-  s7243 :: SWord8 = if s7217 then s7241 else s7242
-  s7244 :: SWord8 = s7243 >>> 1
-  s7245 :: SWord8 = s24 | s7244
-  s7246 :: SWord8 = s26 & s7244
-  s7247 :: SWord8 = if s7238 then s7245 else s7246
-  s7248 :: SWord1 = choose [0:0] s7231
-  s7249 :: SBool = s19 /= s7248
-  s7250 :: SWord8 = s7236 >>> 1
-  s7251 :: SWord8 = s24 | s7250
-  s7252 :: SWord8 = s26 & s7250
-  s7253 :: SWord8 = if s7249 then s7251 else s7252
-  s7254 :: SWord8 = if s29 then s7192 else s7045
-  s7255 :: SWord8 = if s170 then s7209 else s7254
-  s7256 :: SWord8 = if s29 then s7214 else s7255
-  s7257 :: SWord8 = if s170 then s7230 else s7256
-  s7258 :: SWord8 = if s29 then s7235 else s7257
-  s7259 :: SWord8 = if s170 then s7253 else s7258
-  s7260 :: SWord8 = s7243 + s7259
-  s7261 :: SBool = s7260 < s7259
-  s7262 :: SBool = s7260 < s7243
-  s7263 :: SBool = s7261 | s7262
-  s7264 :: SWord8 = s7260 >>> 1
-  s7265 :: SWord8 = s24 | s7264
-  s7266 :: SWord8 = s26 & s7264
-  s7267 :: SWord8 = if s7263 then s7265 else s7266
-  s7268 :: SWord8 = if s7239 then s7247 else s7267
-  s7269 :: SWord8 = s7222 + s7257
-  s7270 :: SWord1 = choose [0:0] s7269
-  s7271 :: SBool = s19 /= s7270
-  s7272 :: SWord8 = if s7271 then s7233 else s7234
-  s7273 :: SWord8 = if s22 then s7272 else s7230
-  s7274 :: SWord1 = choose [0:0] s7273
-  s7275 :: SBool = s19 /= s7274
-  s7276 :: SBool = s_2 == s7275
-  s7277 :: SBool = s7269 < s7257
-  s7278 :: SBool = s7269 < s7222
-  s7279 :: SBool = s7277 | s7278
-  s7280 :: SWord8 = s7269 >>> 1
-  s7281 :: SWord8 = s24 | s7280
-  s7282 :: SWord8 = s26 & s7280
-  s7283 :: SWord8 = if s7279 then s7281 else s7282
-  s7284 :: SWord8 = s7283 >>> 1
-  s7285 :: SWord8 = s24 | s7284
-  s7286 :: SWord8 = s26 & s7284
-  s7287 :: SWord8 = if s7275 then s7285 else s7286
-  s7288 :: SWord8 = s7273 >>> 1
-  s7289 :: SWord8 = s24 | s7288
-  s7290 :: SWord8 = s26 & s7288
-  s7291 :: SWord8 = if s7249 then s7289 else s7290
-  s7292 :: SWord8 = if s29 then s7272 else s7257
-  s7293 :: SWord8 = if s170 then s7291 else s7292
-  s7294 :: SWord8 = s7283 + s7293
-  s7295 :: SBool = s7294 < s7293
-  s7296 :: SBool = s7294 < s7283
-  s7297 :: SBool = s7295 | s7296
-  s7298 :: SWord8 = s7294 >>> 1
-  s7299 :: SWord8 = s24 | s7298
-  s7300 :: SWord8 = s26 & s7298
-  s7301 :: SWord8 = if s7297 then s7299 else s7300
-  s7302 :: SWord8 = if s7276 then s7287 else s7301
-  s7303 :: SWord8 = if s7218 then s7268 else s7302
-  s7304 :: SWord8 = s7203 + s7255
-  s7305 :: SWord1 = choose [0:0] s7304
-  s7306 :: SBool = s19 /= s7305
-  s7307 :: SWord8 = if s7306 then s7212 else s7213
-  s7308 :: SWord8 = if s22 then s7307 else s7209
-  s7309 :: SWord1 = choose [0:0] s7308
-  s7310 :: SBool = s19 /= s7309
-  s7311 :: SBool = s_2 == s7310
-  s7312 :: SBool = s7304 < s7255
-  s7313 :: SBool = s7304 < s7203
-  s7314 :: SBool = s7312 | s7313
-  s7315 :: SWord8 = s7304 >>> 1
-  s7316 :: SWord8 = s24 | s7315
-  s7317 :: SWord8 = s26 & s7315
-  s7318 :: SWord8 = if s7314 then s7316 else s7317
-  s7319 :: SWord1 = choose [0:0] s7318
-  s7320 :: SBool = s19 /= s7319
-  s7321 :: SWord8 = s7308 >>> 1
-  s7322 :: SWord8 = s24 | s7321
-  s7323 :: SWord8 = s26 & s7321
-  s7324 :: SWord8 = if s7226 then s7322 else s7323
-  s7325 :: SWord8 = if s22 then s7324 else s7307
-  s7326 :: SWord8 = s7325 >>> 1
-  s7327 :: SWord8 = s24 | s7326
-  s7328 :: SWord8 = s26 & s7326
-  s7329 :: SWord8 = if s7320 then s7327 else s7328
-  s7330 :: SWord8 = if s22 then s7329 else s7324
-  s7331 :: SWord1 = choose [0:0] s7330
-  s7332 :: SBool = s19 /= s7331
-  s7333 :: SBool = s_2 == s7332
-  s7334 :: SWord8 = s7318 >>> 1
-  s7335 :: SWord8 = s24 | s7334
-  s7336 :: SWord8 = s26 & s7334
-  s7337 :: SWord8 = if s7310 then s7335 else s7336
-  s7338 :: SWord8 = s7337 >>> 1
-  s7339 :: SWord8 = s24 | s7338
-  s7340 :: SWord8 = s26 & s7338
-  s7341 :: SWord8 = if s7332 then s7339 else s7340
-  s7342 :: SWord1 = choose [0:0] s7325
-  s7343 :: SBool = s19 /= s7342
-  s7344 :: SWord8 = s7330 >>> 1
-  s7345 :: SWord8 = s24 | s7344
-  s7346 :: SWord8 = s26 & s7344
-  s7347 :: SWord8 = if s7343 then s7345 else s7346
-  s7348 :: SWord8 = if s29 then s7307 else s7255
-  s7349 :: SWord8 = if s170 then s7324 else s7348
-  s7350 :: SWord8 = if s29 then s7329 else s7349
-  s7351 :: SWord8 = if s170 then s7347 else s7350
-  s7352 :: SWord8 = s7337 + s7351
-  s7353 :: SBool = s7352 < s7351
-  s7354 :: SBool = s7352 < s7337
-  s7355 :: SBool = s7353 | s7354
-  s7356 :: SWord8 = s7352 >>> 1
-  s7357 :: SWord8 = s24 | s7356
-  s7358 :: SWord8 = s26 & s7356
-  s7359 :: SWord8 = if s7355 then s7357 else s7358
-  s7360 :: SWord8 = if s7333 then s7341 else s7359
-  s7361 :: SWord8 = s7318 + s7349
-  s7362 :: SWord1 = choose [0:0] s7361
-  s7363 :: SBool = s19 /= s7362
-  s7364 :: SWord8 = if s7363 then s7327 else s7328
-  s7365 :: SWord8 = if s22 then s7364 else s7324
-  s7366 :: SWord1 = choose [0:0] s7365
-  s7367 :: SBool = s19 /= s7366
-  s7368 :: SBool = s_2 == s7367
-  s7369 :: SBool = s7361 < s7349
-  s7370 :: SBool = s7361 < s7318
-  s7371 :: SBool = s7369 | s7370
-  s7372 :: SWord8 = s7361 >>> 1
-  s7373 :: SWord8 = s24 | s7372
-  s7374 :: SWord8 = s26 & s7372
-  s7375 :: SWord8 = if s7371 then s7373 else s7374
-  s7376 :: SWord8 = s7375 >>> 1
-  s7377 :: SWord8 = s24 | s7376
-  s7378 :: SWord8 = s26 & s7376
-  s7379 :: SWord8 = if s7367 then s7377 else s7378
-  s7380 :: SWord8 = s7365 >>> 1
-  s7381 :: SWord8 = s24 | s7380
-  s7382 :: SWord8 = s26 & s7380
-  s7383 :: SWord8 = if s7343 then s7381 else s7382
-  s7384 :: SWord8 = if s29 then s7364 else s7349
-  s7385 :: SWord8 = if s170 then s7383 else s7384
-  s7386 :: SWord8 = s7375 + s7385
-  s7387 :: SBool = s7386 < s7385
-  s7388 :: SBool = s7386 < s7375
-  s7389 :: SBool = s7387 | s7388
-  s7390 :: SWord8 = s7386 >>> 1
-  s7391 :: SWord8 = s24 | s7390
-  s7392 :: SWord8 = s26 & s7390
-  s7393 :: SWord8 = if s7389 then s7391 else s7392
-  s7394 :: SWord8 = if s7368 then s7379 else s7393
-  s7395 :: SWord8 = if s7311 then s7360 else s7394
-  s7396 :: SWord8 = if s7196 then s7303 else s7395
-  s7397 :: SWord8 = if s6965 then s7188 else s7396
-  s7398 :: SWord8 = if s6502 then s6957 else s7397
-  s7399 :: SWord8 = if s5575 then s6494 else s7398
-  s7400 :: SWord8 = if s3725 then s5567 else s7399
-  s7401 :: SWord8 = if s21 then s3717 else s7400
-  s7402 :: SWord16 = s17 # s7401
-  s7403 :: SWord16 = s16 * s7402
-  s7404 :: SWord1 = choose [0:0] s165
-  s7405 :: SBool = s19 /= s7404
-  s7406 :: SWord8 = if s22 then s176 else s157
-  s7407 :: SWord8 = s7406 >>> 1
-  s7408 :: SWord8 = s24 | s7407
-  s7409 :: SWord8 = s26 & s7407
-  s7410 :: SWord8 = if s7405 then s7408 else s7409
-  s7411 :: SWord1 = choose [0:0] s193
-  s7412 :: SBool = s19 /= s7411
-  s7413 :: SWord8 = if s7412 then s7408 else s7409
-  s7414 :: SWord8 = if s161 then s7410 else s7413
-  s7415 :: SWord1 = choose [0:0] s216
-  s7416 :: SBool = s19 /= s7415
-  s7417 :: SWord8 = if s22 then s224 else s205
-  s7418 :: SWord8 = s7417 >>> 1
-  s7419 :: SWord8 = s24 | s7418
-  s7420 :: SWord8 = s26 & s7418
-  s7421 :: SWord8 = if s7416 then s7419 else s7420
-  s7422 :: SWord1 = choose [0:0] s227
-  s7423 :: SBool = s19 /= s7422
-  s7424 :: SWord8 = if s7423 then s7419 else s7420
-  s7425 :: SWord8 = if s209 then s7421 else s7424
-  s7426 :: SWord8 = if s140 then s7414 else s7425
-  s7427 :: SWord1 = choose [0:0] s270
-  s7428 :: SBool = s19 /= s7427
-  s7429 :: SWord8 = if s22 then s280 else s262
-  s7430 :: SWord8 = s7429 >>> 1
-  s7431 :: SWord8 = s24 | s7430
-  s7432 :: SWord8 = s26 & s7430
-  s7433 :: SWord8 = if s7428 then s7431 else s7432
-  s7434 :: SWord1 = choose [0:0] s285
-  s7435 :: SBool = s19 /= s7434
-  s7436 :: SWord8 = if s7435 then s7431 else s7432
-  s7437 :: SWord8 = if s266 then s7433 else s7436
-  s7438 :: SWord1 = choose [0:0] s308
-  s7439 :: SBool = s19 /= s7438
-  s7440 :: SWord8 = if s22 then s316 else s297
-  s7441 :: SWord8 = s7440 >>> 1
-  s7442 :: SWord8 = s24 | s7441
-  s7443 :: SWord8 = s26 & s7441
-  s7444 :: SWord8 = if s7439 then s7442 else s7443
-  s7445 :: SWord1 = choose [0:0] s319
-  s7446 :: SBool = s19 /= s7445
-  s7447 :: SWord8 = if s7446 then s7442 else s7443
-  s7448 :: SWord8 = if s301 then s7444 else s7447
-  s7449 :: SWord8 = if s244 then s7437 else s7448
-  s7450 :: SWord8 = if s119 then s7426 else s7449
-  s7451 :: SWord1 = choose [0:0] s384
-  s7452 :: SBool = s19 /= s7451
-  s7453 :: SWord8 = if s22 then s394 else s376
-  s7454 :: SWord8 = s7453 >>> 1
-  s7455 :: SWord8 = s24 | s7454
-  s7456 :: SWord8 = s26 & s7454
-  s7457 :: SWord8 = if s7452 then s7455 else s7456
-  s7458 :: SWord1 = choose [0:0] s401
-  s7459 :: SBool = s19 /= s7458
-  s7460 :: SWord8 = if s7459 then s7455 else s7456
-  s7461 :: SWord8 = if s380 then s7457 else s7460
-  s7462 :: SWord1 = choose [0:0] s424
-  s7463 :: SBool = s19 /= s7462
-  s7464 :: SWord8 = if s22 then s432 else s413
-  s7465 :: SWord8 = s7464 >>> 1
-  s7466 :: SWord8 = s24 | s7465
-  s7467 :: SWord8 = s26 & s7465
-  s7468 :: SWord8 = if s7463 then s7466 else s7467
-  s7469 :: SWord1 = choose [0:0] s435
-  s7470 :: SBool = s19 /= s7469
-  s7471 :: SWord8 = if s7470 then s7466 else s7467
-  s7472 :: SWord8 = if s417 then s7468 else s7471
-  s7473 :: SWord8 = if s359 then s7461 else s7472
-  s7474 :: SWord1 = choose [0:0] s478
-  s7475 :: SBool = s19 /= s7474
-  s7476 :: SWord8 = if s22 then s488 else s470
-  s7477 :: SWord8 = s7476 >>> 1
-  s7478 :: SWord8 = s24 | s7477
-  s7479 :: SWord8 = s26 & s7477
-  s7480 :: SWord8 = if s7475 then s7478 else s7479
-  s7481 :: SWord1 = choose [0:0] s493
-  s7482 :: SBool = s19 /= s7481
-  s7483 :: SWord8 = if s7482 then s7478 else s7479
-  s7484 :: SWord8 = if s474 then s7480 else s7483
-  s7485 :: SWord1 = choose [0:0] s516
-  s7486 :: SBool = s19 /= s7485
-  s7487 :: SWord8 = if s22 then s524 else s505
-  s7488 :: SWord8 = s7487 >>> 1
-  s7489 :: SWord8 = s24 | s7488
-  s7490 :: SWord8 = s26 & s7488
-  s7491 :: SWord8 = if s7486 then s7489 else s7490
-  s7492 :: SWord1 = choose [0:0] s527
-  s7493 :: SBool = s19 /= s7492
-  s7494 :: SWord8 = if s7493 then s7489 else s7490
-  s7495 :: SWord8 = if s509 then s7491 else s7494
-  s7496 :: SWord8 = if s452 then s7484 else s7495
-  s7497 :: SWord8 = if s337 then s7473 else s7496
-  s7498 :: SWord8 = if s98 then s7450 else s7497
-  s7499 :: SWord1 = choose [0:0] s614
-  s7500 :: SBool = s19 /= s7499
-  s7501 :: SWord8 = if s22 then s624 else s606
-  s7502 :: SWord8 = s7501 >>> 1
-  s7503 :: SWord8 = s24 | s7502
-  s7504 :: SWord8 = s26 & s7502
-  s7505 :: SWord8 = if s7500 then s7503 else s7504
-  s7506 :: SWord1 = choose [0:0] s633
-  s7507 :: SBool = s19 /= s7506
-  s7508 :: SWord8 = if s7507 then s7503 else s7504
-  s7509 :: SWord8 = if s610 then s7505 else s7508
-  s7510 :: SWord1 = choose [0:0] s656
-  s7511 :: SBool = s19 /= s7510
-  s7512 :: SWord8 = if s22 then s664 else s645
-  s7513 :: SWord8 = s7512 >>> 1
-  s7514 :: SWord8 = s24 | s7513
-  s7515 :: SWord8 = s26 & s7513
-  s7516 :: SWord8 = if s7511 then s7514 else s7515
-  s7517 :: SWord1 = choose [0:0] s667
-  s7518 :: SBool = s19 /= s7517
-  s7519 :: SWord8 = if s7518 then s7514 else s7515
-  s7520 :: SWord8 = if s649 then s7516 else s7519
-  s7521 :: SWord8 = if s589 then s7509 else s7520
-  s7522 :: SWord1 = choose [0:0] s710
-  s7523 :: SBool = s19 /= s7522
-  s7524 :: SWord8 = if s22 then s720 else s702
-  s7525 :: SWord8 = s7524 >>> 1
-  s7526 :: SWord8 = s24 | s7525
-  s7527 :: SWord8 = s26 & s7525
-  s7528 :: SWord8 = if s7523 then s7526 else s7527
-  s7529 :: SWord1 = choose [0:0] s725
-  s7530 :: SBool = s19 /= s7529
-  s7531 :: SWord8 = if s7530 then s7526 else s7527
-  s7532 :: SWord8 = if s706 then s7528 else s7531
-  s7533 :: SWord1 = choose [0:0] s748
-  s7534 :: SBool = s19 /= s7533
-  s7535 :: SWord8 = if s22 then s756 else s737
-  s7536 :: SWord8 = s7535 >>> 1
-  s7537 :: SWord8 = s24 | s7536
-  s7538 :: SWord8 = s26 & s7536
-  s7539 :: SWord8 = if s7534 then s7537 else s7538
-  s7540 :: SWord1 = choose [0:0] s759
-  s7541 :: SBool = s19 /= s7540
-  s7542 :: SWord8 = if s7541 then s7537 else s7538
-  s7543 :: SWord8 = if s741 then s7539 else s7542
-  s7544 :: SWord8 = if s684 then s7532 else s7543
-  s7545 :: SWord8 = if s568 then s7521 else s7544
-  s7546 :: SWord1 = choose [0:0] s824
-  s7547 :: SBool = s19 /= s7546
-  s7548 :: SWord8 = if s22 then s834 else s816
-  s7549 :: SWord8 = s7548 >>> 1
-  s7550 :: SWord8 = s24 | s7549
-  s7551 :: SWord8 = s26 & s7549
-  s7552 :: SWord8 = if s7547 then s7550 else s7551
-  s7553 :: SWord1 = choose [0:0] s841
-  s7554 :: SBool = s19 /= s7553
-  s7555 :: SWord8 = if s7554 then s7550 else s7551
-  s7556 :: SWord8 = if s820 then s7552 else s7555
-  s7557 :: SWord1 = choose [0:0] s864
-  s7558 :: SBool = s19 /= s7557
-  s7559 :: SWord8 = if s22 then s872 else s853
-  s7560 :: SWord8 = s7559 >>> 1
-  s7561 :: SWord8 = s24 | s7560
-  s7562 :: SWord8 = s26 & s7560
-  s7563 :: SWord8 = if s7558 then s7561 else s7562
-  s7564 :: SWord1 = choose [0:0] s875
-  s7565 :: SBool = s19 /= s7564
-  s7566 :: SWord8 = if s7565 then s7561 else s7562
-  s7567 :: SWord8 = if s857 then s7563 else s7566
-  s7568 :: SWord8 = if s799 then s7556 else s7567
-  s7569 :: SWord1 = choose [0:0] s918
-  s7570 :: SBool = s19 /= s7569
-  s7571 :: SWord8 = if s22 then s928 else s910
-  s7572 :: SWord8 = s7571 >>> 1
-  s7573 :: SWord8 = s24 | s7572
-  s7574 :: SWord8 = s26 & s7572
-  s7575 :: SWord8 = if s7570 then s7573 else s7574
-  s7576 :: SWord1 = choose [0:0] s933
-  s7577 :: SBool = s19 /= s7576
-  s7578 :: SWord8 = if s7577 then s7573 else s7574
-  s7579 :: SWord8 = if s914 then s7575 else s7578
-  s7580 :: SWord1 = choose [0:0] s956
-  s7581 :: SBool = s19 /= s7580
-  s7582 :: SWord8 = if s22 then s964 else s945
-  s7583 :: SWord8 = s7582 >>> 1
-  s7584 :: SWord8 = s24 | s7583
-  s7585 :: SWord8 = s26 & s7583
-  s7586 :: SWord8 = if s7581 then s7584 else s7585
-  s7587 :: SWord1 = choose [0:0] s967
-  s7588 :: SBool = s19 /= s7587
-  s7589 :: SWord8 = if s7588 then s7584 else s7585
-  s7590 :: SWord8 = if s949 then s7586 else s7589
-  s7591 :: SWord8 = if s892 then s7579 else s7590
-  s7592 :: SWord8 = if s777 then s7568 else s7591
-  s7593 :: SWord8 = if s546 then s7545 else s7592
-  s7594 :: SWord8 = if s77 then s7498 else s7593
-  s7595 :: SWord1 = choose [0:0] s1076
-  s7596 :: SBool = s19 /= s7595
-  s7597 :: SWord8 = if s22 then s1086 else s1068
-  s7598 :: SWord8 = s7597 >>> 1
-  s7599 :: SWord8 = s24 | s7598
-  s7600 :: SWord8 = s26 & s7598
-  s7601 :: SWord8 = if s7596 then s7599 else s7600
-  s7602 :: SWord1 = choose [0:0] s1097
-  s7603 :: SBool = s19 /= s7602
-  s7604 :: SWord8 = if s7603 then s7599 else s7600
-  s7605 :: SWord8 = if s1072 then s7601 else s7604
-  s7606 :: SWord1 = choose [0:0] s1120
-  s7607 :: SBool = s19 /= s7606
-  s7608 :: SWord8 = if s22 then s1128 else s1109
-  s7609 :: SWord8 = s7608 >>> 1
-  s7610 :: SWord8 = s24 | s7609
-  s7611 :: SWord8 = s26 & s7609
-  s7612 :: SWord8 = if s7607 then s7610 else s7611
-  s7613 :: SWord1 = choose [0:0] s1131
-  s7614 :: SBool = s19 /= s7613
-  s7615 :: SWord8 = if s7614 then s7610 else s7611
-  s7616 :: SWord8 = if s1113 then s7612 else s7615
-  s7617 :: SWord8 = if s1051 then s7605 else s7616
-  s7618 :: SWord1 = choose [0:0] s1174
-  s7619 :: SBool = s19 /= s7618
-  s7620 :: SWord8 = if s22 then s1184 else s1166
-  s7621 :: SWord8 = s7620 >>> 1
-  s7622 :: SWord8 = s24 | s7621
-  s7623 :: SWord8 = s26 & s7621
-  s7624 :: SWord8 = if s7619 then s7622 else s7623
-  s7625 :: SWord1 = choose [0:0] s1189
-  s7626 :: SBool = s19 /= s7625
-  s7627 :: SWord8 = if s7626 then s7622 else s7623
-  s7628 :: SWord8 = if s1170 then s7624 else s7627
-  s7629 :: SWord1 = choose [0:0] s1212
-  s7630 :: SBool = s19 /= s7629
-  s7631 :: SWord8 = if s22 then s1220 else s1201
-  s7632 :: SWord8 = s7631 >>> 1
-  s7633 :: SWord8 = s24 | s7632
-  s7634 :: SWord8 = s26 & s7632
-  s7635 :: SWord8 = if s7630 then s7633 else s7634
-  s7636 :: SWord1 = choose [0:0] s1223
-  s7637 :: SBool = s19 /= s7636
-  s7638 :: SWord8 = if s7637 then s7633 else s7634
-  s7639 :: SWord8 = if s1205 then s7635 else s7638
-  s7640 :: SWord8 = if s1148 then s7628 else s7639
-  s7641 :: SWord8 = if s1030 then s7617 else s7640
-  s7642 :: SWord1 = choose [0:0] s1288
-  s7643 :: SBool = s19 /= s7642
-  s7644 :: SWord8 = if s22 then s1298 else s1280
-  s7645 :: SWord8 = s7644 >>> 1
-  s7646 :: SWord8 = s24 | s7645
-  s7647 :: SWord8 = s26 & s7645
-  s7648 :: SWord8 = if s7643 then s7646 else s7647
-  s7649 :: SWord1 = choose [0:0] s1305
-  s7650 :: SBool = s19 /= s7649
-  s7651 :: SWord8 = if s7650 then s7646 else s7647
-  s7652 :: SWord8 = if s1284 then s7648 else s7651
-  s7653 :: SWord1 = choose [0:0] s1328
-  s7654 :: SBool = s19 /= s7653
-  s7655 :: SWord8 = if s22 then s1336 else s1317
-  s7656 :: SWord8 = s7655 >>> 1
-  s7657 :: SWord8 = s24 | s7656
-  s7658 :: SWord8 = s26 & s7656
-  s7659 :: SWord8 = if s7654 then s7657 else s7658
-  s7660 :: SWord1 = choose [0:0] s1339
-  s7661 :: SBool = s19 /= s7660
-  s7662 :: SWord8 = if s7661 then s7657 else s7658
-  s7663 :: SWord8 = if s1321 then s7659 else s7662
-  s7664 :: SWord8 = if s1263 then s7652 else s7663
-  s7665 :: SWord1 = choose [0:0] s1382
-  s7666 :: SBool = s19 /= s7665
-  s7667 :: SWord8 = if s22 then s1392 else s1374
-  s7668 :: SWord8 = s7667 >>> 1
-  s7669 :: SWord8 = s24 | s7668
-  s7670 :: SWord8 = s26 & s7668
-  s7671 :: SWord8 = if s7666 then s7669 else s7670
-  s7672 :: SWord1 = choose [0:0] s1397
-  s7673 :: SBool = s19 /= s7672
-  s7674 :: SWord8 = if s7673 then s7669 else s7670
-  s7675 :: SWord8 = if s1378 then s7671 else s7674
-  s7676 :: SWord1 = choose [0:0] s1420
-  s7677 :: SBool = s19 /= s7676
-  s7678 :: SWord8 = if s22 then s1428 else s1409
-  s7679 :: SWord8 = s7678 >>> 1
-  s7680 :: SWord8 = s24 | s7679
-  s7681 :: SWord8 = s26 & s7679
-  s7682 :: SWord8 = if s7677 then s7680 else s7681
-  s7683 :: SWord1 = choose [0:0] s1431
-  s7684 :: SBool = s19 /= s7683
-  s7685 :: SWord8 = if s7684 then s7680 else s7681
-  s7686 :: SWord8 = if s1413 then s7682 else s7685
-  s7687 :: SWord8 = if s1356 then s7675 else s7686
-  s7688 :: SWord8 = if s1241 then s7664 else s7687
-  s7689 :: SWord8 = if s1009 then s7641 else s7688
-  s7690 :: SWord1 = choose [0:0] s1518
-  s7691 :: SBool = s19 /= s7690
-  s7692 :: SWord8 = if s22 then s1528 else s1510
-  s7693 :: SWord8 = s7692 >>> 1
-  s7694 :: SWord8 = s24 | s7693
-  s7695 :: SWord8 = s26 & s7693
-  s7696 :: SWord8 = if s7691 then s7694 else s7695
-  s7697 :: SWord1 = choose [0:0] s1537
-  s7698 :: SBool = s19 /= s7697
-  s7699 :: SWord8 = if s7698 then s7694 else s7695
-  s7700 :: SWord8 = if s1514 then s7696 else s7699
-  s7701 :: SWord1 = choose [0:0] s1560
-  s7702 :: SBool = s19 /= s7701
-  s7703 :: SWord8 = if s22 then s1568 else s1549
-  s7704 :: SWord8 = s7703 >>> 1
-  s7705 :: SWord8 = s24 | s7704
-  s7706 :: SWord8 = s26 & s7704
-  s7707 :: SWord8 = if s7702 then s7705 else s7706
-  s7708 :: SWord1 = choose [0:0] s1571
-  s7709 :: SBool = s19 /= s7708
-  s7710 :: SWord8 = if s7709 then s7705 else s7706
-  s7711 :: SWord8 = if s1553 then s7707 else s7710
-  s7712 :: SWord8 = if s1493 then s7700 else s7711
-  s7713 :: SWord1 = choose [0:0] s1614
-  s7714 :: SBool = s19 /= s7713
-  s7715 :: SWord8 = if s22 then s1624 else s1606
-  s7716 :: SWord8 = s7715 >>> 1
-  s7717 :: SWord8 = s24 | s7716
-  s7718 :: SWord8 = s26 & s7716
-  s7719 :: SWord8 = if s7714 then s7717 else s7718
-  s7720 :: SWord1 = choose [0:0] s1629
-  s7721 :: SBool = s19 /= s7720
-  s7722 :: SWord8 = if s7721 then s7717 else s7718
-  s7723 :: SWord8 = if s1610 then s7719 else s7722
-  s7724 :: SWord1 = choose [0:0] s1652
-  s7725 :: SBool = s19 /= s7724
-  s7726 :: SWord8 = if s22 then s1660 else s1641
-  s7727 :: SWord8 = s7726 >>> 1
-  s7728 :: SWord8 = s24 | s7727
-  s7729 :: SWord8 = s26 & s7727
-  s7730 :: SWord8 = if s7725 then s7728 else s7729
-  s7731 :: SWord1 = choose [0:0] s1663
-  s7732 :: SBool = s19 /= s7731
-  s7733 :: SWord8 = if s7732 then s7728 else s7729
-  s7734 :: SWord8 = if s1645 then s7730 else s7733
-  s7735 :: SWord8 = if s1588 then s7723 else s7734
-  s7736 :: SWord8 = if s1472 then s7712 else s7735
-  s7737 :: SWord1 = choose [0:0] s1728
-  s7738 :: SBool = s19 /= s7737
-  s7739 :: SWord8 = if s22 then s1738 else s1720
-  s7740 :: SWord8 = s7739 >>> 1
-  s7741 :: SWord8 = s24 | s7740
-  s7742 :: SWord8 = s26 & s7740
-  s7743 :: SWord8 = if s7738 then s7741 else s7742
-  s7744 :: SWord1 = choose [0:0] s1745
-  s7745 :: SBool = s19 /= s7744
-  s7746 :: SWord8 = if s7745 then s7741 else s7742
-  s7747 :: SWord8 = if s1724 then s7743 else s7746
-  s7748 :: SWord1 = choose [0:0] s1768
-  s7749 :: SBool = s19 /= s7748
-  s7750 :: SWord8 = if s22 then s1776 else s1757
-  s7751 :: SWord8 = s7750 >>> 1
-  s7752 :: SWord8 = s24 | s7751
-  s7753 :: SWord8 = s26 & s7751
-  s7754 :: SWord8 = if s7749 then s7752 else s7753
-  s7755 :: SWord1 = choose [0:0] s1779
-  s7756 :: SBool = s19 /= s7755
-  s7757 :: SWord8 = if s7756 then s7752 else s7753
-  s7758 :: SWord8 = if s1761 then s7754 else s7757
-  s7759 :: SWord8 = if s1703 then s7747 else s7758
-  s7760 :: SWord1 = choose [0:0] s1822
-  s7761 :: SBool = s19 /= s7760
-  s7762 :: SWord8 = if s22 then s1832 else s1814
-  s7763 :: SWord8 = s7762 >>> 1
-  s7764 :: SWord8 = s24 | s7763
-  s7765 :: SWord8 = s26 & s7763
-  s7766 :: SWord8 = if s7761 then s7764 else s7765
-  s7767 :: SWord1 = choose [0:0] s1837
-  s7768 :: SBool = s19 /= s7767
-  s7769 :: SWord8 = if s7768 then s7764 else s7765
-  s7770 :: SWord8 = if s1818 then s7766 else s7769
-  s7771 :: SWord1 = choose [0:0] s1860
-  s7772 :: SBool = s19 /= s7771
-  s7773 :: SWord8 = if s22 then s1868 else s1849
-  s7774 :: SWord8 = s7773 >>> 1
-  s7775 :: SWord8 = s24 | s7774
-  s7776 :: SWord8 = s26 & s7774
-  s7777 :: SWord8 = if s7772 then s7775 else s7776
-  s7778 :: SWord1 = choose [0:0] s1871
-  s7779 :: SBool = s19 /= s7778
-  s7780 :: SWord8 = if s7779 then s7775 else s7776
-  s7781 :: SWord8 = if s1853 then s7777 else s7780
-  s7782 :: SWord8 = if s1796 then s7770 else s7781
-  s7783 :: SWord8 = if s1681 then s7759 else s7782
-  s7784 :: SWord8 = if s1450 then s7736 else s7783
-  s7785 :: SWord8 = if s987 then s7689 else s7784
-  s7786 :: SWord8 = if s56 then s7594 else s7785
-  s7787 :: SWord1 = choose [0:0] s2002
-  s7788 :: SBool = s19 /= s7787
-  s7789 :: SWord8 = if s22 then s2012 else s1994
-  s7790 :: SWord8 = s7789 >>> 1
-  s7791 :: SWord8 = s24 | s7790
-  s7792 :: SWord8 = s26 & s7790
-  s7793 :: SWord8 = if s7788 then s7791 else s7792
-  s7794 :: SWord1 = choose [0:0] s2025
-  s7795 :: SBool = s19 /= s7794
-  s7796 :: SWord8 = if s7795 then s7791 else s7792
-  s7797 :: SWord8 = if s1998 then s7793 else s7796
-  s7798 :: SWord1 = choose [0:0] s2048
-  s7799 :: SBool = s19 /= s7798
-  s7800 :: SWord8 = if s22 then s2056 else s2037
-  s7801 :: SWord8 = s7800 >>> 1
-  s7802 :: SWord8 = s24 | s7801
-  s7803 :: SWord8 = s26 & s7801
-  s7804 :: SWord8 = if s7799 then s7802 else s7803
-  s7805 :: SWord1 = choose [0:0] s2059
-  s7806 :: SBool = s19 /= s7805
-  s7807 :: SWord8 = if s7806 then s7802 else s7803
-  s7808 :: SWord8 = if s2041 then s7804 else s7807
-  s7809 :: SWord8 = if s1977 then s7797 else s7808
-  s7810 :: SWord1 = choose [0:0] s2102
-  s7811 :: SBool = s19 /= s7810
-  s7812 :: SWord8 = if s22 then s2112 else s2094
-  s7813 :: SWord8 = s7812 >>> 1
-  s7814 :: SWord8 = s24 | s7813
-  s7815 :: SWord8 = s26 & s7813
-  s7816 :: SWord8 = if s7811 then s7814 else s7815
-  s7817 :: SWord1 = choose [0:0] s2117
-  s7818 :: SBool = s19 /= s7817
-  s7819 :: SWord8 = if s7818 then s7814 else s7815
-  s7820 :: SWord8 = if s2098 then s7816 else s7819
-  s7821 :: SWord1 = choose [0:0] s2140
-  s7822 :: SBool = s19 /= s7821
-  s7823 :: SWord8 = if s22 then s2148 else s2129
-  s7824 :: SWord8 = s7823 >>> 1
-  s7825 :: SWord8 = s24 | s7824
-  s7826 :: SWord8 = s26 & s7824
-  s7827 :: SWord8 = if s7822 then s7825 else s7826
-  s7828 :: SWord1 = choose [0:0] s2151
-  s7829 :: SBool = s19 /= s7828
-  s7830 :: SWord8 = if s7829 then s7825 else s7826
-  s7831 :: SWord8 = if s2133 then s7827 else s7830
-  s7832 :: SWord8 = if s2076 then s7820 else s7831
-  s7833 :: SWord8 = if s1956 then s7809 else s7832
-  s7834 :: SWord1 = choose [0:0] s2216
-  s7835 :: SBool = s19 /= s7834
-  s7836 :: SWord8 = if s22 then s2226 else s2208
-  s7837 :: SWord8 = s7836 >>> 1
-  s7838 :: SWord8 = s24 | s7837
-  s7839 :: SWord8 = s26 & s7837
-  s7840 :: SWord8 = if s7835 then s7838 else s7839
-  s7841 :: SWord1 = choose [0:0] s2233
-  s7842 :: SBool = s19 /= s7841
-  s7843 :: SWord8 = if s7842 then s7838 else s7839
-  s7844 :: SWord8 = if s2212 then s7840 else s7843
-  s7845 :: SWord1 = choose [0:0] s2256
-  s7846 :: SBool = s19 /= s7845
-  s7847 :: SWord8 = if s22 then s2264 else s2245
-  s7848 :: SWord8 = s7847 >>> 1
-  s7849 :: SWord8 = s24 | s7848
-  s7850 :: SWord8 = s26 & s7848
-  s7851 :: SWord8 = if s7846 then s7849 else s7850
-  s7852 :: SWord1 = choose [0:0] s2267
-  s7853 :: SBool = s19 /= s7852
-  s7854 :: SWord8 = if s7853 then s7849 else s7850
-  s7855 :: SWord8 = if s2249 then s7851 else s7854
-  s7856 :: SWord8 = if s2191 then s7844 else s7855
-  s7857 :: SWord1 = choose [0:0] s2310
-  s7858 :: SBool = s19 /= s7857
-  s7859 :: SWord8 = if s22 then s2320 else s2302
-  s7860 :: SWord8 = s7859 >>> 1
-  s7861 :: SWord8 = s24 | s7860
-  s7862 :: SWord8 = s26 & s7860
-  s7863 :: SWord8 = if s7858 then s7861 else s7862
-  s7864 :: SWord1 = choose [0:0] s2325
-  s7865 :: SBool = s19 /= s7864
-  s7866 :: SWord8 = if s7865 then s7861 else s7862
-  s7867 :: SWord8 = if s2306 then s7863 else s7866
-  s7868 :: SWord1 = choose [0:0] s2348
-  s7869 :: SBool = s19 /= s7868
-  s7870 :: SWord8 = if s22 then s2356 else s2337
-  s7871 :: SWord8 = s7870 >>> 1
-  s7872 :: SWord8 = s24 | s7871
-  s7873 :: SWord8 = s26 & s7871
-  s7874 :: SWord8 = if s7869 then s7872 else s7873
-  s7875 :: SWord1 = choose [0:0] s2359
-  s7876 :: SBool = s19 /= s7875
-  s7877 :: SWord8 = if s7876 then s7872 else s7873
-  s7878 :: SWord8 = if s2341 then s7874 else s7877
-  s7879 :: SWord8 = if s2284 then s7867 else s7878
-  s7880 :: SWord8 = if s2169 then s7856 else s7879
-  s7881 :: SWord8 = if s1935 then s7833 else s7880
-  s7882 :: SWord1 = choose [0:0] s2446
-  s7883 :: SBool = s19 /= s7882
-  s7884 :: SWord8 = if s22 then s2456 else s2438
-  s7885 :: SWord8 = s7884 >>> 1
-  s7886 :: SWord8 = s24 | s7885
-  s7887 :: SWord8 = s26 & s7885
-  s7888 :: SWord8 = if s7883 then s7886 else s7887
-  s7889 :: SWord1 = choose [0:0] s2465
-  s7890 :: SBool = s19 /= s7889
-  s7891 :: SWord8 = if s7890 then s7886 else s7887
-  s7892 :: SWord8 = if s2442 then s7888 else s7891
-  s7893 :: SWord1 = choose [0:0] s2488
-  s7894 :: SBool = s19 /= s7893
-  s7895 :: SWord8 = if s22 then s2496 else s2477
-  s7896 :: SWord8 = s7895 >>> 1
-  s7897 :: SWord8 = s24 | s7896
-  s7898 :: SWord8 = s26 & s7896
-  s7899 :: SWord8 = if s7894 then s7897 else s7898
-  s7900 :: SWord1 = choose [0:0] s2499
-  s7901 :: SBool = s19 /= s7900
-  s7902 :: SWord8 = if s7901 then s7897 else s7898
-  s7903 :: SWord8 = if s2481 then s7899 else s7902
-  s7904 :: SWord8 = if s2421 then s7892 else s7903
-  s7905 :: SWord1 = choose [0:0] s2542
-  s7906 :: SBool = s19 /= s7905
-  s7907 :: SWord8 = if s22 then s2552 else s2534
-  s7908 :: SWord8 = s7907 >>> 1
-  s7909 :: SWord8 = s24 | s7908
-  s7910 :: SWord8 = s26 & s7908
-  s7911 :: SWord8 = if s7906 then s7909 else s7910
-  s7912 :: SWord1 = choose [0:0] s2557
-  s7913 :: SBool = s19 /= s7912
-  s7914 :: SWord8 = if s7913 then s7909 else s7910
-  s7915 :: SWord8 = if s2538 then s7911 else s7914
-  s7916 :: SWord1 = choose [0:0] s2580
-  s7917 :: SBool = s19 /= s7916
-  s7918 :: SWord8 = if s22 then s2588 else s2569
-  s7919 :: SWord8 = s7918 >>> 1
-  s7920 :: SWord8 = s24 | s7919
-  s7921 :: SWord8 = s26 & s7919
-  s7922 :: SWord8 = if s7917 then s7920 else s7921
-  s7923 :: SWord1 = choose [0:0] s2591
-  s7924 :: SBool = s19 /= s7923
-  s7925 :: SWord8 = if s7924 then s7920 else s7921
-  s7926 :: SWord8 = if s2573 then s7922 else s7925
-  s7927 :: SWord8 = if s2516 then s7915 else s7926
-  s7928 :: SWord8 = if s2400 then s7904 else s7927
-  s7929 :: SWord1 = choose [0:0] s2656
-  s7930 :: SBool = s19 /= s7929
-  s7931 :: SWord8 = if s22 then s2666 else s2648
-  s7932 :: SWord8 = s7931 >>> 1
-  s7933 :: SWord8 = s24 | s7932
-  s7934 :: SWord8 = s26 & s7932
-  s7935 :: SWord8 = if s7930 then s7933 else s7934
-  s7936 :: SWord1 = choose [0:0] s2673
-  s7937 :: SBool = s19 /= s7936
-  s7938 :: SWord8 = if s7937 then s7933 else s7934
-  s7939 :: SWord8 = if s2652 then s7935 else s7938
-  s7940 :: SWord1 = choose [0:0] s2696
-  s7941 :: SBool = s19 /= s7940
-  s7942 :: SWord8 = if s22 then s2704 else s2685
-  s7943 :: SWord8 = s7942 >>> 1
-  s7944 :: SWord8 = s24 | s7943
-  s7945 :: SWord8 = s26 & s7943
-  s7946 :: SWord8 = if s7941 then s7944 else s7945
-  s7947 :: SWord1 = choose [0:0] s2707
-  s7948 :: SBool = s19 /= s7947
-  s7949 :: SWord8 = if s7948 then s7944 else s7945
-  s7950 :: SWord8 = if s2689 then s7946 else s7949
-  s7951 :: SWord8 = if s2631 then s7939 else s7950
-  s7952 :: SWord1 = choose [0:0] s2750
-  s7953 :: SBool = s19 /= s7952
-  s7954 :: SWord8 = if s22 then s2760 else s2742
-  s7955 :: SWord8 = s7954 >>> 1
-  s7956 :: SWord8 = s24 | s7955
-  s7957 :: SWord8 = s26 & s7955
-  s7958 :: SWord8 = if s7953 then s7956 else s7957
-  s7959 :: SWord1 = choose [0:0] s2765
-  s7960 :: SBool = s19 /= s7959
-  s7961 :: SWord8 = if s7960 then s7956 else s7957
-  s7962 :: SWord8 = if s2746 then s7958 else s7961
-  s7963 :: SWord1 = choose [0:0] s2788
-  s7964 :: SBool = s19 /= s7963
-  s7965 :: SWord8 = if s22 then s2796 else s2777
-  s7966 :: SWord8 = s7965 >>> 1
-  s7967 :: SWord8 = s24 | s7966
-  s7968 :: SWord8 = s26 & s7966
-  s7969 :: SWord8 = if s7964 then s7967 else s7968
-  s7970 :: SWord1 = choose [0:0] s2799
-  s7971 :: SBool = s19 /= s7970
-  s7972 :: SWord8 = if s7971 then s7967 else s7968
-  s7973 :: SWord8 = if s2781 then s7969 else s7972
-  s7974 :: SWord8 = if s2724 then s7962 else s7973
-  s7975 :: SWord8 = if s2609 then s7951 else s7974
-  s7976 :: SWord8 = if s2378 then s7928 else s7975
-  s7977 :: SWord8 = if s1914 then s7881 else s7976
-  s7978 :: SWord1 = choose [0:0] s2908
-  s7979 :: SBool = s19 /= s7978
-  s7980 :: SWord8 = if s22 then s2918 else s2900
-  s7981 :: SWord8 = s7980 >>> 1
-  s7982 :: SWord8 = s24 | s7981
-  s7983 :: SWord8 = s26 & s7981
-  s7984 :: SWord8 = if s7979 then s7982 else s7983
-  s7985 :: SWord1 = choose [0:0] s2929
-  s7986 :: SBool = s19 /= s7985
-  s7987 :: SWord8 = if s7986 then s7982 else s7983
-  s7988 :: SWord8 = if s2904 then s7984 else s7987
-  s7989 :: SWord1 = choose [0:0] s2952
-  s7990 :: SBool = s19 /= s7989
-  s7991 :: SWord8 = if s22 then s2960 else s2941
-  s7992 :: SWord8 = s7991 >>> 1
-  s7993 :: SWord8 = s24 | s7992
-  s7994 :: SWord8 = s26 & s7992
-  s7995 :: SWord8 = if s7990 then s7993 else s7994
-  s7996 :: SWord1 = choose [0:0] s2963
-  s7997 :: SBool = s19 /= s7996
-  s7998 :: SWord8 = if s7997 then s7993 else s7994
-  s7999 :: SWord8 = if s2945 then s7995 else s7998
-  s8000 :: SWord8 = if s2883 then s7988 else s7999
-  s8001 :: SWord1 = choose [0:0] s3006
-  s8002 :: SBool = s19 /= s8001
-  s8003 :: SWord8 = if s22 then s3016 else s2998
-  s8004 :: SWord8 = s8003 >>> 1
-  s8005 :: SWord8 = s24 | s8004
-  s8006 :: SWord8 = s26 & s8004
-  s8007 :: SWord8 = if s8002 then s8005 else s8006
-  s8008 :: SWord1 = choose [0:0] s3021
-  s8009 :: SBool = s19 /= s8008
-  s8010 :: SWord8 = if s8009 then s8005 else s8006
-  s8011 :: SWord8 = if s3002 then s8007 else s8010
-  s8012 :: SWord1 = choose [0:0] s3044
-  s8013 :: SBool = s19 /= s8012
-  s8014 :: SWord8 = if s22 then s3052 else s3033
-  s8015 :: SWord8 = s8014 >>> 1
-  s8016 :: SWord8 = s24 | s8015
-  s8017 :: SWord8 = s26 & s8015
-  s8018 :: SWord8 = if s8013 then s8016 else s8017
-  s8019 :: SWord1 = choose [0:0] s3055
-  s8020 :: SBool = s19 /= s8019
-  s8021 :: SWord8 = if s8020 then s8016 else s8017
-  s8022 :: SWord8 = if s3037 then s8018 else s8021
-  s8023 :: SWord8 = if s2980 then s8011 else s8022
-  s8024 :: SWord8 = if s2862 then s8000 else s8023
-  s8025 :: SWord1 = choose [0:0] s3120
-  s8026 :: SBool = s19 /= s8025
-  s8027 :: SWord8 = if s22 then s3130 else s3112
-  s8028 :: SWord8 = s8027 >>> 1
-  s8029 :: SWord8 = s24 | s8028
-  s8030 :: SWord8 = s26 & s8028
-  s8031 :: SWord8 = if s8026 then s8029 else s8030
-  s8032 :: SWord1 = choose [0:0] s3137
-  s8033 :: SBool = s19 /= s8032
-  s8034 :: SWord8 = if s8033 then s8029 else s8030
-  s8035 :: SWord8 = if s3116 then s8031 else s8034
-  s8036 :: SWord1 = choose [0:0] s3160
-  s8037 :: SBool = s19 /= s8036
-  s8038 :: SWord8 = if s22 then s3168 else s3149
-  s8039 :: SWord8 = s8038 >>> 1
-  s8040 :: SWord8 = s24 | s8039
-  s8041 :: SWord8 = s26 & s8039
-  s8042 :: SWord8 = if s8037 then s8040 else s8041
-  s8043 :: SWord1 = choose [0:0] s3171
-  s8044 :: SBool = s19 /= s8043
-  s8045 :: SWord8 = if s8044 then s8040 else s8041
-  s8046 :: SWord8 = if s3153 then s8042 else s8045
-  s8047 :: SWord8 = if s3095 then s8035 else s8046
-  s8048 :: SWord1 = choose [0:0] s3214
-  s8049 :: SBool = s19 /= s8048
-  s8050 :: SWord8 = if s22 then s3224 else s3206
-  s8051 :: SWord8 = s8050 >>> 1
-  s8052 :: SWord8 = s24 | s8051
-  s8053 :: SWord8 = s26 & s8051
-  s8054 :: SWord8 = if s8049 then s8052 else s8053
-  s8055 :: SWord1 = choose [0:0] s3229
-  s8056 :: SBool = s19 /= s8055
-  s8057 :: SWord8 = if s8056 then s8052 else s8053
-  s8058 :: SWord8 = if s3210 then s8054 else s8057
-  s8059 :: SWord1 = choose [0:0] s3252
-  s8060 :: SBool = s19 /= s8059
-  s8061 :: SWord8 = if s22 then s3260 else s3241
-  s8062 :: SWord8 = s8061 >>> 1
-  s8063 :: SWord8 = s24 | s8062
-  s8064 :: SWord8 = s26 & s8062
-  s8065 :: SWord8 = if s8060 then s8063 else s8064
-  s8066 :: SWord1 = choose [0:0] s3263
-  s8067 :: SBool = s19 /= s8066
-  s8068 :: SWord8 = if s8067 then s8063 else s8064
-  s8069 :: SWord8 = if s3245 then s8065 else s8068
-  s8070 :: SWord8 = if s3188 then s8058 else s8069
-  s8071 :: SWord8 = if s3073 then s8047 else s8070
-  s8072 :: SWord8 = if s2841 then s8024 else s8071
-  s8073 :: SWord1 = choose [0:0] s3350
-  s8074 :: SBool = s19 /= s8073
-  s8075 :: SWord8 = if s22 then s3360 else s3342
-  s8076 :: SWord8 = s8075 >>> 1
-  s8077 :: SWord8 = s24 | s8076
-  s8078 :: SWord8 = s26 & s8076
-  s8079 :: SWord8 = if s8074 then s8077 else s8078
-  s8080 :: SWord1 = choose [0:0] s3369
-  s8081 :: SBool = s19 /= s8080
-  s8082 :: SWord8 = if s8081 then s8077 else s8078
-  s8083 :: SWord8 = if s3346 then s8079 else s8082
-  s8084 :: SWord1 = choose [0:0] s3392
-  s8085 :: SBool = s19 /= s8084
-  s8086 :: SWord8 = if s22 then s3400 else s3381
-  s8087 :: SWord8 = s8086 >>> 1
-  s8088 :: SWord8 = s24 | s8087
-  s8089 :: SWord8 = s26 & s8087
-  s8090 :: SWord8 = if s8085 then s8088 else s8089
-  s8091 :: SWord1 = choose [0:0] s3403
-  s8092 :: SBool = s19 /= s8091
-  s8093 :: SWord8 = if s8092 then s8088 else s8089
-  s8094 :: SWord8 = if s3385 then s8090 else s8093
-  s8095 :: SWord8 = if s3325 then s8083 else s8094
-  s8096 :: SWord1 = choose [0:0] s3446
-  s8097 :: SBool = s19 /= s8096
-  s8098 :: SWord8 = if s22 then s3456 else s3438
-  s8099 :: SWord8 = s8098 >>> 1
-  s8100 :: SWord8 = s24 | s8099
-  s8101 :: SWord8 = s26 & s8099
-  s8102 :: SWord8 = if s8097 then s8100 else s8101
-  s8103 :: SWord1 = choose [0:0] s3461
-  s8104 :: SBool = s19 /= s8103
-  s8105 :: SWord8 = if s8104 then s8100 else s8101
-  s8106 :: SWord8 = if s3442 then s8102 else s8105
-  s8107 :: SWord1 = choose [0:0] s3484
-  s8108 :: SBool = s19 /= s8107
-  s8109 :: SWord8 = if s22 then s3492 else s3473
-  s8110 :: SWord8 = s8109 >>> 1
-  s8111 :: SWord8 = s24 | s8110
-  s8112 :: SWord8 = s26 & s8110
-  s8113 :: SWord8 = if s8108 then s8111 else s8112
-  s8114 :: SWord1 = choose [0:0] s3495
-  s8115 :: SBool = s19 /= s8114
-  s8116 :: SWord8 = if s8115 then s8111 else s8112
-  s8117 :: SWord8 = if s3477 then s8113 else s8116
-  s8118 :: SWord8 = if s3420 then s8106 else s8117
-  s8119 :: SWord8 = if s3304 then s8095 else s8118
-  s8120 :: SWord1 = choose [0:0] s3560
-  s8121 :: SBool = s19 /= s8120
-  s8122 :: SWord8 = if s22 then s3570 else s3552
-  s8123 :: SWord8 = s8122 >>> 1
-  s8124 :: SWord8 = s24 | s8123
-  s8125 :: SWord8 = s26 & s8123
-  s8126 :: SWord8 = if s8121 then s8124 else s8125
-  s8127 :: SWord1 = choose [0:0] s3577
-  s8128 :: SBool = s19 /= s8127
-  s8129 :: SWord8 = if s8128 then s8124 else s8125
-  s8130 :: SWord8 = if s3556 then s8126 else s8129
-  s8131 :: SWord1 = choose [0:0] s3600
-  s8132 :: SBool = s19 /= s8131
-  s8133 :: SWord8 = if s22 then s3608 else s3589
-  s8134 :: SWord8 = s8133 >>> 1
-  s8135 :: SWord8 = s24 | s8134
-  s8136 :: SWord8 = s26 & s8134
-  s8137 :: SWord8 = if s8132 then s8135 else s8136
-  s8138 :: SWord1 = choose [0:0] s3611
-  s8139 :: SBool = s19 /= s8138
-  s8140 :: SWord8 = if s8139 then s8135 else s8136
-  s8141 :: SWord8 = if s3593 then s8137 else s8140
-  s8142 :: SWord8 = if s3535 then s8130 else s8141
-  s8143 :: SWord1 = choose [0:0] s3654
-  s8144 :: SBool = s19 /= s8143
-  s8145 :: SWord8 = if s22 then s3664 else s3646
-  s8146 :: SWord8 = s8145 >>> 1
-  s8147 :: SWord8 = s24 | s8146
-  s8148 :: SWord8 = s26 & s8146
-  s8149 :: SWord8 = if s8144 then s8147 else s8148
-  s8150 :: SWord1 = choose [0:0] s3669
-  s8151 :: SBool = s19 /= s8150
-  s8152 :: SWord8 = if s8151 then s8147 else s8148
-  s8153 :: SWord8 = if s3650 then s8149 else s8152
-  s8154 :: SWord1 = choose [0:0] s3692
-  s8155 :: SBool = s19 /= s8154
-  s8156 :: SWord8 = if s22 then s3700 else s3681
-  s8157 :: SWord8 = s8156 >>> 1
-  s8158 :: SWord8 = s24 | s8157
-  s8159 :: SWord8 = s26 & s8157
-  s8160 :: SWord8 = if s8155 then s8158 else s8159
-  s8161 :: SWord1 = choose [0:0] s3703
-  s8162 :: SBool = s19 /= s8161
-  s8163 :: SWord8 = if s8162 then s8158 else s8159
-  s8164 :: SWord8 = if s3685 then s8160 else s8163
-  s8165 :: SWord8 = if s3628 then s8153 else s8164
-  s8166 :: SWord8 = if s3513 then s8142 else s8165
-  s8167 :: SWord8 = if s3282 then s8119 else s8166
-  s8168 :: SWord8 = if s2819 then s8072 else s8167
-  s8169 :: SWord8 = if s1892 then s7977 else s8168
-  s8170 :: SWord8 = if s38 then s7786 else s8169
-  s8171 :: SWord1 = choose [0:0] s3851
-  s8172 :: SBool = s19 /= s8171
-  s8173 :: SWord8 = if s22 then s3861 else s3843
-  s8174 :: SWord8 = s8173 >>> 1
-  s8175 :: SWord8 = s24 | s8174
-  s8176 :: SWord8 = s26 & s8174
-  s8177 :: SWord8 = if s8172 then s8175 else s8176
-  s8178 :: SWord1 = choose [0:0] s3876
-  s8179 :: SBool = s19 /= s8178
-  s8180 :: SWord8 = if s8179 then s8175 else s8176
-  s8181 :: SWord8 = if s3847 then s8177 else s8180
-  s8182 :: SWord1 = choose [0:0] s3899
-  s8183 :: SBool = s19 /= s8182
-  s8184 :: SWord8 = if s22 then s3907 else s3888
-  s8185 :: SWord8 = s8184 >>> 1
-  s8186 :: SWord8 = s24 | s8185
-  s8187 :: SWord8 = s26 & s8185
-  s8188 :: SWord8 = if s8183 then s8186 else s8187
-  s8189 :: SWord1 = choose [0:0] s3910
-  s8190 :: SBool = s19 /= s8189
-  s8191 :: SWord8 = if s8190 then s8186 else s8187
-  s8192 :: SWord8 = if s3892 then s8188 else s8191
-  s8193 :: SWord8 = if s3826 then s8181 else s8192
-  s8194 :: SWord1 = choose [0:0] s3953
-  s8195 :: SBool = s19 /= s8194
-  s8196 :: SWord8 = if s22 then s3963 else s3945
-  s8197 :: SWord8 = s8196 >>> 1
-  s8198 :: SWord8 = s24 | s8197
-  s8199 :: SWord8 = s26 & s8197
-  s8200 :: SWord8 = if s8195 then s8198 else s8199
-  s8201 :: SWord1 = choose [0:0] s3968
-  s8202 :: SBool = s19 /= s8201
-  s8203 :: SWord8 = if s8202 then s8198 else s8199
-  s8204 :: SWord8 = if s3949 then s8200 else s8203
-  s8205 :: SWord1 = choose [0:0] s3991
-  s8206 :: SBool = s19 /= s8205
-  s8207 :: SWord8 = if s22 then s3999 else s3980
-  s8208 :: SWord8 = s8207 >>> 1
-  s8209 :: SWord8 = s24 | s8208
-  s8210 :: SWord8 = s26 & s8208
-  s8211 :: SWord8 = if s8206 then s8209 else s8210
-  s8212 :: SWord1 = choose [0:0] s4002
-  s8213 :: SBool = s19 /= s8212
-  s8214 :: SWord8 = if s8213 then s8209 else s8210
-  s8215 :: SWord8 = if s3984 then s8211 else s8214
-  s8216 :: SWord8 = if s3927 then s8204 else s8215
-  s8217 :: SWord8 = if s3805 then s8193 else s8216
-  s8218 :: SWord1 = choose [0:0] s4067
-  s8219 :: SBool = s19 /= s8218
-  s8220 :: SWord8 = if s22 then s4077 else s4059
-  s8221 :: SWord8 = s8220 >>> 1
-  s8222 :: SWord8 = s24 | s8221
-  s8223 :: SWord8 = s26 & s8221
-  s8224 :: SWord8 = if s8219 then s8222 else s8223
-  s8225 :: SWord1 = choose [0:0] s4084
-  s8226 :: SBool = s19 /= s8225
-  s8227 :: SWord8 = if s8226 then s8222 else s8223
-  s8228 :: SWord8 = if s4063 then s8224 else s8227
-  s8229 :: SWord1 = choose [0:0] s4107
-  s8230 :: SBool = s19 /= s8229
-  s8231 :: SWord8 = if s22 then s4115 else s4096
-  s8232 :: SWord8 = s8231 >>> 1
-  s8233 :: SWord8 = s24 | s8232
-  s8234 :: SWord8 = s26 & s8232
-  s8235 :: SWord8 = if s8230 then s8233 else s8234
-  s8236 :: SWord1 = choose [0:0] s4118
-  s8237 :: SBool = s19 /= s8236
-  s8238 :: SWord8 = if s8237 then s8233 else s8234
-  s8239 :: SWord8 = if s4100 then s8235 else s8238
-  s8240 :: SWord8 = if s4042 then s8228 else s8239
-  s8241 :: SWord1 = choose [0:0] s4161
-  s8242 :: SBool = s19 /= s8241
-  s8243 :: SWord8 = if s22 then s4171 else s4153
-  s8244 :: SWord8 = s8243 >>> 1
-  s8245 :: SWord8 = s24 | s8244
-  s8246 :: SWord8 = s26 & s8244
-  s8247 :: SWord8 = if s8242 then s8245 else s8246
-  s8248 :: SWord1 = choose [0:0] s4176
-  s8249 :: SBool = s19 /= s8248
-  s8250 :: SWord8 = if s8249 then s8245 else s8246
-  s8251 :: SWord8 = if s4157 then s8247 else s8250
-  s8252 :: SWord1 = choose [0:0] s4199
-  s8253 :: SBool = s19 /= s8252
-  s8254 :: SWord8 = if s22 then s4207 else s4188
-  s8255 :: SWord8 = s8254 >>> 1
-  s8256 :: SWord8 = s24 | s8255
-  s8257 :: SWord8 = s26 & s8255
-  s8258 :: SWord8 = if s8253 then s8256 else s8257
-  s8259 :: SWord1 = choose [0:0] s4210
-  s8260 :: SBool = s19 /= s8259
-  s8261 :: SWord8 = if s8260 then s8256 else s8257
-  s8262 :: SWord8 = if s4192 then s8258 else s8261
-  s8263 :: SWord8 = if s4135 then s8251 else s8262
-  s8264 :: SWord8 = if s4020 then s8240 else s8263
-  s8265 :: SWord8 = if s3784 then s8217 else s8264
-  s8266 :: SWord1 = choose [0:0] s4297
-  s8267 :: SBool = s19 /= s8266
-  s8268 :: SWord8 = if s22 then s4307 else s4289
-  s8269 :: SWord8 = s8268 >>> 1
-  s8270 :: SWord8 = s24 | s8269
-  s8271 :: SWord8 = s26 & s8269
-  s8272 :: SWord8 = if s8267 then s8270 else s8271
-  s8273 :: SWord1 = choose [0:0] s4316
-  s8274 :: SBool = s19 /= s8273
-  s8275 :: SWord8 = if s8274 then s8270 else s8271
-  s8276 :: SWord8 = if s4293 then s8272 else s8275
-  s8277 :: SWord1 = choose [0:0] s4339
-  s8278 :: SBool = s19 /= s8277
-  s8279 :: SWord8 = if s22 then s4347 else s4328
-  s8280 :: SWord8 = s8279 >>> 1
-  s8281 :: SWord8 = s24 | s8280
-  s8282 :: SWord8 = s26 & s8280
-  s8283 :: SWord8 = if s8278 then s8281 else s8282
-  s8284 :: SWord1 = choose [0:0] s4350
-  s8285 :: SBool = s19 /= s8284
-  s8286 :: SWord8 = if s8285 then s8281 else s8282
-  s8287 :: SWord8 = if s4332 then s8283 else s8286
-  s8288 :: SWord8 = if s4272 then s8276 else s8287
-  s8289 :: SWord1 = choose [0:0] s4393
-  s8290 :: SBool = s19 /= s8289
-  s8291 :: SWord8 = if s22 then s4403 else s4385
-  s8292 :: SWord8 = s8291 >>> 1
-  s8293 :: SWord8 = s24 | s8292
-  s8294 :: SWord8 = s26 & s8292
-  s8295 :: SWord8 = if s8290 then s8293 else s8294
-  s8296 :: SWord1 = choose [0:0] s4408
-  s8297 :: SBool = s19 /= s8296
-  s8298 :: SWord8 = if s8297 then s8293 else s8294
-  s8299 :: SWord8 = if s4389 then s8295 else s8298
-  s8300 :: SWord1 = choose [0:0] s4431
-  s8301 :: SBool = s19 /= s8300
-  s8302 :: SWord8 = if s22 then s4439 else s4420
-  s8303 :: SWord8 = s8302 >>> 1
-  s8304 :: SWord8 = s24 | s8303
-  s8305 :: SWord8 = s26 & s8303
-  s8306 :: SWord8 = if s8301 then s8304 else s8305
-  s8307 :: SWord1 = choose [0:0] s4442
-  s8308 :: SBool = s19 /= s8307
-  s8309 :: SWord8 = if s8308 then s8304 else s8305
-  s8310 :: SWord8 = if s4424 then s8306 else s8309
-  s8311 :: SWord8 = if s4367 then s8299 else s8310
-  s8312 :: SWord8 = if s4251 then s8288 else s8311
-  s8313 :: SWord1 = choose [0:0] s4507
-  s8314 :: SBool = s19 /= s8313
-  s8315 :: SWord8 = if s22 then s4517 else s4499
-  s8316 :: SWord8 = s8315 >>> 1
-  s8317 :: SWord8 = s24 | s8316
-  s8318 :: SWord8 = s26 & s8316
-  s8319 :: SWord8 = if s8314 then s8317 else s8318
-  s8320 :: SWord1 = choose [0:0] s4524
-  s8321 :: SBool = s19 /= s8320
-  s8322 :: SWord8 = if s8321 then s8317 else s8318
-  s8323 :: SWord8 = if s4503 then s8319 else s8322
-  s8324 :: SWord1 = choose [0:0] s4547
-  s8325 :: SBool = s19 /= s8324
-  s8326 :: SWord8 = if s22 then s4555 else s4536
-  s8327 :: SWord8 = s8326 >>> 1
-  s8328 :: SWord8 = s24 | s8327
-  s8329 :: SWord8 = s26 & s8327
-  s8330 :: SWord8 = if s8325 then s8328 else s8329
-  s8331 :: SWord1 = choose [0:0] s4558
-  s8332 :: SBool = s19 /= s8331
-  s8333 :: SWord8 = if s8332 then s8328 else s8329
-  s8334 :: SWord8 = if s4540 then s8330 else s8333
-  s8335 :: SWord8 = if s4482 then s8323 else s8334
-  s8336 :: SWord1 = choose [0:0] s4601
-  s8337 :: SBool = s19 /= s8336
-  s8338 :: SWord8 = if s22 then s4611 else s4593
-  s8339 :: SWord8 = s8338 >>> 1
-  s8340 :: SWord8 = s24 | s8339
-  s8341 :: SWord8 = s26 & s8339
-  s8342 :: SWord8 = if s8337 then s8340 else s8341
-  s8343 :: SWord1 = choose [0:0] s4616
-  s8344 :: SBool = s19 /= s8343
-  s8345 :: SWord8 = if s8344 then s8340 else s8341
-  s8346 :: SWord8 = if s4597 then s8342 else s8345
-  s8347 :: SWord1 = choose [0:0] s4639
-  s8348 :: SBool = s19 /= s8347
-  s8349 :: SWord8 = if s22 then s4647 else s4628
-  s8350 :: SWord8 = s8349 >>> 1
-  s8351 :: SWord8 = s24 | s8350
-  s8352 :: SWord8 = s26 & s8350
-  s8353 :: SWord8 = if s8348 then s8351 else s8352
-  s8354 :: SWord1 = choose [0:0] s4650
-  s8355 :: SBool = s19 /= s8354
-  s8356 :: SWord8 = if s8355 then s8351 else s8352
-  s8357 :: SWord8 = if s4632 then s8353 else s8356
-  s8358 :: SWord8 = if s4575 then s8346 else s8357
-  s8359 :: SWord8 = if s4460 then s8335 else s8358
-  s8360 :: SWord8 = if s4229 then s8312 else s8359
-  s8361 :: SWord8 = if s3763 then s8265 else s8360
-  s8362 :: SWord1 = choose [0:0] s4759
-  s8363 :: SBool = s19 /= s8362
-  s8364 :: SWord8 = if s22 then s4769 else s4751
-  s8365 :: SWord8 = s8364 >>> 1
-  s8366 :: SWord8 = s24 | s8365
-  s8367 :: SWord8 = s26 & s8365
-  s8368 :: SWord8 = if s8363 then s8366 else s8367
-  s8369 :: SWord1 = choose [0:0] s4780
-  s8370 :: SBool = s19 /= s8369
-  s8371 :: SWord8 = if s8370 then s8366 else s8367
-  s8372 :: SWord8 = if s4755 then s8368 else s8371
-  s8373 :: SWord1 = choose [0:0] s4803
-  s8374 :: SBool = s19 /= s8373
-  s8375 :: SWord8 = if s22 then s4811 else s4792
-  s8376 :: SWord8 = s8375 >>> 1
-  s8377 :: SWord8 = s24 | s8376
-  s8378 :: SWord8 = s26 & s8376
-  s8379 :: SWord8 = if s8374 then s8377 else s8378
-  s8380 :: SWord1 = choose [0:0] s4814
-  s8381 :: SBool = s19 /= s8380
-  s8382 :: SWord8 = if s8381 then s8377 else s8378
-  s8383 :: SWord8 = if s4796 then s8379 else s8382
-  s8384 :: SWord8 = if s4734 then s8372 else s8383
-  s8385 :: SWord1 = choose [0:0] s4857
-  s8386 :: SBool = s19 /= s8385
-  s8387 :: SWord8 = if s22 then s4867 else s4849
-  s8388 :: SWord8 = s8387 >>> 1
-  s8389 :: SWord8 = s24 | s8388
-  s8390 :: SWord8 = s26 & s8388
-  s8391 :: SWord8 = if s8386 then s8389 else s8390
-  s8392 :: SWord1 = choose [0:0] s4872
-  s8393 :: SBool = s19 /= s8392
-  s8394 :: SWord8 = if s8393 then s8389 else s8390
-  s8395 :: SWord8 = if s4853 then s8391 else s8394
-  s8396 :: SWord1 = choose [0:0] s4895
-  s8397 :: SBool = s19 /= s8396
-  s8398 :: SWord8 = if s22 then s4903 else s4884
-  s8399 :: SWord8 = s8398 >>> 1
-  s8400 :: SWord8 = s24 | s8399
-  s8401 :: SWord8 = s26 & s8399
-  s8402 :: SWord8 = if s8397 then s8400 else s8401
-  s8403 :: SWord1 = choose [0:0] s4906
-  s8404 :: SBool = s19 /= s8403
-  s8405 :: SWord8 = if s8404 then s8400 else s8401
-  s8406 :: SWord8 = if s4888 then s8402 else s8405
-  s8407 :: SWord8 = if s4831 then s8395 else s8406
-  s8408 :: SWord8 = if s4713 then s8384 else s8407
-  s8409 :: SWord1 = choose [0:0] s4971
-  s8410 :: SBool = s19 /= s8409
-  s8411 :: SWord8 = if s22 then s4981 else s4963
-  s8412 :: SWord8 = s8411 >>> 1
-  s8413 :: SWord8 = s24 | s8412
-  s8414 :: SWord8 = s26 & s8412
-  s8415 :: SWord8 = if s8410 then s8413 else s8414
-  s8416 :: SWord1 = choose [0:0] s4988
-  s8417 :: SBool = s19 /= s8416
-  s8418 :: SWord8 = if s8417 then s8413 else s8414
-  s8419 :: SWord8 = if s4967 then s8415 else s8418
-  s8420 :: SWord1 = choose [0:0] s5011
-  s8421 :: SBool = s19 /= s8420
-  s8422 :: SWord8 = if s22 then s5019 else s5000
-  s8423 :: SWord8 = s8422 >>> 1
-  s8424 :: SWord8 = s24 | s8423
-  s8425 :: SWord8 = s26 & s8423
-  s8426 :: SWord8 = if s8421 then s8424 else s8425
-  s8427 :: SWord1 = choose [0:0] s5022
-  s8428 :: SBool = s19 /= s8427
-  s8429 :: SWord8 = if s8428 then s8424 else s8425
-  s8430 :: SWord8 = if s5004 then s8426 else s8429
-  s8431 :: SWord8 = if s4946 then s8419 else s8430
-  s8432 :: SWord1 = choose [0:0] s5065
-  s8433 :: SBool = s19 /= s8432
-  s8434 :: SWord8 = if s22 then s5075 else s5057
-  s8435 :: SWord8 = s8434 >>> 1
-  s8436 :: SWord8 = s24 | s8435
-  s8437 :: SWord8 = s26 & s8435
-  s8438 :: SWord8 = if s8433 then s8436 else s8437
-  s8439 :: SWord1 = choose [0:0] s5080
-  s8440 :: SBool = s19 /= s8439
-  s8441 :: SWord8 = if s8440 then s8436 else s8437
-  s8442 :: SWord8 = if s5061 then s8438 else s8441
-  s8443 :: SWord1 = choose [0:0] s5103
-  s8444 :: SBool = s19 /= s8443
-  s8445 :: SWord8 = if s22 then s5111 else s5092
-  s8446 :: SWord8 = s8445 >>> 1
-  s8447 :: SWord8 = s24 | s8446
-  s8448 :: SWord8 = s26 & s8446
-  s8449 :: SWord8 = if s8444 then s8447 else s8448
-  s8450 :: SWord1 = choose [0:0] s5114
-  s8451 :: SBool = s19 /= s8450
-  s8452 :: SWord8 = if s8451 then s8447 else s8448
-  s8453 :: SWord8 = if s5096 then s8449 else s8452
-  s8454 :: SWord8 = if s5039 then s8442 else s8453
-  s8455 :: SWord8 = if s4924 then s8431 else s8454
-  s8456 :: SWord8 = if s4692 then s8408 else s8455
-  s8457 :: SWord1 = choose [0:0] s5201
-  s8458 :: SBool = s19 /= s8457
-  s8459 :: SWord8 = if s22 then s5211 else s5193
-  s8460 :: SWord8 = s8459 >>> 1
-  s8461 :: SWord8 = s24 | s8460
-  s8462 :: SWord8 = s26 & s8460
-  s8463 :: SWord8 = if s8458 then s8461 else s8462
-  s8464 :: SWord1 = choose [0:0] s5220
-  s8465 :: SBool = s19 /= s8464
-  s8466 :: SWord8 = if s8465 then s8461 else s8462
-  s8467 :: SWord8 = if s5197 then s8463 else s8466
-  s8468 :: SWord1 = choose [0:0] s5243
-  s8469 :: SBool = s19 /= s8468
-  s8470 :: SWord8 = if s22 then s5251 else s5232
-  s8471 :: SWord8 = s8470 >>> 1
-  s8472 :: SWord8 = s24 | s8471
-  s8473 :: SWord8 = s26 & s8471
-  s8474 :: SWord8 = if s8469 then s8472 else s8473
-  s8475 :: SWord1 = choose [0:0] s5254
-  s8476 :: SBool = s19 /= s8475
-  s8477 :: SWord8 = if s8476 then s8472 else s8473
-  s8478 :: SWord8 = if s5236 then s8474 else s8477
-  s8479 :: SWord8 = if s5176 then s8467 else s8478
-  s8480 :: SWord1 = choose [0:0] s5297
-  s8481 :: SBool = s19 /= s8480
-  s8482 :: SWord8 = if s22 then s5307 else s5289
-  s8483 :: SWord8 = s8482 >>> 1
-  s8484 :: SWord8 = s24 | s8483
-  s8485 :: SWord8 = s26 & s8483
-  s8486 :: SWord8 = if s8481 then s8484 else s8485
-  s8487 :: SWord1 = choose [0:0] s5312
-  s8488 :: SBool = s19 /= s8487
-  s8489 :: SWord8 = if s8488 then s8484 else s8485
-  s8490 :: SWord8 = if s5293 then s8486 else s8489
-  s8491 :: SWord1 = choose [0:0] s5335
-  s8492 :: SBool = s19 /= s8491
-  s8493 :: SWord8 = if s22 then s5343 else s5324
-  s8494 :: SWord8 = s8493 >>> 1
-  s8495 :: SWord8 = s24 | s8494
-  s8496 :: SWord8 = s26 & s8494
-  s8497 :: SWord8 = if s8492 then s8495 else s8496
-  s8498 :: SWord1 = choose [0:0] s5346
-  s8499 :: SBool = s19 /= s8498
-  s8500 :: SWord8 = if s8499 then s8495 else s8496
-  s8501 :: SWord8 = if s5328 then s8497 else s8500
-  s8502 :: SWord8 = if s5271 then s8490 else s8501
-  s8503 :: SWord8 = if s5155 then s8479 else s8502
-  s8504 :: SWord1 = choose [0:0] s5411
-  s8505 :: SBool = s19 /= s8504
-  s8506 :: SWord8 = if s22 then s5421 else s5403
-  s8507 :: SWord8 = s8506 >>> 1
-  s8508 :: SWord8 = s24 | s8507
-  s8509 :: SWord8 = s26 & s8507
-  s8510 :: SWord8 = if s8505 then s8508 else s8509
-  s8511 :: SWord1 = choose [0:0] s5428
-  s8512 :: SBool = s19 /= s8511
-  s8513 :: SWord8 = if s8512 then s8508 else s8509
-  s8514 :: SWord8 = if s5407 then s8510 else s8513
-  s8515 :: SWord1 = choose [0:0] s5451
-  s8516 :: SBool = s19 /= s8515
-  s8517 :: SWord8 = if s22 then s5459 else s5440
-  s8518 :: SWord8 = s8517 >>> 1
-  s8519 :: SWord8 = s24 | s8518
-  s8520 :: SWord8 = s26 & s8518
-  s8521 :: SWord8 = if s8516 then s8519 else s8520
-  s8522 :: SWord1 = choose [0:0] s5462
-  s8523 :: SBool = s19 /= s8522
-  s8524 :: SWord8 = if s8523 then s8519 else s8520
-  s8525 :: SWord8 = if s5444 then s8521 else s8524
-  s8526 :: SWord8 = if s5386 then s8514 else s8525
-  s8527 :: SWord1 = choose [0:0] s5505
-  s8528 :: SBool = s19 /= s8527
-  s8529 :: SWord8 = if s22 then s5515 else s5497
-  s8530 :: SWord8 = s8529 >>> 1
-  s8531 :: SWord8 = s24 | s8530
-  s8532 :: SWord8 = s26 & s8530
-  s8533 :: SWord8 = if s8528 then s8531 else s8532
-  s8534 :: SWord1 = choose [0:0] s5520
-  s8535 :: SBool = s19 /= s8534
-  s8536 :: SWord8 = if s8535 then s8531 else s8532
-  s8537 :: SWord8 = if s5501 then s8533 else s8536
-  s8538 :: SWord1 = choose [0:0] s5543
-  s8539 :: SBool = s19 /= s8538
-  s8540 :: SWord8 = if s22 then s5551 else s5532
-  s8541 :: SWord8 = s8540 >>> 1
-  s8542 :: SWord8 = s24 | s8541
-  s8543 :: SWord8 = s26 & s8541
-  s8544 :: SWord8 = if s8539 then s8542 else s8543
-  s8545 :: SWord1 = choose [0:0] s5554
-  s8546 :: SBool = s19 /= s8545
-  s8547 :: SWord8 = if s8546 then s8542 else s8543
-  s8548 :: SWord8 = if s5536 then s8544 else s8547
-  s8549 :: SWord8 = if s5479 then s8537 else s8548
-  s8550 :: SWord8 = if s5364 then s8526 else s8549
-  s8551 :: SWord8 = if s5133 then s8503 else s8550
-  s8552 :: SWord8 = if s4670 then s8456 else s8551
-  s8553 :: SWord8 = if s3742 then s8361 else s8552
-  s8554 :: SWord1 = choose [0:0] s5685
-  s8555 :: SBool = s19 /= s8554
-  s8556 :: SWord8 = if s22 then s5695 else s5677
-  s8557 :: SWord8 = s8556 >>> 1
-  s8558 :: SWord8 = s24 | s8557
-  s8559 :: SWord8 = s26 & s8557
-  s8560 :: SWord8 = if s8555 then s8558 else s8559
-  s8561 :: SWord1 = choose [0:0] s5708
-  s8562 :: SBool = s19 /= s8561
-  s8563 :: SWord8 = if s8562 then s8558 else s8559
-  s8564 :: SWord8 = if s5681 then s8560 else s8563
-  s8565 :: SWord1 = choose [0:0] s5731
-  s8566 :: SBool = s19 /= s8565
-  s8567 :: SWord8 = if s22 then s5739 else s5720
-  s8568 :: SWord8 = s8567 >>> 1
-  s8569 :: SWord8 = s24 | s8568
-  s8570 :: SWord8 = s26 & s8568
-  s8571 :: SWord8 = if s8566 then s8569 else s8570
-  s8572 :: SWord1 = choose [0:0] s5742
-  s8573 :: SBool = s19 /= s8572
-  s8574 :: SWord8 = if s8573 then s8569 else s8570
-  s8575 :: SWord8 = if s5724 then s8571 else s8574
-  s8576 :: SWord8 = if s5660 then s8564 else s8575
-  s8577 :: SWord1 = choose [0:0] s5785
-  s8578 :: SBool = s19 /= s8577
-  s8579 :: SWord8 = if s22 then s5795 else s5777
-  s8580 :: SWord8 = s8579 >>> 1
-  s8581 :: SWord8 = s24 | s8580
-  s8582 :: SWord8 = s26 & s8580
-  s8583 :: SWord8 = if s8578 then s8581 else s8582
-  s8584 :: SWord1 = choose [0:0] s5800
-  s8585 :: SBool = s19 /= s8584
-  s8586 :: SWord8 = if s8585 then s8581 else s8582
-  s8587 :: SWord8 = if s5781 then s8583 else s8586
-  s8588 :: SWord1 = choose [0:0] s5823
-  s8589 :: SBool = s19 /= s8588
-  s8590 :: SWord8 = if s22 then s5831 else s5812
-  s8591 :: SWord8 = s8590 >>> 1
-  s8592 :: SWord8 = s24 | s8591
-  s8593 :: SWord8 = s26 & s8591
-  s8594 :: SWord8 = if s8589 then s8592 else s8593
-  s8595 :: SWord1 = choose [0:0] s5834
-  s8596 :: SBool = s19 /= s8595
-  s8597 :: SWord8 = if s8596 then s8592 else s8593
-  s8598 :: SWord8 = if s5816 then s8594 else s8597
-  s8599 :: SWord8 = if s5759 then s8587 else s8598
-  s8600 :: SWord8 = if s5639 then s8576 else s8599
-  s8601 :: SWord1 = choose [0:0] s5899
-  s8602 :: SBool = s19 /= s8601
-  s8603 :: SWord8 = if s22 then s5909 else s5891
-  s8604 :: SWord8 = s8603 >>> 1
-  s8605 :: SWord8 = s24 | s8604
-  s8606 :: SWord8 = s26 & s8604
-  s8607 :: SWord8 = if s8602 then s8605 else s8606
-  s8608 :: SWord1 = choose [0:0] s5916
-  s8609 :: SBool = s19 /= s8608
-  s8610 :: SWord8 = if s8609 then s8605 else s8606
-  s8611 :: SWord8 = if s5895 then s8607 else s8610
-  s8612 :: SWord1 = choose [0:0] s5939
-  s8613 :: SBool = s19 /= s8612
-  s8614 :: SWord8 = if s22 then s5947 else s5928
-  s8615 :: SWord8 = s8614 >>> 1
-  s8616 :: SWord8 = s24 | s8615
-  s8617 :: SWord8 = s26 & s8615
-  s8618 :: SWord8 = if s8613 then s8616 else s8617
-  s8619 :: SWord1 = choose [0:0] s5950
-  s8620 :: SBool = s19 /= s8619
-  s8621 :: SWord8 = if s8620 then s8616 else s8617
-  s8622 :: SWord8 = if s5932 then s8618 else s8621
-  s8623 :: SWord8 = if s5874 then s8611 else s8622
-  s8624 :: SWord1 = choose [0:0] s5993
-  s8625 :: SBool = s19 /= s8624
-  s8626 :: SWord8 = if s22 then s6003 else s5985
-  s8627 :: SWord8 = s8626 >>> 1
-  s8628 :: SWord8 = s24 | s8627
-  s8629 :: SWord8 = s26 & s8627
-  s8630 :: SWord8 = if s8625 then s8628 else s8629
-  s8631 :: SWord1 = choose [0:0] s6008
-  s8632 :: SBool = s19 /= s8631
-  s8633 :: SWord8 = if s8632 then s8628 else s8629
-  s8634 :: SWord8 = if s5989 then s8630 else s8633
-  s8635 :: SWord1 = choose [0:0] s6031
-  s8636 :: SBool = s19 /= s8635
-  s8637 :: SWord8 = if s22 then s6039 else s6020
-  s8638 :: SWord8 = s8637 >>> 1
-  s8639 :: SWord8 = s24 | s8638
-  s8640 :: SWord8 = s26 & s8638
-  s8641 :: SWord8 = if s8636 then s8639 else s8640
-  s8642 :: SWord1 = choose [0:0] s6042
-  s8643 :: SBool = s19 /= s8642
-  s8644 :: SWord8 = if s8643 then s8639 else s8640
-  s8645 :: SWord8 = if s6024 then s8641 else s8644
-  s8646 :: SWord8 = if s5967 then s8634 else s8645
-  s8647 :: SWord8 = if s5852 then s8623 else s8646
-  s8648 :: SWord8 = if s5618 then s8600 else s8647
-  s8649 :: SWord1 = choose [0:0] s6129
-  s8650 :: SBool = s19 /= s8649
-  s8651 :: SWord8 = if s22 then s6139 else s6121
-  s8652 :: SWord8 = s8651 >>> 1
-  s8653 :: SWord8 = s24 | s8652
-  s8654 :: SWord8 = s26 & s8652
-  s8655 :: SWord8 = if s8650 then s8653 else s8654
-  s8656 :: SWord1 = choose [0:0] s6148
-  s8657 :: SBool = s19 /= s8656
-  s8658 :: SWord8 = if s8657 then s8653 else s8654
-  s8659 :: SWord8 = if s6125 then s8655 else s8658
-  s8660 :: SWord1 = choose [0:0] s6171
-  s8661 :: SBool = s19 /= s8660
-  s8662 :: SWord8 = if s22 then s6179 else s6160
-  s8663 :: SWord8 = s8662 >>> 1
-  s8664 :: SWord8 = s24 | s8663
-  s8665 :: SWord8 = s26 & s8663
-  s8666 :: SWord8 = if s8661 then s8664 else s8665
-  s8667 :: SWord1 = choose [0:0] s6182
-  s8668 :: SBool = s19 /= s8667
-  s8669 :: SWord8 = if s8668 then s8664 else s8665
-  s8670 :: SWord8 = if s6164 then s8666 else s8669
-  s8671 :: SWord8 = if s6104 then s8659 else s8670
-  s8672 :: SWord1 = choose [0:0] s6225
-  s8673 :: SBool = s19 /= s8672
-  s8674 :: SWord8 = if s22 then s6235 else s6217
-  s8675 :: SWord8 = s8674 >>> 1
-  s8676 :: SWord8 = s24 | s8675
-  s8677 :: SWord8 = s26 & s8675
-  s8678 :: SWord8 = if s8673 then s8676 else s8677
-  s8679 :: SWord1 = choose [0:0] s6240
-  s8680 :: SBool = s19 /= s8679
-  s8681 :: SWord8 = if s8680 then s8676 else s8677
-  s8682 :: SWord8 = if s6221 then s8678 else s8681
-  s8683 :: SWord1 = choose [0:0] s6263
-  s8684 :: SBool = s19 /= s8683
-  s8685 :: SWord8 = if s22 then s6271 else s6252
-  s8686 :: SWord8 = s8685 >>> 1
-  s8687 :: SWord8 = s24 | s8686
-  s8688 :: SWord8 = s26 & s8686
-  s8689 :: SWord8 = if s8684 then s8687 else s8688
-  s8690 :: SWord1 = choose [0:0] s6274
-  s8691 :: SBool = s19 /= s8690
-  s8692 :: SWord8 = if s8691 then s8687 else s8688
-  s8693 :: SWord8 = if s6256 then s8689 else s8692
-  s8694 :: SWord8 = if s6199 then s8682 else s8693
-  s8695 :: SWord8 = if s6083 then s8671 else s8694
-  s8696 :: SWord1 = choose [0:0] s6339
-  s8697 :: SBool = s19 /= s8696
-  s8698 :: SWord8 = if s22 then s6349 else s6331
-  s8699 :: SWord8 = s8698 >>> 1
-  s8700 :: SWord8 = s24 | s8699
-  s8701 :: SWord8 = s26 & s8699
-  s8702 :: SWord8 = if s8697 then s8700 else s8701
-  s8703 :: SWord1 = choose [0:0] s6356
-  s8704 :: SBool = s19 /= s8703
-  s8705 :: SWord8 = if s8704 then s8700 else s8701
-  s8706 :: SWord8 = if s6335 then s8702 else s8705
-  s8707 :: SWord1 = choose [0:0] s6379
-  s8708 :: SBool = s19 /= s8707
-  s8709 :: SWord8 = if s22 then s6387 else s6368
-  s8710 :: SWord8 = s8709 >>> 1
-  s8711 :: SWord8 = s24 | s8710
-  s8712 :: SWord8 = s26 & s8710
-  s8713 :: SWord8 = if s8708 then s8711 else s8712
-  s8714 :: SWord1 = choose [0:0] s6390
-  s8715 :: SBool = s19 /= s8714
-  s8716 :: SWord8 = if s8715 then s8711 else s8712
-  s8717 :: SWord8 = if s6372 then s8713 else s8716
-  s8718 :: SWord8 = if s6314 then s8706 else s8717
-  s8719 :: SWord1 = choose [0:0] s6433
-  s8720 :: SBool = s19 /= s8719
-  s8721 :: SWord8 = if s22 then s6443 else s6425
-  s8722 :: SWord8 = s8721 >>> 1
-  s8723 :: SWord8 = s24 | s8722
-  s8724 :: SWord8 = s26 & s8722
-  s8725 :: SWord8 = if s8720 then s8723 else s8724
-  s8726 :: SWord1 = choose [0:0] s6448
-  s8727 :: SBool = s19 /= s8726
-  s8728 :: SWord8 = if s8727 then s8723 else s8724
-  s8729 :: SWord8 = if s6429 then s8725 else s8728
-  s8730 :: SWord1 = choose [0:0] s6471
-  s8731 :: SBool = s19 /= s8730
-  s8732 :: SWord8 = if s22 then s6479 else s6460
-  s8733 :: SWord8 = s8732 >>> 1
-  s8734 :: SWord8 = s24 | s8733
-  s8735 :: SWord8 = s26 & s8733
-  s8736 :: SWord8 = if s8731 then s8734 else s8735
-  s8737 :: SWord1 = choose [0:0] s6482
-  s8738 :: SBool = s19 /= s8737
-  s8739 :: SWord8 = if s8738 then s8734 else s8735
-  s8740 :: SWord8 = if s6464 then s8736 else s8739
-  s8741 :: SWord8 = if s6407 then s8729 else s8740
-  s8742 :: SWord8 = if s6292 then s8718 else s8741
-  s8743 :: SWord8 = if s6061 then s8695 else s8742
-  s8744 :: SWord8 = if s5597 then s8648 else s8743
-  s8745 :: SWord1 = choose [0:0] s6591
-  s8746 :: SBool = s19 /= s8745
-  s8747 :: SWord8 = if s22 then s6601 else s6583
-  s8748 :: SWord8 = s8747 >>> 1
-  s8749 :: SWord8 = s24 | s8748
-  s8750 :: SWord8 = s26 & s8748
-  s8751 :: SWord8 = if s8746 then s8749 else s8750
-  s8752 :: SWord1 = choose [0:0] s6612
-  s8753 :: SBool = s19 /= s8752
-  s8754 :: SWord8 = if s8753 then s8749 else s8750
-  s8755 :: SWord8 = if s6587 then s8751 else s8754
-  s8756 :: SWord1 = choose [0:0] s6635
-  s8757 :: SBool = s19 /= s8756
-  s8758 :: SWord8 = if s22 then s6643 else s6624
-  s8759 :: SWord8 = s8758 >>> 1
-  s8760 :: SWord8 = s24 | s8759
-  s8761 :: SWord8 = s26 & s8759
-  s8762 :: SWord8 = if s8757 then s8760 else s8761
-  s8763 :: SWord1 = choose [0:0] s6646
-  s8764 :: SBool = s19 /= s8763
-  s8765 :: SWord8 = if s8764 then s8760 else s8761
-  s8766 :: SWord8 = if s6628 then s8762 else s8765
-  s8767 :: SWord8 = if s6566 then s8755 else s8766
-  s8768 :: SWord1 = choose [0:0] s6689
-  s8769 :: SBool = s19 /= s8768
-  s8770 :: SWord8 = if s22 then s6699 else s6681
-  s8771 :: SWord8 = s8770 >>> 1
-  s8772 :: SWord8 = s24 | s8771
-  s8773 :: SWord8 = s26 & s8771
-  s8774 :: SWord8 = if s8769 then s8772 else s8773
-  s8775 :: SWord1 = choose [0:0] s6704
-  s8776 :: SBool = s19 /= s8775
-  s8777 :: SWord8 = if s8776 then s8772 else s8773
-  s8778 :: SWord8 = if s6685 then s8774 else s8777
-  s8779 :: SWord1 = choose [0:0] s6727
-  s8780 :: SBool = s19 /= s8779
-  s8781 :: SWord8 = if s22 then s6735 else s6716
-  s8782 :: SWord8 = s8781 >>> 1
-  s8783 :: SWord8 = s24 | s8782
-  s8784 :: SWord8 = s26 & s8782
-  s8785 :: SWord8 = if s8780 then s8783 else s8784
-  s8786 :: SWord1 = choose [0:0] s6738
-  s8787 :: SBool = s19 /= s8786
-  s8788 :: SWord8 = if s8787 then s8783 else s8784
-  s8789 :: SWord8 = if s6720 then s8785 else s8788
-  s8790 :: SWord8 = if s6663 then s8778 else s8789
-  s8791 :: SWord8 = if s6545 then s8767 else s8790
-  s8792 :: SWord1 = choose [0:0] s6803
-  s8793 :: SBool = s19 /= s8792
-  s8794 :: SWord8 = if s22 then s6813 else s6795
-  s8795 :: SWord8 = s8794 >>> 1
-  s8796 :: SWord8 = s24 | s8795
-  s8797 :: SWord8 = s26 & s8795
-  s8798 :: SWord8 = if s8793 then s8796 else s8797
-  s8799 :: SWord1 = choose [0:0] s6820
-  s8800 :: SBool = s19 /= s8799
-  s8801 :: SWord8 = if s8800 then s8796 else s8797
-  s8802 :: SWord8 = if s6799 then s8798 else s8801
-  s8803 :: SWord1 = choose [0:0] s6843
-  s8804 :: SBool = s19 /= s8803
-  s8805 :: SWord8 = if s22 then s6851 else s6832
-  s8806 :: SWord8 = s8805 >>> 1
-  s8807 :: SWord8 = s24 | s8806
-  s8808 :: SWord8 = s26 & s8806
-  s8809 :: SWord8 = if s8804 then s8807 else s8808
-  s8810 :: SWord1 = choose [0:0] s6854
-  s8811 :: SBool = s19 /= s8810
-  s8812 :: SWord8 = if s8811 then s8807 else s8808
-  s8813 :: SWord8 = if s6836 then s8809 else s8812
-  s8814 :: SWord8 = if s6778 then s8802 else s8813
-  s8815 :: SWord1 = choose [0:0] s6897
-  s8816 :: SBool = s19 /= s8815
-  s8817 :: SWord8 = if s22 then s6907 else s6889
-  s8818 :: SWord8 = s8817 >>> 1
-  s8819 :: SWord8 = s24 | s8818
-  s8820 :: SWord8 = s26 & s8818
-  s8821 :: SWord8 = if s8816 then s8819 else s8820
-  s8822 :: SWord1 = choose [0:0] s6912
-  s8823 :: SBool = s19 /= s8822
-  s8824 :: SWord8 = if s8823 then s8819 else s8820
-  s8825 :: SWord8 = if s6893 then s8821 else s8824
-  s8826 :: SWord1 = choose [0:0] s6935
-  s8827 :: SBool = s19 /= s8826
-  s8828 :: SWord8 = if s22 then s6943 else s6924
-  s8829 :: SWord8 = s8828 >>> 1
-  s8830 :: SWord8 = s24 | s8829
-  s8831 :: SWord8 = s26 & s8829
-  s8832 :: SWord8 = if s8827 then s8830 else s8831
-  s8833 :: SWord1 = choose [0:0] s6946
-  s8834 :: SBool = s19 /= s8833
-  s8835 :: SWord8 = if s8834 then s8830 else s8831
-  s8836 :: SWord8 = if s6928 then s8832 else s8835
-  s8837 :: SWord8 = if s6871 then s8825 else s8836
-  s8838 :: SWord8 = if s6756 then s8814 else s8837
-  s8839 :: SWord8 = if s6524 then s8791 else s8838
-  s8840 :: SWord1 = choose [0:0] s7033
-  s8841 :: SBool = s19 /= s8840
-  s8842 :: SWord8 = if s22 then s7043 else s7025
-  s8843 :: SWord8 = s8842 >>> 1
-  s8844 :: SWord8 = s24 | s8843
-  s8845 :: SWord8 = s26 & s8843
-  s8846 :: SWord8 = if s8841 then s8844 else s8845
-  s8847 :: SWord1 = choose [0:0] s7052
-  s8848 :: SBool = s19 /= s8847
-  s8849 :: SWord8 = if s8848 then s8844 else s8845
-  s8850 :: SWord8 = if s7029 then s8846 else s8849
-  s8851 :: SWord1 = choose [0:0] s7075
-  s8852 :: SBool = s19 /= s8851
-  s8853 :: SWord8 = if s22 then s7083 else s7064
-  s8854 :: SWord8 = s8853 >>> 1
-  s8855 :: SWord8 = s24 | s8854
-  s8856 :: SWord8 = s26 & s8854
-  s8857 :: SWord8 = if s8852 then s8855 else s8856
-  s8858 :: SWord1 = choose [0:0] s7086
-  s8859 :: SBool = s19 /= s8858
-  s8860 :: SWord8 = if s8859 then s8855 else s8856
-  s8861 :: SWord8 = if s7068 then s8857 else s8860
-  s8862 :: SWord8 = if s7008 then s8850 else s8861
-  s8863 :: SWord1 = choose [0:0] s7129
-  s8864 :: SBool = s19 /= s8863
-  s8865 :: SWord8 = if s22 then s7139 else s7121
-  s8866 :: SWord8 = s8865 >>> 1
-  s8867 :: SWord8 = s24 | s8866
-  s8868 :: SWord8 = s26 & s8866
-  s8869 :: SWord8 = if s8864 then s8867 else s8868
-  s8870 :: SWord1 = choose [0:0] s7144
-  s8871 :: SBool = s19 /= s8870
-  s8872 :: SWord8 = if s8871 then s8867 else s8868
-  s8873 :: SWord8 = if s7125 then s8869 else s8872
-  s8874 :: SWord1 = choose [0:0] s7167
-  s8875 :: SBool = s19 /= s8874
-  s8876 :: SWord8 = if s22 then s7175 else s7156
-  s8877 :: SWord8 = s8876 >>> 1
-  s8878 :: SWord8 = s24 | s8877
-  s8879 :: SWord8 = s26 & s8877
-  s8880 :: SWord8 = if s8875 then s8878 else s8879
-  s8881 :: SWord1 = choose [0:0] s7178
-  s8882 :: SBool = s19 /= s8881
-  s8883 :: SWord8 = if s8882 then s8878 else s8879
-  s8884 :: SWord8 = if s7160 then s8880 else s8883
-  s8885 :: SWord8 = if s7103 then s8873 else s8884
-  s8886 :: SWord8 = if s6987 then s8862 else s8885
-  s8887 :: SWord1 = choose [0:0] s7243
-  s8888 :: SBool = s19 /= s8887
-  s8889 :: SWord8 = if s22 then s7253 else s7235
-  s8890 :: SWord8 = s8889 >>> 1
-  s8891 :: SWord8 = s24 | s8890
-  s8892 :: SWord8 = s26 & s8890
-  s8893 :: SWord8 = if s8888 then s8891 else s8892
-  s8894 :: SWord1 = choose [0:0] s7260
-  s8895 :: SBool = s19 /= s8894
-  s8896 :: SWord8 = if s8895 then s8891 else s8892
-  s8897 :: SWord8 = if s7239 then s8893 else s8896
-  s8898 :: SWord1 = choose [0:0] s7283
-  s8899 :: SBool = s19 /= s8898
-  s8900 :: SWord8 = if s22 then s7291 else s7272
-  s8901 :: SWord8 = s8900 >>> 1
-  s8902 :: SWord8 = s24 | s8901
-  s8903 :: SWord8 = s26 & s8901
-  s8904 :: SWord8 = if s8899 then s8902 else s8903
-  s8905 :: SWord1 = choose [0:0] s7294
-  s8906 :: SBool = s19 /= s8905
-  s8907 :: SWord8 = if s8906 then s8902 else s8903
-  s8908 :: SWord8 = if s7276 then s8904 else s8907
-  s8909 :: SWord8 = if s7218 then s8897 else s8908
-  s8910 :: SWord1 = choose [0:0] s7337
-  s8911 :: SBool = s19 /= s8910
-  s8912 :: SWord8 = if s22 then s7347 else s7329
-  s8913 :: SWord8 = s8912 >>> 1
-  s8914 :: SWord8 = s24 | s8913
-  s8915 :: SWord8 = s26 & s8913
-  s8916 :: SWord8 = if s8911 then s8914 else s8915
-  s8917 :: SWord1 = choose [0:0] s7352
-  s8918 :: SBool = s19 /= s8917
-  s8919 :: SWord8 = if s8918 then s8914 else s8915
-  s8920 :: SWord8 = if s7333 then s8916 else s8919
-  s8921 :: SWord1 = choose [0:0] s7375
-  s8922 :: SBool = s19 /= s8921
-  s8923 :: SWord8 = if s22 then s7383 else s7364
-  s8924 :: SWord8 = s8923 >>> 1
-  s8925 :: SWord8 = s24 | s8924
-  s8926 :: SWord8 = s26 & s8924
-  s8927 :: SWord8 = if s8922 then s8925 else s8926
-  s8928 :: SWord1 = choose [0:0] s7386
-  s8929 :: SBool = s19 /= s8928
-  s8930 :: SWord8 = if s8929 then s8925 else s8926
-  s8931 :: SWord8 = if s7368 then s8927 else s8930
-  s8932 :: SWord8 = if s7311 then s8920 else s8931
-  s8933 :: SWord8 = if s7196 then s8909 else s8932
-  s8934 :: SWord8 = if s6965 then s8886 else s8933
-  s8935 :: SWord8 = if s6502 then s8839 else s8934
-  s8936 :: SWord8 = if s5575 then s8744 else s8935
-  s8937 :: SWord8 = if s3725 then s8553 else s8936
-  s8938 :: SWord8 = if s21 then s8170 else s8937
-  s8939 :: SWord16 = s17 # s8938
-  s8940 :: SWord16 = s7403 + s8939
-  s8941 :: SWord16 = s17 # s1
-  s8942 :: SWord16 = s17 # s3
-  s8943 :: SWord16 = s8941 * s8942
-  s8944 :: SBool = s8940 == s8943
-  s8945 :: SBool = s15 | s8944
-CONSTRAINTS
-ASSERTIONS
-OUTPUTS
-  s8945
diff --git a/SBVUnitTest/GoldFiles/legato_c.gold b/SBVUnitTest/GoldFiles/legato_c.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/legato_c.gold
+++ /dev/null
@@ -1,6425 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for legatoMult. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: legatoMult_driver
-
-legatoMult.o: legatoMult.c legatoMult.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-legatoMult_driver.o: legatoMult_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-legatoMult_driver: legatoMult.o legatoMult_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f legatoMult_driver
-== END: "Makefile" ==================
-== BEGIN: "legatoMult.h" ================
-/* Header file for legatoMult. Automatically generated by SBV. Do not edit! */
-
-#ifndef __legatoMult__HEADER_INCLUDED__
-#define __legatoMult__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-void legatoMult(const SWord8 x, const SWord8 y, SWord8 *hi,
-                SWord8 *lo);
-
-#endif /* __legatoMult__HEADER_INCLUDED__ */
-== END: "legatoMult.h" ==================
-== BEGIN: "legatoMult_driver.c" ================
-/* Example driver program for legatoMult. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "legatoMult.h"
-
-int main(void)
-{
-  SWord8 hi;
-  SWord8 lo;
-
-  legatoMult(87, 92, &hi, &lo);
-
-  printf("legatoMult(87, 92, &hi, &lo) ->\n");
-  printf("  hi = %"PRIu8"\n", hi);
-  printf("  lo = %"PRIu8"\n", lo);
-
-  return 0;
-}
-== END: "legatoMult_driver.c" ==================
-== BEGIN: "legatoMult.c" ================
-/* File: "legatoMult.c". Automatically generated by SBV. Do not edit! */
-
-#include "legatoMult.h"
-
-void legatoMult(const SWord8 x, const SWord8 y, SWord8 *hi,
-                SWord8 *lo)
-{
-  const SWord8 s0 = x;
-  const SWord8 s1 = y;
-  const SBool  s2 = (SBool) ((s0 >> 0) & 1);
-  const SBool  s4 = s2 != false;
-  const SBool  s5 = false == s4;
-  const SWord8 s6 = (s0 >> 1) | (s0 << 7);
-  const SWord8 s8 = s6 & 127;
-  const SBool  s9 = (SBool) ((s8 >> 0) & 1);
-  const SBool  s10 = false != s9;
-  const SBool  s11 = false == s10;
-  const SWord8 s12 = (s8 >> 1) | (s8 << 7);
-  const SWord8 s13 = 127 & s12;
-  const SBool  s14 = (SBool) ((s13 >> 0) & 1);
-  const SBool  s15 = false != s14;
-  const SBool  s16 = false == s15;
-  const SWord8 s17 = (s13 >> 1) | (s13 << 7);
-  const SWord8 s18 = 127 & s17;
-  const SBool  s19 = (SBool) ((s18 >> 0) & 1);
-  const SBool  s20 = false != s19;
-  const SBool  s21 = false == s20;
-  const SWord8 s24 = s4 ? 128 : 0;
-  const SBool  s25 = (SBool) ((s24 >> 0) & 1);
-  const SBool  s26 = false != s25;
-  const SWord8 s27 = s26 ? 128 : 0;
-  const SBool  s28 = (SBool) ((s27 >> 0) & 1);
-  const SBool  s29 = false != s28;
-  const SWord8 s30 = (s18 >> 1) | (s18 << 7);
-  const SWord8 s31 = 128 | s30;
-  const SWord8 s32 = 127 & s30;
-  const SWord8 s33 = s29 ? s31 : s32;
-  const SBool  s34 = (SBool) ((s33 >> 0) & 1);
-  const SBool  s35 = false != s34;
-  const SBool  s36 = false == s35;
-  const SWord8 s37 = (s24 >> 1) | (s24 << 7);
-  const SWord8 s38 = 128 | s37;
-  const SWord8 s39 = 127 & s37;
-  const SWord8 s40 = s10 ? s38 : s39;
-  const SBool  s41 = (SBool) ((s40 >> 0) & 1);
-  const SBool  s42 = false != s41;
-  const SWord8 s43 = (s27 >> 1) | (s27 << 7);
-  const SWord8 s44 = 128 | s43;
-  const SWord8 s45 = 127 & s43;
-  const SWord8 s46 = s42 ? s44 : s45;
-  const SBool  s47 = (SBool) ((s46 >> 0) & 1);
-  const SBool  s48 = false != s47;
-  const SWord8 s49 = (s33 >> 1) | (s33 << 7);
-  const SWord8 s50 = 128 | s49;
-  const SWord8 s51 = 127 & s49;
-  const SWord8 s52 = s48 ? s50 : s51;
-  const SBool  s53 = (SBool) ((s52 >> 0) & 1);
-  const SBool  s54 = false != s53;
-  const SBool  s55 = false == s54;
-  const SWord8 s56 = (s40 >> 1) | (s40 << 7);
-  const SWord8 s57 = 128 | s56;
-  const SWord8 s58 = 127 & s56;
-  const SWord8 s59 = s15 ? s57 : s58;
-  const SBool  s60 = (SBool) ((s59 >> 0) & 1);
-  const SBool  s61 = false != s60;
-  const SWord8 s62 = (s46 >> 1) | (s46 << 7);
-  const SWord8 s63 = 128 | s62;
-  const SWord8 s64 = 127 & s62;
-  const SWord8 s65 = s61 ? s63 : s64;
-  const SBool  s66 = (SBool) ((s65 >> 0) & 1);
-  const SBool  s67 = false != s66;
-  const SWord8 s68 = (s52 >> 1) | (s52 << 7);
-  const SWord8 s69 = 128 | s68;
-  const SWord8 s70 = 127 & s68;
-  const SWord8 s71 = s67 ? s69 : s70;
-  const SBool  s72 = (SBool) ((s71 >> 0) & 1);
-  const SBool  s73 = false != s72;
-  const SBool  s74 = false == s73;
-  const SWord8 s75 = (s59 >> 1) | (s59 << 7);
-  const SWord8 s76 = 128 | s75;
-  const SWord8 s77 = 127 & s75;
-  const SWord8 s78 = s20 ? s76 : s77;
-  const SBool  s79 = (SBool) ((s78 >> 0) & 1);
-  const SBool  s80 = false != s79;
-  const SWord8 s81 = (s65 >> 1) | (s65 << 7);
-  const SWord8 s82 = 128 | s81;
-  const SWord8 s83 = 127 & s81;
-  const SWord8 s84 = s80 ? s82 : s83;
-  const SBool  s85 = (SBool) ((s84 >> 0) & 1);
-  const SBool  s86 = false != s85;
-  const SWord8 s87 = (s71 >> 1) | (s71 << 7);
-  const SWord8 s88 = 128 | s87;
-  const SWord8 s89 = 127 & s87;
-  const SWord8 s90 = s86 ? s88 : s89;
-  const SBool  s91 = (SBool) ((s90 >> 0) & 1);
-  const SBool  s92 = false != s91;
-  const SBool  s93 = false == s92;
-  const SWord8 s94 = (s78 >> 1) | (s78 << 7);
-  const SWord8 s95 = 128 | s94;
-  const SWord8 s96 = 127 & s94;
-  const SWord8 s97 = s35 ? s95 : s96;
-  const SWord8 s98 = (s97 >> 1) | (s97 << 7);
-  const SWord8 s99 = 128 | s98;
-  const SWord8 s100 = 127 & s98;
-  const SWord8 s101 = s54 ? s99 : s100;
-  const SWord8 s102 = (s101 >> 1) | (s101 << 7);
-  const SWord8 s103 = 128 | s102;
-  const SWord8 s104 = 127 & s102;
-  const SWord8 s105 = s73 ? s103 : s104;
-  const SWord8 s106 = (s105 >> 1) | (s105 << 7);
-  const SWord8 s107 = 128 | s106;
-  const SWord8 s108 = 127 & s106;
-  const SWord8 s109 = s92 ? s107 : s108;
-  const SWord8 s110 = s1 + s105;
-  const SBool  s111 = s110 < s1;
-  const SBool  s112 = s110 < s105;
-  const SBool  s113 = s111 || s112;
-  const SWord8 s114 = (s110 >> 1) | (s110 << 7);
-  const SWord8 s115 = 128 | s114;
-  const SWord8 s116 = 127 & s114;
-  const SWord8 s117 = s113 ? s115 : s116;
-  const SWord8 s118 = s93 ? s109 : s117;
-  const SWord8 s119 = s1 + s101;
-  const SBool  s120 = s119 < s1;
-  const SBool  s121 = s119 < s101;
-  const SBool  s122 = s120 || s121;
-  const SWord8 s123 = (s119 >> 1) | (s119 << 7);
-  const SWord8 s124 = 128 | s123;
-  const SWord8 s125 = 127 & s123;
-  const SWord8 s126 = s122 ? s124 : s125;
-  const SWord8 s127 = (s126 >> 1) | (s126 << 7);
-  const SWord8 s128 = 128 | s127;
-  const SWord8 s129 = 127 & s127;
-  const SWord8 s130 = s92 ? s128 : s129;
-  const SWord8 s131 = s1 + s126;
-  const SBool  s132 = s131 < s1;
-  const SBool  s133 = s131 < s126;
-  const SBool  s134 = s132 || s133;
-  const SWord8 s135 = (s131 >> 1) | (s131 << 7);
-  const SWord8 s136 = 128 | s135;
-  const SWord8 s137 = 127 & s135;
-  const SWord8 s138 = s134 ? s136 : s137;
-  const SWord8 s139 = s93 ? s130 : s138;
-  const SWord8 s140 = s74 ? s118 : s139;
-  const SWord8 s141 = s1 + s97;
-  const SBool  s142 = s141 < s1;
-  const SBool  s143 = s141 < s97;
-  const SBool  s144 = s142 || s143;
-  const SWord8 s145 = (s141 >> 1) | (s141 << 7);
-  const SWord8 s146 = 128 | s145;
-  const SWord8 s147 = 127 & s145;
-  const SWord8 s148 = s144 ? s146 : s147;
-  const SWord8 s149 = (s148 >> 1) | (s148 << 7);
-  const SWord8 s150 = 128 | s149;
-  const SWord8 s151 = 127 & s149;
-  const SWord8 s152 = s73 ? s150 : s151;
-  const SWord8 s153 = (s152 >> 1) | (s152 << 7);
-  const SWord8 s154 = 128 | s153;
-  const SWord8 s155 = 127 & s153;
-  const SWord8 s156 = s92 ? s154 : s155;
-  const SWord8 s157 = s1 + s152;
-  const SBool  s158 = s157 < s1;
-  const SBool  s159 = s157 < s152;
-  const SBool  s160 = s158 || s159;
-  const SWord8 s161 = (s157 >> 1) | (s157 << 7);
-  const SWord8 s162 = 128 | s161;
-  const SWord8 s163 = 127 & s161;
-  const SWord8 s164 = s160 ? s162 : s163;
-  const SWord8 s165 = s93 ? s156 : s164;
-  const SWord8 s166 = s1 + s148;
-  const SBool  s167 = s166 < s1;
-  const SBool  s168 = s166 < s148;
-  const SBool  s169 = s167 || s168;
-  const SWord8 s170 = (s166 >> 1) | (s166 << 7);
-  const SWord8 s171 = 128 | s170;
-  const SWord8 s172 = 127 & s170;
-  const SWord8 s173 = s169 ? s171 : s172;
-  const SWord8 s174 = (s173 >> 1) | (s173 << 7);
-  const SWord8 s175 = 128 | s174;
-  const SWord8 s176 = 127 & s174;
-  const SWord8 s177 = s92 ? s175 : s176;
-  const SWord8 s178 = s1 + s173;
-  const SBool  s179 = s178 < s1;
-  const SBool  s180 = s178 < s173;
-  const SBool  s181 = s179 || s180;
-  const SWord8 s182 = (s178 >> 1) | (s178 << 7);
-  const SWord8 s183 = 128 | s182;
-  const SWord8 s184 = 127 & s182;
-  const SWord8 s185 = s181 ? s183 : s184;
-  const SWord8 s186 = s93 ? s177 : s185;
-  const SWord8 s187 = s74 ? s165 : s186;
-  const SWord8 s188 = s55 ? s140 : s187;
-  const SWord8 s189 = s1 + s78;
-  const SBool  s190 = (SBool) ((s189 >> 0) & 1);
-  const SBool  s191 = false != s190;
-  const SWord8 s192 = s191 ? s82 : s83;
-  const SBool  s193 = (SBool) ((s192 >> 0) & 1);
-  const SBool  s194 = false != s193;
-  const SWord8 s195 = s194 ? s88 : s89;
-  const SBool  s196 = (SBool) ((s195 >> 0) & 1);
-  const SBool  s197 = false != s196;
-  const SBool  s198 = false == s197;
-  const SBool  s199 = s189 < s1;
-  const SBool  s200 = s189 < s78;
-  const SBool  s201 = s199 || s200;
-  const SWord8 s202 = (s189 >> 1) | (s189 << 7);
-  const SWord8 s203 = 128 | s202;
-  const SWord8 s204 = 127 & s202;
-  const SWord8 s205 = s201 ? s203 : s204;
-  const SWord8 s206 = (s205 >> 1) | (s205 << 7);
-  const SWord8 s207 = 128 | s206;
-  const SWord8 s208 = 127 & s206;
-  const SWord8 s209 = s54 ? s207 : s208;
-  const SWord8 s210 = (s209 >> 1) | (s209 << 7);
-  const SWord8 s211 = 128 | s210;
-  const SWord8 s212 = 127 & s210;
-  const SWord8 s213 = s73 ? s211 : s212;
-  const SWord8 s214 = (s213 >> 1) | (s213 << 7);
-  const SWord8 s215 = 128 | s214;
-  const SWord8 s216 = 127 & s214;
-  const SWord8 s217 = s197 ? s215 : s216;
-  const SWord8 s218 = s1 + s213;
-  const SBool  s219 = s218 < s1;
-  const SBool  s220 = s218 < s213;
-  const SBool  s221 = s219 || s220;
-  const SWord8 s222 = (s218 >> 1) | (s218 << 7);
-  const SWord8 s223 = 128 | s222;
-  const SWord8 s224 = 127 & s222;
-  const SWord8 s225 = s221 ? s223 : s224;
-  const SWord8 s226 = s198 ? s217 : s225;
-  const SWord8 s227 = s1 + s209;
-  const SBool  s228 = s227 < s1;
-  const SBool  s229 = s227 < s209;
-  const SBool  s230 = s228 || s229;
-  const SWord8 s231 = (s227 >> 1) | (s227 << 7);
-  const SWord8 s232 = 128 | s231;
-  const SWord8 s233 = 127 & s231;
-  const SWord8 s234 = s230 ? s232 : s233;
-  const SWord8 s235 = (s234 >> 1) | (s234 << 7);
-  const SWord8 s236 = 128 | s235;
-  const SWord8 s237 = 127 & s235;
-  const SWord8 s238 = s197 ? s236 : s237;
-  const SWord8 s239 = s1 + s234;
-  const SBool  s240 = s239 < s1;
-  const SBool  s241 = s239 < s234;
-  const SBool  s242 = s240 || s241;
-  const SWord8 s243 = (s239 >> 1) | (s239 << 7);
-  const SWord8 s244 = 128 | s243;
-  const SWord8 s245 = 127 & s243;
-  const SWord8 s246 = s242 ? s244 : s245;
-  const SWord8 s247 = s198 ? s238 : s246;
-  const SWord8 s248 = s74 ? s226 : s247;
-  const SWord8 s249 = s1 + s205;
-  const SBool  s250 = s249 < s1;
-  const SBool  s251 = s249 < s205;
-  const SBool  s252 = s250 || s251;
-  const SWord8 s253 = (s249 >> 1) | (s249 << 7);
-  const SWord8 s254 = 128 | s253;
-  const SWord8 s255 = 127 & s253;
-  const SWord8 s256 = s252 ? s254 : s255;
-  const SWord8 s257 = (s256 >> 1) | (s256 << 7);
-  const SWord8 s258 = 128 | s257;
-  const SWord8 s259 = 127 & s257;
-  const SWord8 s260 = s73 ? s258 : s259;
-  const SWord8 s261 = (s260 >> 1) | (s260 << 7);
-  const SWord8 s262 = 128 | s261;
-  const SWord8 s263 = 127 & s261;
-  const SWord8 s264 = s197 ? s262 : s263;
-  const SWord8 s265 = s1 + s260;
-  const SBool  s266 = s265 < s1;
-  const SBool  s267 = s265 < s260;
-  const SBool  s268 = s266 || s267;
-  const SWord8 s269 = (s265 >> 1) | (s265 << 7);
-  const SWord8 s270 = 128 | s269;
-  const SWord8 s271 = 127 & s269;
-  const SWord8 s272 = s268 ? s270 : s271;
-  const SWord8 s273 = s198 ? s264 : s272;
-  const SWord8 s274 = s1 + s256;
-  const SBool  s275 = s274 < s1;
-  const SBool  s276 = s274 < s256;
-  const SBool  s277 = s275 || s276;
-  const SWord8 s278 = (s274 >> 1) | (s274 << 7);
-  const SWord8 s279 = 128 | s278;
-  const SWord8 s280 = 127 & s278;
-  const SWord8 s281 = s277 ? s279 : s280;
-  const SWord8 s282 = (s281 >> 1) | (s281 << 7);
-  const SWord8 s283 = 128 | s282;
-  const SWord8 s284 = 127 & s282;
-  const SWord8 s285 = s197 ? s283 : s284;
-  const SWord8 s286 = s1 + s281;
-  const SBool  s287 = s286 < s1;
-  const SBool  s288 = s286 < s281;
-  const SBool  s289 = s287 || s288;
-  const SWord8 s290 = (s286 >> 1) | (s286 << 7);
-  const SWord8 s291 = 128 | s290;
-  const SWord8 s292 = 127 & s290;
-  const SWord8 s293 = s289 ? s291 : s292;
-  const SWord8 s294 = s198 ? s285 : s293;
-  const SWord8 s295 = s74 ? s273 : s294;
-  const SWord8 s296 = s55 ? s248 : s295;
-  const SWord8 s297 = s36 ? s188 : s296;
-  const SWord8 s298 = s1 + s59;
-  const SBool  s299 = (SBool) ((s298 >> 0) & 1);
-  const SBool  s300 = false != s299;
-  const SWord8 s301 = s300 ? s63 : s64;
-  const SBool  s302 = (SBool) ((s301 >> 0) & 1);
-  const SBool  s303 = false != s302;
-  const SWord8 s304 = s303 ? s69 : s70;
-  const SBool  s305 = (SBool) ((s304 >> 0) & 1);
-  const SBool  s306 = false != s305;
-  const SBool  s307 = false == s306;
-  const SBool  s308 = s298 < s1;
-  const SBool  s309 = s298 < s59;
-  const SBool  s310 = s308 || s309;
-  const SWord8 s311 = (s298 >> 1) | (s298 << 7);
-  const SWord8 s312 = 128 | s311;
-  const SWord8 s313 = 127 & s311;
-  const SWord8 s314 = s310 ? s312 : s313;
-  const SBool  s315 = (SBool) ((s314 >> 0) & 1);
-  const SBool  s316 = false != s315;
-  const SWord8 s317 = (s301 >> 1) | (s301 << 7);
-  const SWord8 s318 = 128 | s317;
-  const SWord8 s319 = 127 & s317;
-  const SWord8 s320 = s316 ? s318 : s319;
-  const SBool  s321 = (SBool) ((s320 >> 0) & 1);
-  const SBool  s322 = false != s321;
-  const SWord8 s323 = (s304 >> 1) | (s304 << 7);
-  const SWord8 s324 = 128 | s323;
-  const SWord8 s325 = 127 & s323;
-  const SWord8 s326 = s322 ? s324 : s325;
-  const SBool  s327 = (SBool) ((s326 >> 0) & 1);
-  const SBool  s328 = false != s327;
-  const SBool  s329 = false == s328;
-  const SWord8 s330 = (s314 >> 1) | (s314 << 7);
-  const SWord8 s331 = 128 | s330;
-  const SWord8 s332 = 127 & s330;
-  const SWord8 s333 = s35 ? s331 : s332;
-  const SWord8 s334 = (s333 >> 1) | (s333 << 7);
-  const SWord8 s335 = 128 | s334;
-  const SWord8 s336 = 127 & s334;
-  const SWord8 s337 = s54 ? s335 : s336;
-  const SWord8 s338 = (s337 >> 1) | (s337 << 7);
-  const SWord8 s339 = 128 | s338;
-  const SWord8 s340 = 127 & s338;
-  const SWord8 s341 = s306 ? s339 : s340;
-  const SWord8 s342 = (s341 >> 1) | (s341 << 7);
-  const SWord8 s343 = 128 | s342;
-  const SWord8 s344 = 127 & s342;
-  const SWord8 s345 = s328 ? s343 : s344;
-  const SWord8 s346 = s1 + s341;
-  const SBool  s347 = s346 < s1;
-  const SBool  s348 = s346 < s341;
-  const SBool  s349 = s347 || s348;
-  const SWord8 s350 = (s346 >> 1) | (s346 << 7);
-  const SWord8 s351 = 128 | s350;
-  const SWord8 s352 = 127 & s350;
-  const SWord8 s353 = s349 ? s351 : s352;
-  const SWord8 s354 = s329 ? s345 : s353;
-  const SWord8 s355 = s1 + s337;
-  const SBool  s356 = s355 < s1;
-  const SBool  s357 = s355 < s337;
-  const SBool  s358 = s356 || s357;
-  const SWord8 s359 = (s355 >> 1) | (s355 << 7);
-  const SWord8 s360 = 128 | s359;
-  const SWord8 s361 = 127 & s359;
-  const SWord8 s362 = s358 ? s360 : s361;
-  const SWord8 s363 = (s362 >> 1) | (s362 << 7);
-  const SWord8 s364 = 128 | s363;
-  const SWord8 s365 = 127 & s363;
-  const SWord8 s366 = s328 ? s364 : s365;
-  const SWord8 s367 = s1 + s362;
-  const SBool  s368 = s367 < s1;
-  const SBool  s369 = s367 < s362;
-  const SBool  s370 = s368 || s369;
-  const SWord8 s371 = (s367 >> 1) | (s367 << 7);
-  const SWord8 s372 = 128 | s371;
-  const SWord8 s373 = 127 & s371;
-  const SWord8 s374 = s370 ? s372 : s373;
-  const SWord8 s375 = s329 ? s366 : s374;
-  const SWord8 s376 = s307 ? s354 : s375;
-  const SWord8 s377 = s1 + s333;
-  const SBool  s378 = s377 < s1;
-  const SBool  s379 = s377 < s333;
-  const SBool  s380 = s378 || s379;
-  const SWord8 s381 = (s377 >> 1) | (s377 << 7);
-  const SWord8 s382 = 128 | s381;
-  const SWord8 s383 = 127 & s381;
-  const SWord8 s384 = s380 ? s382 : s383;
-  const SWord8 s385 = (s384 >> 1) | (s384 << 7);
-  const SWord8 s386 = 128 | s385;
-  const SWord8 s387 = 127 & s385;
-  const SWord8 s388 = s306 ? s386 : s387;
-  const SWord8 s389 = (s388 >> 1) | (s388 << 7);
-  const SWord8 s390 = 128 | s389;
-  const SWord8 s391 = 127 & s389;
-  const SWord8 s392 = s328 ? s390 : s391;
-  const SWord8 s393 = s1 + s388;
-  const SBool  s394 = s393 < s1;
-  const SBool  s395 = s393 < s388;
-  const SBool  s396 = s394 || s395;
-  const SWord8 s397 = (s393 >> 1) | (s393 << 7);
-  const SWord8 s398 = 128 | s397;
-  const SWord8 s399 = 127 & s397;
-  const SWord8 s400 = s396 ? s398 : s399;
-  const SWord8 s401 = s329 ? s392 : s400;
-  const SWord8 s402 = s1 + s384;
-  const SBool  s403 = s402 < s1;
-  const SBool  s404 = s402 < s384;
-  const SBool  s405 = s403 || s404;
-  const SWord8 s406 = (s402 >> 1) | (s402 << 7);
-  const SWord8 s407 = 128 | s406;
-  const SWord8 s408 = 127 & s406;
-  const SWord8 s409 = s405 ? s407 : s408;
-  const SWord8 s410 = (s409 >> 1) | (s409 << 7);
-  const SWord8 s411 = 128 | s410;
-  const SWord8 s412 = 127 & s410;
-  const SWord8 s413 = s328 ? s411 : s412;
-  const SWord8 s414 = s1 + s409;
-  const SBool  s415 = s414 < s1;
-  const SBool  s416 = s414 < s409;
-  const SBool  s417 = s415 || s416;
-  const SWord8 s418 = (s414 >> 1) | (s414 << 7);
-  const SWord8 s419 = 128 | s418;
-  const SWord8 s420 = 127 & s418;
-  const SWord8 s421 = s417 ? s419 : s420;
-  const SWord8 s422 = s329 ? s413 : s421;
-  const SWord8 s423 = s307 ? s401 : s422;
-  const SWord8 s424 = s55 ? s376 : s423;
-  const SWord8 s425 = s1 + s314;
-  const SBool  s426 = (SBool) ((s425 >> 0) & 1);
-  const SBool  s427 = false != s426;
-  const SWord8 s428 = s427 ? s318 : s319;
-  const SBool  s429 = (SBool) ((s428 >> 0) & 1);
-  const SBool  s430 = false != s429;
-  const SWord8 s431 = s430 ? s324 : s325;
-  const SBool  s432 = (SBool) ((s431 >> 0) & 1);
-  const SBool  s433 = false != s432;
-  const SBool  s434 = false == s433;
-  const SBool  s435 = s425 < s1;
-  const SBool  s436 = s425 < s314;
-  const SBool  s437 = s435 || s436;
-  const SWord8 s438 = (s425 >> 1) | (s425 << 7);
-  const SWord8 s439 = 128 | s438;
-  const SWord8 s440 = 127 & s438;
-  const SWord8 s441 = s437 ? s439 : s440;
-  const SWord8 s442 = (s441 >> 1) | (s441 << 7);
-  const SWord8 s443 = 128 | s442;
-  const SWord8 s444 = 127 & s442;
-  const SWord8 s445 = s54 ? s443 : s444;
-  const SWord8 s446 = (s445 >> 1) | (s445 << 7);
-  const SWord8 s447 = 128 | s446;
-  const SWord8 s448 = 127 & s446;
-  const SWord8 s449 = s306 ? s447 : s448;
-  const SWord8 s450 = (s449 >> 1) | (s449 << 7);
-  const SWord8 s451 = 128 | s450;
-  const SWord8 s452 = 127 & s450;
-  const SWord8 s453 = s433 ? s451 : s452;
-  const SWord8 s454 = s1 + s449;
-  const SBool  s455 = s454 < s1;
-  const SBool  s456 = s454 < s449;
-  const SBool  s457 = s455 || s456;
-  const SWord8 s458 = (s454 >> 1) | (s454 << 7);
-  const SWord8 s459 = 128 | s458;
-  const SWord8 s460 = 127 & s458;
-  const SWord8 s461 = s457 ? s459 : s460;
-  const SWord8 s462 = s434 ? s453 : s461;
-  const SWord8 s463 = s1 + s445;
-  const SBool  s464 = s463 < s1;
-  const SBool  s465 = s463 < s445;
-  const SBool  s466 = s464 || s465;
-  const SWord8 s467 = (s463 >> 1) | (s463 << 7);
-  const SWord8 s468 = 128 | s467;
-  const SWord8 s469 = 127 & s467;
-  const SWord8 s470 = s466 ? s468 : s469;
-  const SWord8 s471 = (s470 >> 1) | (s470 << 7);
-  const SWord8 s472 = 128 | s471;
-  const SWord8 s473 = 127 & s471;
-  const SWord8 s474 = s433 ? s472 : s473;
-  const SWord8 s475 = s1 + s470;
-  const SBool  s476 = s475 < s1;
-  const SBool  s477 = s475 < s470;
-  const SBool  s478 = s476 || s477;
-  const SWord8 s479 = (s475 >> 1) | (s475 << 7);
-  const SWord8 s480 = 128 | s479;
-  const SWord8 s481 = 127 & s479;
-  const SWord8 s482 = s478 ? s480 : s481;
-  const SWord8 s483 = s434 ? s474 : s482;
-  const SWord8 s484 = s307 ? s462 : s483;
-  const SWord8 s485 = s1 + s441;
-  const SBool  s486 = s485 < s1;
-  const SBool  s487 = s485 < s441;
-  const SBool  s488 = s486 || s487;
-  const SWord8 s489 = (s485 >> 1) | (s485 << 7);
-  const SWord8 s490 = 128 | s489;
-  const SWord8 s491 = 127 & s489;
-  const SWord8 s492 = s488 ? s490 : s491;
-  const SWord8 s493 = (s492 >> 1) | (s492 << 7);
-  const SWord8 s494 = 128 | s493;
-  const SWord8 s495 = 127 & s493;
-  const SWord8 s496 = s306 ? s494 : s495;
-  const SWord8 s497 = (s496 >> 1) | (s496 << 7);
-  const SWord8 s498 = 128 | s497;
-  const SWord8 s499 = 127 & s497;
-  const SWord8 s500 = s433 ? s498 : s499;
-  const SWord8 s501 = s1 + s496;
-  const SBool  s502 = s501 < s1;
-  const SBool  s503 = s501 < s496;
-  const SBool  s504 = s502 || s503;
-  const SWord8 s505 = (s501 >> 1) | (s501 << 7);
-  const SWord8 s506 = 128 | s505;
-  const SWord8 s507 = 127 & s505;
-  const SWord8 s508 = s504 ? s506 : s507;
-  const SWord8 s509 = s434 ? s500 : s508;
-  const SWord8 s510 = s1 + s492;
-  const SBool  s511 = s510 < s1;
-  const SBool  s512 = s510 < s492;
-  const SBool  s513 = s511 || s512;
-  const SWord8 s514 = (s510 >> 1) | (s510 << 7);
-  const SWord8 s515 = 128 | s514;
-  const SWord8 s516 = 127 & s514;
-  const SWord8 s517 = s513 ? s515 : s516;
-  const SWord8 s518 = (s517 >> 1) | (s517 << 7);
-  const SWord8 s519 = 128 | s518;
-  const SWord8 s520 = 127 & s518;
-  const SWord8 s521 = s433 ? s519 : s520;
-  const SWord8 s522 = s1 + s517;
-  const SBool  s523 = s522 < s1;
-  const SBool  s524 = s522 < s517;
-  const SBool  s525 = s523 || s524;
-  const SWord8 s526 = (s522 >> 1) | (s522 << 7);
-  const SWord8 s527 = 128 | s526;
-  const SWord8 s528 = 127 & s526;
-  const SWord8 s529 = s525 ? s527 : s528;
-  const SWord8 s530 = s434 ? s521 : s529;
-  const SWord8 s531 = s307 ? s509 : s530;
-  const SWord8 s532 = s55 ? s484 : s531;
-  const SWord8 s533 = s36 ? s424 : s532;
-  const SWord8 s534 = s21 ? s297 : s533;
-  const SWord8 s535 = s1 + s40;
-  const SBool  s536 = (SBool) ((s535 >> 0) & 1);
-  const SBool  s537 = false != s536;
-  const SWord8 s538 = s537 ? s44 : s45;
-  const SBool  s539 = (SBool) ((s538 >> 0) & 1);
-  const SBool  s540 = false != s539;
-  const SWord8 s541 = s540 ? s50 : s51;
-  const SBool  s542 = (SBool) ((s541 >> 0) & 1);
-  const SBool  s543 = false != s542;
-  const SBool  s544 = false == s543;
-  const SBool  s545 = s535 < s1;
-  const SBool  s546 = s535 < s40;
-  const SBool  s547 = s545 || s546;
-  const SWord8 s548 = (s535 >> 1) | (s535 << 7);
-  const SWord8 s549 = 128 | s548;
-  const SWord8 s550 = 127 & s548;
-  const SWord8 s551 = s547 ? s549 : s550;
-  const SBool  s552 = (SBool) ((s551 >> 0) & 1);
-  const SBool  s553 = false != s552;
-  const SWord8 s554 = (s538 >> 1) | (s538 << 7);
-  const SWord8 s555 = 128 | s554;
-  const SWord8 s556 = 127 & s554;
-  const SWord8 s557 = s553 ? s555 : s556;
-  const SBool  s558 = (SBool) ((s557 >> 0) & 1);
-  const SBool  s559 = false != s558;
-  const SWord8 s560 = (s541 >> 1) | (s541 << 7);
-  const SWord8 s561 = 128 | s560;
-  const SWord8 s562 = 127 & s560;
-  const SWord8 s563 = s559 ? s561 : s562;
-  const SBool  s564 = (SBool) ((s563 >> 0) & 1);
-  const SBool  s565 = false != s564;
-  const SBool  s566 = false == s565;
-  const SWord8 s567 = (s551 >> 1) | (s551 << 7);
-  const SWord8 s568 = 128 | s567;
-  const SWord8 s569 = 127 & s567;
-  const SWord8 s570 = s20 ? s568 : s569;
-  const SBool  s571 = (SBool) ((s570 >> 0) & 1);
-  const SBool  s572 = false != s571;
-  const SWord8 s573 = (s557 >> 1) | (s557 << 7);
-  const SWord8 s574 = 128 | s573;
-  const SWord8 s575 = 127 & s573;
-  const SWord8 s576 = s572 ? s574 : s575;
-  const SBool  s577 = (SBool) ((s576 >> 0) & 1);
-  const SBool  s578 = false != s577;
-  const SWord8 s579 = (s563 >> 1) | (s563 << 7);
-  const SWord8 s580 = 128 | s579;
-  const SWord8 s581 = 127 & s579;
-  const SWord8 s582 = s578 ? s580 : s581;
-  const SBool  s583 = (SBool) ((s582 >> 0) & 1);
-  const SBool  s584 = false != s583;
-  const SBool  s585 = false == s584;
-  const SWord8 s586 = (s570 >> 1) | (s570 << 7);
-  const SWord8 s587 = 128 | s586;
-  const SWord8 s588 = 127 & s586;
-  const SWord8 s589 = s35 ? s587 : s588;
-  const SWord8 s590 = (s589 >> 1) | (s589 << 7);
-  const SWord8 s591 = 128 | s590;
-  const SWord8 s592 = 127 & s590;
-  const SWord8 s593 = s543 ? s591 : s592;
-  const SWord8 s594 = (s593 >> 1) | (s593 << 7);
-  const SWord8 s595 = 128 | s594;
-  const SWord8 s596 = 127 & s594;
-  const SWord8 s597 = s565 ? s595 : s596;
-  const SWord8 s598 = (s597 >> 1) | (s597 << 7);
-  const SWord8 s599 = 128 | s598;
-  const SWord8 s600 = 127 & s598;
-  const SWord8 s601 = s584 ? s599 : s600;
-  const SWord8 s602 = s1 + s597;
-  const SBool  s603 = s602 < s1;
-  const SBool  s604 = s602 < s597;
-  const SBool  s605 = s603 || s604;
-  const SWord8 s606 = (s602 >> 1) | (s602 << 7);
-  const SWord8 s607 = 128 | s606;
-  const SWord8 s608 = 127 & s606;
-  const SWord8 s609 = s605 ? s607 : s608;
-  const SWord8 s610 = s585 ? s601 : s609;
-  const SWord8 s611 = s1 + s593;
-  const SBool  s612 = s611 < s1;
-  const SBool  s613 = s611 < s593;
-  const SBool  s614 = s612 || s613;
-  const SWord8 s615 = (s611 >> 1) | (s611 << 7);
-  const SWord8 s616 = 128 | s615;
-  const SWord8 s617 = 127 & s615;
-  const SWord8 s618 = s614 ? s616 : s617;
-  const SWord8 s619 = (s618 >> 1) | (s618 << 7);
-  const SWord8 s620 = 128 | s619;
-  const SWord8 s621 = 127 & s619;
-  const SWord8 s622 = s584 ? s620 : s621;
-  const SWord8 s623 = s1 + s618;
-  const SBool  s624 = s623 < s1;
-  const SBool  s625 = s623 < s618;
-  const SBool  s626 = s624 || s625;
-  const SWord8 s627 = (s623 >> 1) | (s623 << 7);
-  const SWord8 s628 = 128 | s627;
-  const SWord8 s629 = 127 & s627;
-  const SWord8 s630 = s626 ? s628 : s629;
-  const SWord8 s631 = s585 ? s622 : s630;
-  const SWord8 s632 = s566 ? s610 : s631;
-  const SWord8 s633 = s1 + s589;
-  const SBool  s634 = s633 < s1;
-  const SBool  s635 = s633 < s589;
-  const SBool  s636 = s634 || s635;
-  const SWord8 s637 = (s633 >> 1) | (s633 << 7);
-  const SWord8 s638 = 128 | s637;
-  const SWord8 s639 = 127 & s637;
-  const SWord8 s640 = s636 ? s638 : s639;
-  const SWord8 s641 = (s640 >> 1) | (s640 << 7);
-  const SWord8 s642 = 128 | s641;
-  const SWord8 s643 = 127 & s641;
-  const SWord8 s644 = s565 ? s642 : s643;
-  const SWord8 s645 = (s644 >> 1) | (s644 << 7);
-  const SWord8 s646 = 128 | s645;
-  const SWord8 s647 = 127 & s645;
-  const SWord8 s648 = s584 ? s646 : s647;
-  const SWord8 s649 = s1 + s644;
-  const SBool  s650 = s649 < s1;
-  const SBool  s651 = s649 < s644;
-  const SBool  s652 = s650 || s651;
-  const SWord8 s653 = (s649 >> 1) | (s649 << 7);
-  const SWord8 s654 = 128 | s653;
-  const SWord8 s655 = 127 & s653;
-  const SWord8 s656 = s652 ? s654 : s655;
-  const SWord8 s657 = s585 ? s648 : s656;
-  const SWord8 s658 = s1 + s640;
-  const SBool  s659 = s658 < s1;
-  const SBool  s660 = s658 < s640;
-  const SBool  s661 = s659 || s660;
-  const SWord8 s662 = (s658 >> 1) | (s658 << 7);
-  const SWord8 s663 = 128 | s662;
-  const SWord8 s664 = 127 & s662;
-  const SWord8 s665 = s661 ? s663 : s664;
-  const SWord8 s666 = (s665 >> 1) | (s665 << 7);
-  const SWord8 s667 = 128 | s666;
-  const SWord8 s668 = 127 & s666;
-  const SWord8 s669 = s584 ? s667 : s668;
-  const SWord8 s670 = s1 + s665;
-  const SBool  s671 = s670 < s1;
-  const SBool  s672 = s670 < s665;
-  const SBool  s673 = s671 || s672;
-  const SWord8 s674 = (s670 >> 1) | (s670 << 7);
-  const SWord8 s675 = 128 | s674;
-  const SWord8 s676 = 127 & s674;
-  const SWord8 s677 = s673 ? s675 : s676;
-  const SWord8 s678 = s585 ? s669 : s677;
-  const SWord8 s679 = s566 ? s657 : s678;
-  const SWord8 s680 = s544 ? s632 : s679;
-  const SWord8 s681 = s1 + s570;
-  const SBool  s682 = (SBool) ((s681 >> 0) & 1);
-  const SBool  s683 = false != s682;
-  const SWord8 s684 = s683 ? s574 : s575;
-  const SBool  s685 = (SBool) ((s684 >> 0) & 1);
-  const SBool  s686 = false != s685;
-  const SWord8 s687 = s686 ? s580 : s581;
-  const SBool  s688 = (SBool) ((s687 >> 0) & 1);
-  const SBool  s689 = false != s688;
-  const SBool  s690 = false == s689;
-  const SBool  s691 = s681 < s1;
-  const SBool  s692 = s681 < s570;
-  const SBool  s693 = s691 || s692;
-  const SWord8 s694 = (s681 >> 1) | (s681 << 7);
-  const SWord8 s695 = 128 | s694;
-  const SWord8 s696 = 127 & s694;
-  const SWord8 s697 = s693 ? s695 : s696;
-  const SWord8 s698 = (s697 >> 1) | (s697 << 7);
-  const SWord8 s699 = 128 | s698;
-  const SWord8 s700 = 127 & s698;
-  const SWord8 s701 = s543 ? s699 : s700;
-  const SWord8 s702 = (s701 >> 1) | (s701 << 7);
-  const SWord8 s703 = 128 | s702;
-  const SWord8 s704 = 127 & s702;
-  const SWord8 s705 = s565 ? s703 : s704;
-  const SWord8 s706 = (s705 >> 1) | (s705 << 7);
-  const SWord8 s707 = 128 | s706;
-  const SWord8 s708 = 127 & s706;
-  const SWord8 s709 = s689 ? s707 : s708;
-  const SWord8 s710 = s1 + s705;
-  const SBool  s711 = s710 < s1;
-  const SBool  s712 = s710 < s705;
-  const SBool  s713 = s711 || s712;
-  const SWord8 s714 = (s710 >> 1) | (s710 << 7);
-  const SWord8 s715 = 128 | s714;
-  const SWord8 s716 = 127 & s714;
-  const SWord8 s717 = s713 ? s715 : s716;
-  const SWord8 s718 = s690 ? s709 : s717;
-  const SWord8 s719 = s1 + s701;
-  const SBool  s720 = s719 < s1;
-  const SBool  s721 = s719 < s701;
-  const SBool  s722 = s720 || s721;
-  const SWord8 s723 = (s719 >> 1) | (s719 << 7);
-  const SWord8 s724 = 128 | s723;
-  const SWord8 s725 = 127 & s723;
-  const SWord8 s726 = s722 ? s724 : s725;
-  const SWord8 s727 = (s726 >> 1) | (s726 << 7);
-  const SWord8 s728 = 128 | s727;
-  const SWord8 s729 = 127 & s727;
-  const SWord8 s730 = s689 ? s728 : s729;
-  const SWord8 s731 = s1 + s726;
-  const SBool  s732 = s731 < s1;
-  const SBool  s733 = s731 < s726;
-  const SBool  s734 = s732 || s733;
-  const SWord8 s735 = (s731 >> 1) | (s731 << 7);
-  const SWord8 s736 = 128 | s735;
-  const SWord8 s737 = 127 & s735;
-  const SWord8 s738 = s734 ? s736 : s737;
-  const SWord8 s739 = s690 ? s730 : s738;
-  const SWord8 s740 = s566 ? s718 : s739;
-  const SWord8 s741 = s1 + s697;
-  const SBool  s742 = s741 < s1;
-  const SBool  s743 = s741 < s697;
-  const SBool  s744 = s742 || s743;
-  const SWord8 s745 = (s741 >> 1) | (s741 << 7);
-  const SWord8 s746 = 128 | s745;
-  const SWord8 s747 = 127 & s745;
-  const SWord8 s748 = s744 ? s746 : s747;
-  const SWord8 s749 = (s748 >> 1) | (s748 << 7);
-  const SWord8 s750 = 128 | s749;
-  const SWord8 s751 = 127 & s749;
-  const SWord8 s752 = s565 ? s750 : s751;
-  const SWord8 s753 = (s752 >> 1) | (s752 << 7);
-  const SWord8 s754 = 128 | s753;
-  const SWord8 s755 = 127 & s753;
-  const SWord8 s756 = s689 ? s754 : s755;
-  const SWord8 s757 = s1 + s752;
-  const SBool  s758 = s757 < s1;
-  const SBool  s759 = s757 < s752;
-  const SBool  s760 = s758 || s759;
-  const SWord8 s761 = (s757 >> 1) | (s757 << 7);
-  const SWord8 s762 = 128 | s761;
-  const SWord8 s763 = 127 & s761;
-  const SWord8 s764 = s760 ? s762 : s763;
-  const SWord8 s765 = s690 ? s756 : s764;
-  const SWord8 s766 = s1 + s748;
-  const SBool  s767 = s766 < s1;
-  const SBool  s768 = s766 < s748;
-  const SBool  s769 = s767 || s768;
-  const SWord8 s770 = (s766 >> 1) | (s766 << 7);
-  const SWord8 s771 = 128 | s770;
-  const SWord8 s772 = 127 & s770;
-  const SWord8 s773 = s769 ? s771 : s772;
-  const SWord8 s774 = (s773 >> 1) | (s773 << 7);
-  const SWord8 s775 = 128 | s774;
-  const SWord8 s776 = 127 & s774;
-  const SWord8 s777 = s689 ? s775 : s776;
-  const SWord8 s778 = s1 + s773;
-  const SBool  s779 = s778 < s1;
-  const SBool  s780 = s778 < s773;
-  const SBool  s781 = s779 || s780;
-  const SWord8 s782 = (s778 >> 1) | (s778 << 7);
-  const SWord8 s783 = 128 | s782;
-  const SWord8 s784 = 127 & s782;
-  const SWord8 s785 = s781 ? s783 : s784;
-  const SWord8 s786 = s690 ? s777 : s785;
-  const SWord8 s787 = s566 ? s765 : s786;
-  const SWord8 s788 = s544 ? s740 : s787;
-  const SWord8 s789 = s36 ? s680 : s788;
-  const SWord8 s790 = s1 + s551;
-  const SBool  s791 = (SBool) ((s790 >> 0) & 1);
-  const SBool  s792 = false != s791;
-  const SWord8 s793 = s792 ? s555 : s556;
-  const SBool  s794 = (SBool) ((s793 >> 0) & 1);
-  const SBool  s795 = false != s794;
-  const SWord8 s796 = s795 ? s561 : s562;
-  const SBool  s797 = (SBool) ((s796 >> 0) & 1);
-  const SBool  s798 = false != s797;
-  const SBool  s799 = false == s798;
-  const SBool  s800 = s790 < s1;
-  const SBool  s801 = s790 < s551;
-  const SBool  s802 = s800 || s801;
-  const SWord8 s803 = (s790 >> 1) | (s790 << 7);
-  const SWord8 s804 = 128 | s803;
-  const SWord8 s805 = 127 & s803;
-  const SWord8 s806 = s802 ? s804 : s805;
-  const SBool  s807 = (SBool) ((s806 >> 0) & 1);
-  const SBool  s808 = false != s807;
-  const SWord8 s809 = (s793 >> 1) | (s793 << 7);
-  const SWord8 s810 = 128 | s809;
-  const SWord8 s811 = 127 & s809;
-  const SWord8 s812 = s808 ? s810 : s811;
-  const SBool  s813 = (SBool) ((s812 >> 0) & 1);
-  const SBool  s814 = false != s813;
-  const SWord8 s815 = (s796 >> 1) | (s796 << 7);
-  const SWord8 s816 = 128 | s815;
-  const SWord8 s817 = 127 & s815;
-  const SWord8 s818 = s814 ? s816 : s817;
-  const SBool  s819 = (SBool) ((s818 >> 0) & 1);
-  const SBool  s820 = false != s819;
-  const SBool  s821 = false == s820;
-  const SWord8 s822 = (s806 >> 1) | (s806 << 7);
-  const SWord8 s823 = 128 | s822;
-  const SWord8 s824 = 127 & s822;
-  const SWord8 s825 = s35 ? s823 : s824;
-  const SWord8 s826 = (s825 >> 1) | (s825 << 7);
-  const SWord8 s827 = 128 | s826;
-  const SWord8 s828 = 127 & s826;
-  const SWord8 s829 = s543 ? s827 : s828;
-  const SWord8 s830 = (s829 >> 1) | (s829 << 7);
-  const SWord8 s831 = 128 | s830;
-  const SWord8 s832 = 127 & s830;
-  const SWord8 s833 = s798 ? s831 : s832;
-  const SWord8 s834 = (s833 >> 1) | (s833 << 7);
-  const SWord8 s835 = 128 | s834;
-  const SWord8 s836 = 127 & s834;
-  const SWord8 s837 = s820 ? s835 : s836;
-  const SWord8 s838 = s1 + s833;
-  const SBool  s839 = s838 < s1;
-  const SBool  s840 = s838 < s833;
-  const SBool  s841 = s839 || s840;
-  const SWord8 s842 = (s838 >> 1) | (s838 << 7);
-  const SWord8 s843 = 128 | s842;
-  const SWord8 s844 = 127 & s842;
-  const SWord8 s845 = s841 ? s843 : s844;
-  const SWord8 s846 = s821 ? s837 : s845;
-  const SWord8 s847 = s1 + s829;
-  const SBool  s848 = s847 < s1;
-  const SBool  s849 = s847 < s829;
-  const SBool  s850 = s848 || s849;
-  const SWord8 s851 = (s847 >> 1) | (s847 << 7);
-  const SWord8 s852 = 128 | s851;
-  const SWord8 s853 = 127 & s851;
-  const SWord8 s854 = s850 ? s852 : s853;
-  const SWord8 s855 = (s854 >> 1) | (s854 << 7);
-  const SWord8 s856 = 128 | s855;
-  const SWord8 s857 = 127 & s855;
-  const SWord8 s858 = s820 ? s856 : s857;
-  const SWord8 s859 = s1 + s854;
-  const SBool  s860 = s859 < s1;
-  const SBool  s861 = s859 < s854;
-  const SBool  s862 = s860 || s861;
-  const SWord8 s863 = (s859 >> 1) | (s859 << 7);
-  const SWord8 s864 = 128 | s863;
-  const SWord8 s865 = 127 & s863;
-  const SWord8 s866 = s862 ? s864 : s865;
-  const SWord8 s867 = s821 ? s858 : s866;
-  const SWord8 s868 = s799 ? s846 : s867;
-  const SWord8 s869 = s1 + s825;
-  const SBool  s870 = s869 < s1;
-  const SBool  s871 = s869 < s825;
-  const SBool  s872 = s870 || s871;
-  const SWord8 s873 = (s869 >> 1) | (s869 << 7);
-  const SWord8 s874 = 128 | s873;
-  const SWord8 s875 = 127 & s873;
-  const SWord8 s876 = s872 ? s874 : s875;
-  const SWord8 s877 = (s876 >> 1) | (s876 << 7);
-  const SWord8 s878 = 128 | s877;
-  const SWord8 s879 = 127 & s877;
-  const SWord8 s880 = s798 ? s878 : s879;
-  const SWord8 s881 = (s880 >> 1) | (s880 << 7);
-  const SWord8 s882 = 128 | s881;
-  const SWord8 s883 = 127 & s881;
-  const SWord8 s884 = s820 ? s882 : s883;
-  const SWord8 s885 = s1 + s880;
-  const SBool  s886 = s885 < s1;
-  const SBool  s887 = s885 < s880;
-  const SBool  s888 = s886 || s887;
-  const SWord8 s889 = (s885 >> 1) | (s885 << 7);
-  const SWord8 s890 = 128 | s889;
-  const SWord8 s891 = 127 & s889;
-  const SWord8 s892 = s888 ? s890 : s891;
-  const SWord8 s893 = s821 ? s884 : s892;
-  const SWord8 s894 = s1 + s876;
-  const SBool  s895 = s894 < s1;
-  const SBool  s896 = s894 < s876;
-  const SBool  s897 = s895 || s896;
-  const SWord8 s898 = (s894 >> 1) | (s894 << 7);
-  const SWord8 s899 = 128 | s898;
-  const SWord8 s900 = 127 & s898;
-  const SWord8 s901 = s897 ? s899 : s900;
-  const SWord8 s902 = (s901 >> 1) | (s901 << 7);
-  const SWord8 s903 = 128 | s902;
-  const SWord8 s904 = 127 & s902;
-  const SWord8 s905 = s820 ? s903 : s904;
-  const SWord8 s906 = s1 + s901;
-  const SBool  s907 = s906 < s1;
-  const SBool  s908 = s906 < s901;
-  const SBool  s909 = s907 || s908;
-  const SWord8 s910 = (s906 >> 1) | (s906 << 7);
-  const SWord8 s911 = 128 | s910;
-  const SWord8 s912 = 127 & s910;
-  const SWord8 s913 = s909 ? s911 : s912;
-  const SWord8 s914 = s821 ? s905 : s913;
-  const SWord8 s915 = s799 ? s893 : s914;
-  const SWord8 s916 = s544 ? s868 : s915;
-  const SWord8 s917 = s1 + s806;
-  const SBool  s918 = (SBool) ((s917 >> 0) & 1);
-  const SBool  s919 = false != s918;
-  const SWord8 s920 = s919 ? s810 : s811;
-  const SBool  s921 = (SBool) ((s920 >> 0) & 1);
-  const SBool  s922 = false != s921;
-  const SWord8 s923 = s922 ? s816 : s817;
-  const SBool  s924 = (SBool) ((s923 >> 0) & 1);
-  const SBool  s925 = false != s924;
-  const SBool  s926 = false == s925;
-  const SBool  s927 = s917 < s1;
-  const SBool  s928 = s917 < s806;
-  const SBool  s929 = s927 || s928;
-  const SWord8 s930 = (s917 >> 1) | (s917 << 7);
-  const SWord8 s931 = 128 | s930;
-  const SWord8 s932 = 127 & s930;
-  const SWord8 s933 = s929 ? s931 : s932;
-  const SWord8 s934 = (s933 >> 1) | (s933 << 7);
-  const SWord8 s935 = 128 | s934;
-  const SWord8 s936 = 127 & s934;
-  const SWord8 s937 = s543 ? s935 : s936;
-  const SWord8 s938 = (s937 >> 1) | (s937 << 7);
-  const SWord8 s939 = 128 | s938;
-  const SWord8 s940 = 127 & s938;
-  const SWord8 s941 = s798 ? s939 : s940;
-  const SWord8 s942 = (s941 >> 1) | (s941 << 7);
-  const SWord8 s943 = 128 | s942;
-  const SWord8 s944 = 127 & s942;
-  const SWord8 s945 = s925 ? s943 : s944;
-  const SWord8 s946 = s1 + s941;
-  const SBool  s947 = s946 < s1;
-  const SBool  s948 = s946 < s941;
-  const SBool  s949 = s947 || s948;
-  const SWord8 s950 = (s946 >> 1) | (s946 << 7);
-  const SWord8 s951 = 128 | s950;
-  const SWord8 s952 = 127 & s950;
-  const SWord8 s953 = s949 ? s951 : s952;
-  const SWord8 s954 = s926 ? s945 : s953;
-  const SWord8 s955 = s1 + s937;
-  const SBool  s956 = s955 < s1;
-  const SBool  s957 = s955 < s937;
-  const SBool  s958 = s956 || s957;
-  const SWord8 s959 = (s955 >> 1) | (s955 << 7);
-  const SWord8 s960 = 128 | s959;
-  const SWord8 s961 = 127 & s959;
-  const SWord8 s962 = s958 ? s960 : s961;
-  const SWord8 s963 = (s962 >> 1) | (s962 << 7);
-  const SWord8 s964 = 128 | s963;
-  const SWord8 s965 = 127 & s963;
-  const SWord8 s966 = s925 ? s964 : s965;
-  const SWord8 s967 = s1 + s962;
-  const SBool  s968 = s967 < s1;
-  const SBool  s969 = s967 < s962;
-  const SBool  s970 = s968 || s969;
-  const SWord8 s971 = (s967 >> 1) | (s967 << 7);
-  const SWord8 s972 = 128 | s971;
-  const SWord8 s973 = 127 & s971;
-  const SWord8 s974 = s970 ? s972 : s973;
-  const SWord8 s975 = s926 ? s966 : s974;
-  const SWord8 s976 = s799 ? s954 : s975;
-  const SWord8 s977 = s1 + s933;
-  const SBool  s978 = s977 < s1;
-  const SBool  s979 = s977 < s933;
-  const SBool  s980 = s978 || s979;
-  const SWord8 s981 = (s977 >> 1) | (s977 << 7);
-  const SWord8 s982 = 128 | s981;
-  const SWord8 s983 = 127 & s981;
-  const SWord8 s984 = s980 ? s982 : s983;
-  const SWord8 s985 = (s984 >> 1) | (s984 << 7);
-  const SWord8 s986 = 128 | s985;
-  const SWord8 s987 = 127 & s985;
-  const SWord8 s988 = s798 ? s986 : s987;
-  const SWord8 s989 = (s988 >> 1) | (s988 << 7);
-  const SWord8 s990 = 128 | s989;
-  const SWord8 s991 = 127 & s989;
-  const SWord8 s992 = s925 ? s990 : s991;
-  const SWord8 s993 = s1 + s988;
-  const SBool  s994 = s993 < s1;
-  const SBool  s995 = s993 < s988;
-  const SBool  s996 = s994 || s995;
-  const SWord8 s997 = (s993 >> 1) | (s993 << 7);
-  const SWord8 s998 = 128 | s997;
-  const SWord8 s999 = 127 & s997;
-  const SWord8 s1000 = s996 ? s998 : s999;
-  const SWord8 s1001 = s926 ? s992 : s1000;
-  const SWord8 s1002 = s1 + s984;
-  const SBool  s1003 = s1002 < s1;
-  const SBool  s1004 = s1002 < s984;
-  const SBool  s1005 = s1003 || s1004;
-  const SWord8 s1006 = (s1002 >> 1) | (s1002 << 7);
-  const SWord8 s1007 = 128 | s1006;
-  const SWord8 s1008 = 127 & s1006;
-  const SWord8 s1009 = s1005 ? s1007 : s1008;
-  const SWord8 s1010 = (s1009 >> 1) | (s1009 << 7);
-  const SWord8 s1011 = 128 | s1010;
-  const SWord8 s1012 = 127 & s1010;
-  const SWord8 s1013 = s925 ? s1011 : s1012;
-  const SWord8 s1014 = s1 + s1009;
-  const SBool  s1015 = s1014 < s1;
-  const SBool  s1016 = s1014 < s1009;
-  const SBool  s1017 = s1015 || s1016;
-  const SWord8 s1018 = (s1014 >> 1) | (s1014 << 7);
-  const SWord8 s1019 = 128 | s1018;
-  const SWord8 s1020 = 127 & s1018;
-  const SWord8 s1021 = s1017 ? s1019 : s1020;
-  const SWord8 s1022 = s926 ? s1013 : s1021;
-  const SWord8 s1023 = s799 ? s1001 : s1022;
-  const SWord8 s1024 = s544 ? s976 : s1023;
-  const SWord8 s1025 = s36 ? s916 : s1024;
-  const SWord8 s1026 = s21 ? s789 : s1025;
-  const SWord8 s1027 = s16 ? s534 : s1026;
-  const SWord8 s1028 = s1 + s24;
-  const SBool  s1029 = (SBool) ((s1028 >> 0) & 1);
-  const SBool  s1030 = false != s1029;
-  const SWord8 s1031 = s1030 ? 128 : 0;
-  const SBool  s1032 = (SBool) ((s1031 >> 0) & 1);
-  const SBool  s1033 = false != s1032;
-  const SWord8 s1034 = s1033 ? s31 : s32;
-  const SBool  s1035 = (SBool) ((s1034 >> 0) & 1);
-  const SBool  s1036 = false != s1035;
-  const SBool  s1037 = false == s1036;
-  const SBool  s1038 = s1028 < s1;
-  const SBool  s1039 = s1028 < s24;
-  const SBool  s1040 = s1038 || s1039;
-  const SWord8 s1041 = (s1028 >> 1) | (s1028 << 7);
-  const SWord8 s1042 = 128 | s1041;
-  const SWord8 s1043 = 127 & s1041;
-  const SWord8 s1044 = s1040 ? s1042 : s1043;
-  const SBool  s1045 = (SBool) ((s1044 >> 0) & 1);
-  const SBool  s1046 = false != s1045;
-  const SWord8 s1047 = (s1031 >> 1) | (s1031 << 7);
-  const SWord8 s1048 = 128 | s1047;
-  const SWord8 s1049 = 127 & s1047;
-  const SWord8 s1050 = s1046 ? s1048 : s1049;
-  const SBool  s1051 = (SBool) ((s1050 >> 0) & 1);
-  const SBool  s1052 = false != s1051;
-  const SWord8 s1053 = (s1034 >> 1) | (s1034 << 7);
-  const SWord8 s1054 = 128 | s1053;
-  const SWord8 s1055 = 127 & s1053;
-  const SWord8 s1056 = s1052 ? s1054 : s1055;
-  const SBool  s1057 = (SBool) ((s1056 >> 0) & 1);
-  const SBool  s1058 = false != s1057;
-  const SBool  s1059 = false == s1058;
-  const SWord8 s1060 = (s1044 >> 1) | (s1044 << 7);
-  const SWord8 s1061 = 128 | s1060;
-  const SWord8 s1062 = 127 & s1060;
-  const SWord8 s1063 = s15 ? s1061 : s1062;
-  const SBool  s1064 = (SBool) ((s1063 >> 0) & 1);
-  const SBool  s1065 = false != s1064;
-  const SWord8 s1066 = (s1050 >> 1) | (s1050 << 7);
-  const SWord8 s1067 = 128 | s1066;
-  const SWord8 s1068 = 127 & s1066;
-  const SWord8 s1069 = s1065 ? s1067 : s1068;
-  const SBool  s1070 = (SBool) ((s1069 >> 0) & 1);
-  const SBool  s1071 = false != s1070;
-  const SWord8 s1072 = (s1056 >> 1) | (s1056 << 7);
-  const SWord8 s1073 = 128 | s1072;
-  const SWord8 s1074 = 127 & s1072;
-  const SWord8 s1075 = s1071 ? s1073 : s1074;
-  const SBool  s1076 = (SBool) ((s1075 >> 0) & 1);
-  const SBool  s1077 = false != s1076;
-  const SBool  s1078 = false == s1077;
-  const SWord8 s1079 = (s1063 >> 1) | (s1063 << 7);
-  const SWord8 s1080 = 128 | s1079;
-  const SWord8 s1081 = 127 & s1079;
-  const SWord8 s1082 = s20 ? s1080 : s1081;
-  const SBool  s1083 = (SBool) ((s1082 >> 0) & 1);
-  const SBool  s1084 = false != s1083;
-  const SWord8 s1085 = (s1069 >> 1) | (s1069 << 7);
-  const SWord8 s1086 = 128 | s1085;
-  const SWord8 s1087 = 127 & s1085;
-  const SWord8 s1088 = s1084 ? s1086 : s1087;
-  const SBool  s1089 = (SBool) ((s1088 >> 0) & 1);
-  const SBool  s1090 = false != s1089;
-  const SWord8 s1091 = (s1075 >> 1) | (s1075 << 7);
-  const SWord8 s1092 = 128 | s1091;
-  const SWord8 s1093 = 127 & s1091;
-  const SWord8 s1094 = s1090 ? s1092 : s1093;
-  const SBool  s1095 = (SBool) ((s1094 >> 0) & 1);
-  const SBool  s1096 = false != s1095;
-  const SBool  s1097 = false == s1096;
-  const SWord8 s1098 = (s1082 >> 1) | (s1082 << 7);
-  const SWord8 s1099 = 128 | s1098;
-  const SWord8 s1100 = 127 & s1098;
-  const SWord8 s1101 = s1036 ? s1099 : s1100;
-  const SWord8 s1102 = (s1101 >> 1) | (s1101 << 7);
-  const SWord8 s1103 = 128 | s1102;
-  const SWord8 s1104 = 127 & s1102;
-  const SWord8 s1105 = s1058 ? s1103 : s1104;
-  const SWord8 s1106 = (s1105 >> 1) | (s1105 << 7);
-  const SWord8 s1107 = 128 | s1106;
-  const SWord8 s1108 = 127 & s1106;
-  const SWord8 s1109 = s1077 ? s1107 : s1108;
-  const SWord8 s1110 = (s1109 >> 1) | (s1109 << 7);
-  const SWord8 s1111 = 128 | s1110;
-  const SWord8 s1112 = 127 & s1110;
-  const SWord8 s1113 = s1096 ? s1111 : s1112;
-  const SWord8 s1114 = s1 + s1109;
-  const SBool  s1115 = s1114 < s1;
-  const SBool  s1116 = s1114 < s1109;
-  const SBool  s1117 = s1115 || s1116;
-  const SWord8 s1118 = (s1114 >> 1) | (s1114 << 7);
-  const SWord8 s1119 = 128 | s1118;
-  const SWord8 s1120 = 127 & s1118;
-  const SWord8 s1121 = s1117 ? s1119 : s1120;
-  const SWord8 s1122 = s1097 ? s1113 : s1121;
-  const SWord8 s1123 = s1 + s1105;
-  const SBool  s1124 = s1123 < s1;
-  const SBool  s1125 = s1123 < s1105;
-  const SBool  s1126 = s1124 || s1125;
-  const SWord8 s1127 = (s1123 >> 1) | (s1123 << 7);
-  const SWord8 s1128 = 128 | s1127;
-  const SWord8 s1129 = 127 & s1127;
-  const SWord8 s1130 = s1126 ? s1128 : s1129;
-  const SWord8 s1131 = (s1130 >> 1) | (s1130 << 7);
-  const SWord8 s1132 = 128 | s1131;
-  const SWord8 s1133 = 127 & s1131;
-  const SWord8 s1134 = s1096 ? s1132 : s1133;
-  const SWord8 s1135 = s1 + s1130;
-  const SBool  s1136 = s1135 < s1;
-  const SBool  s1137 = s1135 < s1130;
-  const SBool  s1138 = s1136 || s1137;
-  const SWord8 s1139 = (s1135 >> 1) | (s1135 << 7);
-  const SWord8 s1140 = 128 | s1139;
-  const SWord8 s1141 = 127 & s1139;
-  const SWord8 s1142 = s1138 ? s1140 : s1141;
-  const SWord8 s1143 = s1097 ? s1134 : s1142;
-  const SWord8 s1144 = s1078 ? s1122 : s1143;
-  const SWord8 s1145 = s1 + s1101;
-  const SBool  s1146 = s1145 < s1;
-  const SBool  s1147 = s1145 < s1101;
-  const SBool  s1148 = s1146 || s1147;
-  const SWord8 s1149 = (s1145 >> 1) | (s1145 << 7);
-  const SWord8 s1150 = 128 | s1149;
-  const SWord8 s1151 = 127 & s1149;
-  const SWord8 s1152 = s1148 ? s1150 : s1151;
-  const SWord8 s1153 = (s1152 >> 1) | (s1152 << 7);
-  const SWord8 s1154 = 128 | s1153;
-  const SWord8 s1155 = 127 & s1153;
-  const SWord8 s1156 = s1077 ? s1154 : s1155;
-  const SWord8 s1157 = (s1156 >> 1) | (s1156 << 7);
-  const SWord8 s1158 = 128 | s1157;
-  const SWord8 s1159 = 127 & s1157;
-  const SWord8 s1160 = s1096 ? s1158 : s1159;
-  const SWord8 s1161 = s1 + s1156;
-  const SBool  s1162 = s1161 < s1;
-  const SBool  s1163 = s1161 < s1156;
-  const SBool  s1164 = s1162 || s1163;
-  const SWord8 s1165 = (s1161 >> 1) | (s1161 << 7);
-  const SWord8 s1166 = 128 | s1165;
-  const SWord8 s1167 = 127 & s1165;
-  const SWord8 s1168 = s1164 ? s1166 : s1167;
-  const SWord8 s1169 = s1097 ? s1160 : s1168;
-  const SWord8 s1170 = s1 + s1152;
-  const SBool  s1171 = s1170 < s1;
-  const SBool  s1172 = s1170 < s1152;
-  const SBool  s1173 = s1171 || s1172;
-  const SWord8 s1174 = (s1170 >> 1) | (s1170 << 7);
-  const SWord8 s1175 = 128 | s1174;
-  const SWord8 s1176 = 127 & s1174;
-  const SWord8 s1177 = s1173 ? s1175 : s1176;
-  const SWord8 s1178 = (s1177 >> 1) | (s1177 << 7);
-  const SWord8 s1179 = 128 | s1178;
-  const SWord8 s1180 = 127 & s1178;
-  const SWord8 s1181 = s1096 ? s1179 : s1180;
-  const SWord8 s1182 = s1 + s1177;
-  const SBool  s1183 = s1182 < s1;
-  const SBool  s1184 = s1182 < s1177;
-  const SBool  s1185 = s1183 || s1184;
-  const SWord8 s1186 = (s1182 >> 1) | (s1182 << 7);
-  const SWord8 s1187 = 128 | s1186;
-  const SWord8 s1188 = 127 & s1186;
-  const SWord8 s1189 = s1185 ? s1187 : s1188;
-  const SWord8 s1190 = s1097 ? s1181 : s1189;
-  const SWord8 s1191 = s1078 ? s1169 : s1190;
-  const SWord8 s1192 = s1059 ? s1144 : s1191;
-  const SWord8 s1193 = s1 + s1082;
-  const SBool  s1194 = (SBool) ((s1193 >> 0) & 1);
-  const SBool  s1195 = false != s1194;
-  const SWord8 s1196 = s1195 ? s1086 : s1087;
-  const SBool  s1197 = (SBool) ((s1196 >> 0) & 1);
-  const SBool  s1198 = false != s1197;
-  const SWord8 s1199 = s1198 ? s1092 : s1093;
-  const SBool  s1200 = (SBool) ((s1199 >> 0) & 1);
-  const SBool  s1201 = false != s1200;
-  const SBool  s1202 = false == s1201;
-  const SBool  s1203 = s1193 < s1;
-  const SBool  s1204 = s1193 < s1082;
-  const SBool  s1205 = s1203 || s1204;
-  const SWord8 s1206 = (s1193 >> 1) | (s1193 << 7);
-  const SWord8 s1207 = 128 | s1206;
-  const SWord8 s1208 = 127 & s1206;
-  const SWord8 s1209 = s1205 ? s1207 : s1208;
-  const SWord8 s1210 = (s1209 >> 1) | (s1209 << 7);
-  const SWord8 s1211 = 128 | s1210;
-  const SWord8 s1212 = 127 & s1210;
-  const SWord8 s1213 = s1058 ? s1211 : s1212;
-  const SWord8 s1214 = (s1213 >> 1) | (s1213 << 7);
-  const SWord8 s1215 = 128 | s1214;
-  const SWord8 s1216 = 127 & s1214;
-  const SWord8 s1217 = s1077 ? s1215 : s1216;
-  const SWord8 s1218 = (s1217 >> 1) | (s1217 << 7);
-  const SWord8 s1219 = 128 | s1218;
-  const SWord8 s1220 = 127 & s1218;
-  const SWord8 s1221 = s1201 ? s1219 : s1220;
-  const SWord8 s1222 = s1 + s1217;
-  const SBool  s1223 = s1222 < s1;
-  const SBool  s1224 = s1222 < s1217;
-  const SBool  s1225 = s1223 || s1224;
-  const SWord8 s1226 = (s1222 >> 1) | (s1222 << 7);
-  const SWord8 s1227 = 128 | s1226;
-  const SWord8 s1228 = 127 & s1226;
-  const SWord8 s1229 = s1225 ? s1227 : s1228;
-  const SWord8 s1230 = s1202 ? s1221 : s1229;
-  const SWord8 s1231 = s1 + s1213;
-  const SBool  s1232 = s1231 < s1;
-  const SBool  s1233 = s1231 < s1213;
-  const SBool  s1234 = s1232 || s1233;
-  const SWord8 s1235 = (s1231 >> 1) | (s1231 << 7);
-  const SWord8 s1236 = 128 | s1235;
-  const SWord8 s1237 = 127 & s1235;
-  const SWord8 s1238 = s1234 ? s1236 : s1237;
-  const SWord8 s1239 = (s1238 >> 1) | (s1238 << 7);
-  const SWord8 s1240 = 128 | s1239;
-  const SWord8 s1241 = 127 & s1239;
-  const SWord8 s1242 = s1201 ? s1240 : s1241;
-  const SWord8 s1243 = s1 + s1238;
-  const SBool  s1244 = s1243 < s1;
-  const SBool  s1245 = s1243 < s1238;
-  const SBool  s1246 = s1244 || s1245;
-  const SWord8 s1247 = (s1243 >> 1) | (s1243 << 7);
-  const SWord8 s1248 = 128 | s1247;
-  const SWord8 s1249 = 127 & s1247;
-  const SWord8 s1250 = s1246 ? s1248 : s1249;
-  const SWord8 s1251 = s1202 ? s1242 : s1250;
-  const SWord8 s1252 = s1078 ? s1230 : s1251;
-  const SWord8 s1253 = s1 + s1209;
-  const SBool  s1254 = s1253 < s1;
-  const SBool  s1255 = s1253 < s1209;
-  const SBool  s1256 = s1254 || s1255;
-  const SWord8 s1257 = (s1253 >> 1) | (s1253 << 7);
-  const SWord8 s1258 = 128 | s1257;
-  const SWord8 s1259 = 127 & s1257;
-  const SWord8 s1260 = s1256 ? s1258 : s1259;
-  const SWord8 s1261 = (s1260 >> 1) | (s1260 << 7);
-  const SWord8 s1262 = 128 | s1261;
-  const SWord8 s1263 = 127 & s1261;
-  const SWord8 s1264 = s1077 ? s1262 : s1263;
-  const SWord8 s1265 = (s1264 >> 1) | (s1264 << 7);
-  const SWord8 s1266 = 128 | s1265;
-  const SWord8 s1267 = 127 & s1265;
-  const SWord8 s1268 = s1201 ? s1266 : s1267;
-  const SWord8 s1269 = s1 + s1264;
-  const SBool  s1270 = s1269 < s1;
-  const SBool  s1271 = s1269 < s1264;
-  const SBool  s1272 = s1270 || s1271;
-  const SWord8 s1273 = (s1269 >> 1) | (s1269 << 7);
-  const SWord8 s1274 = 128 | s1273;
-  const SWord8 s1275 = 127 & s1273;
-  const SWord8 s1276 = s1272 ? s1274 : s1275;
-  const SWord8 s1277 = s1202 ? s1268 : s1276;
-  const SWord8 s1278 = s1 + s1260;
-  const SBool  s1279 = s1278 < s1;
-  const SBool  s1280 = s1278 < s1260;
-  const SBool  s1281 = s1279 || s1280;
-  const SWord8 s1282 = (s1278 >> 1) | (s1278 << 7);
-  const SWord8 s1283 = 128 | s1282;
-  const SWord8 s1284 = 127 & s1282;
-  const SWord8 s1285 = s1281 ? s1283 : s1284;
-  const SWord8 s1286 = (s1285 >> 1) | (s1285 << 7);
-  const SWord8 s1287 = 128 | s1286;
-  const SWord8 s1288 = 127 & s1286;
-  const SWord8 s1289 = s1201 ? s1287 : s1288;
-  const SWord8 s1290 = s1 + s1285;
-  const SBool  s1291 = s1290 < s1;
-  const SBool  s1292 = s1290 < s1285;
-  const SBool  s1293 = s1291 || s1292;
-  const SWord8 s1294 = (s1290 >> 1) | (s1290 << 7);
-  const SWord8 s1295 = 128 | s1294;
-  const SWord8 s1296 = 127 & s1294;
-  const SWord8 s1297 = s1293 ? s1295 : s1296;
-  const SWord8 s1298 = s1202 ? s1289 : s1297;
-  const SWord8 s1299 = s1078 ? s1277 : s1298;
-  const SWord8 s1300 = s1059 ? s1252 : s1299;
-  const SWord8 s1301 = s1037 ? s1192 : s1300;
-  const SWord8 s1302 = s1 + s1063;
-  const SBool  s1303 = (SBool) ((s1302 >> 0) & 1);
-  const SBool  s1304 = false != s1303;
-  const SWord8 s1305 = s1304 ? s1067 : s1068;
-  const SBool  s1306 = (SBool) ((s1305 >> 0) & 1);
-  const SBool  s1307 = false != s1306;
-  const SWord8 s1308 = s1307 ? s1073 : s1074;
-  const SBool  s1309 = (SBool) ((s1308 >> 0) & 1);
-  const SBool  s1310 = false != s1309;
-  const SBool  s1311 = false == s1310;
-  const SBool  s1312 = s1302 < s1;
-  const SBool  s1313 = s1302 < s1063;
-  const SBool  s1314 = s1312 || s1313;
-  const SWord8 s1315 = (s1302 >> 1) | (s1302 << 7);
-  const SWord8 s1316 = 128 | s1315;
-  const SWord8 s1317 = 127 & s1315;
-  const SWord8 s1318 = s1314 ? s1316 : s1317;
-  const SBool  s1319 = (SBool) ((s1318 >> 0) & 1);
-  const SBool  s1320 = false != s1319;
-  const SWord8 s1321 = (s1305 >> 1) | (s1305 << 7);
-  const SWord8 s1322 = 128 | s1321;
-  const SWord8 s1323 = 127 & s1321;
-  const SWord8 s1324 = s1320 ? s1322 : s1323;
-  const SBool  s1325 = (SBool) ((s1324 >> 0) & 1);
-  const SBool  s1326 = false != s1325;
-  const SWord8 s1327 = (s1308 >> 1) | (s1308 << 7);
-  const SWord8 s1328 = 128 | s1327;
-  const SWord8 s1329 = 127 & s1327;
-  const SWord8 s1330 = s1326 ? s1328 : s1329;
-  const SBool  s1331 = (SBool) ((s1330 >> 0) & 1);
-  const SBool  s1332 = false != s1331;
-  const SBool  s1333 = false == s1332;
-  const SWord8 s1334 = (s1318 >> 1) | (s1318 << 7);
-  const SWord8 s1335 = 128 | s1334;
-  const SWord8 s1336 = 127 & s1334;
-  const SWord8 s1337 = s1036 ? s1335 : s1336;
-  const SWord8 s1338 = (s1337 >> 1) | (s1337 << 7);
-  const SWord8 s1339 = 128 | s1338;
-  const SWord8 s1340 = 127 & s1338;
-  const SWord8 s1341 = s1058 ? s1339 : s1340;
-  const SWord8 s1342 = (s1341 >> 1) | (s1341 << 7);
-  const SWord8 s1343 = 128 | s1342;
-  const SWord8 s1344 = 127 & s1342;
-  const SWord8 s1345 = s1310 ? s1343 : s1344;
-  const SWord8 s1346 = (s1345 >> 1) | (s1345 << 7);
-  const SWord8 s1347 = 128 | s1346;
-  const SWord8 s1348 = 127 & s1346;
-  const SWord8 s1349 = s1332 ? s1347 : s1348;
-  const SWord8 s1350 = s1 + s1345;
-  const SBool  s1351 = s1350 < s1;
-  const SBool  s1352 = s1350 < s1345;
-  const SBool  s1353 = s1351 || s1352;
-  const SWord8 s1354 = (s1350 >> 1) | (s1350 << 7);
-  const SWord8 s1355 = 128 | s1354;
-  const SWord8 s1356 = 127 & s1354;
-  const SWord8 s1357 = s1353 ? s1355 : s1356;
-  const SWord8 s1358 = s1333 ? s1349 : s1357;
-  const SWord8 s1359 = s1 + s1341;
-  const SBool  s1360 = s1359 < s1;
-  const SBool  s1361 = s1359 < s1341;
-  const SBool  s1362 = s1360 || s1361;
-  const SWord8 s1363 = (s1359 >> 1) | (s1359 << 7);
-  const SWord8 s1364 = 128 | s1363;
-  const SWord8 s1365 = 127 & s1363;
-  const SWord8 s1366 = s1362 ? s1364 : s1365;
-  const SWord8 s1367 = (s1366 >> 1) | (s1366 << 7);
-  const SWord8 s1368 = 128 | s1367;
-  const SWord8 s1369 = 127 & s1367;
-  const SWord8 s1370 = s1332 ? s1368 : s1369;
-  const SWord8 s1371 = s1 + s1366;
-  const SBool  s1372 = s1371 < s1;
-  const SBool  s1373 = s1371 < s1366;
-  const SBool  s1374 = s1372 || s1373;
-  const SWord8 s1375 = (s1371 >> 1) | (s1371 << 7);
-  const SWord8 s1376 = 128 | s1375;
-  const SWord8 s1377 = 127 & s1375;
-  const SWord8 s1378 = s1374 ? s1376 : s1377;
-  const SWord8 s1379 = s1333 ? s1370 : s1378;
-  const SWord8 s1380 = s1311 ? s1358 : s1379;
-  const SWord8 s1381 = s1 + s1337;
-  const SBool  s1382 = s1381 < s1;
-  const SBool  s1383 = s1381 < s1337;
-  const SBool  s1384 = s1382 || s1383;
-  const SWord8 s1385 = (s1381 >> 1) | (s1381 << 7);
-  const SWord8 s1386 = 128 | s1385;
-  const SWord8 s1387 = 127 & s1385;
-  const SWord8 s1388 = s1384 ? s1386 : s1387;
-  const SWord8 s1389 = (s1388 >> 1) | (s1388 << 7);
-  const SWord8 s1390 = 128 | s1389;
-  const SWord8 s1391 = 127 & s1389;
-  const SWord8 s1392 = s1310 ? s1390 : s1391;
-  const SWord8 s1393 = (s1392 >> 1) | (s1392 << 7);
-  const SWord8 s1394 = 128 | s1393;
-  const SWord8 s1395 = 127 & s1393;
-  const SWord8 s1396 = s1332 ? s1394 : s1395;
-  const SWord8 s1397 = s1 + s1392;
-  const SBool  s1398 = s1397 < s1;
-  const SBool  s1399 = s1397 < s1392;
-  const SBool  s1400 = s1398 || s1399;
-  const SWord8 s1401 = (s1397 >> 1) | (s1397 << 7);
-  const SWord8 s1402 = 128 | s1401;
-  const SWord8 s1403 = 127 & s1401;
-  const SWord8 s1404 = s1400 ? s1402 : s1403;
-  const SWord8 s1405 = s1333 ? s1396 : s1404;
-  const SWord8 s1406 = s1 + s1388;
-  const SBool  s1407 = s1406 < s1;
-  const SBool  s1408 = s1406 < s1388;
-  const SBool  s1409 = s1407 || s1408;
-  const SWord8 s1410 = (s1406 >> 1) | (s1406 << 7);
-  const SWord8 s1411 = 128 | s1410;
-  const SWord8 s1412 = 127 & s1410;
-  const SWord8 s1413 = s1409 ? s1411 : s1412;
-  const SWord8 s1414 = (s1413 >> 1) | (s1413 << 7);
-  const SWord8 s1415 = 128 | s1414;
-  const SWord8 s1416 = 127 & s1414;
-  const SWord8 s1417 = s1332 ? s1415 : s1416;
-  const SWord8 s1418 = s1 + s1413;
-  const SBool  s1419 = s1418 < s1;
-  const SBool  s1420 = s1418 < s1413;
-  const SBool  s1421 = s1419 || s1420;
-  const SWord8 s1422 = (s1418 >> 1) | (s1418 << 7);
-  const SWord8 s1423 = 128 | s1422;
-  const SWord8 s1424 = 127 & s1422;
-  const SWord8 s1425 = s1421 ? s1423 : s1424;
-  const SWord8 s1426 = s1333 ? s1417 : s1425;
-  const SWord8 s1427 = s1311 ? s1405 : s1426;
-  const SWord8 s1428 = s1059 ? s1380 : s1427;
-  const SWord8 s1429 = s1 + s1318;
-  const SBool  s1430 = (SBool) ((s1429 >> 0) & 1);
-  const SBool  s1431 = false != s1430;
-  const SWord8 s1432 = s1431 ? s1322 : s1323;
-  const SBool  s1433 = (SBool) ((s1432 >> 0) & 1);
-  const SBool  s1434 = false != s1433;
-  const SWord8 s1435 = s1434 ? s1328 : s1329;
-  const SBool  s1436 = (SBool) ((s1435 >> 0) & 1);
-  const SBool  s1437 = false != s1436;
-  const SBool  s1438 = false == s1437;
-  const SBool  s1439 = s1429 < s1;
-  const SBool  s1440 = s1429 < s1318;
-  const SBool  s1441 = s1439 || s1440;
-  const SWord8 s1442 = (s1429 >> 1) | (s1429 << 7);
-  const SWord8 s1443 = 128 | s1442;
-  const SWord8 s1444 = 127 & s1442;
-  const SWord8 s1445 = s1441 ? s1443 : s1444;
-  const SWord8 s1446 = (s1445 >> 1) | (s1445 << 7);
-  const SWord8 s1447 = 128 | s1446;
-  const SWord8 s1448 = 127 & s1446;
-  const SWord8 s1449 = s1058 ? s1447 : s1448;
-  const SWord8 s1450 = (s1449 >> 1) | (s1449 << 7);
-  const SWord8 s1451 = 128 | s1450;
-  const SWord8 s1452 = 127 & s1450;
-  const SWord8 s1453 = s1310 ? s1451 : s1452;
-  const SWord8 s1454 = (s1453 >> 1) | (s1453 << 7);
-  const SWord8 s1455 = 128 | s1454;
-  const SWord8 s1456 = 127 & s1454;
-  const SWord8 s1457 = s1437 ? s1455 : s1456;
-  const SWord8 s1458 = s1 + s1453;
-  const SBool  s1459 = s1458 < s1;
-  const SBool  s1460 = s1458 < s1453;
-  const SBool  s1461 = s1459 || s1460;
-  const SWord8 s1462 = (s1458 >> 1) | (s1458 << 7);
-  const SWord8 s1463 = 128 | s1462;
-  const SWord8 s1464 = 127 & s1462;
-  const SWord8 s1465 = s1461 ? s1463 : s1464;
-  const SWord8 s1466 = s1438 ? s1457 : s1465;
-  const SWord8 s1467 = s1 + s1449;
-  const SBool  s1468 = s1467 < s1;
-  const SBool  s1469 = s1467 < s1449;
-  const SBool  s1470 = s1468 || s1469;
-  const SWord8 s1471 = (s1467 >> 1) | (s1467 << 7);
-  const SWord8 s1472 = 128 | s1471;
-  const SWord8 s1473 = 127 & s1471;
-  const SWord8 s1474 = s1470 ? s1472 : s1473;
-  const SWord8 s1475 = (s1474 >> 1) | (s1474 << 7);
-  const SWord8 s1476 = 128 | s1475;
-  const SWord8 s1477 = 127 & s1475;
-  const SWord8 s1478 = s1437 ? s1476 : s1477;
-  const SWord8 s1479 = s1 + s1474;
-  const SBool  s1480 = s1479 < s1;
-  const SBool  s1481 = s1479 < s1474;
-  const SBool  s1482 = s1480 || s1481;
-  const SWord8 s1483 = (s1479 >> 1) | (s1479 << 7);
-  const SWord8 s1484 = 128 | s1483;
-  const SWord8 s1485 = 127 & s1483;
-  const SWord8 s1486 = s1482 ? s1484 : s1485;
-  const SWord8 s1487 = s1438 ? s1478 : s1486;
-  const SWord8 s1488 = s1311 ? s1466 : s1487;
-  const SWord8 s1489 = s1 + s1445;
-  const SBool  s1490 = s1489 < s1;
-  const SBool  s1491 = s1489 < s1445;
-  const SBool  s1492 = s1490 || s1491;
-  const SWord8 s1493 = (s1489 >> 1) | (s1489 << 7);
-  const SWord8 s1494 = 128 | s1493;
-  const SWord8 s1495 = 127 & s1493;
-  const SWord8 s1496 = s1492 ? s1494 : s1495;
-  const SWord8 s1497 = (s1496 >> 1) | (s1496 << 7);
-  const SWord8 s1498 = 128 | s1497;
-  const SWord8 s1499 = 127 & s1497;
-  const SWord8 s1500 = s1310 ? s1498 : s1499;
-  const SWord8 s1501 = (s1500 >> 1) | (s1500 << 7);
-  const SWord8 s1502 = 128 | s1501;
-  const SWord8 s1503 = 127 & s1501;
-  const SWord8 s1504 = s1437 ? s1502 : s1503;
-  const SWord8 s1505 = s1 + s1500;
-  const SBool  s1506 = s1505 < s1;
-  const SBool  s1507 = s1505 < s1500;
-  const SBool  s1508 = s1506 || s1507;
-  const SWord8 s1509 = (s1505 >> 1) | (s1505 << 7);
-  const SWord8 s1510 = 128 | s1509;
-  const SWord8 s1511 = 127 & s1509;
-  const SWord8 s1512 = s1508 ? s1510 : s1511;
-  const SWord8 s1513 = s1438 ? s1504 : s1512;
-  const SWord8 s1514 = s1 + s1496;
-  const SBool  s1515 = s1514 < s1;
-  const SBool  s1516 = s1514 < s1496;
-  const SBool  s1517 = s1515 || s1516;
-  const SWord8 s1518 = (s1514 >> 1) | (s1514 << 7);
-  const SWord8 s1519 = 128 | s1518;
-  const SWord8 s1520 = 127 & s1518;
-  const SWord8 s1521 = s1517 ? s1519 : s1520;
-  const SWord8 s1522 = (s1521 >> 1) | (s1521 << 7);
-  const SWord8 s1523 = 128 | s1522;
-  const SWord8 s1524 = 127 & s1522;
-  const SWord8 s1525 = s1437 ? s1523 : s1524;
-  const SWord8 s1526 = s1 + s1521;
-  const SBool  s1527 = s1526 < s1;
-  const SBool  s1528 = s1526 < s1521;
-  const SBool  s1529 = s1527 || s1528;
-  const SWord8 s1530 = (s1526 >> 1) | (s1526 << 7);
-  const SWord8 s1531 = 128 | s1530;
-  const SWord8 s1532 = 127 & s1530;
-  const SWord8 s1533 = s1529 ? s1531 : s1532;
-  const SWord8 s1534 = s1438 ? s1525 : s1533;
-  const SWord8 s1535 = s1311 ? s1513 : s1534;
-  const SWord8 s1536 = s1059 ? s1488 : s1535;
-  const SWord8 s1537 = s1037 ? s1428 : s1536;
-  const SWord8 s1538 = s21 ? s1301 : s1537;
-  const SWord8 s1539 = s1 + s1044;
-  const SBool  s1540 = (SBool) ((s1539 >> 0) & 1);
-  const SBool  s1541 = false != s1540;
-  const SWord8 s1542 = s1541 ? s1048 : s1049;
-  const SBool  s1543 = (SBool) ((s1542 >> 0) & 1);
-  const SBool  s1544 = false != s1543;
-  const SWord8 s1545 = s1544 ? s1054 : s1055;
-  const SBool  s1546 = (SBool) ((s1545 >> 0) & 1);
-  const SBool  s1547 = false != s1546;
-  const SBool  s1548 = false == s1547;
-  const SBool  s1549 = s1539 < s1;
-  const SBool  s1550 = s1539 < s1044;
-  const SBool  s1551 = s1549 || s1550;
-  const SWord8 s1552 = (s1539 >> 1) | (s1539 << 7);
-  const SWord8 s1553 = 128 | s1552;
-  const SWord8 s1554 = 127 & s1552;
-  const SWord8 s1555 = s1551 ? s1553 : s1554;
-  const SBool  s1556 = (SBool) ((s1555 >> 0) & 1);
-  const SBool  s1557 = false != s1556;
-  const SWord8 s1558 = (s1542 >> 1) | (s1542 << 7);
-  const SWord8 s1559 = 128 | s1558;
-  const SWord8 s1560 = 127 & s1558;
-  const SWord8 s1561 = s1557 ? s1559 : s1560;
-  const SBool  s1562 = (SBool) ((s1561 >> 0) & 1);
-  const SBool  s1563 = false != s1562;
-  const SWord8 s1564 = (s1545 >> 1) | (s1545 << 7);
-  const SWord8 s1565 = 128 | s1564;
-  const SWord8 s1566 = 127 & s1564;
-  const SWord8 s1567 = s1563 ? s1565 : s1566;
-  const SBool  s1568 = (SBool) ((s1567 >> 0) & 1);
-  const SBool  s1569 = false != s1568;
-  const SBool  s1570 = false == s1569;
-  const SWord8 s1571 = (s1555 >> 1) | (s1555 << 7);
-  const SWord8 s1572 = 128 | s1571;
-  const SWord8 s1573 = 127 & s1571;
-  const SWord8 s1574 = s20 ? s1572 : s1573;
-  const SBool  s1575 = (SBool) ((s1574 >> 0) & 1);
-  const SBool  s1576 = false != s1575;
-  const SWord8 s1577 = (s1561 >> 1) | (s1561 << 7);
-  const SWord8 s1578 = 128 | s1577;
-  const SWord8 s1579 = 127 & s1577;
-  const SWord8 s1580 = s1576 ? s1578 : s1579;
-  const SBool  s1581 = (SBool) ((s1580 >> 0) & 1);
-  const SBool  s1582 = false != s1581;
-  const SWord8 s1583 = (s1567 >> 1) | (s1567 << 7);
-  const SWord8 s1584 = 128 | s1583;
-  const SWord8 s1585 = 127 & s1583;
-  const SWord8 s1586 = s1582 ? s1584 : s1585;
-  const SBool  s1587 = (SBool) ((s1586 >> 0) & 1);
-  const SBool  s1588 = false != s1587;
-  const SBool  s1589 = false == s1588;
-  const SWord8 s1590 = (s1574 >> 1) | (s1574 << 7);
-  const SWord8 s1591 = 128 | s1590;
-  const SWord8 s1592 = 127 & s1590;
-  const SWord8 s1593 = s1036 ? s1591 : s1592;
-  const SWord8 s1594 = (s1593 >> 1) | (s1593 << 7);
-  const SWord8 s1595 = 128 | s1594;
-  const SWord8 s1596 = 127 & s1594;
-  const SWord8 s1597 = s1547 ? s1595 : s1596;
-  const SWord8 s1598 = (s1597 >> 1) | (s1597 << 7);
-  const SWord8 s1599 = 128 | s1598;
-  const SWord8 s1600 = 127 & s1598;
-  const SWord8 s1601 = s1569 ? s1599 : s1600;
-  const SWord8 s1602 = (s1601 >> 1) | (s1601 << 7);
-  const SWord8 s1603 = 128 | s1602;
-  const SWord8 s1604 = 127 & s1602;
-  const SWord8 s1605 = s1588 ? s1603 : s1604;
-  const SWord8 s1606 = s1 + s1601;
-  const SBool  s1607 = s1606 < s1;
-  const SBool  s1608 = s1606 < s1601;
-  const SBool  s1609 = s1607 || s1608;
-  const SWord8 s1610 = (s1606 >> 1) | (s1606 << 7);
-  const SWord8 s1611 = 128 | s1610;
-  const SWord8 s1612 = 127 & s1610;
-  const SWord8 s1613 = s1609 ? s1611 : s1612;
-  const SWord8 s1614 = s1589 ? s1605 : s1613;
-  const SWord8 s1615 = s1 + s1597;
-  const SBool  s1616 = s1615 < s1;
-  const SBool  s1617 = s1615 < s1597;
-  const SBool  s1618 = s1616 || s1617;
-  const SWord8 s1619 = (s1615 >> 1) | (s1615 << 7);
-  const SWord8 s1620 = 128 | s1619;
-  const SWord8 s1621 = 127 & s1619;
-  const SWord8 s1622 = s1618 ? s1620 : s1621;
-  const SWord8 s1623 = (s1622 >> 1) | (s1622 << 7);
-  const SWord8 s1624 = 128 | s1623;
-  const SWord8 s1625 = 127 & s1623;
-  const SWord8 s1626 = s1588 ? s1624 : s1625;
-  const SWord8 s1627 = s1 + s1622;
-  const SBool  s1628 = s1627 < s1;
-  const SBool  s1629 = s1627 < s1622;
-  const SBool  s1630 = s1628 || s1629;
-  const SWord8 s1631 = (s1627 >> 1) | (s1627 << 7);
-  const SWord8 s1632 = 128 | s1631;
-  const SWord8 s1633 = 127 & s1631;
-  const SWord8 s1634 = s1630 ? s1632 : s1633;
-  const SWord8 s1635 = s1589 ? s1626 : s1634;
-  const SWord8 s1636 = s1570 ? s1614 : s1635;
-  const SWord8 s1637 = s1 + s1593;
-  const SBool  s1638 = s1637 < s1;
-  const SBool  s1639 = s1637 < s1593;
-  const SBool  s1640 = s1638 || s1639;
-  const SWord8 s1641 = (s1637 >> 1) | (s1637 << 7);
-  const SWord8 s1642 = 128 | s1641;
-  const SWord8 s1643 = 127 & s1641;
-  const SWord8 s1644 = s1640 ? s1642 : s1643;
-  const SWord8 s1645 = (s1644 >> 1) | (s1644 << 7);
-  const SWord8 s1646 = 128 | s1645;
-  const SWord8 s1647 = 127 & s1645;
-  const SWord8 s1648 = s1569 ? s1646 : s1647;
-  const SWord8 s1649 = (s1648 >> 1) | (s1648 << 7);
-  const SWord8 s1650 = 128 | s1649;
-  const SWord8 s1651 = 127 & s1649;
-  const SWord8 s1652 = s1588 ? s1650 : s1651;
-  const SWord8 s1653 = s1 + s1648;
-  const SBool  s1654 = s1653 < s1;
-  const SBool  s1655 = s1653 < s1648;
-  const SBool  s1656 = s1654 || s1655;
-  const SWord8 s1657 = (s1653 >> 1) | (s1653 << 7);
-  const SWord8 s1658 = 128 | s1657;
-  const SWord8 s1659 = 127 & s1657;
-  const SWord8 s1660 = s1656 ? s1658 : s1659;
-  const SWord8 s1661 = s1589 ? s1652 : s1660;
-  const SWord8 s1662 = s1 + s1644;
-  const SBool  s1663 = s1662 < s1;
-  const SBool  s1664 = s1662 < s1644;
-  const SBool  s1665 = s1663 || s1664;
-  const SWord8 s1666 = (s1662 >> 1) | (s1662 << 7);
-  const SWord8 s1667 = 128 | s1666;
-  const SWord8 s1668 = 127 & s1666;
-  const SWord8 s1669 = s1665 ? s1667 : s1668;
-  const SWord8 s1670 = (s1669 >> 1) | (s1669 << 7);
-  const SWord8 s1671 = 128 | s1670;
-  const SWord8 s1672 = 127 & s1670;
-  const SWord8 s1673 = s1588 ? s1671 : s1672;
-  const SWord8 s1674 = s1 + s1669;
-  const SBool  s1675 = s1674 < s1;
-  const SBool  s1676 = s1674 < s1669;
-  const SBool  s1677 = s1675 || s1676;
-  const SWord8 s1678 = (s1674 >> 1) | (s1674 << 7);
-  const SWord8 s1679 = 128 | s1678;
-  const SWord8 s1680 = 127 & s1678;
-  const SWord8 s1681 = s1677 ? s1679 : s1680;
-  const SWord8 s1682 = s1589 ? s1673 : s1681;
-  const SWord8 s1683 = s1570 ? s1661 : s1682;
-  const SWord8 s1684 = s1548 ? s1636 : s1683;
-  const SWord8 s1685 = s1 + s1574;
-  const SBool  s1686 = (SBool) ((s1685 >> 0) & 1);
-  const SBool  s1687 = false != s1686;
-  const SWord8 s1688 = s1687 ? s1578 : s1579;
-  const SBool  s1689 = (SBool) ((s1688 >> 0) & 1);
-  const SBool  s1690 = false != s1689;
-  const SWord8 s1691 = s1690 ? s1584 : s1585;
-  const SBool  s1692 = (SBool) ((s1691 >> 0) & 1);
-  const SBool  s1693 = false != s1692;
-  const SBool  s1694 = false == s1693;
-  const SBool  s1695 = s1685 < s1;
-  const SBool  s1696 = s1685 < s1574;
-  const SBool  s1697 = s1695 || s1696;
-  const SWord8 s1698 = (s1685 >> 1) | (s1685 << 7);
-  const SWord8 s1699 = 128 | s1698;
-  const SWord8 s1700 = 127 & s1698;
-  const SWord8 s1701 = s1697 ? s1699 : s1700;
-  const SWord8 s1702 = (s1701 >> 1) | (s1701 << 7);
-  const SWord8 s1703 = 128 | s1702;
-  const SWord8 s1704 = 127 & s1702;
-  const SWord8 s1705 = s1547 ? s1703 : s1704;
-  const SWord8 s1706 = (s1705 >> 1) | (s1705 << 7);
-  const SWord8 s1707 = 128 | s1706;
-  const SWord8 s1708 = 127 & s1706;
-  const SWord8 s1709 = s1569 ? s1707 : s1708;
-  const SWord8 s1710 = (s1709 >> 1) | (s1709 << 7);
-  const SWord8 s1711 = 128 | s1710;
-  const SWord8 s1712 = 127 & s1710;
-  const SWord8 s1713 = s1693 ? s1711 : s1712;
-  const SWord8 s1714 = s1 + s1709;
-  const SBool  s1715 = s1714 < s1;
-  const SBool  s1716 = s1714 < s1709;
-  const SBool  s1717 = s1715 || s1716;
-  const SWord8 s1718 = (s1714 >> 1) | (s1714 << 7);
-  const SWord8 s1719 = 128 | s1718;
-  const SWord8 s1720 = 127 & s1718;
-  const SWord8 s1721 = s1717 ? s1719 : s1720;
-  const SWord8 s1722 = s1694 ? s1713 : s1721;
-  const SWord8 s1723 = s1 + s1705;
-  const SBool  s1724 = s1723 < s1;
-  const SBool  s1725 = s1723 < s1705;
-  const SBool  s1726 = s1724 || s1725;
-  const SWord8 s1727 = (s1723 >> 1) | (s1723 << 7);
-  const SWord8 s1728 = 128 | s1727;
-  const SWord8 s1729 = 127 & s1727;
-  const SWord8 s1730 = s1726 ? s1728 : s1729;
-  const SWord8 s1731 = (s1730 >> 1) | (s1730 << 7);
-  const SWord8 s1732 = 128 | s1731;
-  const SWord8 s1733 = 127 & s1731;
-  const SWord8 s1734 = s1693 ? s1732 : s1733;
-  const SWord8 s1735 = s1 + s1730;
-  const SBool  s1736 = s1735 < s1;
-  const SBool  s1737 = s1735 < s1730;
-  const SBool  s1738 = s1736 || s1737;
-  const SWord8 s1739 = (s1735 >> 1) | (s1735 << 7);
-  const SWord8 s1740 = 128 | s1739;
-  const SWord8 s1741 = 127 & s1739;
-  const SWord8 s1742 = s1738 ? s1740 : s1741;
-  const SWord8 s1743 = s1694 ? s1734 : s1742;
-  const SWord8 s1744 = s1570 ? s1722 : s1743;
-  const SWord8 s1745 = s1 + s1701;
-  const SBool  s1746 = s1745 < s1;
-  const SBool  s1747 = s1745 < s1701;
-  const SBool  s1748 = s1746 || s1747;
-  const SWord8 s1749 = (s1745 >> 1) | (s1745 << 7);
-  const SWord8 s1750 = 128 | s1749;
-  const SWord8 s1751 = 127 & s1749;
-  const SWord8 s1752 = s1748 ? s1750 : s1751;
-  const SWord8 s1753 = (s1752 >> 1) | (s1752 << 7);
-  const SWord8 s1754 = 128 | s1753;
-  const SWord8 s1755 = 127 & s1753;
-  const SWord8 s1756 = s1569 ? s1754 : s1755;
-  const SWord8 s1757 = (s1756 >> 1) | (s1756 << 7);
-  const SWord8 s1758 = 128 | s1757;
-  const SWord8 s1759 = 127 & s1757;
-  const SWord8 s1760 = s1693 ? s1758 : s1759;
-  const SWord8 s1761 = s1 + s1756;
-  const SBool  s1762 = s1761 < s1;
-  const SBool  s1763 = s1761 < s1756;
-  const SBool  s1764 = s1762 || s1763;
-  const SWord8 s1765 = (s1761 >> 1) | (s1761 << 7);
-  const SWord8 s1766 = 128 | s1765;
-  const SWord8 s1767 = 127 & s1765;
-  const SWord8 s1768 = s1764 ? s1766 : s1767;
-  const SWord8 s1769 = s1694 ? s1760 : s1768;
-  const SWord8 s1770 = s1 + s1752;
-  const SBool  s1771 = s1770 < s1;
-  const SBool  s1772 = s1770 < s1752;
-  const SBool  s1773 = s1771 || s1772;
-  const SWord8 s1774 = (s1770 >> 1) | (s1770 << 7);
-  const SWord8 s1775 = 128 | s1774;
-  const SWord8 s1776 = 127 & s1774;
-  const SWord8 s1777 = s1773 ? s1775 : s1776;
-  const SWord8 s1778 = (s1777 >> 1) | (s1777 << 7);
-  const SWord8 s1779 = 128 | s1778;
-  const SWord8 s1780 = 127 & s1778;
-  const SWord8 s1781 = s1693 ? s1779 : s1780;
-  const SWord8 s1782 = s1 + s1777;
-  const SBool  s1783 = s1782 < s1;
-  const SBool  s1784 = s1782 < s1777;
-  const SBool  s1785 = s1783 || s1784;
-  const SWord8 s1786 = (s1782 >> 1) | (s1782 << 7);
-  const SWord8 s1787 = 128 | s1786;
-  const SWord8 s1788 = 127 & s1786;
-  const SWord8 s1789 = s1785 ? s1787 : s1788;
-  const SWord8 s1790 = s1694 ? s1781 : s1789;
-  const SWord8 s1791 = s1570 ? s1769 : s1790;
-  const SWord8 s1792 = s1548 ? s1744 : s1791;
-  const SWord8 s1793 = s1037 ? s1684 : s1792;
-  const SWord8 s1794 = s1 + s1555;
-  const SBool  s1795 = (SBool) ((s1794 >> 0) & 1);
-  const SBool  s1796 = false != s1795;
-  const SWord8 s1797 = s1796 ? s1559 : s1560;
-  const SBool  s1798 = (SBool) ((s1797 >> 0) & 1);
-  const SBool  s1799 = false != s1798;
-  const SWord8 s1800 = s1799 ? s1565 : s1566;
-  const SBool  s1801 = (SBool) ((s1800 >> 0) & 1);
-  const SBool  s1802 = false != s1801;
-  const SBool  s1803 = false == s1802;
-  const SBool  s1804 = s1794 < s1;
-  const SBool  s1805 = s1794 < s1555;
-  const SBool  s1806 = s1804 || s1805;
-  const SWord8 s1807 = (s1794 >> 1) | (s1794 << 7);
-  const SWord8 s1808 = 128 | s1807;
-  const SWord8 s1809 = 127 & s1807;
-  const SWord8 s1810 = s1806 ? s1808 : s1809;
-  const SBool  s1811 = (SBool) ((s1810 >> 0) & 1);
-  const SBool  s1812 = false != s1811;
-  const SWord8 s1813 = (s1797 >> 1) | (s1797 << 7);
-  const SWord8 s1814 = 128 | s1813;
-  const SWord8 s1815 = 127 & s1813;
-  const SWord8 s1816 = s1812 ? s1814 : s1815;
-  const SBool  s1817 = (SBool) ((s1816 >> 0) & 1);
-  const SBool  s1818 = false != s1817;
-  const SWord8 s1819 = (s1800 >> 1) | (s1800 << 7);
-  const SWord8 s1820 = 128 | s1819;
-  const SWord8 s1821 = 127 & s1819;
-  const SWord8 s1822 = s1818 ? s1820 : s1821;
-  const SBool  s1823 = (SBool) ((s1822 >> 0) & 1);
-  const SBool  s1824 = false != s1823;
-  const SBool  s1825 = false == s1824;
-  const SWord8 s1826 = (s1810 >> 1) | (s1810 << 7);
-  const SWord8 s1827 = 128 | s1826;
-  const SWord8 s1828 = 127 & s1826;
-  const SWord8 s1829 = s1036 ? s1827 : s1828;
-  const SWord8 s1830 = (s1829 >> 1) | (s1829 << 7);
-  const SWord8 s1831 = 128 | s1830;
-  const SWord8 s1832 = 127 & s1830;
-  const SWord8 s1833 = s1547 ? s1831 : s1832;
-  const SWord8 s1834 = (s1833 >> 1) | (s1833 << 7);
-  const SWord8 s1835 = 128 | s1834;
-  const SWord8 s1836 = 127 & s1834;
-  const SWord8 s1837 = s1802 ? s1835 : s1836;
-  const SWord8 s1838 = (s1837 >> 1) | (s1837 << 7);
-  const SWord8 s1839 = 128 | s1838;
-  const SWord8 s1840 = 127 & s1838;
-  const SWord8 s1841 = s1824 ? s1839 : s1840;
-  const SWord8 s1842 = s1 + s1837;
-  const SBool  s1843 = s1842 < s1;
-  const SBool  s1844 = s1842 < s1837;
-  const SBool  s1845 = s1843 || s1844;
-  const SWord8 s1846 = (s1842 >> 1) | (s1842 << 7);
-  const SWord8 s1847 = 128 | s1846;
-  const SWord8 s1848 = 127 & s1846;
-  const SWord8 s1849 = s1845 ? s1847 : s1848;
-  const SWord8 s1850 = s1825 ? s1841 : s1849;
-  const SWord8 s1851 = s1 + s1833;
-  const SBool  s1852 = s1851 < s1;
-  const SBool  s1853 = s1851 < s1833;
-  const SBool  s1854 = s1852 || s1853;
-  const SWord8 s1855 = (s1851 >> 1) | (s1851 << 7);
-  const SWord8 s1856 = 128 | s1855;
-  const SWord8 s1857 = 127 & s1855;
-  const SWord8 s1858 = s1854 ? s1856 : s1857;
-  const SWord8 s1859 = (s1858 >> 1) | (s1858 << 7);
-  const SWord8 s1860 = 128 | s1859;
-  const SWord8 s1861 = 127 & s1859;
-  const SWord8 s1862 = s1824 ? s1860 : s1861;
-  const SWord8 s1863 = s1 + s1858;
-  const SBool  s1864 = s1863 < s1;
-  const SBool  s1865 = s1863 < s1858;
-  const SBool  s1866 = s1864 || s1865;
-  const SWord8 s1867 = (s1863 >> 1) | (s1863 << 7);
-  const SWord8 s1868 = 128 | s1867;
-  const SWord8 s1869 = 127 & s1867;
-  const SWord8 s1870 = s1866 ? s1868 : s1869;
-  const SWord8 s1871 = s1825 ? s1862 : s1870;
-  const SWord8 s1872 = s1803 ? s1850 : s1871;
-  const SWord8 s1873 = s1 + s1829;
-  const SBool  s1874 = s1873 < s1;
-  const SBool  s1875 = s1873 < s1829;
-  const SBool  s1876 = s1874 || s1875;
-  const SWord8 s1877 = (s1873 >> 1) | (s1873 << 7);
-  const SWord8 s1878 = 128 | s1877;
-  const SWord8 s1879 = 127 & s1877;
-  const SWord8 s1880 = s1876 ? s1878 : s1879;
-  const SWord8 s1881 = (s1880 >> 1) | (s1880 << 7);
-  const SWord8 s1882 = 128 | s1881;
-  const SWord8 s1883 = 127 & s1881;
-  const SWord8 s1884 = s1802 ? s1882 : s1883;
-  const SWord8 s1885 = (s1884 >> 1) | (s1884 << 7);
-  const SWord8 s1886 = 128 | s1885;
-  const SWord8 s1887 = 127 & s1885;
-  const SWord8 s1888 = s1824 ? s1886 : s1887;
-  const SWord8 s1889 = s1 + s1884;
-  const SBool  s1890 = s1889 < s1;
-  const SBool  s1891 = s1889 < s1884;
-  const SBool  s1892 = s1890 || s1891;
-  const SWord8 s1893 = (s1889 >> 1) | (s1889 << 7);
-  const SWord8 s1894 = 128 | s1893;
-  const SWord8 s1895 = 127 & s1893;
-  const SWord8 s1896 = s1892 ? s1894 : s1895;
-  const SWord8 s1897 = s1825 ? s1888 : s1896;
-  const SWord8 s1898 = s1 + s1880;
-  const SBool  s1899 = s1898 < s1;
-  const SBool  s1900 = s1898 < s1880;
-  const SBool  s1901 = s1899 || s1900;
-  const SWord8 s1902 = (s1898 >> 1) | (s1898 << 7);
-  const SWord8 s1903 = 128 | s1902;
-  const SWord8 s1904 = 127 & s1902;
-  const SWord8 s1905 = s1901 ? s1903 : s1904;
-  const SWord8 s1906 = (s1905 >> 1) | (s1905 << 7);
-  const SWord8 s1907 = 128 | s1906;
-  const SWord8 s1908 = 127 & s1906;
-  const SWord8 s1909 = s1824 ? s1907 : s1908;
-  const SWord8 s1910 = s1 + s1905;
-  const SBool  s1911 = s1910 < s1;
-  const SBool  s1912 = s1910 < s1905;
-  const SBool  s1913 = s1911 || s1912;
-  const SWord8 s1914 = (s1910 >> 1) | (s1910 << 7);
-  const SWord8 s1915 = 128 | s1914;
-  const SWord8 s1916 = 127 & s1914;
-  const SWord8 s1917 = s1913 ? s1915 : s1916;
-  const SWord8 s1918 = s1825 ? s1909 : s1917;
-  const SWord8 s1919 = s1803 ? s1897 : s1918;
-  const SWord8 s1920 = s1548 ? s1872 : s1919;
-  const SWord8 s1921 = s1 + s1810;
-  const SBool  s1922 = (SBool) ((s1921 >> 0) & 1);
-  const SBool  s1923 = false != s1922;
-  const SWord8 s1924 = s1923 ? s1814 : s1815;
-  const SBool  s1925 = (SBool) ((s1924 >> 0) & 1);
-  const SBool  s1926 = false != s1925;
-  const SWord8 s1927 = s1926 ? s1820 : s1821;
-  const SBool  s1928 = (SBool) ((s1927 >> 0) & 1);
-  const SBool  s1929 = false != s1928;
-  const SBool  s1930 = false == s1929;
-  const SBool  s1931 = s1921 < s1;
-  const SBool  s1932 = s1921 < s1810;
-  const SBool  s1933 = s1931 || s1932;
-  const SWord8 s1934 = (s1921 >> 1) | (s1921 << 7);
-  const SWord8 s1935 = 128 | s1934;
-  const SWord8 s1936 = 127 & s1934;
-  const SWord8 s1937 = s1933 ? s1935 : s1936;
-  const SWord8 s1938 = (s1937 >> 1) | (s1937 << 7);
-  const SWord8 s1939 = 128 | s1938;
-  const SWord8 s1940 = 127 & s1938;
-  const SWord8 s1941 = s1547 ? s1939 : s1940;
-  const SWord8 s1942 = (s1941 >> 1) | (s1941 << 7);
-  const SWord8 s1943 = 128 | s1942;
-  const SWord8 s1944 = 127 & s1942;
-  const SWord8 s1945 = s1802 ? s1943 : s1944;
-  const SWord8 s1946 = (s1945 >> 1) | (s1945 << 7);
-  const SWord8 s1947 = 128 | s1946;
-  const SWord8 s1948 = 127 & s1946;
-  const SWord8 s1949 = s1929 ? s1947 : s1948;
-  const SWord8 s1950 = s1 + s1945;
-  const SBool  s1951 = s1950 < s1;
-  const SBool  s1952 = s1950 < s1945;
-  const SBool  s1953 = s1951 || s1952;
-  const SWord8 s1954 = (s1950 >> 1) | (s1950 << 7);
-  const SWord8 s1955 = 128 | s1954;
-  const SWord8 s1956 = 127 & s1954;
-  const SWord8 s1957 = s1953 ? s1955 : s1956;
-  const SWord8 s1958 = s1930 ? s1949 : s1957;
-  const SWord8 s1959 = s1 + s1941;
-  const SBool  s1960 = s1959 < s1;
-  const SBool  s1961 = s1959 < s1941;
-  const SBool  s1962 = s1960 || s1961;
-  const SWord8 s1963 = (s1959 >> 1) | (s1959 << 7);
-  const SWord8 s1964 = 128 | s1963;
-  const SWord8 s1965 = 127 & s1963;
-  const SWord8 s1966 = s1962 ? s1964 : s1965;
-  const SWord8 s1967 = (s1966 >> 1) | (s1966 << 7);
-  const SWord8 s1968 = 128 | s1967;
-  const SWord8 s1969 = 127 & s1967;
-  const SWord8 s1970 = s1929 ? s1968 : s1969;
-  const SWord8 s1971 = s1 + s1966;
-  const SBool  s1972 = s1971 < s1;
-  const SBool  s1973 = s1971 < s1966;
-  const SBool  s1974 = s1972 || s1973;
-  const SWord8 s1975 = (s1971 >> 1) | (s1971 << 7);
-  const SWord8 s1976 = 128 | s1975;
-  const SWord8 s1977 = 127 & s1975;
-  const SWord8 s1978 = s1974 ? s1976 : s1977;
-  const SWord8 s1979 = s1930 ? s1970 : s1978;
-  const SWord8 s1980 = s1803 ? s1958 : s1979;
-  const SWord8 s1981 = s1 + s1937;
-  const SBool  s1982 = s1981 < s1;
-  const SBool  s1983 = s1981 < s1937;
-  const SBool  s1984 = s1982 || s1983;
-  const SWord8 s1985 = (s1981 >> 1) | (s1981 << 7);
-  const SWord8 s1986 = 128 | s1985;
-  const SWord8 s1987 = 127 & s1985;
-  const SWord8 s1988 = s1984 ? s1986 : s1987;
-  const SWord8 s1989 = (s1988 >> 1) | (s1988 << 7);
-  const SWord8 s1990 = 128 | s1989;
-  const SWord8 s1991 = 127 & s1989;
-  const SWord8 s1992 = s1802 ? s1990 : s1991;
-  const SWord8 s1993 = (s1992 >> 1) | (s1992 << 7);
-  const SWord8 s1994 = 128 | s1993;
-  const SWord8 s1995 = 127 & s1993;
-  const SWord8 s1996 = s1929 ? s1994 : s1995;
-  const SWord8 s1997 = s1 + s1992;
-  const SBool  s1998 = s1997 < s1;
-  const SBool  s1999 = s1997 < s1992;
-  const SBool  s2000 = s1998 || s1999;
-  const SWord8 s2001 = (s1997 >> 1) | (s1997 << 7);
-  const SWord8 s2002 = 128 | s2001;
-  const SWord8 s2003 = 127 & s2001;
-  const SWord8 s2004 = s2000 ? s2002 : s2003;
-  const SWord8 s2005 = s1930 ? s1996 : s2004;
-  const SWord8 s2006 = s1 + s1988;
-  const SBool  s2007 = s2006 < s1;
-  const SBool  s2008 = s2006 < s1988;
-  const SBool  s2009 = s2007 || s2008;
-  const SWord8 s2010 = (s2006 >> 1) | (s2006 << 7);
-  const SWord8 s2011 = 128 | s2010;
-  const SWord8 s2012 = 127 & s2010;
-  const SWord8 s2013 = s2009 ? s2011 : s2012;
-  const SWord8 s2014 = (s2013 >> 1) | (s2013 << 7);
-  const SWord8 s2015 = 128 | s2014;
-  const SWord8 s2016 = 127 & s2014;
-  const SWord8 s2017 = s1929 ? s2015 : s2016;
-  const SWord8 s2018 = s1 + s2013;
-  const SBool  s2019 = s2018 < s1;
-  const SBool  s2020 = s2018 < s2013;
-  const SBool  s2021 = s2019 || s2020;
-  const SWord8 s2022 = (s2018 >> 1) | (s2018 << 7);
-  const SWord8 s2023 = 128 | s2022;
-  const SWord8 s2024 = 127 & s2022;
-  const SWord8 s2025 = s2021 ? s2023 : s2024;
-  const SWord8 s2026 = s1930 ? s2017 : s2025;
-  const SWord8 s2027 = s1803 ? s2005 : s2026;
-  const SWord8 s2028 = s1548 ? s1980 : s2027;
-  const SWord8 s2029 = s1037 ? s1920 : s2028;
-  const SWord8 s2030 = s21 ? s1793 : s2029;
-  const SWord8 s2031 = s16 ? s1538 : s2030;
-  const SWord8 s2032 = s11 ? s1027 : s2031;
-  const SBool  s2033 = (SBool) ((s1 >> 0) & 1);
-  const SBool  s2034 = false != s2033;
-  const SWord8 s2035 = s2034 ? 128 : 0;
-  const SBool  s2036 = (SBool) ((s2035 >> 0) & 1);
-  const SBool  s2037 = false != s2036;
-  const SWord8 s2038 = s17 | 128;
-  const SWord8 s2039 = s2037 ? s2038 : s18;
-  const SBool  s2040 = (SBool) ((s2039 >> 0) & 1);
-  const SBool  s2041 = false != s2040;
-  const SBool  s2042 = false == s2041;
-  const SWord8 s2043 = (s1 >> 1) | (s1 << 7);
-  const SWord8 s2044 = 127 & s2043;
-  const SBool  s2045 = (SBool) ((s2044 >> 0) & 1);
-  const SBool  s2046 = false != s2045;
-  const SWord8 s2047 = (s2035 >> 1) | (s2035 << 7);
-  const SWord8 s2048 = 128 | s2047;
-  const SWord8 s2049 = 127 & s2047;
-  const SWord8 s2050 = s2046 ? s2048 : s2049;
-  const SBool  s2051 = (SBool) ((s2050 >> 0) & 1);
-  const SBool  s2052 = false != s2051;
-  const SWord8 s2053 = (s2039 >> 1) | (s2039 << 7);
-  const SWord8 s2054 = 128 | s2053;
-  const SWord8 s2055 = 127 & s2053;
-  const SWord8 s2056 = s2052 ? s2054 : s2055;
-  const SBool  s2057 = (SBool) ((s2056 >> 0) & 1);
-  const SBool  s2058 = false != s2057;
-  const SBool  s2059 = false == s2058;
-  const SWord8 s2060 = (s2044 >> 1) | (s2044 << 7);
-  const SWord8 s2061 = 128 | s2060;
-  const SWord8 s2062 = 127 & s2060;
-  const SWord8 s2063 = s10 ? s2061 : s2062;
-  const SBool  s2064 = (SBool) ((s2063 >> 0) & 1);
-  const SBool  s2065 = false != s2064;
-  const SWord8 s2066 = (s2050 >> 1) | (s2050 << 7);
-  const SWord8 s2067 = 128 | s2066;
-  const SWord8 s2068 = 127 & s2066;
-  const SWord8 s2069 = s2065 ? s2067 : s2068;
-  const SBool  s2070 = (SBool) ((s2069 >> 0) & 1);
-  const SBool  s2071 = false != s2070;
-  const SWord8 s2072 = (s2056 >> 1) | (s2056 << 7);
-  const SWord8 s2073 = 128 | s2072;
-  const SWord8 s2074 = 127 & s2072;
-  const SWord8 s2075 = s2071 ? s2073 : s2074;
-  const SBool  s2076 = (SBool) ((s2075 >> 0) & 1);
-  const SBool  s2077 = false != s2076;
-  const SBool  s2078 = false == s2077;
-  const SWord8 s2079 = (s2063 >> 1) | (s2063 << 7);
-  const SWord8 s2080 = 128 | s2079;
-  const SWord8 s2081 = 127 & s2079;
-  const SWord8 s2082 = s15 ? s2080 : s2081;
-  const SBool  s2083 = (SBool) ((s2082 >> 0) & 1);
-  const SBool  s2084 = false != s2083;
-  const SWord8 s2085 = (s2069 >> 1) | (s2069 << 7);
-  const SWord8 s2086 = 128 | s2085;
-  const SWord8 s2087 = 127 & s2085;
-  const SWord8 s2088 = s2084 ? s2086 : s2087;
-  const SBool  s2089 = (SBool) ((s2088 >> 0) & 1);
-  const SBool  s2090 = false != s2089;
-  const SWord8 s2091 = (s2075 >> 1) | (s2075 << 7);
-  const SWord8 s2092 = 128 | s2091;
-  const SWord8 s2093 = 127 & s2091;
-  const SWord8 s2094 = s2090 ? s2092 : s2093;
-  const SBool  s2095 = (SBool) ((s2094 >> 0) & 1);
-  const SBool  s2096 = false != s2095;
-  const SBool  s2097 = false == s2096;
-  const SWord8 s2098 = (s2082 >> 1) | (s2082 << 7);
-  const SWord8 s2099 = 128 | s2098;
-  const SWord8 s2100 = 127 & s2098;
-  const SWord8 s2101 = s2041 ? s2099 : s2100;
-  const SBool  s2102 = (SBool) ((s2101 >> 0) & 1);
-  const SBool  s2103 = false != s2102;
-  const SWord8 s2104 = (s2088 >> 1) | (s2088 << 7);
-  const SWord8 s2105 = 128 | s2104;
-  const SWord8 s2106 = 127 & s2104;
-  const SWord8 s2107 = s2103 ? s2105 : s2106;
-  const SBool  s2108 = (SBool) ((s2107 >> 0) & 1);
-  const SBool  s2109 = false != s2108;
-  const SWord8 s2110 = (s2094 >> 1) | (s2094 << 7);
-  const SWord8 s2111 = 128 | s2110;
-  const SWord8 s2112 = 127 & s2110;
-  const SWord8 s2113 = s2109 ? s2111 : s2112;
-  const SBool  s2114 = (SBool) ((s2113 >> 0) & 1);
-  const SBool  s2115 = false != s2114;
-  const SBool  s2116 = false == s2115;
-  const SWord8 s2117 = (s2101 >> 1) | (s2101 << 7);
-  const SWord8 s2118 = 128 | s2117;
-  const SWord8 s2119 = 127 & s2117;
-  const SWord8 s2120 = s2058 ? s2118 : s2119;
-  const SWord8 s2121 = (s2120 >> 1) | (s2120 << 7);
-  const SWord8 s2122 = 128 | s2121;
-  const SWord8 s2123 = 127 & s2121;
-  const SWord8 s2124 = s2077 ? s2122 : s2123;
-  const SWord8 s2125 = (s2124 >> 1) | (s2124 << 7);
-  const SWord8 s2126 = 128 | s2125;
-  const SWord8 s2127 = 127 & s2125;
-  const SWord8 s2128 = s2096 ? s2126 : s2127;
-  const SWord8 s2129 = (s2128 >> 1) | (s2128 << 7);
-  const SWord8 s2130 = 128 | s2129;
-  const SWord8 s2131 = 127 & s2129;
-  const SWord8 s2132 = s2115 ? s2130 : s2131;
-  const SWord8 s2133 = s1 + s2128;
-  const SBool  s2134 = s2133 < s1;
-  const SBool  s2135 = s2133 < s2128;
-  const SBool  s2136 = s2134 || s2135;
-  const SWord8 s2137 = (s2133 >> 1) | (s2133 << 7);
-  const SWord8 s2138 = 128 | s2137;
-  const SWord8 s2139 = 127 & s2137;
-  const SWord8 s2140 = s2136 ? s2138 : s2139;
-  const SWord8 s2141 = s2116 ? s2132 : s2140;
-  const SWord8 s2142 = s1 + s2124;
-  const SBool  s2143 = s2142 < s1;
-  const SBool  s2144 = s2142 < s2124;
-  const SBool  s2145 = s2143 || s2144;
-  const SWord8 s2146 = (s2142 >> 1) | (s2142 << 7);
-  const SWord8 s2147 = 128 | s2146;
-  const SWord8 s2148 = 127 & s2146;
-  const SWord8 s2149 = s2145 ? s2147 : s2148;
-  const SWord8 s2150 = (s2149 >> 1) | (s2149 << 7);
-  const SWord8 s2151 = 128 | s2150;
-  const SWord8 s2152 = 127 & s2150;
-  const SWord8 s2153 = s2115 ? s2151 : s2152;
-  const SWord8 s2154 = s1 + s2149;
-  const SBool  s2155 = s2154 < s1;
-  const SBool  s2156 = s2154 < s2149;
-  const SBool  s2157 = s2155 || s2156;
-  const SWord8 s2158 = (s2154 >> 1) | (s2154 << 7);
-  const SWord8 s2159 = 128 | s2158;
-  const SWord8 s2160 = 127 & s2158;
-  const SWord8 s2161 = s2157 ? s2159 : s2160;
-  const SWord8 s2162 = s2116 ? s2153 : s2161;
-  const SWord8 s2163 = s2097 ? s2141 : s2162;
-  const SWord8 s2164 = s1 + s2120;
-  const SBool  s2165 = s2164 < s1;
-  const SBool  s2166 = s2164 < s2120;
-  const SBool  s2167 = s2165 || s2166;
-  const SWord8 s2168 = (s2164 >> 1) | (s2164 << 7);
-  const SWord8 s2169 = 128 | s2168;
-  const SWord8 s2170 = 127 & s2168;
-  const SWord8 s2171 = s2167 ? s2169 : s2170;
-  const SWord8 s2172 = (s2171 >> 1) | (s2171 << 7);
-  const SWord8 s2173 = 128 | s2172;
-  const SWord8 s2174 = 127 & s2172;
-  const SWord8 s2175 = s2096 ? s2173 : s2174;
-  const SWord8 s2176 = (s2175 >> 1) | (s2175 << 7);
-  const SWord8 s2177 = 128 | s2176;
-  const SWord8 s2178 = 127 & s2176;
-  const SWord8 s2179 = s2115 ? s2177 : s2178;
-  const SWord8 s2180 = s1 + s2175;
-  const SBool  s2181 = s2180 < s1;
-  const SBool  s2182 = s2180 < s2175;
-  const SBool  s2183 = s2181 || s2182;
-  const SWord8 s2184 = (s2180 >> 1) | (s2180 << 7);
-  const SWord8 s2185 = 128 | s2184;
-  const SWord8 s2186 = 127 & s2184;
-  const SWord8 s2187 = s2183 ? s2185 : s2186;
-  const SWord8 s2188 = s2116 ? s2179 : s2187;
-  const SWord8 s2189 = s1 + s2171;
-  const SBool  s2190 = s2189 < s1;
-  const SBool  s2191 = s2189 < s2171;
-  const SBool  s2192 = s2190 || s2191;
-  const SWord8 s2193 = (s2189 >> 1) | (s2189 << 7);
-  const SWord8 s2194 = 128 | s2193;
-  const SWord8 s2195 = 127 & s2193;
-  const SWord8 s2196 = s2192 ? s2194 : s2195;
-  const SWord8 s2197 = (s2196 >> 1) | (s2196 << 7);
-  const SWord8 s2198 = 128 | s2197;
-  const SWord8 s2199 = 127 & s2197;
-  const SWord8 s2200 = s2115 ? s2198 : s2199;
-  const SWord8 s2201 = s1 + s2196;
-  const SBool  s2202 = s2201 < s1;
-  const SBool  s2203 = s2201 < s2196;
-  const SBool  s2204 = s2202 || s2203;
-  const SWord8 s2205 = (s2201 >> 1) | (s2201 << 7);
-  const SWord8 s2206 = 128 | s2205;
-  const SWord8 s2207 = 127 & s2205;
-  const SWord8 s2208 = s2204 ? s2206 : s2207;
-  const SWord8 s2209 = s2116 ? s2200 : s2208;
-  const SWord8 s2210 = s2097 ? s2188 : s2209;
-  const SWord8 s2211 = s2078 ? s2163 : s2210;
-  const SWord8 s2212 = s1 + s2101;
-  const SBool  s2213 = (SBool) ((s2212 >> 0) & 1);
-  const SBool  s2214 = false != s2213;
-  const SWord8 s2215 = s2214 ? s2105 : s2106;
-  const SBool  s2216 = (SBool) ((s2215 >> 0) & 1);
-  const SBool  s2217 = false != s2216;
-  const SWord8 s2218 = s2217 ? s2111 : s2112;
-  const SBool  s2219 = (SBool) ((s2218 >> 0) & 1);
-  const SBool  s2220 = false != s2219;
-  const SBool  s2221 = false == s2220;
-  const SBool  s2222 = s2212 < s1;
-  const SBool  s2223 = s2212 < s2101;
-  const SBool  s2224 = s2222 || s2223;
-  const SWord8 s2225 = (s2212 >> 1) | (s2212 << 7);
-  const SWord8 s2226 = 128 | s2225;
-  const SWord8 s2227 = 127 & s2225;
-  const SWord8 s2228 = s2224 ? s2226 : s2227;
-  const SWord8 s2229 = (s2228 >> 1) | (s2228 << 7);
-  const SWord8 s2230 = 128 | s2229;
-  const SWord8 s2231 = 127 & s2229;
-  const SWord8 s2232 = s2077 ? s2230 : s2231;
-  const SWord8 s2233 = (s2232 >> 1) | (s2232 << 7);
-  const SWord8 s2234 = 128 | s2233;
-  const SWord8 s2235 = 127 & s2233;
-  const SWord8 s2236 = s2096 ? s2234 : s2235;
-  const SWord8 s2237 = (s2236 >> 1) | (s2236 << 7);
-  const SWord8 s2238 = 128 | s2237;
-  const SWord8 s2239 = 127 & s2237;
-  const SWord8 s2240 = s2220 ? s2238 : s2239;
-  const SWord8 s2241 = s1 + s2236;
-  const SBool  s2242 = s2241 < s1;
-  const SBool  s2243 = s2241 < s2236;
-  const SBool  s2244 = s2242 || s2243;
-  const SWord8 s2245 = (s2241 >> 1) | (s2241 << 7);
-  const SWord8 s2246 = 128 | s2245;
-  const SWord8 s2247 = 127 & s2245;
-  const SWord8 s2248 = s2244 ? s2246 : s2247;
-  const SWord8 s2249 = s2221 ? s2240 : s2248;
-  const SWord8 s2250 = s1 + s2232;
-  const SBool  s2251 = s2250 < s1;
-  const SBool  s2252 = s2250 < s2232;
-  const SBool  s2253 = s2251 || s2252;
-  const SWord8 s2254 = (s2250 >> 1) | (s2250 << 7);
-  const SWord8 s2255 = 128 | s2254;
-  const SWord8 s2256 = 127 & s2254;
-  const SWord8 s2257 = s2253 ? s2255 : s2256;
-  const SWord8 s2258 = (s2257 >> 1) | (s2257 << 7);
-  const SWord8 s2259 = 128 | s2258;
-  const SWord8 s2260 = 127 & s2258;
-  const SWord8 s2261 = s2220 ? s2259 : s2260;
-  const SWord8 s2262 = s1 + s2257;
-  const SBool  s2263 = s2262 < s1;
-  const SBool  s2264 = s2262 < s2257;
-  const SBool  s2265 = s2263 || s2264;
-  const SWord8 s2266 = (s2262 >> 1) | (s2262 << 7);
-  const SWord8 s2267 = 128 | s2266;
-  const SWord8 s2268 = 127 & s2266;
-  const SWord8 s2269 = s2265 ? s2267 : s2268;
-  const SWord8 s2270 = s2221 ? s2261 : s2269;
-  const SWord8 s2271 = s2097 ? s2249 : s2270;
-  const SWord8 s2272 = s1 + s2228;
-  const SBool  s2273 = s2272 < s1;
-  const SBool  s2274 = s2272 < s2228;
-  const SBool  s2275 = s2273 || s2274;
-  const SWord8 s2276 = (s2272 >> 1) | (s2272 << 7);
-  const SWord8 s2277 = 128 | s2276;
-  const SWord8 s2278 = 127 & s2276;
-  const SWord8 s2279 = s2275 ? s2277 : s2278;
-  const SWord8 s2280 = (s2279 >> 1) | (s2279 << 7);
-  const SWord8 s2281 = 128 | s2280;
-  const SWord8 s2282 = 127 & s2280;
-  const SWord8 s2283 = s2096 ? s2281 : s2282;
-  const SWord8 s2284 = (s2283 >> 1) | (s2283 << 7);
-  const SWord8 s2285 = 128 | s2284;
-  const SWord8 s2286 = 127 & s2284;
-  const SWord8 s2287 = s2220 ? s2285 : s2286;
-  const SWord8 s2288 = s1 + s2283;
-  const SBool  s2289 = s2288 < s1;
-  const SBool  s2290 = s2288 < s2283;
-  const SBool  s2291 = s2289 || s2290;
-  const SWord8 s2292 = (s2288 >> 1) | (s2288 << 7);
-  const SWord8 s2293 = 128 | s2292;
-  const SWord8 s2294 = 127 & s2292;
-  const SWord8 s2295 = s2291 ? s2293 : s2294;
-  const SWord8 s2296 = s2221 ? s2287 : s2295;
-  const SWord8 s2297 = s1 + s2279;
-  const SBool  s2298 = s2297 < s1;
-  const SBool  s2299 = s2297 < s2279;
-  const SBool  s2300 = s2298 || s2299;
-  const SWord8 s2301 = (s2297 >> 1) | (s2297 << 7);
-  const SWord8 s2302 = 128 | s2301;
-  const SWord8 s2303 = 127 & s2301;
-  const SWord8 s2304 = s2300 ? s2302 : s2303;
-  const SWord8 s2305 = (s2304 >> 1) | (s2304 << 7);
-  const SWord8 s2306 = 128 | s2305;
-  const SWord8 s2307 = 127 & s2305;
-  const SWord8 s2308 = s2220 ? s2306 : s2307;
-  const SWord8 s2309 = s1 + s2304;
-  const SBool  s2310 = s2309 < s1;
-  const SBool  s2311 = s2309 < s2304;
-  const SBool  s2312 = s2310 || s2311;
-  const SWord8 s2313 = (s2309 >> 1) | (s2309 << 7);
-  const SWord8 s2314 = 128 | s2313;
-  const SWord8 s2315 = 127 & s2313;
-  const SWord8 s2316 = s2312 ? s2314 : s2315;
-  const SWord8 s2317 = s2221 ? s2308 : s2316;
-  const SWord8 s2318 = s2097 ? s2296 : s2317;
-  const SWord8 s2319 = s2078 ? s2271 : s2318;
-  const SWord8 s2320 = s2059 ? s2211 : s2319;
-  const SWord8 s2321 = s1 + s2082;
-  const SBool  s2322 = (SBool) ((s2321 >> 0) & 1);
-  const SBool  s2323 = false != s2322;
-  const SWord8 s2324 = s2323 ? s2086 : s2087;
-  const SBool  s2325 = (SBool) ((s2324 >> 0) & 1);
-  const SBool  s2326 = false != s2325;
-  const SWord8 s2327 = s2326 ? s2092 : s2093;
-  const SBool  s2328 = (SBool) ((s2327 >> 0) & 1);
-  const SBool  s2329 = false != s2328;
-  const SBool  s2330 = false == s2329;
-  const SBool  s2331 = s2321 < s1;
-  const SBool  s2332 = s2321 < s2082;
-  const SBool  s2333 = s2331 || s2332;
-  const SWord8 s2334 = (s2321 >> 1) | (s2321 << 7);
-  const SWord8 s2335 = 128 | s2334;
-  const SWord8 s2336 = 127 & s2334;
-  const SWord8 s2337 = s2333 ? s2335 : s2336;
-  const SBool  s2338 = (SBool) ((s2337 >> 0) & 1);
-  const SBool  s2339 = false != s2338;
-  const SWord8 s2340 = (s2324 >> 1) | (s2324 << 7);
-  const SWord8 s2341 = 128 | s2340;
-  const SWord8 s2342 = 127 & s2340;
-  const SWord8 s2343 = s2339 ? s2341 : s2342;
-  const SBool  s2344 = (SBool) ((s2343 >> 0) & 1);
-  const SBool  s2345 = false != s2344;
-  const SWord8 s2346 = (s2327 >> 1) | (s2327 << 7);
-  const SWord8 s2347 = 128 | s2346;
-  const SWord8 s2348 = 127 & s2346;
-  const SWord8 s2349 = s2345 ? s2347 : s2348;
-  const SBool  s2350 = (SBool) ((s2349 >> 0) & 1);
-  const SBool  s2351 = false != s2350;
-  const SBool  s2352 = false == s2351;
-  const SWord8 s2353 = (s2337 >> 1) | (s2337 << 7);
-  const SWord8 s2354 = 128 | s2353;
-  const SWord8 s2355 = 127 & s2353;
-  const SWord8 s2356 = s2058 ? s2354 : s2355;
-  const SWord8 s2357 = (s2356 >> 1) | (s2356 << 7);
-  const SWord8 s2358 = 128 | s2357;
-  const SWord8 s2359 = 127 & s2357;
-  const SWord8 s2360 = s2077 ? s2358 : s2359;
-  const SWord8 s2361 = (s2360 >> 1) | (s2360 << 7);
-  const SWord8 s2362 = 128 | s2361;
-  const SWord8 s2363 = 127 & s2361;
-  const SWord8 s2364 = s2329 ? s2362 : s2363;
-  const SWord8 s2365 = (s2364 >> 1) | (s2364 << 7);
-  const SWord8 s2366 = 128 | s2365;
-  const SWord8 s2367 = 127 & s2365;
-  const SWord8 s2368 = s2351 ? s2366 : s2367;
-  const SWord8 s2369 = s1 + s2364;
-  const SBool  s2370 = s2369 < s1;
-  const SBool  s2371 = s2369 < s2364;
-  const SBool  s2372 = s2370 || s2371;
-  const SWord8 s2373 = (s2369 >> 1) | (s2369 << 7);
-  const SWord8 s2374 = 128 | s2373;
-  const SWord8 s2375 = 127 & s2373;
-  const SWord8 s2376 = s2372 ? s2374 : s2375;
-  const SWord8 s2377 = s2352 ? s2368 : s2376;
-  const SWord8 s2378 = s1 + s2360;
-  const SBool  s2379 = s2378 < s1;
-  const SBool  s2380 = s2378 < s2360;
-  const SBool  s2381 = s2379 || s2380;
-  const SWord8 s2382 = (s2378 >> 1) | (s2378 << 7);
-  const SWord8 s2383 = 128 | s2382;
-  const SWord8 s2384 = 127 & s2382;
-  const SWord8 s2385 = s2381 ? s2383 : s2384;
-  const SWord8 s2386 = (s2385 >> 1) | (s2385 << 7);
-  const SWord8 s2387 = 128 | s2386;
-  const SWord8 s2388 = 127 & s2386;
-  const SWord8 s2389 = s2351 ? s2387 : s2388;
-  const SWord8 s2390 = s1 + s2385;
-  const SBool  s2391 = s2390 < s1;
-  const SBool  s2392 = s2390 < s2385;
-  const SBool  s2393 = s2391 || s2392;
-  const SWord8 s2394 = (s2390 >> 1) | (s2390 << 7);
-  const SWord8 s2395 = 128 | s2394;
-  const SWord8 s2396 = 127 & s2394;
-  const SWord8 s2397 = s2393 ? s2395 : s2396;
-  const SWord8 s2398 = s2352 ? s2389 : s2397;
-  const SWord8 s2399 = s2330 ? s2377 : s2398;
-  const SWord8 s2400 = s1 + s2356;
-  const SBool  s2401 = s2400 < s1;
-  const SBool  s2402 = s2400 < s2356;
-  const SBool  s2403 = s2401 || s2402;
-  const SWord8 s2404 = (s2400 >> 1) | (s2400 << 7);
-  const SWord8 s2405 = 128 | s2404;
-  const SWord8 s2406 = 127 & s2404;
-  const SWord8 s2407 = s2403 ? s2405 : s2406;
-  const SWord8 s2408 = (s2407 >> 1) | (s2407 << 7);
-  const SWord8 s2409 = 128 | s2408;
-  const SWord8 s2410 = 127 & s2408;
-  const SWord8 s2411 = s2329 ? s2409 : s2410;
-  const SWord8 s2412 = (s2411 >> 1) | (s2411 << 7);
-  const SWord8 s2413 = 128 | s2412;
-  const SWord8 s2414 = 127 & s2412;
-  const SWord8 s2415 = s2351 ? s2413 : s2414;
-  const SWord8 s2416 = s1 + s2411;
-  const SBool  s2417 = s2416 < s1;
-  const SBool  s2418 = s2416 < s2411;
-  const SBool  s2419 = s2417 || s2418;
-  const SWord8 s2420 = (s2416 >> 1) | (s2416 << 7);
-  const SWord8 s2421 = 128 | s2420;
-  const SWord8 s2422 = 127 & s2420;
-  const SWord8 s2423 = s2419 ? s2421 : s2422;
-  const SWord8 s2424 = s2352 ? s2415 : s2423;
-  const SWord8 s2425 = s1 + s2407;
-  const SBool  s2426 = s2425 < s1;
-  const SBool  s2427 = s2425 < s2407;
-  const SBool  s2428 = s2426 || s2427;
-  const SWord8 s2429 = (s2425 >> 1) | (s2425 << 7);
-  const SWord8 s2430 = 128 | s2429;
-  const SWord8 s2431 = 127 & s2429;
-  const SWord8 s2432 = s2428 ? s2430 : s2431;
-  const SWord8 s2433 = (s2432 >> 1) | (s2432 << 7);
-  const SWord8 s2434 = 128 | s2433;
-  const SWord8 s2435 = 127 & s2433;
-  const SWord8 s2436 = s2351 ? s2434 : s2435;
-  const SWord8 s2437 = s1 + s2432;
-  const SBool  s2438 = s2437 < s1;
-  const SBool  s2439 = s2437 < s2432;
-  const SBool  s2440 = s2438 || s2439;
-  const SWord8 s2441 = (s2437 >> 1) | (s2437 << 7);
-  const SWord8 s2442 = 128 | s2441;
-  const SWord8 s2443 = 127 & s2441;
-  const SWord8 s2444 = s2440 ? s2442 : s2443;
-  const SWord8 s2445 = s2352 ? s2436 : s2444;
-  const SWord8 s2446 = s2330 ? s2424 : s2445;
-  const SWord8 s2447 = s2078 ? s2399 : s2446;
-  const SWord8 s2448 = s1 + s2337;
-  const SBool  s2449 = (SBool) ((s2448 >> 0) & 1);
-  const SBool  s2450 = false != s2449;
-  const SWord8 s2451 = s2450 ? s2341 : s2342;
-  const SBool  s2452 = (SBool) ((s2451 >> 0) & 1);
-  const SBool  s2453 = false != s2452;
-  const SWord8 s2454 = s2453 ? s2347 : s2348;
-  const SBool  s2455 = (SBool) ((s2454 >> 0) & 1);
-  const SBool  s2456 = false != s2455;
-  const SBool  s2457 = false == s2456;
-  const SBool  s2458 = s2448 < s1;
-  const SBool  s2459 = s2448 < s2337;
-  const SBool  s2460 = s2458 || s2459;
-  const SWord8 s2461 = (s2448 >> 1) | (s2448 << 7);
-  const SWord8 s2462 = 128 | s2461;
-  const SWord8 s2463 = 127 & s2461;
-  const SWord8 s2464 = s2460 ? s2462 : s2463;
-  const SWord8 s2465 = (s2464 >> 1) | (s2464 << 7);
-  const SWord8 s2466 = 128 | s2465;
-  const SWord8 s2467 = 127 & s2465;
-  const SWord8 s2468 = s2077 ? s2466 : s2467;
-  const SWord8 s2469 = (s2468 >> 1) | (s2468 << 7);
-  const SWord8 s2470 = 128 | s2469;
-  const SWord8 s2471 = 127 & s2469;
-  const SWord8 s2472 = s2329 ? s2470 : s2471;
-  const SWord8 s2473 = (s2472 >> 1) | (s2472 << 7);
-  const SWord8 s2474 = 128 | s2473;
-  const SWord8 s2475 = 127 & s2473;
-  const SWord8 s2476 = s2456 ? s2474 : s2475;
-  const SWord8 s2477 = s1 + s2472;
-  const SBool  s2478 = s2477 < s1;
-  const SBool  s2479 = s2477 < s2472;
-  const SBool  s2480 = s2478 || s2479;
-  const SWord8 s2481 = (s2477 >> 1) | (s2477 << 7);
-  const SWord8 s2482 = 128 | s2481;
-  const SWord8 s2483 = 127 & s2481;
-  const SWord8 s2484 = s2480 ? s2482 : s2483;
-  const SWord8 s2485 = s2457 ? s2476 : s2484;
-  const SWord8 s2486 = s1 + s2468;
-  const SBool  s2487 = s2486 < s1;
-  const SBool  s2488 = s2486 < s2468;
-  const SBool  s2489 = s2487 || s2488;
-  const SWord8 s2490 = (s2486 >> 1) | (s2486 << 7);
-  const SWord8 s2491 = 128 | s2490;
-  const SWord8 s2492 = 127 & s2490;
-  const SWord8 s2493 = s2489 ? s2491 : s2492;
-  const SWord8 s2494 = (s2493 >> 1) | (s2493 << 7);
-  const SWord8 s2495 = 128 | s2494;
-  const SWord8 s2496 = 127 & s2494;
-  const SWord8 s2497 = s2456 ? s2495 : s2496;
-  const SWord8 s2498 = s1 + s2493;
-  const SBool  s2499 = s2498 < s1;
-  const SBool  s2500 = s2498 < s2493;
-  const SBool  s2501 = s2499 || s2500;
-  const SWord8 s2502 = (s2498 >> 1) | (s2498 << 7);
-  const SWord8 s2503 = 128 | s2502;
-  const SWord8 s2504 = 127 & s2502;
-  const SWord8 s2505 = s2501 ? s2503 : s2504;
-  const SWord8 s2506 = s2457 ? s2497 : s2505;
-  const SWord8 s2507 = s2330 ? s2485 : s2506;
-  const SWord8 s2508 = s1 + s2464;
-  const SBool  s2509 = s2508 < s1;
-  const SBool  s2510 = s2508 < s2464;
-  const SBool  s2511 = s2509 || s2510;
-  const SWord8 s2512 = (s2508 >> 1) | (s2508 << 7);
-  const SWord8 s2513 = 128 | s2512;
-  const SWord8 s2514 = 127 & s2512;
-  const SWord8 s2515 = s2511 ? s2513 : s2514;
-  const SWord8 s2516 = (s2515 >> 1) | (s2515 << 7);
-  const SWord8 s2517 = 128 | s2516;
-  const SWord8 s2518 = 127 & s2516;
-  const SWord8 s2519 = s2329 ? s2517 : s2518;
-  const SWord8 s2520 = (s2519 >> 1) | (s2519 << 7);
-  const SWord8 s2521 = 128 | s2520;
-  const SWord8 s2522 = 127 & s2520;
-  const SWord8 s2523 = s2456 ? s2521 : s2522;
-  const SWord8 s2524 = s1 + s2519;
-  const SBool  s2525 = s2524 < s1;
-  const SBool  s2526 = s2524 < s2519;
-  const SBool  s2527 = s2525 || s2526;
-  const SWord8 s2528 = (s2524 >> 1) | (s2524 << 7);
-  const SWord8 s2529 = 128 | s2528;
-  const SWord8 s2530 = 127 & s2528;
-  const SWord8 s2531 = s2527 ? s2529 : s2530;
-  const SWord8 s2532 = s2457 ? s2523 : s2531;
-  const SWord8 s2533 = s1 + s2515;
-  const SBool  s2534 = s2533 < s1;
-  const SBool  s2535 = s2533 < s2515;
-  const SBool  s2536 = s2534 || s2535;
-  const SWord8 s2537 = (s2533 >> 1) | (s2533 << 7);
-  const SWord8 s2538 = 128 | s2537;
-  const SWord8 s2539 = 127 & s2537;
-  const SWord8 s2540 = s2536 ? s2538 : s2539;
-  const SWord8 s2541 = (s2540 >> 1) | (s2540 << 7);
-  const SWord8 s2542 = 128 | s2541;
-  const SWord8 s2543 = 127 & s2541;
-  const SWord8 s2544 = s2456 ? s2542 : s2543;
-  const SWord8 s2545 = s1 + s2540;
-  const SBool  s2546 = s2545 < s1;
-  const SBool  s2547 = s2545 < s2540;
-  const SBool  s2548 = s2546 || s2547;
-  const SWord8 s2549 = (s2545 >> 1) | (s2545 << 7);
-  const SWord8 s2550 = 128 | s2549;
-  const SWord8 s2551 = 127 & s2549;
-  const SWord8 s2552 = s2548 ? s2550 : s2551;
-  const SWord8 s2553 = s2457 ? s2544 : s2552;
-  const SWord8 s2554 = s2330 ? s2532 : s2553;
-  const SWord8 s2555 = s2078 ? s2507 : s2554;
-  const SWord8 s2556 = s2059 ? s2447 : s2555;
-  const SWord8 s2557 = s2042 ? s2320 : s2556;
-  const SWord8 s2558 = s1 + s2063;
-  const SBool  s2559 = (SBool) ((s2558 >> 0) & 1);
-  const SBool  s2560 = false != s2559;
-  const SWord8 s2561 = s2560 ? s2067 : s2068;
-  const SBool  s2562 = (SBool) ((s2561 >> 0) & 1);
-  const SBool  s2563 = false != s2562;
-  const SWord8 s2564 = s2563 ? s2073 : s2074;
-  const SBool  s2565 = (SBool) ((s2564 >> 0) & 1);
-  const SBool  s2566 = false != s2565;
-  const SBool  s2567 = false == s2566;
-  const SBool  s2568 = s2558 < s1;
-  const SBool  s2569 = s2558 < s2063;
-  const SBool  s2570 = s2568 || s2569;
-  const SWord8 s2571 = (s2558 >> 1) | (s2558 << 7);
-  const SWord8 s2572 = 128 | s2571;
-  const SWord8 s2573 = 127 & s2571;
-  const SWord8 s2574 = s2570 ? s2572 : s2573;
-  const SBool  s2575 = (SBool) ((s2574 >> 0) & 1);
-  const SBool  s2576 = false != s2575;
-  const SWord8 s2577 = (s2561 >> 1) | (s2561 << 7);
-  const SWord8 s2578 = 128 | s2577;
-  const SWord8 s2579 = 127 & s2577;
-  const SWord8 s2580 = s2576 ? s2578 : s2579;
-  const SBool  s2581 = (SBool) ((s2580 >> 0) & 1);
-  const SBool  s2582 = false != s2581;
-  const SWord8 s2583 = (s2564 >> 1) | (s2564 << 7);
-  const SWord8 s2584 = 128 | s2583;
-  const SWord8 s2585 = 127 & s2583;
-  const SWord8 s2586 = s2582 ? s2584 : s2585;
-  const SBool  s2587 = (SBool) ((s2586 >> 0) & 1);
-  const SBool  s2588 = false != s2587;
-  const SBool  s2589 = false == s2588;
-  const SWord8 s2590 = (s2574 >> 1) | (s2574 << 7);
-  const SWord8 s2591 = 128 | s2590;
-  const SWord8 s2592 = 127 & s2590;
-  const SWord8 s2593 = s2041 ? s2591 : s2592;
-  const SBool  s2594 = (SBool) ((s2593 >> 0) & 1);
-  const SBool  s2595 = false != s2594;
-  const SWord8 s2596 = (s2580 >> 1) | (s2580 << 7);
-  const SWord8 s2597 = 128 | s2596;
-  const SWord8 s2598 = 127 & s2596;
-  const SWord8 s2599 = s2595 ? s2597 : s2598;
-  const SBool  s2600 = (SBool) ((s2599 >> 0) & 1);
-  const SBool  s2601 = false != s2600;
-  const SWord8 s2602 = (s2586 >> 1) | (s2586 << 7);
-  const SWord8 s2603 = 128 | s2602;
-  const SWord8 s2604 = 127 & s2602;
-  const SWord8 s2605 = s2601 ? s2603 : s2604;
-  const SBool  s2606 = (SBool) ((s2605 >> 0) & 1);
-  const SBool  s2607 = false != s2606;
-  const SBool  s2608 = false == s2607;
-  const SWord8 s2609 = (s2593 >> 1) | (s2593 << 7);
-  const SWord8 s2610 = 128 | s2609;
-  const SWord8 s2611 = 127 & s2609;
-  const SWord8 s2612 = s2058 ? s2610 : s2611;
-  const SWord8 s2613 = (s2612 >> 1) | (s2612 << 7);
-  const SWord8 s2614 = 128 | s2613;
-  const SWord8 s2615 = 127 & s2613;
-  const SWord8 s2616 = s2566 ? s2614 : s2615;
-  const SWord8 s2617 = (s2616 >> 1) | (s2616 << 7);
-  const SWord8 s2618 = 128 | s2617;
-  const SWord8 s2619 = 127 & s2617;
-  const SWord8 s2620 = s2588 ? s2618 : s2619;
-  const SWord8 s2621 = (s2620 >> 1) | (s2620 << 7);
-  const SWord8 s2622 = 128 | s2621;
-  const SWord8 s2623 = 127 & s2621;
-  const SWord8 s2624 = s2607 ? s2622 : s2623;
-  const SWord8 s2625 = s1 + s2620;
-  const SBool  s2626 = s2625 < s1;
-  const SBool  s2627 = s2625 < s2620;
-  const SBool  s2628 = s2626 || s2627;
-  const SWord8 s2629 = (s2625 >> 1) | (s2625 << 7);
-  const SWord8 s2630 = 128 | s2629;
-  const SWord8 s2631 = 127 & s2629;
-  const SWord8 s2632 = s2628 ? s2630 : s2631;
-  const SWord8 s2633 = s2608 ? s2624 : s2632;
-  const SWord8 s2634 = s1 + s2616;
-  const SBool  s2635 = s2634 < s1;
-  const SBool  s2636 = s2634 < s2616;
-  const SBool  s2637 = s2635 || s2636;
-  const SWord8 s2638 = (s2634 >> 1) | (s2634 << 7);
-  const SWord8 s2639 = 128 | s2638;
-  const SWord8 s2640 = 127 & s2638;
-  const SWord8 s2641 = s2637 ? s2639 : s2640;
-  const SWord8 s2642 = (s2641 >> 1) | (s2641 << 7);
-  const SWord8 s2643 = 128 | s2642;
-  const SWord8 s2644 = 127 & s2642;
-  const SWord8 s2645 = s2607 ? s2643 : s2644;
-  const SWord8 s2646 = s1 + s2641;
-  const SBool  s2647 = s2646 < s1;
-  const SBool  s2648 = s2646 < s2641;
-  const SBool  s2649 = s2647 || s2648;
-  const SWord8 s2650 = (s2646 >> 1) | (s2646 << 7);
-  const SWord8 s2651 = 128 | s2650;
-  const SWord8 s2652 = 127 & s2650;
-  const SWord8 s2653 = s2649 ? s2651 : s2652;
-  const SWord8 s2654 = s2608 ? s2645 : s2653;
-  const SWord8 s2655 = s2589 ? s2633 : s2654;
-  const SWord8 s2656 = s1 + s2612;
-  const SBool  s2657 = s2656 < s1;
-  const SBool  s2658 = s2656 < s2612;
-  const SBool  s2659 = s2657 || s2658;
-  const SWord8 s2660 = (s2656 >> 1) | (s2656 << 7);
-  const SWord8 s2661 = 128 | s2660;
-  const SWord8 s2662 = 127 & s2660;
-  const SWord8 s2663 = s2659 ? s2661 : s2662;
-  const SWord8 s2664 = (s2663 >> 1) | (s2663 << 7);
-  const SWord8 s2665 = 128 | s2664;
-  const SWord8 s2666 = 127 & s2664;
-  const SWord8 s2667 = s2588 ? s2665 : s2666;
-  const SWord8 s2668 = (s2667 >> 1) | (s2667 << 7);
-  const SWord8 s2669 = 128 | s2668;
-  const SWord8 s2670 = 127 & s2668;
-  const SWord8 s2671 = s2607 ? s2669 : s2670;
-  const SWord8 s2672 = s1 + s2667;
-  const SBool  s2673 = s2672 < s1;
-  const SBool  s2674 = s2672 < s2667;
-  const SBool  s2675 = s2673 || s2674;
-  const SWord8 s2676 = (s2672 >> 1) | (s2672 << 7);
-  const SWord8 s2677 = 128 | s2676;
-  const SWord8 s2678 = 127 & s2676;
-  const SWord8 s2679 = s2675 ? s2677 : s2678;
-  const SWord8 s2680 = s2608 ? s2671 : s2679;
-  const SWord8 s2681 = s1 + s2663;
-  const SBool  s2682 = s2681 < s1;
-  const SBool  s2683 = s2681 < s2663;
-  const SBool  s2684 = s2682 || s2683;
-  const SWord8 s2685 = (s2681 >> 1) | (s2681 << 7);
-  const SWord8 s2686 = 128 | s2685;
-  const SWord8 s2687 = 127 & s2685;
-  const SWord8 s2688 = s2684 ? s2686 : s2687;
-  const SWord8 s2689 = (s2688 >> 1) | (s2688 << 7);
-  const SWord8 s2690 = 128 | s2689;
-  const SWord8 s2691 = 127 & s2689;
-  const SWord8 s2692 = s2607 ? s2690 : s2691;
-  const SWord8 s2693 = s1 + s2688;
-  const SBool  s2694 = s2693 < s1;
-  const SBool  s2695 = s2693 < s2688;
-  const SBool  s2696 = s2694 || s2695;
-  const SWord8 s2697 = (s2693 >> 1) | (s2693 << 7);
-  const SWord8 s2698 = 128 | s2697;
-  const SWord8 s2699 = 127 & s2697;
-  const SWord8 s2700 = s2696 ? s2698 : s2699;
-  const SWord8 s2701 = s2608 ? s2692 : s2700;
-  const SWord8 s2702 = s2589 ? s2680 : s2701;
-  const SWord8 s2703 = s2567 ? s2655 : s2702;
-  const SWord8 s2704 = s1 + s2593;
-  const SBool  s2705 = (SBool) ((s2704 >> 0) & 1);
-  const SBool  s2706 = false != s2705;
-  const SWord8 s2707 = s2706 ? s2597 : s2598;
-  const SBool  s2708 = (SBool) ((s2707 >> 0) & 1);
-  const SBool  s2709 = false != s2708;
-  const SWord8 s2710 = s2709 ? s2603 : s2604;
-  const SBool  s2711 = (SBool) ((s2710 >> 0) & 1);
-  const SBool  s2712 = false != s2711;
-  const SBool  s2713 = false == s2712;
-  const SBool  s2714 = s2704 < s1;
-  const SBool  s2715 = s2704 < s2593;
-  const SBool  s2716 = s2714 || s2715;
-  const SWord8 s2717 = (s2704 >> 1) | (s2704 << 7);
-  const SWord8 s2718 = 128 | s2717;
-  const SWord8 s2719 = 127 & s2717;
-  const SWord8 s2720 = s2716 ? s2718 : s2719;
-  const SWord8 s2721 = (s2720 >> 1) | (s2720 << 7);
-  const SWord8 s2722 = 128 | s2721;
-  const SWord8 s2723 = 127 & s2721;
-  const SWord8 s2724 = s2566 ? s2722 : s2723;
-  const SWord8 s2725 = (s2724 >> 1) | (s2724 << 7);
-  const SWord8 s2726 = 128 | s2725;
-  const SWord8 s2727 = 127 & s2725;
-  const SWord8 s2728 = s2588 ? s2726 : s2727;
-  const SWord8 s2729 = (s2728 >> 1) | (s2728 << 7);
-  const SWord8 s2730 = 128 | s2729;
-  const SWord8 s2731 = 127 & s2729;
-  const SWord8 s2732 = s2712 ? s2730 : s2731;
-  const SWord8 s2733 = s1 + s2728;
-  const SBool  s2734 = s2733 < s1;
-  const SBool  s2735 = s2733 < s2728;
-  const SBool  s2736 = s2734 || s2735;
-  const SWord8 s2737 = (s2733 >> 1) | (s2733 << 7);
-  const SWord8 s2738 = 128 | s2737;
-  const SWord8 s2739 = 127 & s2737;
-  const SWord8 s2740 = s2736 ? s2738 : s2739;
-  const SWord8 s2741 = s2713 ? s2732 : s2740;
-  const SWord8 s2742 = s1 + s2724;
-  const SBool  s2743 = s2742 < s1;
-  const SBool  s2744 = s2742 < s2724;
-  const SBool  s2745 = s2743 || s2744;
-  const SWord8 s2746 = (s2742 >> 1) | (s2742 << 7);
-  const SWord8 s2747 = 128 | s2746;
-  const SWord8 s2748 = 127 & s2746;
-  const SWord8 s2749 = s2745 ? s2747 : s2748;
-  const SWord8 s2750 = (s2749 >> 1) | (s2749 << 7);
-  const SWord8 s2751 = 128 | s2750;
-  const SWord8 s2752 = 127 & s2750;
-  const SWord8 s2753 = s2712 ? s2751 : s2752;
-  const SWord8 s2754 = s1 + s2749;
-  const SBool  s2755 = s2754 < s1;
-  const SBool  s2756 = s2754 < s2749;
-  const SBool  s2757 = s2755 || s2756;
-  const SWord8 s2758 = (s2754 >> 1) | (s2754 << 7);
-  const SWord8 s2759 = 128 | s2758;
-  const SWord8 s2760 = 127 & s2758;
-  const SWord8 s2761 = s2757 ? s2759 : s2760;
-  const SWord8 s2762 = s2713 ? s2753 : s2761;
-  const SWord8 s2763 = s2589 ? s2741 : s2762;
-  const SWord8 s2764 = s1 + s2720;
-  const SBool  s2765 = s2764 < s1;
-  const SBool  s2766 = s2764 < s2720;
-  const SBool  s2767 = s2765 || s2766;
-  const SWord8 s2768 = (s2764 >> 1) | (s2764 << 7);
-  const SWord8 s2769 = 128 | s2768;
-  const SWord8 s2770 = 127 & s2768;
-  const SWord8 s2771 = s2767 ? s2769 : s2770;
-  const SWord8 s2772 = (s2771 >> 1) | (s2771 << 7);
-  const SWord8 s2773 = 128 | s2772;
-  const SWord8 s2774 = 127 & s2772;
-  const SWord8 s2775 = s2588 ? s2773 : s2774;
-  const SWord8 s2776 = (s2775 >> 1) | (s2775 << 7);
-  const SWord8 s2777 = 128 | s2776;
-  const SWord8 s2778 = 127 & s2776;
-  const SWord8 s2779 = s2712 ? s2777 : s2778;
-  const SWord8 s2780 = s1 + s2775;
-  const SBool  s2781 = s2780 < s1;
-  const SBool  s2782 = s2780 < s2775;
-  const SBool  s2783 = s2781 || s2782;
-  const SWord8 s2784 = (s2780 >> 1) | (s2780 << 7);
-  const SWord8 s2785 = 128 | s2784;
-  const SWord8 s2786 = 127 & s2784;
-  const SWord8 s2787 = s2783 ? s2785 : s2786;
-  const SWord8 s2788 = s2713 ? s2779 : s2787;
-  const SWord8 s2789 = s1 + s2771;
-  const SBool  s2790 = s2789 < s1;
-  const SBool  s2791 = s2789 < s2771;
-  const SBool  s2792 = s2790 || s2791;
-  const SWord8 s2793 = (s2789 >> 1) | (s2789 << 7);
-  const SWord8 s2794 = 128 | s2793;
-  const SWord8 s2795 = 127 & s2793;
-  const SWord8 s2796 = s2792 ? s2794 : s2795;
-  const SWord8 s2797 = (s2796 >> 1) | (s2796 << 7);
-  const SWord8 s2798 = 128 | s2797;
-  const SWord8 s2799 = 127 & s2797;
-  const SWord8 s2800 = s2712 ? s2798 : s2799;
-  const SWord8 s2801 = s1 + s2796;
-  const SBool  s2802 = s2801 < s1;
-  const SBool  s2803 = s2801 < s2796;
-  const SBool  s2804 = s2802 || s2803;
-  const SWord8 s2805 = (s2801 >> 1) | (s2801 << 7);
-  const SWord8 s2806 = 128 | s2805;
-  const SWord8 s2807 = 127 & s2805;
-  const SWord8 s2808 = s2804 ? s2806 : s2807;
-  const SWord8 s2809 = s2713 ? s2800 : s2808;
-  const SWord8 s2810 = s2589 ? s2788 : s2809;
-  const SWord8 s2811 = s2567 ? s2763 : s2810;
-  const SWord8 s2812 = s2059 ? s2703 : s2811;
-  const SWord8 s2813 = s1 + s2574;
-  const SBool  s2814 = (SBool) ((s2813 >> 0) & 1);
-  const SBool  s2815 = false != s2814;
-  const SWord8 s2816 = s2815 ? s2578 : s2579;
-  const SBool  s2817 = (SBool) ((s2816 >> 0) & 1);
-  const SBool  s2818 = false != s2817;
-  const SWord8 s2819 = s2818 ? s2584 : s2585;
-  const SBool  s2820 = (SBool) ((s2819 >> 0) & 1);
-  const SBool  s2821 = false != s2820;
-  const SBool  s2822 = false == s2821;
-  const SBool  s2823 = s2813 < s1;
-  const SBool  s2824 = s2813 < s2574;
-  const SBool  s2825 = s2823 || s2824;
-  const SWord8 s2826 = (s2813 >> 1) | (s2813 << 7);
-  const SWord8 s2827 = 128 | s2826;
-  const SWord8 s2828 = 127 & s2826;
-  const SWord8 s2829 = s2825 ? s2827 : s2828;
-  const SBool  s2830 = (SBool) ((s2829 >> 0) & 1);
-  const SBool  s2831 = false != s2830;
-  const SWord8 s2832 = (s2816 >> 1) | (s2816 << 7);
-  const SWord8 s2833 = 128 | s2832;
-  const SWord8 s2834 = 127 & s2832;
-  const SWord8 s2835 = s2831 ? s2833 : s2834;
-  const SBool  s2836 = (SBool) ((s2835 >> 0) & 1);
-  const SBool  s2837 = false != s2836;
-  const SWord8 s2838 = (s2819 >> 1) | (s2819 << 7);
-  const SWord8 s2839 = 128 | s2838;
-  const SWord8 s2840 = 127 & s2838;
-  const SWord8 s2841 = s2837 ? s2839 : s2840;
-  const SBool  s2842 = (SBool) ((s2841 >> 0) & 1);
-  const SBool  s2843 = false != s2842;
-  const SBool  s2844 = false == s2843;
-  const SWord8 s2845 = (s2829 >> 1) | (s2829 << 7);
-  const SWord8 s2846 = 128 | s2845;
-  const SWord8 s2847 = 127 & s2845;
-  const SWord8 s2848 = s2058 ? s2846 : s2847;
-  const SWord8 s2849 = (s2848 >> 1) | (s2848 << 7);
-  const SWord8 s2850 = 128 | s2849;
-  const SWord8 s2851 = 127 & s2849;
-  const SWord8 s2852 = s2566 ? s2850 : s2851;
-  const SWord8 s2853 = (s2852 >> 1) | (s2852 << 7);
-  const SWord8 s2854 = 128 | s2853;
-  const SWord8 s2855 = 127 & s2853;
-  const SWord8 s2856 = s2821 ? s2854 : s2855;
-  const SWord8 s2857 = (s2856 >> 1) | (s2856 << 7);
-  const SWord8 s2858 = 128 | s2857;
-  const SWord8 s2859 = 127 & s2857;
-  const SWord8 s2860 = s2843 ? s2858 : s2859;
-  const SWord8 s2861 = s1 + s2856;
-  const SBool  s2862 = s2861 < s1;
-  const SBool  s2863 = s2861 < s2856;
-  const SBool  s2864 = s2862 || s2863;
-  const SWord8 s2865 = (s2861 >> 1) | (s2861 << 7);
-  const SWord8 s2866 = 128 | s2865;
-  const SWord8 s2867 = 127 & s2865;
-  const SWord8 s2868 = s2864 ? s2866 : s2867;
-  const SWord8 s2869 = s2844 ? s2860 : s2868;
-  const SWord8 s2870 = s1 + s2852;
-  const SBool  s2871 = s2870 < s1;
-  const SBool  s2872 = s2870 < s2852;
-  const SBool  s2873 = s2871 || s2872;
-  const SWord8 s2874 = (s2870 >> 1) | (s2870 << 7);
-  const SWord8 s2875 = 128 | s2874;
-  const SWord8 s2876 = 127 & s2874;
-  const SWord8 s2877 = s2873 ? s2875 : s2876;
-  const SWord8 s2878 = (s2877 >> 1) | (s2877 << 7);
-  const SWord8 s2879 = 128 | s2878;
-  const SWord8 s2880 = 127 & s2878;
-  const SWord8 s2881 = s2843 ? s2879 : s2880;
-  const SWord8 s2882 = s1 + s2877;
-  const SBool  s2883 = s2882 < s1;
-  const SBool  s2884 = s2882 < s2877;
-  const SBool  s2885 = s2883 || s2884;
-  const SWord8 s2886 = (s2882 >> 1) | (s2882 << 7);
-  const SWord8 s2887 = 128 | s2886;
-  const SWord8 s2888 = 127 & s2886;
-  const SWord8 s2889 = s2885 ? s2887 : s2888;
-  const SWord8 s2890 = s2844 ? s2881 : s2889;
-  const SWord8 s2891 = s2822 ? s2869 : s2890;
-  const SWord8 s2892 = s1 + s2848;
-  const SBool  s2893 = s2892 < s1;
-  const SBool  s2894 = s2892 < s2848;
-  const SBool  s2895 = s2893 || s2894;
-  const SWord8 s2896 = (s2892 >> 1) | (s2892 << 7);
-  const SWord8 s2897 = 128 | s2896;
-  const SWord8 s2898 = 127 & s2896;
-  const SWord8 s2899 = s2895 ? s2897 : s2898;
-  const SWord8 s2900 = (s2899 >> 1) | (s2899 << 7);
-  const SWord8 s2901 = 128 | s2900;
-  const SWord8 s2902 = 127 & s2900;
-  const SWord8 s2903 = s2821 ? s2901 : s2902;
-  const SWord8 s2904 = (s2903 >> 1) | (s2903 << 7);
-  const SWord8 s2905 = 128 | s2904;
-  const SWord8 s2906 = 127 & s2904;
-  const SWord8 s2907 = s2843 ? s2905 : s2906;
-  const SWord8 s2908 = s1 + s2903;
-  const SBool  s2909 = s2908 < s1;
-  const SBool  s2910 = s2908 < s2903;
-  const SBool  s2911 = s2909 || s2910;
-  const SWord8 s2912 = (s2908 >> 1) | (s2908 << 7);
-  const SWord8 s2913 = 128 | s2912;
-  const SWord8 s2914 = 127 & s2912;
-  const SWord8 s2915 = s2911 ? s2913 : s2914;
-  const SWord8 s2916 = s2844 ? s2907 : s2915;
-  const SWord8 s2917 = s1 + s2899;
-  const SBool  s2918 = s2917 < s1;
-  const SBool  s2919 = s2917 < s2899;
-  const SBool  s2920 = s2918 || s2919;
-  const SWord8 s2921 = (s2917 >> 1) | (s2917 << 7);
-  const SWord8 s2922 = 128 | s2921;
-  const SWord8 s2923 = 127 & s2921;
-  const SWord8 s2924 = s2920 ? s2922 : s2923;
-  const SWord8 s2925 = (s2924 >> 1) | (s2924 << 7);
-  const SWord8 s2926 = 128 | s2925;
-  const SWord8 s2927 = 127 & s2925;
-  const SWord8 s2928 = s2843 ? s2926 : s2927;
-  const SWord8 s2929 = s1 + s2924;
-  const SBool  s2930 = s2929 < s1;
-  const SBool  s2931 = s2929 < s2924;
-  const SBool  s2932 = s2930 || s2931;
-  const SWord8 s2933 = (s2929 >> 1) | (s2929 << 7);
-  const SWord8 s2934 = 128 | s2933;
-  const SWord8 s2935 = 127 & s2933;
-  const SWord8 s2936 = s2932 ? s2934 : s2935;
-  const SWord8 s2937 = s2844 ? s2928 : s2936;
-  const SWord8 s2938 = s2822 ? s2916 : s2937;
-  const SWord8 s2939 = s2567 ? s2891 : s2938;
-  const SWord8 s2940 = s1 + s2829;
-  const SBool  s2941 = (SBool) ((s2940 >> 0) & 1);
-  const SBool  s2942 = false != s2941;
-  const SWord8 s2943 = s2942 ? s2833 : s2834;
-  const SBool  s2944 = (SBool) ((s2943 >> 0) & 1);
-  const SBool  s2945 = false != s2944;
-  const SWord8 s2946 = s2945 ? s2839 : s2840;
-  const SBool  s2947 = (SBool) ((s2946 >> 0) & 1);
-  const SBool  s2948 = false != s2947;
-  const SBool  s2949 = false == s2948;
-  const SBool  s2950 = s2940 < s1;
-  const SBool  s2951 = s2940 < s2829;
-  const SBool  s2952 = s2950 || s2951;
-  const SWord8 s2953 = (s2940 >> 1) | (s2940 << 7);
-  const SWord8 s2954 = 128 | s2953;
-  const SWord8 s2955 = 127 & s2953;
-  const SWord8 s2956 = s2952 ? s2954 : s2955;
-  const SWord8 s2957 = (s2956 >> 1) | (s2956 << 7);
-  const SWord8 s2958 = 128 | s2957;
-  const SWord8 s2959 = 127 & s2957;
-  const SWord8 s2960 = s2566 ? s2958 : s2959;
-  const SWord8 s2961 = (s2960 >> 1) | (s2960 << 7);
-  const SWord8 s2962 = 128 | s2961;
-  const SWord8 s2963 = 127 & s2961;
-  const SWord8 s2964 = s2821 ? s2962 : s2963;
-  const SWord8 s2965 = (s2964 >> 1) | (s2964 << 7);
-  const SWord8 s2966 = 128 | s2965;
-  const SWord8 s2967 = 127 & s2965;
-  const SWord8 s2968 = s2948 ? s2966 : s2967;
-  const SWord8 s2969 = s1 + s2964;
-  const SBool  s2970 = s2969 < s1;
-  const SBool  s2971 = s2969 < s2964;
-  const SBool  s2972 = s2970 || s2971;
-  const SWord8 s2973 = (s2969 >> 1) | (s2969 << 7);
-  const SWord8 s2974 = 128 | s2973;
-  const SWord8 s2975 = 127 & s2973;
-  const SWord8 s2976 = s2972 ? s2974 : s2975;
-  const SWord8 s2977 = s2949 ? s2968 : s2976;
-  const SWord8 s2978 = s1 + s2960;
-  const SBool  s2979 = s2978 < s1;
-  const SBool  s2980 = s2978 < s2960;
-  const SBool  s2981 = s2979 || s2980;
-  const SWord8 s2982 = (s2978 >> 1) | (s2978 << 7);
-  const SWord8 s2983 = 128 | s2982;
-  const SWord8 s2984 = 127 & s2982;
-  const SWord8 s2985 = s2981 ? s2983 : s2984;
-  const SWord8 s2986 = (s2985 >> 1) | (s2985 << 7);
-  const SWord8 s2987 = 128 | s2986;
-  const SWord8 s2988 = 127 & s2986;
-  const SWord8 s2989 = s2948 ? s2987 : s2988;
-  const SWord8 s2990 = s1 + s2985;
-  const SBool  s2991 = s2990 < s1;
-  const SBool  s2992 = s2990 < s2985;
-  const SBool  s2993 = s2991 || s2992;
-  const SWord8 s2994 = (s2990 >> 1) | (s2990 << 7);
-  const SWord8 s2995 = 128 | s2994;
-  const SWord8 s2996 = 127 & s2994;
-  const SWord8 s2997 = s2993 ? s2995 : s2996;
-  const SWord8 s2998 = s2949 ? s2989 : s2997;
-  const SWord8 s2999 = s2822 ? s2977 : s2998;
-  const SWord8 s3000 = s1 + s2956;
-  const SBool  s3001 = s3000 < s1;
-  const SBool  s3002 = s3000 < s2956;
-  const SBool  s3003 = s3001 || s3002;
-  const SWord8 s3004 = (s3000 >> 1) | (s3000 << 7);
-  const SWord8 s3005 = 128 | s3004;
-  const SWord8 s3006 = 127 & s3004;
-  const SWord8 s3007 = s3003 ? s3005 : s3006;
-  const SWord8 s3008 = (s3007 >> 1) | (s3007 << 7);
-  const SWord8 s3009 = 128 | s3008;
-  const SWord8 s3010 = 127 & s3008;
-  const SWord8 s3011 = s2821 ? s3009 : s3010;
-  const SWord8 s3012 = (s3011 >> 1) | (s3011 << 7);
-  const SWord8 s3013 = 128 | s3012;
-  const SWord8 s3014 = 127 & s3012;
-  const SWord8 s3015 = s2948 ? s3013 : s3014;
-  const SWord8 s3016 = s1 + s3011;
-  const SBool  s3017 = s3016 < s1;
-  const SBool  s3018 = s3016 < s3011;
-  const SBool  s3019 = s3017 || s3018;
-  const SWord8 s3020 = (s3016 >> 1) | (s3016 << 7);
-  const SWord8 s3021 = 128 | s3020;
-  const SWord8 s3022 = 127 & s3020;
-  const SWord8 s3023 = s3019 ? s3021 : s3022;
-  const SWord8 s3024 = s2949 ? s3015 : s3023;
-  const SWord8 s3025 = s1 + s3007;
-  const SBool  s3026 = s3025 < s1;
-  const SBool  s3027 = s3025 < s3007;
-  const SBool  s3028 = s3026 || s3027;
-  const SWord8 s3029 = (s3025 >> 1) | (s3025 << 7);
-  const SWord8 s3030 = 128 | s3029;
-  const SWord8 s3031 = 127 & s3029;
-  const SWord8 s3032 = s3028 ? s3030 : s3031;
-  const SWord8 s3033 = (s3032 >> 1) | (s3032 << 7);
-  const SWord8 s3034 = 128 | s3033;
-  const SWord8 s3035 = 127 & s3033;
-  const SWord8 s3036 = s2948 ? s3034 : s3035;
-  const SWord8 s3037 = s1 + s3032;
-  const SBool  s3038 = s3037 < s1;
-  const SBool  s3039 = s3037 < s3032;
-  const SBool  s3040 = s3038 || s3039;
-  const SWord8 s3041 = (s3037 >> 1) | (s3037 << 7);
-  const SWord8 s3042 = 128 | s3041;
-  const SWord8 s3043 = 127 & s3041;
-  const SWord8 s3044 = s3040 ? s3042 : s3043;
-  const SWord8 s3045 = s2949 ? s3036 : s3044;
-  const SWord8 s3046 = s2822 ? s3024 : s3045;
-  const SWord8 s3047 = s2567 ? s2999 : s3046;
-  const SWord8 s3048 = s2059 ? s2939 : s3047;
-  const SWord8 s3049 = s2042 ? s2812 : s3048;
-  const SWord8 s3050 = s16 ? s2557 : s3049;
-  const SWord8 s3051 = s1 + s2044;
-  const SBool  s3052 = (SBool) ((s3051 >> 0) & 1);
-  const SBool  s3053 = false != s3052;
-  const SWord8 s3054 = s3053 ? s2048 : s2049;
-  const SBool  s3055 = (SBool) ((s3054 >> 0) & 1);
-  const SBool  s3056 = false != s3055;
-  const SWord8 s3057 = s3056 ? s2054 : s2055;
-  const SBool  s3058 = (SBool) ((s3057 >> 0) & 1);
-  const SBool  s3059 = false != s3058;
-  const SBool  s3060 = false == s3059;
-  const SBool  s3061 = s3051 < s1;
-  const SBool  s3062 = s3051 < s2044;
-  const SBool  s3063 = s3061 || s3062;
-  const SWord8 s3064 = (s3051 >> 1) | (s3051 << 7);
-  const SWord8 s3065 = 128 | s3064;
-  const SWord8 s3066 = 127 & s3064;
-  const SWord8 s3067 = s3063 ? s3065 : s3066;
-  const SBool  s3068 = (SBool) ((s3067 >> 0) & 1);
-  const SBool  s3069 = false != s3068;
-  const SWord8 s3070 = (s3054 >> 1) | (s3054 << 7);
-  const SWord8 s3071 = 128 | s3070;
-  const SWord8 s3072 = 127 & s3070;
-  const SWord8 s3073 = s3069 ? s3071 : s3072;
-  const SBool  s3074 = (SBool) ((s3073 >> 0) & 1);
-  const SBool  s3075 = false != s3074;
-  const SWord8 s3076 = (s3057 >> 1) | (s3057 << 7);
-  const SWord8 s3077 = 128 | s3076;
-  const SWord8 s3078 = 127 & s3076;
-  const SWord8 s3079 = s3075 ? s3077 : s3078;
-  const SBool  s3080 = (SBool) ((s3079 >> 0) & 1);
-  const SBool  s3081 = false != s3080;
-  const SBool  s3082 = false == s3081;
-  const SWord8 s3083 = (s3067 >> 1) | (s3067 << 7);
-  const SWord8 s3084 = 128 | s3083;
-  const SWord8 s3085 = 127 & s3083;
-  const SWord8 s3086 = s15 ? s3084 : s3085;
-  const SBool  s3087 = (SBool) ((s3086 >> 0) & 1);
-  const SBool  s3088 = false != s3087;
-  const SWord8 s3089 = (s3073 >> 1) | (s3073 << 7);
-  const SWord8 s3090 = 128 | s3089;
-  const SWord8 s3091 = 127 & s3089;
-  const SWord8 s3092 = s3088 ? s3090 : s3091;
-  const SBool  s3093 = (SBool) ((s3092 >> 0) & 1);
-  const SBool  s3094 = false != s3093;
-  const SWord8 s3095 = (s3079 >> 1) | (s3079 << 7);
-  const SWord8 s3096 = 128 | s3095;
-  const SWord8 s3097 = 127 & s3095;
-  const SWord8 s3098 = s3094 ? s3096 : s3097;
-  const SBool  s3099 = (SBool) ((s3098 >> 0) & 1);
-  const SBool  s3100 = false != s3099;
-  const SBool  s3101 = false == s3100;
-  const SWord8 s3102 = (s3086 >> 1) | (s3086 << 7);
-  const SWord8 s3103 = 128 | s3102;
-  const SWord8 s3104 = 127 & s3102;
-  const SWord8 s3105 = s2041 ? s3103 : s3104;
-  const SBool  s3106 = (SBool) ((s3105 >> 0) & 1);
-  const SBool  s3107 = false != s3106;
-  const SWord8 s3108 = (s3092 >> 1) | (s3092 << 7);
-  const SWord8 s3109 = 128 | s3108;
-  const SWord8 s3110 = 127 & s3108;
-  const SWord8 s3111 = s3107 ? s3109 : s3110;
-  const SBool  s3112 = (SBool) ((s3111 >> 0) & 1);
-  const SBool  s3113 = false != s3112;
-  const SWord8 s3114 = (s3098 >> 1) | (s3098 << 7);
-  const SWord8 s3115 = 128 | s3114;
-  const SWord8 s3116 = 127 & s3114;
-  const SWord8 s3117 = s3113 ? s3115 : s3116;
-  const SBool  s3118 = (SBool) ((s3117 >> 0) & 1);
-  const SBool  s3119 = false != s3118;
-  const SBool  s3120 = false == s3119;
-  const SWord8 s3121 = (s3105 >> 1) | (s3105 << 7);
-  const SWord8 s3122 = 128 | s3121;
-  const SWord8 s3123 = 127 & s3121;
-  const SWord8 s3124 = s3059 ? s3122 : s3123;
-  const SWord8 s3125 = (s3124 >> 1) | (s3124 << 7);
-  const SWord8 s3126 = 128 | s3125;
-  const SWord8 s3127 = 127 & s3125;
-  const SWord8 s3128 = s3081 ? s3126 : s3127;
-  const SWord8 s3129 = (s3128 >> 1) | (s3128 << 7);
-  const SWord8 s3130 = 128 | s3129;
-  const SWord8 s3131 = 127 & s3129;
-  const SWord8 s3132 = s3100 ? s3130 : s3131;
-  const SWord8 s3133 = (s3132 >> 1) | (s3132 << 7);
-  const SWord8 s3134 = 128 | s3133;
-  const SWord8 s3135 = 127 & s3133;
-  const SWord8 s3136 = s3119 ? s3134 : s3135;
-  const SWord8 s3137 = s1 + s3132;
-  const SBool  s3138 = s3137 < s1;
-  const SBool  s3139 = s3137 < s3132;
-  const SBool  s3140 = s3138 || s3139;
-  const SWord8 s3141 = (s3137 >> 1) | (s3137 << 7);
-  const SWord8 s3142 = 128 | s3141;
-  const SWord8 s3143 = 127 & s3141;
-  const SWord8 s3144 = s3140 ? s3142 : s3143;
-  const SWord8 s3145 = s3120 ? s3136 : s3144;
-  const SWord8 s3146 = s1 + s3128;
-  const SBool  s3147 = s3146 < s1;
-  const SBool  s3148 = s3146 < s3128;
-  const SBool  s3149 = s3147 || s3148;
-  const SWord8 s3150 = (s3146 >> 1) | (s3146 << 7);
-  const SWord8 s3151 = 128 | s3150;
-  const SWord8 s3152 = 127 & s3150;
-  const SWord8 s3153 = s3149 ? s3151 : s3152;
-  const SWord8 s3154 = (s3153 >> 1) | (s3153 << 7);
-  const SWord8 s3155 = 128 | s3154;
-  const SWord8 s3156 = 127 & s3154;
-  const SWord8 s3157 = s3119 ? s3155 : s3156;
-  const SWord8 s3158 = s1 + s3153;
-  const SBool  s3159 = s3158 < s1;
-  const SBool  s3160 = s3158 < s3153;
-  const SBool  s3161 = s3159 || s3160;
-  const SWord8 s3162 = (s3158 >> 1) | (s3158 << 7);
-  const SWord8 s3163 = 128 | s3162;
-  const SWord8 s3164 = 127 & s3162;
-  const SWord8 s3165 = s3161 ? s3163 : s3164;
-  const SWord8 s3166 = s3120 ? s3157 : s3165;
-  const SWord8 s3167 = s3101 ? s3145 : s3166;
-  const SWord8 s3168 = s1 + s3124;
-  const SBool  s3169 = s3168 < s1;
-  const SBool  s3170 = s3168 < s3124;
-  const SBool  s3171 = s3169 || s3170;
-  const SWord8 s3172 = (s3168 >> 1) | (s3168 << 7);
-  const SWord8 s3173 = 128 | s3172;
-  const SWord8 s3174 = 127 & s3172;
-  const SWord8 s3175 = s3171 ? s3173 : s3174;
-  const SWord8 s3176 = (s3175 >> 1) | (s3175 << 7);
-  const SWord8 s3177 = 128 | s3176;
-  const SWord8 s3178 = 127 & s3176;
-  const SWord8 s3179 = s3100 ? s3177 : s3178;
-  const SWord8 s3180 = (s3179 >> 1) | (s3179 << 7);
-  const SWord8 s3181 = 128 | s3180;
-  const SWord8 s3182 = 127 & s3180;
-  const SWord8 s3183 = s3119 ? s3181 : s3182;
-  const SWord8 s3184 = s1 + s3179;
-  const SBool  s3185 = s3184 < s1;
-  const SBool  s3186 = s3184 < s3179;
-  const SBool  s3187 = s3185 || s3186;
-  const SWord8 s3188 = (s3184 >> 1) | (s3184 << 7);
-  const SWord8 s3189 = 128 | s3188;
-  const SWord8 s3190 = 127 & s3188;
-  const SWord8 s3191 = s3187 ? s3189 : s3190;
-  const SWord8 s3192 = s3120 ? s3183 : s3191;
-  const SWord8 s3193 = s1 + s3175;
-  const SBool  s3194 = s3193 < s1;
-  const SBool  s3195 = s3193 < s3175;
-  const SBool  s3196 = s3194 || s3195;
-  const SWord8 s3197 = (s3193 >> 1) | (s3193 << 7);
-  const SWord8 s3198 = 128 | s3197;
-  const SWord8 s3199 = 127 & s3197;
-  const SWord8 s3200 = s3196 ? s3198 : s3199;
-  const SWord8 s3201 = (s3200 >> 1) | (s3200 << 7);
-  const SWord8 s3202 = 128 | s3201;
-  const SWord8 s3203 = 127 & s3201;
-  const SWord8 s3204 = s3119 ? s3202 : s3203;
-  const SWord8 s3205 = s1 + s3200;
-  const SBool  s3206 = s3205 < s1;
-  const SBool  s3207 = s3205 < s3200;
-  const SBool  s3208 = s3206 || s3207;
-  const SWord8 s3209 = (s3205 >> 1) | (s3205 << 7);
-  const SWord8 s3210 = 128 | s3209;
-  const SWord8 s3211 = 127 & s3209;
-  const SWord8 s3212 = s3208 ? s3210 : s3211;
-  const SWord8 s3213 = s3120 ? s3204 : s3212;
-  const SWord8 s3214 = s3101 ? s3192 : s3213;
-  const SWord8 s3215 = s3082 ? s3167 : s3214;
-  const SWord8 s3216 = s1 + s3105;
-  const SBool  s3217 = (SBool) ((s3216 >> 0) & 1);
-  const SBool  s3218 = false != s3217;
-  const SWord8 s3219 = s3218 ? s3109 : s3110;
-  const SBool  s3220 = (SBool) ((s3219 >> 0) & 1);
-  const SBool  s3221 = false != s3220;
-  const SWord8 s3222 = s3221 ? s3115 : s3116;
-  const SBool  s3223 = (SBool) ((s3222 >> 0) & 1);
-  const SBool  s3224 = false != s3223;
-  const SBool  s3225 = false == s3224;
-  const SBool  s3226 = s3216 < s1;
-  const SBool  s3227 = s3216 < s3105;
-  const SBool  s3228 = s3226 || s3227;
-  const SWord8 s3229 = (s3216 >> 1) | (s3216 << 7);
-  const SWord8 s3230 = 128 | s3229;
-  const SWord8 s3231 = 127 & s3229;
-  const SWord8 s3232 = s3228 ? s3230 : s3231;
-  const SWord8 s3233 = (s3232 >> 1) | (s3232 << 7);
-  const SWord8 s3234 = 128 | s3233;
-  const SWord8 s3235 = 127 & s3233;
-  const SWord8 s3236 = s3081 ? s3234 : s3235;
-  const SWord8 s3237 = (s3236 >> 1) | (s3236 << 7);
-  const SWord8 s3238 = 128 | s3237;
-  const SWord8 s3239 = 127 & s3237;
-  const SWord8 s3240 = s3100 ? s3238 : s3239;
-  const SWord8 s3241 = (s3240 >> 1) | (s3240 << 7);
-  const SWord8 s3242 = 128 | s3241;
-  const SWord8 s3243 = 127 & s3241;
-  const SWord8 s3244 = s3224 ? s3242 : s3243;
-  const SWord8 s3245 = s1 + s3240;
-  const SBool  s3246 = s3245 < s1;
-  const SBool  s3247 = s3245 < s3240;
-  const SBool  s3248 = s3246 || s3247;
-  const SWord8 s3249 = (s3245 >> 1) | (s3245 << 7);
-  const SWord8 s3250 = 128 | s3249;
-  const SWord8 s3251 = 127 & s3249;
-  const SWord8 s3252 = s3248 ? s3250 : s3251;
-  const SWord8 s3253 = s3225 ? s3244 : s3252;
-  const SWord8 s3254 = s1 + s3236;
-  const SBool  s3255 = s3254 < s1;
-  const SBool  s3256 = s3254 < s3236;
-  const SBool  s3257 = s3255 || s3256;
-  const SWord8 s3258 = (s3254 >> 1) | (s3254 << 7);
-  const SWord8 s3259 = 128 | s3258;
-  const SWord8 s3260 = 127 & s3258;
-  const SWord8 s3261 = s3257 ? s3259 : s3260;
-  const SWord8 s3262 = (s3261 >> 1) | (s3261 << 7);
-  const SWord8 s3263 = 128 | s3262;
-  const SWord8 s3264 = 127 & s3262;
-  const SWord8 s3265 = s3224 ? s3263 : s3264;
-  const SWord8 s3266 = s1 + s3261;
-  const SBool  s3267 = s3266 < s1;
-  const SBool  s3268 = s3266 < s3261;
-  const SBool  s3269 = s3267 || s3268;
-  const SWord8 s3270 = (s3266 >> 1) | (s3266 << 7);
-  const SWord8 s3271 = 128 | s3270;
-  const SWord8 s3272 = 127 & s3270;
-  const SWord8 s3273 = s3269 ? s3271 : s3272;
-  const SWord8 s3274 = s3225 ? s3265 : s3273;
-  const SWord8 s3275 = s3101 ? s3253 : s3274;
-  const SWord8 s3276 = s1 + s3232;
-  const SBool  s3277 = s3276 < s1;
-  const SBool  s3278 = s3276 < s3232;
-  const SBool  s3279 = s3277 || s3278;
-  const SWord8 s3280 = (s3276 >> 1) | (s3276 << 7);
-  const SWord8 s3281 = 128 | s3280;
-  const SWord8 s3282 = 127 & s3280;
-  const SWord8 s3283 = s3279 ? s3281 : s3282;
-  const SWord8 s3284 = (s3283 >> 1) | (s3283 << 7);
-  const SWord8 s3285 = 128 | s3284;
-  const SWord8 s3286 = 127 & s3284;
-  const SWord8 s3287 = s3100 ? s3285 : s3286;
-  const SWord8 s3288 = (s3287 >> 1) | (s3287 << 7);
-  const SWord8 s3289 = 128 | s3288;
-  const SWord8 s3290 = 127 & s3288;
-  const SWord8 s3291 = s3224 ? s3289 : s3290;
-  const SWord8 s3292 = s1 + s3287;
-  const SBool  s3293 = s3292 < s1;
-  const SBool  s3294 = s3292 < s3287;
-  const SBool  s3295 = s3293 || s3294;
-  const SWord8 s3296 = (s3292 >> 1) | (s3292 << 7);
-  const SWord8 s3297 = 128 | s3296;
-  const SWord8 s3298 = 127 & s3296;
-  const SWord8 s3299 = s3295 ? s3297 : s3298;
-  const SWord8 s3300 = s3225 ? s3291 : s3299;
-  const SWord8 s3301 = s1 + s3283;
-  const SBool  s3302 = s3301 < s1;
-  const SBool  s3303 = s3301 < s3283;
-  const SBool  s3304 = s3302 || s3303;
-  const SWord8 s3305 = (s3301 >> 1) | (s3301 << 7);
-  const SWord8 s3306 = 128 | s3305;
-  const SWord8 s3307 = 127 & s3305;
-  const SWord8 s3308 = s3304 ? s3306 : s3307;
-  const SWord8 s3309 = (s3308 >> 1) | (s3308 << 7);
-  const SWord8 s3310 = 128 | s3309;
-  const SWord8 s3311 = 127 & s3309;
-  const SWord8 s3312 = s3224 ? s3310 : s3311;
-  const SWord8 s3313 = s1 + s3308;
-  const SBool  s3314 = s3313 < s1;
-  const SBool  s3315 = s3313 < s3308;
-  const SBool  s3316 = s3314 || s3315;
-  const SWord8 s3317 = (s3313 >> 1) | (s3313 << 7);
-  const SWord8 s3318 = 128 | s3317;
-  const SWord8 s3319 = 127 & s3317;
-  const SWord8 s3320 = s3316 ? s3318 : s3319;
-  const SWord8 s3321 = s3225 ? s3312 : s3320;
-  const SWord8 s3322 = s3101 ? s3300 : s3321;
-  const SWord8 s3323 = s3082 ? s3275 : s3322;
-  const SWord8 s3324 = s3060 ? s3215 : s3323;
-  const SWord8 s3325 = s1 + s3086;
-  const SBool  s3326 = (SBool) ((s3325 >> 0) & 1);
-  const SBool  s3327 = false != s3326;
-  const SWord8 s3328 = s3327 ? s3090 : s3091;
-  const SBool  s3329 = (SBool) ((s3328 >> 0) & 1);
-  const SBool  s3330 = false != s3329;
-  const SWord8 s3331 = s3330 ? s3096 : s3097;
-  const SBool  s3332 = (SBool) ((s3331 >> 0) & 1);
-  const SBool  s3333 = false != s3332;
-  const SBool  s3334 = false == s3333;
-  const SBool  s3335 = s3325 < s1;
-  const SBool  s3336 = s3325 < s3086;
-  const SBool  s3337 = s3335 || s3336;
-  const SWord8 s3338 = (s3325 >> 1) | (s3325 << 7);
-  const SWord8 s3339 = 128 | s3338;
-  const SWord8 s3340 = 127 & s3338;
-  const SWord8 s3341 = s3337 ? s3339 : s3340;
-  const SBool  s3342 = (SBool) ((s3341 >> 0) & 1);
-  const SBool  s3343 = false != s3342;
-  const SWord8 s3344 = (s3328 >> 1) | (s3328 << 7);
-  const SWord8 s3345 = 128 | s3344;
-  const SWord8 s3346 = 127 & s3344;
-  const SWord8 s3347 = s3343 ? s3345 : s3346;
-  const SBool  s3348 = (SBool) ((s3347 >> 0) & 1);
-  const SBool  s3349 = false != s3348;
-  const SWord8 s3350 = (s3331 >> 1) | (s3331 << 7);
-  const SWord8 s3351 = 128 | s3350;
-  const SWord8 s3352 = 127 & s3350;
-  const SWord8 s3353 = s3349 ? s3351 : s3352;
-  const SBool  s3354 = (SBool) ((s3353 >> 0) & 1);
-  const SBool  s3355 = false != s3354;
-  const SBool  s3356 = false == s3355;
-  const SWord8 s3357 = (s3341 >> 1) | (s3341 << 7);
-  const SWord8 s3358 = 128 | s3357;
-  const SWord8 s3359 = 127 & s3357;
-  const SWord8 s3360 = s3059 ? s3358 : s3359;
-  const SWord8 s3361 = (s3360 >> 1) | (s3360 << 7);
-  const SWord8 s3362 = 128 | s3361;
-  const SWord8 s3363 = 127 & s3361;
-  const SWord8 s3364 = s3081 ? s3362 : s3363;
-  const SWord8 s3365 = (s3364 >> 1) | (s3364 << 7);
-  const SWord8 s3366 = 128 | s3365;
-  const SWord8 s3367 = 127 & s3365;
-  const SWord8 s3368 = s3333 ? s3366 : s3367;
-  const SWord8 s3369 = (s3368 >> 1) | (s3368 << 7);
-  const SWord8 s3370 = 128 | s3369;
-  const SWord8 s3371 = 127 & s3369;
-  const SWord8 s3372 = s3355 ? s3370 : s3371;
-  const SWord8 s3373 = s1 + s3368;
-  const SBool  s3374 = s3373 < s1;
-  const SBool  s3375 = s3373 < s3368;
-  const SBool  s3376 = s3374 || s3375;
-  const SWord8 s3377 = (s3373 >> 1) | (s3373 << 7);
-  const SWord8 s3378 = 128 | s3377;
-  const SWord8 s3379 = 127 & s3377;
-  const SWord8 s3380 = s3376 ? s3378 : s3379;
-  const SWord8 s3381 = s3356 ? s3372 : s3380;
-  const SWord8 s3382 = s1 + s3364;
-  const SBool  s3383 = s3382 < s1;
-  const SBool  s3384 = s3382 < s3364;
-  const SBool  s3385 = s3383 || s3384;
-  const SWord8 s3386 = (s3382 >> 1) | (s3382 << 7);
-  const SWord8 s3387 = 128 | s3386;
-  const SWord8 s3388 = 127 & s3386;
-  const SWord8 s3389 = s3385 ? s3387 : s3388;
-  const SWord8 s3390 = (s3389 >> 1) | (s3389 << 7);
-  const SWord8 s3391 = 128 | s3390;
-  const SWord8 s3392 = 127 & s3390;
-  const SWord8 s3393 = s3355 ? s3391 : s3392;
-  const SWord8 s3394 = s1 + s3389;
-  const SBool  s3395 = s3394 < s1;
-  const SBool  s3396 = s3394 < s3389;
-  const SBool  s3397 = s3395 || s3396;
-  const SWord8 s3398 = (s3394 >> 1) | (s3394 << 7);
-  const SWord8 s3399 = 128 | s3398;
-  const SWord8 s3400 = 127 & s3398;
-  const SWord8 s3401 = s3397 ? s3399 : s3400;
-  const SWord8 s3402 = s3356 ? s3393 : s3401;
-  const SWord8 s3403 = s3334 ? s3381 : s3402;
-  const SWord8 s3404 = s1 + s3360;
-  const SBool  s3405 = s3404 < s1;
-  const SBool  s3406 = s3404 < s3360;
-  const SBool  s3407 = s3405 || s3406;
-  const SWord8 s3408 = (s3404 >> 1) | (s3404 << 7);
-  const SWord8 s3409 = 128 | s3408;
-  const SWord8 s3410 = 127 & s3408;
-  const SWord8 s3411 = s3407 ? s3409 : s3410;
-  const SWord8 s3412 = (s3411 >> 1) | (s3411 << 7);
-  const SWord8 s3413 = 128 | s3412;
-  const SWord8 s3414 = 127 & s3412;
-  const SWord8 s3415 = s3333 ? s3413 : s3414;
-  const SWord8 s3416 = (s3415 >> 1) | (s3415 << 7);
-  const SWord8 s3417 = 128 | s3416;
-  const SWord8 s3418 = 127 & s3416;
-  const SWord8 s3419 = s3355 ? s3417 : s3418;
-  const SWord8 s3420 = s1 + s3415;
-  const SBool  s3421 = s3420 < s1;
-  const SBool  s3422 = s3420 < s3415;
-  const SBool  s3423 = s3421 || s3422;
-  const SWord8 s3424 = (s3420 >> 1) | (s3420 << 7);
-  const SWord8 s3425 = 128 | s3424;
-  const SWord8 s3426 = 127 & s3424;
-  const SWord8 s3427 = s3423 ? s3425 : s3426;
-  const SWord8 s3428 = s3356 ? s3419 : s3427;
-  const SWord8 s3429 = s1 + s3411;
-  const SBool  s3430 = s3429 < s1;
-  const SBool  s3431 = s3429 < s3411;
-  const SBool  s3432 = s3430 || s3431;
-  const SWord8 s3433 = (s3429 >> 1) | (s3429 << 7);
-  const SWord8 s3434 = 128 | s3433;
-  const SWord8 s3435 = 127 & s3433;
-  const SWord8 s3436 = s3432 ? s3434 : s3435;
-  const SWord8 s3437 = (s3436 >> 1) | (s3436 << 7);
-  const SWord8 s3438 = 128 | s3437;
-  const SWord8 s3439 = 127 & s3437;
-  const SWord8 s3440 = s3355 ? s3438 : s3439;
-  const SWord8 s3441 = s1 + s3436;
-  const SBool  s3442 = s3441 < s1;
-  const SBool  s3443 = s3441 < s3436;
-  const SBool  s3444 = s3442 || s3443;
-  const SWord8 s3445 = (s3441 >> 1) | (s3441 << 7);
-  const SWord8 s3446 = 128 | s3445;
-  const SWord8 s3447 = 127 & s3445;
-  const SWord8 s3448 = s3444 ? s3446 : s3447;
-  const SWord8 s3449 = s3356 ? s3440 : s3448;
-  const SWord8 s3450 = s3334 ? s3428 : s3449;
-  const SWord8 s3451 = s3082 ? s3403 : s3450;
-  const SWord8 s3452 = s1 + s3341;
-  const SBool  s3453 = (SBool) ((s3452 >> 0) & 1);
-  const SBool  s3454 = false != s3453;
-  const SWord8 s3455 = s3454 ? s3345 : s3346;
-  const SBool  s3456 = (SBool) ((s3455 >> 0) & 1);
-  const SBool  s3457 = false != s3456;
-  const SWord8 s3458 = s3457 ? s3351 : s3352;
-  const SBool  s3459 = (SBool) ((s3458 >> 0) & 1);
-  const SBool  s3460 = false != s3459;
-  const SBool  s3461 = false == s3460;
-  const SBool  s3462 = s3452 < s1;
-  const SBool  s3463 = s3452 < s3341;
-  const SBool  s3464 = s3462 || s3463;
-  const SWord8 s3465 = (s3452 >> 1) | (s3452 << 7);
-  const SWord8 s3466 = 128 | s3465;
-  const SWord8 s3467 = 127 & s3465;
-  const SWord8 s3468 = s3464 ? s3466 : s3467;
-  const SWord8 s3469 = (s3468 >> 1) | (s3468 << 7);
-  const SWord8 s3470 = 128 | s3469;
-  const SWord8 s3471 = 127 & s3469;
-  const SWord8 s3472 = s3081 ? s3470 : s3471;
-  const SWord8 s3473 = (s3472 >> 1) | (s3472 << 7);
-  const SWord8 s3474 = 128 | s3473;
-  const SWord8 s3475 = 127 & s3473;
-  const SWord8 s3476 = s3333 ? s3474 : s3475;
-  const SWord8 s3477 = (s3476 >> 1) | (s3476 << 7);
-  const SWord8 s3478 = 128 | s3477;
-  const SWord8 s3479 = 127 & s3477;
-  const SWord8 s3480 = s3460 ? s3478 : s3479;
-  const SWord8 s3481 = s1 + s3476;
-  const SBool  s3482 = s3481 < s1;
-  const SBool  s3483 = s3481 < s3476;
-  const SBool  s3484 = s3482 || s3483;
-  const SWord8 s3485 = (s3481 >> 1) | (s3481 << 7);
-  const SWord8 s3486 = 128 | s3485;
-  const SWord8 s3487 = 127 & s3485;
-  const SWord8 s3488 = s3484 ? s3486 : s3487;
-  const SWord8 s3489 = s3461 ? s3480 : s3488;
-  const SWord8 s3490 = s1 + s3472;
-  const SBool  s3491 = s3490 < s1;
-  const SBool  s3492 = s3490 < s3472;
-  const SBool  s3493 = s3491 || s3492;
-  const SWord8 s3494 = (s3490 >> 1) | (s3490 << 7);
-  const SWord8 s3495 = 128 | s3494;
-  const SWord8 s3496 = 127 & s3494;
-  const SWord8 s3497 = s3493 ? s3495 : s3496;
-  const SWord8 s3498 = (s3497 >> 1) | (s3497 << 7);
-  const SWord8 s3499 = 128 | s3498;
-  const SWord8 s3500 = 127 & s3498;
-  const SWord8 s3501 = s3460 ? s3499 : s3500;
-  const SWord8 s3502 = s1 + s3497;
-  const SBool  s3503 = s3502 < s1;
-  const SBool  s3504 = s3502 < s3497;
-  const SBool  s3505 = s3503 || s3504;
-  const SWord8 s3506 = (s3502 >> 1) | (s3502 << 7);
-  const SWord8 s3507 = 128 | s3506;
-  const SWord8 s3508 = 127 & s3506;
-  const SWord8 s3509 = s3505 ? s3507 : s3508;
-  const SWord8 s3510 = s3461 ? s3501 : s3509;
-  const SWord8 s3511 = s3334 ? s3489 : s3510;
-  const SWord8 s3512 = s1 + s3468;
-  const SBool  s3513 = s3512 < s1;
-  const SBool  s3514 = s3512 < s3468;
-  const SBool  s3515 = s3513 || s3514;
-  const SWord8 s3516 = (s3512 >> 1) | (s3512 << 7);
-  const SWord8 s3517 = 128 | s3516;
-  const SWord8 s3518 = 127 & s3516;
-  const SWord8 s3519 = s3515 ? s3517 : s3518;
-  const SWord8 s3520 = (s3519 >> 1) | (s3519 << 7);
-  const SWord8 s3521 = 128 | s3520;
-  const SWord8 s3522 = 127 & s3520;
-  const SWord8 s3523 = s3333 ? s3521 : s3522;
-  const SWord8 s3524 = (s3523 >> 1) | (s3523 << 7);
-  const SWord8 s3525 = 128 | s3524;
-  const SWord8 s3526 = 127 & s3524;
-  const SWord8 s3527 = s3460 ? s3525 : s3526;
-  const SWord8 s3528 = s1 + s3523;
-  const SBool  s3529 = s3528 < s1;
-  const SBool  s3530 = s3528 < s3523;
-  const SBool  s3531 = s3529 || s3530;
-  const SWord8 s3532 = (s3528 >> 1) | (s3528 << 7);
-  const SWord8 s3533 = 128 | s3532;
-  const SWord8 s3534 = 127 & s3532;
-  const SWord8 s3535 = s3531 ? s3533 : s3534;
-  const SWord8 s3536 = s3461 ? s3527 : s3535;
-  const SWord8 s3537 = s1 + s3519;
-  const SBool  s3538 = s3537 < s1;
-  const SBool  s3539 = s3537 < s3519;
-  const SBool  s3540 = s3538 || s3539;
-  const SWord8 s3541 = (s3537 >> 1) | (s3537 << 7);
-  const SWord8 s3542 = 128 | s3541;
-  const SWord8 s3543 = 127 & s3541;
-  const SWord8 s3544 = s3540 ? s3542 : s3543;
-  const SWord8 s3545 = (s3544 >> 1) | (s3544 << 7);
-  const SWord8 s3546 = 128 | s3545;
-  const SWord8 s3547 = 127 & s3545;
-  const SWord8 s3548 = s3460 ? s3546 : s3547;
-  const SWord8 s3549 = s1 + s3544;
-  const SBool  s3550 = s3549 < s1;
-  const SBool  s3551 = s3549 < s3544;
-  const SBool  s3552 = s3550 || s3551;
-  const SWord8 s3553 = (s3549 >> 1) | (s3549 << 7);
-  const SWord8 s3554 = 128 | s3553;
-  const SWord8 s3555 = 127 & s3553;
-  const SWord8 s3556 = s3552 ? s3554 : s3555;
-  const SWord8 s3557 = s3461 ? s3548 : s3556;
-  const SWord8 s3558 = s3334 ? s3536 : s3557;
-  const SWord8 s3559 = s3082 ? s3511 : s3558;
-  const SWord8 s3560 = s3060 ? s3451 : s3559;
-  const SWord8 s3561 = s2042 ? s3324 : s3560;
-  const SWord8 s3562 = s1 + s3067;
-  const SBool  s3563 = (SBool) ((s3562 >> 0) & 1);
-  const SBool  s3564 = false != s3563;
-  const SWord8 s3565 = s3564 ? s3071 : s3072;
-  const SBool  s3566 = (SBool) ((s3565 >> 0) & 1);
-  const SBool  s3567 = false != s3566;
-  const SWord8 s3568 = s3567 ? s3077 : s3078;
-  const SBool  s3569 = (SBool) ((s3568 >> 0) & 1);
-  const SBool  s3570 = false != s3569;
-  const SBool  s3571 = false == s3570;
-  const SBool  s3572 = s3562 < s1;
-  const SBool  s3573 = s3562 < s3067;
-  const SBool  s3574 = s3572 || s3573;
-  const SWord8 s3575 = (s3562 >> 1) | (s3562 << 7);
-  const SWord8 s3576 = 128 | s3575;
-  const SWord8 s3577 = 127 & s3575;
-  const SWord8 s3578 = s3574 ? s3576 : s3577;
-  const SBool  s3579 = (SBool) ((s3578 >> 0) & 1);
-  const SBool  s3580 = false != s3579;
-  const SWord8 s3581 = (s3565 >> 1) | (s3565 << 7);
-  const SWord8 s3582 = 128 | s3581;
-  const SWord8 s3583 = 127 & s3581;
-  const SWord8 s3584 = s3580 ? s3582 : s3583;
-  const SBool  s3585 = (SBool) ((s3584 >> 0) & 1);
-  const SBool  s3586 = false != s3585;
-  const SWord8 s3587 = (s3568 >> 1) | (s3568 << 7);
-  const SWord8 s3588 = 128 | s3587;
-  const SWord8 s3589 = 127 & s3587;
-  const SWord8 s3590 = s3586 ? s3588 : s3589;
-  const SBool  s3591 = (SBool) ((s3590 >> 0) & 1);
-  const SBool  s3592 = false != s3591;
-  const SBool  s3593 = false == s3592;
-  const SWord8 s3594 = (s3578 >> 1) | (s3578 << 7);
-  const SWord8 s3595 = 128 | s3594;
-  const SWord8 s3596 = 127 & s3594;
-  const SWord8 s3597 = s2041 ? s3595 : s3596;
-  const SBool  s3598 = (SBool) ((s3597 >> 0) & 1);
-  const SBool  s3599 = false != s3598;
-  const SWord8 s3600 = (s3584 >> 1) | (s3584 << 7);
-  const SWord8 s3601 = 128 | s3600;
-  const SWord8 s3602 = 127 & s3600;
-  const SWord8 s3603 = s3599 ? s3601 : s3602;
-  const SBool  s3604 = (SBool) ((s3603 >> 0) & 1);
-  const SBool  s3605 = false != s3604;
-  const SWord8 s3606 = (s3590 >> 1) | (s3590 << 7);
-  const SWord8 s3607 = 128 | s3606;
-  const SWord8 s3608 = 127 & s3606;
-  const SWord8 s3609 = s3605 ? s3607 : s3608;
-  const SBool  s3610 = (SBool) ((s3609 >> 0) & 1);
-  const SBool  s3611 = false != s3610;
-  const SBool  s3612 = false == s3611;
-  const SWord8 s3613 = (s3597 >> 1) | (s3597 << 7);
-  const SWord8 s3614 = 128 | s3613;
-  const SWord8 s3615 = 127 & s3613;
-  const SWord8 s3616 = s3059 ? s3614 : s3615;
-  const SWord8 s3617 = (s3616 >> 1) | (s3616 << 7);
-  const SWord8 s3618 = 128 | s3617;
-  const SWord8 s3619 = 127 & s3617;
-  const SWord8 s3620 = s3570 ? s3618 : s3619;
-  const SWord8 s3621 = (s3620 >> 1) | (s3620 << 7);
-  const SWord8 s3622 = 128 | s3621;
-  const SWord8 s3623 = 127 & s3621;
-  const SWord8 s3624 = s3592 ? s3622 : s3623;
-  const SWord8 s3625 = (s3624 >> 1) | (s3624 << 7);
-  const SWord8 s3626 = 128 | s3625;
-  const SWord8 s3627 = 127 & s3625;
-  const SWord8 s3628 = s3611 ? s3626 : s3627;
-  const SWord8 s3629 = s1 + s3624;
-  const SBool  s3630 = s3629 < s1;
-  const SBool  s3631 = s3629 < s3624;
-  const SBool  s3632 = s3630 || s3631;
-  const SWord8 s3633 = (s3629 >> 1) | (s3629 << 7);
-  const SWord8 s3634 = 128 | s3633;
-  const SWord8 s3635 = 127 & s3633;
-  const SWord8 s3636 = s3632 ? s3634 : s3635;
-  const SWord8 s3637 = s3612 ? s3628 : s3636;
-  const SWord8 s3638 = s1 + s3620;
-  const SBool  s3639 = s3638 < s1;
-  const SBool  s3640 = s3638 < s3620;
-  const SBool  s3641 = s3639 || s3640;
-  const SWord8 s3642 = (s3638 >> 1) | (s3638 << 7);
-  const SWord8 s3643 = 128 | s3642;
-  const SWord8 s3644 = 127 & s3642;
-  const SWord8 s3645 = s3641 ? s3643 : s3644;
-  const SWord8 s3646 = (s3645 >> 1) | (s3645 << 7);
-  const SWord8 s3647 = 128 | s3646;
-  const SWord8 s3648 = 127 & s3646;
-  const SWord8 s3649 = s3611 ? s3647 : s3648;
-  const SWord8 s3650 = s1 + s3645;
-  const SBool  s3651 = s3650 < s1;
-  const SBool  s3652 = s3650 < s3645;
-  const SBool  s3653 = s3651 || s3652;
-  const SWord8 s3654 = (s3650 >> 1) | (s3650 << 7);
-  const SWord8 s3655 = 128 | s3654;
-  const SWord8 s3656 = 127 & s3654;
-  const SWord8 s3657 = s3653 ? s3655 : s3656;
-  const SWord8 s3658 = s3612 ? s3649 : s3657;
-  const SWord8 s3659 = s3593 ? s3637 : s3658;
-  const SWord8 s3660 = s1 + s3616;
-  const SBool  s3661 = s3660 < s1;
-  const SBool  s3662 = s3660 < s3616;
-  const SBool  s3663 = s3661 || s3662;
-  const SWord8 s3664 = (s3660 >> 1) | (s3660 << 7);
-  const SWord8 s3665 = 128 | s3664;
-  const SWord8 s3666 = 127 & s3664;
-  const SWord8 s3667 = s3663 ? s3665 : s3666;
-  const SWord8 s3668 = (s3667 >> 1) | (s3667 << 7);
-  const SWord8 s3669 = 128 | s3668;
-  const SWord8 s3670 = 127 & s3668;
-  const SWord8 s3671 = s3592 ? s3669 : s3670;
-  const SWord8 s3672 = (s3671 >> 1) | (s3671 << 7);
-  const SWord8 s3673 = 128 | s3672;
-  const SWord8 s3674 = 127 & s3672;
-  const SWord8 s3675 = s3611 ? s3673 : s3674;
-  const SWord8 s3676 = s1 + s3671;
-  const SBool  s3677 = s3676 < s1;
-  const SBool  s3678 = s3676 < s3671;
-  const SBool  s3679 = s3677 || s3678;
-  const SWord8 s3680 = (s3676 >> 1) | (s3676 << 7);
-  const SWord8 s3681 = 128 | s3680;
-  const SWord8 s3682 = 127 & s3680;
-  const SWord8 s3683 = s3679 ? s3681 : s3682;
-  const SWord8 s3684 = s3612 ? s3675 : s3683;
-  const SWord8 s3685 = s1 + s3667;
-  const SBool  s3686 = s3685 < s1;
-  const SBool  s3687 = s3685 < s3667;
-  const SBool  s3688 = s3686 || s3687;
-  const SWord8 s3689 = (s3685 >> 1) | (s3685 << 7);
-  const SWord8 s3690 = 128 | s3689;
-  const SWord8 s3691 = 127 & s3689;
-  const SWord8 s3692 = s3688 ? s3690 : s3691;
-  const SWord8 s3693 = (s3692 >> 1) | (s3692 << 7);
-  const SWord8 s3694 = 128 | s3693;
-  const SWord8 s3695 = 127 & s3693;
-  const SWord8 s3696 = s3611 ? s3694 : s3695;
-  const SWord8 s3697 = s1 + s3692;
-  const SBool  s3698 = s3697 < s1;
-  const SBool  s3699 = s3697 < s3692;
-  const SBool  s3700 = s3698 || s3699;
-  const SWord8 s3701 = (s3697 >> 1) | (s3697 << 7);
-  const SWord8 s3702 = 128 | s3701;
-  const SWord8 s3703 = 127 & s3701;
-  const SWord8 s3704 = s3700 ? s3702 : s3703;
-  const SWord8 s3705 = s3612 ? s3696 : s3704;
-  const SWord8 s3706 = s3593 ? s3684 : s3705;
-  const SWord8 s3707 = s3571 ? s3659 : s3706;
-  const SWord8 s3708 = s1 + s3597;
-  const SBool  s3709 = (SBool) ((s3708 >> 0) & 1);
-  const SBool  s3710 = false != s3709;
-  const SWord8 s3711 = s3710 ? s3601 : s3602;
-  const SBool  s3712 = (SBool) ((s3711 >> 0) & 1);
-  const SBool  s3713 = false != s3712;
-  const SWord8 s3714 = s3713 ? s3607 : s3608;
-  const SBool  s3715 = (SBool) ((s3714 >> 0) & 1);
-  const SBool  s3716 = false != s3715;
-  const SBool  s3717 = false == s3716;
-  const SBool  s3718 = s3708 < s1;
-  const SBool  s3719 = s3708 < s3597;
-  const SBool  s3720 = s3718 || s3719;
-  const SWord8 s3721 = (s3708 >> 1) | (s3708 << 7);
-  const SWord8 s3722 = 128 | s3721;
-  const SWord8 s3723 = 127 & s3721;
-  const SWord8 s3724 = s3720 ? s3722 : s3723;
-  const SWord8 s3725 = (s3724 >> 1) | (s3724 << 7);
-  const SWord8 s3726 = 128 | s3725;
-  const SWord8 s3727 = 127 & s3725;
-  const SWord8 s3728 = s3570 ? s3726 : s3727;
-  const SWord8 s3729 = (s3728 >> 1) | (s3728 << 7);
-  const SWord8 s3730 = 128 | s3729;
-  const SWord8 s3731 = 127 & s3729;
-  const SWord8 s3732 = s3592 ? s3730 : s3731;
-  const SWord8 s3733 = (s3732 >> 1) | (s3732 << 7);
-  const SWord8 s3734 = 128 | s3733;
-  const SWord8 s3735 = 127 & s3733;
-  const SWord8 s3736 = s3716 ? s3734 : s3735;
-  const SWord8 s3737 = s1 + s3732;
-  const SBool  s3738 = s3737 < s1;
-  const SBool  s3739 = s3737 < s3732;
-  const SBool  s3740 = s3738 || s3739;
-  const SWord8 s3741 = (s3737 >> 1) | (s3737 << 7);
-  const SWord8 s3742 = 128 | s3741;
-  const SWord8 s3743 = 127 & s3741;
-  const SWord8 s3744 = s3740 ? s3742 : s3743;
-  const SWord8 s3745 = s3717 ? s3736 : s3744;
-  const SWord8 s3746 = s1 + s3728;
-  const SBool  s3747 = s3746 < s1;
-  const SBool  s3748 = s3746 < s3728;
-  const SBool  s3749 = s3747 || s3748;
-  const SWord8 s3750 = (s3746 >> 1) | (s3746 << 7);
-  const SWord8 s3751 = 128 | s3750;
-  const SWord8 s3752 = 127 & s3750;
-  const SWord8 s3753 = s3749 ? s3751 : s3752;
-  const SWord8 s3754 = (s3753 >> 1) | (s3753 << 7);
-  const SWord8 s3755 = 128 | s3754;
-  const SWord8 s3756 = 127 & s3754;
-  const SWord8 s3757 = s3716 ? s3755 : s3756;
-  const SWord8 s3758 = s1 + s3753;
-  const SBool  s3759 = s3758 < s1;
-  const SBool  s3760 = s3758 < s3753;
-  const SBool  s3761 = s3759 || s3760;
-  const SWord8 s3762 = (s3758 >> 1) | (s3758 << 7);
-  const SWord8 s3763 = 128 | s3762;
-  const SWord8 s3764 = 127 & s3762;
-  const SWord8 s3765 = s3761 ? s3763 : s3764;
-  const SWord8 s3766 = s3717 ? s3757 : s3765;
-  const SWord8 s3767 = s3593 ? s3745 : s3766;
-  const SWord8 s3768 = s1 + s3724;
-  const SBool  s3769 = s3768 < s1;
-  const SBool  s3770 = s3768 < s3724;
-  const SBool  s3771 = s3769 || s3770;
-  const SWord8 s3772 = (s3768 >> 1) | (s3768 << 7);
-  const SWord8 s3773 = 128 | s3772;
-  const SWord8 s3774 = 127 & s3772;
-  const SWord8 s3775 = s3771 ? s3773 : s3774;
-  const SWord8 s3776 = (s3775 >> 1) | (s3775 << 7);
-  const SWord8 s3777 = 128 | s3776;
-  const SWord8 s3778 = 127 & s3776;
-  const SWord8 s3779 = s3592 ? s3777 : s3778;
-  const SWord8 s3780 = (s3779 >> 1) | (s3779 << 7);
-  const SWord8 s3781 = 128 | s3780;
-  const SWord8 s3782 = 127 & s3780;
-  const SWord8 s3783 = s3716 ? s3781 : s3782;
-  const SWord8 s3784 = s1 + s3779;
-  const SBool  s3785 = s3784 < s1;
-  const SBool  s3786 = s3784 < s3779;
-  const SBool  s3787 = s3785 || s3786;
-  const SWord8 s3788 = (s3784 >> 1) | (s3784 << 7);
-  const SWord8 s3789 = 128 | s3788;
-  const SWord8 s3790 = 127 & s3788;
-  const SWord8 s3791 = s3787 ? s3789 : s3790;
-  const SWord8 s3792 = s3717 ? s3783 : s3791;
-  const SWord8 s3793 = s1 + s3775;
-  const SBool  s3794 = s3793 < s1;
-  const SBool  s3795 = s3793 < s3775;
-  const SBool  s3796 = s3794 || s3795;
-  const SWord8 s3797 = (s3793 >> 1) | (s3793 << 7);
-  const SWord8 s3798 = 128 | s3797;
-  const SWord8 s3799 = 127 & s3797;
-  const SWord8 s3800 = s3796 ? s3798 : s3799;
-  const SWord8 s3801 = (s3800 >> 1) | (s3800 << 7);
-  const SWord8 s3802 = 128 | s3801;
-  const SWord8 s3803 = 127 & s3801;
-  const SWord8 s3804 = s3716 ? s3802 : s3803;
-  const SWord8 s3805 = s1 + s3800;
-  const SBool  s3806 = s3805 < s1;
-  const SBool  s3807 = s3805 < s3800;
-  const SBool  s3808 = s3806 || s3807;
-  const SWord8 s3809 = (s3805 >> 1) | (s3805 << 7);
-  const SWord8 s3810 = 128 | s3809;
-  const SWord8 s3811 = 127 & s3809;
-  const SWord8 s3812 = s3808 ? s3810 : s3811;
-  const SWord8 s3813 = s3717 ? s3804 : s3812;
-  const SWord8 s3814 = s3593 ? s3792 : s3813;
-  const SWord8 s3815 = s3571 ? s3767 : s3814;
-  const SWord8 s3816 = s3060 ? s3707 : s3815;
-  const SWord8 s3817 = s1 + s3578;
-  const SBool  s3818 = (SBool) ((s3817 >> 0) & 1);
-  const SBool  s3819 = false != s3818;
-  const SWord8 s3820 = s3819 ? s3582 : s3583;
-  const SBool  s3821 = (SBool) ((s3820 >> 0) & 1);
-  const SBool  s3822 = false != s3821;
-  const SWord8 s3823 = s3822 ? s3588 : s3589;
-  const SBool  s3824 = (SBool) ((s3823 >> 0) & 1);
-  const SBool  s3825 = false != s3824;
-  const SBool  s3826 = false == s3825;
-  const SBool  s3827 = s3817 < s1;
-  const SBool  s3828 = s3817 < s3578;
-  const SBool  s3829 = s3827 || s3828;
-  const SWord8 s3830 = (s3817 >> 1) | (s3817 << 7);
-  const SWord8 s3831 = 128 | s3830;
-  const SWord8 s3832 = 127 & s3830;
-  const SWord8 s3833 = s3829 ? s3831 : s3832;
-  const SBool  s3834 = (SBool) ((s3833 >> 0) & 1);
-  const SBool  s3835 = false != s3834;
-  const SWord8 s3836 = (s3820 >> 1) | (s3820 << 7);
-  const SWord8 s3837 = 128 | s3836;
-  const SWord8 s3838 = 127 & s3836;
-  const SWord8 s3839 = s3835 ? s3837 : s3838;
-  const SBool  s3840 = (SBool) ((s3839 >> 0) & 1);
-  const SBool  s3841 = false != s3840;
-  const SWord8 s3842 = (s3823 >> 1) | (s3823 << 7);
-  const SWord8 s3843 = 128 | s3842;
-  const SWord8 s3844 = 127 & s3842;
-  const SWord8 s3845 = s3841 ? s3843 : s3844;
-  const SBool  s3846 = (SBool) ((s3845 >> 0) & 1);
-  const SBool  s3847 = false != s3846;
-  const SBool  s3848 = false == s3847;
-  const SWord8 s3849 = (s3833 >> 1) | (s3833 << 7);
-  const SWord8 s3850 = 128 | s3849;
-  const SWord8 s3851 = 127 & s3849;
-  const SWord8 s3852 = s3059 ? s3850 : s3851;
-  const SWord8 s3853 = (s3852 >> 1) | (s3852 << 7);
-  const SWord8 s3854 = 128 | s3853;
-  const SWord8 s3855 = 127 & s3853;
-  const SWord8 s3856 = s3570 ? s3854 : s3855;
-  const SWord8 s3857 = (s3856 >> 1) | (s3856 << 7);
-  const SWord8 s3858 = 128 | s3857;
-  const SWord8 s3859 = 127 & s3857;
-  const SWord8 s3860 = s3825 ? s3858 : s3859;
-  const SWord8 s3861 = (s3860 >> 1) | (s3860 << 7);
-  const SWord8 s3862 = 128 | s3861;
-  const SWord8 s3863 = 127 & s3861;
-  const SWord8 s3864 = s3847 ? s3862 : s3863;
-  const SWord8 s3865 = s1 + s3860;
-  const SBool  s3866 = s3865 < s1;
-  const SBool  s3867 = s3865 < s3860;
-  const SBool  s3868 = s3866 || s3867;
-  const SWord8 s3869 = (s3865 >> 1) | (s3865 << 7);
-  const SWord8 s3870 = 128 | s3869;
-  const SWord8 s3871 = 127 & s3869;
-  const SWord8 s3872 = s3868 ? s3870 : s3871;
-  const SWord8 s3873 = s3848 ? s3864 : s3872;
-  const SWord8 s3874 = s1 + s3856;
-  const SBool  s3875 = s3874 < s1;
-  const SBool  s3876 = s3874 < s3856;
-  const SBool  s3877 = s3875 || s3876;
-  const SWord8 s3878 = (s3874 >> 1) | (s3874 << 7);
-  const SWord8 s3879 = 128 | s3878;
-  const SWord8 s3880 = 127 & s3878;
-  const SWord8 s3881 = s3877 ? s3879 : s3880;
-  const SWord8 s3882 = (s3881 >> 1) | (s3881 << 7);
-  const SWord8 s3883 = 128 | s3882;
-  const SWord8 s3884 = 127 & s3882;
-  const SWord8 s3885 = s3847 ? s3883 : s3884;
-  const SWord8 s3886 = s1 + s3881;
-  const SBool  s3887 = s3886 < s1;
-  const SBool  s3888 = s3886 < s3881;
-  const SBool  s3889 = s3887 || s3888;
-  const SWord8 s3890 = (s3886 >> 1) | (s3886 << 7);
-  const SWord8 s3891 = 128 | s3890;
-  const SWord8 s3892 = 127 & s3890;
-  const SWord8 s3893 = s3889 ? s3891 : s3892;
-  const SWord8 s3894 = s3848 ? s3885 : s3893;
-  const SWord8 s3895 = s3826 ? s3873 : s3894;
-  const SWord8 s3896 = s1 + s3852;
-  const SBool  s3897 = s3896 < s1;
-  const SBool  s3898 = s3896 < s3852;
-  const SBool  s3899 = s3897 || s3898;
-  const SWord8 s3900 = (s3896 >> 1) | (s3896 << 7);
-  const SWord8 s3901 = 128 | s3900;
-  const SWord8 s3902 = 127 & s3900;
-  const SWord8 s3903 = s3899 ? s3901 : s3902;
-  const SWord8 s3904 = (s3903 >> 1) | (s3903 << 7);
-  const SWord8 s3905 = 128 | s3904;
-  const SWord8 s3906 = 127 & s3904;
-  const SWord8 s3907 = s3825 ? s3905 : s3906;
-  const SWord8 s3908 = (s3907 >> 1) | (s3907 << 7);
-  const SWord8 s3909 = 128 | s3908;
-  const SWord8 s3910 = 127 & s3908;
-  const SWord8 s3911 = s3847 ? s3909 : s3910;
-  const SWord8 s3912 = s1 + s3907;
-  const SBool  s3913 = s3912 < s1;
-  const SBool  s3914 = s3912 < s3907;
-  const SBool  s3915 = s3913 || s3914;
-  const SWord8 s3916 = (s3912 >> 1) | (s3912 << 7);
-  const SWord8 s3917 = 128 | s3916;
-  const SWord8 s3918 = 127 & s3916;
-  const SWord8 s3919 = s3915 ? s3917 : s3918;
-  const SWord8 s3920 = s3848 ? s3911 : s3919;
-  const SWord8 s3921 = s1 + s3903;
-  const SBool  s3922 = s3921 < s1;
-  const SBool  s3923 = s3921 < s3903;
-  const SBool  s3924 = s3922 || s3923;
-  const SWord8 s3925 = (s3921 >> 1) | (s3921 << 7);
-  const SWord8 s3926 = 128 | s3925;
-  const SWord8 s3927 = 127 & s3925;
-  const SWord8 s3928 = s3924 ? s3926 : s3927;
-  const SWord8 s3929 = (s3928 >> 1) | (s3928 << 7);
-  const SWord8 s3930 = 128 | s3929;
-  const SWord8 s3931 = 127 & s3929;
-  const SWord8 s3932 = s3847 ? s3930 : s3931;
-  const SWord8 s3933 = s1 + s3928;
-  const SBool  s3934 = s3933 < s1;
-  const SBool  s3935 = s3933 < s3928;
-  const SBool  s3936 = s3934 || s3935;
-  const SWord8 s3937 = (s3933 >> 1) | (s3933 << 7);
-  const SWord8 s3938 = 128 | s3937;
-  const SWord8 s3939 = 127 & s3937;
-  const SWord8 s3940 = s3936 ? s3938 : s3939;
-  const SWord8 s3941 = s3848 ? s3932 : s3940;
-  const SWord8 s3942 = s3826 ? s3920 : s3941;
-  const SWord8 s3943 = s3571 ? s3895 : s3942;
-  const SWord8 s3944 = s1 + s3833;
-  const SBool  s3945 = (SBool) ((s3944 >> 0) & 1);
-  const SBool  s3946 = false != s3945;
-  const SWord8 s3947 = s3946 ? s3837 : s3838;
-  const SBool  s3948 = (SBool) ((s3947 >> 0) & 1);
-  const SBool  s3949 = false != s3948;
-  const SWord8 s3950 = s3949 ? s3843 : s3844;
-  const SBool  s3951 = (SBool) ((s3950 >> 0) & 1);
-  const SBool  s3952 = false != s3951;
-  const SBool  s3953 = false == s3952;
-  const SBool  s3954 = s3944 < s1;
-  const SBool  s3955 = s3944 < s3833;
-  const SBool  s3956 = s3954 || s3955;
-  const SWord8 s3957 = (s3944 >> 1) | (s3944 << 7);
-  const SWord8 s3958 = 128 | s3957;
-  const SWord8 s3959 = 127 & s3957;
-  const SWord8 s3960 = s3956 ? s3958 : s3959;
-  const SWord8 s3961 = (s3960 >> 1) | (s3960 << 7);
-  const SWord8 s3962 = 128 | s3961;
-  const SWord8 s3963 = 127 & s3961;
-  const SWord8 s3964 = s3570 ? s3962 : s3963;
-  const SWord8 s3965 = (s3964 >> 1) | (s3964 << 7);
-  const SWord8 s3966 = 128 | s3965;
-  const SWord8 s3967 = 127 & s3965;
-  const SWord8 s3968 = s3825 ? s3966 : s3967;
-  const SWord8 s3969 = (s3968 >> 1) | (s3968 << 7);
-  const SWord8 s3970 = 128 | s3969;
-  const SWord8 s3971 = 127 & s3969;
-  const SWord8 s3972 = s3952 ? s3970 : s3971;
-  const SWord8 s3973 = s1 + s3968;
-  const SBool  s3974 = s3973 < s1;
-  const SBool  s3975 = s3973 < s3968;
-  const SBool  s3976 = s3974 || s3975;
-  const SWord8 s3977 = (s3973 >> 1) | (s3973 << 7);
-  const SWord8 s3978 = 128 | s3977;
-  const SWord8 s3979 = 127 & s3977;
-  const SWord8 s3980 = s3976 ? s3978 : s3979;
-  const SWord8 s3981 = s3953 ? s3972 : s3980;
-  const SWord8 s3982 = s1 + s3964;
-  const SBool  s3983 = s3982 < s1;
-  const SBool  s3984 = s3982 < s3964;
-  const SBool  s3985 = s3983 || s3984;
-  const SWord8 s3986 = (s3982 >> 1) | (s3982 << 7);
-  const SWord8 s3987 = 128 | s3986;
-  const SWord8 s3988 = 127 & s3986;
-  const SWord8 s3989 = s3985 ? s3987 : s3988;
-  const SWord8 s3990 = (s3989 >> 1) | (s3989 << 7);
-  const SWord8 s3991 = 128 | s3990;
-  const SWord8 s3992 = 127 & s3990;
-  const SWord8 s3993 = s3952 ? s3991 : s3992;
-  const SWord8 s3994 = s1 + s3989;
-  const SBool  s3995 = s3994 < s1;
-  const SBool  s3996 = s3994 < s3989;
-  const SBool  s3997 = s3995 || s3996;
-  const SWord8 s3998 = (s3994 >> 1) | (s3994 << 7);
-  const SWord8 s3999 = 128 | s3998;
-  const SWord8 s4000 = 127 & s3998;
-  const SWord8 s4001 = s3997 ? s3999 : s4000;
-  const SWord8 s4002 = s3953 ? s3993 : s4001;
-  const SWord8 s4003 = s3826 ? s3981 : s4002;
-  const SWord8 s4004 = s1 + s3960;
-  const SBool  s4005 = s4004 < s1;
-  const SBool  s4006 = s4004 < s3960;
-  const SBool  s4007 = s4005 || s4006;
-  const SWord8 s4008 = (s4004 >> 1) | (s4004 << 7);
-  const SWord8 s4009 = 128 | s4008;
-  const SWord8 s4010 = 127 & s4008;
-  const SWord8 s4011 = s4007 ? s4009 : s4010;
-  const SWord8 s4012 = (s4011 >> 1) | (s4011 << 7);
-  const SWord8 s4013 = 128 | s4012;
-  const SWord8 s4014 = 127 & s4012;
-  const SWord8 s4015 = s3825 ? s4013 : s4014;
-  const SWord8 s4016 = (s4015 >> 1) | (s4015 << 7);
-  const SWord8 s4017 = 128 | s4016;
-  const SWord8 s4018 = 127 & s4016;
-  const SWord8 s4019 = s3952 ? s4017 : s4018;
-  const SWord8 s4020 = s1 + s4015;
-  const SBool  s4021 = s4020 < s1;
-  const SBool  s4022 = s4020 < s4015;
-  const SBool  s4023 = s4021 || s4022;
-  const SWord8 s4024 = (s4020 >> 1) | (s4020 << 7);
-  const SWord8 s4025 = 128 | s4024;
-  const SWord8 s4026 = 127 & s4024;
-  const SWord8 s4027 = s4023 ? s4025 : s4026;
-  const SWord8 s4028 = s3953 ? s4019 : s4027;
-  const SWord8 s4029 = s1 + s4011;
-  const SBool  s4030 = s4029 < s1;
-  const SBool  s4031 = s4029 < s4011;
-  const SBool  s4032 = s4030 || s4031;
-  const SWord8 s4033 = (s4029 >> 1) | (s4029 << 7);
-  const SWord8 s4034 = 128 | s4033;
-  const SWord8 s4035 = 127 & s4033;
-  const SWord8 s4036 = s4032 ? s4034 : s4035;
-  const SWord8 s4037 = (s4036 >> 1) | (s4036 << 7);
-  const SWord8 s4038 = 128 | s4037;
-  const SWord8 s4039 = 127 & s4037;
-  const SWord8 s4040 = s3952 ? s4038 : s4039;
-  const SWord8 s4041 = s1 + s4036;
-  const SBool  s4042 = s4041 < s1;
-  const SBool  s4043 = s4041 < s4036;
-  const SBool  s4044 = s4042 || s4043;
-  const SWord8 s4045 = (s4041 >> 1) | (s4041 << 7);
-  const SWord8 s4046 = 128 | s4045;
-  const SWord8 s4047 = 127 & s4045;
-  const SWord8 s4048 = s4044 ? s4046 : s4047;
-  const SWord8 s4049 = s3953 ? s4040 : s4048;
-  const SWord8 s4050 = s3826 ? s4028 : s4049;
-  const SWord8 s4051 = s3571 ? s4003 : s4050;
-  const SWord8 s4052 = s3060 ? s3943 : s4051;
-  const SWord8 s4053 = s2042 ? s3816 : s4052;
-  const SWord8 s4054 = s16 ? s3561 : s4053;
-  const SWord8 s4055 = s11 ? s3050 : s4054;
-  const SWord8 s4056 = s5 ? s2032 : s4055;
-  const SBool  s4057 = (SBool) ((s105 >> 0) & 1);
-  const SBool  s4058 = false != s4057;
-  const SBool  s4059 = (SBool) ((s101 >> 0) & 1);
-  const SBool  s4060 = false != s4059;
-  const SBool  s4061 = (SBool) ((s97 >> 0) & 1);
-  const SBool  s4062 = false != s4061;
-  const SWord8 s4063 = (s84 >> 1) | (s84 << 7);
-  const SWord8 s4064 = 128 | s4063;
-  const SWord8 s4065 = 127 & s4063;
-  const SWord8 s4066 = s4062 ? s4064 : s4065;
-  const SWord8 s4067 = (s4066 >> 1) | (s4066 << 7);
-  const SWord8 s4068 = 128 | s4067;
-  const SWord8 s4069 = 127 & s4067;
-  const SWord8 s4070 = s4060 ? s4068 : s4069;
-  const SWord8 s4071 = (s4070 >> 1) | (s4070 << 7);
-  const SWord8 s4072 = 128 | s4071;
-  const SWord8 s4073 = 127 & s4071;
-  const SWord8 s4074 = s4058 ? s4072 : s4073;
-  const SBool  s4075 = (SBool) ((s110 >> 0) & 1);
-  const SBool  s4076 = false != s4075;
-  const SWord8 s4077 = s4076 ? s4072 : s4073;
-  const SWord8 s4078 = s93 ? s4074 : s4077;
-  const SBool  s4079 = (SBool) ((s126 >> 0) & 1);
-  const SBool  s4080 = false != s4079;
-  const SBool  s4081 = (SBool) ((s119 >> 0) & 1);
-  const SBool  s4082 = false != s4081;
-  const SWord8 s4083 = s4082 ? s4068 : s4069;
-  const SWord8 s4084 = (s4083 >> 1) | (s4083 << 7);
-  const SWord8 s4085 = 128 | s4084;
-  const SWord8 s4086 = 127 & s4084;
-  const SWord8 s4087 = s4080 ? s4085 : s4086;
-  const SBool  s4088 = (SBool) ((s131 >> 0) & 1);
-  const SBool  s4089 = false != s4088;
-  const SWord8 s4090 = s4089 ? s4085 : s4086;
-  const SWord8 s4091 = s93 ? s4087 : s4090;
-  const SWord8 s4092 = s74 ? s4078 : s4091;
-  const SBool  s4093 = (SBool) ((s152 >> 0) & 1);
-  const SBool  s4094 = false != s4093;
-  const SBool  s4095 = (SBool) ((s148 >> 0) & 1);
-  const SBool  s4096 = false != s4095;
-  const SBool  s4097 = (SBool) ((s141 >> 0) & 1);
-  const SBool  s4098 = false != s4097;
-  const SWord8 s4099 = s4098 ? s4064 : s4065;
-  const SWord8 s4100 = (s4099 >> 1) | (s4099 << 7);
-  const SWord8 s4101 = 128 | s4100;
-  const SWord8 s4102 = 127 & s4100;
-  const SWord8 s4103 = s4096 ? s4101 : s4102;
-  const SWord8 s4104 = (s4103 >> 1) | (s4103 << 7);
-  const SWord8 s4105 = 128 | s4104;
-  const SWord8 s4106 = 127 & s4104;
-  const SWord8 s4107 = s4094 ? s4105 : s4106;
-  const SBool  s4108 = (SBool) ((s157 >> 0) & 1);
-  const SBool  s4109 = false != s4108;
-  const SWord8 s4110 = s4109 ? s4105 : s4106;
-  const SWord8 s4111 = s93 ? s4107 : s4110;
-  const SBool  s4112 = (SBool) ((s173 >> 0) & 1);
-  const SBool  s4113 = false != s4112;
-  const SBool  s4114 = (SBool) ((s166 >> 0) & 1);
-  const SBool  s4115 = false != s4114;
-  const SWord8 s4116 = s4115 ? s4101 : s4102;
-  const SWord8 s4117 = (s4116 >> 1) | (s4116 << 7);
-  const SWord8 s4118 = 128 | s4117;
-  const SWord8 s4119 = 127 & s4117;
-  const SWord8 s4120 = s4113 ? s4118 : s4119;
-  const SBool  s4121 = (SBool) ((s178 >> 0) & 1);
-  const SBool  s4122 = false != s4121;
-  const SWord8 s4123 = s4122 ? s4118 : s4119;
-  const SWord8 s4124 = s93 ? s4120 : s4123;
-  const SWord8 s4125 = s74 ? s4111 : s4124;
-  const SWord8 s4126 = s55 ? s4092 : s4125;
-  const SBool  s4127 = (SBool) ((s213 >> 0) & 1);
-  const SBool  s4128 = false != s4127;
-  const SBool  s4129 = (SBool) ((s209 >> 0) & 1);
-  const SBool  s4130 = false != s4129;
-  const SBool  s4131 = (SBool) ((s205 >> 0) & 1);
-  const SBool  s4132 = false != s4131;
-  const SWord8 s4133 = (s192 >> 1) | (s192 << 7);
-  const SWord8 s4134 = 128 | s4133;
-  const SWord8 s4135 = 127 & s4133;
-  const SWord8 s4136 = s4132 ? s4134 : s4135;
-  const SWord8 s4137 = (s4136 >> 1) | (s4136 << 7);
-  const SWord8 s4138 = 128 | s4137;
-  const SWord8 s4139 = 127 & s4137;
-  const SWord8 s4140 = s4130 ? s4138 : s4139;
-  const SWord8 s4141 = (s4140 >> 1) | (s4140 << 7);
-  const SWord8 s4142 = 128 | s4141;
-  const SWord8 s4143 = 127 & s4141;
-  const SWord8 s4144 = s4128 ? s4142 : s4143;
-  const SBool  s4145 = (SBool) ((s218 >> 0) & 1);
-  const SBool  s4146 = false != s4145;
-  const SWord8 s4147 = s4146 ? s4142 : s4143;
-  const SWord8 s4148 = s198 ? s4144 : s4147;
-  const SBool  s4149 = (SBool) ((s234 >> 0) & 1);
-  const SBool  s4150 = false != s4149;
-  const SBool  s4151 = (SBool) ((s227 >> 0) & 1);
-  const SBool  s4152 = false != s4151;
-  const SWord8 s4153 = s4152 ? s4138 : s4139;
-  const SWord8 s4154 = (s4153 >> 1) | (s4153 << 7);
-  const SWord8 s4155 = 128 | s4154;
-  const SWord8 s4156 = 127 & s4154;
-  const SWord8 s4157 = s4150 ? s4155 : s4156;
-  const SBool  s4158 = (SBool) ((s239 >> 0) & 1);
-  const SBool  s4159 = false != s4158;
-  const SWord8 s4160 = s4159 ? s4155 : s4156;
-  const SWord8 s4161 = s198 ? s4157 : s4160;
-  const SWord8 s4162 = s74 ? s4148 : s4161;
-  const SBool  s4163 = (SBool) ((s260 >> 0) & 1);
-  const SBool  s4164 = false != s4163;
-  const SBool  s4165 = (SBool) ((s256 >> 0) & 1);
-  const SBool  s4166 = false != s4165;
-  const SBool  s4167 = (SBool) ((s249 >> 0) & 1);
-  const SBool  s4168 = false != s4167;
-  const SWord8 s4169 = s4168 ? s4134 : s4135;
-  const SWord8 s4170 = (s4169 >> 1) | (s4169 << 7);
-  const SWord8 s4171 = 128 | s4170;
-  const SWord8 s4172 = 127 & s4170;
-  const SWord8 s4173 = s4166 ? s4171 : s4172;
-  const SWord8 s4174 = (s4173 >> 1) | (s4173 << 7);
-  const SWord8 s4175 = 128 | s4174;
-  const SWord8 s4176 = 127 & s4174;
-  const SWord8 s4177 = s4164 ? s4175 : s4176;
-  const SBool  s4178 = (SBool) ((s265 >> 0) & 1);
-  const SBool  s4179 = false != s4178;
-  const SWord8 s4180 = s4179 ? s4175 : s4176;
-  const SWord8 s4181 = s198 ? s4177 : s4180;
-  const SBool  s4182 = (SBool) ((s281 >> 0) & 1);
-  const SBool  s4183 = false != s4182;
-  const SBool  s4184 = (SBool) ((s274 >> 0) & 1);
-  const SBool  s4185 = false != s4184;
-  const SWord8 s4186 = s4185 ? s4171 : s4172;
-  const SWord8 s4187 = (s4186 >> 1) | (s4186 << 7);
-  const SWord8 s4188 = 128 | s4187;
-  const SWord8 s4189 = 127 & s4187;
-  const SWord8 s4190 = s4183 ? s4188 : s4189;
-  const SBool  s4191 = (SBool) ((s286 >> 0) & 1);
-  const SBool  s4192 = false != s4191;
-  const SWord8 s4193 = s4192 ? s4188 : s4189;
-  const SWord8 s4194 = s198 ? s4190 : s4193;
-  const SWord8 s4195 = s74 ? s4181 : s4194;
-  const SWord8 s4196 = s55 ? s4162 : s4195;
-  const SWord8 s4197 = s36 ? s4126 : s4196;
-  const SBool  s4198 = (SBool) ((s341 >> 0) & 1);
-  const SBool  s4199 = false != s4198;
-  const SBool  s4200 = (SBool) ((s337 >> 0) & 1);
-  const SBool  s4201 = false != s4200;
-  const SBool  s4202 = (SBool) ((s333 >> 0) & 1);
-  const SBool  s4203 = false != s4202;
-  const SWord8 s4204 = (s320 >> 1) | (s320 << 7);
-  const SWord8 s4205 = 128 | s4204;
-  const SWord8 s4206 = 127 & s4204;
-  const SWord8 s4207 = s4203 ? s4205 : s4206;
-  const SWord8 s4208 = (s4207 >> 1) | (s4207 << 7);
-  const SWord8 s4209 = 128 | s4208;
-  const SWord8 s4210 = 127 & s4208;
-  const SWord8 s4211 = s4201 ? s4209 : s4210;
-  const SWord8 s4212 = (s4211 >> 1) | (s4211 << 7);
-  const SWord8 s4213 = 128 | s4212;
-  const SWord8 s4214 = 127 & s4212;
-  const SWord8 s4215 = s4199 ? s4213 : s4214;
-  const SBool  s4216 = (SBool) ((s346 >> 0) & 1);
-  const SBool  s4217 = false != s4216;
-  const SWord8 s4218 = s4217 ? s4213 : s4214;
-  const SWord8 s4219 = s329 ? s4215 : s4218;
-  const SBool  s4220 = (SBool) ((s362 >> 0) & 1);
-  const SBool  s4221 = false != s4220;
-  const SBool  s4222 = (SBool) ((s355 >> 0) & 1);
-  const SBool  s4223 = false != s4222;
-  const SWord8 s4224 = s4223 ? s4209 : s4210;
-  const SWord8 s4225 = (s4224 >> 1) | (s4224 << 7);
-  const SWord8 s4226 = 128 | s4225;
-  const SWord8 s4227 = 127 & s4225;
-  const SWord8 s4228 = s4221 ? s4226 : s4227;
-  const SBool  s4229 = (SBool) ((s367 >> 0) & 1);
-  const SBool  s4230 = false != s4229;
-  const SWord8 s4231 = s4230 ? s4226 : s4227;
-  const SWord8 s4232 = s329 ? s4228 : s4231;
-  const SWord8 s4233 = s307 ? s4219 : s4232;
-  const SBool  s4234 = (SBool) ((s388 >> 0) & 1);
-  const SBool  s4235 = false != s4234;
-  const SBool  s4236 = (SBool) ((s384 >> 0) & 1);
-  const SBool  s4237 = false != s4236;
-  const SBool  s4238 = (SBool) ((s377 >> 0) & 1);
-  const SBool  s4239 = false != s4238;
-  const SWord8 s4240 = s4239 ? s4205 : s4206;
-  const SWord8 s4241 = (s4240 >> 1) | (s4240 << 7);
-  const SWord8 s4242 = 128 | s4241;
-  const SWord8 s4243 = 127 & s4241;
-  const SWord8 s4244 = s4237 ? s4242 : s4243;
-  const SWord8 s4245 = (s4244 >> 1) | (s4244 << 7);
-  const SWord8 s4246 = 128 | s4245;
-  const SWord8 s4247 = 127 & s4245;
-  const SWord8 s4248 = s4235 ? s4246 : s4247;
-  const SBool  s4249 = (SBool) ((s393 >> 0) & 1);
-  const SBool  s4250 = false != s4249;
-  const SWord8 s4251 = s4250 ? s4246 : s4247;
-  const SWord8 s4252 = s329 ? s4248 : s4251;
-  const SBool  s4253 = (SBool) ((s409 >> 0) & 1);
-  const SBool  s4254 = false != s4253;
-  const SBool  s4255 = (SBool) ((s402 >> 0) & 1);
-  const SBool  s4256 = false != s4255;
-  const SWord8 s4257 = s4256 ? s4242 : s4243;
-  const SWord8 s4258 = (s4257 >> 1) | (s4257 << 7);
-  const SWord8 s4259 = 128 | s4258;
-  const SWord8 s4260 = 127 & s4258;
-  const SWord8 s4261 = s4254 ? s4259 : s4260;
-  const SBool  s4262 = (SBool) ((s414 >> 0) & 1);
-  const SBool  s4263 = false != s4262;
-  const SWord8 s4264 = s4263 ? s4259 : s4260;
-  const SWord8 s4265 = s329 ? s4261 : s4264;
-  const SWord8 s4266 = s307 ? s4252 : s4265;
-  const SWord8 s4267 = s55 ? s4233 : s4266;
-  const SBool  s4268 = (SBool) ((s449 >> 0) & 1);
-  const SBool  s4269 = false != s4268;
-  const SBool  s4270 = (SBool) ((s445 >> 0) & 1);
-  const SBool  s4271 = false != s4270;
-  const SBool  s4272 = (SBool) ((s441 >> 0) & 1);
-  const SBool  s4273 = false != s4272;
-  const SWord8 s4274 = (s428 >> 1) | (s428 << 7);
-  const SWord8 s4275 = 128 | s4274;
-  const SWord8 s4276 = 127 & s4274;
-  const SWord8 s4277 = s4273 ? s4275 : s4276;
-  const SWord8 s4278 = (s4277 >> 1) | (s4277 << 7);
-  const SWord8 s4279 = 128 | s4278;
-  const SWord8 s4280 = 127 & s4278;
-  const SWord8 s4281 = s4271 ? s4279 : s4280;
-  const SWord8 s4282 = (s4281 >> 1) | (s4281 << 7);
-  const SWord8 s4283 = 128 | s4282;
-  const SWord8 s4284 = 127 & s4282;
-  const SWord8 s4285 = s4269 ? s4283 : s4284;
-  const SBool  s4286 = (SBool) ((s454 >> 0) & 1);
-  const SBool  s4287 = false != s4286;
-  const SWord8 s4288 = s4287 ? s4283 : s4284;
-  const SWord8 s4289 = s434 ? s4285 : s4288;
-  const SBool  s4290 = (SBool) ((s470 >> 0) & 1);
-  const SBool  s4291 = false != s4290;
-  const SBool  s4292 = (SBool) ((s463 >> 0) & 1);
-  const SBool  s4293 = false != s4292;
-  const SWord8 s4294 = s4293 ? s4279 : s4280;
-  const SWord8 s4295 = (s4294 >> 1) | (s4294 << 7);
-  const SWord8 s4296 = 128 | s4295;
-  const SWord8 s4297 = 127 & s4295;
-  const SWord8 s4298 = s4291 ? s4296 : s4297;
-  const SBool  s4299 = (SBool) ((s475 >> 0) & 1);
-  const SBool  s4300 = false != s4299;
-  const SWord8 s4301 = s4300 ? s4296 : s4297;
-  const SWord8 s4302 = s434 ? s4298 : s4301;
-  const SWord8 s4303 = s307 ? s4289 : s4302;
-  const SBool  s4304 = (SBool) ((s496 >> 0) & 1);
-  const SBool  s4305 = false != s4304;
-  const SBool  s4306 = (SBool) ((s492 >> 0) & 1);
-  const SBool  s4307 = false != s4306;
-  const SBool  s4308 = (SBool) ((s485 >> 0) & 1);
-  const SBool  s4309 = false != s4308;
-  const SWord8 s4310 = s4309 ? s4275 : s4276;
-  const SWord8 s4311 = (s4310 >> 1) | (s4310 << 7);
-  const SWord8 s4312 = 128 | s4311;
-  const SWord8 s4313 = 127 & s4311;
-  const SWord8 s4314 = s4307 ? s4312 : s4313;
-  const SWord8 s4315 = (s4314 >> 1) | (s4314 << 7);
-  const SWord8 s4316 = 128 | s4315;
-  const SWord8 s4317 = 127 & s4315;
-  const SWord8 s4318 = s4305 ? s4316 : s4317;
-  const SBool  s4319 = (SBool) ((s501 >> 0) & 1);
-  const SBool  s4320 = false != s4319;
-  const SWord8 s4321 = s4320 ? s4316 : s4317;
-  const SWord8 s4322 = s434 ? s4318 : s4321;
-  const SBool  s4323 = (SBool) ((s517 >> 0) & 1);
-  const SBool  s4324 = false != s4323;
-  const SBool  s4325 = (SBool) ((s510 >> 0) & 1);
-  const SBool  s4326 = false != s4325;
-  const SWord8 s4327 = s4326 ? s4312 : s4313;
-  const SWord8 s4328 = (s4327 >> 1) | (s4327 << 7);
-  const SWord8 s4329 = 128 | s4328;
-  const SWord8 s4330 = 127 & s4328;
-  const SWord8 s4331 = s4324 ? s4329 : s4330;
-  const SBool  s4332 = (SBool) ((s522 >> 0) & 1);
-  const SBool  s4333 = false != s4332;
-  const SWord8 s4334 = s4333 ? s4329 : s4330;
-  const SWord8 s4335 = s434 ? s4331 : s4334;
-  const SWord8 s4336 = s307 ? s4322 : s4335;
-  const SWord8 s4337 = s55 ? s4303 : s4336;
-  const SWord8 s4338 = s36 ? s4267 : s4337;
-  const SWord8 s4339 = s21 ? s4197 : s4338;
-  const SBool  s4340 = (SBool) ((s597 >> 0) & 1);
-  const SBool  s4341 = false != s4340;
-  const SBool  s4342 = (SBool) ((s593 >> 0) & 1);
-  const SBool  s4343 = false != s4342;
-  const SBool  s4344 = (SBool) ((s589 >> 0) & 1);
-  const SBool  s4345 = false != s4344;
-  const SWord8 s4346 = (s576 >> 1) | (s576 << 7);
-  const SWord8 s4347 = 128 | s4346;
-  const SWord8 s4348 = 127 & s4346;
-  const SWord8 s4349 = s4345 ? s4347 : s4348;
-  const SWord8 s4350 = (s4349 >> 1) | (s4349 << 7);
-  const SWord8 s4351 = 128 | s4350;
-  const SWord8 s4352 = 127 & s4350;
-  const SWord8 s4353 = s4343 ? s4351 : s4352;
-  const SWord8 s4354 = (s4353 >> 1) | (s4353 << 7);
-  const SWord8 s4355 = 128 | s4354;
-  const SWord8 s4356 = 127 & s4354;
-  const SWord8 s4357 = s4341 ? s4355 : s4356;
-  const SBool  s4358 = (SBool) ((s602 >> 0) & 1);
-  const SBool  s4359 = false != s4358;
-  const SWord8 s4360 = s4359 ? s4355 : s4356;
-  const SWord8 s4361 = s585 ? s4357 : s4360;
-  const SBool  s4362 = (SBool) ((s618 >> 0) & 1);
-  const SBool  s4363 = false != s4362;
-  const SBool  s4364 = (SBool) ((s611 >> 0) & 1);
-  const SBool  s4365 = false != s4364;
-  const SWord8 s4366 = s4365 ? s4351 : s4352;
-  const SWord8 s4367 = (s4366 >> 1) | (s4366 << 7);
-  const SWord8 s4368 = 128 | s4367;
-  const SWord8 s4369 = 127 & s4367;
-  const SWord8 s4370 = s4363 ? s4368 : s4369;
-  const SBool  s4371 = (SBool) ((s623 >> 0) & 1);
-  const SBool  s4372 = false != s4371;
-  const SWord8 s4373 = s4372 ? s4368 : s4369;
-  const SWord8 s4374 = s585 ? s4370 : s4373;
-  const SWord8 s4375 = s566 ? s4361 : s4374;
-  const SBool  s4376 = (SBool) ((s644 >> 0) & 1);
-  const SBool  s4377 = false != s4376;
-  const SBool  s4378 = (SBool) ((s640 >> 0) & 1);
-  const SBool  s4379 = false != s4378;
-  const SBool  s4380 = (SBool) ((s633 >> 0) & 1);
-  const SBool  s4381 = false != s4380;
-  const SWord8 s4382 = s4381 ? s4347 : s4348;
-  const SWord8 s4383 = (s4382 >> 1) | (s4382 << 7);
-  const SWord8 s4384 = 128 | s4383;
-  const SWord8 s4385 = 127 & s4383;
-  const SWord8 s4386 = s4379 ? s4384 : s4385;
-  const SWord8 s4387 = (s4386 >> 1) | (s4386 << 7);
-  const SWord8 s4388 = 128 | s4387;
-  const SWord8 s4389 = 127 & s4387;
-  const SWord8 s4390 = s4377 ? s4388 : s4389;
-  const SBool  s4391 = (SBool) ((s649 >> 0) & 1);
-  const SBool  s4392 = false != s4391;
-  const SWord8 s4393 = s4392 ? s4388 : s4389;
-  const SWord8 s4394 = s585 ? s4390 : s4393;
-  const SBool  s4395 = (SBool) ((s665 >> 0) & 1);
-  const SBool  s4396 = false != s4395;
-  const SBool  s4397 = (SBool) ((s658 >> 0) & 1);
-  const SBool  s4398 = false != s4397;
-  const SWord8 s4399 = s4398 ? s4384 : s4385;
-  const SWord8 s4400 = (s4399 >> 1) | (s4399 << 7);
-  const SWord8 s4401 = 128 | s4400;
-  const SWord8 s4402 = 127 & s4400;
-  const SWord8 s4403 = s4396 ? s4401 : s4402;
-  const SBool  s4404 = (SBool) ((s670 >> 0) & 1);
-  const SBool  s4405 = false != s4404;
-  const SWord8 s4406 = s4405 ? s4401 : s4402;
-  const SWord8 s4407 = s585 ? s4403 : s4406;
-  const SWord8 s4408 = s566 ? s4394 : s4407;
-  const SWord8 s4409 = s544 ? s4375 : s4408;
-  const SBool  s4410 = (SBool) ((s705 >> 0) & 1);
-  const SBool  s4411 = false != s4410;
-  const SBool  s4412 = (SBool) ((s701 >> 0) & 1);
-  const SBool  s4413 = false != s4412;
-  const SBool  s4414 = (SBool) ((s697 >> 0) & 1);
-  const SBool  s4415 = false != s4414;
-  const SWord8 s4416 = (s684 >> 1) | (s684 << 7);
-  const SWord8 s4417 = 128 | s4416;
-  const SWord8 s4418 = 127 & s4416;
-  const SWord8 s4419 = s4415 ? s4417 : s4418;
-  const SWord8 s4420 = (s4419 >> 1) | (s4419 << 7);
-  const SWord8 s4421 = 128 | s4420;
-  const SWord8 s4422 = 127 & s4420;
-  const SWord8 s4423 = s4413 ? s4421 : s4422;
-  const SWord8 s4424 = (s4423 >> 1) | (s4423 << 7);
-  const SWord8 s4425 = 128 | s4424;
-  const SWord8 s4426 = 127 & s4424;
-  const SWord8 s4427 = s4411 ? s4425 : s4426;
-  const SBool  s4428 = (SBool) ((s710 >> 0) & 1);
-  const SBool  s4429 = false != s4428;
-  const SWord8 s4430 = s4429 ? s4425 : s4426;
-  const SWord8 s4431 = s690 ? s4427 : s4430;
-  const SBool  s4432 = (SBool) ((s726 >> 0) & 1);
-  const SBool  s4433 = false != s4432;
-  const SBool  s4434 = (SBool) ((s719 >> 0) & 1);
-  const SBool  s4435 = false != s4434;
-  const SWord8 s4436 = s4435 ? s4421 : s4422;
-  const SWord8 s4437 = (s4436 >> 1) | (s4436 << 7);
-  const SWord8 s4438 = 128 | s4437;
-  const SWord8 s4439 = 127 & s4437;
-  const SWord8 s4440 = s4433 ? s4438 : s4439;
-  const SBool  s4441 = (SBool) ((s731 >> 0) & 1);
-  const SBool  s4442 = false != s4441;
-  const SWord8 s4443 = s4442 ? s4438 : s4439;
-  const SWord8 s4444 = s690 ? s4440 : s4443;
-  const SWord8 s4445 = s566 ? s4431 : s4444;
-  const SBool  s4446 = (SBool) ((s752 >> 0) & 1);
-  const SBool  s4447 = false != s4446;
-  const SBool  s4448 = (SBool) ((s748 >> 0) & 1);
-  const SBool  s4449 = false != s4448;
-  const SBool  s4450 = (SBool) ((s741 >> 0) & 1);
-  const SBool  s4451 = false != s4450;
-  const SWord8 s4452 = s4451 ? s4417 : s4418;
-  const SWord8 s4453 = (s4452 >> 1) | (s4452 << 7);
-  const SWord8 s4454 = 128 | s4453;
-  const SWord8 s4455 = 127 & s4453;
-  const SWord8 s4456 = s4449 ? s4454 : s4455;
-  const SWord8 s4457 = (s4456 >> 1) | (s4456 << 7);
-  const SWord8 s4458 = 128 | s4457;
-  const SWord8 s4459 = 127 & s4457;
-  const SWord8 s4460 = s4447 ? s4458 : s4459;
-  const SBool  s4461 = (SBool) ((s757 >> 0) & 1);
-  const SBool  s4462 = false != s4461;
-  const SWord8 s4463 = s4462 ? s4458 : s4459;
-  const SWord8 s4464 = s690 ? s4460 : s4463;
-  const SBool  s4465 = (SBool) ((s773 >> 0) & 1);
-  const SBool  s4466 = false != s4465;
-  const SBool  s4467 = (SBool) ((s766 >> 0) & 1);
-  const SBool  s4468 = false != s4467;
-  const SWord8 s4469 = s4468 ? s4454 : s4455;
-  const SWord8 s4470 = (s4469 >> 1) | (s4469 << 7);
-  const SWord8 s4471 = 128 | s4470;
-  const SWord8 s4472 = 127 & s4470;
-  const SWord8 s4473 = s4466 ? s4471 : s4472;
-  const SBool  s4474 = (SBool) ((s778 >> 0) & 1);
-  const SBool  s4475 = false != s4474;
-  const SWord8 s4476 = s4475 ? s4471 : s4472;
-  const SWord8 s4477 = s690 ? s4473 : s4476;
-  const SWord8 s4478 = s566 ? s4464 : s4477;
-  const SWord8 s4479 = s544 ? s4445 : s4478;
-  const SWord8 s4480 = s36 ? s4409 : s4479;
-  const SBool  s4481 = (SBool) ((s833 >> 0) & 1);
-  const SBool  s4482 = false != s4481;
-  const SBool  s4483 = (SBool) ((s829 >> 0) & 1);
-  const SBool  s4484 = false != s4483;
-  const SBool  s4485 = (SBool) ((s825 >> 0) & 1);
-  const SBool  s4486 = false != s4485;
-  const SWord8 s4487 = (s812 >> 1) | (s812 << 7);
-  const SWord8 s4488 = 128 | s4487;
-  const SWord8 s4489 = 127 & s4487;
-  const SWord8 s4490 = s4486 ? s4488 : s4489;
-  const SWord8 s4491 = (s4490 >> 1) | (s4490 << 7);
-  const SWord8 s4492 = 128 | s4491;
-  const SWord8 s4493 = 127 & s4491;
-  const SWord8 s4494 = s4484 ? s4492 : s4493;
-  const SWord8 s4495 = (s4494 >> 1) | (s4494 << 7);
-  const SWord8 s4496 = 128 | s4495;
-  const SWord8 s4497 = 127 & s4495;
-  const SWord8 s4498 = s4482 ? s4496 : s4497;
-  const SBool  s4499 = (SBool) ((s838 >> 0) & 1);
-  const SBool  s4500 = false != s4499;
-  const SWord8 s4501 = s4500 ? s4496 : s4497;
-  const SWord8 s4502 = s821 ? s4498 : s4501;
-  const SBool  s4503 = (SBool) ((s854 >> 0) & 1);
-  const SBool  s4504 = false != s4503;
-  const SBool  s4505 = (SBool) ((s847 >> 0) & 1);
-  const SBool  s4506 = false != s4505;
-  const SWord8 s4507 = s4506 ? s4492 : s4493;
-  const SWord8 s4508 = (s4507 >> 1) | (s4507 << 7);
-  const SWord8 s4509 = 128 | s4508;
-  const SWord8 s4510 = 127 & s4508;
-  const SWord8 s4511 = s4504 ? s4509 : s4510;
-  const SBool  s4512 = (SBool) ((s859 >> 0) & 1);
-  const SBool  s4513 = false != s4512;
-  const SWord8 s4514 = s4513 ? s4509 : s4510;
-  const SWord8 s4515 = s821 ? s4511 : s4514;
-  const SWord8 s4516 = s799 ? s4502 : s4515;
-  const SBool  s4517 = (SBool) ((s880 >> 0) & 1);
-  const SBool  s4518 = false != s4517;
-  const SBool  s4519 = (SBool) ((s876 >> 0) & 1);
-  const SBool  s4520 = false != s4519;
-  const SBool  s4521 = (SBool) ((s869 >> 0) & 1);
-  const SBool  s4522 = false != s4521;
-  const SWord8 s4523 = s4522 ? s4488 : s4489;
-  const SWord8 s4524 = (s4523 >> 1) | (s4523 << 7);
-  const SWord8 s4525 = 128 | s4524;
-  const SWord8 s4526 = 127 & s4524;
-  const SWord8 s4527 = s4520 ? s4525 : s4526;
-  const SWord8 s4528 = (s4527 >> 1) | (s4527 << 7);
-  const SWord8 s4529 = 128 | s4528;
-  const SWord8 s4530 = 127 & s4528;
-  const SWord8 s4531 = s4518 ? s4529 : s4530;
-  const SBool  s4532 = (SBool) ((s885 >> 0) & 1);
-  const SBool  s4533 = false != s4532;
-  const SWord8 s4534 = s4533 ? s4529 : s4530;
-  const SWord8 s4535 = s821 ? s4531 : s4534;
-  const SBool  s4536 = (SBool) ((s901 >> 0) & 1);
-  const SBool  s4537 = false != s4536;
-  const SBool  s4538 = (SBool) ((s894 >> 0) & 1);
-  const SBool  s4539 = false != s4538;
-  const SWord8 s4540 = s4539 ? s4525 : s4526;
-  const SWord8 s4541 = (s4540 >> 1) | (s4540 << 7);
-  const SWord8 s4542 = 128 | s4541;
-  const SWord8 s4543 = 127 & s4541;
-  const SWord8 s4544 = s4537 ? s4542 : s4543;
-  const SBool  s4545 = (SBool) ((s906 >> 0) & 1);
-  const SBool  s4546 = false != s4545;
-  const SWord8 s4547 = s4546 ? s4542 : s4543;
-  const SWord8 s4548 = s821 ? s4544 : s4547;
-  const SWord8 s4549 = s799 ? s4535 : s4548;
-  const SWord8 s4550 = s544 ? s4516 : s4549;
-  const SBool  s4551 = (SBool) ((s941 >> 0) & 1);
-  const SBool  s4552 = false != s4551;
-  const SBool  s4553 = (SBool) ((s937 >> 0) & 1);
-  const SBool  s4554 = false != s4553;
-  const SBool  s4555 = (SBool) ((s933 >> 0) & 1);
-  const SBool  s4556 = false != s4555;
-  const SWord8 s4557 = (s920 >> 1) | (s920 << 7);
-  const SWord8 s4558 = 128 | s4557;
-  const SWord8 s4559 = 127 & s4557;
-  const SWord8 s4560 = s4556 ? s4558 : s4559;
-  const SWord8 s4561 = (s4560 >> 1) | (s4560 << 7);
-  const SWord8 s4562 = 128 | s4561;
-  const SWord8 s4563 = 127 & s4561;
-  const SWord8 s4564 = s4554 ? s4562 : s4563;
-  const SWord8 s4565 = (s4564 >> 1) | (s4564 << 7);
-  const SWord8 s4566 = 128 | s4565;
-  const SWord8 s4567 = 127 & s4565;
-  const SWord8 s4568 = s4552 ? s4566 : s4567;
-  const SBool  s4569 = (SBool) ((s946 >> 0) & 1);
-  const SBool  s4570 = false != s4569;
-  const SWord8 s4571 = s4570 ? s4566 : s4567;
-  const SWord8 s4572 = s926 ? s4568 : s4571;
-  const SBool  s4573 = (SBool) ((s962 >> 0) & 1);
-  const SBool  s4574 = false != s4573;
-  const SBool  s4575 = (SBool) ((s955 >> 0) & 1);
-  const SBool  s4576 = false != s4575;
-  const SWord8 s4577 = s4576 ? s4562 : s4563;
-  const SWord8 s4578 = (s4577 >> 1) | (s4577 << 7);
-  const SWord8 s4579 = 128 | s4578;
-  const SWord8 s4580 = 127 & s4578;
-  const SWord8 s4581 = s4574 ? s4579 : s4580;
-  const SBool  s4582 = (SBool) ((s967 >> 0) & 1);
-  const SBool  s4583 = false != s4582;
-  const SWord8 s4584 = s4583 ? s4579 : s4580;
-  const SWord8 s4585 = s926 ? s4581 : s4584;
-  const SWord8 s4586 = s799 ? s4572 : s4585;
-  const SBool  s4587 = (SBool) ((s988 >> 0) & 1);
-  const SBool  s4588 = false != s4587;
-  const SBool  s4589 = (SBool) ((s984 >> 0) & 1);
-  const SBool  s4590 = false != s4589;
-  const SBool  s4591 = (SBool) ((s977 >> 0) & 1);
-  const SBool  s4592 = false != s4591;
-  const SWord8 s4593 = s4592 ? s4558 : s4559;
-  const SWord8 s4594 = (s4593 >> 1) | (s4593 << 7);
-  const SWord8 s4595 = 128 | s4594;
-  const SWord8 s4596 = 127 & s4594;
-  const SWord8 s4597 = s4590 ? s4595 : s4596;
-  const SWord8 s4598 = (s4597 >> 1) | (s4597 << 7);
-  const SWord8 s4599 = 128 | s4598;
-  const SWord8 s4600 = 127 & s4598;
-  const SWord8 s4601 = s4588 ? s4599 : s4600;
-  const SBool  s4602 = (SBool) ((s993 >> 0) & 1);
-  const SBool  s4603 = false != s4602;
-  const SWord8 s4604 = s4603 ? s4599 : s4600;
-  const SWord8 s4605 = s926 ? s4601 : s4604;
-  const SBool  s4606 = (SBool) ((s1009 >> 0) & 1);
-  const SBool  s4607 = false != s4606;
-  const SBool  s4608 = (SBool) ((s1002 >> 0) & 1);
-  const SBool  s4609 = false != s4608;
-  const SWord8 s4610 = s4609 ? s4595 : s4596;
-  const SWord8 s4611 = (s4610 >> 1) | (s4610 << 7);
-  const SWord8 s4612 = 128 | s4611;
-  const SWord8 s4613 = 127 & s4611;
-  const SWord8 s4614 = s4607 ? s4612 : s4613;
-  const SBool  s4615 = (SBool) ((s1014 >> 0) & 1);
-  const SBool  s4616 = false != s4615;
-  const SWord8 s4617 = s4616 ? s4612 : s4613;
-  const SWord8 s4618 = s926 ? s4614 : s4617;
-  const SWord8 s4619 = s799 ? s4605 : s4618;
-  const SWord8 s4620 = s544 ? s4586 : s4619;
-  const SWord8 s4621 = s36 ? s4550 : s4620;
-  const SWord8 s4622 = s21 ? s4480 : s4621;
-  const SWord8 s4623 = s16 ? s4339 : s4622;
-  const SBool  s4624 = (SBool) ((s1109 >> 0) & 1);
-  const SBool  s4625 = false != s4624;
-  const SBool  s4626 = (SBool) ((s1105 >> 0) & 1);
-  const SBool  s4627 = false != s4626;
-  const SBool  s4628 = (SBool) ((s1101 >> 0) & 1);
-  const SBool  s4629 = false != s4628;
-  const SWord8 s4630 = (s1088 >> 1) | (s1088 << 7);
-  const SWord8 s4631 = 128 | s4630;
-  const SWord8 s4632 = 127 & s4630;
-  const SWord8 s4633 = s4629 ? s4631 : s4632;
-  const SWord8 s4634 = (s4633 >> 1) | (s4633 << 7);
-  const SWord8 s4635 = 128 | s4634;
-  const SWord8 s4636 = 127 & s4634;
-  const SWord8 s4637 = s4627 ? s4635 : s4636;
-  const SWord8 s4638 = (s4637 >> 1) | (s4637 << 7);
-  const SWord8 s4639 = 128 | s4638;
-  const SWord8 s4640 = 127 & s4638;
-  const SWord8 s4641 = s4625 ? s4639 : s4640;
-  const SBool  s4642 = (SBool) ((s1114 >> 0) & 1);
-  const SBool  s4643 = false != s4642;
-  const SWord8 s4644 = s4643 ? s4639 : s4640;
-  const SWord8 s4645 = s1097 ? s4641 : s4644;
-  const SBool  s4646 = (SBool) ((s1130 >> 0) & 1);
-  const SBool  s4647 = false != s4646;
-  const SBool  s4648 = (SBool) ((s1123 >> 0) & 1);
-  const SBool  s4649 = false != s4648;
-  const SWord8 s4650 = s4649 ? s4635 : s4636;
-  const SWord8 s4651 = (s4650 >> 1) | (s4650 << 7);
-  const SWord8 s4652 = 128 | s4651;
-  const SWord8 s4653 = 127 & s4651;
-  const SWord8 s4654 = s4647 ? s4652 : s4653;
-  const SBool  s4655 = (SBool) ((s1135 >> 0) & 1);
-  const SBool  s4656 = false != s4655;
-  const SWord8 s4657 = s4656 ? s4652 : s4653;
-  const SWord8 s4658 = s1097 ? s4654 : s4657;
-  const SWord8 s4659 = s1078 ? s4645 : s4658;
-  const SBool  s4660 = (SBool) ((s1156 >> 0) & 1);
-  const SBool  s4661 = false != s4660;
-  const SBool  s4662 = (SBool) ((s1152 >> 0) & 1);
-  const SBool  s4663 = false != s4662;
-  const SBool  s4664 = (SBool) ((s1145 >> 0) & 1);
-  const SBool  s4665 = false != s4664;
-  const SWord8 s4666 = s4665 ? s4631 : s4632;
-  const SWord8 s4667 = (s4666 >> 1) | (s4666 << 7);
-  const SWord8 s4668 = 128 | s4667;
-  const SWord8 s4669 = 127 & s4667;
-  const SWord8 s4670 = s4663 ? s4668 : s4669;
-  const SWord8 s4671 = (s4670 >> 1) | (s4670 << 7);
-  const SWord8 s4672 = 128 | s4671;
-  const SWord8 s4673 = 127 & s4671;
-  const SWord8 s4674 = s4661 ? s4672 : s4673;
-  const SBool  s4675 = (SBool) ((s1161 >> 0) & 1);
-  const SBool  s4676 = false != s4675;
-  const SWord8 s4677 = s4676 ? s4672 : s4673;
-  const SWord8 s4678 = s1097 ? s4674 : s4677;
-  const SBool  s4679 = (SBool) ((s1177 >> 0) & 1);
-  const SBool  s4680 = false != s4679;
-  const SBool  s4681 = (SBool) ((s1170 >> 0) & 1);
-  const SBool  s4682 = false != s4681;
-  const SWord8 s4683 = s4682 ? s4668 : s4669;
-  const SWord8 s4684 = (s4683 >> 1) | (s4683 << 7);
-  const SWord8 s4685 = 128 | s4684;
-  const SWord8 s4686 = 127 & s4684;
-  const SWord8 s4687 = s4680 ? s4685 : s4686;
-  const SBool  s4688 = (SBool) ((s1182 >> 0) & 1);
-  const SBool  s4689 = false != s4688;
-  const SWord8 s4690 = s4689 ? s4685 : s4686;
-  const SWord8 s4691 = s1097 ? s4687 : s4690;
-  const SWord8 s4692 = s1078 ? s4678 : s4691;
-  const SWord8 s4693 = s1059 ? s4659 : s4692;
-  const SBool  s4694 = (SBool) ((s1217 >> 0) & 1);
-  const SBool  s4695 = false != s4694;
-  const SBool  s4696 = (SBool) ((s1213 >> 0) & 1);
-  const SBool  s4697 = false != s4696;
-  const SBool  s4698 = (SBool) ((s1209 >> 0) & 1);
-  const SBool  s4699 = false != s4698;
-  const SWord8 s4700 = (s1196 >> 1) | (s1196 << 7);
-  const SWord8 s4701 = 128 | s4700;
-  const SWord8 s4702 = 127 & s4700;
-  const SWord8 s4703 = s4699 ? s4701 : s4702;
-  const SWord8 s4704 = (s4703 >> 1) | (s4703 << 7);
-  const SWord8 s4705 = 128 | s4704;
-  const SWord8 s4706 = 127 & s4704;
-  const SWord8 s4707 = s4697 ? s4705 : s4706;
-  const SWord8 s4708 = (s4707 >> 1) | (s4707 << 7);
-  const SWord8 s4709 = 128 | s4708;
-  const SWord8 s4710 = 127 & s4708;
-  const SWord8 s4711 = s4695 ? s4709 : s4710;
-  const SBool  s4712 = (SBool) ((s1222 >> 0) & 1);
-  const SBool  s4713 = false != s4712;
-  const SWord8 s4714 = s4713 ? s4709 : s4710;
-  const SWord8 s4715 = s1202 ? s4711 : s4714;
-  const SBool  s4716 = (SBool) ((s1238 >> 0) & 1);
-  const SBool  s4717 = false != s4716;
-  const SBool  s4718 = (SBool) ((s1231 >> 0) & 1);
-  const SBool  s4719 = false != s4718;
-  const SWord8 s4720 = s4719 ? s4705 : s4706;
-  const SWord8 s4721 = (s4720 >> 1) | (s4720 << 7);
-  const SWord8 s4722 = 128 | s4721;
-  const SWord8 s4723 = 127 & s4721;
-  const SWord8 s4724 = s4717 ? s4722 : s4723;
-  const SBool  s4725 = (SBool) ((s1243 >> 0) & 1);
-  const SBool  s4726 = false != s4725;
-  const SWord8 s4727 = s4726 ? s4722 : s4723;
-  const SWord8 s4728 = s1202 ? s4724 : s4727;
-  const SWord8 s4729 = s1078 ? s4715 : s4728;
-  const SBool  s4730 = (SBool) ((s1264 >> 0) & 1);
-  const SBool  s4731 = false != s4730;
-  const SBool  s4732 = (SBool) ((s1260 >> 0) & 1);
-  const SBool  s4733 = false != s4732;
-  const SBool  s4734 = (SBool) ((s1253 >> 0) & 1);
-  const SBool  s4735 = false != s4734;
-  const SWord8 s4736 = s4735 ? s4701 : s4702;
-  const SWord8 s4737 = (s4736 >> 1) | (s4736 << 7);
-  const SWord8 s4738 = 128 | s4737;
-  const SWord8 s4739 = 127 & s4737;
-  const SWord8 s4740 = s4733 ? s4738 : s4739;
-  const SWord8 s4741 = (s4740 >> 1) | (s4740 << 7);
-  const SWord8 s4742 = 128 | s4741;
-  const SWord8 s4743 = 127 & s4741;
-  const SWord8 s4744 = s4731 ? s4742 : s4743;
-  const SBool  s4745 = (SBool) ((s1269 >> 0) & 1);
-  const SBool  s4746 = false != s4745;
-  const SWord8 s4747 = s4746 ? s4742 : s4743;
-  const SWord8 s4748 = s1202 ? s4744 : s4747;
-  const SBool  s4749 = (SBool) ((s1285 >> 0) & 1);
-  const SBool  s4750 = false != s4749;
-  const SBool  s4751 = (SBool) ((s1278 >> 0) & 1);
-  const SBool  s4752 = false != s4751;
-  const SWord8 s4753 = s4752 ? s4738 : s4739;
-  const SWord8 s4754 = (s4753 >> 1) | (s4753 << 7);
-  const SWord8 s4755 = 128 | s4754;
-  const SWord8 s4756 = 127 & s4754;
-  const SWord8 s4757 = s4750 ? s4755 : s4756;
-  const SBool  s4758 = (SBool) ((s1290 >> 0) & 1);
-  const SBool  s4759 = false != s4758;
-  const SWord8 s4760 = s4759 ? s4755 : s4756;
-  const SWord8 s4761 = s1202 ? s4757 : s4760;
-  const SWord8 s4762 = s1078 ? s4748 : s4761;
-  const SWord8 s4763 = s1059 ? s4729 : s4762;
-  const SWord8 s4764 = s1037 ? s4693 : s4763;
-  const SBool  s4765 = (SBool) ((s1345 >> 0) & 1);
-  const SBool  s4766 = false != s4765;
-  const SBool  s4767 = (SBool) ((s1341 >> 0) & 1);
-  const SBool  s4768 = false != s4767;
-  const SBool  s4769 = (SBool) ((s1337 >> 0) & 1);
-  const SBool  s4770 = false != s4769;
-  const SWord8 s4771 = (s1324 >> 1) | (s1324 << 7);
-  const SWord8 s4772 = 128 | s4771;
-  const SWord8 s4773 = 127 & s4771;
-  const SWord8 s4774 = s4770 ? s4772 : s4773;
-  const SWord8 s4775 = (s4774 >> 1) | (s4774 << 7);
-  const SWord8 s4776 = 128 | s4775;
-  const SWord8 s4777 = 127 & s4775;
-  const SWord8 s4778 = s4768 ? s4776 : s4777;
-  const SWord8 s4779 = (s4778 >> 1) | (s4778 << 7);
-  const SWord8 s4780 = 128 | s4779;
-  const SWord8 s4781 = 127 & s4779;
-  const SWord8 s4782 = s4766 ? s4780 : s4781;
-  const SBool  s4783 = (SBool) ((s1350 >> 0) & 1);
-  const SBool  s4784 = false != s4783;
-  const SWord8 s4785 = s4784 ? s4780 : s4781;
-  const SWord8 s4786 = s1333 ? s4782 : s4785;
-  const SBool  s4787 = (SBool) ((s1366 >> 0) & 1);
-  const SBool  s4788 = false != s4787;
-  const SBool  s4789 = (SBool) ((s1359 >> 0) & 1);
-  const SBool  s4790 = false != s4789;
-  const SWord8 s4791 = s4790 ? s4776 : s4777;
-  const SWord8 s4792 = (s4791 >> 1) | (s4791 << 7);
-  const SWord8 s4793 = 128 | s4792;
-  const SWord8 s4794 = 127 & s4792;
-  const SWord8 s4795 = s4788 ? s4793 : s4794;
-  const SBool  s4796 = (SBool) ((s1371 >> 0) & 1);
-  const SBool  s4797 = false != s4796;
-  const SWord8 s4798 = s4797 ? s4793 : s4794;
-  const SWord8 s4799 = s1333 ? s4795 : s4798;
-  const SWord8 s4800 = s1311 ? s4786 : s4799;
-  const SBool  s4801 = (SBool) ((s1392 >> 0) & 1);
-  const SBool  s4802 = false != s4801;
-  const SBool  s4803 = (SBool) ((s1388 >> 0) & 1);
-  const SBool  s4804 = false != s4803;
-  const SBool  s4805 = (SBool) ((s1381 >> 0) & 1);
-  const SBool  s4806 = false != s4805;
-  const SWord8 s4807 = s4806 ? s4772 : s4773;
-  const SWord8 s4808 = (s4807 >> 1) | (s4807 << 7);
-  const SWord8 s4809 = 128 | s4808;
-  const SWord8 s4810 = 127 & s4808;
-  const SWord8 s4811 = s4804 ? s4809 : s4810;
-  const SWord8 s4812 = (s4811 >> 1) | (s4811 << 7);
-  const SWord8 s4813 = 128 | s4812;
-  const SWord8 s4814 = 127 & s4812;
-  const SWord8 s4815 = s4802 ? s4813 : s4814;
-  const SBool  s4816 = (SBool) ((s1397 >> 0) & 1);
-  const SBool  s4817 = false != s4816;
-  const SWord8 s4818 = s4817 ? s4813 : s4814;
-  const SWord8 s4819 = s1333 ? s4815 : s4818;
-  const SBool  s4820 = (SBool) ((s1413 >> 0) & 1);
-  const SBool  s4821 = false != s4820;
-  const SBool  s4822 = (SBool) ((s1406 >> 0) & 1);
-  const SBool  s4823 = false != s4822;
-  const SWord8 s4824 = s4823 ? s4809 : s4810;
-  const SWord8 s4825 = (s4824 >> 1) | (s4824 << 7);
-  const SWord8 s4826 = 128 | s4825;
-  const SWord8 s4827 = 127 & s4825;
-  const SWord8 s4828 = s4821 ? s4826 : s4827;
-  const SBool  s4829 = (SBool) ((s1418 >> 0) & 1);
-  const SBool  s4830 = false != s4829;
-  const SWord8 s4831 = s4830 ? s4826 : s4827;
-  const SWord8 s4832 = s1333 ? s4828 : s4831;
-  const SWord8 s4833 = s1311 ? s4819 : s4832;
-  const SWord8 s4834 = s1059 ? s4800 : s4833;
-  const SBool  s4835 = (SBool) ((s1453 >> 0) & 1);
-  const SBool  s4836 = false != s4835;
-  const SBool  s4837 = (SBool) ((s1449 >> 0) & 1);
-  const SBool  s4838 = false != s4837;
-  const SBool  s4839 = (SBool) ((s1445 >> 0) & 1);
-  const SBool  s4840 = false != s4839;
-  const SWord8 s4841 = (s1432 >> 1) | (s1432 << 7);
-  const SWord8 s4842 = 128 | s4841;
-  const SWord8 s4843 = 127 & s4841;
-  const SWord8 s4844 = s4840 ? s4842 : s4843;
-  const SWord8 s4845 = (s4844 >> 1) | (s4844 << 7);
-  const SWord8 s4846 = 128 | s4845;
-  const SWord8 s4847 = 127 & s4845;
-  const SWord8 s4848 = s4838 ? s4846 : s4847;
-  const SWord8 s4849 = (s4848 >> 1) | (s4848 << 7);
-  const SWord8 s4850 = 128 | s4849;
-  const SWord8 s4851 = 127 & s4849;
-  const SWord8 s4852 = s4836 ? s4850 : s4851;
-  const SBool  s4853 = (SBool) ((s1458 >> 0) & 1);
-  const SBool  s4854 = false != s4853;
-  const SWord8 s4855 = s4854 ? s4850 : s4851;
-  const SWord8 s4856 = s1438 ? s4852 : s4855;
-  const SBool  s4857 = (SBool) ((s1474 >> 0) & 1);
-  const SBool  s4858 = false != s4857;
-  const SBool  s4859 = (SBool) ((s1467 >> 0) & 1);
-  const SBool  s4860 = false != s4859;
-  const SWord8 s4861 = s4860 ? s4846 : s4847;
-  const SWord8 s4862 = (s4861 >> 1) | (s4861 << 7);
-  const SWord8 s4863 = 128 | s4862;
-  const SWord8 s4864 = 127 & s4862;
-  const SWord8 s4865 = s4858 ? s4863 : s4864;
-  const SBool  s4866 = (SBool) ((s1479 >> 0) & 1);
-  const SBool  s4867 = false != s4866;
-  const SWord8 s4868 = s4867 ? s4863 : s4864;
-  const SWord8 s4869 = s1438 ? s4865 : s4868;
-  const SWord8 s4870 = s1311 ? s4856 : s4869;
-  const SBool  s4871 = (SBool) ((s1500 >> 0) & 1);
-  const SBool  s4872 = false != s4871;
-  const SBool  s4873 = (SBool) ((s1496 >> 0) & 1);
-  const SBool  s4874 = false != s4873;
-  const SBool  s4875 = (SBool) ((s1489 >> 0) & 1);
-  const SBool  s4876 = false != s4875;
-  const SWord8 s4877 = s4876 ? s4842 : s4843;
-  const SWord8 s4878 = (s4877 >> 1) | (s4877 << 7);
-  const SWord8 s4879 = 128 | s4878;
-  const SWord8 s4880 = 127 & s4878;
-  const SWord8 s4881 = s4874 ? s4879 : s4880;
-  const SWord8 s4882 = (s4881 >> 1) | (s4881 << 7);
-  const SWord8 s4883 = 128 | s4882;
-  const SWord8 s4884 = 127 & s4882;
-  const SWord8 s4885 = s4872 ? s4883 : s4884;
-  const SBool  s4886 = (SBool) ((s1505 >> 0) & 1);
-  const SBool  s4887 = false != s4886;
-  const SWord8 s4888 = s4887 ? s4883 : s4884;
-  const SWord8 s4889 = s1438 ? s4885 : s4888;
-  const SBool  s4890 = (SBool) ((s1521 >> 0) & 1);
-  const SBool  s4891 = false != s4890;
-  const SBool  s4892 = (SBool) ((s1514 >> 0) & 1);
-  const SBool  s4893 = false != s4892;
-  const SWord8 s4894 = s4893 ? s4879 : s4880;
-  const SWord8 s4895 = (s4894 >> 1) | (s4894 << 7);
-  const SWord8 s4896 = 128 | s4895;
-  const SWord8 s4897 = 127 & s4895;
-  const SWord8 s4898 = s4891 ? s4896 : s4897;
-  const SBool  s4899 = (SBool) ((s1526 >> 0) & 1);
-  const SBool  s4900 = false != s4899;
-  const SWord8 s4901 = s4900 ? s4896 : s4897;
-  const SWord8 s4902 = s1438 ? s4898 : s4901;
-  const SWord8 s4903 = s1311 ? s4889 : s4902;
-  const SWord8 s4904 = s1059 ? s4870 : s4903;
-  const SWord8 s4905 = s1037 ? s4834 : s4904;
-  const SWord8 s4906 = s21 ? s4764 : s4905;
-  const SBool  s4907 = (SBool) ((s1601 >> 0) & 1);
-  const SBool  s4908 = false != s4907;
-  const SBool  s4909 = (SBool) ((s1597 >> 0) & 1);
-  const SBool  s4910 = false != s4909;
-  const SBool  s4911 = (SBool) ((s1593 >> 0) & 1);
-  const SBool  s4912 = false != s4911;
-  const SWord8 s4913 = (s1580 >> 1) | (s1580 << 7);
-  const SWord8 s4914 = 128 | s4913;
-  const SWord8 s4915 = 127 & s4913;
-  const SWord8 s4916 = s4912 ? s4914 : s4915;
-  const SWord8 s4917 = (s4916 >> 1) | (s4916 << 7);
-  const SWord8 s4918 = 128 | s4917;
-  const SWord8 s4919 = 127 & s4917;
-  const SWord8 s4920 = s4910 ? s4918 : s4919;
-  const SWord8 s4921 = (s4920 >> 1) | (s4920 << 7);
-  const SWord8 s4922 = 128 | s4921;
-  const SWord8 s4923 = 127 & s4921;
-  const SWord8 s4924 = s4908 ? s4922 : s4923;
-  const SBool  s4925 = (SBool) ((s1606 >> 0) & 1);
-  const SBool  s4926 = false != s4925;
-  const SWord8 s4927 = s4926 ? s4922 : s4923;
-  const SWord8 s4928 = s1589 ? s4924 : s4927;
-  const SBool  s4929 = (SBool) ((s1622 >> 0) & 1);
-  const SBool  s4930 = false != s4929;
-  const SBool  s4931 = (SBool) ((s1615 >> 0) & 1);
-  const SBool  s4932 = false != s4931;
-  const SWord8 s4933 = s4932 ? s4918 : s4919;
-  const SWord8 s4934 = (s4933 >> 1) | (s4933 << 7);
-  const SWord8 s4935 = 128 | s4934;
-  const SWord8 s4936 = 127 & s4934;
-  const SWord8 s4937 = s4930 ? s4935 : s4936;
-  const SBool  s4938 = (SBool) ((s1627 >> 0) & 1);
-  const SBool  s4939 = false != s4938;
-  const SWord8 s4940 = s4939 ? s4935 : s4936;
-  const SWord8 s4941 = s1589 ? s4937 : s4940;
-  const SWord8 s4942 = s1570 ? s4928 : s4941;
-  const SBool  s4943 = (SBool) ((s1648 >> 0) & 1);
-  const SBool  s4944 = false != s4943;
-  const SBool  s4945 = (SBool) ((s1644 >> 0) & 1);
-  const SBool  s4946 = false != s4945;
-  const SBool  s4947 = (SBool) ((s1637 >> 0) & 1);
-  const SBool  s4948 = false != s4947;
-  const SWord8 s4949 = s4948 ? s4914 : s4915;
-  const SWord8 s4950 = (s4949 >> 1) | (s4949 << 7);
-  const SWord8 s4951 = 128 | s4950;
-  const SWord8 s4952 = 127 & s4950;
-  const SWord8 s4953 = s4946 ? s4951 : s4952;
-  const SWord8 s4954 = (s4953 >> 1) | (s4953 << 7);
-  const SWord8 s4955 = 128 | s4954;
-  const SWord8 s4956 = 127 & s4954;
-  const SWord8 s4957 = s4944 ? s4955 : s4956;
-  const SBool  s4958 = (SBool) ((s1653 >> 0) & 1);
-  const SBool  s4959 = false != s4958;
-  const SWord8 s4960 = s4959 ? s4955 : s4956;
-  const SWord8 s4961 = s1589 ? s4957 : s4960;
-  const SBool  s4962 = (SBool) ((s1669 >> 0) & 1);
-  const SBool  s4963 = false != s4962;
-  const SBool  s4964 = (SBool) ((s1662 >> 0) & 1);
-  const SBool  s4965 = false != s4964;
-  const SWord8 s4966 = s4965 ? s4951 : s4952;
-  const SWord8 s4967 = (s4966 >> 1) | (s4966 << 7);
-  const SWord8 s4968 = 128 | s4967;
-  const SWord8 s4969 = 127 & s4967;
-  const SWord8 s4970 = s4963 ? s4968 : s4969;
-  const SBool  s4971 = (SBool) ((s1674 >> 0) & 1);
-  const SBool  s4972 = false != s4971;
-  const SWord8 s4973 = s4972 ? s4968 : s4969;
-  const SWord8 s4974 = s1589 ? s4970 : s4973;
-  const SWord8 s4975 = s1570 ? s4961 : s4974;
-  const SWord8 s4976 = s1548 ? s4942 : s4975;
-  const SBool  s4977 = (SBool) ((s1709 >> 0) & 1);
-  const SBool  s4978 = false != s4977;
-  const SBool  s4979 = (SBool) ((s1705 >> 0) & 1);
-  const SBool  s4980 = false != s4979;
-  const SBool  s4981 = (SBool) ((s1701 >> 0) & 1);
-  const SBool  s4982 = false != s4981;
-  const SWord8 s4983 = (s1688 >> 1) | (s1688 << 7);
-  const SWord8 s4984 = 128 | s4983;
-  const SWord8 s4985 = 127 & s4983;
-  const SWord8 s4986 = s4982 ? s4984 : s4985;
-  const SWord8 s4987 = (s4986 >> 1) | (s4986 << 7);
-  const SWord8 s4988 = 128 | s4987;
-  const SWord8 s4989 = 127 & s4987;
-  const SWord8 s4990 = s4980 ? s4988 : s4989;
-  const SWord8 s4991 = (s4990 >> 1) | (s4990 << 7);
-  const SWord8 s4992 = 128 | s4991;
-  const SWord8 s4993 = 127 & s4991;
-  const SWord8 s4994 = s4978 ? s4992 : s4993;
-  const SBool  s4995 = (SBool) ((s1714 >> 0) & 1);
-  const SBool  s4996 = false != s4995;
-  const SWord8 s4997 = s4996 ? s4992 : s4993;
-  const SWord8 s4998 = s1694 ? s4994 : s4997;
-  const SBool  s4999 = (SBool) ((s1730 >> 0) & 1);
-  const SBool  s5000 = false != s4999;
-  const SBool  s5001 = (SBool) ((s1723 >> 0) & 1);
-  const SBool  s5002 = false != s5001;
-  const SWord8 s5003 = s5002 ? s4988 : s4989;
-  const SWord8 s5004 = (s5003 >> 1) | (s5003 << 7);
-  const SWord8 s5005 = 128 | s5004;
-  const SWord8 s5006 = 127 & s5004;
-  const SWord8 s5007 = s5000 ? s5005 : s5006;
-  const SBool  s5008 = (SBool) ((s1735 >> 0) & 1);
-  const SBool  s5009 = false != s5008;
-  const SWord8 s5010 = s5009 ? s5005 : s5006;
-  const SWord8 s5011 = s1694 ? s5007 : s5010;
-  const SWord8 s5012 = s1570 ? s4998 : s5011;
-  const SBool  s5013 = (SBool) ((s1756 >> 0) & 1);
-  const SBool  s5014 = false != s5013;
-  const SBool  s5015 = (SBool) ((s1752 >> 0) & 1);
-  const SBool  s5016 = false != s5015;
-  const SBool  s5017 = (SBool) ((s1745 >> 0) & 1);
-  const SBool  s5018 = false != s5017;
-  const SWord8 s5019 = s5018 ? s4984 : s4985;
-  const SWord8 s5020 = (s5019 >> 1) | (s5019 << 7);
-  const SWord8 s5021 = 128 | s5020;
-  const SWord8 s5022 = 127 & s5020;
-  const SWord8 s5023 = s5016 ? s5021 : s5022;
-  const SWord8 s5024 = (s5023 >> 1) | (s5023 << 7);
-  const SWord8 s5025 = 128 | s5024;
-  const SWord8 s5026 = 127 & s5024;
-  const SWord8 s5027 = s5014 ? s5025 : s5026;
-  const SBool  s5028 = (SBool) ((s1761 >> 0) & 1);
-  const SBool  s5029 = false != s5028;
-  const SWord8 s5030 = s5029 ? s5025 : s5026;
-  const SWord8 s5031 = s1694 ? s5027 : s5030;
-  const SBool  s5032 = (SBool) ((s1777 >> 0) & 1);
-  const SBool  s5033 = false != s5032;
-  const SBool  s5034 = (SBool) ((s1770 >> 0) & 1);
-  const SBool  s5035 = false != s5034;
-  const SWord8 s5036 = s5035 ? s5021 : s5022;
-  const SWord8 s5037 = (s5036 >> 1) | (s5036 << 7);
-  const SWord8 s5038 = 128 | s5037;
-  const SWord8 s5039 = 127 & s5037;
-  const SWord8 s5040 = s5033 ? s5038 : s5039;
-  const SBool  s5041 = (SBool) ((s1782 >> 0) & 1);
-  const SBool  s5042 = false != s5041;
-  const SWord8 s5043 = s5042 ? s5038 : s5039;
-  const SWord8 s5044 = s1694 ? s5040 : s5043;
-  const SWord8 s5045 = s1570 ? s5031 : s5044;
-  const SWord8 s5046 = s1548 ? s5012 : s5045;
-  const SWord8 s5047 = s1037 ? s4976 : s5046;
-  const SBool  s5048 = (SBool) ((s1837 >> 0) & 1);
-  const SBool  s5049 = false != s5048;
-  const SBool  s5050 = (SBool) ((s1833 >> 0) & 1);
-  const SBool  s5051 = false != s5050;
-  const SBool  s5052 = (SBool) ((s1829 >> 0) & 1);
-  const SBool  s5053 = false != s5052;
-  const SWord8 s5054 = (s1816 >> 1) | (s1816 << 7);
-  const SWord8 s5055 = 128 | s5054;
-  const SWord8 s5056 = 127 & s5054;
-  const SWord8 s5057 = s5053 ? s5055 : s5056;
-  const SWord8 s5058 = (s5057 >> 1) | (s5057 << 7);
-  const SWord8 s5059 = 128 | s5058;
-  const SWord8 s5060 = 127 & s5058;
-  const SWord8 s5061 = s5051 ? s5059 : s5060;
-  const SWord8 s5062 = (s5061 >> 1) | (s5061 << 7);
-  const SWord8 s5063 = 128 | s5062;
-  const SWord8 s5064 = 127 & s5062;
-  const SWord8 s5065 = s5049 ? s5063 : s5064;
-  const SBool  s5066 = (SBool) ((s1842 >> 0) & 1);
-  const SBool  s5067 = false != s5066;
-  const SWord8 s5068 = s5067 ? s5063 : s5064;
-  const SWord8 s5069 = s1825 ? s5065 : s5068;
-  const SBool  s5070 = (SBool) ((s1858 >> 0) & 1);
-  const SBool  s5071 = false != s5070;
-  const SBool  s5072 = (SBool) ((s1851 >> 0) & 1);
-  const SBool  s5073 = false != s5072;
-  const SWord8 s5074 = s5073 ? s5059 : s5060;
-  const SWord8 s5075 = (s5074 >> 1) | (s5074 << 7);
-  const SWord8 s5076 = 128 | s5075;
-  const SWord8 s5077 = 127 & s5075;
-  const SWord8 s5078 = s5071 ? s5076 : s5077;
-  const SBool  s5079 = (SBool) ((s1863 >> 0) & 1);
-  const SBool  s5080 = false != s5079;
-  const SWord8 s5081 = s5080 ? s5076 : s5077;
-  const SWord8 s5082 = s1825 ? s5078 : s5081;
-  const SWord8 s5083 = s1803 ? s5069 : s5082;
-  const SBool  s5084 = (SBool) ((s1884 >> 0) & 1);
-  const SBool  s5085 = false != s5084;
-  const SBool  s5086 = (SBool) ((s1880 >> 0) & 1);
-  const SBool  s5087 = false != s5086;
-  const SBool  s5088 = (SBool) ((s1873 >> 0) & 1);
-  const SBool  s5089 = false != s5088;
-  const SWord8 s5090 = s5089 ? s5055 : s5056;
-  const SWord8 s5091 = (s5090 >> 1) | (s5090 << 7);
-  const SWord8 s5092 = 128 | s5091;
-  const SWord8 s5093 = 127 & s5091;
-  const SWord8 s5094 = s5087 ? s5092 : s5093;
-  const SWord8 s5095 = (s5094 >> 1) | (s5094 << 7);
-  const SWord8 s5096 = 128 | s5095;
-  const SWord8 s5097 = 127 & s5095;
-  const SWord8 s5098 = s5085 ? s5096 : s5097;
-  const SBool  s5099 = (SBool) ((s1889 >> 0) & 1);
-  const SBool  s5100 = false != s5099;
-  const SWord8 s5101 = s5100 ? s5096 : s5097;
-  const SWord8 s5102 = s1825 ? s5098 : s5101;
-  const SBool  s5103 = (SBool) ((s1905 >> 0) & 1);
-  const SBool  s5104 = false != s5103;
-  const SBool  s5105 = (SBool) ((s1898 >> 0) & 1);
-  const SBool  s5106 = false != s5105;
-  const SWord8 s5107 = s5106 ? s5092 : s5093;
-  const SWord8 s5108 = (s5107 >> 1) | (s5107 << 7);
-  const SWord8 s5109 = 128 | s5108;
-  const SWord8 s5110 = 127 & s5108;
-  const SWord8 s5111 = s5104 ? s5109 : s5110;
-  const SBool  s5112 = (SBool) ((s1910 >> 0) & 1);
-  const SBool  s5113 = false != s5112;
-  const SWord8 s5114 = s5113 ? s5109 : s5110;
-  const SWord8 s5115 = s1825 ? s5111 : s5114;
-  const SWord8 s5116 = s1803 ? s5102 : s5115;
-  const SWord8 s5117 = s1548 ? s5083 : s5116;
-  const SBool  s5118 = (SBool) ((s1945 >> 0) & 1);
-  const SBool  s5119 = false != s5118;
-  const SBool  s5120 = (SBool) ((s1941 >> 0) & 1);
-  const SBool  s5121 = false != s5120;
-  const SBool  s5122 = (SBool) ((s1937 >> 0) & 1);
-  const SBool  s5123 = false != s5122;
-  const SWord8 s5124 = (s1924 >> 1) | (s1924 << 7);
-  const SWord8 s5125 = 128 | s5124;
-  const SWord8 s5126 = 127 & s5124;
-  const SWord8 s5127 = s5123 ? s5125 : s5126;
-  const SWord8 s5128 = (s5127 >> 1) | (s5127 << 7);
-  const SWord8 s5129 = 128 | s5128;
-  const SWord8 s5130 = 127 & s5128;
-  const SWord8 s5131 = s5121 ? s5129 : s5130;
-  const SWord8 s5132 = (s5131 >> 1) | (s5131 << 7);
-  const SWord8 s5133 = 128 | s5132;
-  const SWord8 s5134 = 127 & s5132;
-  const SWord8 s5135 = s5119 ? s5133 : s5134;
-  const SBool  s5136 = (SBool) ((s1950 >> 0) & 1);
-  const SBool  s5137 = false != s5136;
-  const SWord8 s5138 = s5137 ? s5133 : s5134;
-  const SWord8 s5139 = s1930 ? s5135 : s5138;
-  const SBool  s5140 = (SBool) ((s1966 >> 0) & 1);
-  const SBool  s5141 = false != s5140;
-  const SBool  s5142 = (SBool) ((s1959 >> 0) & 1);
-  const SBool  s5143 = false != s5142;
-  const SWord8 s5144 = s5143 ? s5129 : s5130;
-  const SWord8 s5145 = (s5144 >> 1) | (s5144 << 7);
-  const SWord8 s5146 = 128 | s5145;
-  const SWord8 s5147 = 127 & s5145;
-  const SWord8 s5148 = s5141 ? s5146 : s5147;
-  const SBool  s5149 = (SBool) ((s1971 >> 0) & 1);
-  const SBool  s5150 = false != s5149;
-  const SWord8 s5151 = s5150 ? s5146 : s5147;
-  const SWord8 s5152 = s1930 ? s5148 : s5151;
-  const SWord8 s5153 = s1803 ? s5139 : s5152;
-  const SBool  s5154 = (SBool) ((s1992 >> 0) & 1);
-  const SBool  s5155 = false != s5154;
-  const SBool  s5156 = (SBool) ((s1988 >> 0) & 1);
-  const SBool  s5157 = false != s5156;
-  const SBool  s5158 = (SBool) ((s1981 >> 0) & 1);
-  const SBool  s5159 = false != s5158;
-  const SWord8 s5160 = s5159 ? s5125 : s5126;
-  const SWord8 s5161 = (s5160 >> 1) | (s5160 << 7);
-  const SWord8 s5162 = 128 | s5161;
-  const SWord8 s5163 = 127 & s5161;
-  const SWord8 s5164 = s5157 ? s5162 : s5163;
-  const SWord8 s5165 = (s5164 >> 1) | (s5164 << 7);
-  const SWord8 s5166 = 128 | s5165;
-  const SWord8 s5167 = 127 & s5165;
-  const SWord8 s5168 = s5155 ? s5166 : s5167;
-  const SBool  s5169 = (SBool) ((s1997 >> 0) & 1);
-  const SBool  s5170 = false != s5169;
-  const SWord8 s5171 = s5170 ? s5166 : s5167;
-  const SWord8 s5172 = s1930 ? s5168 : s5171;
-  const SBool  s5173 = (SBool) ((s2013 >> 0) & 1);
-  const SBool  s5174 = false != s5173;
-  const SBool  s5175 = (SBool) ((s2006 >> 0) & 1);
-  const SBool  s5176 = false != s5175;
-  const SWord8 s5177 = s5176 ? s5162 : s5163;
-  const SWord8 s5178 = (s5177 >> 1) | (s5177 << 7);
-  const SWord8 s5179 = 128 | s5178;
-  const SWord8 s5180 = 127 & s5178;
-  const SWord8 s5181 = s5174 ? s5179 : s5180;
-  const SBool  s5182 = (SBool) ((s2018 >> 0) & 1);
-  const SBool  s5183 = false != s5182;
-  const SWord8 s5184 = s5183 ? s5179 : s5180;
-  const SWord8 s5185 = s1930 ? s5181 : s5184;
-  const SWord8 s5186 = s1803 ? s5172 : s5185;
-  const SWord8 s5187 = s1548 ? s5153 : s5186;
-  const SWord8 s5188 = s1037 ? s5117 : s5187;
-  const SWord8 s5189 = s21 ? s5047 : s5188;
-  const SWord8 s5190 = s16 ? s4906 : s5189;
-  const SWord8 s5191 = s11 ? s4623 : s5190;
-  const SBool  s5192 = (SBool) ((s2128 >> 0) & 1);
-  const SBool  s5193 = false != s5192;
-  const SBool  s5194 = (SBool) ((s2124 >> 0) & 1);
-  const SBool  s5195 = false != s5194;
-  const SBool  s5196 = (SBool) ((s2120 >> 0) & 1);
-  const SBool  s5197 = false != s5196;
-  const SWord8 s5198 = (s2107 >> 1) | (s2107 << 7);
-  const SWord8 s5199 = 128 | s5198;
-  const SWord8 s5200 = 127 & s5198;
-  const SWord8 s5201 = s5197 ? s5199 : s5200;
-  const SWord8 s5202 = (s5201 >> 1) | (s5201 << 7);
-  const SWord8 s5203 = 128 | s5202;
-  const SWord8 s5204 = 127 & s5202;
-  const SWord8 s5205 = s5195 ? s5203 : s5204;
-  const SWord8 s5206 = (s5205 >> 1) | (s5205 << 7);
-  const SWord8 s5207 = 128 | s5206;
-  const SWord8 s5208 = 127 & s5206;
-  const SWord8 s5209 = s5193 ? s5207 : s5208;
-  const SBool  s5210 = (SBool) ((s2133 >> 0) & 1);
-  const SBool  s5211 = false != s5210;
-  const SWord8 s5212 = s5211 ? s5207 : s5208;
-  const SWord8 s5213 = s2116 ? s5209 : s5212;
-  const SBool  s5214 = (SBool) ((s2149 >> 0) & 1);
-  const SBool  s5215 = false != s5214;
-  const SBool  s5216 = (SBool) ((s2142 >> 0) & 1);
-  const SBool  s5217 = false != s5216;
-  const SWord8 s5218 = s5217 ? s5203 : s5204;
-  const SWord8 s5219 = (s5218 >> 1) | (s5218 << 7);
-  const SWord8 s5220 = 128 | s5219;
-  const SWord8 s5221 = 127 & s5219;
-  const SWord8 s5222 = s5215 ? s5220 : s5221;
-  const SBool  s5223 = (SBool) ((s2154 >> 0) & 1);
-  const SBool  s5224 = false != s5223;
-  const SWord8 s5225 = s5224 ? s5220 : s5221;
-  const SWord8 s5226 = s2116 ? s5222 : s5225;
-  const SWord8 s5227 = s2097 ? s5213 : s5226;
-  const SBool  s5228 = (SBool) ((s2175 >> 0) & 1);
-  const SBool  s5229 = false != s5228;
-  const SBool  s5230 = (SBool) ((s2171 >> 0) & 1);
-  const SBool  s5231 = false != s5230;
-  const SBool  s5232 = (SBool) ((s2164 >> 0) & 1);
-  const SBool  s5233 = false != s5232;
-  const SWord8 s5234 = s5233 ? s5199 : s5200;
-  const SWord8 s5235 = (s5234 >> 1) | (s5234 << 7);
-  const SWord8 s5236 = 128 | s5235;
-  const SWord8 s5237 = 127 & s5235;
-  const SWord8 s5238 = s5231 ? s5236 : s5237;
-  const SWord8 s5239 = (s5238 >> 1) | (s5238 << 7);
-  const SWord8 s5240 = 128 | s5239;
-  const SWord8 s5241 = 127 & s5239;
-  const SWord8 s5242 = s5229 ? s5240 : s5241;
-  const SBool  s5243 = (SBool) ((s2180 >> 0) & 1);
-  const SBool  s5244 = false != s5243;
-  const SWord8 s5245 = s5244 ? s5240 : s5241;
-  const SWord8 s5246 = s2116 ? s5242 : s5245;
-  const SBool  s5247 = (SBool) ((s2196 >> 0) & 1);
-  const SBool  s5248 = false != s5247;
-  const SBool  s5249 = (SBool) ((s2189 >> 0) & 1);
-  const SBool  s5250 = false != s5249;
-  const SWord8 s5251 = s5250 ? s5236 : s5237;
-  const SWord8 s5252 = (s5251 >> 1) | (s5251 << 7);
-  const SWord8 s5253 = 128 | s5252;
-  const SWord8 s5254 = 127 & s5252;
-  const SWord8 s5255 = s5248 ? s5253 : s5254;
-  const SBool  s5256 = (SBool) ((s2201 >> 0) & 1);
-  const SBool  s5257 = false != s5256;
-  const SWord8 s5258 = s5257 ? s5253 : s5254;
-  const SWord8 s5259 = s2116 ? s5255 : s5258;
-  const SWord8 s5260 = s2097 ? s5246 : s5259;
-  const SWord8 s5261 = s2078 ? s5227 : s5260;
-  const SBool  s5262 = (SBool) ((s2236 >> 0) & 1);
-  const SBool  s5263 = false != s5262;
-  const SBool  s5264 = (SBool) ((s2232 >> 0) & 1);
-  const SBool  s5265 = false != s5264;
-  const SBool  s5266 = (SBool) ((s2228 >> 0) & 1);
-  const SBool  s5267 = false != s5266;
-  const SWord8 s5268 = (s2215 >> 1) | (s2215 << 7);
-  const SWord8 s5269 = 128 | s5268;
-  const SWord8 s5270 = 127 & s5268;
-  const SWord8 s5271 = s5267 ? s5269 : s5270;
-  const SWord8 s5272 = (s5271 >> 1) | (s5271 << 7);
-  const SWord8 s5273 = 128 | s5272;
-  const SWord8 s5274 = 127 & s5272;
-  const SWord8 s5275 = s5265 ? s5273 : s5274;
-  const SWord8 s5276 = (s5275 >> 1) | (s5275 << 7);
-  const SWord8 s5277 = 128 | s5276;
-  const SWord8 s5278 = 127 & s5276;
-  const SWord8 s5279 = s5263 ? s5277 : s5278;
-  const SBool  s5280 = (SBool) ((s2241 >> 0) & 1);
-  const SBool  s5281 = false != s5280;
-  const SWord8 s5282 = s5281 ? s5277 : s5278;
-  const SWord8 s5283 = s2221 ? s5279 : s5282;
-  const SBool  s5284 = (SBool) ((s2257 >> 0) & 1);
-  const SBool  s5285 = false != s5284;
-  const SBool  s5286 = (SBool) ((s2250 >> 0) & 1);
-  const SBool  s5287 = false != s5286;
-  const SWord8 s5288 = s5287 ? s5273 : s5274;
-  const SWord8 s5289 = (s5288 >> 1) | (s5288 << 7);
-  const SWord8 s5290 = 128 | s5289;
-  const SWord8 s5291 = 127 & s5289;
-  const SWord8 s5292 = s5285 ? s5290 : s5291;
-  const SBool  s5293 = (SBool) ((s2262 >> 0) & 1);
-  const SBool  s5294 = false != s5293;
-  const SWord8 s5295 = s5294 ? s5290 : s5291;
-  const SWord8 s5296 = s2221 ? s5292 : s5295;
-  const SWord8 s5297 = s2097 ? s5283 : s5296;
-  const SBool  s5298 = (SBool) ((s2283 >> 0) & 1);
-  const SBool  s5299 = false != s5298;
-  const SBool  s5300 = (SBool) ((s2279 >> 0) & 1);
-  const SBool  s5301 = false != s5300;
-  const SBool  s5302 = (SBool) ((s2272 >> 0) & 1);
-  const SBool  s5303 = false != s5302;
-  const SWord8 s5304 = s5303 ? s5269 : s5270;
-  const SWord8 s5305 = (s5304 >> 1) | (s5304 << 7);
-  const SWord8 s5306 = 128 | s5305;
-  const SWord8 s5307 = 127 & s5305;
-  const SWord8 s5308 = s5301 ? s5306 : s5307;
-  const SWord8 s5309 = (s5308 >> 1) | (s5308 << 7);
-  const SWord8 s5310 = 128 | s5309;
-  const SWord8 s5311 = 127 & s5309;
-  const SWord8 s5312 = s5299 ? s5310 : s5311;
-  const SBool  s5313 = (SBool) ((s2288 >> 0) & 1);
-  const SBool  s5314 = false != s5313;
-  const SWord8 s5315 = s5314 ? s5310 : s5311;
-  const SWord8 s5316 = s2221 ? s5312 : s5315;
-  const SBool  s5317 = (SBool) ((s2304 >> 0) & 1);
-  const SBool  s5318 = false != s5317;
-  const SBool  s5319 = (SBool) ((s2297 >> 0) & 1);
-  const SBool  s5320 = false != s5319;
-  const SWord8 s5321 = s5320 ? s5306 : s5307;
-  const SWord8 s5322 = (s5321 >> 1) | (s5321 << 7);
-  const SWord8 s5323 = 128 | s5322;
-  const SWord8 s5324 = 127 & s5322;
-  const SWord8 s5325 = s5318 ? s5323 : s5324;
-  const SBool  s5326 = (SBool) ((s2309 >> 0) & 1);
-  const SBool  s5327 = false != s5326;
-  const SWord8 s5328 = s5327 ? s5323 : s5324;
-  const SWord8 s5329 = s2221 ? s5325 : s5328;
-  const SWord8 s5330 = s2097 ? s5316 : s5329;
-  const SWord8 s5331 = s2078 ? s5297 : s5330;
-  const SWord8 s5332 = s2059 ? s5261 : s5331;
-  const SBool  s5333 = (SBool) ((s2364 >> 0) & 1);
-  const SBool  s5334 = false != s5333;
-  const SBool  s5335 = (SBool) ((s2360 >> 0) & 1);
-  const SBool  s5336 = false != s5335;
-  const SBool  s5337 = (SBool) ((s2356 >> 0) & 1);
-  const SBool  s5338 = false != s5337;
-  const SWord8 s5339 = (s2343 >> 1) | (s2343 << 7);
-  const SWord8 s5340 = 128 | s5339;
-  const SWord8 s5341 = 127 & s5339;
-  const SWord8 s5342 = s5338 ? s5340 : s5341;
-  const SWord8 s5343 = (s5342 >> 1) | (s5342 << 7);
-  const SWord8 s5344 = 128 | s5343;
-  const SWord8 s5345 = 127 & s5343;
-  const SWord8 s5346 = s5336 ? s5344 : s5345;
-  const SWord8 s5347 = (s5346 >> 1) | (s5346 << 7);
-  const SWord8 s5348 = 128 | s5347;
-  const SWord8 s5349 = 127 & s5347;
-  const SWord8 s5350 = s5334 ? s5348 : s5349;
-  const SBool  s5351 = (SBool) ((s2369 >> 0) & 1);
-  const SBool  s5352 = false != s5351;
-  const SWord8 s5353 = s5352 ? s5348 : s5349;
-  const SWord8 s5354 = s2352 ? s5350 : s5353;
-  const SBool  s5355 = (SBool) ((s2385 >> 0) & 1);
-  const SBool  s5356 = false != s5355;
-  const SBool  s5357 = (SBool) ((s2378 >> 0) & 1);
-  const SBool  s5358 = false != s5357;
-  const SWord8 s5359 = s5358 ? s5344 : s5345;
-  const SWord8 s5360 = (s5359 >> 1) | (s5359 << 7);
-  const SWord8 s5361 = 128 | s5360;
-  const SWord8 s5362 = 127 & s5360;
-  const SWord8 s5363 = s5356 ? s5361 : s5362;
-  const SBool  s5364 = (SBool) ((s2390 >> 0) & 1);
-  const SBool  s5365 = false != s5364;
-  const SWord8 s5366 = s5365 ? s5361 : s5362;
-  const SWord8 s5367 = s2352 ? s5363 : s5366;
-  const SWord8 s5368 = s2330 ? s5354 : s5367;
-  const SBool  s5369 = (SBool) ((s2411 >> 0) & 1);
-  const SBool  s5370 = false != s5369;
-  const SBool  s5371 = (SBool) ((s2407 >> 0) & 1);
-  const SBool  s5372 = false != s5371;
-  const SBool  s5373 = (SBool) ((s2400 >> 0) & 1);
-  const SBool  s5374 = false != s5373;
-  const SWord8 s5375 = s5374 ? s5340 : s5341;
-  const SWord8 s5376 = (s5375 >> 1) | (s5375 << 7);
-  const SWord8 s5377 = 128 | s5376;
-  const SWord8 s5378 = 127 & s5376;
-  const SWord8 s5379 = s5372 ? s5377 : s5378;
-  const SWord8 s5380 = (s5379 >> 1) | (s5379 << 7);
-  const SWord8 s5381 = 128 | s5380;
-  const SWord8 s5382 = 127 & s5380;
-  const SWord8 s5383 = s5370 ? s5381 : s5382;
-  const SBool  s5384 = (SBool) ((s2416 >> 0) & 1);
-  const SBool  s5385 = false != s5384;
-  const SWord8 s5386 = s5385 ? s5381 : s5382;
-  const SWord8 s5387 = s2352 ? s5383 : s5386;
-  const SBool  s5388 = (SBool) ((s2432 >> 0) & 1);
-  const SBool  s5389 = false != s5388;
-  const SBool  s5390 = (SBool) ((s2425 >> 0) & 1);
-  const SBool  s5391 = false != s5390;
-  const SWord8 s5392 = s5391 ? s5377 : s5378;
-  const SWord8 s5393 = (s5392 >> 1) | (s5392 << 7);
-  const SWord8 s5394 = 128 | s5393;
-  const SWord8 s5395 = 127 & s5393;
-  const SWord8 s5396 = s5389 ? s5394 : s5395;
-  const SBool  s5397 = (SBool) ((s2437 >> 0) & 1);
-  const SBool  s5398 = false != s5397;
-  const SWord8 s5399 = s5398 ? s5394 : s5395;
-  const SWord8 s5400 = s2352 ? s5396 : s5399;
-  const SWord8 s5401 = s2330 ? s5387 : s5400;
-  const SWord8 s5402 = s2078 ? s5368 : s5401;
-  const SBool  s5403 = (SBool) ((s2472 >> 0) & 1);
-  const SBool  s5404 = false != s5403;
-  const SBool  s5405 = (SBool) ((s2468 >> 0) & 1);
-  const SBool  s5406 = false != s5405;
-  const SBool  s5407 = (SBool) ((s2464 >> 0) & 1);
-  const SBool  s5408 = false != s5407;
-  const SWord8 s5409 = (s2451 >> 1) | (s2451 << 7);
-  const SWord8 s5410 = 128 | s5409;
-  const SWord8 s5411 = 127 & s5409;
-  const SWord8 s5412 = s5408 ? s5410 : s5411;
-  const SWord8 s5413 = (s5412 >> 1) | (s5412 << 7);
-  const SWord8 s5414 = 128 | s5413;
-  const SWord8 s5415 = 127 & s5413;
-  const SWord8 s5416 = s5406 ? s5414 : s5415;
-  const SWord8 s5417 = (s5416 >> 1) | (s5416 << 7);
-  const SWord8 s5418 = 128 | s5417;
-  const SWord8 s5419 = 127 & s5417;
-  const SWord8 s5420 = s5404 ? s5418 : s5419;
-  const SBool  s5421 = (SBool) ((s2477 >> 0) & 1);
-  const SBool  s5422 = false != s5421;
-  const SWord8 s5423 = s5422 ? s5418 : s5419;
-  const SWord8 s5424 = s2457 ? s5420 : s5423;
-  const SBool  s5425 = (SBool) ((s2493 >> 0) & 1);
-  const SBool  s5426 = false != s5425;
-  const SBool  s5427 = (SBool) ((s2486 >> 0) & 1);
-  const SBool  s5428 = false != s5427;
-  const SWord8 s5429 = s5428 ? s5414 : s5415;
-  const SWord8 s5430 = (s5429 >> 1) | (s5429 << 7);
-  const SWord8 s5431 = 128 | s5430;
-  const SWord8 s5432 = 127 & s5430;
-  const SWord8 s5433 = s5426 ? s5431 : s5432;
-  const SBool  s5434 = (SBool) ((s2498 >> 0) & 1);
-  const SBool  s5435 = false != s5434;
-  const SWord8 s5436 = s5435 ? s5431 : s5432;
-  const SWord8 s5437 = s2457 ? s5433 : s5436;
-  const SWord8 s5438 = s2330 ? s5424 : s5437;
-  const SBool  s5439 = (SBool) ((s2519 >> 0) & 1);
-  const SBool  s5440 = false != s5439;
-  const SBool  s5441 = (SBool) ((s2515 >> 0) & 1);
-  const SBool  s5442 = false != s5441;
-  const SBool  s5443 = (SBool) ((s2508 >> 0) & 1);
-  const SBool  s5444 = false != s5443;
-  const SWord8 s5445 = s5444 ? s5410 : s5411;
-  const SWord8 s5446 = (s5445 >> 1) | (s5445 << 7);
-  const SWord8 s5447 = 128 | s5446;
-  const SWord8 s5448 = 127 & s5446;
-  const SWord8 s5449 = s5442 ? s5447 : s5448;
-  const SWord8 s5450 = (s5449 >> 1) | (s5449 << 7);
-  const SWord8 s5451 = 128 | s5450;
-  const SWord8 s5452 = 127 & s5450;
-  const SWord8 s5453 = s5440 ? s5451 : s5452;
-  const SBool  s5454 = (SBool) ((s2524 >> 0) & 1);
-  const SBool  s5455 = false != s5454;
-  const SWord8 s5456 = s5455 ? s5451 : s5452;
-  const SWord8 s5457 = s2457 ? s5453 : s5456;
-  const SBool  s5458 = (SBool) ((s2540 >> 0) & 1);
-  const SBool  s5459 = false != s5458;
-  const SBool  s5460 = (SBool) ((s2533 >> 0) & 1);
-  const SBool  s5461 = false != s5460;
-  const SWord8 s5462 = s5461 ? s5447 : s5448;
-  const SWord8 s5463 = (s5462 >> 1) | (s5462 << 7);
-  const SWord8 s5464 = 128 | s5463;
-  const SWord8 s5465 = 127 & s5463;
-  const SWord8 s5466 = s5459 ? s5464 : s5465;
-  const SBool  s5467 = (SBool) ((s2545 >> 0) & 1);
-  const SBool  s5468 = false != s5467;
-  const SWord8 s5469 = s5468 ? s5464 : s5465;
-  const SWord8 s5470 = s2457 ? s5466 : s5469;
-  const SWord8 s5471 = s2330 ? s5457 : s5470;
-  const SWord8 s5472 = s2078 ? s5438 : s5471;
-  const SWord8 s5473 = s2059 ? s5402 : s5472;
-  const SWord8 s5474 = s2042 ? s5332 : s5473;
-  const SBool  s5475 = (SBool) ((s2620 >> 0) & 1);
-  const SBool  s5476 = false != s5475;
-  const SBool  s5477 = (SBool) ((s2616 >> 0) & 1);
-  const SBool  s5478 = false != s5477;
-  const SBool  s5479 = (SBool) ((s2612 >> 0) & 1);
-  const SBool  s5480 = false != s5479;
-  const SWord8 s5481 = (s2599 >> 1) | (s2599 << 7);
-  const SWord8 s5482 = 128 | s5481;
-  const SWord8 s5483 = 127 & s5481;
-  const SWord8 s5484 = s5480 ? s5482 : s5483;
-  const SWord8 s5485 = (s5484 >> 1) | (s5484 << 7);
-  const SWord8 s5486 = 128 | s5485;
-  const SWord8 s5487 = 127 & s5485;
-  const SWord8 s5488 = s5478 ? s5486 : s5487;
-  const SWord8 s5489 = (s5488 >> 1) | (s5488 << 7);
-  const SWord8 s5490 = 128 | s5489;
-  const SWord8 s5491 = 127 & s5489;
-  const SWord8 s5492 = s5476 ? s5490 : s5491;
-  const SBool  s5493 = (SBool) ((s2625 >> 0) & 1);
-  const SBool  s5494 = false != s5493;
-  const SWord8 s5495 = s5494 ? s5490 : s5491;
-  const SWord8 s5496 = s2608 ? s5492 : s5495;
-  const SBool  s5497 = (SBool) ((s2641 >> 0) & 1);
-  const SBool  s5498 = false != s5497;
-  const SBool  s5499 = (SBool) ((s2634 >> 0) & 1);
-  const SBool  s5500 = false != s5499;
-  const SWord8 s5501 = s5500 ? s5486 : s5487;
-  const SWord8 s5502 = (s5501 >> 1) | (s5501 << 7);
-  const SWord8 s5503 = 128 | s5502;
-  const SWord8 s5504 = 127 & s5502;
-  const SWord8 s5505 = s5498 ? s5503 : s5504;
-  const SBool  s5506 = (SBool) ((s2646 >> 0) & 1);
-  const SBool  s5507 = false != s5506;
-  const SWord8 s5508 = s5507 ? s5503 : s5504;
-  const SWord8 s5509 = s2608 ? s5505 : s5508;
-  const SWord8 s5510 = s2589 ? s5496 : s5509;
-  const SBool  s5511 = (SBool) ((s2667 >> 0) & 1);
-  const SBool  s5512 = false != s5511;
-  const SBool  s5513 = (SBool) ((s2663 >> 0) & 1);
-  const SBool  s5514 = false != s5513;
-  const SBool  s5515 = (SBool) ((s2656 >> 0) & 1);
-  const SBool  s5516 = false != s5515;
-  const SWord8 s5517 = s5516 ? s5482 : s5483;
-  const SWord8 s5518 = (s5517 >> 1) | (s5517 << 7);
-  const SWord8 s5519 = 128 | s5518;
-  const SWord8 s5520 = 127 & s5518;
-  const SWord8 s5521 = s5514 ? s5519 : s5520;
-  const SWord8 s5522 = (s5521 >> 1) | (s5521 << 7);
-  const SWord8 s5523 = 128 | s5522;
-  const SWord8 s5524 = 127 & s5522;
-  const SWord8 s5525 = s5512 ? s5523 : s5524;
-  const SBool  s5526 = (SBool) ((s2672 >> 0) & 1);
-  const SBool  s5527 = false != s5526;
-  const SWord8 s5528 = s5527 ? s5523 : s5524;
-  const SWord8 s5529 = s2608 ? s5525 : s5528;
-  const SBool  s5530 = (SBool) ((s2688 >> 0) & 1);
-  const SBool  s5531 = false != s5530;
-  const SBool  s5532 = (SBool) ((s2681 >> 0) & 1);
-  const SBool  s5533 = false != s5532;
-  const SWord8 s5534 = s5533 ? s5519 : s5520;
-  const SWord8 s5535 = (s5534 >> 1) | (s5534 << 7);
-  const SWord8 s5536 = 128 | s5535;
-  const SWord8 s5537 = 127 & s5535;
-  const SWord8 s5538 = s5531 ? s5536 : s5537;
-  const SBool  s5539 = (SBool) ((s2693 >> 0) & 1);
-  const SBool  s5540 = false != s5539;
-  const SWord8 s5541 = s5540 ? s5536 : s5537;
-  const SWord8 s5542 = s2608 ? s5538 : s5541;
-  const SWord8 s5543 = s2589 ? s5529 : s5542;
-  const SWord8 s5544 = s2567 ? s5510 : s5543;
-  const SBool  s5545 = (SBool) ((s2728 >> 0) & 1);
-  const SBool  s5546 = false != s5545;
-  const SBool  s5547 = (SBool) ((s2724 >> 0) & 1);
-  const SBool  s5548 = false != s5547;
-  const SBool  s5549 = (SBool) ((s2720 >> 0) & 1);
-  const SBool  s5550 = false != s5549;
-  const SWord8 s5551 = (s2707 >> 1) | (s2707 << 7);
-  const SWord8 s5552 = 128 | s5551;
-  const SWord8 s5553 = 127 & s5551;
-  const SWord8 s5554 = s5550 ? s5552 : s5553;
-  const SWord8 s5555 = (s5554 >> 1) | (s5554 << 7);
-  const SWord8 s5556 = 128 | s5555;
-  const SWord8 s5557 = 127 & s5555;
-  const SWord8 s5558 = s5548 ? s5556 : s5557;
-  const SWord8 s5559 = (s5558 >> 1) | (s5558 << 7);
-  const SWord8 s5560 = 128 | s5559;
-  const SWord8 s5561 = 127 & s5559;
-  const SWord8 s5562 = s5546 ? s5560 : s5561;
-  const SBool  s5563 = (SBool) ((s2733 >> 0) & 1);
-  const SBool  s5564 = false != s5563;
-  const SWord8 s5565 = s5564 ? s5560 : s5561;
-  const SWord8 s5566 = s2713 ? s5562 : s5565;
-  const SBool  s5567 = (SBool) ((s2749 >> 0) & 1);
-  const SBool  s5568 = false != s5567;
-  const SBool  s5569 = (SBool) ((s2742 >> 0) & 1);
-  const SBool  s5570 = false != s5569;
-  const SWord8 s5571 = s5570 ? s5556 : s5557;
-  const SWord8 s5572 = (s5571 >> 1) | (s5571 << 7);
-  const SWord8 s5573 = 128 | s5572;
-  const SWord8 s5574 = 127 & s5572;
-  const SWord8 s5575 = s5568 ? s5573 : s5574;
-  const SBool  s5576 = (SBool) ((s2754 >> 0) & 1);
-  const SBool  s5577 = false != s5576;
-  const SWord8 s5578 = s5577 ? s5573 : s5574;
-  const SWord8 s5579 = s2713 ? s5575 : s5578;
-  const SWord8 s5580 = s2589 ? s5566 : s5579;
-  const SBool  s5581 = (SBool) ((s2775 >> 0) & 1);
-  const SBool  s5582 = false != s5581;
-  const SBool  s5583 = (SBool) ((s2771 >> 0) & 1);
-  const SBool  s5584 = false != s5583;
-  const SBool  s5585 = (SBool) ((s2764 >> 0) & 1);
-  const SBool  s5586 = false != s5585;
-  const SWord8 s5587 = s5586 ? s5552 : s5553;
-  const SWord8 s5588 = (s5587 >> 1) | (s5587 << 7);
-  const SWord8 s5589 = 128 | s5588;
-  const SWord8 s5590 = 127 & s5588;
-  const SWord8 s5591 = s5584 ? s5589 : s5590;
-  const SWord8 s5592 = (s5591 >> 1) | (s5591 << 7);
-  const SWord8 s5593 = 128 | s5592;
-  const SWord8 s5594 = 127 & s5592;
-  const SWord8 s5595 = s5582 ? s5593 : s5594;
-  const SBool  s5596 = (SBool) ((s2780 >> 0) & 1);
-  const SBool  s5597 = false != s5596;
-  const SWord8 s5598 = s5597 ? s5593 : s5594;
-  const SWord8 s5599 = s2713 ? s5595 : s5598;
-  const SBool  s5600 = (SBool) ((s2796 >> 0) & 1);
-  const SBool  s5601 = false != s5600;
-  const SBool  s5602 = (SBool) ((s2789 >> 0) & 1);
-  const SBool  s5603 = false != s5602;
-  const SWord8 s5604 = s5603 ? s5589 : s5590;
-  const SWord8 s5605 = (s5604 >> 1) | (s5604 << 7);
-  const SWord8 s5606 = 128 | s5605;
-  const SWord8 s5607 = 127 & s5605;
-  const SWord8 s5608 = s5601 ? s5606 : s5607;
-  const SBool  s5609 = (SBool) ((s2801 >> 0) & 1);
-  const SBool  s5610 = false != s5609;
-  const SWord8 s5611 = s5610 ? s5606 : s5607;
-  const SWord8 s5612 = s2713 ? s5608 : s5611;
-  const SWord8 s5613 = s2589 ? s5599 : s5612;
-  const SWord8 s5614 = s2567 ? s5580 : s5613;
-  const SWord8 s5615 = s2059 ? s5544 : s5614;
-  const SBool  s5616 = (SBool) ((s2856 >> 0) & 1);
-  const SBool  s5617 = false != s5616;
-  const SBool  s5618 = (SBool) ((s2852 >> 0) & 1);
-  const SBool  s5619 = false != s5618;
-  const SBool  s5620 = (SBool) ((s2848 >> 0) & 1);
-  const SBool  s5621 = false != s5620;
-  const SWord8 s5622 = (s2835 >> 1) | (s2835 << 7);
-  const SWord8 s5623 = 128 | s5622;
-  const SWord8 s5624 = 127 & s5622;
-  const SWord8 s5625 = s5621 ? s5623 : s5624;
-  const SWord8 s5626 = (s5625 >> 1) | (s5625 << 7);
-  const SWord8 s5627 = 128 | s5626;
-  const SWord8 s5628 = 127 & s5626;
-  const SWord8 s5629 = s5619 ? s5627 : s5628;
-  const SWord8 s5630 = (s5629 >> 1) | (s5629 << 7);
-  const SWord8 s5631 = 128 | s5630;
-  const SWord8 s5632 = 127 & s5630;
-  const SWord8 s5633 = s5617 ? s5631 : s5632;
-  const SBool  s5634 = (SBool) ((s2861 >> 0) & 1);
-  const SBool  s5635 = false != s5634;
-  const SWord8 s5636 = s5635 ? s5631 : s5632;
-  const SWord8 s5637 = s2844 ? s5633 : s5636;
-  const SBool  s5638 = (SBool) ((s2877 >> 0) & 1);
-  const SBool  s5639 = false != s5638;
-  const SBool  s5640 = (SBool) ((s2870 >> 0) & 1);
-  const SBool  s5641 = false != s5640;
-  const SWord8 s5642 = s5641 ? s5627 : s5628;
-  const SWord8 s5643 = (s5642 >> 1) | (s5642 << 7);
-  const SWord8 s5644 = 128 | s5643;
-  const SWord8 s5645 = 127 & s5643;
-  const SWord8 s5646 = s5639 ? s5644 : s5645;
-  const SBool  s5647 = (SBool) ((s2882 >> 0) & 1);
-  const SBool  s5648 = false != s5647;
-  const SWord8 s5649 = s5648 ? s5644 : s5645;
-  const SWord8 s5650 = s2844 ? s5646 : s5649;
-  const SWord8 s5651 = s2822 ? s5637 : s5650;
-  const SBool  s5652 = (SBool) ((s2903 >> 0) & 1);
-  const SBool  s5653 = false != s5652;
-  const SBool  s5654 = (SBool) ((s2899 >> 0) & 1);
-  const SBool  s5655 = false != s5654;
-  const SBool  s5656 = (SBool) ((s2892 >> 0) & 1);
-  const SBool  s5657 = false != s5656;
-  const SWord8 s5658 = s5657 ? s5623 : s5624;
-  const SWord8 s5659 = (s5658 >> 1) | (s5658 << 7);
-  const SWord8 s5660 = 128 | s5659;
-  const SWord8 s5661 = 127 & s5659;
-  const SWord8 s5662 = s5655 ? s5660 : s5661;
-  const SWord8 s5663 = (s5662 >> 1) | (s5662 << 7);
-  const SWord8 s5664 = 128 | s5663;
-  const SWord8 s5665 = 127 & s5663;
-  const SWord8 s5666 = s5653 ? s5664 : s5665;
-  const SBool  s5667 = (SBool) ((s2908 >> 0) & 1);
-  const SBool  s5668 = false != s5667;
-  const SWord8 s5669 = s5668 ? s5664 : s5665;
-  const SWord8 s5670 = s2844 ? s5666 : s5669;
-  const SBool  s5671 = (SBool) ((s2924 >> 0) & 1);
-  const SBool  s5672 = false != s5671;
-  const SBool  s5673 = (SBool) ((s2917 >> 0) & 1);
-  const SBool  s5674 = false != s5673;
-  const SWord8 s5675 = s5674 ? s5660 : s5661;
-  const SWord8 s5676 = (s5675 >> 1) | (s5675 << 7);
-  const SWord8 s5677 = 128 | s5676;
-  const SWord8 s5678 = 127 & s5676;
-  const SWord8 s5679 = s5672 ? s5677 : s5678;
-  const SBool  s5680 = (SBool) ((s2929 >> 0) & 1);
-  const SBool  s5681 = false != s5680;
-  const SWord8 s5682 = s5681 ? s5677 : s5678;
-  const SWord8 s5683 = s2844 ? s5679 : s5682;
-  const SWord8 s5684 = s2822 ? s5670 : s5683;
-  const SWord8 s5685 = s2567 ? s5651 : s5684;
-  const SBool  s5686 = (SBool) ((s2964 >> 0) & 1);
-  const SBool  s5687 = false != s5686;
-  const SBool  s5688 = (SBool) ((s2960 >> 0) & 1);
-  const SBool  s5689 = false != s5688;
-  const SBool  s5690 = (SBool) ((s2956 >> 0) & 1);
-  const SBool  s5691 = false != s5690;
-  const SWord8 s5692 = (s2943 >> 1) | (s2943 << 7);
-  const SWord8 s5693 = 128 | s5692;
-  const SWord8 s5694 = 127 & s5692;
-  const SWord8 s5695 = s5691 ? s5693 : s5694;
-  const SWord8 s5696 = (s5695 >> 1) | (s5695 << 7);
-  const SWord8 s5697 = 128 | s5696;
-  const SWord8 s5698 = 127 & s5696;
-  const SWord8 s5699 = s5689 ? s5697 : s5698;
-  const SWord8 s5700 = (s5699 >> 1) | (s5699 << 7);
-  const SWord8 s5701 = 128 | s5700;
-  const SWord8 s5702 = 127 & s5700;
-  const SWord8 s5703 = s5687 ? s5701 : s5702;
-  const SBool  s5704 = (SBool) ((s2969 >> 0) & 1);
-  const SBool  s5705 = false != s5704;
-  const SWord8 s5706 = s5705 ? s5701 : s5702;
-  const SWord8 s5707 = s2949 ? s5703 : s5706;
-  const SBool  s5708 = (SBool) ((s2985 >> 0) & 1);
-  const SBool  s5709 = false != s5708;
-  const SBool  s5710 = (SBool) ((s2978 >> 0) & 1);
-  const SBool  s5711 = false != s5710;
-  const SWord8 s5712 = s5711 ? s5697 : s5698;
-  const SWord8 s5713 = (s5712 >> 1) | (s5712 << 7);
-  const SWord8 s5714 = 128 | s5713;
-  const SWord8 s5715 = 127 & s5713;
-  const SWord8 s5716 = s5709 ? s5714 : s5715;
-  const SBool  s5717 = (SBool) ((s2990 >> 0) & 1);
-  const SBool  s5718 = false != s5717;
-  const SWord8 s5719 = s5718 ? s5714 : s5715;
-  const SWord8 s5720 = s2949 ? s5716 : s5719;
-  const SWord8 s5721 = s2822 ? s5707 : s5720;
-  const SBool  s5722 = (SBool) ((s3011 >> 0) & 1);
-  const SBool  s5723 = false != s5722;
-  const SBool  s5724 = (SBool) ((s3007 >> 0) & 1);
-  const SBool  s5725 = false != s5724;
-  const SBool  s5726 = (SBool) ((s3000 >> 0) & 1);
-  const SBool  s5727 = false != s5726;
-  const SWord8 s5728 = s5727 ? s5693 : s5694;
-  const SWord8 s5729 = (s5728 >> 1) | (s5728 << 7);
-  const SWord8 s5730 = 128 | s5729;
-  const SWord8 s5731 = 127 & s5729;
-  const SWord8 s5732 = s5725 ? s5730 : s5731;
-  const SWord8 s5733 = (s5732 >> 1) | (s5732 << 7);
-  const SWord8 s5734 = 128 | s5733;
-  const SWord8 s5735 = 127 & s5733;
-  const SWord8 s5736 = s5723 ? s5734 : s5735;
-  const SBool  s5737 = (SBool) ((s3016 >> 0) & 1);
-  const SBool  s5738 = false != s5737;
-  const SWord8 s5739 = s5738 ? s5734 : s5735;
-  const SWord8 s5740 = s2949 ? s5736 : s5739;
-  const SBool  s5741 = (SBool) ((s3032 >> 0) & 1);
-  const SBool  s5742 = false != s5741;
-  const SBool  s5743 = (SBool) ((s3025 >> 0) & 1);
-  const SBool  s5744 = false != s5743;
-  const SWord8 s5745 = s5744 ? s5730 : s5731;
-  const SWord8 s5746 = (s5745 >> 1) | (s5745 << 7);
-  const SWord8 s5747 = 128 | s5746;
-  const SWord8 s5748 = 127 & s5746;
-  const SWord8 s5749 = s5742 ? s5747 : s5748;
-  const SBool  s5750 = (SBool) ((s3037 >> 0) & 1);
-  const SBool  s5751 = false != s5750;
-  const SWord8 s5752 = s5751 ? s5747 : s5748;
-  const SWord8 s5753 = s2949 ? s5749 : s5752;
-  const SWord8 s5754 = s2822 ? s5740 : s5753;
-  const SWord8 s5755 = s2567 ? s5721 : s5754;
-  const SWord8 s5756 = s2059 ? s5685 : s5755;
-  const SWord8 s5757 = s2042 ? s5615 : s5756;
-  const SWord8 s5758 = s16 ? s5474 : s5757;
-  const SBool  s5759 = (SBool) ((s3132 >> 0) & 1);
-  const SBool  s5760 = false != s5759;
-  const SBool  s5761 = (SBool) ((s3128 >> 0) & 1);
-  const SBool  s5762 = false != s5761;
-  const SBool  s5763 = (SBool) ((s3124 >> 0) & 1);
-  const SBool  s5764 = false != s5763;
-  const SWord8 s5765 = (s3111 >> 1) | (s3111 << 7);
-  const SWord8 s5766 = 128 | s5765;
-  const SWord8 s5767 = 127 & s5765;
-  const SWord8 s5768 = s5764 ? s5766 : s5767;
-  const SWord8 s5769 = (s5768 >> 1) | (s5768 << 7);
-  const SWord8 s5770 = 128 | s5769;
-  const SWord8 s5771 = 127 & s5769;
-  const SWord8 s5772 = s5762 ? s5770 : s5771;
-  const SWord8 s5773 = (s5772 >> 1) | (s5772 << 7);
-  const SWord8 s5774 = 128 | s5773;
-  const SWord8 s5775 = 127 & s5773;
-  const SWord8 s5776 = s5760 ? s5774 : s5775;
-  const SBool  s5777 = (SBool) ((s3137 >> 0) & 1);
-  const SBool  s5778 = false != s5777;
-  const SWord8 s5779 = s5778 ? s5774 : s5775;
-  const SWord8 s5780 = s3120 ? s5776 : s5779;
-  const SBool  s5781 = (SBool) ((s3153 >> 0) & 1);
-  const SBool  s5782 = false != s5781;
-  const SBool  s5783 = (SBool) ((s3146 >> 0) & 1);
-  const SBool  s5784 = false != s5783;
-  const SWord8 s5785 = s5784 ? s5770 : s5771;
-  const SWord8 s5786 = (s5785 >> 1) | (s5785 << 7);
-  const SWord8 s5787 = 128 | s5786;
-  const SWord8 s5788 = 127 & s5786;
-  const SWord8 s5789 = s5782 ? s5787 : s5788;
-  const SBool  s5790 = (SBool) ((s3158 >> 0) & 1);
-  const SBool  s5791 = false != s5790;
-  const SWord8 s5792 = s5791 ? s5787 : s5788;
-  const SWord8 s5793 = s3120 ? s5789 : s5792;
-  const SWord8 s5794 = s3101 ? s5780 : s5793;
-  const SBool  s5795 = (SBool) ((s3179 >> 0) & 1);
-  const SBool  s5796 = false != s5795;
-  const SBool  s5797 = (SBool) ((s3175 >> 0) & 1);
-  const SBool  s5798 = false != s5797;
-  const SBool  s5799 = (SBool) ((s3168 >> 0) & 1);
-  const SBool  s5800 = false != s5799;
-  const SWord8 s5801 = s5800 ? s5766 : s5767;
-  const SWord8 s5802 = (s5801 >> 1) | (s5801 << 7);
-  const SWord8 s5803 = 128 | s5802;
-  const SWord8 s5804 = 127 & s5802;
-  const SWord8 s5805 = s5798 ? s5803 : s5804;
-  const SWord8 s5806 = (s5805 >> 1) | (s5805 << 7);
-  const SWord8 s5807 = 128 | s5806;
-  const SWord8 s5808 = 127 & s5806;
-  const SWord8 s5809 = s5796 ? s5807 : s5808;
-  const SBool  s5810 = (SBool) ((s3184 >> 0) & 1);
-  const SBool  s5811 = false != s5810;
-  const SWord8 s5812 = s5811 ? s5807 : s5808;
-  const SWord8 s5813 = s3120 ? s5809 : s5812;
-  const SBool  s5814 = (SBool) ((s3200 >> 0) & 1);
-  const SBool  s5815 = false != s5814;
-  const SBool  s5816 = (SBool) ((s3193 >> 0) & 1);
-  const SBool  s5817 = false != s5816;
-  const SWord8 s5818 = s5817 ? s5803 : s5804;
-  const SWord8 s5819 = (s5818 >> 1) | (s5818 << 7);
-  const SWord8 s5820 = 128 | s5819;
-  const SWord8 s5821 = 127 & s5819;
-  const SWord8 s5822 = s5815 ? s5820 : s5821;
-  const SBool  s5823 = (SBool) ((s3205 >> 0) & 1);
-  const SBool  s5824 = false != s5823;
-  const SWord8 s5825 = s5824 ? s5820 : s5821;
-  const SWord8 s5826 = s3120 ? s5822 : s5825;
-  const SWord8 s5827 = s3101 ? s5813 : s5826;
-  const SWord8 s5828 = s3082 ? s5794 : s5827;
-  const SBool  s5829 = (SBool) ((s3240 >> 0) & 1);
-  const SBool  s5830 = false != s5829;
-  const SBool  s5831 = (SBool) ((s3236 >> 0) & 1);
-  const SBool  s5832 = false != s5831;
-  const SBool  s5833 = (SBool) ((s3232 >> 0) & 1);
-  const SBool  s5834 = false != s5833;
-  const SWord8 s5835 = (s3219 >> 1) | (s3219 << 7);
-  const SWord8 s5836 = 128 | s5835;
-  const SWord8 s5837 = 127 & s5835;
-  const SWord8 s5838 = s5834 ? s5836 : s5837;
-  const SWord8 s5839 = (s5838 >> 1) | (s5838 << 7);
-  const SWord8 s5840 = 128 | s5839;
-  const SWord8 s5841 = 127 & s5839;
-  const SWord8 s5842 = s5832 ? s5840 : s5841;
-  const SWord8 s5843 = (s5842 >> 1) | (s5842 << 7);
-  const SWord8 s5844 = 128 | s5843;
-  const SWord8 s5845 = 127 & s5843;
-  const SWord8 s5846 = s5830 ? s5844 : s5845;
-  const SBool  s5847 = (SBool) ((s3245 >> 0) & 1);
-  const SBool  s5848 = false != s5847;
-  const SWord8 s5849 = s5848 ? s5844 : s5845;
-  const SWord8 s5850 = s3225 ? s5846 : s5849;
-  const SBool  s5851 = (SBool) ((s3261 >> 0) & 1);
-  const SBool  s5852 = false != s5851;
-  const SBool  s5853 = (SBool) ((s3254 >> 0) & 1);
-  const SBool  s5854 = false != s5853;
-  const SWord8 s5855 = s5854 ? s5840 : s5841;
-  const SWord8 s5856 = (s5855 >> 1) | (s5855 << 7);
-  const SWord8 s5857 = 128 | s5856;
-  const SWord8 s5858 = 127 & s5856;
-  const SWord8 s5859 = s5852 ? s5857 : s5858;
-  const SBool  s5860 = (SBool) ((s3266 >> 0) & 1);
-  const SBool  s5861 = false != s5860;
-  const SWord8 s5862 = s5861 ? s5857 : s5858;
-  const SWord8 s5863 = s3225 ? s5859 : s5862;
-  const SWord8 s5864 = s3101 ? s5850 : s5863;
-  const SBool  s5865 = (SBool) ((s3287 >> 0) & 1);
-  const SBool  s5866 = false != s5865;
-  const SBool  s5867 = (SBool) ((s3283 >> 0) & 1);
-  const SBool  s5868 = false != s5867;
-  const SBool  s5869 = (SBool) ((s3276 >> 0) & 1);
-  const SBool  s5870 = false != s5869;
-  const SWord8 s5871 = s5870 ? s5836 : s5837;
-  const SWord8 s5872 = (s5871 >> 1) | (s5871 << 7);
-  const SWord8 s5873 = 128 | s5872;
-  const SWord8 s5874 = 127 & s5872;
-  const SWord8 s5875 = s5868 ? s5873 : s5874;
-  const SWord8 s5876 = (s5875 >> 1) | (s5875 << 7);
-  const SWord8 s5877 = 128 | s5876;
-  const SWord8 s5878 = 127 & s5876;
-  const SWord8 s5879 = s5866 ? s5877 : s5878;
-  const SBool  s5880 = (SBool) ((s3292 >> 0) & 1);
-  const SBool  s5881 = false != s5880;
-  const SWord8 s5882 = s5881 ? s5877 : s5878;
-  const SWord8 s5883 = s3225 ? s5879 : s5882;
-  const SBool  s5884 = (SBool) ((s3308 >> 0) & 1);
-  const SBool  s5885 = false != s5884;
-  const SBool  s5886 = (SBool) ((s3301 >> 0) & 1);
-  const SBool  s5887 = false != s5886;
-  const SWord8 s5888 = s5887 ? s5873 : s5874;
-  const SWord8 s5889 = (s5888 >> 1) | (s5888 << 7);
-  const SWord8 s5890 = 128 | s5889;
-  const SWord8 s5891 = 127 & s5889;
-  const SWord8 s5892 = s5885 ? s5890 : s5891;
-  const SBool  s5893 = (SBool) ((s3313 >> 0) & 1);
-  const SBool  s5894 = false != s5893;
-  const SWord8 s5895 = s5894 ? s5890 : s5891;
-  const SWord8 s5896 = s3225 ? s5892 : s5895;
-  const SWord8 s5897 = s3101 ? s5883 : s5896;
-  const SWord8 s5898 = s3082 ? s5864 : s5897;
-  const SWord8 s5899 = s3060 ? s5828 : s5898;
-  const SBool  s5900 = (SBool) ((s3368 >> 0) & 1);
-  const SBool  s5901 = false != s5900;
-  const SBool  s5902 = (SBool) ((s3364 >> 0) & 1);
-  const SBool  s5903 = false != s5902;
-  const SBool  s5904 = (SBool) ((s3360 >> 0) & 1);
-  const SBool  s5905 = false != s5904;
-  const SWord8 s5906 = (s3347 >> 1) | (s3347 << 7);
-  const SWord8 s5907 = 128 | s5906;
-  const SWord8 s5908 = 127 & s5906;
-  const SWord8 s5909 = s5905 ? s5907 : s5908;
-  const SWord8 s5910 = (s5909 >> 1) | (s5909 << 7);
-  const SWord8 s5911 = 128 | s5910;
-  const SWord8 s5912 = 127 & s5910;
-  const SWord8 s5913 = s5903 ? s5911 : s5912;
-  const SWord8 s5914 = (s5913 >> 1) | (s5913 << 7);
-  const SWord8 s5915 = 128 | s5914;
-  const SWord8 s5916 = 127 & s5914;
-  const SWord8 s5917 = s5901 ? s5915 : s5916;
-  const SBool  s5918 = (SBool) ((s3373 >> 0) & 1);
-  const SBool  s5919 = false != s5918;
-  const SWord8 s5920 = s5919 ? s5915 : s5916;
-  const SWord8 s5921 = s3356 ? s5917 : s5920;
-  const SBool  s5922 = (SBool) ((s3389 >> 0) & 1);
-  const SBool  s5923 = false != s5922;
-  const SBool  s5924 = (SBool) ((s3382 >> 0) & 1);
-  const SBool  s5925 = false != s5924;
-  const SWord8 s5926 = s5925 ? s5911 : s5912;
-  const SWord8 s5927 = (s5926 >> 1) | (s5926 << 7);
-  const SWord8 s5928 = 128 | s5927;
-  const SWord8 s5929 = 127 & s5927;
-  const SWord8 s5930 = s5923 ? s5928 : s5929;
-  const SBool  s5931 = (SBool) ((s3394 >> 0) & 1);
-  const SBool  s5932 = false != s5931;
-  const SWord8 s5933 = s5932 ? s5928 : s5929;
-  const SWord8 s5934 = s3356 ? s5930 : s5933;
-  const SWord8 s5935 = s3334 ? s5921 : s5934;
-  const SBool  s5936 = (SBool) ((s3415 >> 0) & 1);
-  const SBool  s5937 = false != s5936;
-  const SBool  s5938 = (SBool) ((s3411 >> 0) & 1);
-  const SBool  s5939 = false != s5938;
-  const SBool  s5940 = (SBool) ((s3404 >> 0) & 1);
-  const SBool  s5941 = false != s5940;
-  const SWord8 s5942 = s5941 ? s5907 : s5908;
-  const SWord8 s5943 = (s5942 >> 1) | (s5942 << 7);
-  const SWord8 s5944 = 128 | s5943;
-  const SWord8 s5945 = 127 & s5943;
-  const SWord8 s5946 = s5939 ? s5944 : s5945;
-  const SWord8 s5947 = (s5946 >> 1) | (s5946 << 7);
-  const SWord8 s5948 = 128 | s5947;
-  const SWord8 s5949 = 127 & s5947;
-  const SWord8 s5950 = s5937 ? s5948 : s5949;
-  const SBool  s5951 = (SBool) ((s3420 >> 0) & 1);
-  const SBool  s5952 = false != s5951;
-  const SWord8 s5953 = s5952 ? s5948 : s5949;
-  const SWord8 s5954 = s3356 ? s5950 : s5953;
-  const SBool  s5955 = (SBool) ((s3436 >> 0) & 1);
-  const SBool  s5956 = false != s5955;
-  const SBool  s5957 = (SBool) ((s3429 >> 0) & 1);
-  const SBool  s5958 = false != s5957;
-  const SWord8 s5959 = s5958 ? s5944 : s5945;
-  const SWord8 s5960 = (s5959 >> 1) | (s5959 << 7);
-  const SWord8 s5961 = 128 | s5960;
-  const SWord8 s5962 = 127 & s5960;
-  const SWord8 s5963 = s5956 ? s5961 : s5962;
-  const SBool  s5964 = (SBool) ((s3441 >> 0) & 1);
-  const SBool  s5965 = false != s5964;
-  const SWord8 s5966 = s5965 ? s5961 : s5962;
-  const SWord8 s5967 = s3356 ? s5963 : s5966;
-  const SWord8 s5968 = s3334 ? s5954 : s5967;
-  const SWord8 s5969 = s3082 ? s5935 : s5968;
-  const SBool  s5970 = (SBool) ((s3476 >> 0) & 1);
-  const SBool  s5971 = false != s5970;
-  const SBool  s5972 = (SBool) ((s3472 >> 0) & 1);
-  const SBool  s5973 = false != s5972;
-  const SBool  s5974 = (SBool) ((s3468 >> 0) & 1);
-  const SBool  s5975 = false != s5974;
-  const SWord8 s5976 = (s3455 >> 1) | (s3455 << 7);
-  const SWord8 s5977 = 128 | s5976;
-  const SWord8 s5978 = 127 & s5976;
-  const SWord8 s5979 = s5975 ? s5977 : s5978;
-  const SWord8 s5980 = (s5979 >> 1) | (s5979 << 7);
-  const SWord8 s5981 = 128 | s5980;
-  const SWord8 s5982 = 127 & s5980;
-  const SWord8 s5983 = s5973 ? s5981 : s5982;
-  const SWord8 s5984 = (s5983 >> 1) | (s5983 << 7);
-  const SWord8 s5985 = 128 | s5984;
-  const SWord8 s5986 = 127 & s5984;
-  const SWord8 s5987 = s5971 ? s5985 : s5986;
-  const SBool  s5988 = (SBool) ((s3481 >> 0) & 1);
-  const SBool  s5989 = false != s5988;
-  const SWord8 s5990 = s5989 ? s5985 : s5986;
-  const SWord8 s5991 = s3461 ? s5987 : s5990;
-  const SBool  s5992 = (SBool) ((s3497 >> 0) & 1);
-  const SBool  s5993 = false != s5992;
-  const SBool  s5994 = (SBool) ((s3490 >> 0) & 1);
-  const SBool  s5995 = false != s5994;
-  const SWord8 s5996 = s5995 ? s5981 : s5982;
-  const SWord8 s5997 = (s5996 >> 1) | (s5996 << 7);
-  const SWord8 s5998 = 128 | s5997;
-  const SWord8 s5999 = 127 & s5997;
-  const SWord8 s6000 = s5993 ? s5998 : s5999;
-  const SBool  s6001 = (SBool) ((s3502 >> 0) & 1);
-  const SBool  s6002 = false != s6001;
-  const SWord8 s6003 = s6002 ? s5998 : s5999;
-  const SWord8 s6004 = s3461 ? s6000 : s6003;
-  const SWord8 s6005 = s3334 ? s5991 : s6004;
-  const SBool  s6006 = (SBool) ((s3523 >> 0) & 1);
-  const SBool  s6007 = false != s6006;
-  const SBool  s6008 = (SBool) ((s3519 >> 0) & 1);
-  const SBool  s6009 = false != s6008;
-  const SBool  s6010 = (SBool) ((s3512 >> 0) & 1);
-  const SBool  s6011 = false != s6010;
-  const SWord8 s6012 = s6011 ? s5977 : s5978;
-  const SWord8 s6013 = (s6012 >> 1) | (s6012 << 7);
-  const SWord8 s6014 = 128 | s6013;
-  const SWord8 s6015 = 127 & s6013;
-  const SWord8 s6016 = s6009 ? s6014 : s6015;
-  const SWord8 s6017 = (s6016 >> 1) | (s6016 << 7);
-  const SWord8 s6018 = 128 | s6017;
-  const SWord8 s6019 = 127 & s6017;
-  const SWord8 s6020 = s6007 ? s6018 : s6019;
-  const SBool  s6021 = (SBool) ((s3528 >> 0) & 1);
-  const SBool  s6022 = false != s6021;
-  const SWord8 s6023 = s6022 ? s6018 : s6019;
-  const SWord8 s6024 = s3461 ? s6020 : s6023;
-  const SBool  s6025 = (SBool) ((s3544 >> 0) & 1);
-  const SBool  s6026 = false != s6025;
-  const SBool  s6027 = (SBool) ((s3537 >> 0) & 1);
-  const SBool  s6028 = false != s6027;
-  const SWord8 s6029 = s6028 ? s6014 : s6015;
-  const SWord8 s6030 = (s6029 >> 1) | (s6029 << 7);
-  const SWord8 s6031 = 128 | s6030;
-  const SWord8 s6032 = 127 & s6030;
-  const SWord8 s6033 = s6026 ? s6031 : s6032;
-  const SBool  s6034 = (SBool) ((s3549 >> 0) & 1);
-  const SBool  s6035 = false != s6034;
-  const SWord8 s6036 = s6035 ? s6031 : s6032;
-  const SWord8 s6037 = s3461 ? s6033 : s6036;
-  const SWord8 s6038 = s3334 ? s6024 : s6037;
-  const SWord8 s6039 = s3082 ? s6005 : s6038;
-  const SWord8 s6040 = s3060 ? s5969 : s6039;
-  const SWord8 s6041 = s2042 ? s5899 : s6040;
-  const SBool  s6042 = (SBool) ((s3624 >> 0) & 1);
-  const SBool  s6043 = false != s6042;
-  const SBool  s6044 = (SBool) ((s3620 >> 0) & 1);
-  const SBool  s6045 = false != s6044;
-  const SBool  s6046 = (SBool) ((s3616 >> 0) & 1);
-  const SBool  s6047 = false != s6046;
-  const SWord8 s6048 = (s3603 >> 1) | (s3603 << 7);
-  const SWord8 s6049 = 128 | s6048;
-  const SWord8 s6050 = 127 & s6048;
-  const SWord8 s6051 = s6047 ? s6049 : s6050;
-  const SWord8 s6052 = (s6051 >> 1) | (s6051 << 7);
-  const SWord8 s6053 = 128 | s6052;
-  const SWord8 s6054 = 127 & s6052;
-  const SWord8 s6055 = s6045 ? s6053 : s6054;
-  const SWord8 s6056 = (s6055 >> 1) | (s6055 << 7);
-  const SWord8 s6057 = 128 | s6056;
-  const SWord8 s6058 = 127 & s6056;
-  const SWord8 s6059 = s6043 ? s6057 : s6058;
-  const SBool  s6060 = (SBool) ((s3629 >> 0) & 1);
-  const SBool  s6061 = false != s6060;
-  const SWord8 s6062 = s6061 ? s6057 : s6058;
-  const SWord8 s6063 = s3612 ? s6059 : s6062;
-  const SBool  s6064 = (SBool) ((s3645 >> 0) & 1);
-  const SBool  s6065 = false != s6064;
-  const SBool  s6066 = (SBool) ((s3638 >> 0) & 1);
-  const SBool  s6067 = false != s6066;
-  const SWord8 s6068 = s6067 ? s6053 : s6054;
-  const SWord8 s6069 = (s6068 >> 1) | (s6068 << 7);
-  const SWord8 s6070 = 128 | s6069;
-  const SWord8 s6071 = 127 & s6069;
-  const SWord8 s6072 = s6065 ? s6070 : s6071;
-  const SBool  s6073 = (SBool) ((s3650 >> 0) & 1);
-  const SBool  s6074 = false != s6073;
-  const SWord8 s6075 = s6074 ? s6070 : s6071;
-  const SWord8 s6076 = s3612 ? s6072 : s6075;
-  const SWord8 s6077 = s3593 ? s6063 : s6076;
-  const SBool  s6078 = (SBool) ((s3671 >> 0) & 1);
-  const SBool  s6079 = false != s6078;
-  const SBool  s6080 = (SBool) ((s3667 >> 0) & 1);
-  const SBool  s6081 = false != s6080;
-  const SBool  s6082 = (SBool) ((s3660 >> 0) & 1);
-  const SBool  s6083 = false != s6082;
-  const SWord8 s6084 = s6083 ? s6049 : s6050;
-  const SWord8 s6085 = (s6084 >> 1) | (s6084 << 7);
-  const SWord8 s6086 = 128 | s6085;
-  const SWord8 s6087 = 127 & s6085;
-  const SWord8 s6088 = s6081 ? s6086 : s6087;
-  const SWord8 s6089 = (s6088 >> 1) | (s6088 << 7);
-  const SWord8 s6090 = 128 | s6089;
-  const SWord8 s6091 = 127 & s6089;
-  const SWord8 s6092 = s6079 ? s6090 : s6091;
-  const SBool  s6093 = (SBool) ((s3676 >> 0) & 1);
-  const SBool  s6094 = false != s6093;
-  const SWord8 s6095 = s6094 ? s6090 : s6091;
-  const SWord8 s6096 = s3612 ? s6092 : s6095;
-  const SBool  s6097 = (SBool) ((s3692 >> 0) & 1);
-  const SBool  s6098 = false != s6097;
-  const SBool  s6099 = (SBool) ((s3685 >> 0) & 1);
-  const SBool  s6100 = false != s6099;
-  const SWord8 s6101 = s6100 ? s6086 : s6087;
-  const SWord8 s6102 = (s6101 >> 1) | (s6101 << 7);
-  const SWord8 s6103 = 128 | s6102;
-  const SWord8 s6104 = 127 & s6102;
-  const SWord8 s6105 = s6098 ? s6103 : s6104;
-  const SBool  s6106 = (SBool) ((s3697 >> 0) & 1);
-  const SBool  s6107 = false != s6106;
-  const SWord8 s6108 = s6107 ? s6103 : s6104;
-  const SWord8 s6109 = s3612 ? s6105 : s6108;
-  const SWord8 s6110 = s3593 ? s6096 : s6109;
-  const SWord8 s6111 = s3571 ? s6077 : s6110;
-  const SBool  s6112 = (SBool) ((s3732 >> 0) & 1);
-  const SBool  s6113 = false != s6112;
-  const SBool  s6114 = (SBool) ((s3728 >> 0) & 1);
-  const SBool  s6115 = false != s6114;
-  const SBool  s6116 = (SBool) ((s3724 >> 0) & 1);
-  const SBool  s6117 = false != s6116;
-  const SWord8 s6118 = (s3711 >> 1) | (s3711 << 7);
-  const SWord8 s6119 = 128 | s6118;
-  const SWord8 s6120 = 127 & s6118;
-  const SWord8 s6121 = s6117 ? s6119 : s6120;
-  const SWord8 s6122 = (s6121 >> 1) | (s6121 << 7);
-  const SWord8 s6123 = 128 | s6122;
-  const SWord8 s6124 = 127 & s6122;
-  const SWord8 s6125 = s6115 ? s6123 : s6124;
-  const SWord8 s6126 = (s6125 >> 1) | (s6125 << 7);
-  const SWord8 s6127 = 128 | s6126;
-  const SWord8 s6128 = 127 & s6126;
-  const SWord8 s6129 = s6113 ? s6127 : s6128;
-  const SBool  s6130 = (SBool) ((s3737 >> 0) & 1);
-  const SBool  s6131 = false != s6130;
-  const SWord8 s6132 = s6131 ? s6127 : s6128;
-  const SWord8 s6133 = s3717 ? s6129 : s6132;
-  const SBool  s6134 = (SBool) ((s3753 >> 0) & 1);
-  const SBool  s6135 = false != s6134;
-  const SBool  s6136 = (SBool) ((s3746 >> 0) & 1);
-  const SBool  s6137 = false != s6136;
-  const SWord8 s6138 = s6137 ? s6123 : s6124;
-  const SWord8 s6139 = (s6138 >> 1) | (s6138 << 7);
-  const SWord8 s6140 = 128 | s6139;
-  const SWord8 s6141 = 127 & s6139;
-  const SWord8 s6142 = s6135 ? s6140 : s6141;
-  const SBool  s6143 = (SBool) ((s3758 >> 0) & 1);
-  const SBool  s6144 = false != s6143;
-  const SWord8 s6145 = s6144 ? s6140 : s6141;
-  const SWord8 s6146 = s3717 ? s6142 : s6145;
-  const SWord8 s6147 = s3593 ? s6133 : s6146;
-  const SBool  s6148 = (SBool) ((s3779 >> 0) & 1);
-  const SBool  s6149 = false != s6148;
-  const SBool  s6150 = (SBool) ((s3775 >> 0) & 1);
-  const SBool  s6151 = false != s6150;
-  const SBool  s6152 = (SBool) ((s3768 >> 0) & 1);
-  const SBool  s6153 = false != s6152;
-  const SWord8 s6154 = s6153 ? s6119 : s6120;
-  const SWord8 s6155 = (s6154 >> 1) | (s6154 << 7);
-  const SWord8 s6156 = 128 | s6155;
-  const SWord8 s6157 = 127 & s6155;
-  const SWord8 s6158 = s6151 ? s6156 : s6157;
-  const SWord8 s6159 = (s6158 >> 1) | (s6158 << 7);
-  const SWord8 s6160 = 128 | s6159;
-  const SWord8 s6161 = 127 & s6159;
-  const SWord8 s6162 = s6149 ? s6160 : s6161;
-  const SBool  s6163 = (SBool) ((s3784 >> 0) & 1);
-  const SBool  s6164 = false != s6163;
-  const SWord8 s6165 = s6164 ? s6160 : s6161;
-  const SWord8 s6166 = s3717 ? s6162 : s6165;
-  const SBool  s6167 = (SBool) ((s3800 >> 0) & 1);
-  const SBool  s6168 = false != s6167;
-  const SBool  s6169 = (SBool) ((s3793 >> 0) & 1);
-  const SBool  s6170 = false != s6169;
-  const SWord8 s6171 = s6170 ? s6156 : s6157;
-  const SWord8 s6172 = (s6171 >> 1) | (s6171 << 7);
-  const SWord8 s6173 = 128 | s6172;
-  const SWord8 s6174 = 127 & s6172;
-  const SWord8 s6175 = s6168 ? s6173 : s6174;
-  const SBool  s6176 = (SBool) ((s3805 >> 0) & 1);
-  const SBool  s6177 = false != s6176;
-  const SWord8 s6178 = s6177 ? s6173 : s6174;
-  const SWord8 s6179 = s3717 ? s6175 : s6178;
-  const SWord8 s6180 = s3593 ? s6166 : s6179;
-  const SWord8 s6181 = s3571 ? s6147 : s6180;
-  const SWord8 s6182 = s3060 ? s6111 : s6181;
-  const SBool  s6183 = (SBool) ((s3860 >> 0) & 1);
-  const SBool  s6184 = false != s6183;
-  const SBool  s6185 = (SBool) ((s3856 >> 0) & 1);
-  const SBool  s6186 = false != s6185;
-  const SBool  s6187 = (SBool) ((s3852 >> 0) & 1);
-  const SBool  s6188 = false != s6187;
-  const SWord8 s6189 = (s3839 >> 1) | (s3839 << 7);
-  const SWord8 s6190 = 128 | s6189;
-  const SWord8 s6191 = 127 & s6189;
-  const SWord8 s6192 = s6188 ? s6190 : s6191;
-  const SWord8 s6193 = (s6192 >> 1) | (s6192 << 7);
-  const SWord8 s6194 = 128 | s6193;
-  const SWord8 s6195 = 127 & s6193;
-  const SWord8 s6196 = s6186 ? s6194 : s6195;
-  const SWord8 s6197 = (s6196 >> 1) | (s6196 << 7);
-  const SWord8 s6198 = 128 | s6197;
-  const SWord8 s6199 = 127 & s6197;
-  const SWord8 s6200 = s6184 ? s6198 : s6199;
-  const SBool  s6201 = (SBool) ((s3865 >> 0) & 1);
-  const SBool  s6202 = false != s6201;
-  const SWord8 s6203 = s6202 ? s6198 : s6199;
-  const SWord8 s6204 = s3848 ? s6200 : s6203;
-  const SBool  s6205 = (SBool) ((s3881 >> 0) & 1);
-  const SBool  s6206 = false != s6205;
-  const SBool  s6207 = (SBool) ((s3874 >> 0) & 1);
-  const SBool  s6208 = false != s6207;
-  const SWord8 s6209 = s6208 ? s6194 : s6195;
-  const SWord8 s6210 = (s6209 >> 1) | (s6209 << 7);
-  const SWord8 s6211 = 128 | s6210;
-  const SWord8 s6212 = 127 & s6210;
-  const SWord8 s6213 = s6206 ? s6211 : s6212;
-  const SBool  s6214 = (SBool) ((s3886 >> 0) & 1);
-  const SBool  s6215 = false != s6214;
-  const SWord8 s6216 = s6215 ? s6211 : s6212;
-  const SWord8 s6217 = s3848 ? s6213 : s6216;
-  const SWord8 s6218 = s3826 ? s6204 : s6217;
-  const SBool  s6219 = (SBool) ((s3907 >> 0) & 1);
-  const SBool  s6220 = false != s6219;
-  const SBool  s6221 = (SBool) ((s3903 >> 0) & 1);
-  const SBool  s6222 = false != s6221;
-  const SBool  s6223 = (SBool) ((s3896 >> 0) & 1);
-  const SBool  s6224 = false != s6223;
-  const SWord8 s6225 = s6224 ? s6190 : s6191;
-  const SWord8 s6226 = (s6225 >> 1) | (s6225 << 7);
-  const SWord8 s6227 = 128 | s6226;
-  const SWord8 s6228 = 127 & s6226;
-  const SWord8 s6229 = s6222 ? s6227 : s6228;
-  const SWord8 s6230 = (s6229 >> 1) | (s6229 << 7);
-  const SWord8 s6231 = 128 | s6230;
-  const SWord8 s6232 = 127 & s6230;
-  const SWord8 s6233 = s6220 ? s6231 : s6232;
-  const SBool  s6234 = (SBool) ((s3912 >> 0) & 1);
-  const SBool  s6235 = false != s6234;
-  const SWord8 s6236 = s6235 ? s6231 : s6232;
-  const SWord8 s6237 = s3848 ? s6233 : s6236;
-  const SBool  s6238 = (SBool) ((s3928 >> 0) & 1);
-  const SBool  s6239 = false != s6238;
-  const SBool  s6240 = (SBool) ((s3921 >> 0) & 1);
-  const SBool  s6241 = false != s6240;
-  const SWord8 s6242 = s6241 ? s6227 : s6228;
-  const SWord8 s6243 = (s6242 >> 1) | (s6242 << 7);
-  const SWord8 s6244 = 128 | s6243;
-  const SWord8 s6245 = 127 & s6243;
-  const SWord8 s6246 = s6239 ? s6244 : s6245;
-  const SBool  s6247 = (SBool) ((s3933 >> 0) & 1);
-  const SBool  s6248 = false != s6247;
-  const SWord8 s6249 = s6248 ? s6244 : s6245;
-  const SWord8 s6250 = s3848 ? s6246 : s6249;
-  const SWord8 s6251 = s3826 ? s6237 : s6250;
-  const SWord8 s6252 = s3571 ? s6218 : s6251;
-  const SBool  s6253 = (SBool) ((s3968 >> 0) & 1);
-  const SBool  s6254 = false != s6253;
-  const SBool  s6255 = (SBool) ((s3964 >> 0) & 1);
-  const SBool  s6256 = false != s6255;
-  const SBool  s6257 = (SBool) ((s3960 >> 0) & 1);
-  const SBool  s6258 = false != s6257;
-  const SWord8 s6259 = (s3947 >> 1) | (s3947 << 7);
-  const SWord8 s6260 = 128 | s6259;
-  const SWord8 s6261 = 127 & s6259;
-  const SWord8 s6262 = s6258 ? s6260 : s6261;
-  const SWord8 s6263 = (s6262 >> 1) | (s6262 << 7);
-  const SWord8 s6264 = 128 | s6263;
-  const SWord8 s6265 = 127 & s6263;
-  const SWord8 s6266 = s6256 ? s6264 : s6265;
-  const SWord8 s6267 = (s6266 >> 1) | (s6266 << 7);
-  const SWord8 s6268 = 128 | s6267;
-  const SWord8 s6269 = 127 & s6267;
-  const SWord8 s6270 = s6254 ? s6268 : s6269;
-  const SBool  s6271 = (SBool) ((s3973 >> 0) & 1);
-  const SBool  s6272 = false != s6271;
-  const SWord8 s6273 = s6272 ? s6268 : s6269;
-  const SWord8 s6274 = s3953 ? s6270 : s6273;
-  const SBool  s6275 = (SBool) ((s3989 >> 0) & 1);
-  const SBool  s6276 = false != s6275;
-  const SBool  s6277 = (SBool) ((s3982 >> 0) & 1);
-  const SBool  s6278 = false != s6277;
-  const SWord8 s6279 = s6278 ? s6264 : s6265;
-  const SWord8 s6280 = (s6279 >> 1) | (s6279 << 7);
-  const SWord8 s6281 = 128 | s6280;
-  const SWord8 s6282 = 127 & s6280;
-  const SWord8 s6283 = s6276 ? s6281 : s6282;
-  const SBool  s6284 = (SBool) ((s3994 >> 0) & 1);
-  const SBool  s6285 = false != s6284;
-  const SWord8 s6286 = s6285 ? s6281 : s6282;
-  const SWord8 s6287 = s3953 ? s6283 : s6286;
-  const SWord8 s6288 = s3826 ? s6274 : s6287;
-  const SBool  s6289 = (SBool) ((s4015 >> 0) & 1);
-  const SBool  s6290 = false != s6289;
-  const SBool  s6291 = (SBool) ((s4011 >> 0) & 1);
-  const SBool  s6292 = false != s6291;
-  const SBool  s6293 = (SBool) ((s4004 >> 0) & 1);
-  const SBool  s6294 = false != s6293;
-  const SWord8 s6295 = s6294 ? s6260 : s6261;
-  const SWord8 s6296 = (s6295 >> 1) | (s6295 << 7);
-  const SWord8 s6297 = 128 | s6296;
-  const SWord8 s6298 = 127 & s6296;
-  const SWord8 s6299 = s6292 ? s6297 : s6298;
-  const SWord8 s6300 = (s6299 >> 1) | (s6299 << 7);
-  const SWord8 s6301 = 128 | s6300;
-  const SWord8 s6302 = 127 & s6300;
-  const SWord8 s6303 = s6290 ? s6301 : s6302;
-  const SBool  s6304 = (SBool) ((s4020 >> 0) & 1);
-  const SBool  s6305 = false != s6304;
-  const SWord8 s6306 = s6305 ? s6301 : s6302;
-  const SWord8 s6307 = s3953 ? s6303 : s6306;
-  const SBool  s6308 = (SBool) ((s4036 >> 0) & 1);
-  const SBool  s6309 = false != s6308;
-  const SBool  s6310 = (SBool) ((s4029 >> 0) & 1);
-  const SBool  s6311 = false != s6310;
-  const SWord8 s6312 = s6311 ? s6297 : s6298;
-  const SWord8 s6313 = (s6312 >> 1) | (s6312 << 7);
-  const SWord8 s6314 = 128 | s6313;
-  const SWord8 s6315 = 127 & s6313;
-  const SWord8 s6316 = s6309 ? s6314 : s6315;
-  const SBool  s6317 = (SBool) ((s4041 >> 0) & 1);
-  const SBool  s6318 = false != s6317;
-  const SWord8 s6319 = s6318 ? s6314 : s6315;
-  const SWord8 s6320 = s3953 ? s6316 : s6319;
-  const SWord8 s6321 = s3826 ? s6307 : s6320;
-  const SWord8 s6322 = s3571 ? s6288 : s6321;
-  const SWord8 s6323 = s3060 ? s6252 : s6322;
-  const SWord8 s6324 = s2042 ? s6182 : s6323;
-  const SWord8 s6325 = s16 ? s6041 : s6324;
-  const SWord8 s6326 = s11 ? s5758 : s6325;
-  const SWord8 s6327 = s5 ? s5191 : s6326;
-
-  *hi = s4056;
-  *lo = s6327;
-}
-== END: "legatoMult.c" ==================
diff --git a/SBVUnitTest/GoldFiles/merge.gold b/SBVUnitTest/GoldFiles/merge.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/merge.gold
+++ /dev/null
@@ -1,156 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for merge. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: merge_driver
-
-merge.o: merge.c merge.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-merge_driver.o: merge_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-merge_driver: merge.o merge_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f merge_driver
-== END: "Makefile" ==================
-== BEGIN: "merge.h" ================
-/* Header file for merge. Automatically generated by SBV. Do not edit! */
-
-#ifndef __merge__HEADER_INCLUDED__
-#define __merge__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-void merge(const SWord8 *xs, SWord8 *ys);
-
-#endif /* __merge__HEADER_INCLUDED__ */
-== END: "merge.h" ==================
-== BEGIN: "merge_driver.c" ================
-/* Example driver program for merge. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "merge.h"
-
-int main(void)
-{
-  const SWord8 xs[5] = {
-      10,  6,  4, 82, 71
-  };
-
-  printf("Contents of input array xs:\n");
-  int xs_ctr;
-  for(xs_ctr = 0; xs_ctr < 5 ; ++xs_ctr)
-    printf("  xs[%d] = %"PRIu8"\n", xs_ctr ,xs[xs_ctr]);
-
-  SWord8 ys[5];
-
-  merge(xs, ys);
-
-  printf("merge(xs, ys) ->\n");
-  int ys_ctr;
-  for(ys_ctr = 0; ys_ctr < 5 ; ++ys_ctr)
-    printf("  ys[%d] = %"PRIu8"\n", ys_ctr ,ys[ys_ctr]);
-
-  return 0;
-}
-== END: "merge_driver.c" ==================
-== BEGIN: "merge.c" ================
-/* File: "merge.c". Automatically generated by SBV. Do not edit! */
-
-#include "merge.h"
-
-void merge(const SWord8 *xs, SWord8 *ys)
-{
-  const SWord8 s0 = xs[0];
-  const SWord8 s1 = xs[1];
-  const SWord8 s2 = xs[2];
-  const SWord8 s3 = xs[3];
-  const SWord8 s4 = xs[4];
-  const SBool  s5 = s0 < s1;
-  const SWord8 s6 = s5 ? s0 : s1;
-  const SBool  s7 = s3 < s4;
-  const SWord8 s8 = s7 ? s3 : s4;
-  const SBool  s9 = s2 < s8;
-  const SWord8 s10 = s9 ? s2 : s8;
-  const SBool  s11 = s6 < s10;
-  const SWord8 s12 = s11 ? s6 : s10;
-  const SWord8 s13 = s5 ? s1 : s0;
-  const SBool  s14 = s13 < s10;
-  const SWord8 s15 = s14 ? s13 : s10;
-  const SWord8 s16 = s7 ? s4 : s3;
-  const SBool  s17 = s2 < s16;
-  const SWord8 s18 = s17 ? s2 : s16;
-  const SWord8 s19 = s9 ? s8 : s18;
-  const SBool  s20 = s6 < s19;
-  const SWord8 s21 = s20 ? s6 : s19;
-  const SWord8 s22 = s11 ? s15 : s21;
-  const SBool  s23 = s13 < s19;
-  const SWord8 s24 = s23 ? s13 : s19;
-  const SWord8 s25 = s14 ? s10 : s24;
-  const SWord8 s26 = s17 ? s16 : s2;
-  const SWord8 s27 = s9 ? s16 : s26;
-  const SBool  s28 = s6 < s27;
-  const SWord8 s29 = s28 ? s6 : s27;
-  const SWord8 s30 = s20 ? s24 : s29;
-  const SWord8 s31 = s11 ? s25 : s30;
-  const SBool  s32 = s13 < s27;
-  const SWord8 s33 = s32 ? s13 : s27;
-  const SWord8 s34 = s23 ? s19 : s33;
-  const SWord8 s35 = s14 ? s19 : s34;
-  const SWord8 s36 = s28 ? s33 : s6;
-  const SWord8 s37 = s20 ? s34 : s36;
-  const SWord8 s38 = s11 ? s35 : s37;
-  const SWord8 s39 = s32 ? s27 : s13;
-  const SWord8 s40 = s23 ? s27 : s39;
-  const SWord8 s41 = s14 ? s27 : s40;
-  const SWord8 s42 = s28 ? s39 : s13;
-  const SWord8 s43 = s20 ? s40 : s42;
-  const SWord8 s44 = s11 ? s41 : s43;
-
-  ys[0] = s12;
-  ys[1] = s22;
-  ys[2] = s31;
-  ys[3] = s38;
-  ys[4] = s44;
-}
-== END: "merge.c" ==================
diff --git a/SBVUnitTest/GoldFiles/popCount1.gold b/SBVUnitTest/GoldFiles/popCount1.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/popCount1.gold
+++ /dev/null
@@ -1,138 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for popCount. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: popCount_driver
-
-popCount.o: popCount.c popCount.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-popCount_driver.o: popCount_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-popCount_driver: popCount.o popCount_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f popCount_driver
-== END: "Makefile" ==================
-== BEGIN: "popCount.h" ================
-/* Header file for popCount. Automatically generated by SBV. Do not edit! */
-
-#ifndef __popCount__HEADER_INCLUDED__
-#define __popCount__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord8 popCount(const SWord64 x);
-
-#endif /* __popCount__HEADER_INCLUDED__ */
-== END: "popCount.h" ==================
-== BEGIN: "popCount_driver.c" ================
-/* Example driver program for popCount. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "popCount.h"
-
-int main(void)
-{
-  const SWord8 __result = popCount(0x0123456789abcdefULL);
-
-  printf("popCount(0x0123456789abcdefULL) = %"PRIu8"\n", __result);
-
-  return 0;
-}
-== END: "popCount_driver.c" ==================
-== BEGIN: "popCount.c" ================
-/* File: "popCount.c". Automatically generated by SBV. Do not edit! */
-
-#include "popCount.h"
-
-SWord8 popCount(const SWord64 x)
-{
-  const SWord64 s0 = x;
-  static const SWord8 table0[] = {
-      0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
-      3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
-      3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
-      2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
-      3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
-      5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
-      2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
-      4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-      3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
-      4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
-      5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
-      5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
-  };
-  const SWord64 s11 = s0 & 0x00000000000000ffULL;
-  const SWord8  s12 = table0[s11];
-  const SWord64 s13 = s0 >> 8;
-  const SWord64 s14 = 0x00000000000000ffULL & s13;
-  const SWord8  s15 = table0[s14];
-  const SWord8  s16 = s12 + s15;
-  const SWord64 s17 = s13 >> 8;
-  const SWord64 s18 = 0x00000000000000ffULL & s17;
-  const SWord8  s19 = table0[s18];
-  const SWord8  s20 = s16 + s19;
-  const SWord64 s21 = s17 >> 8;
-  const SWord64 s22 = 0x00000000000000ffULL & s21;
-  const SWord8  s23 = table0[s22];
-  const SWord8  s24 = s20 + s23;
-  const SWord64 s25 = s21 >> 8;
-  const SWord64 s26 = 0x00000000000000ffULL & s25;
-  const SWord8  s27 = table0[s26];
-  const SWord8  s28 = s24 + s27;
-  const SWord64 s29 = s25 >> 8;
-  const SWord64 s30 = 0x00000000000000ffULL & s29;
-  const SWord8  s31 = table0[s30];
-  const SWord8  s32 = s28 + s31;
-  const SWord64 s33 = s29 >> 8;
-  const SWord64 s34 = 0x00000000000000ffULL & s33;
-  const SWord8  s35 = table0[s34];
-  const SWord8  s36 = s32 + s35;
-  const SWord64 s37 = s33 >> 8;
-  const SWord64 s38 = 0x00000000000000ffULL & s37;
-  const SWord8  s39 = table0[s38];
-  const SWord8  s40 = s36 + s39;
-
-  return s40;
-}
-== END: "popCount.c" ==================
diff --git a/SBVUnitTest/GoldFiles/popCount2.gold b/SBVUnitTest/GoldFiles/popCount2.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/popCount2.gold
+++ /dev/null
@@ -1,138 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for popCount. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: popCount_driver
-
-popCount.o: popCount.c popCount.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-popCount_driver.o: popCount_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-popCount_driver: popCount.o popCount_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f popCount_driver
-== END: "Makefile" ==================
-== BEGIN: "popCount.h" ================
-/* Header file for popCount. Automatically generated by SBV. Do not edit! */
-
-#ifndef __popCount__HEADER_INCLUDED__
-#define __popCount__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord8 popCount(const SWord64 x);
-
-#endif /* __popCount__HEADER_INCLUDED__ */
-== END: "popCount.h" ==================
-== BEGIN: "popCount_driver.c" ================
-/* Example driver program for popCount. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "popCount.h"
-
-int main(void)
-{
-  const SWord8 __result = popCount(0x0123456789abcdefULL);
-
-  printf("popCount(0x0123456789abcdefULL) = %"PRIu8"\n", __result);
-
-  return 0;
-}
-== END: "popCount_driver.c" ==================
-== BEGIN: "popCount.c" ================
-/* File: "popCount.c". Automatically generated by SBV. Do not edit! */
-
-#include "popCount.h"
-
-SWord8 popCount(const SWord64 x)
-{
-  const SWord64 s0 = x;
-  static const SWord8 table0[] = {
-      0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3,
-      3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
-      3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2,
-      2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5,
-      3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
-      5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
-      2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
-      4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-      3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4,
-      4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
-      5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5,
-      5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
-  };
-  const SWord64 s11 = s0 & 0x00000000000000ffULL;
-  const SWord8  s12 = s11 >= 256 ? 0 : table0[s11];
-  const SWord64 s13 = s0 >> 8;
-  const SWord64 s14 = 0x00000000000000ffULL & s13;
-  const SWord8  s15 = s14 >= 256 ? 0 : table0[s14];
-  const SWord8  s16 = s12 + s15;
-  const SWord64 s17 = s13 >> 8;
-  const SWord64 s18 = 0x00000000000000ffULL & s17;
-  const SWord8  s19 = s18 >= 256 ? 0 : table0[s18];
-  const SWord8  s20 = s16 + s19;
-  const SWord64 s21 = s17 >> 8;
-  const SWord64 s22 = 0x00000000000000ffULL & s21;
-  const SWord8  s23 = s22 >= 256 ? 0 : table0[s22];
-  const SWord8  s24 = s20 + s23;
-  const SWord64 s25 = s21 >> 8;
-  const SWord64 s26 = 0x00000000000000ffULL & s25;
-  const SWord8  s27 = s26 >= 256 ? 0 : table0[s26];
-  const SWord8  s28 = s24 + s27;
-  const SWord64 s29 = s25 >> 8;
-  const SWord64 s30 = 0x00000000000000ffULL & s29;
-  const SWord8  s31 = s30 >= 256 ? 0 : table0[s30];
-  const SWord8  s32 = s28 + s31;
-  const SWord64 s33 = s29 >> 8;
-  const SWord64 s34 = 0x00000000000000ffULL & s33;
-  const SWord8  s35 = s34 >= 256 ? 0 : table0[s34];
-  const SWord8  s36 = s32 + s35;
-  const SWord64 s37 = s33 >> 8;
-  const SWord64 s38 = 0x00000000000000ffULL & s37;
-  const SWord8  s39 = s38 >= 256 ? 0 : table0[s38];
-  const SWord8  s40 = s36 + s39;
-
-  return s40;
-}
-== END: "popCount.c" ==================
diff --git a/SBVUnitTest/GoldFiles/selChecked.gold b/SBVUnitTest/GoldFiles/selChecked.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/selChecked.gold
+++ /dev/null
@@ -1,99 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for selChecked. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: selChecked_driver
-
-selChecked.o: selChecked.c selChecked.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-selChecked_driver.o: selChecked_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-selChecked_driver: selChecked.o selChecked_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f selChecked_driver
-== END: "Makefile" ==================
-== BEGIN: "selChecked.h" ================
-/* Header file for selChecked. Automatically generated by SBV. Do not edit! */
-
-#ifndef __selChecked__HEADER_INCLUDED__
-#define __selChecked__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord8 selChecked(const SWord8 x);
-
-#endif /* __selChecked__HEADER_INCLUDED__ */
-== END: "selChecked.h" ==================
-== BEGIN: "selChecked_driver.c" ================
-/* Example driver program for selChecked. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "selChecked.h"
-
-int main(void)
-{
-  const SWord8 __result = selChecked(65);
-
-  printf("selChecked(65) = %"PRIu8"\n", __result);
-
-  return 0;
-}
-== END: "selChecked_driver.c" ==================
-== BEGIN: "selChecked.c" ================
-/* File: "selChecked.c". Automatically generated by SBV. Do not edit! */
-
-#include "selChecked.h"
-
-SWord8 selChecked(const SWord8 x)
-{
-  const SWord8 s0 = x;
-  const SWord8 s3 = s0 + 2;
-  const SWord8 table0[] = {
-       1, s3
-  };
-  const SWord8 s5 = s0 >= 2 ? 3 : table0[s0];
-
-  return s5;
-}
-== END: "selChecked.c" ==================
diff --git a/SBVUnitTest/GoldFiles/selUnchecked.gold b/SBVUnitTest/GoldFiles/selUnchecked.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/selUnchecked.gold
+++ /dev/null
@@ -1,99 +0,0 @@
-== BEGIN: "Makefile" ================
-# Makefile for selUnChecked. Automatically generated by SBV. Do not edit!
-
-# include any user-defined .mk file in the current directory.
--include *.mk
-
-CC?=gcc
-CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-
-all: selUnChecked_driver
-
-selUnChecked.o: selUnChecked.c selUnChecked.h
-	${CC} ${CCFLAGS} -c $< -o $@
-
-selUnChecked_driver.o: selUnChecked_driver.c
-	${CC} ${CCFLAGS} -c $< -o $@
-
-selUnChecked_driver: selUnChecked.o selUnChecked_driver.o
-	${CC} ${CCFLAGS} $^ -o $@
-
-clean:
-	rm -f *.o
-
-veryclean: clean
-	rm -f selUnChecked_driver
-== END: "Makefile" ==================
-== BEGIN: "selUnChecked.h" ================
-/* Header file for selUnChecked. Automatically generated by SBV. Do not edit! */
-
-#ifndef __selUnChecked__HEADER_INCLUDED__
-#define __selUnChecked__HEADER_INCLUDED__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-#include <math.h>
-
-/* The boolean type */
-typedef bool SBool;
-
-/* The float type */
-typedef float SFloat;
-
-/* The double type */
-typedef double SDouble;
-
-/* Unsigned bit-vectors */
-typedef uint8_t  SWord8 ;
-typedef uint16_t SWord16;
-typedef uint32_t SWord32;
-typedef uint64_t SWord64;
-
-/* Signed bit-vectors */
-typedef int8_t  SInt8 ;
-typedef int16_t SInt16;
-typedef int32_t SInt32;
-typedef int64_t SInt64;
-
-/* Entry point prototype: */
-SWord8 selUnChecked(const SWord8 x);
-
-#endif /* __selUnChecked__HEADER_INCLUDED__ */
-== END: "selUnChecked.h" ==================
-== BEGIN: "selUnChecked_driver.c" ================
-/* Example driver program for selUnChecked. */
-/* Automatically generated by SBV. Edit as you see fit! */
-
-#include <stdio.h>
-#include "selUnChecked.h"
-
-int main(void)
-{
-  const SWord8 __result = selUnChecked(65);
-
-  printf("selUnChecked(65) = %"PRIu8"\n", __result);
-
-  return 0;
-}
-== END: "selUnChecked_driver.c" ==================
-== BEGIN: "selUnChecked.c" ================
-/* File: "selUnChecked.c". Automatically generated by SBV. Do not edit! */
-
-#include "selUnChecked.h"
-
-SWord8 selUnChecked(const SWord8 x)
-{
-  const SWord8 s0 = x;
-  const SWord8 s3 = s0 + 2;
-  const SWord8 table0[] = {
-       1, s3
-  };
-  const SWord8 s5 = table0[s0];
-
-  return s5;
-}
-== END: "selUnChecked.c" ==================
diff --git a/SBVUnitTest/GoldFiles/temperature.gold b/SBVUnitTest/GoldFiles/temperature.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/temperature.gold
+++ /dev/null
@@ -1,5 +0,0 @@
-Solution #1:
-  s0 = 28 :: Integer
-Solution #2:
-  s0 = 16 :: Integer
-Found 2 different solutions.
diff --git a/SBVUnitTest/SBVBasicTests.hs b/SBVUnitTest/SBVBasicTests.hs
deleted file mode 100644
--- a/SBVUnitTest/SBVBasicTests.hs
+++ /dev/null
@@ -1,71 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Main
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- SBV library basic test suite; i.e., those tests that do not
--- require the use of an external SMT solver.
------------------------------------------------------------------------------
-
--- Nothing needs to be changed in this file, add test cases
--- appropriately to SBVUnitTest.hs file, and they will be
--- picked up here automagically
-module Main(main) where
-
-import Control.Monad    (unless, when)
-import System.Directory (doesDirectoryExist)
-import System.Exit      (exitWith, exitSuccess, ExitCode(..))
-import System.FilePath  ((</>))
-import System.IO        (stderr, hPutStrLn)
-import Test.HUnit       (Test(..), Counts(..), runTestText, PutText(..), showCounts)
-
-import Data.Version     (showVersion)
-import SBVTest          (SBVTestSuite(..), generateGoldCheck)
-import Paths_sbv        (getDataDir, version)
-
-import SBVTestCollection    (allTestCases)
-import SBVUnitTestBuildTime (buildTime)
-
-testCollection :: [(String, SBVTestSuite)]
-testCollection = [(n, s) | (n, False, s) <- allTestCases]
-
-main :: IO ()
-main = do putStrLn $ "*** SBVBasicTester, version: " ++ showVersion version ++ ", time stamp: " ++ buildTime
-          d <- getDataDir 
-          run $ d </> "SBVUnitTest" </> "GoldFiles"
-
-checkGoldDir :: FilePath -> IO ()
-checkGoldDir gd = do e <- doesDirectoryExist gd
-                     unless e $ do putStrLn "*** Cannot locate gold file repository!"
-                                   putStrLn "*** Please call with one argument, the directory name of the gold files."
-                                   putStrLn "*** Cannot run test cases, exiting."
-                                   exitWith $ ExitFailure 1
-
-run :: FilePath -> IO ()
-run gd = do putStrLn $ "*** Starting SBV basic tests..\n*** Gold files at: " ++ show gd
-            checkGoldDir gd
-            let collections = map (mkTst . snd) testCollection
-                cNames      = map fst testCollection
-            putStrLn $ "*** Running " ++ show (length collections) ++ " test categories."
-            runEach 1 (zip cNames collections)
-  where runEach :: Int -> [(String, Test)] -> IO ()
-        runEach _ []            = exitSuccess
-        runEach i ((n, tc):tcs) = do putStrLn $ "Starting category: " ++ show n
-                                     (cts, _) <- runTestText (PutText put ()) tc
-                                     hPutStrLn stderr $ showCounts cts
-                                     decide n cts
-                                     runEach (i+1) tcs
-        mkTst (SBVTestSuite f) = f $ generateGoldCheck gd False
-        put _ _ = return
-
-decide :: String -> Counts -> IO ()
-decide cat (Counts c t e f) = do
-        when (c /= t) $ putStrLn $ "*** Not all test cases were tried. (Only tested " ++ show t ++ " of " ++ show c ++ ")"
-        when (e /= 0) $ putStrLn $ "*** " ++ show e ++ " (of " ++ show c ++ ") test cases in error."
-        when (f /= 0) $ putStrLn $ "*** " ++ show f ++ " (of " ++ show c ++ ") test cases failed."
-        if c == t && e == 0 && f == 0
-           then putStrLn $ "All " ++ show c ++ " test cases in category " ++ show cat ++ " successfully passed."
-           else exitWith $ ExitFailure 2
diff --git a/SBVUnitTest/SBVTest.hs b/SBVUnitTest/SBVTest.hs
deleted file mode 100644
--- a/SBVUnitTest/SBVTest.hs
+++ /dev/null
@@ -1,70 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  SBVTest
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Integration with HUnit-based test suite for SBV
------------------------------------------------------------------------------
-
-{-# LANGUAGE RankNTypes #-}
-module SBVTest(
-          generateGoldCheck, showsAs, ioShowsAs, mkTestSuite, SBVTestSuite(..)
-        , isThm, isSat, runSAT, numberOfModels
-        , module Test.HUnit
-        , module Data.SBV
-        ) where
-
-import Data.SBV                (SMTConfig(..), Provable(..), isTheorem, isTheoremWith, isSatisfiable, AllSatResult(..), allSat, SymWord(free), SymArray(newArray), defaultSMTCfg)
-import Data.SBV.Internals      (runSymbolic, Symbolic, Result)
-
-import Data.Maybe              (fromJust)
-import System.FilePath         ((</>))
-import Test.HUnit              (Test(..), Assertion, assert, (~:), test)
-
--- | A Test-suite, parameterized by the gold-check generator/checker
-newtype SBVTestSuite = SBVTestSuite ((forall a. Show a => (IO a -> FilePath -> IO ())) -> Test)
-
--- | Wrap over 'SBVTestSuite', avoids exporting the constructor
-mkTestSuite :: ((forall a. (Show a) => IO a -> FilePath -> IO ()) -> Test) -> SBVTestSuite
-mkTestSuite = SBVTestSuite
-
--- | Checks that a particular result shows as @s@
-showsAs :: Show a => a -> String -> Assertion
-showsAs r s = assert $ show r == s
-
--- | Run an IO computation and check that it's result shows as @s@
-ioShowsAs :: Show a => IO a -> String -> Assertion
-ioShowsAs r s = do v <- r
-                   assert $ show v == s
-
--- | Create a gold file for the test case
-generateGoldCheck :: FilePath -> Bool -> (forall a. Show a => IO a -> FilePath -> IO ())
-generateGoldCheck goldDir shouldCreate action goldFile
-  | shouldCreate = do v <- action
-                      writeFile gf (show v)
-                      putStrLn $ "\nCreated Gold File: " ++ show gf
-                      assert True
-  | True         = do v <- action
-                      g <- readFile gf
-                      assert $ show v == g
- where gf = goldDir </> goldFile
-
--- | Check if a property is a theorem, no timeout
-isThm :: Provable a => a -> IO Bool
-isThm p = fromJust `fmap` isTheorem Nothing p
-
--- | Check if a property is satisfiable, no timeout
-isSat :: Provable a => a -> IO Bool
-isSat p = fromJust `fmap` isSatisfiable Nothing p
-
--- | Count the number of models
-numberOfModels :: Provable a => a -> IO Int
-numberOfModels p = do AllSatResult (_, rs) <- allSat p
-                      return $ length rs
-
--- | Symbolicly run a SAT instance using the default config
-runSAT :: Symbolic a -> IO Result
-runSAT = runSymbolic (True, defaultSMTCfg)
diff --git a/SBVUnitTest/SBVTestCollection.hs b/SBVUnitTest/SBVTestCollection.hs
deleted file mode 100644
--- a/SBVUnitTest/SBVTestCollection.hs
+++ /dev/null
@@ -1,114 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Main
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- SBV test collection
------------------------------------------------------------------------------
-
-module SBVTestCollection(allTestCases) where
-
-import SBVTest
-
--- To add a new collection of tests, import below and add to allTestCases variable
-import qualified TestSuite.Arrays.Memory                  as T01_01(testSuite)
-import qualified TestSuite.Basics.ArithNoSolver           as T02_01(testSuite)
-import qualified TestSuite.Basics.ArithSolver             as T02_02(testSuite)
-import qualified TestSuite.Basics.BasicTests              as T02_03(testSuite)
-import qualified TestSuite.Basics.Higher                  as T02_04(testSuite)
-import qualified TestSuite.Basics.Index                   as T02_05(testSuite)
-import qualified TestSuite.Basics.IteTest                 as T02_06(testSuite)
-import qualified TestSuite.Basics.ProofTests              as T02_07(testSuite)
-import qualified TestSuite.Basics.QRem                    as T02_08(testSuite)
-import qualified TestSuite.BitPrecise.BitTricks           as T03_01(testSuite)
-import qualified TestSuite.BitPrecise.Legato              as T03_02(testSuite)
-import qualified TestSuite.BitPrecise.MergeSort           as T03_03(testSuite)
-import qualified TestSuite.BitPrecise.PrefixSum           as T03_04(testSuite)
-import qualified TestSuite.CRC.CCITT                      as T04_01(testSuite)
-import qualified TestSuite.CRC.CCITT_Unidir               as T04_02(testSuite)
-import qualified TestSuite.CRC.GenPoly                    as T04_03(testSuite)
-import qualified TestSuite.CRC.Parity                     as T04_04(testSuite)
-import qualified TestSuite.CRC.USB5                       as T04_05(testSuite)
-import qualified TestSuite.CodeGeneration.AddSub          as T05_01(testSuite)
-import qualified TestSuite.CodeGeneration.CgTests         as T05_02(testSuite)
-import qualified TestSuite.CodeGeneration.CRC_USB5        as T05_03(testSuite)
-import qualified TestSuite.CodeGeneration.Fibonacci       as T05_04(testSuite)
-import qualified TestSuite.CodeGeneration.Floats          as T05_05(testSuite)
-import qualified TestSuite.CodeGeneration.GCD             as T05_06(testSuite)
-import qualified TestSuite.CodeGeneration.PopulationCount as T05_07(testSuite)
-import qualified TestSuite.CodeGeneration.Uninterpreted   as T05_08(testSuite)
-import qualified TestSuite.Crypto.AES                     as T06_01(testSuite)
-import qualified TestSuite.Crypto.RC4                     as T06_02(testSuite)
-import qualified TestSuite.Existentials.CRCPolynomial     as T07_01(testSuite)
-import qualified TestSuite.Polynomials.Polynomials        as T08_01(testSuite)
-import qualified TestSuite.Puzzles.Coins                  as T09_01(testSuite)
-import qualified TestSuite.Puzzles.Counts                 as T09_02(testSuite)
-import qualified TestSuite.Puzzles.DogCatMouse            as T09_03(testSuite)
-import qualified TestSuite.Puzzles.Euler185               as T09_04(testSuite)
-import qualified TestSuite.Puzzles.MagicSquare            as T09_05(testSuite)
-import qualified TestSuite.Puzzles.NQueens                as T09_06(testSuite)
-import qualified TestSuite.Puzzles.PowerSet               as T09_07(testSuite)
-import qualified TestSuite.Puzzles.Sudoku                 as T09_08(testSuite)
-import qualified TestSuite.Puzzles.Temperature            as T09_09(testSuite)
-import qualified TestSuite.Puzzles.U2Bridge               as T09_10(testSuite)
-import qualified TestSuite.Uninterpreted.AUF              as T10_01(testSuite)
-import qualified TestSuite.Uninterpreted.Axioms           as T10_02(testSuite)
-import qualified TestSuite.Uninterpreted.Function         as T10_03(testSuite)
-import qualified TestSuite.Uninterpreted.Sort             as T10_04(testSuite)
-import qualified TestSuite.Uninterpreted.Uninterpreted    as T10_05(testSuite)
-
--- Bool says whether we need a real SMT solver to run this test
--- Note that it's ok to say True even if an SMT solver is *not*
--- needed, but we'd like most things to be targeted False so that
--- those tests can be run as part of cabal.
-allTestCases :: [(String, Bool, SBVTestSuite)]
-allTestCases = [
-       ("mem",         True,  T01_01.testSuite)
-     , ("arithCF",     False, T02_01.testSuite)
-     , ("arith",       True,  T02_02.testSuite)
-     , ("basic",       False, T02_03.testSuite)
-     , ("higher",      True,  T02_04.testSuite)
-     , ("index",       True,  T02_05.testSuite)
-     , ("ite",         True,  T02_06.testSuite)
-     , ("proof",       True,  T02_07.testSuite)
-     , ("qrem",        True,  T02_08.testSuite)
-     , ("bitTricks",   True,  T03_01.testSuite)
-     , ("legato",      False, T03_02.testSuite)
-     , ("mergeSort",   False, T03_03.testSuite)
-     , ("prefixSum",   True,  T03_04.testSuite)
-     , ("ccitt",       False, T04_01.testSuite)
-     , ("ccitt2",      True,  T04_02.testSuite)
-     , ("genPoly",     True,  T04_03.testSuite)
-     , ("parity",      True,  T04_04.testSuite)
-     , ("usb5",        True,  T04_05.testSuite)
-     , ("addSub",      False, T05_01.testSuite)
-     , ("cgtest",      False, T05_02.testSuite)
-     , ("cgUSB5",      False, T05_03.testSuite)
-     , ("fib",         False, T05_04.testSuite)
-     , ("floats",      False, T05_05.testSuite)
-     , ("gcd",         False, T05_06.testSuite)
-     , ("popCount",    False, T05_07.testSuite)
-     , ("cgUninterp",  False, T05_08.testSuite)
-     , ("aes",         False, T06_01.testSuite)
-     , ("rc4",         True,  T06_02.testSuite)
-     , ("existPoly",   False, T07_01.testSuite)
-     , ("poly",        True,  T08_01.testSuite)
-     , ("coins",       False, T09_01.testSuite)
-     , ("counts",      False, T09_02.testSuite)
-     , ("dogCatMouse", True,  T09_03.testSuite)
-     , ("euler185",    True,  T09_04.testSuite)
-     , ("magicSquare", True,  T09_05.testSuite)
-     , ("nQueens",     True,  T09_06.testSuite)
-     , ("powerset",    True,  T09_07.testSuite)
-     , ("sudoku",      True,  T09_08.testSuite)
-     , ("temperature", True,  T09_09.testSuite)
-     , ("u2bridge",    True,  T09_10.testSuite)
-     , ("auf1",        True,  T10_01.testSuite)
-     , ("unint-axms",  True,  T10_02.testSuite)
-     , ("auf2",        True,  T10_03.testSuite)
-     , ("unint-sort",  True,  T10_04.testSuite)
-     , ("unint",       True,  T10_05.testSuite)
-     ]
diff --git a/SBVUnitTest/SBVUnitTest.hs b/SBVUnitTest/SBVUnitTest.hs
deleted file mode 100644
--- a/SBVUnitTest/SBVUnitTest.hs
+++ /dev/null
@@ -1,107 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Main
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- SBV library unit-test program
------------------------------------------------------------------------------
-
-module Main(main) where
-
-import Control.Monad        (unless, when)
-import Data.Maybe           (isJust)
-import Data.List            (isInfixOf)
-import System.Directory     (doesDirectoryExist)
-import System.Environment   (getArgs)
-import System.Exit          (exitWith, exitSuccess, ExitCode(..))
-import System.FilePath      ((</>))
-import Test.HUnit           (Test(..), Counts(..), runTestTT)
-
-import Data.Version         (showVersion)
-import SBVTest              (SBVTestSuite(..), generateGoldCheck)
-import Paths_sbv            (getDataDir, version)
-
-import SBVUnitTestBuildTime (buildTime)
-import SBVTestCollection    (allTestCases)
-
-main :: IO ()
-main = do putStrLn $ "*** SBVUnitTester, version: " ++ showVersion version ++ ", time stamp: " ++ buildTime
-          tgts <- getArgs
-          case tgts of
-            [x] | x `elem` ["-h", "--help", "-?"]
-                   -> do putStrLn "Usage: SBVUnitTests [-c] [-l] [-s] [targets]" -- Not quite right, but sufficient
-                         putStrLn "  -l: List all tests"
-                         putStrLn "  -s: Skip constant-folding tests"
-                         putStrLn "  -c: Create gold-files"
-                         putStrLn "  -m: Do a wild-card match on targets"
-                         putStrLn "  -i: Do an inverse wild-card match on targets"
-                         putStrLn "If targets are given, run those groups; except with the -m flag which matches test names."
-            ["-l"] -> showTargets
-            -- undocumented really
-            ("-c":ts) -> run (Nothing,     ts)   False True ["SBVUnitTest/GoldFiles"]
-            ("-s":ts) -> run (Nothing,     ts)   True  False []
-            ("-m":ts) -> run (Just False,  ts)   False False []
-            ("-i":ts) -> run (Just True,   ts)   False False []
-            _         -> run (Nothing,   tgts) False False []
-
-checkGoldDir :: FilePath -> IO ()
-checkGoldDir gd = do e <- doesDirectoryExist gd
-                     unless e $ do putStrLn "*** Cannot locate gold file repository!"
-                                   putStrLn "*** Please call with one argument, the directory name of the gold files."
-                                   putStrLn "*** Cannot run test cases, exiting."
-                                   exitWith $ ExitFailure 1
-
-allTargets :: [String]
-allTargets = [s | (s, _, _) <- allTestCases]
-
-showTargets :: IO ()
-showTargets = do putStrLn "Known test targets are:"
-                 mapM_ (putStrLn . ("\t" ++))  allTargets
-
-run :: (Maybe Bool, [String]) -> Bool -> Bool -> [String] -> IO ()
-run (mbWCMatch, targets) skipCF shouldCreate [gd] =
-        do mapM_ checkTgt targets
-           putStrLn $ "*** Starting SBV unit tests..\n*** Gold files at: " ++ show gd
-           checkGoldDir gd
-           cts <- runTestTT $ TestList $ concatMap mkTst [c | (tc, needsSolver, c) <- allTestCases, select needsSolver tc]
-           decide shouldCreate cts
-  where mkTst (SBVTestSuite f) = pick $ f (generateGoldCheck gd shouldCreate)
-          where pick :: Test -> [Test]
-                pick tst = case mbWCMatch of
-                             Nothing       -> [tst]
-                             Just inverted -> collect tst
-                              where collect (TestCase _)    = []
-                                    collect (TestList ts)   = concatMap collect ts
-                                    collect t@(TestLabel s _)
-                                       | all (`isInfixOf` s) targets = [t | not inverted]
-                                       | True                        = [t |     inverted]
-        wcMode = isJust mbWCMatch
-        select needsSolver tc
-           | not included = False
-           | shouldCreate = True
-           | needsSolver  = True
-           | True         = not skipCF
-          where included | wcMode = True
-                         | True   = null targets || tc `elem` targets
-        checkTgt t | wcMode              = return ()
-                   | t `elem` allTargets = return ()
-                   | True                = do putStrLn $ "*** Unknown test target: " ++ show t
-                                              exitWith $ ExitFailure 1
-run targets skipCF shouldCreate [] = getDataDir >>= \d -> run targets skipCF shouldCreate [d </> "SBVUnitTest" </> "GoldFiles"]
-run _       _      _            _  = error "SBVUnitTests.run: impossible happened!"
-
-decide :: Bool -> Counts -> IO ()
-decide shouldCreate (Counts c t e f) = do
-        when (c /= t) $ putStrLn $ "*** Not all test cases were tried. (Only tested " ++ show t ++ " of " ++ show c ++ ")"
-        when (e /= 0) $ putStrLn $ "*** " ++ show e ++ " (of " ++ show c ++ ") test cases in error."
-        when (f /= 0) $ putStrLn $ "*** " ++ show f ++ " (of " ++ show c ++ ") test cases failed."
-        if c == t && e == 0 && f == 0
-           then do putStrLn $ "All " ++ show c ++ " test cases "
-                            ++ (if shouldCreate
-                                then " executed in gold-file generation mode."
-                                else " successfully passed.")
-                   exitSuccess
-           else exitWith $ ExitFailure 2
diff --git a/SBVUnitTest/SBVUnitTestBuildTime.hs b/SBVUnitTest/SBVUnitTestBuildTime.hs
deleted file mode 100644
--- a/SBVUnitTest/SBVUnitTestBuildTime.hs
+++ /dev/null
@@ -1,5 +0,0 @@
--- Auto-generated, don't edit
-module SBVUnitTestBuildTime (buildTime) where
-
-buildTime :: String
-buildTime = "Mon Jan 30 16:59:33 PST 2017"
diff --git a/SBVUnitTest/TestSuite/Arrays/Memory.hs b/SBVUnitTest/TestSuite/Arrays/Memory.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Arrays/Memory.hs
+++ /dev/null
@@ -1,30 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Arrays.Memory
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Arrays.Memory
------------------------------------------------------------------------------
-
-module TestSuite.Arrays.Memory(testSuite) where
-
-import Examples.Arrays.Memory
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-     "memory-raw"           ~: assert       =<< isThm t1
-   , "memory-waw"           ~: assert       =<< isThm t2
-   , "memory-wcommute-good" ~: assert       =<< isThm t3
-   , "memory-wcommute-bad"  ~: assert . not =<< isThm t4
-   ]
-   where t1 = free "a" >>= \a -> free "x" >>= \x ->                                       newArray "m" Nothing >>= return . raw a x
-         t2 = free "a" >>= \a -> free "x" >>= \x -> free "y" >>= \y ->                    newArray "m" Nothing >>= return . waw a x y
-         t3 = free "a" >>= \a -> free "x" >>= \x -> free "b" >>= \b -> free "y" >>= \y -> newArray "m" Nothing >>= return . wcommutesGood (a, x) (b, y)
-         t4 = free "a" >>= \a -> free "x" >>= \x -> free "b" >>= \b -> free "y" >>= \y -> newArray "m" Nothing >>= return . wcommutesBad  (a, x) (b, y)
-
-{-# ANN module ("HLint: ignore Use fmap" :: String) #-}
diff --git a/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs b/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs
+++ /dev/null
@@ -1,488 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.ArithNoSolver
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for basic concrete arithmetic, i.e., testing all
--- the constant folding based arithmetic implementation in SBV
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types    #-}
-{-# LANGUAGE TupleSections #-}
-
-module TestSuite.Basics.ArithNoSolver(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-
-import Data.Maybe(fromJust, fromMaybe)
-
-import SBVTest
-import qualified Data.Binary.IEEE754 as DB (wordToFloat, wordToDouble, floatToWord, doubleToWord)
-
-ghcBitSize :: Bits a => a -> Int
-ghcBitSize x = fromMaybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") (bitSizeMaybe x)
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test $
-        genReals
-     ++ genFloats
-     ++ genQRems
-     ++ genBinTest  "+"                (+)
-     ++ genBinTest  "-"                (-)
-     ++ genBinTest  "*"                (*)
-     ++ genUnTest   "negate"           negate
-     ++ genUnTest   "abs"              abs
-     ++ genUnTest   "signum"           signum
-     ++ genBinTest  ".&."              (.&.)
-     ++ genBinTest  ".|."              (.|.)
-     ++ genBoolTest "<"                (<)  (.<)
-     ++ genBoolTest "<="               (<=) (.<=)
-     ++ genBoolTest ">"                (>)  (.>)
-     ++ genBoolTest ">="               (>=) (.>=)
-     ++ genBoolTest "=="               (==) (.==)
-     ++ genBoolTest "/="               (/=) (./=)
-     ++ genBinTest  "xor"              xor
-     ++ genUnTest   "complement"       complement
-     ++ genIntTest  "shift"            shift
-     ++ genIntTest  "rotate"           rotate
-     ++ genIntTestS "setBit"           setBit
-     ++ genIntTestS "clearBit"         clearBit
-     ++ genIntTestS "complementBit"    complementBit
-     ++ genIntTest  "shift"            shift
-     ++ genIntTestS "shiftL"           shiftL
-     ++ genIntTestS "shiftR"           shiftR
-     ++ genIntTest  "rotate"           rotate
-     ++ genIntTestS "rotateL"          rotateL
-     ++ genIntTestS "rotateR"          rotateR
-     ++ genBlasts
-     ++ genIntCasts
-
-genBinTest :: String -> (forall a. (Num a, Bits a) => a -> a -> a) -> [Test]
-genBinTest nm op = map mkTest $
-        zipWith pair [(show x, show y, x `op` y) | x <- w8s,  y <- w8s ] [x `op` y | x <- sw8s,  y <- sw8s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w16s, y <- w16s] [x `op` y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w32s, y <- w32s] [x `op` y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w64s, y <- w64s] [x `op` y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i8s,  y <- i8s ] [x `op` y | x <- si8s,  y <- si8s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i16s, y <- i16s] [x `op` y | x <- si16s, y <- si16s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i32s, y <- i32s] [x `op` y | x <- si32s, y <- si32s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i64s, y <- i64s] [x `op` y | x <- si64s, y <- si64s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- iUBs, y <- iUBs] [x `op` y | x <- siUBs, y <- siUBs]
-  where pair (x, y, a) b   = (x, y, show (fromIntegral a `asTypeOf` b) == show b)
-        mkTest (x, y, s) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
-
-genBoolTest :: String -> (forall a. Ord a => a -> a -> Bool) -> (forall a. OrdSymbolic a => a -> a -> SBool) -> [Test]
-genBoolTest nm op opS = map mkTest $
-        zipWith pair [(show x, show y, x `op` y) | x <- w8s,  y <- w8s ] [x `opS` y | x <- sw8s,  y <- sw8s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w16s, y <- w16s] [x `opS` y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w32s, y <- w32s] [x `opS` y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- w64s, y <- w64s] [x `opS` y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i8s,  y <- i8s ] [x `opS` y | x <- si8s,  y <- si8s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i16s, y <- i16s] [x `opS` y | x <- si16s, y <- si16s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i32s, y <- i32s] [x `opS` y | x <- si32s, y <- si32s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- i64s, y <- i64s] [x `opS` y | x <- si64s, y <- si64s]
-     ++ zipWith pair [(show x, show y, x `op` y) | x <- iUBs, y <- iUBs] [x `opS` y | x <- siUBs, y <- siUBs]
-  where pair (x, y, a) b   = (x, y, Just a == unliteral b)
-        mkTest (x, y, s) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
-
-genUnTest :: String -> (forall a. (Num a, Bits a) => a -> a) -> [Test]
-genUnTest nm op = map mkTest $
-        zipWith pair [(show x, op x) | x <- w8s ] [op x | x <- sw8s ]
-     ++ zipWith pair [(show x, op x) | x <- w16s] [op x | x <- sw16s]
-     ++ zipWith pair [(show x, op x) | x <- w32s] [op x | x <- sw32s]
-     ++ zipWith pair [(show x, op x) | x <- w64s] [op x | x <- sw64s]
-     ++ zipWith pair [(show x, op x) | x <- i8s ] [op x | x <- si8s ]
-     ++ zipWith pair [(show x, op x) | x <- i16s] [op x | x <- si16s]
-     ++ zipWith pair [(show x, op x) | x <- i32s] [op x | x <- si32s]
-     ++ zipWith pair [(show x, op x) | x <- i64s] [op x | x <- si64s]
-     ++ zipWith pair [(show x, op x) | x <- iUBs] [op x | x <- siUBs]
-  where pair (x, a) b   = (x, show (fromIntegral a `asTypeOf` b) == show b)
-        mkTest (x, s) = "arithCF-" ++ nm ++ "." ++ x ~: s `showsAs` "True"
-
-genIntTest :: String -> (forall a. (Num a, Bits a) => a -> Int -> a) -> [Test]
-genIntTest nm op = map mkTest $
-        zipWith pair [("u8",  show x, show y, x `op` y) | x <- w8s,  y <- is] [x `op` y | x <- sw8s,  y <- is]
-     ++ zipWith pair [("u16", show x, show y, x `op` y) | x <- w16s, y <- is] [x `op` y | x <- sw16s, y <- is]
-     ++ zipWith pair [("u32", show x, show y, x `op` y) | x <- w32s, y <- is] [x `op` y | x <- sw32s, y <- is]
-     ++ zipWith pair [("u64", show x, show y, x `op` y) | x <- w64s, y <- is] [x `op` y | x <- sw64s, y <- is]
-     ++ zipWith pair [("s8",  show x, show y, x `op` y) | x <- i8s,  y <- is] [x `op` y | x <- si8s,  y <- is]
-     ++ zipWith pair [("s16", show x, show y, x `op` y) | x <- i16s, y <- is] [x `op` y | x <- si16s, y <- is]
-     ++ zipWith pair [("s32", show x, show y, x `op` y) | x <- i32s, y <- is] [x `op` y | x <- si32s, y <- is]
-     ++ zipWith pair [("s64", show x, show y, x `op` y) | x <- i64s, y <- is] [x `op` y | x <- si64s, y <- is]
-     ++ zipWith pair [("iUB", show x, show y, x `op` y) | x <- iUBs, y <- is] [x `op` y | x <- siUBs, y <- is]
-  where pair (t, x, y, a) b       = (t, x, y, show a, show b, show (fromIntegral a `asTypeOf` b) == show b)
-        mkTest (t, x, y, a, b, s) = "arithCF-" ++ nm ++ "." ++ t ++ "_" ++ x ++ "_" ++ y ++ "_" ++ a ++ "_" ++ b ~: s `showsAs` "True"
-        is = [-10 .. 10]
-
-genIntTestS :: String -> (forall a. (Num a, Bits a) => a -> Int -> a) -> [Test]
-genIntTestS nm op = map mkTest $
-        zipWith pair [("u8",  show x, show y, x `op` y) | x <- w8s,  y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- sw8s,  y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("u16", show x, show y, x `op` y) | x <- w16s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- sw16s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("u32", show x, show y, x `op` y) | x <- w32s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- sw32s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("u64", show x, show y, x `op` y) | x <- w64s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- sw64s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("s8",  show x, show y, x `op` y) | x <- i8s,  y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- si8s,  y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("s16", show x, show y, x `op` y) | x <- i16s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- si16s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("s32", show x, show y, x `op` y) | x <- i32s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- si32s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("s64", show x, show y, x `op` y) | x <- i64s, y <- [0 .. (ghcBitSize x - 1)]] [x `op` y | x <- si64s, y <- [0 .. (ghcBitSize x - 1)]]
-     ++ zipWith pair [("iUB", show x, show y, x `op` y) | x <- iUBs, y <- [0 .. 10]]              [x `op` y | x <- siUBs, y <- [0 .. 10             ]]
-  where pair (t, x, y, a) b       = (t, x, y, show a, show b, show (fromIntegral a `asTypeOf` b) == show b)
-        mkTest (t, x, y, a, b, s) = "arithCF-" ++ nm ++ "." ++ t ++ "_" ++ x ++ "_" ++ y ++ "_" ++ a ++ "_" ++ b ~: s `showsAs` "True"
-
-genBlasts :: [Test]
-genBlasts = map mkTest $
-             [(show x, fromBitsLE (blastLE x) .== x) | x <- sw8s ]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw8s ]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si8s ]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si8s ]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw16s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw16s]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si16s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si16s]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw32s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw32s]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si32s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si32s]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- sw64s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- sw64s]
-          ++ [(show x, fromBitsLE (blastLE x) .== x) | x <- si64s]
-          ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si64s]
-  where mkTest (x, r) = "blast-" ++ x ~: r `showsAs` "True"
-
-genIntCasts :: [Test]
-genIntCasts = map mkTest $  cast w8s ++ cast w16s ++ cast w32s ++ cast w64s
-                         ++ cast i8s ++ cast i16s ++ cast i32s ++ cast i64s
-                         ++ cast iUBs
-   where mkTest (x, r) = "intCast-" ++ x ~: r `showsAs` "True"
-         lhs x = sFromIntegral (literal x)
-         rhs x = literal (fromIntegral x)
-         cast :: forall a. (Show a, Integral a, SymWord a) => [a] -> [(String, SBool)]
-         cast xs = toWords xs ++ toInts xs
-         toWords xs =  [(show x, lhs x .== (rhs x :: SWord8 ))  | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SWord16))  | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SWord32))  | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SWord64))  | x <- xs]
-         toInts  xs =  [(show x, lhs x .== (rhs x :: SInt8 ))   | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SInt16))   | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SInt32))   | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SInt64))   | x <- xs]
-                    ++ [(show x, lhs x .== (rhs x :: SInteger)) | x <- xs]
-
-genQRems :: [Test]
-genQRems = map mkTest $
-        zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w8s,  y <- w8s ] [x `sDivMod`  y | x <- sw8s,  y <- sw8s ]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w16s, y <- w16s] [x `sDivMod`  y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w32s, y <- w32s] [x `sDivMod`  y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- w64s, y <- w64s] [x `sDivMod`  y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i8s,  y <- i8s ] [x `sDivMod`  y | x <- si8s,  y <- si8s ]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i16s, y <- i16s] [x `sDivMod`  y | x <- si16s, y <- si16s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i32s, y <- i32s] [x `sDivMod`  y | x <- si32s, y <- si32s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod1`  y) | x <- i64s, y <- i64s] [x `sDivMod`  y | x <- si64s, y <- si64s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod0`  y) | x <- iUBs, y <- iUBs] [x `sDivMod`  y | x <- siUBs, y <- siUBs]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w8s,  y <- w8s ] [x `sQuotRem` y | x <- sw8s,  y <- sw8s ]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w16s, y <- w16s] [x `sQuotRem` y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w32s, y <- w32s] [x `sQuotRem` y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- w64s, y <- w64s] [x `sQuotRem` y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i8s,  y <- i8s ] [x `sQuotRem` y | x <- si8s,  y <- si8s ]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i16s, y <- i16s] [x `sQuotRem` y | x <- si16s, y <- si16s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i32s, y <- i32s] [x `sQuotRem` y | x <- si32s, y <- si32s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem1` y) | x <- i64s, y <- i64s] [x `sQuotRem` y | x <- si64s, y <- si64s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem0` y) | x <- iUBs, y <- iUBs] [x `sQuotRem` y | x <- siUBs, y <- siUBs]
-  where pair (nm, x, y, (r1, r2)) (e1, e2)   = (nm, x, y, show (fromIntegral r1 `asTypeOf` e1, fromIntegral r2 `asTypeOf` e2) == show (e1, e2))
-        mkTest (nm, x, y, s) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
-        -- Haskell's divMod and quotRem differs from SBV's in two ways:
-        --     - when y is 0, Haskell throws an exception, SBV sets the result to 0; like in division
-        --     - Haskell overflows if x == minBound and y == -1 for bounded signed types; but SBV returns minBound, 0; which is more meaningful
-        -- NB. There was a ticket filed against the second anomaly above, See: https://ghc.haskell.org/trac/ghc/ticket/8695
-        -- But the Haskell folks decided not to fix it. Sigh..
-        overflow x y = x == minBound && y == -1
-        divMod0  x y = if y == 0       then (0, x) else x `divMod`   y
-        divMod1  x y = if overflow x y then (x, 0) else x `divMod0`  y
-        quotRem0 x y = if y == 0       then (0, x) else x `quotRem`  y
-        quotRem1 x y = if overflow x y then (x, 0) else x `quotRem0` y
-
-genReals :: [Test]
-genReals = map mkTest $
-        map ("+",)  (zipWith pair [(show x, show y, x +  y) | x <- rs, y <- rs        ] [x +   y | x <- srs,  y <- srs                       ])
-     ++ map ("-",)  (zipWith pair [(show x, show y, x -  y) | x <- rs, y <- rs        ] [x -   y | x <- srs,  y <- srs                       ])
-     ++ map ("*",)  (zipWith pair [(show x, show y, x *  y) | x <- rs, y <- rs        ] [x *   y | x <- srs,  y <- srs                       ])
-     ++ map ("<",)  (zipWith pair [(show x, show y, x <  y) | x <- rs, y <- rs        ] [x .<  y | x <- srs,  y <- srs                       ])
-     ++ map ("<=",) (zipWith pair [(show x, show y, x <= y) | x <- rs, y <- rs        ] [x .<= y | x <- srs,  y <- srs                       ])
-     ++ map (">",)  (zipWith pair [(show x, show y, x >  y) | x <- rs, y <- rs        ] [x .>  y | x <- srs,  y <- srs                       ])
-     ++ map (">=",) (zipWith pair [(show x, show y, x >= y) | x <- rs, y <- rs        ] [x .>= y | x <- srs,  y <- srs                       ])
-     ++ map ("==",) (zipWith pair [(show x, show y, x == y) | x <- rs, y <- rs        ] [x .== y | x <- srs,  y <- srs                       ])
-     ++ map ("/=",) (zipWith pair [(show x, show y, x /= y) | x <- rs, y <- rs        ] [x ./= y | x <- srs,  y <- srs                       ])
-     ++ map ("/",)  (zipWith pair [(show x, show y, x /  y) | x <- rs, y <- rs, y /= 0] [x / y   | x <- srs,  y <- srs, unliteral y /= Just 0])
-  where pair (x, y, a) b   = (x, y, Just a == unliteral b)
-        mkTest (nm, (x, y, s)) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
-
-genFloats :: [Test]
-genFloats = bTests ++ uTests ++ fpTests1 ++ fpTests2 ++ converts
-  where bTests = map mkTest2 $  floatRun2  "+"  (+)  (+)   comb
-                             ++ doubleRun2 "+"  (+)  (+)   comb
-
-                             ++ floatRun2  "-"  (-)  (-)   comb
-                             ++ doubleRun2 "-"  (-)  (-)   comb
-
-                             ++ floatRun2  "*"  (*)  (*)   comb
-                             ++ doubleRun2 "*"  (*)  (*)   comb
-
-                             ++ floatRun2  "/"  (/)  (/)   comb
-                             ++ doubleRun2 "/"  (/)  (/)   comb
-
-                             ++ floatRun2  "<"  (<)  (.<)  combB
-                             ++ doubleRun2 "<"  (<)  (.<)  combB
-
-                             ++ floatRun2  "<=" (<=) (.<=) combB
-                             ++ doubleRun2 "<=" (<=) (.<=) combB
-
-                             ++ floatRun2  ">"  (>)  (.>)  combB
-                             ++ doubleRun2 ">"  (>)  (.>)  combB
-
-                             ++ floatRun2  ">=" (>=) (.>=) combB
-                             ++ doubleRun2 ">=" (>=) (.>=) combB
-
-                             ++ floatRun2  "==" (==) (.==) combB
-                             ++ doubleRun2 "==" (==) (.==) combB
-
-                             ++ floatRun2  "/=" (/=) (./=) combN
-                             ++ doubleRun2 "/=" (/=) (./=) combN
-
-        fpTests1 = map mkTest1 $  floatRun1   "abs"               abs                abs               comb1
-                               ++ floatRun1   "fpAbs"             abs                fpAbs             comb1
-                               ++ doubleRun1  "abs"               abs                abs               comb1
-                               ++ doubleRun1  "fpAbs"             abs                fpAbs             comb1
-
-                               ++ floatRun1   "negate"            negate             negate            comb1
-                               ++ floatRun1   "fpNeg"             negate             fpNeg             comb1
-                               ++ doubleRun1  "negate"            negate             negate            comb1
-                               ++ doubleRun1  "fpNeg"             negate             fpNeg             comb1
-
-                               ++ floatRun1M  "fpSqrt"            sqrt               fpSqrt            comb1
-                               ++ doubleRun1M "fpSqrt"            sqrt               fpSqrt            comb1
-
-                               ++ floatRun1M  "fpRoundToIntegral" fpRoundToIntegralH fpRoundToIntegral comb1
-                               ++ doubleRun1M "fpRoundToIntegral" fpRoundToIntegralH fpRoundToIntegral comb1
-
-                               ++ floatRun1   "signum"            signum             signum            comb1
-                               ++ doubleRun1  "signum"            signum             signum            comb1
-
-        -- TODO. Can't possibly test fma, unless we FFI out to C. Leave it out for the time being
-        fpTests2 = map mkTest2 $  floatRun2M  "fpAdd"           (+)              fpAdd           comb
-                               ++ doubleRun2M "fpAdd"           (+)              fpAdd           comb
-
-                               ++ floatRun2M  "fpSub"           (-)              fpSub           comb
-                               ++ doubleRun2M "fpSub"           (-)              fpSub           comb
-
-                               ++ floatRun2M  "fpMul"           (*)              fpMul           comb
-                               ++ doubleRun2M "fpMul"           (*)              fpMul           comb
-
-                               ++ floatRun2M  "fpDiv"           (/)              fpDiv           comb
-                               ++ doubleRun2M "fpDiv"           (/)              fpDiv           comb
-
-                               ++ floatRunMM  "fpMin"           fpMinH           fpMin           comb
-                               ++ doubleRunMM "fpMin"           fpMinH           fpMin           comb
-
-                               ++ floatRunMM  "fpMax"           fpMaxH           fpMax           comb
-                               ++ doubleRunMM "fpMax"           fpMaxH           fpMax           comb
-
-                               ++ floatRun2   "fpRem"           fpRemH           fpRem           comb
-                               ++ doubleRun2  "fpRem"           fpRemH           fpRem           comb
-
-                               ++ 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]
-
-                 ++ 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]
-
-                 ++ map cvtTest  [("reinterp_Word32_Float",  show x, sWord32AsSFloat  (literal x), literal (DB.wordToFloat  x)) | x <- w32s]
-                 ++ map cvtTest  [("reinterp_Word64_Double", show x, sWord64AsSDouble (literal x), literal (DB.wordToDouble x)) | x <- w64s]
-
-                 ++ map cvtTestI [("reinterp_Float_Word32",  show x, sFloatAsSWord32  (literal x), literal (DB.floatToWord x))  | x <- fs, not (isNaN x)] -- Not unique for NaN
-                 ++ map cvtTestI [("reinterp_Double_Word64", show x, sDoubleAsSWord64 (literal x), literal (DB.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)]
-        -- 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
-                             ++ concatMap (checkPred ds sds) predicates
-        extract :: SymWord a => SBV a -> a
-        extract = fromJust . unliteral
-
-        comb  (x, y, a, b) = (show x, show y, same a b)
-        combB (x, y, a, b) = (show x, show y, checkNaN f x y a b) where f v w = not (v || w)  -- All comparisons except /=: Both should be False if we have a NaN argument
-        combN (x, y, a, b) = (show x, show y, checkNaN f x y a b) where f v w =      v && w   -- /=: Both should be True
-        combE (x, y, a, b) = (show x, show y, a == b)
-        comb1 (x, a, b)    = (show x, same a b)
-        same a b = (isNaN a &&& isNaN b) || (a == b)
-        checkNaN f x y a b
-          | isNaN x || isNaN y = f a b
-          | True               = a == b
-
-        cvtTest  (nm, x, a, b)  = "arithCF-" ++ nm ++ "." ++ x ~: same (extract a) (extract b) `showsAs` "True"
-        cvtTestI (nm, x, a, b)  = "arithCF-" ++ nm ++ "." ++ x ~: (a == b) `showsAs` "True"
-
-        mkTest1 (nm, (x, s))    = "arithCF-" ++ nm ++ "." ++ x ~: s `showsAs` "True"
-        mkTest2 (nm, (x, y, s)) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
-
-        checkPred :: Show a => [a] -> [SBV a] -> (String, SBV a -> SBool, a -> Bool) -> [(String, (String, Bool))]
-        checkPred xs sxs (n, ps, p) = zipWith (chk n) (map (\x -> (x, p x)) xs) (map ps sxs)
-          where chk nm (x, v) sv = (nm, (show x, Just v == unliteral sv))
-
-        predicates :: IEEEFloating a => [(String, SBV a -> SBool, a -> Bool)]
-        predicates = [ ("fpIsNormal",       fpIsNormal,        fpIsNormalizedH)
-                     , ("fpIsSubnormal",    fpIsSubnormal,     isDenormalized)
-                     , ("fpIsZero",         fpIsZero,          (== 0))
-                     , ("fpIsInfinite",     fpIsInfinite,      isInfinite)
-                     , ("fpIsNaN",          fpIsNaN,           isNaN)
-                     , ("fpIsNegative",     fpIsNegative,      \x -> x < 0  ||      isNegativeZero x)
-                     , ("fpIsPositive",     fpIsPositive,      \x -> x >= 0 && not (isNegativeZero x))
-                     , ("fpIsNegativeZero", fpIsNegativeZero,  isNegativeZero)
-                     , ("fpIsPositiveZero", fpIsPositiveZero,  \x -> x == 0 && not (isNegativeZero x))
-                     , ("fpIsPoint",        fpIsPoint,         \x -> not (isNaN x || isInfinite x))
-                     ]
-
--- Concrete test data
-xsUnsigned :: (Num a, Bounded a) => [a]
-xsUnsigned = take 5 (iterate (1+) minBound) ++ take 5 (iterate (\x -> x-1) maxBound)
-
-xsSigned :: (Num a, Enum a, Bounded a) => [a]
-xsSigned   = xsUnsigned ++ [-5 .. 5]
-
-w8s :: [Word8]
-w8s = xsUnsigned
-
-sw8s :: [SWord8]
-sw8s = xsUnsigned
-
-w16s :: [Word16]
-w16s = xsUnsigned
-
-sw16s :: [SWord16]
-sw16s = xsUnsigned
-
-w32s :: [Word32]
-w32s = xsUnsigned
-
-sw32s :: [SWord32]
-sw32s = xsUnsigned
-
-w64s :: [Word64]
-w64s = xsUnsigned
-
-sw64s :: [SWord64]
-sw64s = xsUnsigned
-
-i8s :: [Int8]
-i8s = xsSigned
-
-si8s :: [SInt8]
-si8s = xsSigned
-
-i16s :: [Int16]
-i16s = xsSigned
-
-si16s :: [SInt16]
-si16s = xsSigned
-
-i32s :: [Int32]
-i32s = xsSigned
-
-si32s :: [SInt32]
-si32s = xsSigned
-
-i64s :: [Int64]
-i64s = xsSigned
-
-si64s :: [SInt64]
-si64s = xsSigned
-
-iUBs :: [Integer]
-iUBs = [-1000000 .. -999995] ++ [-5 .. 5] ++ [999995 ..  1000000]
-
-siUBs :: [SInteger]
-siUBs = map literal iUBs
-
-rs :: [AlgReal]
-rs = [fromRational (i % d) | i <- nums, d <- dens]
- where nums = [-1000000 .. -999998] ++ [-2 .. 2] ++ [999998 ..  1000001]
-       dens = [2 .. 5] ++ [98 .. 102] ++ [999998 .. 1000000]
-
-srs :: [SReal]
-srs = map literal rs
-
-fs :: [Float]
-fs = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
- where xs = [nan, infinity, 0, 0.5, 0.68302244, 0.5268265, 0.10283524, 5.8336496e-2, 1.0e-45]
-
-sfs :: [SFloat]
-sfs = map literal fs
-
-ds :: [Double]
-ds = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
- where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 7.518897767550192e-2, 1.1656043286207285e-2, 5.0e-324]
-
-sds :: [SDouble]
-sds = map literal ds
diff --git a/SBVUnitTest/TestSuite/Basics/ArithSolver.hs b/SBVUnitTest/TestSuite/Basics/ArithSolver.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/ArithSolver.hs
+++ /dev/null
@@ -1,485 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.ArithSolver
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for basic non-concrete arithmetic, i.e., testing all
--- basic arithmetic reasoning using an SMT solver without any
--- constant folding.
------------------------------------------------------------------------------
-
-{-# LANGUAGE Rank2Types    #-}
-{-# LANGUAGE TupleSections #-}
-
-module TestSuite.Basics.ArithSolver(testSuite) where
-
-import Data.Maybe (fromMaybe, fromJust)
-import qualified Data.Binary.IEEE754 as DB (wordToFloat, wordToDouble, floatToWord, doubleToWord)
-
-import Data.SBV
-import Data.SBV.Internals
-
-import SBVTest
-
-ghcBitSize :: Bits a => a -> Int
-ghcBitSize x = fromMaybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") (bitSizeMaybe x)
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test $
-        genReals
-     ++ genFloats
-     ++ genDoubles
-     ++ genFPConverts
-     ++ genQRems
-     ++ genBinTest  True   "+"                (+)
-     ++ genBinTest  True   "-"                (-)
-     ++ genBinTest  True   "*"                (*)
-     ++ genUnTest   True   "negate"           negate
-     ++ genUnTest   True   "abs"              abs
-     ++ genUnTest   True   "signum"           signum
-     ++ genBinTest  False  ".&."              (.&.)
-     ++ genBinTest  False  ".|."              (.|.)
-     ++ genBoolTest        "<"                (<)  (.<)
-     ++ genBoolTest        "<="               (<=) (.<=)
-     ++ genBoolTest        ">"                (>)  (.>)
-     ++ genBoolTest        ">="               (>=) (.>=)
-     ++ genBoolTest        "=="               (==) (.==)
-     ++ genBoolTest        "/="               (/=) (./=)
-     ++ genBinTest  False  "xor"              xor
-     ++ genUnTest   False  "complement"       complement
-     ++ genIntTest         "shift"            shift
-     ++ genIntTest         "rotate"           rotate
-     ++ genIntTestS False  "setBit"           setBit
-     ++ genIntTestS False  "clearBit"         clearBit
-     ++ genIntTestS False  "complementBit"    complementBit
-     ++ genIntTest         "shift"            shift
-     ++ genIntTestS True   "shiftL"           shiftL
-     ++ genIntTestS True   "shiftR"           shiftR
-     ++ genIntTest         "rotate"           rotate
-     ++ genIntTestS True   "rotateL"          rotateL
-     ++ genIntTestS True   "rotateR"          rotateR
-     ++ genBlasts
-     ++ genIntCasts
-
-genBinTest :: Bool -> String -> (forall a. (Num a, Bits a) => a -> a -> a) -> [Test]
-genBinTest unboundedOK nm op = 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)) | unboundedOK, x <- iUBs, y <- iUBs]
-  where mkTest (x, y, t) = "genBinTest.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: assert t
-        mkThm2 x y r = isThm $ do [a, b] <- mapM free ["x", "y"]
-                                  constrain $ a .== literal x
-                                  constrain $ b .== literal y
-                                  return $ literal r .== a `op` b
-
-genBoolTest :: String -> (forall a. Ord a => a -> a -> Bool) -> (forall a. OrdSymbolic a => a -> a -> SBool) -> [Test]
-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]
-  where mkTest (x, y, t) = "genBoolTest.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: assert t
-        mkThm2 x y r = isThm $ do [a, b] <- mapM free ["x", "y"]
-                                  constrain $ a .== literal x
-                                  constrain $ b .== literal y
-                                  return $ literal r .== a `opS` b
-
-genUnTest :: Bool -> String -> (forall a. (Num a, Bits a) => a -> a) -> [Test]
-genUnTest unboundedOK nm op = map mkTest $  [(show x, mkThm x (op x)) | x <- w8s ]
-                                         ++ [(show x, mkThm x (op x)) | x <- w16s]
-                                         ++ [(show x, mkThm x (op x)) | x <- w32s]
-                                         ++ [(show x, mkThm x (op x)) | x <- w64s]
-                                         ++ [(show x, mkThm x (op x)) | x <- i8s ]
-                                         ++ [(show x, mkThm x (op x)) | x <- i16s]
-                                         ++ [(show x, mkThm x (op x)) | x <- i32s]
-                                         ++ [(show x, mkThm x (op x)) | x <- i64s]
-                                         ++ [(show x, mkThm x (op x)) | unboundedOK, x <- iUBs]
-  where mkTest (x, t) = "genUnTest.arithmetic-" ++ nm ++ "." ++ x ~: assert t
-        mkThm x r = isThm $ do a <- free "x"
-                               constrain $ a .== literal x
-                               return $ literal r .== op a
-
-genIntTest :: String -> (forall a. (Num a, Bits a) => a -> Int -> a) -> [Test]
-genIntTest nm op = map mkTest $  [("u8",  show x, show y, mkThm2 x y (x `op` y)) | x <- w8s,  y <- is]
-                              ++ [("u16", show x, show y, mkThm2 x y (x `op` y)) | x <- w16s, y <- is]
-                              ++ [("u32", show x, show y, mkThm2 x y (x `op` y)) | x <- w32s, y <- is]
-                              ++ [("u64", show x, show y, mkThm2 x y (x `op` y)) | x <- w64s, y <- is]
-                              ++ [("s8",  show x, show y, mkThm2 x y (x `op` y)) | x <- i8s,  y <- is]
-                              ++ [("s16", show x, show y, mkThm2 x y (x `op` y)) | x <- i16s, y <- is]
-                              ++ [("s32", show x, show y, mkThm2 x y (x `op` y)) | x <- i32s, y <- is]
-                              ++ [("s64", show x, show y, mkThm2 x y (x `op` y)) | x <- i64s, y <- is]
-                              ++ [("iUB", show x, show y, mkThm2 x y (x `op` y)) | x <- iUBs, y <- is]
-  where mkTest (l, x, y, t) = "genIntTest.arithmetic-" ++ nm ++ "." ++ l ++ "_" ++ x ++ "_" ++ y ~: assert t
-        is = [-10 .. 10]
-        mkThm2 x y r = isThm $ do a <- free "x"
-                                  constrain $ a .== literal x
-                                  return $ literal r .== a `op` y
-
-
-genIntTestS :: Bool -> String -> (forall a. (Num a, Bits a) => a -> Int -> a) -> [Test]
-genIntTestS unboundedOK nm op = map mkTest $  [("u8",  show x, show y, mkThm2 x y (x `op` y)) | x <- w8s,  y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("u16", show x, show y, mkThm2 x y (x `op` y)) | x <- w16s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("u32", show x, show y, mkThm2 x y (x `op` y)) | x <- w32s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("u64", show x, show y, mkThm2 x y (x `op` y)) | x <- w64s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("s8",  show x, show y, mkThm2 x y (x `op` y)) | x <- i8s,  y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("s16", show x, show y, mkThm2 x y (x `op` y)) | x <- i16s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("s32", show x, show y, mkThm2 x y (x `op` y)) | x <- i32s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("s64", show x, show y, mkThm2 x y (x `op` y)) | x <- i64s, y <- [0 .. (ghcBitSize x - 1)]]
-                                           ++ [("iUB", show x, show y, mkThm2 x y (x `op` y)) | unboundedOK, x <- iUBs, y <- [0 .. 10]]
-  where mkTest (l, x, y, t) = "genIntTestS.arithmetic-" ++ nm ++ "." ++ l ++ "_" ++ x ++ "_" ++ y ~: assert t
-        mkThm2 x y r = isThm $ do a <- free "x"
-                                  constrain $ a .== literal x
-                                  return $ literal r .== a `op` y
-
-genBlasts :: [Test]
-genBlasts = map mkTest $  [(show x, mkThm fromBitsLE blastLE x) | x <- w8s ]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w8s ]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i8s ]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i8s ]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w16s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w16s]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i16s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i16s]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w32s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w32s]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i32s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i32s]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- w64s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- w64s]
-                       ++ [(show x, mkThm fromBitsLE blastLE x) | x <- i64s]
-                       ++ [(show x, mkThm fromBitsBE blastBE x) | x <- i64s]
-  where mkTest (x, t) = "genBlasts.blast-" ++ show x ~: assert t
-        mkThm from to v = isThm $ do a <- free "x"
-                                     constrain $ a .== literal v
-                                     return $ a .== from (to a)
-
-genIntCasts :: [Test]
-genIntCasts = map mkTest $  cast w8s ++ cast w16s ++ cast w32s ++ cast w64s
-                         ++ cast i8s ++ cast i16s ++ cast i32s ++ cast i64s
-                         ++ cast iUBs
-   where mkTest (x, t) = "sIntCast-" ++ x ~: assert t
-         cast :: forall a. (Show a, Integral a, SymWord a) => [a] -> [(String, IO Bool)]
-         cast xs = toWords xs ++ toInts xs
-         toWords xs =  [(show x, mkThm x (fromIntegral x :: Word8 ))  | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Word16))  | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Word32))  | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Word64))  | x <- xs]
-         toInts  xs =  [(show x, mkThm x (fromIntegral x :: Int8 ))   | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Int16))   | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Int32))   | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Int64))   | x <- xs]
-                    ++ [(show x, mkThm x (fromIntegral x :: Integer)) | x <- xs]
-         mkThm v res = isThm $ do a <- free "x"
-                                  constrain $ a .== literal v
-                                  return $ literal res .== sFromIntegral a
-
-genReals :: [Test]
-genReals = map mkTest $  [("+",  show x, show y, mkThm2 (+)   x y (x +  y)) | x <- rs, y <- rs        ]
-                      ++ [("-",  show x, show y, mkThm2 (-)   x y (x -  y)) | x <- rs, y <- rs        ]
-                      ++ [("*",  show x, show y, mkThm2 (*)   x y (x *  y)) | x <- rs, y <- rs        ]
-                      ++ [("/",  show x, show y, mkThm2 (/)   x y (x /  y)) | x <- rs, y <- rs, y /= 0]
-                      ++ [("<",  show x, show y, mkThm2 (.<)  x y (x <  y)) | x <- rs, y <- rs        ]
-                      ++ [("<=", show x, show y, mkThm2 (.<=) x y (x <= y)) | x <- rs, y <- rs        ]
-                      ++ [(">",  show x, show y, mkThm2 (.>)  x y (x >  y)) | x <- rs, y <- rs        ]
-                      ++ [(">=", show x, show y, mkThm2 (.>=) x y (x >= y)) | x <- rs, y <- rs        ]
-                      ++ [("==", show x, show y, mkThm2 (.==) x y (x == y)) | x <- rs, y <- rs        ]
-                      ++ [("/=", show x, show y, mkThm2 (./=) x y (x /= y)) | x <- rs, y <- rs        ]
-  where mkTest (nm, x, y, t) = "genReals.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: assert t
-        mkThm2 op x y r = isThm $ do [a, b] <- mapM free ["x", "y"]
-                                     constrain $ a .== literal x
-                                     constrain $ b .== literal y
-                                     return $ literal r .== a `op` b
-
-genFloats :: [Test]
-genFloats = genIEEE754 "genFloats" fs
-
-genDoubles :: [Test]
-genDoubles = genIEEE754 "genDoubles" ds
-
-genIEEE754 :: (IEEEFloating a, Show a, Ord a) => String -> [a] -> [Test]
-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]
-  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]
-               ++ [("fpAbs",             show x, mkThm1 fpAbs                 x  (abs x))                | x <- vs]
-               ++ [("fpNeg",             show x, mkThm1 fpNeg                 x  (negate x))             | x <- vs]
-               ++ [("fpSqrt",            show x, mkThm1 (m fpSqrt)            x  (sqrt   x))             | x <- vs]
-               ++ [("fpRoundToIntegral", show x, mkThm1 (m fpRoundToIntegral) x  (fpRoundToIntegralH x)) | x <- vs]
-
-        bins =    [("+",      show x,  show y, mkThm2        (+)       x y (x +  y))   | x <- vs, y <- vs]
-               ++ [("-",      show x,  show y, mkThm2        (-)       x y (x -  y))   | x <- vs, y <- vs]
-               ++ [("*",      show x,  show y, mkThm2        (*)       x y (x *  y))   | x <- vs, y <- vs]
-               ++ [("/",      show x,  show y, mkThm2        (/)       x y (x /  y))   | x <- vs, y <- vs]
-               ++ [("<",      show x,  show y, mkThm2C False (.<)      x y (x <  y))   | x <- vs, y <- vs]
-               ++ [("<=",     show x,  show y, mkThm2C False (.<=)     x y (x <= y))   | x <- vs, y <- vs]
-               ++ [(">",      show x,  show y, mkThm2C False (.>)      x y (x >  y))   | x <- vs, y <- vs]
-               ++ [(">=",     show x,  show y, mkThm2C False (.>=)     x y (x >= y))   | x <- vs, y <- vs]
-               ++ [("==",     show x,  show y, mkThm2C False (.==)     x y (x == y))   | x <- vs, y <- vs]
-               ++ [("/=",     show x,  show y, mkThm2C True  (./=)     x y (x /= y))   | x <- vs, y <- vs]
-               -- TODO. Can't possibly test fma, unless we FFI out to C. Leave it out for the time being
-               ++ [("fpAdd",           show x, show y, mkThm2  (m fpAdd)        x y ((+)              x y)) | x <- vs, y <- vs]
-               ++ [("fpSub",           show x, show y, mkThm2  (m fpSub)        x y ((-)              x y)) | x <- vs, y <- vs]
-               ++ [("fpMul",           show x, show y, mkThm2  (m fpMul)        x y ((*)              x y)) | x <- vs, y <- vs]
-               ++ [("fpDiv",           show x, show y, mkThm2  (m fpDiv)        x y ((/)              x y)) | x <- vs, y <- vs]
-               ++ [("fpMin",           show x, show y, mkThm2  fpMin            x y (fpMinH           x y)) | x <- vs, y <- vs, not (alt0 x y || alt0 y x)]
-               ++ [("fpMax",           show x, show y, mkThm2  fpMax            x y (fpMaxH           x y)) | x <- vs, y <- vs, not (alt0 x y || alt0 y x)]
-               ++ [("fpIsEqualObject", show x, show y, mkThm2P fpIsEqualObject  x y (fpIsEqualObjectH x y)) | x <- vs, y <- vs]
-               ++ [("fpRem",           show x, show y, mkThm2  fpRem            x y (fpRemH           x y)) | x <- vsFPRem, y <- vsFPRem]
-
-        -- TODO: For doubles fpRem takes too long, so we only do a subset
-        vsFPRem
-          | origin == "genDoubles" = [nan, infinity, 0, 0.5, -infinity, -0, -0.5]
-          | True                   = vs
-
-        -- fpMin/fpMax: skip +0/-0 case as this is underspecified
-        alt0 x y = isNegativeZero x && y == 0 && not (isNegativeZero y)
-
-        m f = f sRNE
-
-        preds =   [(pn, show x, mkThmP ps x (pc x)) | (pn, ps, pc) <- predicates, x <- vs]
-        tst2 (nm, x, y, t) = origin ++ ".arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: assert t
-        tst1 (nm, x,    t) = origin ++ ".arithmetic-" ++ nm ++ "." ++ x              ~: assert t
-
-        eqF v val
-          | isNaN          val        = constrain $ fpIsNaN v
-          | isNegativeZero val        = constrain $ fpIsNegativeZero v
-          | val == 0                  = constrain $ fpIsPositiveZero v
-          | isInfinite val && val > 0 = constrain $ fpIsInfinite v &&& fpIsPositive v
-          | isInfinite val && val < 0 = constrain $ fpIsInfinite v &&& fpIsNegative v
-          | True                      = constrain $ v .== literal val
-
-        -- Quickly pick which solver to use. Currently z3 or mathSAT supports FP
-        fpProver :: SMTConfig
-        fpProver = z3 -- mathSAT
-
-        fpThm :: Provable a => a -> IO Bool
-        fpThm p = fromJust `fmap` isTheoremWith fpProver Nothing p
-
-        mkThmP op x r = fpThm $ do a <- free "x"
-                                   eqF a x
-                                   return $ literal r .== op a
-
-        mkThm2P op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
-                                      eqF a x
-                                      eqF b y
-                                      return $ literal r .== a `op` b
-
-        mkThm1 op x r = fpThm $ do a <- free "x"
-                                   eqF a x
-                                   return $ literal r `fpIsEqualObject` op a
-
-        mkThm2 op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
-                                     eqF a x
-                                     eqF b y
-                                     return $ literal r `fpIsEqualObject` (a `op` b)
-
-        mkThm2C neq op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
-                                          eqF a x
-                                          eqF b y
-                                          return $ if isNaN x || isNaN y
-                                                   then (if neq then a `op` b else bnot (a `op` b))
-                                                   else literal r .== a `op` b
-
-        predicates :: (IEEEFloating a) => [(String, SBV a -> SBool, a -> Bool)]
-        predicates = [ ("fpIsNormal",       fpIsNormal,        fpIsNormalizedH)
-                     , ("fpIsSubnormal",    fpIsSubnormal,     isDenormalized)
-                     , ("fpIsZero",         fpIsZero,          (== 0))
-                     , ("fpIsInfinite",     fpIsInfinite,      isInfinite)
-                     , ("fpIsNaN",          fpIsNaN,           isNaN)
-                     , ("fpIsNegative",     fpIsNegative,      \x -> x < 0  ||      isNegativeZero x)
-                     , ("fpIsPositive",     fpIsPositive,      \x -> x >= 0 && not (isNegativeZero x))
-                     , ("fpIsNegativeZero", fpIsNegativeZero,  isNegativeZero)
-                     , ("fpIsPositiveZero", fpIsPositiveZero,  \x -> x == 0 && not (isNegativeZero x))
-                     , ("fpIsPoint",        fpIsPoint,         \x -> not (isNaN x || isInfinite x))
-                     ]
-
-genFPConverts :: [Test]
-genFPConverts = map 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]
-                 ++  [("toFP_Int64_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- i64s]
-                 ++  [("toFP_Word8_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w8s ]
-                 ++  [("toFP_Word16_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w16s]
-                 ++  [("toFP_Word32_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w32s]
-                 ++  [("toFP_Word64_ToFloat",   show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- w64s]
-                 ++  [("toFP_Float_ToFloat",    show x, mkThm1 (m toSFloat) x                           x  ) | x <- fs  ]
-                 ++  [("toFP_Double_ToFloat",   show x, mkThm1 (m toSFloat) x (                   fp2fp x )) | x <- ds  ]
-                 ++  [("toFP_Integer_ToFloat",  show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- iUBs]
-                 ++  [("toFP_Real_ToFloat",     show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- rs  ]
-
-                 ++  [("toFP_Int8_ToDouble",    show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i8s ]
-                 ++  [("toFP_Int16_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i16s]
-                 ++  [("toFP_Int32_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i32s]
-                 ++  [("toFP_Int64_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- i64s]
-                 ++  [("toFP_Word8_ToDouble",   show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w8s ]
-                 ++  [("toFP_Word16_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w16s]
-                 ++  [("toFP_Word32_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w32s]
-                 ++  [("toFP_Word64_ToDouble",  show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- w64s]
-                 ++  [("toFP_Float_ToDouble",   show x, mkThm1 (m toSDouble) x (                   fp2fp x )) | x <- fs  ]
-                 ++  [("toFP_Double_ToDouble",  show x, mkThm1 (m toSDouble) x                           x )  | x <- ds  ]
-                 ++  [("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]
-
-                 ++  [("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]
-
-                 ++  [("reinterp_Word32_Float",  show x, mkThmC sWord32AsSFloat  x (DB.wordToFloat  x)) | x <- w32s]
-                 ++  [("reinterp_Word64_Double", show x, mkThmC sWord64AsSDouble x (DB.wordToDouble x)) | x <- w64s]
-
-                 ++  [("reinterp_Float_Word32",  show x, mkThmP sFloatAsSWord32  x (DB.floatToWord x))  | x <- fs, not (isNaN x)] -- Not unique for NaN
-                 ++  [("reinterp_Double_Word64", show x, mkThmP sDoubleAsSWord64 x (DB.doubleToWord x)) | x <- ds, not (isNaN x)] -- Not unique for NaN
-
-        m f = f sRNE
-
-        tst1 (nm, x, t) = "fpConverts.arithmetic-" ++ nm ++ "." ++ x ~: assert t
-
-        eqF v val
-          | isNaN          val        = constrain $ fpIsNaN v
-          | isNegativeZero val        = constrain $ fpIsNegativeZero v
-          | val == 0                  = constrain $ fpIsPositiveZero v
-          | isInfinite val && val > 0 = constrain $ fpIsInfinite v &&& fpIsPositive v
-          | isInfinite val && val < 0 = constrain $ fpIsInfinite v &&& fpIsNegative v
-          | True                      = constrain $ v .== literal val
-
-        -- Quickly pick which solver to use. Currently z3 or mathSAT supports FP
-        fpProver :: SMTConfig
-        fpProver = z3 -- mathSAT
-
-        fpThm :: Provable a => a -> IO Bool
-        fpThm p = fromJust `fmap` isTheoremWith fpProver Nothing p
-
-        mkThmP op x r = fpThm $ do a <- free "x"
-                                   eqF a x
-                                   return $ literal r .== op a
-
-        mkThm1 op x r = fpThm $ do a <- free "x"
-                                   eqF a x
-                                   return $ literal r `fpIsEqualObject` op a
-
-        mkThmC op x r = fpThm $ do a <- free "x"
-                                   constrain $ a .== literal x
-                                   return $ literal r `fpIsEqualObject` op a
-
-        mkThmC' op x r = fpThm $ do a <- free "x"
-                                    eqF a x
-                                    return $ literal r .== op a
-
-genQRems :: [Test]
-genQRems = map mkTest $  [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w8s,  y <- w8s ]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w16s, y <- w16s]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w32s, y <- w32s]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w64s, y <- w64s]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i8s,  y <- i8s , noOverflow x y]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i16s, y <- i16s, noOverflow x y]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i32s, y <- i32s, noOverflow x y]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- i64s, y <- i64s, noOverflow x y]
-                      ++ [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- iUBs, y <- iUBs]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w8s,  y <- w8s ]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w16s, y <- w16s]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w32s, y <- w32s]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- w64s, y <- w64s]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i8s,  y <- i8s , noOverflow x y]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i16s, y <- i16s, noOverflow x y]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i32s, y <- i32s, noOverflow x y]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- i64s, y <- i64s, noOverflow x y]
-                      ++ [("quotRem", show x, show y, mkThm2 sQuotRem x y (x `quotRem'` y)) | x <- iUBs, y <- iUBs]
-  where divMod'  x y = if y == 0 then (0, x) else x `divMod`  y
-        quotRem' x y = if y == 0 then (0, x) else x `quotRem` y
-        mkTest (nm, x, y, t) = "genQRems.arithmetic-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: assert t
-        mkThm2 op x y (e1, e2) = isThm $ do [a, b] <- mapM free ["x", "y"]
-                                            constrain $ a .== literal x
-                                            constrain $ b .== literal y
-                                            return $ (literal e1, literal e2) .== a `op` b
-        -- Haskell's divMod and quotRem overflows if x == minBound and y == -1 for signed types; so avoid that case
-        noOverflow x y = not (x == minBound && y == -1)
-
--- Concrete test data
-xsSigned, xsUnsigned :: (Num a, Bounded a) => [a]
-xsUnsigned = [0, 1, maxBound - 1, maxBound]
-xsSigned   = xsUnsigned ++ [minBound, minBound + 1, -1]
-
-w8s :: [Word8]
-w8s = xsUnsigned
-
-w16s :: [Word16]
-w16s = xsUnsigned
-
-w32s :: [Word32]
-w32s = xsUnsigned
-
-w64s :: [Word64]
-w64s = xsUnsigned
-
-i8s :: [Int8]
-i8s = xsSigned
-
-i16s :: [Int16]
-i16s = xsSigned
-
-i32s :: [Int32]
-i32s = xsSigned
-
-i64s :: [Int64]
-i64s = xsSigned
-
-iUBs :: [Integer]
-iUBs = [-1000000] ++ [-1 .. 1] ++ [1000000]
-
-rs :: [AlgReal]
-rs = [fromRational (i % d) | i <- is, d <- dens]
- where is   = [-1000000] ++ [-1 .. 1] ++ [10000001]
-       dens = [5,100,1000000]
-
--- Admittedly paltry test-cases for float/double
-fs :: [Float]
-fs = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
-   where xs = [nan, infinity, 0, 0.5, 0.68302244, 0.5268265, 0.10283524, 5.8336496e-2, 1.0e-45]
-
-ds :: [Double]
-ds = xs ++ map (* (-1)) (filter (not . isNaN) xs) -- -nan is the same as nan
-  where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 5.0e-324]
-
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVUnitTest/TestSuite/Basics/BasicTests.hs b/SBVUnitTest/TestSuite/Basics/BasicTests.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/BasicTests.hs
+++ /dev/null
@@ -1,50 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.BasicTests
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Basics.BasicTests
------------------------------------------------------------------------------
-
-module TestSuite.Basics.BasicTests(testSuite) where
-
-import Examples.Basics.BasicTests
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "basic-0.1" ~: test0 f1 `showsAs` "5"
- , "basic-0.2" ~: test0 f2 `showsAs` "5"
- , "basic-0.3" ~: test0 f3 `showsAs` "25"
- , "basic-0.4" ~: test0 f4 `showsAs` "25"
- , "basic-0.5" ~: test0 f5 `showsAs` "4"
- , "basic-1.1" ~: test1 f1 `goldCheck` "basic-1_1.gold"
- , "basic-1.2" ~: test1 f2 `goldCheck` "basic-1_2.gold"
- , "basic-1.3" ~: test1 f3 `goldCheck` "basic-1_3.gold"
- , "basic-1.4" ~: test1 f4 `goldCheck` "basic-1_4.gold"
- , "basic-1.5" ~: test1 f5 `goldCheck` "basic-1_5.gold"
- , "basic-2.1" ~: test2 f1 `goldCheck` "basic-2_1.gold"
- , "basic-2.2" ~: test2 f2 `goldCheck` "basic-2_2.gold"
- , "basic-2.3" ~: test2 f3 `goldCheck` "basic-2_3.gold"
- , "basic-2.4" ~: test2 f4 `goldCheck` "basic-2_4.gold"
- , "basic-2.5" ~: test2 f5 `goldCheck` "basic-2_5.gold"
- , "basic-3.1" ~: test3 f1 `goldCheck` "basic-3_1.gold"
- , "basic-3.2" ~: test3 f2 `goldCheck` "basic-3_2.gold"
- , "basic-3.3" ~: test3 f3 `goldCheck` "basic-3_3.gold"
- , "basic-3.4" ~: test3 f4 `goldCheck` "basic-3_4.gold"
- , "basic-3.5" ~: test3 f5 `goldCheck` "basic-3_5.gold"
- , "basic-4.1" ~: test4 f1 `goldCheck` "basic-4_1.gold"
- , "basic-4.2" ~: test4 f2 `goldCheck` "basic-4_2.gold"
- , "basic-4.3" ~: test4 f3 `goldCheck` "basic-4_3.gold"
- , "basic-4.4" ~: test4 f4 `goldCheck` "basic-4_4.gold"
- , "basic-4.5" ~: test4 f5 `goldCheck` "basic-4_5.gold"
- , "basic-5.1" ~: test5 f1 `goldCheck` "basic-5_1.gold"
- , "basic-5.2" ~: test5 f2 `goldCheck` "basic-5_2.gold"
- , "basic-5.3" ~: test5 f3 `goldCheck` "basic-5_3.gold"
- , "basic-5.4" ~: test5 f4 `goldCheck` "basic-5_4.gold"
- , "basic-5.5" ~: test5 f5 `goldCheck` "basic-5_5.gold"
- ]
diff --git a/SBVUnitTest/TestSuite/Basics/Higher.hs b/SBVUnitTest/TestSuite/Basics/Higher.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/Higher.hs
+++ /dev/null
@@ -1,33 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.Higher
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Basics.Higher
------------------------------------------------------------------------------
-
-module TestSuite.Basics.Higher(testSuite) where
-
-import Data.SBV
-
-import Examples.Basics.Higher
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "higher-1"  ~: (f11 === f11)   `goldCheck` "higher-1.gold"
- , "higher-2"  ~: (f12 === f12)   `goldCheck` "higher-2.gold"
- , "higher-3"  ~: (f21 === f21)   `goldCheck` "higher-3.gold"
- , "higher-4"  ~: (f22 === f22)   `goldCheck` "higher-4.gold"
- , "higher-5"  ~: (f31 === f31)   `goldCheck` "higher-5.gold"
- , "higher-6"  ~: (f32 === f32)   `goldCheck` "higher-6.gold"
- , "higher-7"  ~: (f33 === f33)   `goldCheck` "higher-7.gold"
- , "higher-8"  ~: double          `goldCheck` "higher-8.gold"
- , "higher-9"  ~: onlyFailsFor128 `goldCheck` "higher-9.gold"
- ]
- where double          = (2*) === (\x -> x+(x::SWord8))
-       onlyFailsFor128 = (2*) === (\x -> ite (x .== 128) 5 (x+(x::SWord8)))
diff --git a/SBVUnitTest/TestSuite/Basics/Index.hs b/SBVUnitTest/TestSuite/Basics/Index.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/Index.hs
+++ /dev/null
@@ -1,20 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.Index
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Basics.Index
------------------------------------------------------------------------------
-
-module TestSuite.Basics.Index(testSuite) where
-
-import Examples.Basics.Index
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test $ zipWith tst [f x | f <- [test1, test2, test3], x <- [0..13]] [(0::Int)..]
-  where tst t i = "index-" ++ show i ~: t `ioShowsAs` "True"
diff --git a/SBVUnitTest/TestSuite/Basics/IteTest.hs b/SBVUnitTest/TestSuite/Basics/IteTest.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/IteTest.hs
+++ /dev/null
@@ -1,37 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.IteTest
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test various incarnations of ite/iteLazy/sBranch
------------------------------------------------------------------------------
-
-module TestSuite.Basics.IteTest(testSuite)  where
-
-import Data.SBV
-
-import SBVTest
-
-chk1 :: (SBool -> SBool -> SBool -> SBool) -> SWord8 -> SBool
-chk1 cond x = cond (x .== x) true undefined
-
-chk2 :: (SBool -> [SBool] -> [SBool] -> [SBool]) -> SWord8 -> SBool
-chk2 cond x = head (cond (x .== x) [true] [undefined])
-
-chk3 :: (SBool -> (SBool, SBool) -> (SBool, SBool)  -> (SBool, SBool)) -> SWord8 -> SBool
-chk3 cond x = fst (cond (x .== x) (true, undefined::SBool) (undefined, undefined))
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "ite-1"  ~: rs (chk1 ite) `goldCheck` "iteTest1.gold"
- , "ite-2"  ~: rs (chk2 ite) `goldCheck` "iteTest2.gold"
- , "ite-3"  ~: rs (chk3 ite) `goldCheck` "iteTest3.gold"
- , "ite-4"  ~: assert =<< isThm (chk1 iteLazy)
- , "ite-5"  ~: assert =<< isThm (chk2 iteLazy)
- , "ite-6"  ~: assert =<< isThm (chk3 iteLazy)
- ]
- where rs f = runSAT $ forAll ["x"] f
diff --git a/SBVUnitTest/TestSuite/Basics/ProofTests.hs b/SBVUnitTest/TestSuite/Basics/ProofTests.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/ProofTests.hs
+++ /dev/null
@@ -1,34 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.ProofTests
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Basics.ProofTests
------------------------------------------------------------------------------
-
-module TestSuite.Basics.ProofTests(testSuite)  where
-
-import Data.SBV
-
-import Examples.Basics.ProofTests
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "proofs-1"  ~: assert       =<< isThm f1eqf2
- , "proofs-2"  ~: assert . not =<< isThm f1eqf3
- , "proofs-3"  ~: assert       =<< isThm f3eqf4
- , "proofs-4"  ~: assert       =<< isThm f1Single
- , "proofs-5"  ~: assert       =<< isSat (f1 `xyEq` f2)
- , "proofs-6"  ~: assert       =<< isSat (f1 `xyEq` f3)
- , "proofs-7"  ~: assert . not =<< isSat (exists "x" >>= \x -> return (x .== x + (1 :: SWord16)))
- , "proofs-8"  ~: assert       =<< isSat (exists "x" >>= \x -> return (x :: SBool))
- , "proofs-9"  ~: assert       =<< isSat (exists "x" >>= \x -> return x :: Predicate)
- ]
- where func1 `xyEq` func2 = do x <- exists_
-                               y <- exists_
-                               return $ func1 x y .== func2 x (y :: SWord8)
diff --git a/SBVUnitTest/TestSuite/Basics/QRem.hs b/SBVUnitTest/TestSuite/Basics/QRem.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Basics/QRem.hs
+++ /dev/null
@@ -1,25 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Basics.QRem
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Basics.QRem
------------------------------------------------------------------------------
-
-module TestSuite.Basics.QRem(testSuite) where
-
-import Data.SBV
-
-import Examples.Basics.QRem
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "qremW8" ~: assert =<< isThm (qrem :: SWord8   -> SWord8   -> SBool)
- , "qremI8" ~: assert =<< isThm (qrem :: SInt8    -> SInt8    -> SBool)
- , "qremI"  ~: assert =<< isThm (qrem :: SInteger -> SInteger -> SBool)
- ]
diff --git a/SBVUnitTest/TestSuite/BitPrecise/BitTricks.hs b/SBVUnitTest/TestSuite/BitPrecise/BitTricks.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/BitPrecise/BitTricks.hs
+++ /dev/null
@@ -1,26 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.BitPrecise.BitTricks
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.BitPrecise.BitTricks
------------------------------------------------------------------------------
-
-module TestSuite.BitPrecise.BitTricks(testSuite) where
-
-import Data.SBV.Examples.BitPrecise.BitTricks
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "fast min"              ~: assert =<< isThm fastMinCorrect
- , "fast max"              ~: assert =<< isThm fastMaxCorrect
- , "opposite signs"        ~: assert =<< isThm oppositeSignsCorrect
- , "conditional set clear" ~: assert =<< isThm conditionalSetClearCorrect
- , "power of two"          ~: assert =<< isThm powerOfTwoCorrect
- ]
diff --git a/SBVUnitTest/TestSuite/BitPrecise/Legato.hs b/SBVUnitTest/TestSuite/BitPrecise/Legato.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/BitPrecise/Legato.hs
+++ /dev/null
@@ -1,46 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.BitPrecise.Legato
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.BitPrecise.Legato
------------------------------------------------------------------------------
-
-module TestSuite.BitPrecise.Legato(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.BitPrecise.Legato
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "legato-1" ~: legatoPgm `goldCheck` "legato.gold"
- , "legato-2" ~: legatoC `goldCheck` "legato_c.gold"
- ]
- where legatoPgm = runSAT $ do
-                       mem     <- newArray "mem" Nothing
-                       addrX   <- free "addrX"
-                       x       <- free "x"
-                       addrY   <- free "addrY"
-                       y       <- free "y"
-                       addrLow <- free "addrLow"
-                       regX    <- free "regX"
-                       regA    <- free "regA"
-                       memVals <- free "memVals"
-                       flagC   <- free "flagC"
-                       flagZ   <- free "flagZ"
-                       output $ legatoIsCorrect mem (addrX, x) (addrY, y) addrLow (regX, regA, memVals, flagC, flagZ)
-       legatoC = compileToC' "legatoMult" $ do
-                    cgSetDriverValues [87, 92]
-                    cgPerformRTCs True
-                    x <- cgInput "x"
-                    y <- cgInput "y"
-                    let (hi, lo) = runLegato (0, x) (1, y) 2 (initMachine (mkSFunArray (const 0)) (0, 0, 0, false, false))
-                    cgOutput "hi" hi
-                    cgOutput "lo" lo
diff --git a/SBVUnitTest/TestSuite/BitPrecise/MergeSort.hs b/SBVUnitTest/TestSuite/BitPrecise/MergeSort.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/BitPrecise/MergeSort.hs
+++ /dev/null
@@ -1,28 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.BitPrecise.MergeSort
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.BitPrecise.MergeSort
------------------------------------------------------------------------------
-
-module TestSuite.BitPrecise.MergeSort where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.BitPrecise.MergeSort
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "mergeSort" ~: mergeC `goldCheck` "merge.gold"
- ]
- where mergeC = compileToC' "merge" $ do
-                   cgSetDriverValues [10, 6, 4, 82, 71]
-                   xs <- cgInputArr 5 "xs"
-                   cgOutputArr "ys" (mergeSort xs)
diff --git a/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs b/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs
+++ /dev/null
@@ -1,24 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.BitPrecise.PrefixSum
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.PrefixSum.PrefixSum
------------------------------------------------------------------------------
-
-module TestSuite.BitPrecise.PrefixSum(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.BitPrecise.PrefixSum
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-    "prefixSum1" ~: assert =<< isThm (flIsCorrect  8 (0, (+)))
-  , "prefixSum2" ~: assert =<< isThm (flIsCorrect 16 (0, smax))
-  ]
diff --git a/SBVUnitTest/TestSuite/CRC/CCITT.hs b/SBVUnitTest/TestSuite/CRC/CCITT.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CRC/CCITT.hs
+++ /dev/null
@@ -1,24 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CRC.CCITT
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.CRC.CCITT
------------------------------------------------------------------------------
-
-module TestSuite.CRC.CCITT(testSuite) where
-
-import Data.SBV
-
-import Examples.CRC.CCITT
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "ccitt" ~: crcPgm `goldCheck` "ccitt.gold"
- ]
- where crcPgm = runSAT $ forAll_ crcGood >>= output
diff --git a/SBVUnitTest/TestSuite/CRC/CCITT_Unidir.hs b/SBVUnitTest/TestSuite/CRC/CCITT_Unidir.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CRC/CCITT_Unidir.hs
+++ /dev/null
@@ -1,22 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CRC.CCITT_Unidir
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.CRC.CCITT_Unidir
------------------------------------------------------------------------------
-
-module TestSuite.CRC.CCITT_Unidir(testSuite) where
-
-import Examples.CRC.CCITT_Unidir
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "ccitHDis3" ~: assert       =<< isThm (crcUniGood 3)
- , "ccitHDis4" ~: assert . not =<< isThm (crcUniGood 4)
- ]
diff --git a/SBVUnitTest/TestSuite/CRC/GenPoly.hs b/SBVUnitTest/TestSuite/CRC/GenPoly.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CRC/GenPoly.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CRC.GenPoly
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.CRC.GenPoly
------------------------------------------------------------------------------
-
-module TestSuite.CRC.GenPoly(testSuite) where
-
-import Data.SBV
-
-import Examples.CRC.GenPoly
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "crcGood" ~: assert       =<< isSat crcGoodE
- , "crcGood" ~: assert . not =<< isThm (crcGood 3 12)
- ]
- where crcGoodE = do x1 <- exists_
-                     x2 <- exists_
-                     y1 <- exists_
-                     y2 <- exists_
-                     return (crcGood 3 0 (x1,x2) (y1,y2))
diff --git a/SBVUnitTest/TestSuite/CRC/Parity.hs b/SBVUnitTest/TestSuite/CRC/Parity.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CRC/Parity.hs
+++ /dev/null
@@ -1,21 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CRC.Parity
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.CRC.Parity
------------------------------------------------------------------------------
-
-module TestSuite.CRC.Parity(testSuite) where
-
-import Examples.CRC.Parity
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "parity" ~: assert =<< isThm parityOK
- ]
diff --git a/SBVUnitTest/TestSuite/CRC/USB5.hs b/SBVUnitTest/TestSuite/CRC/USB5.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CRC/USB5.hs
+++ /dev/null
@@ -1,21 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CRC.USB5
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.CRC.USB5
------------------------------------------------------------------------------
-
-module TestSuite.CRC.USB5(testSuite) where
-
-import Examples.CRC.USB5
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "usbGood" ~: assert =<< isThm usbGood
- ]
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/AddSub.hs b/SBVUnitTest/TestSuite/CodeGeneration/AddSub.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/AddSub.hs
+++ /dev/null
@@ -1,32 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.AddSub
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.AddSub
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.AddSub(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.AddSub
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "addSub" ~: code `goldCheck` "addSub.gold"
- ]
- where code = compileToC' "addSub" $ do
-                cgSetDriverValues [76, 92]
-                cgPerformRTCs True
-                x <- cgInput "x"
-                y <- cgInput "y"
-                let (s, d) = addSub x y
-                cgOutput "sum" s
-                cgOutput "dif" d
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/CRC_USB5.hs b/SBVUnitTest/TestSuite/CodeGeneration/CRC_USB5.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/CRC_USB5.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.CRC_USB5
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.CRC_USB5
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.CRC_USB5(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.CRC_USB5
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "crcUSB5-1" ~: genC crcUSB  `goldCheck` "crcUSB5_1.gold"
- , "crcUSB5-2" ~: genC crcUSB' `goldCheck` "crcUSB5_2.gold"
- ]
- where genC f = compileToC' "crcUSB5" $ do
-                   cgSetDriverValues [0xFEDC]
-                   msg <- cgInput "msg"
-                   cgReturn $ f msg
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/CgTests.hs b/SBVUnitTest/TestSuite/CodeGeneration/CgTests.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/CgTests.hs
+++ /dev/null
@@ -1,42 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.CgTests
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for code-generation features
------------------------------------------------------------------------------
-
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module TestSuite.CodeGeneration.CgTests(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "selChecked"   ~: genSelect True  "selChecked"   `goldCheck` "selChecked.gold"
- , "selUnchecked" ~: genSelect False "selUnChecked" `goldCheck` "selUnchecked.gold"
- , "codegen1"     ~: foo `goldCheck` "codeGen1.gold"
- ]
- where genSelect b n = compileToC' n $ do
-                         cgSetDriverValues [65]
-                         cgPerformRTCs b
-                         let sel :: SWord8 -> SWord8
-                             sel x = select [1, x+2] 3 x
-                         x <- cgInput "x"
-                         cgReturn $ sel x
-       foo = compileToC' "foo" $ do
-                        cgSetDriverValues $ repeat 0
-                        (x::SInt16)    <- cgInput "x"
-                        (ys::[SInt64]) <- cgInputArr 45 "xArr"
-                        cgOutput "z" (5 :: SWord16)
-                        cgOutputArr "zArr" (replicate 7 (x+1))
-                        cgOutputArr "yArr" ys
-                        cgReturn (x*2)
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/Fibonacci.hs b/SBVUnitTest/TestSuite/CodeGeneration/Fibonacci.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/Fibonacci.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.Fibonacci
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.Fibonacci
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.Fibonacci(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.Fibonacci
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "fib1" ~: tst [12] "fib1" (fib1 64) `goldCheck` "fib1.gold"
- , "fib2" ~: tst [20] "fib2" (fib2 64) `goldCheck` "fib2.gold"
- ]
- where tst vs nm f = compileToC' nm $ do cgPerformRTCs True
-                                         cgSetDriverValues vs
-                                         n <- cgInput "n"
-                                         cgReturn $ f n
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs b/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs
+++ /dev/null
@@ -1,164 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.Floats
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test-suite for generating floating-point related C code
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.Floats(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "floats_cgen" ~: code `goldCheck` "floats_cgen.gold"
- ]
- where code  = compileToCLib' "floatCodeGen" cases
-
-       setup = do cgSRealType CgLongDouble
-                  cgIntegerSize 64
-                  cgSetDriverValues [42, 43, 44]
-
-       test1 nm f = (nm, do setup
-                            a <- cgInput "a"
-                            cgReturn (f a))
-
-       test2 nm f = (nm, do setup
-                            a <- cgInput "a"
-                            b <- cgInput "b"
-                            cgReturn (f a b))
-
-       test3 nm f = (nm, do setup
-                            a <- cgInput "a"
-                            b <- cgInput "b"
-                            c <- cgInput "c"
-                            cgReturn (f a b c))
-
-       cases = [
-            test1 "toFP_Int8_ToFloat"       (toSFloat sRoundNearestTiesToEven  :: SInt8    -> SFloat)
-          , test1 "toFP_Int16_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt16   -> SFloat)
-          , test1 "toFP_Int32_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt32   -> SFloat)
-          , test1 "toFP_Int64_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SInt64   -> SFloat)
-          , test1 "toFP_Word8_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SWord8   -> SFloat)
-          , test1 "toFP_Word16_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord16  -> SFloat)
-          , test1 "toFP_Word32_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord32  -> SFloat)
-          , test1 "toFP_Word64_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SWord64  -> SFloat)
-          , test1 "toFP_Float_ToFloat"      (toSFloat sRoundNearestTiesToEven  :: SFloat   -> SFloat)
-          , test1 "toFP_Double_ToFloat"     (toSFloat sRoundNearestTiesToEven  :: SDouble  -> SFloat)
-          , test1 "toFP_Integer_ToFloat"    (toSFloat sRoundNearestTiesToEven  :: SInteger -> SFloat)
-          , test1 "toFP_Real_ToFloat"       (toSFloat sRoundNearestTiesToEven  :: SReal    -> SFloat)
-
-          , test1 "toFP_Int8_ToDouble"      (toSDouble sRoundNearestTiesToEven :: SInt8    -> SDouble)
-          , test1 "toFP_Int16_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt16   -> SDouble)
-          , test1 "toFP_Int32_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt32   -> SDouble)
-          , test1 "toFP_Int64_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SInt64   -> SDouble)
-          , test1 "toFP_Word8_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SWord8   -> SDouble)
-          , test1 "toFP_Word16_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord16  -> SDouble)
-          , test1 "toFP_Word32_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord32  -> SDouble)
-          , test1 "toFP_Word64_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SWord64  -> SDouble)
-          , test1 "toFP_Float_ToDouble"     (toSDouble sRoundNearestTiesToEven :: SFloat   -> SDouble)
-          , test1 "toFP_Double_ToDouble"    (toSDouble sRoundNearestTiesToEven :: SDouble  -> SDouble)
-          , test1 "toFP_Integer_ToDouble"   (toSDouble sRoundNearestTiesToEven :: SInteger -> SDouble)
-          , test1 "toFP_Real_ToDouble"      (toSDouble sRoundNearestTiesToEven :: SReal    -> SDouble)
-
-          , test1 "fromFP_Float_ToInt8"     (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt8)
-          , test1 "fromFP_Float_ToInt16"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt16)
-          , test1 "fromFP_Float_ToInt32"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt32)
-          , test1 "fromFP_Float_ToInt64"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInt64)
-          , test1 "fromFP_Float_ToWord8"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord8)
-          , test1 "fromFP_Float_ToWord16"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord16)
-          , test1 "fromFP_Float_ToWord32"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord32)
-          , test1 "fromFP_Float_ToWord64"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SWord64)
-          , test1 "fromFP_Float_ToFloat"    (fromSFloat sRoundNearestTiesToEven :: SFloat -> SFloat)
-          , test1 "fromFP_Float_ToDouble"   (fromSFloat sRoundNearestTiesToEven :: SFloat -> SDouble)
-          , test1 "fromFP_Float_ToInteger"  (fromSFloat sRoundNearestTiesToEven :: SFloat -> SInteger)
-          , test1 "fromFP_Float_ToReal"     (fromSFloat sRoundNearestTiesToEven :: SFloat -> SReal)
-
-          , test1 "fromFP_DoubleTo_Int8"    (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt8)
-          , test1 "fromFP_DoubleTo_Int16"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt16)
-          , test1 "fromFP_DoubleTo_Int32"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt32)
-          , test1 "fromFP_DoubleTo_Int64"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInt64)
-          , test1 "fromFP_DoubleTo_Word8"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord8)
-          , test1 "fromFP_DoubleTo_Word16"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord16)
-          , test1 "fromFP_DoubleTo_Word32"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord32)
-          , test1 "fromFP_DoubleTo_Word64"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SWord64)
-          , test1 "fromFP_DoubleTo_Float"   (fromSDouble sRoundNearestTiesToEven :: SDouble -> SFloat)
-          , test1 "fromFP_DoubleTo_Double"  (fromSDouble sRoundNearestTiesToEven :: SDouble -> SDouble)
-          , test1 "fromFP_DoubleTo_Integer" (fromSDouble sRoundNearestTiesToEven :: SDouble -> SInteger)
-          , test1 "fromFP_DoubleTo_Real"    (fromSDouble sRoundNearestTiesToEven :: SDouble -> SReal)
-
-          , test1 "fromFP_SWord32_SFloat"   (sWord32AsSFloat  :: SWord32 -> SFloat)
-          , test1 "fromFP_SWord64_SDouble"  (sWord64AsSDouble :: SWord64 -> SDouble)
-          , test1 "fromFP_SFloat_SWord32"   (sFloatAsSWord32  :: SFloat  -> SWord32)
-          , test1 "fromFP_SDouble_SWord64"  (sDoubleAsSWord64 :: SDouble -> SWord64)
-
-          , test1 "f_FP_Abs"                (abs    :: SFloat -> SFloat)
-          , test1 "d_FP_Abs"                (abs    :: SDouble -> SDouble)
-
-          , test1 "f_FP_Neg"                (negate :: SFloat -> SFloat)
-          , test1 "d_FP_Neg"                (negate :: SDouble -> SDouble)
-
-          , test2 "f_FP_Add"                (fpAdd  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Add"                (fpAdd  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
-
-          , test2 "f_FP_Sub"                (fpSub  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Sub"                (fpSub  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
-
-          , test2 "f_FP_Mul"                (fpMul  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Mul"                (fpMul  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
-
-          , test2 "f_FP_Div"                (fpDiv  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Div"                (fpDiv  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble)
-
-          , test3 "f_FP_FMA"                (fpFMA  sRoundNearestTiesToEven :: SFloat  -> SFloat  -> SFloat  -> SFloat)
-          , test3 "d_FP_FMA"                (fpFMA  sRoundNearestTiesToEven :: SDouble -> SDouble -> SDouble -> SDouble)
-
-          , test1 "f_FP_Sqrt"               (fpSqrt sRoundNearestTiesToEven :: SFloat  -> SFloat)
-          , test1 "d_FP_Sqrt"               (fpSqrt sRoundNearestTiesToEven :: SDouble -> SDouble)
-
-          , test2 "f_FP_Rem"                (fpRem  :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Rem"                (fpRem  :: SDouble -> SDouble -> SDouble)
-
-          , test1 "f_FP_RoundToIntegral"    (fpRoundToIntegral sRoundNearestTiesToEven :: SFloat  -> SFloat)
-          , test1 "d_FP_RoundToIntegral"    (fpRoundToIntegral sRoundNearestTiesToEven :: SDouble -> SDouble)
-
-          , test2 "f_FP_Min"                (fpMin :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Min"                (fpMin :: SDouble -> SDouble -> SDouble)
-
-          , test2 "f_FP_Max"                (fpMax :: SFloat  -> SFloat  -> SFloat)
-          , test2 "d_FP_Max"                (fpMax :: SDouble -> SDouble -> SDouble)
-
-          , test2 "f_FP_IsEqualObject"      (fpIsEqualObject :: SFloat  -> SFloat  -> SBool)
-          , test2 "d_FP_IsEqualObject"      (fpIsEqualObject :: SDouble -> SDouble -> SBool)
-
-          , test1 "f_FP_IsNormal"           (fpIsNormal :: SFloat  -> SBool)
-          , test1 "d_FP_IsNormal"           (fpIsNormal :: SDouble -> SBool)
-
-          , test1 "f_FP_IsZero"             (fpIsZero :: SFloat  -> SBool)
-          , test1 "d_FP_IsZero"             (fpIsZero :: SDouble -> SBool)
-
-          , test1 "f_FP_IsSubnormal"        (fpIsSubnormal :: SFloat  -> SBool)
-          , test1 "d_FP_IsSubnormal"        (fpIsSubnormal :: SDouble -> SBool)
-
-          , test1 "f_FP_IsInfinite"         (fpIsInfinite :: SFloat  -> SBool)
-          , test1 "d_FP_IsInfinite"         (fpIsInfinite :: SDouble -> SBool)
-
-          , test1 "f_FP_IsNaN"              (fpIsNaN :: SFloat  -> SBool)
-          , test1 "d_FP_IsNaN"              (fpIsNaN :: SDouble -> SBool)
-
-          , test1 "f_FP_IsNegative"         (fpIsNegative :: SFloat  -> SBool)
-          , test1 "d_FP_IsNegative"         (fpIsNegative :: SDouble -> SBool)
-
-          , test1 "f_FP_IsPositive"         (fpIsPositive :: SFloat  -> SBool)
-          , test1 "d_FP_IsPositive"         (fpIsPositive :: SDouble -> SBool)
-          ]
-
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/GCD.hs b/SBVUnitTest/TestSuite/CodeGeneration/GCD.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/GCD.hs
+++ /dev/null
@@ -1,29 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.GCD
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.GCD
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.GCD(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.GCD
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "gcd" ~: gcdC `goldCheck` "gcd.gold"
- ]
- where gcdC = compileToC' "sgcd" $ do
-                cgSetDriverValues [55,154]
-                x <- cgInput "x"
-                y <- cgInput "y"
-                cgReturn $ sgcd x y
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/PopulationCount.hs b/SBVUnitTest/TestSuite/CodeGeneration/PopulationCount.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/PopulationCount.hs
+++ /dev/null
@@ -1,30 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.PopulationCount
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.PopulationCount
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.PopulationCount(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.PopulationCount
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "popCount-1" ~: genC False `goldCheck` "popCount1.gold"
- , "popCount-2" ~: genC True  `goldCheck` "popCount2.gold"
- ]
- where genC b = compileToC' "popCount" $ do
-                  cgSetDriverValues [0x0123456789ABCDEF]
-                  cgPerformRTCs b
-                  x <- cgInput "x"
-                  cgReturn $ popCountFast x
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/Uninterpreted.hs b/SBVUnitTest/TestSuite/CodeGeneration/Uninterpreted.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/CodeGeneration/Uninterpreted.hs
+++ /dev/null
@@ -1,28 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.CodeGeneration.Uninterpreted
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.CodeGeneration.Uninterpreted
------------------------------------------------------------------------------
-
-module TestSuite.CodeGeneration.Uninterpreted(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.CodeGeneration.Uninterpreted
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "cgUninterpret" ~: genC `goldCheck` "cgUninterpret.gold"
- ]
- where genC = compileToC' "tstShiftLeft" $ do
-                  cgSetDriverValues [1, 2, 3]
-                  [x, y, z] <- cgInputArr 3 "vs"
-                  cgReturn $ tstShiftLeft x y z
diff --git a/SBVUnitTest/TestSuite/Crypto/AES.hs b/SBVUnitTest/TestSuite/Crypto/AES.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Crypto/AES.hs
+++ /dev/null
@@ -1,35 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Crypto.AES
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Crypto.AES
------------------------------------------------------------------------------
-
-module TestSuite.Crypto.AES(testSuite) where
-
-import Data.SBV
-import Data.SBV.Internals
-import Data.SBV.Examples.Crypto.AES
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "aes128Enc" ~: compileToC'    "aes128Enc" (aes128EncDec True)  `goldCheck` "aes128Enc.gold"
- , "aes128Dec" ~: compileToC'    "aes128Dec" (aes128EncDec False) `goldCheck` "aes128Dec.gold"
- , "aes128Lib" ~: compileToCLib' "aes128Lib" aes128Comps          `goldCheck` "aes128Lib.gold"
- ]
- where aes128EncDec d = do pt  <- cgInputArr 4 "pt"
-                           key <- cgInputArr 4 "key"
-                           cgSetDriverValues $ repeat 0
-                           let (encKs, decKs) = aesKeySchedule key
-                               res | d    = aesEncrypt pt encKs
-                                   | True = aesDecrypt pt decKs
-                           cgOutputArr "ct" res
-       aes128Comps = [(f, setVals c) | (f, c) <- aes128LibComponents]
-       setVals c = cgSetDriverValues (repeat 0) >> c
diff --git a/SBVUnitTest/TestSuite/Crypto/RC4.hs b/SBVUnitTest/TestSuite/Crypto/RC4.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Crypto/RC4.hs
+++ /dev/null
@@ -1,24 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Crypto.RC4
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Crypto.RC4
------------------------------------------------------------------------------
-
-module TestSuite.Crypto.RC4(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Crypto.RC4
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "rc4swap" ~: assert =<< isThm readWrite
- ]
- where readWrite i j = readSTree (writeSTree initS i j) i .== j
diff --git a/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs b/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs
+++ /dev/null
@@ -1,32 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Existentials.CRCPolynomial
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Existentials.CRCPolynomial
------------------------------------------------------------------------------
-
-module TestSuite.Existentials.CRCPolynomial(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Existentials.CRCPolynomial
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "crcPolyExist" ~: pgm `goldCheck` "crcPolyExist.gold"
- ]
- where pgm = runSAT $ do
-                p <- exists "poly"
-                s <- do sh <- forall "sh"
-                        sl <- forall "sl"
-                        return (sh, sl)
-                r <- do rh <- forall "rh"
-                        rl <- forall "rl"
-                        return (rh, rl)
-                output $ sTestBit p 0 &&& crcGood 4 p s r
diff --git a/SBVUnitTest/TestSuite/Polynomials/Polynomials.hs b/SBVUnitTest/TestSuite/Polynomials/Polynomials.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Polynomials/Polynomials.hs
+++ /dev/null
@@ -1,24 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Polynomials.Polynomials
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Polynomials.Polynomials
------------------------------------------------------------------------------
-
-module TestSuite.Polynomials.Polynomials(testSuite) where
-
-import Data.SBV.Examples.Polynomials.Polynomials
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "polynomial-1" ~: assert =<< isThm multUnit
- , "polynomial-2" ~: assert =<< isThm multComm
- , "polynomial-3" ~: assert =<< isThm polyDivMod
- ]
diff --git a/SBVUnitTest/TestSuite/Puzzles/Coins.hs b/SBVUnitTest/TestSuite/Puzzles/Coins.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/Coins.hs
+++ /dev/null
@@ -1,27 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.Coins
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.Coins
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.Coins(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.Coins
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "coins" ~: coinsPgm `goldCheck` "coins.gold"
- ]
- where coinsPgm = runSAT $ do cs <- mapM mkCoin [1..6]
-                              mapM_ constrain [c s | s <- combinations cs, length s >= 2, c <- [c1, c2, c3, c4, c5, c6]]
-                              constrain $ bAnd $ zipWith (.>=) cs (tail cs)
-                              output $ sum cs .== 115
diff --git a/SBVUnitTest/TestSuite/Puzzles/Counts.hs b/SBVUnitTest/TestSuite/Puzzles/Counts.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/Counts.hs
+++ /dev/null
@@ -1,25 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.Counts
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.Counts
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.Counts(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.Counts
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "counts" ~: countPgm `goldCheck` "counts.gold"
- ]
- where countPgm = runSAT $ forAll_ puzzle' >>= output
-       puzzle' d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 = puzzle [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9]
diff --git a/SBVUnitTest/TestSuite/Puzzles/DogCatMouse.hs b/SBVUnitTest/TestSuite/Puzzles/DogCatMouse.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/DogCatMouse.hs
+++ /dev/null
@@ -1,30 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.DogCatMouse
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.DogCatMouse
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.DogCatMouse(testSuite) where
-
-import Data.SBV
--- import Data.SBV.Examples.Puzzles.DogCatMouse   -- everything defined here
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "dog_cat_mouse" ~: allSat p `goldCheck` "dogCatMouse.gold"
- ]
- where p = do [dog, cat, mouse] <- sIntegers ["dog", "cat", "mouse"]
-              solve [ dog   .>= 1                                   -- at least one dog
-                    , cat   .>= 1                                   -- at least one cat
-                    , mouse .>= 1                                   -- at least one mouse
-                    , dog + cat + mouse .== 100                     -- buy precisely 100 animals
-                    , 1500 * dog + 100 * cat + 25 * mouse .== 10000 -- spend exactly 100 dollars (use cents since we don't have fractions)
-                    ]
diff --git a/SBVUnitTest/TestSuite/Puzzles/Euler185.hs b/SBVUnitTest/TestSuite/Puzzles/Euler185.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/Euler185.hs
+++ /dev/null
@@ -1,23 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.Euler185
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.Euler185
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.Euler185(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.Euler185
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "euler185" ~: allSat euler185 `goldCheck` "euler185.gold"
- ]
diff --git a/SBVUnitTest/TestSuite/Puzzles/MagicSquare.hs b/SBVUnitTest/TestSuite/Puzzles/MagicSquare.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/MagicSquare.hs
+++ /dev/null
@@ -1,25 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.MagicSquare
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.MagicSquare
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.MagicSquare(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.MagicSquare
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "magic 2" ~: assert . not =<< isSat (mkMagic 2)
- , "magic 3" ~: assert       =<< isSat (mkMagic 3)
- ]
- where mkMagic n = (isMagic . chunk n) `fmap` mkExistVars (n*n)
diff --git a/SBVUnitTest/TestSuite/Puzzles/NQueens.hs b/SBVUnitTest/TestSuite/Puzzles/NQueens.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/NQueens.hs
+++ /dev/null
@@ -1,32 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.NQueens
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.NQueens
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.NQueens(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.NQueens
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   -- number of *distinct* solutions is given in http://en.wikipedia.org/wiki/Eight_queens_puzzle
-   "nQueens 1" ~: assert $ (==  1) `fmap` numberOfModels (mkQueens 1)
- , "nQueens 2" ~: assert $ (==  0) `fmap` numberOfModels (mkQueens 2)
- , "nQueens 3" ~: assert $ (==  0) `fmap` numberOfModels (mkQueens 3)
- , "nQueens 4" ~: assert $ (==  2) `fmap` numberOfModels (mkQueens 4)
- , "nQueens 5" ~: assert $ (== 10) `fmap` numberOfModels (mkQueens 5)
- , "nQueens 6" ~: assert $ (==  4) `fmap` numberOfModels (mkQueens 6)
- , "nQueens 7" ~: assert $ (== 40) `fmap` numberOfModels (mkQueens 7)
- , "nQueens 8" ~: assert $ (== 92) `fmap` numberOfModels (mkQueens 8)
- ]
- where mkQueens n = isValid n `fmap` mkExistVars n
diff --git a/SBVUnitTest/TestSuite/Puzzles/PowerSet.hs b/SBVUnitTest/TestSuite/Puzzles/PowerSet.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/PowerSet.hs
+++ /dev/null
@@ -1,24 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.PowerSet
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Puzzles.PowerSet
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.PowerSet(testSuite) where
-
-import Data.SBV
-
-import Examples.Puzzles.PowerSet
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [ "powerSet " ++ show i ~: assert (pSet i) | i <- [0 .. 7] ]
- where pSet :: Int -> IO Bool
-       pSet n = do cnt <- numberOfModels $ genPowerSet `fmap` mkExistVars n
-                   return (cnt == 2^n)
diff --git a/SBVUnitTest/TestSuite/Puzzles/Sudoku.hs b/SBVUnitTest/TestSuite/Puzzles/Sudoku.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/Sudoku.hs
+++ /dev/null
@@ -1,25 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.Sudoku
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.Sudoku
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.Sudoku(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.Sudoku
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-  "sudoku " ++ show n ~: assert (checkPuzzle s)
-     | (n, s) <- zip [(0::Int)..] [puzzle0, puzzle1, puzzle2, puzzle3, puzzle4, puzzle5, puzzle6]
- ]
- where checkPuzzle (i, f) = isSat $ (valid . f) `fmap` mkExistVars i
diff --git a/SBVUnitTest/TestSuite/Puzzles/Temperature.hs b/SBVUnitTest/TestSuite/Puzzles/Temperature.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/Temperature.hs
+++ /dev/null
@@ -1,23 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.Temperature
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Puzzles.Temperature
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.Temperature(testSuite) where
-
-import Data.SBV
-
-import Examples.Puzzles.Temperature
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-  "temperature" ~: allSat (revOf `fmap` exists_) `goldCheck` "temperature.gold"
- ]
diff --git a/SBVUnitTest/TestSuite/Puzzles/U2Bridge.hs b/SBVUnitTest/TestSuite/Puzzles/U2Bridge.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Puzzles/U2Bridge.hs
+++ /dev/null
@@ -1,31 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Puzzles.U2Bridge
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Puzzles.U2Bridge
------------------------------------------------------------------------------
-
-module TestSuite.Puzzles.U2Bridge(testSuite) where
-
-import Data.SBV
-import Data.SBV.Examples.Puzzles.U2Bridge
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "U2Bridge-1" ~: assert $ (0 ==) `fmap` count 1
- , "U2Bridge-2" ~: assert $ (0 ==) `fmap` count 2
- , "U2Bridge-3" ~: assert $ (0 ==) `fmap` count 3
- , "U2Bridge-4" ~: assert $ (0 ==) `fmap` count 4
- , "U2Bridge-5" ~: slv 5 `goldCheck` "U2Bridge.gold"
- , "U2Bridge-6" ~: assert $ (0 ==) `fmap` count 6
- ]
- 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   = sat $ isValid `fmap` mapM (const act) [1..(n::Int)]
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs b/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs
+++ /dev/null
@@ -1,31 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Uninterpreted.AUF
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Data.SBV.Examples.Uninterpreted.AUF
------------------------------------------------------------------------------
-
-module TestSuite.Uninterpreted.AUF where
-
-import Data.SBV
-import Data.SBV.Examples.Uninterpreted.AUF
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
-   "auf-0" ~: assert =<< isThm (newArray "a" Nothing >>= \a -> free "x" >>= \x -> free "y" >>= \y -> free "i" >>= \i -> return (thm1 x y a i))
- , "auf-1" ~: assert =<< isThm (newArray "b" Nothing >>= \b -> free "x" >>= \x -> free "y" >>= \y                    -> return (thm2 x y b))
- , "auf-2" ~: pgm `goldCheck` "auf-1.gold"
- ]
- where pgm = runSAT $ do
-                x <- free "x"
-                y <- free "y"
-                a <- newArray "a" Nothing
-                i <- free "initVal"
-                output $ thm1 x y a i
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs b/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs
+++ /dev/null
@@ -1,49 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Uninterpreted.Axioms
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for basic axioms and uninterpreted functions
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveAnyClass     #-}
-{-# LANGUAGE DeriveDataTypeable #-}
-
-module TestSuite.Uninterpreted.Axioms(testSuite) where
-
-import Data.SBV
-import SBVTest
-import Data.Generics
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-  "unint-axioms" ~: assert =<< isThm p0
- ]
-
--- Example provided by Thomas DuBuisson:
-newtype Bitstring = Bitstring () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
-type SBitstring = SBV Bitstring
-
-a :: SBitstring -> SBool
-a = uninterpret "a"
-
-e :: SBitstring -> SBitstring -> SBitstring
-e = uninterpret "e"
-
-axE :: [String]
-axE = [ "(assert (forall ((p Bitstring) (k Bitstring))"
-      , "         (=> (and (a k) (a p)) (a (e k p)))))"
-      ]
-
-p0 :: Symbolic SBool
-p0 = do
-    p <- free "p" :: Symbolic SBitstring
-    k <- free "k" :: Symbolic SBitstring
-    addAxiom "axE" axE
-    constrain $ a p
-    constrain $ a k
-    return $ a (e k p)
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Function.hs b/SBVUnitTest/TestSuite/Uninterpreted/Function.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Uninterpreted/Function.hs
+++ /dev/null
@@ -1,22 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Uninterpreted.Function
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Testsuite for Data.SBV.Examples.Uninterpreted.Function
------------------------------------------------------------------------------
-
-module TestSuite.Uninterpreted.Function where
-
-import Data.SBV.Examples.Uninterpreted.Function
-
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "aufunc-0" ~: assert =<< isThm thmGood
- ]
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs b/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs
+++ /dev/null
@@ -1,45 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  TestSuite.Uninterpreted.Sort
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for uninterpreted sorts
------------------------------------------------------------------------------
-
-{-# LANGUAGE DeriveDataTypeable  #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module TestSuite.Uninterpreted.Sort where
-
-import Data.SBV
-import SBVTest
-import Data.Generics
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-  "unint-sort" ~: assert . (==4) . length . (extractModels :: AllSatResult -> [L]) =<< allSat p0
- ]
-
-data L = Nil | Cons Int L deriving (Eq, Ord, Data, Read, Show)
-instance SymWord L
-instance HasKind L
-instance SatModel L where
-  parseCWs = undefined -- make GHC shut up about the missing method, we won't actually call it
-
-type SList = SBV L
-
-len :: SList -> SInteger
-len = uninterpret "len"
-
-p0 :: Symbolic SBool
-p0 = do
-    [l, l0, l1] <- symbolics ["l", "l0", "l1"]
-    constrain $ len l0 .== 0
-    constrain $ len l1 .== 1
-    x :: SInteger <- symbolic "x"
-    constrain $ x .== 0 ||| x.== 1
-    return $ l .== l0 ||| l .== l1
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Uninterpreted.hs b/SBVUnitTest/TestSuite/Uninterpreted/Uninterpreted.hs
deleted file mode 100644
--- a/SBVUnitTest/TestSuite/Uninterpreted/Uninterpreted.hs
+++ /dev/null
@@ -1,23 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Examples.TestSuite.Uninterpreted
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Test suite for Examples.Uninterpreted.Uninterpreted
------------------------------------------------------------------------------
-
-module TestSuite.Uninterpreted.Uninterpreted where
-
-import Examples.Uninterpreted.Uninterpreted
-import SBVTest
-
--- Test suite
-testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \_ -> test [
-   "uninterpreted-0" ~: assert       =<< isThm p0
- , "uninterpreted-1" ~: assert       =<< isThm p1
- , "uninterpreted-2" ~: assert . not =<< isThm p2
- ]
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,15 +1,16 @@
 -----------------------------------------------------------------------------
 -- |
--- Module      :  Main
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
+-- Module    : Setup
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
 --
 -- Setup module for the sbv library
 -----------------------------------------------------------------------------
 
-{-# OPTIONS_GHC -Wall #-}
+{-# OPTIONS_GHC -Wall -Werror #-}
+
 module Main(main) where
 
 import Distribution.Simple
diff --git a/sbv.cabal b/sbv.cabal
--- a/sbv.cabal
+++ b/sbv.cabal
@@ -1,179 +1,421 @@
-Name:          sbv
-Version:       5.15
-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
+Cabal-Version: 2.2
+
+Name        : sbv
+Version     : 14.4
+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
                (Satisfiability Modulo Theories) solvers.
-               .
-               For details, please see: <http://leventerkok.github.com/sbv/>
 
-Copyright:     Levent Erkok, 2010-2017
-License:       BSD3
-License-file:  LICENSE
-Stability:     Experimental
-Author:        Levent Erkok
-Homepage:      http://leventerkok.github.com/sbv/
-Bug-reports:   http://github.com/LeventErkok/sbv/issues
-Maintainer:    Levent Erkok (erkokl@gmail.com)
-Build-Type:    Simple
-Cabal-Version: >= 1.14
-Data-Files: SBVUnitTest/GoldFiles/*.gold
-Extra-Source-Files: INSTALL, README.md, COPYRIGHT, CHANGES.md
+Copyright          : Levent Erkok, 2010-2026
+License            : BSD-3-Clause
+License-file       : LICENSE
+Stability          : Experimental
+Author             : Levent Erkok
+Homepage           : http://github.com/LeventErkok/sbv
+Bug-reports        : http://github.com/LeventErkok/sbv/issues
+Maintainer         : Levent Erkok (erkokl@gmail.com)
+Build-Type         : Simple
+Data-Files         : SBVTestSuite/GoldFiles/*.gold
+                     SBVTestSuite/TestSuite/CompileTests/SCase/*.hs
+                     SBVTestSuite/TestSuite/CompileTests/SCase/*.stderr
+                     SBVTestSuite/TestSuite/CompileTests/PCase/*.hs
+                     SBVTestSuite/TestSuite/CompileTests/PCase/*.stderr
+Extra-Doc-Files    : INSTALL, README.md, COPYRIGHT, CHANGES.md
 
+flag doctest_is_running
+  description: Define this flag during doctest run
+  default    : False
+  manual     : True
+
+flag compile_examples
+  description: Compile examples for documentation.
+  default    : True
+  manual     : True
+
 source-repository head
-    type:       git
-    location:   git://github.com/LeventErkok/sbv.git
+  type    : git
+  location: https://github.com/LeventErkok/sbv.git
 
+common common-settings
+   default-language: Haskell2010
+   ghc-options     : -Wall
+   build-depends   : base >= 4.19.2 && < 5
+   other-extensions: AllowAmbiguousTypes
+                     BangPatterns
+                     CPP
+                     ConstraintKinds
+                     DataKinds
+                     DefaultSignatures
+                     DeriveAnyClass
+                     DeriveDataTypeable
+                     DeriveFunctor
+                     DeriveGeneric
+                     DeriveLift
+                     DeriveTraversable
+                     DerivingStrategies
+                     ExistentialQuantification
+                     FlexibleContexts
+                     FlexibleInstances
+                     FunctionalDependencies
+                     GADTs
+                     GeneralizedNewtypeDeriving
+                     ImplicitParams
+                     InstanceSigs
+                     KindSignatures
+                     LambdaCase
+                     MultiParamTypeClasses
+                     NamedFieldPuns
+                     NegativeLiterals
+                     NumericUnderscores
+                     OverloadedLists
+                     OverloadedRecordDot
+                     OverloadedStrings
+                     PackageImports
+                     ParallelListComp
+                     QuantifiedConstraints
+                     QuasiQuotes
+                     RankNTypes
+                     RecordWildCards
+                     ScopedTypeVariables
+                     StandaloneDeriving
+                     TemplateHaskell
+                     TemplateHaskellQuotes
+                     TupleSections
+                     TypeApplications
+                     TypeFamilies
+                     TypeFamilyDependencies
+                     TypeOperators
+                     UndecidableInstances
+                     ViewPatterns
+                     TypeAbstractions
+
+   ghc-options  : -Wunused-packages
+
 Library
+  import          : common-settings
+
+  if flag(doctest_is_running)
+    CPP-Options: -DDOCTEST
+
   default-language: Haskell2010
-  ghc-options     : -Wall
-  other-extensions: BangPatterns
-                    DefaultSignatures
-                    DeriveAnyClass
-                    DeriveDataTypeable
-                    FlexibleContexts
-                    FlexibleInstances
-                    FunctionalDependencies
-                    GeneralizedNewtypeDeriving
-                    MultiParamTypeClasses
-                    OverlappingInstances
-                    ParallelListComp
-                    PatternGuards
-                    Rank2Types
-                    RankNTypes
-                    ScopedTypeVariables
-                    TupleSections
-                    TypeOperators
-                    TypeSynonymInstances
-  Build-Depends   : base >= 4.8 && < 5
-                  , base-compat >= 0.6
-                  , ghc
-                  , QuickCheck >= 2.9.2
-                  , crackNum >= 1.9
-                  , array, async, containers, deepseq, directory, filepath, old-time
-                  , pretty, process, mtl, random, syb, data-binary-ieee754
+  build-depends   : QuickCheck
+                  , array
+                  , async
+                  , base16-bytestring
+                  , bytestring
+                  , cryptohash-sha512
+                  , containers
+                  , deepseq
+                  , directory
+                  , filepath
+                  , haskell-src-exts
+                  , haskell-src-meta
+                  , libBF
+                  , mtl
+                  , pretty
+                  , process
+                  , random
+                  , syb
+                  , template-haskell
+                  , th-expand-syns
+                  , text
+                  , time
+                  , transformers
+                  , tree-view
+                  , uniplate
   Exposed-modules : Data.SBV
-                  , Data.SBV.Bridge.Boolector
-                  , Data.SBV.Bridge.CVC4
-                  , Data.SBV.Bridge.MathSAT
-                  , Data.SBV.Bridge.Yices
-                  , Data.SBV.Bridge.Z3
-                  , Data.SBV.Bridge.ABC
+                  , Data.SBV.Control
                   , Data.SBV.Dynamic
+                  , Data.SBV.Either
+                  , Data.SBV.Float
                   , Data.SBV.Internals
-                  , Data.SBV.Examples.BitPrecise.BitTricks
-                  , Data.SBV.Examples.BitPrecise.Legato
-                  , Data.SBV.Examples.BitPrecise.MergeSort
-                  , Data.SBV.Examples.BitPrecise.MultMask
-                  , Data.SBV.Examples.BitPrecise.PrefixSum
-                  , Data.SBV.Examples.CodeGeneration.AddSub
-                  , Data.SBV.Examples.CodeGeneration.CRC_USB5
-                  , Data.SBV.Examples.CodeGeneration.Fibonacci
-                  , Data.SBV.Examples.CodeGeneration.GCD
-                  , Data.SBV.Examples.CodeGeneration.PopulationCount
-                  , Data.SBV.Examples.CodeGeneration.Uninterpreted
-                  , Data.SBV.Examples.Crypto.AES
-                  , Data.SBV.Examples.Crypto.RC4
-                  , Data.SBV.Examples.Existentials.CRCPolynomial
-                  , Data.SBV.Examples.Existentials.Diophantine
-                  , Data.SBV.Examples.Misc.Enumerate
-                  , Data.SBV.Examples.Misc.Floating
-                  , Data.SBV.Examples.Misc.ModelExtract
-                  , Data.SBV.Examples.Misc.Auxiliary
-                  , Data.SBV.Examples.Misc.NoDiv0
-                  , Data.SBV.Examples.Misc.Word4
-                  , Data.SBV.Examples.Polynomials.Polynomials
-                  , Data.SBV.Examples.Puzzles.Birthday
-                  , Data.SBV.Examples.Puzzles.Coins
-                  , Data.SBV.Examples.Puzzles.Counts
-                  , Data.SBV.Examples.Puzzles.DogCatMouse
-                  , Data.SBV.Examples.Puzzles.Euler185
-                  , Data.SBV.Examples.Puzzles.Fish
-                  , Data.SBV.Examples.Puzzles.MagicSquare
-                  , Data.SBV.Examples.Puzzles.NQueens
-                  , Data.SBV.Examples.Puzzles.SendMoreMoney
-                  , Data.SBV.Examples.Puzzles.Sudoku
-                  , Data.SBV.Examples.Puzzles.U2Bridge
-                  , Data.SBV.Examples.Uninterpreted.AUF
-                  , Data.SBV.Examples.Uninterpreted.Deduce
-                  , Data.SBV.Examples.Uninterpreted.Function
-                  , Data.SBV.Examples.Uninterpreted.Shannon
-                  , Data.SBV.Examples.Uninterpreted.Sort
-                  , Data.SBV.Examples.Uninterpreted.UISortAllSat
-  Other-modules   : Data.SBV.BitVectors.AlgReals
-                  , Data.SBV.BitVectors.Concrete
-                  , Data.SBV.BitVectors.Data
-                  , Data.SBV.BitVectors.Kind
-                  , Data.SBV.BitVectors.Model
-                  , Data.SBV.BitVectors.Operations
-                  , Data.SBV.BitVectors.PrettyNum
-                  , Data.SBV.BitVectors.Floating
-                  , Data.SBV.BitVectors.Splittable
-                  , Data.SBV.BitVectors.STree
-                  , Data.SBV.BitVectors.Symbolic
+                  , Data.SBV.List
+                  , Data.SBV.Maybe
+                  , Data.SBV.Rational
+                  , Data.SBV.Set
+                  , Data.SBV.Char
+                  , Data.SBV.Tuple
+                  , Data.SBV.RegExp
+                  , Data.SBV.TP
+                  , Data.SBV.Tools.BMC
+                  , Data.SBV.Tools.BVOptimize
+                  , Data.SBV.Tools.Induction
+                  , Data.SBV.Tools.CodeGen
+                  , Data.SBV.Tools.GenTest
+                  , Data.SBV.Tools.Overflow
+                  , Data.SBV.Tools.Polynomial
+                  , Data.SBV.Tools.Range
+                  , Data.SBV.Tools.STree
+                  , Data.SBV.Tools.WeakestPreconditions
+                  , Data.SBV.Trans
+                  , Data.SBV.Trans.Control
+
+  if flag(compile_examples)
+    Exposed-modules : Documentation.SBV.Examples.ADT.Expr
+                    , Documentation.SBV.Examples.ADT.Param
+                    , Documentation.SBV.Examples.ADT.Types
+                    , Documentation.SBV.Examples.BitPrecise.Adders
+                    , Documentation.SBV.Examples.BitPrecise.BitTricks
+                    , Documentation.SBV.Examples.BitPrecise.BrokenSearch
+                    , Documentation.SBV.Examples.BitPrecise.Legato
+                    , Documentation.SBV.Examples.BitPrecise.MergeSort
+                    , Documentation.SBV.Examples.BitPrecise.PEXT_PDEP
+                    , Documentation.SBV.Examples.BitPrecise.PrefixSum
+                    , Documentation.SBV.Examples.CodeGeneration.AddSub
+                    , Documentation.SBV.Examples.CodeGeneration.CRC_USB5
+                    , Documentation.SBV.Examples.CodeGeneration.Fibonacci
+                    , Documentation.SBV.Examples.CodeGeneration.GCD
+                    , Documentation.SBV.Examples.CodeGeneration.PopulationCount
+                    , Documentation.SBV.Examples.CodeGeneration.Uninterpreted
+                    , Documentation.SBV.Examples.Crypto.AES
+                    , Documentation.SBV.Examples.Crypto.RC4
+                    , Documentation.SBV.Examples.Crypto.Prince
+                    , Documentation.SBV.Examples.Crypto.SHA
+                    , Documentation.SBV.Examples.DeltaSat.DeltaSat
+                    , Documentation.SBV.Examples.Existentials.Diophantine
+                    , Documentation.SBV.Examples.Lists.Fibonacci
+                    , Documentation.SBV.Examples.Lists.BoundedMutex
+                    , Documentation.SBV.Examples.Lists.CountOutAndTransfer
+                    , Documentation.SBV.Examples.Misc.Definitions
+                    , Documentation.SBV.Examples.Misc.Enumerate
+                    , Documentation.SBV.Examples.Misc.FirstOrderLogic
+                    , Documentation.SBV.Examples.Misc.Floating
+                    , Documentation.SBV.Examples.Misc.LambdaArray
+                    , Documentation.SBV.Examples.Misc.ModelExtract
+                    , Documentation.SBV.Examples.Misc.NestedArray
+                    , Documentation.SBV.Examples.Misc.Auxiliary
+                    , Documentation.SBV.Examples.Misc.NoDiv0
+                    , Documentation.SBV.Examples.Misc.Newtypes
+                    , Documentation.SBV.Examples.Misc.Polynomials
+                    , Documentation.SBV.Examples.Misc.ProgramPaths
+                    , Documentation.SBV.Examples.Misc.SetAlgebra
+                    , Documentation.SBV.Examples.Misc.SoftConstrain
+                    , Documentation.SBV.Examples.Misc.Tuple
+                    , 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.ProofTools.AddHorn
+                    , 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.Basics
+                    , 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.AOC_2021_24
+                    , Documentation.SBV.Examples.Puzzles.Birthday
+                    , Documentation.SBV.Examples.Puzzles.Coins
+                    , Documentation.SBV.Examples.Puzzles.Counts
+                    , Documentation.SBV.Examples.Puzzles.DieHard
+                    , Documentation.SBV.Examples.Puzzles.DogCatMouse
+                    , Documentation.SBV.Examples.Puzzles.Drinker
+                    , Documentation.SBV.Examples.Puzzles.Euler185
+                    , Documentation.SBV.Examples.Puzzles.Fish
+                    , Documentation.SBV.Examples.Puzzles.Garden
+                    , Documentation.SBV.Examples.Puzzles.HexPuzzle
+                    , Documentation.SBV.Examples.Puzzles.Jugs
+                    , Documentation.SBV.Examples.Puzzles.KnightsAndKnaves
+                    , Documentation.SBV.Examples.Puzzles.LadyAndTigers
+                    , Documentation.SBV.Examples.Puzzles.MagicSquare
+                    , Documentation.SBV.Examples.Puzzles.Murder
+                    , Documentation.SBV.Examples.Puzzles.Newspaper
+                    , Documentation.SBV.Examples.Puzzles.NQueens
+                    , Documentation.SBV.Examples.Puzzles.Orangutans
+                    , Documentation.SBV.Examples.Puzzles.Rabbits
+                    , Documentation.SBV.Examples.Puzzles.SendMoreMoney
+                    , Documentation.SBV.Examples.Puzzles.SquareBirthday
+                    , Documentation.SBV.Examples.Puzzles.Sudoku
+                    , Documentation.SBV.Examples.Puzzles.Tower
+                    , Documentation.SBV.Examples.Puzzles.U2Bridge
+                    , Documentation.SBV.Examples.Queries.Abducts
+                    , Documentation.SBV.Examples.Queries.AllSat
+                    , Documentation.SBV.Examples.Queries.UnsatCore
+                    , Documentation.SBV.Examples.Queries.FourFours
+                    , Documentation.SBV.Examples.Queries.GuessNumber
+                    , Documentation.SBV.Examples.Queries.CaseSplit
+                    , Documentation.SBV.Examples.Queries.Enums
+                    , Documentation.SBV.Examples.Queries.Interpolants
+                    , Documentation.SBV.Examples.Queries.Concurrency
+                    , Documentation.SBV.Examples.Strings.RegexCrossword
+                    , Documentation.SBV.Examples.Strings.SQLInjection
+                    , Documentation.SBV.Examples.TP.Ackermann
+                    , Documentation.SBV.Examples.TP.Adder
+                    , Documentation.SBV.Examples.TP.Basics
+                    , Documentation.SBV.Examples.TP.BinarySearch
+                    , Documentation.SBV.Examples.TP.CaseSplit
+                    , Documentation.SBV.Examples.TP.Coins
+                    , Documentation.SBV.Examples.TP.Collatz
+                    , Documentation.SBV.Examples.TP.ConstFold
+                    , Documentation.SBV.Examples.TP.Countdown
+                    , Documentation.SBV.Examples.TP.Fibonacci
+                    , Documentation.SBV.Examples.TP.GCD
+                    , Documentation.SBV.Examples.TP.InsertionSort
+                    , Documentation.SBV.Examples.TP.Kadane
+                    , Documentation.SBV.Examples.TP.Kleene
+                    , Documentation.SBV.Examples.TP.Lists
+                    , Documentation.SBV.Examples.TP.McCarthy91
+                    , Documentation.SBV.Examples.TP.Majority
+                    , Documentation.SBV.Examples.TP.MergeSort
+                    , Documentation.SBV.Examples.TP.MutualCorecursion
+                    , Documentation.SBV.Examples.TP.NatStream
+                    , Documentation.SBV.Examples.TP.Numeric
+                    , Documentation.SBV.Examples.TP.Peano
+                    , Documentation.SBV.Examples.TP.PigeonHole
+                    , Documentation.SBV.Examples.TP.PowerMod
+                    , Documentation.SBV.Examples.TP.Primes
+                    , Documentation.SBV.Examples.TP.Queue
+                    , Documentation.SBV.Examples.TP.QuickSort
+                    , Documentation.SBV.Examples.TP.RevAcc
+                    , Documentation.SBV.Examples.TP.Reverse
+                    , Documentation.SBV.Examples.TP.RunLength
+                    , Documentation.SBV.Examples.TP.ShefferStroke
+                    , Documentation.SBV.Examples.TP.SortHelpers
+                    , Documentation.SBV.Examples.TP.Sqrt2IsIrrational
+                    , Documentation.SBV.Examples.TP.StrongInduction
+                    , Documentation.SBV.Examples.TP.SumReverse
+                    , Documentation.SBV.Examples.TP.Tao
+                    , Documentation.SBV.Examples.TP.TautologyChecker
+                    , Documentation.SBV.Examples.TP.UpDown
+                    , Documentation.SBV.Examples.TP.VM
+                    , Documentation.SBV.Examples.Transformers.SymbolicEval
+                    , Documentation.SBV.Examples.Uninterpreted.AUF
+                    , Documentation.SBV.Examples.Uninterpreted.Deduce
+                    , Documentation.SBV.Examples.Uninterpreted.EUFLogic
+                    , 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
+
+  other-modules   : Data.SBV.Client
+                  , Data.SBV.Client.BaseIO
+                  , Data.SBV.Core.AlgReals
+                  , Data.SBV.Core.Concrete
+                  , Data.SBV.Core.Data
+                  , Data.SBV.Core.Kind
+                  , Data.SBV.Core.Model
+                  , Data.SBV.Core.Operations
+                  , Data.SBV.Core.Floating
+                  , Data.SBV.Core.Sized
+                  , Data.SBV.Core.SizedFloats
+                  , Data.SBV.Core.Symbolic
+                  , Data.SBV.Core.TH
+                  , Data.SBV.Control.BaseIO
+                  , Data.SBV.Control.Query
+                  , Data.SBV.Control.Types
+                  , Data.SBV.Control.Utils
                   , Data.SBV.Compilers.C
                   , Data.SBV.Compilers.CodeGen
+                  , Data.SBV.Lambda
+                  , Data.SBV.SCase
+                  , Data.SBV.SEnum
                   , Data.SBV.SMT.SMT
                   , Data.SBV.SMT.SMTLib
                   , Data.SBV.SMT.SMTLib2
                   , Data.SBV.SMT.SMTLibNames
+                  , Data.SBV.SMT.Utils
                   , Data.SBV.Provers.Prover
-                  , Data.SBV.Provers.SExpr
+                  , Data.SBV.Provers.ABC
                   , Data.SBV.Provers.Boolector
+                  , Data.SBV.Provers.Bitwuzla
                   , Data.SBV.Provers.CVC4
+                  , Data.SBV.Provers.CVC5
+                  , Data.SBV.Provers.DReal
+                  , Data.SBV.Provers.MathSAT
+                  , Data.SBV.Provers.OpenSMT
                   , Data.SBV.Provers.Yices
                   , Data.SBV.Provers.Z3
-                  , Data.SBV.Provers.MathSAT
-                  , Data.SBV.Provers.ABC
-                  , Data.SBV.Tools.ExpectedValue
-                  , Data.SBV.Tools.GenTest
-                  , Data.SBV.Tools.Optimize
-                  , Data.SBV.Tools.Polynomial
-                  , Data.SBV.Utils.Boolean
+                  , Data.SBV.Utils.CrackNum
+                  , Data.SBV.Utils.ExtractIO
                   , Data.SBV.Utils.Numeric
                   , Data.SBV.Utils.TDiff
                   , Data.SBV.Utils.Lib
-                  , GHC.SrcLoc.Compat
-                  , GHC.Stack.Compat
+                  , Data.SBV.Utils.PrettyNum
+                  , Data.SBV.Utils.SExpr
+                  , Data.SBV.TP.Kernel
+                  , Data.SBV.TP.TP
+                  , Data.SBV.TP.Utils
 
-Executable SBVUnitTests
-  default-language: Haskell2010
-  ghc-options     : -Wall
-  other-extensions: DeriveAnyClass
-                    Rank2Types
-                    RankNTypes
-                    ScopedTypeVariables
-                    TupleSections
-  Build-depends : base  >= 4.8 && < 5
-                , HUnit, directory, filepath, process, syb, sbv, data-binary-ieee754
-  Hs-Source-Dirs  : SBVUnitTest
-  main-is         : SBVUnitTest.hs
-  Other-modules   : SBVUnitTestBuildTime
-                  , SBVTest
-                  , SBVTestCollection
-                  , Examples.Arrays.Memory
-                  , Examples.Basics.BasicTests
-                  , Examples.Basics.Higher
-                  , Examples.Basics.Index
-                  , Examples.Basics.ProofTests
-                  , Examples.Basics.QRem
-                  , Examples.CRC.CCITT
-                  , Examples.CRC.CCITT_Unidir
-                  , Examples.CRC.GenPoly
-                  , Examples.CRC.Parity
-                  , Examples.CRC.USB5
-                  , Examples.Puzzles.PowerSet
-                  , Examples.Puzzles.Temperature
-                  , Examples.Uninterpreted.Uninterpreted
+Test-Suite SBVTest
+  import           : common-settings
+  default-language : Haskell2010
+  type             : exitcode-stdio-1.0
+  ghc-options      : -with-rtsopts=-K64m
+  build-depends   : Glob
+                  , QuickCheck
+                  , bytestring
+                  , containers
+                  , deepseq
+                  , directory
+                  , filepath
+                  , mtl
+                  , process
+                  , random
+                  , sbv
+                  , tasty
+                  , tasty-golden
+                  , tasty-hunit
+                  , tasty-quickcheck
+                  , temporary
+  hs-source-dirs  : SBVTestSuite
+  main-is         : SBVTest.hs
+  other-modules   : Utils.SBVTestFramework
+                  , TestSuite.ADT.ADT
+                  , TestSuite.ADT.Expr
+                  , TestSuite.ADT.MutRec
+                  , TestSuite.ADT.PExpr
+                  , TestSuite.Arrays.InitVals
                   , TestSuite.Arrays.Memory
+                  , TestSuite.Arrays.Query
+                  , TestSuite.Arrays.Caching
+                  , TestSuite.Basics.AllSat
+                  , TestSuite.Basics.ArbFloats
                   , TestSuite.Basics.ArithNoSolver
+                  , TestSuite.Basics.ArithNoSolver2
                   , TestSuite.Basics.ArithSolver
+                  , TestSuite.Basics.Assert
+                  , TestSuite.Basics.BarrelRotate
                   , TestSuite.Basics.BasicTests
+                  , TestSuite.Basics.DynSign
+                  , TestSuite.Basics.EqSym
+                  , TestSuite.Basics.Exceptions
+                  , TestSuite.Basics.GenBenchmark
                   , TestSuite.Basics.Higher
                   , TestSuite.Basics.Index
                   , TestSuite.Basics.IteTest
+                  , TestSuite.Basics.Lambda
+                  , TestSuite.Basics.List
+                  , TestSuite.Basics.ModelValidate
+                  , TestSuite.Basics.Nonlinear
                   , TestSuite.Basics.ProofTests
+                  , TestSuite.Basics.PseudoBoolean
                   , TestSuite.Basics.QRem
+                  , TestSuite.Basics.Quantifiers
+                  , TestSuite.Basics.Recursive
+                  , TestSuite.Basics.TPCaching
+                  , TestSuite.Basics.Set
+                  , TestSuite.Basics.SmtFunctionUnique
+                  , TestSuite.Basics.SmallShifts
+                  , TestSuite.Basics.SquashReals
+                  , TestSuite.Basics.String
+                  , TestSuite.Basics.Sum
+                  , TestSuite.Basics.TOut
+                  , TestSuite.Basics.Tuple
+                  , TestSuite.Basics.UISat
+                  , TestSuite.CRC.CCITT
+                  , TestSuite.CRC.CCITT_Unidir
+                  , TestSuite.CRC.GenPoly
+                  , TestSuite.CRC.Parity
+                  , TestSuite.CRC.USB5
+                  , TestSuite.Char.Char
                   , TestSuite.BitPrecise.BitTricks
                   , TestSuite.BitPrecise.Legato
                   , TestSuite.BitPrecise.MergeSort
@@ -186,16 +428,25 @@
                   , TestSuite.CodeGeneration.GCD
                   , TestSuite.CodeGeneration.PopulationCount
                   , TestSuite.CodeGeneration.Uninterpreted
+                  , TestSuite.CompileTests.SCase
+                  , TestSuite.CompileTests.PCase
                   , TestSuite.Crypto.AES
                   , TestSuite.Crypto.RC4
-                  , TestSuite.Existentials.CRCPolynomial
-                  , TestSuite.CRC.CCITT
-                  , TestSuite.CRC.CCITT_Unidir
-                  , TestSuite.CRC.GenPoly
-                  , TestSuite.CRC.Parity
-                  , TestSuite.CRC.USB5
-                  , TestSuite.Puzzles.Coins
+                  , TestSuite.Crypto.SHA
+                  , TestSuite.GenTest.GenTests
+                  , TestSuite.Optimization.AssertWithPenalty
+                  , TestSuite.Optimization.Basics
+                  , TestSuite.Optimization.Combined
+                  , TestSuite.Optimization.ExtensionField
+                  , TestSuite.Optimization.Floats
+                  , TestSuite.Optimization.NoOpt
+                  , TestSuite.Optimization.Quantified
+                  , TestSuite.Optimization.Reals
+                  , TestSuite.Optimization.Tuples
+                  , TestSuite.Overflows.Arithmetic
+                  , TestSuite.Overflows.Casts
                   , TestSuite.Polynomials.Polynomials
+                  , TestSuite.Puzzles.Coins
                   , TestSuite.Puzzles.Counts
                   , TestSuite.Puzzles.DogCatMouse
                   , TestSuite.Puzzles.Euler185
@@ -203,21 +454,154 @@
                   , TestSuite.Puzzles.NQueens
                   , TestSuite.Puzzles.PowerSet
                   , TestSuite.Puzzles.Sudoku
-                  , TestSuite.Puzzles.U2Bridge
                   , TestSuite.Puzzles.Temperature
+                  , TestSuite.Puzzles.U2Bridge
+                  , TestSuite.Queries.BasicQuery
+                  , TestSuite.Queries.ArrayGetVal
+                  , TestSuite.Queries.BadOption
+                  , TestSuite.Queries.DSat
+                  , TestSuite.Queries.Enums
+                  , TestSuite.Queries.FreshVars
+                  , TestSuite.Queries.Int_ABC
+                  , TestSuite.Queries.Int_Boolector
+                  , TestSuite.Queries.Int_CVC4
+                  , TestSuite.Queries.Int_Mathsat
+                  , TestSuite.Queries.Int_Yices
+                  , TestSuite.Queries.Int_Z3
+                  , TestSuite.Queries.Interpolants
+                  , TestSuite.Queries.Lists
+                  , TestSuite.Queries.Strings
+                  , TestSuite.Queries.Sums
+                  , TestSuite.Queries.Tables
+                  , TestSuite.Queries.Tuples
+                  , TestSuite.Queries.Uninterpreted
+                  , TestSuite.Queries.UISat
+                  , TestSuite.Queries.UISatEx
+                  , TestSuite.QuickCheck.QC
+                  , TestSuite.Transformers.SymbolicEval
                   , TestSuite.Uninterpreted.AUF
+                  , TestSuite.Uninterpreted.Axioms
                   , TestSuite.Uninterpreted.Function
-                  , TestSuite.Uninterpreted.Uninterpreted
                   , TestSuite.Uninterpreted.Sort
-                  , TestSuite.Uninterpreted.Axioms
+                  , TestSuite.Uninterpreted.Uninterpreted
+                  , TestSuite.Uninterpreted.EUFLogic
+                  , TestSuite.CantTypeCheck.Misc
 
-Test-Suite SBVBasicTests
-  type            : exitcode-stdio-1.0
+Test-Suite SBVConnections
+    import          : common-settings
+    default-language: Haskell2010
+    build-depends   : sbv
+    hs-source-dirs  : SBVTestSuite
+    main-is         : SBVConnectionTest.hs
+    type:             exitcode-stdio-1.0
+
+Test-Suite SBVDocTest
+    import          : common-settings
+    default-language: Haskell2010
+    build-depends   : process, sbv
+    hs-source-dirs  : SBVTestSuite
+    main-is:          SBVDocTest.hs
+    type:             exitcode-stdio-1.0
+
+Test-Suite SBVHLint
+    import          : common-settings
+    default-language: Haskell2010
+
+    build-depends   : process
+    hs-source-dirs  : SBVTestSuite
+    main-is         : SBVHLint.hs
+    type            : exitcode-stdio-1.0
+
+Benchmark SBVBench
+  import          : common-settings
   default-language: Haskell2010
-  ghc-options     : -Wall -with-rtsopts=-K64m
-  Build-depends : base >= 4.8 && < 5
-                , HUnit, directory, filepath, syb, sbv, data-binary-ieee754
-  Hs-Source-Dirs  : SBVUnitTest
-  main-is         : SBVBasicTests.hs
-  Other-modules   : SBVBasicTests
-                  , SBVTestCollection
+  type            : exitcode-stdio-1.0
+  ghc-options     : -with-rtsopts=-K64m
+  build-depends   : deepseq
+                  , filepath
+                  , process
+                  , random
+                  , sbv
+                  , tasty
+                  , tasty-bench
+                  , time
+  hs-source-dirs  : SBVBenchSuite
+  main-is         : SBVBench.hs
+  other-modules   : Utils.SBVBenchFramework
+                  , BenchSuite.Bench.Bench
+                  , BenchSuite.Puzzles.Birthday
+                  , BenchSuite.Puzzles.Coins
+                  , BenchSuite.Puzzles.Counts
+                  , BenchSuite.Puzzles.DogCatMouse
+                  , BenchSuite.Puzzles.Euler185
+                  , BenchSuite.Puzzles.Garden
+                  , BenchSuite.Puzzles.LadyAndTigers
+                  , BenchSuite.Puzzles.MagicSquare
+                  , BenchSuite.Puzzles.NQueens
+                  , BenchSuite.Puzzles.SendMoreMoney
+                  , BenchSuite.Puzzles.Sudoku
+                  , BenchSuite.Puzzles.U2Bridge
+                  , BenchSuite.BitPrecise.BitTricks
+                  , BenchSuite.BitPrecise.BrokenSearch
+                  , BenchSuite.BitPrecise.Legato
+                  , BenchSuite.BitPrecise.MergeSort
+                  , BenchSuite.BitPrecise.PrefixSum
+                  , BenchSuite.Queries.AllSat
+                  , BenchSuite.Queries.CaseSplit
+                  , BenchSuite.Queries.Concurrency
+                  , BenchSuite.Queries.Enums
+                  , BenchSuite.Queries.FourFours
+                  , BenchSuite.Queries.GuessNumber
+                  , BenchSuite.Queries.Interpolants
+                  , BenchSuite.Queries.UnsatCore
+                  , BenchSuite.WeakestPreconditions.Instances
+                  , BenchSuite.WeakestPreconditions.Append
+                  , BenchSuite.WeakestPreconditions.Basics
+                  , BenchSuite.WeakestPreconditions.Fib
+                  , BenchSuite.WeakestPreconditions.GCD
+                  , BenchSuite.WeakestPreconditions.IntDiv
+                  , BenchSuite.WeakestPreconditions.IntSqrt
+                  , BenchSuite.WeakestPreconditions.Length
+                  , BenchSuite.WeakestPreconditions.Sum
+                  , BenchSuite.Optimization.Instances
+                  , BenchSuite.Optimization.Enumerate
+                  , BenchSuite.Optimization.ExtField
+                  , BenchSuite.Optimization.LinearOpt
+                  , BenchSuite.Optimization.Production
+                  , BenchSuite.Optimization.VM
+                  , BenchSuite.Uninterpreted.AUF
+                  , BenchSuite.Uninterpreted.Deduce
+                  , BenchSuite.Uninterpreted.Function
+                  , BenchSuite.Uninterpreted.Multiply
+                  , BenchSuite.Uninterpreted.Shannon
+                  , BenchSuite.Uninterpreted.Sort
+                  , BenchSuite.Uninterpreted.UISortAllSat
+                  , BenchSuite.ProofTools.BMC
+                  , BenchSuite.ProofTools.Fibonacci
+                  , BenchSuite.ProofTools.Strengthen
+                  , BenchSuite.ProofTools.Sum
+                  , BenchSuite.CodeGeneration.AddSub
+                  , BenchSuite.CodeGeneration.CRC_USB5
+                  , BenchSuite.CodeGeneration.Fibonacci
+                  , BenchSuite.CodeGeneration.GCD
+                  , BenchSuite.CodeGeneration.PopulationCount
+                  , BenchSuite.CodeGeneration.Uninterpreted
+                  , BenchSuite.Crypto.AES
+                  , BenchSuite.Crypto.RC4
+                  , BenchSuite.Crypto.SHA
+                  , BenchSuite.Misc.Auxiliary
+                  , BenchSuite.Misc.Enumerate
+                  , BenchSuite.Misc.Floating
+                  , BenchSuite.Misc.ModelExtract
+                  , BenchSuite.Misc.Newtypes
+                  , BenchSuite.Misc.NoDiv0
+                  , BenchSuite.Misc.Polynomials
+                  , BenchSuite.Misc.SetAlgebra
+                  , BenchSuite.Misc.SoftConstrain
+                  , BenchSuite.Misc.Tuple
+                  , BenchSuite.Lists.BoundedMutex
+                  , BenchSuite.Lists.Fibonacci
+                  , BenchSuite.Strings.RegexCrossword
+                  , BenchSuite.Strings.SQLInjection
+                  , BenchSuite.Existentials.Diophantine
+                  , BenchSuite.Transformers.SymbolicEval
